1/* 2 * Copyright 2008, Axel D��rfler, axeld@pinc-software.de. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7#include <fcntl.h> 8#include <errno.h> 9#include <stdio.h> 10#include <stdlib.h> 11#include <string.h> 12#include <unistd.h> 13 14 15extern const char *__progname; 16 17const char* kTemporaryFile = "/tmp/axels-lock-test"; 18 19 20const char* 21type_name(int type) 22{ 23 return type == F_RDLCK ? "shared" : type == F_WRLCK 24 ? "exclusive" : "remove"; 25} 26 27 28int 29do_lock(int fd, int type, off_t start, off_t length) 30{ 31 printf("%s lock %lld:%lld\n", type_name(type), start, length); 32 33 struct flock flock; 34 flock.l_type = type; 35 flock.l_whence = SEEK_SET; 36 flock.l_start = start; 37 flock.l_len = length; 38 if (fcntl(fd, F_SETLK, &flock) != 0) { 39 fprintf(stderr, "ERROR: %s lock %lld:%lld failed: %s\n", type_name(type), 40 start, length, strerror(errno)); 41 return -1; 42 } 43 44 return 0; 45} 46 47 48int 49shared_lock(int fd, off_t start, off_t length) 50{ 51 return do_lock(fd, F_RDLCK, start, length); 52} 53 54 55int 56exclusive_lock(int fd, off_t start, off_t length) 57{ 58 return do_lock(fd, F_WRLCK, start, length); 59} 60 61 62int 63remove_lock(int fd, off_t start, off_t length) 64{ 65 return do_lock(fd, F_UNLCK, start, length); 66} 67 68 69void 70wait_for_enter() 71{ 72 puts("wait for <enter>..."); 73 char buffer[64]; 74 fgets(buffer, sizeof(buffer), stdin); 75} 76 77 78void 79usage() 80{ 81 fprintf(stderr, "usage: %s [shared|exclusive|unlock <start> <length>] " 82 "[wait] [...]\n", __progname); 83 exit(1); 84} 85 86 87bool 88is_command(const char* op, const char* command1, const char* command2) 89{ 90 int length = strlen(op); 91 if (length == 0) 92 return false; 93 94 return command1 != NULL && !strncmp(op, command1, length) 95 || command2 != NULL && !strncmp(op, command2, length); 96} 97 98 99int 100main(int argc, char** argv) 101{ 102 int fd = open(kTemporaryFile, O_CREAT | O_RDWR, 0644); 103 if (fd < 0) { 104 fprintf(stderr, "Could not create lock file: %s\n", strerror(errno)); 105 return 1; 106 } 107 108 while (argc > 1) { 109 const char* op = argv[1]; 110 if (is_command(op, "wait", NULL)) { 111 wait_for_enter(); 112 argv++; 113 argc--; 114 continue; 115 } 116 if (argc < 3) 117 usage(); 118 119 off_t start = strtoll(argv[2], NULL, 0); 120 off_t length = strtoll(argv[3], NULL, 0); 121 int type = 0; 122 if (is_command(op, "read", "shared")) 123 type = F_RDLCK; 124 else if (is_command(op, "write", "exclusive")) 125 type = F_WRLCK; 126 else if (is_command(op, "unlock", "remove")) 127 type = F_UNLCK; 128 else 129 usage(); 130 131 do_lock(fd, type, start, length); 132 argc -= 3; 133 argv += 3; 134 } 135 136 close(fd); 137 return 0; 138} 139 140