| The functions in locarchive.c cannot create files in non-default |
| locations. Rather than enhancing locarchive.c (and risk regressions |
| in localedef), this patch adapts build-locale-archive to use the |
| existing output_prefix configuration variable. |
| |
| |
| |
| |
| |
| @@ -92,23 +92,34 @@ xmalloc (size_t size) |
| return p; |
| } |
| |
| +static char * |
| +xasprintf (const char *format, ...) |
| +{ |
| + va_list ap; |
| + va_start (ap, format); |
| + char *result; |
| + if (vasprintf (&result, format, ap) < 0) |
| + error (EXIT_FAILURE, errno, "could not format string"); |
| + va_end (ap); |
| + return result; |
| +} |
| + |
| static void |
| open_tmpl_archive (struct locarhandle *ah) |
| { |
| struct stat64 st; |
| int fd; |
| struct locarhead head; |
| - const char *archivefname = ah->fname == NULL ? tmpl_file : ah->fname; |
| |
| /* Open the archive. We must have exclusive write access. */ |
| - fd = open64 (archivefname, O_RDONLY); |
| + fd = open64 (tmpl_file, O_RDONLY); |
| if (fd == -1) |
| error (EXIT_FAILURE, errno, "cannot open locale archive template file \"%s\"", |
| - archivefname); |
| + tmpl_file); |
| |
| if (fstat64 (fd, &st) < 0) |
| error (EXIT_FAILURE, errno, "cannot stat locale archive template file \"%s\"", |
| - archivefname); |
| + tmpl_file); |
| |
| /* Read the header. */ |
| if (TEMP_FAILURE_RETRY (read (fd, &head, sizeof (head))) != sizeof (head)) |
| @@ -253,12 +264,11 @@ compute_data (struct locarhandle *ah, st |
| |
| static int |
| fill_archive (struct locarhandle *tmpl_ah, |
| - const char *fname, |
| size_t install_langs_count, char *install_langs_list[], |
| size_t nlist, char *list[], |
| const char *primary) |
| { |
| - struct locarhandle ah; |
| + struct locarhandle ah = {}; |
| struct locarhead *head; |
| int result = 0; |
| struct nameent *names; |
| @@ -338,9 +348,6 @@ fill_archive (struct locarhandle *tmpl_a |
| |
| /* Open the archive. This call never returns if we cannot |
| successfully open the archive. */ |
| - ah.fname = NULL; |
| - if (fname != NULL) |
| - ah.fname = fname; |
| open_archive (&ah, false); |
| |
| if (primary != NULL) |
| @@ -619,38 +626,39 @@ Usage: build-locale-archive [OPTION]... |
| \"de\" but also the aliases \"deutsch\"\n\ |
| and and \"german\" although the latter does not\n\ |
| start with \"de\".\n\ |
| + --prefix=DIR Operate under the file system root DIR\n\ |
| \n\ |
| - If the arguments TEMPLATE-FILE and ARCHIVE-FILE are not given the locations\n\ |
| - where the glibc used expects these files are used by default.\n\ |
| "); |
| } |
| |
| int main (int argc, char *argv[]) |
| { |
| - char path[4096]; |
| DIR *dirp; |
| struct dirent64 *d; |
| struct stat64 st; |
| char *list[16384], *primary; |
| char *lang; |
| int install_langs_count = 0; |
| - int i; |
| char *install_langs_arg, *ila_start; |
| char **install_langs_list; |
| unsigned int cnt = 0; |
| - struct locarhandle tmpl_ah; |
| - char *new_locar_fname = NULL; |
| - size_t loc_path_len = strlen (loc_path); |
| + struct locarhandle tmpl_ah = {}; |
| |
| while (1) |
| { |
| int c; |
| |
| + enum |
| + { |
| + opt_prefix = 1000, |
| + }; |
| + |
| static struct option long_options[] = |
| { |
| {"help", no_argument, 0, 'h'}, |
| {"verbose", no_argument, 0, 'v'}, |
| {"install-langs", required_argument, 0, 'l'}, |
| + {"prefix", required_argument, 0, opt_prefix}, |
| {0, 0, 0, 0} |
| }; |
| /* getopt_long stores the option index here. */ |
| @@ -721,6 +729,10 @@ int main (int argc, char *argv[]) |
| } |
| break; |
| |
| + case opt_prefix: |
| + output_prefix = optarg; |
| + break; |
| + |
| case '?': |
| /* getopt_long already printed an error message. */ |
| usage (); |
| @@ -730,23 +742,26 @@ int main (int argc, char *argv[]) |
| abort (); |
| } |
| } |
| - tmpl_ah.fname = NULL; |
| - if (optind < argc) |
| - tmpl_ah.fname = argv[optind]; |
| - if (optind + 1 < argc) |
| - new_locar_fname = argv[optind + 1]; |
| + if (optind != argc) |
| + { |
| + usage (); |
| + exit (1); |
| + } |
| + if (output_prefix) |
| + { |
| + tmpl_file = xasprintf ("%s%s", output_prefix, tmpl_file); |
| + alias_file = xasprintf ("%s%s", output_prefix, alias_file); |
| + locar_file = xasprintf ("%s%s", output_prefix, locar_file); |
| + loc_path = xasprintf ("%s%s", output_prefix, loc_path); |
| + } |
| if (verbose) |
| { |
| - if (tmpl_ah.fname) |
| - printf("input archive file specified on command line: %s\n", |
| - tmpl_ah.fname); |
| - else |
| - printf("using default input archive file.\n"); |
| - if (new_locar_fname) |
| - printf("output archive file specified on command line: %s\n", |
| - new_locar_fname); |
| - else |
| - printf("using default output archive file.\n"); |
| + if (output_prefix != NULL) |
| + printf ("output prefix: %s\n", output_prefix); |
| + printf ("input archive file: %s\n", tmpl_file); |
| + printf ("input alias file: %s\n", alias_file); |
| + printf ("input locale directory prefix: %s\n", loc_path); |
| + printf ("output archive file: %s\n", locar_file); |
| } |
| |
| dirp = opendir (loc_path); |
| @@ -754,11 +769,7 @@ int main (int argc, char *argv[]) |
| error (EXIT_FAILURE, errno, "cannot open directory \"%s\"", loc_path); |
| |
| open_tmpl_archive (&tmpl_ah); |
| - |
| - if (new_locar_fname) |
| - unlink (new_locar_fname); |
| - else |
| - unlink (locar_file); |
| + unlink (locar_file); |
| |
| primary = getenv ("LC_ALL"); |
| if (primary == NULL) |
| @@ -790,8 +801,6 @@ int main (int argc, char *argv[]) |
| } |
| } |
| |
| - memcpy (path, loc_path, loc_path_len); |
| - |
| while ((d = readdir64 (dirp)) != NULL) |
| { |
| if (strcmp (d->d_name, ".") == 0 || strcmp (d->d_name, "..") == 0) |
| @@ -799,32 +808,25 @@ int main (int argc, char *argv[]) |
| if (strchr (d->d_name, '_') == NULL) |
| continue; |
| |
| - size_t d_name_len = strlen (d->d_name); |
| - if (loc_path_len + d_name_len + 1 > sizeof (path)) |
| - { |
| - error (0, 0, "too long filename \"%s\"", d->d_name); |
| - continue; |
| - } |
| - |
| - memcpy (path + loc_path_len, d->d_name, d_name_len + 1); |
| + char *path = xasprintf ("%s%s", loc_path, d->d_name); |
| if (stat64 (path, &st) < 0) |
| { |
| error (0, errno, "cannot stat \"%s\"", path); |
| + free (path); |
| continue; |
| } |
| if (! S_ISDIR (st.st_mode)) |
| - continue; |
| + { |
| + free (path); |
| + continue; |
| + } |
| if (cnt == 16384) |
| { |
| error (0, 0, "too many directories in \"%s\"", loc_path); |
| + free (path); |
| break; |
| } |
| - list[cnt] = strdup (path); |
| - if (list[cnt] == NULL) |
| - { |
| - error (0, errno, "cannot add file to list \"%s\"", path); |
| - continue; |
| - } |
| + list[cnt] = path; |
| if (primary != NULL && cnt > 0 && strcmp (primary, d->d_name) == 0) |
| { |
| char *p = list[0]; |
| @@ -836,7 +838,7 @@ int main (int argc, char *argv[]) |
| closedir (dirp); |
| /* Store the archive to the file specified as the second argument on the |
| command line or the default locale archive. */ |
| - fill_archive (&tmpl_ah, new_locar_fname, |
| + fill_archive (&tmpl_ah, |
| install_langs_count, install_langs_list, |
| cnt, list, primary); |
| close_archive (&tmpl_ah); |