From nobody Thu Apr 2 01:47:56 2026 Received: from mail-dy1-f202.google.com (mail-dy1-f202.google.com [74.125.82.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4A2681E5702 for ; Tue, 3 Mar 2026 01:00:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772499644; cv=none; b=X9TTpfSbkIdNzUBI8+aeh97dI0Zu5xrOjHS8rB5EFMj+0o847defp6xrd8fMGB28p5ddOCPon9dWe8OPEHwJU+TCqDjf8UJYavLV7bQS2DEYSUB+ACyHFB+8r3rZa3saFi2d1FHZ1jPq5k+Izdzt/HULpcbG6n+c0Xjq0PGvBwc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772499644; c=relaxed/simple; bh=pZIzdoHBsTFqWgy15ncCajj5m+dgIqKqfVSYDon3jks=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=jygHTiXgUol/Y+aX2zlj2Ou0lFrUG1W29FvBIDgLC2YAfNDalzaS3eEOVVOTI7kNXxGROMB1MoBkA3Dj5ZFqZUlVZMLT36X+PveUsa0+98LGH2DGS71sOeajKp+AmqHZLTW9sDnTq+7mHLlyTMvtxpzEyegpvZWPEVXoUvXgcF4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--jordanrichards.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=UkAFldir; arc=none smtp.client-ip=74.125.82.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--jordanrichards.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="UkAFldir" Received: by mail-dy1-f202.google.com with SMTP id 5a478bee46e88-2bdc1b30ac8so9703529eec.1 for ; Mon, 02 Mar 2026 17:00:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1772499642; x=1773104442; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=6LBYWilsGadQ1Pufl4WrAtKAejCy/lhARa3nYcHQerM=; b=UkAFldirMBSZU+j201vtp2QPuvl0kXZjRh0Qv/WzbzaiZQihoSUqf2KezEJN+e1uVJ Xfms1Yr43LYdI4yXBy0zqLD7ogWOf8/JxCdgI2yCsv9WRU6B8d6p4rwKi4uIq1pSo7az l/AuBIiyzWI7UslcpT4gtIjO48aQCU19YfT3dI4J/WfntMVzHUxPqb2YIs4SgkdAHRoJ 4/QLOs+WJMVqb3B3z+Nl1ouTiLM2n5WwycuzOldVkYC1qs+cFJsqj6t7q18//tY2Q7lC YVhFn+al5QmEShCeQ1BACgsaxTPMpP5iQ5tUiGGt1AGUffVM27lyuM2FVCtCwOQIeZMT +/zw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772499642; x=1773104442; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=6LBYWilsGadQ1Pufl4WrAtKAejCy/lhARa3nYcHQerM=; b=YI3nzOCPXosC3p2SVubNx3yrbMkl+6iZtzDJdhnS7OyD3Q++oyqVAnaYafCQgN/izL XI+fN+23UzFGfSthyVqEWCwHQs9wMad9hIPxnDA202ig3RgxaC/zB4G3xSafmvzLY9og LKtbx/gtlclwotWb45ZYp4MvAAQMY5EkQ3L9Nj08iuV0ECz8OaqtbIxtQZ0HAIOVdhIP ihuxYRMvjtU8L5eOjYsOCkDjYGThglqWxGnmUVWlQxGdZJy5R58p8rxDpg2EoReTPNFT e16FwYCo7cCiJi/NNfV9QyjnJHK3pbhsYwXjZyN0JajbMyBUim01PK0/3I2C1LPscExz Hk/Q== X-Forwarded-Encrypted: i=1; AJvYcCW1cr8feSkDiSIVHYe1Xn6jj2lijYrG/Ygj31QdgF8/0e6wV0fwKRrGuTXXtT0F/ctQDV4e0eFj2/w5Hfk=@vger.kernel.org X-Gm-Message-State: AOJu0YyWn4Bnor/ll8JO+vg25orEU1UyJ/ghnRO1m2qFu7hT8Eq94aSz //ogPkwu6imWbpsx0Yw4BT+OFiO4TQaUz2pnzAzdmdJcoAp5olnHF4dLXGXAA+1LZUCWPZlCXpj ynWuMsAUnytM50QUhya/R/2CuaC6JiKzFEu307Q== X-Received: from dybir8.prod.google.com ([2002:a05:7300:c8c8:b0:2be:1796:e189]) (user=jordanrichards job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7300:a198:b0:2be:694:5713 with SMTP id 5a478bee46e88-2be069458e8mr3073775eec.36.1772499642072; Mon, 02 Mar 2026 17:00:42 -0800 (PST) Date: Tue, 3 Mar 2026 01:00:38 +0000 In-Reply-To: <20260303010039.2969125-1-jordanrichards@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260303010039.2969125-1-jordanrichards@google.com> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog Message-ID: <20260303010039.2969125-2-jordanrichards@google.com> Subject: [PATCH v3 1/2] tools/nolibc: add ftruncate() From: Jordan Richards To: Pasha Tatashin , Mike Rapoport , Pratyush Yadav , Shuah Khan , Willy Tarreau , "=?UTF-8?q?Thomas=20Wei=C3=9Fschuh?=" Cc: Jason Miu , David Matlack , linux-mm@kvack.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Jordan Richards Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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. Signed-off-by: Jordan Richards --- tools/include/nolibc/arch-arm.h | 11 +++++ tools/include/nolibc/arch-mips.h | 11 +++++ tools/include/nolibc/arch-powerpc.h | 11 +++++ tools/include/nolibc/unistd.h | 35 ++++++++++++++ tools/testing/selftests/nolibc/nolibc-test.c | 51 ++++++++++++++++++++ 5 files changed, 119 insertions(+) diff --git a/tools/include/nolibc/arch-arm.h b/tools/include/nolibc/arch-ar= m.h index 251c42579028..ed65fb674e61 100644 --- a/tools/include/nolibc/arch-arm.h +++ b/tools/include/nolibc/arch-arm.h @@ -6,9 +6,11 @@ =20 #ifndef _NOLIBC_ARCH_ARM_H #define _NOLIBC_ARCH_ARM_H +#include =20 #include "compiler.h" #include "crt.h" +#include "std.h" =20 /* Syscalls for ARM in ARM or Thumb modes : * - registers are 32-bit @@ -196,4 +198,13 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoi= nt __no_stack_protector _s } #endif /* NOLIBC_NO_RUNTIME */ =20 +#ifdef __NR_ftruncate64 +static __attribute__((unused)) +int sys_ftruncate64(int fd, uint32_t length0, uint32_t length1) +{ + return my_syscall4(__NR_ftruncate64, fd, 0, length0, length1); +} +#define sys_ftruncate64 sys_ftruncate64 +#endif + #endif /* _NOLIBC_ARCH_ARM_H */ diff --git a/tools/include/nolibc/arch-mips.h b/tools/include/nolibc/arch-m= ips.h index a72506ceec6b..26d044004ec6 100644 --- a/tools/include/nolibc/arch-mips.h +++ b/tools/include/nolibc/arch-mips.h @@ -6,9 +6,11 @@ =20 #ifndef _NOLIBC_ARCH_MIPS_H #define _NOLIBC_ARCH_MIPS_H +#include =20 #include "compiler.h" #include "crt.h" +#include "std.h" =20 #if !defined(_ABIO32) && !defined(_ABIN32) && !defined(_ABI64) #error Unsupported MIPS ABI @@ -269,4 +271,13 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoi= nt __no_stack_protector __ } #endif /* NOLIBC_NO_RUNTIME */ =20 +#ifdef __NR_ftruncate64 +static __attribute__((unused)) +int sys_ftruncate64(int fd, uint32_t length0, uint32_t length1) +{ + return my_syscall4(__NR_ftruncate64, fd, 0, length0, length1); +} +#define sys_ftruncate64 sys_ftruncate64 +#endif + #endif /* _NOLIBC_ARCH_MIPS_H */ diff --git a/tools/include/nolibc/arch-powerpc.h b/tools/include/nolibc/arc= h-powerpc.h index e0c7e0b81f7c..71829cb027e8 100644 --- a/tools/include/nolibc/arch-powerpc.h +++ b/tools/include/nolibc/arch-powerpc.h @@ -6,9 +6,11 @@ =20 #ifndef _NOLIBC_ARCH_POWERPC_H #define _NOLIBC_ARCH_POWERPC_H +#include =20 #include "compiler.h" #include "crt.h" +#include "std.h" =20 /* Syscalls for PowerPC : * - stack is 16-byte aligned @@ -218,4 +220,13 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoi= nt __no_stack_protector _s } #endif /* NOLIBC_NO_RUNTIME */ =20 +#ifdef __NR_ftruncate64 +static __attribute__((unused)) +int sys_ftruncate64(int fd, uint32_t length0, uint32_t length1) +{ + return my_syscall4(__NR_ftruncate64, fd, 0, length0, length1); +} +#define sys_ftruncate64 sys_ftruncate64 +#endif + #endif /* _NOLIBC_ARCH_POWERPC_H */ diff --git a/tools/include/nolibc/unistd.h b/tools/include/nolibc/unistd.h index bb5e80f3f05d..85ac253f9189 100644 --- a/tools/include/nolibc/unistd.h +++ b/tools/include/nolibc/unistd.h @@ -48,6 +48,41 @@ int access(const char *path, int amode) return faccessat(AT_FDCWD, path, amode, 0); } =20 +#if !defined(sys_ftruncate64) && defined(__NR_ftruncate64) +static __attribute__((unused)) +int sys_ftruncate64(int fd, uint32_t length0, uint32_t length1) +{ + + return my_syscall3(__NR_ftruncate64, fd, length0, length1); +} +#define sys_ftruncate64 sys_ftruncate64 +#endif + +static __attribute__((unused)) +int sys_ftruncate(int fd, off_t length) +{ +#ifdef sys_ftruncate64 + union { + off_t length; + struct { + uint32_t length0; + uint32_t length1; + }; + } arg; + + arg.length =3D length; + + return sys_ftruncate64(fd, arg.length0, arg.length1); +#else + return my_syscall2(__NR_ftruncate, fd, length); +#endif +} + +static __attribute__((unused)) +int ftruncate(int fd, off_t length) +{ + return __sysret(sys_ftruncate(fd, length)); +} =20 static __attribute__((unused)) int msleep(unsigned int msecs) diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/s= elftests/nolibc/nolibc-test.c index 1b9d3b2e2491..6a84dfbb4b73 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -969,6 +969,56 @@ int test_fork(enum fork_type type) } } =20 +int test_ftruncate(void) +{ + int ret; + int fd; + struct stat stat_buf; + const char *filename =3D "/tmp/ftruncate_test"; + + ret =3D ftruncate(-1, 0); + if (ret !=3D -1 || errno !=3D EBADF) { + errno =3D EINVAL; + return __LINE__; + } + + fd =3D open(filename, O_RDWR | O_CREAT); + if (fd =3D=3D -1) + return __LINE__; + + ret =3D ftruncate(fd, -1); + if (ret !=3D -1 || errno !=3D EINVAL) { + if (ret =3D=3D 0) + errno =3D EINVAL; + ret =3D __LINE__; + goto end; + } + + ret =3D ftruncate(fd, 42); + if (ret !=3D 0) { + ret =3D __LINE__; + goto end; + } + + ret =3D fstat(fd, &stat_buf); + if (ret !=3D 0) { + ret =3D __LINE__; + goto end; + } + + if (stat_buf.st_size !=3D 42) { + errno =3D EINVAL; + ret =3D stat_buf.st_size; + goto end; + } + +end: + close(fd); + unlink(filename); + + return ret; +} + int test_stat_timestamps(void) { struct stat st; @@ -1406,6 +1456,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()); b= reak; 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(proc, test_dirent()); break; --=20 2.53.0.473.g4a7958ca14-goog