F_GETFL and F_SETFL commands can be used to get and set the file status flags.
fileio.c:
It get the file status flags and do the bit operation with O_ACCMODE and other flags to get the real flag name.
#include<unistd.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
int main(int argc, char *argv[])
{
int val;
// Convert the first argument to int, which is the file descriptor
if((val = fcntl(atoi(argv[1]), F_GETFL)) < 0) {
printf("fcntl error!\n");
exit(1);
}
// Map val with O_ACCMODE, to check what is the mode
switch(val & O_ACCMODE) {
case O_RDONLY:
printf("read only!\n");
break;
case O_WRONLY:
printf("write only!\n");
break;
case O_RDWR:
printf("read write!\n");
break;
default:
printf("unknown mode!\n");
break;
}
// Map with O_APPEND, O_NONBLOCK, O_SYNC and O_FSYNCx
if(val & O_APPEND)
printf(" append!\n");
if(val & O_NONBLOCK)
printf(" nonblock!\n");
if(val & O_SYNC)
printf(" synchronos writes!\n");
if(val & O_FSYNC)
printf(" file synchronos writes!\n");
exit(0);
}
shell:
1) Open the file /dev/tty as the standard input, and program detect it as read only
2) Open the file /dev/tty as the standard output, and program detect it as write only
3) Open the file test.txt as the standard error, and also specify ">>" to indicate that program will append to the file. So finally it is write only and append
4) Open the file test.txt as the file descriptor 5, and also specify "<>" to indicate that program can read or write to the file. So finally it is read write
ubuntu@ip-172-31-23-227:~$ ./io.out 0 </dev/tty
read only!
ubuntu@ip-172-31-23-227:~$ ./io.out 1 >/dev/tty
write only!
ubuntu@ip-172-31-23-227:~$ ./io.out 2 2>>test.txt
write only!
append!
ubuntu@ip-172-31-23-227:~$ ./io.out 5 5<>test.txt
read write!
bit operation explanation:
O_ACCMODE is defined as 3, binary format: 11.
O_RDONLY: 0, O_WRONLY: 1, O_RDWR: 2(binary format: 10)
So using O_ACCMODE to "&" with flag, will turn off all other bits but only leaving one of above 3 bits.
Similar for O_APPEND, O_SYNC, O_NONBLOCK, only one bit is 1, all others are 0. By "& with" the flag, it will test if the bit is on.
ubuntu@ip-172-31-23-227:~$ sudo find /usr/include -name *.h | xargs grep O_ACCMODE
/usr/include/asm-generic/fcntl.h:#define O_ACCMODE 00000003
/usr/include/x86_64-linux-gnu/bits/fcntl-linux.h:#define O_ACCMODE 0003
2. Change the file status flag
fileio.c:
Retrieve the file status flag and then turn on another bit: O_SYNC.
#include<unistd.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
int main(int argc, char *argv[])
{
int val;
int flag = O_SYNC;
// Convert the first argument to int, which is the file descriptor
// Get the flag of specified file descriptor
if((val = fcntl(atoi(argv[1]), F_GETFL)) < 0) {
printf("fcntl error!\n");
exit(1);
}
// Turn on the O_SYNC bit on existing flag
val |= flag;
// Set up the flag on specified file descriptor
if((val = fcntl(atoi(argv[1]), F_SETFL, flag)) < 0) {
printf("fcntl error!\n");
exit(2);
}
exit(0);
}
O_SYNC and system calls: fsync, fdatasync, sync are very similar. But for some system, it doesn't respect the O_SYNC flag, but only those system calls.
No comments:
Post a Comment