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
- C标准库stdio源码分析
- C标准库源码解剖(13):输入输出函数stdio.h
- C标准库源码解剖(13):输入输出函数stdio.h
- [C标准库] stdio.h
- C标准库学习stdio.h
- C语言标准库 - stdio.h
- C /C++标准库 - <cstdio>(stdio.h)
- C 标准库 —— stdio.h
- C语言标准库(2)--#include<stdio.h>
- [学习标准库]stdio.h
- C标准函数库(二)<stdio.h>
- C语言标准库概览详述[8]-标准IO<stdio.h>
- C语言stdio库(#include<stdio.h>)
- C标准库参考指南系列译文(12)stdio.h(A)
- 走进C标准库(2)——"stdio.h"中的fopen函数
- [学习标准库]IO命令--stdio.h
- C语言之常用标准输入输出函数库<stdio.h>
- C标准库实现分析
- 虚函数的理解
- GBDT(MART)概念简介
- Linux/Unix服务端和客户端Socket编程入门实例(含源码下载)
- test
- 自己动手开发编译器(六)上下文无关语言和文法
- C标准库stdio源码分析
- SQL分页实现
- Unix Networking Programming的源码编译问题
- Android之Broadcast详解
- html checked
- 第一次调试微信的Android版本出现的问题和解决方法
- struts2 jsp标签 学习笔记
- [factorytest]工厂测试软件,安装。
- 8天学习MongoDB——第一天 基础入门