diff options
| author | Thomas Weißschuh <linux@weissschuh.net> | 2026-05-21 19:31:04 +0200 |
|---|---|---|
| committer | Thomas Weißschuh <linux@weissschuh.net> | 2026-05-24 23:58:04 +0200 |
| commit | 835fa43a4d36bd66ad0dd052f9fa15f7bd365fa8 (patch) | |
| tree | 3e0c781168f0d563a73487d5fa1206cbea11e5a2 /tools/testing | |
| parent | acbbec15195b40adefd24993661c93022f6de2b7 (diff) | |
tools/nolibc: add ftruncate()
On architectures with 32-bit longs, call the compat syscall
__NR_ftruncate64. As off_t is 64-bit it must be split into 2 registers.
Unlike llseek() which passes the high and low parts in explicitly named
arguments, the order here is endian independent.
Some architectures (arm, mips, ppc) require this pair of registers to
be aligned to an even register, so add custom _sys_ftruncate64()
wrappers for those.
A test case for ftruncate is added which validates negative length or
invalid fd return the appropriate error, and checks the length is
correct on success.
Co-developed-by: Jordan Richards <jordanrichards@google.com>
Signed-off-by: Jordan Richards <jordanrichards@google.com>
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
Acked-by: Willy Tarreau <w@1wt.eu>
Reviewed-by: Daniel Palmer <daniel@thingy.jp>
Link: https://patch.msgid.link/20260521-nolibc-ftruncate-v1-3-5384a83b2402@weissschuh.net
Diffstat (limited to 'tools/testing')
| -rw-r--r-- | tools/testing/selftests/nolibc/nolibc-test.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index c3867cc570c6..7c3b711c125c 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -1017,6 +1017,57 @@ int test_fork(enum fork_type type) } } +int test_ftruncate(void) +{ + struct stat stat_buf; + int ret, fd; + + ret = ftruncate(-1, 0); + if (ret != -1 || errno != EBADF) { + errno = EINVAL; + return __LINE__; + } + + fd = memfd_create(__func__, 0); + if (fd == -1) + return __LINE__; + + /* + * This also tests that the high 32-bit half is passed through correctly. + * If it gets lost, the kernel will see a positive number and not fail. + */ + ret = ftruncate(fd, -1); + if (!(ret == -1 && errno == EINVAL)) { + if (ret == 0) + errno = EINVAL; + ret = __LINE__; + goto end; + } + + ret = ftruncate(fd, 42); + if (ret != 0) { + ret = __LINE__; + goto end; + } + + ret = fstat(fd, &stat_buf); + if (ret != 0) { + ret = __LINE__; + goto end; + } + + if (stat_buf.st_size != 42) { + errno = EINVAL; + ret = __LINE__; + goto end; + } + +end: + close(fd); + + return ret; +} + int test_stat_timestamps(void) { struct stat st; @@ -1539,6 +1590,7 @@ int run_syscall(int min, int max) CASE_TEST(file_stream); EXPECT_SYSZR(1, test_file_stream()); break; CASE_TEST(file_stream_wsr); EXPECT_SYSZR(1, test_file_stream_wsr()); break; CASE_TEST(fork); EXPECT_SYSZR(1, test_fork(FORK_STANDARD)); break; + CASE_TEST(ftruncate); EXPECT_SYSZR(1, test_ftruncate()); break; CASE_TEST(getdents64_root); EXPECT_SYSNE(1, test_getdents64("/"), -1); break; CASE_TEST(getdents64_null); EXPECT_SYSER(1, test_getdents64("/dev/null"), -1, ENOTDIR); break; CASE_TEST(directories); EXPECT_SYSZR(is_nolibc && proc, test_dirent()); break; |
