diff --git a/examples/printargs.c b/examples/printargs.c index 039205d5e..bf460c294 100644 --- a/examples/printargs.c +++ b/examples/printargs.c @@ -20,39 +20,56 @@ const struct AuxiliaryValue { const char *name; const char *description; } kAuxiliaryValues[] = { - {"%p", &AT_EXECFD, "AT_EXECFD", "file descriptor of program"}, - {"%p", &AT_PHDR, "AT_PHDR", "address of elf program headers"}, - {"%p", &AT_PHENT, "AT_PHENT", "size of program header entry"}, - {"%p", &AT_PHNUM, "AT_PHNUM", "number of program headers"}, - {"%p", &AT_PAGESZ, "AT_PAGESZ", "system page size"}, - {"%p", &AT_BASE, "AT_BASE", "base address of the program interpreter"}, - {"%p", &AT_ENTRY, "AT_ENTRY", "entry address of executable"}, - {"%p", &AT_NOTELF, "AT_NOTELF", "set if not an elf"}, + {"%012lx", &AT_EXECFD, "AT_EXECFD", "file descriptor of program"}, + {"%012lx", &AT_PHDR, "AT_PHDR", "address of elf program headers"}, + {"%012lx", &AT_PHENT, "AT_PHENT", "size of program header entry"}, + {"%012lx", &AT_PHNUM, "AT_PHNUM", "number of program headers"}, + {"%012lx", &AT_PAGESZ, "AT_PAGESZ", "system page size"}, + {"%012lx", &AT_BASE, "AT_BASE", "base address of the program interpreter"}, + {"%012lx", &AT_ENTRY, "AT_ENTRY", "entry address of executable"}, + {"%012lx", &AT_NOTELF, "AT_NOTELF", "set if not an elf"}, {"%-12d", &AT_UID, "AT_UID", "real user id of thread"}, {"%-12d", &AT_EUID, "AT_EUID", "effective user id of thread"}, {"%-12d", &AT_GID, "AT_GID", "real group id of thread"}, {"%-12d", &AT_EGID, "AT_EGID", "effective group id of thread"}, {"%-12d", &AT_CLKTCK, "AT_CLKTCK", "frequency of times() counts"}, - {"%p", &AT_OSRELDATE, "AT_OSRELDATE", + {"%012lx", &AT_OSRELDATE, "AT_OSRELDATE", "freebsd release number, e.g. 1200086"}, - {"%p", &AT_PLATFORM, "AT_PLATFORM", "string identifying hardware platform"}, - {"%p", &AT_DCACHEBSIZE, "AT_DCACHEBSIZE", "data cache block size"}, - {"%p", &AT_ICACHEBSIZE, "AT_ICACHEBSIZE", "instruction cache block size"}, - {"%p", &AT_UCACHEBSIZE, "AT_UCACHEBSIZE", "unified cache block size"}, - {"%p", &AT_SECURE, "AT_SECURE", "for set{u,g}id binz & security blankets"}, + {"%012lx", &AT_PLATFORM, "AT_PLATFORM", + "string identifying hardware platform"}, + {"%012lx", &AT_DCACHEBSIZE, "AT_DCACHEBSIZE", "data cache block size"}, + {"%012lx", &AT_ICACHEBSIZE, "AT_ICACHEBSIZE", + "instruction cache block size"}, + {"%012lx", &AT_UCACHEBSIZE, "AT_UCACHEBSIZE", "unified cache block size"}, + {"%012lx", &AT_SECURE, "AT_SECURE", + "for set{u,g}id binz & security blankets"}, {"%-12s", &AT_BASE_PLATFORM, "AT_BASE_PLATFORM", "string identifying real platform"}, - {"%p", &AT_RANDOM, "AT_RANDOM", "address of sixteen random bytes"}, + {"%012lx", &AT_RANDOM, "AT_RANDOM", "address of sixteen random bytes"}, {"%-12s", &AT_EXECFN, "AT_EXECFN", "pathname used to execute program"}, - {"%p", &AT_SYSINFO_EHDR, "AT_SYSINFO_EHDR", + {"%012lx", &AT_SYSINFO_EHDR, "AT_SYSINFO_EHDR", "linux virtual dso page address"}, + {"%012lx", &AT_FLAGS, "AT_FLAGS", "unused?"}, + {"%012lx", &AT_HWCAP, "AT_HWCAP", "cpu stuff"}, + {"%012lx", &AT_HWCAP2, "AT_HWCAP2", "more cpu stuff"}, }; +const struct AuxiliaryValue *DescribeAuxv(unsigned long x) { + int i; + for (i = 0; i < ARRAYLEN(kAuxiliaryValues); ++i) { + if (x == *kAuxiliaryValues[i].id) { + return kAuxiliaryValues + i; + } + } + return NULL; +} + int main(int argc, char *argv[], char **envp) { long key; unsigned i; - unsigned long val; + unsigned long *auxp; char fmt[64], **env; + struct AuxiliaryValue *auxinfo; printf("\nArguments:\n"); for (i = 0; i < __argc; ++i) { printf(" ☼ %s\n", argv[i]); @@ -62,13 +79,13 @@ int main(int argc, char *argv[], char **envp) { printf(" ☼ %s\n", *env); } printf("\nAuxiliary Values:\n"); - for (i = 0; i < ARRAYLEN(kAuxiliaryValues); ++i) { - key = *kAuxiliaryValues[i].id; - val = getauxval(key); - stpcpy(stpcpy(stpcpy(fmt, "%16s[%p] = "), kAuxiliaryValues[i].fmt), - " # %s\n"); - printf(fmt, kAuxiliaryValues[i].name, key, val, - kAuxiliaryValues[i].description); + for (auxp = __auxv; *auxp; auxp += 2) { + if ((auxinfo = DescribeAuxv(auxp[0]))) { + stpcpy(stpcpy(stpcpy(fmt, "%16s[%4ld] = "), auxinfo->fmt), " # %s\n"); + printf(fmt, auxinfo->name, auxp[0], auxp[1], auxinfo->description); + } else { + printf("%16s[%4ld] = %012lx\n", "unknown", auxp[0], auxp[1]); + } } printf("\nSpecial Directories:\n"); printf(" ☼ kTmpPath = %`'s\n", kTmpPath); diff --git a/libc/calls/getcwd-xnu.c b/libc/calls/getcwd-xnu.c index 4da7837f0..c1ea1ec17 100644 --- a/libc/calls/getcwd-xnu.c +++ b/libc/calls/getcwd-xnu.c @@ -31,7 +31,7 @@ char *sys_getcwd_xnu(char *res, size_t size) { int fd; struct stat st[2]; char buf[XNU_MAXPATHLEN], *ret = NULL; - if ((fd = sys_openat(AT_FDCWD, ".", O_RDONLY | O_DIRECTORY)) != -1) { + if ((fd = sys_openat(AT_FDCWD, ".", O_RDONLY | O_DIRECTORY, 0)) != -1) { if (sys_fstat(fd, &st[0]) != -1) { if (st[0].st_dev && st[0].st_ino) { if (sys_fcntl(fd, XNU_F_GETPATH, buf) != -1) { diff --git a/libc/calls/internal.h b/libc/calls/internal.h index 0e53945fc..4714e12a4 100644 --- a/libc/calls/internal.h +++ b/libc/calls/internal.h @@ -108,6 +108,7 @@ i32 __sys_dup3(i32, i32, i32) hidden; i32 __sys_execve(const char *, char *const[], char *const[]) hidden; i32 __sys_fstat(i32, struct stat *) hidden; i32 __sys_fstatat(i32, const char *, struct stat *, i32) hidden; +i32 __sys_openat(i32, const char *, i32, u32) hidden; i32 __sys_pipe2(i32[hasatleast 2], u32) hidden; i32 __sys_utimensat(i32, const char *, const struct timespec *, i32) hidden; i32 getdents(i32, char *, u32, i64 *) hidden; @@ -153,7 +154,7 @@ i32 sys_mprotect(void *, u64, i32) hidden; i32 sys_msync(void *, u64, i32) hidden; i32 sys_munmap(void *, u64) hidden; i32 sys_nanosleep(const struct timespec *, struct timespec *) hidden; -i32 sys_openat(i32, const char *, i32, ...) hidden; +i32 sys_openat(i32, const char *, i32, u32) hidden; i32 sys_pause(void) hidden; i32 sys_pipe(i32[hasatleast 2]) hidden; i32 sys_pipe2(i32[hasatleast 2], u32) hidden; @@ -218,6 +219,7 @@ void __sigenter_xnu(void *, i32, i32, struct __darwin_siginfo *, int gethostname_linux(char *, size_t) hidden; int gethostname_bsd(char *, size_t) hidden; int gethostname_nt(char *, size_t) hidden; +size_t __iovec_size(const struct iovec *, size_t) hidden; /*───────────────────────────────────────────────────────────────────────────│─╗ │ cosmopolitan § syscalls » windows nt » veneers ─╬─│┼ diff --git a/libc/calls/iovecsize.c b/libc/calls/iovecsize.c new file mode 100644 index 000000000..21b71dcd3 --- /dev/null +++ b/libc/calls/iovecsize.c @@ -0,0 +1,27 @@ +/*-*- 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 2021 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/internal.h" + +size_t __iovec_size(const struct iovec *v, size_t n) { + size_t i, sum; + for (sum = i = 0; i < n; ++i) { + sum += v[i].iov_len; + } + return sum; +} diff --git a/libc/calls/openat-sysv.c b/libc/calls/openat-sysv.c new file mode 100644 index 000000000..2bfbfdeab --- /dev/null +++ b/libc/calls/openat-sysv.c @@ -0,0 +1,44 @@ +/*-*- 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 2021 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/internal.h" +#include "libc/errno.h" +#include "libc/sysv/consts/f.h" +#include "libc/sysv/consts/fd.h" +#include "libc/sysv/consts/o.h" + +int sys_openat(int dirfd, const char *file, int flags, unsigned mode) { + int fd, err; + err = errno; + fd = __sys_openat(dirfd, file, flags, mode); + + /* + * RHEL5 doesn't support O_CLOEXEC + * What on earth is it doing here? + * It returns -530! + */ + if (IsLinux() && fd == -1 && errno > 255) { + errno = err; + fd = __sys_openat(dirfd, file, flags & ~O_CLOEXEC, mode); + if (fd != -1 && (flags & O_CLOEXEC)) { + sys_fcntl(fd, F_SETFD, FD_CLOEXEC); + } + } + + return fd; +} diff --git a/libc/calls/preadv.c b/libc/calls/preadv.c index fa23cbdc3..2467b9370 100644 --- a/libc/calls/preadv.c +++ b/libc/calls/preadv.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/bits/bits.h" +#include "libc/bits/weaken.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" #include "libc/calls/struct/iovec.h" @@ -25,54 +26,84 @@ #include "libc/macros.internal.h" #include "libc/sysv/consts/iov.h" #include "libc/sysv/errfuns.h" +#include "libc/zipos/zipos.internal.h" #define __NR_preadv_linux 0x0127 /** - * Reads data from multiple buffers from file descriptor at offset. + * Reads with maximum generality. * - * @param count is recommended to be 16 or fewer; if it exceeds IOV_MAX - * then the extra buffers are simply ignored * @return number of bytes actually read, or -1 w/ errno * @asyncsignalsafe * @vforksafe */ -ssize_t preadv(int fd, struct iovec *iovec, int count, int64_t off) { +ssize_t preadv(int fd, struct iovec *iov, int iovlen, int64_t off) { static bool once, demodernize; - int olderr; + int i, err; ssize_t rc; - if (!count) return 0; - if ((count = MIN(count, IOV_MAX)) < 0) return einval(); + size_t got, toto; + + if (fd < 0) return einval(); + if (iovlen < 0) return einval(); + 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 (fd < g_fds.n) { + return sys_read_nt(g_fds.p + fd, iov, iovlen, off); + } else { + return ebadf(); + } + } else if (IsMetal()) { + return enosys(); + } /* * NT, XNU, and 2007-era Linux don't support this system call. */ if (!once) { - once = true; - if (IsModeDbg() || (IsLinux() && iovec->iov_len >= __NR_preadv_linux)) { - /* - * Read size is too large to detect older kernels safely without - * introducing nontrivial mechanics. We'll try again later. - */ - once = false; + err = errno; + rc = sys_preadv(fd, iov, iovlen, off, off); + if (rc == -1 && errno == ENOSYS) { + errno = err; + once = true; demodernize = true; - } else { - olderr = errno; - rc = sys_preadv(fd, iovec, count, off, off); - if (rc == -1 && errno == ENOSYS) { - errno = olderr; - demodernize = true; - } else if (IsLinux() && rc == __NR_preadv_linux /*RHEL5:CVE-2010-3301*/) { - demodernize = true; + } else if (IsLinux() && rc == __NR_preadv_linux) { + if (__iovec_size(iov, iovlen) < __NR_preadv_linux) { + demodernize = true; /*RHEL5:CVE-2010-3301*/ + once = true; } else { return rc; } + } else { + once = true; + return rc; } } if (!demodernize) { - return sys_preadv(fd, iovec, count, off, off); - } else { - return pread(fd, iovec[0].iov_base, iovec[0].iov_len, off); + return sys_preadv(fd, iov, iovlen, off, off); } + + if (!iovlen) { + return sys_pread(fd, NULL, 0, off, off); + } + + 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; + } + } + got = rc; + toto += got; + if (got != iov[i].iov_len) { + break; + } + } + + return toto; } diff --git a/libc/calls/pwritev.c b/libc/calls/pwritev.c index 36a64587d..54231e6ec 100644 --- a/libc/calls/pwritev.c +++ b/libc/calls/pwritev.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/bits/weaken.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" #include "libc/calls/struct/iovec.h" @@ -24,6 +25,7 @@ #include "libc/macros.internal.h" #include "libc/sysv/consts/iov.h" #include "libc/sysv/errfuns.h" +#include "libc/zipos/zipos.internal.h" #define __NR_pwritev_linux 0x0128 @@ -35,49 +37,77 @@ * been committed. It can also happen if we need to polyfill this system * call using pwrite(). * - * @param count is recommended to be 16 or fewer; if it exceeds IOV_MAX - * then the extra buffers are simply ignored * @return number of bytes actually sent, or -1 w/ errno * @asyncsignalsafe * @vforksafe */ -ssize_t pwritev(int fd, const struct iovec *iovec, int count, int64_t off) { +ssize_t pwritev(int fd, const struct iovec *iov, int iovlen, int64_t off) { static bool once, demodernize; - int olderr; + int i, err; ssize_t rc; - if (!count) return 0; - if ((count = MIN(count, IOV_MAX)) < 0) return einval(); + size_t sent, toto; + + if (fd < 0) return einval(); + if (iovlen < 0) return einval(); + 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 (fd < g_fds.n) { + return sys_write_nt(g_fds.p + fd, iov, iovlen, off); + } else { + return ebadf(); + } + } else if (IsMetal()) { + return enosys(); + } /* * NT, XNU, and 2007-era Linux don't support this system call. */ if (!once) { - once = true; - if (IsModeDbg() || (IsLinux() && iovec->iov_len >= __NR_pwritev_linux)) { - /* - * Write size is too large to detect older kernels safely without - * introducing nontrivial mechanics. We'll try again later. - */ - once = false; + err = errno; + rc = sys_pwritev(fd, iov, iovlen, off, off); + if (rc == -1 && errno == ENOSYS) { + errno = err; + once = true; demodernize = true; - } else { - olderr = errno; - rc = sys_pwritev(fd, iovec, count, off, off); - if (rc == -1 && errno == ENOSYS) { - errno = olderr; - demodernize = true; - } else if (IsLinux() && - rc == __NR_pwritev_linux /*RHEL5:CVE-2010-3301*/) { - demodernize = true; + } else if (IsLinux() && rc == __NR_pwritev_linux) { + if (__iovec_size(iov, iovlen) < __NR_pwritev_linux) { + demodernize = true; /*RHEL5:CVE-2010-3301*/ + once = true; } else { return rc; } + } else { + once = true; + return rc; } } if (!demodernize) { - return sys_pwritev(fd, iovec, count, off, off); - } else { - return pwrite(fd, iovec[0].iov_base, iovec[0].iov_len, off); + return sys_pwritev(fd, iov, iovlen, off, off); } + + if (!iovlen) { + return sys_pwrite(fd, NULL, 0, off, off); + } + + 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; + } + } + sent = rc; + toto += sent; + if (sent != iov[i].iov_len) { + break; + } + } + + return toto; } diff --git a/libc/calls/unlinkat-nt.c b/libc/calls/unlinkat-nt.c index c690109d3..f8e512fb7 100644 --- a/libc/calls/unlinkat-nt.c +++ b/libc/calls/unlinkat-nt.c @@ -33,25 +33,11 @@ static textwindows int sys_unlink_nt(const char16_t *path) { } static textwindows int sys_rmdir_nt(const char16_t *path) { - int e, ms; - for (ms = 1;; ms *= 2) { - if (RemoveDirectory(path)) return 0; - /* - * Files can linger, for absolutely no reason. - * Possibly some Windows Defender bug on Win7. - * Sleep for up to one second w/ expo backoff. - * Alternative is use Microsoft internal APIs. - * Never could have imagined it'd be this bad. - */ - if ((e = GetLastError()) == kNtErrorDirNotEmpty && ms <= 512) { - Sleep(ms); - continue; - } else { - break; - } + if (RemoveDirectory(path)) { + return 0; + } else { + return __winerr(); } - errno = e; - return -1; } textwindows int sys_unlinkat_nt(int dirfd, const char *path, int flags) { diff --git a/libc/calls/write-nt.c b/libc/calls/write-nt.c index 3a3655aed..c2ebb80a9 100644 --- a/libc/calls/write-nt.c +++ b/libc/calls/write-nt.c @@ -25,14 +25,6 @@ #include "libc/nt/struct/overlapped.h" #include "libc/sysv/errfuns.h" -static textwindows size_t SumIovecLen(const struct iovec *v, size_t n) { - size_t i, sum; - for (sum = i = 0; i < n; ++i) { - sum += v[i].iov_len; - } - return sum; -} - textwindows ssize_t sys_write_nt(struct Fd *fd, const struct iovec *iov, size_t iovlen, ssize_t opt_offset) { size_t i, total; @@ -52,7 +44,7 @@ textwindows ssize_t sys_write_nt(struct Fd *fd, const struct iovec *iov, return __winerr(); } } - if (!total) assert(!SumIovecLen(iov, iovlen)); + if (!total) assert(!__iovec_size(iov, iovlen)); return total; } else { if (WriteFile(fd->handle, NULL, 0, &wrote, diff --git a/libc/stdio/getdelim.c b/libc/stdio/getdelim.c index 8001703ec..69de5843c 100644 --- a/libc/stdio/getdelim.c +++ b/libc/stdio/getdelim.c @@ -37,7 +37,6 @@ * @see getline(), gettok_r() */ ssize_t getdelim(char **line, size_t *n, int delim, FILE *f) { - STATIC_YOINK("realloc"); assert((*line && *n) || (!*line && !*n)); ssize_t rc = -1; size_t i = 0; diff --git a/libc/stdio/spawn.c b/libc/stdio/spawn.c index e7588640f..5dc3980b3 100644 --- a/libc/stdio/spawn.c +++ b/libc/stdio/spawn.c @@ -66,8 +66,7 @@ int posix_spawn(int *pid, const char *path, } } if (file_actions) { - p = *file_actions; - while (*p != '\0') { + for (p = *file_actions; *p; p = strchr(p, ')') + 1) { if (!strncmp(p, "close(", 6)) { if (sscanf(p + 6, "%d)", &fd) != 1) _exit(127); if (close(fd) == -1) _exit(127); @@ -92,7 +91,6 @@ int posix_spawn(int *pid, const char *path, } else { _exit(127); } - p = strchr(p, ')') + 1; } } if (attrp) { diff --git a/libc/stdio/spawn.h b/libc/stdio/spawn.h index d967646e4..7fe335c2e 100644 --- a/libc/stdio/spawn.h +++ b/libc/stdio/spawn.h @@ -16,12 +16,18 @@ COSMOPOLITAN_C_START_ typedef char *posix_spawn_file_actions_t; typedef struct _posix_spawnattr posix_spawnattr_t; +int posix_spawn(int *, const char *, const posix_spawn_file_actions_t *, + const posix_spawnattr_t *, char *const[], char *const[]); +int posix_spawnp(int *, const char *, const posix_spawn_file_actions_t *, + const posix_spawnattr_t *, char *const[], char *const[]); + int posix_spawn_file_actions_init(posix_spawn_file_actions_t *); int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *); int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *, int); int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *, int, int); int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t *, int, const char *, int, unsigned); + int posix_spawnattr_init(posix_spawnattr_t *); int posix_spawnattr_destroy(posix_spawnattr_t *); int posix_spawnattr_getflags(const posix_spawnattr_t *, short *); @@ -38,10 +44,6 @@ int posix_spawnattr_getsigmask(const posix_spawnattr_t *, sigset_t *); int posix_spawnattr_setsigmask(posix_spawnattr_t *, const sigset_t *); int posix_spawnattr_getdefault(const posix_spawnattr_t *, sigset_t *); int posix_spawnattr_setsigdefault(posix_spawnattr_t *, const sigset_t *); -int posix_spawn(int *, const char *, const posix_spawn_file_actions_t *, - const posix_spawnattr_t *, char *const[], char *const[]); -int posix_spawnp(int *, const char *, const posix_spawn_file_actions_t *, - const posix_spawnattr_t *, char *const[], char *const[]); COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/libc/sysv/calls/__sys_openat.s b/libc/sysv/calls/__sys_openat.s new file mode 100644 index 000000000..127fd0967 --- /dev/null +++ b/libc/sysv/calls/__sys_openat.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall __sys_openat,0x1d41411f321cf101,globl,hidden diff --git a/libc/sysv/calls/sys_openat.s b/libc/sysv/calls/sys_openat.s deleted file mode 100644 index c4237e3b1..000000000 --- a/libc/sysv/calls/sys_openat.s +++ /dev/null @@ -1,2 +0,0 @@ -.include "o/libc/sysv/macros.internal.inc" -.scall sys_openat,0x1d41411f321cf101,globl,hidden diff --git a/libc/sysv/consts.sh b/libc/sysv/consts.sh index 6b5acd9d9..195259c9f 100755 --- a/libc/sysv/consts.sh +++ b/libc/sysv/consts.sh @@ -446,6 +446,7 @@ syscon auxv AT_PHENT 4 0 4 0 4 0 syscon auxv AT_PHNUM 5 0 5 0 5 0 syscon auxv AT_PAGESZ 6 0 6 0 6 0 syscon auxv AT_BASE 7 0 7 0 7 0 # address of program interpreter +syscon auxv AT_FLAGS 8 0 0 0 0 0 syscon auxv AT_ENTRY 9 0 9 0 9 0 # entry address of executable syscon auxv AT_NOTELF 10 0 10 0 0 0 syscon auxv AT_OSRELDATE 0 0 18 0 0 0 @@ -453,7 +454,8 @@ syscon auxv AT_UID 11 0 0 0 2001 0 syscon auxv AT_EUID 12 0 0 0 2000 0 syscon auxv AT_GID 13 0 0 0 2003 0 syscon auxv AT_EGID 14 0 0 0 2002 0 -syscon auxv AT_PLATFORM 15 0 0 0 0 0 # address of string with hardware platform for rpath interpretation [RHEL5.0 LIMIT] +syscon auxv AT_PLATFORM 15 0 0 0 0 0 # address of string with hardware platform for rpath interpretation +syscon auxv AT_HWCAP 16 0 0 0 0 0 syscon auxv AT_CLKTCK 17 0 0 0 0 0 syscon auxv AT_DCACHEBSIZE 19 0 0 0 0 0 syscon auxv AT_ICACHEBSIZE 20 0 0 0 0 0 @@ -461,6 +463,7 @@ syscon auxv AT_UCACHEBSIZE 21 0 0 0 0 0 syscon auxv AT_SECURE 23 0 0 0 0 0 syscon auxv AT_BASE_PLATFORM 24 0 0 0 0 0 syscon auxv AT_RANDOM 25 0 0 0 0 0 # address of sixteen bytes of random data +syscon auxv AT_HWCAP2 26 0 0 0 0 0 syscon auxv AT_EXECFN 31 31 999 999 2014 31 # address of string containing first argument passed to execve() used when running program [faked on non-linux] syscon auxv AT_SYSINFO_EHDR 33 0 0 0 0 0 syscon auxv AT_NO_AUTOMOUNT 0x0800 0 0 0 0 0 diff --git a/libc/sysv/consts/AT_FLAGS.S b/libc/sysv/consts/AT_FLAGS.S new file mode 100644 index 000000000..79b4bc1e7 --- /dev/null +++ b/libc/sysv/consts/AT_FLAGS.S @@ -0,0 +1,2 @@ +#include "libc/sysv/consts/syscon.internal.h" +.syscon auxv,AT_FLAGS,8,0,0,0,0,0 diff --git a/libc/sysv/consts/AT_HWCAP.S b/libc/sysv/consts/AT_HWCAP.S new file mode 100644 index 000000000..e8ccfd9cf --- /dev/null +++ b/libc/sysv/consts/AT_HWCAP.S @@ -0,0 +1,2 @@ +#include "libc/sysv/consts/syscon.internal.h" +.syscon auxv,AT_HWCAP,16,0,0,0,0,0 diff --git a/libc/sysv/consts/AT_HWCAP2.S b/libc/sysv/consts/AT_HWCAP2.S new file mode 100644 index 000000000..7bbc03ef8 --- /dev/null +++ b/libc/sysv/consts/AT_HWCAP2.S @@ -0,0 +1,2 @@ +#include "libc/sysv/consts/syscon.internal.h" +.syscon auxv,AT_HWCAP2,26,0,0,0,0,0 diff --git a/libc/sysv/consts/auxv.h b/libc/sysv/consts/auxv.h index 5b915a199..69bf377f9 100644 --- a/libc/sysv/consts/auxv.h +++ b/libc/sysv/consts/auxv.h @@ -13,7 +13,10 @@ extern const long AT_ENTRY; extern const long AT_EUID; extern const long AT_EXECFD; extern const long AT_EXECFN; +extern const long AT_FLAGS; extern const long AT_GID; +extern const long AT_HWCAP2; +extern const long AT_HWCAP; extern const long AT_ICACHEBSIZE; extern const long AT_NOTELF; extern const long AT_NO_AUTOMOUNT; @@ -41,7 +44,10 @@ COSMOPOLITAN_C_END_ #define AT_EUID SYMBOLIC(AT_EUID) #define AT_EXECFD SYMBOLIC(AT_EXECFD) #define AT_EXECFN SYMBOLIC(AT_EXECFN) +#define AT_FLAGS SYMBOLIC(AT_FLAGS) #define AT_GID SYMBOLIC(AT_GID) +#define AT_HWCAP SYMBOLIC(AT_HWCAP) +#define AT_HWCAP2 SYMBOLIC(AT_HWCAP2) #define AT_ICACHEBSIZE SYMBOLIC(AT_ICACHEBSIZE) #define AT_NOTELF SYMBOLIC(AT_NOTELF) #define AT_NO_AUTOMOUNT SYMBOLIC(AT_NO_AUTOMOUNT) diff --git a/libc/sysv/syscalls.sh b/libc/sysv/syscalls.sh index f3307864d..2c0853616 100755 --- a/libc/sysv/syscalls.sh +++ b/libc/sysv/syscalls.sh @@ -278,7 +278,7 @@ scall ioprio_get 0xfffffffffffff0fc globl scall inotify_init 0xfffffffffffff0fd globl # wicked scall inotify_add_watch 0xfffffffffffff0fe globl scall inotify_rm_watch 0xfffffffffffff0ff globl -scall sys_openat 0x1d41411f321cf101 globl hidden # Linux 2.6.16+ (c. 2007) +scall __sys_openat 0x1d41411f321cf101 globl hidden # Linux 2.6.16+ (c. 2007) scall sys_mkdirat 0x1cd13e1f021db102 globl hidden scall sys_fchownat 0x1d013b1eb21d4104 globl hidden # @asyncsignalsafe scall sys_utime 0xfffffffffffff084 globl hidden diff --git a/test/libc/stdio/tmpfile_test.c b/test/libc/stdio/tmpfile_test.c index 0a373b835..5f9039fb0 100644 --- a/test/libc/stdio/tmpfile_test.c +++ b/test/libc/stdio/tmpfile_test.c @@ -35,6 +35,6 @@ TEST(tmpfile, test) { rewind(f); EXPECT_EQ('t', fgetc(f)); EXPECT_NE(-1, fclose(f)); - /* EXPECT_EQ(-1, rmdir("doge")); */ - /* EXPECT_EQ(ENOTEMPTY, errno); */ + EXPECT_EQ(-1, rmdir("doge")); + EXPECT_EQ(ENOTEMPTY, errno); }