int _IO_new_fclose (_IO_FILE *fp) { int status; CHECK_FILE(fp, EOF); #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1) /* We desperately try to help programs which are using streams in a strange way and mix old and new functions. Detect old streams here. */ if (_IO_vtable_offset (fp) != 0) return _IO_old_fclose (fp); #endif /* First unlink the stream. */ if (fp->_IO_file_flags & _IO_IS_FILEBUF) _IO_un_link ((struct _IO_FILE_plus *) fp); _IO_acquire_lock (fp); if (fp->_IO_file_flags & _IO_IS_FILEBUF) status = _IO_file_close_it (fp); else status = fp->_flags & _IO_ERR_SEEN ? -1 : 0; _IO_release_lock (fp); _IO_FINISH (fp); if (fp->_mode > 0) { #if _LIBC /* This stream has a wide orientation. This means we have to free the conversion functions. */ struct _IO_codecvt *cc = fp->_codecvt; __libc_lock_lock (__gconv_lock); __gconv_release_step (cc->__cd_in.__cd.__steps); __gconv_release_step (cc->__cd_out.__cd.__steps); __libc_lock_unlock (__gconv_lock); #endif } else { if (_IO_have_backup (fp)) _IO_free_backup_area (fp); } if (fp != _IO_stdin && fp != _IO_stdout && fp != _IO_stderr) { fp->_IO_file_flags = 0; free(fp); } return status; }
int internal_function __gconv_lookup_cache (const char *toset, const char *fromset, struct __gconv_step **handle, size_t *nsteps, int flags) { return __GCONV_NODB; #if 0 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; #endif }