diff options
Diffstat (limited to 'iconv')
-rw-r--r-- | iconv/Versions | 4 | ||||
-rw-r--r-- | iconv/gconv_cache.c | 49 | ||||
-rw-r--r-- | iconv/iconv_prog.c | 48 |
3 files changed, 72 insertions, 29 deletions
diff --git a/iconv/Versions b/iconv/Versions index 577a54867d..8d6b70c53e 100644 --- a/iconv/Versions +++ b/iconv/Versions @@ -6,4 +6,8 @@ libc { # i* iconv_open; iconv; iconv_close; } + GLIBC_2.2.5 { + # variable shared with iconv program + __gconv_cache; + } } diff --git a/iconv/gconv_cache.c b/iconv/gconv_cache.c index b4fd8d9836..a2beee06fa 100644 --- a/iconv/gconv_cache.c +++ b/iconv/gconv_cache.c @@ -31,7 +31,7 @@ #include "../intl/hash-string.h" -static void *cache; +void *__gconv_cache; static size_t cache_size; static int cache_malloced; @@ -70,25 +70,25 @@ __gconv_load_cache (void) /* Make the file content available. */ cache_size = st.st_size; #ifdef _POSIX_MAPPED_FILES - cache = __mmap (NULL, cache_size, PROT_READ, MAP_SHARED, fd, 0); - if (__builtin_expect (cache == MAP_FAILED, 0)) + __gconv_cache = __mmap (NULL, cache_size, PROT_READ, MAP_SHARED, fd, 0); + if (__builtin_expect (__gconv_cache == MAP_FAILED, 0)) #endif { size_t already_read; - cache = malloc (cache_size); - if (cache == NULL) + __gconv_cache = malloc (cache_size); + if (__gconv_cache == NULL) goto close_and_exit; already_read = 0; do { - ssize_t n = __read (fd, (char *) cache + already_read, + ssize_t n = __read (fd, (char *) __gconv_cache + already_read, cache_size - already_read); if (__builtin_expect (n, 0) == -1) { - free (cache); - cache = NULL; + free (__gconv_cache); + __gconv_cache = NULL; goto close_and_exit; } @@ -103,7 +103,7 @@ __gconv_load_cache (void) __close (fd); /* Check the consistency. */ - header = (struct gconvcache_header *) cache; + header = (struct gconvcache_header *) __gconv_cache; if (__builtin_expect (header->magic, GCONVCACHE_MAGIC) != GCONVCACHE_MAGIC || __builtin_expect (header->string_offset >= cache_size, 0) || __builtin_expect (header->hash_offset >= cache_size, 0) @@ -116,14 +116,14 @@ __gconv_load_cache (void) { if (cache_malloced) { - free (cache); + free (__gconv_cache); cache_malloced = 0; } #ifdef _POSIX_MAPPED_FILES else - __munmap (cache, cache_size); + __munmap (__gconv_cache, cache_size); #endif - cache = NULL; + __gconv_cache = NULL; return -1; } @@ -145,9 +145,10 @@ find_module_idx (const char *str, size_t *idxp) const struct hash_entry *hashtab; unsigned int limit; - header = (const struct gconvcache_header *) cache; - strtab = (char *) cache + header->string_offset; - hashtab = (struct hash_entry *) ((char *) cache + header->hash_offset); + header = (const struct gconvcache_header *) __gconv_cache; + strtab = (char *) __gconv_cache + header->string_offset; + hashtab = (struct hash_entry *) ((char *) __gconv_cache + + header->hash_offset); hval = hash_string (str); idx = hval % header->hash_size; @@ -210,7 +211,7 @@ __gconv_compare_alias_cache (const char *name1, const char *name2, int *result) size_t name1_idx; size_t name2_idx; - if (cache == NULL) + if (__gconv_cache == NULL) return -1; if (find_module_idx (name1, &name1_idx) != 0 @@ -237,13 +238,13 @@ __gconv_lookup_cache (const char *toset, const char *fromset, const struct module_entry *to_module; struct __gconv_step *result; - if (cache == NULL) + if (__gconv_cache == NULL) /* We have no cache available. */ return __GCONV_NODB; - header = (const struct gconvcache_header *) cache; - strtab = (char *) cache + header->string_offset; - modtab = (const struct module_entry *) ((char *) cache + header = (const struct gconvcache_header *) __gconv_cache; + strtab = (char *) __gconv_cache + header->string_offset; + modtab = (const struct module_entry *) ((char *) __gconv_cache + header->module_offset); if (find_module_idx (fromset, &fromidx) != 0 @@ -272,7 +273,7 @@ __gconv_lookup_cache (const char *toset, const char *fromset, /* Note the -1. This is due to the offset added in iconvconfig. See there for more explanations. */ - extra = (const struct extra_entry *) ((char *) cache + extra = (const struct extra_entry *) ((char *) __gconv_cache + header->otherconv_offset + from_module->extra_offset - 1); while (extra->module_cnt != 0 @@ -429,7 +430,7 @@ void internal_function __gconv_release_cache (struct __gconv_step *steps, size_t nsteps) { - if (cache != NULL) + if (__gconv_cache != NULL) /* The only thing we have to deallocate is the record with the steps. */ free (steps); @@ -441,10 +442,10 @@ static void __attribute__ ((unused)) free_mem (void) { if (cache_malloced) - free (cache); + free (__gconv_cache); #ifdef _POSIX_MAPPED_FILES else - __munmap (cache, cache_size); + __munmap (__gconv_cache, cache_size); #endif } diff --git a/iconv/iconv_prog.c b/iconv/iconv_prog.c index 00b4b95672..e71f8d7369 100644 --- a/iconv/iconv_prog.c +++ b/iconv/iconv_prog.c @@ -39,6 +39,7 @@ #include <charmap.h> #include <gconv_int.h> #include "iconv_prog.h" +#include "iconvconfig.h" /* Get libc version number. */ #include "../version.h" @@ -46,6 +47,9 @@ #define PACKAGE _libc_intl_domainname +/* Defined in gconv_cache.c. */ +extern void *__gconv_cache; + /* 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; @@ -653,7 +657,7 @@ add_known_names (struct gconv_module *node) if (strcmp (node->from_string, "INTERNAL")) tsearch (node->from_string, &printlist, (__compar_fn_t) strverscmp); - if (strcmp (node->to_string, "INTERNAL")) + if (strcmp (node->to_string, "INTERNAL") != 0) tsearch (node->to_string, &printlist, (__compar_fn_t) strverscmp); node = node->same; @@ -661,6 +665,31 @@ add_known_names (struct gconv_module *node) while (node != NULL); } + +static void +insert_cache (void) +{ + const struct gconvcache_header *header; + const char *strtab; + const struct hash_entry *hashtab; + size_t cnt; + + header = (const struct gconvcache_header *) __gconv_cache; + strtab = (char *) __gconv_cache + header->string_offset; + hashtab = (struct hash_entry *) ((char *) __gconv_cache + + header->hash_offset); + + for (cnt = 0; cnt < header->hash_size; ++cnt) + if (hashtab[cnt].string_offset != 0) + { + const char *str = strtab + hashtab[cnt].string_offset; + + if (strcmp (str, "INTERNAL") != 0) + tsearch (str, &printlist, (__compar_fn_t) strverscmp); + } +} + + static void internal_function print_known_names (void) @@ -671,11 +700,20 @@ print_known_names (void) h = iconv_open ("L1", "L1"); iconv_close (h); - /* First add the aliases. */ - twalk (__gconv_alias_db, insert_print_list); + /* See whether we have a cache. */ + if (__gconv_cache != NULL) + /* Yep, use only this information. */ + insert_cache (); + else + { + /* No, then use the information read from the gconv-modules file. + First add the aliases. */ + twalk (__gconv_alias_db, insert_print_list); - /* Add the from- and to-names from the known modules. */ - add_known_names (__gconv_modules_db); + /* Add the from- and to-names from the known modules. */ + if (__gconv_modules_db != NULL) + add_known_names (__gconv_modules_db); + } fputs (_("\ The following list contain all the coded character sets known. This does\n\ |