864 lines
18 KiB
C
864 lines
18 KiB
C
/*
|
|
*
|
|
* 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"
|
|
|
|
#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(void)
|
|
{
|
|
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, SIGCHLD);
|
|
if ((sigaction(SIGCHLD, &act, NULL)) < 0) {
|
|
tst_resm(TFAIL, "SIGCHLD signal setup failed, errno: %d", errno);
|
|
fail = 1;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* cleanup()
|
|
* performs all ONE TIME cleanup for this test at completion or
|
|
* premature exit
|
|
*/
|
|
void cleanup(void)
|
|
{
|
|
|
|
tst_rmdir();
|
|
|
|
}
|
|
|
|
void do_child(void)
|
|
{
|
|
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(void)
|
|
{
|
|
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(void)
|
|
{
|
|
struct flock fl;
|
|
|
|
signal(SIGCHLD, SIG_DFL);
|
|
fl.l_type = STOP;
|
|
parent_put(&fl);
|
|
wait(0);
|
|
}
|
|
|
|
void catch_child(void)
|
|
{
|
|
tst_resm(TFAIL, "Unexpected death of child process");
|
|
cleanup();
|
|
}
|
|
|
|
int main(int ac, char **av)
|
|
{
|
|
struct flock tl;
|
|
|
|
int lc;
|
|
|
|
tst_parse_opts(ac, av, NULL, NULL);
|
|
#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();
|
|
}
|