Skip to content

Instantly share code, notes, and snippets.

@Pavlos1
Created January 20, 2020 14:58
Show Gist options
  • Save Pavlos1/d562ce3aa748d42e6c93df30fbf28dad to your computer and use it in GitHub Desktop.
Save Pavlos1/d562ce3aa748d42e6c93df30fbf28dad to your computer and use it in GitHub Desktop.
/*
* 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