diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a810f5d5..d49749e8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -19,7 +19,7 @@ jobs: sudo apt-get install -y \ libpopt-dev ncurses-dev automake autoconf pkgconf \ lua5.3 liblua5.3-dev libmunge-dev libwrap0-dev libcap-dev \ - libattr1-dev dbench attr scrub ${{matrix.cc}} + libattr1-dev dbench attr scrub valgrind ${{matrix.cc}} - name: Display configuration run: | echo "C compiler:" @@ -38,6 +38,10 @@ jobs: run: make - name: make check run: make check + - name: valgrind some unit tests + run: scripts/check-valgrind.sh + - name: sudo some unit tests + run: scripts/check-root.sh - name: check with linux/9p run: sudo make check -C tests/kern - name: make distcheck diff --git a/configure.ac b/configure.ac index b95072a5..bf592aeb 100644 --- a/configure.ac +++ b/configure.ac @@ -7,6 +7,7 @@ AC_CONFIG_AUX_DIR([config]) AC_CONFIG_MACRO_DIR([config]) AC_CONFIG_SRCDIR([NEWS]) AC_CANONICAL_HOST +AC_REQUIRE_AUX_FILE([tap-driver.sh]) X_AC_EXPAND_INSTALL_DIRS ## @@ -217,6 +218,7 @@ RRA_WITH_SYSTEMD_UNITDIR AC_CONFIG_FILES( \ Makefile \ diod.spec \ + src/libtap/Makefile \ src/libdiod/Makefile \ src/liblsd/Makefile \ src/libnpfs/Makefile \ diff --git a/scripts/check-root.sh b/scripts/check-root.sh new file mode 100755 index 00000000..397c0a04 --- /dev/null +++ b/scripts/check-root.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +die () { + echo "$@" >&2 + exit 1 +} + +sudo -n /bin/true || die "passwordless sudo is required to run privileged tests" + +sudo -n make -C src/libnpfs check TESTS="\ + test_capability.t \ + test_setfsuid.t \ + test_setgroups.t \ + test_setreuid.t" || die "test failed" + +sudo -n make -C src/daemon check TESTS="\ + test_multiuser.t" || die "test failed" diff --git a/scripts/check-valgrind.sh b/scripts/check-valgrind.sh new file mode 100755 index 00000000..fa5033e3 --- /dev/null +++ b/scripts/check-valgrind.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +die () { + echo "$@" >&2 + exit 1 +} + +which valgrind >/dev/null 2>&1 || die "valgrind is missing" + +TESTS="src/libnpfs/test_encoding.t \ + src/libnpfs/test_fidpool.t \ + src/libnpclient/test_simple.t \ + src/libdiod/test_configfile.t \ + src/daemon/test_read.t \ + src/daemon/test_directory.t" + +exit_rc=0 + +for test in $TESTS; do + valgrind \ + --tool=memcheck \ + --leak-check=full \ + --error-exitcode=1 \ + --leak-resolution=med \ + --trace-children=no \ + --child-silent-after-fork=yes \ + $test + test $? -eq 0 || exit_rc=1 +done + +exit $exit_rc diff --git a/scripts/install-deps-deb.sh b/scripts/install-deps-deb.sh index 990748da..e81104c3 100755 --- a/scripts/install-deps-deb.sh +++ b/scripts/install-deps-deb.sh @@ -8,8 +8,9 @@ apt install \ libc6-dev \ libpopt-dev \ libncurses-dev \ + libcap2-dev \ lua5.1 \ liblua5.1-dev \ - valgrind + valgrind \ # to build test DEBs you need devscripts and debhelper too diff --git a/src/Makefile.am b/src/Makefile.am index 03a96415..1a1f7e47 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,5 @@ SUBDIRS = \ + libtap \ liblsd \ libnpfs \ libnpclient \ diff --git a/src/cmd/Makefile.am b/src/cmd/Makefile.am index 71ed9da5..2ccd98dc 100644 --- a/src/cmd/Makefile.am +++ b/src/cmd/Makefile.am @@ -43,3 +43,18 @@ diodshowmount_SOURCES = diodshowmount.c $(common_sources) dioddate_LDADD = $(common_ldadd) dioddate_SOURCES = dioddate.c $(common_sources) + +TESTS = \ + test_opt.t + +check_PROGRAMS = $(TESTS) + +TEST_EXTENSIONS = .t +T_LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \ + $(top_srcdir)/config/tap-driver.sh + +test_opt_t_SOURCES = test/opt.c +test_opt_t_LDADD = \ + $(builddir)/opt.o \ + $(common_ldadd) \ + $(top_builddir)/src/libtap/libtap.a diff --git a/src/cmd/test/opt.c b/src/cmd/test/opt.c new file mode 100644 index 00000000..f79556e5 --- /dev/null +++ b/src/cmd/test/opt.c @@ -0,0 +1,79 @@ +/************************************************************\ + * Copyright 2010 Lawrence Livermore National Security, LLC + * (c.f. AUTHORS, NOTICE.LLNS, COPYING) + * + * This file is part of the diod 9P server project. + * For details, see https://github.com/chaos/diod. + * + * SPDX-License-Identifier: GPL-2.0-or-later +\************************************************************/ + +/* topt.c - test didomount/opt.c */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include + +#include "src/libtap/tap.h" +#include "opt.h" + +int +main (int argc, char *argv[]) +{ + Opt o; + + char *s; + int i; + + plan (NO_PLAN); + + o = opt_create (); + ok (o != NULL, "opt_create works"); + + ok (opt_addf (o, "mickey=%d", 42) == 1, "opt_addf mickey=42 works"); + ok (opt_addf (o, "goofey=%s", "yes") == 1, "opt_addf goofey=yes works"); + ok (opt_addf (o, "donald") == 1, "opt_addf donald works"); + ok (opt_addf (o, "foo,bar,baz") == 1, "opt_addf foo,bar,baz works"); + ok (opt_addf (o, "lastone") == 1, "opt_addf lastone works"); + + s = opt_csv (o); + ok (s != NULL + && !strcmp (s, "mickey=42,goofey=yes,donald,foo,bar,baz,lastone"), + "opt_csv returned expected result"); + free (s); + + ok (opt_find (o, "mickey") != NULL, "opt_find mickey works"); + ok (opt_find (o, "bar") != NULL, "opt_find bar works"); + ok (opt_find (o, "barn") == NULL, "opt_find barn fails as expected"); + + i = -1; + ok (opt_scanf (o, "mickey=%d", &i) && i == 42, + "opt_scanf mickey value of 42"); + + ok (opt_addf (o, "mickey=string,foo=%d,bar=%d,baz", 12, 15) == 1, + "opt_addf mickey=string,foo=12,bar=15,baz works"); + s = opt_csv (o); + ok (s != NULL + && !strcmp (s, + "goofey=yes,donald,lastone," + "mickey=string,foo=12,bar=15,baz"), + "opt_csv returned expected result"); + free (s); + + opt_destroy (o); + + done_testing (); + + exit (0); +} + +/* + * vi:tabstop=4 shiftwidth=4 expandtab + */ diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am index 6f20c8eb..799fffd2 100644 --- a/src/daemon/Makefile.am +++ b/src/daemon/Makefile.am @@ -26,3 +26,47 @@ diod_SOURCES = \ fid.h \ xattr.c \ xattr.h + +test_ldadd = \ + $(top_builddir)/src/libdiod/libdiod.a \ + $(top_builddir)/src/libnpclient/libnpclient.a \ + $(top_builddir)/src/libnpfs/libnpfs.a \ + $(top_builddir)/src/liblsd/liblsd.a \ + $(top_builddir)/src/libtap/libtap.a \ + $(LIBPTHREAD) + +xtest_ldadd = \ + $(builddir)/ops.o \ + $(builddir)/fid.o \ + $(builddir)/exp.o \ + $(builddir)/ioctx.o \ + $(builddir)/xattr.o \ + $(test_ldadd) \ + $(LUA_LIB) \ + $(LIBCAP) \ + $(LIBMUNGE) \ + $(LIBWRAP) + +TESTS = \ + test_threadwrlock.t \ + test_read.t \ + test_directory.t \ + test_multiuser.t + +check_PROGRAMS = $(TESTS) + +TEST_EXTENSIONS = .t +T_LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \ + $(top_srcdir)/config/tap-driver.sh + +test_threadwrlock_t_SOURCES = test/threadwrlock.c +test_threadwrlock_t_LDADD = $(test_ldadd) + +test_read_t_SOURCES = test/read.c +test_read_t_LDADD = $(xtest_ldadd) + +test_directory_t_SOURCES = test/directory.c +test_directory_t_LDADD = $(xtest_ldadd) + +test_multiuser_t_SOURCES = test/multiuser.c +test_multiuser_t_LDADD = $(xtest_ldadd) diff --git a/src/daemon/test/directory.c b/src/daemon/test/directory.c new file mode 100644 index 00000000..95263fb7 --- /dev/null +++ b/src/daemon/test/directory.c @@ -0,0 +1,188 @@ +/************************************************************\ + * Copyright 2010 Lawrence Livermore National Security, LLC + * (c.f. AUTHORS, NOTICE.LLNS, COPYING) + * + * This file is part of the diod 9P server project. + * For details, see https://github.com/chaos/diod. + * + * SPDX-License-Identifier: GPL-2.0-or-later +\************************************************************/ + +/* test client/server with diod ops */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "src/libnpfs/9p.h" +#include "src/libnpfs/npfs.h" +#include "src/libnpclient/npclient.h" + +#include "src/liblsd/list.h" +#include "src/libdiod/diod_log.h" +#include "src/libdiod/diod_conf.h" +#include "src/libdiod/diod_sock.h" + +#include "ops.h" +#include "src/libtap/tap.h" + +#define TEST_MSIZE 8192 + +#define TEST_ITER 64 + +int +main (int argc, char *argv[]) +{ + Npsrv *srv; + int s[2]; + int flags = 0; + int rc; + Npcfid *root, *dir, *f[TEST_ITER]; + char tmpdir[] = "/tmp/test-ops.XXXXXX"; + int i; + char tmpstr[PATH_MAX + 1]; + int n; + char dbuf[TEST_MSIZE - P9_IOHDRSZ]; + struct dirent d, *dp; + + plan (NO_PLAN); + + diag ("initialize diod logging and configuration"); + diod_log_init (argv[0]); + diod_conf_init (); + diod_conf_set_auth_required (0); + + /* export */ + if (!mkdtemp (tmpdir)) + BAIL_OUT ("mkdtemp: %s", strerror (errno)); + diag ("exporting %s", tmpdir); + diod_conf_add_exports (tmpdir); + diod_conf_set_exportopts ("sharefd"); + + if (socketpair (AF_LOCAL, SOCK_STREAM, 0, s) < 0) + BAIL_OUT ("socketpair: %s", strerror (errno)); + + srv = np_srv_create (16, flags); + ok (srv != NULL, "np_srv_create works"); + if (!srv) + BAIL_OUT ("need server to continue"); + rc = diod_init (srv); + ok (rc == 0, "diod_init works"); + if (rc < 0) + BAIL_OUT ("diod_init: %s", strerror (np_rerror ())); + + diag ("connecting server to socketpair"); + diod_sock_startfd (srv, s[1], s[1], "loopback", 0); + + root = npc_mount (s[0], s[0], TEST_MSIZE, tmpdir, NULL); + ok (root != NULL, "npc_mount on socketpair works"); + if (!root) + BAIL_OUT ("npc_mount: %s", strerror (np_rerror ())); + + /* create a directory with TEST_ITER files, and exercise various ops + * on the files and directory. + */ + rc = npc_mkdir_bypath (root, "foo", 0755); + ok (rc == 0, "npc_mkdir_bypath foo works"); + if (rc < 0) + BAIL_OUT ("npc_mkdir_bypath: %s", strerror (np_rerror ())); + + /* create files */ + int errors = 0; + for (i = 0; i < TEST_ITER; i++) { + snprintf (tmpstr, sizeof (tmpstr), "foo/%-.200i", i); + f[i] = npc_create_bypath (root, tmpstr, 0, 0644, getgid()); + if (!f[i]) { + diag ("npc_create_bypath %s: %s", tmpstr, strerror (np_rerror ())); + errors++; + } + } + ok (errors == 0, "npc_create_bypath works on %d files under foo", TEST_ITER); + + /* open the directory */ + dir = npc_opendir (root, "foo"); + ok (dir != NULL, "npc_opendir foo works"); + if (!dir) + BAIL_OUT ("npc_opendir foo: %s", strerror (np_rerror ())); + + /* read one chunk of directory (redundant with below) */ + rc = npc_readdir (dir, 0, dbuf, sizeof (dbuf)); + ok (rc >= 0, "npc_readdir works"); + if (rc < 0) + diag ("npc_readdir: %s", strerror (np_rerror ())); + + /* list the files in the directory */ + i = 0; + errors = 0; + do { + if ((n = npc_readdir_r (dir, &d, &dp)) > 0) { + diag ("npc_readdir_r: %s", strerror (n)); + errors++; + break; + } + if (dp) + i++; + } while (n == 0 && dp != NULL); + ok (errors == 0 && i == TEST_ITER + 2, /* . and .. will appear */ + "npc_readdir_r loop found correct number of files"); + + /* close the directory */ + rc = npc_clunk (dir); + ok (rc == 0, "npc_clunk works on directory"); + if (rc < 0) + diag ("npc_clunk: %s", strerror (n)); + + /* remove files (implicit clunk) */ + errors = 0; + for (i = 0; i < TEST_ITER; i++) { + if (npc_remove (f[i]) < 0) { + diag ("npc_remove: %s", strerror (n)); + errors++; + } + } + ok (errors == 0, "npc_remove removed %d files", TEST_ITER); + + /* remove directory */ + rc = npc_remove_bypath (root, "foo"); + ok (rc == 0, "npc_remove_bypath removed foo directory"); + if (rc < 0) + diag ("npc_remove foo: %s", strerror (np_rerror ())); + + diag ("npc_umount"); + npc_umount (root); + + diag ("npc_srv_wait_conncount"); + np_srv_wait_conncount (srv, 0); + + diag ("finalzing server"); + diod_fini (srv); + np_srv_destroy (srv); + + rmdir (tmpdir); + + diod_conf_fini (); + diod_log_fini (); + + done_testing (); + + exit (0); +} + +/* + * vi:tabstop=4 shiftwidth=4 expandtab + */ diff --git a/src/daemon/test/multiuser.c b/src/daemon/test/multiuser.c new file mode 100644 index 00000000..e0116852 --- /dev/null +++ b/src/daemon/test/multiuser.c @@ -0,0 +1,243 @@ +/************************************************************\ + * Copyright 2010 Lawrence Livermore National Security, LLC + * (c.f. AUTHORS, NOTICE.LLNS, COPYING) + * + * This file is part of the diod 9P server project. + * For details, see https://github.com/chaos/diod. + * + * SPDX-License-Identifier: GPL-2.0-or-later +\************************************************************/ + +/* test diod client/server with root/mult users */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "src/libnpfs/9p.h" +#include "src/libnpfs/npfs.h" +#include "src/libnpclient/npclient.h" + +#include "src/liblsd/list.h" +#include "src/libdiod/diod_log.h" +#include "src/libdiod/diod_conf.h" +#include "src/libdiod/diod_sock.h" + +#include "src/libtap/tap.h" + +#include "ops.h" + +#define TEST_MSIZE 8192 + +int +file_test (Npcfid *root) +{ + int n, len = 4096*100; + char *buf = malloc (len); + char *buf2 = malloc (len); + Npcfid *f; + int rc = -1; + + if (!buf || !buf2) + BAIL_OUT ("out of memory"); + + /* create */ + if (!(f = npc_create_bypath (root, "foo", 0, 0644, getgid()))) { + diag ("npc_create_bypath: %s", strerror (np_rerror ())); + goto done; + } + if (npc_clunk (f) < 0) { + diag ("npc_clunk: %s", strerror (np_rerror ())); + goto done; + } + + /* put */ + memset (buf, 9, len); + n = npc_put (root, "foo", buf, len); + if (n < 0) { + diag ("npc_put: %s", strerror (np_rerror ())); + goto done; + } + if (n < len) { + diag ("npc_put: short write: %d", n); + goto done; + } + + /* walk */ + f = npc_walk (root, "foo"); + if (!f) { + diag ("npc_walk: %s", strerror (np_rerror ())); + goto done; + } + + /* open */ + if (npc_open (f, O_RDONLY) < 0) { + diag ("npc_open: %s", strerror (np_rerror ())); + goto done; + } + + /* read */ + memset (buf2, 0, len); + n = npc_get (root, "foo", buf2, len); + if (n < 0) { + diag ("npc_get: %s", strerror (np_rerror ())); + goto done; + } + if (n < len) { + diag ("npc_get: short read: %d bytes", n); + goto done; + } + if (memcmp (buf, buf2, n) != 0) { + diag ("memcmp failure"); + goto done; + } + + /* clunk */ + if (npc_clunk (f) < 0) { + diag ("npc_clunk: %s", strerror (np_rerror ())); + goto done; + } + + /* remove */ + if (npc_remove_bypath (root, "foo") < 0) + diag ("npc_remove_bypath: %s", strerror (np_rerror ())); + rc = 0; +done: + free (buf); + free (buf2); + return rc; +} + +int +main (int argc, char *argv[]) +{ + Npsrv *srv; + int s[2]; + int flags = 0; + int rc; + Npcfsys *fs; + Npcfid *root, *user, *user2; + char tmpdir[] = "/tmp/tnpsrv2.XXXXXX"; + + if (geteuid () != 0 || getenv ("FAKEROOTKEY") != NULL) + plan (SKIP_ALL, "this test must run as root"); + + diag ("initialize diod logging and configuration"); + diod_log_init (argv[0]); + diod_conf_init (); + + /* Allow attach with afid==-1. + */ + diod_conf_set_auth_required (0); + + /* create export directory: will be owned by root, mode=0700 */ + if (!mkdtemp (tmpdir)) + BAIL_OUT ("mkdtemp: %s", strerror (errno)); + diod_conf_add_exports (tmpdir); + diod_conf_set_exportopts ("sharefd"); + + if (socketpair (AF_LOCAL, SOCK_STREAM, 0, s) < 0) + BAIL_OUT ("socketpair: %s", strerror (errno)); + + /* Note: supplementary groups do not work in this mode, however + * regular uid:gid switching of fsid works. Enabling DAC_BYPASS + * assumes v9fs is enforcing permissions, not the case with npclient. + */ + flags |= SRV_FLAGS_SETFSID; + srv = np_srv_create (16, flags); + ok (srv != NULL, "np_srv_create works"); + if (!srv) + BAIL_OUT ("need server to continue"); + rc = diod_init (srv); + ok (rc == 0, "diod_init works"); + if (rc < 0) + BAIL_OUT ("diod_init: %s", strerror (np_rerror ())); + + diag ("connecting server to socketpair"); + diod_sock_startfd (srv, s[1], s[1], "loopback", 0); + + fs = npc_start (s[0], s[0], TEST_MSIZE, 0); + ok (fs != NULL, "npc_start works"); + if (!fs) + BAIL_OUT ("npc_start: %s", strerror (np_rerror ())); + + root = npc_attach (fs, NULL, tmpdir, 0); /* attach as uid=0 */ + ok (root != NULL, "npc_attach %s uid=0 works", tmpdir); + if (!root) + BAIL_OUT ("npc_attach: %s", strerror (np_rerror ())); + + user = npc_attach (fs, NULL, tmpdir, 1); /* attach as uid=1 */ + ok (user != NULL, "npc_attach %s uid=1 works", tmpdir); + if (!user) + BAIL_OUT ("npc_attach: %s", strerror (np_rerror ())); + + /* attach one more time as uid=1 to exercise user cache under valgrind */ + user2 = npc_attach (fs, NULL, tmpdir, 1); + ok (user2 != NULL, "npc_attach %s uid=1 again works", tmpdir); + if (!user2) + diag ("npc_attach: %s", strerror (np_rerror ())); + + ok (file_test (root) == 0, "a file can be manipulated as root"); + ok (file_test (user) < 0, "a file cannot be manipulated as uid=1"); + + rc = npc_chmod (root, ".", 0777); + ok (rc == 0, "npc_chmod . 0777 works as root"); + if (rc < 0) + diag ("npc_chmod: %s", strerror (np_rerror ())); + + ok (file_test (user) == 0, "a file can now be manipulated as uid=1"); + + rc = npc_chown (root, ".", 1, 1); + ok (rc == 0, "npc_chown . 1:1 works as root"); + if (rc < 0) + diag ("npc_chown: %s", strerror (np_rerror ())); + + rc = npc_chmod (root, ".", 0700); + ok (rc == 0, "npc_chmod . 0700 works as root"); + if (rc < 0) + diag ("npc_chmod: %s", strerror (np_rerror ())); + + ok (file_test (user) == 0, "a file can still be manipulated as uid=1"); + + ok (npc_clunk (user) == 0, "npc_clunk user works"); + ok (npc_clunk (user2) == 0, "npc_clunk user2 works"); + ok (npc_clunk (root) == 0, "npc_clunk root works"); + + diag ("npc_finish"); + npc_finish (fs); + + diag ("npc_srv_wait_conncount"); + np_srv_wait_conncount (srv, 0); + + diag ("finalizing server"); + diod_fini (srv); + np_srv_destroy (srv); + + rmdir (tmpdir); + + diod_conf_fini (); + diod_log_fini (); + + done_testing (); + + exit (0); +} + +/* + * vi:tabstop=4 shiftwidth=4 expandtab + */ diff --git a/src/daemon/test/read.c b/src/daemon/test/read.c new file mode 100644 index 00000000..fc860dff --- /dev/null +++ b/src/daemon/test/read.c @@ -0,0 +1,207 @@ +/************************************************************\ + * Copyright 2010 Lawrence Livermore National Security, LLC + * (c.f. AUTHORS, NOTICE.LLNS, COPYING) + * + * This file is part of the diod 9P server project. + * For details, see https://github.com/chaos/diod. + * + * SPDX-License-Identifier: GPL-2.0-or-later +\************************************************************/ + +/* test client/server reads with diod ops */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "src/libnpfs/9p.h" +#include "src/libnpfs/npfs.h" +#include "src/libnpclient/npclient.h" + +#include "src/liblsd/list.h" +#include "src/libdiod/diod_log.h" +#include "src/libdiod/diod_conf.h" +#include "src/libdiod/diod_sock.h" + +#include "ops.h" +#include "src/libtap/tap.h" + +#define TEST_MSIZE 8192 + +#define TEST_ITER 64 + +int +main (int argc, char *argv[]) +{ + Npsrv *srv; + int s[2]; + int flags = 0; + int rc; + Npcfid *root, *f[TEST_ITER]; + char tmpdir[] = "/tmp/test-ops.XXXXXX"; + int i; + int n, len = 4096*100; + char *buf = malloc (len); + char *buf2 = malloc (len); + + plan (NO_PLAN); + + if (!buf || !buf2) + BAIL_OUT ("out of memory"); + + diag ("initialize diod logging and configuration"); + diod_log_init (argv[0]); + diod_conf_init (); + diod_conf_set_auth_required (0); + + /* export */ + if (!mkdtemp (tmpdir)) + BAIL_OUT ("mkdtemp: %s", strerror (errno)); + diag ("exporting %s", tmpdir); + diod_conf_add_exports (tmpdir); + diod_conf_set_exportopts ("sharefd"); + + if (socketpair (AF_LOCAL, SOCK_STREAM, 0, s) < 0) + BAIL_OUT ("socketpair: %s", strerror (errno)); + + srv = np_srv_create (16, flags); + ok (srv != NULL, "np_srv_create works"); + if (!srv) + BAIL_OUT ("need server to continue"); + rc = diod_init (srv); + ok (rc == 0, "diod_init works"); + if (rc < 0) + BAIL_OUT ("diod_init: %s", strerror (np_rerror ())); + + diag ("connecting server to socketpair"); + diod_sock_startfd (srv, s[1], s[1], "loopback", 0); + + root = npc_mount (s[0], s[0], TEST_MSIZE, tmpdir, NULL); + ok (root != NULL, "npc_mount on socketpair works"); + if (!root) + BAIL_OUT ("npc_mount: %s", strerror (np_rerror ())); + + /* create a file, write some data into it, then read it TEST_ITER + * times, each on a unique fid. The path and ioctx will be shared due + * to "sharefd" export option set above. We want to be sure no memory + * leaks result from the management of shared paths and io contexts. + */ + f[0] = npc_create_bypath (root, "foo", 0, 0644, getgid()); + ok (f[0] != NULL, "npc_create_bypath foo works"); + if (!f[0]) + BAIL_OUT ("npc_create_bypath foo: %s", strerror (np_rerror ())); + ok (npc_clunk (f[0]) == 0, "npc_clunk on foo works"); + + /* fill it with some data (npc_put does open + write + clunk) */ + memset (buf, 9, len); + n = npc_put (root, "foo", buf, len); + ok (n == len, "npc_put %d bytes works", len); + if (n < 0) + diag ("ncp_put: %s", strerror (np_rerror ())); + if (n < len) + diag ("npc_put: short write: %d", n); + + /* walk */ + int errors = 0; + for (i = 0; i < TEST_ITER; i++) { + f[i] = npc_walk (root, "foo"); + if (!f[i]) { + diag ("ncp_walk: %s", strerror (np_rerror ())); + errors++; + } + } + ok (errors == 0, "npc_walk created %d fids for foo", TEST_ITER); + + /* open */ + errors = 0; + for (i = 0; i < TEST_ITER; i++) { + if (npc_open (f[i], O_RDONLY) < 0) { + diag ("ncp_open: %s", strerror (np_rerror ())); + errors++; + } + } + ok (errors == 0, "npc_open works on each fid"); + + /* read (using new fids) */ + errors = 0; + for (i = 0; i < TEST_ITER; i++) { + if (f[i]) { + memset (buf2, 0, len); + int count = 0; + while (count < len) { + n = npc_read (f[i], buf2 + count, len - count); + if (n < 0) { + diag ("ncp_read: %s", strerror (np_rerror ())); + break; + } + if (n == 0) { + diag ("npc_read: short read (%d bytes)", count); + break; + } + count += n; + } while (count < len); + if (count != len || memcmp (buf, buf2, n) != 0) + errors++; + } + } + ok (errors == 0, "npc_read works on each fid (full content verified)"); + + /* clunk */ + errors = 0; + for (i = 0; i < TEST_ITER; i++) { + if (f[i]) { + if (npc_clunk (f[i]) < 0) { + diag ("npc_clunk: %s", strerror (np_rerror ())); + errors++; + } + } + } + ok (errors == 0, "npc_clunk works on each fid"); + + /* remove */ + rc = npc_remove_bypath (root, "foo"); + ok (rc == 0, "npc_remove_bypath foo works"); + if (rc < 0) + diag ("npc_remove_bypath: %s", strerror (np_rerror ())); + + free (buf); + free (buf2); + + diag ("npc_umount"); + npc_umount (root); + + diag ("npc_srv_wait_conncount"); + np_srv_wait_conncount (srv, 0); + + diag ("finalizing server"); + diod_fini (srv); + np_srv_destroy (srv); + + rmdir (tmpdir); + + diod_conf_fini (); + diod_log_fini (); + + done_testing (); + + exit (0); +} + +/* + * vi:tabstop=4 shiftwidth=4 expandtab + */ diff --git a/src/daemon/test/threadwrlock.c b/src/daemon/test/threadwrlock.c new file mode 100644 index 00000000..9766ea6f --- /dev/null +++ b/src/daemon/test/threadwrlock.c @@ -0,0 +1,254 @@ +/************************************************************\ + * Copyright 2010 Lawrence Livermore National Security, LLC + * (c.f. AUTHORS, NOTICE.LLNS, COPYING) + * + * This file is part of the diod 9P server project. + * For details, see https://github.com/chaos/diod. + * + * SPDX-License-Identifier: GPL-2.0-or-later +\************************************************************/ + +/* demonstrate that fcntl locking is only effective at process granularity */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "src/libtap/tap.h" + +#define TEST_UID 100 +#define TEST_GID 100 + +typedef enum { S0, S1, S2, S3, S4, S5 } state_t; + +static state_t state = S0; +static pthread_mutex_t state_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t state_cond = PTHREAD_COND_INITIALIZER; +static char path[] = "/tmp/test.fcntl.XXXXXX"; +static int fd = -1; + +static void test_lock (pthread_mutex_t *l) +{ + int n = pthread_mutex_lock (l); + if (n) + BAIL_OUT ("pthread_mutex_lock: %s", strerror (n)); +} +static void test_unlock (pthread_mutex_t *l) +{ + int n = pthread_mutex_unlock (l); + if (n) + BAIL_OUT ("pthread_mutex_unlock: %s", strerror (n)); +} +static void test_condsig (pthread_cond_t *c) +{ + int n = pthread_cond_signal (c); + if (n) + BAIL_OUT ("pthread_cond_signal: %s", strerror (n)); +} +static void test_condwait (pthread_cond_t *c, pthread_mutex_t *l) +{ + int n = pthread_cond_wait (c, l); + if (n) + BAIL_OUT ("pthread_cond_wait: %s", strerror (n)); +} +static void test_thread_create (pthread_t *t, void *(f)(void *), void *a) +{ + int n = pthread_create (t, NULL, f, a); + if (n) + BAIL_OUT ("pthread_create: %s", strerror (n)); +} +static void test_thread_join (pthread_t t, void **a) +{ + int n = pthread_join (t, a); + if (n) + BAIL_OUT ("pthread_join: %s", strerror (n)); +} + +static void change_state (state_t s) +{ + test_lock (&state_lock); + state = s; + test_condsig (&state_cond); + test_unlock (&state_lock); +} + +static void wait_state (state_t s) +{ + test_lock (&state_lock); + while (state != s) + test_condwait (&state_cond, &state_lock); + test_unlock (&state_lock); +} + +static void mkfile (void) +{ + char buf[1024]; + + memset (buf, 0, sizeof (buf)); + if ((fd = mkstemp (path)) < 0) + BAIL_OUT ("mkstemp: %s", strerror (errno)); + if (write (fd, buf, sizeof (buf)) < 0) + BAIL_OUT ("write: %s", strerror (errno)); + if (close (fd) < 0) + BAIL_OUT ("close: %s", strerror (errno)); + if ((fd = open (path, O_RDWR)) < 0) + BAIL_OUT ("open %s: %s", path, strerror (errno)); +} + +static void *proc1 (void *a) +{ + struct flock f; + + diag ("proc1: locking bytes 0-63 (locked in same process)"); + f.l_type = F_WRLCK; + f.l_whence = SEEK_SET; + f.l_start = 0; + f.l_len = 64; + ok (fcntl (fd, F_SETLK, &f) == 0, + "proc1: fcntl F_WRLCK 0-63 works"); + change_state (S1); + + wait_state (S2); + change_state (S3); + wait_state (S4); + return NULL; +} + +static void *proc2 (void *a) +{ + struct flock f; + + wait_state (S1); + diag ("proc2: locking bytes 0-63 (locked in same process)"); + f.l_type = F_WRLCK; + f.l_whence = SEEK_SET; + f.l_start = 0; + f.l_len = 64; + ok (fcntl (fd, F_SETLK, &f) == 0, + "proc2: fcntl F_WRLCK 0-63 works"); + change_state (S2); + + wait_state (S3); + change_state (S4); + return NULL; +} + +int +main (int arg, char *argv[]) +{ + pthread_t t1, t2; + struct flock f; + pid_t pid; + int status; + int rc; + + plan (NO_PLAN); + + mkfile (); + + /* same task/thread contending for write lock */ + diag ("proc0: locking bytes 0-63"); + f.l_type = F_WRLCK; + f.l_whence = SEEK_SET; + f.l_start = 0; + f.l_len = 64; + rc = fcntl (fd, F_SETLK, &f); + ok (rc == 0, "proc0 fcntl F_WRLCK 0-63 works"); + + diag ("proc0: locking bytes 32-63 (locked in same process+thread)"); + f.l_type = F_WRLCK; + f.l_whence = SEEK_SET; + f.l_start = 32; + f.l_len = 64; + rc = fcntl (fd, F_SETLK, &f); + ok (rc == 0, "proc0: F_WRLCK 32-63 works"); + + /* two threads contending for write lock */ + test_thread_create (&t1, proc1, NULL); + test_thread_create (&t2, proc2, NULL); + + test_thread_join (t2, NULL); + test_thread_join (t1, NULL); + + fflush (stderr); + + /* two processes contending for write lock - inherited fd */ + diag ("child0: tries to lock bytes 32-63 (locked in different process)"); + switch (pid = fork ()) { + case -1: + BAIL_OUT ("fork: %s", strerror (errno)); + case 0: /* child */ + f.l_type = F_WRLCK; + f.l_whence = SEEK_SET; + f.l_start = 32; + f.l_len = 64; + if (fcntl (fd, F_SETLK, &f) < 0) { + diag ("fcntl F_WRLCK 32-63: %s", strerror (errno)); + exit (1); + } + exit (0); + break; + default: /* parent */ + if (waitpid (pid, &status, 0) < 0) + BAIL_OUT ("waitpid: %s", strerror (errno)); + ok (WIFEXITED (status) && WEXITSTATUS (status) == 1, + "child0 failed to lock bytes 32-63 as expected"); + break; + } + + /* two processes contending for write lock - seperate fd's */ + diag ("child1: locking bytes 32-63 (locked in different process)"); + switch (pid = fork ()) { + case -1: + BAIL_OUT ("fork: %s", strerror (errno)); + case 0: /* child */ + if (close (fd) < 0 + || (fd = open (path, O_RDWR)) < 0) { + diag ("close/open %s (child): %s", path, strerror (errno)); + exit (2); + } + f.l_type = F_WRLCK; + f.l_whence = SEEK_SET; + f.l_start = 32; + f.l_len = 64; + int exit_code = fcntl (fd, F_SETLK, &f) < 0 ? 1 : 0; + if (exit_code == 1) + diag ("fcntl F_WRLCK 32-63: %s", strerror (errno)); + (void)close (fd); + exit (exit_code); + break; + default: /* parent */ + if (waitpid (pid, &status, 0) < 0) + BAIL_OUT ("waitpid: %s", strerror (errno)); + ok (WIFEXITED (status) && WEXITSTATUS (status) == 1, + "child1 failed to lock bytes 32-63 as expected"); + break; + } + + if (close (fd) < 0) + BAIL_OUT ("close: %s", strerror (errno)); + if (unlink (path) < 0) + BAIL_OUT ("unlink %s: %s", path, strerror (errno)); + exit (0); +} + +/* + * vi:tabstop=4 shiftwidth=4 expandtab + */ diff --git a/src/libdiod/Makefile.am b/src/libdiod/Makefile.am index ab4d4875..dd7df5cb 100644 --- a/src/libdiod/Makefile.am +++ b/src/libdiod/Makefile.am @@ -19,3 +19,24 @@ libdiod_a_SOURCES = \ if RDMATRANS libdiod_a_SOURCES += diod_rdma.c diod_rdma.h endif + +test_ldadd = \ + $(builddir)/libdiod.a \ + $(top_builddir)/src/libnpclient/libnpclient.a \ + $(top_builddir)/src/libnpfs/libnpfs.a \ + $(top_builddir)/src/liblsd/liblsd.a \ + $(top_builddir)/src/libtap/libtap.a \ + $(LUA_LIB) \ + $(LIBCAP) \ + $(LIBPTHREAD) + +TESTS = \ + test_configfile.t + +check_PROGRAMS = $(TESTS) +TEST_EXTENSIONS = .t +T_LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \ + $(top_srcdir)/config/tap-driver.sh + +test_configfile_t_SOURCES = test/configfile.c +test_configfile_t_LDADD = $(test_ldadd) diff --git a/src/libdiod/test/configfile.c b/src/libdiod/test/configfile.c new file mode 100644 index 00000000..493292ef --- /dev/null +++ b/src/libdiod/test/configfile.c @@ -0,0 +1,223 @@ +/************************************************************\ + * Copyright 2010 Lawrence Livermore National Security, LLC + * (c.f. AUTHORS, NOTICE.LLNS, COPYING) + * + * This file is part of the diod 9P server project. + * For details, see https://github.com/chaos/diod. + * + * SPDX-License-Identifier: GPL-2.0-or-later +\************************************************************/ + +/* test config file */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include + +#include "src/liblsd/list.h" +#include "src/libtap/tap.h" + +#include "diod_log.h" +#include "diod_conf.h" + +static void create_testfile (char *template, const char *content) +{ + int fd; + if ((fd = mkstemp (template)) < 0) + BAIL_OUT ("could not create temporary file: %s", strerror (errno)); + int count = write (fd, content, strlen (content)); + if (count < 0) + BAIL_OUT ("could not write to temporary file: %s", strerror (errno)); + if (count < strlen (content)) + BAIL_OUT ("short write"); + close (fd); +} + +static void test_config1 (void) +{ + char *s; + ListIterator itr; + char path[] = "/tmp/config.XXXXXX"; + const char *content = "\ +exports = {\n\ + \"/g/g1\",\n\ + \"/g/g2\",\n\ + { path=\"/g/g3\", opts=\"ro\", users=\"jim,bob\", hosts=\"foo[1-64]\" },\n\ + \"/g/g5\",\n\ + { path=\"/g/g4\", users=\"jim,bob\" },\n\ + \"/g/g6\",\n\ +}\n"; + + diag ("checking config 1"); + create_testfile (path, content); + diod_conf_init (); + diod_conf_init_config_file (path); + + s = diod_conf_get_logdest (); + is (s, DFLT_LOGDEST, "logdest is default"); + s = diod_conf_get_configpath (); + is (s, path, "configpath is %s", path); + ok (diod_conf_get_debuglevel () == DFLT_DEBUGLEVEL, "debuglevel is default"); + ok (diod_conf_get_nwthreads () == DFLT_NWTHREADS, "nwthreads is default"); + ok (diod_conf_get_foreground () == DFLT_FOREGROUND, "foreground is default"); + ok (diod_conf_get_auth_required () == DFLT_AUTH_REQUIRED, + "auth_required is default"); + ok (diod_conf_get_hostname_lookup () == DFLT_HOSTNAME_LOOKUP, + "hostname_lookup is default"); + ok (diod_conf_get_statfs_passthru () == DFLT_STATFS_PASSTHRU, + "statfs_passthru is default"); + ok (diod_conf_get_userdb () == DFLT_USERDB, "userdb is default"); + ok (diod_conf_get_allsquash () == DFLT_ALLSQUASH, "allsquash is default"); + s = diod_conf_get_squashuser (); + is (s, DFLT_SQUASHUSER, "squashuser is default"); + ok (diod_conf_get_runasuid () == DFLT_RUNASUID, "runasuid is default"); + + if (!(itr = list_iterator_create (diod_conf_get_listen ()))) + BAIL_OUT ("could not create list iterator for listen"); + ok ((s = list_next (itr)) != NULL + && !strcmp (s, DFLT_LISTEN) + && list_next (itr) == NULL, + "listen is default"); + ok (diod_conf_opt_listen () == 0, "listen is read-write"); + list_iterator_destroy (itr); + + Export *item; + if (!(itr = list_iterator_create (diod_conf_get_exports ()))) + BAIL_OUT ("could not create list iterator for exports"); + ok ((item = list_next (itr)) != NULL + && !strcmp (item->path, "/g/g1") + && !item->opts + && !item->users + && !item->hosts, + "entry 1 was correctly parsed"); + ok ((item = list_next (itr)) != NULL + && !strcmp (item->path, "/g/g2") + && !item->opts + && !item->users + && !item->hosts, + "entry 2 was correctly parsed"); + ok ((item = list_next (itr)) != NULL + && !strcmp (item->path, "/g/g3") + && item->opts && !strcmp (item->opts, "ro") + && item->users && !strcmp (item->users, "jim,bob") + && item->hosts && !strcmp (item->hosts, "foo[1-64]"), + "entry 3 was correctly parsed"); + ok ((item = list_next (itr)) != NULL + && !strcmp (item->path, "/g/g5") + && !item->opts + && !item->users + && !item->hosts, + "entry 4 was correctly parsed"); + ok ((item = list_next (itr)) != NULL + && !strcmp (item->path, "/g/g4") + && !item->opts + && item->users && !strcmp (item->users, "jim,bob") + && !item->hosts, + "entry 5 was correctly parsed"); + ok ((item = list_next (itr)) != NULL + && !strcmp (item->path, "/g/g6") + && !item->opts + && !item->users + && !item->hosts, + "entry 6 was correctly parsed"); + ok (list_next (itr) == NULL, "that was the last item"); + list_iterator_destroy (itr); + + diod_conf_fini (); + unlink (path); +} + +void test_config2 (void) +{ + char *s; + ListIterator itr; + char path[] = "/tmp/config.XXXXXX"; + const char *content = "\ +nwthreads = 64\n\ +auth_required = 1\n\ +allsquash = 1\n\ +listen = { \"1.2.3.4:42\", \"1,2,3,5:43\" }\n\ +logdest = \"syslog:daemon:err\"\n\ +exportall = 1\n\ +\n\ +exports = { \"/g/g1\" }\n"; + + diag ("checking config 2"); + + create_testfile (path, content); + diod_conf_init (); + diod_conf_init_config_file (path); + + s = diod_conf_get_logdest (); + is (s, "syslog:daemon:err", "logdest is syslog:daemon:err"); + s = diod_conf_get_configpath (); + is (s, path, "configpath is %s", path); + ok (diod_conf_get_debuglevel () == DFLT_DEBUGLEVEL, "debuglevel is default"); + ok (diod_conf_get_nwthreads () == 64, "nwthreads is 64"); + ok (diod_conf_get_foreground () == DFLT_FOREGROUND, "foreground is default"); + ok (diod_conf_get_auth_required () != 0, "auth_required is true"); + ok (diod_conf_get_hostname_lookup () == DFLT_HOSTNAME_LOOKUP, + "hostname_lookup is default"); + ok (diod_conf_get_statfs_passthru () == DFLT_STATFS_PASSTHRU, + "statfs_passthru is default"); + ok (diod_conf_get_userdb () == DFLT_USERDB, "userdb is default"); + ok (diod_conf_get_allsquash () != 0, "allsquash is true"); + s = diod_conf_get_squashuser (); + is (s, DFLT_SQUASHUSER, "squashuser is default"); + ok (diod_conf_get_runasuid () == DFLT_RUNASUID, "runasuid is default"); + + if (!(itr = list_iterator_create (diod_conf_get_listen ()))) + BAIL_OUT ("could not create list iterator for listen"); + ok ((s = list_next (itr)) != NULL + && !strcmp (s, "1.2.3.4:42"), + "listen entry 1 is 1.2.3.4:42"); + // huh, apparently we allow that thru the parser? fix? + ok ((s = list_next (itr)) != NULL + && !strcmp (s, "1,2,3,5:43") + && list_next (itr) == NULL, + "listen entry 2 is 1,2,3,5:43"); + ok (diod_conf_opt_listen () == 0, "listen is read-write"); + list_iterator_destroy (itr); + + Export *item; + if (!(itr = list_iterator_create (diod_conf_get_exports ()))) + BAIL_OUT ("could not create list iterator for exports"); + ok ((item = list_next (itr)) != NULL + && !strcmp (item->path, "/g/g1") + && !item->opts + && !item->users + && !item->hosts + && list_next (itr) == NULL, + "export entry 1 is /g/g1"); + + diod_conf_fini (); + unlink (path); +} + +int main (int argc, char *argv[]) +{ +#ifdef HAVE_CONFIG_FILE + plan (NO_PLAN); +#else + plan (SKIP_ALL, "diod was built without lua config file support"); +#endif + diod_log_init ("test_config.t"); + + test_config1 (); + test_config2 (); + + diod_log_fini (); + + done_testing (); + exit (0); +} + +/* + * vi:tabstop=4 shiftwidth=4 expandtab + */ diff --git a/src/liblsd/Makefile.am b/src/liblsd/Makefile.am index 0b201159..76e8664e 100644 --- a/src/liblsd/Makefile.am +++ b/src/liblsd/Makefile.am @@ -16,3 +16,21 @@ liblsd_a_SOURCES = \ thread.c \ thread.h \ error.c + +test_ldadd = \ + $(builddir)/liblsd.a \ + $(top_builddir)/src/libdiod/libdiod.a \ + $(top_builddir)/src/libtap/libtap.a \ + $(LIBPTHREAD) + +TESTS = \ + test_list.t + +check_PROGRAMS = $(TESTS) + +TEST_EXTENSIONS = .t +T_LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \ + $(top_srcdir)/config/tap-driver.sh + +test_list_t_SOURCES = test/list.c +test_list_t_LDADD = $(test_ldadd) diff --git a/tests/misc/tlist.c b/src/liblsd/test/list.c similarity index 67% rename from tests/misc/tlist.c rename to src/liblsd/test/list.c index 89bb7e25..aedf56bc 100644 --- a/tests/misc/tlist.c +++ b/src/liblsd/test/list.c @@ -8,7 +8,7 @@ * SPDX-License-Identifier: GPL-2.0-or-later \************************************************************/ -/* tlist.c - exercise list package (valgrind me) */ +/* list.c - exercise list package (valgrind me) */ /* Internal memory allocation in list.c hangs on to some memory that's not * freed. This may not really be worth the hassle, so it's disabled and @@ -23,20 +23,14 @@ #include #include #include -#include -#include "src/liblsd/list.h" +#include "src/libtap/tap.h" +#include "list.h" #define ITERATIONS 1024 static int objcount = 0; -void oom (void) -{ - fprintf (stderr, "out of memory\n"); - exit (1); -} - void myfree (void *x) { free (x); @@ -48,7 +42,7 @@ char *myalloc (char *s) char *cpy; if (!(cpy = strdup ("xyz"))) - oom (); + BAIL_OUT ("out of memory"); objcount++; return cpy; @@ -61,19 +55,25 @@ main (int argc, char *argv[]) char *p; int i; - if (!(l = list_create ((ListDelF)myfree))) - oom (); + plan (NO_PLAN); + + l = list_create ((ListDelF)myfree); + ok (l != NULL, "list_create with destructor works"); + int errors = 0; for (i = 0; i < ITERATIONS; i++) { if (!(p = myalloc ("xyz"))) - oom (); - if (!list_append (l, p)) - oom (); + BAIL_OUT ("out of memory"); + if (!list_append (l, p)) { + errors++; + } } - - assert (objcount == i); + ok (errors == 0, "list_append worked %dX", ITERATIONS); + ok (objcount == i, "%d objects were allocated", i); list_destroy (l); - assert (objcount == 0); + ok (objcount == 0, "list_destroy deallocated them"); + + done_testing (); exit (0); } @@ -81,4 +81,3 @@ main (int argc, char *argv[]) /* * vi:tabstop=4 shiftwidth=4 expandtab */ - diff --git a/src/libnpclient/Makefile.am b/src/libnpclient/Makefile.am index 12165a4b..4053840f 100644 --- a/src/libnpclient/Makefile.am +++ b/src/libnpclient/Makefile.am @@ -23,3 +23,23 @@ libnpclient_a_SOURCES = \ readdir.c \ chmod.c \ xattr.c + +test_ldadd = \ + $(builddir)/libnpclient.a \ + $(top_builddir)/src/libnpfs/libnpfs.a \ + $(top_builddir)/src/liblsd/liblsd.a \ + $(top_builddir)/src/libtap/libtap.a \ + $(LUA_LIB) \ + $(LIBCAP) \ + $(LIBPTHREAD) + +TESTS = \ + test_simple.t + +check_PROGRAMS = $(TESTS) +TEST_EXTENSIONS = .t +T_LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \ + $(top_srcdir)/config/tap-driver.sh + +test_simple_t_SOURCES = test/simple.c +test_simple_t_LDADD = $(test_ldadd) diff --git a/src/libnpclient/test/simple.c b/src/libnpclient/test/simple.c new file mode 100644 index 00000000..a19ab884 --- /dev/null +++ b/src/libnpclient/test/simple.c @@ -0,0 +1,147 @@ +/************************************************************\ + * Copyright 2010 Lawrence Livermore National Security, LLC + * (c.f. AUTHORS, NOTICE.LLNS, COPYING) + * + * This file is part of the diod 9P server project. + * For details, see https://github.com/chaos/diod. + * + * SPDX-License-Identifier: GPL-2.0-or-later +\************************************************************/ + +/* simple npfs client/server */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "src/libnpfs/9p.h" +#include "src/libnpfs/npfs.h" +#include "src/libnpclient/npclient.h" +#include "src/libtap/tap.h" + +#define TEST_MSIZE 8192 + +static void diag_logger (const char *fmt, va_list ap) +{ + char buf[1024]; /* make it large enough for protocol debug output */ + vsnprintf (buf, sizeof (buf), fmt, ap); /* ignore overflow */ + fprintf (stderr, "# %s\n", buf); +} + +static void check_data_trimmed (const char *name, const char *s, const char *expect) +{ + size_t len = s ? strlen (s) : 0; + if (len > 0 && s[len - 1] == '\n') + len--; + ok (s && !strncmp (s, expect, len), "%s has expected content", name); +} + +int main (int argc, char *argv[]) +{ + Npsrv *srv; + int s[2]; + int flags = SRV_FLAGS_DEBUG_9PTRACE | SRV_FLAGS_DEBUG_USER; + Npconn *conn; + Nptrans *trans; + Npcfsys *fs; + Npcfid *root0, *root1, *root2; + char *str; + + plan (NO_PLAN); + + if (socketpair (AF_LOCAL, SOCK_STREAM, 0, s) < 0) + BAIL_OUT ("socketpair: %s", strerror (errno)); + + srv = np_srv_create (16, flags); + ok (srv != NULL, "np_srv_create works"); + if (!srv) + BAIL_OUT ("need server to continue"); + srv->logmsg = diag_logger; + + trans = np_fdtrans_create (s[1], s[1]); + ok (trans != NULL, "np_fdtrans_create works"); + if (!trans) + BAIL_OUT ("need transport to continue"); + + /* N.B. trans is destroyed in np_conn_create on failure */ + conn = np_conn_create (srv, trans, "simple-test-client", flags); + ok (conn != NULL, "np_conn_create works"); + if (!conn) { + diag ("np_conn_create: %s", strerror (np_rerror ())); + BAIL_OUT ("need server connection to continue"); + } + + fs = npc_start (s[0], s[0], TEST_MSIZE, 0); + ok (fs != NULL, "npc_start works"); + if (!fs) { + diag ("npc_start: %s", strerror (np_rerror ())); + BAIL_OUT ("need client connection to continue"); + } + root0 = npc_attach (fs, NULL, "ctl", 0); + ok (root0 != NULL, "npc_attach aname=ctl uid=0 works"); + if (!root0) { + diag ("npc_attach: %s", strerror (np_rerror ())); + BAIL_OUT ("need ctl:0 fid to continue"); + } + str = npc_aget (root0, "connections"); + ok (str != NULL, "npc_aget connections on ctl:0 fid works"); + check_data_trimmed ("connections", str, "simple-test-client 2"); + + free (str); + + root1 = npc_attach (fs, NULL, "ctl", 1); + ok (root1 != NULL, "npc_attach aname=ctl uid=1 works"); + if (!root1) { + diag ("npc_attach: %s", strerror (np_rerror ())); + BAIL_OUT ("need ctl:1 fid to continue"); + } + str = npc_aget (root1, "connections"); + ok (str != NULL, "npc_aget connections on ctl:1 fid works"); + check_data_trimmed ("connections", str, "simple-test-client 3"); + free (str); + + /* Same user (1) - user cache should be valid, so we won't see a message + * for this user lookup in the output. + */ + root2 = npc_attach (fs, NULL, "ctl", 1); + ok (root2 != NULL, "second npc_attach aname=ctl uid=1 works"); + if (!root1) { + diag ("npc_attach: %s", strerror (np_rerror ())); + BAIL_OUT ("need second ctl:1 fid to continue"); + } + str = npc_aget (root2, "null"); + ok (str != NULL, "npc_aget connections on second ctl:1 fid works"); + check_data_trimmed ("connections", str, ""); + free (str); + + ok (npc_clunk (root0) == 0, "npc_clunk uid:0 fid works"); + ok (npc_clunk (root1) == 0, "npc_clunk uid:1 fid works"); + ok (npc_clunk (root2) == 0, "npc_clunk second uid:1 fid works"); + + diag ("npc_finish"); + npc_finish (fs); + + diag ("np_srv_wait_conncount 0"); + np_srv_wait_conncount (srv, 0); + diag ("np_srv_wait_conncount returned"); + + diag ("np_srv_destroy"); + np_srv_destroy (srv); + + done_testing (); + + exit (0); +} + +/* + * vi:tabstop=4 shiftwidth=4 expandtab + */ diff --git a/src/libnpfs/Makefile.am b/src/libnpfs/Makefile.am index 015da857..677698a0 100644 --- a/src/libnpfs/Makefile.am +++ b/src/libnpfs/Makefile.am @@ -36,3 +36,43 @@ endif if RDMATRANS libnpfs_a_SOURCES += rdmatrans.c endif + +test_ldadd = \ + $(top_builddir)/src/libdiod/libdiod.a \ + $(top_builddir)/src/libnpclient/libnpclient.a \ + $(builddir)/libnpfs.a \ + $(top_builddir)/src/liblsd/liblsd.a \ + $(top_builddir)/src/libtap/libtap.a \ + $(LIBCAP) \ + $(LIBPTHREAD) + +TESTS = \ + test_encoding.t \ + test_fidpool.t \ + test_capability.t \ + test_setfsuid.t \ + test_setgroups.t \ + test_setreuid.t + +check_PROGRAMS = $(TESTS) +TEST_EXTENSIONS = .t +T_LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \ + $(top_srcdir)/config/tap-driver.sh + +test_encoding_t_SOURCES = test/encoding.c +test_encoding_t_LDADD = $(test_ldadd) + +test_fidpool_t_SOURCES = test/fidpool.c +test_fidpool_t_LDADD = $(test_ldadd) + +test_capability_t_SOURCES = test/capability.c +test_capability_t_LDADD = $(test_ldadd) + +test_setfsuid_t_SOURCES = test/setfsuid.c +test_setfsuid_t_LDADD = $(test_ldadd) + +test_setgroups_t_SOURCES = test/setgroups.c +test_setgroups_t_LDADD = $(test_ldadd) + +test_setreuid_t_SOURCES = test/setreuid.c +test_setreuid_t_LDADD = $(test_ldadd) diff --git a/src/libnpfs/test/capability.c b/src/libnpfs/test/capability.c new file mode 100644 index 00000000..ef05d685 --- /dev/null +++ b/src/libnpfs/test/capability.c @@ -0,0 +1,248 @@ +/*************************************************************\ + * Copyright (C) 2010 by Lawrence Livermore National Security, LLC. + * + * This file is part of npfs, a framework for 9P synthetic file systems. + * For details see https://sourceforge.net/projects/npfs. + * + * SPDX-License-Identifier: MIT + *************************************************************/ + +/* check that threads can independently set capabilities */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if HAVE_LIBCAP +#include +#endif +#include + +#include "src/libdiod/diod_log.h" +#include "src/libtap/tap.h" + +#if HAVE_LIBCAP +typedef enum { S0, S1, S2, S3, S4, S5 } state_t; + +static state_t state = S0; +static pthread_mutex_t state_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t state_cond = PTHREAD_COND_INITIALIZER; + +static void test_lock (pthread_mutex_t *l) +{ + int n = pthread_mutex_lock (l); + if (n) + BAIL_OUT ("pthread_mutex_lock: %s", strerror (n)); +} +static void test_unlock (pthread_mutex_t *l) +{ + int n = pthread_mutex_unlock (l); + if (n) + BAIL_OUT ("pthread_mutex_unlock: %s", strerror (n)); +} +static void test_condsig (pthread_cond_t *c) +{ + int n = pthread_cond_signal (c); + if (n) + BAIL_OUT ("pthread_cond_signal: %s", strerror (n)); +} +static void test_condwait (pthread_cond_t *c, pthread_mutex_t *l) +{ + int n = pthread_cond_wait (c, l); + if (n) + BAIL_OUT ("pthread_cond_wait: %s", strerror (n)); +} +static void test_thread_create (pthread_t *t, void *(f)(void *), void *a) +{ + int n = pthread_create (t, NULL, f, a); + if (n) + BAIL_OUT ("pthread_create: %s", strerror (n)); +} +static void test_thread_join (pthread_t t, void **a) +{ + int n = pthread_join (t, a); + if (n) + BAIL_OUT ("pthread_join: %s", strerror (n)); +} + +static void check_capability (const char *who, + const char *capname, + cap_value_t capflag, + cap_flag_value_t expect) +{ + cap_t cap; + cap_flag_value_t val; + + if (!(cap = cap_get_proc ())) + BAIL_OUT ("%s: cap_get_proc failed", who); + if (cap_get_flag (cap, capflag, CAP_EFFECTIVE, &val) < 0) + BAIL_OUT ("%s: cap_get_flag %s failed", who, capname); + if (cap_free (cap) < 0) + BAIL_OUT ("%s: cap_free failed", capname); + ok (val == expect, + "%s %s is %s", who, capname, expect == CAP_SET ? "set" : "clear"); +} + +static void set_capability (char *who, + const char *capname, + cap_value_t capflag, + cap_flag_value_t val) +{ + cap_t cap; + + if (!(cap = cap_get_proc ())) + BAIL_OUT ("%s: cap_get_proc failed", who); + if (cap_set_flag (cap, CAP_EFFECTIVE, 1, &capflag, val) < 0) + BAIL_OUT ("%s: cap_set_flag %s failed", who, capname); + if (cap_set_proc (cap) < 0) + BAIL_OUT ("%s: cap_set_proc failed", who); + if (cap_free (cap) < 0) + BAIL_OUT ("%s: cap_free failed", who); +} + +static void +change_state (state_t s) +{ + test_lock (&state_lock); + state = s; + test_condsig (&state_cond); + test_unlock (&state_lock); +} + +static void +wait_state (state_t s) +{ + test_lock (&state_lock); + while ((state != s)) + test_condwait (&state_cond, &state_lock); + test_unlock (&state_lock); +} + +static void *proc1 (void *a) +{ + /* 1) task 1, expect clr */ + check_capability ("task1", "DAC_OVERRIDE", CAP_DAC_OVERRIDE, CAP_CLEAR); + check_capability ("task1", "CHOWN", CAP_CHOWN, CAP_CLEAR); + change_state (S1); + wait_state (S2); + /* 4) task 1, still clr */ + check_capability ("task1", "DAC_OVERRIDE", CAP_DAC_OVERRIDE, CAP_CLEAR); + check_capability ("task1", "CHOWN", CAP_CHOWN, CAP_CLEAR); + diag ("task1: clr cap"); + set_capability ("task1", "DAC_OVERRIDE", CAP_DAC_OVERRIDE, CAP_CLEAR); + change_state (S3); + wait_state (S4); + return NULL; +} + +static void *proc2 (void *a) +{ + /* 2) task 2, expect clr */ + wait_state (S1); + check_capability ("task2", "DAC_OVERRIDE", CAP_DAC_OVERRIDE, CAP_CLEAR); + check_capability ("task2", "CHOWN", CAP_CHOWN, CAP_CLEAR); + diag ("task2: set cap"); + set_capability ("task2", "DAC_OVERRIDE", CAP_DAC_OVERRIDE, CAP_SET); + set_capability ("task2", "CHOWN", CAP_CHOWN, CAP_SET); + /* 3) task 2, expect set */ + check_capability ("task2", "DAC_OVERRIDE", CAP_DAC_OVERRIDE, CAP_SET); + check_capability ("task2", "CHOWN", CAP_CHOWN, CAP_SET); + change_state (S2); + wait_state (S3); + /* 5) task 2, expect set */ + check_capability ("task2", "DAC_OVERRIDE", CAP_DAC_OVERRIDE, CAP_SET); + check_capability ("task2", "CHOWN", CAP_CHOWN, CAP_SET); + change_state (S4); + return NULL; +} + +// main +static void proc0 (void) +{ + pthread_t t1, t2; + + /* root, expect set */ + diag ("task0: initial state"); + check_capability ("task0", "DAC_OVERRIDE", CAP_DAC_OVERRIDE, CAP_SET); + check_capability ("task0", "CHOWN", CAP_CHOWN, CAP_SET); + + /* non-root, expect clr */ + diag ("task0: setfsuid 1"); + setfsuid (1); + check_capability ("task0", "DAC_OVERRIDE", CAP_DAC_OVERRIDE, CAP_CLEAR); + check_capability ("task0", "CHOWN", CAP_CHOWN, CAP_CLEAR); + + /* root, expect set */ + diag ("task0: setfsuid 0"); + setfsuid (0); + check_capability ("task0", "DAC_OVERRIDE", CAP_DAC_OVERRIDE, CAP_SET); + check_capability ("task0", "CHOWN", CAP_CHOWN, CAP_SET); + + /* non-root, expect clr */ + diag ("task0: setfsuid 1"); + setfsuid (1); + check_capability ("task0", "DAC_OVERRIDE", CAP_DAC_OVERRIDE, CAP_CLEAR); + check_capability ("task0", "CHOWN", CAP_CHOWN, CAP_CLEAR); + + /* root with cap explicitly set, expect set */ + diag ("task0: set cap"); + set_capability ("task0", "DAC_OVERRIDE", CAP_DAC_OVERRIDE, CAP_SET); + set_capability ("task0", "CHOWN", CAP_CHOWN, CAP_SET); + check_capability ("task0", "DAC_OVERRIDE", CAP_DAC_OVERRIDE, CAP_SET); + check_capability ("task0", "CHOWN", CAP_CHOWN, CAP_SET); + + /* non-root with cap explicitly set (as root) expect set */ + diag ("task0: setfsuid 2"); + setfsuid (2); + check_capability ("task0", "DAC_OVERRIDE", CAP_DAC_OVERRIDE, CAP_SET); + check_capability ("task0", "CHOWN", CAP_CHOWN, CAP_SET); + + /* non-root with cap explicitly clr (as non-root) expect clr */ + diag ("task0: clr cap"); + set_capability ("task0", "DAC_OVERRIDE", CAP_DAC_OVERRIDE, CAP_CLEAR); + set_capability ("task0", "CHOWN", CAP_CHOWN, CAP_CLEAR); + check_capability ("task0", "DAC_OVERRIDE", CAP_DAC_OVERRIDE, CAP_CLEAR); + check_capability ("task0", "CHOWN", CAP_CHOWN, CAP_CLEAR); + + test_thread_create (&t1, proc1, NULL); + test_thread_create (&t2, proc2, NULL); + + test_thread_join (t2, NULL); + test_thread_join (t1, NULL); + + check_capability ("task0", "DAC_OVERRIDE", CAP_DAC_OVERRIDE, CAP_CLEAR); + check_capability ("task0", "CHOWN", CAP_CHOWN, CAP_CLEAR); +} + +#endif + +int main(int argc, char *argv[]) +{ +#if HAVE_LIBCAP + if (geteuid () != 0 || getenv ("FAKEROOTKEY") != NULL) + plan (SKIP_ALL, "this test must run as root"); + plan (NO_PLAN); + diod_log_init (argv[0]); + proc0 (); // spawns proc1 and proc2 +#else + plan (SKIP_ALL, "libcap2-dev is not installed"); +#endif + done_testing (); + + exit (0); +} + +/* + * vi:tabstop=4 shiftwidth=4 expandtab + */ diff --git a/src/libnpfs/test/encoding.c b/src/libnpfs/test/encoding.c new file mode 100644 index 00000000..313e0908 --- /dev/null +++ b/src/libnpfs/test/encoding.c @@ -0,0 +1,997 @@ +/*************************************************************\ + * Copyright (C) 2010 by Lawrence Livermore National Security, LLC. + * + * This file is part of npfs, a framework for 9P synthetic file systems. + * For details see https://sourceforge.net/projects/npfs. + * + * SPDX-License-Identifier: MIT + *************************************************************/ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "9p.h" +#include "npfs.h" + +#include "src/libtap/tap.h" + +#define TEST_MSIZE 4096 + +/* Allocate a new Npfcall to "receive" raw data from fc->pkt. + */ +static Npfcall * +_rcv_buf (Npfcall *fc, int type) +{ + Npfcall *fc2; + char s[256]; + + np_set_tag (fc, 42); + + /* see conn.c:np_conn_new_incall () */ + if (!(fc2 = malloc (sizeof (*fc2) + TEST_MSIZE))) + BAIL_OUT ("malloc failed"); + fc2->pkt = (u8 *)fc2 + sizeof (*fc2); + + /* see conn.c::np_conn_read_proc */ + memcpy (fc2->pkt, fc->pkt, fc->size); + if (!np_deserialize (fc2)) { + diag ("np_deserialize error"); + goto error; + } + + /* check a few things */ + if (fc->type != type) { + diag ("incorrect type"); + goto error; + } + if (fc->size != fc2->size) { + diag ("size mismatch"); + goto error; + } + if (fc->type != fc2->type) { + diag ("type mismatch"); + goto error; + } + + np_snprintfcall (s, sizeof (s), fc); + diag ("%s", s); + + return fc2; +error: + free (fc2); + return NULL; +} + +static void +test_rlerror (void) +{ + Npfcall *fc, *fc2; + char buf[STATIC_RLERROR_SIZE]; + + fc = np_create_rlerror (42); + ok (fc != NULL, "Rlerror encode ecode=42 works"); + fc2 = _rcv_buf (fc, P9_RLERROR); + ok (fc2 != NULL && fc->u.rlerror.ecode == fc2->u.rlerror.ecode, + "Rlerror decode works"); + free (fc); + free (fc2); + + fc = np_create_rlerror_static (42, buf, sizeof(buf)); + ok (fc != NULL, "Rlerror encode (static) ecode=42 works"); + fc2 = _rcv_buf (fc, P9_RLERROR); + ok (fc2 != NULL && fc->u.rlerror.ecode == fc2->u.rlerror.ecode, + "Rlerror decode (from static) works"); + // fc is static memory + free (fc2); +} + +static void test_statfs (void) +{ + Npfcall *fc, *fc2; + + fc = np_create_tstatfs (42); + ok (fc != NULL, "Tstatfs encode fid=42 works"); + fc2 = _rcv_buf (fc, P9_TSTATFS); + ok (fc2 != NULL && fc->u.tstatfs.fid == fc2->u.tstatfs.fid, + "Tstatfs decode works"); + free (fc); + free (fc2); + + fc = np_create_rstatfs (1, 2, 3, 4, 5, 6, 7, 8, 9); + ok (fc != NULL, "Rstatfs type=1 bsize=2 blocks=3 bfree=4 bavail=5... works"); + fc2 = _rcv_buf (fc, P9_RSTATFS); + ok (fc2 != NULL + && fc->u.rstatfs.type == fc2->u.rstatfs.type + && fc->u.rstatfs.bsize == fc2->u.rstatfs.bsize + && fc->u.rstatfs.blocks == fc2->u.rstatfs.blocks + && fc->u.rstatfs.bfree == fc2->u.rstatfs.bfree + && fc->u.rstatfs.bavail== fc2->u.rstatfs.bavail + && fc->u.rstatfs.files == fc2->u.rstatfs.files + && fc->u.rstatfs.ffree == fc2->u.rstatfs.ffree + && fc->u.rstatfs.fsid == fc2->u.rstatfs.fsid + && fc->u.rstatfs.namelen == fc2->u.rstatfs.namelen, + "Rstatfs decode works"); + free (fc); + free (fc2); +} + +static void test_lopen (void) +{ + Npfcall *fc, *fc2; + struct p9_qid qid = { 1, 2, 3 }; + + fc = np_create_tlopen (1, 2); + ok (fc != NULL, "Tlopen encode fid=1 flags=2 works"); + fc2 = _rcv_buf (fc, P9_TLOPEN); + ok (fc2 != NULL + && fc->u.tlopen.fid == fc2->u.tlopen.fid + && fc->u.tlopen.flags == fc2->u.tlopen.flags, + "Tlopen decode works"); + free (fc); + free (fc2); + + fc = np_create_rlopen (&qid, 2); + ok (fc != NULL, + "Rlopen encode qid.type=1 qid.version=2 qid.path=3 iounit=2 works"); + fc2 = _rcv_buf (fc, P9_RLOPEN); + ok (fc2 != NULL + && fc->u.rlopen.qid.type == fc2->u.rlopen.qid.type + && fc->u.rlopen.qid.version == fc2->u.rlopen.qid.version + && fc->u.rlopen.qid.path == fc2->u.rlopen.qid.path + && fc->u.rlopen.iounit == fc2->u.rlopen.iounit, + "Rlopen decode works"); + free (fc); + free (fc2); +} + +static void test_lcreate (void) +{ + Npfcall *fc, *fc2; + struct p9_qid qid = { 1, 2, 3 }; + + fc = np_create_tlcreate (1, "xyz", 3, 4, 5); + ok (fc != NULL, "Tlcreate encode fid=1 name=xyz flags=3 mode=4 gid=5 works"); + fc2 = _rcv_buf (fc, P9_TLCREATE); + ok (fc2 != NULL + && fc->u.tlcreate.fid == fc2->u.tlcreate.fid + && np_str9cmp (&fc->u.tlcreate.name, &fc2->u.tlcreate.name) == 0 + && fc->u.tlcreate.flags == fc2->u.tlcreate.flags + && fc->u.tlcreate.mode == fc2->u.tlcreate.mode + && fc->u.tlcreate.gid == fc2->u.tlcreate.gid, + "Tlcreate decode works"); + free (fc); + free (fc2); + + fc = np_create_rlcreate (&qid, 2); + ok (fc != NULL, "Rlcreate encode qid.type=1 qid.version=2 qid.path=3 works"); + fc2 = _rcv_buf (fc, P9_RLCREATE); + ok (fc2 != NULL + && fc->u.rlcreate.qid.type == fc2->u.rlcreate.qid.type + && fc->u.rlcreate.qid.version == fc2->u.rlcreate.qid.version + && fc->u.rlcreate.qid.path == fc2->u.rlcreate.qid.path + && fc->u.rlcreate.iounit == fc2->u.rlcreate.iounit, + "Rlcreate decode works"); + free (fc); + free (fc2); +} + +static void test_symlink (void) +{ + Npfcall *fc, *fc2; + struct p9_qid qid = { 1, 2, 3 }; + + fc = np_create_tsymlink (1, "xyz", "abc", 4); + ok (fc != NULL, "Tsymlink encode fid=1 name=xyz symtgt=abc gid=4 works"); + fc2 = _rcv_buf (fc, P9_TSYMLINK); + ok (fc2 != NULL + && fc->u.tsymlink.fid == fc2->u.tsymlink.fid + && np_str9cmp (&fc->u.tsymlink.name, &fc2->u.tsymlink.name) == 0 + && np_str9cmp (&fc->u.tsymlink.symtgt, &fc2->u.tsymlink.symtgt) == 0 + && fc->u.tsymlink.gid == fc2->u.tsymlink.gid, + "Tsymlink decode works"); + free (fc); + free (fc2); + + fc = np_create_rsymlink (&qid); + ok (fc != NULL, "Rsymlink encode qid.type=1 qid.version=2 qid.path=3 works"); + fc2 = _rcv_buf (fc, P9_RSYMLINK); + ok (fc2 != NULL + && fc->u.rsymlink.qid.type == fc2->u.rsymlink.qid.type + && fc->u.rsymlink.qid.version == fc2->u.rsymlink.qid.version + && fc->u.rsymlink.qid.path == fc2->u.rsymlink.qid.path, + "Rsymlink decode works"); + free (fc); + free (fc2); +} + +static void test_mknod (void) +{ + Npfcall *fc, *fc2; + struct p9_qid qid = { 1, 2, 3 }; + + fc = np_create_tmknod (1, "xyz", 3, 4, 5, 6); + ok (fc != NULL, + "Tmknod encode fid=1 name=xyz mode=3 major=4 minor=5 gid=6 works"); + fc2 = _rcv_buf (fc, P9_TMKNOD); + ok (fc2 != NULL + && fc->u.tmknod.fid == fc2->u.tmknod.fid + && np_str9cmp (&fc->u.tmknod.name, &fc2->u.tmknod.name) == 0 + && fc->u.tmknod.mode == fc2->u.tmknod.mode + && fc->u.tmknod.major == fc2->u.tmknod.major + && fc->u.tmknod.minor == fc2->u.tmknod.minor + && fc->u.tmknod.gid == fc2->u.tmknod.gid, + "Tmknod decode works"); + free (fc); + free (fc2); + + fc = np_create_rmknod (&qid); + ok (fc != NULL, "Rmknod encode qid.type=1 qid.version=2 qid.path=3 works"); + fc2 = _rcv_buf (fc, P9_RMKNOD); + ok (fc2 != NULL + && fc->u.rmknod.qid.type == fc2->u.rmknod.qid.type + && fc->u.rmknod.qid.version == fc2->u.rmknod.qid.version + && fc->u.rmknod.qid.path == fc2->u.rmknod.qid.path, + "Rmknod decode works"); + free (fc); + free (fc2); +} + +static void test_rename (void) +{ + Npfcall *fc, *fc2; + + fc = np_create_trename (1, 2, "xyz"); + ok (fc != NULL, "Trename encode fid=1 dfid=2 name=xyz works"); + fc2 = _rcv_buf (fc, P9_TRENAME); + ok (fc2 != NULL + && fc->u.trename.fid == fc2->u.trename.fid + && fc->u.trename.dfid == fc2->u.trename.dfid + && np_str9cmp (&fc->u.trename.name, &fc2->u.trename.name) == 0, + "Trename decode works"); + free (fc); + free (fc2); + + fc = np_create_rrename (); + ok (fc != NULL, "Rrename encode works"); + fc2 = _rcv_buf (fc, P9_RRENAME); + ok (fc2 != NULL, "Rrename decode works"); + free (fc); + free (fc2); +} + +static void test_readlink (void) +{ + Npfcall *fc, *fc2; + + fc = np_create_treadlink (1); + ok (fc != NULL, "Treadlink encode fid=1 works"); + fc2 = _rcv_buf (fc, P9_TREADLINK); + ok (fc2 != NULL && fc->u.treadlink.fid == fc2->u.treadlink.fid, + "Treadlink decode works"); + free (fc); + free (fc2); + + fc = np_create_rreadlink ("xyz"); + ok (fc != NULL, "Rreadlink encode target=xyz works"); + fc2 = _rcv_buf (fc, P9_RREADLINK); + ok (fc2 != NULL + && np_str9cmp (&fc->u.rreadlink.target, &fc2->u.rreadlink.target) == 0, + "Rreadlink decode works"); + free (fc); + free (fc2); +} + +static void test_getattr (void) +{ + Npfcall *fc, *fc2; + struct p9_qid qid = { 1, 2, 3 }; + + fc = np_create_tgetattr (42, 5000); + ok (fc != NULL, "Tgetattr encode fid=42 request_mask=5000 works"); + fc2 = _rcv_buf (fc, P9_TGETATTR); + ok (fc2 != NULL + && fc->u.tgetattr.fid == fc2->u.tgetattr.fid + && fc->u.tgetattr.request_mask == fc2->u.tgetattr.request_mask, + "Tgetattr decode works"); + free (fc); + free (fc2); + + fc = np_create_rgetattr (1, &qid, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21); + ok (fc != NULL, + "Rgetattr encode valid=1 qid.type=1 qid.version=2 qid.path=3... works"); + fc2 = _rcv_buf (fc, P9_RGETATTR); + ok (fc2 != NULL + && fc->u.rgetattr.valid == fc2->u.rgetattr.valid + && fc->u.rgetattr.qid.type == fc2->u.rgetattr.qid.type + && fc->u.rgetattr.qid.version == fc2->u.rgetattr.qid.version + && fc->u.rgetattr.qid.path == fc2->u.rgetattr.qid.path + && fc->u.rgetattr.mode == fc2->u.rgetattr.mode + && fc->u.rgetattr.uid == fc2->u.rgetattr.uid + && fc->u.rgetattr.gid == fc2->u.rgetattr.gid + && fc->u.rgetattr.nlink == fc2->u.rgetattr.nlink + && fc->u.rgetattr.rdev == fc2->u.rgetattr.rdev + && fc->u.rgetattr.size == fc2->u.rgetattr.size + && fc->u.rgetattr.blksize == fc2->u.rgetattr.blksize + && fc->u.rgetattr.blocks == fc2->u.rgetattr.blocks + && fc->u.rgetattr.atime_sec == fc2->u.rgetattr.atime_sec + && fc->u.rgetattr.atime_nsec == fc2->u.rgetattr.atime_nsec + && fc->u.rgetattr.mtime_sec == fc2->u.rgetattr.mtime_sec + && fc->u.rgetattr.mtime_nsec == fc2->u.rgetattr.mtime_nsec + && fc->u.rgetattr.ctime_sec == fc2->u.rgetattr.ctime_sec + && fc->u.rgetattr.ctime_nsec == fc2->u.rgetattr.ctime_nsec + && fc->u.rgetattr.btime_sec == fc2->u.rgetattr.btime_sec + && fc->u.rgetattr.btime_nsec == fc2->u.rgetattr.btime_nsec + && fc->u.rgetattr.gen == fc2->u.rgetattr.gen + && fc->u.rgetattr.data_version == fc2->u.rgetattr.data_version, + "Rgetattr decode works"); + free (fc); + free (fc2); +} + +static void test_setattr (void) +{ + Npfcall *fc, *fc2; + + fc = np_create_tsetattr (1,2,3,4,5,6,7,8,9,10); + ok (fc != NULL, + "Tsetattr encode fid=1 valid=2 mode=3 uid=4 gid=5 size=6... works"); + fc2 = _rcv_buf (fc, P9_TSETATTR); + ok (fc2 != NULL + && fc->u.tsetattr.fid == fc2->u.tsetattr.fid + && fc->u.tsetattr.valid == fc2->u.tsetattr.valid + && fc->u.tsetattr.mode == fc2->u.tsetattr.mode + && fc->u.tsetattr.uid == fc2->u.tsetattr.uid + && fc->u.tsetattr.gid == fc2->u.tsetattr.gid + && fc->u.tsetattr.size == fc2->u.tsetattr.size + && fc->u.tsetattr.atime_sec == fc2->u.tsetattr.atime_sec + && fc->u.tsetattr.atime_nsec == fc2->u.tsetattr.atime_nsec + && fc->u.tsetattr.mtime_sec == fc2->u.tsetattr.mtime_sec + && fc->u.tsetattr.mtime_nsec == fc2->u.tsetattr.mtime_nsec, + "Tsetattr decode works"); + free (fc); + free (fc2); + + fc = np_create_rsetattr (); + ok (fc != NULL, "Rsetattr encode works"); + fc2 = _rcv_buf (fc, P9_RSETATTR); + ok (fc2 != NULL, "Rsetattr decode works"); + free (fc); + free (fc2); +} + +static void test_xattrwalk (void) +{ + Npfcall *fc, *fc2; + + fc = np_create_txattrwalk(1, 2, "abc"); + ok (fc != NULL, "Txattrwalk encode fid=1 newfid=2 name=abc works"); + fc2 = _rcv_buf (fc, P9_TXATTRWALK); + ok (fc2 != NULL + && fc->u.txattrwalk.fid == fc2->u.txattrwalk.fid + && fc->u.txattrwalk.attrfid == fc2->u.txattrwalk.attrfid + && np_str9cmp (&fc->u.txattrwalk.name, &fc2->u.txattrwalk.name) == 0, + "Txattrwalk decode works"); + free (fc); + free (fc2); + + fc = np_create_rxattrwalk(1); + ok (fc != NULL, "Rxattrwalk encode size=1 works"); + fc2 = _rcv_buf (fc, P9_RXATTRWALK); + ok (fc2 != NULL && fc->u.rxattrwalk.size == fc2->u.rxattrwalk.size, + "Rxattrwalk decode works"); + free (fc); + free (fc2); +} + +static void test_xattrcreate (void) +{ + Npfcall *fc, *fc2; + + fc = np_create_txattrcreate(1, "abc", 3, 4); + ok (fc != NULL, + "Txattrcreate encode fid=1 name=abc attr_size=3 flags=4 works"); + fc2 = _rcv_buf (fc, P9_TXATTRCREATE); + ok (fc2 != NULL + && fc->u.txattrcreate.fid == fc2->u.txattrcreate.fid + && np_str9cmp (&fc->u.txattrcreate.name, &fc2->u.txattrcreate.name) == 0 + && fc->u.txattrcreate.size == fc2->u.txattrcreate.size + && fc->u.txattrcreate.flag == fc2->u.txattrcreate.flag, + "Txattrcreate decode works"); + free (fc); + free (fc2); + + fc = np_create_rxattrcreate(); + ok (fc != NULL, "Rxattrcreate encode works"); + fc2 = _rcv_buf (fc, P9_RXATTRCREATE); + ok (fc2 != NULL, "Rxattrcreate decode works"); + free (fc); + free (fc2); +} + +static void test_readdir (void) +{ + Npfcall *fc, *fc2; + int n = 0, len = 256; + struct p9_qid qid[3] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } }, qid2[3]; + char *name[3] = { "abc", "def", "ghi" }, name2[3][128]; + u64 offset; + u8 type; + + fc = np_create_treaddir(1, 2, 3); + ok (fc != NULL, "Treaddir encode fid=1 offset=2 count=3 works"); + fc2 = _rcv_buf (fc, P9_TREADDIR); + ok (fc2 != NULL + && fc->u.treaddir.fid == fc2->u.treaddir.fid + && fc->u.treaddir.offset == fc2->u.treaddir.offset + && fc->u.treaddir.count == fc2->u.treaddir.count, + "Treaddir decode works"); + free (fc); + free (fc2); + + fc = np_create_rreaddir (len); + ok (fc != NULL, + "Rreaddir encode len=256 works"); + n += np_serialize_p9dirent (&qid[0], 0, 1, name[0], + fc->u.rreaddir.data + n, len - n); + n += np_serialize_p9dirent (&qid[1], 50, 2, name[1], + fc->u.rreaddir.data + n, len - n); + n += np_serialize_p9dirent (&qid[2], 100, 3, name[2], + fc->u.rreaddir.data + n, len - n); + ok (n < len, "Rreaddir encode three dirents didn't overflow"); + np_finalize_rreaddir (fc, n); + fc2 = _rcv_buf (fc, P9_RREADDIR); + ok (fc2 != NULL && fc->u.rreaddir.count == fc2->u.rreaddir.count, + "Rreaddir decode works"); + n = 0; + n += np_deserialize_p9dirent (&qid2[0], &offset, &type, name2[0], 128, + fc2->u.rreaddir.data + n, fc2->u.rreaddir.count - n); + ok (offset == 0 && type == 1 && strcmp (name2[0], name[0]) == 0, + "Rreaddir decode dirent 1 works"); + n += np_deserialize_p9dirent (&qid2[1], &offset, &type, name2[1], 128, + fc2->u.rreaddir.data + n, fc2->u.rreaddir.count - n); + ok (offset == 50 && type == 2 && strcmp (name2[1], name[1]) == 0, + "Rreaddir decode dirent 2 works"); + n += np_deserialize_p9dirent (&qid2[2], &offset, &type, name2[2], 128, + fc2->u.rreaddir.data + n, fc2->u.rreaddir.count - n); + ok (offset == 100 && type == 3 && strcmp (name2[2], name[2]) == 0, + "Rreaddir decode dirent 3 works"); + ok (n == fc2->u.rreaddir.count, "Rreaddir message is fully consumed"); + free (fc); + free (fc2); +} + +static void test_fsync (void) +{ + Npfcall *fc, *fc2; + + fc = np_create_tfsync(1, 42); + ok (fc != NULL, "Tfsync encode datasync=42 works"); + fc2 = _rcv_buf (fc, P9_TFSYNC); + ok (fc2 != NULL + && fc->u.tfsync.fid == fc2->u.tfsync.fid + && fc->u.tfsync.datasync == fc2->u.tfsync.datasync, + "Tfsync decode works"); + free (fc); + free (fc2); + + fc = np_create_rfsync(); + ok (fc != NULL, "Rfsync encode works"); + fc2 = _rcv_buf (fc, P9_RFSYNC); + ok (fc2 != NULL, "Rfsync decode works"); + + free (fc); + free (fc2); +} + +static void test_lock (void) +{ + Npfcall *fc, *fc2; + + fc = np_create_tlock (1, P9_LOCK_TYPE_UNLCK, 3, 4, 5, 6, "xyz"); + ok (fc != NULL, + "Tlock encode fid=1 type=UNLCK flags=3 start=4 length=5 proc_id=6" + " client_id=xyz works"); + fc2 = _rcv_buf (fc, P9_TLOCK); + ok (fc2 != NULL + && fc->u.tlock.fid == fc2->u.tlock.fid + && fc->u.tlock.type == fc2->u.tlock.type + && fc->u.tlock.flags == fc2->u.tlock.flags + && fc->u.tlock.start == fc2->u.tlock.start + && fc->u.tlock.length == fc2->u.tlock.length + && np_str9cmp (&fc->u.tlock.client_id, &fc2->u.tlock.client_id) == 0, + "Tlock decode works"); + free (fc); + free (fc2); + + fc = np_create_rlock (1); + ok (fc != NULL, "Rlock encode status=1 works"); + fc2 = _rcv_buf (fc, P9_RLOCK); + ok (fc2 != NULL && fc->u.rlock.status == fc2->u.rlock.status, + "Rlock decode works"); + free (fc); + free (fc2); +} + +static void test_getlock (void) +{ + Npfcall *fc, *fc2; + + fc = np_create_tgetlock (1, P9_LOCK_TYPE_UNLCK, 3, 4, 5, "xyz"); + ok (fc != NULL, + "Tgetlock encode fid=1 type=UNLCK start=3 length=4 proc_id=5" + " client_id=xyz works"); + fc2 = _rcv_buf (fc, P9_TGETLOCK); + ok (fc2 != NULL + && fc->u.tgetlock.fid == fc2->u.tgetlock.fid + && fc->u.tgetlock.type == fc2->u.tgetlock.type + && fc->u.tgetlock.start == fc2->u.tgetlock.start + && fc->u.tgetlock.length == fc2->u.tgetlock.length + && fc->u.tgetlock.proc_id == fc2->u.tgetlock.proc_id + && np_str9cmp (&fc->u.tgetlock.client_id, &fc2->u.tgetlock.client_id) == 0, + "Tgetlock decode works"); + free (fc); + free (fc2); + + fc = np_create_rgetlock (P9_LOCK_TYPE_WRLCK, 2, 3, 4, "xyz"); + ok (fc != NULL, + "Rgetlock encode type=WRLCK start=2 length=3 proc_id=4 client_id=xyz" + " works"); + fc2 = _rcv_buf (fc, P9_RGETLOCK); + ok (fc2 != NULL + && fc->u.rgetlock.type == fc2->u.rgetlock.type + && fc->u.rgetlock.start == fc2->u.rgetlock.start + && fc->u.rgetlock.length == fc2->u.rgetlock.length + && fc->u.rgetlock.proc_id == fc2->u.rgetlock.proc_id + && np_str9cmp (&fc->u.rgetlock.client_id, &fc2->u.rgetlock.client_id) == 0, + "Rgetlock decode works"); + free (fc); + free (fc2); +} + +static void test_link (void) +{ + Npfcall *fc, *fc2; + + fc = np_create_tlink (1, 2, "xyz"); + ok (fc != NULL, "Tlink encode dfid=1 fid=2 name=xyz works"); + fc2 = _rcv_buf (fc, P9_TLINK); + ok (fc2 != NULL + && fc->u.tlink.dfid == fc2->u.tlink.dfid + && fc->u.tlink.fid == fc2->u.tlink.fid + && np_str9cmp (&fc->u.tlink.name, &fc2->u.tlink.name) == 0, + "Tlink decode works"); + free (fc); + free (fc2); + + fc = np_create_rlink (); + ok (fc != NULL, "Rlink encode works"); + fc2 = _rcv_buf (fc, P9_RLINK); + ok (fc2 != NULL, "Rlink decodeworks"); + free (fc); + free (fc2); +} + +static void test_mkdir (void) +{ + Npfcall *fc, *fc2; + struct p9_qid qid = { 1, 2, 3 }; + + fc = np_create_tmkdir (1, "abc", 2, 3); + ok (fc != NULL, "Tmkdir encode dfid=1 name=abc mode=2 gid=3 works"); + fc2 = _rcv_buf (fc, P9_TMKDIR); + ok (fc2 != NULL + && fc->u.tmkdir.fid == fc2->u.tmkdir.fid + && np_str9cmp (&fc->u.tmkdir.name, &fc2->u.tmkdir.name) == 0 + && fc->u.tmkdir.mode == fc2->u.tmkdir.mode + && fc->u.tmkdir.gid == fc2->u.tmkdir.gid, + "Tmkdir decode works"); + free (fc); + free (fc2); + + fc = np_create_rmkdir (&qid); + ok (fc != NULL, "Rmkdir encode qid.type=1 qid.version=2 qid.path=3 works"); + fc2 = _rcv_buf (fc, P9_RMKDIR); + ok (fc2 != NULL + && fc->u.rmkdir.qid.type == fc2->u.rmkdir.qid.type + && fc->u.rmkdir.qid.version == fc2->u.rmkdir.qid.version + && fc->u.rmkdir.qid.path == fc2->u.rmkdir.qid.path, + "Rmkdir decode works"); + free (fc); + free (fc2); +} + +static void test_renameat (void) +{ + Npfcall *fc, *fc2; + + fc = np_create_trenameat (1, "abc", 2, "zyx"); + ok (fc != NULL, + "Trenameat encode olddirfd=1 oldname=abc newdirfd=2 newname=zyx works"); + fc2 = _rcv_buf (fc, P9_TRENAMEAT); + ok (fc2 != NULL + && fc->u.trenameat.olddirfid == fc2->u.trenameat.olddirfid + && np_str9cmp (&fc->u.trenameat.oldname, &fc2->u.trenameat.oldname) == 0 + && fc->u.trenameat.newdirfid == fc2->u.trenameat.newdirfid + && np_str9cmp (&fc->u.trenameat.newname, &fc2->u.trenameat.newname) == 0, + "Trenameat decode works"); + free (fc); + free (fc2); + + fc = np_create_rrenameat (); + ok (fc != NULL, "Rrenameat encode works"); + fc2 = _rcv_buf (fc, P9_RRENAMEAT); + ok (fc2 != NULL, "Rrenameat decode works"); + free (fc); + free (fc2); +} + +static void test_unlinkat (void) +{ + Npfcall *fc, *fc2; + + fc = np_create_tunlinkat(1, "abc", 2); + ok (fc != NULL, "Tunlinkat encode dirfd=1 name=abc flags=2 works"); + fc2 = _rcv_buf (fc, P9_TUNLINKAT); + ok (fc2 != NULL + && fc->u.tunlinkat.dirfid == fc2->u.tunlinkat.dirfid + && np_str9cmp (&fc->u.tunlinkat.name, &fc2->u.tunlinkat.name) == 0 + && fc->u.tunlinkat.flags == fc2->u.tunlinkat.flags, + "Tunlinkat decode works"); + free (fc); + free (fc2); + + fc = np_create_runlinkat (); + ok (fc != NULL, "Runlinkat encode works"); + fc2 = _rcv_buf (fc, P9_RUNLINKAT); + ok (fc2 != NULL, "Runlinkat works"); + + free (fc); + free (fc2); +} + +static void test_version (void) +{ + Npfcall *fc, *fc2; + + fc = np_create_tversion (TEST_MSIZE, "9p2000.L"); + ok (fc != NULL, "Tversion encode msize=%d version=9p2000.L works", TEST_MSIZE); + fc2 = _rcv_buf (fc, P9_TVERSION); + ok (fc2 != NULL + && fc->u.tversion.msize == fc2->u.tversion.msize + && np_str9cmp (&fc->u.tversion.version, &fc2->u.tversion.version) == 0, + "Tversion decode works"); + free (fc); + free (fc2); + + fc = np_create_rversion (TEST_MSIZE, "9p2000.L"); + ok (fc != NULL, "Rversion encode msize=%d version=9p2000.L works", TEST_MSIZE); + fc2 = _rcv_buf (fc, P9_RVERSION); + ok (fc2 != NULL + && fc->u.rversion.msize == fc2->u.rversion.msize + && np_str9cmp (&fc->u.rversion.version, &fc2->u.rversion.version) == 0, + "Rversion decode works"); + free (fc); + free (fc2); +} + +static void test_auth (void) +{ + Npfcall *fc, *fc2; + struct p9_qid qid = { 1, 2, 3 }; + + fc = np_create_tauth (1, "abc", "xyz", 4); + ok (fc != NULL, "Tauth encode afid=1 uname=abc aname=xyz n_uname=4 works"); + fc2 = _rcv_buf (fc, P9_TAUTH); + ok (fc2 != NULL + && fc->u.tauth.afid == fc2->u.tauth.afid + && np_str9cmp (&fc->u.tauth.uname, &fc2->u.tauth.uname) == 0 + && np_str9cmp (&fc->u.tauth.aname, &fc2->u.tauth.aname) == 0 + && fc->u.tauth.n_uname == fc2->u.tauth.n_uname, + "Tauth decode works"); + free (fc); + free (fc2); + + fc = np_create_rauth (&qid); + ok (fc != NULL, "Rauth encode qid.type=1 qid.version=2 qid.path=3 works"); + fc2 = _rcv_buf (fc, P9_RAUTH); + ok (fc2 != NULL + && fc->u.rauth.qid.type == fc2->u.rauth.qid.type + && fc->u.rauth.qid.version == fc2->u.rauth.qid.version + && fc->u.rauth.qid.path == fc2->u.rauth.qid.path, + "Rauth decode works"); + free (fc); + free (fc2); +} + +static void test_flush (void) +{ + Npfcall *fc, *fc2; + char buf[STATIC_RFLUSH_SIZE]; + + fc = np_create_tflush (1); + ok (fc != NULL, "Tflush encode oldtag=1 works"); + fc2 = _rcv_buf (fc, P9_TFLUSH); + ok (fc2 != NULL && fc->u.tflush.oldtag == fc2->u.tflush.oldtag, + "Tflush decode works"); + free (fc); + free (fc2); + + fc = np_create_rflush (); + ok (fc != NULL, "Rflush encode works"); + fc2 = _rcv_buf (fc, P9_RFLUSH); + ok (fc2 != NULL, "Rflush decode works"); + free (fc); + free (fc2); + + fc = np_create_rflush_static (buf, sizeof(buf)); + ok (fc != NULL, "Rflush encode (static) works"); + fc2 = _rcv_buf (fc, P9_RFLUSH); + ok (fc2 != NULL, "Rflush decode (from static) works"); + // fc is static memory + free (fc2); +} + +static void test_attach (void) +{ + Npfcall *fc, *fc2; + struct p9_qid qid = { 1, 2, 3 }; + + fc = np_create_tattach (1, 2, "abc", "xyz", 5); + ok (fc != NULL, + "Tattach encode fid=1 afid=2 uname=abc aname=xyz, n_uname=5 works"); + fc2 = _rcv_buf (fc, P9_TATTACH); + ok (fc2 != NULL + && fc->u.tattach.fid == fc2->u.tattach.fid + && fc->u.tattach.afid == fc2->u.tattach.afid + && np_str9cmp (&fc->u.tattach.uname, &fc2->u.tattach.uname) == 0 + && np_str9cmp (&fc->u.tattach.aname, &fc2->u.tattach.aname) == 0 + && fc->u.tattach.n_uname == fc2->u.tattach.n_uname, + "Tattach decode works"); + free (fc); + free (fc2); + + fc = np_create_rattach (&qid); + ok (fc != NULL, "Rattach encode qid.type=1 qid.version=2 qid.path=3 works"); + fc2 = _rcv_buf (fc, P9_RATTACH); + ok (fc2 != NULL + && fc->u.rattach.qid.type == fc2->u.rattach.qid.type + && fc->u.rattach.qid.version == fc2->u.rattach.qid.version + && fc->u.rattach.qid.path == fc2->u.rattach.qid.path, + "Rattach decode works"); + free (fc); + free (fc2); +} + +static void test_walk (void) +{ + Npfcall *fc, *fc2; + char *wnames[P9_MAXWELEM] = { + "abc", "def", "ghi", "jkl", + "abc", "def", "ghi", "jkl", + "abc", "def", "ghi", "jkl", + "abc", "def", "ghi", "jkl", + }; + struct p9_qid wqids [P9_MAXWELEM] = { + { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }, { 10, 11, 12 }, + { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }, { 10, 11, 12 }, + { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }, { 10, 11, 12 }, + { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }, { 10, 11, 12 }, + }; + int i; + + if (P9_MAXWELEM != 16) + BAIL_OUT ("P9_MAXWELEM != 16"); + fc = np_create_twalk (1, 2, P9_MAXWELEM, wnames); + ok (fc != NULL, "Twalk encode fid=1 newfid=2 nwname=16 works"); + fc2 = _rcv_buf (fc, P9_TWALK); + ok (fc2 != NULL + && fc->u.twalk.fid == fc2->u.twalk.fid + && fc->u.twalk.newfid == fc2->u.twalk.newfid + && fc->u.twalk.nwname == fc2->u.twalk.nwname + && fc->u.twalk.nwname == P9_MAXWELEM, + "Twalk decode works"); + int errors = 0; + for (i = 0; i < P9_MAXWELEM; i++) { + if (np_str9cmp (&fc->u.twalk.wnames[i], &fc2->u.twalk.wnames[i]) != 0) + errors++; + } + ok (errors == 0, "Twalk decoded wnames correctly"); + free (fc); + free (fc2); + + fc = np_create_rwalk (P9_MAXWELEM, wqids); + ok (fc != NULL, "Rwalk encode nwqid=16 works"); + fc2 = _rcv_buf (fc, P9_RWALK); + ok (fc2 != NULL + && fc->u.rwalk.nwqid == P9_MAXWELEM + && fc->u.rwalk.nwqid == fc2->u.rwalk.nwqid, + "Rwalk decode works"); + errors = 0; + for (i = 0; i < P9_MAXWELEM; i++) { + if (fc->u.rwalk.wqids[i].type != fc2->u.rwalk.wqids[i].type + || fc->u.rwalk.wqids[i].version != fc2->u.rwalk.wqids[i].version + || fc->u.rwalk.wqids[i].path != fc2->u.rwalk.wqids[i].path) + errors++; + } + ok (errors == 0, "Rwalk decoded qids correctly"); + free (fc); + free (fc2); +} + +static void test_read (void) +{ + Npfcall *fc, *fc2; + u8 buf[128]; + + fc = np_create_tread (1, 2, 3); + ok (fc != NULL, "Tread encode fid=1 offset=2 count=3 works"); + fc2 = _rcv_buf (fc, P9_TREAD); + ok (fc2 != NULL + && fc->u.tread.fid == fc2->u.tread.fid + && fc->u.tread.offset == fc2->u.tread.offset + && fc->u.tread.count == fc2->u.tread.count, + "Tread decode works"); + free (fc); + free (fc2); + + memset (buf, 0xf0, sizeof(buf)); + fc = np_create_rread (sizeof (buf), buf); + ok (fc != NULL, "Rread encode count=128 works"); + np_set_rread_count (fc, sizeof (buf)); + fc2 = _rcv_buf (fc, P9_RREAD); + ok (fc2 != NULL + && fc->u.rread.count == fc2->u.rread.count + && memcmp (fc->u.rread.data, fc2->u.rread.data, fc->u.rread.count) == 0, + "Rread decode works"); + free (fc); + free (fc2); +} + +static void test_write (void) +{ + Npfcall *fc, *fc2; + u8 buf[128]; + + memset (buf, 0x0f, sizeof(buf)); + + fc = np_create_twrite (1, 2, sizeof (buf), buf); + ok (fc != NULL, "Twrite encode fid=1 offset=2 count=128 works"); + fc2 = _rcv_buf (fc, P9_TWRITE); + ok (fc2 != NULL + && fc->u.twrite.fid == fc2->u.twrite.fid + && fc->u.twrite.offset == fc2->u.twrite.offset + && fc->u.twrite.count == fc2->u.twrite.count + && memcmp (fc->u.twrite.data, fc2->u.twrite.data, fc->u.twrite.count) == 0, + "Twrite decode works"); + free (fc); + free (fc2); + + fc = np_create_rwrite (1); + ok (fc != NULL, "Rwrite encode count=1 works"); + fc2 = _rcv_buf (fc, P9_RWRITE); + ok (fc2 != NULL && fc->u.rwrite.count == fc2->u.rwrite.count, + "Rwrite decode works"); + free (fc); + free (fc2); +} + +static void test_clunk (void) +{ + Npfcall *fc, *fc2; + + fc = np_create_tclunk (1); + ok (fc != NULL, "Tclunk encode fid=1 works"); + fc2 = _rcv_buf (fc, P9_TCLUNK); + ok (fc2 != NULL && fc->u.tclunk.fid == fc2->u.tclunk.fid, + "Tclunk decode works"); + free (fc); + free (fc2); + + fc = np_create_rclunk (); + ok (fc != NULL, "Rclunk encode works"); + fc2 = _rcv_buf (fc, P9_RCLUNK); + ok (fc2 != NULL, "Rclunk decode works"); + + free (fc); + free (fc2); +} + +static void test_remove (void) +{ + Npfcall *fc, *fc2; + + fc = np_create_tremove (1); + ok (fc != NULL, "Tremove encode fid=1 works"); + fc2 = _rcv_buf (fc, P9_TREMOVE); + ok (fc2 != NULL && fc->u.tremove.fid == fc2->u.tremove.fid, + "Tremove decode works"); + free (fc); + free (fc2); + + fc = np_create_rremove (); + ok (fc != NULL, "Rremove encode works"); + fc2 = _rcv_buf (fc, P9_RREMOVE); + ok (fc2 != NULL, "Rremove decode works"); + free (fc); + free (fc2); +} + +static void test_truncated_tlink (void) +{ + Npfcall *fc; + + if (!(fc = np_create_tlink (1, 2, "xyz"))) + BAIL_OUT ("np_create_tlink failed"); + + // truncate fc->pkt so entire name is missing + fc->size -= 3; + fc->pkt[0] = fc->size; + fc->pkt[1] = fc->size >> 8; + fc->pkt[2] = fc->size >> 16; + fc->pkt[3] = fc->size >> 24; + + ok (np_deserialize (fc) == 0, + "Tlink decode failed as expected on truncated message (issue#109)"); + + free (fc); +} + +int main (int argc, char *argv[]) +{ + plan (NO_PLAN); + + test_rlerror (); + test_statfs (); + test_lopen (); + test_lcreate (); + test_symlink (); + test_mknod (); + test_rename (); + test_readlink(); + test_getattr (); + test_setattr (); + test_xattrwalk (); + test_xattrcreate (); + test_readdir (); + test_fsync (); + test_lock (); + test_getlock (); + test_link (); + test_mkdir (); + test_renameat (); + test_unlinkat (); + test_version (); + test_auth (); + test_flush (); + test_attach (); + test_walk (); + test_read (); + test_write (); + test_clunk (); + test_remove (); + + test_truncated_tlink (); + + done_testing (); + + exit (0); +} + +/* + * vi:tabstop=4 shiftwidth=4 expandtab + */ diff --git a/src/libnpfs/test/fidpool.c b/src/libnpfs/test/fidpool.c new file mode 100644 index 00000000..d83a2fab --- /dev/null +++ b/src/libnpfs/test/fidpool.c @@ -0,0 +1,110 @@ +/*************************************************************\ + * Copyright (C) 2010 by Lawrence Livermore National Security, LLC. + * + * This file is part of npfs, a framework for 9P synthetic file systems. + * For details see https://sourceforge.net/projects/npfs. + * + * SPDX-License-Identifier: MIT + *************************************************************/ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "src/libnpfs/9p.h" +#include "src/libnpfs/npfs.h" + +#include "src/liblsd/list.h" +#include "src/libtap/tap.h" + + +void diag_logger (const char *fmt, va_list ap) +{ + char buf[1024]; /* make it large enough for protocol debug output */ + vsnprintf (buf, sizeof (buf), fmt, ap); /* ignore overflow */ + fprintf (stderr, "# %s\n", buf); +} + + +int main (int argc, char *argv[]) +{ + Npsrv srv; + Npconn conn; + Npfid **fid; + unsigned long nfids = 1000; + int i, n; + + plan (NO_PLAN); + + if (argc > 2) + BAIL_OUT ("Usage: test_fidpool.t [nfids]"); + if (argc == 2) { + nfids = strtoul (argv[1], NULL, 10); + if (nfids == 0) + BAIL_OUT ("invalid nfids value\n"); + } + fid = (Npfid **)malloc (nfids * sizeof (Npfid *)); + if (!fid) + BAIL_OUT ("out of memory"); + memset (&srv, 0, sizeof (srv)); + srv.logmsg = diag_logger; + srv.flags |= SRV_FLAGS_DEBUG_FIDPOOL; + conn.fidpool = np_fidpool_create (); + conn.srv = &srv; + + ok (np_fidpool_count (conn.fidpool) == 0, + "np_fidpool_count returns 0") ; + + int errors = 0; + for (i = 0; i < nfids; i++) { + fid[i] = np_fid_find (&conn, i); + if (fid[i] != NULL) { + diag ("np_fid_find (i=%d) failed", i); + errors++; + } + } + diag ("np_find_fid called on %d fids", nfids); + ok (errors == 0, "there were no errors"); + ok (np_fidpool_count (conn.fidpool) == 0, + "np_fidpool_count returns 0"); + + for (i = 0; i < nfids; i++) { + fid[i] = np_fid_create (&conn, i); + np_fid_incref (fid[i]); + np_fid_incref (fid[i]); + } + diag ("np_fid_create called %d times (with 2 increfs each)"); + ok (np_fidpool_count (conn.fidpool) == nfids, + "np_fidpool_count returns %d", nfids); + + for (i = 0; i < nfids; i++) { + np_fid_decref (&fid[i]); + np_fid_decref (&fid[i]); + np_fid_decref (&fid[i]); + } + diag ("np_fid_decref called %d times (with 2 more decrefs each)", nfids); + ok (np_fidpool_count (conn.fidpool) == 0, + "np_fidpool_count returns 0"); + + n = np_fidpool_destroy (conn.fidpool); + ok (n == 0, + "np_fidpool_destroy returned 0 (meaning 0 unclunked)", n); + + free (fid); + + done_testing (); + exit (0); +} + +/* + * vi:tabstop=4 shiftwidth=4 expandtab + */ diff --git a/src/libnpfs/test/setfsuid.c b/src/libnpfs/test/setfsuid.c new file mode 100644 index 00000000..8511119d --- /dev/null +++ b/src/libnpfs/test/setfsuid.c @@ -0,0 +1,194 @@ +/*************************************************************\ + * Copyright (C) 2010 by Lawrence Livermore National Security, LLC. + * + * This file is part of npfs, a framework for 9P synthetic file systems. + * For details see https://sourceforge.net/projects/npfs. + * + * SPDX-License-Identifier: MIT + *************************************************************/ + +/* check that threads can independently setfsuid + * + * N.B. error handling for setfsuid/setfsgid is broken in the kernel. + * Two errors can be detected: + * - return -1 with errno set (EINVAL) + * - return of value != previous fsuid/fsgid + * However, they can silently fail, e.g. if process doesn't have CAP_SETUID. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "src/libtap/tap.h" + +#define TEST_UID 100 +#define TEST_GID 100 + +typedef enum { S0, S1, S2, S3, S4, S5 } state_t; + +static state_t state = S0; +static pthread_mutex_t state_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t state_cond = PTHREAD_COND_INITIALIZER; + +static void test_lock (pthread_mutex_t *l) +{ + int n = pthread_mutex_lock (l); + if (n) + BAIL_OUT ("pthread_mutex_lock: %s", strerror (n)); +} +static void test_unlock (pthread_mutex_t *l) +{ + int n = pthread_mutex_unlock (l); + if (n) + BAIL_OUT ("pthread_mutex_unlock: %s", strerror (n)); +} +static void test_condsig (pthread_cond_t *c) +{ + int n = pthread_cond_signal (c); + if (n) + BAIL_OUT ("pthread_cond_signal: %s", strerror (n)); +} +static void test_condwait (pthread_cond_t *c, pthread_mutex_t *l) +{ + int n = pthread_cond_wait (c, l); + if (n) + BAIL_OUT ("pthread_cond_wait: %s", strerror (n)); +} +static void test_thread_create (pthread_t *t, void *(f)(void *), void *a) +{ + int n = pthread_create (t, NULL, f, a); + if (n) + BAIL_OUT ("pthread_create: %s", strerror (n)); +} +static void test_thread_join (pthread_t t, void **a) +{ + int n = pthread_join (t, a); + if (n) + BAIL_OUT ("pthread_join: %s", strerror (n)); +} + +static void +check_fsid (char *s, uid_t uid, gid_t gid) +{ + int fd; + char path[] = "/tmp/testfsuid.XXXXXX"; + struct stat sb; + + fd = mkstemp (path); + if (fd < 0) + BAIL_OUT ("mkstemp: %s", strerror (errno)); + if (fstat (fd, &sb) < 0) + BAIL_OUT ("fstat: %s", strerror (errno)); + if (unlink (path) < 0) + BAIL_OUT ("unlink %s: %s", path, strerror (errno)); + ok (sb.st_uid == uid && sb.st_gid == gid, + "%s: temp file created with %d:%d", s, uid, gid); +} + +static void +change_fsid (char *s, uid_t fromuid, gid_t fromgid, uid_t uid, gid_t gid) +{ + int u; + int g; + + diag ("%s: changing to %d:%d", s, uid, gid); + if (fromuid != uid) { + u = setfsuid (uid); + if (u == -1) + diag ("%s: setfsuid: %s", s, strerror (errno)); + else if (u != fromuid) + diag ("%s: setfsuid returned %d (wanted %d)", s, u, fromuid); + } + if (fromgid != gid) { + g = setfsgid (gid); + if (g == -1) + diag ("%s: setfsgid: %s", s, strerror (errno)); + if (g != fromgid) + diag ("%s: setfsgid returned %d (wanted %d)", s, g, fromgid); + } +} + +static void +change_state (state_t s) +{ + test_lock (&state_lock); + state = s; + test_condsig (&state_cond); + test_unlock (&state_lock); +} + +static void +wait_state (state_t s) +{ + test_lock (&state_lock); + while ((state != s)) + test_condwait (&state_cond, &state_lock); + test_unlock (&state_lock); +} + +static void *proc1 (void *a) +{ + check_fsid ("task1", 0, 0); + change_state (S1); + wait_state (S2); + check_fsid ("task1", 0, 0); + change_fsid ("task1", 0, 0, TEST_UID, TEST_GID); + check_fsid ("task1", TEST_UID, TEST_GID); + change_state (S3); + wait_state (S4); + check_fsid ("task1", TEST_UID, TEST_GID); + return NULL; +} + +static void *proc2 (void *a) +{ + wait_state (S1); + check_fsid ("task2", 0, 0); + change_fsid ("task2", 0, 0, TEST_UID, TEST_GID); + check_fsid ("task2", TEST_UID, TEST_GID); + change_state (S2); + wait_state (S3); + change_fsid ("task2", TEST_UID, TEST_GID, 0, 0); + check_fsid ("task2", 0, 0); + change_state (S4); + return NULL; +} + +int main(int argc, char *argv[]) +{ + pthread_t t1, t2; + + if (geteuid () != 0 || getenv ("FAKEROOTKEY") != NULL) + plan (SKIP_ALL, "this test must run as root"); + plan (NO_PLAN); + + check_fsid ("task0", 0, 0); + + test_thread_create (&t1, proc1, NULL); + test_thread_create (&t2, proc2, NULL); + + test_thread_join (t2, NULL); + test_thread_join (t1, NULL); + + check_fsid ("task0", 0, 0); + + exit (0); +} + +/* + * vi:tabstop=4 shiftwidth=4 expandtab + */ diff --git a/src/libnpfs/test/setgroups.c b/src/libnpfs/test/setgroups.c new file mode 100644 index 00000000..df4312b0 --- /dev/null +++ b/src/libnpfs/test/setgroups.c @@ -0,0 +1,305 @@ +/*************************************************************\ + * Copyright (C) 2010 by Lawrence Livermore National Security, LLC. + * + * This file is part of npfs, a framework for 9P synthetic file systems. + * For details see https://sourceforge.net/projects/npfs. + * + * SPDX-License-Identifier: MIT + *************************************************************/ + +/* Check that setgroups(2) works as expected with setfsuid/fsgid. + * + * setgroups(2) affects the entire process as dictated by POSIX. + * Check that threads can use the underlying system call, SYS_setgroups, + * to independently change their supplementary groups. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "src/libtap/tap.h" + +static void check_fsid (uid_t uid, gid_t gid) +{ + int fd; + char path[] = "/tmp/testfsuidsupp.XXXXXX"; + struct stat sb; + + fd = mkstemp (path); + if (fd < 0) + BAIL_OUT ("mkstemp: %s", strerror (errno)); + if (fstat (fd, &sb) < 0) + BAIL_OUT ("fstat: %s", strerror (errno)); + if (unlink (path) < 0) + BAIL_OUT ("unlink: %s", strerror (errno)); + + ok (uid == sb.st_uid && gid == sb.st_gid, + "now files are created with %d:%d", uid, gid); +} + +/* Create a test file and return its path. + */ +static char *create_file (uid_t uid, gid_t gid, mode_t mode) +{ + int fd; + static char path[] = "/tmp/testfsuidsupp.XXXXXX"; + + fd = mkstemp (path); + if (fd < 0) + BAIL_OUT ("mkstemp: %s", strerror (errno)); + if (fchown (fd, 0, 101) < 0) + BAIL_OUT ("fchown: %s", strerror (errno)); + if (fchmod (fd, 0040) < 0) + BAIL_OUT ("fchmod: %s", strerror (errno)); + + diag ("created %s %d:%d mode 0%o", path, uid, gid, mode); + + return path; +} + +static void check_open_rdonly (char *path, bool expect_success) +{ + int fd; + + fd = open (path, O_RDONLY); + if (expect_success) + ok (fd >= 0, "successfully opened %s", path); + else + ok (fd < 0, "failed to open %s (as expected)", path); + close (fd); +} + +static void change_fsid (uid_t olduid, gid_t oldgid, uid_t uid, gid_t gid) +{ + int u; + int g; + + if (uid != olduid) { + u = setfsuid (uid); + ok (u == olduid, "setfsuid %d->%d works", olduid, uid); + if (u == -1) + diag ("setfsuid: %s", strerror (errno)); + else if (u != olduid) + diag ("setfsuid returned %d (wanted %d)", u, olduid); + } + if (gid != oldgid) { + g = setfsgid (gid); + ok (g == oldgid, "setfsgid %d->%d works", oldgid, gid); + if (g == -1) + diag ("setfsgid: %s", strerror (errno)); + else if (g != oldgid) + diag ("setfsgid returned %d (wanted %d)", g, oldgid); + } + check_fsid (uid, gid); +} + +void test_single_thread (void) +{ + char *path; + gid_t gids[] = { 101 }; + + /* clear supplemental groups */ + if (setgroups (0, NULL) < 0) + BAIL_OUT ("setgroups: %s", strerror (errno)); + diag ("supplemental groups cleared"); + + path = create_file (0, 101, 0440); + + change_fsid (0, 0, 100, 100); + check_open_rdonly (path, false); + + change_fsid (100, 100, 100, 101); + check_open_rdonly (path, true); + + change_fsid (100, 101, 100, 100); + check_open_rdonly (path, false); + + /* set 101 in supplemental groups */ + if (setgroups (1, gids) < 0) + BAIL_OUT ("setgroups: %s", strerror (errno)); + diag ("%d added to supplemental groups", gids[0]); + check_open_rdonly (path, true); + + /* clear supplemental groups */ + if (setgroups (0, NULL) < 0) + BAIL_OUT ("setgroups: %s", strerror (errno)); + diag ("supplemental groups cleared"); + check_open_rdonly (path, false); + + /* clean up */ + change_fsid (100, 100, 0, 0); + if (unlink (path) < 0) + BAIL_OUT ("unlink %s: %s", path, strerror (errno)); +} + +typedef enum { S0, S1, S2, S3, S4, S5 } state_t; + +static state_t state = S0; +static pthread_mutex_t state_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t state_cond = PTHREAD_COND_INITIALIZER; + +static void test_lock (pthread_mutex_t *l) +{ + int n = pthread_mutex_lock (l); + if (n) + BAIL_OUT ("pthread_mutex_lock: %s", strerror (n)); +} +static void test_unlock (pthread_mutex_t *l) +{ + int n = pthread_mutex_unlock (l); + if (n) + BAIL_OUT ("pthread_mutex_unlock: %s", strerror (n)); +} +static void test_condsig (pthread_cond_t *c) +{ + int n = pthread_cond_signal (c); + if (n) + BAIL_OUT ("pthread_cond_signal: %s", strerror (n)); +} +static void test_condwait (pthread_cond_t *c, pthread_mutex_t *l) +{ + int n = pthread_cond_wait (c, l); + if (n) + BAIL_OUT ("pthread_cond_wait: %s", strerror (n)); +} +static void test_thread_create (pthread_t *t, void *(f)(void *), void *a) +{ + int n = pthread_create (t, NULL, f, a); + if (n) + BAIL_OUT ("pthread_create: %s", strerror (n)); +} +static void test_thread_join (pthread_t t, void **a) +{ + int n = pthread_join (t, a); + if (n) + BAIL_OUT ("pthread_join: %s", strerror (n)); +} + +static void change_state (state_t s) +{ + test_lock (&state_lock); + state = s; + test_condsig (&state_cond); + test_unlock (&state_lock); +} + +static void wait_state (state_t s) +{ + test_lock (&state_lock); + while ((state != s)) + test_condwait (&state_cond, &state_lock); + test_unlock (&state_lock); +} + +static const char *strgroups (char *buf, size_t size, gid_t *g, size_t len) +{ + buf[0] = '\0'; + for (int i = 0; i < len; i++) { + const char *pad = i == 0 ? "" : " "; + snprintf (buf + strlen (buf), size - strlen (buf), "%s%d", pad, g[i]); + } + return buf; +} + +static void check_groups (char *s, char *expect) +{ + gid_t g[32]; + int n; + char buf[256]; + + n = getgroups (1, g); + if (n < 0) + BAIL_OUT ("%s: getgroups: %s", s, strerror (errno)); + strgroups (buf, sizeof (buf), g, n); + is (buf, expect, "%s: getgroups returned [%s]", s, expect); +} + +static void *proc1 (void *a) +{ + gid_t g[] = { 101 }; + + check_groups ("task1", ""); + change_state (S1); + + wait_state (S2); + check_groups ("task1", ""); + + diag ("task1: SYS_setgroups [101]"); + if (syscall (SYS_setgroups, 1, g) < 0) + BAIL_OUT ("task1: SYS_setgroups: %s", strerror (errno)); + check_groups ("task1", "101"); + change_state (S3); + + wait_state (S4); + return NULL; +} + +static void *proc2 (void *a) +{ + gid_t g[] = { 100 }; + + wait_state (S1); + check_groups ("task2", ""); + + diag ("task2: SYS_setgroups [100]"); + if (syscall (SYS_setgroups, 1, g) < 0) + BAIL_OUT ("task2: SYS_setgroups: %s", strerror (errno)); + check_groups ("task2", "100"); + change_state (S2); + + wait_state (S3); + check_groups ("task2", "100"); + change_state (S4); + return NULL; +} + +void test_multi_thread (void) +{ + pthread_t t1, t2; + + diag ("task0: SYS_setgroups []"); + if (syscall (SYS_setgroups, 0, NULL) < 0) + BAIL_OUT ("task0: SYS_setgroups: %s", strerror (errno)); + check_groups ("task0", ""); + + test_thread_create (&t1, proc1, NULL); + test_thread_create (&t2, proc2, NULL); + + test_thread_join (t2, NULL); + test_thread_join (t1, NULL); + + check_groups ("task0", ""); +} + +int main(int argc, char *argv[]) +{ + if (geteuid () != 0 || getenv ("FAKEROOTKEY") != NULL) + plan (SKIP_ALL, "this test must run as root"); + plan (NO_PLAN); + + test_single_thread (); + test_multi_thread (); + + done_testing (); + + exit (0); +} + +/* + * vi:tabstop=4 shiftwidth=4 expandtab + */ diff --git a/src/libnpfs/test/setreuid.c b/src/libnpfs/test/setreuid.c new file mode 100644 index 00000000..cd93e37f --- /dev/null +++ b/src/libnpfs/test/setreuid.c @@ -0,0 +1,155 @@ +/*************************************************************\ + * Copyright (C) 2010 by Lawrence Livermore National Security, LLC. + * + * This file is part of npfs, a framework for 9P synthetic file systems. + * For details see https://sourceforge.net/projects/npfs. + * + * SPDX-License-Identifier: MIT + *************************************************************/ + +/* check that threads CANNOT independently setreuid */ + +/* This was an assumption made in the old npfs code, no longer true + * post-linuxthreads. It's here as a demonstration of that fact, + * and in case anything changes in this area we might want to flag it. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "src/libtap/tap.h" + +typedef enum { S0, S1, S2, S3, S4, S5 } state_t; + +static state_t state = S0; +static pthread_mutex_t state_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t state_cond = PTHREAD_COND_INITIALIZER; + +static void test_lock (pthread_mutex_t *l) +{ + int n = pthread_mutex_lock (l); + if (n) + BAIL_OUT ("pthread_mutex_lock: %s", strerror (n)); +} +static void test_unlock (pthread_mutex_t *l) +{ + int n = pthread_mutex_unlock (l); + if (n) + BAIL_OUT ("pthread_mutex_unlock: %s", strerror (n)); +} +static void test_condsig (pthread_cond_t *c) +{ + int n = pthread_cond_signal (c); + if (n) + BAIL_OUT ("pthread_cond_signal: %s", strerror (n)); +} +static void test_condwait (pthread_cond_t *c, pthread_mutex_t *l) +{ + int n = pthread_cond_wait (c, l); + if (n) + BAIL_OUT ("pthread_cond_wait: %s", strerror (n)); +} +static void test_thread_create (pthread_t *t, void *(f)(void *), void *a) +{ + int n = pthread_create (t, NULL, f, a); + if (n) + BAIL_OUT ("pthread_create: %s", strerror (n)); +} +static void test_thread_join (pthread_t t, void **a) +{ + int n = pthread_join (t, a); + if (n) + BAIL_OUT ("pthread_join: %s", strerror (n)); +} + +static void change_state (state_t s) +{ + test_lock (&state_lock); + state = s; + test_condsig (&state_cond); + test_unlock (&state_lock); +} + +static void wait_state (state_t s) +{ + test_lock (&state_lock); + while ((state != s)) + test_condwait (&state_cond, &state_lock); + test_unlock (&state_lock); +} + +static void *proc1 (void *a) +{ + ok (geteuid () == 0, "task1: geteuid returned 0"); + change_state (S1); + + wait_state (S2); + ok (geteuid () == 100, "task1: geteuid returned 100"); + ok (setreuid (0, 0) == 0, "task1: setreuid 0 0 worked"); + ok (setreuid (-1, 101) == 0, "task1: setreuid -1 %d works", 101); + ok (geteuid () == 101, "task1: geteuid returned 101"); + change_state (S3); + + wait_state (S4); + ok (geteuid () == 102, "task1: geteuid returned 102"); + return NULL; +} + +static void *proc2 (void *a) +{ + wait_state (S1); + ok (geteuid () == 0, "task2: geteuid returned 0"); + ok (setreuid (0, 0) == 0, "setreuid 0 0 worked"); + ok (setreuid (-1, 100) == 0, "setreuid -1 %d worked", 100); + ok (geteuid () == 100, "task2: geteuid returned 100"); + change_state (S2); + + wait_state (S3); + ok (geteuid () == 101, "task2: geteuid returned 101"); + ok (setreuid (0, 0) == 0, "setreuid 0 0 worked"); + ok (setreuid (-1, 102) == 0, "setreuid -1 %d worked", 102); + ok (geteuid () == 102, "task2: geteuid returned 102"); + change_state (S4); + return NULL; +} + +int main(int argc, char *argv[]) +{ + if (geteuid () != 0 || getenv ("FAKEROOTKEY") != NULL) + plan (SKIP_ALL, "this test must run as root"); + + plan (NO_PLAN); + + pthread_t t1, t2; + + ok (geteuid () == 0, "task0: geteuid returned 0"); + + test_thread_create (&t1, proc1, NULL); + test_thread_create (&t2, proc2, NULL); + + test_thread_join (t2, NULL); + test_thread_join (t1, NULL); + + ok (geteuid () == 102, "task0: geteuid returned 102"); + + done_testing (); + + exit (0); +} + +/* + * vi:tabstop=4 shiftwidth=4 expandtab + */ diff --git a/src/libtap/Makefile.am b/src/libtap/Makefile.am new file mode 100644 index 00000000..6ccf1a23 --- /dev/null +++ b/src/libtap/Makefile.am @@ -0,0 +1,5 @@ +AM_CFLAGS = @WARNING_CFLAGS@ + +check_LIBRARIES = libtap.a + +libtap_a_SOURCES = tap.c tap.h diff --git a/src/libtap/tap.c b/src/libtap/tap.c new file mode 100644 index 00000000..152e39e8 --- /dev/null +++ b/src/libtap/tap.c @@ -0,0 +1,354 @@ +/* +libtap - Write tests in C +Copyright 2012 Jake Gelbman +This file is licensed under the LGPL +*/ + +#define _DEFAULT_SOURCE 1 + +#include +#include +#include +#include +#include "tap.h" + +static int expected_tests = NO_PLAN; +static int failed_tests; +static int current_test; +static char *todo_mesg; + +static char * +vstrdupf (const char *fmt, va_list args) { + char *str; + int size; + va_list args2; + va_copy(args2, args); + if (!fmt) + fmt = ""; + size = vsnprintf(NULL, 0, fmt, args2) + 2; + str = malloc(size); + if (!str) { + perror("malloc error"); + exit(1); + } + vsprintf(str, fmt, args); + va_end(args2); + return str; +} + +void +tap_plan (int tests, const char *fmt, ...) { + expected_tests = tests; + if (tests == SKIP_ALL) { + char *why; + va_list args; + va_start(args, fmt); + why = vstrdupf(fmt, args); + va_end(args); + printf("1..0 "); + diag("SKIP %s\n", why); + exit(0); + } + if (tests != NO_PLAN) { + printf("1..%d\n", tests); + } +} + +int +vok_at_loc (const char *file, int line, int test, const char *fmt, + va_list args) +{ + char *name = vstrdupf(fmt, args); + if (!test) { + printf("not "); + } + printf("ok %d", ++current_test); + if (*name) + printf(" - %s", name); + if (todo_mesg) { + printf(" # TODO"); + if (*todo_mesg) + printf(" %s", todo_mesg); + } + printf("\n"); + if (!test) { + printf("# Failed "); + if (todo_mesg) + printf("(TODO) "); + printf("test "); + if (*name) + printf("'%s'\n# ", name); + printf("at %s line %d.\n", file, line); + if (!todo_mesg) + failed_tests++; + } + free(name); + return test; +} + +int +ok_at_loc (const char *file, int line, int test, const char *fmt, ...) { + va_list args; + va_start(args, fmt); + vok_at_loc(file, line, test, fmt, args); + va_end(args); + return test; +} + +static int +mystrcmp (const char *a, const char *b) { + return a == b ? 0 : !a ? -1 : !b ? 1 : strcmp(a, b); +} + +#define eq(a, b) (!mystrcmp(a, b)) +#define ne(a, b) (mystrcmp(a, b)) + +int +is_at_loc (const char *file, int line, const char *got, const char *expected, + const char *fmt, ...) +{ + int test = eq(got, expected); + va_list args; + va_start(args, fmt); + vok_at_loc(file, line, test, fmt, args); + va_end(args); + if (!test) { + diag(" got: '%s'", got); + diag(" expected: '%s'", expected); + } + return test; +} + +int +isnt_at_loc (const char *file, int line, const char *got, const char *expected, + const char *fmt, ...) +{ + int test = ne(got, expected); + va_list args; + va_start(args, fmt); + vok_at_loc(file, line, test, fmt, args); + va_end(args); + if (!test) { + diag(" got: '%s'", got); + diag(" expected: anything else"); + } + return test; +} + +int +cmp_ok_at_loc (const char *file, int line, int a, const char *op, int b, + const char *fmt, ...) +{ + int test = eq(op, "||") ? a || b + : eq(op, "&&") ? a && b + : eq(op, "|") ? a | b + : eq(op, "^") ? a ^ b + : eq(op, "&") ? a & b + : eq(op, "==") ? a == b + : eq(op, "!=") ? a != b + : eq(op, "<") ? a < b + : eq(op, ">") ? a > b + : eq(op, "<=") ? a <= b + : eq(op, ">=") ? a >= b + : eq(op, "<<") ? a << b + : eq(op, ">>") ? a >> b + : eq(op, "+") ? a + b + : eq(op, "-") ? a - b + : eq(op, "*") ? a * b + : eq(op, "/") ? a / b + : eq(op, "%") ? a % b + : diag("unrecognized operator '%s'", op); + va_list args; + va_start(args, fmt); + vok_at_loc(file, line, test, fmt, args); + va_end(args); + if (!test) { + diag(" %d", a); + diag(" %s", op); + diag(" %d", b); + } + return test; +} + +static int +find_mem_diff (const char *a, const char *b, size_t n, size_t *offset) { + size_t i; + if (a == b) + return 0; + if (!a || !b) + return 2; + for (i = 0; i < n; i++) { + if (a[i] != b[i]) { + *offset = i; + return 1; + } + } + return 0; +} + +int +cmp_mem_at_loc (const char *file, int line, const void *got, + const void *expected, size_t n, const char *fmt, ...) +{ + size_t offset; + int diff = find_mem_diff(got, expected, n, &offset); + va_list args; + va_start(args, fmt); + vok_at_loc(file, line, !diff, fmt, args); + va_end(args); + if (diff == 1) { + diag(" Difference starts at offset %d", offset); + diag(" got: 0x%02x", ((unsigned char *)got)[offset]); + diag(" expected: 0x%02x", ((unsigned char *)expected)[offset]); + } + else if (diff == 2) { + diag(" got: %s", got ? "not NULL" : "NULL"); + diag(" expected: %s", expected ? "not NULL" : "NULL"); + } + return !diff; +} + +int +diag (const char *fmt, ...) { + va_list args; + char *mesg, *line; + int i; + va_start(args, fmt); + if (!fmt) + return 0; + mesg = vstrdupf(fmt, args); + line = mesg; + for (i = 0; *line; i++) { + char c = mesg[i]; + if (!c || c == '\n') { + mesg[i] = '\0'; + printf("# %s\n", line); + if (!c) + break; + mesg[i] = c; + line = mesg + i + 1; + } + } + free(mesg); + va_end(args); + return 0; +} + +int +exit_status () { + int retval = 0; + if (expected_tests == NO_PLAN) { + printf("1..%d\n", current_test); + } + else if (current_test != expected_tests) { + diag("Looks like you planned %d test%s but ran %d.", + expected_tests, expected_tests > 1 ? "s" : "", current_test); + retval = 2; + } + if (failed_tests) { + diag("Looks like you failed %d test%s of %d run.", + failed_tests, failed_tests > 1 ? "s" : "", current_test); + retval = 1; + } + return retval; +} + +int +bail_out (int ignore, const char *fmt, ...) { + va_list args; + va_start(args, fmt); + printf("Bail out! "); + vprintf(fmt, args); + printf("\n"); + va_end(args); + exit(255); + return 0; +} + +void +tap_skip (int n, const char *fmt, ...) { + char *why; + va_list args; + va_start(args, fmt); + why = vstrdupf(fmt, args); + va_end(args); + while (n --> 0) { + printf("ok %d ", ++current_test); + diag("skip %s\n", why); + } + free(why); +} + +void +tap_todo (int ignore, const char *fmt, ...) { + va_list args; + va_start(args, fmt); + todo_mesg = vstrdupf(fmt, args); + va_end(args); +} + +void +tap_end_todo () { + free(todo_mesg); + todo_mesg = NULL; +} + +#ifndef _WIN32 +#include +#include +#include + +#if defined __APPLE__ || defined BSD +#define MAP_ANONYMOUS MAP_ANON +#endif + +/* Create a shared memory int to keep track of whether a piece of code executed +dies. to be used in the dies_ok and lives_ok macros. */ +int +tap_test_died (int status) { + static int *test_died = NULL; + int prev; + if (!test_died) { + test_died = mmap(0, sizeof (int), PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS, -1, 0); + *test_died = 0; + } + prev = *test_died; + *test_died = status; + return prev; +} + +int +like_at_loc (int for_match, const char *file, int line, const char *got, + const char *expected, const char *fmt, ...) +{ + int test; + regex_t re; + va_list args; + int err = regcomp(&re, expected, REG_EXTENDED); + if (err) { + char errbuf[256]; + regerror(err, &re, errbuf, sizeof errbuf); + fprintf(stderr, "Unable to compile regex '%s': %s at %s line %d\n", + expected, errbuf, file, line); + exit(255); + } + err = regexec(&re, got, 0, NULL, 0); + regfree(&re); + test = for_match ? !err : err; + va_start(args, fmt); + vok_at_loc(file, line, test, fmt, args); + va_end(args); + if (!test) { + if (for_match) { + diag(" '%s'", got); + diag(" doesn't match: '%s'", expected); + } + else { + diag(" '%s'", got); + diag(" matches: '%s'", expected); + } + } + return test; +} +#endif diff --git a/src/libtap/tap.h b/src/libtap/tap.h new file mode 100644 index 00000000..8269e7ea --- /dev/null +++ b/src/libtap/tap.h @@ -0,0 +1,115 @@ +/* +libtap - Write tests in C +Copyright 2012 Jake Gelbman +This file is licensed under the LGPL +*/ + +#ifndef __TAP_H__ +#define __TAP_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef va_copy +#ifdef __va_copy +#define va_copy __va_copy +#else +#define va_copy(d, s) ((d) = (s)) +#endif +#endif + +#include +#include +#include + +int vok_at_loc (const char *file, int line, int test, const char *fmt, + va_list args); +int ok_at_loc (const char *file, int line, int test, const char *fmt, + ...); +int is_at_loc (const char *file, int line, const char *got, + const char *expected, const char *fmt, ...); +int isnt_at_loc (const char *file, int line, const char *got, + const char *expected, const char *fmt, ...); +int cmp_ok_at_loc (const char *file, int line, int a, const char *op, + int b, const char *fmt, ...); +int cmp_mem_at_loc (const char *file, int line, const void *got, + const void *expected, size_t n, const char *fmt, ...); +int bail_out (int ignore, const char *fmt, ...); +void tap_plan (int tests, const char *fmt, ...); +int diag (const char *fmt, ...); +int exit_status (void); +void tap_skip (int n, const char *fmt, ...); +void tap_todo (int ignore, const char *fmt, ...); +void tap_end_todo (void); + +#define NO_PLAN -1 +#define SKIP_ALL -2 +#define ok(...) ok_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL) +#define is(...) is_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL) +#define isnt(...) isnt_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL) +#define cmp_ok(...) cmp_ok_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL) +#define cmp_mem(...) cmp_mem_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL); +#define plan(...) tap_plan(__VA_ARGS__, NULL) +#define done_testing() return exit_status() +#define BAIL_OUT(...) bail_out(0, "" __VA_ARGS__, NULL) +#define pass(...) ok(1, "" __VA_ARGS__) +#define fail(...) ok(0, "" __VA_ARGS__) + +#define skip(test, ...) do {if (test) {tap_skip(__VA_ARGS__, NULL); break;} +#define end_skip } while (0) + +#define todo(...) tap_todo(0, "" __VA_ARGS__, NULL) +#define end_todo tap_end_todo() + +#define dies_ok(...) dies_ok_common(1, __VA_ARGS__) +#define lives_ok(...) dies_ok_common(0, __VA_ARGS__) + +#ifdef _WIN32 +#define like(...) tap_skip(1, "like is not implemented on Windows") +#define unlike tap_skip(1, "unlike is not implemented on Windows") +#define dies_ok_common(...) \ + tap_skip(1, "Death detection is not supported on Windows") +#else +#define like(...) like_at_loc(1, __FILE__, __LINE__, __VA_ARGS__, NULL) +#define unlike(...) like_at_loc(0, __FILE__, __LINE__, __VA_ARGS__, NULL) +int like_at_loc (int for_match, const char *file, int line, + const char *got, const char *expected, + const char *fmt, ...); +#include +#include +#include +int tap_test_died (int status); +#define dies_ok_common(for_death, code, ...) \ + do { \ + int cpid; \ + int it_died; \ + tap_test_died(1); \ + cpid = fork(); \ + switch (cpid) { \ + case -1: \ + perror("fork error"); \ + exit(1); \ + case 0: \ + close(1); \ + close(2); \ + code \ + tap_test_died(0); \ + exit(0); \ + } \ + if (waitpid(cpid, NULL, 0) < 0) { \ + perror("waitpid error"); \ + exit(1); \ + } \ + it_died = tap_test_died(0); \ + if (!it_died) \ + {code} \ + ok(for_death ? it_died : !it_died, "" __VA_ARGS__); \ + } while (0) +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tests/misc/Makefile.am b/tests/misc/Makefile.am index c9a3fcb9..1c587ac6 100644 --- a/tests/misc/Makefile.am +++ b/tests/misc/Makefile.am @@ -1,19 +1,4 @@ -check_PROGRAMS = \ - tfcntl \ - tsetfsuid \ - tsetfsuidsupp \ - tsetuid \ - tsuppgrp \ - topt \ - tconf \ - tserialize \ - tlist \ - tnpsrv \ - tnpsrv2 \ - tnpsrv3 \ - tlua \ - tcap \ - tfidpool +check_PROGRAMS = TESTS_ENVIRONMENT = env TESTS_ENVIRONMENT += "MISC_SRCDIR=$(top_srcdir)/tests/misc" @@ -21,8 +6,7 @@ TESTS_ENVIRONMENT += "MISC_BUILDDIR=$(top_builddir)/tests/misc" TESTS_ENVIRONMENT += "TOP_SRCDIR=$(top_srcdir)" TESTS_ENVIRONMENT += "TOP_BUILDDIR=$(top_builddir)" -TESTS = t00 t01 t02 t03 t04 t05 t06 t07 t08 t09 t10 t11 t12 t13 t14 t15 -# XFAIL_TESTS = t12 +TESTS = t15 CLEANFILES = *.out *.diff @@ -44,21 +28,4 @@ LDADD = $(top_builddir)/src/cmd/opt.o \ $(top_builddir)/src/liblsd/liblsd.a \ $(LIBWRAP) $(LIBPTHREAD) $(LUA_LIB) $(LIBMUNGE) $(LIBCAP) $(LIBTCMALLOC) -common_sources = test.h - -tsetuid_SOURCES = tsetuid.c $(common_sources) -tsuppgrp_SOURCES = tsuppgrp.c $(common_sources) -tsetfsuid_SOURCES = tsetfsuid.c $(common_sources) -tsetfsuidsupp_SOURCES = tsetfsuidsupp.c $(common_sources) -tfcntl_SOURCES = tfcntl.c $(common_sources) -topt_SOURCES = topt.c $(common_sources) -tconf_SOURCES = tconf.c $(common_sources) -tserialize_SOURCES = tserialize.c $(common_sources) -tlist_SOURCES = tlist.c $(common_sources) -tnpsrv_SOURCES = tnpsrv.c $(common_sources) -tnpsrv2_SOURCES = tnpsrv2.c $(common_sources) -tnpsrv3_SOURCES = tnpsrv3.c $(common_sources) -tlua_SOURCES = tlua.c $(common_sources) -tcap_SOURCES = tcap.c $(common_sources) - -EXTRA_DIST = $(TESTS) $(TESTS:%=%.exp) memcheck t06.conf t08.conf valgrind.supp +EXTRA_DIST = $(TESTS) $(TESTS:%=%.exp) memcheck valgrind.supp diff --git a/tests/misc/README b/tests/misc/README index c8734271..478898d9 100644 --- a/tests/misc/README +++ b/tests/misc/README @@ -16,15 +16,9 @@ t04 Demonstrate that fcntl advisory locking does not treat threads like individual procesess, e.g. locks are shared among threads. This means a threaded work crew cannot manage fcntl locks on behalf of multiple remote processes. -t05 Unit test for diodmount option handling module. t06(@) Unit test for parsing diod.conf. -t07 Check for memory problems in libnpfs serialize/deserialize t08(@) Check for memory problems in libdiod conf/log -t09 Check for memory problems in list package - Actually this was to run down a specific case, now fixed. t10 Check for memory problems in a skeletal libnpfs client/server -t11(*) Show that pthreads can independently set/clear CAP_DAC_OVERRIDE -t12 Check for memory problems in fidpool t13 Check for memory problems in client/server with diod ops t14(*) Check for memory problems in client/server with user switching t15 Check actual diod server for memory probs with multiple conns diff --git a/tests/misc/t00 b/tests/misc/t00 deleted file mode 100755 index 99f47a46..00000000 --- a/tests/misc/t00 +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -e - -TEST=$(basename $0 | cut -d- -f1) -test -n "$FAKEROOTKEY" && exit 77 #skip if under fakeroot -test $(id -u) == 0 || exit 77 #skip if not root -${MISC_BUILDDIR}/tsetfsuid >$TEST.out 2>&1 -diff ${MISC_SRCDIR}/$TEST.exp $TEST.out >$TEST.diff diff --git a/tests/misc/t00.exp b/tests/misc/t00.exp deleted file mode 100644 index 531af40e..00000000 --- a/tests/misc/t00.exp +++ /dev/null @@ -1,12 +0,0 @@ -tsetfsuid: task0: 0:0 -tsetfsuid: task1: 0:0 -tsetfsuid: task2: 0:0 -tsetfsuid: task2: changing to 100:100 -tsetfsuid: task2: 100:100 -tsetfsuid: task1: 0:0 -tsetfsuid: task1: changing to 100:100 -tsetfsuid: task1: 100:100 -tsetfsuid: task2: changing to 0:0 -tsetfsuid: task2: 0:0 -tsetfsuid: task1: 100:100 -tsetfsuid: task0: 0:0 diff --git a/tests/misc/t01 b/tests/misc/t01 deleted file mode 100755 index 00e0601b..00000000 --- a/tests/misc/t01 +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -e - -TEST=$(basename $0 | cut -d- -f1) -test -n "$FAKEROOTKEY" && exit 77 #skip if under fakeroot -test $(id -u) == 0 || exit 77 #skip if not root -${MISC_BUILDDIR}/tsetfsuidsupp >$TEST.out 2>&1 -diff ${MISC_SRCDIR}/$TEST.exp $TEST.out >$TEST.diff diff --git a/tests/misc/t01.exp b/tests/misc/t01.exp deleted file mode 100644 index 605e33a3..00000000 --- a/tests/misc/t01.exp +++ /dev/null @@ -1,14 +0,0 @@ -tsetfsuidsupp: supplemental groups cleared -tsetfsuidsupp: file created 0:101 mode 0440 -tsetfsuidsupp: fsid changed to 100:100 -tsetfsuidsupp: file is NOT readable -tsetfsuidsupp: fsid changed to 100:101 -tsetfsuidsupp: file is readable -tsetfsuidsupp: fsid changed to 100:100 -tsetfsuidsupp: file is NOT readable -tsetfsuidsupp: 101 added to supplemental groups -tsetfsuidsupp: file is readable -tsetfsuidsupp: supplemental groups cleared -tsetfsuidsupp: file is NOT readable -tsetfsuidsupp: fsid changed to 0:0 -tsetfsuidsupp: test complete diff --git a/tests/misc/t02 b/tests/misc/t02 deleted file mode 100755 index de878d7a..00000000 --- a/tests/misc/t02 +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -e - -TEST=$(basename $0 | cut -d- -f1) -test -n "$FAKEROOTKEY" && exit 77 #skip if under fakeroot -test $(id -u) == 0 || exit 77 #skip if not root -${MISC_BUILDDIR}/tsuppgrp >$TEST.out 2>&1 -diff ${MISC_SRCDIR}/$TEST.exp $TEST.out >$TEST.diff diff --git a/tests/misc/t02.exp b/tests/misc/t02.exp deleted file mode 100644 index 55f0dca9..00000000 --- a/tests/misc/t02.exp +++ /dev/null @@ -1,11 +0,0 @@ -tsuppgrp: task0: setgroups (NULL) -tsuppgrp: task0: getgroups -tsuppgrp: task1: getgroups -tsuppgrp: task2: getgroups -tsuppgrp: task2: setgroups 100 -tsuppgrp: task2: getgroups 100 -tsuppgrp: task1: getgroups -tsuppgrp: task1: setgroups 101 -tsuppgrp: task1: getgroups 101 -tsuppgrp: task2: getgroups 100 -tsuppgrp: task0: getgroups diff --git a/tests/misc/t03 b/tests/misc/t03 deleted file mode 100755 index d29ea2e3..00000000 --- a/tests/misc/t03 +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -e - -TEST=$(basename $0 | cut -d- -f1) -test -n "$FAKEROOTKEY" && exit 77 #skip if under fakeroot -test $(id -u) == 0 || exit 77 #skip if not root -${MISC_BUILDDIR}/tsetuid >$TEST.out 2>&1 -diff ${MISC_SRCDIR}/$TEST.exp $TEST.out >$TEST.diff diff --git a/tests/misc/t03.exp b/tests/misc/t03.exp deleted file mode 100644 index 51fd783a..00000000 --- a/tests/misc/t03.exp +++ /dev/null @@ -1,13 +0,0 @@ -tsetuid: task0: geteuid 0 -tsetuid: task1: geteuid 0 -tsetuid: task2: geteuid 0 -tsetuid: task2: seteuid 100 -tsetuid: task2: geteuid 100 -tsetuid: task1: geteuid 100 -tsetuid: task1: seteuid 101 -tsetuid: task1: geteuid 101 -tsetuid: task2: geteuid 101 -tsetuid: task2: seteuid 102 -tsetuid: task2: geteuid 102 -tsetuid: task1: geteuid 102 -tsetuid: task0: geteuid 102 diff --git a/tests/misc/t04 b/tests/misc/t04 deleted file mode 100755 index c14c8775..00000000 --- a/tests/misc/t04 +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -e - -TEST=$(basename $0 | cut -d- -f1) -# test $(id -u) == 0 || exit 77 #skip if not root -${MISC_BUILDDIR}/tfcntl >$TEST.out 2>&1 -diff ${MISC_SRCDIR}/$TEST.exp $TEST.out >$TEST.diff diff --git a/tests/misc/t04.exp b/tests/misc/t04.exp deleted file mode 100644 index c53c77ee..00000000 --- a/tests/misc/t04.exp +++ /dev/null @@ -1,8 +0,0 @@ -tfcntl: proc0: locking bytes 0-64 -tfcntl: proc0: locking bytes 32-64 -tfcntl: proc1: locking bytes 0-64 -tfcntl: proc2: locking bytes 32-64 -tfcntl: child0: locking bytes 32-64 -tfcntl: child0: fcntl F_SETLK: Resource temporarily unavailable -tfcntl: child1: locking bytes 32-64 -tfcntl: child1: fcntl F_SETLK: Resource temporarily unavailable diff --git a/tests/misc/t05 b/tests/misc/t05 deleted file mode 100755 index bdf9361b..00000000 --- a/tests/misc/t05 +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -e - -TEST=$(basename $0 | cut -d- -f1) -# test $(id -u) == 0 || exit 77 #skip if not root -${MISC_BUILDDIR}/topt >$TEST.out 2>&1 -diff ${MISC_SRCDIR}/$TEST.exp $TEST.out >$TEST.diff diff --git a/tests/misc/t05.exp b/tests/misc/t05.exp deleted file mode 100644 index 56dc1888..00000000 --- a/tests/misc/t05.exp +++ /dev/null @@ -1,2 +0,0 @@ -topt: opt string='mickey=42,goofey=yes,donald,foo,bar,baz,lastone' -topt: opt string='goofey=yes,donald,lastone,mickey=string,foo=12,bar=15,baz' diff --git a/tests/misc/t06 b/tests/misc/t06 deleted file mode 100755 index 5fb14855..00000000 --- a/tests/misc/t06 +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -e - -TEST=$(basename $0 | cut -d- -f1) -# test $(id -u) == 0 || exit 77 #skip if not root -${MISC_BUILDDIR}/tlua || exit 77 #skip if no lua -${MISC_BUILDDIR}/tconf -c ${MISC_SRCDIR}/$TEST.conf -e >$TEST.out 2>&1 -diff ${MISC_SRCDIR}/$TEST.exp $TEST.out >$TEST.diff diff --git a/tests/misc/t06.conf b/tests/misc/t06.conf deleted file mode 100644 index ba5cae3f..00000000 --- a/tests/misc/t06.conf +++ /dev/null @@ -1,8 +0,0 @@ -exports = { - "/g/g1", - "/g/g2", - { path="/g/g3", opts="ro", users="jim,bob", hosts="foo[1-64]" }, - "/g/g5", - { path="/g/g4", users="jim,bob" }, - "/g/g6", -} diff --git a/tests/misc/t06.exp b/tests/misc/t06.exp deleted file mode 100644 index c1622b9b..00000000 --- a/tests/misc/t06.exp +++ /dev/null @@ -1,6 +0,0 @@ -path=/g/g1 -path=/g/g2 -path=/g/g3 opts=ro(0x1) users=jim,bob hosts=foo[1-64] -path=/g/g5 -path=/g/g4 opts=NULL(0x0) users=jim,bob hosts=NULL -path=/g/g6 diff --git a/tests/misc/t07 b/tests/misc/t07 deleted file mode 100755 index e8264cbd..00000000 --- a/tests/misc/t07 +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -e - -TEST=$(basename $0 | cut -d- -f1) -${MISC_SRCDIR}/memcheck ${MISC_BUILDDIR}/tserialize >$TEST.out 2>&1 -diff ${MISC_SRCDIR}/$TEST.exp $TEST.out >$TEST.diff diff --git a/tests/misc/t07.exp b/tests/misc/t07.exp deleted file mode 100644 index ba48fcf0..00000000 --- a/tests/misc/t07.exp +++ /dev/null @@ -1,125 +0,0 @@ -test_rlerror(7): 11 -P9_RLERROR tag 42 ecode 42 -test_rlerror(7): 11 -P9_RLERROR tag 42 ecode 42 -test_tstatfs(8): 11 -P9_TSTATFS tag 42 fid 42 -test_rstatfs(9): 67 -P9_RSTATFS tag 42 type 1 bsize 2 blocks 3 bfree 4 bavail 5 files 6 ffree 7 fsid 8 namelen 9 -test_tlopen(12): 15 -P9_TLOPEN tag 42 fid 1 flags 02 -test_rlopen(13): 24 -P9_RLOPEN tag 42 qid (0000000000000003 2 '') iounit 2 -test_tlcreate(14): 28 -P9_TLCREATE tag 42 fid 1 name 'xyz' flags 0x3 mode 04 gid 5 -test_rlcreate(15): 24 -P9_RLCREATE tag 42 qid (0000000000000003 2 '') iounit 2 -test_tsymlink(16): 25 -P9_TSYMLINK tag 42 fid 1 name 'xyz' symtgt 'abc' gid 4 -test_rsymlink(17): 20 -P9_RSYMLINK tag 42 qid (0000000000000003 2 '') -test_tmknod(18): 32 -P9_TMKNOD tag 42 fid 1 name 'xyz' mode 03 major 4 minor 5 gid 6 -test_rmknod(19): 20 -P9_RMKNOD tag 42 qid (0000000000000003 2 '') -test_trename(20): 20 -P9_TRENAME tag 42 fid 1 dfid 2 name 'xyz' -test_rrename(21): 7 -P9_RRENAME tag 42 -test_treadlink(22): 11 -P9_TREADLINK tag 42 fid 1 -test_rreadlink(23): 12 -P9_RREADLINK tag 42 target 'xyz' -test_tgetattr(24): 19 -P9_TGETATTR tag 42 fid 42 request_mask 0x1388 -test_rgetattr(25): 160 -P9_RGETATTR tag 42 valid 0x1 qid X mode 04 uid X gid X nlink X rdev X size X blksize 10 blocks X atime X mtime X ctime X btime X gen X data_version X -test_tsetattr(26): 67 -P9_TSETATTR tag 42 fid 1 valid 0x2 mode X uid 4 gid X size X atime X mtime X -test_rsetattr(27): 7 -P9_RSETATTR tag 42 -test_txattrwalk(30): 20 -P9_TXATTRWALK tag 42 fid 1 attrfid 2 name 'abc' -test_rxattrwalk(31): 15 -P9_RXATTRWALK tag 42 size 1 -test_txattrcreate(32): 28 -P9_TXATTRCREATE tag 42 fid 1 name 'abc' size 3 flag 4 -test_rxattrcreate(33): 7 -P9_RXATTRCREATE tag 42 -test_treaddir(40): 23 -P9_TREADDIR tag 42 fid 1 offset 2 count 3 -test_rreaddir(41): 92 -P9_RREADDIR tag 42 count 81 -01020000 00030000 00000000 00000000 00000000 00010300 61626304 05000000 -06000000 00000000 32000000 00000000 02030064 65660708 00000009 00000000 -test_tfsync(50): 15 -P9_TFSYNC tag 42 fid 1 -test_rfsync(51): 7 -P9_RFSYNC tag 42 -test_tlock(52): 41 -P9_TLOCK tag 42 fid 1 type P9_LOCK_TYPE_UNLCK flags 3 start 4 length 5 proc_id 6 client_id 'xyz' -test_rlock(53): 8 -P9_RLOCK tag 42 status P9_LOCK_BLOCKED -test_tgetlock(54): 37 -P9_TGETLOCK tag 42 fid 1 type P9_LOCK_TYPE_UNLCK start 3 length 4 proc_id 5 client_id 'xyz' -test_rgetlock(55): 33 -P9_RGETLOCK tag 42 type P9_LOCK_TYPE_WRLCK start 2 length 3 proc_id 4 client_id 'xyz' -test_tlink(70): 20 -P9_TLINK tag 42 dfid 1 fid 2 name 'xyz' -test_rlink(71): 7 -P9_RLINK tag 42 -test_tmkdir(72): 24 -P9_TMKDIR tag 42 fid 1 name 'abc' mode 02 gid 3 -test_rmkdir(73): 20 -P9_RMKDIR tag 42 qid (0000000000000003 2 '') -test_trenameat(74): 25 -P9_TRENAMEAT tag 42 olddirfid 1 oldname 'abc' newdirfid 2 newname 'zyx' -test_rrenameat(75): 7 -P9_RRENAMEAT tag 42 -test_tunlinkat(76): 20 -P9_TUNLINKAT tag 42 dirfid 1 name 'abc' flags 2 -test_runlinkat(77): 7 -P9_RUNLINKAT tag 42 -test_tversion(100): 21 -P9_TVERSION tag 42 msize 4096 version '9p2000.L' -test_rversion(101): 21 -P9_RVERSION tag 42 msize 4096 version '9p2000.L' -test_tauth(102): 25 -P9_TAUTH tag 42 afid 1 uname 'abc' aname 'xyz' n_uname 4 -test_rauth(103): 20 -P9_RAUTH tag 42 qid (0000000000000003 2 '') -test_tflush(108): 9 -P9_TFLUSH tag 42 oldtag 1 -test_rflush(109): 7 -P9_RFLUSH tag 42 -test_rflush(109): 7 -P9_RFLUSH tag 42 -test_tattach(104): 29 -P9_TATTACH tag 42 fid 1 afid 2 uname 'abc' aname 'xyz' n_uname 5 -test_rattach(105): 20 -P9_RATTACH tag 42 qid (0000000000000003 2 '') -test_twalk(110): 97 -P9_TWALK tag 42 fid 1 newfid 2 nwname 16 'abc' 'def' 'ghi' 'jkl' 'abc' 'def' 'ghi' 'jkl' 'abc' 'def' 'ghi' 'jkl' 'abc' 'def' 'ghi' 'jkl' -test_rwalk(111): 217 -P9_RWALK tag 42 nwqid 16 (0000000000000003 2 '')(0000000000000006 5 't')(0000000000000009 8 'tL')(000000000000000c b 'AL')(0000000000000003 2 '')(0000000000000006 5 't')(0000000000000009 8 'tL')(000000000000000c b 'AL')(0000000000000003 2 '')(000000000000 -test_tread(116): 23 -P9_TREAD tag 42 fid 1 offset 2 count 3 -test_rread(117): 139 -P9_RREAD tag 42 count 128 -f0f0f0f0 f0f0f0f0 f0f0f0f0 f0f0f0f0 f0f0f0f0 f0f0f0f0 f0f0f0f0 f0f0f0f0 -f0f0f0f0 f0f0f0f0 f0f0f0f0 f0f0f0f0 f0f0f0f0 f0f0f0f0 f0f0f0f0 f0f0f0f0 -test_twrite(118): 151 -P9_TWRITE tag 42 fid 1 offset 2 count 128 -0f0f0f0f 0f0f0f0f 0f0f0f0f 0f0f0f0f 0f0f0f0f 0f0f0f0f 0f0f0f0f 0f0f0f0f -0f0f0f0f 0f0f0f0f 0f0f0f0f 0f0f0f0f 0f0f0f0f 0f0f0f0f 0f0f0f0f 0f0f0f0f -test_rwrite(119): 11 -P9_RWRITE tag 42 count 1 -test_tclunk(120): 11 -P9_TCLUNK tag 42 fid 1 -test_rclunk(121): 7 -P9_RCLUNK tag 42 -test_tremove(122): 11 -P9_TREMOVE tag 42 fid 1 -test_rremove(123): 7 -P9_RREMOVE tag 42 -OK np_deserialize failed on truncated Tlink (issue#109) diff --git a/tests/misc/t08 b/tests/misc/t08 deleted file mode 100755 index 9f7b5f80..00000000 --- a/tests/misc/t08 +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -e - -TEST=$(basename $0 | cut -d- -f1) -${MISC_BUILDDIR}/tlua || exit 77 #skip if no lua -${MISC_SRCDIR}/memcheck ${MISC_BUILDDIR}/tconf -c ${MISC_SRCDIR}/$TEST.conf >$TEST.out 2>&1 -diff ${MISC_SRCDIR}/$TEST.exp $TEST.out >$TEST.diff diff --git a/tests/misc/t08.conf b/tests/misc/t08.conf deleted file mode 100644 index f76e048e..00000000 --- a/tests/misc/t08.conf +++ /dev/null @@ -1,16 +0,0 @@ -nwthreads = 64 -auth_required = 1 -allsquash = 1 -diodctllisten = { "1.2.3.4:42", "1,2,3,5:43" } -diodlisten = { "1.2.3.5:43", "1.2.3.6:10000" } -logdest = "syslog:daemon:err" -exportall = 1 - -exports = { - "/g/g1", - "/g/g2", - { path="/g/g3", opts="ro", users="jim,bob", hosts="foo[1-64]" }, - "/g/g5", - { path="/g/g4", users="jim,bob" }, - "/g/g6", -} diff --git a/tests/misc/t08.exp b/tests/misc/t08.exp deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/misc/t09 b/tests/misc/t09 deleted file mode 100755 index 9d04bb00..00000000 --- a/tests/misc/t09 +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -e - -TEST=$(basename $0 | cut -d- -f1) -${MISC_SRCDIR}/memcheck ${MISC_BUILDDIR}/tlist >$TEST.out 2>&1 -diff ${MISC_SRCDIR}/$TEST.exp $TEST.out >$TEST.diff diff --git a/tests/misc/t09.exp b/tests/misc/t09.exp deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/misc/t10 b/tests/misc/t10 deleted file mode 100755 index 167fa920..00000000 --- a/tests/misc/t10 +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -e - -# skip if uid 1 doesn't exist -getent passwd 1 >/dev/null 2>&1 || exit 77 - -TEST=$(basename $0 | cut -d- -f1) -${MISC_SRCDIR}/memcheck ${MISC_BUILDDIR}/tnpsrv >$TEST.out 2>&1 -diff ${MISC_SRCDIR}/$TEST.exp $TEST.out >$TEST.diff diff --git a/tests/misc/t10.exp b/tests/misc/t10.exp deleted file mode 100644 index 1c780c3f..00000000 --- a/tests/misc/t10.exp +++ /dev/null @@ -1,46 +0,0 @@ -tnpsrv: P9_TVERSION tag 65535 msize 8192 version '9P2000.L' -tnpsrv: P9_RVERSION tag 65535 msize 8192 version '9P2000.L' -tnpsrv: P9_TATTACH tag 0 fid 0 afid -1 uname '' aname 'ctl' n_uname 0 -tnpsrv: user lookup: 0 -tnpsrv: P9_RATTACH tag 0 qid (0000000000000001 0 'dt') -tnpsrv: P9_TWALK tag 0 fid 0 newfid 1 nwname 1 'connections' -tnpsrv: P9_RWALK tag 0 nwqid 1 (000000000000000a 0 't') -tnpsrv: P9_TLOPEN tag 0 fid 1 flags 00 -tnpsrv: P9_RLOPEN tag 0 qid (000000000000000a 0 't') iounit 0 -tnpsrv: P9_TREAD tag 0 fid 1 offset 0 count 4095 -tnpsrv: P9_RREAD tag 0 count 11 -6c6f6f70 6261636b 20320a -tnpsrv: P9_TREAD tag 0 fid 1 offset 11 count 4084 -tnpsrv: P9_RREAD tag 0 count 0 -tnpsrv: P9_TCLUNK tag 0 fid 1 -tnpsrv: P9_RCLUNK tag 0 -tnpsrv: P9_TATTACH tag 0 fid 1 afid -1 uname '' aname 'ctl' n_uname 1 -tnpsrv: user lookup: 1 -tnpsrv: P9_RATTACH tag 0 qid (0000000000000001 0 'dt') -tnpsrv: P9_TWALK tag 0 fid 1 newfid 2 nwname 1 'connections' -tnpsrv: P9_RWALK tag 0 nwqid 1 (000000000000000a 0 't') -tnpsrv: P9_TLOPEN tag 0 fid 2 flags 00 -tnpsrv: P9_RLOPEN tag 0 qid (000000000000000a 0 't') iounit 0 -tnpsrv: P9_TREAD tag 0 fid 2 offset 0 count 4095 -tnpsrv: P9_RREAD tag 0 count 11 -6c6f6f70 6261636b 20330a -tnpsrv: P9_TREAD tag 0 fid 2 offset 11 count 4084 -tnpsrv: P9_RREAD tag 0 count 0 -tnpsrv: P9_TCLUNK tag 0 fid 2 -tnpsrv: P9_RCLUNK tag 0 -tnpsrv: P9_TATTACH tag 0 fid 2 afid -1 uname '' aname 'ctl' n_uname 1 -tnpsrv: P9_RATTACH tag 0 qid (0000000000000001 0 'dt') -tnpsrv: P9_TWALK tag 0 fid 2 newfid 3 nwname 1 'null' -tnpsrv: P9_RWALK tag 0 nwqid 1 (0000000000000006 0 't') -tnpsrv: P9_TLOPEN tag 0 fid 3 flags 00 -tnpsrv: P9_RLOPEN tag 0 qid (0000000000000006 0 't') iounit 0 -tnpsrv: P9_TREAD tag 0 fid 3 offset 0 count 4095 -tnpsrv: P9_RREAD tag 0 count 0 -tnpsrv: P9_TCLUNK tag 0 fid 3 -tnpsrv: P9_RCLUNK tag 0 -tnpsrv: P9_TCLUNK tag 0 fid 0 -tnpsrv: P9_RCLUNK tag 0 -tnpsrv: P9_TCLUNK tag 0 fid 1 -tnpsrv: P9_RCLUNK tag 0 -tnpsrv: P9_TCLUNK tag 0 fid 2 -tnpsrv: P9_RCLUNK tag 0 diff --git a/tests/misc/t11 b/tests/misc/t11 deleted file mode 100755 index 10d0891c..00000000 --- a/tests/misc/t11 +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -e - -TEST=$(basename $0 | cut -d- -f1) -test -n "$FAKEROOTKEY" && exit 77 #skip if under fakeroot -test $(id -u) == 0 || exit 77 #skip if not root -${MISC_BUILDDIR}/tcap >$TEST.out 2>&1 -diff ${MISC_SRCDIR}/$TEST.exp $TEST.out >$TEST.diff diff --git a/tests/misc/t11.exp b/tests/misc/t11.exp deleted file mode 100644 index f44edb71..00000000 --- a/tests/misc/t11.exp +++ /dev/null @@ -1,34 +0,0 @@ -tcap: task0: cap is set -tcap: task0: cap is set -tcap: task0: setfsuid 1 -tcap: task0: cap is clear -tcap: task0: cap is clear -tcap: task0: setfsuid 0 -tcap: task0: cap is set -tcap: task0: cap is set -tcap: task0: setfsuid 1 -tcap: task0: cap is clear -tcap: task0: cap is clear -tcap: task0: set cap -tcap: task0: cap is set -tcap: task0: cap is set -tcap: task0: setfsuid 2 -tcap: task0: cap is set -tcap: task0: cap is set -tcap: task0: clr cap -tcap: task0: cap is clear -tcap: task0: cap is clear -tcap: task1: cap is clear -tcap: task1: cap is clear -tcap: task2: cap is clear -tcap: task2: cap is clear -tcap: task2: set cap -tcap: task2: cap is set -tcap: task2: cap is set -tcap: task1: cap is clear -tcap: task1: cap is clear -tcap: task1: clr cap -tcap: task2: cap is set -tcap: task2: cap is set -tcap: task0: cap is clear -tcap: task0: cap is clear diff --git a/tests/misc/t12 b/tests/misc/t12 deleted file mode 100755 index 8aab1f80..00000000 --- a/tests/misc/t12 +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -e - -TEST=$(basename $0 | cut -d- -f1) -${MISC_SRCDIR}/memcheck ${MISC_BUILDDIR}/tfidpool 1000 >$TEST.out 2>&1 -diff ${MISC_SRCDIR}/$TEST.exp $TEST.out >$TEST.diff diff --git a/tests/misc/t12.exp b/tests/misc/t12.exp deleted file mode 100644 index 7a923441..00000000 --- a/tests/misc/t12.exp +++ /dev/null @@ -1,4 +0,0 @@ -tfidpool: initial count: 0 -tfidpool: count after fid create: 1000 -tfidpool: count after fid destroy: 0 -tfidpool: unclunked: 0 diff --git a/tests/misc/t13 b/tests/misc/t13 deleted file mode 100755 index 13f70de1..00000000 --- a/tests/misc/t13 +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -e - -TEST=$(basename $0 | cut -d- -f1) -${MISC_SRCDIR}/memcheck ${MISC_BUILDDIR}/tnpsrv2 >$TEST.out 2>&1 -diff ${MISC_SRCDIR}/$TEST.exp $TEST.out >$TEST.diff diff --git a/tests/misc/t13.exp b/tests/misc/t13.exp deleted file mode 100644 index 2cdc583a..00000000 --- a/tests/misc/t13.exp +++ /dev/null @@ -1,4 +0,0 @@ -tnpsrv2: attached -tnpsrv2: file test finished -tnpsrv2: directory test finished -tnpsrv2: detached diff --git a/tests/misc/t14 b/tests/misc/t14 deleted file mode 100755 index f6a56db4..00000000 --- a/tests/misc/t14 +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -e - -TEST=$(basename $0 | cut -d- -f1) -test $(id -u) == 0 || exit 77 #skip if not root -${MISC_SRCDIR}/memcheck ${MISC_BUILDDIR}/tnpsrv3 >$TEST.out 2>&1 -diff ${MISC_SRCDIR}/$TEST.exp $TEST.out >$TEST.diff diff --git a/tests/misc/t14.exp b/tests/misc/t14.exp deleted file mode 100644 index 77414a22..00000000 --- a/tests/misc/t14.exp +++ /dev/null @@ -1,10 +0,0 @@ -tnpsrv3: attached -tnpsrv3: root file test done -tnpsrv3: npc_create_bypath foo: Permission denied -tnpsrv3: user file test done -tnpsrv3: chmod 0777 mount point -tnpsrv3: user file test done -tnpsrv3: chown 1 mount point -tnpsrv3: chmod 0700 mount point -tnpsrv3: user file test done -tnpsrv3: detached diff --git a/tests/misc/tcap.c b/tests/misc/tcap.c deleted file mode 100644 index 46d9253b..00000000 --- a/tests/misc/tcap.c +++ /dev/null @@ -1,207 +0,0 @@ -/************************************************************\ - * Copyright 2010 Lawrence Livermore National Security, LLC - * (c.f. AUTHORS, NOTICE.LLNS, COPYING) - * - * This file is part of the diod 9P server project. - * For details, see https://github.com/chaos/diod. - * - * SPDX-License-Identifier: GPL-2.0-or-later -\************************************************************/ - -/* tcap.c - check that pthreads can independently set capabilities */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if HAVE_LIBCAP -#include -#endif -#include - -#include "src/libdiod/diod_log.h" - -#include "test.h" - -#if HAVE_LIBCAP -typedef enum { S0, S1, S2, S3, S4, S5 } state_t; - -static state_t state = S0; -static pthread_mutex_t state_lock = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t state_cond = PTHREAD_COND_INITIALIZER; - -static void -_prtcap (char *s, cap_value_t capflag) -{ - cap_t cap; - cap_flag_value_t val; - - if (!(cap = cap_get_proc ())) - err_exit ("%s: cap_get_proc", s); - if (cap_get_flag (cap, capflag, CAP_EFFECTIVE, &val) < 0) - err_exit ("%s: cap_get_flag", s); - if (cap_free (cap) < 0) - err_exit ("%s: cap_free", s); - msg ("%s: cap is %s", s, val == CAP_SET ? "set" : "clear"); -} - -static void -_setcap (char *s, cap_value_t capflag) -{ - cap_t cap; - - if (!(cap = cap_get_proc ())) - err_exit ("%s: cap_get_proc", s); - if (cap_set_flag (cap, CAP_EFFECTIVE, 1, &capflag, CAP_SET) < 0) - err_exit ("%s: cap_set_flag", s); - if (cap_set_proc (cap) < 0) - err_exit ("%s: cap_set_proc", s); - if (cap_free (cap) < 0) - err_exit ("%s: cap_free", s); -} - -static void -_clrcap (char *s, cap_value_t capflag) -{ - cap_t cap; - - if (!(cap = cap_get_proc ())) - err_exit ("%s: cap_get_proc", s); - if (cap_set_flag (cap, CAP_EFFECTIVE, 1, &capflag, CAP_CLEAR) < 0) - err_exit ("%s: cap_set_flag", s); - if (cap_set_proc (cap) < 0) - err_exit ("%s: cap_set_proc", s); - if (cap_free (cap) < 0) - err_exit ("%s: cap_free", s); -} - -static void -change_state (state_t s) -{ - _lock (&state_lock); - state = s; - _condsig (&state_cond); - _unlock (&state_lock); -} - -static void -wait_state (state_t s) -{ - _lock (&state_lock); - while ((state != s)) - _condwait (&state_cond, &state_lock); - _unlock (&state_lock); -} - -static void *proc1 (void *a) -{ - _prtcap ("task1", CAP_DAC_OVERRIDE); /* 1) task 1, expect clr */ - _prtcap ("task1", CAP_CHOWN); - change_state (S1); - - wait_state (S2); - _prtcap ("task1", CAP_DAC_OVERRIDE); /* 4) task 1, still clr */ - _prtcap ("task1", CAP_CHOWN); - - msg ("task1: clr cap"); - _clrcap ("task1", CAP_DAC_OVERRIDE); - change_state (S3); - - wait_state (S4); - return NULL; -} - -static void *proc2 (void *a) -{ - wait_state (S1); - _prtcap ("task2", CAP_DAC_OVERRIDE); /* 2) task 2, expect clr */ - _prtcap ("task2", CAP_CHOWN); - - msg ("task2: set cap"); - _setcap ("task2", CAP_DAC_OVERRIDE); - _setcap ("task2", CAP_CHOWN); - _prtcap ("task2", CAP_DAC_OVERRIDE); /* 3) task 2, expect set */ - _prtcap ("task2", CAP_CHOWN); - change_state (S2); - - wait_state (S3); - _prtcap ("task2", CAP_DAC_OVERRIDE); /* 5) task 2, expect set */ - _prtcap ("task2", CAP_CHOWN); - change_state (S4); - return NULL; -} -#endif - -int main(int argc, char *argv[]) -{ -#if HAVE_LIBCAP - pthread_t t1, t2; - - assert (geteuid () == 0); - - diod_log_init (argv[0]); - _prtcap ("task0", CAP_DAC_OVERRIDE); /* root, expect set */ - _prtcap ("task0", CAP_CHOWN); - - msg ("task0: setfsuid 1"); - setfsuid (1); - _prtcap ("task0", CAP_DAC_OVERRIDE); /* non-root, expect clr */ - _prtcap ("task0", CAP_CHOWN); - - msg ("task0: setfsuid 0"); /* root, expect set */ - setfsuid (0); - _prtcap ("task0", CAP_DAC_OVERRIDE); - _prtcap ("task0", CAP_CHOWN); - - msg ("task0: setfsuid 1"); - setfsuid (1); - _prtcap ("task0", CAP_DAC_OVERRIDE); /* non-root, expect clr */ - _prtcap ("task0", CAP_CHOWN); - - msg ("task0: set cap"); - _setcap ("task0", CAP_DAC_OVERRIDE); - _setcap ("task0", CAP_CHOWN); - _prtcap ("task0", CAP_DAC_OVERRIDE); /* root with cap explicitly set, */ - _prtcap ("task0", CAP_CHOWN); /* expect set */ - - msg ("task0: setfsuid 2"); - setfsuid (2); - _prtcap ("task0", CAP_DAC_OVERRIDE);/* non-root with cap explicitly set, */ - _prtcap ("task0", CAP_CHOWN); /* (as root) expect set */ - - msg ("task0: clr cap"); - _clrcap ("task0", CAP_DAC_OVERRIDE); - _clrcap ("task0", CAP_CHOWN); - _prtcap ("task0", CAP_DAC_OVERRIDE);/* non-root with cap explicitly clr, */ - _prtcap ("task0", CAP_CHOWN); /* (as non-root) expect clr */ - - _create (&t1, proc1, NULL); - _create (&t2, proc2, NULL); - - _join (t2, NULL); - _join (t1, NULL); - - _prtcap ("task0", CAP_DAC_OVERRIDE); /* after threads, expect clr */ - _prtcap ("task0", CAP_CHOWN); -#else - fprintf (stderr, "libcap unavailable\n"); - exit (77); -#endif - - exit (0); -} - -/* - * vi:tabstop=4 shiftwidth=4 expandtab - */ diff --git a/tests/misc/tconf.c b/tests/misc/tconf.c deleted file mode 100644 index 86a73d3a..00000000 --- a/tests/misc/tconf.c +++ /dev/null @@ -1,140 +0,0 @@ -/************************************************************\ - * Copyright 2010 Lawrence Livermore National Security, LLC - * (c.f. AUTHORS, NOTICE.LLNS, COPYING) - * - * This file is part of the diod 9P server project. - * For details, see https://github.com/chaos/diod. - * - * SPDX-License-Identifier: GPL-2.0-or-later -\************************************************************/ - -/* tconf.c - test config file */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif -#include -#include -#include -#include -#if HAVE_GETOPT_H -#include -#endif -#include -#include - -#include "src/liblsd/list.h" - -#include "src/libdiod/diod_log.h" -#include "src/libdiod/diod_conf.h" - -#define OPTIONS "c:em" - -#if HAVE_GETOPT_LONG -#define GETOPT(ac,av,opt,lopt) getopt_long (ac,av,opt,lopt,NULL) -static const struct option longopts[] = { - {"config-file", required_argument, 0, 'c'}, - {"exports", no_argument, 0, 'e'}, - {"mounts", no_argument, 0, 'm'}, - {0, 0, 0, 0}, -}; -#else -#define GETOPT(ac,av,opt,lopt) getopt (ac,av,opt) -#endif - -static void -usage(void) -{ - fprintf (stderr, -"Usage: tconf [OPTIONS]\n" -" -c,--config-file FILE set config file path\n" -" -e,--exports dump exports\n" -" -m,--mounts dump /proc/mounts\n" - ); - exit (1); -} - -static void -dump_exports (List l) -{ - ListIterator itr = list_iterator_create (l); - Export *x; - - if (!itr) - msg_exit ("out of memory"); - while ((x = list_next (itr))) { - assert (x->path); - if (x->opts || x->users || x->hosts) { - printf("path=%s opts=%s(0x%x) users=%s hosts=%s\n", - x->path, - x->opts ? x->opts : "NULL", x->opts ? x->oflags : 0, - x->users ? x->users : "NULL", - x->hosts ? x->hosts : "NULL"); - } else if (x->path) - printf("path=%s\n", x->path); - } - list_iterator_destroy (itr); -} - -int -main (int argc, char *argv[]) -{ - List e, m; - char *copt = NULL; - int c; - - diod_log_init (argv[0]); - diod_conf_init (); - - opterr = 0; - while ((c = GETOPT (argc, argv, OPTIONS, longopts)) != -1) { - switch (c) { - case 'c': /* --config-file PATH */ - copt = optarg; - break; - default: - break; - } - } - diod_conf_init_config_file (copt); - - diod_conf_set_exportall (1); - if (!(m = diod_conf_get_mounts ())) - msg_exit ("out of memory"); - - if (!(e = diod_conf_get_exports ())) - msg_exit ("out of memory"); - - /* Command line overrides config file. - */ - optind = 0; - opterr = 0; - while ((c = GETOPT (argc, argv, OPTIONS, longopts)) != -1) { - switch (c) { - case 'c': /* --config-file PATH (already handled) */ - break; - case 'e': /* --exports */ - dump_exports (e); - break; - case 'm': /* --mounts */ - dump_exports (m); - break; - default: - usage (); - /*NOTREACHED*/ - } - } - if (optind < argc) - usage (); - - list_destroy (m); - diod_conf_fini (); - diod_log_fini (); - - exit (0); -} - -/* - * vi:tabstop=4 shiftwidth=4 expandtab - */ - diff --git a/tests/misc/test.h b/tests/misc/test.h deleted file mode 100644 index 3d903aab..00000000 --- a/tests/misc/test.h +++ /dev/null @@ -1,120 +0,0 @@ -/************************************************************\ - * Copyright 2010 Lawrence Livermore National Security, LLC - * (c.f. AUTHORS, NOTICE.LLNS, COPYING) - * - * This file is part of the diod 9P server project. - * For details, see https://github.com/chaos/diod. - * - * SPDX-License-Identifier: GPL-2.0-or-later -\************************************************************/ - -static inline void -_lock (pthread_mutex_t *l) -{ - int n = pthread_mutex_lock (l); - if (n) - errn_exit (n, "_lock"); -} -static inline void -_unlock (pthread_mutex_t *l) -{ - int n = pthread_mutex_unlock (l); - if (n) - errn_exit (n, "_unlock"); -} -static inline void -_condsig (pthread_cond_t *c) -{ - int n = pthread_cond_signal (c); - if (n) - errn_exit (n, "_condsig"); -} -static inline void -_condwait (pthread_cond_t *c, pthread_mutex_t *l) -{ - int n = pthread_cond_wait (c, l); - if (n) - errn_exit (n, "_condwait"); -} -static inline void -_create (pthread_t *t, void *(f)(void *), void *a) -{ - int n = pthread_create (t, NULL, f, a); - if (n) - errn_exit (n,"_create"); -} -static inline void -_join (pthread_t t, void **a) -{ - int n = pthread_join (t, a); - if (n) - errn_exit (n,"_join"); -} -static inline int -_mkstemp (char *p) -{ - int fd = mkstemp (p); - if (fd < 0) - err_exit ("_mkstemp"); - return fd; -} -static inline void -_fstat (int fd, struct stat *sb) -{ - if (fstat (fd, sb) < 0) - err_exit ("_fstat"); -} -static inline void -_unlink (char *p) -{ - if (unlink (p) < 0) - err_exit ("_unlink"); -} -static inline void -_fchown (int fd, uid_t u, gid_t g) -{ - if (fchown (fd, u, g) < 0) - err_exit ("_fchown"); -} -static inline void -_fchmod (int fd, mode_t m) -{ - if (fchmod (fd, m) < 0) - err_exit ("_fchmod"); -} -static inline void -_setgroups (size_t s, gid_t *g) -{ -#if 0 - if (setgroups (s, g) < 0) -#else - if (syscall(SYS_setgroups, s, g) < 0) -#endif - err_exit ("_setgroups"); - -} -static inline int -_getgroups (size_t s, gid_t *g) -{ - int n = getgroups (s, g); - if (n < 0) - err_exit ("_getgroups"); - return n; -} -static inline void -_setreuid (uid_t r, uid_t u) -{ - if (setreuid (r, u) < 0) - err_exit ("_setreuid"); -} -static inline void -_setregid (gid_t r, gid_t g) -{ - if (setregid (r, g) < 0) - err_exit ("_setregid"); -} - -/* - * vi:tabstop=4 shiftwidth=4 expandtab - */ - diff --git a/tests/misc/tfcntl.c b/tests/misc/tfcntl.c deleted file mode 100644 index 9a8f7017..00000000 --- a/tests/misc/tfcntl.c +++ /dev/null @@ -1,211 +0,0 @@ -/************************************************************\ - * Copyright 2010 Lawrence Livermore National Security, LLC - * (c.f. AUTHORS, NOTICE.LLNS, COPYING) - * - * This file is part of the diod 9P server project. - * For details, see https://github.com/chaos/diod. - * - * SPDX-License-Identifier: GPL-2.0-or-later -\************************************************************/ - -/* tfcntl.c - pthreads contending for fcntl locks are like one process */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "src/libdiod/diod_log.h" - -#include "test.h" - -#define TEST_UID 100 -#define TEST_GID 100 - -typedef enum { S0, S1, S2, S3, S4, S5 } state_t; - -static state_t state = S0; -static pthread_mutex_t state_lock = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t state_cond = PTHREAD_COND_INITIALIZER; -static char path[] = "/tmp/test.fcntl.XXXXXX"; -static int fd = -1; - -static void -change_state (state_t s) -{ - _lock (&state_lock); - state = s; - _condsig (&state_cond); - _unlock (&state_lock); -} - -static void -wait_state (state_t s) -{ - _lock (&state_lock); - while ((state != s)) - _condwait (&state_cond, &state_lock); - _unlock (&state_lock); -} - -static void -mkfile (void) -{ - char buf[1024]; - - memset (buf, 0, sizeof (buf)); - fd = _mkstemp (path); - if (write (fd, buf, sizeof (buf)) < 0) - err_exit ("write"); - if (close (fd) < 0) - err_exit ("close"); - if ((fd = open (path, O_RDWR)) < 0) - err_exit ("open %s", path); -} - -static void *proc1 (void *a) -{ - struct flock f; - - msg ("proc1: locking bytes 0-64"); - f.l_type = F_WRLCK; - f.l_whence = SEEK_SET; - f.l_start = 0; - f.l_len = 64; - if (fcntl (fd, F_SETLK, &f) < 0) - err_exit ("proc1: fcntl F_SETLK"); - change_state (S1); - - wait_state (S2); - change_state (S3); - wait_state (S4); - return NULL; -} - -static void *proc2 (void *a) -{ - struct flock f; - - wait_state (S1); - msg ("proc2: locking bytes 32-64"); - f.l_type = F_WRLCK; - f.l_whence = SEEK_SET; - f.l_start = 0; - f.l_len = 64; - if (fcntl (fd, F_SETLK, &f) < 0) - err_exit ("proc2: fcntl F_SETLK"); - change_state (S2); - - wait_state (S3); - change_state (S4); - return NULL; -} - -int -main (int arg, char *argv[]) -{ - pthread_t t1, t2; - struct flock f; - pid_t pid; - int status; - - diod_log_init (argv[0]); - - mkfile (); - - /* same task/thread contending for write lock */ - msg ("proc0: locking bytes 0-64"); - f.l_type = F_WRLCK; - f.l_whence = SEEK_SET; - f.l_start = 0; - f.l_len = 64; - if (fcntl (fd, F_SETLK, &f) < 0) - err_exit ("proc0: fcntl F_SETLK"); - msg ("proc0: locking bytes 32-64"); - f.l_type = F_WRLCK; - f.l_whence = SEEK_SET; - f.l_start = 32; - f.l_len = 64; - if (fcntl (fd, F_SETLK, &f) < 0) - err_exit ("proc0: fcntl F_SETLK"); - - /* two threads contending for write lock */ - _create (&t1, proc1, NULL); - _create (&t2, proc2, NULL); - - _join (t2, NULL); - _join (t1, NULL); - - fflush (stderr); - - /* two processes contending for write lock - inherited fd */ - switch (pid = fork ()) { - case -1: - err_exit ("fork"); - case 0: /* child */ - msg ("child0: locking bytes 32-64"); - f.l_type = F_WRLCK; - f.l_whence = SEEK_SET; - f.l_start = 32; - f.l_len = 64; - if (fcntl (fd, F_SETLK, &f) < 0) - err_exit ("child0: fcntl F_SETLK"); - msg ("child0: unexpected success"); - break; - default: /* parent */ - if (waitpid (pid, &status, 0) < 0) - err_exit ("wait"); - break; - } - - /* two processes contending for write lock - seperate fd's */ - switch (pid = fork ()) { - case -1: - err_exit ("fork"); - case 0: /* child */ - if (close (fd) < 0) - err_exit ("child1: close"); - if ((fd = open (path, O_RDWR)) < 0) - err_exit ("open %s (child)", path); - msg ("child1: locking bytes 32-64"); - f.l_type = F_WRLCK; - f.l_whence = SEEK_SET; - f.l_start = 32; - f.l_len = 64; - if (fcntl (fd, F_SETLK, &f) < 0) - err_exit ("child1: fcntl F_SETLK"); - msg ("child1: unexpected success"); - close (fd); - break; - default: /* parent */ - if (waitpid (pid, &status, 0) < 0) - err_exit ("wait"); - break; - } - - if (close (fd) < 0) - err_exit ("close"); - if (unlink (path) < 0) - err_exit ("unlink %s", path); - exit (0); -} - -/* - * vi:tabstop=4 shiftwidth=4 expandtab - */ diff --git a/tests/misc/tfidpool.c b/tests/misc/tfidpool.c deleted file mode 100644 index ebcdd6d7..00000000 --- a/tests/misc/tfidpool.c +++ /dev/null @@ -1,95 +0,0 @@ -/************************************************************\ - * Copyright 2010 Lawrence Livermore National Security, LLC - * (c.f. AUTHORS, NOTICE.LLNS, COPYING) - * - * This file is part of the diod 9P server project. - * For details, see https://github.com/chaos/diod. - * - * SPDX-License-Identifier: GPL-2.0-or-later -\************************************************************/ - -/* tfidpool.c - exercise fidpool.c (valgrind me) */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "src/libnpfs/9p.h" -#include "src/libnpfs/npfs.h" - -#include "src/liblsd/list.h" -#include "src/libdiod/diod_log.h" - -int -main (int argc, char *argv[]) -{ - Npsrv srv; - Npconn conn; - Npfid **fid; - unsigned long nfids; - int i, n; - - diod_log_init (argv[0]); - - if (argc != 2) { - fprintf (stderr, "Usage: tfidpool nfids\n"); - exit (1); - } - nfids = strtoul (argv[1], NULL, 10); - if (nfids == 0) - msg_exit ("invalid nfids value"); - fid = (Npfid **)malloc (nfids * sizeof (Npfid *)); - if (!fid) - msg_exit ("out of memory"); - - memset (&srv, 0, sizeof (srv)); - srv.logmsg = diod_log_msg; - srv.flags |= SRV_FLAGS_DEBUG_FIDPOOL; - conn.fidpool = np_fidpool_create (); - conn.srv = &srv; - - msg ("initial count: %d", np_fidpool_count (conn.fidpool)); - - for (i = 0; i < nfids; i++) { - fid[i] = np_fid_find (&conn, i); - assert (fid[i] == NULL); - } - - for (i = 0; i < nfids; i++) { - fid[i] = np_fid_create (&conn, i); - np_fid_incref (fid[i]); - np_fid_incref (fid[i]); - } - - msg ("count after fid create: %d", np_fidpool_count (conn.fidpool)); - - for (i = 0; i < nfids; i++) { - np_fid_decref (&fid[i]); - np_fid_decref (&fid[i]); - np_fid_decref (&fid[i]); - } - - msg ("count after fid destroy: %d", np_fidpool_count (conn.fidpool)); - - n = np_fidpool_destroy (conn.fidpool); - - msg ("unclunked: %d", n); - - free (fid); - - diod_log_fini (); - exit (0); -} - -/* - * vi:tabstop=4 shiftwidth=4 expandtab - */ diff --git a/tests/misc/tlua.c b/tests/misc/tlua.c deleted file mode 100644 index 25e1ca64..00000000 --- a/tests/misc/tlua.c +++ /dev/null @@ -1,25 +0,0 @@ -/************************************************************\ - * Copyright 2010 Lawrence Livermore National Security, LLC - * (c.f. AUTHORS, NOTICE.LLNS, COPYING) - * - * This file is part of the diod 9P server project. - * For details, see https://github.com/chaos/diod. - * - * SPDX-License-Identifier: GPL-2.0-or-later -\************************************************************/ - -/* tlua.c - is lua configured? */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif - -int -main (int argc, char *argv[]) -{ -#if HAVE_CONFIG_FILE - return 0; -#else - return 1; -#endif -} diff --git a/tests/misc/tnpsrv.c b/tests/misc/tnpsrv.c deleted file mode 100644 index 5278ce16..00000000 --- a/tests/misc/tnpsrv.c +++ /dev/null @@ -1,106 +0,0 @@ -/************************************************************\ - * Copyright 2010 Lawrence Livermore National Security, LLC - * (c.f. AUTHORS, NOTICE.LLNS, COPYING) - * - * This file is part of the diod 9P server project. - * For details, see https://github.com/chaos/diod. - * - * SPDX-License-Identifier: GPL-2.0-or-later -\************************************************************/ - -/* tnpsrv.c - test simple client/server (valgrind me) */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "src/libnpfs/9p.h" -#include "src/libnpfs/npfs.h" -#include "src/libnpclient/npclient.h" - -#include "src/liblsd/list.h" -#include "src/libdiod/diod_log.h" -#include "src/libdiod/diod_conf.h" -#include "src/libdiod/diod_sock.h" - -#define TEST_MSIZE 8192 - -int -main (int argc, char *argv[]) -{ - Npsrv *srv; - int s[2]; - int flags = SRV_FLAGS_DEBUG_9PTRACE | SRV_FLAGS_DEBUG_USER; - Npcfsys *fs; - Npcfid *root0, *root1, *root2; - char *str; - - diod_log_init (argv[0]); - diod_conf_init (); - - if (socketpair (AF_LOCAL, SOCK_STREAM, 0, s) < 0) - err_exit ("socketpair"); - - if (!(srv = np_srv_create (16, flags))) - errn_exit (np_rerror (), "out of memory"); - srv->logmsg = diod_log_msg; - diod_sock_startfd (srv, s[1], s[1], "loopback", 0); - - if (!(fs = npc_start (s[0], s[0], TEST_MSIZE, 0))) - errn_exit (np_rerror (), "npc_start"); - - if (!(root0 = npc_attach (fs, NULL, "ctl", 0))) - errn_exit (np_rerror (), "npc_attach"); - if (!(str = npc_aget (root0, "connections"))) - errn_exit (np_rerror (), "npc_aget connections"); - free (str); - - if (!(root1 = npc_attach (fs, NULL, "ctl", 1))) - errn_exit (np_rerror (), "npc_attach"); - if (!(str = npc_aget (root1, "connections"))) - errn_exit (np_rerror (), "npc_aget connections"); - free (str); - - /* Same user (1) - user cache should be valid, so we won't see a message - * for this user lookup in the output. - */ - if (!(root2 = npc_attach (fs, NULL, "ctl", 1))) - errn_exit (np_rerror (), "npc_attach"); - if (!(str = npc_aget (root2, "null"))) - errn_exit (np_rerror (), "npc_aget null"); - free (str); - - npc_clunk (root0); - npc_clunk (root1); - npc_clunk (root2); - - npc_finish (fs); - - np_srv_wait_conncount (srv, 1); - - /* N.B. The conn reader thread runs detached and signals us as it is - * about to exit. If we manage to wake up and exit first, valgrind - * reports the reader's tls as leaked. Add the sleep to work around - * this race for now. - */ - sleep (1); - - np_srv_destroy (srv); - - diod_conf_fini (); - diod_log_fini (); - exit (0); -} - -/* - * vi:tabstop=4 shiftwidth=4 expandtab - */ diff --git a/tests/misc/tnpsrv2.c b/tests/misc/tnpsrv2.c deleted file mode 100644 index c762558e..00000000 --- a/tests/misc/tnpsrv2.c +++ /dev/null @@ -1,230 +0,0 @@ -/************************************************************\ - * Copyright 2010 Lawrence Livermore National Security, LLC - * (c.f. AUTHORS, NOTICE.LLNS, COPYING) - * - * This file is part of the diod 9P server project. - * For details, see https://github.com/chaos/diod. - * - * SPDX-License-Identifier: GPL-2.0-or-later -\************************************************************/ - -/* tnpsrv2.c - test client/server with diod ops (valgrind me) */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "src/libnpfs/9p.h" -#include "src/libnpfs/npfs.h" -#include "src/libnpclient/npclient.h" - -#include "src/liblsd/list.h" -#include "src/libdiod/diod_log.h" -#include "src/libdiod/diod_conf.h" -#include "src/libdiod/diod_sock.h" - -#include "src/daemon/ops.h" - -#define TEST_MSIZE 8192 - -#define TEST_ITER 64 - -int -main (int argc, char *argv[]) -{ - Npsrv *srv; - int s[2]; - int flags = 0; - Npcfid *root, *dir, *f[TEST_ITER]; - char tmpdir[] = "/tmp/tnpsrv2.XXXXXX"; - int i; - char tmpstr[PATH_MAX + 1]; - int n, len = 4096*100; - char *buf = malloc (len); - char *buf2 = malloc (len); - char dbuf[TEST_MSIZE - P9_IOHDRSZ]; - struct dirent d, *dp; - - diod_log_init (argv[0]); - diod_conf_init (); - diod_conf_set_auth_required (0); - - /* create export */ - if (!mkdtemp (tmpdir)) - err_exit ("mkdtemp"); - diod_conf_add_exports (tmpdir); - diod_conf_set_exportopts ("sharefd"); - - if (socketpair (AF_LOCAL, SOCK_STREAM, 0, s) < 0) - err_exit ("socketpair"); - - if (!(srv = np_srv_create (16, flags))) - errn_exit (np_rerror (), "np_srv_create"); - if (diod_init (srv) < 0) - errn_exit (np_rerror (), "diod_init"); - diod_sock_startfd (srv, s[1], s[1], "loopback", 0); - - if (!(root = npc_mount (s[0], s[0], TEST_MSIZE, tmpdir, NULL))) - errn_exit (np_rerror (), "npc_mount"); - - msg ("attached"); - - /* create a file, write some data into it, then read it TEST_ITER - * times, each on a unique fid. The path and ioctx will be shared due - * to "sharefd" export option set above. We want to be sure no memory - * leaks result from the management of shared paths and io contexts. - */ - if (!(f[0] = npc_create_bypath (root, "foo", 0, 0644, getgid()))) - errn (np_rerror (), "npc_create_bypath foo"); - else { - if (!buf || !buf2) - errn_exit (ENOMEM, "malloc"); - if (npc_clunk (f[0]) < 0) - errn (np_rerror (), "npc_clunk"); - - /* fill it with some data */ - memset (buf, 9, len); - n = npc_put (root, "foo", buf, len); - if (n < 0) - errn (np_rerror (), "npc_put"); - if (n < len) - msg ("npc_put: short write: %d", n); - - /* walk */ - for (i = 0; i < TEST_ITER; i++) { - f[i] = npc_walk (root, "foo"); - if (!f[i]) - errn (np_rerror (), "npc_walk"); - } - /* open */ - for (i = 0; i < TEST_ITER; i++) { - if (f[i]) { - if (npc_open (f[i], O_RDONLY) < 0) - errn (np_rerror (), "npc_open"); - } - } - /* read (using new fids) */ - for (i = 0; i < TEST_ITER; i++) { - if (f[i]) { - memset (buf2, 0, len); - n = npc_get (root, "foo", buf2, len); - if (n < 0) - errn (np_rerror (), "npc_get"); - if (n < len) - msg ("short read: %d bytes", n); - if (memcmp (buf, buf2, n) != 0) - msg ("memcmp failure"); - } - } - /* clunk */ - for (i = 0; i < TEST_ITER; i++) { - if (f[i]) { - if (npc_clunk (f[i]) < 0) - errn (np_rerror (), "npc_clunk"); - } - } - - /* remove */ - if (npc_remove_bypath (root, "foo") < 0) - errn_exit (np_rerror(), "np_remove_bypath"); - - free (buf); - free (buf2); - - msg ("file test finished"); - } - - /* create a directory with TEST_ITER files, and exercise varios ops - * on the files and directory. - */ - if (npc_mkdir_bypath (root, "foo", 0755) < 0) - errn (np_rerror (), "npc_mkdir_bypath"); - else { - - /* create files */ - for (i = 0; i < TEST_ITER; i++) { - snprintf (tmpstr, sizeof (tmpstr), "foo/%-.200i", i); - if (!(f[i] = npc_create_bypath (root, tmpstr, 0, 0644, getgid()))) - errn (np_rerror (), "npc_create_bypath %s", tmpstr); - } - /* open the directory */ - if ((dir = npc_opendir (root, "foo"))) { - - /* read one chunk of directory (redundant with below) */ - if (npc_readdir (dir, 0, dbuf, sizeof (dbuf)) < 0) - errn (np_rerror (), "npc_readdir"); - - /* list the files in the directory */ - i = 0; - do { - if ((n = npc_readdir_r (dir, &d, &dp)) > 0) { - errn (n, "npc_readdir_r"); - break; - } - if (dp) - i++; - } while (n == 0 && dp != NULL); - if (i != TEST_ITER + 2) /* . and .. will appear */ - msg ("readdir found fewer than expected files: %d", i); - - /* close the directory */ - if (npc_clunk (dir) < 0) - errn (np_rerror (), "npc_clunk foo"); - } - - /* remove files (implicit clunk) */ - for (i = 0; i < TEST_ITER; i++) { - if (f[i]) { - if (npc_remove (f[i]) < 0) - errn (np_rerror (), "npc_remove"); - } - } - - /* remove directory */ - if (npc_remove_bypath (root, "foo") < 0) - errn_exit (np_rerror (), "npc_remove_bypath"); - - msg ("directory test finished"); - } - - npc_umount (root); - - msg ("detached"); - - np_srv_wait_conncount (srv, 1); - - /* N.B. The conn reader thread runs detached and signals us as it is - * about to exit. If we manage to wake up and exit first, valgrind - * reports the reader's tls as leaked. Add the sleep to work around - * this race for now. - */ - sleep (1); - - diod_fini (srv); - np_srv_destroy (srv); - - rmdir (tmpdir); - - diod_conf_fini (); - diod_log_fini (); - exit (0); -} - -/* - * vi:tabstop=4 shiftwidth=4 expandtab - */ diff --git a/tests/misc/tnpsrv3.c b/tests/misc/tnpsrv3.c deleted file mode 100644 index 55be19ac..00000000 --- a/tests/misc/tnpsrv3.c +++ /dev/null @@ -1,205 +0,0 @@ -/************************************************************\ - * Copyright 2010 Lawrence Livermore National Security, LLC - * (c.f. AUTHORS, NOTICE.LLNS, COPYING) - * - * This file is part of the diod 9P server project. - * For details, see https://github.com/chaos/diod. - * - * SPDX-License-Identifier: GPL-2.0-or-later -\************************************************************/ - -/* tnpsrv3.c - test diod client/server with root/mult users (valgrind me) */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "src/libnpfs/9p.h" -#include "src/libnpfs/npfs.h" -#include "src/libnpclient/npclient.h" - -#include "src/liblsd/list.h" -#include "src/libdiod/diod_log.h" -#include "src/libdiod/diod_conf.h" -#include "src/libdiod/diod_sock.h" - -#include "src/daemon/ops.h" - -#define TEST_MSIZE 8192 - -void -file_test (Npcfid *root) -{ - int n, len = 4096*100; - char *buf = malloc (len); - char *buf2 = malloc (len); - Npcfid *f; - - if (!buf || !buf2) - errn_exit (ENOMEM, "malloc"); - - if (!(f = npc_create_bypath (root, "foo", 0, 0644, getgid()))) { - errn (np_rerror (), "npc_create_bypath foo"); - goto done; - } - if (npc_clunk (f) < 0) - errn (np_rerror (), "npc_clunk"); - - /* fill it with some data */ - memset (buf, 9, len); - n = npc_put (root, "foo", buf, len); - if (n < 0) - errn (np_rerror (), "npc_put"); - if (n < len) - msg ("npc_put: short write: %d", n); - - /* walk */ - f = npc_walk (root, "foo"); - if (!f) - errn (np_rerror (), "npc_walk"); - else { - /* open */ - if (npc_open (f, O_RDONLY) < 0) - errn (np_rerror (), "npc_open"); - - /* read */ - memset (buf2, 0, len); - n = npc_get (root, "foo", buf2, len); - if (n < 0) - errn (np_rerror (), "npc_get"); - if (n < len) - msg ("short read: %d bytes", n); - if (memcmp (buf, buf2, n) != 0) - msg ("memcmp failure"); - - /* clunk */ - if (npc_clunk (f) < 0) - errn (np_rerror (), "npc_clunk"); - } - - /* remove */ - if (npc_remove_bypath (root, "foo") < 0) - errn_exit (np_rerror(), "np_remove_bypath"); -done: - free (buf); - free (buf2); -} - -int -main (int argc, char *argv[]) -{ - Npsrv *srv; - int s[2]; - int flags = 0; - Npcfsys *fs; - Npcfid *root, *user, *user2; - char tmpdir[] = "/tmp/tnpsrv2.XXXXXX"; - - assert (geteuid () == 0); - - diod_log_init (argv[0]); - diod_conf_init (); - - /* Allow attach with afid==-1. - */ - diod_conf_set_auth_required (0); - - /* create export directory: will be owned by root, mode=0700 */ - if (!mkdtemp (tmpdir)) - err_exit ("mkdtemp"); - diod_conf_add_exports (tmpdir); - diod_conf_set_exportopts ("sharefd"); - - if (socketpair (AF_LOCAL, SOCK_STREAM, 0, s) < 0) - err_exit ("socketpair"); - - /* Note: supplementary groups do not work in this mode, however - * regular uid:gid switching of fsid works. Enabling DAC_BYPASS - * assumes v9fs is enforcing permissions, not the case with npclient. - */ - flags |= SRV_FLAGS_SETFSID; - if (!(srv = np_srv_create (16, flags))) - errn_exit (np_rerror (), "np_srv_create"); - if (diod_init (srv) < 0) - errn_exit (np_rerror (), "diod_init"); - diod_sock_startfd (srv, s[1], s[1], "loopback", 0); - - if (!(fs = npc_start (s[0], s[0], TEST_MSIZE, 0))) - errn_exit (np_rerror (), "npc_start"); - - if (!(root = npc_attach (fs, NULL, tmpdir, 0))) /* attach as uid=0 */ - errn_exit (np_rerror (), "npc_attach"); - if (!(user = npc_attach (fs, NULL, tmpdir, 1))) /* attach as uid=1 */ - errn_exit (np_rerror (), "npc_attach (uid=1)"); - /* attach one more time as uid=1 to exercise user cache under valgrind */ - if (!(user2 = npc_attach (fs, NULL, tmpdir, 1))) - errn_exit (np_rerror (), "npc_attach (uid=1)"); - msg ("attached"); - - file_test (root); /* expect success */ - msg ("root file test done"); - - file_test (user); /* expect failure */ - msg ("user file test done"); - - if (npc_chmod (root, ".", 0777) < 0) - errn (np_rerror (), "npc_chmod"); - msg ("chmod 0777 mount point"); - file_test (user); /* expect success */ - msg ("user file test done"); - - if (npc_chown (root, ".", 1, 1) < 0) - errn (np_rerror (), "npc_chmod"); - msg ("chown 1 mount point"); - if (npc_chmod (root, ".", 0700) < 0) - errn (np_rerror (), "npc_chmod"); - msg ("chmod 0700 mount point"); - file_test (user); /* expect success */ - msg ("user file test done"); - - if (npc_clunk (user) < 0) - errn (np_rerror (), "npc_clunk (uid=1)"); - if (npc_clunk (user2) < 0) - errn (np_rerror (), "npc_clunk (uid=1)"); - if (npc_clunk (root) < 0) - errn (np_rerror (), "npc_clunk"); - npc_finish (fs); - msg ("detached"); - - np_srv_wait_conncount (srv, 1); - - /* N.B. The conn reader thread runs detached and signals us as it is - * about to exit. If we manage to wake up and exit first, valgrind - * reports the reader's tls as leaked. Add the sleep to work around - * this race for now. - */ - sleep (1); - - diod_fini (srv); - np_srv_destroy (srv); - - rmdir (tmpdir); - - diod_conf_fini (); - diod_log_fini (); - exit (0); -} - -/* - * vi:tabstop=4 shiftwidth=4 expandtab - */ diff --git a/tests/misc/topt.c b/tests/misc/topt.c deleted file mode 100644 index 98def5f0..00000000 --- a/tests/misc/topt.c +++ /dev/null @@ -1,65 +0,0 @@ -/************************************************************\ - * Copyright 2010 Lawrence Livermore National Security, LLC - * (c.f. AUTHORS, NOTICE.LLNS, COPYING) - * - * This file is part of the diod 9P server project. - * For details, see https://github.com/chaos/diod. - * - * SPDX-License-Identifier: GPL-2.0-or-later -\************************************************************/ - -/* topt.c - test didomount/opt.c */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif -#include -#include -#include -#include -#include -#include -#include - -#include "src/libdiod/diod_log.h" -#include "src/cmd/opt.h" - -int -main (int argc, char *argv[]) -{ - Opt o = opt_create (); - char *s; - int i; - - diod_log_init (argv[0]); - - opt_addf (o, "mickey=%d", 42); - opt_addf (o, "goofey=%s", "yes"); - opt_addf (o, "donald"); - opt_addf (o, "foo,bar,baz"); - opt_addf (o, "lastone"); - - s = opt_csv (o); - msg ("opt string='%s'", s); - free (s); - - assert (opt_find (o, "mickey")); - assert (opt_find (o, "bar")); - assert (!opt_find (o, "barn")); - - assert (opt_scanf (o, "mickey=%d", &i)); - assert (i == 42); - - opt_addf (o, "mickey=string,foo=%d,bar=%d,baz", 12, 15); - s = opt_csv (o); - msg ("opt string='%s'", s); - free (s); - - opt_destroy (o); - - exit (0); -} - -/* - * vi:tabstop=4 shiftwidth=4 expandtab - */ diff --git a/tests/misc/tserialize.c b/tests/misc/tserialize.c deleted file mode 100644 index 571fe7b5..00000000 --- a/tests/misc/tserialize.c +++ /dev/null @@ -1,1226 +0,0 @@ -/************************************************************\ - * Copyright 2010 Lawrence Livermore National Security, LLC - * (c.f. AUTHORS, NOTICE.LLNS, COPYING) - * - * This file is part of the diod 9P server project. - * For details, see https://github.com/chaos/diod. - * - * SPDX-License-Identifier: GPL-2.0-or-later -\************************************************************/ - -/* tserialize.c - exercise serialize/deserialize libnpfs functions */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "src/libnpfs/9p.h" -#include "src/libnpfs/npfs.h" - -#include "src/libdiod/diod_log.h" - -#define TEST_MSIZE 4096 - -static void test_rlerror (void); -static void test_tstatfs (void); static void test_rstatfs (void); -static void test_tlopen (void); static void test_rlopen (void); -static void test_tlcreate (void); static void test_rlcreate (void); -static void test_tsymlink (void); static void test_rsymlink (void); -static void test_tmknod (void); static void test_rmknod (void); -static void test_trename (void); static void test_rrename(void); -static void test_treadlink (void); static void test_rreadlink (void); -static void test_tgetattr (void); static void test_rgetattr (void); -static void test_tsetattr (void); static void test_rsetattr (void); -static void test_txattrwalk (void); static void test_rxattrwalk (void); -static void test_txattrcreate (void); static void test_rxattrcreate (void); -static void test_treaddir (void); static void test_rreaddir (void); -static void test_tfsync (void); static void test_rfsync (void); -static void test_tlock (void); static void test_rlock (void); -static void test_tgetlock (void); static void test_rgetlock (void); -static void test_tlink (void); static void test_rlink (void); -static void test_tmkdir (void); static void test_rmkdir (void); -static void test_trenameat (void); static void test_rrenameat (void); -static void test_tunlinkat (void); static void test_runlinkat (void); - -static void test_tversion (void); static void test_rversion (void); -static void test_tauth (void); static void test_rauth (void); -static void test_tflush (void); static void test_rflush (void); -static void test_tattach (void); static void test_rattach (void); -static void test_twalk (void); static void test_rwalk (void); -static void test_tread (void); static void test_rread (void); -static void test_twrite (void); static void test_rwrite (void); -static void test_tclunk (void); static void test_rclunk (void); -static void test_tremove (void); static void test_rremove (void); - -static void test_truncated_tlink (void); - -static void -usage (void) -{ - fprintf (stderr, "Usage: tserialize\n"); - exit (1); -} - - -int -main (int argc, char *argv[]) -{ - diod_log_init (argv[0]); - - if (argc != 1) - usage (); - - test_rlerror (); - test_tstatfs (); test_rstatfs (); - test_tlopen (); test_rlopen (); - test_tlcreate (); test_rlcreate (); - test_tsymlink (); test_rsymlink (); - test_tmknod (); test_rmknod (); - test_trename (); test_rrename (); - test_treadlink(); test_rreadlink (); - test_tgetattr (); test_rgetattr (); - test_tsetattr (); test_rsetattr (); - test_txattrwalk (); test_rxattrwalk (); - test_txattrcreate (); test_rxattrcreate (); - test_treaddir (); test_rreaddir (); - test_tfsync (); test_rfsync (); - test_tlock (); test_rlock (); - test_tgetlock (); test_rgetlock (); - test_tlink (); test_rlink (); - test_tmkdir (); test_rmkdir (); - test_trenameat (); test_rrenameat (); - test_tunlinkat (); test_runlinkat (); - - test_tversion (); test_rversion (); - test_tauth (); test_rauth (); - test_tflush (); test_rflush (); - test_tattach (); test_rattach (); - test_twalk (); test_rwalk (); - test_tread (); test_rread (); - test_twrite (); test_rwrite (); - test_tclunk (); test_rclunk (); - test_tremove (); test_rremove (); - - test_truncated_tlink (); - - exit (0); -} - -/* Allocate a new Npfcall to "receive" raw data from fc->pkt. - */ -static Npfcall * -_rcv_buf (Npfcall *fc, int type, const char *fun) -{ - Npfcall *fc2; - char s[256]; - - printf ("%s(%d): %d\n", fun, type, fc->size); - np_set_tag (fc, 42); - - /* see conn.c:np_conn_new_incall () */ - if (!(fc2 = malloc (sizeof (*fc2) + TEST_MSIZE))) - msg_exit ("out of memory"); - fc2->pkt = (u8 *)fc2 + sizeof (*fc2); - - /* see conn.c::np_conn_read_proc */ - memcpy (fc2->pkt, fc->pkt, fc->size); - if (!np_deserialize (fc2)) - msg_exit ("np_deserialize error in %s", fun); - - /* check a few things */ - if (fc->type != type) - msg_exit ("incorrect type in %s", fun); - if (fc->size != fc2->size) - msg_exit ("size mismatch in %s", fun); - if (fc->type != fc2->type) - msg_exit ("type mismatch in %s", fun); - - np_snprintfcall (s, sizeof (s), fc); - printf ("%s\n", s); - - return fc2; -} - -static void -test_rlerror (void) -{ - Npfcall *fc, *fc2; - char buf[STATIC_RLERROR_SIZE]; - - if (!(fc = np_create_rlerror (42))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_RLERROR, __FUNCTION__); - - assert (fc->u.rlerror.ecode == fc2->u.rlerror.ecode); - - free (fc); - free (fc2); - - fc = np_create_rlerror_static (42, buf, sizeof(buf)); - fc2 = _rcv_buf (fc, P9_RLERROR, __FUNCTION__); - - assert (fc->u.rlerror.ecode == fc2->u.rlerror.ecode); - - free (fc2); -} - -static void -test_tstatfs (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_tstatfs (42))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_TSTATFS, __FUNCTION__); - - assert (fc->u.tstatfs.fid == fc2->u.tstatfs.fid); - - free (fc); - free (fc2); -} - -static void -test_rstatfs(void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_rstatfs (1, 2, 3, 4, 5, 6, 7, 8, 9))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_RSTATFS, __FUNCTION__); - - assert (fc->u.rstatfs.type == fc2->u.rstatfs.type); - assert (fc->u.rstatfs.bsize == fc2->u.rstatfs.bsize); - assert (fc->u.rstatfs.blocks == fc2->u.rstatfs.blocks); - assert (fc->u.rstatfs.bfree == fc2->u.rstatfs.bfree); - assert (fc->u.rstatfs.bavail== fc2->u.rstatfs.bavail); - assert (fc->u.rstatfs.files == fc2->u.rstatfs.files); - assert (fc->u.rstatfs.ffree == fc2->u.rstatfs.ffree); - assert (fc->u.rstatfs.fsid == fc2->u.rstatfs.fsid); - assert (fc->u.rstatfs.namelen == fc2->u.rstatfs.namelen); - - free (fc); - free (fc2); -} - -static void -test_tlopen (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_tlopen (1, 2))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_TLOPEN, __FUNCTION__); - - assert (fc->u.tlopen.fid == fc2->u.tlopen.fid); - assert (fc->u.tlopen.flags == fc2->u.tlopen.flags); - - free (fc); - free (fc2); -} - -static void -test_rlopen (void) -{ - Npfcall *fc, *fc2; - struct p9_qid qid = { 1, 2, 3 }; - - if (!(fc = np_create_rlopen (&qid, 2))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_RLOPEN, __FUNCTION__); - - assert (fc->u.rlopen.qid.type == fc2->u.rlopen.qid.type); - assert (fc->u.rlopen.qid.version == fc2->u.rlopen.qid.version); - assert (fc->u.rlopen.qid.path == fc2->u.rlopen.qid.path); - assert (fc->u.rlopen.iounit == fc2->u.rlopen.iounit); - - free (fc); - free (fc2); -} - -static void -test_tlcreate (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_tlcreate (1, "xyz", 3, 4, 5))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_TLCREATE, __FUNCTION__); - - assert (fc->u.tlcreate.fid == fc2->u.tlcreate.fid); - assert (np_str9cmp (&fc->u.tlcreate.name, &fc2->u.tlcreate.name) == 0); - assert (fc->u.tlcreate.flags == fc2->u.tlcreate.flags); - assert (fc->u.tlcreate.mode == fc2->u.tlcreate.mode); - assert (fc->u.tlcreate.gid == fc2->u.tlcreate.gid); - - free (fc); - free (fc2); -} - -static void -test_rlcreate (void) -{ - Npfcall *fc, *fc2; - struct p9_qid qid = { 1, 2, 3 }; - - if (!(fc = np_create_rlcreate (&qid, 2))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_RLCREATE, __FUNCTION__); - - assert (fc->u.rlcreate.qid.type == fc2->u.rlcreate.qid.type); - assert (fc->u.rlcreate.qid.version == fc2->u.rlcreate.qid.version); - assert (fc->u.rlcreate.qid.path == fc2->u.rlcreate.qid.path); - assert (fc->u.rlcreate.iounit == fc2->u.rlcreate.iounit); - - free (fc); - free (fc2); -} - -static void -test_tsymlink (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_tsymlink (1, "xyz", "abc", 4))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_TSYMLINK, __FUNCTION__); - - assert (fc->u.tsymlink.fid == fc2->u.tsymlink.fid); - assert (np_str9cmp (&fc->u.tsymlink.name, &fc2->u.tsymlink.name) == 0); - assert (np_str9cmp (&fc->u.tsymlink.symtgt, &fc2->u.tsymlink.symtgt) == 0); - assert (fc->u.tsymlink.gid == fc2->u.tsymlink.gid); - - free (fc); - free (fc2); -} - -static void -test_rsymlink (void) -{ - Npfcall *fc, *fc2; - struct p9_qid qid = { 1, 2, 3 }; - - if (!(fc = np_create_rsymlink (&qid))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_RSYMLINK, __FUNCTION__); - - assert (fc->u.rsymlink.qid.type == fc2->u.rsymlink.qid.type); - assert (fc->u.rsymlink.qid.version == fc2->u.rsymlink.qid.version); - assert (fc->u.rsymlink.qid.path == fc2->u.rsymlink.qid.path); - - free (fc); - free (fc2); -} - -static void -test_tmknod (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_tmknod (1, "xyz", 3, 4, 5, 6))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_TMKNOD, __FUNCTION__); - - assert (fc->u.tmknod.fid == fc2->u.tmknod.fid); - assert (np_str9cmp (&fc->u.tmknod.name, &fc2->u.tmknod.name) == 0); - assert (fc->u.tmknod.mode == fc2->u.tmknod.mode); - assert (fc->u.tmknod.major == fc2->u.tmknod.major); - assert (fc->u.tmknod.minor == fc2->u.tmknod.minor); - assert (fc->u.tmknod.gid == fc2->u.tmknod.gid); - - free (fc); - free (fc2); -} - -static void -test_rmknod (void) -{ - Npfcall *fc, *fc2; - struct p9_qid qid = { 1, 2, 3 }; - - if (!(fc = np_create_rmknod (&qid))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_RMKNOD, __FUNCTION__); - - assert (fc->u.rmknod.qid.type == fc2->u.rmknod.qid.type); - assert (fc->u.rmknod.qid.version == fc2->u.rmknod.qid.version); - assert (fc->u.rmknod.qid.path == fc2->u.rmknod.qid.path); - - free (fc); - free (fc2); -} - -static void -test_trename (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_trename (1, 2, "xyz"))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_TRENAME, __FUNCTION__); - - assert (fc->u.trename.fid == fc2->u.trename.fid); - assert (fc->u.trename.dfid == fc2->u.trename.dfid); - assert (np_str9cmp (&fc->u.trename.name, &fc2->u.trename.name) == 0); - - free (fc); - free (fc2); -} - -static void -test_rrename(void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_rrename ())) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_RRENAME, __FUNCTION__); - - free (fc); - free (fc2); -} - -static void -test_treadlink (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_treadlink (1))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_TREADLINK, __FUNCTION__); - - assert (fc->u.treadlink.fid == fc2->u.treadlink.fid); - - free (fc); - free (fc2); -} - -static void -test_rreadlink (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_rreadlink ("xyz"))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_RREADLINK, __FUNCTION__); - - assert (np_str9cmp (&fc->u.rreadlink.target, &fc2->u.rreadlink.target) == 0); - - free (fc); - free (fc2); -} - -static void -test_tgetattr (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_tgetattr (42, 5000))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_TGETATTR, __FUNCTION__); - - assert (fc->u.tgetattr.fid == fc2->u.tgetattr.fid); - assert (fc->u.tgetattr.request_mask == fc2->u.tgetattr.request_mask); - - free (fc); - free (fc2); -} - -static void -test_rgetattr (void) -{ - Npfcall *fc, *fc2; - struct p9_qid qid = { 1, 2, 3 }; - - if (!(fc = np_create_rgetattr (1, &qid, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, 20, 21))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_RGETATTR, __FUNCTION__); - - assert (fc->u.rgetattr.valid == fc2->u.rgetattr.valid); - assert (fc->u.rgetattr.qid.type == fc2->u.rgetattr.qid.type); - assert (fc->u.rgetattr.qid.version == fc2->u.rgetattr.qid.version); - assert (fc->u.rgetattr.qid.path == fc2->u.rgetattr.qid.path); - assert (fc->u.rgetattr.mode == fc2->u.rgetattr.mode); - assert (fc->u.rgetattr.uid == fc2->u.rgetattr.uid); - assert (fc->u.rgetattr.gid == fc2->u.rgetattr.gid); - assert (fc->u.rgetattr.nlink == fc2->u.rgetattr.nlink); - assert (fc->u.rgetattr.rdev == fc2->u.rgetattr.rdev); - assert (fc->u.rgetattr.size == fc2->u.rgetattr.size); - assert (fc->u.rgetattr.blksize == fc2->u.rgetattr.blksize); - assert (fc->u.rgetattr.blocks == fc2->u.rgetattr.blocks); - assert (fc->u.rgetattr.atime_sec == fc2->u.rgetattr.atime_sec); - assert (fc->u.rgetattr.atime_nsec == fc2->u.rgetattr.atime_nsec); - assert (fc->u.rgetattr.mtime_sec == fc2->u.rgetattr.mtime_sec); - assert (fc->u.rgetattr.mtime_nsec == fc2->u.rgetattr.mtime_nsec); - assert (fc->u.rgetattr.ctime_sec == fc2->u.rgetattr.ctime_sec); - assert (fc->u.rgetattr.ctime_nsec == fc2->u.rgetattr.ctime_nsec); - assert (fc->u.rgetattr.btime_sec == fc2->u.rgetattr.btime_sec); - assert (fc->u.rgetattr.btime_nsec == fc2->u.rgetattr.btime_nsec); - assert (fc->u.rgetattr.gen == fc2->u.rgetattr.gen); - assert (fc->u.rgetattr.data_version == fc2->u.rgetattr.data_version); - - free (fc); - free (fc2); -} - -static void -test_tsetattr (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_tsetattr (1,2,3,4,5,6,7,8,9,10))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_TSETATTR, __FUNCTION__); - - assert (fc->u.tsetattr.fid == fc2->u.tsetattr.fid); - assert (fc->u.tsetattr.valid == fc2->u.tsetattr.valid); - assert (fc->u.tsetattr.mode == fc2->u.tsetattr.mode); - assert (fc->u.tsetattr.uid == fc2->u.tsetattr.uid); - assert (fc->u.tsetattr.gid == fc2->u.tsetattr.gid); - assert (fc->u.tsetattr.size == fc2->u.tsetattr.size); - assert (fc->u.tsetattr.atime_sec == fc2->u.tsetattr.atime_sec); - assert (fc->u.tsetattr.atime_nsec == fc2->u.tsetattr.atime_nsec); - assert (fc->u.tsetattr.mtime_sec == fc2->u.tsetattr.mtime_sec); - assert (fc->u.tsetattr.mtime_nsec == fc2->u.tsetattr.mtime_nsec); - - free (fc); - free (fc2); -} - -static void -test_rsetattr (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_rsetattr ())) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_RSETATTR, __FUNCTION__); - - free (fc); - free (fc2); -} - -static void -test_txattrwalk (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_txattrwalk(1, 2, "abc"))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_TXATTRWALK, __FUNCTION__); - - assert (fc->u.txattrwalk.fid == fc2->u.txattrwalk.fid); - assert (fc->u.txattrwalk.attrfid == fc2->u.txattrwalk.attrfid); - assert (np_str9cmp (&fc->u.txattrwalk.name, &fc2->u.txattrwalk.name) == 0); - - free (fc); - free (fc2); -} - -static void -test_rxattrwalk (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_rxattrwalk(1))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_RXATTRWALK, __FUNCTION__); - - assert (fc->u.rxattrwalk.size == fc2->u.rxattrwalk.size); - - free (fc); - free (fc2); -} - -static void -test_txattrcreate (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_txattrcreate(1, "abc", 3, 4))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_TXATTRCREATE, __FUNCTION__); - - assert (fc->u.txattrcreate.fid == fc2->u.txattrcreate.fid); - assert (np_str9cmp (&fc->u.txattrcreate.name, &fc2->u.txattrcreate.name) == 0); - assert (fc->u.txattrcreate.size == fc2->u.txattrcreate.size); - assert (fc->u.txattrcreate.flag == fc2->u.txattrcreate.flag); - - free (fc); - free (fc2); -} - -static void -test_rxattrcreate (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_rxattrcreate())) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_RXATTRCREATE, __FUNCTION__); - - free (fc); - free (fc2); -} - -static void -test_treaddir (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_treaddir(1, 2, 3))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_TREADDIR, __FUNCTION__); - - assert (fc->u.treaddir.fid == fc2->u.treaddir.fid); - assert (fc->u.treaddir.offset == fc2->u.treaddir.offset); - assert (fc->u.treaddir.count == fc2->u.treaddir.count); - - free (fc); - free (fc2); -} - -static void -test_rreaddir (void) -{ - Npfcall *fc, *fc2; - int n = 0, len = 256; - struct p9_qid qid[3] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } }, qid2[3]; - char *name[3] = { "abc", "def", "ghi" }, name2[3][128]; - u64 offset; - u8 type; - - if (!(fc = np_create_rreaddir (len))) - msg_exit ("out of memory"); - n += np_serialize_p9dirent (&qid[0], 0, 1, name[0], - fc->u.rreaddir.data + n, len - n); - n += np_serialize_p9dirent (&qid[1], 50, 2, name[1], - fc->u.rreaddir.data + n, len - n); - n += np_serialize_p9dirent (&qid[2], 100, 3, name[2], - fc->u.rreaddir.data + n, len - n); - assert (n < len); - np_finalize_rreaddir (fc, n); - fc2 = _rcv_buf (fc, P9_RREADDIR, __FUNCTION__); - - assert (fc->u.rreaddir.count == fc2->u.rreaddir.count); - - n = 0; - n += np_deserialize_p9dirent (&qid2[0], &offset, &type, name2[0], 128, - fc2->u.rreaddir.data + n, fc2->u.rreaddir.count - n); - assert (offset == 0); - assert (type == 1); - assert (strcmp (name2[0], name[0]) == 0); - n += np_deserialize_p9dirent (&qid2[1], &offset, &type, name2[1], 128, - fc2->u.rreaddir.data + n, fc2->u.rreaddir.count - n); - assert (offset == 50); - assert (type == 2); - assert (strcmp (name2[1], name[1]) == 0); - n += np_deserialize_p9dirent (&qid2[2], &offset, &type, name2[2], 128, - fc2->u.rreaddir.data + n, fc2->u.rreaddir.count - n); - assert (offset == 100); - assert (type == 3); - assert (strcmp (name2[2], name[2]) == 0); - assert (n == fc2->u.rreaddir.count); - - free (fc); - free (fc2); -} - -static void -test_tfsync (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_tfsync(1, 42))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_TFSYNC, __FUNCTION__); - - assert (fc->u.tfsync.fid == fc2->u.tfsync.fid); - assert (fc->u.tfsync.datasync == fc2->u.tfsync.datasync); - - free (fc); - free (fc2); -} - -static void -test_rfsync (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_rfsync())) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_RFSYNC, __FUNCTION__); - - free (fc); - free (fc2); -} - -static void -test_tlock (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_tlock (1, P9_LOCK_TYPE_UNLCK, 3, 4, 5, 6, "xyz"))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_TLOCK, __FUNCTION__); - - assert (fc->u.tlock.fid == fc2->u.tlock.fid); - assert (fc->u.tlock.type == fc2->u.tlock.type); - assert (fc->u.tlock.flags == fc2->u.tlock.flags); - assert (fc->u.tlock.start == fc2->u.tlock.start); - assert (fc->u.tlock.length == fc2->u.tlock.length); - assert (np_str9cmp (&fc->u.tlock.client_id, &fc2->u.tlock.client_id) == 0); - - free (fc); - free (fc2); -} - -static void -test_rlock (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_rlock (1))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_RLOCK, __FUNCTION__); - - assert (fc->u.rlock.status == fc2->u.rlock.status); - - free (fc); - free (fc2); -} - -static void -test_tgetlock (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_tgetlock (1, P9_LOCK_TYPE_UNLCK, 3, 4, 5, "xyz"))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_TGETLOCK, __FUNCTION__); - - assert (fc->u.tgetlock.fid == fc2->u.tgetlock.fid); - assert (fc->u.tgetlock.type == fc2->u.tgetlock.type); - assert (fc->u.tgetlock.start == fc2->u.tgetlock.start); - assert (fc->u.tgetlock.length == fc2->u.tgetlock.length); - assert (fc->u.tgetlock.proc_id == fc2->u.tgetlock.proc_id); - assert (np_str9cmp (&fc->u.tgetlock.client_id, &fc2->u.tgetlock.client_id) == 0); - - free (fc); - free (fc2); -} - -static void -test_rgetlock (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_rgetlock (P9_LOCK_TYPE_WRLCK, 2, 3, 4, "xyz"))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_RGETLOCK, __FUNCTION__); - - assert (fc->u.rgetlock.type == fc2->u.rgetlock.type); - assert (fc->u.rgetlock.start == fc2->u.rgetlock.start); - assert (fc->u.rgetlock.length == fc2->u.rgetlock.length); - assert (fc->u.rgetlock.proc_id == fc2->u.rgetlock.proc_id); - assert (np_str9cmp (&fc->u.rgetlock.client_id, &fc2->u.rgetlock.client_id) == 0); - - free (fc); - free (fc2); -} - -static void -test_tlink (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_tlink (1, 2, "xyz"))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_TLINK, __FUNCTION__); - - assert (fc->u.tlink.dfid == fc2->u.tlink.dfid); - assert (fc->u.tlink.fid == fc2->u.tlink.fid); - assert (np_str9cmp (&fc->u.tlink.name, &fc2->u.tlink.name) == 0); - - free (fc); - free (fc2); -} - -static void -test_rlink (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_rlink ())) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_RLINK, __FUNCTION__); - - free (fc); - free (fc2); -} - -static void -test_tmkdir (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_tmkdir (1, "abc", 2, 3))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_TMKDIR, __FUNCTION__); - - assert (fc->u.tmkdir.fid == fc2->u.tmkdir.fid); - assert (np_str9cmp (&fc->u.tmkdir.name, &fc2->u.tmkdir.name) == 0); - assert (fc->u.tmkdir.mode == fc2->u.tmkdir.mode); - assert (fc->u.tmkdir.gid == fc2->u.tmkdir.gid); - - free (fc); - free (fc2); -} - -static void -test_rmkdir (void) -{ - Npfcall *fc, *fc2; - struct p9_qid qid = { 1, 2, 3 }; - - if (!(fc = np_create_rmkdir (&qid))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_RMKDIR, __FUNCTION__); - - assert (fc->u.rmkdir.qid.type == fc2->u.rmkdir.qid.type); - assert (fc->u.rmkdir.qid.version == fc2->u.rmkdir.qid.version); - assert (fc->u.rmkdir.qid.path == fc2->u.rmkdir.qid.path); - - free (fc); - free (fc2); -} - -static void -test_trenameat (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_trenameat (1, "abc", 2, "zyx"))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_TRENAMEAT, __FUNCTION__); - - assert (fc->u.trenameat.olddirfid == fc2->u.trenameat.olddirfid); - assert (np_str9cmp (&fc->u.trenameat.oldname, &fc2->u.trenameat.oldname) == 0); - assert (fc->u.trenameat.newdirfid == fc2->u.trenameat.newdirfid); - assert (np_str9cmp (&fc->u.trenameat.newname, &fc2->u.trenameat.newname) == 0); - - free (fc); - free (fc2); -} - -static void -test_rrenameat (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_rrenameat ())) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_RRENAMEAT, __FUNCTION__); - - free (fc); - free (fc2); -} - -static void -test_tunlinkat (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_tunlinkat(1, "abc", 2))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_TUNLINKAT, __FUNCTION__); - - assert (fc->u.tunlinkat.dirfid == fc2->u.tunlinkat.dirfid); - assert (np_str9cmp (&fc->u.tunlinkat.name, &fc2->u.tunlinkat.name) == 0); - assert (fc->u.tunlinkat.flags == fc2->u.tunlinkat.flags); - - free (fc); - free (fc2); -} - -static void -test_runlinkat (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_runlinkat ())) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_RUNLINKAT, __FUNCTION__); - - free (fc); - free (fc2); -} - -static void -test_tversion (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_tversion (TEST_MSIZE, "9p2000.L"))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_TVERSION, __FUNCTION__); - - assert (fc->u.tversion.msize == fc2->u.tversion.msize); - assert (np_str9cmp (&fc->u.tversion.version, &fc2->u.tversion.version) == 0); - - free (fc); - free (fc2); -} - -static void -test_rversion (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_rversion (TEST_MSIZE, "9p2000.L"))) - msg_exit ("out of memory"); - fc2 = _rcv_buf (fc, P9_RVERSION, __FUNCTION__); - - assert (fc->u.rversion.msize == fc2->u.rversion.msize); - assert (np_str9cmp (&fc->u.rversion.version, &fc2->u.rversion.version) == 0); - - free (fc); - free (fc2); -} - -static void -test_tauth (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_tauth (1, "abc", "xyz", 4))) - msg_exit ("out of memory in %s", __FUNCTION__); - fc2 = _rcv_buf (fc, P9_TAUTH, __FUNCTION__); - - assert (fc->u.tauth.afid == fc2->u.tauth.afid); - assert (np_str9cmp (&fc->u.tauth.uname, &fc2->u.tauth.uname) == 0); - assert (np_str9cmp (&fc->u.tauth.aname, &fc2->u.tauth.aname) == 0); - assert (fc->u.tauth.n_uname == fc2->u.tauth.n_uname); - - free (fc); - free (fc2); -} - -static void -test_rauth (void) -{ - Npfcall *fc, *fc2; - struct p9_qid qid = { 1, 2, 3 }; - - if (!(fc = np_create_rauth (&qid))) - msg_exit ("out of memory in %s", __FUNCTION__); - fc2 = _rcv_buf (fc, P9_RAUTH, __FUNCTION__); - - assert (fc->u.rauth.qid.type == fc2->u.rauth.qid.type); - assert (fc->u.rauth.qid.version == fc2->u.rauth.qid.version); - assert (fc->u.rauth.qid.path == fc2->u.rauth.qid.path); - - free (fc); - free (fc2); -} - -static void -test_tflush (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_tflush (1))) - msg_exit ("out of memory in %s", __FUNCTION__); - fc2 = _rcv_buf (fc, P9_TFLUSH, __FUNCTION__); - - assert (fc->u.tflush.oldtag == fc2->u.tflush.oldtag); - - free (fc); - free (fc2); -} - -static void -test_rflush (void) -{ - Npfcall *fc, *fc2; - char buf[STATIC_RFLUSH_SIZE]; - - if (!(fc = np_create_rflush ())) - msg_exit ("out of memory in %s", __FUNCTION__); - fc2 = _rcv_buf (fc, P9_RFLUSH, __FUNCTION__); - - free (fc); - free (fc2); - - if (!(fc = np_create_rflush_static (buf, sizeof(buf)))) - msg_exit ("out of memory in %s", __FUNCTION__); - fc2 = _rcv_buf (fc, P9_RFLUSH, __FUNCTION__); - - free (fc2); -} - -static void -test_tattach (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_tattach (1, 2, "abc", "xyz", 5))) - msg_exit ("out of memory in %s", __FUNCTION__); - fc2 = _rcv_buf (fc, P9_TATTACH, __FUNCTION__); - - assert (fc->u.tattach.fid == fc2->u.tattach.fid); - assert (fc->u.tattach.afid == fc2->u.tattach.afid); - assert (np_str9cmp (&fc->u.tattach.uname, &fc2->u.tattach.uname) == 0); - assert (np_str9cmp (&fc->u.tattach.aname, &fc2->u.tattach.aname) == 0); - assert (fc->u.tattach.n_uname == fc2->u.tattach.n_uname); - - free (fc); - free (fc2); -} - -static void -test_rattach (void) -{ - Npfcall *fc, *fc2; - struct p9_qid qid = { 1, 2, 3 }; - - if (!(fc = np_create_rattach (&qid))) - msg_exit ("out of memory in %s", __FUNCTION__); - fc2 = _rcv_buf (fc, P9_RATTACH, __FUNCTION__); - - assert (fc->u.rattach.qid.type == fc2->u.rattach.qid.type); - assert (fc->u.rattach.qid.version == fc2->u.rattach.qid.version); - assert (fc->u.rattach.qid.path == fc2->u.rattach.qid.path); - - free (fc); - free (fc2); -} - -static void -test_twalk (void) -{ - Npfcall *fc, *fc2; - char *wnames[P9_MAXWELEM] = { - "abc", "def", "ghi", "jkl", - "abc", "def", "ghi", "jkl", - "abc", "def", "ghi", "jkl", - "abc", "def", "ghi", "jkl", - }; - int i; - - assert (P9_MAXWELEM == 16); - if (!(fc = np_create_twalk (1, 2, P9_MAXWELEM, wnames))) - msg_exit ("out of memory in %s", __FUNCTION__); - fc2 = _rcv_buf (fc, P9_TWALK, __FUNCTION__); - - assert (fc->u.twalk.fid == fc2->u.twalk.fid); - assert (fc->u.twalk.newfid == fc2->u.twalk.newfid); - assert (fc->u.twalk.nwname == fc2->u.twalk.nwname); - assert (fc->u.twalk.nwname == P9_MAXWELEM); - - for (i = 0; i < P9_MAXWELEM; i++) { - assert (np_str9cmp (&fc->u.twalk.wnames[i], &fc2->u.twalk.wnames[i]) ==0); - } - - free (fc); - free (fc2); -} - -static void -test_rwalk (void) -{ - Npfcall *fc, *fc2; - struct p9_qid wqids [P9_MAXWELEM] = { - { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }, { 10, 11, 12 }, - { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }, { 10, 11, 12 }, - { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }, { 10, 11, 12 }, - { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }, { 10, 11, 12 }, - }; - int i; - - assert (P9_MAXWELEM == 16); - - if (!(fc = np_create_rwalk (P9_MAXWELEM, wqids))) - msg_exit ("out of memory in %s", __FUNCTION__); - fc2 = _rcv_buf (fc, P9_RWALK, __FUNCTION__); - - assert (fc->u.rwalk.nwqid == P9_MAXWELEM); - assert (fc->u.rwalk.nwqid == fc2->u.rwalk.nwqid); - - for (i = 0; i < P9_MAXWELEM; i++) { - assert (fc->u.rwalk.wqids[i].type == fc2->u.rwalk.wqids[i].type); - assert (fc->u.rwalk.wqids[i].version == fc2->u.rwalk.wqids[i].version); - assert (fc->u.rwalk.wqids[i].path == fc2->u.rwalk.wqids[i].path); - } - - free (fc); - free (fc2); -} - -static void -test_tread (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_tread (1, 2, 3))) - msg_exit ("out of memory in %s", __FUNCTION__); - fc2 = _rcv_buf (fc, P9_TREAD, __FUNCTION__); - - assert (fc->u.tread.fid == fc2->u.tread.fid); - assert (fc->u.tread.offset == fc2->u.tread.offset); - assert (fc->u.tread.count == fc2->u.tread.count); - - free (fc); - free (fc2); -} - -static void -test_rread (void) -{ - Npfcall *fc, *fc2; - u8 buf[128]; - - memset (buf, 0xf0, sizeof(buf)); - - if (!(fc = np_create_rread (sizeof (buf), buf))) - msg_exit ("out of memory in %s", __FUNCTION__); - np_set_rread_count (fc, sizeof (buf)); - fc2 = _rcv_buf (fc, P9_RREAD, __FUNCTION__); - - assert (fc->u.rread.count == fc2->u.rread.count); - assert (memcmp (fc->u.rread.data, fc2->u.rread.data, fc->u.rread.count) == 0); - - free (fc); - free (fc2); -} - -static void -test_twrite (void) -{ - Npfcall *fc, *fc2; - u8 buf[128]; - - memset (buf, 0x0f, sizeof(buf)); - - if (!(fc = np_create_twrite (1, 2, sizeof (buf), buf))) - msg_exit ("out of memory in %s", __FUNCTION__); - fc2 = _rcv_buf (fc, P9_TWRITE, __FUNCTION__); - - assert (fc->u.twrite.fid == fc2->u.twrite.fid); - assert (fc->u.twrite.offset == fc2->u.twrite.offset); - assert (fc->u.twrite.count == fc2->u.twrite.count); - assert (memcmp (fc->u.twrite.data, fc2->u.twrite.data, fc->u.twrite.count) == 0); - - free (fc); - free (fc2); -} - -static void -test_rwrite (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_rwrite (1))) - msg_exit ("out of memory in %s", __FUNCTION__); - fc2 = _rcv_buf (fc, P9_RWRITE, __FUNCTION__); - - assert (fc->u.rwrite.count == fc2->u.rwrite.count); - - free (fc); - free (fc2); -} - -static void -test_tclunk (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_tclunk (1))) - msg_exit ("out of memory in %s", __FUNCTION__); - fc2 = _rcv_buf (fc, P9_TCLUNK, __FUNCTION__); - - assert (fc->u.tclunk.fid == fc2->u.tclunk.fid); - - free (fc); - free (fc2); -} - -static void -test_rclunk (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_rclunk ())) - msg_exit ("out of memory in %s", __FUNCTION__); - fc2 = _rcv_buf (fc, P9_RCLUNK, __FUNCTION__); - - free (fc); - free (fc2); -} - -static void -test_tremove (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_tremove (1))) - msg_exit ("out of memory in %s", __FUNCTION__); - fc2 = _rcv_buf (fc, P9_TREMOVE, __FUNCTION__); - - assert (fc->u.tremove.fid == fc2->u.tremove.fid); - - free (fc); - free (fc2); -} - -static void -test_rremove (void) -{ - Npfcall *fc, *fc2; - - if (!(fc = np_create_rremove ())) - msg_exit ("out of memory in %s", __FUNCTION__); - fc2 = _rcv_buf (fc, P9_RREMOVE, __FUNCTION__); - - free (fc); - free (fc2); -} - -static void test_truncated_tlink (void) -{ - Npfcall *fc; - - if (!(fc = np_create_tlink (1, 2, "xyz"))) - msg_exit ("out of memory"); - - // truncate fc->pkt so entire name is missing - fc->size -= 3; - fc->pkt[0] = fc->size; - fc->pkt[1] = fc->size >> 8; - fc->pkt[2] = fc->size >> 16; - fc->pkt[3] = fc->size >> 24; - - if (np_deserialize (fc) == 0) - printf ("OK np_deserialize failed on truncated Tlink (issue#109)\n"); - else - printf ("FAIL np_deserialize worked on truncated Tlink (issue#109)\n"); - - free (fc); -} - -/* - * vi:tabstop=4 shiftwidth=4 expandtab - */ diff --git a/tests/misc/tsetfsuid.c b/tests/misc/tsetfsuid.c deleted file mode 100644 index db2aaff3..00000000 --- a/tests/misc/tsetfsuid.c +++ /dev/null @@ -1,159 +0,0 @@ -/************************************************************\ - * Copyright 2010 Lawrence Livermore National Security, LLC - * (c.f. AUTHORS, NOTICE.LLNS, COPYING) - * - * This file is part of the diod 9P server project. - * For details, see https://github.com/chaos/diod. - * - * SPDX-License-Identifier: GPL-2.0-or-later -\************************************************************/ - -/* tsetfsuid.c - check that pthreads can independently setfsuid */ - -/* N.B. error handling for setfsuid/setfsgid is broken in the kernel. - * Two errors can be detected: - * - return -1 with errno set (EINVAL) - * - return of value != previous fsuid/fsgid - * However, they can silently fail, e.g. if process doesn't have CAP_SETUID. - */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "src/libdiod/diod_log.h" - -#include "test.h" - -#define TEST_UID 100 -#define TEST_GID 100 - -typedef enum { S0, S1, S2, S3, S4, S5 } state_t; - -static state_t state = S0; -static pthread_mutex_t state_lock = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t state_cond = PTHREAD_COND_INITIALIZER; - -static int -check_fsid (char *s, uid_t uid, gid_t gid) -{ - int fd; - char path[] = "/tmp/testfsuid.XXXXXX"; - - struct stat sb; - - fd = _mkstemp (path); - _fstat (fd, &sb); - _unlink (path); - - msg ("%s: %d:%d", s, sb.st_uid, sb.st_gid); - - return (sb.st_uid == uid && sb.st_gid == gid); -} - -static void -change_fsid (char *s, uid_t fromuid, gid_t fromgid, uid_t uid, gid_t gid) -{ - int u; - int g; - - msg ("%s: changing to %d:%d", s, uid, gid); - if (fromuid != uid) { - u = setfsuid (uid); - if (u == -1) - err ("%s: setfsuid", s); - else if (u != fromuid) - msg ("%s: setfsuid returned %d (wanted %d)", s, u, fromuid); - } - if (fromgid != gid) { - g = setfsgid (gid); - if (g == -1) - err ("%s: setfsgid", s); - if (g != fromgid) - msg ("%s: setfsgid returned %d (wanted %d)", s, g, fromgid); - } -} - -static void -change_state (state_t s) -{ - _lock (&state_lock); - state = s; - _condsig (&state_cond); - _unlock (&state_lock); -} - -static void -wait_state (state_t s) -{ - _lock (&state_lock); - while ((state != s)) - _condwait (&state_cond, &state_lock); - _unlock (&state_lock); -} - -static void *proc1 (void *a) -{ - assert (check_fsid ("task1", 0, 0)); - change_state (S1); - wait_state (S2); - assert (check_fsid ("task1", 0, 0)); - change_fsid ("task1", 0, 0, TEST_UID, TEST_GID); - assert (check_fsid ("task1", TEST_UID, TEST_GID)); - change_state (S3); - wait_state (S4); - assert (check_fsid ("task1", TEST_UID, TEST_GID)); - return NULL; -} - -static void *proc2 (void *a) -{ - wait_state (S1); - assert (check_fsid ("task2", 0, 0)); - change_fsid ("task2", 0, 0, TEST_UID, TEST_GID); - assert (check_fsid ("task2", TEST_UID, TEST_GID)); - change_state (S2); - wait_state (S3); - change_fsid ("task2", TEST_UID, TEST_GID, 0, 0); - assert (check_fsid ("task2", 0, 0)); - change_state (S4); - return NULL; -} - -int main(int argc, char *argv[]) -{ - pthread_t t1, t2; - - diod_log_init (argv[0]); - - assert (geteuid () == 0); - - assert (check_fsid ("task0", 0, 0)); - - _create (&t1, proc1, NULL); - _create (&t2, proc2, NULL); - - _join (t2, NULL); - _join (t1, NULL); - - assert (check_fsid ("task0", 0, 0)); - - exit (0); -} - -/* - * vi:tabstop=4 shiftwidth=4 expandtab - */ diff --git a/tests/misc/tsetfsuidsupp.c b/tests/misc/tsetfsuidsupp.c deleted file mode 100644 index d20b307b..00000000 --- a/tests/misc/tsetfsuidsupp.c +++ /dev/null @@ -1,156 +0,0 @@ -/************************************************************\ - * Copyright 2010 Lawrence Livermore National Security, LLC - * (c.f. AUTHORS, NOTICE.LLNS, COPYING) - * - * This file is part of the diod 9P server project. - * For details, see https://github.com/chaos/diod. - * - * SPDX-License-Identifier: GPL-2.0-or-later -\************************************************************/ - -/* tsetfsuidsupp.c - do suppl. groups work as expected with fsuid/fsgid? */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "src/libdiod/diod_log.h" -#include "test.h" - -#define TEST_UID 100 -#define TEST_GID 100 -#define TEST_SGID 101 - -static int -check_fsid (uid_t uid, gid_t gid) -{ - int fd; - char path[] = "/tmp/testfsuidsupp.XXXXXX"; - struct stat sb; - - fd = _mkstemp (path); - _fstat (fd, &sb); - _unlink (path); - - return (sb.st_uid == uid && sb.st_gid == gid); -} - -/* Create a test file and return its path. - */ -static char * -create_file (uid_t uid, gid_t gid, mode_t mode) -{ - int fd; - static char path[] = "/tmp/testfsuidsupp.XXXXXX"; - - fd = _mkstemp (path); - _fchown (fd, 0, TEST_SGID); - _fchmod (fd, 0040); - - msg ("file created %d:%d mode 0%o", uid, gid, mode); - - return path; -} - -/* Return 0 if 'path' cannot be opened for reading, - * nonzero if it can. - */ -static int -read_file (char *path) -{ - int fd; - - if ((fd = open (path, O_RDONLY)) < 0) { - msg ("file is NOT readable"); - return 0; - } - close (fd); - msg ("file is readable"); - return 1; -} - -static void -change_fsid (uid_t olduid, gid_t oldgid, uid_t uid, gid_t gid) -{ - int u; - int g; - - if (uid != olduid) { - u = setfsuid (uid); - if (u == -1) - err ("setfsuid"); - else if (u != olduid) - msg ("setfsuid returned %d (wanted %d)", u, olduid); - } - if (gid != oldgid) { - g = setfsgid (gid); - if (g == -1) - err ("setfsgid"); - else if (g != oldgid) - msg ("setfsgid returned %d (wanted %d)", g, oldgid); - } - if (!check_fsid (uid, gid)) - msg_exit ("setfsuid/setfsgid failed"); - msg ("fsid changed to %d:%d", uid, gid); -} - -int main(int argc, char *argv[]) -{ - char *path; - gid_t gids[] = { TEST_SGID }; - - diod_log_init (argv[0]); - - assert (geteuid () == 0); - - /* clear supplemental groups */ - _setgroups (0, NULL); - msg ("supplemental groups cleared"); - - assert (geteuid () == 0); - path = create_file (0, TEST_SGID, 0440); - - change_fsid (0, 0, TEST_UID, TEST_GID); - assert (!read_file (path)); - - change_fsid (TEST_UID, TEST_GID, TEST_UID, TEST_SGID); - assert (read_file (path)); - - change_fsid (TEST_UID, TEST_SGID, TEST_UID, TEST_GID); - assert (!read_file (path)); - - /* set TEST_SGID in supplemental groups */ - _setgroups (1, gids); - msg ("%d added to supplemental groups", gids[0]); - assert (read_file (path)); - - /* clear supplemental groups */ - _setgroups (0, NULL); - msg ("supplemental groups cleared"); - assert (!read_file (path)); - - /* clean up */ - change_fsid (TEST_UID, TEST_GID, 0, 0); - _unlink (path); - - msg ("test complete"); - exit (0); -} - -/* - * vi:tabstop=4 shiftwidth=4 expandtab - */ diff --git a/tests/misc/tsetuid.c b/tests/misc/tsetuid.c deleted file mode 100644 index 9add7543..00000000 --- a/tests/misc/tsetuid.c +++ /dev/null @@ -1,126 +0,0 @@ -/************************************************************\ - * Copyright 2010 Lawrence Livermore National Security, LLC - * (c.f. AUTHORS, NOTICE.LLNS, COPYING) - * - * This file is part of the diod 9P server project. - * For details, see https://github.com/chaos/diod. - * - * SPDX-License-Identifier: GPL-2.0-or-later -\************************************************************/ - -/* tsetuid.c - check that pthreads CANNOT independently setreuid */ - -/* This was an assumption made in the old npfs code, no longer true - * post-linuxthreads. It's here as a demonstration of that fact, - * and in case anything changes in this area we might want to flag it. - */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "src/libdiod/diod_log.h" -#include "test.h" - -#define TEST_UID 100 -#define TEST_UID2 101 -#define TEST_UID3 102 - -typedef enum { S0, S1, S2, S3, S4, S5 } state_t; - -static state_t state = S0; -static pthread_mutex_t state_lock = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t state_cond = PTHREAD_COND_INITIALIZER; - -static void -change_state (state_t s) -{ - _lock (&state_lock); - state = s; - _condsig (&state_cond); - _unlock (&state_lock); -} - -static void -wait_state (state_t s) -{ - _lock (&state_lock); - while ((state != s)) - _condwait (&state_cond, &state_lock); - _unlock (&state_lock); -} - -static void *proc1 (void *a) -{ - msg ("task1: geteuid %d", geteuid ()); - change_state (S1); - - wait_state (S2); - msg ("task1: geteuid %d", geteuid ()); - msg ("task1: seteuid %d", TEST_UID2); - _setreuid (0, 0); - _setreuid (-1, TEST_UID2); - msg ("task1: geteuid %d", geteuid ()); - change_state (S3); - - wait_state (S4); - msg ("task1: geteuid %d", geteuid ()); - return NULL; -} - -static void *proc2 (void *a) -{ - wait_state (S1); - msg ("task2: geteuid %d", geteuid ()); - msg ("task2: seteuid %d", TEST_UID); - _setreuid (0, 0); - _setreuid (-1, TEST_UID); - msg ("task2: geteuid %d", geteuid ()); - change_state (S2); - - wait_state (S3); - msg ("task2: geteuid %d", geteuid ()); - msg ("task2: seteuid %d", TEST_UID3); - _setreuid (0, 0); - _setreuid (-1, TEST_UID3); - msg ("task2: geteuid %d", geteuid ()); - change_state (S4); - return NULL; -} - -int main(int argc, char *argv[]) -{ - pthread_t t1, t2; - - diod_log_init (argv[0]); - - assert (geteuid () == 0); - - msg ("task0: geteuid %d", geteuid ()); - - _create (&t1, proc1, NULL); - _create (&t2, proc2, NULL); - - _join (t2, NULL); - _join (t1, NULL); - - msg ("task0: geteuid %d", geteuid ()); - - exit (0); -} - -/* - * vi:tabstop=4 shiftwidth=4 expandtab - */ diff --git a/tests/misc/tsuppgrp.c b/tests/misc/tsuppgrp.c deleted file mode 100644 index 528742e0..00000000 --- a/tests/misc/tsuppgrp.c +++ /dev/null @@ -1,136 +0,0 @@ -/************************************************************\ - * Copyright 2010 Lawrence Livermore National Security, LLC - * (c.f. AUTHORS, NOTICE.LLNS, COPYING) - * - * This file is part of the diod 9P server project. - * For details, see https://github.com/chaos/diod. - * - * SPDX-License-Identifier: GPL-2.0-or-later -\************************************************************/ - -/* tsuppgrp.c - check that pthreads can independently setgroups */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "src/libdiod/diod_log.h" - -#include "test.h" - -#define TEST_GID 100 -#define TEST_GID2 101 - -typedef enum { S0, S1, S2, S3, S4, S5 } state_t; - -static state_t state = S0; -static pthread_mutex_t state_lock = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t state_cond = PTHREAD_COND_INITIALIZER; - -static void -show_groups (char *s) -{ - gid_t g[32]; - int n, i; - char buf[256]; - - snprintf (buf, sizeof(buf), "getgroups "); - n = _getgroups (1, g); - for (i = 0; i < n; i++) - snprintf (buf+strlen(buf), sizeof(buf)-strlen(buf), "%d ", g[i]); - msg ("%s: %s", s, buf); -} - -static void -change_state (state_t s) -{ - _lock (&state_lock); - state = s; - _condsig (&state_cond); - _unlock (&state_lock); -} - -static void -wait_state (state_t s) -{ - _lock (&state_lock); - while ((state != s)) - _condwait (&state_cond, &state_lock); - _unlock (&state_lock); -} - -static void *proc1 (void *a) -{ - gid_t g[] = { TEST_GID2 }; - - show_groups ("task1"); - change_state (S1); - - wait_state (S2); - show_groups ("task1"); - - msg ("task1: setgroups %d", TEST_GID2); - _setgroups (1, g); - show_groups ("task1"); - change_state (S3); - - wait_state (S4); - return NULL; -} - -static void *proc2 (void *a) -{ - gid_t g[] = { TEST_GID }; - - wait_state (S1); - show_groups ("task2"); - - msg ("task2: setgroups %d", TEST_GID); - _setgroups (1, g); - show_groups ("task2"); - change_state (S2); - - wait_state (S3); - show_groups ("task2"); - change_state (S4); - return NULL; -} - -int main(int argc, char *argv[]) -{ - pthread_t t1, t2; - - diod_log_init (argv[0]); - - assert (geteuid () == 0); - - msg ("task0: setgroups (NULL)"); - _setgroups (0, NULL); - show_groups ("task0"); - - _create (&t1, proc1, NULL); - _create (&t2, proc2, NULL); - - _join (t2, NULL); - _join (t1, NULL); - - show_groups ("task0"); - - exit (0); -} - -/* - * vi:tabstop=4 shiftwidth=4 expandtab - */