C标准库stdio源码分析

来源:互联网 发布:淘宝网怎么修改密码 编辑:程序博客网 时间:2024/04/30 08:23
//// stdio.h//// Standard I/O routines//// Copyright (C) 2002 Michael Ringgaard. All rights reserved.//// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions// are met://// 1. Redistributions of source code must retain the above copyright//    notice, this list of conditions and the following disclaimer.// 2. Redistributions in binary form must reproduce the above copyright//    notice, this list of conditions and the following disclaimer in the//    documentation and/or other materials provided with the distribution.// 3. Neither the name of the project nor the names of its contributors//    may be used to endorse or promote products derived from this software//    without specific prior written permission.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE// ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF// SUCH DAMAGE.//#if _MSC_VER > 1000#pragma once#endif#ifndef STDIO_H#define STDIO_H#include <sys/types.h>#ifndef _FPOS_T_DEFINED#define _FPOS_T_DEFINEDtypedef long fpos_t;#endif#ifndef SEEK_SET#define SEEK_SET   0#define SEEK_CUR   1#define SEEK_END   2#endif#define L_tmpnam       256#define FILENAME_MAX   256#define EOF            (-1)#define BUFSIZ         512struct _iobuf {  char *ptr;        //缓冲区指针  int cnt;          //流缓冲区大小  char *base;       //缓冲区指针  int flag;//文件当前状态 _IORD  _IOWR _IORW 等等...  handle_t file;//Unix中的文件描述符   int charbuf;  int bufsiz;  int phndl;};typedef struct _iobuf FILE;#define stdin   __getstdfile(0)#define stdout  __getstdfile(1)#define stderr  __getstdfile(2)#define _IORD           0x0001//0000 0000 0000 0001  read#define _IOWR           0x0002//  0000 0000 0000 0010  write#define _IOFBF          0x0000  //  全缓冲#define _IOLBF          0x0040  //  行缓冲#define _IONBF          0x0004  //  无缓冲#define _IOOWNBUF       0x0008#define _IOEXTBUF       0x0100#define _IOTMPBUF       0x1000#define _IOEOF          0x0010#define _IOERR          0x0020#define _IOSTR          0x0040#define _IORW           0x0080//  0000 0000 0000 0100#define _IOCRLF         0x8000#ifdef  __cplusplusextern "C" {#endifint filbuf(FILE *stream);int flsbuf(int, FILE *stream);FILE *fdopen(int fd, const char *mode);FILE *freopen(const char *filename, const char *mode, FILE *stream);FILE *fopen(const char *filename, const char *mode);FILE *popen(const char *command, const char *mode);int pclose(FILE *stream);void clearerr(FILE *stream);int fclose(FILE *stream);int fflush(FILE *stream);int fgetc(FILE *stream);int fputc(int c, FILE *stream);char *fgets(char *string, int n, FILE *stream);int fputs(const char *string, FILE *stream);char *gets(char *buf);int puts(const char *string);size_t fread(void *buffer, size_t size, size_t num, FILE *stream);size_t fwrite(const void *buffer, size_t size, size_t num, FILE *stream);int fseek(FILE *stream, long offset, int whence);long ftell(FILE *stream);void rewind(FILE *stream);int fsetpos(FILE *stream, const fpos_t *pos);int fgetpos(FILE *stream, fpos_t *pos);void perror(const char *message);void setbuf(FILE *stream, char *buffer);int setvbuf(FILE *stream, char *buffer, int type, size_t size);int ungetc(int c, FILE *stream);int fready(FILE *stream);int remove(const char *filename);osapi int rename(const char *oldname, const char *newname);FILE *tmpfile();char *tmpnam(char *string);char *tempnam(const char *dir, const char *prefix);int vfprintf(FILE *stream, const char *fmt, va_list args);int fprintf(FILE *stream, const char *fmt, ...);int vprintf(const char *fmt, va_list args);int printf(const char *fmt, ...);int vsprintf(char *buf, const char *fmt, va_list args);int sprintf(char *buf, const char *fmt, ...);int vsnprintf(char *buf, size_t count, const char *fmt, va_list args);int snprintf(char *buf, size_t count, const char *fmt, ...);int fscanf(FILE *stream, const char *fmt, ...);int scanf(const char *fmt, ...);int sscanf(const char *buffer, const char *fmt, ...);int vfscanf(FILE *stream, const char *fmt, va_list args);int vscanf(const char *fmt, va_list args);int vsscanf(const char *buffer, const char *fmt, va_list args);FILE *__getstdfile(int n);#ifdef  __cplusplus}#endif#define feof(stream)     ((stream)->flag & _IOEOF)#define ferror(stream)   ((stream)->flag & _IOERR)#define fileno(stream)   ((stream)->file)  //not a ISO C but POSIX.1 support#define getc(stream)     (--(stream)->cnt >= 0 ? 0xff & *(stream)->ptr++ : filbuf(stream))#define putc(c, stream)  (--(stream)->cnt >= 0 ? 0xff & (*(stream)->ptr++ = (char) (c)) :  flsbuf((c), (stream)))#define getchar()        getc(stdin)#define putchar(c)       putc((c), stdout)#endif

