/* is_writeable.c - demonstrate use of fcntl to query FILE * writeability * Andrew Ho (andrew@zeuscat.com) * * In a C API that takes a FILE *, you sometimes need to know whether * that FILE * is opened for reading, writing or both. The F_GETFL * argument to fcntl() gives you this. Unclear documentation is here: * * http://www.gnu.org/software/libc/manual/html_node/Getting-File-Status-Flags.html * http://www.gnu.org/software/libc/manual/html_node/Access-Modes.html * * Build: gcc -Wall -o is_writeable is_writeable.c * Usage: is_writeable */ #include #include /* returns true if fh was opened as O_WRONLY or O_RDWR, see fcntl(2) */ int fh_is_writeable(FILE *fh) { int accmode = O_ACCMODE & fcntl(fileno(fh), F_GETFL); return accmode == O_WRONLY || accmode == O_RDWR ? 1 : 0; } int main(int argc, char **argv) { char wronly_fn[L_tmpnam], rdwr_fn[L_tmpnam]; FILE *rdonly, *wronly, *rdwr; /* open tempfiles in each of O_RDONLY, O_WRONLY, O_RDWR */ if(!(rdonly = fopen("/etc/hosts", "r"))) { perror("could not open /etc/hosts for reading"); return 1; } if(!tmpnam(wronly_fn)) { fprintf(stderr, "could not create temporary filename\n"); return 1; } if(!(wronly = fopen(wronly_fn, "w"))) { fprintf(stderr, "could not open %s for writing: ", wronly_fn); perror(NULL); return 1; } if(!tmpnam(rdwr_fn)) { fprintf(stderr, "could not create temporary filename\n"); return 1; } if(!(rdwr = fopen(rdwr_fn, "w+"))) { fprintf(stderr, "could not open %s for update: ", rdwr_fn); perror(NULL); return 1; } /* for debugging, confirm constant values from fcntl.h */ fprintf( stderr, "O_RDONLY = 0x%04x, O_WRONLY = 0x%04x, O_RDWR = 0x%04x\n", O_RDONLY, O_WRONLY, O_RDWR ); /* display fh_is_writeable() status for each of stdio filehandles */ fprintf( stderr, "stdin (%d) = %d, stdout (%d) = %d, stderr (%d) = %d\n", fileno(stdin), fh_is_writeable(stdin), fileno(stdout), fh_is_writeable(stdout), fileno(stderr), fh_is_writeable(stderr) ); /* display fh_is_writeable() status for each filehandle we opened */ fprintf( stderr, "rdonly (%d) = %d, wronly (%d) = %d, rdwr (%d) = %d\n", fileno(rdonly), fh_is_writeable(rdonly), fileno(wronly), fh_is_writeable(wronly), fileno(rdwr), fh_is_writeable(rdwr) ); /* clean up and exit */ fclose(rdonly); fclose(wronly); fclose(rdwr); return 0; }