Back to index

glibc  2.9
strops.c
Go to the documentation of this file.
00001 /* Copyright (C) 1993, 1997-2003, 2004, 2006 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003 
00004    The GNU C Library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Lesser General Public
00006    License as published by the Free Software Foundation; either
00007    version 2.1 of the License, or (at your option) any later version.
00008 
00009    The GNU C Library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Lesser General Public License for more details.
00013 
00014    You should have received a copy of the GNU Lesser General Public
00015    License along with the GNU C Library; if not, write to the Free
00016    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00017    02111-1307 USA.
00018 
00019    As a special exception, if you link the code in this file with
00020    files compiled with a GNU compiler to produce an executable,
00021    that does not cause the resulting executable to be covered by
00022    the GNU Lesser General Public License.  This exception does not
00023    however invalidate any other reasons why the executable file
00024    might be covered by the GNU Lesser General Public License.
00025    This exception applies to code released by its copyright holders
00026    in files containing the exception.  */
00027 
00028 #include <assert.h>
00029 #include "strfile.h"
00030 #include "libioP.h"
00031 #include <string.h>
00032 #include <stdio_ext.h>
00033 
00034 void
00035 _IO_str_init_static_internal (sf, ptr, size, pstart)
00036      _IO_strfile *sf;
00037      char *ptr;
00038      _IO_size_t size;
00039      char *pstart;
00040 {
00041   _IO_FILE *fp = &sf->_sbf._f;
00042   char *end;
00043 
00044   if (size == 0)
00045     end = __rawmemchr (ptr, '\0');
00046   else if ((_IO_size_t) ptr + size > (_IO_size_t) ptr)
00047     end = ptr + size;
00048   else
00049     end = (char *) -1;
00050   INTUSE(_IO_setb) (fp, ptr, end, 0);
00051 
00052   fp->_IO_write_base = ptr;
00053   fp->_IO_read_base = ptr;
00054   fp->_IO_read_ptr = ptr;
00055   if (pstart)
00056     {
00057       fp->_IO_write_ptr = pstart;
00058       fp->_IO_write_end = end;
00059       fp->_IO_read_end = pstart;
00060     }
00061   else
00062     {
00063       fp->_IO_write_ptr = ptr;
00064       fp->_IO_write_end = ptr;
00065       fp->_IO_read_end = end;
00066     }
00067   /* A null _allocate_buffer function flags the strfile as being static. */
00068   sf->_s._allocate_buffer = (_IO_alloc_type) 0;
00069 }
00070 
00071 void
00072 _IO_str_init_static (sf, ptr, size, pstart)
00073      _IO_strfile *sf;
00074      char *ptr;
00075      int size;
00076      char *pstart;
00077 {
00078   return _IO_str_init_static_internal (sf, ptr, size < 0 ? -1 : size, pstart);
00079 }
00080 
00081 void
00082 _IO_str_init_readonly (sf, ptr, size)
00083      _IO_strfile *sf;
00084      const char *ptr;
00085      int size;
00086 {
00087   _IO_str_init_static_internal (sf, (char *) ptr, size < 0 ? -1 : size, NULL);
00088   sf->_sbf._f._IO_file_flags |= _IO_NO_WRITES;
00089 }
00090 
00091 int
00092 _IO_str_overflow (fp, c)
00093      _IO_FILE *fp;
00094      int c;
00095 {
00096   int flush_only = c == EOF;
00097   _IO_size_t pos;
00098   if (fp->_flags & _IO_NO_WRITES)
00099       return flush_only ? 0 : EOF;
00100   if ((fp->_flags & _IO_TIED_PUT_GET) && !(fp->_flags & _IO_CURRENTLY_PUTTING))
00101     {
00102       fp->_flags |= _IO_CURRENTLY_PUTTING;
00103       fp->_IO_write_ptr = fp->_IO_read_ptr;
00104       fp->_IO_read_ptr = fp->_IO_read_end;
00105     }
00106   pos = fp->_IO_write_ptr - fp->_IO_write_base;
00107   if (pos >= (_IO_size_t) (_IO_blen (fp) + flush_only))
00108     {
00109       if (fp->_flags & _IO_USER_BUF) /* not allowed to enlarge */
00110        return EOF;
00111       else
00112        {
00113          char *new_buf;
00114          char *old_buf = fp->_IO_buf_base;
00115          size_t old_blen = _IO_blen (fp);
00116          _IO_size_t new_size = 2 * old_blen + 100;
00117          if (new_size < old_blen)
00118            return EOF;
00119          new_buf
00120            = (char *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size);
00121          if (new_buf == NULL)
00122            {
00123              /*        __ferror(fp) = 1; */
00124              return EOF;
00125            }
00126          if (old_buf)
00127            {
00128              memcpy (new_buf, old_buf, old_blen);
00129              (*((_IO_strfile *) fp)->_s._free_buffer) (old_buf);
00130              /* Make sure _IO_setb won't try to delete _IO_buf_base. */
00131              fp->_IO_buf_base = NULL;
00132            }
00133          memset (new_buf + old_blen, '\0', new_size - old_blen);
00134 
00135          INTUSE(_IO_setb) (fp, new_buf, new_buf + new_size, 1);
00136          fp->_IO_read_base = new_buf + (fp->_IO_read_base - old_buf);
00137          fp->_IO_read_ptr = new_buf + (fp->_IO_read_ptr - old_buf);
00138          fp->_IO_read_end = new_buf + (fp->_IO_read_end - old_buf);
00139          fp->_IO_write_ptr = new_buf + (fp->_IO_write_ptr - old_buf);
00140 
00141          fp->_IO_write_base = new_buf;
00142          fp->_IO_write_end = fp->_IO_buf_end;
00143        }
00144     }
00145 
00146   if (!flush_only)
00147     *fp->_IO_write_ptr++ = (unsigned char) c;
00148   if (fp->_IO_write_ptr > fp->_IO_read_end)
00149     fp->_IO_read_end = fp->_IO_write_ptr;
00150   return c;
00151 }
00152 INTDEF(_IO_str_overflow)
00153 
00154 int
00155 _IO_str_underflow (fp)
00156      _IO_FILE *fp;
00157 {
00158   if (fp->_IO_write_ptr > fp->_IO_read_end)
00159     fp->_IO_read_end = fp->_IO_write_ptr;
00160   if ((fp->_flags & _IO_TIED_PUT_GET) && (fp->_flags & _IO_CURRENTLY_PUTTING))
00161     {
00162       fp->_flags &= ~_IO_CURRENTLY_PUTTING;
00163       fp->_IO_read_ptr = fp->_IO_write_ptr;
00164       fp->_IO_write_ptr = fp->_IO_write_end;
00165     }
00166   if (fp->_IO_read_ptr < fp->_IO_read_end)
00167     return *((unsigned char *) fp->_IO_read_ptr);
00168   else
00169     return EOF;
00170 }
00171 INTDEF(_IO_str_underflow)
00172 
00173 /* The size of the valid part of the buffer.  */
00174 
00175 _IO_ssize_t
00176 _IO_str_count (fp)
00177      _IO_FILE *fp;
00178 {
00179   return ((fp->_IO_write_ptr > fp->_IO_read_end
00180           ? fp->_IO_write_ptr : fp->_IO_read_end)
00181          - fp->_IO_read_base);
00182 }
00183 
00184 
00185 static int
00186 enlarge_userbuf (_IO_FILE *fp, _IO_off64_t offset, int reading)
00187 {
00188   if ((_IO_ssize_t) offset <= _IO_blen (fp))
00189     return 0;
00190 
00191   _IO_ssize_t oldend = fp->_IO_write_end - fp->_IO_write_base;
00192 
00193   /* Try to enlarge the buffer.  */
00194   if (fp->_flags & _IO_USER_BUF)
00195     /* User-provided buffer.  */
00196     return 1;
00197 
00198   _IO_size_t newsize = offset + 100;
00199   char *oldbuf = fp->_IO_buf_base;
00200   char *newbuf
00201     = (char *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (newsize);
00202   if (newbuf == NULL)
00203     return 1;
00204 
00205   if (oldbuf != NULL)
00206     {
00207       memcpy (newbuf, oldbuf, _IO_blen (fp));
00208       (*((_IO_strfile *) fp)->_s._free_buffer) (oldbuf);
00209       /* Make sure _IO_setb won't try to delete
00210         _IO_buf_base. */
00211       fp->_IO_buf_base = NULL;
00212     }
00213 
00214   INTUSE(_IO_setb) (fp, newbuf, newbuf + newsize, 1);
00215 
00216   if (reading)
00217     {
00218       fp->_IO_write_base = newbuf + (fp->_IO_write_base - oldbuf);
00219       fp->_IO_write_ptr = newbuf + (fp->_IO_write_ptr - oldbuf);
00220       fp->_IO_write_end = newbuf + (fp->_IO_write_end - oldbuf);
00221       fp->_IO_read_ptr = newbuf + (fp->_IO_read_ptr - oldbuf);
00222 
00223       fp->_IO_read_base = newbuf;
00224       fp->_IO_read_end = fp->_IO_buf_end;
00225     }
00226   else
00227     {
00228       fp->_IO_read_base = newbuf + (fp->_IO_read_base - oldbuf);
00229       fp->_IO_read_ptr = newbuf + (fp->_IO_read_ptr - oldbuf);
00230       fp->_IO_read_end = newbuf + (fp->_IO_read_end - oldbuf);
00231       fp->_IO_write_ptr = newbuf + (fp->_IO_write_ptr - oldbuf);
00232 
00233       fp->_IO_write_base = newbuf;
00234       fp->_IO_write_end = fp->_IO_buf_end;
00235     }
00236 
00237   /* Clear the area between the last write position and th
00238      new position.  */
00239   assert (offset >= oldend);
00240   if (reading)
00241     memset (fp->_IO_read_base + oldend, '\0', offset - oldend);
00242   else
00243     memset (fp->_IO_write_base + oldend, '\0', offset - oldend);
00244 
00245   return 0;
00246 }
00247 
00248 
00249 _IO_off64_t
00250 _IO_str_seekoff (fp, offset, dir, mode)
00251      _IO_FILE *fp;
00252      _IO_off64_t offset;
00253      int dir;
00254      int mode;
00255 {
00256   _IO_off64_t new_pos;
00257 
00258   if (mode == 0 && (fp->_flags & _IO_TIED_PUT_GET))
00259     mode = (fp->_flags & _IO_CURRENTLY_PUTTING ? _IOS_OUTPUT : _IOS_INPUT);
00260 
00261   if (mode == 0)
00262     {
00263       /* Don't move any pointers. But there is no clear indication what
00264         mode FP is in. Let's guess. */
00265       if (fp->_IO_file_flags & _IO_NO_WRITES)
00266         new_pos = fp->_IO_read_ptr - fp->_IO_read_base;
00267       else
00268         new_pos = fp->_IO_write_ptr - fp->_IO_write_base;
00269     }
00270   else
00271     {
00272       _IO_ssize_t cur_size = _IO_str_count(fp);
00273       new_pos = EOF;
00274 
00275       /* Move the get pointer, if requested. */
00276       if (mode & _IOS_INPUT)
00277        {
00278          switch (dir)
00279            {
00280            case _IO_seek_end:
00281              offset += cur_size;
00282              break;
00283            case _IO_seek_cur:
00284              offset += fp->_IO_read_ptr - fp->_IO_read_base;
00285              break;
00286            default: /* case _IO_seek_set: */
00287              break;
00288            }
00289          if (offset < 0)
00290            return EOF;
00291          if ((_IO_ssize_t) offset > cur_size
00292              && enlarge_userbuf (fp, offset, 1) != 0)
00293            return EOF;
00294          fp->_IO_read_ptr = fp->_IO_read_base + offset;
00295          fp->_IO_read_end = fp->_IO_read_base + cur_size;
00296          new_pos = offset;
00297        }
00298 
00299       /* Move the put pointer, if requested. */
00300       if (mode & _IOS_OUTPUT)
00301        {
00302          switch (dir)
00303            {
00304            case _IO_seek_end:
00305              offset += cur_size;
00306              break;
00307            case _IO_seek_cur:
00308              offset += fp->_IO_write_ptr - fp->_IO_write_base;
00309              break;
00310            default: /* case _IO_seek_set: */
00311              break;
00312            }
00313          if (offset < 0)
00314            return EOF;
00315          if ((_IO_ssize_t) offset > cur_size
00316              && enlarge_userbuf (fp, offset, 0) != 0)
00317            return EOF;
00318          fp->_IO_write_ptr = fp->_IO_write_base + offset;
00319          new_pos = offset;
00320        }
00321     }
00322   return new_pos;
00323 }
00324 INTDEF(_IO_str_seekoff)
00325 
00326 int
00327 _IO_str_pbackfail (fp, c)
00328      _IO_FILE *fp;
00329      int c;
00330 {
00331   if ((fp->_flags & _IO_NO_WRITES) && c != EOF)
00332     return EOF;
00333   return INTUSE(_IO_default_pbackfail) (fp, c);
00334 }
00335 INTDEF(_IO_str_pbackfail)
00336 
00337 void
00338 _IO_str_finish (fp, dummy)
00339      _IO_FILE *fp;
00340      int dummy;
00341 {
00342   if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF))
00343     (((_IO_strfile *) fp)->_s._free_buffer) (fp->_IO_buf_base);
00344   fp->_IO_buf_base = NULL;
00345 
00346   INTUSE(_IO_default_finish) (fp, 0);
00347 }
00348 
00349 const struct _IO_jump_t _IO_str_jumps =
00350 {
00351   JUMP_INIT_DUMMY,
00352   JUMP_INIT(finish, _IO_str_finish),
00353   JUMP_INIT(overflow, INTUSE(_IO_str_overflow)),
00354   JUMP_INIT(underflow, INTUSE(_IO_str_underflow)),
00355   JUMP_INIT(uflow, INTUSE(_IO_default_uflow)),
00356   JUMP_INIT(pbackfail, INTUSE(_IO_str_pbackfail)),
00357   JUMP_INIT(xsputn, INTUSE(_IO_default_xsputn)),
00358   JUMP_INIT(xsgetn, INTUSE(_IO_default_xsgetn)),
00359   JUMP_INIT(seekoff, INTUSE(_IO_str_seekoff)),
00360   JUMP_INIT(seekpos, _IO_default_seekpos),
00361   JUMP_INIT(setbuf, _IO_default_setbuf),
00362   JUMP_INIT(sync, _IO_default_sync),
00363   JUMP_INIT(doallocate, INTUSE(_IO_default_doallocate)),
00364   JUMP_INIT(read, _IO_default_read),
00365   JUMP_INIT(write, _IO_default_write),
00366   JUMP_INIT(seek, _IO_default_seek),
00367   JUMP_INIT(close, _IO_default_close),
00368   JUMP_INIT(stat, _IO_default_stat),
00369   JUMP_INIT(showmanyc, _IO_default_showmanyc),
00370   JUMP_INIT(imbue, _IO_default_imbue)
00371 };