//// stdio.c//// Standard I/O routines//// Copyright (C) 2002 Michael Ringgaard. All rights reserved.//// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions// are met:// // 1. Redistributions of source code must retain the above copyright //    notice, this list of conditions and the following disclaimer.  // 2. Redistributions in binary form must reproduce the above copyright//    notice, this list of conditions and the following disclaimer in the//    documentation and/or other materials provided with the distribution.  // 3. Neither the name of the project nor the names of its contributors//    may be used to endorse or promote products derived from this software//    without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE// ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF // SUCH DAMAGE.// #include <os.h>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <stdarg.h>#include <crtbase.h>#include <atomic.h>#define bigbuf(s) ((s)->flag & (_IOOWNBUF | _IOEXTBUF | _IOTMPBUF))#define anybuf(s) ((s)->flag & (_IOOWNBUF | _IOEXTBUF | _IOTMPBUF | _IONBF))/*如果文件是 _IORD |_IOWR |_IORW 三种状态任意一个  被freopen()调用*/#define inuse(s)  ((s)->flag & (_IORD |_IOWR |_IORW)) static void exit_stdio(void) {  // Flush stdout and stderr  fflush(stdout);  fflush(stderr);}static void init_stdio() {  struct process *proc = gettib()->proc;  struct crtbase *crtbase = (struct crtbase *) proc->crtbase;  // Only initialize on first call.  if (crtbase->stdio_initialized) return;  if (atomic_increment(&crtbase->stdio_init) == 1) {    // Set up stdin, stdout, and stderr.    crtbase->iob[0].file = proc->iob[0];    crtbase->iob[0].base = crtbase->iob[0].ptr = crtbase->stdinbuf;    crtbase->iob[0].flag = _IORD | _IOEXTBUF;    crtbase->iob[0].bufsiz = BUFSIZ;    crtbase->iob[1].file = proc->iob[1];    crtbase->iob[1].flag = _IOWR | _IONBF | _IOCRLF;    crtbase->iob[2].file = proc->iob[2];    crtbase->iob[2].flag = _IOWR | _IONBF | _IOCRLF;    atexit(exit_stdio);    crtbase->stdio_initialized = 1;  } else {    // Wait until initialization done.    while (!crtbase->stdio_initialized) msleep(0);  }}FILE *__getstdfile(int n) {  struct process *proc = gettib()->proc;  struct crtbase *crtbase = (struct crtbase *) proc->crtbase;  if (!crtbase->stdio_initialized) init_stdio();  return &crtbase->iob[n];}static void getbuf(FILE *stream) {  // Try to get a buffer  if (stream->base = malloc(BUFSIZ)) {    // Got a buffer    stream->flag |= _IOOWNBUF;    stream->bufsiz = BUFSIZ;  } else {    // Did NOT get a buffer - use single char buffering.    stream->flag |= _IONBF;    stream->base = (char *) &stream->charbuf;    stream->bufsiz = 1;  }  stream->ptr = stream->base;  stream->cnt = 0;}static void freebuf(FILE *stream) {  if (stream->flag & _IOOWNBUF) {    free(stream->base);    stream->flag &= ~_IOOWNBUF;    stream->base = stream->ptr = NULL;    stream->cnt = 0;  }}int _stbuf(FILE *stream, char *buf, int bufsiz) {  // Setup temp buffering  stream->base = stream->ptr = buf;  stream->cnt = bufsiz;  stream->flag |= (_IOWR | _IOTMPBUF | _IOEXTBUF);  return 0;}void _ftbuf(FILE *stream) {  if (stream->flag & _IOTMPBUF) {    // Flush the stream and tear down temp buffering    fflush(stream);    stream->flag &= ~(_IOEXTBUF | _IOTMPBUF);    stream->bufsiz = 0;    stream->base = stream->ptr = NULL;  }}static int write_translated(int fh, char *buf, int len) {  char *ptr = buf;  char *end = buf + len;  int written = 0;  int rc;  while (ptr < end) {    if (*ptr == '\n') {      if (buf < ptr) {        rc = write(fh, buf, ptr - buf);        if (rc < 0) return rc;        written += rc;      }      rc = write(fh, "\r", 1);      if (rc < 0) return -1;      buf = ptr;    }    ptr++;  }  if (buf < end) {    rc = write(fh, buf, end - buf);    if (rc < 0) return rc;    written += rc;  }  return written;}int filbuf(FILE *stream) {  if (stream->flag & _IOSTR) return EOF;  if (stream->flag & _IOWR) {    stream->flag |= _IOERR;    return EOF;  }  stream->flag |= _IORD;  // Get a buffer, if necessary.  if (!anybuf(stream)) {    getbuf(stream);  } else {    stream->ptr = stream->base;  }  stream->cnt = read(fileno(stream), stream->base, stream->bufsiz);  if (stream->cnt <= 0) {    stream->flag |= stream->cnt ? _IOERR : _IOEOF;    stream->cnt = 0;    return EOF;  }  stream->cnt--;  return *stream->ptr++ & 0xff;}int flsbuf(int ch, FILE *stream) {  int count;  int written;  int fh;  char chbuf;  fh = fileno(stream);  if (!(stream->flag & (_IOWR | _IORW)) || (stream->flag & _IOSTR)) {    stream->flag |= _IOERR;    return -1;  }  if (stream->flag & _IORD) {    stream->cnt = 0;    if (stream->flag & _IOEOF) {      stream->ptr = stream->base;      stream->flag &= ~_IORD;    } else {      stream->flag |= _IOERR;      return -1;    }  }  stream->flag |= _IOWR;  stream->flag &= ~_IOEOF;  written = count = stream->cnt = 0;  // Get a buffer for this stream, if necessary  if (!anybuf(stream)) getbuf(stream);  // If big buffer is assigned to stream  if (bigbuf(stream)) {    count = stream->ptr - stream->base;    stream->ptr = stream->base + 1;    stream->cnt = stream->bufsiz - 1;    if (count > 0) {      if (stream->flag & _IOCRLF) {        written = write_translated(fh, stream->base, count);      } else {        written = write(fh, stream->base, count);      }    }    *stream->base = (char) ch;  } else {    // Perform single character output (either _IONBF or no buffering)    count = 1;    chbuf = (char) ch;    if (stream->flag & _IOCRLF) {      written = write_translated(fh, &chbuf, count);    } else {      written = write(fh, &chbuf, count);    }  }  // See if the write was successful.  if (written != count) {    stream->flag |= _IOERR;    return -1;  }  return ch & 0xff;}/* 内部函数 open_file  * 作用:把流与文件关联*/ static int open_file(FILE *stream, const char *filename, const char *mode) {  int oflag;  int streamflag;   handle_t handle;  switch (*mode) {    case 'r':      oflag = O_RDONLY;      streamflag = _IORD;      break;    case 'w':      oflag = O_WRONLY | O_CREAT | O_TRUNC;      streamflag = _IOWR;      break;    case 'a':      oflag = O_WRONLY | O_CREAT | O_APPEND;      streamflag = _IOWR;      break;      default:      errno = EINVAL;      return -1;  }  while (*++mode) {    switch (*mode) {      case '+':        oflag |= O_RDWR;        oflag &= ~(O_RDONLY | O_WRONLY);        streamflag |= _IORW;        streamflag &= ~(_IORD | _IOWR);        break;      case 't':        oflag &= ~(O_TEXT | O_BINARY);        oflag |= O_TEXT;        break;      case 'b':        oflag &= ~(O_TEXT | O_BINARY);        oflag |= O_BINARY;        break;      case 'c':      case 'n':        break;      case 'S':        oflag |= O_SEQUENTIAL;        break;      case 'R':        oflag |= O_RANDOM;        break;      case 'T':        oflag |= O_SHORT_LIVED;        break;      case 'D':        oflag |= O_TEMPORARY;        break;      case ' ':        // Ignore        break;      default:        errno = EINVAL;        return -1;    }  }  /* 打开或新建  一个文件 unix 系统调用 */  handle = open(filename, oflag, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);  if (handle < 0) return -1;  stream->flag = streamflag;  stream->cnt = 0;  stream->base = stream->ptr = NULL;  stream->file = handle;//将open()的文件描述符传递给stream的文件描述符   stream->phndl = NOHANDLE;  return 0;}/* close_file 关闭流与文件的关联 * * */static int close_file(FILE *stream) {  int rc = EOF;  if (stream->flag & _IOSTR) {    stream->flag = 0;    return EOF;  }  rc = fflush(stream);  freebuf(stream);  if (close(fileno(stream)) < 0) rc = EOF;  return rc;}FILE *fdopen(int fd, const char *mode) {  FILE *stream;   int streamflag;  switch (*mode) {    case 'r':      streamflag = _IORD;      break;    case 'w':      streamflag = _IOWR;      break;    case 'a':      streamflag = _IOWR;      break;      default:      errno = EINVAL;      return NULL;  }  while (*++mode) {    switch (*mode) {      case '+':        streamflag |= _IORW;        streamflag &= ~(_IORD | _IOWR);        break;    }  }  stream = malloc(sizeof(FILE));  if (!stream) {    errno = ENFILE;    return NULL;  }  stream->flag = streamflag;  stream->cnt = 0;  stream->base = stream->ptr = NULL;  stream->file = fd;  stream->phndl = NOHANDLE;  return stream;}FILE *freopen(const char *filename, const char *mode, FILE *stream) {   if (inuse(stream)) close_file(stream);//参考46行   if (open_file(stream, filename, mode) < 0) { //参考261行  open_file()    free(stream);    return NULL;  }  return stream;}FILE *fopen(const char *filename, const char *mode) {  FILE *stream;  stream = malloc(sizeof(FILE));    //在堆中malloc一个流  if (!stream) {    errno = ENFILE;    return NULL;  }  /* 把流与文件关联 */  if (open_file(stream, filename, mode) < 0) {    free(stream);    return NULL;  }  return stream;}/* clearerr函数的作用是清除由stream * 指向的文件流的文件尾标识和错误标识。 * 它没有返回值,也未定义任何错误。 */void clearerr(FILE *stream) {  // Clear flags  stream->flag &= ~(_IOERR | _IOEOF);}/* 关闭文件函数 */int fclose(FILE *stream) {  int rc;  rc = close_file(stream);  free(stream);  return rc;}/* 清空流文件缓冲区*/int fflush(FILE *stream) {  int rc = 0;  int count;  int written;  if (!stream) stream = stdout;  if ((stream->flag & (_IORD | _IOWR)) == _IOWR &&       bigbuf(stream) &&       (count = stream->ptr - stream->base) > 0) {    if (stream->flag & _IOCRLF) {      written = write_translated(fileno(stream), stream->base, count);    } else {      written = write(fileno(stream), stream->base, count);    }    if (written == count)  {      // If this is a read/write file, clear _IOWR so that next operation can be a read      if (stream->flag & _IORW) stream->flag &= ~_IOWR;    } else {      stream->flag |= _IOERR;      rc = EOF;    }  }  stream->ptr = stream->base;  stream->cnt = 0;  return rc;}int fgetc(FILE *stream) {  return getc(stream);}int fputc(int c, FILE *stream) {  return putc(c, stream);}/* fgets 读进'\n' */char *fgets(char *string, int n, FILE *stream) {  char *ptr = string;  int ch;  if (n <= 0) return NULL;  while (--n) {    if ((ch = getc(stream)) == EOF) {      if (ptr == string) return NULL;      break;    }    if ((*ptr++ = ch) == '\n') break;  }  *ptr = '\0';  return string;}int fputs(const char *string, FILE *stream) {  int len;  int written;  len = strlen(string);  if (stream->flag & _IONBF) {    char buf[BUFSIZ];    _stbuf(stream, buf, BUFSIZ);    written = fwrite(string, 1, len, stream);    _ftbuf(stream);  } else {    written = fwrite(string, 1, len, stream);  }  return written == len ? 0 : EOF;}/*从stdin流中读取字符串, *直至接受到换行符或EOF时停止, *并将读取的结果存放在buf指针 *所指向的字符数组中。换行符不作为 *读取串的内容,读取的换行符被转换为null值 *并由此来结束字符串。 */char *gets(char *buf){  char *p = buf;  int ch;  while (1) {    ch = getchar();    if (ch == EOF) {      if (errno == ETIMEDOUT) continue;      return NULL;    }    if (ch == 8) {   // 8 ascii means backspace      if (p > buf) {        putchar('\b');        putchar(' ');        putchar('\b');        p--;      }    } else if (ch == '\r' || ch =='\n' || ch >= ' ') {      putchar(ch);      if (ch == '\r') putchar('\n');      if (ch == '\n' || ch == '\r') break;      *p++ = ch;    }  }  *p = 0;  return buf;}/*puts()函数用来向标准输出设备(屏幕) *写字符串并换行 */int puts(const char *string) {  FILE *stream = stdout;  if (stream->flag & _IONBF) {    char buf[BUFSIZ];    _stbuf(stream, buf, BUFSIZ);    while (*string) {      if (putchar(*string) == EOF) {        _ftbuf(stream);        return EOF;      }      string++;    }      if (putchar('\n') == EOF) {      _ftbuf(stream);      return EOF;    }    _ftbuf(stream);  } else {    while (*string) {      if (putchar(*string) == EOF) return EOF;      string++;    }      if (putchar('\n') == EOF) return EOF;  }  return 0;}size_t fread(void *buffer, size_t size, size_t num, FILE *stream) {  char *data;                     // Point to where should be read next  unsigned total;                 // Total bytes to read  unsigned count;                 // Num bytes left to read  unsigned bufsize;               // Size of stream buffer  unsigned nbytes;                // How much to read now  unsigned nread;                 // How much we did read  int c;                          // A temp char  // Initialize local vars  data = buffer;  if ((count = total = size * num) == 0) return 0;  if (anybuf(stream)) {    // Already has buffer, use its size    bufsize = stream->bufsiz;  } else {    // Assume will get BUFSIZ buffer    bufsize = BUFSIZ;  }  // Here is the main loop -- we go through here until we're done  while (count != 0) {    // if the buffer exists and has characters, copy them to user buffer    if (anybuf(stream) && stream->cnt != 0) {      // How much do we want?      nbytes = (count < (unsigned) stream->cnt) ? count : stream->cnt;      memcpy(data, stream->ptr, nbytes);      // Update stream and amount of data read      count -= nbytes;      stream->cnt -= nbytes;      stream->ptr += nbytes;      data += nbytes;    } else if (count >= bufsize) {      // If we have more than bufsize chars to read, get data      // by calling read with an integral number of bufsiz      // blocks.      // Calc chars to read -- (count / bufsize) * bufsize      nbytes = bufsize ? count - count % bufsize : count;      nread = read(fileno(stream), data, nbytes);      if (nread == 0) {        // End of file -- out of here        stream->flag |= _IOEOF;        return (total - count) / size;      } else if ((int) nread < 0) {        // Error -- out of here        stream->flag |= _IOERR;        return (total - count) / size;      }      // Update count and data to reflect read      count -= nread;      data += nread;    } else {      // Less than bufsize chars to read, so call filbuf to fill buffer      if ((c = filbuf(stream)) == EOF) {        // Error or eof, stream flags set by filbuf        return (total - count) / size;      }      // filbuf returned a char -- store it      *data++ = (char) c;      count--;      // Update buffer size      bufsize = stream->bufsiz;    }  }  // We finished successfully, so just return num  return num;}size_t fwrite(const void *buffer, size_t size, size_t num, FILE *stream) {  const char *data;               // Point to where data comes from next  unsigned total;                 // Total bytes to write  unsigned count;                 // Num bytes left to write  unsigned bufsize;               // Size of stream buffer  unsigned nbytes;                // Number of bytes to write now  unsigned nwritten;              // Number of bytes written  int c;                          // A temp char  // Initialize local vars  data = buffer;  count = total = size * num;  if (count == 0) return 0;  if (anybuf(stream)) {    // Already has buffer, use its size    bufsize = stream->bufsiz;  } else {    // Assume will get BUFSIZ buffer    bufsize = BUFSIZ;  }  // Here is the main loop -- we go through here until we're done  while (count != 0) {    // If the buffer is big and has room, copy data to buffer    if (bigbuf(stream) && stream->cnt != 0) {      // How much do we want?      nbytes = (count < (unsigned) stream->cnt) ? count : stream->cnt;      memcpy(stream->ptr, data, nbytes);      // Update stream and amount of data written      count -= nbytes;      stream->cnt -= nbytes;      stream->ptr += nbytes;      data += nbytes;    } else if (count >= bufsize) {      // If we have more than bufsize chars to write, write      // data by calling write with an integral number of      // bufsiz blocks.  If we reach here and we have a big      // buffer, it must be full so flush it.      if (bigbuf(stream)) {        if (fflush(stream)) {          // Error, stream flags set -- we're out of here          return (total - count) / size;        }      }      // Calc chars to write -- (count / bufsize) * bufsize      nbytes = bufsize ? (count - count % bufsize) : count;      if (stream->flag & _IOCRLF) {        nwritten = write_translated(fileno(stream), (char *) data, nbytes);      } else {        nwritten = write(fileno(stream), data, nbytes);      }      if ((int) nwritten < 0) {        // Error -- out of here        stream->flag |= _IOERR;        return (total - count) / size;      }      // Update count and data to reflect write      count -= nwritten;      data += nwritten;      if (nwritten < nbytes) {        // Error -- out of here        stream->flag |= _IOERR;        return (total - count) / size;      }    } else {      // Buffer full and not enough chars to do direct write, so do a flsbuf.      c = *data;        if (flsbuf(c, stream) == EOF) {        // Error or eof, stream flags set by _flsbuf        return (total - count) / size;      }      // flsbuf wrote a char -- update count      ++data;      --count;      // Update buffer size      bufsize = stream->bufsiz > 0 ? stream->bufsiz : 1;    }  }  // We finished successfully, so just return num  return num;}int fseek(FILE *stream, long offset, int whence) {  if (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END) {    errno = EINVAL;    return -1;  }  // Clear EOF flag  stream->flag &= ~_IOEOF;    // Adjust for prefetched data on relative seek.  if (whence == SEEK_CUR && (stream->flag & _IORD)) offset -= stream->cnt;    // Flush buffer as necessary  fflush(stream);  // If file opened for read/write, clear flags since we don't know  // what the user is going to do next.  if (stream->flag & _IORW) stream->flag &= ~(_IOWR | _IORD);  // Seek to the desired location and return  return lseek(fileno(stream), offset, whence) < 0 ? -1 : 0;}long ftell(FILE *stream) {  long filepos;  if (stream->cnt < 0) stream->cnt = 0;      if ((filepos = tell(fileno(stream))) < 0L) return -1;  if (!bigbuf(stream)) return filepos - stream->cnt;  if (stream->flag & _IORD) {    filepos -= stream->cnt;  } else if (stream->flag & _IOWR) {    filepos += (stream->ptr - stream->base);  }  return filepos;}void rewind(FILE *stream) {  fseek(stream, 0, SEEK_SET);  clearerr(stream);}int fsetpos(FILE *stream, const fpos_t *pos) {  return fseek(stream, *pos, SEEK_SET);}int fgetpos(FILE *stream, fpos_t *pos) {  long n;  n = ftell(stream);  if (n < 0) return n;  *pos = n;  return 0;}void perror(const char *message) {  fputs(message, stderr);  fputs(": ", stderr);  fputs(strerror(errno), stderr);  fputs("\n", stderr);}void setbuf(FILE *stream, char *buffer) {  if (buffer == NULL) {    setvbuf(stream, NULL, _IONBF, 0);  } else {    setvbuf(stream, buffer, _IOFBF, BUFSIZ);  }}int setvbuf(FILE *stream, char *buffer, int type, size_t size) {  fflush(stream);  freebuf(stream);  stream->flag &= ~(_IOOWNBUF | _IOEXTBUF | _IONBF);  if (type & _IONBF) {    stream->flag |= _IONBF;    buffer = (char *) &stream->charbuf;    size = 1;  } else if (buffer == NULL) {    if ((buffer = malloc(size)) == NULL ) return -1;    stream->flag |= _IOOWNBUF;  } else {    stream->flag |= _IOEXTBUF;  }  stream->bufsiz = size;  stream->ptr = stream->base = buffer;  stream->cnt = 0;  return 0;}int ungetc(int c, FILE *stream) {  // Stream must be open for read and can NOT be currently in write mode.  // Also, ungetc() character cannot be EOF.  if (c == EOF) return EOF;  if (!((stream->flag & _IORD) || ((stream->flag & _IORW) && !(stream->flag & _IOWR)))) return EOF;  // If stream is unbuffered, get one.  if (stream->base == NULL) getbuf(stream);  // Now we know base != NULL; since file must be buffered  if (stream->ptr == stream->base) {    if (stream->cnt) return EOF;    stream->ptr++;  }  if (stream->flag & _IOSTR) {    // If stream opened by sscanf do not modify buffer    if (*--stream->ptr != (char) c) {      ++stream->ptr;      return EOF;    }  } else {    *--stream->ptr = (char) c;  }  stream->cnt++;  stream->flag &= ~_IOEOF;  stream->flag |= _IORD;  return c & 0xff;}/* 删除文件  直接使用unlink系统调用*/int remove(const char *filename) {  return unlink(filename);}int fready(FILE *stream) {  struct pollfd pfd;  // Ready for read if there is anything in the buffer  if (stream->cnt > 0) return 1;  // String streams have all data in the buffer  if (stream->flag & _IOSTR) return 0;  // Must be in read mode  if (stream->flag & _IOWR) return 0;  // Poll input file for available data  pfd.fd = fileno(stream);  pfd.events = POLLIN;  pfd.revents = 0;  return poll(&pfd, 1, 0) > 0 && (pfd.revents & POLLIN);}


0 0
原创粉丝点击