diff --git a/build/config.mk b/build/config.mk index 753ebb0ae..e7e2b08ab 100644 --- a/build/config.mk +++ b/build/config.mk @@ -152,6 +152,10 @@ CONFIG_CCFLAGS += \ -fomit-frame-pointer \ -momit-leaf-frame-pointer \ -foptimize-sibling-calls +CONFIG_OFLAGS += \ + -g0 +CONFIG_LDFLAGS += \ + -S TARGET_ARCH ?= \ -msse3 PYFLAGS += \ @@ -180,6 +184,10 @@ CONFIG_CPPFLAGS += \ -DSUPPORT_VECTOR=1 DEFAULT_COPTS += \ -mred-zone +CONFIG_OFLAGS += \ + -g0 +CONFIG_LDFLAGS += \ + -S CONFIG_CCFLAGS += \ -Os \ -fno-align-functions \ @@ -212,6 +220,10 @@ CONFIG_CPPFLAGS += \ -DSUPPORT_VECTOR=113 DEFAULT_COPTS += \ -mred-zone +CONFIG_OFLAGS += \ + -g0 +CONFIG_LDFLAGS += \ + -S CONFIG_CCFLAGS += \ -Os \ -fno-align-functions \ @@ -249,6 +261,10 @@ CONFIG_CCFLAGS += \ -fno-align-jumps \ -fno-align-labels \ -fno-align-loops +CONFIG_OFLAGS += \ + -g0 +CONFIG_LDFLAGS += \ + -S TARGET_ARCH ?= \ -msse3 endif @@ -278,6 +294,10 @@ CONFIG_CCFLAGS += \ -fno-align-jumps \ -fno-align-labels \ -fno-align-loops +CONFIG_OFLAGS += \ + -g0 +CONFIG_LDFLAGS += \ + -S TARGET_ARCH ?= \ -msse3 endif diff --git a/examples/clock_getres.c b/examples/clock_getres.c new file mode 100644 index 000000000..e40a47d54 --- /dev/null +++ b/examples/clock_getres.c @@ -0,0 +1,56 @@ +#if 0 +/*─────────────────────────────────────────────────────────────────╗ +│ To the extent possible under law, Justine Tunney has waived │ +│ all copyright and related or neighboring rights to this file, │ +│ as it is written in the following disclaimers: │ +│ • http://unlicense.org/ │ +│ • http://creativecommons.org/publicdomain/zero/1.0/ │ +╚─────────────────────────────────────────────────────────────────*/ +#endif +#include "libc/calls/struct/timespec.h" +#include "libc/errno.h" +#include "libc/intrin/describeflags.internal.h" +#include "libc/intrin/kprintf.h" +#include "libc/str/str.h" +#include "libc/sysv/consts/clock.h" + +int n; +int shown[64]; + +void show(int clock) { + int i; + struct timespec ts; + if (clock == 127) return; + for (i = 0; i < n; ++i) { + if (shown[i] == clock) { + return; + } + } + shown[n++] = clock; + if (clock_getres(clock, &ts) != -1) { + kprintf("%s %'ld ns\n", DescribeClockName(clock), _timespec_tonanos(ts)); + } else { + kprintf("%s %s\n", DescribeClockName(clock), _strerrno(errno)); + } +} + +int main(int argc, char *argv[]) { + show(CLOCK_REALTIME); + show(CLOCK_REALTIME_FAST); + show(CLOCK_REALTIME_PRECISE); + show(CLOCK_MONOTONIC); + show(CLOCK_MONOTONIC_RAW); + show(CLOCK_MONOTONIC_FAST); + show(CLOCK_MONOTONIC_PRECISE); + show(CLOCK_PROCESS_CPUTIME_ID); + show(CLOCK_THREAD_CPUTIME_ID); + show(CLOCK_PROF); + show(CLOCK_BOOTTIME); + show(CLOCK_REALTIME_ALARM); + show(CLOCK_BOOTTIME_ALARM); + show(CLOCK_TAI); + show(CLOCK_UPTIME); + show(CLOCK_UPTIME_PRECISE); + show(CLOCK_UPTIME_FAST); + show(CLOCK_SECOND); +} diff --git a/libc/assert.h b/libc/assert.h index ce6933b2a..5850a574f 100644 --- a/libc/assert.h +++ b/libc/assert.h @@ -7,16 +7,29 @@ extern bool __assert_disable; void __assert_fail(const char *, const char *, int) hidden relegated; #ifdef NDEBUG -#define assert(EXPR) ((void)0) +#define assert(x) ((void)0) #else -#define assert(EXPR) \ - ((void)((EXPR) || (__assert_fail(#EXPR, __FILE__, __LINE__), 0))) +#define assert(x) ((void)((x) || (__assert_fail(#x, __FILE__, __LINE__), 0))) #endif #ifndef __cplusplus #define static_assert _Static_assert #endif +#define _unassert(x) \ + do { \ + if (__builtin_expect(!(x), 0)) { \ + unreachable; \ + } \ + } while (0) + +#define _npassert(x) \ + do { \ + if (__builtin_expect(!(x), 0)) { \ + notpossible; \ + } \ + } while (0) + COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* COSMOPOLITAN_LIBC_ASSERT_H_ */ diff --git a/libc/calls/chdir-nt.c b/libc/calls/chdir-nt.c index 75a3e0ad0..18e1bc0f0 100644 --- a/libc/calls/chdir-nt.c +++ b/libc/calls/chdir-nt.c @@ -26,35 +26,36 @@ #include "libc/nt/synchronization.h" #include "libc/sysv/errfuns.h" -textwindows int sys_chdir_nt(const char *path) { +textwindows int sys_chdir_nt_impl(char16_t path[hasatleast PATH_MAX], + uint32_t len) { uint32_t n; - int e, ms, err, len; - char16_t path16[PATH_MAX], var[4]; - if ((len = __mkntpath(path, path16)) == -1) return -1; - if (!len) return enoent(); - if (len && path16[len - 1] != u'\\') { + int e, ms, err; + char16_t var[4]; + + if (len && path[len - 1] != u'\\') { if (len + 2 > PATH_MAX) return enametoolong(); - path16[len + 0] = u'\\'; - path16[len + 1] = u'\0'; + path[len + 0] = u'\\'; + path[len + 1] = u'\0'; } + /* * chdir() seems flaky on windows 7 * in a similar way to rmdir() sigh */ for (err = errno, ms = 1;; ms *= 2) { - if (SetCurrentDirectory(path16)) { + if (SetCurrentDirectory(path)) { /* * Now we need to set a magic environment variable. */ - if ((n = GetCurrentDirectory(ARRAYLEN(path16), path16))) { - if (n < ARRAYLEN(path16)) { - if (!((path16[0] == '/' && path16[1] == '/') || - (path16[0] == '\\' && path16[1] == '\\'))) { + if ((n = GetCurrentDirectory(PATH_MAX, path))) { + if (n < PATH_MAX) { + if (!((path[0] == '/' && path[1] == '/') || + (path[0] == '\\' && path[1] == '\\'))) { var[0] = '='; - var[1] = path16[0]; + var[1] = path[0]; var[2] = ':'; var[3] = 0; - if (!SetEnvironmentVariable(var, path16)) { + if (!SetEnvironmentVariable(var, path)) { return __winerr(); } } @@ -77,5 +78,13 @@ textwindows int sys_chdir_nt(const char *path) { } } } - return __fix_enotdir(-1, path16); + return __fix_enotdir(-1, path); +} + +textwindows int sys_chdir_nt(const char *path) { + int len; + char16_t path16[PATH_MAX]; + if ((len = __mkntpath(path, path16)) == -1) return -1; + if (!len) return enoent(); + return sys_chdir_nt_impl(path16, len); } diff --git a/libc/calls/dup-nt.c b/libc/calls/dup-nt.c index 598056055..d6add874f 100644 --- a/libc/calls/dup-nt.c +++ b/libc/calls/dup-nt.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/assert.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" #include "libc/calls/state.internal.h" @@ -32,10 +33,9 @@ */ textwindows int sys_dup_nt(int oldfd, int newfd, int flags, int start) { int64_t rc, proc, handle; - - // validate the api usage - if (oldfd < 0) return ebadf(); - if (flags & ~O_CLOEXEC) return einval(); + _unassert(oldfd >= 0); + _unassert(newfd >= -1); + _unassert(!(flags & ~O_CLOEXEC)); __fds_lock(); diff --git a/libc/calls/dup3-sysv.c b/libc/calls/dup3-sysv.c index 7ac62b1fe..842284992 100644 --- a/libc/calls/dup3-sysv.c +++ b/libc/calls/dup3-sysv.c @@ -16,41 +16,52 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/intrin/strace.internal.h" +#include "libc/assert.h" #include "libc/calls/syscall-sysv.internal.h" #include "libc/calls/syscall_support-sysv.internal.h" #include "libc/dce.h" #include "libc/errno.h" +#include "libc/intrin/strace.internal.h" #include "libc/sysv/consts/o.h" #include "libc/sysv/errfuns.h" +#include "libc/thread/thread.h" #define F_DUP2FD 10 #define F_DUP2FD_CLOEXEC 18 -int32_t sys_dup3(int32_t oldfd, int32_t newfd, int flags) { - static bool once; - static bool demodernize; - int olderr, how, fd; - if (!once) { - olderr = errno; - fd = __sys_dup3(oldfd, newfd, flags); - if (fd == -1 && errno == ENOSYS) { - STRACE("demodernizing %s() due to %s", "dup3", "RHEL5:CVE-2010-3301"); - demodernize = true; - once = true; - errno = olderr; - } else { - once = true; - return fd; - } - } else if (!demodernize) { - return __sys_dup3(oldfd, newfd, flags); +static struct Dup3 { + pthread_once_t once; + bool demodernize; +} g_dup3; + +static void sys_dup3_test(void) { + int e = errno; + __sys_dup3(-1, -1, 0); + if ((g_dup3.demodernize = errno == ENOSYS)) { + STRACE("demodernizing %s() due to %s", "dup3", "ENOSYS"); } - if (oldfd == newfd) return einval(); - if (flags & ~O_CLOEXEC) return einval(); + errno = e; +} + +int32_t sys_dup3(int32_t oldfd, int32_t newfd, int flags) { + int how; + _unassert(oldfd >= 0); + _unassert(newfd >= 0); + _unassert(!(flags & ~O_CLOEXEC)); + if (IsFreebsd()) { - how = flags & O_CLOEXEC ? F_DUP2FD_CLOEXEC : F_DUP2FD; + if (flags & O_CLOEXEC) { + how = F_DUP2FD_CLOEXEC; + } else { + how = F_DUP2FD; + } return __sys_fcntl(oldfd, how, newfd); + } + + pthread_once(&g_dup3.once, sys_dup3_test); + + if (!g_dup3.demodernize) { + return __sys_dup3(oldfd, newfd, flags); } else { return __fixupnewfd(sys_dup2(oldfd, newfd), flags); } diff --git a/libc/calls/dup3.c b/libc/calls/dup3.c index 1f487f096..c06b175d7 100644 --- a/libc/calls/dup3.c +++ b/libc/calls/dup3.c @@ -18,10 +18,11 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #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/intrin/strace.internal.h" +#include "libc/sysv/consts/o.h" #include "libc/sysv/errfuns.h" /** @@ -46,14 +47,14 @@ */ int dup3(int oldfd, int newfd, int flags) { int rc; - if (__isfdkind(oldfd, kFdZip)) { + if (oldfd == newfd || (flags & ~O_CLOEXEC)) { + rc = einval(); // NetBSD doesn't do this + } else if (oldfd < 0 || newfd < 0) { + rc = ebadf(); + } else if (__isfdkind(oldfd, kFdZip)) { rc = eopnotsupp(); - } else if (oldfd == newfd) { - rc = einval(); } else if (!IsWindows()) { rc = sys_dup3(oldfd, newfd, flags); - } else if (newfd < 0) { - rc = ebadf(); } else { rc = sys_dup_nt(oldfd, newfd, flags, -1); } diff --git a/libc/calls/fchdir-nt.c b/libc/calls/fchdir-nt.c index f01d804b3..0a5956de3 100644 --- a/libc/calls/fchdir-nt.c +++ b/libc/calls/fchdir-nt.c @@ -23,20 +23,12 @@ #include "libc/nt/files.h" #include "libc/sysv/errfuns.h" +int sys_chdir_nt_impl(char16_t[hasatleast PATH_MAX], uint32_t); + textwindows int sys_fchdir_nt(int dirfd) { - uint32_t len; char16_t dir[PATH_MAX]; if (!__isfdkind(dirfd, kFdFile)) return ebadf(); - len = GetFinalPathNameByHandle(g_fds.p[dirfd].handle, dir, ARRAYLEN(dir), - kNtFileNameNormalized | kNtVolumeNameDos); - if (len + 1 + 1 > ARRAYLEN(dir)) return enametoolong(); - if (dir[len - 1] != u'\\') { - dir[len + 0] = u'\\'; - dir[len + 1] = u'\0'; - } - if (SetCurrentDirectory(dir)) { - return 0; - } else { - return __winerr(); - } + return sys_chdir_nt_impl( + dir, GetFinalPathNameByHandle(g_fds.p[dirfd].handle, dir, ARRAYLEN(dir), + kNtFileNameNormalized | kNtVolumeNameDos)); } diff --git a/libc/calls/fcntl-nt.c b/libc/calls/fcntl-nt.c index 9ddd29789..10a7a83ad 100644 --- a/libc/calls/fcntl-nt.c +++ b/libc/calls/fcntl-nt.c @@ -24,42 +24,47 @@ #include "libc/calls/syscall_support-nt.internal.h" #include "libc/calls/wincrash.internal.h" #include "libc/errno.h" -#include "libc/intrin/cmpxchg.h" -#include "libc/macros.internal.h" -#include "libc/nt/createfile.h" -#include "libc/nt/enum/accessmask.h" -#include "libc/nt/enum/fileflagandattributes.h" +#include "libc/intrin/weaken.h" +#include "libc/log/backtrace.internal.h" #include "libc/nt/enum/filelockflags.h" -#include "libc/nt/enum/filesharemode.h" -#include "libc/nt/enum/formatmessageflags.h" #include "libc/nt/errors.h" #include "libc/nt/files.h" -#include "libc/nt/process.h" #include "libc/nt/runtime.h" #include "libc/nt/struct/byhandlefileinformation.h" #include "libc/nt/struct/overlapped.h" -#include "libc/nt/synchronization.h" #include "libc/sysv/consts/f.h" #include "libc/sysv/consts/fd.h" #include "libc/sysv/consts/o.h" #include "libc/sysv/errfuns.h" +bool __force_sqlite_to_work_until_we_can_fix_it; + static textwindows int sys_fcntl_nt_dupfd(int fd, int cmd, int start) { + if (start < 0) return einval(); return sys_dup_nt(fd, -1, (cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0), start); } static textwindows int sys_fcntl_nt_lock(struct Fd *f, int cmd, uintptr_t arg) { + int e; struct flock *l; uint32_t flags, err; - struct NtOverlapped ov; int64_t pos, off, len, size; struct NtByHandleFileInformation info; - if (!GetFileInformationByHandle(f->handle, &info)) return __winerr(); - if (!SetFilePointerEx(f->handle, 0, &pos, SEEK_CUR)) return __winerr(); + + if (!GetFileInformationByHandle(f->handle, &info)) { + return __winerr(); + } + + pos = 0; + if (!SetFilePointerEx(f->handle, 0, &pos, SEEK_CUR)) { + return __winerr(); + } + l = (struct flock *)arg; len = l->l_len; off = l->l_start; size = (uint64_t)info.nFileSizeHigh << 32 | info.nFileSizeLow; + switch (l->l_whence) { case SEEK_SET: break; @@ -72,37 +77,60 @@ static textwindows int sys_fcntl_nt_lock(struct Fd *f, int cmd, uintptr_t arg) { default: return einval(); } - if (!len) len = size - off; - if (off < 0 || len < 0) return einval(); - _offset2overlap(f->handle, off, &ov); - if (l->l_type == F_RDLCK || l->l_type == F_WRLCK) { - flags = 0; - if (cmd == F_SETLK) flags |= kNtLockfileFailImmediately; - /* TODO: How can we make SQLite locks on Windows to work? */ - /* if (l->l_type == F_WRLCK) flags |= kNtLockfileExclusiveLock; */ - if (LockFileEx(f->handle, flags, 0, len, len >> 32, &ov)) { - return 0; - } else { - err = GetLastError(); - if (err == kNtErrorLockViolation) err = EAGAIN; - errno = err; - return -1; - } - } else if (l->l_type == F_UNLCK) { - if (UnlockFileEx(f->handle, 0, len, len >> 32, &ov)) { - return 0; - } else { - err = GetLastError(); - if (err == kNtErrorNotLocked) { - return 0; - } else { - errno = err; - return -1; - } - } - } else { + + if (!len) { + len = size - off; + } + + if (off < 0 || len < 0) { return einval(); } + + bool32 ok; + struct NtOverlapped ov = {.hEvent = f->handle, + .Pointer = (void *)(uintptr_t)off}; + + if (l->l_type == F_RDLCK || l->l_type == F_WRLCK) { + flags = 0; + if (cmd != F_SETLKW) { + flags |= kNtLockfileFailImmediately; + } + if (l->l_type == F_WRLCK) { + flags |= kNtLockfileExclusiveLock; + } + ok = LockFileEx(f->handle, flags, 0, len, len >> 32, &ov); + if (cmd == F_GETLK) { + if (ok) { + l->l_type = F_UNLCK; + if (!UnlockFileEx(f->handle, 0, len, len >> 32, &ov)) { + notpossible; + } + } else { + l->l_pid = -1; + ok = true; + } + } + if (ok || __force_sqlite_to_work_until_we_can_fix_it) { + return 0; + } else { + return -1; + } + } + + if (l->l_type == F_UNLCK) { + if (cmd == F_GETLK) return einval(); + e = errno; + if (UnlockFileEx(f->handle, 0, len, len >> 32, &ov)) { + return 0; + } else if (errno == ENOLCK) { + errno = e; + return 0; + } else { + return 0; + } + } + + return einval(); } textwindows int sys_fcntl_nt(int fd, int cmd, uintptr_t arg) { diff --git a/libc/calls/fcntl-sysv.c b/libc/calls/fcntl-sysv.c index 66b398274..2cfbf8d0c 100644 --- a/libc/calls/fcntl-sysv.c +++ b/libc/calls/fcntl-sysv.c @@ -20,12 +20,14 @@ #include "libc/calls/syscall-sysv.internal.h" #include "libc/calls/syscall_support-sysv.internal.h" #include "libc/dce.h" +#include "libc/errno.h" #include "libc/intrin/asan.internal.h" #include "libc/sysv/consts/f.h" +#include "libc/sysv/consts/o.h" #include "libc/sysv/errfuns.h" int sys_fcntl(int fd, int cmd, uintptr_t arg) { - int rc; + int e, rc; bool islock; if ((islock = cmd == F_GETLK || // cmd == F_SETLK || // @@ -37,9 +39,13 @@ int sys_fcntl(int fd, int cmd, uintptr_t arg) { } cosmo2flock(arg); } + e = errno; rc = __sys_fcntl(fd, cmd, arg); if (islock) { flock2cosmo(arg); + } else if (rc == -1 && cmd == F_DUPFD_CLOEXEC && errno == EINVAL) { + errno = e; + rc = __fixupnewfd(__sys_fcntl(fd, F_DUPFD, arg), O_CLOEXEC); } return rc; } diff --git a/libc/calls/fcntl.c b/libc/calls/fcntl.c index 7bc3d0a04..62bb12415 100644 --- a/libc/calls/fcntl.c +++ b/libc/calls/fcntl.c @@ -37,11 +37,9 @@ * CHECK_GE((newfd = fcntl(oldfd, F_DUPFD, 3)), 3); * CHECK_GE((newfd = fcntl(oldfd, F_DUPFD_CLOEXEC, 3)), 3); * - * This function implements POSIX Advisory Locks, e.g. - * - * CHECK_NE(-1, fcntl(zfd, F_SETLKW, &(struct flock){F_WRLCK})); - * // ... - * CHECK_NE(-1, fcntl(zfd, F_SETLK, &(struct flock){F_UNLCK})); + * This function implements POSIX Advisory Locks, which let independent + * processes (and on Windows, threads too!) read/write lock byte ranges + * of files. See `test/libc/calls/lock_test.c` for an example. * * Please be warned that locks currently do nothing on Windows since * figuring out how to polyfill them correctly is a work in progress. diff --git a/libc/calls/fixupnewfd.c b/libc/calls/fixupnewfd.c index 93911893a..36f234f79 100644 --- a/libc/calls/fixupnewfd.c +++ b/libc/calls/fixupnewfd.c @@ -16,19 +16,19 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/assert.h" #include "libc/calls/syscall-sysv.internal.h" +#include "libc/calls/syscall_support-sysv.internal.h" #include "libc/sysv/consts/f.h" #include "libc/sysv/consts/fd.h" #include "libc/sysv/consts/o.h" -/** - * Applies file descriptor fixups on XNU or old Linux. - * @see __fixupnewsockfd() for socket file descriptors - */ +// Applies file descriptor fixups on XNU or old Linux. +// See __fixupnewsockfd() for socket file descriptors. int __fixupnewfd(int fd, int flags) { if (fd != -1) { if (flags & O_CLOEXEC) { - __sys_fcntl(fd, F_SETFD, FD_CLOEXEC); + _npassert(!__sys_fcntl(fd, F_SETFD, FD_CLOEXEC)); } } return fd; diff --git a/libc/calls/flock-nt.c b/libc/calls/flock-nt.c index 764905d20..4a04890d5 100644 --- a/libc/calls/flock-nt.c +++ b/libc/calls/flock-nt.c @@ -17,28 +17,49 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/internal.h" +#include "libc/calls/struct/fd.internal.h" +#include "libc/calls/syscall-nt.internal.h" #include "libc/calls/syscall_support-nt.internal.h" +#include "libc/nt/enum/filelockflags.h" #include "libc/nt/files.h" -#include "libc/nt/runtime.h" #include "libc/nt/struct/byhandlefileinformation.h" #include "libc/nt/struct/overlapped.h" -#include "libc/str/str.h" -#include "libc/sysv/consts/lock.h" #include "libc/sysv/errfuns.h" +#define _LOCK_SH 0 +#define _LOCK_EX kNtLockfileExclusiveLock +#define _LOCK_NB kNtLockfileFailImmediately +#define _LOCK_UN 8 + textwindows int sys_flock_nt(int fd, int op) { - struct NtOverlapped ov; + int64_t h; struct NtByHandleFileInformation info; if (!__isfdkind(fd, kFdFile)) return ebadf(); - bzero(&ov, sizeof(ov)); - if (GetFileInformationByHandle(g_fds.p[fd].handle, &info) && - ((!(op & LOCK_UN) && - LockFileEx(g_fds.p[fd].handle, op, 0, info.nFileSizeLow, - info.nFileSizeHigh, &ov)) || - ((op & LOCK_UN) && UnlockFileEx(g_fds.p[fd].handle, 0, info.nFileSizeLow, - info.nFileSizeHigh, &ov)))) { - return 0; - } else { + h = g_fds.p[fd].handle; + struct NtOverlapped ov = {.hEvent = h}; + + if (!GetFileInformationByHandle(h, &info)) { return __winerr(); } + + if (op & _LOCK_UN) { + if (op & ~_LOCK_UN) { + return einval(); + } + if (UnlockFileEx(h, 0, info.nFileSizeLow, info.nFileSizeHigh, &ov)) { + return 0; + } else { + return -1; + } + } + + if (op & ~(_LOCK_SH | _LOCK_EX | _LOCK_NB)) { + return einval(); + } + + if (LockFileEx(h, op, 0, info.nFileSizeLow, info.nFileSizeHigh, &ov)) { + return 0; + } else { + return -1; + } } diff --git a/libc/calls/pipe2-sysv.c b/libc/calls/pipe2-sysv.c index 526917b8b..9f890e036 100644 --- a/libc/calls/pipe2-sysv.c +++ b/libc/calls/pipe2-sysv.c @@ -24,16 +24,18 @@ #include "libc/sysv/errfuns.h" int32_t sys_pipe2(int pipefd[hasatleast 2], unsigned flags) { - int rc, olderr; + int e, rc; if (!flags) goto OldSkool; - olderr = errno; + e = errno; rc = __sys_pipe2(pipefd, flags); if (rc == -1 && errno == ENOSYS) { - errno = olderr; + errno = e; OldSkool: if ((rc = sys_pipe(pipefd)) != -1) { - __fixupnewfd(pipefd[0], flags); - __fixupnewfd(pipefd[1], flags); + if (flags) { + __fixupnewfd(pipefd[0], flags); + __fixupnewfd(pipefd[1], flags); + } } } return rc; diff --git a/libc/calls/pread.c b/libc/calls/pread.c index 951f2f05a..6b79f8315 100644 --- a/libc/calls/pread.c +++ b/libc/calls/pread.c @@ -46,8 +46,11 @@ */ ssize_t pread(int fd, void *buf, size_t size, int64_t offset) { ssize_t rc; - if (fd == -1 || offset < 0) return einval(); - if (IsAsan() && !__asan_is_valid(buf, size)) { + if (offset < 0) { + rc = einval(); + } else if (fd < 0) { + rc = ebadf(); + } else if (IsAsan() && !__asan_is_valid(buf, size)) { rc = efault(); } else if (__isfdkind(fd, kFdZip)) { rc = _weaken(__zipos_read)( @@ -60,7 +63,7 @@ ssize_t pread(int fd, void *buf, size_t size, int64_t offset) { } else { rc = ebadf(); } - assert(rc == -1 || (size_t)rc <= size); + _npassert(rc == -1 || (size_t)rc <= size); DATATRACE("pread(%d, [%#.*hhs%s], %'zu, %'zd) → %'zd% m", fd, MAX(0, MIN(40, rc)), buf, rc > 40 ? "..." : "", size, offset, rc); return rc; diff --git a/libc/calls/preadv.c b/libc/calls/preadv.c index 93b7a4b4f..2d85c355d 100644 --- a/libc/calls/preadv.c +++ b/libc/calls/preadv.c @@ -16,91 +16,104 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/calls/calls.h" +#include "libc/assert.h" #include "libc/calls/internal.h" -#include "libc/calls/state.internal.h" #include "libc/calls/struct/iovec.h" #include "libc/calls/struct/iovec.internal.h" +#include "libc/calls/struct/sigset.h" +#include "libc/calls/struct/sigset.internal.h" #include "libc/calls/syscall-sysv.internal.h" +#include "libc/calls/syscall_support-sysv.internal.h" #include "libc/dce.h" #include "libc/errno.h" #include "libc/intrin/asan.internal.h" -#include "libc/intrin/bits.h" -#include "libc/intrin/describeflags.internal.h" #include "libc/intrin/kprintf.h" #include "libc/intrin/likely.h" #include "libc/intrin/strace.internal.h" #include "libc/intrin/weaken.h" -#include "libc/macros.internal.h" -#include "libc/sysv/consts/iov.h" +#include "libc/sysv/consts/sig.h" #include "libc/sysv/errfuns.h" #include "libc/zipos/zipos.internal.h" static ssize_t Preadv(int fd, struct iovec *iov, int iovlen, int64_t off) { - static bool once, demodernize; - int i, err; - ssize_t rc; - size_t got, toto; + int e, i; + size_t got; + bool masked; + ssize_t rc, toto; + sigset_t mask, oldmask; + + if (fd < 0) { + return ebadf(); + } + + if (iovlen < 0) { + return einval(); + } + + if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) { + return efault(); + } - if (fd < 0) return einval(); - if (iovlen < 0) return einval(); - if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) return efault(); if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) { return _weaken(__zipos_read)( (struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, off); - } else if (IsWindows()) { + } + + if (IsMetal()) { + return espipe(); // must be serial or console if not zipos + } + + if (IsWindows()) { if (fd < g_fds.n) { return sys_read_nt(g_fds.p + fd, iov, iovlen, off); } else { return ebadf(); } - } else if (IsMetal()) { - return enosys(); } - if (iovlen == 1) { - return sys_pread(fd, iov[0].iov_base, iov[0].iov_len, off, off); - } - - /* - * NT, 2018-era XNU, and 2007-era Linux don't support this system call - */ - if (!__vforked && !once) { - err = errno; - rc = sys_preadv(fd, iov, iovlen, off, off); - if (rc == -1 && errno == ENOSYS) { - errno = err; - once = true; - demodernize = true; - STRACE("demodernizing %s() due to %s", "preadv", "ENOSYS"); - } else { - once = true; - return rc; - } - } - - if (!demodernize) { - return sys_preadv(fd, iov, iovlen, off, off); + while (iovlen && !iov->iov_len) { + --iovlen; + ++iov; } if (!iovlen) { - return sys_pread(fd, NULL, 0, off, off); + return sys_pread(fd, 0, 0, off, off); } + if (iovlen == 1) { + return sys_pread(fd, iov->iov_base, iov->iov_len, off, off); + } + + e = errno; + rc = sys_preadv(fd, iov, iovlen, off, off); + if (rc != -1 || errno != ENOSYS) return rc; + errno = e; + for (toto = i = 0; i < iovlen; ++i) { rc = sys_pread(fd, iov[i].iov_base, iov[i].iov_len, off, off); if (rc == -1) { - if (toto && (errno == EINTR || errno == EAGAIN)) { - return toto; - } else { - return -1; + if (!toto) { + toto = -1; } + break; } + got = rc; toto += got; + off += got; if (got != iov[i].iov_len) { break; } + + if (!masked) { + sigfillset(&mask); + _npassert(!sys_sigprocmask(SIG_SETMASK, &mask, &oldmask)); + masked = true; + } + } + + if (masked) { + _npassert(!sys_sigprocmask(SIG_SETMASK, &oldmask, 0)); } return toto; diff --git a/libc/calls/pwrite.c b/libc/calls/pwrite.c index 779ab96a4..2d9c7d561 100644 --- a/libc/calls/pwrite.c +++ b/libc/calls/pwrite.c @@ -19,12 +19,12 @@ #include "libc/assert.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" -#include "libc/intrin/strace.internal.h" #include "libc/calls/struct/iovec.h" #include "libc/calls/struct/iovec.internal.h" #include "libc/calls/syscall-sysv.internal.h" #include "libc/dce.h" #include "libc/intrin/asan.internal.h" +#include "libc/intrin/strace.internal.h" #include "libc/macros.internal.h" #include "libc/sysv/errfuns.h" @@ -46,9 +46,11 @@ ssize_t pwrite(int fd, const void *buf, size_t size, int64_t offset) { ssize_t rc; size_t wrote; - if (fd == -1 || offset < 0) return einval(); - size = MIN(size, 0x7ffff000); - if (IsAsan() && !__asan_is_valid(buf, size)) { + if (offset < 0) { + rc = einval(); + } else if (fd == -1) { + rc = ebadf(); + } else if (IsAsan() && !__asan_is_valid(buf, size)) { rc = efault(); } else if (!IsWindows()) { rc = sys_pwrite(fd, buf, size, offset, offset); @@ -59,10 +61,10 @@ ssize_t pwrite(int fd, const void *buf, size_t size, int64_t offset) { } if (rc != -1) { wrote = (size_t)rc; - if (wrote == 0) { - assert(size == 0); + if (!wrote) { + _npassert(size == 0); } else { - assert(wrote <= size); + _npassert(wrote <= size); } } DATATRACE("pwrite(%d, %#.*hhs%s, %'zu, %'zd) → %'zd% m", fd, diff --git a/libc/calls/pwritev.c b/libc/calls/pwritev.c index 9387a720b..afa626d0f 100644 --- a/libc/calls/pwritev.c +++ b/libc/calls/pwritev.c @@ -16,90 +16,105 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/calls/calls.h" +#include "libc/assert.h" #include "libc/calls/internal.h" #include "libc/calls/struct/iovec.h" #include "libc/calls/struct/iovec.internal.h" +#include "libc/calls/struct/sigset.h" +#include "libc/calls/struct/sigset.internal.h" #include "libc/calls/syscall-sysv.internal.h" +#include "libc/calls/syscall_support-sysv.internal.h" #include "libc/dce.h" #include "libc/errno.h" #include "libc/intrin/asan.internal.h" -#include "libc/intrin/describeflags.internal.h" #include "libc/intrin/kprintf.h" #include "libc/intrin/likely.h" #include "libc/intrin/strace.internal.h" #include "libc/intrin/weaken.h" -#include "libc/macros.internal.h" -#include "libc/sysv/consts/iov.h" +#include "libc/sysv/consts/sig.h" #include "libc/sysv/errfuns.h" #include "libc/zipos/zipos.internal.h" static ssize_t Pwritev(int fd, const struct iovec *iov, int iovlen, int64_t off) { - static bool once, demodernize; - int i, err; - ssize_t rc; - size_t sent, toto; + int i, e; + bool masked; + size_t sent; + ssize_t rc, toto; + sigset_t mask, oldmask; + + if (fd < 0) { + return ebadf(); + } + + if (iovlen < 0) { + return einval(); + } + + if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) { + return efault(); + } - if (fd < 0) return einval(); - if (iovlen < 0) return einval(); - if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) return efault(); if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) { return _weaken(__zipos_write)( (struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, off); - } else if (IsWindows()) { + } + + if (IsWindows()) { if (fd < g_fds.n) { return sys_write_nt(fd, iov, iovlen, off); } else { return ebadf(); } - } else if (IsMetal()) { - return enosys(); } - if (iovlen == 1) { - return sys_pwrite(fd, iov[0].iov_base, iov[0].iov_len, off, off); + if (IsMetal()) { + return espipe(); // must be serial or console if not zipos } - /* - * NT, 2018-era XNU, and 2007-era Linux don't support this system call - */ - if (!once) { - err = errno; - rc = sys_pwritev(fd, iov, iovlen, off, off); - if (rc == -1 && errno == ENOSYS) { - errno = err; - once = true; - demodernize = true; - STRACE("demodernizing %s() due to %s", "pwritev", "ENOSYS"); - } else { - once = true; - return rc; - } - } - - if (!demodernize) { - return sys_pwritev(fd, iov, iovlen, off, off); + while (iovlen && !iov->iov_len) { + --iovlen; + ++iov; } if (!iovlen) { - return sys_pwrite(fd, NULL, 0, off, off); + return sys_pwrite(fd, 0, 0, off, off); } + if (iovlen == 1) { + return sys_pwrite(fd, iov->iov_base, iov->iov_len, off, off); + } + + e = errno; + rc = sys_pwritev(fd, iov, iovlen, off, off); + if (rc != -1 || errno != ENOSYS) return rc; + errno = e; + for (toto = i = 0; i < iovlen; ++i) { rc = sys_pwrite(fd, iov[i].iov_base, iov[i].iov_len, off, off); if (rc == -1) { - if (toto && (errno == EINTR || errno == EAGAIN)) { - return toto; - } else { - return -1; + if (!toto) { + toto = -1; } + break; } + sent = rc; toto += sent; + off += sent; if (sent != iov[i].iov_len) { break; } + + if (!masked) { + sigfillset(&mask); + _npassert(!sys_sigprocmask(SIG_SETMASK, &mask, &oldmask)); + masked = true; + } + } + + if (masked) { + _npassert(!sys_sigprocmask(SIG_SETMASK, &oldmask, 0)); } return toto; diff --git a/libc/calls/read-nt.c b/libc/calls/read-nt.c index 6afd415c3..c51fcd657 100644 --- a/libc/calls/read-nt.c +++ b/libc/calls/read-nt.c @@ -16,14 +16,16 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/assert.h" +#include "libc/calls/calls.h" #include "libc/calls/internal.h" #include "libc/calls/sig.internal.h" -#include "libc/intrin/strace.internal.h" #include "libc/calls/struct/fd.internal.h" #include "libc/calls/struct/iovec.h" #include "libc/calls/struct/iovec.internal.h" #include "libc/calls/syscall_support-nt.internal.h" #include "libc/calls/wincrash.internal.h" +#include "libc/intrin/strace.internal.h" #include "libc/nt/enum/filetype.h" #include "libc/nt/errors.h" #include "libc/nt/files.h" @@ -35,8 +37,10 @@ static textwindows ssize_t sys_read_nt_impl(struct Fd *fd, void *data, size_t size, ssize_t offset) { + int64_t p; uint32_t got, avail; struct NtOverlapped overlap; + if (GetFileType(fd->handle) == kNtFileTypePipe) { for (;;) { if (!PeekNamedPipe(fd->handle, 0, 0, 0, &avail, 0)) break; @@ -52,10 +56,20 @@ static textwindows ssize_t sys_read_nt_impl(struct Fd *fd, void *data, } POLLTRACE("sys_read_nt ready to read"); } + + if (offset != -1) { + // windows changes the file pointer even if overlapped is passed + _npassert(SetFilePointerEx(fd->handle, 0, &p, SEEK_CUR)); + } + if (ReadFile(fd->handle, data, _clampio(size), &got, _offset2overlap(fd->handle, offset, &overlap))) { + if (offset != -1) { + _npassert(SetFilePointerEx(fd->handle, p, 0, SEEK_SET)); + } return got; } + switch (GetLastError()) { case kNtErrorBrokenPipe: // broken pipe case kNtErrorNoData: // closing named pipe @@ -73,6 +87,7 @@ textwindows ssize_t sys_read_nt(struct Fd *fd, const struct iovec *iov, ssize_t rc; uint32_t size; size_t i, total; + if (opt_offset < -1) return einval(); if (_check_interrupts(true, fd)) return eintr(); while (iovlen && !iov[0].iov_len) iov++, iovlen--; if (iovlen) { diff --git a/libc/calls/sched-sysv.internal.h b/libc/calls/sched-sysv.internal.h index 7da6db8f5..43026efde 100644 --- a/libc/calls/sched-sysv.internal.h +++ b/libc/calls/sched-sysv.internal.h @@ -18,7 +18,7 @@ int sys_sched_setscheduler(int, int, const struct sched_param *); int sys_sched_yield(void) hidden; int64_t sys_sched_getaffinity(int, uint64_t, void *) hidden; -int sys_sched_getscheduler_netbsd(int); +int sys_sched_getscheduler_netbsd(int, struct sched_param *); int sys_sched_setparam_netbsd(int, int, int, const struct sched_param *) // asm("sys_sched_setparam"); int sys_sched_getparam_netbsd(int, int, int *, struct sched_param *) // diff --git a/libc/calls/sched_getaffinity.c b/libc/calls/sched_getaffinity.c index 9a2d3cd75..45a8e3071 100644 --- a/libc/calls/sched_getaffinity.c +++ b/libc/calls/sched_getaffinity.c @@ -16,11 +16,13 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" #include "libc/calls/sched-sysv.internal.h" -#include "libc/intrin/strace.internal.h" #include "libc/calls/struct/cpuset.h" #include "libc/calls/syscall_support-nt.internal.h" #include "libc/dce.h" +#include "libc/intrin/strace.internal.h" +#include "libc/macros.internal.h" #include "libc/nt/process.h" #include "libc/nt/runtime.h" #include "libc/nt/thread.h" @@ -52,7 +54,7 @@ static textwindows int sys_sched_getaffinity_nt(int tid, size_t size, * @param bitset receives bitset and should be uint64_t[16] in order to * work on older versions of Linux * @return 0 on success, or -1 w/ errno - * @raise ENOSYS on non-Linux + * @raise ENOSYS if not Linux, NetBSD, or Windows */ int sched_getaffinity(int tid, size_t size, cpu_set_t *bitset) { int rc; @@ -60,6 +62,12 @@ int sched_getaffinity(int tid, size_t size, cpu_set_t *bitset) { rc = einval(); } else if (IsWindows()) { rc = sys_sched_getaffinity_nt(tid, size, bitset); + } else if (IsNetbsd()) { + if (!sys_sched_getaffinity_netbsd(0, tid, MIN(size, 32), bitset)) { + rc = MIN(size, 32); + } else { + rc = -1; + } } else { rc = sys_sched_getaffinity(tid, size, bitset); } diff --git a/libc/calls/sched_getparam.c b/libc/calls/sched_getparam.c index 85b91545b..049ce4a56 100644 --- a/libc/calls/sched_getparam.c +++ b/libc/calls/sched_getparam.c @@ -18,13 +18,31 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/sched-sysv.internal.h" #include "libc/calls/struct/sched_param.h" +#include "libc/calls/struct/sched_param.internal.h" +#include "libc/dce.h" +#include "libc/intrin/asan.internal.h" +#include "libc/intrin/strace.internal.h" +#include "libc/sysv/errfuns.h" /** * Gets scheduler policy parameter. * * @return 0 on success, or -1 w/ errno - * @raise ENOSYS on XNU, Windows + * @raise ENOSYS on XNU, Windows, OpenBSD */ int sched_getparam(int pid, struct sched_param *param) { - return sys_sched_getparam(pid, param); + int rc; + struct sched_param p; + if (!param || (IsAsan() && !__asan_is_valid(param, sizeof(*param)))) { + rc = efault(); + } else if (IsNetbsd()) { + if (!(rc = sys_sched_getscheduler_netbsd(pid, &p))) { + *param = p; + } + } else { + rc = sys_sched_getparam(pid, param); + } + STRACE("sched_getparam(%d, [%s]) → %d% m", pid, DescribeSchedParam(param), + rc); + return rc; } diff --git a/libc/calls/sched_getscheduler-netbsd.c b/libc/calls/sched_getscheduler-netbsd.c index 860acbc2b..bb89fabdf 100644 --- a/libc/calls/sched_getscheduler-netbsd.c +++ b/libc/calls/sched_getscheduler-netbsd.c @@ -20,10 +20,9 @@ #include "libc/calls/sched-sysv.internal.h" #include "libc/calls/struct/sched_param.h" -int sys_sched_getscheduler_netbsd(int pid) { +int sys_sched_getscheduler_netbsd(int pid, struct sched_param *sp) { int policy; - struct sched_param sp; - if (sys_sched_getparam_netbsd(pid, P_ALL_LWPS, &policy, &sp) != -1) { + if (sys_sched_getparam_netbsd(pid, P_ALL_LWPS, &policy, sp) != -1) { return policy; } else { return -1; diff --git a/libc/calls/sched_getscheduler.c b/libc/calls/sched_getscheduler.c index 44d408604..4b1246125 100644 --- a/libc/calls/sched_getscheduler.c +++ b/libc/calls/sched_getscheduler.c @@ -17,10 +17,10 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/sched-sysv.internal.h" -#include "libc/intrin/strace.internal.h" #include "libc/calls/struct/sched_param.h" #include "libc/dce.h" #include "libc/intrin/describeflags.internal.h" +#include "libc/intrin/strace.internal.h" /** * Gets scheduler policy for `pid`. @@ -40,7 +40,8 @@ int sched_getscheduler(int pid) { int rc; if (IsNetbsd()) { - rc = sys_sched_getscheduler_netbsd(pid); + struct sched_param p; + rc = sys_sched_getscheduler_netbsd(pid, &p); } else { rc = sys_sched_getscheduler(pid); } diff --git a/libc/calls/sched_setaffinity.c b/libc/calls/sched_setaffinity.c index a45b8b3a0..4e56a7a24 100644 --- a/libc/calls/sched_setaffinity.c +++ b/libc/calls/sched_setaffinity.c @@ -18,13 +18,14 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/sched-sysv.internal.h" -#include "libc/intrin/strace.internal.h" #include "libc/calls/struct/cpuset.h" #include "libc/calls/syscall-sysv.internal.h" #include "libc/calls/syscall_support-nt.internal.h" #include "libc/dce.h" #include "libc/intrin/safemacros.internal.h" +#include "libc/intrin/strace.internal.h" #include "libc/limits.h" +#include "libc/macros.internal.h" #include "libc/nt/enum/processaccess.h" #include "libc/nt/enum/threadaccess.h" #include "libc/nt/process.h" @@ -34,14 +35,14 @@ #include "libc/sysv/errfuns.h" static textwindows dontinline int sys_sched_setaffinity_nt(int pid, - uint64_t bitsetsize, + uint64_t size, const void *bitset) { int rc; - uintptr_t mask; int64_t handle; + uintptr_t mask; typeof(SetThreadAffinityMask) *SetAffinityMask = SetThreadAffinityMask; mask = 0; - memcpy(&mask, bitset, min(bitsetsize, sizeof(uintptr_t))); + memcpy(&mask, bitset, min(size, sizeof(uintptr_t))); handle = 0; if (!pid) pid = GetCurrentThreadId(); if (0 < pid && pid <= UINT32_MAX) { @@ -69,19 +70,21 @@ static textwindows dontinline int sys_sched_setaffinity_nt(int pid, * Asks kernel to only schedule thread on particular CPUs. * * @param tid is the process or thread id (or 0 for caller) - * @param bitsetsize is byte length of bitset, which should be 128 + * @param size is byte length of bitset, which should be 128 * @return 0 on success, or -1 w/ errno - * @raise ENOSYS if not Linux or Windows + * @raise ENOSYS if not Linux, NetBSD, or Windows */ -int sched_setaffinity(int tid, size_t bitsetsize, const cpu_set_t *bitset) { +int sched_setaffinity(int tid, size_t size, const cpu_set_t *bitset) { int rc; - if (bitsetsize != 128) { + if (size != 128) { rc = einval(); } else if (IsWindows()) { - rc = sys_sched_setaffinity_nt(tid, bitsetsize, bitset); + rc = sys_sched_setaffinity_nt(tid, size, bitset); + } else if (IsNetbsd()) { + rc = sys_sched_setaffinity_netbsd(0, tid, MIN(size, 32), bitset); } else { - rc = sys_sched_setaffinity(tid, bitsetsize, bitset); + rc = sys_sched_setaffinity(tid, size, bitset); } - STRACE("sched_setaffinity(%d, %'zu, %p) → %d% m", tid, bitsetsize, bitset); + STRACE("sched_setaffinity(%d, %'zu, %p) → %d% m", tid, size, bitset); return rc; } diff --git a/libc/calls/sched_setparam.c b/libc/calls/sched_setparam.c index fcb31c091..565c071ba 100644 --- a/libc/calls/sched_setparam.c +++ b/libc/calls/sched_setparam.c @@ -18,11 +18,30 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/sched-sysv.internal.h" #include "libc/calls/struct/sched_param.h" +#include "libc/calls/struct/sched_param.internal.h" +#include "libc/dce.h" +#include "libc/intrin/asan.internal.h" +#include "libc/intrin/strace.internal.h" +#include "libc/sysv/errfuns.h" /** * Sets scheduler policy parameter. - * @raise ENOSYS on XNU, Windows + * + * @return 0 on success, or -1 w/ errno + * @raise ENOSYS on XNU, Windows, OpenBSD */ int sched_setparam(int pid, const struct sched_param *param) { - return sys_sched_setparam(pid, param); + int rc, policy; + struct sched_param p; + if (!param || (IsAsan() && !__asan_is_valid(param, sizeof(*param)))) { + rc = efault(); + } else if (IsNetbsd()) { + if ((rc = policy = sys_sched_getscheduler_netbsd(pid, &p)) != -1) { + rc = sys_sched_setparam_netbsd(pid, P_ALL_LWPS, policy, param); + } + } else { + rc = sys_sched_setparam(pid, param); + } + STRACE("sched_setparam(%d, %s) → %d% m", pid, DescribeSchedParam(param), rc); + return rc; } diff --git a/libc/calls/sched_setscheduler.c b/libc/calls/sched_setscheduler.c index 06fd7b43a..64e1fd2b4 100644 --- a/libc/calls/sched_setscheduler.c +++ b/libc/calls/sched_setscheduler.c @@ -17,14 +17,14 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/sched-sysv.internal.h" -#include "libc/intrin/strace.internal.h" #include "libc/calls/struct/sched_param.h" #include "libc/calls/struct/sched_param.internal.h" #include "libc/dce.h" #include "libc/intrin/describeflags.internal.h" -#include "libc/thread/tls.h" +#include "libc/intrin/strace.internal.h" #include "libc/str/str.h" #include "libc/sysv/errfuns.h" +#include "libc/thread/tls.h" /** * Sets scheduling policy of process, e.g. @@ -94,9 +94,10 @@ */ int sched_setscheduler(int pid, int policy, const struct sched_param *param) { int rc, old; + struct sched_param p; if (IsNetbsd()) { - rc = sys_sched_getscheduler_netbsd(pid); + rc = sys_sched_getscheduler_netbsd(pid, &p); } else { rc = sys_sched_getscheduler(pid); } diff --git a/libc/calls/write-nt.c b/libc/calls/write-nt.c index 77f825d29..b7939ba28 100644 --- a/libc/calls/write-nt.c +++ b/libc/calls/write-nt.c @@ -16,6 +16,8 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/assert.h" +#include "libc/calls/calls.h" #include "libc/calls/internal.h" #include "libc/calls/sig.internal.h" #include "libc/calls/struct/iovec.h" @@ -26,6 +28,7 @@ #include "libc/intrin/strace.internal.h" #include "libc/intrin/weaken.h" #include "libc/nt/errors.h" +#include "libc/nt/files.h" #include "libc/nt/runtime.h" #include "libc/runtime/internal.h" #include "libc/runtime/runtime.h" @@ -35,12 +38,25 @@ static textwindows ssize_t sys_write_nt_impl(int fd, void *data, size_t size, ssize_t offset) { + int64_t h, p; uint32_t err, sent; struct NtOverlapped overlap; - if (WriteFile(g_fds.p[fd].handle, data, _clampio(size), &sent, - _offset2overlap(g_fds.p[fd].handle, offset, &overlap))) { + + h = g_fds.p[fd].handle; + + if (offset != -1) { + // windows changes the file pointer even if overlapped is passed + _npassert(SetFilePointerEx(h, 0, &p, SEEK_CUR)); + } + + if (WriteFile(h, data, _clampio(size), &sent, + _offset2overlap(h, offset, &overlap))) { + if (offset != -1) { + _npassert(SetFilePointerEx(h, p, 0, SEEK_SET)); + } return sent; } + switch (GetLastError()) { // case kNtErrorInvalidHandle: // return ebadf(); /* handled by consts.sh */ @@ -68,6 +84,7 @@ textwindows ssize_t sys_write_nt(int fd, const struct iovec *iov, size_t iovlen, size_t i, total; uint32_t size, wrote; struct NtOverlapped overlap; + if (opt_offset < -1) return einval(); while (iovlen && !iov[0].iov_len) iov++, iovlen--; if (iovlen) { for (total = i = 0; i < iovlen; ++i) { diff --git a/libc/fmt/bing.c b/libc/fmt/bing.c index 86449e891..92eafdbf0 100644 --- a/libc/fmt/bing.c +++ b/libc/fmt/bing.c @@ -19,6 +19,7 @@ #include "libc/assert.h" #include "libc/fmt/bing.internal.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" /** * Turns binary octet into unicode glyph representation. diff --git a/libc/fmt/stoa.c b/libc/fmt/stoa.c index 4d87f7a38..6b6d02450 100644 --- a/libc/fmt/stoa.c +++ b/libc/fmt/stoa.c @@ -16,7 +16,6 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/assert.h" #include "libc/fmt/fmt.internal.h" #include "libc/fmt/internal.h" #include "libc/intrin/bits.h" @@ -26,6 +25,7 @@ #include "libc/intrin/weaken.h" #include "libc/str/str.h" #include "libc/str/strwidth.h" +#include "libc/str/tab.internal.h" #include "libc/str/thompike.h" #include "libc/str/unicode.h" #include "libc/str/utf16.h" diff --git a/libc/fmt/strtoi128.c b/libc/fmt/strtoi128.c index ff9d6a317..c20acf08a 100644 --- a/libc/fmt/strtoi128.c +++ b/libc/fmt/strtoi128.c @@ -21,6 +21,7 @@ #include "libc/fmt/strtol.internal.h" #include "libc/limits.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" /** * Decodes 128-bit signed integer from ASCII string. diff --git a/libc/fmt/strtoimax.c b/libc/fmt/strtoimax.c index 7eacb3322..d91291ed0 100644 --- a/libc/fmt/strtoimax.c +++ b/libc/fmt/strtoimax.c @@ -21,6 +21,7 @@ #include "libc/fmt/strtol.internal.h" #include "libc/limits.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" /** * Decodes intmax_t from ASCII string. diff --git a/libc/fmt/strtol.c b/libc/fmt/strtol.c index 8fc107153..4094f6da2 100644 --- a/libc/fmt/strtol.c +++ b/libc/fmt/strtol.c @@ -21,6 +21,7 @@ #include "libc/fmt/strtol.internal.h" #include "libc/limits.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" /** * Decodes signed integer from ASCII string. diff --git a/libc/fmt/strtou128.c b/libc/fmt/strtou128.c index b8005fd18..1dd25cf88 100644 --- a/libc/fmt/strtou128.c +++ b/libc/fmt/strtou128.c @@ -19,6 +19,7 @@ #include "libc/fmt/conv.h" #include "libc/fmt/strtol.internal.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" /** * Decodes 128-bit unsigned integer from ASCII string. diff --git a/libc/fmt/strtoul.c b/libc/fmt/strtoul.c index b9eaef49f..facc41c18 100644 --- a/libc/fmt/strtoul.c +++ b/libc/fmt/strtoul.c @@ -20,6 +20,7 @@ #include "libc/fmt/conv.h" #include "libc/fmt/strtol.internal.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" /** * Decodes unsigned integer from ASCII string. diff --git a/libc/fmt/strtoumax.c b/libc/fmt/strtoumax.c index eb4e5134e..c1f41910c 100644 --- a/libc/fmt/strtoumax.c +++ b/libc/fmt/strtoumax.c @@ -19,6 +19,7 @@ #include "libc/fmt/conv.h" #include "libc/fmt/strtol.internal.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" /** * Decodes uintmax_t from ASCII string. diff --git a/libc/fmt/unbing.c b/libc/fmt/unbing.c index 0de72eaa2..9bf2c6112 100644 --- a/libc/fmt/unbing.c +++ b/libc/fmt/unbing.c @@ -21,6 +21,7 @@ #include "libc/nexgen32e/nexgen32e.h" #include "libc/runtime/runtime.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" static const int kCp437iMultimappings[] = { u'\n' << 8 | '\n', // NEWLINE diff --git a/libc/fmt/vcscanf.c b/libc/fmt/vcscanf.c index c51d4044e..22aa93a26 100644 --- a/libc/fmt/vcscanf.c +++ b/libc/fmt/vcscanf.c @@ -23,6 +23,7 @@ #include "libc/runtime/runtime.h" #include "libc/str/oldutf16.internal.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" #include "libc/str/tpdecodecb.internal.h" #include "libc/str/utf16.h" #include "libc/sysv/errfuns.h" diff --git a/libc/fmt/wcstoi128.c b/libc/fmt/wcstoi128.c index 4bb79d338..3337ed488 100644 --- a/libc/fmt/wcstoi128.c +++ b/libc/fmt/wcstoi128.c @@ -21,6 +21,7 @@ #include "libc/fmt/strtol.internal.h" #include "libc/limits.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" /** * Decodes 128-bit signed integer from wide string. diff --git a/libc/fmt/wcstoimax.c b/libc/fmt/wcstoimax.c index b6abb147d..10bf752a1 100644 --- a/libc/fmt/wcstoimax.c +++ b/libc/fmt/wcstoimax.c @@ -21,6 +21,7 @@ #include "libc/fmt/strtol.internal.h" #include "libc/limits.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" /** * Decodes intmax_t from wide string. diff --git a/libc/fmt/wcstol.c b/libc/fmt/wcstol.c index e27dfd204..28562afb4 100644 --- a/libc/fmt/wcstol.c +++ b/libc/fmt/wcstol.c @@ -21,6 +21,7 @@ #include "libc/fmt/strtol.internal.h" #include "libc/limits.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" /** * Decodes signed long integer from wide string. diff --git a/libc/fmt/wcstoll.c b/libc/fmt/wcstoll.c index 4b63f8d55..6851237ed 100644 --- a/libc/fmt/wcstoll.c +++ b/libc/fmt/wcstoll.c @@ -21,6 +21,7 @@ #include "libc/fmt/strtol.internal.h" #include "libc/limits.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" /** * Decodes signed long long integer from wide string. diff --git a/libc/fmt/wcstou128.c b/libc/fmt/wcstou128.c index 38c74f8b2..2d2fa01d1 100644 --- a/libc/fmt/wcstou128.c +++ b/libc/fmt/wcstou128.c @@ -19,6 +19,7 @@ #include "libc/fmt/conv.h" #include "libc/fmt/strtol.internal.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" /** * Decodes 128-bit unsigned integer from wide string. diff --git a/libc/fmt/wcstoul.c b/libc/fmt/wcstoul.c index 3a68c651a..6f2ddeef2 100644 --- a/libc/fmt/wcstoul.c +++ b/libc/fmt/wcstoul.c @@ -20,6 +20,7 @@ #include "libc/fmt/conv.h" #include "libc/fmt/strtol.internal.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" /** * Decodes unsigned integer from wide string. diff --git a/libc/fmt/wcstoull.c b/libc/fmt/wcstoull.c index c17fe8605..73739c6ca 100644 --- a/libc/fmt/wcstoull.c +++ b/libc/fmt/wcstoull.c @@ -20,6 +20,7 @@ #include "libc/fmt/conv.h" #include "libc/fmt/strtol.internal.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" /** * Decodes unsigned long long integer from wide string. diff --git a/libc/fmt/wcstoumax.c b/libc/fmt/wcstoumax.c index 80f720756..8fc617813 100644 --- a/libc/fmt/wcstoumax.c +++ b/libc/fmt/wcstoumax.c @@ -19,6 +19,7 @@ #include "libc/fmt/conv.h" #include "libc/fmt/strtol.internal.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" /** * Decodes uintmax_t from wide string. diff --git a/libc/intrin/asan.c b/libc/intrin/asan.c index dc1426b68..a1f001ca8 100644 --- a/libc/intrin/asan.c +++ b/libc/intrin/asan.c @@ -50,6 +50,7 @@ #include "libc/runtime/stack.h" #include "libc/runtime/symbols.internal.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" #include "libc/sysv/consts/auxv.h" #include "libc/sysv/consts/map.h" #include "libc/sysv/consts/nr.h" diff --git a/libc/intrin/asan.internal.h b/libc/intrin/asan.internal.h index eee7b4797..ad40b1a61 100644 --- a/libc/intrin/asan.internal.h +++ b/libc/intrin/asan.internal.h @@ -3,7 +3,6 @@ #include "libc/calls/struct/iovec.h" #include "libc/intrin/asancodes.h" #include "libc/macros.internal.h" -#include "libc/thread/thread.h" #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ diff --git a/libc/intrin/describeflags.internal.h b/libc/intrin/describeflags.internal.h index afb87b598..8ec3b0aa5 100644 --- a/libc/intrin/describeflags.internal.h +++ b/libc/intrin/describeflags.internal.h @@ -30,6 +30,7 @@ const char *DescribeNtFileFlagAttr(char[256], uint32_t); const char *DescribeNtFileMapFlags(char[64], uint32_t); const char *DescribeNtFileShareFlags(char[64], uint32_t); const char *DescribeNtFiletypeFlags(char[64], uint32_t); +const char *DescribeNtLockFileFlags(char[64], uint32_t); const char *DescribeNtMovFileInpFlags(char[256], uint32_t); const char *DescribeNtPageFlags(char[64], uint32_t); const char *DescribeNtPipeModeFlags(char[64], uint32_t); @@ -72,6 +73,7 @@ const char *DescribeWhence(char[12], int); #define DescribeNtFileMapFlags(x) DescribeNtFileMapFlags(alloca(64), x) #define DescribeNtFileShareFlags(x) DescribeNtFileShareFlags(alloca(64), x) #define DescribeNtFiletypeFlags(x) DescribeNtFiletypeFlags(alloca(64), x) +#define DescribeNtLockFileFlags(x) DescribeNtLockFileFlags(alloca(64), x) #define DescribeNtMovFileInpFlags(x) DescribeNtMovFileInpFlags(alloca(256), x) #define DescribeNtPageFlags(x) DescribeNtPageFlags(alloca(64), x) #define DescribeNtPipeModeFlags(x) DescribeNtPipeModeFlags(alloca(64), x) diff --git a/libc/intrin/describemagnums.c b/libc/intrin/describemagnums.c index 0474405fa..18e18565e 100644 --- a/libc/intrin/describemagnums.c +++ b/libc/intrin/describemagnums.c @@ -22,6 +22,7 @@ char *DescribeMagnum(char *b, const struct MagnumStr *m, const char *p, int x) { char *s; + if (x == 127) return "CLOCK_INVALID"; if ((s = GetMagnumStr(m, x))) { stpcpy(stpcpy(b, p), s); return b; diff --git a/libc/intrin/describentlockfileflags.c b/libc/intrin/describentlockfileflags.c new file mode 100644 index 000000000..d7afc98c6 --- /dev/null +++ b/libc/intrin/describentlockfileflags.c @@ -0,0 +1,31 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2022 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/intrin/describeflags.internal.h" +#include "libc/macros.internal.h" +#include "libc/nt/enum/filelockflags.h" + +static const struct DescribeFlags kNtLockFileFlags[] = { + {kNtLockfileFailImmediately, "FailImmediately"}, // + {kNtLockfileExclusiveLock, "ExclusiveLock"}, // +}; + +const char *(DescribeNtLockFileFlags)(char buf[64], uint32_t x) { + return DescribeFlags(buf, 64, kNtLockFileFlags, ARRAYLEN(kNtLockFileFlags), + "kNtLockfile", x); +} diff --git a/libc/intrin/describentoverlapped.c b/libc/intrin/describentoverlapped.c new file mode 100644 index 000000000..cc1edef4e --- /dev/null +++ b/libc/intrin/describentoverlapped.c @@ -0,0 +1,49 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2022 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/intrin/describentoverlapped.internal.h" +#include "libc/intrin/kprintf.h" +#include "libc/macros.internal.h" + +const char *(DescribeNtOverlapped)(char b[128], struct NtOverlapped *o) { + int i = 0, n = 128; + bool gotsome = false; + if (!o) return "NULL"; + i += ksnprintf(b + i, MAX(0, n - i), "{"); + + if (o->hEvent) { + if (gotsome) { + i += ksnprintf(b + i, MAX(0, n - i), ", "); + } else { + gotsome = true; + } + i += ksnprintf(b + i, MAX(0, n - i), ".hEvent = %ld", o->hEvent); + } + + if (o->Pointer) { + if (gotsome) { + i += ksnprintf(b + i, MAX(0, n - i), ", "); + } else { + gotsome = true; + } + i += ksnprintf(b + i, MAX(0, n - i), ".Pointer = (void *)%p", o->Pointer); + } + + i += ksnprintf(b + i, MAX(0, n - i), "}"); + return b; +} diff --git a/libc/intrin/describentoverlapped.internal.h b/libc/intrin/describentoverlapped.internal.h new file mode 100644 index 000000000..8d33a7611 --- /dev/null +++ b/libc/intrin/describentoverlapped.internal.h @@ -0,0 +1,13 @@ +#ifndef COSMOPOLITAN_LIBC_INTRIN_DESCRIBENTOVERLAPPED_INTERNAL_H_ +#define COSMOPOLITAN_LIBC_INTRIN_DESCRIBENTOVERLAPPED_INTERNAL_H_ +#include "libc/mem/alloca.h" +#include "libc/nt/struct/overlapped.h" +#if !(__ASSEMBLER__ + __LINKER__ + 0) +COSMOPOLITAN_C_START_ + +const char *DescribeNtOverlapped(char[128], struct NtOverlapped *); +#define DescribeNtOverlapped(x) DescribeNtOverlapped(alloca(128), x) + +COSMOPOLITAN_C_END_ +#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ +#endif /* COSMOPOLITAN_LIBC_INTRIN_DESCRIBENTOVERLAPPED_INTERNAL_H_ */ diff --git a/libc/intrin/deviceiocontrol.c b/libc/intrin/deviceiocontrol.c index e5e8c2845..6f0af1b16 100644 --- a/libc/intrin/deviceiocontrol.c +++ b/libc/intrin/deviceiocontrol.c @@ -16,8 +16,9 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/intrin/strace.internal.h" #include "libc/calls/syscall_support-nt.internal.h" +#include "libc/intrin/describentoverlapped.internal.h" +#include "libc/intrin/strace.internal.h" #include "libc/nt/files.h" #include "libc/nt/struct/overlapped.h" #include "libc/nt/thunk/msabi.h" @@ -40,8 +41,9 @@ textwindows bool32 DeviceIoControl(int64_t hDevice, uint32_t dwIoControlCode, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped); if (!ok) __winerr(); - NTTRACE("DeviceIoControl(%ld, %#x, %p, %'zu, %p, %'zu, %p, %p) → %hhhd% m", + NTTRACE("DeviceIoControl(%ld, %#x, %p, %'zu, %p, %'zu, %p, %s) → %hhhd% m", hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, - nOutBufferSize, lpBytesReturned, lpOverlapped, ok); + nOutBufferSize, lpBytesReturned, DescribeNtOverlapped(lpOverlapped), + ok); return ok; } diff --git a/libc/intrin/kclocknames.S b/libc/intrin/kclocknames.S index cd3c0f120..02c6e9f14 100644 --- a/libc/intrin/kclocknames.S +++ b/libc/intrin/kclocknames.S @@ -33,17 +33,24 @@ kClockNames: .e CLOCK_REALTIME,"REALTIME" .e CLOCK_REALTIME_FAST,"REALTIME_FAST" + .e CLOCK_REALTIME_PRECISE,"REALTIME_PRECISE" .e CLOCK_MONOTONIC,"MONOTONIC" .e CLOCK_MONOTONIC_FAST,"MONOTONIC_FAST" .e CLOCK_MONOTONIC_RAW,"MONOTONIC_RAW" + .e CLOCK_MONOTONIC_PRECISE,"MONOTONIC_PRECISE" .e CLOCK_REALTIME_COARSE,"REALTIME_COARSE" .e CLOCK_MONOTONIC_COARSE,"MONOTONIC_COARSE" .e CLOCK_PROCESS_CPUTIME_ID,"PROCESS_CPUTIME_ID" + .e CLOCK_THREAD_CPUTIME_ID,"THREAD_CPUTIME_ID" .e CLOCK_TAI,"TAI" .e CLOCK_PROF,"PROF" .e CLOCK_BOOTTIME,"BOOTTIME" .e CLOCK_REALTIME_ALARM,"REALTIME_ALARM" .e CLOCK_BOOTTIME_ALARM,"BOOTTIME_ALARM" + .e CLOCK_UPTIME,"UPTIME" + .e CLOCK_UPTIME_FAST,"UPTIME_FAST" + .e CLOCK_UPTIME_PRECISE,"UPTIME_PRECISE" + .e CLOCK_SECOND,"SECOND" .long MAGNUM_TERMINATOR .endobj kClockNames,globl,hidden .overrun diff --git a/libc/intrin/kprintf.greg.c b/libc/intrin/kprintf.greg.c index ffee3ed4f..3b91f4260 100644 --- a/libc/intrin/kprintf.greg.c +++ b/libc/intrin/kprintf.greg.c @@ -48,6 +48,7 @@ #include "libc/runtime/runtime.h" #include "libc/runtime/symbols.internal.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" #include "libc/str/utf16.h" #include "libc/sysv/consts/nr.h" #include "libc/sysv/consts/prot.h" diff --git a/libc/intrin/lockfileex.c b/libc/intrin/lockfileex.c new file mode 100644 index 000000000..2a8d1b671 --- /dev/null +++ b/libc/intrin/lockfileex.c @@ -0,0 +1,50 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2022 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/syscall_support-nt.internal.h" +#include "libc/intrin/describeflags.internal.h" +#include "libc/intrin/describentoverlapped.internal.h" +#include "libc/intrin/strace.internal.h" +#include "libc/nt/files.h" + +__msabi extern typeof(LockFileEx) *const __imp_LockFileEx; + +/** + * Locks file on the New Technology. + * + * @return handle, or -1 on failure + * @note this wrapper takes care of ABI, STRACE(), and __winerr() + */ +bool32 LockFileEx(int64_t hFile, uint32_t dwFlags, uint32_t dwReserved, + uint32_t nNumberOfBytesToLockLow, + uint32_t nNumberOfBytesToLockHigh, + struct NtOverlapped *lpOverlapped) { + bool32 ok; + STRACE("LockFileEx(%ld, %s, %#x, %'zu, %s) → ...", hFile, + DescribeNtLockFileFlags(dwFlags), dwReserved, + (uint64_t)nNumberOfBytesToLockHigh << 32 | nNumberOfBytesToLockLow, + DescribeNtOverlapped(lpOverlapped)); + ok = __imp_LockFileEx(hFile, dwFlags, dwReserved, nNumberOfBytesToLockLow, + nNumberOfBytesToLockHigh, lpOverlapped); + if (!ok) __winerr(); + STRACE("LockFileEx(%ld, %s, %#x, %'zu, [%s]) → %hhhd% m", hFile, + DescribeNtLockFileFlags(dwFlags), dwReserved, + (uint64_t)nNumberOfBytesToLockHigh << 32 | nNumberOfBytesToLockLow, + DescribeNtOverlapped(lpOverlapped), ok); + return ok; +} diff --git a/libc/intrin/unlockfileex.c b/libc/intrin/unlockfileex.c new file mode 100644 index 000000000..4e5debda2 --- /dev/null +++ b/libc/intrin/unlockfileex.c @@ -0,0 +1,50 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2022 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/syscall_support-nt.internal.h" +#include "libc/errno.h" +#include "libc/intrin/describeflags.internal.h" +#include "libc/intrin/describentoverlapped.internal.h" +#include "libc/intrin/strace.internal.h" +#include "libc/nt/files.h" +#include "libc/str/str.h" + +__msabi extern typeof(UnlockFileEx) *const __imp_UnlockFileEx; + +/** + * Unlocks file on the New Technology. + * + * @return handle, or -1 on failure + * @note this wrapper takes care of ABI, STRACE(), and __winerr() + */ +bool32 UnlockFileEx(int64_t hFile, uint32_t dwReserved, + uint32_t nNumberOfBytesToUnlockLow, + uint32_t nNumberOfBytesToUnlockHigh, + struct NtOverlapped *lpOverlapped) { + bool32 ok; + STRACE("UnlockFileEx(%ld, %#x, %'zu, %s) → ...", hFile, dwReserved, + (uint64_t)nNumberOfBytesToUnlockHigh << 32 | nNumberOfBytesToUnlockLow, + DescribeNtOverlapped(lpOverlapped)); + ok = __imp_UnlockFileEx(hFile, dwReserved, nNumberOfBytesToUnlockLow, + nNumberOfBytesToUnlockHigh, lpOverlapped); + if (!ok) __winerr(); + STRACE("UnlockFileEx(%ld, %#x, %'zu, [%s]) → %hhhd% m", hFile, dwReserved, + (uint64_t)nNumberOfBytesToUnlockHigh << 32 | nNumberOfBytesToUnlockLow, + DescribeNtOverlapped(lpOverlapped), ok); + return ok; +} diff --git a/libc/intrin/wsarecv.c b/libc/intrin/wsarecv.c index 8029cccfd..d4e40f72d 100644 --- a/libc/intrin/wsarecv.c +++ b/libc/intrin/wsarecv.c @@ -16,10 +16,11 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/intrin/strace.internal.h" #include "libc/calls/syscall_support-nt.internal.h" #include "libc/intrin/describeflags.internal.h" +#include "libc/intrin/describentoverlapped.internal.h" #include "libc/intrin/kprintf.h" +#include "libc/intrin/strace.internal.h" #include "libc/nt/thunk/msabi.h" #include "libc/nt/winsock.h" @@ -55,8 +56,9 @@ textwindows int WSARecv( kprintf(STRACE_PROLOGUE "WSARecv(%lu, [", s); DescribeIovNt(inout_lpBuffers, dwBufferCount, rc != -1 ? NumberOfBytesRecvd : 0); - kprintf("], %u, [%'u], %p, %p, %p) → %d% lm\n", dwBufferCount, - NumberOfBytesRecvd, inout_lpFlags, opt_inout_lpOverlapped, + kprintf("], %u, [%'u], %p, %s, %p) → %d% lm\n", dwBufferCount, + NumberOfBytesRecvd, inout_lpFlags, + DescribeNtOverlapped(opt_inout_lpOverlapped), opt_lpCompletionRoutine, rc); } #else diff --git a/libc/intrin/wsarecvfrom.c b/libc/intrin/wsarecvfrom.c index 6d49a094c..ef13557d2 100644 --- a/libc/intrin/wsarecvfrom.c +++ b/libc/intrin/wsarecvfrom.c @@ -16,10 +16,11 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/intrin/strace.internal.h" #include "libc/calls/syscall_support-nt.internal.h" #include "libc/intrin/describeflags.internal.h" +#include "libc/intrin/describentoverlapped.internal.h" #include "libc/intrin/kprintf.h" +#include "libc/intrin/strace.internal.h" #include "libc/nt/thunk/msabi.h" #include "libc/nt/winsock.h" @@ -57,9 +58,10 @@ textwindows int WSARecvFrom( kprintf(STRACE_PROLOGUE "WSARecvFrom(%lu, [", s); DescribeIovNt(inout_lpBuffers, dwBufferCount, rc != -1 ? NumberOfBytesRecvd : 0); - kprintf("], %u, [%'u], %p, %p, %p, %p, %p) → %d% lm\n", dwBufferCount, + kprintf("], %u, [%'u], %p, %p, %p, %s, %p) → %d% lm\n", dwBufferCount, NumberOfBytesRecvd, opt_out_fromsockaddr, opt_inout_fromsockaddrlen, - inout_lpFlags, opt_inout_lpOverlapped, opt_lpCompletionRoutine, rc); + inout_lpFlags, DescribeNtOverlapped(opt_inout_lpOverlapped), + opt_lpCompletionRoutine, rc); } #else rc = __imp_WSARecvFrom(s, inout_lpBuffers, dwBufferCount, diff --git a/libc/nt/errors.h b/libc/nt/errors.h index 484e668e6..51018e957 100644 --- a/libc/nt/errors.h +++ b/libc/nt/errors.h @@ -131,7 +131,7 @@ #define kNtErrorTooManyTcbs 155 #define kNtErrorSignalRefused 156 #define kNtErrorDiscarded 157 -#define kNtErrorNotLocked 158 +#define kNtErrorNotLocked 158 /* ENOLCK */ #define kNtErrorBadThreadidAddr 159 #define kNtErrorBadArguments 160 #define kNtErrorBadPathname 161 @@ -1531,7 +1531,7 @@ #define kNtErrorLogSectorParityInvalid 6601 #define kNtErrorLogSectorRemapped 6602 #define kNtErrorLogBlockIncomplete 6603 -#define kNtErrorLogInvalidRange 6604 +#define kNtErrorLogInvalidRange 6604 /* ERANGE */ #define kNtErrorLogBlocksExhausted 6605 #define kNtErrorLogReadContextInvalid 6606 #define kNtErrorLogRestartInvalid 6607 diff --git a/libc/nt/files.h b/libc/nt/files.h index b61db4569..df6da98bb 100644 --- a/libc/nt/files.h +++ b/libc/nt/files.h @@ -116,13 +116,13 @@ bool32 DeviceIoControl(int64_t hDevice, uint32_t dwIoControlCode, bool32 LockFile(int64_t hFile, uint32_t dwFileOffsetLow, uint32_t dwFileOffsetHigh, uint32_t nNumberOfBytesToLockLow, uint32_t nNumberOfBytesToLockHigh); +bool32 UnlockFile(int64_t hFile, uint32_t dwFileOffsetLow, + uint32_t dwFileOffsetHigh, uint32_t nNumberOfBytesToUnlockLow, + uint32_t nNumberOfBytesToUnlockHigh); bool32 LockFileEx(int64_t hFile, uint32_t dwFlags, uint32_t dwReserved, uint32_t nNumberOfBytesToLockLow, uint32_t nNumberOfBytesToLockHigh, struct NtOverlapped *lpOverlapped) paramsnonnull(); -bool32 UnlockFile(int64_t hFile, uint32_t dwFileOffsetLow, - uint32_t dwFileOffsetHigh, uint32_t nNumberOfBytesToUnlockLow, - uint32_t nNumberOfBytesToUnlockHigh); bool32 UnlockFileEx(int64_t hFile, uint32_t dwReserved, uint32_t nNumberOfBytesToUnlockLow, uint32_t nNumberOfBytesToUnlockHigh, diff --git a/libc/nt/kernel32/LockFileEx.s b/libc/nt/kernel32/LockFileEx.s index 9aba0a595..f74843927 100644 --- a/libc/nt/kernel32/LockFileEx.s +++ b/libc/nt/kernel32/LockFileEx.s @@ -2,11 +2,11 @@ .imp kernel32,__imp_LockFileEx,LockFileEx,0 .text.windows -LockFileEx: +__LockFileEx: push %rbp mov %rsp,%rbp .profilable mov __imp_LockFileEx(%rip),%rax jmp __sysv2nt6 - .endfn LockFileEx,globl + .endfn __LockFileEx,globl .previous diff --git a/libc/nt/kernel32/UnlockFileEx.s b/libc/nt/kernel32/UnlockFileEx.s index 577232d60..0dedd8b8b 100644 --- a/libc/nt/kernel32/UnlockFileEx.s +++ b/libc/nt/kernel32/UnlockFileEx.s @@ -2,11 +2,11 @@ .imp kernel32,__imp_UnlockFileEx,UnlockFileEx,0 .text.windows -UnlockFileEx: +__UnlockFileEx: push %rbp mov %rsp,%rbp .profilable mov __imp_UnlockFileEx(%rip),%rax jmp __sysv2nt6 - .endfn UnlockFileEx,globl + .endfn __UnlockFileEx,globl .previous diff --git a/libc/nt/master.sh b/libc/nt/master.sh index 1d269f4fc..415068d57 100755 --- a/libc/nt/master.sh +++ b/libc/nt/master.sh @@ -700,7 +700,6 @@ imp 'LocalUnlock' LocalUnlock kernel32 0 imp 'LocaleNameToLCID' LocaleNameToLCID kernel32 0 imp 'LocateXStateFeature' LocateXStateFeature kernel32 0 imp 'LockFile' LockFile kernel32 0 5 -imp 'LockFileEx' LockFileEx kernel32 0 6 imp 'LockResource' LockResource kernel32 0 1 imp 'MapUserPhysicalPages' MapUserPhysicalPages kernel32 0 imp 'MapUserPhysicalPagesScatter' MapUserPhysicalPagesScatter kernel32 986 @@ -1024,7 +1023,6 @@ imp 'UTUnRegister' UTUnRegister kernel32 1459 imp 'UmsThreadYield' UmsThreadYield kernel32 1460 imp 'UnhandledExceptionFilter' UnhandledExceptionFilter kernel32 0 imp 'UnlockFile' UnlockFile kernel32 0 5 -imp 'UnlockFileEx' UnlockFileEx kernel32 0 5 imp 'UnmapViewOfFile2' UnmapViewOfFile2 kernel32 0 2 imp 'UnmapViewOfFileEx' UnmapViewOfFileEx kernel32 0 3 imp 'UnregisterApplicationRecoveryCallback' UnregisterApplicationRecoveryCallback kernel32 1466 @@ -1120,6 +1118,7 @@ imp '__FlushViewOfFile' FlushViewOfFile kernel32 0 2 imp '__GenerateConsoleCtrlEvent' GenerateConsoleCtrlEvent kernel32 0 2 imp '__GetExitCodeProcess' GetExitCodeProcess kernel32 0 2 imp '__GetFileAttributes' GetFileAttributesW kernel32 0 1 +imp '__LockFileEx' LockFileEx kernel32 0 6 imp '__MapViewOfFileEx' MapViewOfFileEx kernel32 0 6 imp '__MapViewOfFileExNuma' MapViewOfFileExNuma kernel32 0 7 imp '__MoveFileEx' MoveFileExW kernel32 0 3 @@ -1128,6 +1127,7 @@ imp '__ReOpenFile' ReOpenFile kernel32 0 4 # TODO(jart): 6.2 and highe imp '__RemoveDirectory' RemoveDirectoryW kernel32 0 1 imp '__SetCurrentDirectory' SetCurrentDirectoryW kernel32 0 1 imp '__TerminateProcess' TerminateProcess kernel32 0 2 +imp '__UnlockFileEx' UnlockFileEx kernel32 0 5 imp '__UnmapViewOfFile' UnmapViewOfFile kernel32 0 1 imp '__VirtualProtect' VirtualProtect kernel32 0 4 imp '__WaitForMultipleObjects' WaitForMultipleObjects kernel32 0 4 diff --git a/libc/stdio/fdopen.c b/libc/stdio/fdopen.c index de8875d62..ad295a27d 100644 --- a/libc/stdio/fdopen.c +++ b/libc/stdio/fdopen.c @@ -38,7 +38,7 @@ FILE *fdopen(int fd, const char *mode) { f->fd = fd; f->bufmode = ischardev(fd) ? _IOLBF : _IOFBF; f->iomode = fopenflags(mode); - f->lock._type = PTHREAD_MUTEX_RECURSIVE; + ((pthread_mutex_t *)f->lock)->_type = PTHREAD_MUTEX_RECURSIVE; f->size = BUFSIZ; if ((f->buf = malloc(f->size))) { if ((f->iomode & O_ACCMODE) != O_RDONLY) { diff --git a/libc/stdio/flockfile.c b/libc/stdio/flockfile.c index 36ae8a3e5..852459e73 100644 --- a/libc/stdio/flockfile.c +++ b/libc/stdio/flockfile.c @@ -23,5 +23,5 @@ * Acquires reentrant lock on stdio object, blocking if needed. */ void(flockfile)(FILE *f) { - pthread_mutex_lock(&f->lock); + pthread_mutex_lock((pthread_mutex_t *)f->lock); } diff --git a/libc/stdio/fmemopen.c b/libc/stdio/fmemopen.c index 3183982a3..1425ae79a 100644 --- a/libc/stdio/fmemopen.c +++ b/libc/stdio/fmemopen.c @@ -54,7 +54,7 @@ FILE *fmemopen(void *buf, size_t size, const char *mode) { f->end = size; f->size = size; f->iomode = fopenflags(mode); - f->lock._type = PTHREAD_MUTEX_RECURSIVE; + ((pthread_mutex_t *)f->lock)->_type = PTHREAD_MUTEX_RECURSIVE; if (f->iomode & O_APPEND) { if ((p = memchr(buf, '\0', size))) { f->beg = p - (char *)buf; diff --git a/libc/stdio/ftrylockfile.c b/libc/stdio/ftrylockfile.c index 501c9b3a0..e29a2c28c 100644 --- a/libc/stdio/ftrylockfile.c +++ b/libc/stdio/ftrylockfile.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/lock.internal.h" #include "libc/stdio/stdio.h" /** @@ -24,5 +25,5 @@ * @return 0 on success, or non-zero if another thread owns the lock */ int(ftrylockfile)(FILE *f) { - return pthread_mutex_trylock(&f->lock); + return pthread_mutex_trylock((pthread_mutex_t *)f->lock); } diff --git a/libc/stdio/funlockfile.c b/libc/stdio/funlockfile.c index bef058320..20a9358f6 100644 --- a/libc/stdio/funlockfile.c +++ b/libc/stdio/funlockfile.c @@ -16,11 +16,12 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/lock.internal.h" #include "libc/stdio/stdio.h" /** * Releases lock on stdio object. */ void(funlockfile)(FILE *f) { - pthread_mutex_unlock(&f->lock); + pthread_mutex_unlock((pthread_mutex_t *)f->lock); } diff --git a/libc/stdio/gets.c b/libc/stdio/gets.c index d62e6239f..a499b8721 100644 --- a/libc/stdio/gets.c +++ b/libc/stdio/gets.c @@ -19,6 +19,6 @@ #include "libc/limits.h" #include "libc/stdio/stdio.h" -compatfn char *gets(char *s) { +char *gets(char *s) { return fgets(s, INT_MAX, stdin); } diff --git a/libc/stdio/stdio.h b/libc/stdio/stdio.h index 401e344e2..8a5e4e1ae 100644 --- a/libc/stdio/stdio.h +++ b/libc/stdio/stdio.h @@ -1,9 +1,7 @@ -#ifndef COSMOPOLITAN_LIBC_STDIO_STDIO_H_ -#define COSMOPOLITAN_LIBC_STDIO_STDIO_H_ -#include "libc/fmt/pflink.h" -#include "libc/thread/thread.h" - +#ifndef _STDIO_H #define _STDIO_H +#include "libc/fmt/pflink.h" + #define L_ctermid 20 #define FILENAME_MAX PATH_MAX #define FOPEN_MAX 1000 @@ -17,19 +15,19 @@ COSMOPOLITAN_C_START_ ╚────────────────────────────────────────────────────────────────────────────│*/ typedef struct FILE { - uint8_t bufmode; /* 0x00 _IOFBF, etc. (ignored if fd=-1) */ - bool noclose; /* 0x01 for fake dup() todo delete! */ - uint32_t iomode; /* 0x04 O_RDONLY, etc. (ignored if fd=-1) */ - int32_t state; /* 0x08 0=OK, -1=EOF, >0=errno */ - int fd; /* 0x0c ≥0=fd, -1=closed|buffer */ - uint32_t beg; /* 0x10 */ - uint32_t end; /* 0x14 */ - char *buf; /* 0x18 */ - uint32_t size; /* 0x20 */ - uint32_t nofree; /* 0x24 */ - int pid; /* 0x28 */ - char *getln; /* 0x30 */ - pthread_mutex_t lock; /* 0x38 */ + uint8_t bufmode; /* 0x00 _IOFBF, etc. (ignored if fd=-1) */ + bool noclose; /* 0x01 for fake dup() todo delete! */ + uint32_t iomode; /* 0x04 O_RDONLY, etc. (ignored if fd=-1) */ + int32_t state; /* 0x08 0=OK, -1=EOF, >0=errno */ + int fd; /* 0x0c ≥0=fd, -1=closed|buffer */ + uint32_t beg; /* 0x10 */ + uint32_t end; /* 0x14 */ + char *buf; /* 0x18 */ + uint32_t size; /* 0x20 */ + uint32_t nofree; /* 0x24 */ + int pid; /* 0x28 */ + char *getln; /* 0x30 */ + char lock[16]; /* 0x38 */ } FILE; extern FILE *stdin; @@ -91,9 +89,9 @@ char *ctermid(char *); void perror(const char *) relegated; typedef uint64_t fpos_t; -compatfn char *gets(char *) paramsnonnull(); -compatfn int fgetpos(FILE *, fpos_t *) paramsnonnull(); -compatfn int fsetpos(FILE *, const fpos_t *) paramsnonnull(); +char *gets(char *) paramsnonnull(); +int fgetpos(FILE *, fpos_t *) paramsnonnull(); +int fsetpos(FILE *, const fpos_t *) paramsnonnull(); int system(const char *); int systemexec(const char *); @@ -195,4 +193,4 @@ int vfprintf_unlocked(FILE *, const char *, va_list) COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_LIBC_STDIO_STDIO_H_ */ +#endif /* _STDIO_H */ diff --git a/libc/str/_tpenc.h b/libc/str/_tpenc.h deleted file mode 100755 index e69de29bb..000000000 diff --git a/libc/str/djbsort.c b/libc/str/djbsort.c index 2ad8d5055..17b0e303e 100644 --- a/libc/str/djbsort.c +++ b/libc/str/djbsort.c @@ -18,40 +18,11 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/dce.h" #include "libc/intrin/asan.internal.h" -#include "libc/intrin/bsr.h" -#include "libc/mem/alg.h" -#include "libc/nexgen32e/nexgen32e.h" #include "libc/nexgen32e/x86feature.h" +#include "libc/runtime/runtime.h" void djbsort_avx2(int32_t *, long); -static dontinline void intsort(int *x, size_t n, size_t t) { - int a, b, c; - size_t i, p, q; - for (p = t; p > 0; p >>= 1) { - for (i = 0; i < n - p; ++i) { - if (!(i & p)) { - a = x[i + 0]; - b = x[i + p]; - if (a > b) c = a, a = b, b = c; - x[i + 0] = a; - x[i + p] = b; - } - } - for (q = t; q > p; q >>= 1) { - for (i = 0; i < n - q; ++i) { - if (!(i & p)) { - a = x[i + p]; - b = x[i + q]; - if (a > b) c = a, a = b, b = c; - x[i + p] = a; - x[i + q] = b; - } - } - } - } -} - /** * D.J. Bernstein's outrageously fast integer sorting algorithm. */ @@ -65,7 +36,7 @@ void djbsort(int32_t *a, size_t n) { if (X86_HAVE(AVX2)) { djbsort_avx2(a, n); } else { - intsort(a, n, 1ul << _bsrl(n - 1)); + _intsort(a, n); } } } diff --git a/libc/str/memcasecmp.c b/libc/str/memcasecmp.c index a4a58f19d..03569ed90 100644 --- a/libc/str/memcasecmp.c +++ b/libc/str/memcasecmp.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/intrin/bits.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" /** * Compares memory case-insensitively. diff --git a/libc/str/startswithi.c b/libc/str/startswithi.c index a749d733d..cc3f81476 100644 --- a/libc/str/startswithi.c +++ b/libc/str/startswithi.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/str/str.h" +#include "libc/str/tab.internal.h" bool _startswithi(const char *s, const char *prefix) { for (;;) { diff --git a/libc/str/str.h b/libc/str/str.h index a39fd83ac..ea805da38 100644 --- a/libc/str/str.h +++ b/libc/str/str.h @@ -6,13 +6,6 @@ #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ -extern const int8_t kHexToInt[256]; -extern const uint8_t gperf_downcase[256]; -extern const uint8_t kToLower[256]; -extern const uint8_t kToUpper[256]; -extern const uint8_t kBase36[256]; -extern const char16_t kCp437[256]; - int isascii(int); int isspace(int); int isalpha(int); diff --git a/libc/str/strcasecmp.c b/libc/str/strcasecmp.c index 9dfcf80f4..cc05da1ec 100644 --- a/libc/str/strcasecmp.c +++ b/libc/str/strcasecmp.c @@ -19,6 +19,7 @@ #include "libc/dce.h" #include "libc/intrin/asan.internal.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" /** * Compares NUL-terminated strings ascii case-insensitively. diff --git a/libc/str/strcasestr.c b/libc/str/strcasestr.c index fee268a3d..1d7d31877 100644 --- a/libc/str/strcasestr.c +++ b/libc/str/strcasestr.c @@ -19,6 +19,7 @@ #include "libc/dce.h" #include "libc/intrin/asan.internal.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(16))); diff --git a/libc/str/strncasecmp.c b/libc/str/strncasecmp.c index bf6ae681a..f63658d01 100644 --- a/libc/str/strncasecmp.c +++ b/libc/str/strncasecmp.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/str/str.h" +#include "libc/str/tab.internal.h" /** * Compares NUL-terminated strings case-insensitively w/ limit. diff --git a/libc/str/tab.internal.h b/libc/str/tab.internal.h new file mode 100644 index 000000000..e6e15d33a --- /dev/null +++ b/libc/str/tab.internal.h @@ -0,0 +1,15 @@ +#ifndef COSMOPOLITAN_LIBC_STR_TAB_INTERNAL_H_ +#define COSMOPOLITAN_LIBC_STR_TAB_INTERNAL_H_ +#if !(__ASSEMBLER__ + __LINKER__ + 0) +COSMOPOLITAN_C_START_ + +extern const int8_t kHexToInt[256]; +extern const uint8_t gperf_downcase[256]; +extern const uint8_t kToLower[256]; +extern const uint8_t kToUpper[256]; +extern const uint8_t kBase36[256]; +extern const char16_t kCp437[256]; + +COSMOPOLITAN_C_END_ +#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ +#endif /* COSMOPOLITAN_LIBC_STR_TAB_INTERNAL_H_ */ diff --git a/libc/sysv/consts.sh b/libc/sysv/consts.sh index f0fa3aa50..93cba7b4a 100755 --- a/libc/sysv/consts.sh +++ b/libc/sysv/consts.sh @@ -57,11 +57,11 @@ syscon errno ESPIPE 29 29 29 29 29 25 # invalid seek; unix conse syscon errno EROFS 30 30 30 30 30 6009 # read-only filesystem; unix consensus; kNtErrorFileReadOnly; raised by access(2), acct(2), bind(2), chmod(2), chown(2), link(2), mkdir(2), mknod(2), mount(2), open(2), rename(2), rmdir(2), symlink(2), truncate(2), unlink(2), utime(2), utimensat(2) syscon errno EMLINK 31 31 31 31 31 1142 # too many links; unix consensus; kNtErrorTooManyLinks; raised by link(2), mkdir(2), rename(2) syscon errno EPIPE 32 32 32 32 32 109 # broken pipe; unix consensus; kNtErrorBrokenPipe; raised by send(2), write(2), tcp(7), unix(7), ip(7) -syscon errno EDOM 33 33 33 33 33 33 # mathematics argument out of domain of function; bsd consensus; fudged on NT; returned by cos(3), fmod(3), log1p(3), sin(3), tan(3), tgamma(3) -syscon errno ERANGE 34 34 34 34 34 34 # result too large; bsd consensus; fudged on NT; raised by getxattr(2), listxattr(2), lookup_dcookie(2), prctl(2), quotactl(2), semctl(2), semop(2), setxattr(2) +syscon errno EDOM 33 33 33 33 33 20000 # mathematics argument out of domain of function; bsd consensus; made up on NT; returned by cos(3), fmod(3), log1p(3), sin(3), tan(3), tgamma(3) +syscon errno ERANGE 34 34 34 34 34 6604 # result too large; bsd consensus; kNtErrorLogInvalidRange; raised by getxattr(2), listxattr(2), lookup_dcookie(2), prctl(2), quotactl(2), semctl(2), semop(2), setxattr(2) syscon errno EDEADLK 35 11 11 11 11 1131 # resource deadlock avoided; bsd consensus; kNtErrorPossibleDeadlock; raised by fcntl(2), keyctl(2) syscon errno ENAMETOOLONG 36 63 63 63 63 10063 # filename too long; bsd consensus; WSAENAMETOOLONG; raised by access(2), acct(2), bind(2), chdir(2), chmod(2), chown(2), chroot(2), execve(2), gethostname(2), inotify_add_watch(2), link(2), lookup_dcookie(2), mkdir(2), mknod(2), mount(2), open(2), readlink(2), rename(2), rmdir(2), spu_create(2), stat(2), statfs(2), statx(2), symlink(2), truncate(2), umount(2), unlink(2), utimensat(2) -syscon errno ENOLCK 37 77 77 77 77 0 # no locks available; bsd consensus; raised by fcntl(2), flock(2) +syscon errno ENOLCK 37 77 77 77 77 158 # no locks available; kNtErrorNotLocked; bsd consensus; raised by fcntl(2), flock(2) syscon errno ENOTEMPTY 39 66 66 66 66 145 # directory not empty; bsd consensus; kNtErrorDirNotEmpty (TODO: What is WSAENOTEMPTY? 10066); raised by rmdir(2) syscon errno ELOOP 40 62 62 62 62 1921 # too many levels of symbolic links; bsd consensus; kNtErrorCantResolveFilename; raised by access(2), acct(2), bind(2), chdir(2), chmod(2), chown(2), chroot(2), epoll_ctl(2), execve(2), execveat(2), keyctl(2), link(2), mkdir(2), mknod(2), mount(2), open(2), open_by_handle_at(2), openat2(2), readlink(2), rename(2), rmdir(2), spu_create(2), stat(2), statfs(2), statx(2), symlink(2), truncate(2), unlink(2), utimensat(2) syscon errno ENOMSG 42 91 83 90 83 0 # raised by msgop(2) @@ -328,10 +328,10 @@ syscon access R_OK 4 4 4 4 4 0x80000000 # unix consensus and kNtG # flock() flags # # group name GNU/Systemd XNU's Not UNIX! FreeBSD OpenBSD NetBSD The New Technology Commentary -syscon lock LOCK_SH 1 1 1 1 1 0 # shared [unix consensus] +syscon lock LOCK_SH 1 1 1 1 1 0 # shared [unix consensus]; hard-coded into flock-nt.c too syscon lock LOCK_EX 2 2 2 2 2 2 # exclusive [consensus!] a.k.a. kNtLockfileExclusiveLock syscon lock LOCK_NB 4 4 4 4 4 1 # non-blocking [unix consensus] a.k.a. kNtLockfileFailImmediately -syscon lock LOCK_UN 8 8 8 8 8 8 # unlock [unix consensus & faked NT] +syscon lock LOCK_UN 8 8 8 8 8 8 # unlock [unix consensus & faked NT]; hard-coded into flock-nt.c too # waitpid() / wait4() options # diff --git a/libc/sysv/consts/EAGAIN.s b/libc/sysv/consts/EAGAIN.s index 289348a8f..bec611ad4 100644 --- a/libc/sysv/consts/EAGAIN.s +++ b/libc/sysv/consts/EAGAIN.s @@ -1,2 +1,3 @@ .include "o/libc/sysv/consts/syscon.internal.inc" .syscon errno,EAGAIN,11,35,35,35,35,10035 +.yoink kDos2Errno.EAGAIN diff --git a/libc/sysv/consts/EDOM.s b/libc/sysv/consts/EDOM.s index 285a5bd8b..4f9bee5d7 100644 --- a/libc/sysv/consts/EDOM.s +++ b/libc/sysv/consts/EDOM.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon errno,EDOM,33,33,33,33,33,33 +.syscon errno,EDOM,33,33,33,33,33,20000 diff --git a/libc/sysv/consts/ENOLCK.s b/libc/sysv/consts/ENOLCK.s index a260aab23..9686bd637 100644 --- a/libc/sysv/consts/ENOLCK.s +++ b/libc/sysv/consts/ENOLCK.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon errno,ENOLCK,37,77,77,77,77,0 +.syscon errno,ENOLCK,37,77,77,77,77,158 diff --git a/libc/sysv/consts/ERANGE.s b/libc/sysv/consts/ERANGE.s index 64182ad33..121962c60 100644 --- a/libc/sysv/consts/ERANGE.s +++ b/libc/sysv/consts/ERANGE.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/consts/syscon.internal.inc" -.syscon errno,ERANGE,34,34,34,34,34,34 +.syscon errno,ERANGE,34,34,34,34,34,6604 diff --git a/libc/sysv/dos2errno.sh b/libc/sysv/dos2errno.sh index a9ca19cbb..2dea062fc 100755 --- a/libc/sysv/dos2errno.sh +++ b/libc/sysv/dos2errno.sh @@ -129,7 +129,7 @@ dos kNtErrorInvalidFunction EINVAL dos kNtErrorInvalidNetname EADDRNOTAVAIL dos kNtErrorInvalidUserBuffer EMSGSIZE dos kNtErrorIoPending EINPROGRESS -dos kNtErrorLockViolation EACCES +dos kNtErrorLockViolation EAGAIN dos kNtErrorMoreData EMSGSIZE dos kNtErrorNetnameDeleted ECONNABORTED dos kNtErrorNetworkAccessDenied EACCES @@ -139,7 +139,6 @@ dos kNtErrorNonpagedSystemResources ENOMEM dos kNtErrorNotEnoughMemory ENOMEM dos kNtErrorNotEnoughQuota ENOMEM dos kNtErrorNotFound ENOENT -dos kNtErrorNotLocked EACCES dos kNtErrorNotReady EACCES dos kNtErrorNotSupported ENOTSUP dos kNtErrorNoMoreFiles ENOENT diff --git a/libc/sysv/dos2errno/EACCES.S b/libc/sysv/dos2errno/EACCES.S index 71d4e1264..4af9d1a26 100644 --- a/libc/sysv/dos2errno/EACCES.S +++ b/libc/sysv/dos2errno/EACCES.S @@ -13,9 +13,7 @@ kDos2Errno.EACCES: .e kNtErrorCannotMake,EACCES .e kNtErrorCrc,EACCES .e kNtErrorGenFailure,EACCES - .e kNtErrorLockViolation,EACCES .e kNtErrorNetworkAccessDenied,EACCES - .e kNtErrorNotLocked,EACCES .e kNtErrorNotReady,EACCES .e kNtErrorOutOfPaper,EACCES .e kNtErrorSectorNotFound,EACCES diff --git a/libc/sysv/dos2errno/EAGAIN.S b/libc/sysv/dos2errno/EAGAIN.S new file mode 100644 index 000000000..6fa2738b8 --- /dev/null +++ b/libc/sysv/dos2errno/EAGAIN.S @@ -0,0 +1,11 @@ +// generated by libc/sysv/dos2errno.sh +#include "libc/nt/errors.h" + .macro .e doscode systemv + .short \doscode + .long \systemv + .endm + .section .sort.rodata.dos2errno.2,"a",@progbits + .globl kDos2Errno.EAGAIN + .type kDos2Errno.EAGAIN,@object +kDos2Errno.EAGAIN: + .e kNtErrorLockViolation,EAGAIN diff --git a/libc/testlib/binequals.c b/libc/testlib/binequals.c index 35fab15b0..0c3b145e5 100644 --- a/libc/testlib/binequals.c +++ b/libc/testlib/binequals.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/str/str.h" +#include "libc/str/tab.internal.h" #include "libc/testlib/testlib.h" /** diff --git a/net/http/encodeurl.c b/net/http/encodeurl.c index b486a706f..ea4a79f06 100644 --- a/net/http/encodeurl.c +++ b/net/http/encodeurl.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/mem/mem.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" #include "net/http/escape.h" #include "net/http/url.h" diff --git a/net/http/findcontenttype.c b/net/http/findcontenttype.c index e9ac53029..defb2ab42 100644 --- a/net/http/findcontenttype.c +++ b/net/http/findcontenttype.c @@ -21,6 +21,7 @@ #include "libc/intrin/bswap.h" #include "libc/macros.internal.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" #include "net/http/http.h" static const struct ContentTypeExtension { diff --git a/net/http/gethttpheader.inc b/net/http/gethttpheader.inc index f5fd11e93..cfff0bbbc 100644 --- a/net/http/gethttpheader.inc +++ b/net/http/gethttpheader.inc @@ -33,6 +33,7 @@ #line 1 "gethttpheader.gperf" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" #include "net/http/http.h" #define GPERF_DOWNCASE #line 12 "gethttpheader.gperf" diff --git a/net/http/gethttpmethod.inc b/net/http/gethttpmethod.inc index 8d45d2fd9..2c475fef2 100644 --- a/net/http/gethttpmethod.inc +++ b/net/http/gethttpmethod.inc @@ -33,6 +33,7 @@ #line 1 "gethttpmethod.gperf" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" #include "net/http/http.h" #define GPERF_DOWNCASE #line 12 "gethttpmethod.gperf" diff --git a/net/http/ismimetype.c b/net/http/ismimetype.c index 45a35b107..1d0e8c49f 100644 --- a/net/http/ismimetype.c +++ b/net/http/ismimetype.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/str/str.h" +#include "libc/str/tab.internal.h" #include "net/http/http.h" /** diff --git a/net/http/parseurl.c b/net/http/parseurl.c index dfcbbfde9..7fa60fd52 100644 --- a/net/http/parseurl.c +++ b/net/http/parseurl.c @@ -20,6 +20,7 @@ #include "libc/limits.h" #include "libc/mem/mem.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" #include "libc/x/x.h" #include "net/http/escape.h" #include "net/http/url.h" diff --git a/net/http/unchunk.c b/net/http/unchunk.c index f87750ffc..f854244e2 100644 --- a/net/http/unchunk.c +++ b/net/http/unchunk.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/macros.internal.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" #include "libc/sysv/errfuns.h" #include "net/http/escape.h" #include "net/http/http.h" diff --git a/test/libc/calls/fcntl_test.c b/test/libc/calls/fcntl_test.c index e4c4a4ce6..5af72435b 100644 --- a/test/libc/calls/fcntl_test.c +++ b/test/libc/calls/fcntl_test.c @@ -30,8 +30,29 @@ #include "libc/sysv/consts/o.h" #include "libc/sysv/consts/sig.h" #include "libc/testlib/testlib.h" +#include "libc/thread/thread.h" #include "libc/x/x.h" +int Lock(int fd, int type, long start, long len) { + int e; + struct flock lock = { + .l_type = type, + .l_whence = SEEK_SET, + .l_start = start, + .l_len = len, + }; + e = errno; + while (fcntl(fd, F_SETLK, &lock)) { + if (errno == EAGAIN || errno == EACCES) { + errno = e; + continue; + } else { + return -1; + } + } + return 0; +} + char testlib_enable_tmp_setup_teardown; TEST(fcntl_getfl, testRemembersAccessMode) { @@ -70,59 +91,15 @@ TEST(fcntl, getfd) { ASSERT_SYS(0, 0, close(3)); } -void OnSig(int sig) { +TEST(fcntl, F_DUPFD_CLOEXEC) { + ASSERT_SYS(0, 3, open("/dev/null", O_RDWR)); + ASSERT_SYS(0, 5, fcntl(3, F_DUPFD_CLOEXEC, 5)); + ASSERT_SYS(0, FD_CLOEXEC, fcntl(5, F_GETFD)); + ASSERT_SYS(0, 0, close(5)); + ASSERT_SYS(0, 0, close(3)); } -TEST(posixAdvisoryLocks, oneProcess_unlockedFromOwnPerspectiveHuh) { - struct flock lock; - ASSERT_SYS(0, 3, open("foo", O_RDWR | O_CREAT | O_TRUNC, 0644)); - ASSERT_SYS(0, 5, write(3, "hello", 5)); - - // set lock - lock.l_type = F_WRLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 1; - lock.l_len = 3; - lock.l_pid = -2; - ASSERT_SYS(0, 0, fcntl(3, F_SETLK, &lock)); - EXPECT_EQ(F_WRLCK, lock.l_type); - EXPECT_EQ(SEEK_SET, lock.l_whence); - EXPECT_EQ(1, lock.l_start); - EXPECT_EQ(3, lock.l_len); - EXPECT_EQ(-2, lock.l_pid); - - ASSERT_SYS(0, 4, open("foo", O_RDWR)); - - // try lock - lock.l_type = F_WRLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 0; - lock.l_pid = -1; - ASSERT_SYS(0, 0, fcntl(4, F_SETLK, &lock)); - EXPECT_EQ(F_WRLCK, lock.l_type); - EXPECT_EQ(SEEK_SET, lock.l_whence); - EXPECT_EQ(0, lock.l_start); - EXPECT_EQ(0, lock.l_len); - EXPECT_EQ(-1, lock.l_pid); - - // get lock information - if (!IsWindows()) { - lock.l_type = F_RDLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 0; - lock.l_pid = -7; - ASSERT_SYS(0, 0, fcntl(4, F_GETLK, &lock)); - EXPECT_EQ(F_UNLCK, lock.l_type); - EXPECT_EQ(SEEK_SET, lock.l_whence); - EXPECT_EQ(0, lock.l_start); - EXPECT_EQ(0, lock.l_len); - EXPECT_EQ(-7, lock.l_pid); // doesn't change due to F_UNLCK - } - - ASSERT_SYS(0, 0, close(4)); - ASSERT_SYS(0, 0, close(3)); +void OnSig(int sig) { } TEST(posixAdvisoryLocks, twoProcesses) { diff --git a/test/libc/calls/lock_test.c b/test/libc/calls/lock_test.c new file mode 100644 index 000000000..c9f454a82 --- /dev/null +++ b/test/libc/calls/lock_test.c @@ -0,0 +1,186 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2022 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" +#include "libc/calls/struct/flock.h" +#include "libc/dce.h" +#include "libc/errno.h" +#include "libc/intrin/kprintf.h" +#include "libc/macros.internal.h" +#include "libc/runtime/runtime.h" +#include "libc/sysv/consts/f.h" +#include "libc/sysv/consts/o.h" +#include "libc/testlib/testlib.h" +#include "libc/thread/thread.h" + +/** + * @fileoverview POSIX Advisory Locks Test + */ + +#define PROCESSES 8 +#define THREADS (IsWindows() ? 8 : 0) +#define RATIO 3 +#define ITERATIONS 10 + +char testlib_enable_tmp_setup_teardown; + +_Thread_local const char *kind; + +void Log(const char *fmt, ...) { +#if 0 + va_list va; + char b[512]; + int i, n = sizeof(b); + va_start(va, fmt); + i = ksnprintf(b, n, "%s pid=%d tid=%d ", kind, getpid(), gettid()); + i += kvsnprintf(b + i, MAX(0, n - i), fmt, va); + i += ksnprintf(b + i, MAX(0, n - i), "\n"); + write(2, b, MIN(i, n)); + va_end(va); +#endif +} + +void Lock(int fd, int type, long start, long len) { + int e; + struct flock lock = { + .l_type = type, + .l_whence = SEEK_SET, + .l_start = start, + .l_len = len, + }; + e = errno; + while (fcntl(fd, F_SETLK, &lock)) { + ASSERT_TRUE(errno == EAGAIN || errno == EACCES); + errno = e; + Log("flock spinning on %d", fd); + } +} + +void WriteLock(int fd, long start, long len) { + Lock(fd, F_WRLCK, start, len); + Log("acquired write lock on %d", fd); +} + +void ReadLock(int fd, long start, long len) { + Lock(fd, F_RDLCK, start, len); + Log("acquired read lock on %d", fd); +} + +void Unlock(int fd, long start, long len) { + Lock(fd, F_UNLCK, start, len); + Log("released lock on %d", fd); +} + +void *Reader(void *arg) { + int i, j, fd; + char buf[10]; + kind = arg; + ASSERT_NE(-1, (fd = open("db", O_RDONLY))); + for (j = 0; j < ITERATIONS; ++j) { + ReadLock(fd, 10, 10); + for (i = 0; i < 10; ++i) { + ASSERT_SYS(0, 1, pread(fd, buf + i, 1, 10 + i)); + ASSERT_EQ(buf[0], buf[i]); + } + Unlock(fd, 10, 10); + sched_yield(); + } + ASSERT_SYS(0, 0, close(fd)); + return 0; +} + +void *Writer(void *arg) { + int i, j, fd; + char buf[10]; + kind = arg; + ASSERT_NE(-1, (fd = open("db", O_RDWR))); + for (j = 0; j < ITERATIONS; ++j) { + WriteLock(fd, 10, 10); + for (i = 0; i < 10; ++i) { + ASSERT_SYS(0, 1, pread(fd, buf + i, 1, 10 + i)); + ASSERT_EQ(buf[0], buf[i]); + } + for (i = 0; i < 10; ++i) { + buf[i]++; + } + for (i = 0; i < 10; ++i) { + ASSERT_SYS(0, 1, pwrite(fd, buf + i, 1, 10 + i)); + } + Unlock(fd, 10, 10); + sched_yield(); + } + ASSERT_SYS(0, 0, close(fd)); + return 0; +} + +TEST(posixAdvisoryLocks, threadsAndProcessesFightingForLock) { + int i, rc, pid, fd, ws; + pthread_t th[THREADS + 1]; + + ASSERT_SYS(0, 3, creat("db", 0644)); + ASSERT_SYS(0, 0, ftruncate(3, 30)); + ASSERT_SYS(0, 0, close(3)); + + for (i = 0; i < THREADS; ++i) { + if (i % RATIO == 0) { + ASSERT_EQ(0, pthread_create(th + i, 0, Reader, "reader thread")); + } else { + ASSERT_EQ(0, pthread_create(th + i, 0, Writer, "writer thread")); + } + } + + for (i = 0; i < PROCESSES; ++i) { + ASSERT_NE(-1, (rc = fork())); + if (!rc) { + if (i % RATIO == 0) { + Writer("writer process"); + } else { + Reader("reader process"); + } + _Exit(0); + } + } + + ASSERT_NE(-1, (fd = open("db", O_RDWR))); + Lock(fd, F_WRLCK, 0, 10); + Lock(fd, F_WRLCK, 20, 10); + + for (i = 0; i < THREADS; ++i) { + ASSERT_EQ(0, pthread_join(th[i], 0)); + } + + kind = "main process"; + for (;;) { + int e = errno; + if ((pid = waitpid(0, &ws, 0)) != -1) { + if (WIFSIGNALED(ws)) { + Log("process %d terminated with %G", pid, WTERMSIG(ws)); + testlib_incrementfailed(); + } else if (WEXITSTATUS(ws)) { + Log("process %d exited with %d", pid, WEXITSTATUS(ws)); + testlib_incrementfailed(); + } + } else { + ASSERT_EQ(ECHILD, errno); + errno = e; + break; + } + } + + ASSERT_SYS(0, 0, close(fd)); +} diff --git a/test/libc/calls/pledge_test.c b/test/libc/calls/pledge_test.c index b5d02d59c..beb8dfbcc 100644 --- a/test/libc/calls/pledge_test.c +++ b/test/libc/calls/pledge_test.c @@ -560,7 +560,7 @@ TEST(pledge_openbsd, bigSyscalls) { int LockWorker(void *arg, int tid) { flockfile(stdout); - ASSERT_EQ(gettid(), stdout->lock._owner); + ASSERT_EQ(gettid(), ((pthread_mutex_t *)stdout->lock)->_owner); funlockfile(stdout); return 0; } diff --git a/test/libc/calls/preadv_test.c b/test/libc/calls/preadv_test.c new file mode 100644 index 000000000..2a74a62b1 --- /dev/null +++ b/test/libc/calls/preadv_test.c @@ -0,0 +1,91 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2022 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/assert.h" +#include "libc/calls/calls.h" +#include "libc/calls/internal.h" +#include "libc/calls/struct/iovec.h" +#include "libc/errno.h" +#include "libc/nt/files.h" +#include "libc/sysv/consts/o.h" +#include "libc/testlib/testlib.h" + +char testlib_enable_tmp_setup_teardown; + +TEST(preadv, ebadf) { + EXPECT_SYS(EBADF, -1, preadv(-1, 0, 0, 0)); + EXPECT_SYS(EBADF, -1, pwritev(-1, 0, 0, 0)); +} + +TEST(preadv, testOneIovecWorks_itDelegatesToPread) { + char b1[2] = "hi"; + struct iovec v[1] = {{b1, 2}}; + ASSERT_SYS(0, 3, open("foo", O_RDWR | O_CREAT | O_TRUNC, 0644)); + EXPECT_SYS(0, 2, pwritev(3, v, 1, 0)); + b1[0] = 0; + b1[1] = 0; + EXPECT_SYS(0, 0, preadv(3, 0, 0, 0)); + EXPECT_SYS(0, 0, pwritev(3, 0, 0, 0)); + EXPECT_SYS(0, 2, preadv(3, v, 1, 0)); + ASSERT_EQ('h', b1[0]); + ASSERT_EQ('i', b1[1]); + b1[0] = 0; + b1[1] = 0x55; + EXPECT_SYS(0, 1, preadv(3, v, 1, 1)); + ASSERT_EQ('i', b1[0]); + ASSERT_EQ(0x55, b1[1]); + ASSERT_SYS(0, 0, close(3)); +} + +TEST(preadv, testTwoIovecWorks_itMustDoItsThing) { + char b1[1] = "h"; + char b2[1] = "i"; + struct iovec v[2] = {{b1, 1}, {b2, 1}}; + ASSERT_SYS(0, 3, open("foo", O_RDWR | O_CREAT | O_TRUNC, 0644)); + EXPECT_SYS(0, 2, pwritev(3, v, 2, 0)); + b1[0] = 0; + b2[0] = 0; + EXPECT_SYS(0, 2, preadv(3, v, 2, 0)); + ASSERT_EQ('h', b1[0]); + ASSERT_EQ('i', b2[0]); + b1[0] = 0; + b2[0] = 0x55; + EXPECT_SYS(0, 1, preadv(3, v, 2, 1)); + ASSERT_EQ('i', b1[0]); + ASSERT_EQ(0x55, b2[0]); + ASSERT_SYS(0, 0, close(3)); +} + +TEST(pwritev, writePastEof_zeroExtendsFile_alsoDoesntChangeFilePointer) { + char b[6] = {0x55, 0x55, 0x55, 0x55, 0x55, 0x55}; + char s[2] = "hi"; + struct iovec v[1] = {{s, 2}}; + ASSERT_SYS(0, 3, open("foo", O_RDWR | O_CREAT | O_TRUNC, 0644)); + ASSERT_SYS(EINVAL, -1, pwritev(3, v, 1, -999)); + ASSERT_SYS(0, 2, pwritev(3, v, 1, 0)); + ASSERT_SYS(0, 2, pwritev(3, v, 1, 4)); + ASSERT_SYS(0, 2, preadv(3, v, 1, 0)); + ASSERT_SYS(0, 6, read(3, b, 6)); + ASSERT_EQ('h', b[0]); + ASSERT_EQ('i', b[1]); + ASSERT_EQ(0, b[2]); + ASSERT_EQ(0, b[3]); + ASSERT_EQ('h', b[4]); + ASSERT_EQ('i', b[5]); + ASSERT_SYS(0, 0, close(3)); +} diff --git a/test/libc/calls/test.mk b/test/libc/calls/test.mk index 16c467504..ff00f3200 100644 --- a/test/libc/calls/test.mk +++ b/test/libc/calls/test.mk @@ -38,6 +38,7 @@ TEST_LIBC_CALLS_DIRECTDEPS = \ LIBC_MEM \ LIBC_NEXGEN32E \ LIBC_STDIO \ + LIBC_NT_KERNEL32 \ LIBC_SYSV_CALLS \ LIBC_RUNTIME \ LIBC_STR \ @@ -103,6 +104,9 @@ o/$(MODE)/test/libc/calls/poll_test.com.runs: \ o/$(MODE)/test/libc/calls/fcntl_test.com.runs: \ private .PLEDGE = stdio rpath wpath cpath fattr proc flock +o/$(MODE)/test/libc/calls/lock_test.com.runs: \ + private .PLEDGE = stdio rpath wpath cpath fattr proc flock + o/$(MODE)/test/libc/calls/openbsd_test.com.runs: \ private .PLEDGE = stdio rpath wpath cpath fattr proc unveil diff --git a/test/libc/intrin/dos2errno_test.c b/test/libc/intrin/dos2errno_test.c index db4b6ccda..1438bfffb 100644 --- a/test/libc/intrin/dos2errno_test.c +++ b/test/libc/intrin/dos2errno_test.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/dce.h" #include "libc/errno.h" #include "libc/intrin/dos2errno.internal.h" #include "libc/intrin/kprintf.h" @@ -28,4 +29,8 @@ TEST(__dos2errno, test) { EXPECT_EQ(0, __dos2errno(0)); EXPECT_EQ(EACCES, __dos2errno(kNtErrorSectorNotFound)); EXPECT_EQ(EADDRNOTAVAIL, __dos2errno(kNtErrorInvalidNetname)); + EXPECT_EQ(EAGAIN, __dos2errno(33)); + if (IsWindows()) { + EXPECT_EQ(ENOLCK, __dos2errno(kNtErrorNotLocked)); + } } diff --git a/test/libc/mem/djbsort_test.c b/test/libc/mem/djbsort_test.c index ce7b379b0..e419a09fb 100644 --- a/test/libc/mem/djbsort_test.c +++ b/test/libc/mem/djbsort_test.c @@ -20,10 +20,11 @@ #include "libc/log/log.h" #include "libc/macros.internal.h" #include "libc/mem/alg.h" +#include "libc/mem/gc.h" #include "libc/mem/mem.h" #include "libc/nexgen32e/nexgen32e.h" #include "libc/nexgen32e/x86feature.h" -#include "libc/mem/gc.internal.h" +#include "libc/runtime/runtime.h" #include "libc/stdio/rand.h" #include "libc/stdio/stdio.h" #include "libc/str/str.h" @@ -52,9 +53,9 @@ void insertionsort(int32_t *a, size_t n) { TEST(djbsort, test4) { static const int kA[] = {4, 3, 2, 1}; n = ARRAYLEN(kA); - a = memcpy(gc(malloc(n * 4)), kA, n * 4); - b = memcpy(gc(malloc(n * 4)), kA, n * 4); - c = memcpy(gc(malloc(n * 4)), kA, n * 4); + a = memcpy(_gc(malloc(n * 4)), kA, n * 4); + b = memcpy(_gc(malloc(n * 4)), kA, n * 4); + c = memcpy(_gc(malloc(n * 4)), kA, n * 4); insertionsort(a, n); djbsort_avx2(b, n); djbsort(c, n); @@ -79,9 +80,9 @@ TEST(djbsort, test64) { -1323943608, -1219421355, -582289873, 1062699814, }; n = ARRAYLEN(kA); - a = memcpy(gc(malloc(n * 4)), kA, n * 4); - b = memcpy(gc(malloc(n * 4)), kA, n * 4); - c = memcpy(gc(malloc(n * 4)), kA, n * 4); + a = memcpy(_gc(malloc(n * 4)), kA, n * 4); + b = memcpy(_gc(malloc(n * 4)), kA, n * 4); + c = memcpy(_gc(malloc(n * 4)), kA, n * 4); insertionsort(a, n); djbsort(c, n); ASSERT_EQ(0, memcmp(a, c, n * 4)); @@ -91,10 +92,19 @@ TEST(djbsort, test64) { } } +static int CompareInt(const void *a, const void *b) { + if (*(const int *)a < *(const int *)b) return -1; + if (*(const int *)a > *(const int *)b) return +1; + return 0; +} + BENCH(djbsort, bench) { n = 256; - a = gc(memalign(32, n * 4)); + a = _gc(memalign(32, n * 4)); EZBENCH2("insertionsort[255]", rngset(a, n * 4, rand64, -1), insertionsort(a, n)); EZBENCH2("djbsort[255]", rngset(a, n * 4, rand64, -1), djbsort(a, n)); + EZBENCH2("_intsort[255]", rngset(a, n * 4, rand64, -1), _intsort(a, n)); + EZBENCH2("qsort[255]", rngset(a, n * 4, rand64, -1), + qsort(a, n, sizeof(int), CompareInt)); } diff --git a/test/libc/nexgen32e/kbase36_test.c b/test/libc/nexgen32e/kbase36_test.c index 86a7e1fa5..6699c2fa1 100644 --- a/test/libc/nexgen32e/kbase36_test.c +++ b/test/libc/nexgen32e/kbase36_test.c @@ -16,8 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/nexgen32e/nexgen32e.h" -#include "libc/str/str.h" +#include "libc/str/tab.internal.h" #include "libc/testlib/testlib.h" TEST(kBase36, test) { diff --git a/test/libc/nexgen32e/kcp437_test.c b/test/libc/nexgen32e/kcp437_test.c index 2497ff162..abfcd9615 100644 --- a/test/libc/nexgen32e/kcp437_test.c +++ b/test/libc/nexgen32e/kcp437_test.c @@ -16,10 +16,9 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/nexgen32e/nexgen32e.h" -#include "libc/str/str.h" -#include "libc/testlib/testlib.h" +#include "libc/str/tab.internal.h" #include "libc/str/unicode.h" +#include "libc/testlib/testlib.h" TEST(kcp437, test) { long i; diff --git a/test/libc/str/blake2_test.c b/test/libc/str/blake2_test.c index cee7d1f22..bc669e6e8 100644 --- a/test/libc/str/blake2_test.c +++ b/test/libc/str/blake2_test.c @@ -21,6 +21,7 @@ #include "libc/stdio/rand.h" #include "libc/str/blake2.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" #include "libc/testlib/ezbench.h" #include "libc/testlib/hyperion.h" #include "libc/testlib/testlib.h" diff --git a/test/libc/str/strcasestr_test.c b/test/libc/str/strcasestr_test.c index 0bd777e94..ac8d93cd8 100644 --- a/test/libc/str/strcasestr_test.c +++ b/test/libc/str/strcasestr_test.c @@ -16,13 +16,14 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/mem/alg.h" -#include "libc/intrin/bits.h" #include "libc/dce.h" +#include "libc/intrin/bits.h" +#include "libc/mem/alg.h" +#include "libc/mem/gc.internal.h" #include "libc/mem/mem.h" #include "libc/nexgen32e/x86feature.h" -#include "libc/mem/gc.internal.h" #include "libc/str/internal.h" +#include "libc/str/tab.internal.h" #include "libc/testlib/ezbench.h" #include "libc/testlib/hyperion.h" #include "libc/testlib/testlib.h" diff --git a/test/tool/net/sqlite_test.c b/test/tool/net/sqlite_test.c index dc5340790..0ef05fbf9 100644 --- a/test/tool/net/sqlite_test.c +++ b/test/tool/net/sqlite_test.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/dce.h" #include "libc/testlib/testlib.h" #include "third_party/sqlite3/sqlite3.h" diff --git a/third_party/chibicc/as.c b/third_party/chibicc/as.c index 56f66d6f9..32b82b8b9 100644 --- a/third_party/chibicc/as.c +++ b/third_party/chibicc/as.c @@ -31,6 +31,7 @@ #include "libc/runtime/runtime.h" #include "libc/stdio/stdio.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" #include "libc/sysv/consts/o.h" #include "libc/sysv/consts/s.h" #include "libc/x/x.h" diff --git a/third_party/chibicc/tokenize.c b/third_party/chibicc/tokenize.c index b6d213837..a0d59d415 100644 --- a/third_party/chibicc/tokenize.c +++ b/third_party/chibicc/tokenize.c @@ -2,6 +2,7 @@ #include "libc/log/log.h" #include "libc/runtime/runtime.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" #include "third_party/chibicc/chibicc.h" #include "third_party/chibicc/file.h" #include "third_party/chibicc/kw.h" diff --git a/third_party/linenoise/linenoise.c b/third_party/linenoise/linenoise.c index 5819c47ab..f98e33a36 100644 --- a/third_party/linenoise/linenoise.c +++ b/third_party/linenoise/linenoise.c @@ -154,6 +154,7 @@ #include "libc/stdio/append.h" #include "libc/stdio/stdio.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" #include "libc/str/unicode.h" #include "libc/sysv/consts/fileno.h" #include "libc/sysv/consts/map.h" diff --git a/third_party/lua/llock.c b/third_party/lua/llock.c index b9eb6a9a8..992d700a4 100644 --- a/third_party/lua/llock.c +++ b/third_party/lua/llock.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/thread/thread.h" #include "third_party/lua/lrepl.h" static pthread_mutex_t lua_repl_lock_obj; diff --git a/third_party/python/Include/pyctype.h b/third_party/python/Include/pyctype.h index 05ea304b3..58ad51ca4 100644 --- a/third_party/python/Include/pyctype.h +++ b/third_party/python/Include/pyctype.h @@ -1,7 +1,7 @@ #ifndef Py_LIMITED_API #ifndef PYCTYPE_H #define PYCTYPE_H -#include "libc/str/str.h" +#include "libc/str/tab.internal.h" #define Py_TOLOWER(c) kToLower[255 & (c)] #define Py_TOUPPER(c) kToUpper[255 & (c)] diff --git a/third_party/sqlite3/main.c b/third_party/sqlite3/main.c index 31673e193..02e7fe6a8 100644 --- a/third_party/sqlite3/main.c +++ b/third_party/sqlite3/main.c @@ -3105,6 +3105,10 @@ static int openDatabase( char *zErrMsg = 0; /* Error message from sqlite3ParseUri() */ int i; /* Loop counter */ + // TODO(jart): Fix SQLite. + extern bool __force_sqlite_to_work_until_we_can_fix_it; + __force_sqlite_to_work_until_we_can_fix_it = true; + #ifdef SQLITE_ENABLE_API_ARMOR if( ppDb==0 ) return SQLITE_MISUSE_BKPT; #endif diff --git a/tool/build/blinkenlights.c b/tool/build/blinkenlights.c index 8c3d71a3c..0171519e4 100644 --- a/tool/build/blinkenlights.c +++ b/tool/build/blinkenlights.c @@ -59,6 +59,7 @@ #include "libc/stdio/stdio.h" #include "libc/str/str.h" #include "libc/str/strwidth.h" +#include "libc/str/tab.internal.h" #include "libc/str/thompike.h" #include "libc/str/tpdecode.internal.h" #include "libc/str/tpencode.internal.h" diff --git a/tool/build/lib/cga.c b/tool/build/lib/cga.c index 016b641ab..144d9c7f6 100644 --- a/tool/build/lib/cga.c +++ b/tool/build/lib/cga.c @@ -19,6 +19,7 @@ #include "libc/fmt/itoa.h" #include "libc/macros.internal.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" #include "tool/build/lib/buffer.h" #include "tool/build/lib/cga.h" diff --git a/tool/build/lib/isnocompressext.c b/tool/build/lib/isnocompressext.c index d6dcf3151..3f1b60be8 100644 --- a/tool/build/lib/isnocompressext.c +++ b/tool/build/lib/isnocompressext.c @@ -20,6 +20,7 @@ #include "libc/intrin/bswap.h" #include "libc/macros.internal.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" #include "tool/build/lib/isnocompressext.h" static const char kNoCompressExts[][8] = { diff --git a/tool/build/lib/mda.c b/tool/build/lib/mda.c index 52b9ab678..012509479 100644 --- a/tool/build/lib/mda.c +++ b/tool/build/lib/mda.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/macros.internal.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" #include "tool/build/lib/buffer.h" #include "tool/build/lib/mda.h" diff --git a/tool/build/lz4toasm.c b/tool/build/lz4toasm.c index 6f16ca23c..ee6eb079d 100644 --- a/tool/build/lz4toasm.c +++ b/tool/build/lz4toasm.c @@ -22,14 +22,15 @@ #include "libc/log/check.h" #include "libc/log/log.h" #include "libc/macros.internal.h" +#include "libc/mem/gc.internal.h" #include "libc/mem/mem.h" #include "libc/nexgen32e/kompressor.h" #include "libc/nexgen32e/lz4.h" #include "libc/runtime/ezmap.internal.h" -#include "libc/mem/gc.internal.h" #include "libc/runtime/runtime.h" #include "libc/stdio/stdio.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" #include "libc/x/x.h" #include "third_party/getopt/getopt.h" diff --git a/tool/build/pledge.c b/tool/build/pledge.c index 937e67676..be6c47df7 100644 --- a/tool/build/pledge.c +++ b/tool/build/pledge.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/assert.h" #include "libc/calls/calls.h" +#include "libc/calls/copyfd.internal.h" #include "libc/calls/landlock.h" #include "libc/calls/pledge.h" #include "libc/calls/pledge.internal.h" @@ -39,10 +40,9 @@ #include "libc/intrin/safemacros.internal.h" #include "libc/macros.internal.h" #include "libc/math.h" -#include "libc/calls/copyfd.internal.h" +#include "libc/mem/gc.internal.h" #include "libc/mem/mem.h" #include "libc/nexgen32e/kcpuids.h" -#include "libc/mem/gc.internal.h" #include "libc/runtime/runtime.h" #include "libc/runtime/sysconf.h" #include "libc/sock/sock.h" diff --git a/tool/build/xlat.c b/tool/build/xlat.c index 68f298597..9a6655886 100644 --- a/tool/build/xlat.c +++ b/tool/build/xlat.c @@ -21,11 +21,12 @@ #include "libc/fmt/conv.h" #include "libc/log/check.h" #include "libc/math.h" -#include "libc/mem/mem.h" #include "libc/mem/gc.h" +#include "libc/mem/mem.h" #include "libc/runtime/runtime.h" #include "libc/stdio/stdio.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" #include "libc/x/xasprintf.h" /** diff --git a/tool/decode/lib/disassemblehex.c b/tool/decode/lib/disassemblehex.c index 4a7b0a964..e86137de8 100644 --- a/tool/decode/lib/disassemblehex.c +++ b/tool/decode/lib/disassemblehex.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/stdio/stdio.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" #include "tool/decode/lib/disassemblehex.h" static size_t countzeroes(const uint8_t *data, size_t size) { diff --git a/tool/hash/crctab.c b/tool/hash/crctab.c index a111abb5e..63da79974 100644 --- a/tool/hash/crctab.c +++ b/tool/hash/crctab.c @@ -16,8 +16,8 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/intrin/bits.h" #include "libc/fmt/conv.h" +#include "libc/intrin/bits.h" #include "libc/macros.internal.h" #include "libc/nexgen32e/crc32.h" #include "libc/runtime/runtime.h" diff --git a/tool/net/ljson.c b/tool/net/ljson.c index efb20606a..d929b3792 100644 --- a/tool/net/ljson.c +++ b/tool/net/ljson.c @@ -22,6 +22,7 @@ #include "libc/log/log.h" #include "libc/runtime/stack.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" #include "libc/str/utf16.h" #include "third_party/double-conversion/wrapper.h" #include "third_party/lua/cosmo.h" diff --git a/tool/viz/bf.c b/tool/viz/bf.c index 746e2e38e..454e6021d 100644 --- a/tool/viz/bf.c +++ b/tool/viz/bf.c @@ -25,6 +25,7 @@ #include "libc/macros.internal.h" #include "libc/runtime/runtime.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" #include "libc/sysv/consts/o.h" #include "libc/sysv/consts/s.h" diff --git a/tool/viz/bin2asm.c b/tool/viz/bin2asm.c index 4e2e19457..afbcc8019 100644 --- a/tool/viz/bin2asm.c +++ b/tool/viz/bin2asm.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/stdio/stdio.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" #define COLS 8 diff --git a/tool/viz/bing.c b/tool/viz/bing.c index 48b4738d0..672637e64 100644 --- a/tool/viz/bing.c +++ b/tool/viz/bing.c @@ -21,6 +21,7 @@ #include "libc/runtime/runtime.h" #include "libc/stdio/stdio.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" #include "libc/sysv/consts/ex.h" #include "libc/sysv/consts/exit.h" #include "libc/sysv/consts/fileno.h" diff --git a/tool/viz/memzoom.c b/tool/viz/memzoom.c index 4ddeb649d..b9bcf4201 100644 --- a/tool/viz/memzoom.c +++ b/tool/viz/memzoom.c @@ -41,6 +41,7 @@ #include "libc/sock/struct/pollfd.h" #include "libc/stdio/stdio.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" #include "libc/str/unicode.h" #include "libc/sysv/consts/ex.h" #include "libc/sysv/consts/exit.h" diff --git a/tool/viz/unbing.c b/tool/viz/unbing.c index ccad3ca76..fad80b9d3 100644 --- a/tool/viz/unbing.c +++ b/tool/viz/unbing.c @@ -19,6 +19,7 @@ #include "libc/calls/calls.h" #include "libc/stdio/stdio.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" /** * @fileoverview UnBing: Glyphs → Binary.