Improve system call polyfills

- Polyfill open() w/ O_CLOEXEC on RHEL5
- Remove old workaround from rmdir() on the New Technology
- preadv() and pwritev() are now smarter about demodernization
- preadv() and pwritev() are now available on the New Technology
This commit is contained in:
Justine Tunney 2021-03-08 10:07:02 -08:00
parent 816b0e1851
commit 0ad609268f
21 changed files with 260 additions and 117 deletions

View file

@ -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);

View file

@ -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) {

View file

@ -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

27
libc/calls/iovecsize.c Normal file
View file

@ -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;
}

44
libc/calls/openat-sysv.c Normal file
View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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) {

View file

@ -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,

View file

@ -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;

View file

@ -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) {

View file

@ -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) */

View file

@ -0,0 +1,2 @@
.include "o/libc/sysv/macros.internal.inc"
.scall __sys_openat,0x1d41411f321cf101,globl,hidden

View file

@ -1,2 +0,0 @@
.include "o/libc/sysv/macros.internal.inc"
.scall sys_openat,0x1d41411f321cf101,globl,hidden

View file

@ -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

View file

@ -0,0 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon auxv,AT_FLAGS,8,0,0,0,0,0

View file

@ -0,0 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon auxv,AT_HWCAP,16,0,0,0,0,0

View file

@ -0,0 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon auxv,AT_HWCAP2,26,0,0,0,0,0

View file

@ -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)

View file

@ -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

View file

@ -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);
}