Compare commits

...

4 commits

Author SHA1 Message Date
Gavin Hayes ac77cab158
Merge 1c9f462e77 into 181cd4cbe8 2024-05-03 06:49:51 +00:00
Gavin Hayes 1c9f462e77 /dev/(u)random return eperm on write, update ioctl fionread to linux behavior, cleanup tests 2024-05-03 02:49:44 -04:00
Justine Tunney 181cd4cbe8
Add sysctlbyname() for MacOS 2024-05-02 23:21:43 -07:00
Gavin Hayes 542b817cc8 add /dev/(u)random on nt 2024-04-30 00:54:00 -04:00
38 changed files with 290 additions and 57 deletions

View file

@ -31,6 +31,8 @@
#include <string.h>
#include <sys/mman.h>
#include <sys/random.h>
#include <sys/sysctl.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <time.h>
#include <unistd.h>
@ -39,7 +41,7 @@
/* maximum path size that cosmo can take */
#define PATHSIZE (PATH_MAX < 1024 ? PATH_MAX : 1024)
#define SYSLIB_MAGIC ('s' | 'l' << 8 | 'i' << 16 | 'b' << 24)
#define SYSLIB_VERSION 9 /* sync with libc/runtime/syslib.internal.h */
#define SYSLIB_VERSION 10 /* sync with libc/runtime/syslib.internal.h */
struct Syslib {
int magic;
@ -106,6 +108,10 @@ struct Syslib {
OPTIONAL (cosmo lib should check __syslib->version) */
/* v9 (2024-01-31) */
int (*pthread_cpu_number_np)(size_t *);
/* v10 (2024-05-02) */
long (*sysctl)(int *, u_int, void *, size_t *, void *, size_t);
long (*sysctlbyname)(const char *, void *, size_t *, void *, size_t);
long (*sysctlnametomib)(const char *, int *, size_t *);
};
#define ELFCLASS32 1
@ -148,8 +154,8 @@ struct Syslib {
#define _COMM_PAGE_APRR_WRITE_ENABLE (_COMM_PAGE_START_ADDRESS + 0x110)
#define _COMM_PAGE_APRR_WRITE_DISABLE (_COMM_PAGE_START_ADDRESS + 0x118)
#define MIN(X, Y) ((Y) > (X) ? (X) : (Y))
#define MAX(X, Y) ((Y) < (X) ? (X) : (Y))
#define Min(X, Y) ((Y) > (X) ? (X) : (Y))
#define Max(X, Y) ((Y) < (X) ? (X) : (Y))
#define READ32(S) \
((unsigned)(255 & (S)[3]) << 030 | (unsigned)(255 & (S)[2]) << 020 | \
@ -552,6 +558,20 @@ static long sys_pselect(int nfds, fd_set *readfds, fd_set *writefds,
return sysret(pselect(nfds, readfds, writefds, errorfds, timeout, sigmask));
}
static long sys_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
void *newp, size_t newlen) {
return sysret(sysctl(name, namelen, oldp, oldlenp, newp, newlen));
}
static long sys_sysctlbyname(const char *name, void *oldp, size_t *oldlenp,
void *newp, size_t newlen) {
return sysret(sysctlbyname(name, oldp, oldlenp, newp, newlen));
}
static long sys_sysctlnametomib(const char *name, int *mibp, size_t *sizep) {
return sysret(sysctlnametomib(name, mibp, sizep));
}
__attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
long *sp, struct ElfEhdr *e,
struct ElfPhdr *p,
@ -596,7 +616,7 @@ __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
continue;
c = p[j].p_vaddr & -pagesz;
d = (p[j].p_vaddr + p[j].p_memsz + (pagesz - 1)) & -pagesz;
if (MAX(a, c) < MIN(b, d)) {
if (Max(a, c) < Min(b, d)) {
Pexit(exe, 0, "ELF segments overlap each others virtual memory");
}
}
@ -670,7 +690,7 @@ __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
a = p[i].p_vaddr + p[i].p_filesz; /* end of file content */
b = (a + (pagesz - 1)) & -pagesz; /* first pure bss page */
c = p[i].p_vaddr + p[i].p_memsz; /* end of segment data */
wipe = MIN(b - a, c - a);
wipe = Min(b - a, c - a);
if (wipe && (~prot1 & PROT_WRITE)) {
prot1 = PROT_READ | PROT_WRITE;
}
@ -970,6 +990,9 @@ int main(int argc, char **argv, char **envp) {
M->lib.dlclose = dlclose;
M->lib.dlerror = dlerror;
M->lib.pthread_cpu_number_np = pthread_cpu_number_np;
M->lib.sysctl = sys_sysctl;
M->lib.sysctlbyname = sys_sysctlbyname;
M->lib.sysctlnametomib = sys_sysctlnametomib;
/* getenv("_") is close enough to at_execfn */
execfn = 0;

View file

@ -237,7 +237,9 @@ int sys_munlock(const void *, size_t) libcesque;
int sys_munlockall(void) libcesque;
int sys_personality(uint64_t) libcesque;
int sys_ptrace(int, ...) libcesque;
int sys_sysctl(const int *, unsigned, void *, size_t *, void *, size_t);
int sysctl(int *, unsigned, void *, size_t *, void *, size_t) libcesque;
int sysctlbyname(const char *, void *, size_t *, void *, size_t) libcesque;
int sysctlnametomib(const char *, int *, size_t *) libcesque;
int tmpfd(void) libcesque;
int touch(const char *, unsigned) libcesque;
int unveil(const char *, const char *) libcesque;

View file

@ -53,7 +53,7 @@ static dontinline int __clk_tck_init(void) {
cmd[0] = 1; // CTL_KERN
cmd[1] = 12; // KERN_CLOCKRATE
len = sizeof(clock);
if (sys_sysctl(cmd, 2, &clock, &len, NULL, 0) != -1) {
if (sysctl(cmd, 2, &clock, &len, NULL, 0) != -1) {
x = clock.hz;
} else {
x = -1;

View file

@ -67,7 +67,7 @@ int sys_clock_gettime_xnu(int clock, struct timespec *ts) {
struct timeval x;
size_t n = sizeof(x);
int mib[] = {CTL_KERN, KERN_BOOTTIME};
if (sys_sysctl(mib, ARRAYLEN(mib), &x, &n, 0, 0) == -1)
if (sysctl(mib, ARRAYLEN(mib), &x, &n, 0, 0) == -1)
return -1;
if (ts)
*ts = timeval_totimespec(timeval_sub(timeval_real(), x));

View file

@ -332,7 +332,8 @@ textwindows int sys_fcntl_nt(int fd, int cmd, uintptr_t arg) {
if (__isfdkind(fd, kFdFile) || //
__isfdkind(fd, kFdSocket) || //
__isfdkind(fd, kFdConsole) || //
__isfdkind(fd, kFdDevNull)) {
__isfdkind(fd, kFdDevNull) || //
__isfdkind(fd, kFdDevRandom)) {
if (cmd == F_GETFL) {
rc = g_fds.p[fd].flags & (O_ACCMODE | _O_APPEND | _O_DIRECT |
_O_NONBLOCK | _O_RANDOM | _O_SEQUENTIAL);

View file

@ -104,6 +104,7 @@ textwindows int sys_fstat_nt(int fd, struct stat *st) {
return ebadf();
case kFdConsole:
case kFdDevNull:
case kFdDevRandom:
return sys_fstat_nt_special(g_fds.p[fd].kind, st);
case kFdSocket:
return sys_fstat_nt_socket(g_fds.p[fd].kind, st);

View file

@ -59,6 +59,8 @@ textwindows int sys_fstatat_nt(int dirfd, const char *path, struct stat *st,
return sys_fstat_nt_special(kFdConsole, st);
} else if (!strcmp(path + 5, "null")) {
return sys_fstat_nt_special(kFdDevNull, st);
} else if (!strcmp(path + 5, "random") || !strcmp(path + 5, "urandom")) {
return sys_fstat_nt_special(kFdDevRandom, st);
} else if (!strcmp(path + 5, "stdin")) {
return sys_fstat_nt(STDIN_FILENO, st);
} else if (!strcmp(path + 5, "stdout")) {

View file

@ -51,7 +51,7 @@ static int __get_cpu_count_bsd(void) {
} else {
cmd[1] = HW_NCPU;
}
if (!sys_sysctl(cmd, 2, &c, &n, 0, 0)) {
if (!sysctl(cmd, 2, &c, &n, 0, 0)) {
return c;
} else {
return -1;

View file

@ -24,7 +24,7 @@
int gethostname_bsd(char *name, size_t len, int kind) {
int cmd[2] = {CTL_KERN, kind};
if (sys_sysctl(cmd, 2, name, &len, 0, 0) != -1) {
if (sysctl(cmd, 2, name, &len, 0, 0) != -1) {
return 0;
} else {
if (errno == ENOMEM) {

View file

@ -64,7 +64,7 @@ int getloadavg(double *a, int n) {
struct loadavg loadinfo;
int mib[2] = {CTL_VM, VM_LOADAVG};
size = sizeof(loadinfo);
if ((rc = sys_sysctl(mib, 2, &loadinfo, &size, 0, 0)) != -1) {
if ((rc = sysctl(mib, 2, &loadinfo, &size, 0, 0)) != -1) {
for (i = 0; i < n; i++) {
a[i] = (double)loadinfo.ldavg[i] / loadinfo.fscale;
}

View file

@ -195,7 +195,7 @@ static inline void InitProgramExecutableNameImpl(void) {
cmd[2] = KERN_PROC_PATHNAME_NETBSD;
}
cmd[3] = -1; // current process
if (sys_sysctl(cmd, ARRAYLEN(cmd), b, &n, 0, 0) != -1) {
if (sysctl(cmd, ARRAYLEN(cmd), b, &n, 0, 0) != -1) {
if (!OldApeLoader(b)) {
goto UseBuf;
}

View file

@ -70,7 +70,7 @@ static void GetRandomArnd(char *p, size_t n) {
cmd[0] = 1; // CTL_KERN
cmd[1] = IsFreebsd() ? 37 : 81; // KERN_ARND
unassert((m = n) <= 256);
if (sys_sysctl(cmd, 2, p, &n, 0, 0) == -1)
if (sysctl(cmd, 2, p, &n, 0, 0) == -1)
notpossible;
if (m != n)
notpossible;

View file

@ -24,7 +24,6 @@
#include "libc/calls/termios.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/serialize.h"
#include "libc/intrin/cmpxchg.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
@ -42,6 +41,7 @@
#include "libc/nt/winsock.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/stack.h"
#include "libc/serialize.h"
#include "libc/sock/internal.h"
#include "libc/sock/struct/ifconf.h"
#include "libc/sock/struct/ifreq.h"
@ -66,7 +66,7 @@ static struct HostAdapterInfoNode {
struct sockaddr netmask;
struct sockaddr broadcast;
short flags;
} *__hostInfo;
} * __hostInfo;
static int ioctl_default(int fd, unsigned long request, void *arg) {
int rc;
@ -107,8 +107,9 @@ static int ioctl_fionread(int fd, uint32_t *arg) {
*arg = MAX(0, bytes);
return 0;
} else if (g_fds.p[fd].kind == kFdDevNull) {
*arg = 1;
return 0;
return enotty();
} else if (g_fds.p[fd].kind == kFdDevRandom) {
return einval();
} else if (GetFileType(handle) == kNtFileTypePipe) {
uint32_t avail;
if (PeekNamedPipe(handle, 0, 0, 0, &avail, 0)) {

View file

@ -55,6 +55,7 @@ bool32 ischardev(int fd) {
}
} else {
return __isfdkind(fd, kFdConsole) || __isfdkind(fd, kFdDevNull) ||
__isfdkind(fd, kFdDevRandom) ||
(__isfdkind(fd, kFdFile) &&
GetFileType(g_fds.p[fd].handle) == kNtFileTypeChar);
}

View file

@ -62,7 +62,7 @@ static textwindows int64_t Seek(struct Fd *f, int64_t offset, int whence) {
}
textwindows int64_t sys_lseek_nt(int fd, int64_t offset, int whence) {
if (__isfdkind(fd, kFdDevNull)) {
if (__isfdkind(fd, kFdDevNull) || __isfdkind(fd, kFdDevRandom)) {
return offset;
} else if (__isfdkind(fd, kFdFile)) {
struct Fd *f = g_fds.p + fd;

View file

@ -159,6 +159,15 @@ static textwindows int sys_open_nt_special(int fd, int flags, int mode,
return fd;
}
static textwindows int sys_open_nt_no_handle(int fd, int flags, int mode,
int kind) {
g_fds.p[fd].kind = kind;
g_fds.p[fd].mode = mode;
g_fds.p[fd].flags = flags;
g_fds.p[fd].handle = -1;
return fd;
}
static textwindows int sys_open_nt_dup(int fd, int flags, int mode, int oldfd) {
int64_t handle;
if (!__isfdopen(oldfd)) {
@ -211,6 +220,8 @@ textwindows int sys_open_nt(int dirfd, const char *file, uint32_t flags,
rc = sys_open_nt_special(fd, flags, mode, kFdConsole, u"CONIN$");
} else if (!strcmp(file + 5, "null")) {
rc = sys_open_nt_special(fd, flags, mode, kFdDevNull, u"NUL");
} else if (!strcmp(file + 5, "urandom") || !strcmp(file + 5, "random")) {
rc = sys_open_nt_no_handle(fd, flags, mode, kFdDevRandom);
} else if (!strcmp(file + 5, "stdin")) {
rc = sys_open_nt_dup(fd, flags, mode, STDIN_FILENO);
} else if (!strcmp(file + 5, "stdout")) {

View file

@ -72,7 +72,8 @@ ssize_t pread(int fd, void *buf, size_t size, int64_t offset) {
rc = sys_pread(fd, buf, size, offset, offset);
} else if (__isfdkind(fd, kFdSocket)) {
rc = espipe();
} else if (__isfdkind(fd, kFdFile) || __isfdkind(fd, kFdDevNull)) {
} else if (__isfdkind(fd, kFdFile) || __isfdkind(fd, kFdDevNull) ||
__isfdkind(fd, kFdDevRandom)) {
rc = sys_read_nt(fd, (struct iovec[]){{buf, size}}, 1, offset);
} else {
rc = ebadf();

View file

@ -40,6 +40,8 @@ static const char *__fdkind2str(int x) {
return "kFdZip";
case kFdEpoll:
return "kFdEpoll";
case kFdDevRandom:
return "kFdRandom";
default:
return "kFdWut";
}

View file

@ -65,7 +65,8 @@ ssize_t pwrite(int fd, const void *buf, size_t size, int64_t offset) {
rc = sys_pwrite(fd, buf, size, offset, offset);
} else if (__isfdkind(fd, kFdSocket)) {
rc = espipe();
} else if (__isfdkind(fd, kFdFile) || __isfdkind(fd, kFdDevNull)) {
} else if (__isfdkind(fd, kFdFile) || __isfdkind(fd, kFdDevNull) ||
__isfdkind(fd, kFdDevRandom)) {
rc = sys_write_nt(fd, (struct iovec[]){{(void *)buf, size}}, 1, offset);
} else {
return ebadf();

View file

@ -786,6 +786,10 @@ textwindows ssize_t ReadBuffer(int fd, void *data, size_t size, int64_t offset,
return 0;
}
if (f->kind == kFdDevRandom) {
return ProcessPrng(data, size) ? size : __winerr();
}
if (f->kind == kFdConsole) {
return ReadFromConsole(f, data, size, waitmask);
}

View file

@ -29,6 +29,7 @@ textwindows ssize_t sys_readv_nt(int fd, const struct iovec *iov, int iovlen) {
case kFdFile:
case kFdConsole:
case kFdDevNull:
case kFdDevRandom:
return sys_read_nt(fd, iov, iovlen, -1);
case kFdSocket:
return _weaken(sys_recv_nt)(fd, iov, iovlen, 0);

View file

@ -61,7 +61,7 @@ sys_readwrite_nt(int fd, void *data, size_t size, ssize_t offset,
bool pwriting = offset != -1;
bool seekable =
(f->kind == kFdFile && GetFileType(handle) == kNtFileTypeDisk) ||
f->kind == kFdDevNull;
f->kind == kFdDevNull || f->kind == kFdDevRandom;
if (pwriting && !seekable) {
return espipe();
}

View file

@ -2,15 +2,16 @@
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_FD_INTERNAL_H_
COSMOPOLITAN_C_START_
#define kFdEmpty 0
#define kFdFile 1
#define kFdSocket 2
#define kFdConsole 4
#define kFdSerial 5
#define kFdZip 6
#define kFdEpoll 7
#define kFdReserved 8
#define kFdDevNull 9
#define kFdEmpty 0
#define kFdFile 1
#define kFdSocket 2
#define kFdConsole 4
#define kFdSerial 5
#define kFdZip 6
#define kFdEpoll 7
#define kFdReserved 8
#define kFdDevNull 9
#define kFdDevRandom 10
struct Fd {
char kind;

33
libc/calls/sysctl.c Normal file
View file

@ -0,0 +1,33 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2024 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/syscall-sysv.internal.h"
#include "libc/runtime/syslib.internal.h"
int sys_sysctl(int *, unsigned, void *, size_t *, void *, size_t) libcesque;
int sysctl(int *name, unsigned namelen, void *oldp, size_t *oldlenp, void *newp,
size_t newlen) {
if (__syslib && __syslib->__version >= 10) {
return _sysret(
__syslib->__sysctl(name, namelen, oldp, oldlenp, newp, newlen));
} else {
return sys_sysctl(name, namelen, oldp, oldlenp, newp, newlen);
}
}

31
libc/calls/sysctlbyname.c Normal file
View file

@ -0,0 +1,31 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2024 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/syscall-sysv.internal.h"
#include "libc/runtime/syslib.internal.h"
#include "libc/sysv/errfuns.h"
int sysctlbyname(const char *name, void *oldp, size_t *oldlenp, void *newp,
size_t newlen) {
if (__syslib && __syslib->__version >= 10) {
return _sysret(__syslib->__sysctlbyname(name, oldp, oldlenp, newp, newlen));
} else {
return enosys();
}
}

View file

@ -0,0 +1,30 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2024 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/syscall-sysv.internal.h"
#include "libc/runtime/syslib.internal.h"
#include "libc/sysv/errfuns.h"
int sysctlnametomib(const char *name, int *mibp, size_t *sizep) {
if (__syslib && __syslib->__version >= 10) {
return _sysret(__syslib->__sysctlnametomib(name, mibp, sizep));
} else {
return enosys();
}
}

View file

@ -46,7 +46,7 @@ static int64_t GetUptime(void) {
struct timeval x;
size_t n = sizeof(x);
int mib[] = {CTL_KERN, KERN_BOOTTIME};
if (sys_sysctl(mib, ARRAYLEN(mib), &x, &n, 0, 0) == -1)
if (sysctl(mib, ARRAYLEN(mib), &x, &n, 0, 0) == -1)
return 0;
return timespec_real().tv_sec - x.tv_sec;
}
@ -55,7 +55,7 @@ static int64_t GetPhysmem(void) {
uint64_t x = 0;
size_t n = sizeof(x);
int mib[] = {CTL_HW, HW_PHYSMEM};
if (sys_sysctl(mib, ARRAYLEN(mib), &x, &n, 0, 0) == -1)
if (sysctl(mib, ARRAYLEN(mib), &x, &n, 0, 0) == -1)
return 0;
return x;
}
@ -65,7 +65,7 @@ static void GetLoads(uint64_t loads[3]) {
struct loadavg loadinfo;
int mib[2] = {CTL_VM, VM_LOADAVG};
size = sizeof(loadinfo);
if (sys_sysctl(mib, 2, &loadinfo, &size, 0, 0) != -1) {
if (sysctl(mib, 2, &loadinfo, &size, 0, 0) != -1) {
for (int i = 0; i < 3; i++) {
loads[i] = (double)loadinfo.ldavg[i] / loadinfo.fscale * 65536;
}

View file

@ -62,7 +62,7 @@ static void GetBsdStr(int c0, int c1, char *s) {
size_t n = SYS_NMLN;
int cmd[2] = {c0, c1};
bzero(s, n), --n;
sys_sysctl(cmd, 2, s, &n, NULL, 0);
sysctl(cmd, 2, s, &n, NULL, 0);
errno = e;
// sysctl kern.version is too verbose for uname
if ((p = strchr(s, '\n'))) {

View file

@ -52,6 +52,11 @@ static textwindows ssize_t sys_write_nt_impl(int fd, void *data, size_t size,
struct Fd *f = g_fds.p + fd;
bool isconsole = f->kind == kFdConsole;
// not implemented, XNU returns eperm();
if (f->kind == kFdDevRandom) {
return eperm();
}
// determine win32 handle for writing
int64_t handle = f->handle;
if (isconsole && _weaken(GetConsoleOutputHandle)) {

View file

@ -28,6 +28,7 @@ textwindows ssize_t sys_writev_nt(int fd, const struct iovec *iov, int iovlen) {
case kFdFile:
case kFdConsole:
case kFdDevNull:
case kFdDevRandom:
return sys_write_nt(fd, iov, iovlen, -1);
case kFdSocket:
return _weaken(sys_send_nt)(fd, iov, iovlen, 0);

View file

@ -254,10 +254,28 @@ static relegated void ShowCrashReport(int err, int sig, struct siginfo *si,
kprintf("\n");
}
static inline void SpinLock(atomic_uint *lock) {
int x;
for (;;) {
x = atomic_exchange_explicit(lock, 1, memory_order_acquire);
if (!x)
break;
}
}
static inline void SpinUnlock(atomic_uint *lock) {
atomic_store_explicit(lock, 0, memory_order_release);
}
relegated void __oncrash(int sig, struct siginfo *si, void *arg) {
static atomic_uint lock;
BLOCK_CANCELATION;
SpinLock(&lock);
int err = errno;
__restore_tty();
ShowCrashReport(err, sig, si, arg);
SpinUnlock(&lock);
ALLOW_CANCELATION;
}
#endif /* __x86_64__ */

View file

@ -18,6 +18,7 @@
*/
#include "ape/sections.internal.h"
#include "libc/assert.h"
#include "libc/atomic.h"
#include "libc/calls/blockcancel.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/aarch64.internal.h"
@ -32,6 +33,7 @@
#include "libc/calls/ucontext.h"
#include "libc/cxxabi.h"
#include "libc/errno.h"
#include "libc/intrin/atomic.h"
#include "libc/intrin/describebacktrace.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/kprintf.h"
@ -377,10 +379,25 @@ static relegated void __oncrash_impl(int sig, struct siginfo *si,
klog(b->p, MIN(b->i, b->n));
}
static inline void SpinLock(atomic_uint *lock) {
int x;
for (;;) {
x = atomic_exchange_explicit(lock, 1, memory_order_acquire);
if (!x)
break;
}
}
static inline void SpinUnlock(atomic_uint *lock) {
atomic_store_explicit(lock, 0, memory_order_release);
}
relegated void __oncrash(int sig, struct siginfo *si, void *arg) {
ucontext_t *ctx = arg;
static atomic_uint lock;
BLOCK_CANCELATION;
__oncrash_impl(sig, si, ctx);
SpinLock(&lock);
__oncrash_impl(sig, si, arg);
SpinUnlock(&lock);
ALLOW_CANCELATION;
}

View file

@ -74,9 +74,9 @@ char *GetInterpreterExecutableName(char *p, size_t n) {
cmd[2] = 12; // KERN_PROC_PATHNAME
} else { //
cmd[2] = 5; // KERN_PROC_PATHNAME
} //
cmd[3] = -1; // current process
if (sys_sysctl(cmd, ARRAYLEN(cmd), p, &n, 0, 0) != -1) {
} //
cmd[3] = -1; // current process
if (sysctl(cmd, ARRAYLEN(cmd), p, &n, 0, 0) != -1) {
errno = e;
return p;
}

View file

@ -23,7 +23,7 @@ long __get_sysctl(int x, int y) {
int value;
int mib[2] = {x, y};
size_t len = sizeof(value);
if (sys_sysctl(mib, 2, &value, &len, 0, 0) != -1) {
if (sysctl(mib, 2, &value, &len, 0, 0) != -1) {
return value;
} else {
return -1;

View file

@ -12,7 +12,7 @@ COSMOPOLITAN_C_START_
#define SYSLIB_MAGIC ('s' | 'l' << 8 | 'i' << 16 | 'b' << 24)
#define SYSLIB_VERSION 9 /* sync with ape/ape-m1.c */
#define SYSLIB_VERSION 10 /* sync with ape/ape-m1.c */
/* if this number increases, then everyone on macos arm will need to
reinstall ape loader in order to run newer ape binaries so please
@ -82,6 +82,9 @@ struct Syslib {
char *(*__dlerror)(void);
/* v9 (2024-01-31) */
int (*__pthread_cpu_number_np)(size_t *);
long (*__sysctl)(int *, unsigned, void *, size_t *, void *, size_t);
long (*__sysctlbyname)(const char *, void *, size_t *, void *, size_t);
long (*__sysctlnametomib)(const char *, int *, size_t *);
};
extern struct Syslib *__syslib;

View file

@ -20,15 +20,19 @@
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/nt/files.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/f.h"
#include "libc/sysv/consts/o.h"
#include "libc/testlib/testlib.h"
int pipefd[2];
int stdoutBack;
int allowMask;
void SetUpOnce(void) {
testlib_enable_tmp_setup_teardown();
// qemu-aarch64 defines o_largefile wrong
allowMask = ~(O_LARGEFILE | 0x00008000);
}
void CaptureStdout(void) {
@ -46,8 +50,7 @@ void RestoreStdout(void) {
TEST(specialfile, devNull) {
ASSERT_SYS(0, 3, creat("/dev/null", 0644));
// qemu-aarch64 defines o_largefile wrong
ASSERT_EQ(O_WRONLY, fcntl(3, F_GETFL) & ~(O_LARGEFILE | 0x00008000));
ASSERT_EQ(O_WRONLY, fcntl(3, F_GETFL) & allowMask);
ASSERT_SYS(0, 2, write(3, "hi", 2));
ASSERT_SYS(0, 2, pwrite(3, "hi", 2, 0));
ASSERT_SYS(0, 2, pwrite(3, "hi", 2, 2));
@ -64,12 +67,51 @@ TEST(specialfile, devNull) {
TEST(specialfile, devNullRead) {
char buf[8] = {0};
ASSERT_SYS(0, 3, open("/dev/null", O_RDONLY));
// qemu-aarch64 defines o_largefile wrong
ASSERT_EQ(O_RDONLY, fcntl(3, F_GETFL) & ~(O_LARGEFILE | 0x00008000));
ASSERT_EQ(O_RDONLY, fcntl(3, F_GETFL) & allowMask);
ASSERT_SYS(0, 0, read(3, buf, 8));
ASSERT_SYS(0, 0, close(3));
}
TEST(specialfile, devRandomRead) {
char buf[8] = {0};
ASSERT_SYS(0, 3, open("/dev/random", O_RDONLY));
ASSERT_EQ(O_RDONLY, fcntl(3, F_GETFL) & allowMask);
ASSERT_SYS(0, 8, read(3, buf, 8));
ASSERT_NE(0, memcmp(buf, " ", 8));
ASSERT_SYS(0, 0, close(3));
}
TEST(specialfile, devUrandomRead) {
char buf[8] = {0};
ASSERT_SYS(0, 3, open("/dev/urandom", O_RDONLY));
ASSERT_EQ(O_RDONLY, fcntl(3, F_GETFL) & allowMask);
ASSERT_SYS(0, 8, read(3, buf, 8));
ASSERT_NE(0, memcmp(buf, " ", 8));
ASSERT_SYS(0, 0, close(3));
}
TEST(specialfile, devRandomWrite_fails_on_nt) {
if (!IsWindows()) {
return;
}
char buf[8] = {0};
ASSERT_SYS(0, 3, creat("/dev/random", 0644));
ASSERT_EQ(O_WRONLY, fcntl(3, F_GETFL) & allowMask);
ASSERT_SYS(EPERM, -1, write(3, buf, 8));
ASSERT_SYS(0, 0, close(3));
}
TEST(specialfile, devUrandomWrite_fails_on_nt) {
if (!IsWindows()) {
return;
}
char buf[8] = {0};
ASSERT_SYS(0, 3, creat("/dev/urandom", 0644));
ASSERT_EQ(O_WRONLY, fcntl(3, F_GETFL) & allowMask);
ASSERT_SYS(EPERM, -1, write(3, buf, 8));
ASSERT_SYS(0, 0, close(3));
}
TEST(specialfile, devStdout) {
char buf[8] = {8};
CaptureStdout();

1
third_party/awk/b.c vendored
View file

@ -1463,6 +1463,7 @@ rescan:
}
break;
}
__builtin_unreachable();
}
int cgoto(fa *f, int s, int c)

View file

@ -215,7 +215,7 @@
(runs (format "o/$m/%s%s V=5 TESTARGS=-b" name runsuffix))
(buns (format "o/$m/test/%s_test%s V=5 TESTARGS=-b" name runsuffix)))
(cond ((not (member ext '("c" "cc" "cpp" "s" "S" "rl" "f" "cu")))
(format "m=%s; make -j32 MODE=$m o/$m/%s"
(format "m=%s; make -j96 MODE=$m o/$m/%s"
mode
(directory-file-name
(or (file-name-directory
@ -226,7 +226,7 @@
(cosmo-join
" && "
`("m=%s; f=o/$m/%s"
,(concat "make -j32 $f MODE=$m")
,(concat "make -j96 $f MODE=$m")
"scp $f $f.dbg win10:; ssh win10 ./%s"))
mode name (file-name-nondirectory name)))
((eq kind 'run-xnu)
@ -234,19 +234,19 @@
(cosmo-join
" && "
`("m=%s; f=o/$m/%s"
,(concat "make -j32 $f MODE=$m")
,(concat "make -j96 $f MODE=$m")
"scp $f $f.dbg xnu:"
"ssh xnu ./%s"))
mode name (file-name-nondirectory name)))
((and (equal suffix "")
(cosmo-contains "_test." (buffer-file-name)))
(format "m=%s; make -j32 MODE=$m %s"
(format "m=%s; make -j96 MODE=$m %s"
mode runs))
((and (equal suffix "")
(file-exists-p (format "%s" buddy)))
(format (cosmo-join
" && "
'("m=%s; n=%s; make -j32 o/$m/$n%s.o MODE=$m"
'("m=%s; n=%s; make -j96 o/$m/$n%s.o MODE=$m"
;; "bloat o/$m/%s.o | head"
;; "nm -C --size o/$m/%s.o | sort -r"
"echo"
@ -258,11 +258,11 @@
(cosmo-join
" && "
`("m=%s; f=o/$m/%s"
,(concat "make -j32 $f MODE=$m")
,(concat "make -j96 $f MODE=$m")
"build/run ./$f"))
mode name))
((eq kind 'test)
(format `"m=%s; f=o/$m/%s.ok && make -j32 $f MODE=$m" mode name))
(format `"m=%s; f=o/$m/%s.ok && make -j96 $f MODE=$m" mode name))
((and (file-regular-p this)
(file-executable-p this))
(format "build/run ./%s" file))
@ -271,7 +271,7 @@
(cosmo-join
" && "
`("m=%s; f=o/$m/%s%s.o"
,(concat "make -j32 $f MODE=$m")
,(concat "make -j96 $f MODE=$m")
;; "nm -C --size $f | sort -r"
"echo"
"size -A $f | grep '^[.T]' | grep -v 'debug\\|command.line\\|stack' | sort -rnk2"
@ -481,7 +481,7 @@
(error "don't know how to show assembly for non c/c++ source file"))
(let* ((default-directory root)
(compile-command
(format "make %s -j32 MODE=%s %s %s"
(format "make %s -j96 MODE=%s %s %s"
(or extra-make-flags "") mode asm-gcc asm-clang)))
(save-buffer)
(set-visited-file-modtime (current-time))
@ -641,11 +641,11 @@
(compile (format "sh -c %s" file)))
((eq major-mode 'lua-mode)
(let* ((mode (cosmo--make-mode arg)))
(compile (format "make -j32 MODE=%s o/%s/tool/net/redbean && build/run o/%s/tool/net/redbean -i %s" mode mode mode file))))
(compile (format "make -j96 MODE=%s o/%s/tool/net/redbean && build/run o/%s/tool/net/redbean -i %s" mode mode mode file))))
((and (eq major-mode 'python-mode)
(cosmo-startswith "third_party/python/Lib/test/" file))
(let ((mode (cosmo--make-mode arg)))
(compile (format "make -j32 MODE=%s PYHARNESSARGS=-vv PYTESTARGS=-v o/%s/%s.py.runs"
(compile (format "make -j96 MODE=%s PYHARNESSARGS=-vv PYTESTARGS=-v o/%s/%s.py.runs"
mode mode (file-name-sans-extension file)))))
((eq major-mode 'python-mode)
(compile (format "python %s" file)))