mirror of
https://codeberg.org/landley/toybox.git
synced 2026-01-26 14:13:25 +00:00
Fix macOS posix_fallocate().
The fallback ftruncate() call was wrong, because posix_fallocate()
will never shrink a file, but ftruncate() will. Also, if that failed,
we didn't turn errno into a return code.
Also the fcntl() was wrong. In my defense, here's the documentation:
The position modes (fst_posmode) for the F_PREALLOCATE command indicate
how to use the offset field. The modes are as follows:
F_PEOFPOSMODE Allocate from the physical end of file. In this
case, fst_length indicates the number of newly
allocated bytes desired.
F_VOLPOSMODE Allocate from the volume offset.
I think the new version is right, though it's obviously a lot more
conservative than the real posix_fallocate(), but I don't think
it's possible to do better?
Also add tests for some of the prior failures.
Fixes #472.
This commit is contained in:
parent
20d5dade3a
commit
d908031520
@ -380,18 +380,19 @@ int mknodat(int dirfd, const char *path, mode_t mode, dev_t dev)
|
||||
}
|
||||
|
||||
// As of 10.15, macOS offers an fcntl F_PREALLOCATE rather than fallocate()
|
||||
// or posix_fallocate() calls.
|
||||
// or posix_fallocate() calls. The fcntl only (as the name implies)
|
||||
// pre-allocates, so we also need to ftruncate() afterwards.
|
||||
int posix_fallocate(int fd, off_t offset, off_t length)
|
||||
{
|
||||
int e = errno, result;
|
||||
int e = errno, result = 0;
|
||||
fstore_t f;
|
||||
|
||||
f.fst_flags = F_ALLOCATEALL;
|
||||
f.fst_posmode = F_PEOFPOSMODE;
|
||||
f.fst_offset = offset;
|
||||
f.fst_length = length;
|
||||
f.fst_offset = 0;
|
||||
f.fst_length = offset + length;
|
||||
if (fcntl(fd, F_PREALLOCATE, &f) == -1) result = errno;
|
||||
else result = ftruncate(fd, length);
|
||||
else if (ftruncate(fd, maxof(offset+length, fdlength(fd)))) result = errno;
|
||||
errno = e;
|
||||
return result;
|
||||
}
|
||||
|
||||
8
tests/fallocate.test
Executable file
8
tests/fallocate.test
Executable file
@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
#testing "name" "command" "result" "infile" "stdin"
|
||||
|
||||
rm -f foo
|
||||
testcmd 'simple' '-l 123 foo && stat -c %s foo' '123\n' '' ''
|
||||
testcmd 'shorter' '-l 12 foo && stat -c %s foo' '123\n' '' ''
|
||||
testcmd 'longer' '-o 200 -l 12 foo && stat -c %s foo' '212\n' '' ''
|
||||
Loading…
x
Reference in New Issue
Block a user