On Sun, 9 Jul 2023 13:29:58 -0700
Andrew Hewus Fresh <[email protected]> wrote:
> + case SYS_truncate:
> + {
> + const char * path = va_arg(args, const char *);
> + off_t length = va_arg(args, off_t);
> + ret = truncate(path, length);
> + }
> + break;
I prefer braces like this,
case SYS_truncate: {
...
break;
}
In my opinion, all va_arg()s should look like
off_t length = (off_t)va_arg(args, long);
because perl passes every argument as long (from pp_syscall in
pp_sys.c). I worry that va_arg(args, off_t) would act strangely
on platforms with 32-bit long and 64-bit off_t. Only a few syscalls
have off_t arguments, and these few calls are almost useless in Perl,
so this might not affect real programs.
How to pread($fd, $buf, 4, 16)?
1. syscall(169, $fd, $buf, 4, 0, 16)
2. syscall(169, $fd, $buf, 4, 0, 0, 16)
3. syscall(169, $fd, $buf, 4, 16, 0)
4. syscall(169, $fd, $buf, 4, 0, 16, 0)
5. syscall(169, $fd, $buf, 4, 16)
If va_args(args, off_t) takes 2 longs, then pick line 1 if big-endian,
or line 3 if little-endian. If it skips a 3rd long for alignment,
then pick line 2 or 4. If it takes 1 long, then pick line 5.
If we (off_t)va_args(args, long), then it always takes 1 long, so
every platform picks line 5, but the offset must fit in a long.
The syscalls with off_t are
void *mmap(void *, size_t, int, int, int, off_t);
void *mquery(void *, size_t, int, int, int, off_t);
off_t lseek(int, off_t, int);
int truncate(const char *, off_t);
int ftruncate(int, off_t);
ssize_t pread(int, void *, size_t, off_t);
ssize_t pwrite(int, const void *, size_t, off_t);
ssize_t preadv(int, const struct iovec *, int, off_t);
ssize_t pwritev(int, const struct iovec *, int, off_t);
syscall(SYS_lseek, @args) would truncate its return from off_t to
long, but that is fine, because everyone should use Perl's sysseek.
POSIX::2008 in CPAN looks like a better way to call pread.