static inline int find_object (struct ftw_data *data, struct STAT *st) { struct known_object obj; obj.dev = st->st_dev; obj.ino = st->st_ino; return __tfind (&obj, &data->known_objects, object_compare) != NULL; }
/* Open the gconv database if necessary. A non-negative return value means success. */ struct __gconv_loaded_object * __gconv_find_shlib (const char *name) { struct __gconv_loaded_object *found; void *keyp; /* Search the tree of shared objects previously requested. Data in the tree are `loaded_object' structures, whose first member is a `const char *', the lookup key. The search returns a pointer to the tree node structure; the first member of the is a pointer to our structure (i.e. what will be a `loaded_object'); since the first member of that is the lookup key string, &FCT_NAME is close enough to a pointer to our structure to use as a lookup key that will be passed to `known_compare' (above). */ keyp = __tfind (&name, &loaded, known_compare); if (keyp == NULL) { /* This name was not known before. */ size_t namelen = strlen (name) + 1; found = malloc (sizeof (struct __gconv_loaded_object) + namelen); if (found != NULL) { /* Point the tree node at this new structure. */ found->name = (char *) memcpy (found + 1, name, namelen); found->counter = -TRIES_BEFORE_UNLOAD - 1; found->handle = NULL; if (__builtin_expect (__tsearch (found, &loaded, known_compare) == NULL, 0)) { /* Something went wrong while inserting the entry. */ free (found); found = NULL; } } } else found = *(struct __gconv_loaded_object **) keyp; /* Try to load the shared object if the usage count is 0. This implies that if the shared object is not loadable, the handle is NULL and the usage count > 0. */ if (found != NULL) { if (found->counter < -TRIES_BEFORE_UNLOAD) { assert (found->handle == NULL); found->handle = __libc_dlopen (found->name); if (found->handle != NULL) { found->fct = __libc_dlsym (found->handle, "gconv"); if (found->fct == NULL) { /* Argh, no conversion function. There is something wrong here. */ __gconv_release_shlib (found); found = NULL; } else { found->init_fct = __libc_dlsym (found->handle, "gconv_init"); found->end_fct = __libc_dlsym (found->handle, "gconv_end"); #ifdef PTR_MANGLE PTR_MANGLE (found->fct); PTR_MANGLE (found->init_fct); PTR_MANGLE (found->end_fct); #endif /* We have succeeded in loading the shared object. */ found->counter = 1; } } else /* Error while loading the shared object. */ found = NULL; } else if (found->handle != NULL) found->counter = MAX (found->counter + 1, 1); } return found; }
/* Add new module. */ static void internal_function add_module (char *rp, const char *directory, size_t dir_len, void **modules, size_t *nmodules, int modcounter) { /* We expect now 1. `from' name 2. `to' name 3. filename of the module 4. an optional cost value */ struct gconv_alias fake_alias; struct gconv_module *new_module; char *from, *to, *module, *wp; int need_ext; int cost_hi; while (__isspace_l (*rp, &_nl_C_locobj)) ++rp; from = rp; while (*rp != '\0' && !__isspace_l (*rp, &_nl_C_locobj)) { *rp = __toupper_l (*rp, &_nl_C_locobj); ++rp; } if (*rp == '\0') return; *rp++ = '\0'; to = wp = rp; while (__isspace_l (*rp, &_nl_C_locobj)) ++rp; while (*rp != '\0' && !__isspace_l (*rp, &_nl_C_locobj)) *wp++ = __toupper_l (*rp++, &_nl_C_locobj); if (*rp == '\0') return; *wp++ = '\0'; do ++rp; while (__isspace_l (*rp, &_nl_C_locobj)); module = wp; while (*rp != '\0' && !__isspace_l (*rp, &_nl_C_locobj)) *wp++ = *rp++; if (*rp == '\0') { /* There is no cost, use one by default. */ *wp++ = '\0'; cost_hi = 1; } else { /* There might be a cost value. */ char *endp; *wp++ = '\0'; cost_hi = strtol (rp, &endp, 10); if (rp == endp || cost_hi < 1) /* No useful information. */ cost_hi = 1; } if (module[0] == '\0') /* No module name given. */ return; if (module[0] == '/') dir_len = 0; /* See whether we must add the ending. */ need_ext = 0; if (wp - module < (ptrdiff_t) sizeof (gconv_module_ext) || memcmp (wp - sizeof (gconv_module_ext), gconv_module_ext, sizeof (gconv_module_ext)) != 0) /* We must add the module extension. */ need_ext = sizeof (gconv_module_ext) - 1; /* See whether we have already an alias with this name defined. */ fake_alias.fromname = strndupa (from, to - from); if (__tfind (&fake_alias, &__gconv_alias_db, __gconv_alias_compare) != NULL) /* This module duplicates an alias. */ return; new_module = (struct gconv_module *) calloc (1, sizeof (struct gconv_module) + (wp - from) + dir_len + need_ext); if (new_module != NULL) { char *tmp; new_module->from_string = tmp = (char *) (new_module + 1); tmp = __mempcpy (tmp, from, to - from); new_module->to_string = tmp; tmp = __mempcpy (tmp, to, module - to); new_module->cost_hi = cost_hi; new_module->cost_lo = modcounter; new_module->module_name = tmp; if (dir_len != 0) tmp = __mempcpy (tmp, directory, dir_len); tmp = __mempcpy (tmp, module, wp - module); if (need_ext) memcpy (tmp - 1, gconv_module_ext, sizeof (gconv_module_ext)); /* Now insert the new module data structure in our search tree. */ insert_module (new_module, 1); } }