Passing a 64 bit value with syscall() has problems in certain older

syscalls on some 32 bit architectures, and this one is used as the
_example_ in the the "Architecture-specific requirements" section of
"man 2 syscall".

Some 32-bit processors can only use 64 bit values in even register
pairs. Eight old syscalls (fadvise64_64, ftruncate64, posix_fadvise,
pread64, pwrite64, readahead, sync_file_range, and truncate64) didn't
arrange the argument order to naturally align, so required padding on
32-bit arm eabi, mips oabi, powerpc, parisc, and xtensa.

The libc wrapper inserts this padding when necessary, and using that is
less ugly than architecture specific whack-a-mole in toybox, even
working around glibc's refusal to provide the prototype unless we
declare Linux to be somehow owned by the Free Softare Foundation (which
was why it was using the syscall directly before).
This commit is contained in:
Rob Landley 2025-08-14 19:06:58 -05:00
parent 7932d08016
commit a3e5f1b1ea

View File

@ -15,18 +15,15 @@ config READAHEAD
Preload files into disk cache.
*/
#define _LARGEFILE64_SOURCE // musl's _ALL_SOURCE lies, no off64_t
#include "toys.h"
// glibc won't provide this prototype unless we claim Linux belongs to the FSF
ssize_t readahead(int fd, off64_t offset, size_t count);
static void do_readahead(int fd, char *name)
{
int rc;
// Since including fcntl.h doesn't give us the wrapper, use the syscall.
// 32 bits takes LO/HI offset (we don't care about endianness of 0).
if (sizeof(long) == 4) rc = syscall(__NR_readahead, fd, 0, 0, INT_MAX);
else rc = syscall(__NR_readahead, fd, 0, INT_MAX);
if (rc) perror_msg("readahead: %s", name);
if (readahead(fd, 0, INT_MAX)) perror_msg("readahead: %s", name);
}
void readahead_main(void)