diff --git a/test/zdtm.sh b/test/zdtm.sh index 2bddcb54f..86003596e 100755 --- a/test/zdtm.sh +++ b/test/zdtm.sh @@ -117,6 +117,7 @@ static/file_locks00 static/file_locks01 static/file_locks02 static/file_locks03 +static/file_locks04 static/sigpending static/sigaltstack static/sk-netlink diff --git a/test/zdtm/live/static/Makefile b/test/zdtm/live/static/Makefile index fb3d9c059..f5adcad83 100644 --- a/test/zdtm/live/static/Makefile +++ b/test/zdtm/live/static/Makefile @@ -151,6 +151,7 @@ TST_FILE = \ file_locks01 \ file_locks02 \ file_locks03 \ + file_locks04 \ netns-nf \ maps_file_prot \ diff --git a/test/zdtm/live/static/file_locks04.c b/test/zdtm/live/static/file_locks04.c new file mode 100644 index 000000000..9d6aa9040 --- /dev/null +++ b/test/zdtm/live/static/file_locks04.c @@ -0,0 +1,119 @@ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include + +#include "zdtmtst.h" + +const char *test_doc = "Check that 'overlapping' flocks work"; +const char *test_author = "Pavel Emelyanov "; + +char *filename; +TEST_OPTION(filename, string, "file name", 1); + +static int check_file_locks(int alt_pid, int fd) +{ + FILE *fp_locks = NULL; + char buf[100], fl_flag[16], fl_type[16], fl_option[16]; + pid_t pid = getpid(); + int found = 0, num, fl_owner; + + fp_locks = fopen("/proc/locks", "r"); + if (!fp_locks) + return -1; + + while (fgets(buf, sizeof(buf), fp_locks)) { + if (strstr(buf, "->")) + continue; + + num = sscanf(buf, + "%*d:%s %s %s %d %*02x:%*02x:%*d %*d %*s", + fl_flag, fl_type, fl_option, &fl_owner); + + if (num < 4) { + err("Invalid lock info.\n"); + break; + } + + if (fl_owner != pid && fl_owner != alt_pid) + continue; + + if (!strcmp(fl_flag, "FLOCK") && + !strcmp(fl_type, "ADVISORY") && + !strcmp(fl_option, "WRITE")) + found++; + + memset(fl_flag, 0, sizeof(fl_flag)); + memset(fl_type, 0, sizeof(fl_type)); + memset(fl_option, 0, sizeof(fl_option)); + } + + fclose(fp_locks); + + if (flock(fd, LOCK_EX | LOCK_NB) == 0) + return 0; + + return found == 1; +} + +int main(int argc, char **argv) +{ + int fd, pf[2], pid; + + test_init(argc, argv); + + pipe(pf); + + fd = open(filename, O_CREAT | O_RDWR, 0600); + if (fd < 0) { + err("No file"); + return -1; + } + + flock(fd, LOCK_EX); + + pid = fork(); + if (pid == 0) { + close(pf[1]); + read(pf[0], &pid, sizeof(pid)); + exit(0); + } + + close(pf[0]); + close(fd); + + fd = open(filename, O_RDONLY); + if (fd < 0) { + err("No file 2"); + close(pf[1]); + waitpid(pid, NULL, 0); + return -1; + } + + if (flock(fd, LOCK_EX | LOCK_NB) == 0) { + err("Bogus locks"); + close(pf[1]); + waitpid(pid, NULL, 0); + return -1; + } + + test_daemon(); + test_waitsig(); + + if (check_file_locks(pid, fd)) + pass(); + else + fail("Flock file locks check failed"); + + close(pf[1]); + waitpid(pid, NULL, 0); + close(fd); + unlink(filename); + + return 0; +} diff --git a/test/zdtm/live/static/file_locks04.opts b/test/zdtm/live/static/file_locks04.opts new file mode 100644 index 000000000..738083ade --- /dev/null +++ b/test/zdtm/live/static/file_locks04.opts @@ -0,0 +1 @@ +--file-locks