From e2cd8e97c5d8a5f27f591a347dd0e7c2b141fed0 Mon Sep 17 00:00:00 2001 From: ngie Date: Sat, 11 Apr 2015 10:14:59 +0000 Subject: Integrate tools/regression/file into the FreeBSD test suite as tests/sys/file --- tools/regression/file/closefrom/Makefile | 9 - tools/regression/file/closefrom/closefrom.c | 274 ---- tools/regression/file/closefrom/closefrom.t | 10 - tools/regression/file/dup/Makefile | 7 - tools/regression/file/dup/dup.c | 386 ----- tools/regression/file/dup/dup.t | 10 - tools/regression/file/fcntlflags/Makefile | 7 - tools/regression/file/fcntlflags/fcntlflags.c | 110 -- tools/regression/file/fcntlflags/fcntlflags.t | 10 - tools/regression/file/flock/Makefile | 9 - tools/regression/file/flock/flock.c | 1598 -------------------- tools/regression/file/ftruncate/Makefile | 7 - tools/regression/file/ftruncate/ftruncate.c | 177 --- tools/regression/file/newfileops_on_fork/Makefile | 8 - .../file/newfileops_on_fork/newfileops_on_fork.c | 121 -- 15 files changed, 2743 deletions(-) delete mode 100644 tools/regression/file/closefrom/Makefile delete mode 100644 tools/regression/file/closefrom/closefrom.c delete mode 100644 tools/regression/file/closefrom/closefrom.t delete mode 100644 tools/regression/file/dup/Makefile delete mode 100644 tools/regression/file/dup/dup.c delete mode 100644 tools/regression/file/dup/dup.t delete mode 100644 tools/regression/file/fcntlflags/Makefile delete mode 100644 tools/regression/file/fcntlflags/fcntlflags.c delete mode 100644 tools/regression/file/fcntlflags/fcntlflags.t delete mode 100644 tools/regression/file/flock/Makefile delete mode 100644 tools/regression/file/flock/flock.c delete mode 100644 tools/regression/file/ftruncate/Makefile delete mode 100644 tools/regression/file/ftruncate/ftruncate.c delete mode 100644 tools/regression/file/newfileops_on_fork/Makefile delete mode 100644 tools/regression/file/newfileops_on_fork/newfileops_on_fork.c (limited to 'tools') diff --git a/tools/regression/file/closefrom/Makefile b/tools/regression/file/closefrom/Makefile deleted file mode 100644 index 4b8829c..0000000 --- a/tools/regression/file/closefrom/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# $FreeBSD$ - -PROG= closefrom -MAN= -WARNS?= 6 -DPADD= ${LIBUTIL} -LDADD= -lutil - -.include diff --git a/tools/regression/file/closefrom/closefrom.c b/tools/regression/file/closefrom/closefrom.c deleted file mode 100644 index e119f20..0000000 --- a/tools/regression/file/closefrom/closefrom.c +++ /dev/null @@ -1,274 +0,0 @@ -/*- - * Copyright (c) 2009 Advanced Computing Technologies LLC - * Written by: John H. Baldwin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -/* - * Regression tests for the closefrom(2) system call. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct shared_info { - int failed; - char tag[64]; - char message[0]; -}; - -static int test = 1; - -static void -ok(const char *descr) -{ - - printf("ok %d - %s\n", test, descr); - test++; -} - -static void -fail(const char *descr, const char *fmt, ...) -{ - va_list ap; - - printf("not ok %d - %s", test, descr); - test++; - if (fmt) { - va_start(ap, fmt); - printf(" # "); - vprintf(fmt, ap); - va_end(ap); - } - printf("\n"); - exit(1); -} - -#define fail_err(descr) fail((descr), "%s", strerror(errno)) - -static void -cok(struct shared_info *info, const char *descr) -{ - - info->failed = 0; - strlcpy(info->tag, descr, sizeof(info->tag)); - exit(0); -} - -static void -cfail(struct shared_info *info, const char *descr, const char *fmt, ...) -{ - va_list ap; - - info->failed = 1; - strlcpy(info->tag, descr, sizeof(info->tag)); - if (fmt) { - va_start(ap, fmt); - vsprintf(info->message, fmt, ap); - va_end(ap); - } - exit(0); -} - -#define cfail_err(info, descr) cfail((info), (descr), "%s", strerror(errno)) - -/* - * Use kinfo_getfile() to fetch the list of file descriptors and figure out - * the highest open file descriptor. - */ -static int -highest_fd(void) -{ - struct kinfo_file *kif; - int cnt, i, highest; - - kif = kinfo_getfile(getpid(), &cnt); - if (kif == NULL) - fail_err("kinfo_getfile"); - highest = INT_MIN; - for (i = 0; i < cnt; i++) - if (kif[i].kf_fd > highest) - highest = kif[i].kf_fd; - free(kif); - return (highest); -} - -static int -devnull(void) -{ - int fd; - - fd = open("/dev/null", O_RDONLY); - if (fd < 0) - fail_err("open(\"/dev/null\")"); - return (fd); -} - -int -main(int __unused argc, char __unused *argv[]) -{ - struct shared_info *info; - pid_t pid; - int fd, i; - - printf("1..15\n"); - - /* We better start up with fd's 0, 1, and 2 open. */ - fd = devnull(); - if (fd != 3) - fail("open", "bad descriptor %d", fd); - ok("open"); - - /* Make sure highest_fd() works. */ - fd = highest_fd(); - if (fd != 3) - fail("highest_fd", "bad descriptor %d", fd); - ok("highest_fd"); - - /* Try to use closefrom() for just closing fd 3. */ - closefrom(3); - fd = highest_fd(); - if (fd != 2) - fail("closefrom", "highest fd %d", fd); - ok("closefrom"); - - /* Eat up 16 descriptors. */ - for (i = 0; i < 16; i++) - (void)devnull(); - fd = highest_fd(); - if (fd != 18) - fail("open 16", "highest fd %d", fd); - ok("open 16"); - - /* Close half of them. */ - closefrom(11); - fd = highest_fd(); - if (fd != 10) - fail("closefrom", "highest fd %d", fd); - ok("closefrom"); - - /* Explicitly close descriptors 6 and 8 to create holes. */ - if (close(6) < 0 || close(8) < 0) - fail_err("close2 "); - ok("close 2"); - - /* Verify that close on 6 and 8 fails with EBADF. */ - if (close(6) == 0) - fail("close(6)", "did not fail"); - if (errno != EBADF) - fail_err("close(6)"); - ok("close(6)"); - if (close(8) == 0) - fail("close(8)", "did not fail"); - if (errno != EBADF) - fail_err("close(8)"); - ok("close(8)"); - - /* Close from 4 on. */ - closefrom(4); - fd = highest_fd(); - if (fd != 3) - fail("closefrom", "highest fd %d", fd); - ok("closefrom"); - - /* Allocate a small SHM region for IPC with our child. */ - info = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_ANON | - MAP_SHARED, -1, 0); - if (info == MAP_FAILED) - fail_err("mmap"); - ok("mmap"); - - /* Fork a child process to test closefrom(0). */ - pid = fork(); - if (pid < 0) - fail_err("fork"); - if (pid == 0) { - /* Child. */ - closefrom(0); - fd = highest_fd(); - if (fd >= 0) - cfail(info, "closefrom(0)", "highest fd %d", fd); - cok(info, "closefrom(0)"); - } - if (wait(NULL) < 0) - fail_err("wait"); - if (info->failed) - fail(info->tag, "%s", info->message); - ok(info->tag); - - /* Fork a child process to test closefrom(-1). */ - pid = fork(); - if (pid < 0) - fail_err("fork"); - if (pid == 0) { - /* Child. */ - closefrom(-1); - fd = highest_fd(); - if (fd >= 0) - cfail(info, "closefrom(-1)", "highest fd %d", fd); - cok(info, "closefrom(-1)"); - } - if (wait(NULL) < 0) - fail_err("wait"); - if (info->failed) - fail(info->tag, "%s", info->message); - ok(info->tag); - - /* Dup stdout to 6. */ - if (dup2(1, 6) < 0) - fail_err("dup2"); - fd = highest_fd(); - if (fd != 6) - fail("dup2", "highest fd %d", fd); - ok("dup2"); - - /* Do a closefrom() starting in a hole. */ - closefrom(4); - fd = highest_fd(); - if (fd != 3) - fail("closefrom", "highest fd %d", fd); - ok("closefrom"); - - /* Do a closefrom() beyond our highest open fd. */ - closefrom(32); - fd = highest_fd(); - if (fd != 3) - fail("closefrom", "highest fd %d", fd); - ok("closefrom"); - - return (0); -} diff --git a/tools/regression/file/closefrom/closefrom.t b/tools/regression/file/closefrom/closefrom.t deleted file mode 100644 index 8bdfd03..0000000 --- a/tools/regression/file/closefrom/closefrom.t +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -# $FreeBSD$ - -cd `dirname $0` - -executable=`basename $0 .t` - -make $executable 2>&1 > /dev/null - -exec ./$executable diff --git a/tools/regression/file/dup/Makefile b/tools/regression/file/dup/Makefile deleted file mode 100644 index 225c2e2..0000000 --- a/tools/regression/file/dup/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# $FreeBSD$ - -PROG= dup -MAN= -WARNS?= 6 - -.include diff --git a/tools/regression/file/dup/dup.c b/tools/regression/file/dup/dup.c deleted file mode 100644 index 8173818..0000000 --- a/tools/regression/file/dup/dup.c +++ /dev/null @@ -1,386 +0,0 @@ -/* - * $OpenBSD: dup2test.c,v 1.3 2003/07/31 21:48:08 deraadt Exp $ - * $OpenBSD: dup2_self.c,v 1.3 2003/07/31 21:48:08 deraadt Exp $ - * $OpenBSD: fcntl_dup.c,v 1.2 2003/07/31 21:48:08 deraadt Exp $ - * - * Written by Artur Grabowski 2002 Public Domain. - * - * $FreeBSD$ - */ - -/* - * Test #1: check if dup(2) works. - * Test #2: check if dup2(2) works. - * Test #3: check if dup2(2) returned a fd we asked for. - * Test #4: check if dup2(2) cleared close-on-exec flag for duped fd. - * Test #5: check if dup2(2) allows to dup fd to itself. - * Test #6: check if dup2(2) returned a fd we asked for. - * Test #7: check if dup2(2) did not clear close-on-exec flag for duped fd. - * Test #8: check if fcntl(F_DUPFD) works. - * Test #9: check if fcntl(F_DUPFD) cleared close-on-exec flag for duped fd. - * Test #10: check if dup2() to a fd > current maximum number of open files - * limit work. - * Test #11: check if fcntl(F_DUP2FD) works. - * Test #12: check if fcntl(F_DUP2FD) returned a fd we asked for. - * Test #13: check if fcntl(F_DUP2FD) cleared close-on-exec flag for duped fd. - * Test #14: check if fcntl(F_DUP2FD) allows to dup fd to itself. - * Test #15: check if fcntl(F_DUP2FD) returned a fd we asked for. - * Test #16: check if fcntl(F_DUP2FD) did not clear close-on-exec flag for - * duped fd. - * Test #17: check if fcntl(F_DUP2FD) to a fd > current maximum number of open - * files limit work. - * Test #18: check if fcntl(F_DUPFD_CLOEXEC) works. - * Test #19: check if fcntl(F_DUPFD_CLOEXEC) set close-on-exec flag for duped - * fd. - * Test #20: check if fcntl(F_DUP2FD_CLOEXEC) works. - * Test #21: check if fcntl(F_DUP2FD_CLOEXEC) returned a fd we asked for. - * Test #22: check if fcntl(F_DUP2FD_CLOEXEC) set close-on-exec flag for duped - * fd. - * Test #23: check if fcntl(F_DUP2FD_CLOEXEC) to a fd > current maximum number - * of open files limit work. - * Test #24: check if dup3(O_CLOEXEC) works. - * Test #25: check if dup3(O_CLOEXEC) returned a fd we asked for. - * Test #26: check if dup3(O_CLOEXEC) set close-on-exec flag for duped fd. - * Test #27: check if dup3(0) works. - * Test #28: check if dup3(0) returned a fd we asked for. - * Test #29: check if dup3(0) cleared close-on-exec flag for duped fd. - * Test #30: check if dup3(O_CLOEXEC) fails if oldfd == newfd. - * Test #31: check if dup3(0) fails if oldfd == newfd. - * Test #32: check if dup3(O_CLOEXEC) to a fd > current maximum number of - * open files limit work. - */ - -#include -#include -#include - -#include -#include -#include -#include -#include - -static int getafile(void); - -static int -getafile(void) -{ - int fd; - - char temp[] = "/tmp/dup2XXXXXXXXX"; - if ((fd = mkstemp(temp)) < 0) - err(1, "mkstemp"); - remove(temp); - if (ftruncate(fd, 1024) != 0) - err(1, "ftruncate"); - return (fd); -} - -int -main(int __unused argc, char __unused *argv[]) -{ - struct rlimit rlp; - int orgfd, fd1, fd2, test = 0; - - orgfd = getafile(); - - printf("1..32\n"); - - /* If dup(2) ever work? */ - if ((fd1 = dup(orgfd)) < 0) - err(1, "dup"); - printf("ok %d - dup(2) works\n", ++test); - - /* Set close-on-exec */ - if (fcntl(fd1, F_SETFD, 1) != 0) - err(1, "fcntl(F_SETFD)"); - - /* If dup2(2) ever work? */ - if ((fd2 = dup2(fd1, fd1 + 1)) < 0) - err(1, "dup2"); - printf("ok %d - dup2(2) works\n", ++test); - - /* Do we get the right fd? */ - ++test; - if (fd2 != fd1 + 1) - printf("no ok %d - dup2(2) didn't give us the right fd\n", - test); - else - printf("ok %d - dup2(2) returned a correct fd\n", test); - - /* Was close-on-exec cleared? */ - ++test; - if (fcntl(fd2, F_GETFD) != 0) - printf("not ok %d - dup2(2) didn't clear close-on-exec\n", - test); - else - printf("ok %d - dup2(2) cleared close-on-exec\n", test); - - /* - * Dup to itself. - * - * We're testing a small tweak in dup2 semantics. - * Normally dup and dup2 will clear the close-on-exec - * flag on the new fd (which appears to be an implementation - * mistake from start and not some planned behavior). - * In today's implementations of dup and dup2 we have to make - * an effort to really clear that flag. But all tested - * implementations of dup2 have another tweak. If we - * dup2(old, new) when old == new, the syscall short-circuits - * and returns early (because there is no need to do all the - * work (and there is a risk for serious mistakes)). - * So although the docs say that dup2 should "take 'old', - * close 'new' perform a dup(2) of 'old' into 'new'" - * the docs are not really followed because close-on-exec - * is not cleared on 'new'. - * - * Since everyone has this bug, we pretend that this is - * the way it is supposed to be and test here that it really - * works that way. - * - * This is a fine example on where two separate implementation - * fuckups take out each other and make the end-result the way - * it was meant to be. - */ - if ((fd2 = dup2(fd1, fd1)) < 0) - err(1, "dup2"); - printf("ok %d - dup2(2) to itself works\n", ++test); - - /* Do we get the right fd? */ - ++test; - if (fd2 != fd1) - printf("not ok %d - dup2(2) didn't give us the right fd\n", - test); - else - printf("ok %d - dup2(2) to itself returned a correct fd\n", - test); - - /* Was close-on-exec cleared? */ - ++test; - if (fcntl(fd2, F_GETFD) == 0) - printf("not ok %d - dup2(2) cleared close-on-exec\n", test); - else - printf("ok %d - dup2(2) didn't clear close-on-exec\n", test); - - /* Does fcntl(F_DUPFD) work? */ - if ((fd2 = fcntl(fd1, F_DUPFD, 10)) < 0) - err(1, "fcntl(F_DUPFD)"); - if (fd2 < 10) - printf("not ok %d - fcntl(F_DUPFD) returned wrong fd %d\n", - ++test, fd2); - else - printf("ok %d - fcntl(F_DUPFD) works\n", ++test); - - /* Was close-on-exec cleared? */ - ++test; - if (fcntl(fd2, F_GETFD) != 0) - printf( - "not ok %d - fcntl(F_DUPFD) didn't clear close-on-exec\n", - test); - else - printf("ok %d - fcntl(F_DUPFD) cleared close-on-exec\n", test); - - ++test; - if (getrlimit(RLIMIT_NOFILE, &rlp) < 0) - err(1, "getrlimit"); - if ((fd2 = dup2(fd1, rlp.rlim_cur + 1)) >= 0) - printf("not ok %d - dup2(2) bypassed NOFILE limit\n", test); - else - printf("ok %d - dup2(2) didn't bypass NOFILE limit\n", test); - - /* If fcntl(F_DUP2FD) ever work? */ - if ((fd2 = fcntl(fd1, F_DUP2FD, fd1 + 1)) < 0) - err(1, "fcntl(F_DUP2FD)"); - printf("ok %d - fcntl(F_DUP2FD) works\n", ++test); - - /* Do we get the right fd? */ - ++test; - if (fd2 != fd1 + 1) - printf( - "no ok %d - fcntl(F_DUP2FD) didn't give us the right fd\n", - test); - else - printf("ok %d - fcntl(F_DUP2FD) returned a correct fd\n", - test); - - /* Was close-on-exec cleared? */ - ++test; - if (fcntl(fd2, F_GETFD) != 0) - printf( - "not ok %d - fcntl(F_DUP2FD) didn't clear close-on-exec\n", - test); - else - printf("ok %d - fcntl(F_DUP2FD) cleared close-on-exec\n", - test); - - /* Dup to itself */ - if ((fd2 = fcntl(fd1, F_DUP2FD, fd1)) < 0) - err(1, "fcntl(F_DUP2FD)"); - printf("ok %d - fcntl(F_DUP2FD) to itself works\n", ++test); - - /* Do we get the right fd? */ - ++test; - if (fd2 != fd1) - printf( - "not ok %d - fcntl(F_DUP2FD) didn't give us the right fd\n", - test); - else - printf( - "ok %d - fcntl(F_DUP2FD) to itself returned a correct fd\n", - test); - - /* Was close-on-exec cleared? */ - ++test; - if (fcntl(fd2, F_GETFD) == 0) - printf("not ok %d - fcntl(F_DUP2FD) cleared close-on-exec\n", - test); - else - printf("ok %d - fcntl(F_DUP2FD) didn't clear close-on-exec\n", - test); - - ++test; - if (getrlimit(RLIMIT_NOFILE, &rlp) < 0) - err(1, "getrlimit"); - if ((fd2 = fcntl(fd1, F_DUP2FD, rlp.rlim_cur + 1)) >= 0) - printf("not ok %d - fcntl(F_DUP2FD) bypassed NOFILE limit\n", - test); - else - printf("ok %d - fcntl(F_DUP2FD) didn't bypass NOFILE limit\n", - test); - - /* Does fcntl(F_DUPFD_CLOEXEC) work? */ - if ((fd2 = fcntl(fd1, F_DUPFD_CLOEXEC, 10)) < 0) - err(1, "fcntl(F_DUPFD_CLOEXEC)"); - if (fd2 < 10) - printf("not ok %d - fcntl(F_DUPFD_CLOEXEC) returned wrong fd %d\n", - ++test, fd2); - else - printf("ok %d - fcntl(F_DUPFD_CLOEXEC) works\n", ++test); - - /* Was close-on-exec cleared? */ - ++test; - if (fcntl(fd2, F_GETFD) != 1) - printf( - "not ok %d - fcntl(F_DUPFD_CLOEXEC) didn't set close-on-exec\n", - test); - else - printf("ok %d - fcntl(F_DUPFD_CLOEXEC) set close-on-exec\n", - test); - - /* If fcntl(F_DUP2FD_CLOEXEC) ever work? */ - if ((fd2 = fcntl(fd1, F_DUP2FD_CLOEXEC, fd1 + 1)) < 0) - err(1, "fcntl(F_DUP2FD_CLOEXEC)"); - printf("ok %d - fcntl(F_DUP2FD_CLOEXEC) works\n", ++test); - - /* Do we get the right fd? */ - ++test; - if (fd2 != fd1 + 1) - printf( - "no ok %d - fcntl(F_DUP2FD_CLOEXEC) didn't give us the right fd\n", - test); - else - printf("ok %d - fcntl(F_DUP2FD_CLOEXEC) returned a correct fd\n", - test); - - /* Was close-on-exec set? */ - ++test; - if (fcntl(fd2, F_GETFD) != FD_CLOEXEC) - printf( - "not ok %d - fcntl(F_DUP2FD_CLOEXEC) didn't set close-on-exec\n", - test); - else - printf("ok %d - fcntl(F_DUP2FD_CLOEXEC) set close-on-exec\n", - test); - - /* - * It is unclear what F_DUP2FD_CLOEXEC should do when duplicating a - * file descriptor onto itself. - */ - - ++test; - if (getrlimit(RLIMIT_NOFILE, &rlp) < 0) - err(1, "getrlimit"); - if ((fd2 = fcntl(fd1, F_DUP2FD_CLOEXEC, rlp.rlim_cur + 1)) >= 0) - printf("not ok %d - fcntl(F_DUP2FD_CLOEXEC) bypassed NOFILE limit\n", - test); - else - printf("ok %d - fcntl(F_DUP2FD_CLOEXEC) didn't bypass NOFILE limit\n", - test); - - /* Does dup3(O_CLOEXEC) ever work? */ - if ((fd2 = dup3(fd1, fd1 + 1, O_CLOEXEC)) < 0) - err(1, "dup3(O_CLOEXEC)"); - printf("ok %d - dup3(O_CLOEXEC) works\n", ++test); - - /* Do we get the right fd? */ - ++test; - if (fd2 != fd1 + 1) - printf( - "no ok %d - dup3(O_CLOEXEC) didn't give us the right fd\n", - test); - else - printf("ok %d - dup3(O_CLOEXEC) returned a correct fd\n", - test); - - /* Was close-on-exec set? */ - ++test; - if (fcntl(fd2, F_GETFD) != FD_CLOEXEC) - printf( - "not ok %d - dup3(O_CLOEXEC) didn't set close-on-exec\n", - test); - else - printf("ok %d - dup3(O_CLOEXEC) set close-on-exec\n", - test); - - /* Does dup3(0) ever work? */ - if ((fd2 = dup3(fd1, fd1 + 1, 0)) < 0) - err(1, "dup3(0)"); - printf("ok %d - dup3(0) works\n", ++test); - - /* Do we get the right fd? */ - ++test; - if (fd2 != fd1 + 1) - printf( - "no ok %d - dup3(0) didn't give us the right fd\n", - test); - else - printf("ok %d - dup3(0) returned a correct fd\n", - test); - - /* Was close-on-exec cleared? */ - ++test; - if (fcntl(fd2, F_GETFD) != 0) - printf( - "not ok %d - dup3(0) didn't clear close-on-exec\n", - test); - else - printf("ok %d - dup3(0) cleared close-on-exec\n", - test); - - /* dup3() does not allow duplicating to the same fd */ - ++test; - if (dup3(fd1, fd1, O_CLOEXEC) != -1) - printf( - "not ok %d - dup3(fd1, fd1, O_CLOEXEC) succeeded\n", test); - else - printf("ok %d - dup3(fd1, fd1, O_CLOEXEC) failed\n", test); - - ++test; - if (dup3(fd1, fd1, 0) != -1) - printf( - "not ok %d - dup3(fd1, fd1, 0) succeeded\n", test); - else - printf("ok %d - dup3(fd1, fd1, 0) failed\n", test); - - ++test; - if (getrlimit(RLIMIT_NOFILE, &rlp) < 0) - err(1, "getrlimit"); - if ((fd2 = dup3(fd1, rlp.rlim_cur + 1, O_CLOEXEC)) >= 0) - printf("not ok %d - dup3(O_CLOEXEC) bypassed NOFILE limit\n", - test); - else - printf("ok %d - dup3(O_CLOEXEC) didn't bypass NOFILE limit\n", - test); - - return (0); -} diff --git a/tools/regression/file/dup/dup.t b/tools/regression/file/dup/dup.t deleted file mode 100644 index 8bdfd03..0000000 --- a/tools/regression/file/dup/dup.t +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -# $FreeBSD$ - -cd `dirname $0` - -executable=`basename $0 .t` - -make $executable 2>&1 > /dev/null - -exec ./$executable diff --git a/tools/regression/file/fcntlflags/Makefile b/tools/regression/file/fcntlflags/Makefile deleted file mode 100644 index 9e7fc3e..0000000 --- a/tools/regression/file/fcntlflags/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# $FreeBSD$ - -PROG= fcntlflags -MAN= -WARNS?= 6 - -.include diff --git a/tools/regression/file/fcntlflags/fcntlflags.c b/tools/regression/file/fcntlflags/fcntlflags.c deleted file mode 100644 index bcb3b54..0000000 --- a/tools/regression/file/fcntlflags/fcntlflags.c +++ /dev/null @@ -1,110 +0,0 @@ -/*- - * Copyright (c) 2013 Jilles Tjoelker - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include - -#include -#include -#include - -/* - * O_ACCMODE is currently defined incorrectly. This is what it should be. - * Various code depends on the incorrect value. - */ -#define CORRECT_O_ACCMODE (O_ACCMODE | O_EXEC) - -static int testnum; - -static void -subtests(const char *path, int omode, const char *omodetext) -{ - int fd, flags1, flags2, flags3; - - fd = open(path, omode); - if (fd == -1) - printf("not ok %d - open(\"%s\", %s) failed\n", - testnum++, path, omodetext); - else - printf("ok %d - open(\"%s\", %s) succeeded\n", - testnum++, path, omodetext); - flags1 = fcntl(fd, F_GETFL); - if (flags1 == -1) - printf("not ok %d - fcntl(F_GETFL) failed\n", testnum++); - else if ((flags1 & CORRECT_O_ACCMODE) == omode) - printf("ok %d - fcntl(F_GETFL) gave correct result\n", - testnum++); - else - printf("not ok %d - fcntl(F_GETFL) gave incorrect result " - "(%#x & %#x != %#x)\n", - testnum++, flags1, CORRECT_O_ACCMODE, omode); - if (fcntl(fd, F_SETFL, flags1) == -1) - printf("not ok %d - fcntl(F_SETFL) same flags failed\n", - testnum++); - else - printf("ok %d - fcntl(F_SETFL) same flags succeeded\n", - testnum++); - flags2 = fcntl(fd, F_GETFL); - if (flags2 == -1) - printf("not ok %d - fcntl(F_GETFL) failed\n", testnum++); - else if (flags2 == flags1) - printf("ok %d - fcntl(F_GETFL) gave same result\n", - testnum++); - else - printf("not ok %d - fcntl(F_SETFL) caused fcntl(F_GETFL) to " - "change from %#x to %#x\n", - testnum++, flags1, flags2); - if (fcntl(fd, F_SETFL, flags2 | O_NONBLOCK) == -1) - printf("not ok %d - fcntl(F_SETFL) O_NONBLOCK failed\n", - testnum++); - else - printf("ok %d - fcntl(F_SETFL) O_NONBLOCK succeeded\n", - testnum++); - flags3 = fcntl(fd, F_GETFL); - if (flags3 == -1) - printf("not ok %d - fcntl(F_GETFL) failed\n", testnum++); - else if (flags3 == (flags2 | O_NONBLOCK)) - printf("ok %d - fcntl(F_GETFL) gave expected result\n", - testnum++); - else - printf("not ok %d - fcntl(F_SETFL) gave unexpected result " - "(%#x != %#x)\n", - testnum++, flags3, flags2 | O_NONBLOCK); - (void)close(fd); -} - -int -main(int argc __unused, char **argv __unused) -{ - printf("1..24\n"); - testnum = 1; - subtests("/dev/null", O_RDONLY, "O_RDONLY"); - subtests("/dev/null", O_WRONLY, "O_WRONLY"); - subtests("/dev/null", O_RDWR, "O_RDWR"); - subtests("/bin/sh", O_EXEC, "O_EXEC"); - return (0); -} diff --git a/tools/regression/file/fcntlflags/fcntlflags.t b/tools/regression/file/fcntlflags/fcntlflags.t deleted file mode 100644 index 8bdfd03..0000000 --- a/tools/regression/file/fcntlflags/fcntlflags.t +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -# $FreeBSD$ - -cd `dirname $0` - -executable=`basename $0 .t` - -make $executable 2>&1 > /dev/null - -exec ./$executable diff --git a/tools/regression/file/flock/Makefile b/tools/regression/file/flock/Makefile deleted file mode 100644 index cd1a46d..0000000 --- a/tools/regression/file/flock/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# $FreeBSD$ - -PROG= flock -MAN= -WARNS?= 6 -DPADD= ${LIBPTHREAD} -LDADD= -lpthread - -.include diff --git a/tools/regression/file/flock/flock.c b/tools/regression/file/flock/flock.c deleted file mode 100644 index 49e47b8..0000000 --- a/tools/regression/file/flock/flock.c +++ /dev/null @@ -1,1598 +0,0 @@ -/*- - * Copyright (c) 2008 Isilon Inc http://www.isilon.com/ - * Authors: Doug Rabson - * Developed with Red Inc: Alfred Perlstein - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include -#include -#include -#ifdef __FreeBSD__ -#include -#endif -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __FreeBSD__ -#if __FreeBSD_version >= 800028 -#define HAVE_SYSID -#endif -#include -#else -#ifndef nitems -#define nitems(x) (sizeof((x)) / sizeof((x)[0])) -#endif - -#ifndef __unused -#ifdef __GNUC__ -#define __unused __attribute__((__unused__)) -#else -#define __unused -#endif -#endif -#endif - -static int verbose = 0; - -static int -make_file(const char *pathname, off_t sz) -{ - struct stat st; - const char *template = "/flocktempXXXXXX"; - size_t len; - char *filename; - int fd; - - if (stat(pathname, &st) == 0) { - if (S_ISREG(st.st_mode)) { - fd = open(pathname, O_RDWR); - if (fd < 0) - err(1, "open(%s)", pathname); - if (ftruncate(fd, sz) < 0) - err(1, "ftruncate"); - return (fd); - } - } - - len = strlen(pathname) + strlen(template) + 1; - filename = malloc(len); - strcpy(filename, pathname); - strcat(filename, template); - fd = mkstemp(filename); - if (fd < 0) - err(1, "mkstemp"); - if (ftruncate(fd, sz) < 0) - err(1, "ftruncate"); - if (unlink(filename) < 0) - err(1, "unlink"); - free(filename); - - return (fd); -} - -static void -ignore_alarm(int __unused sig) -{ -} - -static int -safe_waitpid(pid_t pid) -{ - int save_errno; - int status; - - save_errno = errno; - errno = 0; - while (waitpid(pid, &status, 0) != pid) { - if (errno == EINTR) - continue; - err(1, "waitpid"); - } - errno = save_errno; - - return (status); -} - -#define FAIL(test) \ - do { \ - if (test) { \ - printf("FAIL (%s)\n", #test); \ - return -1; \ - } \ - } while (0) - -#define SUCCEED \ - do { printf("SUCCEED\n"); return 0; } while (0) - -/* - * Test 1 - F_GETLK on unlocked region - * - * If no lock is found that would prevent this lock from being - * created, the structure is left unchanged by this function call - * except for the lock type which is set to F_UNLCK. - */ -static int -test1(int fd, __unused int argc, const __unused char **argv) -{ - struct flock fl1, fl2; - - memset(&fl1, 1, sizeof(fl1)); - fl1.l_type = F_WRLCK; - fl1.l_whence = SEEK_SET; - fl2 = fl1; - - if (fcntl(fd, F_GETLK, &fl1) < 0) - err(1, "F_GETLK"); - - printf("1 - F_GETLK on unlocked region: "); - FAIL(fl1.l_start != fl2.l_start); - FAIL(fl1.l_len != fl2.l_len); - FAIL(fl1.l_pid != fl2.l_pid); - FAIL(fl1.l_type != F_UNLCK); - FAIL(fl1.l_whence != fl2.l_whence); -#ifdef HAVE_SYSID - FAIL(fl1.l_sysid != fl2.l_sysid); -#endif - - SUCCEED; -} - -/* - * Test 2 - F_SETLK on locked region - * - * If a shared or exclusive lock cannot be set, fcntl returns - * immediately with EACCES or EAGAIN. - */ -static int -test2(int fd, __unused int argc, const __unused char **argv) -{ - /* - * We create a child process to hold the lock which we will - * test. We use a pipe to communicate with the child. - */ - int pid; - int pfd[2]; - struct flock fl; - char ch; - int res; - - if (pipe(pfd) < 0) - err(1, "pipe"); - - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - - pid = fork(); - if (pid < 0) - err(1, "fork"); - - if (pid == 0) { - /* - * We are the child. We set a write lock and then - * write one byte back to the parent to tell it. The - * parent will kill us when its done. - */ - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_SETLK (child)"); - if (write(pfd[1], "a", 1) < 0) - err(1, "writing to pipe (child)"); - pause(); - exit(0); - } - - /* - * Wait until the child has set its lock and then perform the - * test. - */ - if (read(pfd[0], &ch, 1) != 1) - err(1, "reading from pipe (child)"); - - /* - * fcntl should return -1 with errno set to either EACCES or - * EAGAIN. - */ - printf("2 - F_SETLK on locked region: "); - res = fcntl(fd, F_SETLK, &fl); - kill(pid, SIGTERM); - safe_waitpid(pid); - close(pfd[0]); - close(pfd[1]); - FAIL(res == 0); - FAIL(errno != EACCES && errno != EAGAIN); - - SUCCEED; -} - -/* - * Test 3 - F_SETLKW on locked region - * - * If a shared or exclusive lock is blocked by other locks, the - * process waits until the request can be satisfied. - * - * XXX this test hangs on FreeBSD NFS filesystems due to limitations - * in FreeBSD's client (and server) lockd implementation. - */ -static int -test3(int fd, __unused int argc, const __unused char **argv) -{ - /* - * We create a child process to hold the lock which we will - * test. We use a pipe to communicate with the child. - */ - int pid; - int pfd[2]; - struct flock fl; - char ch; - int res; - - if (pipe(pfd) < 0) - err(1, "pipe"); - - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - - pid = fork(); - if (pid < 0) - err(1, "fork"); - - if (pid == 0) { - /* - * We are the child. We set a write lock and then - * write one byte back to the parent to tell it. The - * parent will kill us when its done. - */ - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_SETLK (child)"); - if (write(pfd[1], "a", 1) < 0) - err(1, "writing to pipe (child)"); - pause(); - exit(0); - } - - /* - * Wait until the child has set its lock and then perform the - * test. - */ - if (read(pfd[0], &ch, 1) != 1) - err(1, "reading from pipe (child)"); - - /* - * fcntl should wait until the alarm and then return -1 with - * errno set to EINTR. - */ - printf("3 - F_SETLKW on locked region: "); - - alarm(1); - - res = fcntl(fd, F_SETLKW, &fl); - kill(pid, SIGTERM); - safe_waitpid(pid); - close(pfd[0]); - close(pfd[1]); - FAIL(res == 0); - FAIL(errno != EINTR); - - SUCCEED; -} - -/* - * Test 4 - F_GETLK on locked region - * - * Get the first lock that blocks the lock. - */ -static int -test4(int fd, __unused int argc, const __unused char **argv) -{ - /* - * We create a child process to hold the lock which we will - * test. We use a pipe to communicate with the child. - */ - int pid; - int pfd[2]; - struct flock fl; - char ch; - - if (pipe(pfd) < 0) - err(1, "pipe"); - - fl.l_start = 0; - fl.l_len = 99; - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - - pid = fork(); - if (pid < 0) - err(1, "fork"); - - if (pid == 0) { - /* - * We are the child. We set a write lock and then - * write one byte back to the parent to tell it. The - * parent will kill us when its done. - */ - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_SETLK (child)"); - if (write(pfd[1], "a", 1) < 0) - err(1, "writing to pipe (child)"); - pause(); - exit(0); - } - - /* - * Wait until the child has set its lock and then perform the - * test. - */ - if (read(pfd[0], &ch, 1) != 1) - err(1, "reading from pipe (child)"); - - /* - * fcntl should return a lock structure reflecting the lock we - * made in the child process. - */ - if (fcntl(fd, F_GETLK, &fl) < 0) - err(1, "F_GETLK"); - - printf("4 - F_GETLK on locked region: "); - FAIL(fl.l_start != 0); - FAIL(fl.l_len != 99); - FAIL(fl.l_type != F_WRLCK); - FAIL(fl.l_pid != pid); -#ifdef HAVE_SYSID - FAIL(fl.l_sysid != 0); -#endif - - kill(pid, SIGTERM); - safe_waitpid(pid); - close(pfd[0]); - close(pfd[1]); - - SUCCEED; -} - -/* - * Test 5 - F_SETLKW simple deadlock - * - * If a blocking shared lock request would cause a deadlock (i.e. the - * lock request is blocked by a process which is itself blocked on a - * lock currently owned by the process making the new request), - * EDEADLK is returned. - */ -static int -test5(int fd, __unused int argc, const __unused char **argv) -{ - /* - * We create a child process to hold the lock which we will - * test. Because our test relies on the child process being - * blocked on the parent's lock, we can't easily use a pipe to - * synchronize so we just sleep in the parent to given the - * child a chance to setup. - * - * To create the deadlock condition, we arrange for the parent - * to lock the first byte of the file and the child to lock - * the second byte. After locking the second byte, the child - * will attempt to lock the first byte of the file, and - * block. The parent will then attempt to lock the second byte - * (owned by the child) which should cause deadlock. - */ - int pid; - struct flock fl; - int res; - - /* - * Lock the first byte in the parent. - */ - fl.l_start = 0; - fl.l_len = 1; - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_SETLK 1 (parent)"); - - pid = fork(); - if (pid < 0) - err(1, "fork"); - - if (pid == 0) { - /* - * Lock the second byte in the child and then block on - * the parent's lock. - */ - fl.l_start = 1; - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_SETLK (child)"); - fl.l_start = 0; - if (fcntl(fd, F_SETLKW, &fl) < 0) - err(1, "F_SETLKW (child)"); - exit(0); - } - - /* - * Wait until the child has set its lock and then perform the - * test. - */ - sleep(1); - - /* - * fcntl should immediately return -1 with errno set to - * EDEADLK. If the alarm fires, we failed to detect the - * deadlock. - */ - alarm(1); - printf("5 - F_SETLKW simple deadlock: "); - - fl.l_start = 1; - res = fcntl(fd, F_SETLKW, &fl); - kill(pid, SIGTERM); - safe_waitpid(pid); - - FAIL(res == 0); - FAIL(errno != EDEADLK); - - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_UNLCK; - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_UNLCK"); - - /* - * Cancel the alarm to avoid confusing later tests. - */ - alarm(0); - - SUCCEED; -} - -/* - * Test 6 - F_SETLKW complex deadlock. - * - * This test involves three process, P, C1 and C2. We set things up so - * that P locks byte zero, C1 locks byte 1 and C2 locks byte 2. We - * also block C2 by attempting to lock byte zero. Lastly, P attempts - * to lock a range including byte 1 and 2. This represents a deadlock - * (due to C2's blocking attempt to lock byte zero). - */ -static int -test6(int fd, __unused int argc, const __unused char **argv) -{ - /* - * Because our test relies on the child process being blocked - * on the parent's lock, we can't easily use a pipe to - * synchronize so we just sleep in the parent to given the - * children a chance to setup. - */ - int pid1, pid2; - struct flock fl; - int res; - - /* - * Lock the first byte in the parent. - */ - fl.l_start = 0; - fl.l_len = 1; - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_SETLK 1 (parent)"); - - pid1 = fork(); - if (pid1 < 0) - err(1, "fork"); - - if (pid1 == 0) { - /* - * C1 - * Lock the second byte in the child and then sleep - */ - fl.l_start = 1; - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_SETLK (child1)"); - pause(); - exit(0); - } - - pid2 = fork(); - if (pid2 < 0) - err(1, "fork"); - - if (pid2 == 0) { - /* - * C2 - * Lock the third byte in the child and then block on - * the parent's lock. - */ - fl.l_start = 2; - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_SETLK (child2)"); - fl.l_start = 0; - if (fcntl(fd, F_SETLKW, &fl) < 0) - err(1, "F_SETLKW (child2)"); - exit(0); - } - - /* - * Wait until the children have set their locks and then - * perform the test. - */ - sleep(1); - - /* - * fcntl should immediately return -1 with errno set to - * EDEADLK. If the alarm fires, we failed to detect the - * deadlock. - */ - alarm(1); - printf("6 - F_SETLKW complex deadlock: "); - - fl.l_start = 1; - fl.l_len = 2; - res = fcntl(fd, F_SETLKW, &fl); - kill(pid1, SIGTERM); - safe_waitpid(pid1); - kill(pid2, SIGTERM); - safe_waitpid(pid2); - - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_UNLCK; - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_UNLCK"); - - FAIL(res == 0); - FAIL(errno != EDEADLK); - - /* - * Cancel the alarm to avoid confusing later tests. - */ - alarm(0); - - SUCCEED; -} - -/* - * Test 7 - F_SETLK shared lock on exclusive locked region - * - * If a shared or exclusive lock cannot be set, fcntl returns - * immediately with EACCES or EAGAIN. - */ -static int -test7(int fd, __unused int argc, const __unused char **argv) -{ - /* - * We create a child process to hold the lock which we will - * test. We use a pipe to communicate with the child. - */ - int pid; - int pfd[2]; - struct flock fl; - char ch; - int res; - - if (pipe(pfd) < 0) - err(1, "pipe"); - - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - - pid = fork(); - if (pid < 0) - err(1, "fork"); - - if (pid == 0) { - /* - * We are the child. We set a write lock and then - * write one byte back to the parent to tell it. The - * parent will kill us when its done. - */ - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_SETLK (child)"); - if (write(pfd[1], "a", 1) < 0) - err(1, "writing to pipe (child)"); - pause(); - exit(0); - } - - /* - * Wait until the child has set its lock and then perform the - * test. - */ - if (read(pfd[0], &ch, 1) != 1) - err(1, "reading from pipe (child)"); - - /* - * fcntl should wait until the alarm and then return -1 with - * errno set to EINTR. - */ - printf("7 - F_SETLK shared lock on exclusive locked region: "); - - fl.l_type = F_RDLCK; - res = fcntl(fd, F_SETLK, &fl); - kill(pid, SIGTERM); - safe_waitpid(pid); - close(pfd[0]); - close(pfd[1]); - - FAIL(res == 0); - FAIL(errno != EACCES && errno != EAGAIN); - - SUCCEED; -} - -/* - * Test 8 - F_SETLK shared lock on share locked region - * - * When a shared lock is set on a segment of a file, other processes - * shall be able to set shared locks on that segment or a portion of - * it. - */ -static int -test8(int fd, __unused int argc, const __unused char **argv) -{ - /* - * We create a child process to hold the lock which we will - * test. We use a pipe to communicate with the child. - */ - int pid; - int pfd[2]; - struct flock fl; - char ch; - int res; - - if (pipe(pfd) < 0) - err(1, "pipe"); - - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_RDLCK; - fl.l_whence = SEEK_SET; - - pid = fork(); - if (pid < 0) - err(1, "fork"); - - if (pid == 0) { - /* - * We are the child. We set a write lock and then - * write one byte back to the parent to tell it. The - * parent will kill us when its done. - */ - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_SETLK (child)"); - if (write(pfd[1], "a", 1) < 0) - err(1, "writing to pipe (child)"); - pause(); - exit(0); - } - - /* - * Wait until the child has set its lock and then perform the - * test. - */ - if (read(pfd[0], &ch, 1) != 1) - err(1, "reading from pipe (child)"); - - /* - * fcntl should wait until the alarm and then return -1 with - * errno set to EINTR. - */ - printf("8 - F_SETLK shared lock on share locked region: "); - - fl.l_type = F_RDLCK; - res = fcntl(fd, F_SETLK, &fl); - - kill(pid, SIGTERM); - safe_waitpid(pid); - close(pfd[0]); - close(pfd[1]); - - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_UNLCK; - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_UNLCK"); - - FAIL(res != 0); - - SUCCEED; -} - -/* - * Test 9 - F_SETLK exclusive lock on share locked region - * - * If a shared or exclusive lock cannot be set, fcntl returns - * immediately with EACCES or EAGAIN. - */ -static int -test9(int fd, __unused int argc, const __unused char **argv) -{ - /* - * We create a child process to hold the lock which we will - * test. We use a pipe to communicate with the child. - */ - int pid; - int pfd[2]; - struct flock fl; - char ch; - int res; - - if (pipe(pfd) < 0) - err(1, "pipe"); - - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_RDLCK; - fl.l_whence = SEEK_SET; - - pid = fork(); - if (pid < 0) - err(1, "fork"); - - if (pid == 0) { - /* - * We are the child. We set a write lock and then - * write one byte back to the parent to tell it. The - * parent will kill us when its done. - */ - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_SETLK (child)"); - if (write(pfd[1], "a", 1) < 0) - err(1, "writing to pipe (child)"); - pause(); - exit(0); - } - - /* - * Wait until the child has set its lock and then perform the - * test. - */ - if (read(pfd[0], &ch, 1) != 1) - err(1, "reading from pipe (child)"); - - /* - * fcntl should wait until the alarm and then return -1 with - * errno set to EINTR. - */ - printf("9 - F_SETLK exclusive lock on share locked region: "); - - fl.l_type = F_WRLCK; - res = fcntl(fd, F_SETLK, &fl); - kill(pid, SIGTERM); - safe_waitpid(pid); - close(pfd[0]); - close(pfd[1]); - - FAIL(res == 0); - FAIL(errno != EACCES && errno != EAGAIN); - - SUCCEED; -} - -/* - * Test 10 - trying to set bogus pid or sysid values - * - * The l_pid and l_sysid fields are only used with F_GETLK to return - * the process ID of the process holding a blocking lock and the - * system ID of the system that owns that process - */ -static int -test10(int fd, __unused int argc, const __unused char **argv) -{ - /* - * We create a child process to hold the lock which we will - * test. We use a pipe to communicate with the child. - */ - int pid; - int pfd[2]; - struct flock fl; - char ch; - - if (pipe(pfd) < 0) - err(1, "pipe"); - - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - fl.l_pid = 9999; -#ifdef HAVE_SYSID - fl.l_sysid = 9999; -#endif - - pid = fork(); - if (pid < 0) - err(1, "fork"); - - if (pid == 0) { - /* - * We are the child. We set a write lock and then - * write one byte back to the parent to tell it. The - * parent will kill us when its done. - */ - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_SETLK (child)"); - if (write(pfd[1], "a", 1) < 0) - err(1, "writing to pipe (child)"); - pause(); - exit(0); - } - - /* - * Wait until the child has set its lock and then perform the - * test. - */ - if (read(pfd[0], &ch, 1) != 1) - err(1, "reading from pipe (child)"); - - printf("10 - trying to set bogus pid or sysid values: "); - - if (fcntl(fd, F_GETLK, &fl) < 0) - err(1, "F_GETLK"); - - kill(pid, SIGTERM); - safe_waitpid(pid); - close(pfd[0]); - close(pfd[1]); - - FAIL(fl.l_pid != pid); -#ifdef HAVE_SYSID - FAIL(fl.l_sysid != 0); -#endif - - SUCCEED; -} - -/* - * Test 11 - remote locks - * - * XXX temporary interface which will be removed when the kernel lockd - * is added. - */ -static int -test11(int fd, __unused int argc, const __unused char **argv) -{ -#ifdef F_SETLK_REMOTE - struct flock fl; - int res; - - if (geteuid() != 0) - return 0; - - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - fl.l_pid = 9999; - fl.l_sysid = 1001; - - printf("11 - remote locks: "); - - res = fcntl(fd, F_SETLK_REMOTE, &fl); - FAIL(res != 0); - - fl.l_sysid = 1002; - res = fcntl(fd, F_SETLK_REMOTE, &fl); - FAIL(res == 0); - FAIL(errno != EACCES && errno != EAGAIN); - - res = fcntl(fd, F_GETLK, &fl); - FAIL(res != 0); - FAIL(fl.l_pid != 9999); - FAIL(fl.l_sysid != 1001); - - fl.l_type = F_UNLCK; - fl.l_sysid = 1001; - fl.l_start = 0; - fl.l_len = 0; - res = fcntl(fd, F_SETLK_REMOTE, &fl); - FAIL(res != 0); - - fl.l_pid = 1234; - fl.l_sysid = 1001; - fl.l_start = 0; - fl.l_len = 1; - fl.l_whence = SEEK_SET; - fl.l_type = F_RDLCK; - res = fcntl(fd, F_SETLK_REMOTE, &fl); - FAIL(res != 0); - - fl.l_sysid = 1002; - res = fcntl(fd, F_SETLK_REMOTE, &fl); - FAIL(res != 0); - - fl.l_type = F_UNLCKSYS; - fl.l_sysid = 1001; - res = fcntl(fd, F_SETLK_REMOTE, &fl); - FAIL(res != 0); - - fl.l_type = F_WRLCK; - res = fcntl(fd, F_GETLK, &fl); - FAIL(res != 0); - FAIL(fl.l_pid != 1234); - FAIL(fl.l_sysid != 1002); - - fl.l_type = F_UNLCKSYS; - fl.l_sysid = 1002; - res = fcntl(fd, F_SETLK_REMOTE, &fl); - FAIL(res != 0); - - SUCCEED; -#else - return 0; -#endif -} - -/* - * Test 12 - F_SETLKW on locked region which is then unlocked - * - * If a shared or exclusive lock is blocked by other locks, the - * process waits until the request can be satisfied. - */ -static int -test12(int fd, __unused int argc, const __unused char **argv) -{ - /* - * We create a child process to hold the lock which we will - * test. We use a pipe to communicate with the child. - */ - int pid; - int pfd[2]; - struct flock fl; - char ch; - int res; - - if (pipe(pfd) < 0) - err(1, "pipe"); - - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - - pid = fork(); - if (pid < 0) - err(1, "fork"); - - if (pid == 0) { - /* - * We are the child. We set a write lock and then - * write one byte back to the parent to tell it. The - * parent will kill us when its done. - */ - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_SETLK (child)"); - if (write(pfd[1], "a", 1) < 0) - err(1, "writing to pipe (child)"); - - sleep(1); - exit(0); - } - - /* - * Wait until the child has set its lock and then perform the - * test. - */ - if (read(pfd[0], &ch, 1) != 1) - err(1, "reading from pipe (child)"); - - /* - * fcntl should wait until the alarm and then return -1 with - * errno set to EINTR. - */ - printf("12 - F_SETLKW on locked region which is then unlocked: "); - - //alarm(1); - - res = fcntl(fd, F_SETLKW, &fl); - kill(pid, SIGTERM); - safe_waitpid(pid); - close(pfd[0]); - close(pfd[1]); - FAIL(res != 0); - - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_UNLCK; - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_UNLCK"); - - SUCCEED; -} - -/* - * Test 13 - F_SETLKW on locked region, race with owner - * - * If a shared or exclusive lock is blocked by other locks, the - * process waits until the request can be satisfied. - */ -static int -test13(int fd, __unused int argc, const __unused char **argv) -{ - /* - * We create a child process to hold the lock which we will - * test. We use a pipe to communicate with the child. - */ - int i; - int pid; - int pfd[2]; - struct flock fl; - char ch; - int res; - struct itimerval itv; - - printf("13 - F_SETLKW on locked region, race with owner: "); - fflush(stdout); - - for (i = 0; i < 100; i++) { - if (pipe(pfd) < 0) - err(1, "pipe"); - - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - - pid = fork(); - if (pid < 0) - err(1, "fork"); - - if (pid == 0) { - /* - * We are the child. We set a write lock and then - * write one byte back to the parent to tell it. The - * parent will kill us when its done. - */ - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_SETLK (child)"); - if (write(pfd[1], "a", 1) < 0) - err(1, "writing to pipe (child)"); - - usleep(1); - exit(0); - } - - /* - * Wait until the child has set its lock and then perform the - * test. - */ - while (read(pfd[0], &ch, 1) != 1) { - if (errno == EINTR) - continue; - err(1, "reading from pipe (child)"); - } - - /* - * fcntl should wait until the alarm and then return -1 with - * errno set to EINTR. - */ - itv.it_interval.tv_sec = 0; - itv.it_interval.tv_usec = 0; - itv.it_value.tv_sec = 0; - itv.it_value.tv_usec = 2; - setitimer(ITIMER_REAL, &itv, NULL); - - res = fcntl(fd, F_SETLKW, &fl); - kill(pid, SIGTERM); - safe_waitpid(pid); - close(pfd[0]); - close(pfd[1]); - FAIL(!(res == 0 || (res == -1 && errno == EINTR))); - - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_UNLCK; - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_UNLCK"); - } - SUCCEED; -} - -/* - * Test 14 - soak test - */ -static int -test14(int fd, int argc, const char **argv) -{ -#define CHILD_COUNT 20 - /* - * We create a set of child processes and let each one run - * through a random sequence of locks and unlocks. - */ - int i, j, id, id_base; - int pids[CHILD_COUNT], pid; - char buf[128]; - char tbuf[128]; - int map[128]; - char outbuf[512]; - struct flock fl; - struct itimerval itv; - int status; - - id_base = 0; - if (argc >= 2) - id_base = strtol(argv[1], NULL, 0); - - printf("14 - soak test: "); - fflush(stdout); - - for (i = 0; i < 128; i++) - map[i] = F_UNLCK; - - for (i = 0; i < CHILD_COUNT; i++) { - - pid = fork(); - if (pid < 0) - err(1, "fork"); - if (pid) { - /* - * Parent - record the pid and continue. - */ - pids[i] = pid; - continue; - } - - /* - * Child - do some work and exit. - */ - id = id_base + i; - srandom(getpid()); - - for (j = 0; j < 50; j++) { - int start, end, len; - int set, wrlock; - - do { - start = random() & 127; - end = random() & 127; - } while (end <= start); - - set = random() & 1; - wrlock = random() & 1; - - len = end - start; - fl.l_start = start; - fl.l_len = len; - fl.l_whence = SEEK_SET; - if (set) - fl.l_type = wrlock ? F_WRLCK : F_RDLCK; - else - fl.l_type = F_UNLCK; - - itv.it_interval.tv_sec = 0; - itv.it_interval.tv_usec = 0; - itv.it_value.tv_sec = 0; - itv.it_value.tv_usec = 3000; - setitimer(ITIMER_REAL, &itv, NULL); - - if (fcntl(fd, F_SETLKW, &fl) < 0) { - if (errno == EDEADLK || errno == EINTR) { - if (verbose) { - snprintf(outbuf, sizeof(outbuf), - "%d[%d]: %s [%d .. %d] %s\n", - id, j, - set ? (wrlock ? "write lock" - : "read lock") - : "unlock", start, end, - errno == EDEADLK - ? "deadlock" - : "interrupted"); - write(1, outbuf, - strlen(outbuf)); - } - continue; - } else { - perror("fcntl"); - } - } - - itv.it_interval.tv_sec = 0; - itv.it_interval.tv_usec = 0; - itv.it_value.tv_sec = 0; - itv.it_value.tv_usec = 0; - setitimer(ITIMER_REAL, &itv, NULL); - - if (verbose) { - snprintf(outbuf, sizeof(outbuf), - "%d[%d]: %s [%d .. %d] succeeded\n", - id, j, - set ? (wrlock ? "write lock" : "read lock") - : "unlock", start, end); - write(1, outbuf, strlen(outbuf)); - } - - if (set) { - if (wrlock) { - /* - * We got a write lock - write - * our ID to each byte that we - * managed to claim. - */ - for (i = start; i < end; i++) - map[i] = F_WRLCK; - memset(&buf[start], id, len); - if (pwrite(fd, &buf[start], len, - start) != len) { - printf("%d: short write\n", id); - exit(1); - } - } else { - /* - * We got a read lock - read - * the bytes which we claimed - * so that we can check that - * they don't change - * unexpectedly. - */ - for (i = start; i < end; i++) - map[i] = F_RDLCK; - if (pread(fd, &buf[start], len, - start) != len) { - printf("%d: short read\n", id); - exit(1); - } - } - } else { - for (i = start; i < end; i++) - map[i] = F_UNLCK; - } - - usleep(1000); - - /* - * Read back the whole region so that we can - * check that all the bytes we have some kind - * of claim to have the correct value. - */ - if (pread(fd, tbuf, sizeof(tbuf), 0) != sizeof(tbuf)) { - printf("%d: short read\n", id); - exit(1); - } - - for (i = 0; i < 128; i++) { - if (map[i] != F_UNLCK && buf[i] != tbuf[i]) { - snprintf(outbuf, sizeof(outbuf), - "%d: byte %d expected %d, " - "got %d\n", id, i, buf[i], tbuf[i]); - write(1, outbuf, strlen(outbuf)); - exit(1); - } - } - } - if (verbose) - printf("%d[%d]: done\n", id, j); - - exit(0); - } - - status = 0; - for (i = 0; i < CHILD_COUNT; i++) { - status += safe_waitpid(pids[i]); - } - if (status) - FAIL(status != 0); - - SUCCEED; -} - -/* - * Test 15 - flock(2) semantcs - * - * When a lock holder has a shared lock and attempts to upgrade that - * shared lock to exclusive, it must drop the shared lock before - * blocking on the exclusive lock. - * - * To test this, we first arrange for two shared locks on the file, - * and then attempt to upgrade one of them to exclusive. This should - * drop one of the shared locks and block. We interrupt the blocking - * lock request and examine the lock state of the file after dropping - * the other shared lock - there should be no active locks at this - * point. - */ -static int -test15(int fd, __unused int argc, const __unused char **argv) -{ -#ifdef LOCK_EX - /* - * We create a child process to hold the lock which we will - * test. We use a pipe to communicate with the child. - * - * Since we only have one file descriptors and lock ownership - * for flock(2) goes with the file descriptor, we use fcntl to - * set the child's shared lock. - */ - int pid; - int pfd[2]; - struct flock fl; - char ch; - int res; - - if (pipe(pfd) < 0) - err(1, "pipe"); - - pid = fork(); - if (pid < 0) - err(1, "fork"); - - if (pid == 0) { - /* - * We are the child. We set a shared lock and then - * write one byte back to the parent to tell it. The - * parent will kill us when its done. - */ - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_RDLCK; - fl.l_whence = SEEK_SET; - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "fcntl(F_SETLK) (child)"); - if (write(pfd[1], "a", 1) < 0) - err(1, "writing to pipe (child)"); - pause(); - exit(0); - } - - /* - * Wait until the child has set its lock and then perform the - * test. - */ - if (read(pfd[0], &ch, 1) != 1) - err(1, "reading from pipe (child)"); - - (void)dup(fd); - if (flock(fd, LOCK_SH) < 0) - err(1, "flock shared"); - - /* - * flock should wait until the alarm and then return -1 with - * errno set to EINTR. - */ - printf("15 - flock(2) semantics: "); - - alarm(1); - flock(fd, LOCK_EX); - - /* - * Kill the child to force it to drop its locks. - */ - kill(pid, SIGTERM); - safe_waitpid(pid); - - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - res = fcntl(fd, F_GETLK, &fl); - - close(pfd[0]); - close(pfd[1]); - FAIL(res != 0); - FAIL(fl.l_type != F_UNLCK); - - SUCCEED; -#else - return 0; -#endif -} - -struct test_ctx { - struct flock tc_fl; - int tc_fd; -}; - -static void * -test16_func(void *tc_in) -{ - uintptr_t error; - struct test_ctx *tc = tc_in; - - error = fcntl(tc->tc_fd, F_SETLKW, &tc->tc_fl); - - pthread_exit((void *)error); -} - -#define THREADS 10 - -/* - * Test 16 - F_SETLKW from two threads - * - * If two threads within a process are blocked on a lock and the lock - * is granted, make sure things are sane. - */ -static int -test16(int fd, __unused int argc, const __unused char **argv) -{ - /* - * We create a child process to hold the lock which we will - * test. We use a pipe to communicate with the child. - */ - int pid; - int pfd[2]; - struct test_ctx tc = { .tc_fd = fd }; - char ch; - int i; - int error; - pthread_t thr[THREADS]; - - if (pipe(pfd) < 0) - err(1, "pipe"); - - tc.tc_fl.l_start = 0; - tc.tc_fl.l_len = 0; - tc.tc_fl.l_type = F_WRLCK; - tc.tc_fl.l_whence = SEEK_SET; - - pid = fork(); - if (pid < 0) - err(1, "fork"); - - if (pid == 0) { - /* - * We are the child. We set a write lock and then - * write one byte back to the parent to tell it. The - * parent will kill us when its done. - */ - if (fcntl(fd, F_SETLK, &tc.tc_fl) < 0) - err(1, "F_SETLK (child)"); - if (write(pfd[1], "a", 1) < 0) - err(1, "writing to pipe (child)"); - pause(); - exit(0); - } - - /* - * Wait until the child has set its lock and then perform the - * test. - */ - if (read(pfd[0], &ch, 1) != 1) - err(1, "reading from pipe (child)"); - - /* - * fcntl should wait until the alarm and then return -1 with - * errno set to EINTR. - */ - printf("16 - F_SETLKW on locked region by two threads: "); - - for (i = 0; i < THREADS; i++) { - error = pthread_create(&thr[i], NULL, test16_func, &tc); - if (error) - err(1, "pthread_create"); - } - - /* - * Sleep, then kill the child. This makes me a little sad, but it's - * tricky to tell whether the threads are all really blocked by this - * point. - */ - sleep(1); - kill(pid, SIGTERM); - safe_waitpid(pid); - close(pfd[0]); - close(pfd[1]); - - for (i = 0; i < THREADS; i++) { - void *res; - error = pthread_join(thr[i], &res); - if (error) - err(1, "pthread_join"); - FAIL((uintptr_t)res != 0); - } - - SUCCEED; -} - -struct test { - int (*testfn)(int, int, const char **); /* function to perform the test */ - int num; /* test number */ - int intr; /* non-zero if the test interrupts a lock */ -}; - -static struct test tests[] = { - { test1, 1, 0 }, - { test2, 2, 0 }, - { test3, 3, 1 }, - { test4, 4, 0 }, - { test5, 5, 1 }, - { test6, 6, 1 }, - { test7, 7, 0 }, - { test8, 8, 0 }, - { test9, 9, 0 }, - { test10, 10, 0 }, - { test11, 11, 1 }, - { test12, 12, 0 }, - { test13, 13, 1 }, - { test14, 14, 0 }, - { test15, 15, 1 }, - { test16, 16, 1 }, -}; - -int -main(int argc, const char *argv[]) -{ - int testnum; - int fd; - int nointr; - unsigned i; - struct sigaction sa; - int test_argc; - const char **test_argv; - - if (argc < 2) { - errx(1, "usage: flock [test number] ..."); - } - - fd = make_file(argv[1], 1024); - if (argc >= 3) { - testnum = strtol(argv[2], NULL, 0); - test_argc = argc - 2; - test_argv = argv + 2; - } else { - testnum = 0; - test_argc = 0; - test_argv = 0; - } - - sa.sa_handler = ignore_alarm; - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - sigaction(SIGALRM, &sa, 0); - - nointr = 0; -#if defined(__FreeBSD__) && __FreeBSD_version < 800040 - { - /* - * FreeBSD with userland NLM can't interrupt a blocked - * lock request on an NFS mounted filesystem. - */ - struct statfs st; - fstatfs(fd, &st); - nointr = !strcmp(st.f_fstypename, "nfs"); - } -#endif - - for (i = 0; i < nitems(tests); i++) { - if (tests[i].intr && nointr) - continue; - if (!testnum || tests[i].num == testnum) - tests[i].testfn(fd, test_argc, test_argv); - } - - return 0; -} diff --git a/tools/regression/file/ftruncate/Makefile b/tools/regression/file/ftruncate/Makefile deleted file mode 100644 index 40b753e..0000000 --- a/tools/regression/file/ftruncate/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# $FreeBSD$ - -PROG= ftruncate -MAN= -WARNS?= 2 - -.include diff --git a/tools/regression/file/ftruncate/ftruncate.c b/tools/regression/file/ftruncate/ftruncate.c deleted file mode 100644 index aebcdcd..0000000 --- a/tools/regression/file/ftruncate/ftruncate.c +++ /dev/null @@ -1,177 +0,0 @@ -/*- - * Copyright (c) 2006 Robert N. M. Watson - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -/* - * Very simple regression test. - * - * Future tests that might be of interest: - * - * - Make sure we get EISDIR on a directory. - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -/* - * Select various potentially interesting lengths at and around power of 2 - * edges. - */ -static off_t lengths[] = {0, 1, 2, 3, 4, 127, 128, 129, 511, 512, 513, 1023, - 1024, 1025, 2047, 2048, 2049, 4095, 4096, 4097, 8191, 8192, 8193, 16383, - 16384, 16385}; -static int lengths_count = sizeof(lengths) / sizeof(off_t); - -int -main(int argc, char *argv[]) -{ - int error, fd, fds[2], i, read_only_fd; - char path[PATH_MAX]; - struct stat sb; - size_t size; - off_t len; - char ch; - - /* - * Tests using a writable temporary file: grow and then shrink a file - * using ftruncate and various lengths. Make sure that a negative - * file length is rejected. Make sure that when we grow the file, - * bytes now in the range of the file size return 0. - * - * Save a read-only reference to the file to use later for read-only - * descriptor tests. - */ - snprintf(path, PATH_MAX, "/tmp/ftruncate.XXXXXXXXXXXXX"); - fd = mkstemp(path); - if (fd < 0) - err(-1, "makestemp"); - read_only_fd = open(path, O_RDONLY); - if (read_only_fd < 0) { - error = errno; - (void)unlink(path); - errno = error; - err(-1, "open(%s, O_RDONLY)", path); - } - (void)unlink(path); - - if (ftruncate(fd, -1) == 0) - errx(-1, "ftruncate(fd, -1) succeeded"); - if (errno != EINVAL) - err(-1, "ftruncate(fd, -1) returned wrong error"); - - for (i = 0; i < lengths_count; i++) { - len = lengths[i]; - if (ftruncate(fd, len) < 0) - err(-1, "ftruncate(%llu) up", len); - if (fstat(fd, &sb) < 0) - err(-1, "stat"); - if (sb.st_size != len) - errx(-1, "fstat(%llu) returned len %llu up", len, - sb.st_size); - if (len != 0) { - size = pread(fd, &ch, sizeof(ch), len - 1); - if (size < 0) - err(-1, "pread on len %llu up", len); - if (size != sizeof(ch)) - errx(-1, "pread len %llu size %jd up", - len, (intmax_t)size); - if (ch != 0) - errx(-1, - "pread length %llu size %jd ch %d up", - len, (intmax_t)size, ch); - } - } - - for (i = lengths_count - 1; i >= 0; i--) { - len = lengths[i]; - if (ftruncate(fd, len) < 0) - err(-1, "ftruncate(%llu) down", len); - if (fstat(fd, &sb) < 0) - err(-1, "stat"); - if (sb.st_size != len) - errx(-1, "fstat(%llu) returned %llu down", len, - sb.st_size); - } - close(fd); - - /* - * Make sure that a read-only descriptor can't be truncated. - */ - if (ftruncate(read_only_fd, 0) == 0) - errx(-1, "ftruncate(read_only_fd) succeeded"); - if (errno != EINVAL) - err(-1, "ftruncate(read_only_fd) returned wrong error"); - close(read_only_fd); - - /* - * Make sure that ftruncate on sockets doesn't work. - */ - fd = socket(PF_UNIX, SOCK_STREAM, 0); - if (fd < 0) - err(-1, "socket(PF_UNIX, SOCK_STREAM, 0)"); - if (ftruncate(fd, 0) == 0) - errx(-1, "ftruncate(socket) succeeded"); - if (errno != EINVAL) - err(-1, "ftruncate(socket) returned wrong error"); - close(fd); - - /* - * Make sure that ftruncate on pipes doesn't work. - */ - if (pipe(fds) < 0) - err(-1, "pipe"); - if (ftruncate(fds[0], 0) == 0) - errx(-1, "ftruncate(pipe) succeeded"); - if (errno != EINVAL) - err(-1, "ftruncate(pipe) returned wrong error"); - close(fds[0]); - close(fds[1]); - - /* - * Make sure that ftruncate on kqueues doesn't work. - */ - fd = kqueue(); - if (fd < 0) - err(-1, "kqueue"); - if (ftruncate(fds[0], 0) == 0) - errx(-1, "ftruncate(kqueue) succeeded"); - if (errno != EINVAL) - err(-1, "ftruncate(kqueue) returned wrong error"); - close(fd); - - return (0); -} diff --git a/tools/regression/file/newfileops_on_fork/Makefile b/tools/regression/file/newfileops_on_fork/Makefile deleted file mode 100644 index be0c5fe..0000000 --- a/tools/regression/file/newfileops_on_fork/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# $FreeBSD$ - -PROG= newfileops_on_fork -MAN= -WARNS?= 6 -LDFLAGS= -lpthread - -.include diff --git a/tools/regression/file/newfileops_on_fork/newfileops_on_fork.c b/tools/regression/file/newfileops_on_fork/newfileops_on_fork.c deleted file mode 100644 index 8713a82..0000000 --- a/tools/regression/file/newfileops_on_fork/newfileops_on_fork.c +++ /dev/null @@ -1,121 +0,0 @@ -/*- - * Copyright (c) 2009 Robert N. M. Watson - * All rights reserved. - * - * This software was developed at the University of Cambridge Computer - * Laboratory with support from a grant from Google, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -/* - * When a multi-threaded application calls fork(2) from one thread while - * another thread is blocked in accept(2), we prefer that the file descriptor - * to be returned by accept(2) not appear in the child process. Test this by - * creating a thread blocked in accept(2), then forking a child and seeing if - * the fd it would have returned is defined in the child or not. - */ - -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include - -#define PORT 9000 - -static int listen_fd; - -static void * -do_accept(__unused void *arg) -{ - int accept_fd; - - accept_fd = accept(listen_fd, NULL, NULL); - if (accept_fd < 0) - err(-1, "accept"); - - return (NULL); -} - -static void -do_fork(void) -{ - int pid; - - pid = fork(); - if (pid < 0) - err(-1, "fork"); - if (pid > 0) { - waitpid(pid, NULL, 0); - exit(0); - } - - /* - * We will call ftruncate(2) on the next available file descriptor, - * listen_fd+1, and get back EBADF if it's not a valid descriptor, - * and EINVAL if it is. This (currently) works fine in practice. - */ - if (ftruncate(listen_fd + 1, 0 < 0)) { - if (errno == EBADF) - exit(0); - else if (errno == EINVAL) - errx(-1, "file descriptor still open in child"); - else - err(-1, "unexpected error"); - } else - errx(-1, "ftruncate succeeded"); -} - -int -main(__unused int argc, __unused char *argv[]) -{ - struct sockaddr_in sin; - pthread_t accept_thread; - - listen_fd = socket(PF_INET, SOCK_STREAM, 0); - if (listen_fd < 0) - err(-1, "socket"); - bzero(&sin, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_len = sizeof(sin); - sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sin.sin_port = htons(PORT); - if (bind(listen_fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) - err(-1, "bind"); - if (listen(listen_fd, -1) <0) - err(-1, "listen"); - if (pthread_create(&accept_thread, NULL, do_accept, NULL) != 0) - err(-1, "pthread_create"); - sleep(1); /* Easier than using a CV. */; - do_fork(); - exit(0); -} -- cgit v1.1