📄 test7.c
字号:
while (access("T7.e1", 0) != 0) ;
unlink("T7.e1");
sleep(1);
if (kill(pid, SIGKILL) < 0) e(6);
if (wait(&s) != pid) e(7);
} else {
/* Child tries to lock and should block. */
if (creat("T7.e1", 0777) < 0) e(8);
func_code = F_SETLKW;
if (set(WRITE, 0, 3) != 0) e(9); /* should block */
errno = -1000;
e(10); /* process should be killed by signal */
exit(0); /* should never happen */
}
close(xfd);
}
void test7f()
{
/* Test to see if SETLKW gives EINTR when interrupted. */
int pid, s;
subtest = 6;
if ( (xfd = creat("T7.f", 0777)) != 3) e(1);
if (close(xfd) != 0) e(2);
if ( (xfd = open("T7.f", O_RDWR)) < 0) e(3);
if (write(xfd, buf, ITEMS) != ITEMS) e(4);
if (set(WRITE, 0, 3) != 0) e(5);
if ( (pid = fork()) ) {
/* Parent waits until child has started before signaling it. */
while (access("T7.f1", 0) != 0) ;
unlink("T7.f1");
sleep(1);
if (kill(pid, SIGTERM) < 0) e(6);
if (wait(&s) != pid) e(7);
if ( (s>>8) != 19) e(8);
} else {
/* Child tries to lock and should block.
* `signal(SIGTERM, sigfunc);' to set the signal handler is inadequate
* because on systems like BSD the sigaction flags for signal include
* `SA_RESTART' so syscalls are restarted after they have been
* interrupted by a signal.
*/
struct sigaction sa, osa;
sa.sa_handler = sigfunc;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGTERM, &sa, &osa) < 0) e(999);
if (creat("T7.f1", 0777) < 0) e(9);
func_code = F_SETLKW;
if (set(WRITE, 0, 3) != -1) e(10); /* should block */
if (errno != EINTR) e(11); /* signal should release it */
exit(19);
}
close(xfd);
}
void test7g()
{
/* Test to see if SETLKW unlocks when the needed lock becomes available. */
int pid, s;
subtest = 7;
if ( (xfd = creat("T7.g", 0777)) != 3) e(1);
if (close(xfd) != 0) e(2);
if ( (xfd = open("T7.g", O_RDWR)) < 0) e(3);
if (write(xfd, buf, ITEMS) != ITEMS) e(4);
if (set(WRITE, 0, 3) != 0) e(5); /* bytes 0 to 3 are now locked */
if ( (pid = fork()) ) {
/* Parent waits for child to start. */
while (access("T7.g1", 0) != 0) ;
unlink("T7.g1");
sleep(1);
if (set(UNLOCK, 0, 3) != 0) e(5);
if (wait(&s) != pid) e(6);
if ( (s >> 8) != 29) e(7);
} else {
/* Child tells parent it is alive, then tries to lock and is blocked.*/
func_code = F_SETLKW;
if (creat("T7.g1", 0777) < 0) e(8);
if (set(WRITE, 3, 3) != 0) e(9); /* process must block now */
if (set(UNLOCK, 3, 3) != 0) e(10);
exit(29);
}
close(xfd);
}
void test7h()
{
/* Test to see what happens if two processed block on the same lock. */
int pid, pid2, s, w;
subtest = 8;
if ( (xfd = creat("T7.h", 0777)) != 3) e(1);
if (close(xfd) != 0) e(2);
if ( (xfd = open("T7.h", O_RDWR)) < 0) e(3);
if (write(xfd, buf, ITEMS) != ITEMS) e(4);
if (set(WRITE, 0, 3) != 0) e(5); /* bytes 0 to 3 are now locked */
if ( (pid = fork()) ) {
if ( (pid2 = fork()) ) {
/* Parent waits for child to start. */
while (access("T7.h1", 0) != 0) ;
while (access("T7.h2", 0) != 0) ;
unlink("T7.h1");
unlink("T7.h2");
sleep(1);
if (set(UNLOCK, 0, 3) != 0) e(6);
w = wait(&s);
if (w != pid && w != pid2) e(7);
s = s >> 8;
if (s != 39 && s != 49) e(8);
w = wait(&s);
if (w != pid && w != pid2) e(9);
s = s >> 8;
if (s != 39 && s != 49) e(10);
} else {
func_code = F_SETLKW;
if (creat("T7.h1", 0777) < 0) e(11);
if (set(WRITE, 0, 0) != 0) e(12); /* block now */
if (set(UNLOCK, 0, 0) != 0) e(13);
exit(39);
}
} else {
/* Child tells parent it is alive, then tries to lock and is blocked.*/
func_code = F_SETLKW;
if (creat("T7.h2", 0777) < 0) e(14);
if (set(WRITE, 0, 1) != 0) e(15); /* process must block now */
if (set(UNLOCK, 0, 1) != 0) e(16);
exit(49);
}
close(xfd);
}
void test7i()
{
/* Check error conditions for fcntl(). */
int tfd, i;
subtest = 9;
errno = 0;
if ( (xfd = creat("T7.i", 0777)) != 3) e(1);
if (close(xfd) != 0) e(2);
if ( (xfd = open("T7.i", O_RDWR)) < 0) e(3);
if (write(xfd, buf, ITEMS) != ITEMS) e(4);
if (set(WRITE, 0, 3) != 0) e(5); /* bytes 0 to 3 are now locked */
if (set(WRITE, 0, 0) != 0) e(6);
if (errno != 0) e(7);
errno = 0;
if (set(WRITE, 3, 3) != 0) e(8);
if (errno != 0) e(9);
tfd = xfd; /* hold good value */
xfd = -99;
errno = 0;
if (set(WRITE, 0, 0) != -1) e(10);
if (errno != EBADF) e(11);
errno = 0;
if ( (xfd = open("T7.i", O_WRONLY)) < 0) e(12);
if (set(READ, 0, 0) != -1) e(13);
if (errno != EBADF) e(14);
if (close(xfd) != 0) e(15);
errno = 0;
if ( (xfd = open("T7.i", O_RDONLY)) < 0) e(16);
if (set(WRITE, 0, 0) != -1) e(17);
if (errno != EBADF) e(18);
if (close(xfd) != 0) e(19);
xfd = tfd; /* restore legal xfd value */
/* Check for EINVAL. */
errno = 0;
if (fcntl(xfd, F_DUPFD, OPEN_MAX) != -1) e(20);
if (errno != EINVAL) e(21);
errno = 0;
if (fcntl(xfd, F_DUPFD, -1) != -1) e(22);
if (errno != EINVAL) e(23);
xfd = 0; /* stdin does not support locking */
errno = 0;
if (set(READ, 0, 0) != -1) e(24);
if (errno != EINVAL) e(25);
xfd = tfd;
/* Check ENOLCK. */
for (i = 0; i < ITEMS; i++) {
if (set(WRITE, i, i) == 0) continue;
if (errno != ENOLCK) {
e(26);
break;
}
}
/* Check EMFILE. */
for (i = xfd + 1; i < OPEN_MAX; i++) open("T7.i", 0); /* use up all fds */
errno = 0;
if (fcntl(xfd, F_DUPFD, 0) != -1) e(27); /* No fds left */
if (errno != EMFILE) e(28);
for (i = xfd; i < OPEN_MAX; i++) if (close(i) != 0) e(29);
}
void test7j()
{
/* Test file locking with two processes. */
int s;
subtest = 10;
if ( (xfd = creat("T7.j", 0777)) != 3) e(1);
close(xfd);
if ( (xfd = open("T7.j", O_RDWR)) < 0) e(2);
if (write(xfd, buf, ITEMS) != ITEMS) e(3);
if (set(WRITE, 0, 4) != 0) e(4); /* lock belongs to parent */
if (set(READ, 10, 16) != 0) e(5); /* lock belongs to parent */
/* Up until now, all locks have been disjoint. Now try conflicts. */
if (fork()) {
/* Parent just waits for child to finish. */
wait(&s);
} else {
/* Child does the testing. */
errno = -100;
if (set(WRITE, 5, 7) < 0) e(6); /* should work */
if (set(WRITE, 4, 7) >= 0) e(7); /* child may not lock byte 4 */
if (errno != EACCES && errno != EAGAIN) e(8);
if (set(WRITE, 5, 9) != 0) e(9);
if (set(UNLOCK, 5, 9) != 0) e(10);
if (set(READ, 9, 17) < 0) e(11); /* shared READ lock is ok */
exit(0);
}
close(xfd);
}
void cloexec_test()
{
/* To text whether the FD_CLOEXEC flag actually causes files to be
* closed upon exec, we have to exec something. The test is carried
* out by forking, and then having the child exec test7 itself, but
* with argument 0. This is detected, and control comes here.
* File descriptors 3 and 10 should be closed here, and 10 open.
*/
if (close(3) == 0) e(1001); /* close should fail; it was closed on exec */
if (close(6) != 0) e(1002); /* close should succeed */
if (close(10) == 0) e(1003); /* close should fail */
fflush(stdout);
exit(0);
}
int set(how, first, last)
int how, first, last;
{
int r;
struct flock flock;
if (how == READ) flock.l_type = F_RDLCK;
if (how == WRITE) flock.l_type = F_WRLCK;
if (how == UNLOCK) flock.l_type = F_UNLCK;
flock.l_whence = whence;
flock.l_start = (long) first;
flock.l_len = (long) last - (long) first + 1;
r = fcntl(xfd, func_code, &flock);
if (r != -1)
return(0);
else
return(-1);
}
int locked(b)
int b;
/* Test to see if byte b is locked. Return L or U */
{
struct flock flock;
pid_t pid;
int status;
flock.l_type = F_WRLCK;
flock.l_whence = whence;
flock.l_start = (long) b;
flock.l_len = 1;
/* Process' own locks are invisible to F_GETLK, so fork a child to test. */
pid = fork();
if (pid == 0) {
if (fcntl(xfd, F_GETLK, &flock) != 0) e(2000);
exit(flock.l_type == F_UNLCK ? U : L);
}
if (pid == -1) e(2001);
if (fcntl(xfd, F_GETLK, &flock) != 0) e(2002);
if (flock.l_type != F_UNLCK) e(2003);
if (wait(&status) != pid) e(2004);
if (!WIFEXITED(status)) e(2005);
return(WEXITSTATUS(status));
}
void e(n)
int n;
{
int err_num = errno; /* save errno in case printf clobbers it */
printf("Subtest %d, error %d errno=%d ", subtest, n, errno);
fflush(stdout);
errno = err_num; /* restore errno, just in case */
perror("");
if (errct++ > MAX_ERROR) {
printf("Too many errors; test aborted\n");
chdir("..");
system("rm -rf DIR*");
exit(1);
}
}
void sigfunc(s)
int s; /* for ANSI */
{
}
void quit()
{
chdir("..");
system("rm -rf DIR*");
if (errct == 0) {
printf("ok\n");
exit(0);
} else {
printf("%d errors\n", errct);
exit(1);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -