Lines 43-52
Link Here
|
43 |
|
43 |
|
44 |
#include "localeinfo.h" |
44 |
#include "localeinfo.h" |
45 |
#include "charmap-dir.h" |
45 |
#include "charmap-dir.h" |
|
|
46 |
#include "../locarchive.h" |
46 |
|
47 |
|
47 |
extern void *xmalloc (size_t __n); |
48 |
extern void *xmalloc (size_t __n); |
48 |
extern char *xstrdup (const char *__str); |
49 |
extern char *xstrdup (const char *__str); |
49 |
|
50 |
|
|
|
51 |
#define ARCHIVE_NAME LOCALEDIR "/locale-archive" |
50 |
|
52 |
|
51 |
/* If set print the name of the category. */ |
53 |
/* If set print the name of the category. */ |
52 |
static int show_category_name; |
54 |
static int show_category_name; |
Lines 168-174
Link Here
|
168 |
int show_keyword_name); |
170 |
int show_keyword_name); |
169 |
|
171 |
|
170 |
/* Prototypes for local functions. */ |
172 |
/* Prototypes for local functions. */ |
|
|
173 |
static void print_LC_IDENTIFICATION (void *mapped, size_t size); |
174 |
static void print_LC_CTYPE (void *mapped, size_t size); |
171 |
static void write_locales (void); |
175 |
static void write_locales (void); |
|
|
176 |
static int nameentcmp (const void *a, const void *b); |
177 |
static int write_archive_locales (void **all_datap, char *linebuf); |
172 |
static void write_charmaps (void); |
178 |
static void write_charmaps (void); |
173 |
static void show_locale_vars (void); |
179 |
static void show_locale_vars (void); |
174 |
static void show_info (const char *name); |
180 |
static void show_info (const char *name); |
Lines 327-332
Link Here
|
327 |
} |
333 |
} |
328 |
|
334 |
|
329 |
|
335 |
|
|
|
336 |
static void |
337 |
print_LC_IDENTIFICATION (void *mapped, size_t size) |
338 |
{ |
339 |
/* Read the information from the file. */ |
340 |
struct |
341 |
{ |
342 |
unsigned int magic; |
343 |
unsigned int nstrings; |
344 |
unsigned int strindex[0]; |
345 |
} *filedata = mapped; |
346 |
|
347 |
if (filedata->magic == LIMAGIC (LC_IDENTIFICATION) |
348 |
&& (sizeof *filedata |
349 |
+ (filedata->nstrings |
350 |
* sizeof (unsigned int)) |
351 |
<= size)) |
352 |
{ |
353 |
const char *str; |
354 |
|
355 |
#define HANDLE(idx, name) \ |
356 |
str = ((char *) mapped \ |
357 |
+ filedata->strindex[_NL_ITEM_INDEX (_NL_IDENTIFICATION_##idx)]); \ |
358 |
if (*str != '\0') \ |
359 |
printf ("%9s | %s\n", name, str) |
360 |
HANDLE (TITLE, "title"); |
361 |
HANDLE (SOURCE, "source"); |
362 |
HANDLE (ADDRESS, "address"); |
363 |
HANDLE (CONTACT, "contact"); |
364 |
HANDLE (EMAIL, "email"); |
365 |
HANDLE (TEL, "telephone"); |
366 |
HANDLE (FAX, "fax"); |
367 |
HANDLE (LANGUAGE, "language"); |
368 |
HANDLE (TERRITORY, "territory"); |
369 |
HANDLE (AUDIENCE, "audience"); |
370 |
HANDLE (APPLICATION, "application"); |
371 |
HANDLE (ABBREVIATION, "abbreviation"); |
372 |
HANDLE (REVISION, "revision"); |
373 |
HANDLE (DATE, "date"); |
374 |
} |
375 |
} |
376 |
|
377 |
|
378 |
static void |
379 |
print_LC_CTYPE (void *mapped, size_t size) |
380 |
{ |
381 |
struct |
382 |
{ |
383 |
unsigned int magic; |
384 |
unsigned int nstrings; |
385 |
unsigned int strindex[0]; |
386 |
} *filedata = mapped; |
387 |
|
388 |
if (filedata->magic == LIMAGIC (LC_CTYPE) |
389 |
&& (sizeof *filedata |
390 |
+ (filedata->nstrings |
391 |
* sizeof (unsigned int)) |
392 |
<= size)) |
393 |
{ |
394 |
const char *str; |
395 |
|
396 |
str = ((char *) mapped |
397 |
+ filedata->strindex[_NL_ITEM_INDEX (_NL_CTYPE_CODESET_NAME)]); |
398 |
if (*str != '\0') |
399 |
printf (" codeset | %s\n", str); |
400 |
} |
401 |
} |
402 |
|
403 |
|
330 |
/* Write the names of all available locales to stdout. We have some |
404 |
/* Write the names of all available locales to stdout. We have some |
331 |
sources of the information: the contents of the locale directory |
405 |
sources of the information: the contents of the locale directory |
332 |
and the locale.alias file. To avoid duplicates and print the |
406 |
and the locale.alias file. To avoid duplicates and print the |
Lines 358-363
Link Here
|
358 |
memset (linebuf, '-', sizeof (linebuf) - 1); |
432 |
memset (linebuf, '-', sizeof (linebuf) - 1); |
359 |
linebuf[sizeof (linebuf) - 1] = '\0'; |
433 |
linebuf[sizeof (linebuf) - 1] = '\0'; |
360 |
|
434 |
|
|
|
435 |
/* First scan the locale archive. */ |
436 |
if (write_archive_locales (&all_data, linebuf)) |
437 |
first_locale = 0; |
438 |
|
361 |
/* Now we can look for all files in the directory. */ |
439 |
/* Now we can look for all files in the directory. */ |
362 |
ndirents = scandir (LOCALEDIR, &dirents, select_dirs, alphasort); |
440 |
ndirents = scandir (LOCALEDIR, &dirents, select_dirs, alphasort); |
363 |
for (cnt = 0; cnt < ndirents; ++cnt) |
441 |
for (cnt = 0; cnt < ndirents; ++cnt) |
Lines 375-381
Link Here
|
375 |
|
453 |
|
376 |
if (stat64 (buf, &st) == 0 && S_ISREG (st.st_mode)) |
454 |
if (stat64 (buf, &st) == 0 && S_ISREG (st.st_mode)) |
377 |
{ |
455 |
{ |
378 |
if (verbose) |
456 |
if (verbose && GET (dirents[cnt]->d_name) == NULL) |
379 |
{ |
457 |
{ |
380 |
/* Provide some nice output of all kinds of |
458 |
/* Provide some nice output of all kinds of |
381 |
information. */ |
459 |
information. */ |
Lines 396-437
Link Here
|
396 |
MAP_SHARED, fd, 0); |
474 |
MAP_SHARED, fd, 0); |
397 |
if (mapped != MAP_FAILED) |
475 |
if (mapped != MAP_FAILED) |
398 |
{ |
476 |
{ |
399 |
/* Read the information from the file. */ |
477 |
print_LC_IDENTIFICATION (mapped, st.st_size); |
400 |
struct |
|
|
401 |
{ |
402 |
unsigned int magic; |
403 |
unsigned int nstrings; |
404 |
unsigned int strindex[0]; |
405 |
} *filedata = mapped; |
406 |
|
407 |
if (filedata->magic == LIMAGIC (LC_IDENTIFICATION) |
408 |
&& (sizeof *filedata |
409 |
+ (filedata->nstrings |
410 |
* sizeof (unsigned int)) |
411 |
<= (size_t) st.st_size)) |
412 |
{ |
413 |
const char *str; |
414 |
|
415 |
#define HANDLE(idx, name) \ |
416 |
str = ((char *) mapped \ |
417 |
+ filedata->strindex[_NL_ITEM_INDEX (_NL_IDENTIFICATION_##idx)]); \ |
418 |
if (*str != '\0') \ |
419 |
printf ("%9s | %s\n", name, str) |
420 |
HANDLE (TITLE, "title"); |
421 |
HANDLE (SOURCE, "source"); |
422 |
HANDLE (ADDRESS, "address"); |
423 |
HANDLE (CONTACT, "contact"); |
424 |
HANDLE (EMAIL, "email"); |
425 |
HANDLE (TEL, "telephone"); |
426 |
HANDLE (FAX, "fax"); |
427 |
HANDLE (LANGUAGE, "language"); |
428 |
HANDLE (TERRITORY, "territory"); |
429 |
HANDLE (AUDIENCE, "audience"); |
430 |
HANDLE (APPLICATION, "application"); |
431 |
HANDLE (ABBREVIATION, "abbreviation"); |
432 |
HANDLE (REVISION, "revision"); |
433 |
HANDLE (DATE, "date"); |
434 |
} |
435 |
|
478 |
|
436 |
munmap (mapped, st.st_size); |
479 |
munmap (mapped, st.st_size); |
437 |
} |
480 |
} |
Lines 446-471
Link Here
|
446 |
MAP_SHARED, fd, 0)) |
489 |
MAP_SHARED, fd, 0)) |
447 |
!= MAP_FAILED)) |
490 |
!= MAP_FAILED)) |
448 |
{ |
491 |
{ |
449 |
struct |
492 |
print_LC_CTYPE (mapped, st.st_size); |
450 |
{ |
|
|
451 |
unsigned int magic; |
452 |
unsigned int nstrings; |
453 |
unsigned int strindex[0]; |
454 |
} *filedata = mapped; |
455 |
|
456 |
if (filedata->magic == LIMAGIC (LC_CTYPE) |
457 |
&& (sizeof *filedata |
458 |
+ (filedata->nstrings |
459 |
* sizeof (unsigned int)) |
460 |
<= (size_t) st.st_size)) |
461 |
{ |
462 |
const char *str; |
463 |
|
464 |
str = ((char *) mapped |
465 |
+ filedata->strindex[_NL_ITEM_INDEX (_NL_CTYPE_CODESET_NAME)]); |
466 |
if (*str != '\0') |
467 |
printf (" codeset | %s\n", str); |
468 |
} |
469 |
|
493 |
|
470 |
munmap (mapped, st.st_size); |
494 |
munmap (mapped, st.st_size); |
471 |
} |
495 |
} |
Lines 474-483
Link Here
|
474 |
close (fd); |
498 |
close (fd); |
475 |
} |
499 |
} |
476 |
} |
500 |
} |
477 |
else |
501 |
|
478 |
/* If the verbose format is not selected we simply |
502 |
/* If the verbose format is not selected we simply |
479 |
collect the names. */ |
503 |
collect the names. */ |
480 |
PUT (xstrdup (dirents[cnt]->d_name)); |
504 |
PUT (xstrdup (dirents[cnt]->d_name)); |
481 |
} |
505 |
} |
482 |
} |
506 |
} |
483 |
if (ndirents > 0) |
507 |
if (ndirents > 0) |
Lines 584-589
Link Here
|
584 |
} |
608 |
} |
585 |
|
609 |
|
586 |
|
610 |
|
|
|
611 |
struct nameent |
612 |
{ |
613 |
char *name; |
614 |
uint32_t locrec_offset; |
615 |
}; |
616 |
|
617 |
|
618 |
static int |
619 |
nameentcmp (const void *a, const void *b) |
620 |
{ |
621 |
return strcoll (((const struct nameent *) a)->name, |
622 |
((const struct nameent *) b)->name); |
623 |
} |
624 |
|
625 |
|
626 |
static int |
627 |
write_archive_locales (void **all_datap, char *linebuf) |
628 |
{ |
629 |
struct stat64 st; |
630 |
void *all_data = *all_datap; |
631 |
size_t len = 0; |
632 |
struct locarhead *head; |
633 |
struct namehashent *namehashtab; |
634 |
char *addr = MAP_FAILED; |
635 |
int fd, ret = 0; |
636 |
uint32_t cnt; |
637 |
|
638 |
fd = open64 (ARCHIVE_NAME, O_RDONLY); |
639 |
if (fd < 0) |
640 |
return 0; |
641 |
|
642 |
if (fstat64 (fd, &st) < 0 || st.st_size < sizeof (*head)) |
643 |
goto error_out; |
644 |
|
645 |
len = st.st_size; |
646 |
addr = mmap64 (NULL, len, PROT_READ, MAP_SHARED, fd, 0); |
647 |
if (addr == MAP_FAILED) |
648 |
goto error_out; |
649 |
|
650 |
head = (struct locarhead *) addr; |
651 |
if (head->namehash_offset + head->namehash_size > len |
652 |
|| head->string_offset + head->string_size > len |
653 |
|| head->locrectab_offset + head->locrectab_size > len |
654 |
|| head->sumhash_offset + head->sumhash_size > len) |
655 |
goto error_out; |
656 |
|
657 |
namehashtab = (struct namehashent *) (addr + head->namehash_offset); |
658 |
if (! verbose) |
659 |
{ |
660 |
for (cnt = 0; cnt < head->namehash_size; ++cnt) |
661 |
if (namehashtab[cnt].locrec_offset != 0) |
662 |
{ |
663 |
PUT (xstrdup (addr + namehashtab[cnt].name_offset)); |
664 |
++ret; |
665 |
} |
666 |
} |
667 |
else |
668 |
{ |
669 |
struct nameent *names; |
670 |
uint32_t used; |
671 |
|
672 |
names = (struct nameent *) xmalloc (head->namehash_used |
673 |
* sizeof (struct nameent)); |
674 |
for (cnt = used = 0; cnt < head->namehash_size; ++cnt) |
675 |
if (namehashtab[cnt].locrec_offset != 0) |
676 |
{ |
677 |
names[used].name = addr + namehashtab[cnt].name_offset; |
678 |
names[used++].locrec_offset = namehashtab[cnt].locrec_offset; |
679 |
} |
680 |
|
681 |
/* Sort the names. */ |
682 |
qsort (names, used, sizeof (struct nameent), nameentcmp); |
683 |
|
684 |
for (cnt = 0; cnt < used; ++cnt) |
685 |
{ |
686 |
struct locrecent *locrec; |
687 |
|
688 |
PUT (xstrdup (names[cnt].name)); |
689 |
|
690 |
if (cnt) |
691 |
putchar_unlocked ('\n'); |
692 |
|
693 |
printf ("locale: %-15.15s archive: " ARCHIVE_NAME "\n%s\n", |
694 |
names[cnt].name, linebuf); |
695 |
|
696 |
locrec = (struct locrecent *) (addr + names[cnt].locrec_offset); |
697 |
|
698 |
print_LC_IDENTIFICATION (addr |
699 |
+ locrec->record[LC_IDENTIFICATION].offset, |
700 |
locrec->record[LC_IDENTIFICATION].len); |
701 |
|
702 |
print_LC_CTYPE (addr + locrec->record[LC_CTYPE].offset, |
703 |
locrec->record[LC_CTYPE].len); |
704 |
} |
705 |
|
706 |
ret = used; |
707 |
} |
708 |
|
709 |
error_out: |
710 |
if (addr != MAP_FAILED) |
711 |
munmap (addr, len); |
712 |
close (fd); |
713 |
*all_datap = all_data; |
714 |
return ret; |
715 |
} |
716 |
|
717 |
|
587 |
/* Write the names of all available character maps to stdout. */ |
718 |
/* Write the names of all available character maps to stdout. */ |
588 |
static void |
719 |
static void |
589 |
write_charmaps (void) |
720 |
write_charmaps (void) |