1 /* Load needed message catalogs.
2 Copyright (C) 1995-2020 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 Lesser General Public License as published by
6 the Free Software Foundation; either version 2.1 of the License, or
7 (at your option) 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 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
16
17 /* Tell glibc's <string.h> to provide a prototype for mempcpy().
18 This must come before <config.h> because <config.h> may include
19 <features.h>, and once <features.h> has been included, it's too late. */
20 #ifndef _GNU_SOURCE
21 # define _GNU_SOURCE 1
22 #endif
23
24 #ifdef HAVE_CONFIG_H
25 # include <config.h>
26 #endif
27
28 #include <assert.h>
29 #include <ctype.h>
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34
35 #ifdef __GNUC__
36 # undef alloca
37 # define alloca __builtin_alloca
38 # define HAVE_ALLOCA 1
39 #else
40 # ifdef _MSC_VER
41 # include <malloc.h>
42 # define alloca _alloca
43 # else
44 # if defined HAVE_ALLOCA_H || defined _LIBC
45 # include <alloca.h>
46 # else
47 # ifdef _AIX
48 #pragma alloca
49 # else
50 # ifndef alloca
51 char *alloca ();
52 # endif
53 # endif
54 # endif
55 # endif
56 #endif
57
58 #include <stdlib.h>
59 #include <string.h>
60
61 #if defined HAVE_UNISTD_H || defined _LIBC
62 # include <unistd.h>
63 #endif
64
65 #ifdef _LIBC
66 # include <langinfo.h>
67 # include <locale.h>
68 #endif
69
70 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
71 || (defined _LIBC && defined _POSIX_MAPPED_FILES)
72 # include <sys/mman.h>
73 # undef HAVE_MMAP
74 # define HAVE_MMAP 1
75 #else
76 # undef HAVE_MMAP
77 #endif
78
79 #if defined HAVE_STDINT_H_WITH_UINTMAX || defined _LIBC
80 # include <stdint.h>
81 #endif
82 #if defined HAVE_INTTYPES_H || defined _LIBC
83 # include <inttypes.h>
84 #endif
85
86 #include "gmo.h"
87 #include "gettextP.h"
88 #include "hash-string.h"
89 #include "plural-exp.h"
90
91 #ifdef _LIBC
92 # include "../locale/localeinfo.h"
93 # include <not-cancel.h>
94 #endif
95
96 /* Handle multi-threaded applications. */
97 #ifdef _LIBC
98 # include <bits/libc-lock.h>
99 #else
100 # include "lock.h"
101 #endif
102
103 /* Provide fallback values for macros that ought to be defined in <inttypes.h>.
104 Note that our fallback values need not be literal strings, because we don't
105 use them with preprocessor string concatenation. */
106 #if !defined PRId8
107 # define PRId8 "d"
108 #endif
109 #if !defined PRIi8
110 # define PRIi8 "i"
111 #endif
112 #if !defined PRIo8
113 # define PRIo8 "o"
114 #endif
115 #if !defined PRIu8
116 # define PRIu8 "u"
117 #endif
118 #if !defined PRIx8
119 # define PRIx8 "x"
120 #endif
121 #if !defined PRIX8
122 # define PRIX8 "X"
123 #endif
124 #if !defined PRId16
125 # define PRId16 "d"
126 #endif
127 #if !defined PRIi16
128 # define PRIi16 "i"
129 #endif
130 #if !defined PRIo16
131 # define PRIo16 "o"
132 #endif
133 #if !defined PRIu16
134 # define PRIu16 "u"
135 #endif
136 #if !defined PRIx16
137 # define PRIx16 "x"
138 #endif
139 #if !defined PRIX16
140 # define PRIX16 "X"
141 #endif
142 #if !defined PRId32
143 # define PRId32 "d"
144 #endif
145 #if !defined PRIi32
146 # define PRIi32 "i"
147 #endif
148 #if !defined PRIo32
149 # define PRIo32 "o"
150 #endif
151 #if !defined PRIu32
152 # define PRIu32 "u"
153 #endif
154 #if !defined PRIx32
155 # define PRIx32 "x"
156 #endif
157 #if !defined PRIX32
158 # define PRIX32 "X"
159 #endif
160 #if !defined PRId64
161 # define PRId64 (sizeof (long) == 8 ? "ld" : "lld")
162 #endif
163 #if !defined PRIi64
164 # define PRIi64 (sizeof (long) == 8 ? "li" : "lli")
165 #endif
166 #if !defined PRIo64
167 # define PRIo64 (sizeof (long) == 8 ? "lo" : "llo")
168 #endif
169 #if !defined PRIu64
170 # define PRIu64 (sizeof (long) == 8 ? "lu" : "llu")
171 #endif
172 #if !defined PRIx64
173 # define PRIx64 (sizeof (long) == 8 ? "lx" : "llx")
174 #endif
175 #if !defined PRIX64
176 # define PRIX64 (sizeof (long) == 8 ? "lX" : "llX")
177 #endif
178 #if !defined PRIdLEAST8
179 # define PRIdLEAST8 "d"
180 #endif
181 #if !defined PRIiLEAST8
182 # define PRIiLEAST8 "i"
183 #endif
184 #if !defined PRIoLEAST8
185 # define PRIoLEAST8 "o"
186 #endif
187 #if !defined PRIuLEAST8
188 # define PRIuLEAST8 "u"
189 #endif
190 #if !defined PRIxLEAST8
191 # define PRIxLEAST8 "x"
192 #endif
193 #if !defined PRIXLEAST8
194 # define PRIXLEAST8 "X"
195 #endif
196 #if !defined PRIdLEAST16
197 # define PRIdLEAST16 "d"
198 #endif
199 #if !defined PRIiLEAST16
200 # define PRIiLEAST16 "i"
201 #endif
202 #if !defined PRIoLEAST16
203 # define PRIoLEAST16 "o"
204 #endif
205 #if !defined PRIuLEAST16
206 # define PRIuLEAST16 "u"
207 #endif
208 #if !defined PRIxLEAST16
209 # define PRIxLEAST16 "x"
210 #endif
211 #if !defined PRIXLEAST16
212 # define PRIXLEAST16 "X"
213 #endif
214 #if !defined PRIdLEAST32
215 # define PRIdLEAST32 "d"
216 #endif
217 #if !defined PRIiLEAST32
218 # define PRIiLEAST32 "i"
219 #endif
220 #if !defined PRIoLEAST32
221 # define PRIoLEAST32 "o"
222 #endif
223 #if !defined PRIuLEAST32
224 # define PRIuLEAST32 "u"
225 #endif
226 #if !defined PRIxLEAST32
227 # define PRIxLEAST32 "x"
228 #endif
229 #if !defined PRIXLEAST32
230 # define PRIXLEAST32 "X"
231 #endif
232 #if !defined PRIdLEAST64
233 # define PRIdLEAST64 PRId64
234 #endif
235 #if !defined PRIiLEAST64
236 # define PRIiLEAST64 PRIi64
237 #endif
238 #if !defined PRIoLEAST64
239 # define PRIoLEAST64 PRIo64
240 #endif
241 #if !defined PRIuLEAST64
242 # define PRIuLEAST64 PRIu64
243 #endif
244 #if !defined PRIxLEAST64
245 # define PRIxLEAST64 PRIx64
246 #endif
247 #if !defined PRIXLEAST64
248 # define PRIXLEAST64 PRIX64
249 #endif
250 #if !defined PRIdFAST8
251 # define PRIdFAST8 "d"
252 #endif
253 #if !defined PRIiFAST8
254 # define PRIiFAST8 "i"
255 #endif
256 #if !defined PRIoFAST8
257 # define PRIoFAST8 "o"
258 #endif
259 #if !defined PRIuFAST8
260 # define PRIuFAST8 "u"
261 #endif
262 #if !defined PRIxFAST8
263 # define PRIxFAST8 "x"
264 #endif
265 #if !defined PRIXFAST8
266 # define PRIXFAST8 "X"
267 #endif
268 #if !defined PRIdFAST16
269 # define PRIdFAST16 "d"
270 #endif
271 #if !defined PRIiFAST16
272 # define PRIiFAST16 "i"
273 #endif
274 #if !defined PRIoFAST16
275 # define PRIoFAST16 "o"
276 #endif
277 #if !defined PRIuFAST16
278 # define PRIuFAST16 "u"
279 #endif
280 #if !defined PRIxFAST16
281 # define PRIxFAST16 "x"
282 #endif
283 #if !defined PRIXFAST16
284 # define PRIXFAST16 "X"
285 #endif
286 #if !defined PRIdFAST32
287 # define PRIdFAST32 "d"
288 #endif
289 #if !defined PRIiFAST32
290 # define PRIiFAST32 "i"
291 #endif
292 #if !defined PRIoFAST32
293 # define PRIoFAST32 "o"
294 #endif
295 #if !defined PRIuFAST32
296 # define PRIuFAST32 "u"
297 #endif
298 #if !defined PRIxFAST32
299 # define PRIxFAST32 "x"
300 #endif
301 #if !defined PRIXFAST32
302 # define PRIXFAST32 "X"
303 #endif
304 #if !defined PRIdFAST64
305 # define PRIdFAST64 PRId64
306 #endif
307 #if !defined PRIiFAST64
308 # define PRIiFAST64 PRIi64
309 #endif
310 #if !defined PRIoFAST64
311 # define PRIoFAST64 PRIo64
312 #endif
313 #if !defined PRIuFAST64
314 # define PRIuFAST64 PRIu64
315 #endif
316 #if !defined PRIxFAST64
317 # define PRIxFAST64 PRIx64
318 #endif
319 #if !defined PRIXFAST64
320 # define PRIXFAST64 PRIX64
321 #endif
322 #if !defined PRIdMAX
323 # define PRIdMAX (sizeof (uintmax_t) == sizeof (long) ? "ld" : "lld")
324 #endif
325 #if !defined PRIiMAX
326 # define PRIiMAX (sizeof (uintmax_t) == sizeof (long) ? "li" : "lli")
327 #endif
328 #if !defined PRIoMAX
329 # define PRIoMAX (sizeof (uintmax_t) == sizeof (long) ? "lo" : "llo")
330 #endif
331 #if !defined PRIuMAX
332 # define PRIuMAX (sizeof (uintmax_t) == sizeof (long) ? "lu" : "llu")
333 #endif
334 #if !defined PRIxMAX
335 # define PRIxMAX (sizeof (uintmax_t) == sizeof (long) ? "lx" : "llx")
336 #endif
337 #if !defined PRIXMAX
338 # define PRIXMAX (sizeof (uintmax_t) == sizeof (long) ? "lX" : "llX")
339 #endif
340 #if !defined PRIdPTR
341 # define PRIdPTR \
342 (sizeof (void *) == sizeof (long) ? "ld" : \
343 sizeof (void *) == sizeof (int) ? "d" : \
344 "lld")
345 #endif
346 #if !defined PRIiPTR
347 # define PRIiPTR \
348 (sizeof (void *) == sizeof (long) ? "li" : \
349 sizeof (void *) == sizeof (int) ? "i" : \
350 "lli")
351 #endif
352 #if !defined PRIoPTR
353 # define PRIoPTR \
354 (sizeof (void *) == sizeof (long) ? "lo" : \
355 sizeof (void *) == sizeof (int) ? "o" : \
356 "llo")
357 #endif
358 #if !defined PRIuPTR
359 # define PRIuPTR \
360 (sizeof (void *) == sizeof (long) ? "lu" : \
361 sizeof (void *) == sizeof (int) ? "u" : \
362 "llu")
363 #endif
364 #if !defined PRIxPTR
365 # define PRIxPTR \
366 (sizeof (void *) == sizeof (long) ? "lx" : \
367 sizeof (void *) == sizeof (int) ? "x" : \
368 "llx")
369 #endif
370 #if !defined PRIXPTR
371 # define PRIXPTR \
372 (sizeof (void *) == sizeof (long) ? "lX" : \
373 sizeof (void *) == sizeof (int) ? "X" : \
374 "llX")
375 #endif
376
377 /* @@ end of prolog @@ */
378
379 #ifdef _LIBC
380 /* Rename the non ISO C functions. This is required by the standard
381 because some ISO C functions will require linking with this object
382 file and the name space must not be polluted. */
383 # define open(name, flags) open_not_cancel_2 (name, flags)
384 # define close(fd) close_not_cancel_no_status (fd)
385 # define read(fd, buf, n) read_not_cancel (fd, buf, n)
386 # define mmap(addr, len, prot, flags, fd, offset) \
387 __mmap (addr, len, prot, flags, fd, offset)
388 # define munmap(addr, len) __munmap (addr, len)
389 #endif
390
391 /* For those losing systems which don't have `alloca' we have to add
392 some additional code emulating it. */
393 #ifdef HAVE_ALLOCA
394 # define freea(p) /* nothing */
395 #else
396 # define alloca(n) malloc (n)
397 # define freea(p) free (p)
398 #endif
399
400 /* For systems that distinguish between text and binary I/O.
401 O_BINARY is usually declared in <fcntl.h>. */
402 #if !defined O_BINARY && defined _O_BINARY
403 /* For MSC-compatible compilers. */
404 # define O_BINARY _O_BINARY
405 # define O_TEXT _O_TEXT
406 #endif
407 #ifdef __BEOS__
408 /* BeOS 5 has O_BINARY and O_TEXT, but they have no effect. */
409 # undef O_BINARY
410 # undef O_TEXT
411 #endif
412 /* On reasonable systems, binary I/O is the default. */
413 #ifndef O_BINARY
414 # define O_BINARY 0
415 #endif
416
417
418 /* We need a sign, whether a new catalog was loaded, which can be associated
419 with all translations. This is important if the translations are
420 cached by one of GCC's features. */
421 #if defined __APPLE__ && defined __MACH__
422 /* On macOS 10.13 with Apple clang-902.0.39.1 and cctools-895, when linking
423 statically, we need an explicit zero-initialization, in order to avoid a
424 link-time error that __nl_msg_cat_cntr is an undefined symbol. It could
425 be a compiler bug or a ranlib bug. */
426 int _nl_msg_cat_cntr = 0;
427 #else
428 int _nl_msg_cat_cntr;
429 #endif
430
431
432 /* Expand a system dependent string segment. Return NULL if unsupported. */
433 static const char *
get_sysdep_segment_value(const char * name)434 get_sysdep_segment_value (const char *name)
435 {
436 /* Test for an ISO C 99 section 7.8.1 format string directive.
437 Syntax:
438 P R I { d | i | o | u | x | X }
439 { { | LEAST | FAST } { 8 | 16 | 32 | 64 } | MAX | PTR } */
440 /* We don't use a table of 14 times 6 'const char *' strings here, because
441 data relocations cost startup time. */
442 if (name[0] == 'P' && name[1] == 'R' && name[2] == 'I')
443 {
444 if (name[3] == 'd' || name[3] == 'i' || name[3] == 'o' || name[3] == 'u'
445 || name[3] == 'x' || name[3] == 'X')
446 {
447 if (name[4] == '8' && name[5] == '\0')
448 {
449 if (name[3] == 'd')
450 return PRId8;
451 if (name[3] == 'i')
452 return PRIi8;
453 if (name[3] == 'o')
454 return PRIo8;
455 if (name[3] == 'u')
456 return PRIu8;
457 if (name[3] == 'x')
458 return PRIx8;
459 if (name[3] == 'X')
460 return PRIX8;
461 abort ();
462 }
463 if (name[4] == '1' && name[5] == '6' && name[6] == '\0')
464 {
465 if (name[3] == 'd')
466 return PRId16;
467 if (name[3] == 'i')
468 return PRIi16;
469 if (name[3] == 'o')
470 return PRIo16;
471 if (name[3] == 'u')
472 return PRIu16;
473 if (name[3] == 'x')
474 return PRIx16;
475 if (name[3] == 'X')
476 return PRIX16;
477 abort ();
478 }
479 if (name[4] == '3' && name[5] == '2' && name[6] == '\0')
480 {
481 if (name[3] == 'd')
482 return PRId32;
483 if (name[3] == 'i')
484 return PRIi32;
485 if (name[3] == 'o')
486 return PRIo32;
487 if (name[3] == 'u')
488 return PRIu32;
489 if (name[3] == 'x')
490 return PRIx32;
491 if (name[3] == 'X')
492 return PRIX32;
493 abort ();
494 }
495 if (name[4] == '6' && name[5] == '4' && name[6] == '\0')
496 {
497 if (name[3] == 'd')
498 return PRId64;
499 if (name[3] == 'i')
500 return PRIi64;
501 if (name[3] == 'o')
502 return PRIo64;
503 if (name[3] == 'u')
504 return PRIu64;
505 if (name[3] == 'x')
506 return PRIx64;
507 if (name[3] == 'X')
508 return PRIX64;
509 abort ();
510 }
511 if (name[4] == 'L' && name[5] == 'E' && name[6] == 'A'
512 && name[7] == 'S' && name[8] == 'T')
513 {
514 if (name[9] == '8' && name[10] == '\0')
515 {
516 if (name[3] == 'd')
517 return PRIdLEAST8;
518 if (name[3] == 'i')
519 return PRIiLEAST8;
520 if (name[3] == 'o')
521 return PRIoLEAST8;
522 if (name[3] == 'u')
523 return PRIuLEAST8;
524 if (name[3] == 'x')
525 return PRIxLEAST8;
526 if (name[3] == 'X')
527 return PRIXLEAST8;
528 abort ();
529 }
530 if (name[9] == '1' && name[10] == '6' && name[11] == '\0')
531 {
532 if (name[3] == 'd')
533 return PRIdLEAST16;
534 if (name[3] == 'i')
535 return PRIiLEAST16;
536 if (name[3] == 'o')
537 return PRIoLEAST16;
538 if (name[3] == 'u')
539 return PRIuLEAST16;
540 if (name[3] == 'x')
541 return PRIxLEAST16;
542 if (name[3] == 'X')
543 return PRIXLEAST16;
544 abort ();
545 }
546 if (name[9] == '3' && name[10] == '2' && name[11] == '\0')
547 {
548 if (name[3] == 'd')
549 return PRIdLEAST32;
550 if (name[3] == 'i')
551 return PRIiLEAST32;
552 if (name[3] == 'o')
553 return PRIoLEAST32;
554 if (name[3] == 'u')
555 return PRIuLEAST32;
556 if (name[3] == 'x')
557 return PRIxLEAST32;
558 if (name[3] == 'X')
559 return PRIXLEAST32;
560 abort ();
561 }
562 if (name[9] == '6' && name[10] == '4' && name[11] == '\0')
563 {
564 if (name[3] == 'd')
565 return PRIdLEAST64;
566 if (name[3] == 'i')
567 return PRIiLEAST64;
568 if (name[3] == 'o')
569 return PRIoLEAST64;
570 if (name[3] == 'u')
571 return PRIuLEAST64;
572 if (name[3] == 'x')
573 return PRIxLEAST64;
574 if (name[3] == 'X')
575 return PRIXLEAST64;
576 abort ();
577 }
578 }
579 if (name[4] == 'F' && name[5] == 'A' && name[6] == 'S'
580 && name[7] == 'T')
581 {
582 if (name[8] == '8' && name[9] == '\0')
583 {
584 if (name[3] == 'd')
585 return PRIdFAST8;
586 if (name[3] == 'i')
587 return PRIiFAST8;
588 if (name[3] == 'o')
589 return PRIoFAST8;
590 if (name[3] == 'u')
591 return PRIuFAST8;
592 if (name[3] == 'x')
593 return PRIxFAST8;
594 if (name[3] == 'X')
595 return PRIXFAST8;
596 abort ();
597 }
598 if (name[8] == '1' && name[9] == '6' && name[10] == '\0')
599 {
600 if (name[3] == 'd')
601 return PRIdFAST16;
602 if (name[3] == 'i')
603 return PRIiFAST16;
604 if (name[3] == 'o')
605 return PRIoFAST16;
606 if (name[3] == 'u')
607 return PRIuFAST16;
608 if (name[3] == 'x')
609 return PRIxFAST16;
610 if (name[3] == 'X')
611 return PRIXFAST16;
612 abort ();
613 }
614 if (name[8] == '3' && name[9] == '2' && name[10] == '\0')
615 {
616 if (name[3] == 'd')
617 return PRIdFAST32;
618 if (name[3] == 'i')
619 return PRIiFAST32;
620 if (name[3] == 'o')
621 return PRIoFAST32;
622 if (name[3] == 'u')
623 return PRIuFAST32;
624 if (name[3] == 'x')
625 return PRIxFAST32;
626 if (name[3] == 'X')
627 return PRIXFAST32;
628 abort ();
629 }
630 if (name[8] == '6' && name[9] == '4' && name[10] == '\0')
631 {
632 if (name[3] == 'd')
633 return PRIdFAST64;
634 if (name[3] == 'i')
635 return PRIiFAST64;
636 if (name[3] == 'o')
637 return PRIoFAST64;
638 if (name[3] == 'u')
639 return PRIuFAST64;
640 if (name[3] == 'x')
641 return PRIxFAST64;
642 if (name[3] == 'X')
643 return PRIXFAST64;
644 abort ();
645 }
646 }
647 if (name[4] == 'M' && name[5] == 'A' && name[6] == 'X'
648 && name[7] == '\0')
649 {
650 if (name[3] == 'd')
651 return PRIdMAX;
652 if (name[3] == 'i')
653 return PRIiMAX;
654 if (name[3] == 'o')
655 return PRIoMAX;
656 if (name[3] == 'u')
657 return PRIuMAX;
658 if (name[3] == 'x')
659 return PRIxMAX;
660 if (name[3] == 'X')
661 return PRIXMAX;
662 abort ();
663 }
664 if (name[4] == 'P' && name[5] == 'T' && name[6] == 'R'
665 && name[7] == '\0')
666 {
667 if (name[3] == 'd')
668 return PRIdPTR;
669 if (name[3] == 'i')
670 return PRIiPTR;
671 if (name[3] == 'o')
672 return PRIoPTR;
673 if (name[3] == 'u')
674 return PRIuPTR;
675 if (name[3] == 'x')
676 return PRIxPTR;
677 if (name[3] == 'X')
678 return PRIXPTR;
679 abort ();
680 }
681 }
682 }
683 /* Test for a glibc specific printf() format directive flag. */
684 if (name[0] == 'I' && name[1] == '\0')
685 {
686 #if defined _LIBC \
687 || ((__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)) \
688 && !defined __UCLIBC__)
689 /* The 'I' flag, in numeric format directives, replaces ASCII digits
690 with the 'outdigits' defined in the LC_CTYPE locale facet. This is
691 used for Farsi (Persian), some Indic languages, and maybe Arabic. */
692 return "I";
693 #else
694 return "";
695 #endif
696 }
697 /* Other system dependent strings are not valid. */
698 return NULL;
699 }
700
701 /* Lock that protects the various 'struct loaded_l10nfile' objects. */
702 __libc_lock_define_initialized_recursive (static, lock);
703
704 /* Load the message catalogs specified by FILENAME. If it is no valid
705 message catalog do nothing. */
706 void
707 internal_function
_nl_load_domain(struct loaded_l10nfile * domain_file,struct binding * domainbinding)708 _nl_load_domain (struct loaded_l10nfile *domain_file,
709 struct binding *domainbinding)
710 {
711 int fd = -1;
712 size_t size;
713 #ifdef _LIBC
714 struct stat64 st;
715 #else
716 struct stat st;
717 #endif
718 struct mo_file_header *data = (struct mo_file_header *) -1;
719 int use_mmap = 0;
720 struct loaded_domain *domain;
721 int revision;
722 const char *nullentry;
723 size_t nullentrylen;
724
725 __libc_lock_lock_recursive (lock);
726 if (domain_file->decided != 0)
727 {
728 /* There are two possibilities:
729
730 + this is the same thread calling again during this initialization
731 via _nl_find_msg. We have initialized everything this call needs.
732
733 + this is another thread which tried to initialize this object.
734 Not necessary anymore since if the lock is available this
735 is finished.
736 */
737 goto done;
738 }
739
740 domain_file->decided = -1;
741 domain_file->data = NULL;
742
743 /* Note that it would be useless to store domainbinding in domain_file
744 because domainbinding might be == NULL now but != NULL later (after
745 a call to bind_textdomain_codeset). */
746
747 /* If the record does not represent a valid locale the FILENAME
748 might be NULL. This can happen when according to the given
749 specification the locale file name is different for XPG and CEN
750 syntax. */
751 if (domain_file->filename != NULL)
752 {
753 /* Try to open the addressed file. */
754 fd = open (domain_file->filename, O_RDONLY | O_BINARY);
755 if (fd == -1)
756 goto out;
757 }
758 #if defined _WIN32 && !defined __CYGWIN__
759 else if (domain_file->wfilename != NULL)
760 {
761 /* Try to open the addressed file. */
762 fd = _wopen (domain_file->wfilename, O_RDONLY | O_BINARY);
763 if (fd == -1)
764 goto out;
765 }
766 #endif
767 else
768 goto out;
769
770 /* We must know about the size of the file. */
771 if (
772 #ifdef _LIBC
773 __builtin_expect (fstat64 (fd, &st) != 0, 0)
774 #else
775 __builtin_expect (fstat (fd, &st) != 0, 0)
776 #endif
777 || __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0)
778 || __builtin_expect (size < sizeof (struct mo_file_header), 0))
779 /* Something went wrong. */
780 goto out;
781
782 #ifdef HAVE_MMAP
783 /* Now we are ready to load the file. If mmap() is available we try
784 this first. If not available or it failed we try to load it. */
785 data = (struct mo_file_header *) mmap (NULL, size, PROT_READ,
786 MAP_PRIVATE, fd, 0);
787
788 if (__builtin_expect (data != MAP_FAILED, 1))
789 {
790 /* mmap() call was successful. */
791 close (fd);
792 fd = -1;
793 use_mmap = 1;
794 }
795
796 assert (MAP_FAILED == (void *) -1);
797 #endif
798
799 /* If the data is not yet available (i.e. mmap'ed) we try to load
800 it manually. */
801 if (data == (struct mo_file_header *) -1)
802 {
803 size_t to_read;
804 char *read_ptr;
805
806 data = (struct mo_file_header *) malloc (size);
807 if (data == NULL)
808 goto out;
809
810 to_read = size;
811 read_ptr = (char *) data;
812 do
813 {
814 long int nb = (long int) read (fd, read_ptr, to_read);
815 if (nb <= 0)
816 {
817 #ifdef EINTR
818 if (nb == -1 && errno == EINTR)
819 continue;
820 #endif
821 free (data);
822 goto out;
823 }
824 read_ptr += nb;
825 to_read -= nb;
826 }
827 while (to_read > 0);
828
829 close (fd);
830 fd = -1;
831 }
832
833 /* Using the magic number we can test whether it really is a message
834 catalog file. */
835 if (__builtin_expect (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED,
836 0))
837 {
838 /* The magic number is wrong: not a message catalog file. */
839 #ifdef HAVE_MMAP
840 if (use_mmap)
841 munmap ((caddr_t) data, size);
842 else
843 #endif
844 free (data);
845 goto out;
846 }
847
848 domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
849 if (domain == NULL)
850 {
851 #ifdef HAVE_MMAP
852 if (use_mmap)
853 munmap ((caddr_t) data, size);
854 else
855 #endif
856 free (data);
857 goto out;
858 }
859 domain_file->data = domain;
860
861 domain->data = (char *) data;
862 domain->use_mmap = use_mmap;
863 domain->mmap_size = size;
864 domain->must_swap = data->magic != _MAGIC;
865 domain->malloced = NULL;
866
867 /* Fill in the information about the available tables. */
868 revision = W (domain->must_swap, data->revision);
869 /* We support only the major revisions 0 and 1. */
870 switch (revision >> 16)
871 {
872 case 0:
873 case 1:
874 domain->nstrings = W (domain->must_swap, data->nstrings);
875 domain->orig_tab = (const struct string_desc *)
876 ((char *) data + W (domain->must_swap, data->orig_tab_offset));
877 domain->trans_tab = (const struct string_desc *)
878 ((char *) data + W (domain->must_swap, data->trans_tab_offset));
879 domain->hash_size = W (domain->must_swap, data->hash_tab_size);
880 domain->hash_tab =
881 (domain->hash_size > 2
882 ? (const nls_uint32 *)
883 ((char *) data + W (domain->must_swap, data->hash_tab_offset))
884 : NULL);
885 domain->must_swap_hash_tab = domain->must_swap;
886
887 /* Now dispatch on the minor revision. */
888 switch (revision & 0xffff)
889 {
890 case 0:
891 domain->n_sysdep_strings = 0;
892 domain->orig_sysdep_tab = NULL;
893 domain->trans_sysdep_tab = NULL;
894 break;
895 case 1:
896 default:
897 {
898 nls_uint32 n_sysdep_strings;
899
900 if (domain->hash_tab == NULL)
901 /* This is invalid. These minor revisions need a hash table. */
902 goto invalid;
903
904 n_sysdep_strings =
905 W (domain->must_swap, data->n_sysdep_strings);
906 if (n_sysdep_strings > 0)
907 {
908 nls_uint32 n_sysdep_segments;
909 const struct sysdep_segment *sysdep_segments;
910 const char **sysdep_segment_values;
911 const nls_uint32 *orig_sysdep_tab;
912 const nls_uint32 *trans_sysdep_tab;
913 nls_uint32 n_inmem_sysdep_strings;
914 size_t memneed;
915 char *mem;
916 struct sysdep_string_desc *inmem_orig_sysdep_tab;
917 struct sysdep_string_desc *inmem_trans_sysdep_tab;
918 nls_uint32 *inmem_hash_tab;
919 unsigned int i, j;
920
921 /* Get the values of the system dependent segments. */
922 n_sysdep_segments =
923 W (domain->must_swap, data->n_sysdep_segments);
924 sysdep_segments = (const struct sysdep_segment *)
925 ((char *) data
926 + W (domain->must_swap, data->sysdep_segments_offset));
927 sysdep_segment_values =
928 (const char **)
929 alloca (n_sysdep_segments * sizeof (const char *));
930 for (i = 0; i < n_sysdep_segments; i++)
931 {
932 const char *name =
933 (char *) data
934 + W (domain->must_swap, sysdep_segments[i].offset);
935 nls_uint32 namelen =
936 W (domain->must_swap, sysdep_segments[i].length);
937
938 if (!(namelen > 0 && name[namelen - 1] == '\0'))
939 {
940 freea (sysdep_segment_values);
941 goto invalid;
942 }
943
944 sysdep_segment_values[i] = get_sysdep_segment_value (name);
945 }
946
947 orig_sysdep_tab = (const nls_uint32 *)
948 ((char *) data
949 + W (domain->must_swap, data->orig_sysdep_tab_offset));
950 trans_sysdep_tab = (const nls_uint32 *)
951 ((char *) data
952 + W (domain->must_swap, data->trans_sysdep_tab_offset));
953
954 /* Compute the amount of additional memory needed for the
955 system dependent strings and the augmented hash table.
956 At the same time, also drop string pairs which refer to
957 an undefined system dependent segment. */
958 n_inmem_sysdep_strings = 0;
959 memneed = domain->hash_size * sizeof (nls_uint32);
960 for (i = 0; i < n_sysdep_strings; i++)
961 {
962 int valid = 1;
963 size_t needs[2];
964
965 for (j = 0; j < 2; j++)
966 {
967 const struct sysdep_string *sysdep_string =
968 (const struct sysdep_string *)
969 ((char *) data
970 + W (domain->must_swap,
971 j == 0
972 ? orig_sysdep_tab[i]
973 : trans_sysdep_tab[i]));
974 size_t need = 0;
975 const char *static_segments =
976 (char *) data
977 + W (domain->must_swap, sysdep_string->offset);
978 const struct segment_pair *p = sysdep_string->segments;
979
980 if (W (domain->must_swap, p->sysdepref) != SEGMENTS_END)
981 for (;; p++)
982 {
983 nls_uint32 segsize;
984 nls_uint32 sysdepref;
985
986 segsize = W (domain->must_swap, p->segsize);
987 need += segsize;
988
989 sysdepref = W (domain->must_swap, p->sysdepref);
990 if (sysdepref == SEGMENTS_END)
991 break;
992
993 static_segments += segsize;
994
995 if (sysdepref >= n_sysdep_segments)
996 {
997 /* Invalid. */
998 freea (sysdep_segment_values);
999 goto invalid;
1000 }
1001
1002 if (sysdep_segment_values[sysdepref] == NULL)
1003 {
1004 /* This particular string pair is invalid. */
1005 valid = 0;
1006 }
1007
1008 need += strlen (sysdep_segment_values[sysdepref]);
1009 }
1010
1011 /* The last static segment must end in a NUL. */
1012 {
1013 nls_uint32 segsize =
1014 W (domain->must_swap, p->segsize);
1015
1016 if (!(segsize > 0
1017 && static_segments[segsize - 1] == '\0'))
1018 {
1019 /* Invalid. */
1020 freea (sysdep_segment_values);
1021 goto invalid;
1022 }
1023 }
1024
1025 needs[j] = need;
1026 if (!valid)
1027 break;
1028 }
1029
1030 if (valid)
1031 {
1032 n_inmem_sysdep_strings++;
1033 memneed += needs[0] + needs[1];
1034 }
1035 }
1036 memneed += 2 * n_inmem_sysdep_strings
1037 * sizeof (struct sysdep_string_desc);
1038
1039 if (n_inmem_sysdep_strings > 0)
1040 {
1041 unsigned int k;
1042
1043 /* Allocate additional memory. */
1044 mem = (char *) malloc (memneed);
1045 if (mem == NULL)
1046 goto invalid;
1047
1048 domain->malloced = mem;
1049 inmem_orig_sysdep_tab = (struct sysdep_string_desc *) mem;
1050 mem += n_inmem_sysdep_strings
1051 * sizeof (struct sysdep_string_desc);
1052 inmem_trans_sysdep_tab = (struct sysdep_string_desc *) mem;
1053 mem += n_inmem_sysdep_strings
1054 * sizeof (struct sysdep_string_desc);
1055 inmem_hash_tab = (nls_uint32 *) mem;
1056 mem += domain->hash_size * sizeof (nls_uint32);
1057
1058 /* Compute the system dependent strings. */
1059 k = 0;
1060 for (i = 0; i < n_sysdep_strings; i++)
1061 {
1062 int valid = 1;
1063
1064 for (j = 0; j < 2; j++)
1065 {
1066 const struct sysdep_string *sysdep_string =
1067 (const struct sysdep_string *)
1068 ((char *) data
1069 + W (domain->must_swap,
1070 j == 0
1071 ? orig_sysdep_tab[i]
1072 : trans_sysdep_tab[i]));
1073 const struct segment_pair *p =
1074 sysdep_string->segments;
1075
1076 if (W (domain->must_swap, p->sysdepref)
1077 != SEGMENTS_END)
1078 for (;; p++)
1079 {
1080 nls_uint32 sysdepref;
1081
1082 sysdepref =
1083 W (domain->must_swap, p->sysdepref);
1084 if (sysdepref == SEGMENTS_END)
1085 break;
1086
1087 if (sysdep_segment_values[sysdepref] == NULL)
1088 {
1089 /* This particular string pair is
1090 invalid. */
1091 valid = 0;
1092 break;
1093 }
1094 }
1095
1096 if (!valid)
1097 break;
1098 }
1099
1100 if (valid)
1101 {
1102 for (j = 0; j < 2; j++)
1103 {
1104 const struct sysdep_string *sysdep_string =
1105 (const struct sysdep_string *)
1106 ((char *) data
1107 + W (domain->must_swap,
1108 j == 0
1109 ? orig_sysdep_tab[i]
1110 : trans_sysdep_tab[i]));
1111 const char *static_segments =
1112 (char *) data
1113 + W (domain->must_swap, sysdep_string->offset);
1114 const struct segment_pair *p =
1115 sysdep_string->segments;
1116
1117 /* Concatenate the segments, and fill
1118 inmem_orig_sysdep_tab[k] (for j == 0) and
1119 inmem_trans_sysdep_tab[k] (for j == 1). */
1120
1121 struct sysdep_string_desc *inmem_tab_entry =
1122 (j == 0
1123 ? inmem_orig_sysdep_tab
1124 : inmem_trans_sysdep_tab)
1125 + k;
1126
1127 if (W (domain->must_swap, p->sysdepref)
1128 == SEGMENTS_END)
1129 {
1130 /* Only one static segment. */
1131 inmem_tab_entry->length =
1132 W (domain->must_swap, p->segsize);
1133 inmem_tab_entry->pointer = static_segments;
1134 }
1135 else
1136 {
1137 inmem_tab_entry->pointer = mem;
1138
1139 for (;; p++)
1140 {
1141 nls_uint32 segsize =
1142 W (domain->must_swap, p->segsize);
1143 nls_uint32 sysdepref =
1144 W (domain->must_swap, p->sysdepref);
1145 size_t n;
1146
1147 if (segsize > 0)
1148 {
1149 memcpy (mem, static_segments, segsize);
1150 mem += segsize;
1151 static_segments += segsize;
1152 }
1153
1154 if (sysdepref == SEGMENTS_END)
1155 break;
1156
1157 n = strlen (sysdep_segment_values[sysdepref]);
1158 memcpy (mem, sysdep_segment_values[sysdepref], n);
1159 mem += n;
1160 }
1161
1162 inmem_tab_entry->length =
1163 mem - inmem_tab_entry->pointer;
1164 }
1165 }
1166
1167 k++;
1168 }
1169 }
1170 if (k != n_inmem_sysdep_strings)
1171 abort ();
1172
1173 /* Compute the augmented hash table. */
1174 for (i = 0; i < domain->hash_size; i++)
1175 inmem_hash_tab[i] =
1176 W (domain->must_swap_hash_tab, domain->hash_tab[i]);
1177 for (i = 0; i < n_inmem_sysdep_strings; i++)
1178 {
1179 const char *msgid = inmem_orig_sysdep_tab[i].pointer;
1180 nls_uint32 hash_val = __hash_string (msgid);
1181 nls_uint32 idx = hash_val % domain->hash_size;
1182 nls_uint32 incr =
1183 1 + (hash_val % (domain->hash_size - 2));
1184
1185 for (;;)
1186 {
1187 if (inmem_hash_tab[idx] == 0)
1188 {
1189 /* Hash table entry is empty. Use it. */
1190 inmem_hash_tab[idx] = 1 + domain->nstrings + i;
1191 break;
1192 }
1193
1194 if (idx >= domain->hash_size - incr)
1195 idx -= domain->hash_size - incr;
1196 else
1197 idx += incr;
1198 }
1199 }
1200
1201 domain->n_sysdep_strings = n_inmem_sysdep_strings;
1202 domain->orig_sysdep_tab = inmem_orig_sysdep_tab;
1203 domain->trans_sysdep_tab = inmem_trans_sysdep_tab;
1204
1205 domain->hash_tab = inmem_hash_tab;
1206 domain->must_swap_hash_tab = 0;
1207 }
1208 else
1209 {
1210 domain->n_sysdep_strings = 0;
1211 domain->orig_sysdep_tab = NULL;
1212 domain->trans_sysdep_tab = NULL;
1213 }
1214
1215 freea (sysdep_segment_values);
1216 }
1217 else
1218 {
1219 domain->n_sysdep_strings = 0;
1220 domain->orig_sysdep_tab = NULL;
1221 domain->trans_sysdep_tab = NULL;
1222 }
1223 }
1224 break;
1225 }
1226 break;
1227 default:
1228 /* This is an invalid revision. */
1229 invalid:
1230 /* This is an invalid .mo file or we ran out of resources. */
1231 free (domain->malloced);
1232 #ifdef HAVE_MMAP
1233 if (use_mmap)
1234 munmap ((caddr_t) data, size);
1235 else
1236 #endif
1237 free (data);
1238 free (domain);
1239 domain_file->data = NULL;
1240 goto out;
1241 }
1242
1243 /* No caches of converted translations so far. */
1244 domain->conversions = NULL;
1245 domain->nconversions = 0;
1246 #ifdef _LIBC
1247 __libc_rwlock_init (domain->conversions_lock);
1248 #else
1249 gl_rwlock_init (domain->conversions_lock);
1250 #endif
1251
1252 /* Get the header entry and look for a plural specification. */
1253 #ifdef IN_LIBGLOCALE
1254 nullentry =
1255 _nl_find_msg (domain_file, domainbinding, NULL, "", &nullentrylen);
1256 #else
1257 nullentry = _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen);
1258 #endif
1259 if (__builtin_expect (nullentry == (char *) -1, 0))
1260 {
1261 #ifdef _LIBC
1262 __libc_rwlock_fini (domain->conversions_lock);
1263 #else
1264 gl_rwlock_destroy (domain->conversions_lock);
1265 #endif
1266 goto invalid;
1267 }
1268 EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals);
1269
1270 out:
1271 if (fd != -1)
1272 close (fd);
1273
1274 domain_file->decided = 1;
1275
1276 done:
1277 __libc_lock_unlock_recursive (lock);
1278 }
1279
1280
1281 #ifdef _LIBC
1282 void
1283 internal_function __libc_freeres_fn_section
_nl_unload_domain(struct loaded_domain * domain)1284 _nl_unload_domain (struct loaded_domain *domain)
1285 {
1286 size_t i;
1287
1288 if (domain->plural != &__gettext_germanic_plural)
1289 __gettext_free_exp ((struct expression *) domain->plural);
1290
1291 for (i = 0; i < domain->nconversions; i++)
1292 {
1293 struct converted_domain *convd = &domain->conversions[i];
1294
1295 free ((char *) convd->encoding);
1296 if (convd->conv_tab != NULL && convd->conv_tab != (char **) -1)
1297 free (convd->conv_tab);
1298 if (convd->conv != (__gconv_t) -1)
1299 __gconv_close (convd->conv);
1300 }
1301 free (domain->conversions);
1302 __libc_rwlock_fini (domain->conversions_lock);
1303
1304 free (domain->malloced);
1305
1306 # ifdef _POSIX_MAPPED_FILES
1307 if (domain->use_mmap)
1308 munmap ((caddr_t) domain->data, domain->mmap_size);
1309 else
1310 # endif /* _POSIX_MAPPED_FILES */
1311 free ((void *) domain->data);
1312
1313 free (domain);
1314 }
1315 #endif
1316