Annotation of GNUtools/libg++/libio/fileops.c, revision 1.1.1.1

1.1       root        1: /* 
                      2: Copyright (C) 1993 Free Software Foundation
                      3: 
                      4: This file is part of the GNU IO Library.  This library is free
                      5: software; you can redistribute it and/or modify it under the
                      6: terms of the GNU General Public License as published by the
                      7: Free Software Foundation; either version 2, or (at your option)
                      8: any later version.
                      9: 
                     10: This library is distributed in the hope that it will be useful,
                     11: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     12: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     13: GNU General Public License for more details.
                     14: 
                     15: You should have received a copy of the GNU General Public License
                     16: along with GNU CC; see the file COPYING.  If not, write to
                     17: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
                     18: 
                     19: As a special exception, if you link this library with files
                     20: compiled with a GNU compiler to produce an executable, this does not cause
                     21: the resulting executable to be covered by the GNU General Public License.
                     22: This exception does not however invalidate any other reasons why
                     23: the executable file might be covered by the GNU General Public License. */
                     24: 
                     25: /*  written by Per Bothner ([email protected]) */
                     26: 
                     27: #define _POSIX_SOURCE
                     28: #include "libioP.h"
                     29: #include <fcntl.h>
                     30: #include <sys/types.h>
                     31: #include <sys/stat.h>
                     32: #include <string.h>
                     33: #include <errno.h>
                     34: #ifndef errno
                     35: extern int errno;
                     36: #endif
                     37: 
                     38: /* An fstream can be in at most one of put mode, get mode, or putback mode.
                     39:    Putback mode is a variant of get mode.
                     40: 
                     41:    In a filebuf, there is only one current position, instead of two
                     42:    separate get and put pointers.  In get mode, the current posistion
                     43:    is that of gptr(); in put mode that of pptr().
                     44: 
                     45:    The position in the buffer that corresponds to the position
                     46:    in external file system is file_ptr().
                     47:    This is normally egptr(), except in putback mode, when it is _save_egptr.
                     48:    If the field _fb._offset is >= 0, it gives the offset in
                     49:    the file as a whole corresponding to eGptr(). (???)
                     50: 
                     51:    PUT MODE:
                     52:    If a filebuf is in put mode, pbase() is non-NULL and equal to base().
                     53:    Also, epptr() == ebuf().
                     54:    Also, eback() == gptr() && gptr() == egptr().
                     55:    The un-flushed character are those between pbase() and pptr().
                     56:    GET MODE:
                     57:    If a filebuf is in get or putback mode, eback() != egptr().
                     58:    In get mode, the unread characters are between gptr() and egptr().
                     59:    The OS file position corresponds to that of egptr().
                     60:    PUTBACK MODE:
                     61:    Putback mode is used to remember "excess" characters that have
                     62:    been sputbackc'd in a separate putback buffer.
                     63:    In putback mode, the get buffer points to the special putback buffer.
                     64:    The unread characters are the characters between gptr() and egptr()
                     65:    in the putback buffer, as well as the area between save_gptr()
                     66:    and save_egptr(), which point into the original reserve buffer.
                     67:    (The pointers save_gptr() and save_egptr() are the values
                     68:    of gptr() and egptr() at the time putback mode was entered.)
                     69:    The OS position corresponds to that of save_egptr().
                     70:    
                     71:    LINE BUFFERED OUTPUT:
                     72:    During line buffered output, pbase()==base() && epptr()==base().
                     73:    However, ptr() may be anywhere between base() and ebuf().
                     74:    This forces a call to filebuf::overflow(int C) on every put.
                     75:    If there is more space in the buffer, and C is not a '\n',
                     76:    then C is inserted, and pptr() incremented.
                     77:    
                     78:    UNBUFFERED STREAMS:
                     79:    If a filebuf is unbuffered(), the _shortbuf[1] is used as the buffer.
                     80: */
                     81: 
                     82: #define CLOSED_FILEBUF_FLAGS \
                     83:   (_IO_IS_FILEBUF+_IO_NO_READS+_IO_NO_WRITES+_IO_TIED_PUT_GET)
                     84: 
                     85: 
                     86: void
                     87: _IO_file_init(fp)
                     88:      register _IO_FILE *fp;
                     89: {
                     90:   fp->_offset = _IO_pos_0;
                     91: 
                     92:   _IO_link_in(fp);
                     93:   fp->_fileno = -1;
                     94: }
                     95: 
                     96: int
                     97: _IO_file_close_it(fp)
                     98:      register _IO_FILE* fp;
                     99: {
                    100:   int status;
                    101:   if (!_IO_file_is_open(fp))
                    102:     return EOF;
                    103: 
                    104:   /* This flushes as well as switching mode. */
                    105:   if (fp->_IO_write_ptr > fp->_IO_write_base || _IO_in_put_mode(fp))
                    106:     if (_IO_switch_to_get_mode(fp))
                    107:          return EOF;
                    108: 
                    109:   _IO_unsave_markers(fp);
                    110: 
                    111:   status = fp->_jumps->__close(fp);
                    112:   
                    113:   /* Free buffer. */
                    114:   _IO_setb(fp, NULL, NULL, 0);
                    115:   _IO_setg(fp, NULL, NULL, NULL);
                    116:   _IO_setp(fp, NULL, NULL);
                    117: 
                    118:   _IO_un_link(fp);
                    119:   fp->_flags = _IO_MAGIC|CLOSED_FILEBUF_FLAGS;
                    120:   fp->_fileno = EOF;
                    121:   fp->_offset = _IO_pos_0;
                    122: 
                    123:   return status;
                    124: }
                    125: 
                    126: void
                    127: _IO_file_finish(fp)
                    128:      register _IO_FILE* fp;
                    129: {
                    130:   if (!(fp->_flags & _IO_DELETE_DONT_CLOSE))
                    131:     _IO_file_close_it(fp);
                    132:   _IO_default_finish(fp);
                    133: }
                    134: 
                    135: _IO_FILE *
                    136: _IO_file_fopen(fp, filename, mode)
                    137:      register _IO_FILE *fp;
                    138:      const char *filename;
                    139:      const char *mode;
                    140: {
                    141:   int oflags = 0, omode;
                    142:   int read_write, fdesc;
                    143:   int oprot = 0666;
                    144:   if (_IO_file_is_open (fp))
                    145:     return 0;
                    146:   switch (*mode++) {
                    147:   case 'r':
                    148:     omode = O_RDONLY;
                    149:     read_write = _IO_NO_WRITES;
                    150:     break;
                    151:   case 'w':
                    152:     omode = O_WRONLY;
                    153:     oflags = O_CREAT|O_TRUNC;
                    154:     read_write = _IO_NO_READS;
                    155:     break;
                    156:   case 'a':
                    157:     omode = O_WRONLY;
                    158:     oflags = O_CREAT|O_APPEND;
                    159:     read_write = _IO_NO_READS|_IO_IS_APPENDING;
                    160:     break;
                    161:   default:
                    162:     errno = EINVAL;
                    163:     return NULL;
                    164:   }
                    165:   if (mode[0] == '+' || (mode[0] == 'b' && mode[1] == '+')) {
                    166:     omode = O_RDWR;
                    167:     read_write &= _IO_IS_APPENDING;
                    168:   }
                    169:   fdesc = open(filename, omode|oflags, oprot);
                    170:   if (fdesc < 0)
                    171:     return NULL;
                    172:   fp->_fileno = fdesc;
                    173:   fp->_IO_file_flags = 
                    174:     _IO_mask_flags(fp, read_write,_IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
                    175:   if (read_write & _IO_IS_APPENDING)
                    176:     if (fp->_jumps->__seekoff(fp, (_IO_off_t)0, _IO_seek_end) == _IO_pos_BAD)
                    177:       return NULL;
                    178:   _IO_link_in(fp);
                    179:   return fp;
                    180: }
                    181: 
                    182: _IO_FILE*
                    183: _IO_file_attach(fp, fd)
                    184:      _IO_FILE *fp;
                    185:      int fd;
                    186: {
                    187:   if (_IO_file_is_open(fp))
                    188:     return NULL;
                    189:   fp->_fileno = fd;
                    190:   fp->_flags &= ~(_IO_NO_READS+_IO_NO_WRITES);
                    191:   fp->_offset = _IO_pos_BAD;
                    192:   return fp;
                    193: }
                    194: 
                    195: int
                    196: _IO_file_setbuf(fp, p, len)
                    197:      register _IO_FILE *fp;
                    198:      char* p;
                    199:      _IO_ssize_t len;
                    200: {
                    201:     if (_IO_default_setbuf(fp, p, len) == EOF)
                    202:        return EOF;
                    203: 
                    204:     fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
                    205:       = fp->_IO_buf_base;
                    206:     _IO_setg(fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
                    207: 
                    208:     return 0;
                    209: }
                    210: 
                    211: int
                    212: _IO_do_write(fp, data, to_do)
                    213:      register _IO_FILE *fp;
                    214:      const char* data;
                    215:      _IO_size_t to_do;
                    216: {
                    217:   _IO_size_t count;
                    218:   if (to_do == 0)
                    219:     return 0;
                    220:   if (fp->_flags & _IO_IS_APPENDING)
                    221:     /* On a system without a proper O_APPEND implementation,
                    222:        you would need to sys_seek(0, SEEK_END) here, but is
                    223:        is not needed nor desirable for Unix- or Posix-like systems.
                    224:        Instead, just indicate that offset (before and after) is
                    225:        unpredictable. */
                    226:     fp->_offset = _IO_pos_BAD;
                    227:   else if (fp->_IO_read_end != fp->_IO_write_base)
                    228:     { 
                    229:       _IO_pos_t new_pos = fp->_jumps->__seek(fp, fp->_IO_write_base - fp->_IO_read_end, 1);
                    230:       if (new_pos == _IO_pos_BAD)
                    231:        return EOF;
                    232:       fp->_offset = new_pos;
                    233:     }
                    234:   count = fp->_jumps->__write(fp, data, to_do);
                    235:   if (fp->_cur_column)
                    236:     fp->_cur_column = _IO_adjust_column(fp->_cur_column - 1, data, to_do) + 1;
                    237:   _IO_setg(fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
                    238:   fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_buf_base;
                    239:   fp->_IO_write_end = (fp->_flags & _IO_LINE_BUF+_IO_UNBUFFERED) ? fp->_IO_buf_base
                    240:     : fp->_IO_buf_end;
                    241:   return count != to_do ? EOF : 0;
                    242: }
                    243: 
                    244: int
                    245: _IO_file_underflow(fp)
                    246:      register _IO_FILE *fp;
                    247: {
                    248:   _IO_size_t count;
                    249: #if 0
                    250:   /* SysV does not make this test; take it out for compatibility */
                    251:   if (fp->_flags & _IO_EOF_SEEN)
                    252:     return (EOF);
                    253: #endif
                    254: 
                    255:   if (fp->_flags & _IO_NO_READS)
                    256:     return EOF;
                    257:   if (fp->_IO_read_ptr < fp->_IO_read_end)
                    258:     return *(unsigned char*)fp->_IO_read_ptr;
                    259: 
                    260:   if (fp->_IO_buf_base == NULL)
                    261:     _IO_doallocbuf(fp);
                    262: 
                    263:   /* Flush all line buffered files before reading. */
                    264:   /* FIXME This can/should be moved to genops ?? */
                    265:   if (fp->_flags & (_IO_LINE_BUF|_IO_UNBUFFERED))
                    266:     _IO_flush_all_linebuffered();
                    267: 
                    268:   _IO_switch_to_get_mode(fp);
                    269: 
                    270:   count = fp->_jumps->__read(fp, fp->_IO_buf_base,
                    271:                             fp->_IO_buf_end - fp->_IO_buf_base);
                    272:   if (count <= 0)
                    273:     {
                    274:       if (count == 0)
                    275:        fp->_flags |= _IO_EOF_SEEN;
                    276:       else
                    277:        fp->_flags |= _IO_ERR_SEEN, count = 0;
                    278:   }
                    279:   fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base;
                    280:   fp->_IO_read_end = fp->_IO_buf_base + count;
                    281:   fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
                    282:     = fp->_IO_buf_base;
                    283:   if (count == 0)
                    284:     return EOF;
                    285:   if (fp->_offset != _IO_pos_BAD)
                    286:     _IO_pos_adjust(fp->_offset, count);
                    287:   return *(unsigned char*)fp->_IO_read_ptr;
                    288: }
                    289: 
                    290: int _IO_file_overflow (f, ch)
                    291:      register _IO_FILE* f;
                    292:      int ch;
                    293: {
                    294:   if (f->_flags & _IO_NO_WRITES) /* SET ERROR */
                    295:     return EOF;
                    296:   /* If current reading or no buffer allocated. */
                    297:   if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0)
                    298:     {
                    299:       /* Allocate a buffer if needed. */
                    300:       if (f->_IO_buf_base == 0)
                    301:        {
                    302:          _IO_doallocbuf(f);
                    303:          f->_IO_read_end = f->_IO_buf_base;
                    304:          f->_IO_write_ptr = f->_IO_buf_base;
                    305:        }
                    306:       else /* Must be currently reading. */
                    307:        f->_IO_write_ptr = f->_IO_read_ptr;
                    308:       f->_IO_write_base = f->_IO_write_ptr;
                    309:       f->_IO_write_end = f->_IO_buf_end;
                    310:       f->_IO_read_base = f->_IO_read_ptr = f->_IO_read_end;
                    311: 
                    312:       if (f->_flags & _IO_LINE_BUF+_IO_UNBUFFERED)
                    313:        f->_IO_write_end = f->_IO_write_ptr;
                    314:       f->_flags |= _IO_CURRENTLY_PUTTING;
                    315:     }
                    316:   if (ch == EOF)
                    317:     return _IO_do_flush(f);
                    318:   if (f->_IO_write_ptr == f->_IO_buf_end ) /* Buffer is really full */
                    319:     if (_IO_do_flush(f) == EOF)
                    320:       return EOF;
                    321:   *f->_IO_write_ptr++ = ch;
                    322:   if ((f->_flags & _IO_UNBUFFERED)
                    323:       || ((f->_flags & _IO_LINE_BUF) && ch == '\n'))
                    324:     if (_IO_do_flush(f) == EOF)
                    325:       return EOF;
                    326:   return (unsigned char)ch;
                    327: }
                    328: 
                    329: int
                    330: _IO_file_sync(fp)
                    331:      register _IO_FILE* fp;
                    332: {
                    333:   _IO_size_t delta;
                    334:   /*    char* ptr = cur_ptr(); */
                    335:   if (fp->_IO_write_ptr > fp->_IO_write_base)
                    336:     if (_IO_do_flush(fp)) return EOF;
                    337:   delta = fp->_IO_read_ptr - fp->_IO_read_end; 
                    338:   if (delta != 0)
                    339:     {
                    340: #ifdef TODO
                    341:       if (_IO_in_backup(fp))
                    342:        delta -= eGptr() - Gbase();
                    343: #endif
                    344:       _IO_off_t new_pos = fp->_jumps->__seek(fp, delta, 1);
                    345:       if (new_pos == (_IO_off_t)EOF)
                    346:        return EOF;
                    347:       fp->_offset = new_pos;
                    348:       fp->_IO_read_end = fp->_IO_read_ptr;
                    349:     }
                    350:   /* FIXME: Cleanup - can this be shared? */
                    351:   /*    setg(base(), ptr, ptr); */
                    352:   return 0;
                    353: }
                    354: 
                    355: _IO_pos_t
                    356: _IO_file_seekoff(fp, offset, mode)
                    357:      register _IO_FILE *fp;
                    358:      _IO_off_t offset;
                    359:      _IO_seekflags mode;
                    360: {
                    361:   _IO_pos_t result;
                    362:   _IO_off_t delta, new_offset;
                    363:   long count;
                    364:   int dir = mode & 3;
                    365: 
                    366:   if ((mode & _IO_seek_not_in) && (mode & _IO_seek_not_out))
                    367:     dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
                    368: 
                    369:   /* Flush unwritten characters.
                    370:      (This may do an unneeded write if we seek within the buffer.
                    371:      But to be able to switch to reading, we would need to set
                    372:      egptr to ptr.  That can't be done in the current design,
                    373:      which assumes file_ptr() is eGptr.  Anyway, since we probably
                    374:      end up flushing when we close(), it doesn't make much difference.)
                    375:      FIXME: simulate mem-papped files. */
                    376: 
                    377:   if (fp->_IO_write_ptr > fp->_IO_write_base || _IO_in_put_mode(fp))
                    378:     if (_IO_switch_to_get_mode(fp)) return EOF;
                    379: 
                    380:   if (fp->_IO_buf_base == NULL)
                    381:     {
                    382:       _IO_doallocbuf(fp);
                    383:       _IO_setp(fp, fp->_IO_buf_base, fp->_IO_buf_base);
                    384:       _IO_setg(fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
                    385:     }
                    386: 
                    387:   switch (dir)
                    388:     {
                    389:     case _IO_seek_cur:
                    390:       if (fp->_offset == _IO_pos_BAD)
                    391:        goto dumb;
                    392:       /* Adjust for read-ahead (bytes is buffer). */
                    393:       offset -= fp->_IO_read_end - fp->_IO_read_ptr;
                    394:       /* Make offset absolute, assuming current pointer is file_ptr(). */
                    395:       offset += _IO_pos_as_off(fp->_offset);
                    396: 
                    397:       dir = _IO_seek_set;
                    398:       break;
                    399:     case _IO_seek_set:
                    400:       break;
                    401:     case _IO_seek_end:
                    402:       {
                    403:        struct stat st;
                    404:        if (fp->_jumps->__stat(fp, &st) == 0 && S_ISREG(st.st_mode))
                    405:          {
                    406:            offset += st.st_size;
                    407:            dir = _IO_seek_set;
                    408:          }
                    409:        else
                    410:          goto dumb;
                    411:       }
                    412:     }
                    413:   /* At this point, dir==_IO_seek_set. */
                    414: 
                    415: #ifdef TODO
                    416:   /* If destination is within current buffer, optimize: */
                    417:   if (fp->_offset != IO_pos_BAD && fp->_IO_read_base != NULL)
                    418:     {
                    419:       /* Offset relative to start of main get area. */
                    420:       _IO_pos_t rel_offset = offset - _fb._offset
                    421:        + (eGptr()-Gbase());
                    422:       if (rel_offset >= 0)
                    423:        {
                    424:          if (_IO_in_backup(fp))
                    425:            _IO_switch_to_main_get_area(fp);
                    426:          if (rel_offset <= _IO_read_end - _IO_read_base)
                    427:            {
                    428:              _IO_setg(fp->_IO_buf_base, fp->_IO_buf_base + rel_offset,
                    429:                       fp->_IO_read_end);
                    430:              _IO_setp(fp->_IO_buf_base, fp->_IO_buf_base);
                    431:              return offset;
                    432:            }
                    433:            /* If we have streammarkers, seek forward by reading ahead. */
                    434:            if (_IO_have_markers(fp))
                    435:              {
                    436:                int to_skip = rel_offset
                    437:                  - (fp->_IO_read_ptr - fp->_IO_read_base);
                    438:                if (ignore(to_skip) != to_skip)
                    439:                  goto dumb;
                    440:                return offset;
                    441:              }
                    442:        }
                    443:       if (rel_offset < 0 && rel_offset >= Bbase() - Bptr())
                    444:        {
                    445:          if (!_IO_in_backup(fp))
                    446:            _IO_switch_to_backup_area(fp);
                    447:          gbump(fp->_IO_read_end + rel_offset - fp->_IO_read_ptr);
                    448:          return offset;
                    449:        }
                    450:     }
                    451: 
                    452:   _IO_unsave_markers(fp);
                    453: #endif
                    454: 
                    455:   /* Try to seek to a block boundary, to improve kernel page management. */
                    456:   new_offset = offset & ~(fp->_IO_buf_end - fp->_IO_buf_base - 1);
                    457:   delta = offset - new_offset;
                    458:   if (delta > fp->_IO_buf_end - fp->_IO_buf_base)
                    459:     {
                    460:       new_offset = offset;
                    461:       delta = 0;
                    462:     }
                    463:   result = fp->_jumps->__seek(fp, new_offset, 0);
                    464:   if (result < 0)
                    465:     return EOF;
                    466:   if (delta == 0)
                    467:     count = 0;
                    468:   else
                    469:     {
                    470:       count = fp->_jumps->__read(fp, fp->_IO_buf_base,
                    471:                                 fp->_IO_buf_end - fp->_IO_buf_base);
                    472:       if (count < delta)
                    473:        {
                    474:          /* We weren't allowed to read, but try to seek the remainder. */
                    475:          offset = count == EOF ? delta : delta-count;
                    476:          dir = _IO_seek_cur;
                    477:          goto dumb;
                    478:        }
                    479:     }
                    480:   _IO_setg(fp, fp->_IO_buf_base, fp->_IO_buf_base+delta, fp->_IO_buf_base+count);
                    481:   _IO_setp(fp, fp->_IO_buf_base, fp->_IO_buf_base);
                    482:   fp->_offset = result + count;
                    483:   _IO_mask_flags(fp, 0, _IO_EOF_SEEN);
                    484:   return offset;
                    485:  dumb:
                    486: 
                    487:   _IO_unsave_markers(fp);
                    488:   result = fp->_jumps->__seek(fp, offset, dir);
                    489:   if (result != EOF)
                    490:     _IO_mask_flags(fp, 0, _IO_EOF_SEEN);
                    491:   fp->_offset = result;
                    492:   _IO_setg(fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
                    493:   _IO_setp(fp, fp->_IO_buf_base, fp->_IO_buf_base);
                    494:   return result;
                    495: }
                    496: 
                    497: _IO_ssize_t
                    498: _IO_file_read(fp, buf, size)
                    499:      register _IO_FILE* fp;
                    500:      void* buf;
                    501:      _IO_ssize_t size;
                    502: {
                    503:   for (;;)
                    504:     {
                    505:       _IO_ssize_t count = _IO_read(fp->_fileno, buf, size);
                    506: #ifdef EINTR
                    507:       if (errno == EINTR && count == -1)
                    508:        continue;
                    509: #endif
                    510:       return count;
                    511:     }
                    512: }
                    513: 
                    514: _IO_pos_t
                    515: _IO_file_seek(fp, offset, dir)
                    516:      _IO_FILE *fp;
                    517:      _IO_off_t offset;
                    518:      int dir;
                    519: {
                    520:   return _IO_lseek(fp->_fileno, offset, dir);
                    521: }
                    522: 
                    523: int
                    524: _IO_file_stat(fp, st)
                    525:      _IO_FILE *fp;
                    526:      void* st;
                    527: {
                    528:   return _IO_fstat(fp->_fileno, (struct stat*)st);
                    529: }
                    530: 
                    531: int
                    532: _IO_file_close(fp)
                    533:      _IO_FILE* fp;
                    534: {
                    535:   return _IO_close(fp->_fileno);
                    536: }
                    537: 
                    538: _IO_ssize_t
                    539: _IO_file_write(f, data, n)
                    540:      register _IO_FILE* f;
                    541:      const void* data;
                    542:      _IO_ssize_t n;
                    543: {
                    544:   _IO_ssize_t to_do = n;
                    545:   while (to_do > 0)
                    546:     {
                    547:       _IO_ssize_t count = _IO_write(f->_fileno, data, to_do);
                    548:       if (count == EOF)
                    549:        {
                    550: #ifdef EINTR
                    551:          if (errno == EINTR)
                    552:            continue;
                    553:          else
                    554: #endif
                    555:            {
                    556:              f->_flags |= _IO_ERR_SEEN;
                    557:              break;
                    558:             }
                    559:         }
                    560:       to_do -= count;
                    561:       data = (void*)((char*)data + count);
                    562:     }
                    563:   n -= to_do;
                    564:   if (f->_offset >= 0)
                    565:     f->_offset += n;
                    566:   return n;
                    567: }
                    568: 
                    569: _IO_size_t
                    570: _IO_file_xsputn(f, data, n)
                    571:      _IO_FILE *f;
                    572:      const void *data;
                    573:      _IO_size_t n;
                    574: {
                    575:   register const char *s = data;
                    576:   _IO_size_t to_do = n;
                    577:   int must_flush = 0;
                    578:   _IO_size_t count;
                    579: 
                    580:   if (n <= 0)
                    581:     return 0;
                    582:   /* This is an optimized implementation.
                    583:      If the amount to be written straddles a block boundary
                    584:      (or the filebuf is unbuffered), use sys_write directly. */
                    585: 
                    586:   /* First figure out how much space is available in the buffer. */
                    587:   count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */
                    588:   if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING))
                    589:     {
                    590:       count = f->_IO_buf_end - f->_IO_write_ptr;
                    591:       if (count >= n)
                    592:        { register const char *p;
                    593:          for (p = s + n; p > s; )
                    594:            {
                    595:              if (*--p == '\n') {
                    596:                count = p - s + 1;
                    597:                must_flush = 1;
                    598:                break;
                    599:              }
                    600:            }
                    601:        }
                    602:     }
                    603:   /* Then fill the buffer. */
                    604:   if (count > 0)
                    605:     {
                    606:       if (count > to_do)
                    607:        count = to_do;
                    608:       if (count > 20) {
                    609:        memcpy(f->_IO_write_ptr, s, count);
                    610:        s += count;
                    611:       }
                    612:       else
                    613:        {
                    614:          register char *p = f->_IO_write_ptr;
                    615:          register int i = (int)count;
                    616:          while (--i >= 0) *p++ = *s++;
                    617:        }
                    618:       f->_IO_write_ptr += count;
                    619:       to_do -= count;
                    620:     }
                    621:   if (to_do + must_flush > 0)
                    622:     { _IO_size_t block_size, dont_write;
                    623:       /* Next flush the (full) buffer. */
                    624:       if (__overflow(f, EOF) == EOF)
                    625:        return n - to_do;
                    626: 
                    627:       /* Try to maintain alignment: write a whole number of blocks.
                    628:         dont_write is what gets left over. */
                    629:       block_size = f->_IO_buf_end - f->_IO_buf_base;
                    630:       dont_write = block_size >= 128 ? to_do % block_size : 0;
                    631: 
                    632:       count = to_do - dont_write;
                    633:       if (_IO_do_write(f, s, count) == EOF)
                    634:        return n - to_do;
                    635:       to_do = dont_write;
                    636:       
                    637:       /* Now write out the remainder.  Normally, this will fit in the
                    638:         buffer, but it's somewhat messier for line-buffered files,
                    639:         so we let _IO_xsputn handle the general case. */
                    640:       if (dont_write)
                    641:        to_do -= _IO_default_xsputn(f, s+count, dont_write);
                    642:     }
                    643:   return n - to_do;
                    644: }
                    645: 
                    646: struct _IO_jump_t _IO_file_jumps = {
                    647:   _IO_file_overflow,
                    648:   _IO_file_underflow,
                    649:   _IO_file_xsputn,
                    650:   _IO_default_xsgetn,
                    651:   _IO_file_read,
                    652:   _IO_file_write,
                    653:   _IO_file_doallocate,
                    654:   _IO_default_pbackfail,
                    655:   _IO_file_setbuf,
                    656:   _IO_file_sync,
                    657:   _IO_file_finish,
                    658:   _IO_file_close,
                    659:   _IO_file_stat,
                    660:   _IO_file_seek,
                    661:   _IO_file_seekoff,
                    662:   _IO_default_seekpos,
                    663: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.