347
|
1 /* Load needed message catalogs.
|
|
2 Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
|
|
3
|
|
4 This program is free software; you can redistribute it and/or modify
|
|
5 it under the terms of the GNU General Public License as published by
|
|
6 the Free Software Foundation; either version 2, or (at your option)
|
|
7 any later version.
|
|
8
|
|
9 This program is distributed in the hope that it will be useful,
|
|
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12 GNU General Public License for more details.
|
|
13
|
|
14 You should have received a copy of the GNU General Public License
|
|
15 along with this program; if not, write to the Free Software Foundation,
|
|
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|
17
|
|
18 #ifdef HAVE_CONFIG_H
|
|
19 # include <config.h>
|
|
20 #endif
|
|
21
|
|
22 #include <fcntl.h>
|
|
23 #include <sys/types.h>
|
|
24 #include <sys/stat.h>
|
|
25
|
|
26 #if defined STDC_HEADERS || defined _LIBC
|
|
27 # include <stdlib.h>
|
|
28 #endif
|
|
29
|
|
30 #if defined HAVE_UNISTD_H || defined _LIBC
|
|
31 # include <unistd.h>
|
|
32 #endif
|
|
33
|
|
34 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
|
|
35 || (defined _LIBC && defined _POSIX_MAPPED_FILES)
|
|
36 # include <sys/mman.h>
|
|
37 # undef HAVE_MMAP
|
|
38 # define HAVE_MMAP 1
|
|
39 #else
|
|
40 # undef HAVE_MMAP
|
|
41 #endif
|
|
42
|
|
43 #include "gettext.h"
|
|
44 #include "gettextP.h"
|
|
45
|
|
46 /* @@ end of prolog @@ */
|
|
47
|
|
48 #ifdef _LIBC
|
|
49 /* Rename the non ISO C functions. This is required by the standard
|
|
50 because some ISO C functions will require linking with this object
|
|
51 file and the name space must not be polluted. */
|
|
52 # define open __open
|
|
53 # define close __close
|
|
54 # define read __read
|
|
55 # define mmap __mmap
|
|
56 # define munmap __munmap
|
|
57 #endif
|
|
58
|
|
59 /* We need a sign, whether a new catalog was loaded, which can be associated
|
|
60 with all translations. This is important if the translations are
|
|
61 cached by one of GCC's features. */
|
|
62 int _nl_msg_cat_cntr = 0;
|
|
63
|
|
64
|
|
65 /* Load the message catalogs specified by FILENAME. If it is no valid
|
|
66 message catalog do nothing. */
|
|
67 void
|
|
68 internal_function
|
|
69 _nl_load_domain (domain_file)
|
|
70 struct loaded_l10nfile *domain_file;
|
|
71 {
|
|
72 int fd;
|
|
73 size_t size;
|
|
74 struct stat st;
|
|
75 struct mo_file_header *data = (struct mo_file_header *) -1;
|
|
76 int use_mmap = 0;
|
|
77 struct loaded_domain *domain;
|
|
78
|
|
79 domain_file->decided = 1;
|
|
80 domain_file->data = NULL;
|
|
81
|
|
82 /* If the record does not represent a valid locale the FILENAME
|
|
83 might be NULL. This can happen when according to the given
|
|
84 specification the locale file name is different for XPG and CEN
|
|
85 syntax. */
|
|
86 if (domain_file->filename == NULL)
|
|
87 return;
|
|
88
|
|
89 /* Try to open the addressed file. */
|
|
90 fd = open (domain_file->filename, O_RDONLY);
|
|
91 if (fd == -1)
|
|
92 return;
|
|
93
|
|
94 /* We must know about the size of the file. */
|
|
95 if (fstat (fd, &st) != 0
|
|
96 || (size = (size_t) st.st_size) != st.st_size
|
|
97 || size < sizeof (struct mo_file_header))
|
|
98 {
|
|
99 /* Something went wrong. */
|
|
100 close (fd);
|
|
101 return;
|
|
102 }
|
|
103
|
|
104 #ifdef HAVE_MMAP
|
|
105 /* Now we are ready to load the file. If mmap() is available we try
|
|
106 this first. If not available or it failed we try to load it. */
|
|
107 data = (struct mo_file_header *) mmap (NULL, size, PROT_READ,
|
|
108 MAP_PRIVATE, fd, 0);
|
|
109
|
|
110 if (data != (struct mo_file_header *) -1)
|
|
111 {
|
|
112 /* mmap() call was successful. */
|
|
113 close (fd);
|
|
114 use_mmap = 1;
|
|
115 }
|
|
116 #endif
|
|
117
|
|
118 /* If the data is not yet available (i.e. mmap'ed) we try to load
|
|
119 it manually. */
|
|
120 if (data == (struct mo_file_header *) -1)
|
|
121 {
|
|
122 size_t to_read;
|
|
123 char *read_ptr;
|
|
124
|
|
125 data = (struct mo_file_header *) malloc (size);
|
|
126 if (data == NULL)
|
|
127 return;
|
|
128
|
|
129 to_read = size;
|
|
130 read_ptr = (char *) data;
|
|
131 do
|
|
132 {
|
|
133 long int nb = (long int) read (fd, read_ptr, to_read);
|
|
134 if (nb == -1)
|
|
135 {
|
|
136 close (fd);
|
|
137 return;
|
|
138 }
|
|
139
|
|
140 read_ptr += nb;
|
|
141 to_read -= nb;
|
|
142 }
|
|
143 while (to_read > 0);
|
|
144
|
|
145 close (fd);
|
|
146 }
|
|
147
|
|
148 /* Using the magic number we can test whether it really is a message
|
|
149 catalog file. */
|
|
150 if (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED)
|
|
151 {
|
|
152 /* The magic number is wrong: not a message catalog file. */
|
|
153 #ifdef HAVE_MMAP
|
|
154 if (use_mmap)
|
|
155 munmap ((caddr_t) data, size);
|
|
156 else
|
|
157 #endif
|
|
158 free (data);
|
|
159 return;
|
|
160 }
|
|
161
|
|
162 domain_file->data
|
|
163 = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
|
|
164 if (domain_file->data == NULL)
|
|
165 return;
|
|
166
|
|
167 domain = (struct loaded_domain *) domain_file->data;
|
|
168 domain->data = (char *) data;
|
|
169 domain->use_mmap = use_mmap;
|
|
170 domain->mmap_size = size;
|
|
171 domain->must_swap = data->magic != _MAGIC;
|
|
172
|
|
173 /* Fill in the information about the available tables. */
|
|
174 switch (W (domain->must_swap, data->revision))
|
|
175 {
|
|
176 case 0:
|
|
177 domain->nstrings = W (domain->must_swap, data->nstrings);
|
|
178 domain->orig_tab = (struct string_desc *)
|
|
179 ((char *) data + W (domain->must_swap, data->orig_tab_offset));
|
|
180 domain->trans_tab = (struct string_desc *)
|
|
181 ((char *) data + W (domain->must_swap, data->trans_tab_offset));
|
|
182 domain->hash_size = W (domain->must_swap, data->hash_tab_size);
|
|
183 domain->hash_tab = (nls_uint32 *)
|
|
184 ((char *) data + W (domain->must_swap, data->hash_tab_offset));
|
|
185 break;
|
|
186 default:
|
|
187 /* This is an invalid revision. */
|
|
188 #ifdef HAVE_MMAP
|
|
189 if (use_mmap)
|
|
190 munmap ((caddr_t) data, size);
|
|
191 else
|
|
192 #endif
|
|
193 free (data);
|
|
194 free (domain);
|
|
195 domain_file->data = NULL;
|
|
196 return;
|
|
197 }
|
|
198
|
|
199 /* Show that one domain is changed. This might make some cached
|
|
200 translations invalid. */
|
|
201 ++_nl_msg_cat_cntr;
|
|
202 }
|
|
203
|
|
204
|
|
205 #ifdef _LIBC
|
|
206 void
|
|
207 internal_function
|
|
208 _nl_unload_domain (domain)
|
|
209 struct loaded_domain *domain;
|
|
210 {
|
|
211 #ifdef _POSIX_MAPPED_FILES
|
|
212 if (domain->use_mmap)
|
|
213 munmap ((caddr_t) domain->data, domain->mmap_size);
|
|
214 else
|
|
215 #endif /* _POSIX_MAPPED_FILES */
|
|
216 free ((void *) domain->data);
|
|
217
|
|
218 free (domain);
|
|
219 }
|
|
220 #endif
|