aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rwxr-xr-xtest/test-acl.sh188
-rw-r--r--test/test-chroot-symlink.c28
-rwxr-xr-xtest/test-chroot-symlink.sh19
-rw-r--r--test/test-fcntl.c58
-rwxr-xr-xtest/test-fcntl.sh5
-rw-r--r--test/test-fstat.c29
-rwxr-xr-xtest/test-fstat.sh8
-rw-r--r--test/test-openat.c58
-rwxr-xr-xtest/test-openat.sh7
-rwxr-xr-xtest/test-relative-from-root.sh14
-rw-r--r--test/test-rename-fstat.c23
-rwxr-xr-xtest/test-rename-fstat.sh12
-rw-r--r--test/test-statx.c20
-rwxr-xr-xtest/test-statx.sh6
-rwxr-xr-xtest/test-umask.sh1
15 files changed, 476 insertions, 0 deletions
diff --git a/test/test-acl.sh b/test/test-acl.sh
new file mode 100755
index 0000000..fb7d5ec
--- /dev/null
+++ b/test/test-acl.sh
@@ -0,0 +1,188 @@
+#!/bin/bash
+#
+# SPDX-License-Identifier: LGPL-2.1-only
+#
+
+# Return vals: 2 - Unable to run ACL commands, assertion failure
+# 1 - Invalid return value
+# 0 - Pass
+
+# NOTE: these test exclusively test setfacl -m
+
+set -u
+
+check_owner () {
+ local file="$1"
+ local expected="$2"
+ local msg="$3"
+ local actual=$(stat -c "%U" "$file")
+ if [ "$actual" != "$expected" ]
+ then
+ echo "$msg" "Fail, '$file' unexpected owner '$actual'"
+ exit 2
+ fi
+}
+
+check_group () {
+ local file="$1"
+ local expected="$2"
+ local msg="$3"
+ local actual=$(stat -c "%G" "$file")
+ if [ "$actual" != "$expected" ]
+ then
+ echo "$msg" "Fail, '$file' unexpected group '$actual'"
+ exit 2
+ fi
+}
+
+check_acl_contains () {
+ local file="$1"
+ local acl="$2"
+ local msg="$3"
+ IFS=',' read -ra acls <<< "$acl"
+ for pattern in "${acls[@]}"; do
+ result=$(getfacl -c "$file" | grep -o "^$pattern")
+ if [ "$result" != "$pattern" ]
+ then
+ echo "$msg" "Fail, did not find desired acl '$pattern' in '$file'"
+ exit 2
+ fi
+ done
+}
+
+check_acl_minimal () {
+ local file="$1"
+ local msg="${2:-''}"
+ local acls
+ acls=$(getfacl -c "${file}" | grep -v "::")
+ if [ -n "$acls" ]
+ then
+ echo "$msg" "Fail, '$file' unexpected getfacl result '$acls'"
+ exit 1
+ fi
+}
+
+test_modify_once () {
+ local file="$1"
+ local acl="$2"
+ local msg="${3:-''}"
+ # ensure that file is pristine
+ check_acl_minimal "$file" "$msg precondition:"
+ check_owner "$file" root "$msg precondition:"
+ check_group "$file" root "$msg precondition:"
+ if ! setfacl -m "$acl" "$file"
+ then
+ echo "$msg" "Fail, unable to call setfacl"
+ exit 2
+ fi
+ check_acl_contains "$file" "$acl" "$msg: acl not set:"
+ check_owner "$file" root "$msg owner corrupted:"
+ check_group "$file" root "$msg group corrupted:"
+}
+
+
+trap "rm -rf testdir" EXIT
+mkdir testdir || exit 1
+
+
+# user
+touch testdir/f1 || exit 1
+mkdir testdir/d1 || exit 1
+# regular file
+test_modify_once testdir/f1 "user:root:r" "$LINENO:"
+# directory
+test_modify_once testdir/d1 "user:root:r" "$LINENO:"
+rm -rf testdir/f1 testdir/d1
+
+#group
+rm -rf testdir/f1 testdir/d1
+touch testdir/f1 || exit 1
+mkdir testdir/d1 || exit 1
+# regular file
+test_modify_once testdir/f1 "group:root:r" "$LINENO:"
+# directory
+test_modify_once testdir/d1 "group:root:r" "$LINENO:"
+rm -rf testdir/f1 testdir/d1
+
+# multiple users
+touch testdir/f1 || exit 1
+mkdir testdir/d1 || exit 1
+# regular file
+test_modify_once testdir/f1 "user:root:r,group:root:r,user:bin:rw" "$LINENO:"
+# directory
+test_modify_once testdir/d1 "user:root:r,group:root:r,user:bin:rw" "$LINENO:"
+rm -rf testdir/f1 testdir/d1
+
+
+# setfacl default acls
+mkdir testdir/d1 || exit 1
+test_modify_once testdir/d1 "default:user:root:r,user:root:r" "$LINENO:"
+rm -rf testdir/d1
+
+
+# multiple calls to setfacl -m on same file
+touch testdir/f1 || exit 1
+mkdir testdir/d1 || exit 1
+check_owner testdir/f1 root "$LINENO: precondition:"
+check_group testdir/f1 root "$LINENO: precondition:"
+check_acl_minimal testdir/f1 "$LINENO: precondition:"
+
+acl1="user:root:r"
+acl2="user:bin:rw"
+
+if ! setfacl -m "$acl1" testdir/f1 # first setfacl
+then
+ echo "$LINENO:" "Fail, unable to call setfacl"
+ exit 2
+fi
+check_acl_contains testdir/f1 "$acl1" "$LINENO: acl1 not set:"
+check_owner testdir/f1 root "$LINENO: owner corrupted:"
+check_group testdir/f1 root "$LINENO: group corrupted:"
+
+if ! setfacl -m "$acl2" testdir/f1 # second setfacl
+then
+ echo "$LINENO:" "Fail, unable to call setfacl"
+ exit 2
+fi
+
+check_acl_contains testdir/f1 "$acl1" "$LINENO: acl1 not set:"
+check_acl_contains testdir/f1 "$acl2" "$LINENO: acl2 not set:"
+check_owner testdir/f1 root "$LINENO: owner corrupted:"
+check_group testdir/f1 root "$LINENO: group corrupted:"
+rm -rf testdir/f1 testdir/d1
+
+# setfacl recursive
+test_modify_recursive () {
+ local root_dir="$1"
+ local acl="$2"
+ local msg="${3:-''}"
+
+ find "$root_dir" | while read -r file; do
+ check_owner "$file" root "$msg precondition:"
+ check_group "$file" root "$msg precondition:"
+ check_acl_minimal "$file" "$msg precondition:"
+ done
+ if ! setfacl -R -m "$acl" "$root_dir"
+ then
+ echo "$msg" "Fail, unable to call setfacl"
+ exit 2
+ fi
+ find "$root_dir" | while read -r file; do
+ check_owner "$file" root "$msg owner corrupted:"
+ check_group "$file" root "$msg group corrupted:"
+ check_acl_contains "$file" "$acl" "$msg acl not set:"
+ done
+}
+
+mkdir -p testdir/d1/d2 || exit 1
+touch testdir/d1/d2/f1 || exit 1
+test_modify_recursive testdir/d1 "user:root:r,group:root:r,user:bin:rw" "$LINENO:"
+rm -rf testdir/d1
+
+mkdir -p testdir/d1/d2 || exit 1
+mkdir -p testdir/d1/d3 || exit 1
+test_modify_recursive testdir/d1 "default:user:root:rwx,user:root:r,group:root:r,user:bin:rw" "$LINENO:"
+rm -rf testdir/d1
+
+#echo "Passed."
+exit 0
diff --git a/test/test-chroot-symlink.c b/test/test-chroot-symlink.c
new file mode 100644
index 0000000..469cb49
--- /dev/null
+++ b/test/test-chroot-symlink.c
@@ -0,0 +1,28 @@
+/*
+ * Test that stat'ing absolute/relative symlinks in a chroot environment works
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+#define _GNU_SOURCE
+
+#include <unistd.h>
+#include <sys/stat.h>
+#include <stdio.h>
+
+int main(int argc, char *argv[]) {
+ struct stat buf;
+
+ if (argc != 2) {
+ perror("args");
+ return 2;
+ }
+ if (chroot(argv[1]) == -1) {
+ perror("chroot");
+ return 1;
+ }
+ if (stat("symlink", &buf) == -1) {
+ perror("stat symlink");
+ return 1;
+ }
+ return 0;
+}
diff --git a/test/test-chroot-symlink.sh b/test/test-chroot-symlink.sh
new file mode 100755
index 0000000..91092c1
--- /dev/null
+++ b/test/test-chroot-symlink.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+#
+# Test that stat'ing absolute/relative symlinks in a chroot environment works
+# SPDX-License-Identifier: LGPL-2.1-only
+#
+
+set -e
+
+touch symlink_target
+trap "rm -f symlink_target symlink" 0
+
+# Absolute symlink
+ln -s /symlink_target symlink
+./test/test-chroot-symlink `pwd`
+rm symlink
+
+# Relative symlink
+ln -s symlink_target symlink
+./test/test-chroot-symlink `pwd`
diff --git a/test/test-fcntl.c b/test/test-fcntl.c
new file mode 100644
index 0000000..b593d50
--- /dev/null
+++ b/test/test-fcntl.c
@@ -0,0 +1,58 @@
+/* fcntl-linux.h doesn't define F_GETPIPE_SZ and F_SETPIPE_SZ without
+ * this */
+#define _GNU_SOURCE
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <unistd.h>
+#include <string.h>
+
+int test_pipe_sz()
+{
+#if defined(F_GETPIPE_SZ) && defined(F_SETPIPE_SZ)
+ int pipefd[2];
+
+ if (pipe(pipefd) < 0) {
+ perror("pipe");
+ return 1;
+ }
+
+ const int orig_size = fcntl(pipefd[0], F_GETPIPE_SZ);
+ if (orig_size < 0) {
+ perror("F_GETPIPE_SZ");
+ return 1;
+ }
+
+ const int new_size = orig_size * 2;
+
+ if (fcntl(pipefd[0], F_SETPIPE_SZ, new_size) < 0) {
+ perror("F_SETPIPE_SZ");
+ return 1;
+ }
+
+ const int final_size = fcntl(pipefd[0], F_GETPIPE_SZ);
+ if (final_size < 0) {
+ perror("Second F_GETPIPE_SZ");
+ return 1;
+ }
+
+ if (final_size < new_size) {
+ fprintf(stderr, "Unexpected final pipe size: %d\n", final_size);
+ return 1;
+ }
+#else
+ printf("Host too old for F_GETPIPE_SZ and F_SETPIPE_SZ tests\n");
+#endif
+ return 0;
+}
+
+int main()
+{
+ int result = 0;
+ result += test_pipe_sz();
+ return result;
+}
diff --git a/test/test-fcntl.sh b/test/test-fcntl.sh
new file mode 100755
index 0000000..7112620
--- /dev/null
+++ b/test/test-fcntl.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+#
+# SPDX-License-Identifier: LGPL-2.1-only
+#
+./test/test-fcntl
diff --git a/test/test-fstat.c b/test/test-fstat.c
new file mode 100644
index 0000000..78f7013
--- /dev/null
+++ b/test/test-fstat.c
@@ -0,0 +1,29 @@
+/*
+ * Test that stat'ing a file descriptor of a symlink does not dereference the symlink
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+#define _GNU_SOURCE
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+int main(void) {
+ struct stat buf;
+ int fd = open("symlink", O_NOFOLLOW | O_PATH);
+ if (fd == -1) {
+ perror("open symlink");
+ return 1;
+ }
+ if (fstatat(fd, "", &buf, AT_EMPTY_PATH) == -1) {
+ perror("stat symlink");
+ return 1;
+ }
+ if (S_ISLNK(buf.st_mode) != 1) {
+ fprintf(stderr, "path is not a symlink\n");
+ return 1;
+ }
+ return 0;
+}
diff --git a/test/test-fstat.sh b/test/test-fstat.sh
new file mode 100755
index 0000000..88eab8b
--- /dev/null
+++ b/test/test-fstat.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+#
+# SPDX-License-Identifier: LGPL-2.1-only
+#
+
+ln -s . symlink
+trap "rm symlink" 0
+./test/test-fstat
diff --git a/test/test-openat.c b/test/test-openat.c
new file mode 100644
index 0000000..df6655a
--- /dev/null
+++ b/test/test-openat.c
@@ -0,0 +1,58 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <unistd.h>
+#include <string.h>
+
+char *path_of(int fd) {
+ ssize_t len;
+ char proc[PATH_MAX], real[PATH_MAX];
+ snprintf(proc, sizeof(proc), "/proc/self/fd/%d", fd);
+ len = readlink(proc, real, sizeof(real));
+ real[len] = '\0';
+ return strdup(real);
+}
+
+/*
+* Test that recusing up the tree with openat(fd, "../") handles slashes
+* correctly and doesn't end up opening the same directory instead of going up a
+* level.
+*/
+int main () {
+ int fd, dir_fd;
+ struct stat st;
+ ino_t ino;
+ dev_t dev;
+ char *path;
+
+ fd = openat(AT_FDCWD, ".", O_DIRECTORY, 0);
+ fstat(fd, &st);
+ ino = st.st_ino;
+ dev = st.st_dev;
+
+ while (1) {
+ path = path_of(fd);
+ //puts(path);
+
+ dir_fd = openat(fd, "../", O_DIRECTORY, 0);
+ fstat(dir_fd, &st);
+ if (st.st_ino == ino && st.st_dev == dev) {
+ if (strcmp(path, "/") == 0) {
+ //puts("Reached top of tree");
+ return 0;
+ } else {
+ //puts("Recursion failed!");
+ return 1;
+ }
+ }
+
+ free (path);
+ ino = st.st_ino;
+ dev = st.st_dev;
+ fd = dir_fd;
+ }
+ return 0;
+}
diff --git a/test/test-openat.sh b/test/test-openat.sh
new file mode 100755
index 0000000..0455586
--- /dev/null
+++ b/test/test-openat.sh
@@ -0,0 +1,7 @@
+#! /bin/sh
+
+# Test with and without paths being ignored. The bug was with paths being ignored.
+
+./test/test-openat
+
+PSEUDO_IGNORE_PATHS=/ ./test/test-openat
diff --git a/test/test-relative-from-root.sh b/test/test-relative-from-root.sh
new file mode 100755
index 0000000..e2c230e
--- /dev/null
+++ b/test/test-relative-from-root.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+# pseudo had a bug that made it abort() when looking up a relative path from
+# base "/", such as by openat(dirfd_of_root, "foo/bar") or when cwd is /. It
+# tried to look up base+"/"+path = "//foo/bar", which is wrong.
+
+set -e
+
+touch f1
+relative_pwd=${PWD#/}
+
+cd /
+cat "$relative_pwd/f1"
+
+rm "$relative_pwd/f1"
diff --git a/test/test-rename-fstat.c b/test/test-rename-fstat.c
new file mode 100644
index 0000000..fb47c05
--- /dev/null
+++ b/test/test-rename-fstat.c
@@ -0,0 +1,23 @@
+/*
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ * Test we can rename a file whilst holding an open fd which we fstat after renaming
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+int main()
+{
+ struct stat buf;
+ int err;
+ int fd = open("test-rename-fstat1", O_RDONLY);
+ err = rename("test-rename-fstat1", "test-rename-fstat1");
+ if (err)
+ return err;
+ return fstat(fd, &buf);
+}
diff --git a/test/test-rename-fstat.sh b/test/test-rename-fstat.sh
new file mode 100755
index 0000000..4ac89b8
--- /dev/null
+++ b/test/test-rename-fstat.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+#
+# SPDX-License-Identifier: LGPL-2.1-only
+#
+
+rm -f test-rename-fstat1 test-rename-fstat2
+touch test-rename-fstat1
+# Will abort if it fails
+./test/test-rename-fstat
+ecode=$?
+rm -f test-rename-fstat1 test-rename-fstat2
+exit $ecode
diff --git a/test/test-statx.c b/test/test-statx.c
new file mode 100644
index 0000000..06d86af
--- /dev/null
+++ b/test/test-statx.c
@@ -0,0 +1,20 @@
+/*
+ * Test that passing NULL to a parameter marked as nonnull works correctly
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+#define _GNU_SOURCE
+
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+// Passing a null pointer is the test scenario
+#pragma GCC diagnostic ignored "-Wnonnull"
+
+int main(void) {
+ if (statx(0, NULL, 0, 0, NULL) != -1) {
+ return 1;
+ }
+ return 0;
+}
diff --git a/test/test-statx.sh b/test/test-statx.sh
new file mode 100755
index 0000000..77d0302
--- /dev/null
+++ b/test/test-statx.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+#
+# SPDX-License-Identifier: LGPL-2.1-only
+#
+
+exec ./test/test-statx
diff --git a/test/test-umask.sh b/test/test-umask.sh
index e4e366b..e09fdbf 100755
--- a/test/test-umask.sh
+++ b/test/test-umask.sh
@@ -35,3 +35,4 @@ case $(mode b) in
*) exit 1;;
esac
+rm a b