Created
January 20, 2020 14:58
-
-
Save Pavlos1/d562ce3aa748d42e6c93df30fbf28dad to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* This file is a demonstration of the fact that, in POSIX, exclusive access | |
* to a file is dropped once all file descriptors that point to its "open file | |
* description" are closed. | |
* | |
* To compile: | |
* CC excl.c -o excl | |
* | |
* To run: | |
* ./excl <SERIAL DEVICE> both # both fds are closed; no error thrown | |
* ./excl <SERIAL DEVICE> one # only one fd is closed, EBUSY (errno=16) thrown | |
* ./excl <SERIAL DEVICE> neither # neither fd is closed, EBUSY (errno=16) thrown | |
*/ | |
#include <stdio.h> | |
#include <string.h> | |
#include <termios.h> | |
#include <sys/ioctl.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#include <errno.h> | |
#include <unistd.h> | |
#include <stdlib.h> | |
int main(int argc, char **argv) { | |
/* ===================== Setup ======================== */ | |
char *filename; | |
int close_original=0; | |
int close_dup=0; | |
if (argc > 1) { | |
filename = argv[1]; | |
} else { | |
filename = "/dev/ttyS0"; | |
} | |
if (argc > 2) { | |
if (strcmp(argv[2], "both") == 0) { | |
close_original=1; | |
close_dup=1; | |
} else if (strcmp(argv[2], "one") == 0) { | |
close_original=1; | |
close_dup=0; | |
} else { | |
close_original=0; | |
close_dup=0; | |
} | |
} | |
/* ======= Open file, create duplicate, get exclusive access =========== */ | |
int fd = open(filename, 0); | |
if (fd < 0) { | |
fprintf(stderr, "Failed to create initial file, errno=%d\n", errno); | |
exit(1); | |
} | |
if(ioctl(fd, TIOCEXCL) == -1) { | |
fprintf(stderr, "Failed to make file exclusive, errno=%d\n", errno); | |
exit(1); | |
} | |
int dup_fd = dup(fd); | |
if (dup_fd < 0) { | |
fprintf(stderr, "Failed to dup exclusive file, errno=%d\n", errno); | |
} | |
/* ============= Optionally close one or both fds (for experiment) ================== */ | |
if (close_original) { | |
if(close(fd)) { | |
fprintf(stderr, "Close failed (original), errno=%d\n", errno); | |
exit(1); | |
} | |
} | |
if (close_dup) { | |
if(close(dup_fd)) { | |
fprintf(stderr, "Close failed (dup), errno=%d\n", errno); | |
exit(1); | |
} | |
} | |
/* === Check whether opening the same file name fails (i.e. if it is still exclusive) === */ | |
int fd2 = open(filename, 0); | |
if (fd2 < 0) { | |
fprintf(stderr, "Failed to open file second time (as expected?), errno=%d\n", errno); | |
} | |
/* === Finally, verify that once we drop exclusive access that the file can be opened again === */ | |
if (!close_original) { | |
if(ioctl(fd, TIOCNXCL) == -1) { | |
fprintf(stderr, "Failed to make file un-exclusive (original), errno=%d\n", errno); | |
exit(1); | |
} | |
} | |
if (!close_dup) { | |
if(ioctl(dup_fd, TIOCNXCL) == -1) { | |
fprintf(stderr, "Failed to make file un-exclusive (duplicate), errno=%d\n", errno); | |
exit(1); | |
} | |
} | |
int fd3 = open(filename, 0); | |
if (fd3 < 0) { | |
fprintf(stderr, "Failed to open file third time, errno=%d\n", errno); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment