| /* |
| * |
| * Copyright (c) International Business Machines Corp., 2001 |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See |
| * the GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| /* |
| * NAME |
| * fcntl21.c |
| * |
| * DESCRIPTION |
| * Check locking of regions of a file |
| * |
| * ALGORITHM |
| * Test changing lock sections around a read lock |
| * |
| * USAGE |
| * fcntl21 |
| * |
| * HISTORY |
| * 07/2001 Ported by Wayne Boyer |
| * |
| * RESTRICTIONS |
| * None |
| */ |
| |
| #include <fcntl.h> |
| #include <errno.h> |
| #include <signal.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <sys/wait.h> |
| #include <inttypes.h> |
| #include "test.h" |
| #include "usctest.h" |
| |
| #define STRINGSIZE 27 |
| #define STRING "abcdefghijklmnopqrstuvwxyz\n" |
| #define STOP 0xFFF0 |
| |
| int parent_pipe[2]; |
| int child_pipe[2]; |
| int fd; |
| pid_t parent_pid, child_pid; |
| |
| void parent_put(); |
| void parent_get(); |
| void child_put(); |
| void child_get(); |
| void stop_child(); |
| void compare_lock(struct flock *, short, short, int, int, pid_t); |
| void unlock_file(); |
| void do_test(struct flock *, short, short, int, int); |
| void catch_child(); |
| char *str_type(); |
| int do_lock(int, short, short, int, int); |
| |
| char *TCID = "fcntl21"; |
| int TST_TOTAL = 1; |
| |
| void setup(void); |
| void cleanup(void); |
| int fail; |
| |
| /* |
| * setup |
| * performs all ONE TIME setup for this test |
| */ |
| void setup() |
| { |
| char *buf = STRING; |
| char template[PATH_MAX]; |
| struct sigaction act; |
| |
| tst_sig(FORK, DEF_HANDLER, cleanup); |
| |
| umask(0); |
| |
| TEST_PAUSE; |
| |
| pipe(parent_pipe); |
| pipe(child_pipe); |
| parent_pid = getpid(); |
| |
| tst_tmpdir(); |
| |
| snprintf(template, PATH_MAX, "fcntl21XXXXXX"); |
| |
| if ((fd = mkstemp(template)) < 0) { |
| tst_resm(TFAIL, "Couldn't open temp file! errno = %d", errno); |
| } |
| |
| if (write(fd, buf, STRINGSIZE) < 0) { |
| tst_resm(TFAIL, "Couldn't write to temp file! errno = %d", |
| errno); |
| } |
| |
| memset(&act, 0, sizeof(act)); |
| act.sa_handler = catch_child; |
| sigemptyset(&act.sa_mask); |
| sigaddset(&act.sa_mask, SIGCLD); |
| if ((sigaction(SIGCLD, &act, NULL)) < 0) { |
| tst_resm(TFAIL, "SIGCLD signal setup failed, errno: %d", errno); |
| fail = 1; |
| } |
| } |
| |
| /* |
| * cleanup() |
| * performs all ONE TIME cleanup for this test at completion or |
| * premature exit |
| */ |
| void cleanup() |
| { |
| /* |
| * print timing stats if that option was specified |
| * print errno log if that option was specified |
| */ |
| TEST_CLEANUP; |
| |
| tst_rmdir(); |
| |
| } |
| |
| void do_child() |
| { |
| struct flock fl; |
| |
| close(parent_pipe[1]); |
| close(child_pipe[0]); |
| while (1) { |
| child_get(&fl); |
| if (fcntl(fd, F_GETLK, &fl) < 0) { |
| tst_resm(TFAIL, "fcntl on file failed, errno =%d", |
| errno); |
| fail = 1; |
| } |
| child_put(&fl); |
| } |
| } |
| |
| int do_lock(int cmd, short type, short whence, int start, int len) |
| { |
| struct flock fl; |
| |
| fl.l_type = type; |
| fl.l_whence = whence; |
| fl.l_start = start; |
| fl.l_len = len; |
| return (fcntl(fd, cmd, &fl)); |
| } |
| |
| void do_test(struct flock *fl, short type, short whence, int start, int len) |
| { |
| fl->l_type = type; |
| fl->l_whence = whence; |
| fl->l_start = start; |
| fl->l_len = len; |
| fl->l_pid = (short)0; |
| |
| parent_put(fl); |
| parent_get(fl); |
| } |
| |
| void |
| compare_lock(struct flock *fl, short type, short whence, int start, int len, |
| pid_t pid) |
| { |
| if (fl->l_type != type) { |
| tst_resm(TFAIL, "lock type is wrong should be %s is %s", |
| str_type(type), str_type(fl->l_type)); |
| fail = 1; |
| } |
| |
| if (fl->l_whence != whence) { |
| tst_resm(TFAIL, "lock whence is wrong should be %d is %d", |
| whence, fl->l_whence); |
| fail = 1; |
| } |
| |
| if (fl->l_start != start) { |
| tst_resm(TFAIL, "region starts in wrong place, should be" |
| "%d is %"PRId64, start, (int64_t)fl->l_start); |
| fail = 1; |
| } |
| |
| if (fl->l_len != len) { |
| tst_resm(TFAIL, "region length is wrong, should be %d is %"PRId64, |
| len, (int64_t)fl->l_len); |
| fail = 1; |
| } |
| |
| if (fl->l_pid != pid) { |
| tst_resm(TFAIL, "locking pid is wrong, should be %d is %d", |
| pid, fl->l_pid); |
| fail = 1; |
| } |
| } |
| |
| void unlock_file() |
| { |
| struct flock fl; |
| |
| if (do_lock(F_SETLK, (short)F_UNLCK, (short)0, 0, 0) < 0) { |
| tst_resm(TFAIL, "fcntl on file failed, errno =%d", errno); |
| fail = 1; |
| } |
| do_test(&fl, F_WRLCK, 0, 0, 0); |
| compare_lock(&fl, (short)F_UNLCK, (short)0, 0, 0, (pid_t) 0); |
| } |
| |
| char *str_type(int type) |
| { |
| static char buf[20]; |
| |
| switch (type) { |
| case 1: |
| return ("F_RDLCK"); |
| case 2: |
| return ("F_WRLCK"); |
| case 3: |
| return ("F_UNLCK"); |
| default: |
| sprintf(buf, "BAD VALUE: %d", type); |
| return (buf); |
| } |
| } |
| |
| void parent_put(struct flock *l) |
| { |
| if (write(parent_pipe[1], l, sizeof(*l)) != sizeof(*l)) { |
| tst_resm(TFAIL, "couldn't send message to child"); |
| fail = 1; |
| } |
| } |
| |
| void parent_get(struct flock *l) |
| { |
| if (read(child_pipe[0], l, sizeof(*l)) != sizeof(*l)) { |
| tst_resm(TFAIL, "couldn't get message from child"); |
| fail = 1; |
| } |
| } |
| |
| void child_put(struct flock *l) |
| { |
| if (write(child_pipe[1], l, sizeof(*l)) != sizeof(*l)) { |
| tst_resm(TFAIL, "couldn't send message to parent"); |
| fail = 1; |
| } |
| } |
| |
| void child_get(struct flock *l) |
| { |
| if (read(parent_pipe[0], l, sizeof(*l)) != sizeof(*l)) { |
| tst_resm(TFAIL, "couldn't get message from parent"); |
| cleanup(); |
| } else if (l->l_type == (short)STOP) { |
| exit(0); |
| } |
| } |
| |
| void stop_child() |
| { |
| struct flock fl; |
| |
| (void)signal(SIGCLD, (void (*)())SIG_DFL); |
| fl.l_type = STOP; |
| parent_put(&fl); |
| wait(0); |
| } |
| |
| void catch_child() |
| { |
| tst_resm(TFAIL, "Unexpected death of child process"); |
| cleanup(); |
| } |
| |
| int main(int ac, char **av) |
| { |
| struct flock tl; |
| |
| int lc; /* loop counter */ |
| char *msg; /* message returned from parse_opts */ |
| |
| /* parse standard options */ |
| if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL) { |
| tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); |
| } |
| #ifdef UCLINUX |
| maybe_run_child(&do_child, "ddddd", &parent_pipe[0], &parent_pipe[1], |
| &child_pipe[0], &child_pipe[1], &fd); |
| #endif |
| |
| setup(); /* global setup */ |
| |
| /* Check for looping state if -i option is given */ |
| for (lc = 0; TEST_LOOPING(lc); lc++) { |
| /* reset Tst_count in case we are looping */ |
| Tst_count = 0; |
| |
| if ((child_pid = FORK_OR_VFORK()) == 0) { |
| #ifdef UCLINUX |
| if (self_exec |
| (av[0], "ddddd", parent_pipe[0], parent_pipe[1], |
| child_pipe[0], child_pipe[1], fd) < 0) { |
| tst_resm(TFAIL, "self_exec failed"); |
| cleanup(); |
| } |
| #else |
| do_child(); |
| #endif |
| } |
| if (child_pid < 0) { |
| tst_resm(TFAIL, "Fork failed"); |
| cleanup(); |
| } |
| |
| (void)close(parent_pipe[0]); |
| (void)close(child_pipe[1]); |
| |
| /* //block1: */ |
| tst_resm(TINFO, "Enter block 1"); |
| fail = 0; |
| /* |
| * Set a read lock on the whole file |
| */ |
| if (do_lock(F_SETLK, (short)F_RDLCK, (short)0, 0, 0) < 0) { |
| tst_resm(TFAIL, "fcntl on file failed, errno =%d", |
| errno); |
| fail = 1; |
| } |
| |
| /* |
| * Test to make sure it's there. |
| */ |
| do_test(&tl, (short)F_WRLCK, (short)0, 0, 0); |
| compare_lock(&tl, (short)F_RDLCK, (short)0, 0, 0, parent_pid); |
| |
| /* |
| * remove the lock set above |
| */ |
| unlock_file(); |
| |
| if (fail) { |
| tst_resm(TINFO, "Test block 1: FAILED"); |
| } else { |
| tst_resm(TINFO, "Test block 1: PASSED"); |
| } |
| tst_resm(TINFO, "Exit block 1"); |
| |
| /* //block2: */ |
| tst_resm(TINFO, "Enter block 2"); |
| fail = 0; |
| |
| /* |
| * Set a write lock on the whole file |
| */ |
| if (do_lock(F_SETLK, (short)F_WRLCK, (short)0, 0, 0) < 0) { |
| tst_resm(TFAIL, "fcntl on file failed, errno =%d", |
| errno); |
| fail = 1; |
| } |
| |
| /* |
| * Test to make sure its there |
| */ |
| do_test(&tl, (short)F_WRLCK, (short)0, 0, 0); |
| compare_lock(&tl, (short)F_WRLCK, (short)0, 0, 0, parent_pid); |
| |
| /* |
| * remove the lock set above |
| */ |
| unlock_file(); |
| |
| if (fail) { |
| tst_resm(TINFO, "Test block 2: FAILED"); |
| } else { |
| tst_resm(TINFO, "Test block 2: PASSED"); |
| } |
| |
| tst_resm(TINFO, "Exit block 2"); |
| |
| /* //block3: */ |
| tst_resm(TINFO, "Enter block 3"); |
| fail = 0; |
| |
| /* |
| * Add a read lock to the middle of the file and a write |
| * at the begining |
| */ |
| if (do_lock(F_SETLK, (short)F_RDLCK, (short)0, 10, 5) < 0) { |
| tst_resm(TFAIL, "fcntl on file failed, errno =%d", |
| errno); |
| fail = 1; |
| } |
| |
| if (do_lock(F_SETLK, (short)F_WRLCK, (short)0, 1, 5) < 0) { |
| tst_resm(TFAIL, "fcntl on file failed, errno =%d", |
| errno); |
| fail = 1; |
| } |
| |
| /* |
| * Test write lock |
| */ |
| do_test(&tl, F_WRLCK, 0, 0, 0); |
| compare_lock(&tl, (short)F_WRLCK, (short)0, 1, 5, parent_pid); |
| |
| /* |
| * Test read lock |
| */ |
| do_test(&tl, F_WRLCK, 0, 6, 0); |
| compare_lock(&tl, (short)F_RDLCK, (short)0, 10, 5, parent_pid); |
| |
| /* |
| * Test that the rest of the file is unlocked |
| */ |
| do_test(&tl, F_WRLCK, 0, 15, 0); |
| compare_lock(&tl, (short)F_UNLCK, (short)0, 15, 0, 0); |
| |
| /* |
| * remove all the locks set above |
| */ |
| unlock_file(); |
| |
| if (fail) { |
| tst_resm(TINFO, "Test block 3: FAILED"); |
| } else { |
| tst_resm(TINFO, "Test block 3 : PASSED"); |
| } |
| tst_resm(TINFO, "Exit block 3"); |
| |
| /* //block4: */ |
| tst_resm(TINFO, "Enter block 4"); |
| fail = 0; |
| |
| /* |
| * Set a read lock at the middle of the file and a |
| * write lock just before |
| */ |
| if (do_lock(F_SETLK, (short)F_RDLCK, (short)0, 10, 5) < 0) { |
| tst_resm(TFAIL, "fcntl on file failed, errno =%d", |
| errno); |
| fail = 1; |
| } |
| |
| if (do_lock(F_SETLK, (short)F_WRLCK, (short)0, 5, 5) < 0) { |
| tst_resm(TFAIL, "fcntl on file failed, errno =%d", |
| errno); |
| fail = 1; |
| } |
| |
| /* |
| * Test the write lock |
| */ |
| do_test(&tl, (short)F_WRLCK, (short)0, 0, 0); |
| compare_lock(&tl, (short)F_WRLCK, (short)0, 5, 5, parent_pid); |
| |
| /* |
| * Test the read lock. |
| */ |
| do_test(&tl, (short)F_WRLCK, (short)0, 10, 0); |
| compare_lock(&tl, (short)F_RDLCK, (short)0, 10, 5, parent_pid); |
| |
| /* |
| * Test to make sure the rest of the file is unlocked. |
| */ |
| do_test(&tl, (short)F_WRLCK, (short)0, 15, 0); |
| compare_lock(&tl, (short)F_UNLCK, (short)0, 15, 0, 0); |
| |
| /* |
| * remove all the locks set above |
| */ |
| unlock_file(); |
| |
| if (fail) { |
| tst_resm(TINFO, "Test block 4: FAILED"); |
| } else { |
| tst_resm(TINFO, "Test block 4: PASSED"); |
| } |
| tst_resm(TINFO, "Exit block 4"); |
| |
| /* //block5: */ |
| tst_resm(TINFO, "Enter block 5"); |
| fail = 0; |
| |
| /* |
| * Set a read lock in the middle and a write lock that |
| * ends at the first byte of the read lock |
| */ |
| if (do_lock(F_SETLK, (short)F_RDLCK, (short)0, 10, 5) < 0) { |
| tst_resm(TFAIL, "fcntl on file failed, errno =%d", |
| errno); |
| fail = 1; |
| } |
| |
| if (do_lock(F_SETLK, (short)F_WRLCK, (short)0, 5, 6) < 0) { |
| tst_resm(TFAIL, "fcntl on file failed, errno =%d", |
| errno); |
| fail = 1; |
| } |
| |
| /* |
| * Test write lock |
| */ |
| do_test(&tl, (short)F_WRLCK, (short)0, 0, 0); |
| compare_lock(&tl, (short)F_WRLCK, (short)0, 5, 6, parent_pid); |
| |
| /* |
| * Test read lock |
| */ |
| do_test(&tl, (short)F_WRLCK, (short)0, 11, 0); |
| compare_lock(&tl, (short)F_RDLCK, (short)0, 11, 4, parent_pid); |
| |
| /* |
| * Test to make sure the rest of the file is unlocked. |
| */ |
| do_test(&tl, (short)F_WRLCK, (short)0, 15, 0); |
| compare_lock(&tl, (short)F_UNLCK, (short)0, 15, 0, 0); |
| |
| /* |
| * remove all the locks set above |
| */ |
| unlock_file(); |
| |
| if (fail) { |
| tst_resm(TINFO, "Test block 5: FAILED"); |
| } else { |
| tst_resm(TINFO, "Test block 5: PASSED"); |
| } |
| tst_resm(TINFO, "Exit block 5"); |
| |
| /* //block6: */ |
| tst_resm(TINFO, "Enter block 6"); |
| fail = 0; |
| |
| /* |
| * Set a read lock on the middle of the file and a write |
| * lock that overlaps the front of the read. |
| */ |
| if (do_lock(F_SETLK, (short)F_RDLCK, (short)0, 10, 5) < 0) { |
| tst_resm(TFAIL, "fcntl on file failed, errno =%d", |
| errno); |
| fail = 1; |
| } |
| |
| if (do_lock(F_SETLK, (short)F_WRLCK, (short)0, 5, 8) < 0) { |
| tst_resm(TFAIL, "fcntl on file failed, errno =%d", |
| errno); |
| fail = 1; |
| } |
| |
| /* |
| * Test the write lock |
| */ |
| do_test(&tl, (short)F_WRLCK, (short)0, 5, 0); |
| compare_lock(&tl, (short)F_WRLCK, (short)0, 5, 8, parent_pid); |
| |
| /* |
| * Test the read lock |
| */ |
| do_test(&tl, (short)F_WRLCK, (short)0, 13, 0); |
| compare_lock(&tl, (short)F_RDLCK, (short)0, 13, 2, parent_pid); |
| |
| /* |
| * Test to make sure the rest of the file is unlocked. |
| */ |
| do_test(&tl, (short)F_WRLCK, (short)0, 15, 0); |
| compare_lock(&tl, (short)F_UNLCK, (short)0, 15, 0, 0); |
| |
| /* |
| * remove all the locks set above |
| */ |
| unlock_file(); |
| |
| if (fail) { |
| tst_resm(TINFO, "Test block 6 FAILED"); |
| } else { |
| tst_resm(TINFO, "Test block 6 PASSED"); |
| } |
| tst_resm(TINFO, "Exit block 6"); |
| |
| /* //block7: */ |
| tst_resm(TINFO, "Enter block 7"); |
| fail = 0; |
| |
| /* |
| * Set a read lock in the middle of a file and a write |
| * lock in the middle of it |
| */ |
| if (do_lock(F_SETLK, (short)F_RDLCK, (short)0, 10, 10) < 0) { |
| tst_resm(TFAIL, "fcntl on file failed, errno =%d", |
| errno); |
| fail = 1; |
| } |
| |
| if (do_lock(F_SETLK, (short)F_WRLCK, (short)0, 13, 5) < 0) { |
| tst_resm(TFAIL, "fcntl on file failed, errno =%d", |
| errno); |
| fail = 1; |
| } |
| |
| /* |
| * Test the first read lock |
| */ |
| do_test(&tl, (short)F_WRLCK, (short)0, 0, 0); |
| compare_lock(&tl, (short)F_RDLCK, (short)0, 10, 3, parent_pid); |
| |
| /* |
| * Test the write lock |
| */ |
| do_test(&tl, (short)F_WRLCK, (short)0, 13, 0); |
| compare_lock(&tl, (short)F_WRLCK, (short)0, 13, 5, parent_pid); |
| |
| /* |
| * Test the second read lock |
| */ |
| do_test(&tl, (short)F_WRLCK, (short)0, 18, 0); |
| compare_lock(&tl, (short)F_RDLCK, (short)0, 18, 2, parent_pid); |
| |
| /* |
| * Test to make sure the rest of the file is unlocked |
| */ |
| do_test(&tl, (short)F_WRLCK, (short)0, 20, 0); |
| compare_lock(&tl, (short)F_UNLCK, (short)0, 20, 0, 0); |
| |
| /* |
| * remove all the locks set above. |
| */ |
| unlock_file(); |
| if (fail) { |
| tst_resm(TINFO, "Test block 7: FAILED"); |
| } else { |
| tst_resm(TINFO, "Test block 7: PASSED"); |
| } |
| tst_resm(TINFO, "Exit block 7"); |
| |
| /* //block8: */ |
| tst_resm(TINFO, "Enter block 8"); |
| fail = 0; |
| /* |
| * Set a read lock in the middle of the file and a write |
| * lock that overlaps the end |
| */ |
| if (do_lock(F_SETLK, (short)F_RDLCK, (short)0, 10, 5) < 0) { |
| tst_resm(TFAIL, "fcntl on file failed, errno =%d", |
| errno); |
| fail = 1; |
| } |
| |
| /* |
| * Set a write lock on the whole file |
| */ |
| if (do_lock(F_SETLK, (short)F_WRLCK, (short)0, 13, 5) < 0) { |
| tst_resm(TFAIL, "fcntl on file failed, errno =%d", |
| errno); |
| fail = 1; |
| } |
| |
| /* |
| * Test the read lock |
| */ |
| do_test(&tl, (short)F_WRLCK, (short)0, 0, 0); |
| compare_lock(&tl, (short)F_RDLCK, (short)0, 10, 3, parent_pid); |
| |
| /* |
| * Test the write lock |
| */ |
| do_test(&tl, (short)F_WRLCK, (short)0, 13, 0); |
| compare_lock(&tl, (short)F_WRLCK, (short)0, 13, 5, parent_pid); |
| |
| /* |
| * Test to make sure the rest of the file is unlocked |
| */ |
| do_test(&tl, (short)F_WRLCK, (short)0, 18, 0); |
| compare_lock(&tl, (short)F_UNLCK, (short)0, 18, 0, 0); |
| |
| /* |
| * remove all the locks set above |
| */ |
| unlock_file(); |
| |
| if (fail) { |
| tst_resm(TINFO, "Test block 8: FAILED"); |
| } else { |
| tst_resm(TINFO, "Test block 8: PASSED"); |
| } |
| tst_resm(TINFO, "Exit block 8"); |
| |
| /* //block9: */ |
| tst_resm(TINFO, "Enter block 9"); |
| fail = 0; |
| |
| /* |
| * Set a read lock in the middle of the file and a write |
| * lock starting at the last byte of the read lock |
| */ |
| if (do_lock(F_SETLK, (short)F_RDLCK, (short)0, 10, 5) < 0) { |
| tst_resm(TFAIL, "fcntl on file failed, errno =%d", |
| errno); |
| fail = 1; |
| } |
| |
| /* |
| * Set a write lock on the whole file. |
| */ |
| if (do_lock(F_SETLK, (short)F_WRLCK, (short)0, 14, 5) < 0) { |
| tst_resm(TFAIL, "fcntl on file failed, errno =%d", |
| errno); |
| fail = 1; |
| } |
| |
| /* |
| * Test read lock |
| */ |
| do_test(&tl, (short)F_WRLCK, (short)0, 0, 0); |
| compare_lock(&tl, (short)F_RDLCK, (short)0, 10, 4, parent_pid); |
| |
| /* |
| * Test the write lock |
| */ |
| do_test(&tl, (short)F_WRLCK, (short)0, 14, 0); |
| compare_lock(&tl, (short)F_WRLCK, (short)0, 14, 5, parent_pid); |
| |
| /* |
| * Test to make sure the end of the file is unlocked |
| */ |
| do_test(&tl, (short)F_WRLCK, (short)0, 19, 0); |
| compare_lock(&tl, (short)F_UNLCK, (short)0, 19, 0, 0); |
| |
| /* |
| * remove all the locks set above |
| */ |
| unlock_file(); |
| |
| if (fail) { |
| tst_resm(TINFO, "Test block 9: FAILED"); |
| } else { |
| tst_resm(TINFO, "Test block 9: PASSED"); |
| } |
| tst_resm(TINFO, "Exit block 9"); |
| |
| /* //block10: */ |
| tst_resm(TINFO, "Enter block 10"); |
| fail = 0; |
| |
| /* |
| * Set a read lock in the middle of the file and a write |
| * lock that starts just after the last byte of the |
| * read lock. |
| */ |
| if (do_lock(F_SETLK, (short)F_RDLCK, (short)0, 10, 5) < 0) { |
| tst_resm(TFAIL, "fcntl on file failed, errno =%d", |
| errno); |
| fail = 1; |
| } |
| |
| /* |
| * Set a write lock on the whole file |
| */ |
| if (do_lock(F_SETLK, (short)F_WRLCK, (short)0, 15, 5) < 0) { |
| tst_resm(TFAIL, "fcntl on file failed, errno =%d", |
| errno); |
| fail = 1; |
| } |
| |
| /* |
| * Test the read lock |
| */ |
| do_test(&tl, (short)F_WRLCK, (short)0, 0, 0); |
| compare_lock(&tl, (short)F_RDLCK, (short)0, 10, 5, parent_pid); |
| |
| /* |
| * Test the write lock |
| */ |
| do_test(&tl, (short)F_WRLCK, (short)0, 15, 0); |
| compare_lock(&tl, (short)F_WRLCK, (short)0, 15, 5, parent_pid); |
| |
| /* |
| * Test to make sure the rest of the file is unlocked |
| */ |
| do_test(&tl, (short)F_WRLCK, (short)0, 20, 0); |
| compare_lock(&tl, (short)F_UNLCK, (short)0, 20, 0, 0); |
| |
| /* |
| * remove all the locks set above |
| */ |
| unlock_file(); |
| |
| if (fail) { |
| tst_resm(TINFO, "Test block 10: FAILED"); |
| } else { |
| tst_resm(TINFO, "Test block 10: PASSED"); |
| } |
| tst_resm(TINFO, "Exit block 10"); |
| |
| /* //block11: */ |
| tst_resm(TINFO, "Enter block 11"); |
| fail = 0; |
| |
| /* |
| * Set a read lock at the middle of the file and a write |
| * lock that starts past the end of the read lock. |
| */ |
| if (do_lock(F_SETLK, (short)F_RDLCK, (short)0, 10, 5) < 0) { |
| tst_resm(TFAIL, "fcntl on file failed, errno =%d", |
| errno); |
| fail = 1; |
| } |
| |
| if (do_lock(F_SETLK, (short)F_WRLCK, (short)0, 16, 5) < 0) { |
| tst_resm(TFAIL, "fcntl on file failed, errno =%d", |
| errno); |
| fail = 1; |
| } |
| |
| /* |
| * Test the read lock |
| */ |
| do_test(&tl, (short)F_WRLCK, (short)0, 0, 0); |
| compare_lock(&tl, (short)F_RDLCK, (short)0, 10, 5, parent_pid); |
| |
| /* |
| * Test that byte in between is unlocked |
| */ |
| do_test(&tl, (short)F_WRLCK, (short)0, 15, 1); |
| compare_lock(&tl, (short)F_UNLCK, (short)0, 15, 1, 0); |
| |
| /* |
| * Test the write lock |
| */ |
| do_test(&tl, (short)F_WRLCK, (short)0, 16, 0); |
| compare_lock(&tl, (short)F_WRLCK, (short)0, 16, 5, parent_pid); |
| |
| /* |
| * Test to make sure the rest of the file is unlocked |
| */ |
| do_test(&tl, (short)F_WRLCK, (short)0, 21, 0); |
| compare_lock(&tl, (short)F_UNLCK, (short)0, 21, 0, 0); |
| |
| /* |
| * remove all the locks set above |
| */ |
| unlock_file(); |
| |
| if (fail) { |
| tst_resm(TINFO, "Test block 11: FAILED"); |
| } else { |
| tst_resm(TINFO, "Test block 11: PASSED"); |
| } |
| tst_resm(TINFO, "Exit block 11"); |
| |
| stop_child(); |
| close(fd); |
| } |
| cleanup(); |
| tst_exit(); |
| } |