Annotation of GNUtools/libg++/libio/fileops.c, revision 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.