diff options
Diffstat (limited to 'newlib/libc/sys/linux/iconv/gconv_cache.c')
-rw-r--r-- | newlib/libc/sys/linux/iconv/gconv_cache.c | 459 |
1 files changed, 0 insertions, 459 deletions
diff --git a/newlib/libc/sys/linux/iconv/gconv_cache.c b/newlib/libc/sys/linux/iconv/gconv_cache.c deleted file mode 100644 index c887be970..000000000 --- a/newlib/libc/sys/linux/iconv/gconv_cache.c +++ /dev/null @@ -1,459 +0,0 @@ -/* Cache handling for iconv modules. - Copyright (C) 2001 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper <drepper@cygnus.com>, 2001. - - 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. */ - -#include <dlfcn.h> -#include <fcntl.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <sys/mman.h> -#include <sys/stat.h> - -#include <gconv_int.h> -#include <iconvconfig.h> - -#include "hash-string.h" - -void *__gconv_cache; -static size_t cache_size; -static int cache_malloced; - - -int -internal_function -__gconv_load_cache (void) -{ - int fd; - struct stat64 st; - struct gconvcache_header *header; - - /* We cannot use the cache if the GCONV_PATH environment variable is - set. */ - __gconv_path_envvar = getenv ("GCONV_PATH"); - if (__gconv_path_envvar != NULL) - return -1; - - /* See whether the cache file exists. */ - fd = open (GCONV_MODULES_CACHE, O_RDONLY); - if (__builtin_expect (fd, 0) == -1) - /* Not available. */ - return -1; - -#ifdef _POSIX_ASYNC_IO - /* Get information about the file. */ - if (__builtin_expect (fstat64 (fd, &st), 0) < 0 - /* We do not have to start looking at the file if it cannot contain - at least the cache header. */ - || st.st_size < sizeof (struct gconvcache_header)) - { -#endif - close_and_exit: - close (fd); - return -1; -#ifdef _POSIX_ASYNC_IO - } -#endif - - /* Make the file content available. */ - cache_size = st.st_size; -#ifdef _POSIX_MAPPED_FILES - __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; - - __gconv_cache = malloc (cache_size); - if (__gconv_cache == NULL) - goto close_and_exit; - - already_read = 0; - do - { - ssize_t n = read (fd, (char *) __gconv_cache + already_read, - cache_size - already_read); - if (__builtin_expect (n, 0) == -1) - { - free (__gconv_cache); - __gconv_cache = NULL; - goto close_and_exit; - } - - already_read += n; - } - while (already_read < cache_size); - - cache_malloced = 1; - } - - /* We don't need the file descriptor anymore. */ - close (fd); - - /* Check the consistency. */ - 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) - || __builtin_expect (header->hash_size == 0, 0) - || __builtin_expect ((header->hash_offset - + header->hash_size * sizeof (struct hash_entry)) - > cache_size, 0) - || __builtin_expect (header->module_offset >= cache_size, 0) - || __builtin_expect (header->otherconv_offset > cache_size, 0)) - { - if (cache_malloced) - { - free (__gconv_cache); - cache_malloced = 0; - } -#ifdef _POSIX_MAPPED_FILES - else - __munmap (__gconv_cache, cache_size); -#endif - __gconv_cache = NULL; - - return -1; - } - - /* That worked. */ - return 0; -} - - -static int -internal_function -find_module_idx (const char *str, size_t *idxp) -{ - unsigned int idx; - unsigned int hval; - unsigned int hval2; - const struct gconvcache_header *header; - const char *strtab; - const struct hash_entry *hashtab; - unsigned int limit; - - 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; - hval2 = 1 + hval % (header->hash_size - 2); - - limit = cache_size - header->string_offset; - while (hashtab[idx].string_offset != 0) - if (hashtab[idx].string_offset < limit - && strcmp (str, strtab + hashtab[idx].string_offset) == 0) - { - *idxp = hashtab[idx].module_idx; - return 0; - } - else - if ((idx += hval2) >= header->hash_size) - idx -= header->hash_size; - - /* Nothing found. */ - return -1; -} - - -#ifndef STATIC_GCONV -static int -internal_function -find_module (const char *directory, const char *filename, - struct __gconv_step *result) -{ - size_t dirlen = strlen (directory); - size_t fnamelen = strlen (filename) + 1; - char fullname[dirlen + fnamelen]; - int status = __GCONV_NOCONV; - char *tmp; - - tmp = mempcpy (fullname, directory, dirlen); - tmp += dirlen; - memcpy (tmp, filename, fnamelen); - - result->__shlib_handle = __gconv_find_shlib (fullname); - if (result->__shlib_handle != NULL) - { - status = __GCONV_OK; - - result->__modname = NULL; - result->__fct = result->__shlib_handle->fct; - result->__init_fct = result->__shlib_handle->init_fct; - result->__end_fct = result->__shlib_handle->end_fct; - - result->__data = NULL; - if (result->__init_fct != NULL) - status = result->__init_fct (result); - } - - return status; -} -#endif - - -int -internal_function -__gconv_compare_alias_cache (const char *name1, const char *name2, int *result) -{ - size_t name1_idx; - size_t name2_idx; - - if (__gconv_cache == NULL) - return -1; - - if (find_module_idx (name1, &name1_idx) != 0 - || find_module_idx (name2, &name2_idx) != 0) - *result = strcmp (name1, name2); - else - *result = (int) (name1_idx - name2_idx); - - return 0; -} - - -int -internal_function -__gconv_lookup_cache (const char *toset, const char *fromset, - struct __gconv_step **handle, size_t *nsteps, int flags) -{ - const struct gconvcache_header *header; - const char *strtab; - size_t fromidx; - size_t toidx; - const struct module_entry *modtab; - const struct module_entry *from_module; - const struct module_entry *to_module; - struct __gconv_step *result; - - if (__gconv_cache == NULL) - /* We have no cache available. */ - return __GCONV_NODB; - - 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 - || (header->module_offset + (fromidx + 1) * sizeof (struct module_entry) - > cache_size)) - return __GCONV_NOCONV; - from_module = &modtab[fromidx]; - - if (find_module_idx (toset, &toidx) != 0 - || (header->module_offset + (toidx + 1) * sizeof (struct module_entry) - > cache_size)) - return __GCONV_NOCONV; - to_module = &modtab[toidx]; - - /* Avoid copy-only transformations if the user requests. */ - if (__builtin_expect (flags & GCONV_AVOID_NOCONV, 0) && fromidx == toidx) - return __GCONV_NOCONV; - - /* If there are special conversions available examine them first. */ - if (fromidx != 0 && toidx != 0 - && __builtin_expect (from_module->extra_offset, 0) != 0) - { - /* Search through the list to see whether there is a module - matching the destination character set. */ - const struct extra_entry *extra; - - /* Note the -1. This is due to the offset added in iconvconfig. - See there for more explanations. */ - extra = (const struct extra_entry *) ((char *) __gconv_cache - + header->otherconv_offset - + from_module->extra_offset - 1); - while (extra->module_cnt != 0 - && extra->module[extra->module_cnt - 1].outname_offset != toidx) - extra = (const struct extra_entry *) ((char *) extra - + sizeof (struct extra_entry) - + (extra->module_cnt - * sizeof (struct extra_entry_module))); - - if (extra->module_cnt != 0) - { - /* Use the extra module. First determine how many steps. */ - char *fromname; - int idx; - - *nsteps = extra->module_cnt; - *handle = result = - (struct __gconv_step *) malloc (extra->module_cnt - * sizeof (struct __gconv_step)); - if (result == NULL) - return __GCONV_NOMEM; - - fromname = (char *) strtab + from_module->canonname_offset; - idx = 0; - do - { - result[idx].__from_name = fromname; - fromname = result[idx].__to_name = - (char *) strtab + modtab[extra->module[idx].outname_offset].canonname_offset; - - result[idx].__counter = 1; - result[idx].__data = NULL; - -#ifndef STATIC_GCONV - if (strtab[extra->module[idx].dir_offset] != '\0') - { - /* Load the module, return handle for it. */ - int res; - - res = find_module (strtab + extra->module[idx].dir_offset, - strtab + extra->module[idx].name_offset, - &result[idx]); - if (__builtin_expect (res, __GCONV_OK) != __GCONV_OK) - { - /* Something went wrong. */ - free (result); - goto try_internal; - } - } - else -#endif - /* It's a builtin transformation. */ - __gconv_get_builtin_trans (strtab - + extra->module[idx].name_offset, - &result[idx]); - - } - while (++idx < extra->module_cnt); - - return __GCONV_OK; - } - } - - try_internal: - /* See whether we can convert via the INTERNAL charset. */ - if ((fromidx != 0 && __builtin_expect (from_module->fromname_offset, 1) == 0) - || (toidx != 0 && __builtin_expect (to_module->toname_offset, 1) == 0) - || (fromidx == 0 && toidx == 0)) - /* Not possible. Nothing we can do. */ - return __GCONV_NOCONV; - - /* We will use up to two modules. Always allocate room for two. */ - result = (struct __gconv_step *) malloc (2 * sizeof (struct __gconv_step)); - if (result == NULL) - return __GCONV_NOMEM; - - *handle = result; - *nsteps = 0; - - /* Generate data structure for conversion to INTERNAL. */ - if (fromidx != 0) - { - result[0].__from_name = (char *) strtab + from_module->canonname_offset; - result[0].__to_name = (char *) "INTERNAL"; - - result[0].__counter = 1; - result[0].__data = NULL; - -#ifndef STATIC_GCONV - if (strtab[from_module->todir_offset] != '\0') - { - /* Load the module, return handle for it. */ - int res = find_module (strtab + from_module->todir_offset, - strtab + from_module->toname_offset, - &result[0]); - if (__builtin_expect (res, __GCONV_OK) != __GCONV_OK) - { - /* Something went wrong. */ - free (result); - return res; - } - } - else -#endif - /* It's a builtin transformation. */ - __gconv_get_builtin_trans (strtab + from_module->toname_offset, - &result[0]); - - ++*nsteps; - } - - /* Generate data structure for conversion from INTERNAL. */ - if (toidx != 0) - { - int idx = *nsteps; - - result[idx].__from_name = (char *) "INTERNAL"; - result[idx].__to_name = (char *) strtab + to_module->canonname_offset; - - result[idx].__counter = 1; - result[idx].__data = NULL; - -#ifndef STATIC_GCONV - if (strtab[to_module->fromdir_offset] != '\0') - { - /* Load the module, return handle for it. */ - int res = find_module (strtab + to_module->fromdir_offset, - strtab + to_module->fromname_offset, - &result[idx]); - if (__builtin_expect (res, __GCONV_OK) != __GCONV_OK) - { - /* Something went wrong. */ - if (idx != 0) - __gconv_release_step (&result[0]); - free (result); - return res; - } - } - else -#endif - /* It's a builtin transformation. */ - __gconv_get_builtin_trans (strtab + to_module->fromname_offset, - &result[idx]); - - ++*nsteps; - } - - return __GCONV_OK; -} - - -/* Free memory allocated for the transformation record. */ -void -internal_function -__gconv_release_cache (struct __gconv_step *steps, size_t nsteps) -{ - if (__gconv_cache != NULL) - /* The only thing we have to deallocate is the record with the - steps. */ - free (steps); -} - - -/* Free all resources if necessary. */ -static void __attribute__ ((unused)) -free_mem (void) -{ - if (cache_malloced) - free (__gconv_cache); -#ifdef _POSIX_MAPPED_FILES - else - __munmap (__gconv_cache, cache_size); -#endif -} - -text_set_element (__libc_subfreeres, free_mem); |