mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-28 15:28:30 +00:00
Improve docs of more system calls
This change also found a few POSIX compliance bugs with errnos. Another bug was discovered where, on Windows, pread() and pwrite() could modify the file position in cases where ReadFile() returned an error e.g. when seeking past the end of file. We also have more tests!
This commit is contained in:
parent
af24c19db3
commit
ccbae7799e
39 changed files with 589 additions and 175 deletions
|
@ -18,31 +18,65 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Changes size of file.
|
||||
* Changes size of open file.
|
||||
*
|
||||
* If the file size is increased, the extended area shall appear as if
|
||||
* it were zero-filled. If your file size is decreased, the extra data
|
||||
* shall be lost.
|
||||
*
|
||||
* This function never changes the file position. This is true even if
|
||||
* ftruncate() causes the position to become beyond the end of file in
|
||||
* which case, the rules described in the lseek() documentation apply.
|
||||
*
|
||||
* Some operating systems implement an optimization, where `length` is
|
||||
* treated as a logical size and the requested physical space won't be
|
||||
* allocated until non-zero values get written into it. Our tests show
|
||||
* this happens on Linux (usually with 4096 byte granularity), FreeBSD
|
||||
* (which favors 512-byte granularity), and MacOS (prefers 4096 bytes)
|
||||
* however Windows, OpenBSD, and NetBSD always reserve physical space.
|
||||
* This may be inspected using fstat() and consulting stat::st_blocks.
|
||||
*
|
||||
* @param fd must be open for writing
|
||||
* @param length may be greater than current current file size, in which
|
||||
* case System V guarantees it'll be zero'd but Windows NT doesn't;
|
||||
* since the prior extends logically and the latter physically
|
||||
* @param length may be greater than current current file size
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @raise EINVAL if `length` is negative
|
||||
* @raise EINTR if signal was delivered instead
|
||||
* @raise EIO if a low-level i/o error happened
|
||||
* @raise EFBIG or EINVAL if `length` is too huge
|
||||
* @raise ENOTSUP if `fd` is a zip file descriptor
|
||||
* @raise EBADF if `fd` isn't an open file descriptor
|
||||
* @raise EINVAL if `fd` is a non-file, e.g. pipe, socket
|
||||
* @raise EINVAL if `fd` wasn't opened in a writeable mode
|
||||
* @raise ENOSYS on bare metal
|
||||
* @see truncate()
|
||||
* @asyncsignalsafe
|
||||
* @threadsafe
|
||||
*/
|
||||
int ftruncate(int fd, int64_t length) {
|
||||
int rc;
|
||||
if (fd < 0) {
|
||||
rc = einval();
|
||||
rc = ebadf();
|
||||
} else if (__isfdkind(fd, kFdZip)) {
|
||||
rc = enotsup();
|
||||
} else if (IsMetal()) {
|
||||
rc = enosys();
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_ftruncate(fd, length, length);
|
||||
} else {
|
||||
if (fd >= g_fds.n) rc = ebadf();
|
||||
if (IsNetbsd() && rc == -1 && errno == ENOSPC) {
|
||||
errno = EFBIG; // POSIX doesn't specify ENOSPC for ftruncate()
|
||||
}
|
||||
} else if (__isfdopen(fd)) {
|
||||
rc = sys_ftruncate_nt(g_fds.p[fd].handle, length);
|
||||
} else {
|
||||
rc = ebadf();
|
||||
}
|
||||
STRACE("ftruncate(%d, %'ld) → %d% m", fd, length, rc);
|
||||
return rc;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue