int main(int argc, char *argv[]) { int fd, numRead, cmd, status; char lock, cmdCh, whence, line[MAX_LINE]; struct flock fl; long long len, st; int *fdList; int fileNum, j; if (argc < 2 || strcmp(argv[1], "--help") == 0) usageErr("%s file...\n", argv[0]); fdList = calloc(argc, sizeof(int)); if (fdList == NULL) errExit("calloc"); for (j = 1; j < argc; j++) { fdList[j] = open(argv[j], O_RDWR); if (fdList[j] == -1) errExit("open (%s)", argv[j]); } /* Inform user what type of locking is in effect for each file. */ printf("File Locking\n"); printf("---- -------\n"); for (j = 1; j < argc; j++) printf("%-10s %s\n", argv[j], mandLockingEnabled(fdList[j]) ? "mandatory" : "advisory"); printf("\n"); printf("Enter ? for help\n"); for (;;) { /* Prompt for locking command and carry it out */ printf("PID=%ld> ", (long) getpid()); fflush(stdout); if (fgets(line, MAX_LINE, stdin) == NULL) /* EOF */ exit(EXIT_SUCCESS); line[strlen(line) - 1] = '\0'; /* Remove trailing '\n' */ if (*line == '\0') continue; /* Skip blank lines */ if (line[0] == '?') { displayCmdFmt(argc, argv, fdList); continue; } whence = 's'; /* In case not otherwise filled in */ if (argc == 2) { /* Just 1 file arg on command line? */ fileNum = 1; /* Then no need to read a file number */ numRead = sscanf(line, " %c %c %lld %lld %c", &cmdCh, &lock, &st, &len, &whence); } else { numRead = sscanf(line, "%d %c %c %lld %lld %c", &fileNum, &cmdCh, &lock, &st, &len, &whence); } fl.l_start = st; fl.l_len = len; if (fileNum < 1 || fileNum >= argc) { printf("File number must be in range 1 to %d\n", argc-1); continue; } fd = fdList[fileNum]; if (!((numRead >= 4 && argc == 2) || (numRead >= 5 && argc > 2)) || strchr("gswGSW", cmdCh) == NULL || strchr("rwu", lock) == NULL || strchr("sce", whence) == NULL) { printf("Invalid command!\n"); continue; } cmd = #ifdef __linux__ (cmdCh == 'G') ? F_OFD_GETLK : (cmdCh == 'S') ? F_OFD_SETLK : (cmdCh == 'W') ? F_OFD_SETLKW : #endif (cmdCh == 'g') ? F_GETLK : (cmdCh == 's') ? F_SETLK : F_SETLKW; #ifdef __linux__ fl.l_pid = 0; /* Required for 'OFD' locking commands */ #endif fl.l_type = (lock == 'r') ? F_RDLCK : (lock == 'w') ? F_WRLCK : F_UNLCK; fl.l_whence = (whence == 'c') ? SEEK_CUR : (whence == 'e') ? SEEK_END : SEEK_SET; status = fcntl(fd, cmd, &fl); /* Perform request... */ if (cmd == F_GETLK #ifdef __linux__ || cmd == F_OFD_GETLK #endif ) { if (status == -1) { errMsg("fcntl"); } else { if (fl.l_type == F_UNLCK) printf("[PID=%ld] Lock can be placed\n", (long) getpid()); else /* Locked out by someone else */ printf("[PID=%ld] Denied by %s lock on %lld:%lld " "(held by PID %ld)\n", (long) getpid(), (fl.l_type == F_RDLCK) ? "READ" : "WRITE", (long long) fl.l_start, (long long) fl.l_len, (long) fl.l_pid); } } else { if (status == 0) printf("[PID=%ld] %s\n", (long) getpid(), (lock == 'u') ? "unlocked" : "got lock"); else if (errno == EAGAIN || errno == EACCES) printf("[PID=%ld] failed (incompatible lock)\n", (long) getpid()); else if (errno == EDEADLK) /* F_SETLKW */ printf("[PID=%ld] failed (deadlock)\n", (long) getpid()); else errMsg("fcntl"); } } }
int main(int argc, char *argv[]) { int fd, numRead, cmd, status; char lock, cmdCh, whence, line[MAX_LINE]; struct flock fl; long long len, st; if (argc != 2 || strcmp(argv[1], "--help") == 0) usageErr("%s file\n", argv[0]); fd = open(argv[1], O_RDWR); if (fd == -1) errExit("open (%s)", argv[1]); printf("Enter ? for help\n"); for (;;) { /* Prompt for locking command and carry it out */ printf("PID=%ld> ", (long) getpid()); fflush(stdout); if (fgets(line, MAX_LINE, stdin) == NULL) /* EOF */ exit(EXIT_SUCCESS); line[strlen(line) - 1] = '\0'; /* Remove trailing '\n' */ if (*line == '\0') continue; /* Skip blank lines */ if (line[0] == '?') { displayCmdFmt(); continue; } whence = 's'; /* In case not otherwise filled in */ numRead = sscanf(line, "%c %c %lld %lld %c", &cmdCh, &lock, &st, &len, &whence); fl.l_start = st; fl.l_len = len; if (numRead < 4 || strchr("gsw", cmdCh) == NULL || strchr("rwu", lock) == NULL || strchr("sce", whence) == NULL) { printf("Invalid command!\n"); continue; } cmd = (cmdCh == 'g') ? F_GETLK : (cmdCh == 's') ? F_SETLK : F_SETLKW; fl.l_type = (lock == 'r') ? F_RDLCK : (lock == 'w') ? F_WRLCK : F_UNLCK; fl.l_whence = (whence == 'c') ? SEEK_CUR : (whence == 'e') ? SEEK_END : SEEK_SET; status = fcntl(fd, cmd, &fl); /* Perform request... */ if (cmd == F_GETLK) { /* ... and see what happened */ if (status == -1) { errMsg("fcntl - F_GETLK"); } else { if (fl.l_type == F_UNLCK) printf("[PID=%ld] Lock can be placed\n", (long) getpid()); else /* Locked out by someone else */ printf("[PID=%ld] Denied by %s lock on %lld:%lld " "(held by PID %ld)\n", (long) getpid(), (fl.l_type == F_RDLCK) ? "READ" : "WRITE", (long long) fl.l_start, (long long) fl.l_len, (long) fl.l_pid); } } else { /* F_SETLK, F_SETLKW */ if (status == 0) printf("[PID=%ld] %s\n", (long) getpid(), (lock == 'u') ? "unlocked" : "got lock"); else if (errno == EAGAIN || errno == EACCES) /* F_SETLK */ printf("[PID=%ld] failed (incompatible lock)\n", (long) getpid()); else if (errno == EDEADLK) /* F_SETLKW */ printf("[PID=%ld] failed (deadlock)\n", (long) getpid()); else errMsg("fcntl - F_SETLK(W)"); } } }