/* Filename = Locktest2.c 071309 - Added revision information to usage(), and ERROR! to all error functions. */ #include #include #include #include #include #include static void usage(void) { printf("Locktest2 version 1.0\n"); printf("usage: -f filename [-B]\n"); printf("usage: --file filename [--block]\n"); } #define MAX_LOCKS 32 static int lock[MAX_LOCKS]; static void random_action(int fd, int blocking) { unsigned int act; struct flock fl; int opt; act = ((unsigned long)random()) % MAX_LOCKS; if (lock[act]) { fl.l_type = F_UNLCK; } else { fl.l_type = (random()%2) ? F_RDLCK : F_WRLCK; } /* * Appy the lock */ fl.l_whence = SEEK_SET; fl.l_start = act*10; fl.l_len = 10; opt = fcntl(fd, blocking ? F_SETLKW : F_SETLK, &fl); if (opt < 0) { if (EAGAIN == errno) { printf("?"); fflush(stdout); exit(4); } perror("fcntl"); usage(); exit(3); } if (lock[act]) { lock[act] = 0; } else { lock[act] = 1; } } static void excess_type(void) { printf("ERROR! More than one locking type parameter supplied.\n"); } static void insufficient_type(void) { printf("ERROR! No locking type parameter supplied.\n"); } static void excess_start(void) { printf("ERROR! More than one start for locking range supplied.\n"); } static void insufficient_start(void) { printf("ERROR! No start for locking range supplied.\n"); } static void excess_end(void) { printf("ERROR! More than one end for locking range supplied.\n"); } static void insufficient_end(void) { printf("ERROR! No end for locking range supplied.\n"); } static void excess_file(void) { printf("ERROR! More than one target file supplied.\n"); } static void insufficient_file(void) { printf("ERROR! No target file supplied.\n"); } static void get_val(int *val_set, int *val_var, int value, void (*excess)(void)) { if (*val_set) { excess(); usage(); exit(1); } *val_set = 1; *val_var = value; } static void get_num(int *val_set, int *val_var, char *value, void (*excess)(void)) { long temp; char *end; if (*val_set) { excess(); usage(); exit(1); } temp = strtol(value, &end, 0); if ('\0' == *value || NULL == end || '\0' != *end) { printf("Parameter \"%s\" should be a number\n", value); usage(); exit(1); } *val_set = 1; *val_var = temp; } static char options[] = "f:B"; static struct option long_options[] = { { "file", required_argument, NULL, 'f'}, { "block", no_argument, NULL, 'B'}, { NULL, 0, NULL, 0 }, }; int main(int argc, char **argv) { int opt; int start, start_set; int length, length_set; int end, end_set; int type, type_set; int blocking; int count; int rows; char *filename; int filename_set; int fd; struct flock fl; /* * Get arguments */ blocking = 0; start_set = length_set = end_set = type_set = filename_set = 0; while ((opt = getopt_long(argc, argv, options, long_options, NULL)) != -1) { switch (opt) { case 'f': if (filename_set) { excess_file(); usage(); exit(1); } filename_set = 1; filename = optarg; break; case 'B': blocking = 1; break; default: usage(); exit(1); } } /* * Check arguments for consistency */ if (!filename_set) { insufficient_file(); usage(); exit(1); } /* * Open the file */ fd = open(filename, O_RDWR); if (fd < 0) { perror(filename); usage(); exit(2); } count = 0; rows = 0; printf("%4d ", rows); while (1) { random_action(fd, blocking); count++; if (0 == (count % 100)) { printf("#"); fflush(stdout); } if (0 == (count % 6000)) { printf("\n"); count = 0; rows++; printf("%4d ", rows); } } exit(0); }