@@ -65,6 +65,9 @@ static int force_output;
/* Prefix for output files. */
const char *output_prefix;
+/* Locale directory to use for output. */
+const char *output_localedir;
+
/* Name of the character map file. */
static const char *charmap_file;
@@ -74,6 +77,9 @@ static const char *input_file;
/* Name of the repertoire map file. */
const char *repertoire_global;
+/* Location of the locale-archive file. */
+const char *archive_file;
+
/* Name of the locale.alias file. */
const char *alias_file;
@@ -107,11 +113,12 @@ void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
#define OPT_QUIET 302
#define OPT_OLDSTYLE 303
#define OPT_PREFIX 304
-#define OPT_NO_ARCHIVE 305
-#define OPT_ADD_TO_ARCHIVE 306
-#define OPT_REPLACE 307
-#define OPT_DELETE_FROM_ARCHIVE 308
-#define OPT_LIST_ARCHIVE 309
+#define OPT_LOCALEDIR 305
+#define OPT_NO_ARCHIVE 306
+#define OPT_ADD_TO_ARCHIVE 307
+#define OPT_REPLACE 308
+#define OPT_DELETE_FROM_ARCHIVE 309
+#define OPT_LIST_ARCHIVE 310
#define OPT_LITTLE_ENDIAN 400
#define OPT_BIG_ENDIAN 401
@@ -131,11 +138,16 @@ static const struct argp_option options[] =
N_("Create output even if warning messages were issued") },
{ "old-style", OPT_OLDSTYLE, NULL, 0, N_("Create old-style tables") },
{ "prefix", OPT_PREFIX, N_("PATH"), 0, N_("Optional output file prefix") },
+ { "localedir", OPT_LOCALEDIR, N_("PATH"), 0,
+ N_("Optional path to locale directory e.g. /usr/lib64/locale") },
{ "posix", OPT_POSIX, NULL, 0, N_("Strictly conform to POSIX") },
{ "quiet", OPT_QUIET, NULL, 0,
N_("Suppress warnings and information messages") },
{ "verbose", 'v', NULL, 0, N_("Print more messages") },
+
{ NULL, 0, NULL, 0, N_("Archive control:") },
+ { "archive-file", 'a', N_("FILE"), 0,
+ N_("locale-archive file to use instead of default")},
{ "no-archive", OPT_NO_ARCHIVE, NULL, 0,
N_("Don't add new data to archive") },
{ "add-to-archive", OPT_ADD_TO_ARCHIVE, NULL, 0,
@@ -178,6 +190,9 @@ static struct argp argp =
/* Prototypes for local functions. */
static void error_print (void);
static const char *construct_output_path (char *path);
+static const char *construct_prefix_path (const char *prefix,
+ const char *localedir,
+ const char *path);
static const char *normalize_codeset (const char *codeset, size_t name_len);
@@ -189,6 +204,8 @@ main (int argc, char *argv[])
struct charmap_t *charmap;
struct localedef_t global;
int remaining;
+ struct locarhandle ah;
+ const char *prefix_archive_file = NULL;
/* Set initial values for global variables. */
copy_list = NULL;
@@ -207,14 +224,34 @@ main (int argc, char *argv[])
argp_err_exit_status = 4;
argp_parse (&argp, argc, argv, 0, &remaining, NULL);
+ /* Use the user-specified archive file or NULL (default). */
+ ah.fname = archive_file;
+ if (output_prefix != NULL || output_localedir != NULL || archive_file != NULL)
+ {
+ prefix_archive_file = construct_prefix_path (output_prefix ?: "",
+ output_localedir ?: LOCALEDIR,
+ archive_file ?: LOCALE_ARCHIVE);
+ ah.fname = prefix_archive_file;
+ }
+
/* Handle a few special cases. */
if (list_archive)
- show_archive_content (remaining > 1 ? argv[remaining] : NULL, verbose);
+ {
+ /* If using --list-archive FILE and -a FILE at the same time the
+ archive file specified after --list-archive takes precedence.
+ The use of -a only changes the default locale archive file. */
+ if (remaining > 1 && remaining < argc)
+ ah.fname = construct_prefix_path (output_prefix,
+ NULL,
+ argv[remaining]);
+ show_archive_content (ah.fname, verbose);
+ }
if (add_to_archive)
- return add_locales_to_archive (argc - remaining, &argv[remaining],
+ return add_locales_to_archive (&ah, argc - remaining, &argv[remaining],
replace_archive);
if (delete_from_archive)
- return delete_locales_from_archive (argc - remaining, &argv[remaining]);
+ return delete_locales_from_archive (&ah, argc - remaining,
+ &argv[remaining]);
/* POSIX.2 requires to be verbose about missing characters in the
character map. */
@@ -286,9 +323,13 @@ cannot open locale definition file `%s'"), runp->name));
{
if (cannot_write_why != 0)
WITH_CUR_LOCALE (error (4, cannot_write_why, _("\
-cannot write output files to `%s'"), output_path ? : argv[remaining]));
+cannot write output files to `%s' (LOCALEDIR is `%s%s')"),
+ output_path ?: argv[remaining],
+ output_prefix ?: "",
+ output_localedir ?: LOCALEDIR));
else
- write_all_categories (locales, charmap, argv[remaining], output_path);
+ write_all_categories (&ah, locales, charmap,
+ argv[remaining], output_path);
}
else
WITH_CUR_LOCALE (error (4, 0, _("\
@@ -317,6 +358,9 @@ parse_opt (int key, char *arg, struct argp_state *state)
case OPT_PREFIX:
output_prefix = arg;
break;
+ case OPT_LOCALEDIR:
+ output_localedir = arg;
+ break;
case OPT_NO_ARCHIVE:
no_archive = true;
break;
@@ -338,6 +382,9 @@ parse_opt (int key, char *arg, struct argp_state *state)
case OPT_BIG_ENDIAN:
set_big_endian (true);
break;
+ case 'a':
+ archive_file = arg;
+ break;
case 'c':
force_output = 1;
break;
@@ -415,6 +462,26 @@ error_print (void)
{
}
+/* Construct an output path given a prefix directory, an absolute locale
+ directory and a path. The output path is a constant and can be used
+ by any caller and must not be freed. */
+static const char *
+construct_prefix_path (const char *prefix,
+ const char *localedir,
+ const char *path)
+{
+ ssize_t n;
+ char *result;
+ n = asprintf (&result, "%s%s%s%s%c",
+ prefix ?: "",
+ localedir ?: "",
+ localedir ? "/" : "",
+ path, '\0');
+ if (n < 0)
+ WITH_CUR_LOCALE (error (6, errno, _("cannot allocate path")));
+ return result;
+}
+
/* The parameter to localedef describes the output path. If it does
contain a '/' character it is a relative path. Otherwise it names the
@@ -458,10 +525,12 @@ construct_output_path (char *path)
ssize_t n;
if (normal == NULL)
n = asprintf (&result, "%s%s/%s%c",
- output_prefix ?: "", LOCALEDIR, path, '\0');
+ output_prefix ?: "",
+ output_localedir ?: LOCALEDIR, path, '\0');
else
n = asprintf (&result, "%s%s/%.*s%s%s%c",
- output_prefix ?: "", LOCALEDIR,
+ output_prefix ?: "",
+ output_localedir ?: LOCALEDIR,
(int) (startp - path), path, normal, endp, '\0');
if (n < 0)
@@ -523,7 +592,7 @@ normalize_codeset (codeset, name_len)
only_digit = 0;
}
- retval = (char *) malloc ((only_digit ? 3 : 0) + len + 1);
+ retval = (char *) xmalloc ((only_digit ? 3 : 0) + len + 1);
if (retval != NULL)
{
@@ -135,6 +135,8 @@ extern const char *alias_file;
setlocale (LC_CTYPE, cur_locale_); \
} while (0)
+#define LOCALE_ARCHIVE "locale-archive"
+#define ARCHIVE_NAME LOCALEDIR "/"LOCALE_ARCHIVE
/* Mark given locale as to be read. */
extern struct localedef_t *add_to_readlist (int locale, const char *name,
@@ -165,10 +167,13 @@ extern int add_locale_to_archive (struct locarhandle *ah, const char *name,
locale_data_t data, bool replace);
/* Add content of named directories to locale archive. */
-extern int add_locales_to_archive (size_t nlist, char *list[], bool replace);
+extern int add_locales_to_archive (struct locarhandle *ah,
+ size_t nlist,
+ char *list[], bool replace);
/* Removed named locales from archive. */
-extern int delete_locales_from_archive (size_t nlist, char *list[]);
+extern int delete_locales_from_archive (struct locarhandle *ah,
+ size_t nlist, char *list[]);
/* List content of locale archive. If FNAME is non-null use that as
the locale archive to list, otherwise the default. */
@@ -57,8 +57,6 @@
extern const char *output_prefix;
-#define ARCHIVE_NAME LOCALEDIR "/locale-archive"
-
static const char *locnames[] =
{
#define DEFINE_CATEGORY(category, category_name, items, a) \
@@ -581,11 +579,10 @@ open_archive (struct locarhandle *ah, bool readonly)
fd = open64 (archivefname, readonly ? O_RDONLY : O_RDWR);
if (fd == -1)
{
- /* Maybe the file does not yet exist? If we are opening
- the default locale archive we ignore the failure and
- list an empty archive, otherwise we print an error
- and exit. */
- if (errno == ENOENT && archivefname == default_fname)
+ /* Maybe the file does not yet exist?
+ Create it if we are not in readonly mode.
+ If we are in readonly mode pass back an empty structure. */
+ if (errno == ENOENT)
{
if (readonly)
{
@@ -1328,19 +1325,19 @@ add_locale_to_archive (ah, name, data, replace)
}
+/* Add locales to the archive file specified in AH->FNAME or
+ the default if NULL. */
int
-add_locales_to_archive (nlist, list, replace)
- size_t nlist;
- char *list[];
- bool replace;
+add_locales_to_archive (struct locarhandle *ah,
+ size_t nlist,
+ char *list[],
+ bool replace)
{
- struct locarhandle ah;
int result = 0;
/* Open the archive. This call never returns if we cannot
successfully open the archive. */
- ah.fname = NULL;
- open_archive (&ah, false);
+ open_archive (ah, false);
while (nlist-- > 0)
{
@@ -1514,7 +1511,7 @@ add_locales_to_archive (nlist, list, replace)
continue;
}
- result |= add_locale_to_archive (&ah, basename (fname), data, replace);
+ result |= add_locale_to_archive (ah, basename (fname), data, replace);
for (cnt = 0; cnt < __LC_LAST; ++cnt)
if (cnt != LC_ALL)
@@ -1522,28 +1519,28 @@ add_locales_to_archive (nlist, list, replace)
}
/* We are done. */
- close_archive (&ah);
+ close_archive (ah);
return result;
}
+/* Delete the listed locales from archive AH->FNAME or the default
+ archive if NULL. */
int
-delete_locales_from_archive (nlist, list)
- size_t nlist;
- char *list[];
+delete_locales_from_archive (struct locarhandle *ah,
+ size_t nlist,
+ char *list[])
{
- struct locarhandle ah;
struct locarhead *head;
struct namehashent *namehashtab;
/* Open the archive. This call never returns if we cannot
successfully open the archive. */
- ah.fname = NULL;
- open_archive (&ah, false);
+ open_archive (ah, false);
- head = ah.addr;
- namehashtab = (struct namehashent *) ((char *) ah.addr
+ head = ah->addr;
+ namehashtab = (struct namehashent *) ((char *) ah->addr
+ GET (head->namehash_offset));
while (nlist-- > 0)
@@ -1565,7 +1562,7 @@ delete_locales_from_archive (nlist, list)
{
if (GET (namehashtab[idx].hashval) == hval
&& (strcmp (locname,
- ((char *) ah.addr
+ ((char *) ah->addr
+ GET (namehashtab[idx].name_offset)))
== 0))
{
@@ -1584,7 +1581,7 @@ delete_locales_from_archive (nlist, list)
error (0, 0, _("locale \"%s\" not in archive"), locname);
}
- close_archive (&ah);
+ close_archive (ah);
return 0;
}
@@ -326,7 +326,7 @@ static void (*const write_funcs[]) (struct localedef_t *,
void
-write_all_categories (struct localedef_t *definitions,
+write_all_categories (struct locarhandle *ah, struct localedef_t *definitions,
const struct charmap_t *charmap, const char *locname,
const char *output_path)
{
@@ -338,19 +338,15 @@ write_all_categories (struct localedef_t *definitions,
if (! no_archive)
{
- /* The data has to be added to the archive. Do this now. */
- struct locarhandle ah;
-
/* Open the archive. This call never returns if we cannot
successfully open the archive. */
- ah.fname = NULL;
- open_archive (&ah, false);
+ open_archive (ah, false);
- if (add_locale_to_archive (&ah, locname, to_archive, true) != 0)
+ if (add_locale_to_archive (ah, locname, to_archive, true) != 0)
error (EXIT_FAILURE, errno, _("cannot add to locale archive"));
/* We are done. */
- close_archive (&ah);
+ close_archive (ah);
}
}
@@ -64,7 +64,8 @@ extern void check_all_categories (struct localedef_t *definitions,
const struct charmap_t *charmap);
/* Write out all locale categories. */
-extern void write_all_categories (struct localedef_t *definitions,
+extern void write_all_categories (struct locarhandle *ah,
+ struct localedef_t *definitions,
const struct charmap_t *charmap,
const char *locname,
const char *output_path);