Example #1
0
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;
}
Example #2
0
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
}