mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-05 21:00:05 +00:00
Update.
2002-04-18 Ulrich Drepper <drepper@redhat.com> * locale/programs/locfile.c (to_archive): New variable. To collect data which has to be added to the locale archive. (write_all_categories): Take new third parameter with locale name. Unless no_archive flag set add new locale data to the archive (write_locale_data): Unless no-archive flag set store generated data in to_archive data structure instead of generation output file. Add new parameter with locale category index. * locale/programs/locfile.h: Add new parameters in declaractions of write_all_categories and write_locale_data. * locale/programs/localedef.c: Recognize --no-archive, --list-archive, --add-to-archive, and --delete-from-archive options. Pass extra parameter to write_all_categories. * locale/programs/localedef.h: Add prototypes for functions in locarchive.c. * locale/locarchive.h: New file. * locale/programs/locarchive.c: New file. * locale/Makefile (distribute): Add programs/locarchive.c and locarchive.h. (localedef-modules): Add md5 and locarchive. Add vpath to crypt subdir for md5.c. * locale/programs/ld-address.c: Pass locale category ID as new second parameter to write_locale_data. * locale/programs/ld-collate.c: Likewise. * locale/programs/ld-ctype.c: Likewise. * locale/programs/ld-identification.c: Likewise. * locale/programs/ld-measurement.c: Likewise. * locale/programs/ld-messages.c: Likewise. * locale/programs/ld-monetary.c: Likewise. * locale/programs/ld-name.c: Likewise. * locale/programs/ld-numeric.c: Likewise. * locale/programs/ld-paper.c: Likewise. * locale/programs/ld-telephone.c: Likewise. * locale/programs/ld-time.c: Likewise. * locale/simple-hash.c: Move compute_hashval function from here... * locale/hashval.h: ...to here. New file. * locale/simple-hash.h: Add prototype for compute_hashval. * include/libintl.h: Minor cleanups. * elf/reldep7.c: New file. * elf/reldep7mod1.c: New file. * elf/reldep7mod2.c: New file. * elf/Makefile: Add rules to build and run reldep7.
This commit is contained in:
parent
c77694049a
commit
a7b65cdc9a
51
ChangeLog
51
ChangeLog
@ -1,3 +1,46 @@
|
||||
2002-04-18 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* locale/programs/locfile.c (to_archive): New variable. To collect
|
||||
data which has to be added to the locale archive.
|
||||
(write_all_categories): Take new third parameter with locale name.
|
||||
Unless no_archive flag set add new locale data to the archive
|
||||
(write_locale_data): Unless no-archive flag set store generated data
|
||||
in to_archive data structure instead of generation output file.
|
||||
Add new parameter with locale category index.
|
||||
* locale/programs/locfile.h: Add new parameters in declaractions of
|
||||
write_all_categories and write_locale_data.
|
||||
* locale/programs/localedef.c: Recognize --no-archive, --list-archive,
|
||||
--add-to-archive, and --delete-from-archive options. Pass extra
|
||||
parameter to write_all_categories.
|
||||
* locale/programs/localedef.h: Add prototypes for functions in
|
||||
locarchive.c.
|
||||
* locale/locarchive.h: New file.
|
||||
* locale/programs/locarchive.c: New file.
|
||||
* locale/Makefile (distribute): Add programs/locarchive.c and
|
||||
locarchive.h.
|
||||
(localedef-modules): Add md5 and locarchive.
|
||||
Add vpath to crypt subdir for md5.c.
|
||||
|
||||
* locale/programs/ld-address.c: Pass locale category ID as new second
|
||||
parameter to write_locale_data.
|
||||
* locale/programs/ld-collate.c: Likewise.
|
||||
* locale/programs/ld-ctype.c: Likewise.
|
||||
* locale/programs/ld-identification.c: Likewise.
|
||||
* locale/programs/ld-measurement.c: Likewise.
|
||||
* locale/programs/ld-messages.c: Likewise.
|
||||
* locale/programs/ld-monetary.c: Likewise.
|
||||
* locale/programs/ld-name.c: Likewise.
|
||||
* locale/programs/ld-numeric.c: Likewise.
|
||||
* locale/programs/ld-paper.c: Likewise.
|
||||
* locale/programs/ld-telephone.c: Likewise.
|
||||
* locale/programs/ld-time.c: Likewise.
|
||||
|
||||
* locale/simple-hash.c: Move compute_hashval function from here...
|
||||
* locale/hashval.h: ...to here. New file.
|
||||
* locale/simple-hash.h: Add prototype for compute_hashval.
|
||||
|
||||
* include/libintl.h: Minor cleanups.
|
||||
|
||||
2002-04-16 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* posix/regcomp.c (gettext): Use INTUSE for _libc_intl_domainname.
|
||||
@ -13,10 +56,10 @@
|
||||
|
||||
2002-02-17 Andreas Schwab <schwab@suse.de>
|
||||
|
||||
* reldep7.c: New file.
|
||||
* reldep7mod1.c: New file.
|
||||
* reldep7mod2.c: New file.
|
||||
* Makefile: Add rules to build and run reldep7.
|
||||
* elf/reldep7.c: New file.
|
||||
* elf/reldep7mod1.c: New file.
|
||||
* elf/reldep7mod2.c: New file.
|
||||
* elf/Makefile: Add rules to build and run reldep7.
|
||||
|
||||
2002-04-14 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
|
@ -30,10 +30,10 @@ extern const char _libc_intl_domainname_internal[] attribute_hidden;
|
||||
/* This is defined as an optimizing macro, so use it. */
|
||||
# if !defined NOT_IN_libc && defined SHARED
|
||||
# define _(msgid) \
|
||||
__dcgettext_internal (_libc_intl_domainname_internal, (msgid), LC_MESSAGES)
|
||||
__dcgettext_internal (_libc_intl_domainname_internal, msgid, LC_MESSAGES)
|
||||
# else
|
||||
# define _(msgid) \
|
||||
__dcgettext (_libc_intl_domainname, (msgid), LC_MESSAGES)
|
||||
__dcgettext (_libc_intl_domainname, msgid, LC_MESSAGES)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 1991, 92, 1995-1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1991,92,1995-1999,2000,2001,2002 Free Software Foundation, Inc.
|
||||
# This file is part of the GNU C Library.
|
||||
|
||||
# The GNU C Library is free software; you can redistribute it and/or
|
||||
@ -26,6 +26,7 @@ distribute = localeinfo.h categories.def iso-639.def iso-3166.def \
|
||||
iso-4217.def weight.h weightwc.h strlen-hash.h elem-hash.h \
|
||||
indigits.h indigitswc.h outdigits.h outdigitswc.h \
|
||||
coll-lookup.h C-translit.h.in C-translit.h gen-translit.pl \
|
||||
locarchive.h \
|
||||
$(addprefix programs/, \
|
||||
locale.c localedef.c \
|
||||
$(localedef-modules:=.c) $(locale-modules:=.c) \
|
||||
@ -33,7 +34,7 @@ distribute = localeinfo.h categories.def iso-639.def iso-3166.def \
|
||||
charmap-kw.gperf charmap-kw.h locfile-token.h \
|
||||
locfile-kw.gperf locfile-kw.h linereader.h \
|
||||
locfile.h charmap.h repertoire.h localedef.h \
|
||||
3level.h charmap-dir.h)
|
||||
3level.h charmap-dir.h locarchive.c)
|
||||
routines = setlocale findlocale loadlocale localeconv nl_langinfo \
|
||||
nl_langinfo_l mb_cur_max \
|
||||
newlocale duplocale freelocale
|
||||
@ -54,12 +55,12 @@ extra-libs-others = $(extra-libs)
|
||||
libBrokenLocale-routines = broken_cur_max
|
||||
|
||||
subdir-dirs = programs
|
||||
vpath %.c programs
|
||||
vpath %.c programs ../crypt
|
||||
vpath %.h programs
|
||||
vpath %.gperf programs
|
||||
|
||||
localedef-modules := $(categories:%=ld-%) charmap linereader locfile \
|
||||
repertoire
|
||||
repertoire md5 locarchive
|
||||
locale-modules := locale-spec
|
||||
lib-modules := charmap-dir simple-hash xmalloc xstrdup
|
||||
|
||||
|
41
locale/hashval.h
Normal file
41
locale/hashval.h
Normal file
@ -0,0 +1,41 @@
|
||||
/* Implement simple hashing table with string based keys.
|
||||
Copyright (C) 1994-1997, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, October 1994.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
unsigned long
|
||||
compute_hashval (key, keylen)
|
||||
const void *key;
|
||||
size_t keylen;
|
||||
{
|
||||
size_t cnt;
|
||||
unsigned long int hval;
|
||||
|
||||
/* Compute the hash value for the given string. The algorithm
|
||||
is taken from [Aho,Sethi,Ullman], modified to reduce the number of
|
||||
collisions for short strings with very varied bit patterns.
|
||||
See http://www.clisp.org/haible/hashfunc.html. */
|
||||
cnt = 0;
|
||||
hval = keylen;
|
||||
while (cnt < keylen)
|
||||
{
|
||||
hval = (hval << 9) | (hval >> (LONGBITS - 9));
|
||||
hval += (unsigned long int) *(((char *) key) + cnt++);
|
||||
}
|
||||
return hval != 0 ? hval : ~((unsigned long) 0);
|
||||
}
|
97
locale/locarchive.h
Normal file
97
locale/locarchive.h
Normal file
@ -0,0 +1,97 @@
|
||||
/* Definitions for locale archive handling.
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#ifndef _LOCARCHIVE_H
|
||||
#define _LOCARCHIVE_H 1
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#define AR_MAGIC 0xde020109
|
||||
|
||||
struct locarhead
|
||||
{
|
||||
uint32_t magic;
|
||||
/* Serial number. */
|
||||
uint32_t serial;
|
||||
/* Name hash table. */
|
||||
uint32_t namehash_offset;
|
||||
uint32_t namehash_used;
|
||||
uint32_t namehash_size;
|
||||
/* String table. */
|
||||
uint32_t string_offset;
|
||||
uint32_t string_used;
|
||||
uint32_t string_size;
|
||||
/* Table with locale records. */
|
||||
uint32_t locrectab_offset;
|
||||
uint32_t locrectab_used;
|
||||
uint32_t locrectab_size;
|
||||
/* MD5 sum hash table. */
|
||||
uint32_t sumhash_offset;
|
||||
uint32_t sumhash_used;
|
||||
uint32_t sumhash_size;
|
||||
};
|
||||
|
||||
|
||||
struct namehashent
|
||||
{
|
||||
/* Hash value of the name. */
|
||||
uint32_t hashval;
|
||||
/* Offset of the name in the string table. */
|
||||
uint32_t name_offset;
|
||||
/* Offset of the locale record. */
|
||||
uint32_t locrec_offset;
|
||||
};
|
||||
|
||||
|
||||
struct sumhashent
|
||||
{
|
||||
/* MD5 sum. */
|
||||
char sum[16];
|
||||
/* Offset of the file in the archive. */
|
||||
uint32_t file_offset;
|
||||
};
|
||||
|
||||
struct locrecent
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t offset;
|
||||
uint32_t len;
|
||||
} record[__LC_LAST];
|
||||
};
|
||||
|
||||
|
||||
struct locarhandle
|
||||
{
|
||||
int fd;
|
||||
void *addr;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
|
||||
/* In memory data for the locales with their checksums. */
|
||||
typedef struct
|
||||
{
|
||||
off64_t size;
|
||||
void *addr;
|
||||
char sum[16];
|
||||
} locale_data_t[__LC_LAST];
|
||||
|
||||
#endif /* locarchive.h */
|
@ -422,7 +422,7 @@ address_output (struct localedef_t *locale, const struct charmap_t *charmap,
|
||||
|
||||
assert (cnt == 3 + _NL_ITEM_INDEX (_NL_NUM_LC_ADDRESS));
|
||||
|
||||
write_locale_data (output_path, "LC_ADDRESS",
|
||||
write_locale_data (output_path, LC_ADDRESS, "LC_ADDRESS",
|
||||
3 + _NL_ITEM_INDEX (_NL_NUM_LC_ADDRESS), iov);
|
||||
}
|
||||
|
||||
|
@ -1987,7 +1987,7 @@ collate_output (struct localedef_t *locale, const struct charmap_t *charmap,
|
||||
|
||||
assert (cnt == _NL_ITEM_INDEX (_NL_NUM_LC_COLLATE));
|
||||
|
||||
write_locale_data (output_path, "LC_COLLATE", 2 + cnt, iov);
|
||||
write_locale_data (output_path, LC_COLLATE, "LC_COLLATE", 2 + cnt, iov);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -2571,7 +2571,7 @@ collate_output (struct localedef_t *locale, const struct charmap_t *charmap,
|
||||
|
||||
assert (cnt == _NL_ITEM_INDEX (_NL_NUM_LC_COLLATE));
|
||||
|
||||
write_locale_data (output_path, "LC_COLLATE", 2 + cnt, iov);
|
||||
write_locale_data (output_path, LC_COLLATE, "LC_COLLATE", 2 + cnt, iov);
|
||||
|
||||
obstack_free (&weightpool, NULL);
|
||||
obstack_free (&extrapool, NULL);
|
||||
|
@ -1214,7 +1214,8 @@ ctype_output (struct localedef_t *locale, const struct charmap_t *charmap,
|
||||
assert (2 + elem + offset == (nelems + 2 * ctype->nr_charclass
|
||||
+ ctype->map_collection_nr + 4 + 2));
|
||||
|
||||
write_locale_data (output_path, "LC_CTYPE", 2 + elem + offset, iov);
|
||||
write_locale_data (output_path, LC_CTYPE, "LC_CTYPE", 2 + elem + offset,
|
||||
iov);
|
||||
}
|
||||
|
||||
|
||||
|
@ -291,7 +291,8 @@ identification_output (struct localedef_t *locale,
|
||||
assert (cnt == (2 + _NL_ITEM_INDEX (_NL_NUM_LC_IDENTIFICATION)
|
||||
+ (__LC_LAST - 2)));
|
||||
|
||||
write_locale_data (output_path, "LC_IDENTIFICATION", cnt, iov);
|
||||
write_locale_data (output_path, LC_IDENTIFICATION, "LC_IDENTIFICATION", cnt,
|
||||
iov);
|
||||
}
|
||||
|
||||
|
||||
|
@ -150,7 +150,7 @@ measurement_output (struct localedef_t *locale,
|
||||
|
||||
assert (cnt == 2 + _NL_ITEM_INDEX (_NL_NUM_LC_MEASUREMENT));
|
||||
|
||||
write_locale_data (output_path, "LC_MEASUREMENT",
|
||||
write_locale_data (output_path, LC_MEASUREMENT, "LC_MEASUREMENT",
|
||||
2 + _NL_ITEM_INDEX (_NL_NUM_LC_MEASUREMENT), iov);
|
||||
}
|
||||
|
||||
|
@ -226,7 +226,7 @@ messages_output (struct localedef_t *locale, const struct charmap_t *charmap,
|
||||
|
||||
assert (cnt + 1 == 2 + _NL_ITEM_INDEX (_NL_NUM_LC_MESSAGES));
|
||||
|
||||
write_locale_data (output_path, "LC_MESSAGES",
|
||||
write_locale_data (output_path, LC_MESSAGES, "LC_MESSAGES",
|
||||
2 + _NL_ITEM_INDEX (_NL_NUM_LC_MESSAGES), iov);
|
||||
}
|
||||
|
||||
|
@ -612,7 +612,7 @@ monetary_output (struct localedef_t *locale, const struct charmap_t *charmap,
|
||||
|
||||
assert (cnt == 3 + _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY));
|
||||
|
||||
write_locale_data (output_path, "LC_MONETARY",
|
||||
write_locale_data (output_path, LC_MONETARY, "LC_MONETARY",
|
||||
3 + _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY), iov);
|
||||
}
|
||||
|
||||
|
@ -210,7 +210,7 @@ name_output (struct localedef_t *locale, const struct charmap_t *charmap,
|
||||
|
||||
assert (cnt == 2 + _NL_ITEM_INDEX (_NL_NUM_LC_NAME));
|
||||
|
||||
write_locale_data (output_path, "LC_NAME",
|
||||
write_locale_data (output_path, LC_NAME, "LC_NAME",
|
||||
2 + _NL_ITEM_INDEX (_NL_NUM_LC_NAME), iov);
|
||||
}
|
||||
|
||||
|
@ -187,7 +187,7 @@ numeric_output (struct localedef_t *locale, const struct charmap_t *charmap,
|
||||
|
||||
assert (cnt + 1 == 3 + _NL_ITEM_INDEX (_NL_NUM_LC_NUMERIC));
|
||||
|
||||
write_locale_data (output_path, "LC_NUMERIC",
|
||||
write_locale_data (output_path, LC_NUMERIC, "LC_NUMERIC",
|
||||
3 + _NL_ITEM_INDEX (_NL_NUM_LC_NUMERIC), iov);
|
||||
}
|
||||
|
||||
|
@ -154,7 +154,7 @@ paper_output (struct localedef_t *locale, const struct charmap_t *charmap,
|
||||
|
||||
assert (cnt == 2 + _NL_ITEM_INDEX (_NL_NUM_LC_PAPER));
|
||||
|
||||
write_locale_data (output_path, "LC_PAPER",
|
||||
write_locale_data (output_path, LC_PAPER, "LC_PAPER",
|
||||
2 + _NL_ITEM_INDEX (_NL_NUM_LC_PAPER), iov);
|
||||
}
|
||||
|
||||
|
@ -218,7 +218,7 @@ telephone_output (struct localedef_t *locale, const struct charmap_t *charmap,
|
||||
|
||||
assert (cnt == 2 + _NL_ITEM_INDEX (_NL_NUM_LC_TELEPHONE));
|
||||
|
||||
write_locale_data (output_path, "LC_TELEPHONE",
|
||||
write_locale_data (output_path, LC_TELEPHONE, "LC_TELEPHONE",
|
||||
2 + _NL_ITEM_INDEX (_NL_NUM_LC_TELEPHONE), iov);
|
||||
}
|
||||
|
||||
|
@ -906,7 +906,7 @@ time_output (struct localedef_t *locale, const struct charmap_t *charmap,
|
||||
+ 2 + time->num_era * 10 - 1));
|
||||
assert (last_idx == _NL_ITEM_INDEX (_NL_NUM_LC_TIME));
|
||||
|
||||
write_locale_data (output_path, "LC_TIME", 2 + cnt, iov);
|
||||
write_locale_data (output_path, LC_TIME, "LC_TIME", 2 + cnt, iov);
|
||||
}
|
||||
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <libintl.h>
|
||||
#include <locale.h>
|
||||
#include <mcheck.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -56,7 +57,8 @@ int verbose;
|
||||
/* If not zero suppress warnings and information messages. */
|
||||
int be_quiet;
|
||||
|
||||
/* If not zero, produce old-style hash table instead of 3-level access tables. */
|
||||
/* If not zero, produce old-style hash table instead of 3-level access
|
||||
tables. */
|
||||
int oldstyle_tables;
|
||||
|
||||
/* If not zero force output even if warning were issued. */
|
||||
@ -77,15 +79,38 @@ const char *repertoire_global;
|
||||
/* List of all locales. */
|
||||
static struct localedef_t *locales;
|
||||
|
||||
/* If true don't add locale data to archive. */
|
||||
bool no_archive;
|
||||
|
||||
/* If true add named locales to archive. */
|
||||
static bool add_to_archive;
|
||||
|
||||
/* If true delete named locales from archive. */
|
||||
static bool delete_from_archive;
|
||||
|
||||
/* If true replace archive content when adding. */
|
||||
static bool replace_archive;
|
||||
|
||||
/* If true list archive content. */
|
||||
static bool list_archive;
|
||||
|
||||
/* Maximum number of retries when opening the locale archive. */
|
||||
int max_locarchive_open_retry = 10;
|
||||
|
||||
|
||||
/* Name and version of program. */
|
||||
static void print_version (FILE *stream, struct argp_state *state);
|
||||
void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
|
||||
|
||||
#define OPT_POSIX 1
|
||||
#define OPT_QUIET 2
|
||||
#define OPT_OLDSTYLE 3
|
||||
#define OPT_PREFIX 4
|
||||
#define OPT_POSIX 301
|
||||
#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
|
||||
|
||||
/* Definitions of arguments for argp functions. */
|
||||
static const struct argp_option options[] =
|
||||
@ -106,6 +131,15 @@ static const struct argp_option options[] =
|
||||
{ "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:") },
|
||||
{ "no-archive", OPT_NO_ARCHIVE, NULL, 0,
|
||||
N_("Don't add new data to archive") },
|
||||
{ "add-to-archive", OPT_ADD_TO_ARCHIVE, NULL, 0,
|
||||
N_("Add locales named by parameters to archive") },
|
||||
{ "replace", OPT_REPLACE, NULL, 0, N_("Replace existing archive content") },
|
||||
{ "delete-from-archive", OPT_DELETE_FROM_ARCHIVE, NULL, 0,
|
||||
N_("Remove locales named by parameters from archive") },
|
||||
{ "list-archive", OPT_LIST_ARCHIVE, NULL, 0, N_("List content of archive") },
|
||||
{ NULL, 0, NULL, 0, NULL }
|
||||
};
|
||||
|
||||
@ -113,7 +147,10 @@ static const struct argp_option options[] =
|
||||
static const char doc[] = N_("Compile locale specification");
|
||||
|
||||
/* Strings for arguments in help texts. */
|
||||
static const char args_doc[] = N_("NAME");
|
||||
static const char args_doc[] = N_("\
|
||||
NAME\n\
|
||||
[--add-to-archive|--delete-from-archive] FILE...\n\
|
||||
--list-archive [FILE]");
|
||||
|
||||
/* Prototype for option handler. */
|
||||
static error_t parse_opt (int key, char *arg, struct argp_state *state);
|
||||
@ -163,6 +200,15 @@ main (int argc, char *argv[])
|
||||
argp_err_exit_status = 4;
|
||||
argp_parse (&argp, argc, argv, 0, &remaining, NULL);
|
||||
|
||||
/* Handle a few special cases. */
|
||||
if (list_archive)
|
||||
show_archive_content ();
|
||||
if (add_to_archive)
|
||||
return add_locales_to_archive (argc - remaining, &argv[remaining],
|
||||
replace_archive);
|
||||
if (delete_from_archive)
|
||||
return delete_locales_from_archive (argc - remaining, &argv[remaining]);
|
||||
|
||||
/* POSIX.2 requires to be verbose about missing characters in the
|
||||
character map. */
|
||||
verbose |= posix_conformance;
|
||||
@ -177,10 +223,18 @@ main (int argc, char *argv[])
|
||||
|
||||
/* The parameter describes the output path of the constructed files.
|
||||
If the described files cannot be written return a NULL pointer. */
|
||||
output_path = construct_output_path (argv[remaining]);
|
||||
if (output_path == NULL)
|
||||
error (4, errno, _("cannot create directory for output files"));
|
||||
cannot_write_why = errno;
|
||||
if (no_archive)
|
||||
{
|
||||
output_path = construct_output_path (argv[remaining]);
|
||||
if (output_path == NULL)
|
||||
error (4, errno, _("cannot create directory for output files"));
|
||||
cannot_write_why = errno;
|
||||
}
|
||||
else
|
||||
{
|
||||
output_path = NULL;
|
||||
cannot_write_why = 0; /* Just to shut the compiler up. */
|
||||
}
|
||||
|
||||
/* Now that the parameters are processed we have to reset the local
|
||||
ctype locale. (P1003.2 4.35.5.2) */
|
||||
@ -235,7 +289,7 @@ cannot open locale definition file `%s'"), runp->name));
|
||||
WITH_CUR_LOCALE (error (4, cannot_write_why, _("\
|
||||
cannot write output files to `%s'"), output_path));
|
||||
else
|
||||
write_all_categories (locales, charmap, output_path);
|
||||
write_all_categories (locales, charmap, argv[remaining], output_path);
|
||||
}
|
||||
else
|
||||
WITH_CUR_LOCALE (error (4, 0, _("\
|
||||
@ -264,6 +318,21 @@ parse_opt (int key, char *arg, struct argp_state *state)
|
||||
case OPT_PREFIX:
|
||||
output_prefix = arg;
|
||||
break;
|
||||
case OPT_NO_ARCHIVE:
|
||||
no_archive = true;
|
||||
break;
|
||||
case OPT_ADD_TO_ARCHIVE:
|
||||
add_to_archive = true;
|
||||
break;
|
||||
case OPT_REPLACE:
|
||||
replace_archive = true;
|
||||
break;
|
||||
case OPT_DELETE_FROM_ARCHIVE:
|
||||
delete_from_archive = true;
|
||||
break;
|
||||
case OPT_LIST_ARCHIVE:
|
||||
list_archive = true;
|
||||
break;
|
||||
case 'c':
|
||||
force_output = 1;
|
||||
break;
|
||||
@ -392,6 +461,10 @@ construct_output_path (char *path)
|
||||
size_t len = strlen (path) + 1;
|
||||
result = xmalloc (len + 1);
|
||||
endp = mempcpy (result, path, len) - 1;
|
||||
|
||||
/* If the user specified an output path we cannot add the output
|
||||
to the archive. */
|
||||
no_archive = true;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* General definitions for localedef(1).
|
||||
Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
|
||||
|
||||
@ -22,11 +22,13 @@
|
||||
#define _LOCALEDEF_H 1
|
||||
|
||||
/* Get the basic locale definitions. */
|
||||
#include <locale.h>
|
||||
#include <stddef.h>
|
||||
#include <errno.h>
|
||||
#include <locale.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "repertoire.h"
|
||||
#include "../locarchive.h"
|
||||
|
||||
|
||||
/* We need a bitmask for the locales. */
|
||||
@ -114,6 +116,8 @@ extern int verbose;
|
||||
extern int be_quiet;
|
||||
extern int oldstyle_tables;
|
||||
extern const char *repertoire_global;
|
||||
extern int max_locarchive_open_retry;
|
||||
extern bool no_archive;
|
||||
|
||||
|
||||
/* Prototypes for a few program-wide used functions. */
|
||||
@ -153,4 +157,24 @@ extern struct localedef_t *load_locale (int locale, const char *name,
|
||||
const struct charmap_t *charmap,
|
||||
struct localedef_t *copy_locale);
|
||||
|
||||
|
||||
/* Open the locale archive. */
|
||||
extern void open_archive (struct locarhandle *ah);
|
||||
|
||||
/* Close the locale archive. */
|
||||
extern void close_archive (struct locarhandle *ah);
|
||||
|
||||
/* Add given locale data to the archive. */
|
||||
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);
|
||||
|
||||
/* Removed named locales from archive. */
|
||||
extern int delete_locales_from_archive (size_t nlist, char *list[]);
|
||||
|
||||
/* List content of locale archive. */
|
||||
extern void show_archive_content (void);
|
||||
|
||||
#endif /* localedef.h */
|
||||
|
931
locale/programs/locarchive.c
Normal file
931
locale/programs/locarchive.c
Normal file
@ -0,0 +1,931 @@
|
||||
/* Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <error.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <libintl.h>
|
||||
#include <locale.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "../../crypt/md5.h"
|
||||
#include "../localeinfo.h"
|
||||
#include "../locarchive.h"
|
||||
#include "simple-hash.h"
|
||||
#include "localedef.h"
|
||||
|
||||
|
||||
static const char archivefname[] = LOCALEDIR "/locale-archive";
|
||||
|
||||
static const char *locnames[] =
|
||||
{
|
||||
#define DEFINE_CATEGORY(category, category_name, items, a) \
|
||||
[category] = category_name,
|
||||
#include "categories.def"
|
||||
#undef DEFINE_CATEGORY
|
||||
};
|
||||
|
||||
|
||||
/* Size of the initial archive header. */
|
||||
#define INITIAL_NUM_NANES 450
|
||||
#define INITIAL_SIZE_STRINGS 3500
|
||||
#define INITIAL_NUM_LOCREC 350
|
||||
#define INITIAL_NUM_SUMS 2000
|
||||
|
||||
|
||||
static void
|
||||
create_archive (struct locarhandle *ah)
|
||||
{
|
||||
int fd;
|
||||
char fname[] = LOCALEDIR "/locale-archive.XXXXXX";
|
||||
struct locarhead head;
|
||||
void *p;
|
||||
size_t total;
|
||||
|
||||
/* Create a temporary file in the correct directory. */
|
||||
fd = mkstemp (fname);
|
||||
if (fd == -1)
|
||||
error (EXIT_FAILURE, errno, _("cannot create temporary file"));
|
||||
|
||||
/* Create the initial content of the archive. */
|
||||
head.magic = AR_MAGIC;
|
||||
head.namehash_offset = sizeof (struct locarhead);
|
||||
head.namehash_used = 0;
|
||||
head.namehash_size = next_prime (INITIAL_NUM_NANES);
|
||||
|
||||
head.string_offset = (head.namehash_offset
|
||||
+ head.namehash_size * sizeof (struct namehashent));
|
||||
head.string_used = 0;
|
||||
head.string_size = INITIAL_SIZE_STRINGS;
|
||||
|
||||
head.locrectab_offset = head.string_offset + head.string_size;
|
||||
head.locrectab_used = 0;
|
||||
head.locrectab_size = INITIAL_NUM_LOCREC;
|
||||
|
||||
head.sumhash_offset = (head.locrectab_offset
|
||||
+ head.locrectab_size * sizeof (struct locrecent));
|
||||
head.sumhash_used = 0;
|
||||
head.sumhash_size = next_prime (INITIAL_NUM_SUMS);
|
||||
|
||||
total = head.sumhash_offset + head.sumhash_size * sizeof (struct sumhashent);
|
||||
|
||||
/* Write out the header and create room for the other data structures. */
|
||||
if (TEMP_FAILURE_RETRY (write (fd, &head, sizeof (head))) != sizeof (head))
|
||||
{
|
||||
int errval = errno;
|
||||
unlink (fname);
|
||||
error (EXIT_FAILURE, errval, _("cannot initialize archive file"));
|
||||
}
|
||||
|
||||
if (ftruncate64 (fd, total) != 0)
|
||||
{
|
||||
int errval = errno;
|
||||
unlink (fname);
|
||||
error (EXIT_FAILURE, errval, _("cannot resize archive file"));
|
||||
}
|
||||
|
||||
/* Map the header and all the administration data structures. */
|
||||
p = mmap64 (NULL, total, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (p == MAP_FAILED)
|
||||
{
|
||||
int errval = errno;
|
||||
unlink (fname);
|
||||
error (EXIT_FAILURE, errval, _("cannot map archive header"));
|
||||
}
|
||||
|
||||
/* Now try to rename it. We don't use the rename function since
|
||||
this would overwrite a file which has been created in
|
||||
parallel. */
|
||||
if (link (fname, archivefname) == -1)
|
||||
{
|
||||
int errval = errno;
|
||||
|
||||
/* We cannot use the just created file. */
|
||||
close (fd);
|
||||
unlink (fname);
|
||||
|
||||
if (errval == EEXIST)
|
||||
{
|
||||
/* There is already an archive. Must have been a localedef run
|
||||
which happened in parallel. Simply open this file then. */
|
||||
open_archive (ah);
|
||||
return;
|
||||
}
|
||||
|
||||
error (EXIT_FAILURE, errval, _("failed to create new locale archive"));
|
||||
}
|
||||
|
||||
/* Remove the temporary name. */
|
||||
unlink (fname);
|
||||
|
||||
/* Make the file globally readable. */
|
||||
if (fchmod (fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) == -1)
|
||||
{
|
||||
int errval = errno;
|
||||
unlink (archivefname);
|
||||
error (EXIT_FAILURE, errval,
|
||||
_("cannot change mode of new locale archive"));
|
||||
}
|
||||
|
||||
ah->fd = fd;
|
||||
ah->addr = p;
|
||||
ah->len = total;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
enlarge_archive (struct locarhandle *ah, const struct locarhead *head)
|
||||
{
|
||||
struct stat64 st;
|
||||
int fd;
|
||||
char fname[] = LOCALEDIR "/locale-archive.XXXXXX";
|
||||
struct locarhead newhead;
|
||||
size_t total;
|
||||
void *p;
|
||||
unsigned int cnt;
|
||||
struct namehashent *oldnamehashtab;
|
||||
struct locrecent *oldlocrectab;
|
||||
struct locarhandle new_ah;
|
||||
|
||||
/* Not all of the old file has to be mapped. Change this now this
|
||||
we will have to access the whole content. */
|
||||
if (fstat64 (ah->fd, &st) != 0
|
||||
|| (ah->addr = mmap64 (NULL, st.st_size, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, ah->fd, 0)) == MAP_FAILED)
|
||||
error (EXIT_FAILURE, errno, _("cannot map locale archive file"));
|
||||
ah->len = st.st_size;
|
||||
|
||||
/* Create a temporary file in the correct directory. */
|
||||
fd = mkstemp (fname);
|
||||
if (fd == -1)
|
||||
error (EXIT_FAILURE, errno, _("cannot create temporary file"));
|
||||
|
||||
/* Copy the existing head information. */
|
||||
newhead = *head;
|
||||
|
||||
/* Create the new archive header. The sizes of the various tables
|
||||
should be double from what is currently used. */
|
||||
newhead.namehash_size = MAX (next_prime (2 * newhead.namehash_used),
|
||||
newhead.namehash_size);
|
||||
printf ("name: size: %u, used: %d, new: size: %u\n",
|
||||
head->namehash_size, head->namehash_used, newhead.namehash_size);
|
||||
|
||||
newhead.string_offset = (newhead.namehash_offset
|
||||
+ (newhead.namehash_size
|
||||
* sizeof (struct namehashent)));
|
||||
newhead.string_size = MAX (2 * newhead.string_used, newhead.string_size);
|
||||
|
||||
newhead.locrectab_offset = newhead.string_offset + newhead.string_size;
|
||||
newhead.locrectab_size = MAX (2 * newhead.locrectab_used,
|
||||
newhead.locrectab_size);
|
||||
|
||||
newhead.sumhash_offset = (newhead.locrectab_offset
|
||||
+ (newhead.locrectab_size
|
||||
* sizeof (struct locrecent)));
|
||||
newhead.sumhash_size = MAX (next_prime (2 * newhead.sumhash_used),
|
||||
newhead.sumhash_size);
|
||||
|
||||
total = (newhead.sumhash_offset
|
||||
+ newhead.sumhash_size * sizeof (struct sumhashent));
|
||||
|
||||
/* The new file is empty now. */
|
||||
newhead.namehash_used = 0;
|
||||
newhead.string_used = 0;
|
||||
newhead.locrectab_used = 0;
|
||||
newhead.sumhash_used = 0;
|
||||
|
||||
/* Write out the header and create room for the other data structures. */
|
||||
if (TEMP_FAILURE_RETRY (write (fd, &newhead, sizeof (newhead)))
|
||||
!= sizeof (newhead))
|
||||
{
|
||||
int errval = errno;
|
||||
unlink (fname);
|
||||
error (EXIT_FAILURE, errval, _("cannot initialize archive file"));
|
||||
}
|
||||
|
||||
if (ftruncate64 (fd, total) != 0)
|
||||
{
|
||||
int errval = errno;
|
||||
unlink (fname);
|
||||
error (EXIT_FAILURE, errval, _("cannot resize archive file"));
|
||||
}
|
||||
|
||||
/* Map the header and all the administration data structures. */
|
||||
p = mmap64 (NULL, total, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (p == MAP_FAILED)
|
||||
{
|
||||
int errval = errno;
|
||||
unlink (fname);
|
||||
error (EXIT_FAILURE, errval, _("cannot map archive header"));
|
||||
}
|
||||
|
||||
/* Lock the new file. */
|
||||
if (lockf64 (fd, F_LOCK, total) != 0)
|
||||
{
|
||||
int errval = errno;
|
||||
unlink (fname);
|
||||
error (EXIT_FAILURE, errval, _("cannot lock new archive"));
|
||||
}
|
||||
|
||||
new_ah.len = total;
|
||||
new_ah.addr = p;
|
||||
new_ah.fd = fd;
|
||||
|
||||
/* Walk through the hash name hash table to find out what data is
|
||||
still referenced and transfer it into the new file. */
|
||||
oldnamehashtab = (struct namehashent *) ((char *) ah->addr
|
||||
+ head->namehash_offset);
|
||||
oldlocrectab = (struct locrecent *) ((char *) ah->addr
|
||||
+ head->locrectab_offset);
|
||||
for (cnt = 0; cnt < head->namehash_size; ++cnt)
|
||||
if (oldnamehashtab[cnt].locrec_offset != 0)
|
||||
{
|
||||
/* Insert this entry in the new hash table. */
|
||||
locale_data_t old_data;
|
||||
unsigned int idx;
|
||||
struct locrecent *oldlocrec;
|
||||
|
||||
oldlocrec = (struct locrecent *) ((char *) ah->addr
|
||||
+ oldnamehashtab[cnt].locrec_offset);
|
||||
|
||||
for (idx = 0; idx < __LC_LAST; ++idx)
|
||||
if (idx != LC_ALL)
|
||||
{
|
||||
old_data[idx].size = oldlocrec->record[idx].len;
|
||||
old_data[idx].addr
|
||||
= ((char *) ah->addr + oldlocrec->record[idx].offset);
|
||||
|
||||
__md5_buffer (old_data[idx].addr, old_data[idx].size,
|
||||
old_data[idx].sum);
|
||||
}
|
||||
|
||||
if (add_locale_to_archive (&new_ah,
|
||||
((char *) ah->addr
|
||||
+ oldnamehashtab[cnt].name_offset),
|
||||
old_data, 0) != 0)
|
||||
error (EXIT_FAILURE, 0, _("cannot extend locale archive file"));
|
||||
}
|
||||
|
||||
|
||||
/* Make the file globally readable. */
|
||||
if (fchmod (fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) == -1)
|
||||
{
|
||||
int errval = errno;
|
||||
unlink (fname);
|
||||
error (EXIT_FAILURE, errval,
|
||||
_("cannot change mode of resized locale archive"));
|
||||
}
|
||||
|
||||
/* Rename the new file. */
|
||||
if (rename (fname, archivefname) != 0)
|
||||
{
|
||||
int errval = errno;
|
||||
unlink (fname);
|
||||
error (EXIT_FAILURE, errval, _("cannot rename new archive"));
|
||||
}
|
||||
|
||||
/* Close the old file. */
|
||||
close_archive (ah);
|
||||
|
||||
/* Add the information for the new one. */
|
||||
*ah = new_ah;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
open_archive (struct locarhandle *ah)
|
||||
{
|
||||
struct stat64 st;
|
||||
struct stat64 st2;
|
||||
int fd;
|
||||
struct locarhead head;
|
||||
int retry = 0;
|
||||
|
||||
again:
|
||||
/* Open the archive. We must have exclusive write access. */
|
||||
fd = open64 (archivefname, O_RDWR);
|
||||
if (fd == -1)
|
||||
{
|
||||
/* Maybe the file does not yet exist. */
|
||||
if (errno == ENOENT)
|
||||
{
|
||||
create_archive (ah);
|
||||
return;
|
||||
}
|
||||
else
|
||||
error (EXIT_FAILURE, errno, _("cannot open locale archive \"%s\""),
|
||||
archivefname);
|
||||
}
|
||||
|
||||
if (fstat64 (fd, &st) < 0)
|
||||
error (EXIT_FAILURE, errno, _("cannot stat locale archive \"%s\""),
|
||||
archivefname);
|
||||
|
||||
if (lockf64 (fd, F_LOCK, st.st_size) == -1)
|
||||
{
|
||||
close (fd);
|
||||
|
||||
if (retry++ < max_locarchive_open_retry)
|
||||
{
|
||||
struct timespec req;
|
||||
|
||||
/* Wait for a bit. */
|
||||
req.tv_sec = 0;
|
||||
req.tv_nsec = 1000000 * (random () % 500 + 1);
|
||||
(void) nanosleep (&req, NULL);
|
||||
|
||||
goto again;
|
||||
}
|
||||
|
||||
error (EXIT_FAILURE, errno, _("cannot lock locale archive \"%s\""),
|
||||
archivefname);
|
||||
}
|
||||
|
||||
/* One more check. Maybe another process replaced the archive file
|
||||
with a new, larger one since we opened the file. */
|
||||
if (stat64 (archivefname, &st2) == -1
|
||||
|| st.st_dev != st2.st_dev
|
||||
|| st.st_ino != st2.st_ino)
|
||||
{
|
||||
close (fd);
|
||||
goto again;
|
||||
}
|
||||
|
||||
/* Read the header. */
|
||||
if (TEMP_FAILURE_RETRY (read (fd, &head, sizeof (head))) != sizeof (head))
|
||||
error (EXIT_FAILURE, errno, _("cannot read archive header"));
|
||||
|
||||
ah->fd = fd;
|
||||
ah->len = (head.sumhash_offset
|
||||
+ head.sumhash_size * sizeof (struct sumhashent));
|
||||
|
||||
/* Now we know how large the administrative information part is.
|
||||
Map all of it. */
|
||||
ah->addr = mmap64 (NULL, ah->len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (ah->addr == MAP_FAILED)
|
||||
error (EXIT_FAILURE, errno, _("cannot map archive header"));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
close_archive (struct locarhandle *ah)
|
||||
{
|
||||
munmap (ah->addr, ah->len);
|
||||
close (ah->fd);
|
||||
}
|
||||
|
||||
|
||||
/* Check the content of the archive for duplicates. Add the content
|
||||
of the files if necessary. Add all the names, possibly overwriting
|
||||
old files. */
|
||||
int
|
||||
add_locale_to_archive (ah, name, data, replace)
|
||||
struct locarhandle *ah;
|
||||
const char *name;
|
||||
locale_data_t data;
|
||||
bool replace;
|
||||
{
|
||||
/* First look for the name. If it already exists and we are not
|
||||
supposed to replace it don't do anything. If it does not exist
|
||||
we have to allocate a new locale record. */
|
||||
size_t name_len = strlen (name);
|
||||
uint32_t file_offsets[__LC_LAST];
|
||||
unsigned int num_new_offsets = 0;
|
||||
struct sumhashent *sumhashtab;
|
||||
uint32_t hval;
|
||||
unsigned int cnt;
|
||||
unsigned int idx;
|
||||
unsigned int insert_idx;
|
||||
struct locarhead *head;
|
||||
struct namehashent *namehashtab;
|
||||
struct namehashent *namehashent;
|
||||
unsigned int incr;
|
||||
struct locrecent *locrecent;
|
||||
|
||||
head = ah->addr;
|
||||
sumhashtab = (struct sumhashent *) ((char *) ah->addr
|
||||
+ head->sumhash_offset);
|
||||
namehashtab = (struct namehashent *) ((char *) ah->addr
|
||||
+ head->namehash_offset);
|
||||
|
||||
|
||||
/* For each locale category data set determine whether the same data
|
||||
is already somewhere in the archive. */
|
||||
for (cnt = 0; cnt < __LC_LAST; ++cnt)
|
||||
if (cnt != LC_ALL)
|
||||
{
|
||||
/* By default signal that we have no data. */
|
||||
file_offsets[cnt] = 0;
|
||||
++num_new_offsets;
|
||||
|
||||
/* Compute the hash value of the checksum to determine a
|
||||
starting point for the search in the MD5 hash value
|
||||
table. */
|
||||
hval = compute_hashval (data[cnt].sum, 16);
|
||||
|
||||
idx = hval % head->sumhash_size;
|
||||
incr = 1 + hval % (head->sumhash_size - 2);
|
||||
|
||||
while (sumhashtab[idx].file_offset != 0)
|
||||
{
|
||||
if (memcmp (data[cnt].sum, sumhashtab[idx].sum, 16) == 0)
|
||||
{
|
||||
/* Found it. */
|
||||
file_offsets[cnt] = sumhashtab[idx].file_offset;
|
||||
--num_new_offsets;
|
||||
break;
|
||||
}
|
||||
|
||||
idx += incr;
|
||||
if (idx >= head->sumhash_size)
|
||||
idx -= head->sumhash_size;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Hash value of the locale name. */
|
||||
hval = compute_hashval (name, name_len);
|
||||
|
||||
insert_idx = -1;
|
||||
idx = hval % head->namehash_size;
|
||||
incr = 1 + hval % (head->namehash_size - 2);
|
||||
|
||||
/* If the name_offset field is zero this means this is no
|
||||
deleted entry and therefore no entry can be found. */
|
||||
while (namehashtab[idx].name_offset != 0)
|
||||
{
|
||||
if (namehashtab[idx].hashval == hval
|
||||
&& strcmp (name,
|
||||
(char *) ah->addr + namehashtab[idx].name_offset) == 0)
|
||||
{
|
||||
/* Found the entry. */
|
||||
if (! replace)
|
||||
{
|
||||
if (! be_quiet)
|
||||
error (0, 0, _("locale '%s' already exists"), name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Remember the first place we can insert the new entry. */
|
||||
if (namehashtab[idx].locrec_offset == 0 && insert_idx == -1)
|
||||
insert_idx = idx;
|
||||
|
||||
idx += incr;
|
||||
if (idx >= head->namehash_size)
|
||||
idx -= head->namehash_size;
|
||||
}
|
||||
|
||||
/* Add as early as possible. */
|
||||
if (insert_idx != -1)
|
||||
idx = insert_idx;
|
||||
|
||||
namehashent = &namehashtab[idx];
|
||||
|
||||
/* Determine whether we have to resize the file. */
|
||||
if (100 * (head->sumhash_used + num_new_offsets) > 75 * head->sumhash_size
|
||||
|| (namehashent->locrec_offset == 0
|
||||
&& (head->locrectab_used == head->locrectab_size
|
||||
|| head->string_used + name_len + 1 > head->string_size
|
||||
|| 100 * head->namehash_used > 75 * head->namehash_size)))
|
||||
{
|
||||
/* The current archive is not large enough. */
|
||||
enlarge_archive (ah, head);
|
||||
return add_locale_to_archive (ah, name, data, replace);
|
||||
}
|
||||
|
||||
/* Add the locale data which is not yet in the archive. */
|
||||
for (cnt = 0; cnt < __LC_LAST; ++cnt)
|
||||
if (cnt != LC_ALL && file_offsets[cnt] == 0)
|
||||
{
|
||||
/* The data for this section is not yet available in the
|
||||
archive. Append it. */
|
||||
off64_t lastpos;
|
||||
uint32_t md5hval;
|
||||
|
||||
lastpos = lseek64 (ah->fd, 0, SEEK_END);
|
||||
if (lastpos == (off64_t) -1)
|
||||
error (EXIT_FAILURE, errno, _("cannot add to locale archive"));
|
||||
|
||||
/* Align all data to a 16 byte boundary. */
|
||||
if ((lastpos & 15) != 0)
|
||||
{
|
||||
static const char zeros[15] = { 0, };
|
||||
|
||||
if (TEMP_FAILURE_RETRY (write (ah->fd, zeros, 16 - (lastpos & 15)))
|
||||
!= 16 - (lastpos & 15))
|
||||
error (EXIT_FAILURE, errno, _("cannot add to locale archive"));
|
||||
|
||||
lastpos += 16 - (lastpos & 15);
|
||||
}
|
||||
|
||||
/* Remember the position. */
|
||||
file_offsets[cnt] = lastpos;
|
||||
|
||||
/* Write the data. */
|
||||
if (TEMP_FAILURE_RETRY (write (ah->fd, data[cnt].addr, data[cnt].size))
|
||||
!= data[cnt].size)
|
||||
error (EXIT_FAILURE, errno, _("cannot add to locale archive"));
|
||||
|
||||
/* Add the hash value to the hash table. */
|
||||
md5hval = compute_hashval (data[cnt].sum, 16);
|
||||
|
||||
idx = md5hval % head->sumhash_size;
|
||||
incr = 1 + md5hval % (head->sumhash_size - 2);
|
||||
|
||||
while (sumhashtab[idx].file_offset != 0)
|
||||
{
|
||||
idx += incr;
|
||||
if (idx >= head->sumhash_size)
|
||||
idx -= head->sumhash_size;
|
||||
}
|
||||
|
||||
memcpy (sumhashtab[idx].sum, data[cnt].sum, 16);
|
||||
sumhashtab[idx].file_offset = file_offsets[cnt];
|
||||
|
||||
++head->sumhash_used;
|
||||
}
|
||||
|
||||
|
||||
if (namehashent->locrec_offset == 0)
|
||||
{
|
||||
/* Add the name string. */
|
||||
memcpy ((char *) ah->addr + head->string_offset + head->string_used,
|
||||
name, name_len + 1);
|
||||
namehashent->name_offset = head->string_offset + head->string_used;
|
||||
head->string_used += name_len + 1;
|
||||
|
||||
/* Allocate a name location record. */
|
||||
namehashent->locrec_offset = (head->locrectab_offset
|
||||
+ (head->locrectab_used++
|
||||
* sizeof (struct locrecent)));
|
||||
|
||||
namehashent->hashval = hval;
|
||||
|
||||
++head->namehash_used;
|
||||
}
|
||||
|
||||
|
||||
/* Fill in the table with the locations of the locale data. */
|
||||
locrecent = (struct locrecent *) ((char *) ah->addr
|
||||
+ namehashent->locrec_offset);
|
||||
for (cnt = 0; cnt < __LC_LAST; ++cnt)
|
||||
if (cnt != LC_ALL)
|
||||
{
|
||||
locrecent->record[cnt].offset = file_offsets[cnt];
|
||||
locrecent->record[cnt].len = data[cnt].size;
|
||||
}
|
||||
|
||||
|
||||
/* Read the locale.alias file to see whether any matching record is
|
||||
found. If an entry is available check whether it is already in
|
||||
the archive. If this is the case check whether the new locale's
|
||||
name is more specific than the one currently referred to by the
|
||||
alias. */
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
add_locales_to_archive (nlist, list, replace)
|
||||
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. */
|
||||
open_archive (&ah);
|
||||
|
||||
while (nlist-- > 0)
|
||||
{
|
||||
const char *fname = *list++;
|
||||
size_t fnamelen = strlen (fname);
|
||||
struct stat64 st;
|
||||
DIR *dirp;
|
||||
struct dirent64 *d;
|
||||
int seen;
|
||||
locale_data_t data;
|
||||
int cnt;
|
||||
|
||||
if (! be_quiet)
|
||||
printf (_("Adding %s\n"), fname);
|
||||
|
||||
/* First see whether this really is a directory and whether it
|
||||
contains all the require locale category files. */
|
||||
if (stat64 (fname, &st) < 0)
|
||||
{
|
||||
error (0, 0, _("stat of \"%s\" failed: %s: ignored"), fname,
|
||||
strerror (errno));
|
||||
continue;
|
||||
}
|
||||
if (!S_ISDIR (st.st_mode))
|
||||
{
|
||||
error (0, 0, _("\"%s\" is no directory; ignored"), fname);
|
||||
continue;
|
||||
}
|
||||
|
||||
dirp = opendir (fname);
|
||||
if (dirp == NULL)
|
||||
{
|
||||
error (0, 0, _("cannot open directory \"%s\": %s: ignored"),
|
||||
fname, strerror (errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
seen = 0;
|
||||
while ((d = readdir64 (dirp)) != NULL)
|
||||
{
|
||||
for (cnt = 0; cnt < __LC_LAST; ++cnt)
|
||||
if (cnt != LC_ALL)
|
||||
if (strcmp (d->d_name, locnames[cnt]) == 0)
|
||||
{
|
||||
unsigned char d_type;
|
||||
|
||||
/* We have an object of the required name. If it's
|
||||
a directory we have to look at a file with the
|
||||
prefix "SYS_". Otherwise we have found what we
|
||||
are looking for. */
|
||||
#ifdef _DIRENT_HAVE_D_TYPE
|
||||
d_type = d->d_type;
|
||||
|
||||
if (d_type != DT_REG)
|
||||
#endif
|
||||
{
|
||||
char fullname[fnamelen + 2 * strlen (d->d_name) + 7];
|
||||
|
||||
#ifdef _DIRENT_HAVE_D_TYPE
|
||||
if (d_type == DT_UNKNOWN)
|
||||
#endif
|
||||
{
|
||||
strcpy (stpcpy (stpcpy (fullname, fname), "/"),
|
||||
d->d_name);
|
||||
|
||||
if (stat64 (fullname, &st) == -1)
|
||||
/* We cannot stat the file, ignore it. */
|
||||
break;
|
||||
|
||||
d_type = IFTODT (st.st_mode);
|
||||
}
|
||||
|
||||
if (d_type == DT_DIR)
|
||||
{
|
||||
/* We have to do more tests. The file is a
|
||||
directory and it therefore must contain a
|
||||
regular file with the same name except a
|
||||
"SYS_" prefix. */
|
||||
strcpy (stpcpy (stpcpy (stpcpy (stpcpy (fullname,
|
||||
fname),
|
||||
"/"),
|
||||
d->d_name),
|
||||
"/SYS_"),
|
||||
d->d_name);
|
||||
|
||||
if (stat64 (fullname, &st) == -1)
|
||||
/* There is no SYS_* file or we cannot
|
||||
access it. */
|
||||
break;
|
||||
|
||||
d_type = IFTODT (st.st_mode);
|
||||
}
|
||||
}
|
||||
|
||||
/* If we found a regular file (eventually after
|
||||
following a symlink) we are successful. */
|
||||
if (d_type == DT_REG)
|
||||
++seen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
closedir (dirp);
|
||||
|
||||
if (seen != __LC_LAST - 1)
|
||||
{
|
||||
/* We don't have all locale category files. Ignore the name. */
|
||||
error (0, 0, _("incomplete set of locale files in \"%s\""),
|
||||
fname);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Add the files to the archive. To do this we first compute
|
||||
sizes and the MD5 sums of all the files. */
|
||||
for (cnt = 0; cnt < __LC_LAST; ++cnt)
|
||||
if (cnt != LC_ALL)
|
||||
{
|
||||
char fullname[fnamelen + 2 * strlen (locnames[cnt]) + 7];
|
||||
int fd;
|
||||
|
||||
strcpy (stpcpy (stpcpy (fullname, fname), "/"), locnames[cnt]);
|
||||
fd = open64 (fullname, O_RDONLY);
|
||||
if (fd == -1 || fstat64 (fd, &st) == -1)
|
||||
{
|
||||
/* Cannot read the file. */
|
||||
if (fd != -1)
|
||||
close (fd);
|
||||
break;
|
||||
}
|
||||
|
||||
if (S_ISDIR (st.st_mode))
|
||||
{
|
||||
close (fd);
|
||||
strcpy (stpcpy (stpcpy (stpcpy (stpcpy (fullname, fname),
|
||||
"/"),
|
||||
locnames[cnt]),
|
||||
"/SYS_"),
|
||||
locnames[cnt]);
|
||||
|
||||
fd = open64 (fullname, O_RDONLY);
|
||||
if (fd == -1 || fstat64 (fd, &st) == -1
|
||||
|| !S_ISREG (st.st_mode))
|
||||
{
|
||||
if (fd != -1)
|
||||
close (fd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Map the file. */
|
||||
data[cnt].addr = mmap64 (NULL, st.st_size, PROT_READ, MAP_SHARED,
|
||||
fd, 0);
|
||||
if (data[cnt].addr == MAP_FAILED)
|
||||
{
|
||||
/* Cannot map it. */
|
||||
close (fd);
|
||||
break;
|
||||
}
|
||||
|
||||
data[cnt].size = st.st_size;
|
||||
__md5_buffer (data[cnt].addr, st.st_size, data[cnt].sum);
|
||||
|
||||
/* We don't need the file descriptor anymore. */
|
||||
close (fd);
|
||||
}
|
||||
|
||||
if (cnt != __LC_LAST)
|
||||
{
|
||||
while (cnt-- > 0)
|
||||
if (cnt != LC_ALL)
|
||||
munmap (data[cnt].addr, data[cnt].size);
|
||||
|
||||
error (0, 0, _("cannot read all files in \"%s\": ignored"), fname);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
result |= add_locale_to_archive (&ah, basename (fname), data, replace);
|
||||
|
||||
for (cnt = 0; cnt < __LC_LAST; ++cnt)
|
||||
if (cnt != LC_ALL)
|
||||
munmap (data[cnt].addr, data[cnt].size);
|
||||
}
|
||||
|
||||
/* We are done. */
|
||||
close_archive (&ah);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
delete_locales_from_archive (nlist, list)
|
||||
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. */
|
||||
open_archive (&ah);
|
||||
|
||||
head = ah.addr;
|
||||
namehashtab = (struct namehashent *) ((char *) ah.addr
|
||||
+ head->namehash_offset);
|
||||
|
||||
while (nlist-- > 0)
|
||||
{
|
||||
const char *locname = *list++;
|
||||
uint32_t hval;
|
||||
unsigned int idx;
|
||||
unsigned int incr;
|
||||
|
||||
/* Search for this locale in the archive. */
|
||||
hval = compute_hashval (locname, strlen (locname));
|
||||
|
||||
idx = hval % head->namehash_size;
|
||||
incr = 1 + hval % (head->namehash_size - 2);
|
||||
|
||||
/* If the name_offset field is zero this means this is no
|
||||
deleted entry and therefore no entry can be found. */
|
||||
while (namehashtab[idx].name_offset != 0)
|
||||
{
|
||||
if (namehashtab[idx].hashval == hval
|
||||
&& (strcmp (locname,
|
||||
(char *) ah.addr + namehashtab[idx].name_offset)
|
||||
== 0))
|
||||
{
|
||||
/* Found the entry. Now mark it as removed by zero-ing
|
||||
the reference to the locale record. */
|
||||
namehashtab[idx].locrec_offset = 0;
|
||||
--head->namehash_used;
|
||||
break;
|
||||
}
|
||||
|
||||
idx += incr;
|
||||
if (idx >= head->namehash_size)
|
||||
idx -= head->namehash_size;
|
||||
}
|
||||
|
||||
if (namehashtab[idx].name_offset == 0 && ! be_quiet)
|
||||
error (0, 0, _("locale \"%s\" not in archive"), locname);
|
||||
}
|
||||
|
||||
close_archive (&ah);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
xstrcmp (const void *a, const void *b)
|
||||
{
|
||||
return strcmp (*(const char **) a, *(const char **) b);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
show_archive_content (void)
|
||||
{
|
||||
struct locarhandle ah;
|
||||
struct locarhead *head;
|
||||
struct namehashent *namehashtab;
|
||||
int cnt;
|
||||
char **names;
|
||||
int used;
|
||||
|
||||
/* Open the archive. This call never returns if we cannot
|
||||
successfully open the archive. */
|
||||
open_archive (&ah);
|
||||
|
||||
head = ah.addr;
|
||||
|
||||
names = (char **) xmalloc (head->namehash_used * sizeof (char *));
|
||||
|
||||
namehashtab = (struct namehashent *) ((char *) ah.addr
|
||||
+ head->namehash_offset);
|
||||
for (cnt = used = 0; cnt < head->namehash_size; ++cnt)
|
||||
if (namehashtab[cnt].locrec_offset != 0)
|
||||
{
|
||||
assert (used < head->namehash_used);
|
||||
names[used++] = ah.addr + namehashtab[cnt].name_offset;
|
||||
}
|
||||
|
||||
/* Sort the names. */
|
||||
qsort (names, used, sizeof (char *), xstrcmp);
|
||||
|
||||
for (cnt = 0; cnt < used; ++cnt)
|
||||
puts (names[cnt]);
|
||||
|
||||
close_archive (&ah);
|
||||
|
||||
exit (EXIT_SUCCESS);
|
||||
}
|
@ -30,12 +30,18 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "../../crypt/md5.h"
|
||||
#include "localedef.h"
|
||||
#include "locfile.h"
|
||||
#include "simple-hash.h"
|
||||
|
||||
#include "locfile-kw.h"
|
||||
|
||||
|
||||
/* Temporary storage of the locale data before writing it to the archive. */
|
||||
static locale_data_t to_archive;
|
||||
|
||||
|
||||
int
|
||||
locfile_read (struct localedef_t *result, const struct charmap_t *charmap)
|
||||
{
|
||||
@ -312,9 +318,10 @@ static void (*const write_funcs[]) (struct localedef_t *,
|
||||
[LC_IDENTIFICATION] = identification_output
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
write_all_categories (struct localedef_t *definitions,
|
||||
const struct charmap_t *charmap,
|
||||
const struct charmap_t *charmap, const char *locname,
|
||||
const char *output_path)
|
||||
{
|
||||
int cnt;
|
||||
@ -322,8 +329,25 @@ write_all_categories (struct localedef_t *definitions,
|
||||
for (cnt = 0; cnt < sizeof (write_funcs) / sizeof (write_funcs[0]); ++cnt)
|
||||
if (write_funcs[cnt] != NULL)
|
||||
write_funcs[cnt] (definitions, charmap, output_path);
|
||||
|
||||
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. */
|
||||
open_archive (&ah);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Return a NULL terminated list of the directories next to output_path
|
||||
that have the same owner, group, permissions and device as output_path. */
|
||||
static const char **
|
||||
@ -408,6 +432,7 @@ siblings_uncached (const char *output_path)
|
||||
return elems;
|
||||
}
|
||||
|
||||
|
||||
/* Return a NULL terminated list of the directories next to output_path
|
||||
that have the same owner, group, permissions and device as output_path.
|
||||
Cache the result for future calls. */
|
||||
@ -434,6 +459,7 @@ siblings (const char *output_path)
|
||||
return last_result;
|
||||
}
|
||||
|
||||
|
||||
/* Read as many bytes from a file descriptor as possible. */
|
||||
static ssize_t
|
||||
full_read (int fd, void *bufarea, size_t nbyte)
|
||||
@ -457,6 +483,7 @@ full_read (int fd, void *bufarea, size_t nbyte)
|
||||
return buf - (char *) bufarea;
|
||||
}
|
||||
|
||||
|
||||
/* Compare the contents of two regular files of the same size. Return 0
|
||||
if they are equal, 1 if they are different, or -1 if an error occurs. */
|
||||
static int
|
||||
@ -506,9 +533,10 @@ compare_files (const char *filename1, const char *filename2, size_t size,
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Write a locale file, with contents given by N_ELEM and VEC. */
|
||||
void
|
||||
write_locale_data (const char *output_path, const char *category,
|
||||
write_locale_data (const char *output_path, int catidx, const char *category,
|
||||
size_t n_elem, struct iovec *vec)
|
||||
{
|
||||
size_t cnt, step, maxiov;
|
||||
@ -516,6 +544,32 @@ write_locale_data (const char *output_path, const char *category,
|
||||
char *fname;
|
||||
const char **other_paths;
|
||||
|
||||
if (! no_archive)
|
||||
{
|
||||
/* The data will be added to the archive. For now we simply
|
||||
generate the image which will be written. First determine
|
||||
the size. */
|
||||
int cnt;
|
||||
void *endp;
|
||||
|
||||
to_archive[catidx].size = 0;
|
||||
for (cnt = 0; cnt < n_elem; ++cnt)
|
||||
to_archive[catidx].size += vec[cnt].iov_len;
|
||||
|
||||
/* Allocate the memory for it. */
|
||||
to_archive[catidx].addr = xmalloc (to_archive[catidx].size);
|
||||
|
||||
/* Fill it in. */
|
||||
for (cnt = 0, endp = to_archive[catidx].addr; cnt < n_elem; ++cnt)
|
||||
endp = mempcpy (endp, vec[cnt].iov_base, vec[cnt].iov_len);
|
||||
|
||||
/* Compute the MD5 sum for the data. */
|
||||
__md5_buffer (to_archive[catidx].addr, to_archive[catidx].size,
|
||||
to_archive[catidx].sum);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
fname = xmalloc (strlen (output_path) + 2 * strlen (category) + 7);
|
||||
|
||||
/* Normally we write to the directory pointed to by the OUTPUT_PATH.
|
||||
@ -680,8 +734,7 @@ failure while writing data for category `%s'"), category));
|
||||
char * tmp_fname =
|
||||
(char *) xmalloc (strlen (fname) + 4 + 1);
|
||||
|
||||
strcpy (tmp_fname, fname);
|
||||
strcat (tmp_fname, ".tmp");
|
||||
strcpy (stpcpy (tmp_fname, fname), ".tmp");
|
||||
|
||||
if (link (other_fname, tmp_fname) >= 0)
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1996-2001, 2002 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@gnu.org>, 1996.
|
||||
|
||||
@ -115,11 +115,13 @@ extern void check_all_categories (struct localedef_t *definitions,
|
||||
/* Write out all locale categories. */
|
||||
extern void write_all_categories (struct localedef_t *definitions,
|
||||
const struct charmap_t *charmap,
|
||||
const char *locname,
|
||||
const char *output_path);
|
||||
|
||||
/* Write out the data. */
|
||||
extern void write_locale_data (const char *output_path, const char *category,
|
||||
size_t n_elem, struct iovec *vec);
|
||||
extern void write_locale_data (const char *output_path, int catidx,
|
||||
const char *category, size_t n_elem,
|
||||
struct iovec *vec);
|
||||
|
||||
|
||||
/* Entrypoints for the parsers of the individual categories. */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Implement simple hashing table with string based keys.
|
||||
Copyright (C) 1994-1997, 2000, 2001 Free Software Foundation, Inc.
|
||||
Copyright (C) 1994-1997, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, October 1994.
|
||||
|
||||
@ -54,6 +54,8 @@
|
||||
# define bcopy(s, d, n) memcpy ((d), (s), (n))
|
||||
#endif
|
||||
|
||||
#include "hashval.h"
|
||||
|
||||
extern void *xmalloc (size_t __n);
|
||||
extern void *xcalloc (size_t __n, size_t __m);
|
||||
|
||||
@ -72,7 +74,6 @@ static void insert_entry_2 (hash_table *htab, const void *key, size_t keylen,
|
||||
unsigned long hval, size_t idx, void *data);
|
||||
static size_t lookup (const hash_table *htab, const void *key, size_t keylen,
|
||||
unsigned long int hval);
|
||||
static unsigned long compute_hashval (const void *key, size_t keylen);
|
||||
static int is_prime (unsigned long int candidate);
|
||||
|
||||
|
||||
@ -297,30 +298,7 @@ lookup (htab, key, keylen, hval)
|
||||
}
|
||||
|
||||
|
||||
static unsigned long
|
||||
compute_hashval (key, keylen)
|
||||
const void *key;
|
||||
size_t keylen;
|
||||
{
|
||||
size_t cnt;
|
||||
unsigned long int hval;
|
||||
|
||||
/* Compute the hash value for the given string. The algorithm
|
||||
is taken from [Aho,Sethi,Ullman], modified to reduce the number of
|
||||
collisions for short strings with very varied bit patterns.
|
||||
See http://www.clisp.org/haible/hashfunc.html. */
|
||||
cnt = 0;
|
||||
hval = keylen;
|
||||
while (cnt < keylen)
|
||||
{
|
||||
hval = (hval << 9) | (hval >> (LONGBITS - 9));
|
||||
hval += (unsigned long int) *(((char *) key) + cnt++);
|
||||
}
|
||||
return hval != 0 ? hval : ~((unsigned long) 0);
|
||||
}
|
||||
|
||||
|
||||
unsigned long
|
||||
unsigned long int
|
||||
next_prime (seed)
|
||||
unsigned long int seed;
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1995, 1996, 1997, 1998, 1999, 2001 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1995-1999, 2001, 2002 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@gnu.org>, 1995.
|
||||
|
||||
@ -46,6 +46,8 @@ extern int iterate_table (const hash_table *htab, void **ptr,
|
||||
const void **key, size_t *keylen, void **data)
|
||||
__THROW;
|
||||
|
||||
extern unsigned long int compute_hashval (const void *key, size_t keylen)
|
||||
__THROW;
|
||||
extern unsigned long int next_prime (unsigned long int seed) __THROW;
|
||||
|
||||
#endif /* simple-hash.h */
|
||||
|
Loading…
Reference in New Issue
Block a user