Index: user/ngie/more-tests/etc/mtree/BSD.tests.dist =================================================================== --- user/ngie/more-tests/etc/mtree/BSD.tests.dist (revision 281431) +++ user/ngie/more-tests/etc/mtree/BSD.tests.dist (revision 281432) @@ -1,578 +1,580 @@ # $FreeBSD$ # # Please see the file src/etc/mtree/README before making changes to this file. # /set type=dir uname=root gname=wheel mode=0755 . bin cat .. chown .. date .. expr .. mv .. pax .. pkill .. sh builtins .. errors .. execution .. expansion .. parameters .. parser .. set-e .. .. sleep .. test .. .. cddl lib .. sbin .. usr.bin .. usr.sbin dtrace common aggs .. arithmetic .. arrays .. assocs .. begin .. bitfields .. buffering .. builtinvar .. cg .. clauses .. cpc .. decls .. drops .. dtraceUtil .. end .. enum .. error .. exit .. fbtprovider .. funcs .. grammar .. include .. inline .. io .. ip .. java_api .. json .. lexer .. llquantize .. mdb .. mib .. misc .. multiaggs .. offsetof .. operators .. pid .. plockstat .. pointers .. pragma .. predicates .. preprocessor .. print .. printa .. printf .. privs .. probes .. proc .. profile-n .. providers .. raise .. rates .. safety .. scalars .. sched .. scripting .. sdt .. sizeof .. speculation .. stability .. stack .. stackdepth .. stop .. strlen .. strtoll .. struct .. syscall .. sysevent .. tick-n .. trace .. tracemem .. translators .. typedef .. types .. uctf .. union .. usdt .. ustack .. vars .. version .. .. .. .. .. etc rc.d .. .. games .. gnu lib .. usr.bin diff .. .. .. lib atf libatf-c detail .. .. libatf-c++ detail .. .. test-programs .. .. libc c063 .. db .. gen execve .. posix_spawn .. .. hash data .. .. inet .. locale .. net getaddrinfo data .. .. .. regex data .. .. ssp .. stdio .. stdlib .. string .. sys .. time .. tls dso .. .. termios .. ttyio .. .. libcrypt .. libmp .. libnv .. libpam .. libproc .. librt .. libthr dlopen .. .. libutil .. msun .. .. libexec atf atf-check .. atf-sh .. .. rtld-elf .. .. sbin dhclient .. devd .. growfs .. ifconfig .. mdconfig .. .. secure lib .. libexec .. usr.bin .. usr.sbin .. .. share examples tests atf .. plain .. .. .. .. sys + file + .. kern .. kqueue .. mqueue .. netinet .. opencrypto .. posixshm .. pjdfstest chflags .. chmod .. chown .. ftruncate .. granular .. link .. mkdir .. mkfifo .. mknod .. open .. rename .. rmdir .. symlink .. truncate .. unlink .. .. socket .. vfs .. .. usr.bin apply .. basename .. bmake archives fmt_44bsd .. fmt_44bsd_mod .. fmt_oldbsd .. .. basic t0 .. t1 .. t2 .. t3 .. .. execution ellipsis .. empty .. joberr .. plus .. .. shell builtin .. meta .. path .. path_select .. replace .. select .. .. suffixes basic .. src_wild1 .. src_wild2 .. .. syntax directive-t0 .. enl .. funny-targets .. semi .. .. sysmk t0 2 1 .. .. mk .. .. t1 2 1 .. .. mk .. .. t2 2 1 .. .. mk .. .. .. variables modifier_M .. modifier_t .. opt_V .. t0 .. .. .. calendar .. cmp .. comm .. cut .. dirname .. file2c .. grep .. gzip .. join .. jot .. lastcomm .. m4 .. mkimg .. ncal .. opensm .. printf .. sed regress.multitest.out .. .. timeout .. tr .. truncate .. units .. uudecode .. uuencode .. xargs .. yacc yacc .. .. .. usr.sbin etcupdate .. newsyslog .. nmtree .. pw .. sa .. .. .. # vim: set expandtab ts=4 sw=4: Index: user/ngie/more-tests/tests/sys/Makefile =================================================================== --- user/ngie/more-tests/tests/sys/Makefile (revision 281431) +++ user/ngie/more-tests/tests/sys/Makefile (revision 281432) @@ -1,19 +1,20 @@ # $FreeBSD$ .include TESTSDIR= ${TESTSBASE}/sys +TESTS_SUBDIRS+= file TESTS_SUBDIRS+= kern TESTS_SUBDIRS+= kqueue TESTS_SUBDIRS+= mqueue TESTS_SUBDIRS+= netinet TESTS_SUBDIRS+= opencrypto TESTS_SUBDIRS+= posixshm TESTS_SUBDIRS+= sockets TESTS_SUBDIRS+= vfs # Items not integrated into kyua runs by default SUBDIR+= pjdfstest .include Index: user/ngie/more-tests/tests/sys/file/closefrom_test.c =================================================================== --- user/ngie/more-tests/tests/sys/file/closefrom_test.c (nonexistent) +++ user/ngie/more-tests/tests/sys/file/closefrom_test.c (revision 281432) @@ -0,0 +1,275 @@ +/*- + * 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 +#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(_PATH_DEVNULL, O_RDONLY); + if (fd < 0) + fail_err("open(\" "_PATH_DEVNULL" \")"); + return (fd); +} + +int +main(void) +{ + struct shared_info *info; + pid_t pid; + int fd, i, start; + + printf("1..15\n"); + + /* We better start up with fd's 0, 1, and 2 open. */ + start = devnull(); + if (start == -1) + fail("open", "bad descriptor %d", start); + ok("open"); + + /* Make sure highest_fd() works. */ + fd = highest_fd(); + if (start != fd) + fail("highest_fd", "bad descriptor %d != %d", start, fd); + ok("highest_fd"); + + /* Try to use closefrom() for just closing fd 3. */ + closefrom(start + 1); + fd = highest_fd(); + if (fd != start) + 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 != start + 16) + 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); +} Property changes on: user/ngie/more-tests/tests/sys/file/closefrom_test.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/ngie/more-tests/tests/sys/file/dup_test.c =================================================================== --- user/ngie/more-tests/tests/sys/file/dup_test.c (nonexistent) +++ user/ngie/more-tests/tests/sys/file/dup_test.c (revision 281432) @@ -0,0 +1,386 @@ +/* + * $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); +} Property changes on: user/ngie/more-tests/tests/sys/file/dup_test.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: user/ngie/more-tests/tests/sys/file/fcntlflags_test.c =================================================================== --- user/ngie/more-tests/tests/sys/file/fcntlflags_test.c (nonexistent) +++ user/ngie/more-tests/tests/sys/file/fcntlflags_test.c (revision 281432) @@ -0,0 +1,110 @@ +/*- + * 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); +} Property changes on: user/ngie/more-tests/tests/sys/file/fcntlflags_test.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/ngie/more-tests/tests/sys/file/flock_helper.c =================================================================== --- user/ngie/more-tests/tests/sys/file/flock_helper.c (nonexistent) +++ user/ngie/more-tests/tests/sys/file/flock_helper.c (revision 281432) @@ -0,0 +1,1598 @@ +/*- + * 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; +} Property changes on: user/ngie/more-tests/tests/sys/file/flock_helper.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: user/ngie/more-tests/tests/sys/file/flock_test.sh =================================================================== --- user/ngie/more-tests/tests/sys/file/flock_test.sh (nonexistent) +++ user/ngie/more-tests/tests/sys/file/flock_test.sh (revision 281432) @@ -0,0 +1,57 @@ +#!/bin/sh +# +# Copyright 2014 EMC Corp. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT +# OWNER 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$ + +# Testcase # 11 is racy; uses an undocumented kernel interface for testing +# locking +# Testcase # 16 is racy/doesn't handle EINTR properly +last_testcase=16 + +echo "1..$last_testcase" + +for n in `seq 1 $last_testcase`; do + todomsg="" + + if [ $n -eq 11 ]; then + todomsg=" # TODO: racy testcase" + # Test 16 fails: + # F_SETLKW on locked region by two threads: FAIL ((uintptr_t)res != 0) + elif [ $n -eq 16 ]; then + todomsg=" # TODO: racy testcase (doesn't handle EINTR properly)" + fi + + $(dirname $0)/flock_helper . $n | grep -q SUCCEED + if [ $? -eq 0 ]; then + echo "ok $n$todomsg" + else + echo "not ok $n$todomsg" + fi +done Property changes on: user/ngie/more-tests/tests/sys/file/flock_test.sh ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/ngie/more-tests/tests/sys/file/ftruncate_test.c =================================================================== --- user/ngie/more-tests/tests/sys/file/ftruncate_test.c (nonexistent) +++ user/ngie/more-tests/tests/sys/file/ftruncate_test.c (revision 281432) @@ -0,0 +1,177 @@ +/*- + * 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; + ssize_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, "mkstemp"); + 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(%jd) up", (intmax_t)len); + if (fstat(fd, &sb) < 0) + err(-1, "stat"); + if (sb.st_size != len) + errx(-1, "fstat with len=%jd returned len %jd up", + (intmax_t)len, (intmax_t)sb.st_size); + if (len != 0) { + size = pread(fd, &ch, sizeof(ch), len - 1); + if (size < 0) + err(-1, "pread on len %jd up", (intmax_t)len); + if (size != sizeof(ch)) + errx(-1, "pread len %jd size %jd up", + (intmax_t)len, (intmax_t)size); + if (ch != 0) + errx(-1, + "pread length %jd size %jd ch %d up", + (intmax_t)len, (intmax_t)size, ch); + } + } + + for (i = lengths_count - 1; i >= 0; i--) { + len = lengths[i]; + if (ftruncate(fd, len) < 0) + err(-1, "ftruncate(%jd) down", (intmax_t)len); + if (fstat(fd, &sb) < 0) + err(-1, "stat"); + if (sb.st_size != len) + errx(-1, "fstat(%jd) returned %jd down", (intmax_t)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); +} Property changes on: user/ngie/more-tests/tests/sys/file/ftruncate_test.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: user/ngie/more-tests/tests/sys/file/newfileops_on_fork_test.c =================================================================== --- user/ngie/more-tests/tests/sys/file/newfileops_on_fork_test.c (nonexistent) +++ user/ngie/more-tests/tests/sys/file/newfileops_on_fork_test.c (revision 281432) @@ -0,0 +1,121 @@ +/*- + * 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); +} Property changes on: user/ngie/more-tests/tests/sys/file/newfileops_on_fork_test.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/ngie/more-tests/tools/regression/file/newfileops_on_fork/newfileops_on_fork.c =================================================================== --- user/ngie/more-tests/tools/regression/file/newfileops_on_fork/newfileops_on_fork.c (revision 281431) +++ user/ngie/more-tests/tools/regression/file/newfileops_on_fork/newfileops_on_fork.c (nonexistent) @@ -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); -} Property changes on: user/ngie/more-tests/tools/regression/file/newfileops_on_fork/newfileops_on_fork.c ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: user/ngie/more-tests/tools/regression/file/newfileops_on_fork/Makefile =================================================================== --- user/ngie/more-tests/tools/regression/file/newfileops_on_fork/Makefile (revision 281431) +++ user/ngie/more-tests/tools/regression/file/newfileops_on_fork/Makefile (nonexistent) @@ -1,8 +0,0 @@ -# $FreeBSD$ - -PROG= newfileops_on_fork -MAN= -WARNS?= 6 -LDFLAGS= -lpthread - -.include Property changes on: user/ngie/more-tests/tools/regression/file/newfileops_on_fork/Makefile ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: user/ngie/more-tests/tools/regression/file/ftruncate/ftruncate.c =================================================================== --- user/ngie/more-tests/tools/regression/file/ftruncate/ftruncate.c (revision 281431) +++ user/ngie/more-tests/tools/regression/file/ftruncate/ftruncate.c (nonexistent) @@ -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); -} Property changes on: user/ngie/more-tests/tools/regression/file/ftruncate/ftruncate.c ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: user/ngie/more-tests/tools/regression/file/ftruncate/Makefile =================================================================== --- user/ngie/more-tests/tools/regression/file/ftruncate/Makefile (revision 281431) +++ user/ngie/more-tests/tools/regression/file/ftruncate/Makefile (nonexistent) @@ -1,7 +0,0 @@ -# $FreeBSD$ - -PROG= ftruncate -MAN= -WARNS?= 2 - -.include Property changes on: user/ngie/more-tests/tools/regression/file/ftruncate/Makefile ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: user/ngie/more-tests/tools/regression/file/closefrom/closefrom.c =================================================================== --- user/ngie/more-tests/tools/regression/file/closefrom/closefrom.c (revision 281431) +++ user/ngie/more-tests/tools/regression/file/closefrom/closefrom.c (nonexistent) @@ -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); -} Property changes on: user/ngie/more-tests/tools/regression/file/closefrom/closefrom.c ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: user/ngie/more-tests/tools/regression/file/closefrom/closefrom.t =================================================================== --- user/ngie/more-tests/tools/regression/file/closefrom/closefrom.t (revision 281431) +++ user/ngie/more-tests/tools/regression/file/closefrom/closefrom.t (nonexistent) @@ -1,10 +0,0 @@ -#!/bin/sh -# $FreeBSD$ - -cd `dirname $0` - -executable=`basename $0 .t` - -make $executable 2>&1 > /dev/null - -exec ./$executable Property changes on: user/ngie/more-tests/tools/regression/file/closefrom/closefrom.t ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: user/ngie/more-tests/tools/regression/file/closefrom/Makefile =================================================================== --- user/ngie/more-tests/tools/regression/file/closefrom/Makefile (revision 281431) +++ user/ngie/more-tests/tools/regression/file/closefrom/Makefile (nonexistent) @@ -1,9 +0,0 @@ -# $FreeBSD$ - -PROG= closefrom -MAN= -WARNS?= 6 -DPADD= ${LIBUTIL} -LDADD= -lutil - -.include Property changes on: user/ngie/more-tests/tools/regression/file/closefrom/Makefile ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: user/ngie/more-tests/tools/regression/file/flock/flock.c =================================================================== --- user/ngie/more-tests/tools/regression/file/flock/flock.c (revision 281431) +++ user/ngie/more-tests/tools/regression/file/flock/flock.c (nonexistent) @@ -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; -} Property changes on: user/ngie/more-tests/tools/regression/file/flock/flock.c ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: user/ngie/more-tests/tools/regression/file/flock/Makefile =================================================================== --- user/ngie/more-tests/tools/regression/file/flock/Makefile (revision 281431) +++ user/ngie/more-tests/tools/regression/file/flock/Makefile (nonexistent) @@ -1,9 +0,0 @@ -# $FreeBSD$ - -PROG= flock -MAN= -WARNS?= 6 -DPADD= ${LIBPTHREAD} -LDADD= -lpthread - -.include Property changes on: user/ngie/more-tests/tools/regression/file/flock/Makefile ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: user/ngie/more-tests/tools/regression/file/dup/dup.t =================================================================== --- user/ngie/more-tests/tools/regression/file/dup/dup.t (revision 281431) +++ user/ngie/more-tests/tools/regression/file/dup/dup.t (nonexistent) @@ -1,10 +0,0 @@ -#!/bin/sh -# $FreeBSD$ - -cd `dirname $0` - -executable=`basename $0 .t` - -make $executable 2>&1 > /dev/null - -exec ./$executable Property changes on: user/ngie/more-tests/tools/regression/file/dup/dup.t ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: user/ngie/more-tests/tools/regression/file/dup/Makefile =================================================================== --- user/ngie/more-tests/tools/regression/file/dup/Makefile (revision 281431) +++ user/ngie/more-tests/tools/regression/file/dup/Makefile (nonexistent) @@ -1,7 +0,0 @@ -# $FreeBSD$ - -PROG= dup -MAN= -WARNS?= 6 - -.include Property changes on: user/ngie/more-tests/tools/regression/file/dup/Makefile ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: user/ngie/more-tests/tools/regression/file/dup/dup.c =================================================================== --- user/ngie/more-tests/tools/regression/file/dup/dup.c (revision 281431) +++ user/ngie/more-tests/tools/regression/file/dup/dup.c (nonexistent) @@ -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); -} Property changes on: user/ngie/more-tests/tools/regression/file/dup/dup.c ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: user/ngie/more-tests/tools/regression/file/fcntlflags/fcntlflags.c =================================================================== --- user/ngie/more-tests/tools/regression/file/fcntlflags/fcntlflags.c (revision 281431) +++ user/ngie/more-tests/tools/regression/file/fcntlflags/fcntlflags.c (nonexistent) @@ -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); -} Property changes on: user/ngie/more-tests/tools/regression/file/fcntlflags/fcntlflags.c ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: user/ngie/more-tests/tools/regression/file/fcntlflags/fcntlflags.t =================================================================== --- user/ngie/more-tests/tools/regression/file/fcntlflags/fcntlflags.t (revision 281431) +++ user/ngie/more-tests/tools/regression/file/fcntlflags/fcntlflags.t (nonexistent) @@ -1,10 +0,0 @@ -#!/bin/sh -# $FreeBSD$ - -cd `dirname $0` - -executable=`basename $0 .t` - -make $executable 2>&1 > /dev/null - -exec ./$executable Property changes on: user/ngie/more-tests/tools/regression/file/fcntlflags/fcntlflags.t ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: user/ngie/more-tests/tools/regression/file/fcntlflags/Makefile =================================================================== --- user/ngie/more-tests/tools/regression/file/fcntlflags/Makefile (revision 281431) +++ user/ngie/more-tests/tools/regression/file/fcntlflags/Makefile (nonexistent) @@ -1,7 +0,0 @@ -# $FreeBSD$ - -PROG= fcntlflags -MAN= -WARNS?= 6 - -.include Property changes on: user/ngie/more-tests/tools/regression/file/fcntlflags/Makefile ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property