fileno is used to get the file descriptor of given file stream
definition:
ubuntu@ip-172-31-23-227:~$ less /usr/include/stdio.h
......
/* Return the system file descriptor for STREAM. */
extern int fileno (FILE *__stream) __THROW __wur;
......
fileio.c:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main(int argc, char* argv[])
{
FILE* fp;
if((fp = fopen("test.txt", "w+")) == NULL) {
printf("fopen error!\n");
exit(1);
}
printf("file descriptor: %d\n", fileno(fp));
exit(0);
}
shell:
ubuntu@ip-172-31-23-227:~$ ./io.out
file descriptor: 3
2. FILE struct implementation
ubuntu@ip-172-31-23-227:~$ less /usr/include/libio.h
......
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. */
unsigned short _cur_column;
signed char _vtable_offset;
char _shortbuf[1];
/* char* _save_gptr; char* _save_egptr; */
_IO_lock_t *_lock;
#ifdef _IO_USE_OLD_IO_FILE
};
......
ubuntu@ip-172-31-23-227:~$ less /usr/include/stdio.h
......
typedef struct _IO_FILE FILE;
......
3. Get the buffer information of file stream
We will use _IO_file_flags and _IO_UNBUFFERED, _IO_LINE_BUF to detect the buffer type of file stream. We also will use _IO_buf_end, _IO_buf_base to detect the buffer size of the file stream.
fileio.c:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
void pr_stdio(const char* name, FILE* fp)
{
printf("stream = %s.", name);
if(fp -> _IO_file_flags & _IO_UNBUFFERED) {
printf("unbuffered");
} else if(fp -> _IO_file_flags & _IO_LINE_BUF) {
printf("line buffered");
} else {
printf("fully buffered");
}
printf(", buffer size = %ld\n", fp -> _IO_buf_end - fp -> _IO_buf_base);
}
int main(int argc, char* argv[])
{
FILE *fp;
fputs("test line at standard output.\n", stdout);
fputs("test line at standard error.\n", stderr);
// Test the stream buffer for standard input/output/error
pr_stdio("stdin", stdin);
pr_stdio("stdout", stdout);
pr_stdio("stderr", stderr);
if((fp = fopen("test.txt", "w+")) == NULL) {
printf("fopen error!\n");
exit(1);
}
// Test the stream buffer of open file "test.txt"
pr_stdio("test.txt", fp);
// change the buffer
char buf[BUFSIZ];
setvbuf(fp, buf, _IOFBF, BUFSIZ);
printf("after changing the buffer to %d\n", BUFSIZ);
pr_stdio("test.txt", fp);
exit(0);
}
shell:
ubuntu@ip-172-31-23-227:~$ ./io.out
test line at standard output.
test line at standard error.
stream = stdin.fully buffered, buffer size = 0
stream = stdout.line buffered, buffer size = 1024
stream = stderr.unbuffered, buffer size = 1
stream = test.txt.fully buffered, buffer size = 0
after changing the buffer to 8192
stream = test.txt.fully buffered, buffer size = 8192