From 639e0f2cd730ef4ae72e15b8ee740cd876378c7d Mon Sep 17 00:00:00 2001 From: Josh Megnauth Date: Thu, 4 Sep 2025 01:34:47 -0400 Subject: [PATCH] Add lstat test --- tests/Makefile | 1 + .../bins_dynamic/sys_stat/lstat.stderr | 0 .../bins_dynamic/sys_stat/lstat.stdout | 0 .../bins_static/sys_stat/lstat.stderr | 0 .../bins_static/sys_stat/lstat.stdout | 0 tests/sys_stat/lstat.c | 101 ++++++++++++++++++ 6 files changed, 102 insertions(+) create mode 100644 tests/expected/bins_dynamic/sys_stat/lstat.stderr create mode 100644 tests/expected/bins_dynamic/sys_stat/lstat.stdout create mode 100644 tests/expected/bins_static/sys_stat/lstat.stderr create mode 100644 tests/expected/bins_static/sys_stat/lstat.stdout create mode 100644 tests/sys_stat/lstat.c diff --git a/tests/Makefile b/tests/Makefile index 912949c35a..4fccc679b0 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -108,6 +108,7 @@ EXPECT_NAMES=\ string/stpcpy \ string/stpncpy \ strings \ + sys_stat/lstat \ sys_stat/fstatat \ sys_syslog/syslog \ time/asctime \ diff --git a/tests/expected/bins_dynamic/sys_stat/lstat.stderr b/tests/expected/bins_dynamic/sys_stat/lstat.stderr new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/expected/bins_dynamic/sys_stat/lstat.stdout b/tests/expected/bins_dynamic/sys_stat/lstat.stdout new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/expected/bins_static/sys_stat/lstat.stderr b/tests/expected/bins_static/sys_stat/lstat.stderr new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/expected/bins_static/sys_stat/lstat.stdout b/tests/expected/bins_static/sys_stat/lstat.stdout new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/sys_stat/lstat.c b/tests/sys_stat/lstat.c new file mode 100644 index 0000000000..9dd4dd05c1 --- /dev/null +++ b/tests/sys_stat/lstat.c @@ -0,0 +1,101 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +int main(void) { + int status = EXIT_FAILURE; + + char tempdir_path[] = "/tmp/lstat_test.XXXXXX"; + if (!mkdtemp(tempdir_path)) { + perror("mkdtemp"); + goto bye; + } + int tempdir = open(tempdir_path, O_DIRECTORY); + if (tempdir == -1) { + perror("open (tempdir)"); + goto rmtemp; + } + + // Source + const char src_name[] = "kerouac"; + char src_buf[PATH_MAX] = {0}; + strcpy(src_buf, tempdir_path); + strcat(src_buf, "/"); + strcat(src_buf, src_name); + // TODO: Use openat + int source = open(src_buf, O_CREAT); + if (source == -1) { + perror("open"); + goto close_dir; + } + + // Dest (link) + const char dst_name[] = "on_the_road"; + char dst_buf[PATH_MAX] = {0}; + strcpy(dst_buf, tempdir_path); + strcat(dst_buf, "/"); + strcat(dst_buf, dst_name); + if (symlink(src_buf, dst_buf) == -1) { + perror("symlink"); + goto rm_source; + } + + struct stat src_stat = {0}; + if (fstatat(tempdir, dst_name, &src_stat, 0) == -1) { + perror("fstatat"); + goto rm_dest; + } + // Quick consistency check + uid_t uid = getuid(); + gid_t gid = getgid(); + if (src_stat.st_uid != uid) { + fprintf( + stderr, + "uid:\n\tExpected %ld\n\tActual: %ld\n", + (intmax_t) uid, + (intmax_t) gid + ); + goto rm_dest; + } + if (src_stat.st_nlink != 1) { + fputs("nlink: Expected one hard link\n", stderr); + goto rm_dest; + } + if ((src_stat.st_mode & S_IFMT) != S_IFREG) { + fputs("mode: Expected a normal file\n", stderr); + goto rm_dest; + } + + struct stat dst_stat = {0}; + if (lstat(dst_buf, &dst_stat) == -1) { + perror("lstat"); + goto rm_dest; + } + if (memcmp(&src_stat, &dst_stat, sizeof(struct stat)) == 0) { + fputs("lstat incorrectly followed the symlink\n", stderr); + goto rm_dest; + } + if ((dst_stat.st_mode & S_IFMT) != S_IFLNK) { + fputs("lstat did not stat a link\n", stderr); + goto rm_dest; + } + + status = EXIT_SUCCESS; +rm_dest: + unlink(dst_buf); +rm_source: + unlink(src_buf); +close_dir: + close(tempdir); +rmtemp: + rmdir(tempdir_path); +bye: + return status; +}