コード例 #1
0
ファイル: wstrops.c プロジェクト: kraj/glibc
_IO_off64_t
_IO_wstr_seekoff (_IO_FILE *fp, _IO_off64_t offset, int dir, int mode)
{
  _IO_off64_t new_pos;

  if (mode == 0 && (fp->_flags & _IO_TIED_PUT_GET))
    mode = (fp->_flags & _IO_CURRENTLY_PUTTING ? _IOS_OUTPUT : _IOS_INPUT);

  bool was_writing = (fp->_wide_data->_IO_write_ptr >
			fp->_wide_data->_IO_write_base
		     || _IO_in_put_mode (fp));
  if (was_writing)
    _IO_wstr_switch_to_get_mode (fp);

  if (mode == 0)
    {
      new_pos = (fp->_wide_data->_IO_write_ptr
		 - fp->_wide_data->_IO_write_base);
    }
  else
    {
      _IO_ssize_t cur_size = _IO_wstr_count (fp);
      new_pos = EOF;

      /* Move the get pointer, if requested. */
      if (mode & _IOS_INPUT)
	{
	  _IO_ssize_t base;
	  switch (dir)
	    {
	    case _IO_seek_set:
	      base = 0;
	      break;
	    case _IO_seek_cur:
	      base = (fp->_wide_data->_IO_read_ptr
		     - fp->_wide_data->_IO_read_base);
	      break;
	    default: /* case _IO_seek_end: */
	      base = cur_size;
	      break;
	    }
	  _IO_ssize_t maxval = SSIZE_MAX/sizeof (wchar_t) - base;
	  if (offset < -base || offset > maxval)
	    {
	      __set_errno (EINVAL);
	      return EOF;
	    }
	  base += offset;
	  if (base > cur_size
	      && enlarge_userbuf (fp, base, 1) != 0)
	    return EOF;
	  fp->_wide_data->_IO_read_ptr = (fp->_wide_data->_IO_read_base
					  + base);
	  fp->_wide_data->_IO_read_end = (fp->_wide_data->_IO_read_base
					  + cur_size);
	  new_pos = offset;
	}

      /* Move the put pointer, if requested. */
      if (mode & _IOS_OUTPUT)
	{
	  _IO_ssize_t base;
	  switch (dir)
	    {
	    case _IO_seek_set:
	      base = 0;
	      break;
	    case _IO_seek_cur:
	      base = (fp->_wide_data->_IO_write_ptr
		     - fp->_wide_data->_IO_write_base);
	      break;
	    default: /* case _IO_seek_end: */
	      base = cur_size;
	      break;
	    }
	  _IO_ssize_t maxval = SSIZE_MAX/sizeof (wchar_t) - base;
	  if (offset < -base || offset > maxval)
	    {
	      __set_errno (EINVAL);
	      return EOF;
	    }
	  base += offset;
	  if (base > cur_size
	      && enlarge_userbuf (fp, base, 0) != 0)
	    return EOF;
	  fp->_wide_data->_IO_write_ptr = (fp->_wide_data->_IO_write_base
					   + base);
	  new_pos = base;
	}
    }
  return new_pos;
}
コード例 #2
0
ファイル: strops.c プロジェクト: RobbenBasten/glibc
_IO_off64_t
_IO_str_seekoff (_IO_FILE *fp, _IO_off64_t offset, int dir, int mode)
{
  _IO_off64_t new_pos;

  if (mode == 0 && (fp->_flags & _IO_TIED_PUT_GET))
    mode = (fp->_flags & _IO_CURRENTLY_PUTTING ? _IOS_OUTPUT : _IOS_INPUT);

  if (mode == 0)
    {
      /* Don't move any pointers. But there is no clear indication what
	 mode FP is in. Let's guess. */
      if (fp->_IO_file_flags & _IO_NO_WRITES)
        new_pos = fp->_IO_read_ptr - fp->_IO_read_base;
      else
        new_pos = fp->_IO_write_ptr - fp->_IO_write_base;
    }
  else
    {
      _IO_ssize_t cur_size = _IO_str_count(fp);
      new_pos = EOF;

      /* Move the get pointer, if requested. */
      if (mode & _IOS_INPUT)
	{
	  switch (dir)
	    {
	    case _IO_seek_end:
	      offset += cur_size;
	      break;
	    case _IO_seek_cur:
	      offset += fp->_IO_read_ptr - fp->_IO_read_base;
	      break;
	    default: /* case _IO_seek_set: */
	      break;
	    }
	  if (offset < 0)
	    return EOF;
	  if ((_IO_ssize_t) offset > cur_size
	      && enlarge_userbuf (fp, offset, 1) != 0)
	    return EOF;
	  fp->_IO_read_ptr = fp->_IO_read_base + offset;
	  fp->_IO_read_end = fp->_IO_read_base + cur_size;
	  new_pos = offset;
	}

      /* Move the put pointer, if requested. */
      if (mode & _IOS_OUTPUT)
	{
	  switch (dir)
	    {
	    case _IO_seek_end:
	      offset += cur_size;
	      break;
	    case _IO_seek_cur:
	      offset += fp->_IO_write_ptr - fp->_IO_write_base;
	      break;
	    default: /* case _IO_seek_set: */
	      break;
	    }
	  if (offset < 0)
	    return EOF;
	  if ((_IO_ssize_t) offset > cur_size
	      && enlarge_userbuf (fp, offset, 0) != 0)
	    return EOF;
	  fp->_IO_write_ptr = fp->_IO_write_base + offset;
	  new_pos = offset;
	}
    }
  return new_pos;
}