|
|
bca718 |
Adds --install-langs support build-locale-archive.
|
|
|
bca718 |
|
|
|
bca718 |
commit 0457f649e3fe6299efe384da13dfc923bbe65707
|
|
|
bca718 |
Author: Carlos O'Donell <carlos@systemhalted.org>
|
|
|
bca718 |
Date: Thu Sep 17 12:24:49 2015 -0400
|
|
|
bca718 |
|
|
|
bca718 |
[snip]
|
|
|
bca718 |
- Fix --install-langs bug which causes SIGABRT (#1262040).
|
|
|
bca718 |
|
|
|
bca718 |
commit 91764bd9ec690d4b8a886c0a3a104aac12d340d2
|
|
|
bca718 |
Author: Carlos O'Donell <carlos@systemhalted.org>
|
|
|
bca718 |
Date: Thu Mar 5 16:05:43 2015 -0500
|
|
|
bca718 |
|
|
|
bca718 |
Resolves: #156477
|
|
|
bca718 |
|
|
|
bca718 |
- Support installing only those locales specified by the RPM macro
|
|
|
bca718 |
%%_install_langs (#156477).
|
|
|
bca718 |
|
|
|
bca718 |
Index: glibc-2.17-c758a686/releng/build-locale-archive.c
|
|
|
bca718 |
===================================================================
|
|
|
bca718 |
--- glibc-2.17-c758a686.orig/releng/build-locale-archive.c
|
|
|
bca718 |
+++ glibc-2.17-c758a686/releng/build-locale-archive.c
|
|
|
bca718 |
@@ -8,6 +8,7 @@
|
|
|
bca718 |
#include <stdbool.h>
|
|
|
bca718 |
#include <stdio.h>
|
|
|
bca718 |
#include <stdlib.h>
|
|
|
bca718 |
+#include <getopt.h>
|
|
|
bca718 |
#include <string.h>
|
|
|
bca718 |
#include <sys/mman.h>
|
|
|
bca718 |
#include <sys/stat.h>
|
|
|
bca718 |
@@ -21,6 +22,7 @@ const char *alias_file = DATADIR "/local
|
|
|
bca718 |
const char *locar_file = PREFIX "/lib/locale/locale-archive";
|
|
|
bca718 |
const char *tmpl_file = PREFIX "/lib/locale/locale-archive.tmpl";
|
|
|
bca718 |
const char *loc_path = PREFIX "/lib/locale/";
|
|
|
bca718 |
+/* Flags set by `--verbose` option. */
|
|
|
bca718 |
int be_quiet = 1;
|
|
|
bca718 |
int verbose = 0;
|
|
|
bca718 |
int max_locarchive_open_retry = 10;
|
|
|
bca718 |
@@ -96,7 +98,7 @@ open_tmpl_archive (struct locarhandle *a
|
|
|
bca718 |
struct stat64 st;
|
|
|
bca718 |
int fd;
|
|
|
bca718 |
struct locarhead head;
|
|
|
bca718 |
- const char *archivefname = tmpl_file;
|
|
|
bca718 |
+ const char *archivefname = ah->fname == NULL ? tmpl_file : ah->fname;
|
|
|
bca718 |
|
|
|
bca718 |
/* Open the archive. We must have exclusive write access. */
|
|
|
bca718 |
fd = open64 (archivefname, O_RDONLY);
|
|
|
bca718 |
@@ -116,7 +118,7 @@ open_tmpl_archive (struct locarhandle *a
|
|
|
bca718 |
ah->mmaped = (head.sumhash_offset
|
|
|
bca718 |
+ head.sumhash_size * sizeof (struct sumhashent));
|
|
|
bca718 |
if (ah->mmaped > (unsigned long) st.st_size)
|
|
|
bca718 |
- error (EXIT_FAILURE, 0, "locale archite template file truncated");
|
|
|
bca718 |
+ error (EXIT_FAILURE, 0, "locale archive template file truncated");
|
|
|
bca718 |
ah->mmaped = st.st_size;
|
|
|
bca718 |
ah->reserved = st.st_size;
|
|
|
bca718 |
|
|
|
bca718 |
@@ -250,7 +252,10 @@ compute_data (struct locarhandle *ah, st
|
|
|
bca718 |
}
|
|
|
bca718 |
|
|
|
bca718 |
static int
|
|
|
bca718 |
-fill_archive (struct locarhandle *tmpl_ah, size_t nlist, char *list[],
|
|
|
bca718 |
+fill_archive (struct locarhandle *tmpl_ah,
|
|
|
bca718 |
+ const char *fname,
|
|
|
bca718 |
+ size_t install_langs_count, char *install_langs_list[],
|
|
|
bca718 |
+ size_t nlist, char *list[],
|
|
|
bca718 |
const char *primary)
|
|
|
bca718 |
{
|
|
|
bca718 |
struct locarhandle ah;
|
|
|
bca718 |
@@ -281,11 +286,40 @@ fill_archive (struct locarhandle *tmpl_a
|
|
|
bca718 |
for (cnt = used = 0; cnt < head->namehash_size; ++cnt)
|
|
|
bca718 |
if (namehashtab[cnt].locrec_offset != 0)
|
|
|
bca718 |
{
|
|
|
bca718 |
+ char * name;
|
|
|
bca718 |
+ int i;
|
|
|
bca718 |
assert (used < head->namehash_used);
|
|
|
bca718 |
- names[used].name = tmpl_ah->addr + namehashtab[cnt].name_offset;
|
|
|
bca718 |
- names[used++].locrec
|
|
|
bca718 |
- = (struct locrecent *) ((char *) tmpl_ah->addr +
|
|
|
bca718 |
- namehashtab[cnt].locrec_offset);
|
|
|
bca718 |
+ name = tmpl_ah->addr + namehashtab[cnt].name_offset;
|
|
|
bca718 |
+ if (install_langs_count == 0)
|
|
|
bca718 |
+ {
|
|
|
bca718 |
+ /* Always intstall the entry. */
|
|
|
bca718 |
+ names[used].name = name;
|
|
|
bca718 |
+ names[used++].locrec
|
|
|
bca718 |
+ = (struct locrecent *) ((char *) tmpl_ah->addr +
|
|
|
bca718 |
+ namehashtab[cnt].locrec_offset);
|
|
|
bca718 |
+ }
|
|
|
bca718 |
+ else
|
|
|
bca718 |
+ {
|
|
|
bca718 |
+ /* Only install the entry if the user asked for it via
|
|
|
bca718 |
+ --install-langs. */
|
|
|
bca718 |
+ for (i = 0; i < install_langs_count; i++)
|
|
|
bca718 |
+ {
|
|
|
bca718 |
+ /* Add one for "_" and one for the null terminator. */
|
|
|
bca718 |
+ size_t len = strlen (install_langs_list[i]) + 2;
|
|
|
bca718 |
+ char *install_lang = (char *)xmalloc (len);
|
|
|
bca718 |
+ strcpy (install_lang, install_langs_list[i]);
|
|
|
bca718 |
+ if (strchr (install_lang, '_') == NULL)
|
|
|
bca718 |
+ strcat (install_lang, "_");
|
|
|
bca718 |
+ if (strncmp (name, install_lang, strlen (install_lang)) == 0)
|
|
|
bca718 |
+ {
|
|
|
bca718 |
+ names[used].name = name;
|
|
|
bca718 |
+ names[used++].locrec
|
|
|
bca718 |
+ = (struct locrecent *) ((char *)tmpl_ah->addr
|
|
|
bca718 |
+ + namehashtab[cnt].locrec_offset);
|
|
|
bca718 |
+ }
|
|
|
bca718 |
+ free (install_lang);
|
|
|
bca718 |
+ }
|
|
|
bca718 |
+ }
|
|
|
bca718 |
}
|
|
|
bca718 |
|
|
|
bca718 |
/* Sort the names. */
|
|
|
bca718 |
@@ -304,6 +338,9 @@ fill_archive (struct locarhandle *tmpl_a
|
|
|
bca718 |
|
|
|
bca718 |
/* Open the archive. This call never returns if we cannot
|
|
|
bca718 |
successfully open the archive. */
|
|
|
bca718 |
+ ah.fname = NULL;
|
|
|
bca718 |
+ if (fname != NULL)
|
|
|
bca718 |
+ ah.fname = fname;
|
|
|
bca718 |
open_archive (&ah, false);
|
|
|
bca718 |
|
|
|
bca718 |
if (primary != NULL)
|
|
|
bca718 |
@@ -532,24 +569,197 @@ fill_archive (struct locarhandle *tmpl_a
|
|
|
bca718 |
return result;
|
|
|
bca718 |
}
|
|
|
bca718 |
|
|
|
bca718 |
-int main ()
|
|
|
bca718 |
+void usage()
|
|
|
bca718 |
+{
|
|
|
bca718 |
+ printf ("\
|
|
|
bca718 |
+Usage: build-locale-archive [OPTION]... [TEMPLATE-FILE] [ARCHIVE-FILE]\n\
|
|
|
bca718 |
+ Builds a locale archive from a template file.\n\
|
|
|
bca718 |
+ Options:\n\
|
|
|
bca718 |
+ -h, --help Print this usage message.\n\
|
|
|
bca718 |
+ -v, --verbose Verbose execution.\n\
|
|
|
bca718 |
+ -l, --install-langs=LIST Only include locales given in LIST into the \n\
|
|
|
bca718 |
+ locale archive. LIST is a colon separated list\n\
|
|
|
bca718 |
+ of locale prefixes, for example \"de:en:ja\".\n\
|
|
|
bca718 |
+ The special argument \"all\" means to install\n\
|
|
|
bca718 |
+ all languages and it must be present by itself.\n\
|
|
|
bca718 |
+ If \"all\" is present with any other language it\n\
|
|
|
bca718 |
+ will be treated as the name of a locale.\n\
|
|
|
bca718 |
+ If the --install-langs option is missing, all\n\
|
|
|
bca718 |
+ locales are installed. The colon separated list\n\
|
|
|
bca718 |
+ can contain any strings matching the beginning of\n\
|
|
|
bca718 |
+ locale names.\n\
|
|
|
bca718 |
+ If a string does not contain a \"_\", it is added.\n\
|
|
|
bca718 |
+ Examples:\n\
|
|
|
bca718 |
+ --install-langs=\"en\"\n\
|
|
|
bca718 |
+ installs en_US, en_US.iso88591,\n\
|
|
|
bca718 |
+ en_US.iso885915, en_US.utf8,\n\
|
|
|
bca718 |
+ en_GB ...\n\
|
|
|
bca718 |
+ --install-langs=\"en_US.utf8\"\n\
|
|
|
bca718 |
+ installs only en_US.utf8.\n\
|
|
|
bca718 |
+ --install-langs=\"ko\"\n\
|
|
|
bca718 |
+ installs ko_KR, ko_KR.euckr,\n\
|
|
|
bca718 |
+ ko_KR.utf8 but *not* kok_IN\n\
|
|
|
bca718 |
+ because \"ko\" does not contain\n\
|
|
|
bca718 |
+ \"_\" and it is silently added\n\
|
|
|
bca718 |
+ --install-langs\"ko:kok\"\n\
|
|
|
bca718 |
+ installs ko_KR, ko_KR.euckr,\n\
|
|
|
bca718 |
+ ko_KR.utf8, kok_IN, and\n\
|
|
|
bca718 |
+ kok_IN.utf8.\n\
|
|
|
bca718 |
+ --install-langs=\"POSIX\" will\n\
|
|
|
bca718 |
+ installs *no* locales at all\n\
|
|
|
bca718 |
+ because POSIX matches none of\n\
|
|
|
bca718 |
+ the locales. Actually, any string\n\
|
|
|
bca718 |
+ matching nothing will do that.\n\
|
|
|
bca718 |
+ POSIX and C will always be\n\
|
|
|
bca718 |
+ available because they are\n\
|
|
|
bca718 |
+ builtin.\n\
|
|
|
bca718 |
+ Aliases are installed as well,\n\
|
|
|
bca718 |
+ i.e. --install-langs=\"de\"\n\
|
|
|
bca718 |
+ will install not only every locale starting with\n\
|
|
|
bca718 |
+ \"de\" but also the aliases \"deutsch\"\n\
|
|
|
bca718 |
+ and and \"german\" although the latter does not\n\
|
|
|
bca718 |
+ start with \"de\".\n\
|
|
|
bca718 |
+\n\
|
|
|
bca718 |
+ If the arguments TEMPLATE-FILE and ARCHIVE-FILE are not given the locations\n\
|
|
|
bca718 |
+ where the glibc used expects these files are used by default.\n\
|
|
|
bca718 |
+");
|
|
|
bca718 |
+}
|
|
|
bca718 |
+
|
|
|
bca718 |
+int main (int argc, char *argv[])
|
|
|
bca718 |
{
|
|
|
bca718 |
char path[4096];
|
|
|
bca718 |
DIR *dirp;
|
|
|
bca718 |
struct dirent64 *d;
|
|
|
bca718 |
struct stat64 st;
|
|
|
bca718 |
char *list[16384], *primary;
|
|
|
bca718 |
+ char *lang;
|
|
|
bca718 |
+ int install_langs_count = 0;
|
|
|
bca718 |
+ int i;
|
|
|
bca718 |
+ char *install_langs_arg, *ila_start;
|
|
|
bca718 |
+ char **install_langs_list;
|
|
|
bca718 |
unsigned int cnt = 0;
|
|
|
bca718 |
struct locarhandle tmpl_ah;
|
|
|
bca718 |
+ char *new_locar_fname = NULL;
|
|
|
bca718 |
size_t loc_path_len = strlen (loc_path);
|
|
|
bca718 |
|
|
|
bca718 |
+ while (1)
|
|
|
bca718 |
+ {
|
|
|
bca718 |
+ int c;
|
|
|
bca718 |
+
|
|
|
bca718 |
+ static struct option long_options[] =
|
|
|
bca718 |
+ {
|
|
|
bca718 |
+ {"help", no_argument, 0, 'h'},
|
|
|
bca718 |
+ {"verbose", no_argument, 0, 'v'},
|
|
|
bca718 |
+ {"install-langs", required_argument, 0, 'l'},
|
|
|
bca718 |
+ {0, 0, 0, 0}
|
|
|
bca718 |
+ };
|
|
|
bca718 |
+ /* getopt_long stores the option index here. */
|
|
|
bca718 |
+ int option_index = 0;
|
|
|
bca718 |
+
|
|
|
bca718 |
+ c = getopt_long (argc, argv, "vhl:",
|
|
|
bca718 |
+ long_options, &option_index);
|
|
|
bca718 |
+
|
|
|
bca718 |
+ /* Detect the end of the options. */
|
|
|
bca718 |
+ if (c == -1)
|
|
|
bca718 |
+ break;
|
|
|
bca718 |
+
|
|
|
bca718 |
+ switch (c)
|
|
|
bca718 |
+ {
|
|
|
bca718 |
+ case 0:
|
|
|
bca718 |
+ printf ("unknown option %s", long_options[option_index].name);
|
|
|
bca718 |
+ if (optarg)
|
|
|
bca718 |
+ printf (" with arg %s", optarg);
|
|
|
bca718 |
+ printf ("\n");
|
|
|
bca718 |
+ usage ();
|
|
|
bca718 |
+ exit (1);
|
|
|
bca718 |
+
|
|
|
bca718 |
+ case 'v':
|
|
|
bca718 |
+ verbose = 1;
|
|
|
bca718 |
+ be_quiet = 0;
|
|
|
bca718 |
+ break;
|
|
|
bca718 |
+
|
|
|
bca718 |
+ case 'h':
|
|
|
bca718 |
+ usage ();
|
|
|
bca718 |
+ exit (0);
|
|
|
bca718 |
+
|
|
|
bca718 |
+ case 'l':
|
|
|
bca718 |
+ install_langs_arg = ila_start = strdup (optarg);
|
|
|
bca718 |
+ /* If the argument to --install-lang is "all", do
|
|
|
bca718 |
+ not limit the list of languages to install and install
|
|
|
bca718 |
+ them all. We do not support installing a single locale
|
|
|
bca718 |
+ called "all". */
|
|
|
bca718 |
+#define MAGIC_INSTALL_ALL "all"
|
|
|
bca718 |
+ if (install_langs_arg != NULL
|
|
|
bca718 |
+ && install_langs_arg[0] != '\0'
|
|
|
bca718 |
+ && !(strncmp(install_langs_arg, MAGIC_INSTALL_ALL,
|
|
|
bca718 |
+ strlen(MAGIC_INSTALL_ALL)) == 0
|
|
|
bca718 |
+ && strlen (install_langs_arg) == 3))
|
|
|
bca718 |
+ {
|
|
|
bca718 |
+ /* Count the number of languages we will install. */
|
|
|
bca718 |
+ while (true)
|
|
|
bca718 |
+ {
|
|
|
bca718 |
+ lang = strtok(install_langs_arg, ":;,");
|
|
|
bca718 |
+ if (lang == NULL)
|
|
|
bca718 |
+ break;
|
|
|
bca718 |
+ install_langs_count++;
|
|
|
bca718 |
+ install_langs_arg = NULL;
|
|
|
bca718 |
+ }
|
|
|
bca718 |
+ free (ila_start);
|
|
|
bca718 |
+ /* Copy the list. */
|
|
|
bca718 |
+ install_langs_list = (char **)xmalloc (sizeof(char *) * install_langs_count);
|
|
|
bca718 |
+ install_langs_arg = ila_start = strdup (optarg);
|
|
|
bca718 |
+ install_langs_count = 0;
|
|
|
bca718 |
+ while (true)
|
|
|
bca718 |
+ {
|
|
|
bca718 |
+ lang = strtok(install_langs_arg, ":;,");
|
|
|
bca718 |
+ if (lang == NULL)
|
|
|
bca718 |
+ break;
|
|
|
bca718 |
+ install_langs_list[install_langs_count] = lang;
|
|
|
bca718 |
+ install_langs_count++;
|
|
|
bca718 |
+ install_langs_arg = NULL;
|
|
|
bca718 |
+ }
|
|
|
bca718 |
+ }
|
|
|
bca718 |
+ break;
|
|
|
bca718 |
+
|
|
|
bca718 |
+ case '?':
|
|
|
bca718 |
+ /* getopt_long already printed an error message. */
|
|
|
bca718 |
+ usage ();
|
|
|
bca718 |
+ exit (0);
|
|
|
bca718 |
+
|
|
|
bca718 |
+ default:
|
|
|
bca718 |
+ abort ();
|
|
|
bca718 |
+ }
|
|
|
bca718 |
+ }
|
|
|
bca718 |
+ tmpl_ah.fname = NULL;
|
|
|
bca718 |
+ if (optind < argc)
|
|
|
bca718 |
+ tmpl_ah.fname = argv[optind];
|
|
|
bca718 |
+ if (optind + 1 < argc)
|
|
|
bca718 |
+ new_locar_fname = argv[optind + 1];
|
|
|
bca718 |
+ if (verbose)
|
|
|
bca718 |
+ {
|
|
|
bca718 |
+ if (tmpl_ah.fname)
|
|
|
bca718 |
+ printf("input archive file specified on command line: %s\n",
|
|
|
bca718 |
+ tmpl_ah.fname);
|
|
|
bca718 |
+ else
|
|
|
bca718 |
+ printf("using default input archive file.\n");
|
|
|
bca718 |
+ if (new_locar_fname)
|
|
|
bca718 |
+ printf("output archive file specified on command line: %s\n",
|
|
|
bca718 |
+ new_locar_fname);
|
|
|
bca718 |
+ else
|
|
|
bca718 |
+ printf("using default output archive file.\n");
|
|
|
bca718 |
+ }
|
|
|
bca718 |
+
|
|
|
bca718 |
dirp = opendir (loc_path);
|
|
|
bca718 |
if (dirp == NULL)
|
|
|
bca718 |
error (EXIT_FAILURE, errno, "cannot open directory \"%s\"", loc_path);
|
|
|
bca718 |
|
|
|
bca718 |
open_tmpl_archive (&tmpl_ah);
|
|
|
bca718 |
|
|
|
bca718 |
- unlink (locar_file);
|
|
|
bca718 |
+ if (new_locar_fname)
|
|
|
bca718 |
+ unlink (new_locar_fname);
|
|
|
bca718 |
+ else
|
|
|
bca718 |
+ unlink (locar_file);
|
|
|
bca718 |
+
|
|
|
bca718 |
primary = getenv ("LC_ALL");
|
|
|
bca718 |
if (primary == NULL)
|
|
|
bca718 |
primary = getenv ("LANG");
|
|
|
bca718 |
@@ -560,7 +770,8 @@ int main ()
|
|
|
bca718 |
&& strncmp (primary, "zh", 2) != 0)
|
|
|
bca718 |
{
|
|
|
bca718 |
char *ptr = malloc (strlen (primary) + strlen (".utf8") + 1), *p, *q;
|
|
|
bca718 |
-
|
|
|
bca718 |
+ /* This leads to invalid locales sometimes:
|
|
|
bca718 |
+ de_DE.iso885915@euro -> de_DE.utf8@euro */
|
|
|
bca718 |
if (ptr != NULL)
|
|
|
bca718 |
{
|
|
|
bca718 |
p = ptr;
|
|
|
bca718 |
@@ -623,10 +834,19 @@ int main ()
|
|
|
bca718 |
cnt++;
|
|
|
bca718 |
}
|
|
|
bca718 |
closedir (dirp);
|
|
|
bca718 |
- fill_archive (&tmpl_ah, cnt, list, primary);
|
|
|
bca718 |
+ /* Store the archive to the file specified as the second argument on the
|
|
|
bca718 |
+ command line or the default locale archive. */
|
|
|
bca718 |
+ fill_archive (&tmpl_ah, new_locar_fname,
|
|
|
bca718 |
+ install_langs_count, install_langs_list,
|
|
|
bca718 |
+ cnt, list, primary);
|
|
|
bca718 |
close_archive (&tmpl_ah);
|
|
|
bca718 |
truncate (tmpl_file, 0);
|
|
|
bca718 |
- char *argv[] = { "/usr/sbin/tzdata-update", NULL };
|
|
|
bca718 |
- execve (argv[0], (char *const *)argv, (char *const *)&argv[1]);
|
|
|
bca718 |
+ if (install_langs_count > 0)
|
|
|
bca718 |
+ {
|
|
|
bca718 |
+ free (ila_start);
|
|
|
bca718 |
+ free (install_langs_list);
|
|
|
bca718 |
+ }
|
|
|
bca718 |
+ char *tz_argv[] = { "/usr/sbin/tzdata-update", NULL };
|
|
|
bca718 |
+ execve (tz_argv[0], (char *const *)tz_argv, (char *const *)&tz_argv[1]);
|
|
|
bca718 |
exit (0);
|
|
|
bca718 |
}
|