struct _IO_FILE { int _flags; /* High-order word is _IO_MAGIC; rest is flags. */ #define _IO_file_flags _flags
/* The following pointers correspond to the C++ streambuf protocol. */ /* Note: Tk uses the _IO_read_ptr and _IO_read_end fields directly. */ char* _IO_read_ptr; /* Current read pointer */ char* _IO_read_end; /* End of get area. */ char* _IO_read_base; /* Start of putback+get area. */ char* _IO_write_base; /* Start of put area. */ char* _IO_write_ptr; /* Current put pointer. */ char* _IO_write_end; /* End of put area. */ char* _IO_buf_base; /* Start of reserve area. */ char* _IO_buf_end; /* End of reserve area. */ /* The following fields are used to support backing up and undo. */ char *_IO_save_base; /* Pointer to start of non-current get area. */ char *_IO_backup_base; /* Pointer to first valid character of backup area */ char *_IO_save_end; /* Pointer to end of non-current get area. */
struct _IO_marker *_markers;
struct _IO_FILE *_chain;
int _fileno; #if 0 int _blksize; #else int _flags2; #endif _IO_off_t _old_offset; /* This used to be _offset but it's too small. */
#define __HAVE_COLUMN /* temporary */ /* 1+column number of pbase(); 0 is unknown. */ unsignedshort _cur_column; signedchar _vtable_offset; char _shortbuf[1];//如果文件缓冲区是unbuffered(),则_shortbuf[1]用作缓冲区。
/* char* _save_gptr; char* _save_egptr; */
_IO_lock_t *_lock; #ifdef _IO_USE_OLD_IO_FILE };
struct _IO_FILE_complete { struct _IO_FILE _file; #endif #if defined _G_IO_IO_FILE_VERSION && _G_IO_IO_FILE_VERSION == 0x20001 _IO_off64_t _offset;// # if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T /* Wide character stream stuff. */ struct _IO_codecvt *_codecvt; struct _IO_wide_data *_wide_data; struct _IO_FILE *_freeres_list; void *_freeres_buf; # else void *__pad1; void *__pad2; void *__pad3; void *__pad4; # endif size_t __pad5; int _mode; //<=0为非宽字节,>0为宽字节 /* Make sure we don't get into trouble again. */ char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)]; #endif };
/* Magic number and bits for the _flags field. The magic number is mostly vestigial, but preserved for compatibility. It occupies the high 16 bits of _flags; the low 16 bits are actual flag bits. */
#define _IO_MAGIC 0xFBAD0000 /* Magic number 可以校验文件是否有效*/ #define _IO_MAGIC_MASK 0xFFFF0000//掩码,用于提取flag有效部分 #define _IO_USER_BUF 0x0001 /* Don't deallocate buffer on close. */ #define _IO_UNBUFFERED 0x0002//文件流处于无缓冲模式 #define _IO_NO_READS 0x0004 /* Reading not allowed.读文件流被禁止 */ #define _IO_NO_WRITES 0x0008 /* Writing not allowed.写文件流被禁止 */ #define _IO_EOF_SEEN 0x0010//文件流已经到达文件的末尾 #define _IO_ERR_SEEN 0x0020//文件流上发生了错误 #define _IO_DELETE_DONT_CLOSE 0x0040 /* Don't call close(_fileno) on close.执行文件删除操作时不关闭文件流 */ #define _IO_LINKED 0x0080 /* In the list of all open files. */ #define _IO_IN_BACKUP 0x0100//文件流正在执行备份操作 #define _IO_LINE_BUF 0x0200//文件流为行缓冲模式 #define _IO_TIED_PUT_GET 0x0400 /* Put and get pointer move in unison.关联put和get */ #define _IO_CURRENTLY_PUTTING 0x0800//文件流当前正在写入数据(往文件流中写入数据) #define _IO_IS_APPENDING 0x1000//文件流处于"追加模式" #define _IO_IS_FILEBUF 0x2000//标志表示流对象使用了文件缓冲,这意味着它与底层文件描述符相关联,可以用于标准文件操作,如读取和写入文件。 /* 0x4000 No longer used, reserved for compat. */ #define _IO_USER_LOCK 0x8000//表示用户已经为文件流提供了自定义的锁
#define CLOSED_FILEBUF_FLAGS (_IO_IS_FILEBUF+_IO_NO_READS+_IO_NO_WRITES+_IO_TIED_PUT_GET) Expands to: (0x2000+0x0004+0x0008+0x0400)
struct _IO_marker { struct _IO_marker *_next; FILE *_sbuf; /* If _pos >= 0 it points to _buf->Gbase()+_pos. FIXME comment */ /* if _pos < 0, it points to _buf->eBptr()+_pos. FIXME comment */ int _pos; };
struct _IO_FILE { int _flags; /* High-order word is _IO_MAGIC; rest is flags. */ #define _IO_file_flags _flags
/* The following pointers correspond to the C++ streambuf protocol. */ /* Note: Tk uses the _IO_read_ptr and _IO_read_end fields directly. */ char* _IO_read_ptr; /* Current read pointer */ char* _IO_read_end; /* End of get area. */ char* _IO_read_base; /* Start of putback+get area. */ char* _IO_write_base; /* Start of put area. */ char* _IO_write_ptr; /* Current put pointer. */ char* _IO_write_end; /* End of put area. */ char* _IO_buf_base; /* Start of reserve area. */ char* _IO_buf_end; /* End of reserve area. */ /* The following fields are used to support backing up and undo. */ char *_IO_save_base; /* Pointer to start of non-current get area. */ char *_IO_backup_base; /* Pointer to first valid character of backup area */ char *_IO_save_end; /* Pointer to end of non-current get area. */
struct _IO_marker *_markers;
struct _IO_FILE *_chain;
int _fileno; #if 0 int _blksize; #else int _flags2; #endif _IO_off_t _old_offset; /* This used to be _offset but it's too small. */
#define __HAVE_COLUMN /* temporary */ /* 1+column number of pbase(); 0 is unknown. */ unsignedshort _cur_column; signedchar _vtable_offset; char _shortbuf[1];
/* char* _save_gptr; char* _save_egptr; */
_IO_lock_t *_lock; #ifdef _IO_USE_OLD_IO_FILE }; //宏定义,如果宏_IO_USE_OLD_IO_FILE会把_IO_FILE拆成两个部分 struct _IO_FILE_complete { struct _IO_FILE _file; #endif #if defined _G_IO_IO_FILE_VERSION && _G_IO_IO_FILE_VERSION == 0x20001 _IO_off64_t _offset; # if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T /* Wide character stream stuff. */ struct _IO_codecvt *_codecvt; struct _IO_wide_data *_wide_data; struct _IO_FILE *_freeres_list; void *_freeres_buf; # else void *__pad1; void *__pad2; void *__pad3; void *__pad4; # endif size_t __pad5; int _mode; /* Make sure we don't get into trouble again. */ char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)]; #endif };
/* Check if unknown vtable pointers are permitted; otherwise, terminate the process. */ void _IO_vtable_check (void) attribute_hidden;
/* Perform vtable pointer validation. If validation fails, terminate the process. */ staticinlineconststruct _IO_jump_t * IO_validate_vtable(conststruct _IO_jump_t *vtable) { /* Fast path: The vtable pointer is within the __libc_IO_vtables section. */ uintptr_t section_length = __stop___libc_IO_vtables - __start___libc_IO_vtables; constchar *ptr = (constchar *) vtable; uintptr_t offset = ptr - __start___libc_IO_vtables; if (__glibc_unlikely (offset >= section_length)) /* The vtable pointer is not in the expected section. Use the slow path, which will terminate the process if necessary. */ _IO_vtable_check (); return vtable; }
/* In case this libc copy is in a non-default namespace, we always need to accept foreign vtables because there is always a possibility that FILE * objects are passed across the linking boundary. */ { Dl_info di; structlink_map *l; if (_dl_open_hook != NULL || (_dl_addr (_IO_vtable_check, &di, &l, NULL) != 0 && l->l_ns != LM_ID_BASE)) return; }
#else/* !SHARED */ /* We cannot perform vtable validation in the static dlopen case because FILE * handles might be passed back and forth across the boundary. Therefore, we disable checking in this case. */ if (__dlopen != NULL) return; #endif
__libc_fatal ("Fatal error: glibc detected an invalid stdio handle\n"); }
/* This is needed for the Irix6 N32 ABI, which has a 64 bit off_t type, but a 32 bit pointer type. In this case, we get 4 bytes of padding after the vtable pointer. Putting them in a structure together solves this problem. */