mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-07 03:38:31 +00:00
Make more fixes and improvements
- Remove PAGESIZE constant - Fix realloc() documentation - Fix ttyname_r() error reporting - Make forking more reliable on Windows - Make execvp() a few microseconds faster - Make system() a few microseconds faster - Tighten up the socket-related magic numbers - Loosen restrictions on mmap() offset alignment - Improve GetProgramExecutableName() with getenv("_") - Use mkstemp() as basis for mktemp(), tmpfile(), tmpfd() - Fix flakes in pthread_cancel_test, unix_test, fork_test - Fix recently introduced futex stack overflow regression - Let sockets be passed as stdio to subprocesses on Windows - Improve security of bind() on Windows w/ SO_EXCLUSIVEADDRUSE
This commit is contained in:
parent
140a8a52e5
commit
18bb5888e1
311 changed files with 1239 additions and 2622 deletions
|
@ -134,12 +134,6 @@ o/$(MODE)/libc/calls/mkntenvblock.o: private \
|
|||
CPPFLAGS += \
|
||||
-DSTACK_FRAME_UNLIMITED
|
||||
|
||||
# we must segregate codegen because:
|
||||
# file contains multiple independently linkable apis
|
||||
COPTS += \
|
||||
-ffunction-sections \
|
||||
-fdata-sections
|
||||
|
||||
# we always want -Os because:
|
||||
# va_arg codegen is very bloated in default mode
|
||||
o//libc/calls/open.o \
|
||||
|
|
|
@ -17,14 +17,14 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/cosmo.h"
|
||||
#include "libc/nexgen32e/rdtsc.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
static struct {
|
||||
pthread_once_t once;
|
||||
_Atomic(uint32_t) once;
|
||||
struct timespec base_wall;
|
||||
uint64_t base_tick;
|
||||
} g_mono;
|
||||
|
@ -39,7 +39,7 @@ int sys_clock_gettime_mono(struct timespec *time) {
|
|||
uint64_t cycles;
|
||||
struct timespec res;
|
||||
if (X86_HAVE(INVTSC)) {
|
||||
pthread_once(&g_mono.once, sys_clock_gettime_mono_init);
|
||||
cosmo_once(&g_mono.once, sys_clock_gettime_mono_init);
|
||||
cycles = rdtsc() - g_mono.base_tick;
|
||||
nanos = cycles / 3;
|
||||
*time = timespec_add(g_mono.base_wall, timespec_fromnanos(nanos));
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/calls/struct/sigset.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/cosmo.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
|
@ -30,10 +31,9 @@
|
|||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
static struct CopyFileRange {
|
||||
pthread_once_t once;
|
||||
_Atomic(uint32_t) once;
|
||||
bool ok;
|
||||
} g_copy_file_range;
|
||||
|
||||
|
@ -104,7 +104,7 @@ ssize_t copy_file_range(int infd, int64_t *opt_in_out_inoffset, int outfd,
|
|||
int64_t *opt_in_out_outoffset, size_t uptobytes,
|
||||
uint32_t flags) {
|
||||
ssize_t rc;
|
||||
pthread_once(&g_copy_file_range.once, copy_file_range_init);
|
||||
cosmo_once(&g_copy_file_range.once, copy_file_range_init);
|
||||
BEGIN_CANCELLATION_POINT;
|
||||
|
||||
if (!g_copy_file_range.ok) {
|
||||
|
|
|
@ -30,6 +30,17 @@
|
|||
* The `O_CLOEXEC` flag shall be cleared from the resulting file
|
||||
* descriptor; see dup3() to preserve it.
|
||||
*
|
||||
* One use case for duplicating file descriptors is to be able to
|
||||
* reassign an open()'d file or pipe() to the stdio of an executed
|
||||
* subprocess. On Windows, in order for this to work, the subprocess
|
||||
* needs to be a Cosmopolitan program that has socket() linked.
|
||||
*
|
||||
* Only small programs should duplicate sockets. That's because this
|
||||
* implementation uses DuplicateHandle() on Windows, which Microsoft
|
||||
* says might cause its resources to leak internally. Thus it likely
|
||||
* isn't a good idea to design a server that does it a lot and lives
|
||||
* a long time, without contributing a patch to this implementation.
|
||||
*
|
||||
* @param fd remains open afterwards
|
||||
* @return some arbitrary new number for fd
|
||||
* @raise EPERM if pledge() is in play without stdio
|
||||
|
|
|
@ -27,13 +27,24 @@
|
|||
/**
|
||||
* Duplicates file descriptor, granting it specific number.
|
||||
*
|
||||
* The `O_CLOEXEC` flag shall be cleared from the resulting file
|
||||
* descriptor; see dup3() to preserve it.
|
||||
*
|
||||
* Unlike dup3(), the dup2() function permits oldfd and newfd to be the
|
||||
* same, in which case the only thing this function does is test if
|
||||
* oldfd is open.
|
||||
*
|
||||
* The `O_CLOEXEC` flag shall be cleared from the resulting file
|
||||
* descriptor; see dup3() to preserve it.
|
||||
*
|
||||
* One use case for duplicating file descriptors is to be able to
|
||||
* reassign an open()'d file or pipe() to the stdio of an executed
|
||||
* subprocess. On Windows, in order for this to work, the subprocess
|
||||
* needs to be a Cosmopolitan program that has socket() linked.
|
||||
*
|
||||
* Only small programs should duplicate sockets. That's because this
|
||||
* implementation uses DuplicateHandle() on Windows, which Microsoft
|
||||
* says might cause its resources to leak internally. Thus it likely
|
||||
* isn't a good idea to design a server that does it a lot and lives
|
||||
* a long time, without contributing a patch to this implementation.
|
||||
*
|
||||
* @param oldfd isn't closed afterwards
|
||||
* @param newfd if already assigned, is silently closed beforehand;
|
||||
* unless it's equal to oldfd, in which case dup2() is a no-op
|
||||
|
|
|
@ -19,18 +19,18 @@
|
|||
#include "libc/assert.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/syscall_support-sysv.internal.h"
|
||||
#include "libc/cosmo.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
|
||||
|
||||
static struct Dup3 {
|
||||
pthread_once_t once;
|
||||
_Atomic(uint32_t) once;
|
||||
bool demodernize;
|
||||
} g_dup3;
|
||||
|
||||
|
@ -58,7 +58,7 @@ int32_t sys_dup3(int32_t oldfd, int32_t newfd, int flags) {
|
|||
return __sys_fcntl(oldfd, how, newfd);
|
||||
}
|
||||
|
||||
pthread_once(&g_dup3.once, sys_dup3_test);
|
||||
cosmo_once(&g_dup3.once, sys_dup3_test);
|
||||
|
||||
if (!g_dup3.demodernize) {
|
||||
return __sys_dup3(oldfd, newfd, flags);
|
||||
|
|
|
@ -28,9 +28,19 @@
|
|||
/**
|
||||
* Duplicates file descriptor/handle.
|
||||
*
|
||||
* On Windows, we can't guarantee the desired file descriptor is used.
|
||||
* We can however remap the standard handles (non-atomically) if their
|
||||
* symbolic names are used.
|
||||
* The `O_CLOEXEC` flag shall be cleared from the resulting file
|
||||
* descriptor; see dup3() to preserve it.
|
||||
*
|
||||
* One use case for duplicating file descriptors is to be able to
|
||||
* reassign an open()'d file or pipe() to the stdio of an executed
|
||||
* subprocess. On Windows, in order for this to work, the subprocess
|
||||
* needs to be a Cosmopolitan program that has socket() linked.
|
||||
*
|
||||
* Only small programs should duplicate sockets. That's because this
|
||||
* implementation uses DuplicateHandle() on Windows, which Microsoft
|
||||
* says might cause its resources to leak internally. Thus it likely
|
||||
* isn't a good idea to design a server that does it a lot and lives
|
||||
* a long time, without contributing a patch to this implementation.
|
||||
*
|
||||
* @param oldfd isn't closed afterwards
|
||||
* @param newfd if already assigned, is silently closed beforehand;
|
||||
|
|
|
@ -42,11 +42,6 @@ int execlp(const char *prog, const char *arg, ... /*, NULL*/) {
|
|||
va_list va, vb;
|
||||
char pathbuf[PATH_MAX];
|
||||
|
||||
// resolve path of executable
|
||||
if (!(exe = commandv(prog, pathbuf, sizeof(pathbuf)))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// turn varargs into array
|
||||
va_copy(vb, va);
|
||||
va_start(va, arg);
|
||||
|
@ -60,6 +55,15 @@ int execlp(const char *prog, const char *arg, ... /*, NULL*/) {
|
|||
}
|
||||
va_end(vb);
|
||||
|
||||
if (strchr(prog, '/')) {
|
||||
return execv(prog, argv);
|
||||
}
|
||||
|
||||
// resolve path of executable
|
||||
if (!(exe = commandv(prog, pathbuf, sizeof(pathbuf)))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// change argv[0] to resolved path if it's ambiguous
|
||||
// otherwise the program won't have much luck finding itself
|
||||
if (argv[0] && *prog != '/' && *exe == '/' && !strcmp(prog, argv[0])) {
|
||||
|
|
|
@ -21,7 +21,9 @@
|
|||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ntspawn.h"
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
#include "libc/nt/accounting.h"
|
||||
#include "libc/nt/console.h"
|
||||
|
@ -35,6 +37,7 @@
|
|||
#include "libc/nt/thunk/msabi.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
|
@ -84,22 +87,36 @@ textwindows int sys_execve_nt(const char *program, char *const argv[],
|
|||
//////////////////////////////////////////////////////////////////////////////
|
||||
// execve operation is unrecoverable from this point
|
||||
|
||||
// close cloexec handles
|
||||
for (i = 3; i < g_fds.n; ++i) {
|
||||
if (g_fds.p[i].kind != kFdEmpty && (g_fds.p[i].flags & O_CLOEXEC)) {
|
||||
// close non-stdio and cloexec handles
|
||||
for (i = 0; i < g_fds.n; ++i) {
|
||||
if (g_fds.p[i].kind == kFdEmpty) {
|
||||
g_fds.p[i].handle = -1;
|
||||
} else if (i > 2 || (g_fds.p[i].flags & O_CLOEXEC)) {
|
||||
__imp_CloseHandle(g_fds.p[i].handle);
|
||||
g_fds.p[i].handle = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int bits;
|
||||
char buf[32], *v = 0;
|
||||
if (_weaken(socket)) {
|
||||
for (bits = i = 0; i < 3; ++i) {
|
||||
if (g_fds.p[i].kind == kFdSocket) {
|
||||
bits |= 1 << i;
|
||||
}
|
||||
}
|
||||
FormatInt32(stpcpy(buf, "__STDIO_SOCKETS="), bits);
|
||||
v = buf;
|
||||
}
|
||||
bzero(&startinfo, sizeof(startinfo));
|
||||
startinfo.cb = sizeof(struct NtStartupInfo);
|
||||
startinfo.dwFlags = kNtStartfUsestdhandles;
|
||||
startinfo.hStdInput = __getfdhandleactual(0);
|
||||
startinfo.hStdOutput = __getfdhandleactual(1);
|
||||
startinfo.hStdError = __getfdhandleactual(2);
|
||||
startinfo.hStdInput = g_fds.p[0].handle;
|
||||
startinfo.hStdOutput = g_fds.p[1].handle;
|
||||
startinfo.hStdError = g_fds.p[2].handle;
|
||||
|
||||
// spawn the process
|
||||
rc = ntspawn(program, argv, envp, 0, 0, 0, true, 0, 0, &startinfo, &procinfo);
|
||||
rc = ntspawn(program, argv, envp, v, 0, 0, true, 0, 0, &startinfo, &procinfo);
|
||||
if (rc == -1) {
|
||||
STRACE("panic: unrecoverable ntspawn(%#s) error: %m", program);
|
||||
__imp_ExitProcess(6543);
|
||||
|
|
|
@ -40,6 +40,11 @@
|
|||
* to be valid UTF-8 in order to round-trip the WIN32 API, without being
|
||||
* corrupted.
|
||||
*
|
||||
* On Windows, only file descriptors 0, 1 and 2 can be passed to a child
|
||||
* process in such a way that allows them to be automatically discovered
|
||||
* when the child process initializes. Cosmpolitan currently treats your
|
||||
* other file descriptors as implicitly O_CLOEXEC.
|
||||
*
|
||||
* @param program will not be PATH searched, see commandv()
|
||||
* @param argv[0] is the name of the program to run
|
||||
* @param argv[1,n-2] optionally specify program arguments
|
||||
|
|
|
@ -27,7 +27,9 @@
|
|||
/**
|
||||
* Executes program, with path environment search.
|
||||
*
|
||||
* The current process is replaced with the executed one.
|
||||
* This function is a wrapper of the execve() system call that does path
|
||||
* resolution. The `PATH` environment variable is taken from your global
|
||||
* `environ` rather than the `envp` argument.
|
||||
*
|
||||
* @param prog is the program to launch
|
||||
* @param argv is [file,argv₁..argvₙ₋₁,NULL]
|
||||
|
@ -47,6 +49,10 @@ int execvpe(const char *prog, char *const argv[], char *const *envp) {
|
|||
return efault();
|
||||
}
|
||||
|
||||
if (strchr(prog, '/')) {
|
||||
return execve(prog, argv, envp);
|
||||
}
|
||||
|
||||
// resolve path of executable
|
||||
if (!(exe = commandv(prog, pathbuf, sizeof(pathbuf)))) {
|
||||
return -1;
|
||||
|
|
|
@ -321,8 +321,9 @@ static textwindows int sys_fcntl_nt_setfl(int fd, unsigned *flags, unsigned arg,
|
|||
//
|
||||
// - O_NONBLOCK make read() raise EAGAIN
|
||||
// - O_NDELAY same thing as O_NONBLOCK
|
||||
// - O_ACCMODE but has a minimal effect
|
||||
//
|
||||
allowed = O_NONBLOCK;
|
||||
allowed = O_ACCMODE | O_NONBLOCK;
|
||||
if (changed & ~allowed) {
|
||||
// the following access mode flags are supported, but it's currently
|
||||
// not possible to change them on windows.
|
||||
|
|
|
@ -102,7 +102,7 @@ textwindows int sys_fstat_nt(int64_t handle, struct stat *st) {
|
|||
st->st_ctim = FileTimeToTimeSpec(wst.ftCreationFileTime);
|
||||
st->st_birthtim = st->st_ctim;
|
||||
st->st_size = (uint64_t)wst.nFileSizeHigh << 32 | wst.nFileSizeLow;
|
||||
st->st_blksize = PAGESIZE;
|
||||
st->st_blksize = 4096;
|
||||
st->st_dev = wst.dwVolumeSerialNumber;
|
||||
st->st_rdev = 0;
|
||||
st->st_ino = (uint64_t)wst.nFileIndexHigh << 32 | wst.nFileIndexLow;
|
||||
|
@ -118,7 +118,7 @@ textwindows int sys_fstat_nt(int64_t handle, struct stat *st) {
|
|||
&fci, sizeof(fci))) {
|
||||
actualsize = fci.CompressedFileSize;
|
||||
}
|
||||
st->st_blocks = ROUNDUP(actualsize, PAGESIZE) / 512;
|
||||
st->st_blocks = ROUNDUP(actualsize, 4096) / 512;
|
||||
}
|
||||
} else {
|
||||
STRACE("%s failed %m", "GetFileInformationByHandle");
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/metalfile.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/cosmo.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
@ -34,7 +35,10 @@
|
|||
#define KERN_PROC_PATHNAME_FREEBSD 12
|
||||
#define KERN_PROC_PATHNAME_NETBSD 5
|
||||
|
||||
char program_executable_name[PATH_MAX];
|
||||
static struct ProgramExecutableName {
|
||||
_Atomic(uint32_t) once;
|
||||
char buf[PATH_MAX];
|
||||
} program_executable_name;
|
||||
|
||||
static inline int IsAlpha(int c) {
|
||||
return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z');
|
||||
|
@ -50,7 +54,9 @@ static inline char *StrCat(char buf[PATH_MAX], const char *a, const char *b) {
|
|||
}
|
||||
|
||||
static inline void GetProgramExecutableNameImpl(char *p, char *e) {
|
||||
int c;
|
||||
char *q;
|
||||
char **ep;
|
||||
ssize_t rc;
|
||||
size_t i, n;
|
||||
union {
|
||||
|
@ -84,9 +90,9 @@ static inline void GetProgramExecutableNameImpl(char *p, char *e) {
|
|||
|
||||
// if argv[0] exists then turn it into an absolute path. we also try
|
||||
// adding a .com suffix since the ape auto-appends it when resolving
|
||||
if (__argc && (((q = __argv[0]) && !sys_faccessat(AT_FDCWD, q, F_OK, 0)) ||
|
||||
((q = StrCat(u.path, __argv[0], ".com")) &&
|
||||
!sys_faccessat(AT_FDCWD, q, F_OK, 0)))) {
|
||||
if (((q = __argv[0]) && !sys_faccessat(AT_FDCWD, q, F_OK, 0)) ||
|
||||
((q = StrCat(u.path, __argv[0], ".com")) &&
|
||||
!sys_faccessat(AT_FDCWD, q, F_OK, 0))) {
|
||||
if (*q != '/') {
|
||||
if (q[0] == '.' && q[1] == '/') {
|
||||
q += 2;
|
||||
|
@ -103,6 +109,19 @@ static inline void GetProgramExecutableNameImpl(char *p, char *e) {
|
|||
return;
|
||||
}
|
||||
|
||||
// if getenv("_") exists then use that
|
||||
for (ep = __envp; (q = *ep); ++ep) {
|
||||
if (*q++ == '_' && *q++ == '=') {
|
||||
while ((c = *q++)) {
|
||||
if (p + 1 < e) {
|
||||
*p++ = c;
|
||||
}
|
||||
}
|
||||
*p = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// if argv[0] doesn't exist, then fallback to interpreter name
|
||||
if ((rc = sys_readlinkat(AT_FDCWD, "/proc/self/exe", p, e - p - 1)) > 0 ||
|
||||
(rc = sys_readlinkat(AT_FDCWD, "/proc/curproc/file", p, e - p - 1)) > 0) {
|
||||
|
@ -125,28 +144,29 @@ static inline void GetProgramExecutableNameImpl(char *p, char *e) {
|
|||
}
|
||||
|
||||
// otherwise give up and just copy argv[0] into it
|
||||
if (!*p && __argv[0] && strlen(__argv[0]) < e - p) {
|
||||
strcpy(p, __argv[0]);
|
||||
if (!*p && (q = __argv[0])) {
|
||||
while ((c = *q++)) {
|
||||
if (p + 1 < e) {
|
||||
*p++ = c;
|
||||
}
|
||||
}
|
||||
*p = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void InitProgramExecutableName(void) {
|
||||
int e;
|
||||
e = errno;
|
||||
GetProgramExecutableNameImpl(
|
||||
program_executable_name.buf,
|
||||
program_executable_name.buf + sizeof(program_executable_name.buf));
|
||||
errno = e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns absolute path of program.
|
||||
*/
|
||||
char *GetProgramExecutableName(void) {
|
||||
int e;
|
||||
static bool once;
|
||||
if (!once) {
|
||||
e = errno;
|
||||
GetProgramExecutableNameImpl(
|
||||
program_executable_name,
|
||||
program_executable_name + sizeof(program_executable_name));
|
||||
errno = e;
|
||||
once = true;
|
||||
}
|
||||
return program_executable_name;
|
||||
cosmo_once(&program_executable_name.once, InitProgramExecutableName);
|
||||
return program_executable_name.buf;
|
||||
}
|
||||
|
||||
/* const void *const GetProgramExecutableNameCtor[] initarray = { */
|
||||
/* GetProgramExecutableName, */
|
||||
/* }; */
|
||||
|
|
|
@ -48,7 +48,7 @@ __attribute__((__constructor__)) static void kTmpPathInit(void) {
|
|||
char16_t path16[PATH_MAX];
|
||||
|
||||
if ((s = getenv("TMPDIR")) && (n = strlen(s)) < PATH_MAX / 2) {
|
||||
memcpy(kTmpPath, s, n);
|
||||
if (n) memcpy(kTmpPath, s, n);
|
||||
if (n && kTmpPath[n - 1] != '/') {
|
||||
kTmpPath[n + 0] = '/';
|
||||
kTmpPath[n + 1] = 0;
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/stdio/rand.h"
|
||||
#include "libc/stdio/temp.h"
|
||||
|
@ -25,30 +27,54 @@
|
|||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Creates temporary file name and descriptor, e.g.
|
||||
* Creates temporary file name and file descriptor.
|
||||
*
|
||||
* The best way to construct your path template is:
|
||||
*
|
||||
* char path[PATH_MAX+1];
|
||||
* strlcat(path, kTmpDir, sizeof(path));
|
||||
* strlcat(path, "sauce.XXXXXX", sizeof(path));
|
||||
*
|
||||
* This usage pattern makes mkstemp() equivalent to tmpfd():
|
||||
*
|
||||
* int fd;
|
||||
* fd = mkstemp(path);
|
||||
* unlink(path);
|
||||
*
|
||||
* This usage pattern makes mkstemp() equivalent to mktemp():
|
||||
*
|
||||
* close(mkstemp(path));
|
||||
* puts(path);
|
||||
*
|
||||
* @param template is mutated to replace last six X's with rng
|
||||
* @return open file descriptor r + w exclusive or -1 w/ errno
|
||||
* @raise EINVAL if `template` didn't end with `XXXXXX`
|
||||
* @see tmpfd() if you don't need a path
|
||||
*/
|
||||
int mkstemp(char *template) {
|
||||
int i, n;
|
||||
uint64_t w;
|
||||
int i, n, e, fd;
|
||||
if ((n = strlen(template)) < 6 ||
|
||||
READ16LE(template + n - 2) != READ16LE("XX") ||
|
||||
READ32LE(template + n - 6) != READ32LE("XXXX")) {
|
||||
return einval();
|
||||
}
|
||||
w = _rand64();
|
||||
for (i = 0; i < 6; ++i) {
|
||||
template[n - 6 + i] = "0123456789abcdefghijklmnopqrstuvwxyz"[w % 36];
|
||||
w /= 36;
|
||||
for (;;) {
|
||||
w = _rand64();
|
||||
for (i = 0; i < 6; ++i) {
|
||||
template[n - 6 + i] = "0123456789abcdefghijklmnopqrstuvwxyz"[w % 36];
|
||||
w /= 36;
|
||||
}
|
||||
e = errno;
|
||||
if ((fd = open(template,
|
||||
O_RDWR | O_CREAT | O_EXCL | (IsWindows() ? 0x00410000 : 0),
|
||||
0600)) != -1) {
|
||||
return fd;
|
||||
} else if (errno == EEXIST) {
|
||||
errno = e;
|
||||
} else {
|
||||
template[0] = 0;
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
return open(template, O_RDWR | O_CREAT | O_EXCL, 0600);
|
||||
}
|
|
@ -16,11 +16,8 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/stdio/rand.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/stdio/temp.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Generates temporary filename.
|
||||
|
@ -34,18 +31,11 @@
|
|||
* @see mkstemp()
|
||||
*/
|
||||
char *mktemp(char *template) {
|
||||
int i, n;
|
||||
uint64_t w;
|
||||
if ((n = strlen(template)) < 6 ||
|
||||
READ16LE(template + n - 2) != READ16LE("XX") ||
|
||||
READ32LE(template + n - 6) != READ32LE("XXXX")) {
|
||||
errno = EINVAL;
|
||||
int fd;
|
||||
if ((fd = mkstemp(template)) != -1) {
|
||||
close(fd);
|
||||
return template;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
w = _rand64();
|
||||
for (i = 0; i < 6; ++i) {
|
||||
template[n - 6 + i] = "0123456789abcdefghijklmnopqrstuvwxyz"[w % 36];
|
||||
w /= 36;
|
||||
}
|
||||
return template;
|
||||
}
|
|
@ -132,6 +132,7 @@
|
|||
* @raise ENOTSUP if `file` is on zip file system and process is vfork()'d
|
||||
* @raise ENOSPC if file system is full when `file` would be `O_CREAT`ed
|
||||
* @raise EINTR if we needed to block and a signal was delivered instead
|
||||
* @raise EEXIST if `O_CREAT|O_EXCL` are used and `file` already existed
|
||||
* @raise ECANCELED if thread was cancelled in masked mode
|
||||
* @raise ENOENT if `file` doesn't exist when `O_CREAT` isn't in `flags`
|
||||
* @raise ENOENT if `file` points to a string that's empty
|
||||
|
|
|
@ -86,7 +86,7 @@ ssize_t read(int fd, void *buf, size_t size) {
|
|||
rc = ebadf();
|
||||
}
|
||||
END_CANCELLATION_POINT;
|
||||
DATATRACE("read(%d, [%#.*hhs%s], %'zu) → %'zd% m", fd, MAX(0, MIN(40, rc)),
|
||||
buf, rc > 40 ? "..." : "", size, rc);
|
||||
DATATRACE("read(%d, [%#.*hhs%s], %'zu) → %'zd% m", fd,
|
||||
(int)MAX(0, MIN(40, rc)), buf, rc > 40 ? "..." : "", size, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ ssize_t sys_readv_metal(struct Fd *fd, const struct iovec *iov, int iovlen) {
|
|||
file = (struct MetalFile *)fd->handle;
|
||||
for (toto = i = 0; i < iovlen && file->pos < file->size; ++i) {
|
||||
got = MIN(iov[i].iov_len, file->size - file->pos);
|
||||
memcpy(iov[i].iov_base, file->base, got);
|
||||
if (got) memcpy(iov[i].iov_base, file->base, got);
|
||||
toto += got;
|
||||
}
|
||||
return toto;
|
||||
|
|
|
@ -145,7 +145,7 @@ restart:
|
|||
l++;
|
||||
}
|
||||
if (q+l >= PATH_MAX) goto toolong;
|
||||
memcpy(output+q, stack+p, l);
|
||||
if (l) memcpy(output+q, stack+p, l);
|
||||
output[q+l] = 0;
|
||||
p += l;
|
||||
|
||||
|
@ -223,7 +223,7 @@ skip_readlink:
|
|||
if (q-p && !IsSlash(stack[l-1])) stack[l++] = '/';
|
||||
if (l + (q-p) + 1 >= PATH_MAX) goto toolong;
|
||||
memmove(output + l, output + p, q - p + 1);
|
||||
memcpy(output, stack, l);
|
||||
if (l) memcpy(output, stack, l);
|
||||
q = l + q-p;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/cosmo.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
|
@ -28,10 +29,9 @@
|
|||
#include "libc/mem/alloca.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
static struct Splice {
|
||||
pthread_once_t once;
|
||||
_Atomic(uint32_t) once;
|
||||
bool ok;
|
||||
} g_splice;
|
||||
|
||||
|
@ -79,7 +79,7 @@ ssize_t splice(int infd, int64_t *opt_in_out_inoffset, int outfd,
|
|||
int64_t *opt_in_out_outoffset, size_t uptobytes,
|
||||
uint32_t flags) {
|
||||
ssize_t rc;
|
||||
pthread_once(&g_splice.once, splice_init);
|
||||
cosmo_once(&g_splice.once, splice_init);
|
||||
if (!g_splice.ok) {
|
||||
rc = enosys();
|
||||
} else if (IsAsan() && ((opt_in_out_inoffset &&
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/cosmo.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/nt/enum/accessmask.h"
|
||||
#include "libc/nt/enum/fileflagandattributes.h"
|
||||
|
@ -31,12 +32,13 @@
|
|||
#include "libc/nt/struct/tokenprivileges.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
__msabi extern typeof(GetFileAttributes) *const __imp_GetFileAttributesW;
|
||||
|
||||
static _Bool g_winlink_allowed;
|
||||
static pthread_once_t g_winlink_once;
|
||||
static struct {
|
||||
_Atomic(uint32_t) once;
|
||||
_Bool allowed;
|
||||
} g_winlink;
|
||||
|
||||
static textwindows void InitializeWinlink(void) {
|
||||
int64_t tok;
|
||||
|
@ -48,7 +50,7 @@ static textwindows void InitializeWinlink(void) {
|
|||
tp.Privileges[0].Luid = id;
|
||||
tp.Privileges[0].Attributes = kNtSePrivilegeEnabled;
|
||||
if (!AdjustTokenPrivileges(tok, 0, &tp, sizeof(tp), 0, 0)) return;
|
||||
g_winlink_allowed = GetLastError() != kNtErrorNotAllAssigned;
|
||||
g_winlink.allowed = GetLastError() != kNtErrorNotAllAssigned;
|
||||
}
|
||||
|
||||
textwindows int sys_symlinkat_nt(const char *target, int newdirfd,
|
||||
|
@ -82,8 +84,8 @@ textwindows int sys_symlinkat_nt(const char *target, int newdirfd,
|
|||
|
||||
// windows only lets administrators do this
|
||||
// even then we're required to ask for permission
|
||||
pthread_once(&g_winlink_once, InitializeWinlink);
|
||||
if (!g_winlink_allowed) {
|
||||
cosmo_once(&g_winlink.once, InitializeWinlink);
|
||||
if (!g_winlink.allowed) {
|
||||
return eperm();
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
* @note Linux documentation says this call is "dangerous"; for highest
|
||||
* assurance of data recovery after crash, consider fsync() on both
|
||||
* file and directory
|
||||
* @see fsync(), fdatasync(), PAGESIZE
|
||||
* @see fsync(), fdatasync()
|
||||
*/
|
||||
int sync_file_range(int fd, int64_t offset, int64_t bytes, unsigned flags) {
|
||||
int rc, olderr;
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
│ 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/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/rand.h"
|
||||
#include "libc/stdio/temp.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
@ -64,6 +64,7 @@
|
|||
* @return file descriptor on success, or -1 w/ errno
|
||||
* @raise ECANCELED if thread was cancelled in masked mode
|
||||
* @raise EINTR if signal was delivered
|
||||
* @see mkstemp() if you need a path
|
||||
* @see tmpfile() for stdio version
|
||||
* @cancellationpoint
|
||||
* @asyncsignalsafe
|
||||
|
@ -71,45 +72,23 @@
|
|||
* @vforksafe
|
||||
*/
|
||||
int tmpfd(void) {
|
||||
FILE *f;
|
||||
unsigned x;
|
||||
int fd, i, j, e;
|
||||
char path[PATH_MAX], *p;
|
||||
e = errno;
|
||||
if (IsLinux() && (fd = open(kTmpPath, O_RDWR | _O_TMPFILE, 0600)) != -1) {
|
||||
return fd;
|
||||
}
|
||||
errno = e;
|
||||
p = path;
|
||||
p = stpcpy(p, kTmpPath);
|
||||
p = stpcpy(p, "tmp.");
|
||||
if (program_invocation_short_name &&
|
||||
strlen(program_invocation_short_name) < 128) {
|
||||
p = stpcpy(p, program_invocation_short_name);
|
||||
*p++ = '.';
|
||||
}
|
||||
for (i = 0; i < 10; ++i) {
|
||||
x = _rand64();
|
||||
for (j = 0; j < 6; ++j) {
|
||||
p[j] = "0123456789abcdefghijklmnopqrstuvwxyz"[x % 36];
|
||||
x /= 36;
|
||||
}
|
||||
p[j] = 0;
|
||||
int e, fd;
|
||||
const char *prog;
|
||||
char path[PATH_MAX + 1];
|
||||
if (IsLinux()) {
|
||||
e = errno;
|
||||
if ((fd = open(path,
|
||||
O_RDWR | O_CREAT | O_EXCL | (IsWindows() ? _O_TMPFILE : 0),
|
||||
0600)) != -1) {
|
||||
if (!IsWindows()) {
|
||||
if (unlink(path)) {
|
||||
notpossible;
|
||||
}
|
||||
}
|
||||
if ((fd = open(kTmpPath, O_RDWR | _O_TMPFILE, 0600)) != -1) {
|
||||
return fd;
|
||||
} else if (errno == EEXIST) {
|
||||
errno = e;
|
||||
} else {
|
||||
break;
|
||||
errno = e;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
path[0] = 0;
|
||||
strlcat(path, kTmpPath, sizeof(path));
|
||||
if (!(prog = program_invocation_short_name)) prog = "tmp";
|
||||
strlcat(path, prog, sizeof(path));
|
||||
strlcat(path, ".XXXXXX", sizeof(path));
|
||||
if ((fd = mkstemp(path)) == -1) return -1;
|
||||
if (!IsWindows()) unassert(!unlink(path));
|
||||
return fd;
|
||||
}
|
||||
|
|
|
@ -17,15 +17,26 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/sysparam.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/log/log.h"
|
||||
|
||||
static char ttyname_buf[PATH_MAX];
|
||||
#include "libc/paths.h"
|
||||
|
||||
/**
|
||||
* Returns name of terminal.
|
||||
*
|
||||
* This function isn't required to be thread safe, consider ttyname_r().
|
||||
*
|
||||
* @return terminal path on success, or null w/ errno
|
||||
* @see ttyname_r()
|
||||
*/
|
||||
char *ttyname(int fd) {
|
||||
int rc = ttyname_r(fd, ttyname_buf, sizeof(ttyname_buf));
|
||||
if (rc != 0) return NULL;
|
||||
return &ttyname_buf[0];
|
||||
errno_t err;
|
||||
static char buf[sizeof(_PATH_DEV) + MAXNAMLEN];
|
||||
if (!(err = ttyname_r(fd, buf, sizeof(buf)))) {
|
||||
return buf;
|
||||
} else {
|
||||
errno = err;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "libc/errno.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/fmt/magnumstrs.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/nt/console.h"
|
||||
|
@ -34,66 +35,79 @@
|
|||
|
||||
#define FIODGNAME 0x80106678 // freebsd
|
||||
|
||||
static textwindows dontinline int sys_ttyname_nt(int fd, char *buf,
|
||||
size_t size) {
|
||||
static textwindows errno_t sys_ttyname_nt(int fd, char *buf, size_t size) {
|
||||
uint32_t mode;
|
||||
const char *s;
|
||||
if (GetConsoleMode(g_fds.p[fd].handle, &mode)) {
|
||||
if (mode & kNtEnableVirtualTerminalInput) {
|
||||
strncpy(buf, "CONIN$", size);
|
||||
if (strlcpy(buf,
|
||||
(mode & kNtEnableVirtualTerminalInput) ? "CONIN$" : "CONOUT$",
|
||||
size) < size) {
|
||||
return 0;
|
||||
} else {
|
||||
strncpy(buf, "CONOUT$", size);
|
||||
return 0;
|
||||
return ERANGE;
|
||||
}
|
||||
} else {
|
||||
return enotty();
|
||||
return ENOTTY;
|
||||
}
|
||||
}
|
||||
|
||||
static int ttyname_freebsd(int fd, char *buf, size_t size) {
|
||||
// clobbers errno
|
||||
static errno_t ttyname_freebsd(int fd, char *buf, size_t size) {
|
||||
struct fiodgname_arg {
|
||||
int len;
|
||||
void *buf;
|
||||
} fg;
|
||||
fg.buf = buf;
|
||||
fg.len = size;
|
||||
if (sys_ioctl(fd, FIODGNAME, &fg) != -1) return 0;
|
||||
return enotty();
|
||||
if (sys_ioctl(fd, FIODGNAME, &fg) != -1) {
|
||||
return 0;
|
||||
} else {
|
||||
return ENOTTY;
|
||||
}
|
||||
}
|
||||
|
||||
static int ttyname_linux(int fd, char *buf, size_t size) {
|
||||
struct stat st1, st2;
|
||||
if (!isatty(fd)) return errno;
|
||||
char name[PATH_MAX];
|
||||
FormatInt32(stpcpy(name, "/proc/self/fd/"), fd);
|
||||
// clobbers errno
|
||||
static errno_t ttyname_linux(int fd, char *buf, size_t size) {
|
||||
ssize_t got;
|
||||
struct stat st1, st2;
|
||||
char name[14 + 12 + 1];
|
||||
if (!isatty(fd)) return errno;
|
||||
FormatInt32(stpcpy(name, "/proc/self/fd/"), fd);
|
||||
got = readlink(name, buf, size);
|
||||
if (got == -1) return errno;
|
||||
if ((size_t)got >= size) return erange();
|
||||
if (got >= size) return ERANGE;
|
||||
buf[got] = 0;
|
||||
if (stat(buf, &st1) || fstat(fd, &st2)) return errno;
|
||||
if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) return enodev();
|
||||
if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) return ENODEV;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns name of terminal, reentrantly.
|
||||
* Returns name of terminal.
|
||||
*
|
||||
* @return 0 on success, or error number on error
|
||||
* @raise ERANGE if `size` was too small
|
||||
* @returnserrno
|
||||
* @threadsafe
|
||||
*/
|
||||
int ttyname_r(int fd, char *buf, size_t size) {
|
||||
int rc;
|
||||
errno_t ttyname_r(int fd, char *buf, size_t size) {
|
||||
errno_t e, res;
|
||||
e = errno;
|
||||
if (IsLinux()) {
|
||||
rc = ttyname_linux(fd, buf, size);
|
||||
res = ttyname_linux(fd, buf, size);
|
||||
} else if (IsFreebsd()) {
|
||||
rc = ttyname_freebsd(fd, buf, size);
|
||||
res = ttyname_freebsd(fd, buf, size);
|
||||
} else if (IsWindows()) {
|
||||
if (__isfdkind(fd, kFdFile)) {
|
||||
rc = sys_ttyname_nt(fd, buf, size);
|
||||
if (__isfdopen(fd)) {
|
||||
res = sys_ttyname_nt(fd, buf, size);
|
||||
} else {
|
||||
rc = ebadf();
|
||||
res = EBADF;
|
||||
}
|
||||
} else {
|
||||
rc = enosys();
|
||||
res = ENOSYS;
|
||||
}
|
||||
STRACE("ttyname_r(%d, %s) → %d% m", fd, buf, rc);
|
||||
return rc;
|
||||
errno = e;
|
||||
STRACE("ttyname_r(%d, %#.*hhs) → %s", fd, (int)size, buf,
|
||||
!res ? "0" : _strerrno(res));
|
||||
return res;
|
||||
}
|
||||
|
|
10
libc/cosmo.h
Normal file
10
libc/cosmo.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_COSMO_H_
|
||||
#define COSMOPOLITAN_LIBC_COSMO_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
errno_t cosmo_once(_Atomic(uint32_t) *, void (*)(void));
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_COSMO_H_ */
|
|
@ -78,7 +78,7 @@
|
|||
/* Programs should call GetStackSize() */
|
||||
#define APE_STACKSIZE 262144 /* default 256kb stack */
|
||||
#define FRAMESIZE 0x10000
|
||||
#define PAGESIZE 0x1000 /* i386+ */
|
||||
#define _PAGESIZE 0x1000 /* i386+ */
|
||||
#else
|
||||
#define APE_STACKSIZE 4194304 /* default 4mb stack */
|
||||
#endif
|
||||
|
|
|
@ -421,7 +421,7 @@ static struct AsanFault __asan_fault(const signed char *s, signed char dflt) {
|
|||
struct AsanFault r;
|
||||
if (s[0] < 0) {
|
||||
r.kind = s[0];
|
||||
} else if (((uintptr_t)(s + 1) & (PAGESIZE - 1)) && s[1] < 0) {
|
||||
} else if (((uintptr_t)(s + 1) & 4095) && s[1] < 0) {
|
||||
r.kind = s[1];
|
||||
} else {
|
||||
r.kind = dflt;
|
||||
|
@ -652,6 +652,8 @@ static wint_t __asan_symbolize_access_poison(signed char kind) {
|
|||
return L'μ';
|
||||
case kAsanGlobalOverrun:
|
||||
return L'Ω';
|
||||
case kAsanMmapSizeOverrun:
|
||||
return L'Z';
|
||||
default:
|
||||
return L'?';
|
||||
}
|
||||
|
@ -963,14 +965,6 @@ __attribute__((__destructor__)) static void __asan_morgue_flush(void) {
|
|||
}
|
||||
}
|
||||
|
||||
static size_t __asan_user_size(size_t n) {
|
||||
if (n) {
|
||||
return n;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t __asan_heap_size(size_t n) {
|
||||
if (n < 0x7fffffff0000) {
|
||||
n = ROUNDUP(n, _Alignof(struct AsanExtra));
|
||||
|
@ -1043,7 +1037,6 @@ static void *__asan_allocate(size_t a, size_t n, struct AsanTrace *bt,
|
|||
char *p;
|
||||
size_t c;
|
||||
struct AsanExtra *e;
|
||||
n = __asan_user_size(n);
|
||||
if ((p = _weaken(dlmemalign)(a, __asan_heap_size(n)))) {
|
||||
c = _weaken(dlmalloc_usable_size)(p);
|
||||
e = (struct AsanExtra *)(p + c - sizeof(*e));
|
||||
|
@ -1244,12 +1237,7 @@ void *__asan_calloc(size_t n, size_t m) {
|
|||
void *__asan_realloc(void *p, size_t n) {
|
||||
struct AsanTrace bt;
|
||||
if (p) {
|
||||
if (n) {
|
||||
return __asan_realloc_impl(p, n, __asan_realloc_grow);
|
||||
} else {
|
||||
__asan_free(p);
|
||||
return 0;
|
||||
}
|
||||
return __asan_realloc_impl(p, n, __asan_realloc_grow);
|
||||
} else {
|
||||
__asan_trace(&bt, RBP);
|
||||
return __asan_allocate_heap(16, n, &bt);
|
||||
|
|
|
@ -1,28 +1,29 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_INTRIN_ASANCODES_H_
|
||||
#define COSMOPOLITAN_LIBC_INTRIN_ASANCODES_H_
|
||||
|
||||
#define kAsanScale 3
|
||||
#define kAsanMagic 0x7fff8000
|
||||
#define kAsanNullPage -1 /* ∅ 0xff */
|
||||
#define kAsanProtected -2 /* P 0xfe */
|
||||
#define kAsanHeapFree -3 /* F 0xfd */
|
||||
#define kAsanHeapRelocated -4 /* R 0xfc */
|
||||
#define kAsanAllocaOverrun -5 /* 𝑂 0xfb */
|
||||
#define kAsanHeapUnderrun -6 /* U 0xfa */
|
||||
#define kAsanHeapOverrun -7 /* O 0xf9 */
|
||||
#define kAsanStackUnscoped -8 /* s 0xf8 */
|
||||
#define kAsanStackOverflow -9 /* ! 0xf7 */
|
||||
#define kAsanGlobalOrder -10 /* I 0xf6 */
|
||||
#define kAsanStackFree -11 /* r 0xf5 */
|
||||
#define kAsanStackPartial -12 /* p 0xf4 */
|
||||
#define kAsanStackOverrun -13 /* o 0xf3 */
|
||||
#define kAsanStackMiddle -14 /* m 0xf2 */
|
||||
#define kAsanStackUnderrun -15 /* u 0xf1 */
|
||||
#define kAsanAllocaUnderrun -16 /* 𝑈 0xf0 */
|
||||
#define kAsanUnmapped -17 /* M 0xef */
|
||||
#define kAsanGlobalRedzone -18 /* G 0xee */
|
||||
#define kAsanGlobalGone -19 /* 𝐺 0xed */
|
||||
#define kAsanGlobalUnderrun -20 /* μ 0xec */
|
||||
#define kAsanGlobalOverrun -21 /* Ω 0xeb */
|
||||
#define kAsanScale 3
|
||||
#define kAsanMagic 0x7fff8000
|
||||
#define kAsanNullPage -1 /* ∅ 0xff */
|
||||
#define kAsanProtected -2 /* P 0xfe */
|
||||
#define kAsanHeapFree -3 /* F 0xfd */
|
||||
#define kAsanHeapRelocated -4 /* R 0xfc */
|
||||
#define kAsanAllocaOverrun -5 /* 𝑂 0xfb */
|
||||
#define kAsanHeapUnderrun -6 /* U 0xfa */
|
||||
#define kAsanHeapOverrun -7 /* O 0xf9 */
|
||||
#define kAsanStackUnscoped -8 /* s 0xf8 */
|
||||
#define kAsanStackOverflow -9 /* ! 0xf7 */
|
||||
#define kAsanGlobalOrder -10 /* I 0xf6 */
|
||||
#define kAsanStackFree -11 /* r 0xf5 */
|
||||
#define kAsanStackPartial -12 /* p 0xf4 */
|
||||
#define kAsanStackOverrun -13 /* o 0xf3 */
|
||||
#define kAsanStackMiddle -14 /* m 0xf2 */
|
||||
#define kAsanStackUnderrun -15 /* u 0xf1 */
|
||||
#define kAsanAllocaUnderrun -16 /* 𝑈 0xf0 */
|
||||
#define kAsanUnmapped -17 /* M 0xef */
|
||||
#define kAsanGlobalRedzone -18 /* G 0xee */
|
||||
#define kAsanGlobalGone -19 /* 𝐺 0xed */
|
||||
#define kAsanGlobalUnderrun -20 /* μ 0xec */
|
||||
#define kAsanGlobalOverrun -21 /* Ω 0xeb */
|
||||
#define kAsanMmapSizeOverrun -22 /* Z 0xea */
|
||||
|
||||
#endif /* COSMOPOLITAN_LIBC_INTRIN_ASANCODES_H_ */
|
||||
|
|
|
@ -8,9 +8,6 @@ int _bitreverse8(int) pureconst;
|
|||
int _bitreverse16(int) pureconst;
|
||||
uint32_t _bitreverse32(uint32_t) pureconst;
|
||||
uint64_t _bitreverse64(uint64_t) pureconst;
|
||||
unsigned long _roundup2pow(unsigned long) pureconst;
|
||||
unsigned long _roundup2log(unsigned long) pureconst;
|
||||
unsigned long _rounddown2pow(unsigned long) pureconst;
|
||||
|
||||
#define READ16LE(P) \
|
||||
(__extension__({ \
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ Copyright 2023 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 │
|
||||
|
@ -16,29 +16,47 @@
|
|||
│ 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/iovec.h"
|
||||
#include "libc/calls/struct/iovec.internal.h"
|
||||
#include "libc/cosmo.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
#define INIT 0
|
||||
#define CALLING 1
|
||||
#define FINISHED 2
|
||||
|
||||
/**
|
||||
* Transfers memory to pipe.
|
||||
* Ensures initialization function is called exactly once.
|
||||
*
|
||||
* @param flags can have SPLICE_F_{MOVE,NONBLOCK,MORE,GIFT}
|
||||
* @return number of bytes actually transferred, or -1 w/ errno
|
||||
* This is the same as `pthread_once` except that it always uses a tiny
|
||||
* spinlock implementation and won't make any system calls. It's needed
|
||||
* since this function is an upstream dependency of both pthread_once()
|
||||
* and nsync_once(). Most code should favor calling those functions.
|
||||
*
|
||||
* @return 0 on success, or errno on error
|
||||
*/
|
||||
ssize_t vmsplice(int fd, const struct iovec *chunks, int64_t count,
|
||||
uint32_t flags) {
|
||||
int olderr;
|
||||
ssize_t wrote;
|
||||
olderr = errno;
|
||||
if ((wrote = sys_vmsplice(fd, chunks, count, flags)) == -1) {
|
||||
errno = olderr;
|
||||
if (count) {
|
||||
wrote = write(fd, chunks[0].iov_base, chunks[0].iov_len);
|
||||
} else {
|
||||
wrote = write(fd, NULL, 0);
|
||||
}
|
||||
errno_t cosmo_once(_Atomic(uint32_t) *once, void init(void)) {
|
||||
uint32_t old;
|
||||
switch ((old = atomic_load_explicit(once, memory_order_relaxed))) {
|
||||
case INIT:
|
||||
if (atomic_compare_exchange_strong_explicit(once, &old, CALLING,
|
||||
memory_order_acquire,
|
||||
memory_order_relaxed)) {
|
||||
init();
|
||||
atomic_store_explicit(once, FINISHED, memory_order_release);
|
||||
return 0;
|
||||
}
|
||||
// fallthrough
|
||||
case CALLING:
|
||||
for (;;) {
|
||||
if (atomic_load_explicit(once, memory_order_acquire) != CALLING) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
case FINISHED:
|
||||
return 0;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
return wrote;
|
||||
}
|
|
@ -37,8 +37,6 @@ static const char *GetFrameName(int x) {
|
|||
return "automap";
|
||||
} else if (IsFixedFrame(x)) {
|
||||
return "fixed";
|
||||
} else if (IsArenaFrame(x)) {
|
||||
return "arena";
|
||||
} else if (IsStaticStackFrame(x)) {
|
||||
return "stack";
|
||||
} else if (IsGfdsFrame(x)) {
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/sol.h"
|
||||
|
||||
#define N (PAGESIZE / 2 / sizeof(struct DescribeFlags))
|
||||
#define N (4096 / 2 / sizeof(struct DescribeFlags))
|
||||
|
||||
/**
|
||||
* Describes clock_gettime() clock argument.
|
||||
|
|
|
@ -46,6 +46,7 @@ static const char *DescribeSigFlags(char buf[64], int x) {
|
|||
{SA_RESETHAND, "RESETHAND"}, //
|
||||
{SA_NOMASK, "NOMASK"}, //
|
||||
{SA_ONESHOT, "ONESHOT"}, //
|
||||
{0x04000000, "RESTORER"}, //
|
||||
};
|
||||
return DescribeFlags(buf, 64, kSigFlags, ARRAYLEN(kSigFlags), "SA_", x);
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ const char *(DescribeSocketProtocol)(char buf[12], int family) {
|
|||
if (family == IPPROTO_UDP) return "IPPROTO_UDP";
|
||||
if (family == IPPROTO_RAW) return "IPPROTO_RAW";
|
||||
if (family == IPPROTO_IPV6) return "IPPROTO_IPv6";
|
||||
if (family == IPPROTO_ICMPV6) return "IPPROTO_ICMPV6";
|
||||
FormatInt32(buf, family);
|
||||
return buf;
|
||||
}
|
||||
|
|
|
@ -24,10 +24,14 @@
|
|||
* Describes setsockopt() level arguments.
|
||||
*/
|
||||
const char *(DescribeSockLevel)(char buf[12], int x) {
|
||||
if (x == SOL_SOCKET) return "SOL_SOCKET";
|
||||
if (x == SOL_IP) return "SOL_IP";
|
||||
if (x == SOL_ICMP) return "SOL_ICMP";
|
||||
if (x == SOL_TCP) return "SOL_TCP";
|
||||
if (x == SOL_UDP) return "SOL_UDP";
|
||||
if (x == SOL_SOCKET) return "SOL_SOCKET";
|
||||
if (x == SOL_IPV6) return "SOL_IPV6";
|
||||
if (x == SOL_ICMPV6) return "SOL_ICMPV6";
|
||||
if (x == SOL_RAW) return "SOL_RAW";
|
||||
FormatInt32(buf, x);
|
||||
return buf;
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ const char *(DescribeStat)(char buf[N], int rc, const struct stat *st) {
|
|||
append(", .st_%s=%'lu", "rdev", st->st_rdev);
|
||||
}
|
||||
|
||||
if (st->st_blksize != PAGESIZE) {
|
||||
if (st->st_blksize != 4096) {
|
||||
append(", .st_%s=%'lu", "blksize", st->st_blksize);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
* @param delta is added to enabled state
|
||||
* @return enabled state before `delta` was applied
|
||||
*/
|
||||
int ftrace_enabled(int delta) {
|
||||
dontinstrument int ftrace_enabled(int delta) {
|
||||
int res;
|
||||
struct CosmoTib *tib;
|
||||
if (__tls_enabled) {
|
||||
|
|
|
@ -18,13 +18,17 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/intrin/_getenv.internal.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/extend.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/pushpop.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
@ -37,16 +41,26 @@ __static_yoink("_init_g_fds");
|
|||
struct Fds g_fds;
|
||||
static struct Fd g_fds_static[OPEN_MAX];
|
||||
|
||||
static textwindows dontinline void SetupWinStd(struct Fds *fds, int i, int x) {
|
||||
static int Atoi(const char *str) {
|
||||
int i;
|
||||
for (i = 0; '0' <= *str && *str <= '9'; ++str) {
|
||||
i *= 10;
|
||||
i += *str - '0';
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static textwindows dontinline void SetupWinStd(struct Fds *fds, int i, int x,
|
||||
int sockset) {
|
||||
int64_t h;
|
||||
h = GetStdHandle(x);
|
||||
if (!h || h == -1) return;
|
||||
fds->p[i].kind = pushpop(kFdFile);
|
||||
fds->p[i].kind = ((1 << i) & sockset) ? pushpop(kFdSocket) : pushpop(kFdFile);
|
||||
fds->p[i].handle = h;
|
||||
atomic_store_explicit(&fds->f, i + 1, memory_order_relaxed);
|
||||
}
|
||||
|
||||
textstartup void __init_fds(void) {
|
||||
textstartup void __init_fds(int argc, char **argv, char **envp) {
|
||||
struct Fds *fds;
|
||||
__fds_lock_obj._type = PTHREAD_MUTEX_RECURSIVE;
|
||||
fds = __veil("r", &g_fds);
|
||||
|
@ -77,9 +91,29 @@ textstartup void __init_fds(void) {
|
|||
fds->p[1].handle = __veil("r", 0x3F8ull);
|
||||
fds->p[2].handle = __veil("r", 0x3F8ull);
|
||||
} else if (IsWindows()) {
|
||||
SetupWinStd(fds, 0, kNtStdInputHandle);
|
||||
SetupWinStd(fds, 1, kNtStdOutputHandle);
|
||||
SetupWinStd(fds, 2, kNtStdErrorHandle);
|
||||
int sockset = 0;
|
||||
struct Env var;
|
||||
var = _getenv(envp, "__STDIO_SOCKETS");
|
||||
if (var.s) {
|
||||
int i = var.i + 1;
|
||||
do {
|
||||
envp[i - 1] = envp[i];
|
||||
} while (envp[i]);
|
||||
sockset = Atoi(var.s);
|
||||
}
|
||||
if (sockset && !_weaken(socket)) {
|
||||
#ifdef SYSDEBUG
|
||||
kprintf("%s: parent process passed sockets as stdio, but this program"
|
||||
" can't use them since it didn't link the socket() function\n",
|
||||
argv[0]);
|
||||
_Exit(1);
|
||||
#else
|
||||
sockset = 0; // let ReadFile() fail
|
||||
#endif
|
||||
}
|
||||
SetupWinStd(fds, 0, kNtStdInputHandle, sockset);
|
||||
SetupWinStd(fds, 1, kNtStdOutputHandle, sockset);
|
||||
SetupWinStd(fds, 2, kNtStdErrorHandle, sockset);
|
||||
}
|
||||
fds->p[1].flags = O_WRONLY | O_APPEND;
|
||||
fds->p[2].flags = O_WRONLY | O_APPEND;
|
||||
|
|
|
@ -21,6 +21,9 @@
|
|||
.init.start 305,_init_g_fds
|
||||
push %rdi
|
||||
push %rsi
|
||||
mov %r12d,%edi // argc
|
||||
mov %r13,%rsi // argv
|
||||
mov %r14,%rdx // environ
|
||||
call __init_fds
|
||||
pop %rsi
|
||||
pop %rdi
|
||||
|
|
|
@ -35,7 +35,11 @@ unsigned long getauxval(unsigned long key) {
|
|||
x = _getauxval(key);
|
||||
if (key == AT_PAGESZ) {
|
||||
if (!x.isfound) {
|
||||
#ifdef __aarch64__
|
||||
x.value = 16384;
|
||||
#else
|
||||
x.value = 4096;
|
||||
#endif
|
||||
}
|
||||
x.isfound = true;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
* Environment variables can store empty string on Unix but not Windows.
|
||||
*
|
||||
* @return pointer to value of `environ` entry, or null if not found
|
||||
* @threadunsafe
|
||||
*/
|
||||
char *getenv(const char *s) {
|
||||
char **p;
|
||||
|
|
|
@ -625,7 +625,7 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt,
|
|||
++p;
|
||||
}
|
||||
for (i = j = 0; !pdot || j < prec; ++j) {
|
||||
if (UNLIKELY(!((intptr_t)s & (PAGESIZE - 1)))) {
|
||||
if (UNLIKELY(!((intptr_t)s & 4095))) {
|
||||
if (!dang && kisdangerous(s)) break;
|
||||
}
|
||||
if (!type) {
|
||||
|
@ -687,7 +687,7 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt,
|
|||
s += sizeof(char16_t);
|
||||
if (IsHighSurrogate(t)) {
|
||||
if (!pdot || j + 1 < prec) {
|
||||
if (UNLIKELY(!((intptr_t)s & (PAGESIZE - 1)))) {
|
||||
if (UNLIKELY(!((intptr_t)s & 4095))) {
|
||||
if (!dang && kisdangerous(s)) break;
|
||||
}
|
||||
u = *(const char16_t *)s;
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
/*-*- 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 2020 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/morton.h"
|
||||
|
||||
/**
|
||||
* Interleaves bits.
|
||||
* @see https://en.wikipedia.org/wiki/Z-order_curve
|
||||
* @see unmorton()
|
||||
*/
|
||||
unsigned long morton(unsigned long y, unsigned long x) {
|
||||
x = (x | x << 020) & 0x0000FFFF0000FFFF;
|
||||
x = (x | x << 010) & 0x00FF00FF00FF00FF;
|
||||
x = (x | x << 004) & 0x0F0F0F0F0F0F0F0F;
|
||||
x = (x | x << 002) & 0x3333333333333333;
|
||||
x = (x | x << 001) & 0x5555555555555555;
|
||||
y = (y | y << 020) & 0x0000FFFF0000FFFF;
|
||||
y = (y | y << 010) & 0x00FF00FF00FF00FF;
|
||||
y = (y | y << 004) & 0x0F0F0F0F0F0F0F0F;
|
||||
y = (y | y << 002) & 0x3333333333333333;
|
||||
y = (y | y << 001) & 0x5555555555555555;
|
||||
return x | y << 1;
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_BITS_MORTON_H_
|
||||
#define COSMOPOLITAN_LIBC_BITS_MORTON_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
#ifdef COSMO
|
||||
|
||||
#define morton __morton
|
||||
#define unmorton __unmorton
|
||||
|
||||
unsigned long morton(unsigned long, unsigned long) libcesque;
|
||||
axdx_t unmorton(unsigned long) libcesque;
|
||||
|
||||
#endif /* COSMO */
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_BITS_MORTON_H_ */
|
|
@ -27,7 +27,6 @@ static bool IsNoteworthyHole(unsigned i, const struct MemoryIntervals *mm) {
|
|||
// gaps between shadow frames aren't interesting
|
||||
// the chasm from heap to stack ruins statistics
|
||||
return !(
|
||||
(IsArenaFrame(mm->p[i].y) && !IsArenaFrame(mm->p[i + 1].x)) ||
|
||||
(IsShadowFrame(mm->p[i].y) || IsShadowFrame(mm->p[i + 1].x)) ||
|
||||
(!IsStaticStackFrame(mm->p[i].y) && IsStaticStackFrame(mm->p[i + 1].x)));
|
||||
}
|
||||
|
|
|
@ -93,6 +93,7 @@ int PutEnvImpl(char *s, bool overwrite) {
|
|||
* @return 0 on success, or non-zero w/ errno on error
|
||||
* @raise ENOMEM if we require more vespene gas
|
||||
* @see setenv(), getenv()
|
||||
* @threadunsafe
|
||||
*/
|
||||
int putenv(char *s) {
|
||||
int rc;
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
/*-*- 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 2020 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/bits.h"
|
||||
#include "libc/intrin/bsr.h"
|
||||
|
||||
/**
|
||||
* Returns 𝑥 rounded down to previous two power.
|
||||
*
|
||||
* @define (𝑥>0→2^⌊log₂𝑥⌋, x=0→0, 𝑇→⊥)
|
||||
* @see _roundup2pow()
|
||||
*/
|
||||
unsigned long _rounddown2pow(unsigned long x) {
|
||||
return x ? 1ul << _bsrl(x) : 0;
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
/*-*- 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 2020 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/bits.h"
|
||||
#include "libc/intrin/bsr.h"
|
||||
|
||||
/**
|
||||
* Returns 𝑥 rounded up to next two power and log'd.
|
||||
* @see _roundup2pow()
|
||||
*/
|
||||
unsigned long _roundup2log(unsigned long x) {
|
||||
return x > 1 ? (_bsrl(x - 1) + 1) : x ? 1 : 0;
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
/*-*- 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 2020 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/bits.h"
|
||||
#include "libc/intrin/bsr.h"
|
||||
|
||||
/**
|
||||
* Returns 𝑥 rounded up to next two power.
|
||||
*
|
||||
* @define (𝑥>0→2^⌈log₂x⌉, x=0→0, 𝑇→⊥)
|
||||
* @see _rounddown2pow()
|
||||
*/
|
||||
unsigned long _roundup2pow(unsigned long x) {
|
||||
return x > 1 ? 2ul << _bsrl(x - 1) : x ? 1 : 0;
|
||||
}
|
|
@ -30,6 +30,7 @@
|
|||
* @raise EINVAL if `name` is empty or contains `'='`
|
||||
* @raise ENOMEM if we require more vespene gas
|
||||
* @see putenv(), getenv()
|
||||
* @threadunsafe
|
||||
*/
|
||||
int setenv(const char *name, const char *value, int overwrite) {
|
||||
int rc;
|
||||
|
|
|
@ -19,7 +19,9 @@ COSMOPOLITAN_C_START_
|
|||
#define STRACE(FMT, ...) \
|
||||
do { \
|
||||
if (UNLIKELY(__strace > 0) && strace_enabled(0) > 0) { \
|
||||
ftrace_enabled(-1); \
|
||||
__stracef(STRACE_PROLOGUE FMT "\n", ##__VA_ARGS__); \
|
||||
ftrace_enabled(+1); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
* @param delta is added to enabled state
|
||||
* @return enabled state before `delta` was applied
|
||||
*/
|
||||
int strace_enabled(int delta) {
|
||||
dontinstrument int strace_enabled(int delta) {
|
||||
int res;
|
||||
struct CosmoTib *tib;
|
||||
if (__tls_enabled) {
|
||||
|
|
|
@ -85,7 +85,7 @@ forceinline du_int udiv128by64to64(du_int u1, du_int u0, du_int v, du_int *r) {
|
|||
* @param b is divisor
|
||||
* @param rem receives remainder if not NULL
|
||||
*/
|
||||
COMPILER_RT_ABI tu_int __udivmodti4(tu_int a, tu_int b, tu_int *rem) {
|
||||
tu_int __udivmodti4(tu_int a, tu_int b, tu_int *rem) {
|
||||
const unsigned n_utword_bits = sizeof(tu_int) * CHAR_BIT;
|
||||
utwords dividend, divisor, quotient, remainder;
|
||||
si_int shift;
|
||||
|
@ -135,3 +135,7 @@ COMPILER_RT_ABI tu_int __udivmodti4(tu_int a, tu_int b, tu_int *rem) {
|
|||
if (rem) *rem = dividend.all;
|
||||
return quotient.all;
|
||||
}
|
||||
|
||||
tu_int __udivti3(tu_int a, tu_int b) {
|
||||
return __udivmodti4(a, b, NULL);
|
||||
}
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to division, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "third_party/compiler_rt/int_lib.h"
|
||||
|
||||
COMPILER_RT_ABI tu_int __udivti3(tu_int a, tu_int b) {
|
||||
return __udivmodti4(a, b, NULL);
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
/*-*- 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 2020 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/morton.h"
|
||||
|
||||
static unsigned long GetOddBits(unsigned long x) {
|
||||
x = (x | x >> 000) & 0x5555555555555555;
|
||||
x = (x | x >> 001) & 0x3333333333333333;
|
||||
x = (x | x >> 002) & 0x0F0F0F0F0F0F0F0F;
|
||||
x = (x | x >> 004) & 0x00FF00FF00FF00FF;
|
||||
x = (x | x >> 010) & 0x0000FFFF0000FFFF;
|
||||
x = (x | x >> 020) & 0x00000000FFFFFFFF;
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deinterleaves bits.
|
||||
*
|
||||
* @param 𝑖 is interleaved index
|
||||
* @return deinterleaved coordinate {ax := 𝑦, dx := 𝑥}
|
||||
* @see en.wikipedia.org/wiki/Z-order_curve
|
||||
* @see morton()
|
||||
*/
|
||||
axdx_t unmorton(unsigned long i) {
|
||||
return (axdx_t){GetOddBits(i >> 1), GetOddBits(i)};
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
/*-*- 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 2020 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/nexgen32e/x86info.h"
|
||||
#include "tool/decode/lib/x86idnames.h"
|
||||
|
||||
const struct IdName kX86GradeNames[] = {
|
||||
{X86_GRADE_UNKNOWN, "Unknown"}, //
|
||||
{X86_GRADE_APPLIANCE, "Appliance"}, //
|
||||
{X86_GRADE_MOBILE, "Mobile"}, //
|
||||
{X86_GRADE_TABLET, "Tablet"}, //
|
||||
{X86_GRADE_DESKTOP, "Desktop"}, //
|
||||
{X86_GRADE_CLIENT, "Client"}, //
|
||||
{X86_GRADE_DENSITY, "Density"}, //
|
||||
{X86_GRADE_SERVER, "Server"}, //
|
||||
{X86_GRADE_SCIENCE, "Science"}, //
|
||||
{0}, //
|
||||
};
|
|
@ -19,6 +19,19 @@
|
|||
#include "libc/nexgen32e/x86info.h"
|
||||
#include "tool/decode/lib/x86idnames.h"
|
||||
|
||||
const struct IdName kX86GradeNames[] = {
|
||||
{X86_GRADE_UNKNOWN, "Unknown"}, //
|
||||
{X86_GRADE_APPLIANCE, "Appliance"}, //
|
||||
{X86_GRADE_MOBILE, "Mobile"}, //
|
||||
{X86_GRADE_TABLET, "Tablet"}, //
|
||||
{X86_GRADE_DESKTOP, "Desktop"}, //
|
||||
{X86_GRADE_CLIENT, "Client"}, //
|
||||
{X86_GRADE_DENSITY, "Density"}, //
|
||||
{X86_GRADE_SERVER, "Server"}, //
|
||||
{X86_GRADE_SCIENCE, "Science"}, //
|
||||
{0}, //
|
||||
};
|
||||
|
||||
const struct IdName kX86MarchNames[] = {
|
||||
{X86_MARCH_UNKNOWN, "Unknown"}, //
|
||||
{X86_MARCH_CORE2, "Core 2"}, //
|
|
@ -29,6 +29,7 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/cosmo.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/elf/elf.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
|
|
356
libc/mem/arena.c
356
libc/mem/arena.c
|
@ -1,356 +0,0 @@
|
|||
/*-*- 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/mem/arena.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/bsf.h"
|
||||
#include "libc/intrin/bsr.h"
|
||||
#include "libc/intrin/likely.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/hook.internal.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdckdint.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
#define BASE 0x50040000
|
||||
#define SIZE 0x2ff80000
|
||||
#define P(i) ((void *)(intptr_t)(i))
|
||||
#define EXCHANGE(HOOK, SLOT) \
|
||||
__arena_hook((intptr_t *)_weaken(HOOK), (intptr_t *)(&(SLOT)))
|
||||
|
||||
static struct Arena {
|
||||
bool once;
|
||||
size_t size;
|
||||
size_t depth;
|
||||
size_t offset[16];
|
||||
void (*free)(void *);
|
||||
void *(*malloc)(size_t);
|
||||
void *(*calloc)(size_t, size_t);
|
||||
void *(*memalign)(size_t, size_t);
|
||||
void *(*realloc)(void *, size_t);
|
||||
void *(*realloc_in_place)(void *, size_t);
|
||||
size_t (*malloc_usable_size)(const void *);
|
||||
size_t (*bulk_free)(void *[], size_t);
|
||||
int (*malloc_trim)(size_t);
|
||||
} __arena;
|
||||
|
||||
static wontreturn void __arena_die(void) {
|
||||
if (_weaken(__die)) _weaken(__die)();
|
||||
_exit(83);
|
||||
}
|
||||
|
||||
forceinline void __arena_check(void) {
|
||||
unassert(__arena.depth);
|
||||
}
|
||||
|
||||
forceinline void __arena_check_pointer(void *p) {
|
||||
unassert(BASE + __arena.offset[__arena.depth - 1] <= (uintptr_t)p &&
|
||||
(uintptr_t)p < BASE + __arena.offset[__arena.depth]);
|
||||
}
|
||||
|
||||
forceinline bool __arena_is_arena_pointer(void *p) {
|
||||
return BASE <= (uintptr_t)p && (uintptr_t)p < BASE + SIZE;
|
||||
}
|
||||
|
||||
forceinline size_t __arena_get_size(void *p) {
|
||||
return *(const size_t *)((const char *)p - sizeof(size_t));
|
||||
}
|
||||
|
||||
static void __arena_free(void *p) {
|
||||
__arena_check();
|
||||
if (p) {
|
||||
__arena_check_pointer(p);
|
||||
if (!(BASE <= (uintptr_t)p && (uintptr_t)p < BASE + SIZE)) {
|
||||
__arena.free(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static size_t __arena_bulk_free(void *p[], size_t n) {
|
||||
size_t i;
|
||||
for (i = 0; i < n; ++i) {
|
||||
__arena_free(p[i]);
|
||||
p[i] = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static dontinline bool __arena_grow(size_t offset, size_t request) {
|
||||
size_t greed;
|
||||
greed = __arena.size + 1;
|
||||
do {
|
||||
greed += greed >> 1;
|
||||
greed = ROUNDUP(greed, FRAMESIZE);
|
||||
} while (greed < offset + request);
|
||||
if (greed <= SIZE) {
|
||||
if (mmap(P(BASE + __arena.size), greed - __arena.size,
|
||||
PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED,
|
||||
-1, 0) != MAP_FAILED) {
|
||||
__arena.size = greed;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
enomem();
|
||||
}
|
||||
if (_weaken(__oom_hook)) {
|
||||
_weaken(__oom_hook)(request);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void *__arena_alloc(size_t a, size_t n) {
|
||||
size_t o;
|
||||
if (!n) n = 1;
|
||||
o = ROUNDUP(__arena.offset[__arena.depth] + sizeof(size_t), a);
|
||||
if (o + n >= n) {
|
||||
if (n <= sizeof(size_t)) {
|
||||
n = sizeof(size_t);
|
||||
} else {
|
||||
n = ROUNDUP(n, sizeof(size_t));
|
||||
}
|
||||
if (o + n <= SIZE) {
|
||||
if (UNLIKELY(o + n > __arena.size)) {
|
||||
if (!__arena_grow(o, n)) return 0;
|
||||
}
|
||||
__arena.offset[__arena.depth] = o + n;
|
||||
*(size_t *)(BASE + o - sizeof(size_t)) = n;
|
||||
return (void *)(BASE + o);
|
||||
}
|
||||
}
|
||||
enomem();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *__arena_malloc(size_t n) {
|
||||
__arena_check();
|
||||
return __arena_alloc(16, n);
|
||||
}
|
||||
|
||||
static void *__arena_calloc(size_t n, size_t z) {
|
||||
__arena_check();
|
||||
if (ckd_mul(&n, n, z)) n = -1;
|
||||
return __arena_alloc(16, n);
|
||||
}
|
||||
|
||||
static void *__arena_memalign(size_t a, size_t n) {
|
||||
__arena_check();
|
||||
if (a <= sizeof(size_t)) {
|
||||
return __arena_alloc(8, n);
|
||||
} else {
|
||||
return __arena_alloc(2ul << _bsrl(a - 1), n);
|
||||
}
|
||||
}
|
||||
|
||||
static size_t __arena_malloc_usable_size(const void *p) {
|
||||
__arena_check();
|
||||
__arena_check_pointer(p);
|
||||
if (__arena_is_arena_pointer(p)) {
|
||||
return __arena_get_size(p);
|
||||
} else {
|
||||
return __arena.malloc_usable_size(p);
|
||||
}
|
||||
}
|
||||
|
||||
static void *__arena_realloc(void *p, size_t n) {
|
||||
char *q;
|
||||
size_t m, o, z;
|
||||
__arena_check();
|
||||
if (p) {
|
||||
__arena_check_pointer(p);
|
||||
if (__arena_is_arena_pointer(p)) {
|
||||
if (n) {
|
||||
if ((m = __arena_get_size(p)) >= n) {
|
||||
return p;
|
||||
} else if (n <= SIZE) {
|
||||
z = 2ul << _bsrl(n - 1);
|
||||
if (__arena.offset[__arena.depth] - m == (o = (intptr_t)p - BASE)) {
|
||||
if (UNLIKELY(o + z > __arena.size)) {
|
||||
if (o + z <= SIZE) {
|
||||
if (!__arena_grow(o, z)) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
enomem();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
__arena.offset[__arena.depth] = o + z;
|
||||
*(size_t *)((char *)p - sizeof(size_t)) = z;
|
||||
return p;
|
||||
} else if ((q = __arena_alloc(1ul << _bsfl((intptr_t)p), z))) {
|
||||
memmove(q, p, m);
|
||||
return q;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
enomem();
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
return __arena.realloc(p, n);
|
||||
}
|
||||
} else {
|
||||
if (n <= 16) {
|
||||
n = 16;
|
||||
} else {
|
||||
n = 2ul << _bsrl(n - 1);
|
||||
}
|
||||
return __arena_alloc(16, n);
|
||||
}
|
||||
}
|
||||
|
||||
static void *__arena_realloc_in_place(void *p, size_t n) {
|
||||
char *q;
|
||||
size_t m, z;
|
||||
__arena_check();
|
||||
if (p) {
|
||||
__arena_check_pointer(p);
|
||||
if (__arena_is_arena_pointer(p)) {
|
||||
if (n) {
|
||||
if ((m = __arena_get_size(p)) >= n) {
|
||||
return p;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
return __arena.realloc_in_place(p, n);
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int __arena_malloc_trim(size_t n) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __arena_hook(intptr_t *h, intptr_t *f) {
|
||||
intptr_t t;
|
||||
if (h) {
|
||||
t = *h;
|
||||
*h = *f;
|
||||
*f = t;
|
||||
}
|
||||
}
|
||||
|
||||
static void __arena_install(void) {
|
||||
EXCHANGE(hook_free, __arena.free);
|
||||
EXCHANGE(hook_malloc, __arena.malloc);
|
||||
EXCHANGE(hook_calloc, __arena.calloc);
|
||||
EXCHANGE(hook_realloc, __arena.realloc);
|
||||
EXCHANGE(hook_memalign, __arena.memalign);
|
||||
EXCHANGE(hook_bulk_free, __arena.bulk_free);
|
||||
EXCHANGE(hook_malloc_trim, __arena.malloc_trim);
|
||||
EXCHANGE(hook_realloc_in_place, __arena.realloc_in_place);
|
||||
EXCHANGE(hook_malloc_usable_size, __arena.malloc_usable_size);
|
||||
}
|
||||
|
||||
static void __arena_destroy(void) {
|
||||
if (__arena.depth) __arena_install();
|
||||
if (__arena.size) munmap(P(BASE), __arena.size);
|
||||
bzero(&__arena, sizeof(__arena));
|
||||
}
|
||||
|
||||
static void __arena_init(void) {
|
||||
__arena.free = __arena_free;
|
||||
__arena.malloc = __arena_malloc;
|
||||
__arena.calloc = __arena_calloc;
|
||||
__arena.realloc = __arena_realloc;
|
||||
__arena.memalign = __arena_memalign;
|
||||
__arena.bulk_free = __arena_bulk_free;
|
||||
__arena.malloc_trim = __arena_malloc_trim;
|
||||
__arena.realloc_in_place = __arena_realloc_in_place;
|
||||
__arena.malloc_usable_size = __arena_malloc_usable_size;
|
||||
atexit(__arena_destroy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes memory arena.
|
||||
*
|
||||
* This allocator gives a ~3x performance boost over dlmalloc, mostly
|
||||
* because it isn't thread safe and it doesn't do defragmentation.
|
||||
*
|
||||
* Calling this function will push a new arena. It may be called
|
||||
* multiple times from the main thread recursively. The first time it's
|
||||
* called, it hooks all the regular memory allocation functions. Any
|
||||
* allocations that were made previously outside the arena, will be
|
||||
* passed on to the previous hooks. Then, the basic idea, is rather than
|
||||
* bothering with free() you can just call __arena_pop() to bulk free.
|
||||
*
|
||||
* Arena allocations also have a slight size advantage, since 32-bit
|
||||
* pointers are always used. The maximum amount of arena memory is
|
||||
* 805,175,296 bytes.
|
||||
*
|
||||
* @see __arena_pop()
|
||||
*/
|
||||
void __arena_push(void) {
|
||||
if (UNLIKELY(!__arena.once)) {
|
||||
__arena_init();
|
||||
__arena.once = true;
|
||||
}
|
||||
if (!__arena.depth) {
|
||||
__arena_install();
|
||||
} else {
|
||||
unassert(__arena.depth < ARRAYLEN(__arena.offset) - 1);
|
||||
}
|
||||
__arena.offset[__arena.depth + 1] = __arena.offset[__arena.depth];
|
||||
++__arena.depth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pops memory arena.
|
||||
*
|
||||
* This pops the most recently created arena, freeing all the memory
|
||||
* that was allocated between the push and pop arena calls. If this is
|
||||
* the last arena on the stack, then the old malloc hooks are restored.
|
||||
*
|
||||
* @see __arena_push()
|
||||
*/
|
||||
void __arena_pop(void) {
|
||||
size_t a, b, greed;
|
||||
__arena_check();
|
||||
if (!--__arena.depth) __arena_install();
|
||||
a = __arena.offset[__arena.depth];
|
||||
b = __arena.offset[__arena.depth + 1];
|
||||
greed = a;
|
||||
greed += FRAMESIZE;
|
||||
greed <<= 1;
|
||||
if (__arena.size > greed) {
|
||||
munmap(P(BASE + greed), __arena.size - greed);
|
||||
__arena.size = greed;
|
||||
b = MIN(b, greed);
|
||||
a = MIN(b, a);
|
||||
}
|
||||
bzero(P(BASE + a), b - a);
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_MEM_ARENA_H_
|
||||
#define COSMOPOLITAN_LIBC_MEM_ARENA_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
void __arena_push(void);
|
||||
void __arena_pop(void);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_MEM_ARENA_H_ */
|
|
@ -27,9 +27,7 @@ void (*hook_free)(void *) = dlfree;
|
|||
*
|
||||
* Releases the chunk of memory pointed to by p, that had been
|
||||
* previously allocated using malloc or a related routine such as
|
||||
* realloc. It has no effect if p is null. If p was not malloced or
|
||||
* already freed, free(p) will by default cause the current program to
|
||||
* abort.
|
||||
* realloc. It has no effect if p is null.
|
||||
*
|
||||
* @param p is allocation address, which may be NULL
|
||||
* @see dlfree()
|
||||
|
|
|
@ -30,11 +30,14 @@ void *(*hook_malloc)(size_t) = dlmalloc;
|
|||
* on ANSI C systems.
|
||||
*
|
||||
* If n is zero, malloc returns a minimum-sized chunk. (The minimum size
|
||||
* is 32 bytes on 64bit systems.) Note that size_t is an unsigned type,
|
||||
* so calls with arguments that would be negative if signed are
|
||||
* interpreted as requests for huge amounts of space, which will often
|
||||
* fail. The maximum supported value of n differs across systems, but is
|
||||
* in all cases less than the maximum representable value of a size_t.
|
||||
* is 32 bytes on 64bit systems.) It should be assumed that zero bytes
|
||||
* are possible access, since that'll be enforced by `MODE=asan`.
|
||||
*
|
||||
* Note that size_t is an unsigned type, so calls with arguments that
|
||||
* would be negative if signed are interpreted as requests for huge
|
||||
* amounts of space, which will often fail. The maximum supported value
|
||||
* of n differs across systems, but is in all cases less than the
|
||||
* maximum representable value of a size_t.
|
||||
*
|
||||
* @param rdi is number of bytes needed, coerced to 1+
|
||||
* @return new memory, or NULL w/ errno
|
||||
|
|
|
@ -16,8 +16,9 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/stdckdint.h"
|
||||
|
||||
/**
|
||||
* Allocates granular aligned memory of granular size, i.e.
|
||||
|
@ -31,5 +32,9 @@
|
|||
* @threadsafe
|
||||
*/
|
||||
void *pvalloc(size_t n) {
|
||||
return memalign(FRAMESIZE, ROUNDUP(n, FRAMESIZE));
|
||||
if (ckd_add(&n, n, FRAMESIZE - 1)) {
|
||||
errno = ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
return memalign(FRAMESIZE, n & -FRAMESIZE);
|
||||
}
|
||||
|
|
|
@ -29,8 +29,12 @@ void *(*hook_realloc)(void *, size_t) = dlrealloc;
|
|||
* does chunk p up to the minimum of (n, p's size) bytes, or null if no
|
||||
* space is available.
|
||||
*
|
||||
* If p is NULL, realloc is equivalent to malloc.
|
||||
* If p is not NULL and n is 0, realloc is equivalent to free.
|
||||
* If p is NULL, then realloc() is equivalent to malloc().
|
||||
*
|
||||
* If p is not NULL and n is 0, then realloc() shrinks the allocation to
|
||||
* zero bytes. The allocation isn't freed and still continues to be a
|
||||
* uniquely allocated piece of memory. However it should be assumed that
|
||||
* zero bytes can be accessed, since that's enforced by `MODE=asan`.
|
||||
*
|
||||
* The returned pointer may or may not be the same as p. The algorithm
|
||||
* prefers extending p in most cases when possible, otherwise it employs
|
||||
|
@ -54,8 +58,6 @@ void *(*hook_realloc)(void *, size_t) = dlrealloc;
|
|||
* @param p is address of current allocation or NULL
|
||||
* @param n is number of bytes needed
|
||||
* @return rax is result, or NULL w/ errno w/o free(p)
|
||||
* @note realloc(p=0, n=0) → malloc(32)
|
||||
* @note realloc(p≠0, n=0) → free(p)
|
||||
* @see dlrealloc()
|
||||
* @threadsafe
|
||||
*/
|
||||
|
|
|
@ -32,7 +32,7 @@ char *strndup(const char *s, size_t n) {
|
|||
char *s2;
|
||||
size_t len = strnlen(s, n);
|
||||
if ((s2 = malloc(len + 1))) {
|
||||
memcpy(s2, s, len);
|
||||
if (len) memcpy(s2, s, len);
|
||||
s2[len] = '\0';
|
||||
return s2;
|
||||
}
|
||||
|
|
|
@ -85,6 +85,11 @@ bool32 TransactNamedPipe(int64_t hNamedPipe, void *lpInBuffer,
|
|||
uint32_t nOutBufferSize, uint32_t *lpBytesRead,
|
||||
struct NtOverlapped *lpOverlapped);
|
||||
|
||||
bool32 GetNamedPipeInfo(int64_t hNamedPipe, uint32_t *opt_out_lpFlags,
|
||||
uint32_t *opt_out_lpOutBufferSize,
|
||||
uint32_t *opt_out_lpInBufferSize,
|
||||
uint32_t *opt_out_lpMaxInstances);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_NT_IPC_H_ */
|
||||
|
|
18
libc/nt/kernel32/GetNamedPipeInfo.S
Normal file
18
libc/nt/kernel32/GetNamedPipeInfo.S
Normal file
|
@ -0,0 +1,18 @@
|
|||
#include "libc/nt/codegen.h"
|
||||
.imp kernel32,__imp_GetNamedPipeInfo,GetNamedPipeInfo
|
||||
|
||||
.text.windows
|
||||
.ftrace1
|
||||
GetNamedPipeInfo:
|
||||
.ftrace2
|
||||
#ifdef __x86_64__
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
mov __imp_GetNamedPipeInfo(%rip),%rax
|
||||
jmp __sysv2nt6
|
||||
#elif defined(__aarch64__)
|
||||
mov x0,#0
|
||||
ret
|
||||
#endif
|
||||
.endfn GetNamedPipeInfo,globl
|
||||
.previous
|
|
@ -93,6 +93,7 @@ imp 'GetModuleFileName' GetModuleFileNameW kernel32 3
|
|||
imp 'GetModuleHandle' GetModuleHandleA kernel32 1
|
||||
imp 'GetModuleHandleEx' GetModuleHandleExW kernel32 3
|
||||
imp 'GetModuleHandleW' GetModuleHandleW kernel32 1
|
||||
imp 'GetNamedPipeInfo' GetNamedPipeInfo kernel32 5
|
||||
imp 'GetNumberOfConsoleInputEvents' GetNumberOfConsoleInputEvents kernel32 2
|
||||
imp 'GetNumberOfConsoleMouseButtons' GetNumberOfConsoleMouseButtons kernel32 1
|
||||
imp 'GetOverlappedResult' GetOverlappedResult kernel32 4
|
||||
|
@ -246,8 +247,8 @@ imp 'VirtualAlloc' VirtualAlloc kernel32 4
|
|||
imp 'VirtualAllocEx' VirtualAllocEx kernel32 5
|
||||
imp 'VirtualFree' VirtualFree kernel32 3
|
||||
imp 'VirtualLock' VirtualLock kernel32 2
|
||||
imp 'VirtualUnlock' VirtualUnlock kernel32 2
|
||||
imp 'VirtualQuery' VirtualQuery kernel32 3
|
||||
imp 'VirtualUnlock' VirtualUnlock kernel32 2
|
||||
imp 'WaitForMultipleObjectsEx' WaitForMultipleObjectsEx kernel32 5
|
||||
imp 'WaitForSingleObjectEx' WaitForSingleObjectEx kernel32 3
|
||||
imp 'WideCharToMultiByte' WideCharToMultiByte kernel32 8
|
||||
|
|
|
@ -644,7 +644,7 @@ errno_t clone(void *func, void *stk, size_t stksz, int flags, void *arg,
|
|||
if (!func) {
|
||||
rc = EINVAL;
|
||||
} else if (!IsTiny() &&
|
||||
((flags & CLONE_VM) && (stksz < PAGESIZE || (stksz & 15)))) {
|
||||
((flags & CLONE_VM) && (stksz < 4096 || (stksz & 15)))) {
|
||||
rc = EINVAL;
|
||||
} else if (IsAsan() &&
|
||||
(((flags & CLONE_SETTLS) && !__asan_is_valid(tls, 64)) ||
|
||||
|
|
|
@ -148,7 +148,7 @@ textstartup void cosmo(long *sp, struct Syslib *m1) {
|
|||
#endif
|
||||
|
||||
// initialize file system
|
||||
__init_fds();
|
||||
__init_fds(argc, argv, envp);
|
||||
|
||||
// set helpful globals
|
||||
__argc = argc;
|
||||
|
|
|
@ -102,11 +102,11 @@ textstartup void __enable_tls(void) {
|
|||
|
||||
// Here's the layout we're currently using:
|
||||
//
|
||||
// .balign PAGESIZE
|
||||
// .balign 4096
|
||||
// _tdata_start:
|
||||
// .tdata
|
||||
// _tdata_size = . - _tdata_start
|
||||
// .balign PAGESIZE
|
||||
// .balign 4096
|
||||
// _tbss_start:
|
||||
// _tdata_start + _tbss_offset:
|
||||
// .tbss
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/symbols.internal.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
@ -68,7 +69,9 @@ bool32 __onntconsoleevent_nt(uint32_t);
|
|||
void kmalloc_unlock(void);
|
||||
|
||||
static textwindows wontreturn void AbortFork(const char *func) {
|
||||
STRACE("fork() %s() failed %d", func, GetLastError());
|
||||
#ifdef SYSDEBUG
|
||||
kprintf("fork() %s() failed with win32 error %d\n", func, GetLastError());
|
||||
#endif
|
||||
ExitProcess(177);
|
||||
}
|
||||
|
||||
|
@ -104,7 +107,15 @@ static dontinline textwindows bool ForkIo2(int64_t h, void *buf, size_t n,
|
|||
}
|
||||
|
||||
static dontinline textwindows bool WriteAll(int64_t h, void *buf, size_t n) {
|
||||
return ForkIo2(h, buf, n, WriteFile, "WriteFile", false);
|
||||
bool ok;
|
||||
ok = ForkIo2(h, buf, n, WriteFile, "WriteFile", false);
|
||||
#ifdef SYSDEBUG
|
||||
if (!ok) {
|
||||
kprintf("failed to write %zu bytes to forked child: %d\n", n,
|
||||
GetLastError());
|
||||
}
|
||||
#endif
|
||||
return ok;
|
||||
}
|
||||
|
||||
static textwindows dontinline void ReadOrDie(int64_t h, void *buf, size_t n) {
|
||||
|
@ -320,8 +331,13 @@ textwindows int sys_fork_nt(uint32_t dwCreationFlags) {
|
|||
}
|
||||
for (i = 0; i < _mmi.i && ok; ++i) {
|
||||
if ((_mmi.p[i].flags & MAP_TYPE) != MAP_SHARED) {
|
||||
ok = WriteAll(writer, (void *)((uint64_t)_mmi.p[i].x << 16),
|
||||
_mmi.p[i].size);
|
||||
uint32_t op;
|
||||
char *p = (char *)((uint64_t)_mmi.p[i].x << 16);
|
||||
// XXX: forking destroys thread guard pages currently
|
||||
VirtualProtect(
|
||||
p, _mmi.p[i].size,
|
||||
__prot2nt(_mmi.p[i].prot | PROT_READ, _mmi.p[i].iscow), &op);
|
||||
ok = WriteAll(writer, p, _mmi.p[i].size);
|
||||
}
|
||||
}
|
||||
if (ok) ok = WriteAll(writer, __data_start, __data_end - __data_start);
|
||||
|
|
|
@ -51,7 +51,7 @@ int __inflate(void *, size_t, const void *, size_t);
|
|||
void *_Mmap(void *, size_t, int, int, int, int64_t) dontasan;
|
||||
int _Munmap(char *, size_t) dontasan;
|
||||
void __on_arithmetic_overflow(void);
|
||||
void __init_fds(void);
|
||||
void __init_fds(int, char **, char **);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -141,10 +141,6 @@ forceinline pureconst bool IsShadowFrame(int x) {
|
|||
return 0x7fff <= x && x < 0x10008000;
|
||||
}
|
||||
|
||||
forceinline pureconst bool IsArenaFrame(int x) {
|
||||
return 0x5004 <= x && x <= 0x7ffb;
|
||||
}
|
||||
|
||||
forceinline pureconst bool IsStaticStackFrame(int x) {
|
||||
intptr_t stack = GetStaticStackAddr(0);
|
||||
return (int)(stack >> 16) <= x &&
|
||||
|
@ -192,19 +188,6 @@ forceinline pureconst bool OverlapsImageSpace(const void *p, size_t n) {
|
|||
}
|
||||
}
|
||||
|
||||
forceinline pureconst bool OverlapsArenaSpace(const void *p, size_t n) {
|
||||
intptr_t BegA, EndA, BegB, EndB;
|
||||
if (n) {
|
||||
BegA = (intptr_t)p;
|
||||
EndA = BegA + (n - 1);
|
||||
BegB = 0x50000000;
|
||||
EndB = 0x7ffdffff;
|
||||
return MAX(BegA, BegB) < MIN(EndA, EndB);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
forceinline pureconst bool OverlapsShadowSpace(const void *p, size_t n) {
|
||||
intptr_t BegA, EndA, BegB, EndB;
|
||||
if (n) {
|
||||
|
|
|
@ -245,9 +245,10 @@ dontasan inline void *_Mmap(void *addr, size_t size, int prot, int flags,
|
|||
int fd, int64_t off) {
|
||||
char *p = addr;
|
||||
struct DirectMap dm;
|
||||
size_t requested_size;
|
||||
int a, b, i, f, m, n, x;
|
||||
bool needguard, clashes;
|
||||
unsigned long guardsize;
|
||||
unsigned long page_size;
|
||||
size_t virtualused, virtualneed;
|
||||
|
||||
if (VERY_UNLIKELY(!size)) {
|
||||
|
@ -274,11 +275,12 @@ dontasan inline void *_Mmap(void *addr, size_t size, int prot, int flags,
|
|||
flags = MAP_SHARED; // cf. MAP_SHARED_VALIDATE
|
||||
}
|
||||
|
||||
requested_size = size;
|
||||
page_size = getauxval(AT_PAGESZ);
|
||||
if (flags & MAP_ANONYMOUS) {
|
||||
fd = -1;
|
||||
off = 0;
|
||||
size = ROUNDUP(size, FRAMESIZE);
|
||||
if (IsWindows()) prot |= PROT_WRITE; // kludge
|
||||
if ((flags & MAP_TYPE) == MAP_FILE) {
|
||||
STRACE("need MAP_PRIVATE or MAP_SHARED");
|
||||
return VIP(einval());
|
||||
|
@ -289,8 +291,8 @@ dontasan inline void *_Mmap(void *addr, size_t size, int prot, int flags,
|
|||
} else if (VERY_UNLIKELY(off < 0)) {
|
||||
STRACE("mmap negative offset");
|
||||
return VIP(einval());
|
||||
} else if (VERY_UNLIKELY(!ALIGNED(off))) {
|
||||
STRACE("mmap off isn't 64kb aligned");
|
||||
} else if (off & ((IsWindows() ? FRAMESIZE : page_size) - 1)) {
|
||||
STRACE("mmap offset isn't properly aligned");
|
||||
return VIP(einval());
|
||||
} else if (VERY_UNLIKELY(INT64_MAX - size < off)) {
|
||||
STRACE("mmap too large");
|
||||
|
@ -326,8 +328,7 @@ dontasan inline void *_Mmap(void *addr, size_t size, int prot, int flags,
|
|||
OnUnrecoverableMmapError("FIXED UNTRACK FAILED");
|
||||
}
|
||||
}
|
||||
} else if (p && !clashes && !OverlapsArenaSpace(p, size) &&
|
||||
!OverlapsShadowSpace(p, size)) {
|
||||
} else if (p && !clashes && !OverlapsShadowSpace(p, size)) {
|
||||
x = FRAME(p);
|
||||
} else if (!Automap(n, a, &x)) {
|
||||
STRACE("automap has no room for %d frames with %d alignment", n, a);
|
||||
|
@ -335,7 +336,6 @@ dontasan inline void *_Mmap(void *addr, size_t size, int prot, int flags,
|
|||
}
|
||||
|
||||
needguard = false;
|
||||
guardsize = getauxval(AT_PAGESZ);
|
||||
p = (char *)ADDR_32_TO_48(x);
|
||||
if ((f & MAP_TYPE) == MAP_STACK) {
|
||||
if (~f & MAP_ANONYMOUS) {
|
||||
|
@ -374,11 +374,15 @@ dontasan inline void *_Mmap(void *addr, size_t size, int prot, int flags,
|
|||
if ((dm = sys_mmap(p + size - SIGSTKSZ, SIGSTKSZ, prot,
|
||||
f | MAP_GROWSDOWN_linux, fd, off))
|
||||
.addr != MAP_FAILED) {
|
||||
npassert(sys_mmap(p, guardsize, PROT_NONE,
|
||||
npassert(sys_mmap(p, page_size, PROT_NONE,
|
||||
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)
|
||||
.addr == p);
|
||||
dm.addr = p;
|
||||
return FinishMemory(p, size, prot, flags, fd, off, f, x, n, dm);
|
||||
p = FinishMemory(p, size, prot, flags, fd, off, f, x, n, dm);
|
||||
if (IsAsan() && p != MAP_FAILED) {
|
||||
__asan_poison(p, page_size, kAsanStackOverflow);
|
||||
}
|
||||
return p;
|
||||
} else if (errno == ENOTSUP) {
|
||||
// WSL doesn't support MAP_GROWSDOWN
|
||||
needguard = true;
|
||||
|
@ -399,14 +403,14 @@ dontasan inline void *_Mmap(void *addr, size_t size, int prot, int flags,
|
|||
}
|
||||
|
||||
if (p != MAP_FAILED) {
|
||||
if (IsAsan()) {
|
||||
__asan_poison(p + requested_size, size - requested_size,
|
||||
kAsanMmapSizeOverrun);
|
||||
}
|
||||
if (needguard) {
|
||||
if (!IsWindows()) {
|
||||
// make windows fork() code simpler
|
||||
mprotect(p, guardsize, PROT_NONE);
|
||||
}
|
||||
unassert(!mprotect(p, page_size, PROT_NONE));
|
||||
if (IsAsan()) {
|
||||
__repstosb((void *)(((intptr_t)p >> 3) + 0x7fff8000),
|
||||
kAsanStackOverflow, guardsize / 8);
|
||||
__asan_poison(p, page_size, kAsanStackOverflow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -415,7 +419,7 @@ dontasan inline void *_Mmap(void *addr, size_t size, int prot, int flags,
|
|||
}
|
||||
|
||||
/**
|
||||
* Beseeches system for page-table entries, e.g.
|
||||
* Creates virtual memory, e.g.
|
||||
*
|
||||
* char *m;
|
||||
* m = mmap(NULL, FRAMESIZE, PROT_READ | PROT_WRITE,
|
||||
|
@ -430,9 +434,7 @@ dontasan inline void *_Mmap(void *addr, size_t size, int prot, int flags,
|
|||
* needs to be made mandatory because of Windows although you can
|
||||
* use __sys_mmap() to circumvent it on System Five in which case
|
||||
* runtime support services, e.g. asan memory safety, could break
|
||||
* @param size must be >0 and needn't be a multiple of FRAMESIZE, but
|
||||
* will be rounded up to FRAMESIZE automatically if MAP_ANONYMOUS
|
||||
* is specified
|
||||
* @param size must be >0 otherwise EINVAL is raised
|
||||
* @param prot can have PROT_READ/PROT_WRITE/PROT_EXEC/PROT_NONE/etc.
|
||||
* @param flags should have one of the following masked by `MAP_TYPE`
|
||||
* - `MAP_FILE` in which case `MAP_ANONYMOUS` shouldn't be used
|
||||
|
@ -459,8 +461,8 @@ dontasan inline void *_Mmap(void *addr, size_t size, int prot, int flags,
|
|||
* @param fd is an open()'d file descriptor, whose contents shall be
|
||||
* made available w/ automatic reading at the chosen address
|
||||
* @param off specifies absolute byte index of fd's file for mapping,
|
||||
* should be zero if MAP_ANONYMOUS is specified, and sadly needs
|
||||
* to be 64kb aligned too
|
||||
* should be zero if MAP_ANONYMOUS is specified, which SHOULD be
|
||||
* aligned to FRAMESIZE
|
||||
* @return virtual base address of new mapping, or MAP_FAILED w/ errno
|
||||
*/
|
||||
void *mmap(void *addr, size_t size, int prot, int flags, int fd, int64_t off) {
|
||||
|
|
|
@ -27,6 +27,7 @@ textwindows int sys_mprotect_nt(void *addr, size_t size, int prot) {
|
|||
uint32_t op;
|
||||
char *a, *b, *x, *y, *p;
|
||||
__mmi_lock();
|
||||
size = (size + 4095) & -4096;
|
||||
p = addr;
|
||||
i = FindMemoryInterval(&_mmi, (intptr_t)p >> 16);
|
||||
if (i == _mmi.i || (!i && p + size <= (char *)ADDR_32_TO_48(_mmi.p[0].x))) {
|
||||
|
@ -41,9 +42,14 @@ textwindows int sys_mprotect_nt(void *addr, size_t size, int prot) {
|
|||
// we unfortunately must do something similar to this for cow
|
||||
for (; i < _mmi.i; ++i) {
|
||||
x = (char *)ADDR_32_TO_48(_mmi.p[i].x);
|
||||
y = x + _mmi.p[i].size;
|
||||
y = (char *)ADDR_32_TO_48(_mmi.p[i].y) + 65536;
|
||||
if ((x <= p && p < y) || (x < p + size && p + size <= y) ||
|
||||
(p < x && y < p + size)) {
|
||||
if (p <= x && p + size >= y) {
|
||||
_mmi.p[i].prot = prot;
|
||||
} else {
|
||||
_mmi.p[i].prot |= prot;
|
||||
}
|
||||
a = MIN(MAX(p, x), y);
|
||||
b = MAX(MIN(p + size, y), x);
|
||||
if (!VirtualProtect(a, b - a, __prot2nt(prot, _mmi.p[i].iscow), &op)) {
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include "libc/intrin/likely.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
|
@ -41,7 +43,7 @@ int mprotect(void *addr, size_t size, int prot) {
|
|||
rc = einval(); // unix checks prot before checking size
|
||||
} else if (!size) {
|
||||
return 0; // make new technology consistent with unix
|
||||
} else if (UNLIKELY((intptr_t)addr & 4095)) {
|
||||
} else if (UNLIKELY((intptr_t)addr & (getauxval(AT_PAGESZ) - 1))) {
|
||||
rc = einval(); // unix checks prot before checking size
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_mprotect(addr, size, prot);
|
||||
|
|
|
@ -23,13 +23,14 @@
|
|||
* Creates client socket file descriptor for incoming connection.
|
||||
*
|
||||
* @param fd is the server socket file descriptor
|
||||
* @param out_addr will receive the remote address
|
||||
* @param inout_addrsize provides and receives addr's byte length
|
||||
* @param opt_out_addr will receive the remote address
|
||||
* @param opt_inout_addrsize provides and receives addr's byte length
|
||||
* @return client fd which needs close(), or -1 w/ errno
|
||||
* @cancellationpoint
|
||||
* @asyncsignalsafe
|
||||
* @restartable (unless SO_RCVTIMEO)
|
||||
*/
|
||||
int accept(int fd, struct sockaddr *out_addr, uint32_t *inout_addrsize) {
|
||||
return accept4(fd, out_addr, inout_addrsize, 0);
|
||||
int accept(int fd, struct sockaddr *opt_out_addr,
|
||||
uint32_t *opt_inout_addrsize) {
|
||||
return accept4(fd, opt_out_addr, opt_inout_addrsize, 0);
|
||||
}
|
||||
|
|
|
@ -32,8 +32,8 @@
|
|||
* Creates client socket file descriptor for incoming connection.
|
||||
*
|
||||
* @param fd is the server socket file descriptor
|
||||
* @param out_addr will receive the remote address
|
||||
* @param inout_addrsize provides and receives out_addr's byte length
|
||||
* @param opt_out_addr will receive the remote address
|
||||
* @param opt_inout_addrsize provides and receives out_addr's byte length
|
||||
* @param flags can have SOCK_{CLOEXEC,NONBLOCK}, which may apply to
|
||||
* both the newly created socket and the server one
|
||||
* @return client fd which needs close(), or -1 w/ errno
|
||||
|
@ -41,7 +41,7 @@
|
|||
* @asyncsignalsafe
|
||||
* @restartable (unless SO_RCVTIMEO)
|
||||
*/
|
||||
int accept4(int fd, struct sockaddr *out_addr, uint32_t *inout_addrsize,
|
||||
int accept4(int fd, struct sockaddr *opt_out_addr, uint32_t *opt_inout_addrsize,
|
||||
int flags) {
|
||||
int rc;
|
||||
struct sockaddr_storage ss = {0};
|
||||
|
@ -61,11 +61,13 @@ int accept4(int fd, struct sockaddr *out_addr, uint32_t *inout_addrsize,
|
|||
if (IsBsd()) {
|
||||
__convert_bsd_to_sockaddr(&ss);
|
||||
}
|
||||
__write_sockaddr(&ss, out_addr, inout_addrsize);
|
||||
__write_sockaddr(&ss, opt_out_addr, opt_inout_addrsize);
|
||||
}
|
||||
|
||||
END_CANCELLATION_POINT;
|
||||
STRACE("accept4(%d, [%s]) -> %d% lm", fd,
|
||||
DescribeSockaddr(out_addr, inout_addrsize ? *inout_addrsize : 0), rc);
|
||||
DescribeSockaddr(opt_out_addr,
|
||||
opt_inout_addrsize ? *opt_inout_addrsize : 0),
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -17,15 +17,14 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/struct/fd.internal.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/syscall_fd.internal.h"
|
||||
#include "libc/sock/yoink.inc"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int sys_bind_nt(struct Fd *fd, const void *addr,
|
||||
uint32_t addrsize) {
|
||||
npassert(fd->kind == kFdSocket);
|
||||
unassert(fd->kind == kFdSocket);
|
||||
if (__sys_bind_nt(fd->handle, addr, addrsize) != -1) {
|
||||
return 0;
|
||||
} else {
|
||||
|
|
|
@ -32,7 +32,11 @@
|
|||
*
|
||||
* struct sockaddr_in in = {AF_INET, htons(12345), {htonl(0x7f000001)}};
|
||||
* int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
* bind(fd, &in, sizeof(in));
|
||||
* bind(fd, (struct sockaddr *)&in, sizeof(in));
|
||||
*
|
||||
* On Windows, Cosmopolitan's implementation of bind() takes care of
|
||||
* always setting the WIN32-specific `SO_EXCLUSIVEADDRUSE` option on
|
||||
* inet stream sockets in order to safeguard your servers from tests
|
||||
*
|
||||
* @param fd is the file descriptor returned by socket()
|
||||
* @param addr is usually the binary-encoded ip:port on which to listen
|
||||
|
|
|
@ -65,7 +65,7 @@ const char *(DescribeSockaddr)(char buf[128], const struct sockaddr *sa,
|
|||
unix = (const struct sockaddr_un *)sa;
|
||||
n = strnlen(unix->sun_path, sizeof(unix->sun_path));
|
||||
n = MIN(n, 128 - 1);
|
||||
memcpy(buf, unix->sun_path, n);
|
||||
if (n) memcpy(buf, unix->sun_path, n);
|
||||
buf[n] = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,14 +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/internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nt/enum/fileflagandattributes.h"
|
||||
#include "libc/nt/iphlpapi.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/yoink.inc"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/af.h"
|
||||
#include "libc/sysv/consts/ipproto.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/so.h"
|
||||
|
@ -42,13 +47,22 @@ __static_yoink("_dupsockfd");
|
|||
textwindows int sys_socket_nt(int family, int type, int protocol) {
|
||||
int64_t h;
|
||||
struct SockFd *sockfd;
|
||||
int fd, oflags, truetype;
|
||||
int fd, oflags, truetype, yes = 1;
|
||||
fd = __reservefd(-1);
|
||||
if (fd == -1) return -1;
|
||||
truetype = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
|
||||
if ((h = WSASocket(family, truetype, protocol, NULL, 0,
|
||||
kNtWsaFlagOverlapped)) != -1) {
|
||||
oflags = 0;
|
||||
|
||||
// sets SO_EXCLUSIVEADDRUSE on all sockets so they won't get pilfered
|
||||
// you can read a blog post on this subject in the find_unused_port()
|
||||
// pydoc of this file third_party/python/Lib/test/support/__init__.py
|
||||
// this needs to happen right after socket is called or it won't work
|
||||
if (family == AF_INET || family == AF_INET6) {
|
||||
unassert(__sys_setsockopt_nt(h, SOL_SOCKET, -5, &yes, 4) != -1);
|
||||
}
|
||||
|
||||
oflags = O_RDWR;
|
||||
if (type & SOCK_CLOEXEC) oflags |= O_CLOEXEC;
|
||||
if (type & SOCK_NONBLOCK) oflags |= O_NONBLOCK;
|
||||
sockfd = calloc(1, sizeof(struct SockFd));
|
||||
|
@ -62,6 +76,7 @@ textwindows int sys_socket_nt(int family, int type, int protocol) {
|
|||
g_fds.p[fd].handle = h;
|
||||
g_fds.p[fd].extra = (uintptr_t)sockfd;
|
||||
__fds_unlock();
|
||||
|
||||
return fd;
|
||||
} else {
|
||||
__releasefd(fd);
|
||||
|
|
|
@ -22,26 +22,31 @@
|
|||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sysv/consts/af.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Creates new system resource for network communication, e.g.
|
||||
*
|
||||
* int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
*
|
||||
* @param family can be AF_UNIX, AF_INET, etc.
|
||||
* @param family can be AF_UNIX, AF_INET, AF_INET6, etc.
|
||||
* @param type can be SOCK_STREAM (for TCP), SOCK_DGRAM (e.g. UDP), or
|
||||
* SOCK_RAW (IP) so long as IP_HDRINCL was passed to setsockopt();
|
||||
* and additionally, may be or'd with SOCK_NONBLOCK, SOCK_CLOEXEC
|
||||
* @param protocol can be IPPROTO_TCP, IPPROTO_UDP, or IPPROTO_ICMP
|
||||
* @return socket file descriptor or -1 w/ errno
|
||||
* @error ENETDOWN, EPFNOSUPPORT, etc.
|
||||
* @raise EAFNOSUPPORT if `family` isn't supported by system or platform
|
||||
* @see libc/sysv/consts.sh
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int socket(int family, int type, int protocol) {
|
||||
int rc;
|
||||
if (family == AF_UNSPEC) family = AF_INET;
|
||||
if (!IsWindows()) {
|
||||
if (family == AF_UNSPEC) {
|
||||
family = AF_INET;
|
||||
}
|
||||
if (family == -1) {
|
||||
rc = eafnosupport();
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_socket(family, type, protocol);
|
||||
} else {
|
||||
rc = sys_socket_nt(family, type, protocol);
|
||||
|
|
|
@ -285,7 +285,9 @@ DIR *opendir(const char *name) {
|
|||
res->zip.offset = GetZipCdirOffset(zip->cdir);
|
||||
res->zip.records = GetZipCdirRecords(zip->cdir);
|
||||
res->zip.prefix = malloc(zipname.len + 2);
|
||||
memcpy(res->zip.prefix, zipname.path, zipname.len);
|
||||
if (zipname.len) {
|
||||
memcpy(res->zip.prefix, zipname.path, zipname.len);
|
||||
}
|
||||
if (zipname.len && res->zip.prefix[zipname.len - 1] != '/') {
|
||||
res->zip.prefix[zipname.len++] = '/';
|
||||
}
|
||||
|
@ -364,7 +366,9 @@ static struct dirent *readdir_impl(DIR *dir) {
|
|||
ent->d_off = dir->zip.offset;
|
||||
ent->d_reclen = MIN(n, 255);
|
||||
ent->d_type = S_ISDIR(mode) ? DT_DIR : DT_REG;
|
||||
memcpy(ent->d_name, s, ent->d_reclen);
|
||||
if (ent->d_reclen) {
|
||||
memcpy(ent->d_name, s, ent->d_reclen);
|
||||
}
|
||||
ent->d_name[ent->d_reclen] = 0;
|
||||
} else {
|
||||
lastent = (struct dirent *)dir->buf;
|
||||
|
@ -377,7 +381,9 @@ static struct dirent *readdir_impl(DIR *dir) {
|
|||
ent->d_off = -1;
|
||||
ent->d_reclen = n;
|
||||
ent->d_type = DT_DIR;
|
||||
memcpy(ent->d_name, s, ent->d_reclen);
|
||||
if (ent->d_reclen) {
|
||||
memcpy(ent->d_name, s, ent->d_reclen);
|
||||
}
|
||||
ent->d_name[ent->d_reclen] = 0;
|
||||
}
|
||||
}
|
||||
|
@ -474,7 +480,9 @@ errno_t readdir_r(DIR *dir, struct dirent *output, struct dirent **result) {
|
|||
return err;
|
||||
}
|
||||
if (entry) {
|
||||
memcpy(output, entry, entry->d_reclen);
|
||||
if (entry->d_reclen) {
|
||||
memcpy(output, entry, entry->d_reclen);
|
||||
}
|
||||
} else {
|
||||
output = 0;
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ char *fgets_unlocked(char *s, int size, FILE *f) {
|
|||
if ((t = memchr(b, '\n', n))) {
|
||||
n = t + 1 - b;
|
||||
}
|
||||
memcpy(p, b, n);
|
||||
if (n) memcpy(p, b, n);
|
||||
f->beg += n;
|
||||
size -= n - 1;
|
||||
p += n;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
@ -39,7 +40,8 @@ int mkostempsmi(char *tpl, int slen, unsigned flags, uint64_t *rando, int mode,
|
|||
if (len < wildlen || slen > len - wildlen) return einval();
|
||||
char *ss = tpl + len - wildlen - slen;
|
||||
npassert(memcmp(ss, WILDCARD, wildlen) == 0);
|
||||
flags = (flags & ~(flags & O_ACCMODE)) | O_RDWR | O_CREAT | O_EXCL;
|
||||
flags = (flags & ~(flags & O_ACCMODE)) | O_RDWR | O_CREAT | O_EXCL |
|
||||
(IsWindows() ? 0x00410000 : 0);
|
||||
unsigned attempts = ATTEMPTS;
|
||||
do {
|
||||
char *p = ss;
|
||||
|
@ -74,8 +76,7 @@ static uint64_t g_mkostemps_reseed;
|
|||
* or -1 w/ errno
|
||||
* @see kTmpPath
|
||||
*/
|
||||
dontdiscard int mkostempsm(char *template, int suffixlen, unsigned flags,
|
||||
int mode) {
|
||||
int mkostempsm(char *template, int suffixlen, unsigned flags, int mode) {
|
||||
int fd;
|
||||
if (g_mkostemps_reseed++ % RESEED == 0) g_mkostemps_rand = _rand64();
|
||||
fd = mkostempsmi(template, suffixlen, flags, &g_mkostemps_rand, mode, open);
|
||||
|
|
|
@ -87,13 +87,13 @@ errno_t posix_spawn(int *pid, const char *path,
|
|||
posix_spawnattr_getflags(attrp, &flags);
|
||||
if (flags & POSIX_SPAWN_SETSID) {
|
||||
if (setsid()) {
|
||||
STRACE("posix_spawn fail #%d", 1);
|
||||
STRACE("posix_spawn fail #%d% m", 1);
|
||||
_Exit(127);
|
||||
}
|
||||
}
|
||||
if (flags & POSIX_SPAWN_SETPGROUP) {
|
||||
if (setpgid(0, (*attrp)->pgroup)) {
|
||||
STRACE("posix_spawn fail #%d", 1);
|
||||
STRACE("posix_spawn fail #%d% m", 2);
|
||||
_Exit(127);
|
||||
}
|
||||
}
|
||||
|
@ -103,14 +103,14 @@ errno_t posix_spawn(int *pid, const char *path,
|
|||
}
|
||||
if ((flags & POSIX_SPAWN_RESETIDS) &&
|
||||
(setgid(getgid()) || setuid(getuid()))) {
|
||||
STRACE("posix_spawn fail #%d", 2);
|
||||
STRACE("posix_spawn fail #%d% m", 3);
|
||||
_Exit(127);
|
||||
}
|
||||
if (flags & POSIX_SPAWN_SETSIGDEF) {
|
||||
for (s = 1; s < 32; s++) {
|
||||
if (sigismember(&(*attrp)->sigdefault, s)) {
|
||||
if (sigaction(s, &dfl, 0) == -1) {
|
||||
STRACE("posix_spawn fail #%d", 3);
|
||||
STRACE("posix_spawn fail #%d% m", 4);
|
||||
_Exit(127);
|
||||
}
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ errno_t posix_spawn(int *pid, const char *path,
|
|||
}
|
||||
if (file_actions) {
|
||||
if (RunFileActions(*file_actions) == -1) {
|
||||
STRACE("posix_spawn fail #%d", 4);
|
||||
STRACE("posix_spawn fail #%d% m", 5);
|
||||
_Exit(127);
|
||||
}
|
||||
}
|
||||
|
@ -128,21 +128,21 @@ errno_t posix_spawn(int *pid, const char *path,
|
|||
posix_spawnattr_getschedpolicy(attrp, &policy);
|
||||
posix_spawnattr_getschedparam(attrp, ¶m);
|
||||
if (sched_setscheduler(0, policy, ¶m) == -1) {
|
||||
STRACE("posix_spawn fail #%d", 5);
|
||||
STRACE("posix_spawn fail #%d% m", 6);
|
||||
_Exit(127);
|
||||
}
|
||||
}
|
||||
if (flags & POSIX_SPAWN_SETSCHEDPARAM) {
|
||||
posix_spawnattr_getschedparam(attrp, ¶m);
|
||||
if (sched_setparam(0, ¶m) == -1) {
|
||||
STRACE("posix_spawn fail #%d", 6);
|
||||
STRACE("posix_spawn fail #%d% m", 7);
|
||||
_Exit(127);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!envp) envp = environ;
|
||||
execve(path, argv, envp);
|
||||
STRACE("posix_spawn fail #%d", 7);
|
||||
STRACE("posix_spawn fail #%d% m", 8);
|
||||
_Exit(127);
|
||||
} else if (child != -1) {
|
||||
if (pid) *pid = child;
|
||||
|
|
|
@ -46,34 +46,34 @@
|
|||
int system(const char *cmdline) {
|
||||
int pid, wstatus;
|
||||
sigset_t chldmask, savemask;
|
||||
struct sigaction ignore, saveint, savequit;
|
||||
if (!cmdline) return 1;
|
||||
BLOCK_CANCELLATIONS;
|
||||
ignore.sa_flags = 0;
|
||||
ignore.sa_handler = SIG_IGN;
|
||||
sigemptyset(&ignore.sa_mask);
|
||||
sigaction(SIGINT, &ignore, &saveint);
|
||||
sigaction(SIGQUIT, &ignore, &savequit);
|
||||
sigemptyset(&chldmask);
|
||||
sigaddset(&chldmask, SIGINT);
|
||||
sigaddset(&chldmask, SIGQUIT);
|
||||
sigaddset(&chldmask, SIGCHLD);
|
||||
sigprocmask(SIG_BLOCK, &chldmask, &savemask);
|
||||
if (!(pid = fork())) {
|
||||
sigaction(SIGINT, &saveint, 0);
|
||||
sigaction(SIGQUIT, &savequit, 0);
|
||||
sigprocmask(SIG_SETMASK, &savemask, 0);
|
||||
_Exit(_cocmd(3, (char *[]){"system", "-c", cmdline, 0}, environ));
|
||||
} else if (pid != -1) {
|
||||
} else if (pid == -1) {
|
||||
wstatus = -1;
|
||||
} else {
|
||||
struct sigaction ignore, saveint, savequit;
|
||||
ignore.sa_flags = 0;
|
||||
ignore.sa_handler = SIG_IGN;
|
||||
sigemptyset(&ignore.sa_mask);
|
||||
sigaction(SIGINT, &ignore, &saveint);
|
||||
sigaction(SIGQUIT, &ignore, &savequit);
|
||||
while (wait4(pid, &wstatus, 0, 0) == -1) {
|
||||
if (errno != EINTR) {
|
||||
wstatus = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
wstatus = -1;
|
||||
sigaction(SIGINT, &saveint, 0);
|
||||
sigaction(SIGQUIT, &savequit, 0);
|
||||
}
|
||||
sigaction(SIGINT, &saveint, 0);
|
||||
sigaction(SIGQUIT, &savequit, 0);
|
||||
sigprocmask(SIG_SETMASK, &savemask, 0);
|
||||
ALLOW_CANCELLATIONS;
|
||||
return wstatus;
|
||||
|
|
|
@ -180,7 +180,6 @@ syscon compat SIGIOT 6 6 6 6 6 6 6 6 # PDP-11 feature; same
|
|||
# open() flags
|
||||
#
|
||||
# group name GNU/Systemd GNU/Systemd (Aarch64) XNU's Not UNIX! MacOS (Arm64) FreeBSD OpenBSD NetBSD Windoze Commentary
|
||||
syscon open O_RDWR 2 2 2 2 2 2 2 2 # consensus
|
||||
syscon open O_APPEND 0x00000400 0x00000400 8 8 8 8 8 0x00000400 # bsd consensus & kNtFileAppendData; won't pose issues w/ mknod(S_IFIFO) [SYNC libc/calls/open-nt.c]
|
||||
syscon open O_CREAT 0x00000040 0x00000040 0x00000200 0x00000200 0x00000200 0x00000200 0x00000200 0x00000040 # bsd consensus & NT faked as Linux [SYNC libc/calls/open-nt.c]
|
||||
syscon open O_EXCL 0x00000080 0x00000080 0x00000800 0x00000800 0x00000800 0x00000800 0x00000800 0x00000080 # bsd consensus & NT faked as Linux [SYNC libc/calls/open-nt.c]
|
||||
|
@ -606,45 +605,23 @@ syscon poll POLLWRBAND 0x0200 0x0200 0x0100 0x0100 0x0100 0x0100
|
|||
syscon poll POLLWRNORM 0x0100 0x0100 4 4 4 4 4 0x0010 # bsd consensus
|
||||
syscon poll POLLRDHUP 0x2000 0x2000 0x10 0x10 0x10 0x10 0x10 2 # bsd consensus (POLLHUP on non-Linux)
|
||||
|
||||
# epoll
|
||||
#
|
||||
# group name GNU/Systemd GNU/Systemd (Aarch64) XNU's Not UNIX! MacOS (Arm64) FreeBSD OpenBSD NetBSD The New Technology Commentary
|
||||
syscon epoll EPOLL_CLOEXEC 0x080000 0x080000 0x01000000 0x01000000 0x100000 0x010000 0x010000 0x80000 # O_CLOEXEC
|
||||
syscon epoll EPOLL_CTL_ADD 1 1 1 1 1 1 1 1 # forced consensus, linux only natively, polyfilled elsewhere
|
||||
syscon epoll EPOLL_CTL_DEL 2 2 2 2 2 2 2 2 # forced consensus, linux only natively, polyfilled elsewhere
|
||||
syscon epoll EPOLL_CTL_MOD 3 3 3 3 3 3 3 3 # forced consensus, linux only natively, polyfilled elsewhere
|
||||
syscon epoll EPOLLIN 1 1 1 1 1 1 1 1 # forced consensus, linux only natively, polyfilled elsewhere
|
||||
syscon epoll EPOLLOUT 4 4 4 4 4 4 4 4 # forced consensus, linux only natively, polyfilled elsewhere
|
||||
syscon epoll EPOLLERR 8 8 8 8 8 8 8 8 # forced consensus, linux only natively, polyfilled elsewhere
|
||||
syscon epoll EPOLLPRI 2 2 2 2 2 2 2 2 # forced consensus, linux only natively, polyfilled elsewhere
|
||||
syscon epoll EPOLLHUP 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 # forced consensus, linux only natively, polyfilled elsewhere
|
||||
syscon epoll EPOLLRDNORM 0x40 0x40 0x40 0x40 0x40 0x40 0x40 0x40 # forced consensus, linux only natively, polyfilled elsewhere
|
||||
syscon epoll EPOLLRDBAND 0x80 0x80 0x80 0x80 0x80 0x80 0x80 0x80 # forced consensus, linux only natively, polyfilled elsewhere
|
||||
syscon epoll EPOLLWRNORM 0x0100 0x0100 0x0100 0x0100 0x0100 0x0100 0x0100 0x0100 # forced consensus, linux only natively, polyfilled elsewhere
|
||||
syscon epoll EPOLLWRBAND 0x0200 0x0200 0x0200 0x0200 0x0200 0x0200 0x0200 0x0200 # forced consensus, linux only natively, polyfilled elsewhere
|
||||
syscon epoll EPOLLMSG 0x0400 0x0400 0x0400 0x0400 0x0400 0x0400 0x0400 0x0400 # forced consensus, linux only natively, polyfilled elsewhere
|
||||
syscon epoll EPOLLRDHUP 0x2000 0x2000 0x2000 0x2000 0x2000 0x2000 0x2000 0x2000 # forced consensus, linux only natively, polyfilled elsewhere
|
||||
syscon epoll EPOLLEXCLUSIVE 0x10000000 0x10000000 0x10000000 0x10000000 0x10000000 0x10000000 0x10000000 0x10000000 # forced consensus, linux only natively, polyfilled elsewhere
|
||||
syscon epoll EPOLLWAKEUP 0x20000000 0x20000000 0x20000000 0x20000000 0x20000000 0x20000000 0x20000000 0x20000000 # forced consensus, linux only natively, polyfilled elsewhere
|
||||
syscon epoll EPOLLONESHOT 0x40000000 0x40000000 0x40000000 0x40000000 0x40000000 0x40000000 0x40000000 0x40000000 # forced consensus, linux only natively, polyfilled elsewhere
|
||||
syscon epoll EPOLLET 0x80000000 0x80000000 0x80000000 0x80000000 0x80000000 0x80000000 0x80000000 0x80000000 # forced consensus, linux only natively, polyfilled elsewhere
|
||||
|
||||
# {set,get}sockopt(fd, level=SOL_SOCKET, X, ...)
|
||||
#
|
||||
# Unsupported magic numbers are set to zero.
|
||||
#
|
||||
# group name GNU/Systemd GNU/Systemd (Aarch64) XNU's Not UNIX! MacOS (Arm64) FreeBSD OpenBSD NetBSD The New Technology Commentary
|
||||
syscon so SOL_SOCKET 1 1 0xffff 0xffff 0xffff 0xffff 0xffff 0xffff # yes it's actually 0xffff; bsd+nt consensus (todo: what's up with ipproto_icmp overlap)
|
||||
syscon so SO_DEBUG 1 1 1 1 1 1 1 1 # debugging is enabled; consensus
|
||||
syscon so SO_TYPE 3 3 0x1008 0x1008 0x1008 0x1008 0x1008 0x1008 # bsd consensus
|
||||
syscon so SO_ERROR 4 4 0x1007 0x1007 0x1007 0x1007 0x1007 0x1007 # takes int pointer and stores/clears the pending error code; bsd consensus
|
||||
syscon so SO_ACCEPTCONN 30 30 2 2 2 2 2 2 # takes int pointer and stores boolean indicating if listen() was called on fd; bsd consensus
|
||||
syscon so SO_REUSEPORT 15 15 0x0200 0x0200 0x0200 0x0200 0x0200 4 # bsd consensus (NT calls it SO_REUSEADDR)
|
||||
syscon so SO_REUSEPORT 15 15 0x0200 0x0200 0x0200 0x0200 0x0200 0 # bsd consensus; no windows support
|
||||
syscon so SO_REUSEADDR 2 2 4 4 4 4 4 4 # bsd consensus (default behavior on NT)
|
||||
syscon so SO_EXCLUSIVEADDRUSE 0 0 0 0 0 0 0 ~4 # bsd consensus (default behavior on NT)
|
||||
syscon so SO_KEEPALIVE 9 9 8 8 8 8 8 8 # bsd consensus
|
||||
syscon so SO_DONTROUTE 5 5 0x10 0x10 0x10 0x10 0x10 0x10 # bsd consensus
|
||||
syscon so SO_BROADCAST 6 6 0x20 0x20 0x20 0x20 0x20 0x20 # socket is configured for broadcast messages; bsd consensus
|
||||
syscon so SO_USELOOPBACK 0 0 0x40 0x40 0x40 0x40 0x40 0x40 # bsd consensus
|
||||
syscon so SO_LINGER 13 13 0x1080 0x1080 0x80 0x80 0x80 0x80 # takes struct linger; causes close() return value to actually mean something; SO_LINGER_SEC on XNU; bsd consensus
|
||||
syscon so SO_DONTLINGER 0 0 0 0 0 0 0 ~0x80 # disables so_linger on windows
|
||||
syscon so SO_OOBINLINE 10 10 0x0100 0x0100 0x0100 0x0100 0x0100 0x0100 # bsd consensus
|
||||
syscon so SO_SNDBUF 7 7 0x1001 0x1001 0x1001 0x1001 0x1001 0x1001 # bsd consensus
|
||||
syscon so SO_RCVBUF 8 8 0x1002 0x1002 0x1002 0x1002 0x1002 0x1002 # bsd consensus
|
||||
|
@ -652,120 +629,6 @@ syscon so SO_RCVTIMEO 20 20 0x1006 0x1006 0x1006 0x1006 0x100c
|
|||
syscon so SO_SNDTIMEO 21 21 0x1005 0x1005 0x1005 0x1005 0x100b 0x1005 # send timeout; takes struct timeval; bsd consensus
|
||||
syscon so SO_RCVLOWAT 18 18 0x1004 0x1004 0x1004 0x1004 0x1004 0x1004 # bsd consensus
|
||||
syscon so SO_SNDLOWAT 19 19 0x1003 0x1003 0x1003 0x1003 0x1003 0x1003 # bsd consensus
|
||||
syscon so SO_TIMESTAMP 29 29 0x0400 0x0400 0x0400 0x0800 0x2000 0
|
||||
syscon so SO_SETFIB 0 0 0 0 0x1014 0 0 0
|
||||
syscon so SO_DOMAIN 39 39 0 0 0x1019 0x1024 0 0
|
||||
syscon so SO_MAX_PACING_RATE 47 47 0 0 0x1018 0 0 0
|
||||
syscon so SO_PEERCRED 17 17 0 0 0 0x1022 0 0
|
||||
syscon so SO_EXCLUSIVEADDRUSE 0 0 0 0 0 0 0 0xfffffffb # hoo boy
|
||||
syscon so LOCAL_PEERCRED 0 0 1 1 1 0 0 0
|
||||
syscon so SO_PROTOCOL 38 38 0 0 0x1016 0x1025 0 0
|
||||
syscon so SO_ATTACH_BPF 50 50 0 0 0 0 0 0
|
||||
syscon so SO_ATTACH_FILTER 26 26 0 0 0 0 0 0
|
||||
syscon so SO_ATTACH_REUSEPORT_CBPF 51 51 0 0 0 0 0 0
|
||||
syscon so SO_ATTACH_REUSEPORT_EBPF 52 52 0 0 0 0 0 0
|
||||
syscon so SO_BINDTODEVICE 25 25 0 0 0 0 0 0
|
||||
syscon so SO_BPF_EXTENSIONS 48 48 0 0 0 0 0 0
|
||||
syscon so SO_BSDCOMPAT 14 14 0 0 0 0 0 0
|
||||
syscon so SO_BUSY_POLL 46 46 0 0 0 0 0 0
|
||||
syscon so SO_CNX_ADVICE 53 53 0 0 0 0 0 0
|
||||
syscon so SO_DETACH_BPF 27 27 0 0 0 0 0 0
|
||||
syscon so SO_DETACH_FILTER 27 27 0 0 0 0 0 0
|
||||
syscon so SO_GET_FILTER 26 26 0 0 0 0 0 0
|
||||
syscon so SO_INCOMING_CPU 49 49 0 0 0 0 0 0
|
||||
syscon so SO_LOCK_FILTER 44 44 0 0 0 0 0 0
|
||||
syscon so SO_MARK 36 36 0 0 0 0 0 0
|
||||
syscon so SO_NOFCS 43 43 0 0 0 0 0 0
|
||||
syscon so SO_NO_CHECK 11 11 0 0 0 0 0 0
|
||||
syscon so SO_PASSCRED 0x10 0x10 0 0 0 0 0 0
|
||||
syscon so SO_PASSSEC 34 34 0 0 0 0 0 0
|
||||
syscon so SO_PEEK_OFF 42 42 0 0 0 0 0 0
|
||||
syscon so SO_PEERNAME 28 28 0 0 0 0 0 0
|
||||
syscon so SO_PEERSEC 31 31 0 0 0 0 0 0
|
||||
syscon so SO_PRIORITY 12 12 0 0 0 0 0 0
|
||||
syscon so SO_RCVBUFFORCE 33 33 0 0 0 0 0 0
|
||||
syscon so SO_RXQ_OVFL 40 40 0 0 0 0 0 0
|
||||
syscon so SO_SECURITY_AUTHENTICATION 22 22 0 0 0 0 0 0
|
||||
syscon so SO_SECURITY_ENCRYPTION_NETWORK 24 24 0 0 0 0 0 0
|
||||
syscon so SO_SECURITY_ENCRYPTION_TRANSPORT 23 23 0 0 0 0 0 0
|
||||
syscon so SO_SELECT_ERR_QUEUE 45 45 0 0 0 0 0 0
|
||||
syscon so SO_SNDBUFFORCE 0x20 0x20 0 0 0 0 0 0
|
||||
syscon so SO_TIMESTAMPING 37 37 0 0 0 0 0 0
|
||||
syscon so SO_TIMESTAMPNS 35 35 0 0 0 0 0 0
|
||||
syscon so SO_WIFI_STATUS 41 41 0 0 0 0 0 0
|
||||
|
||||
# these are IPPROTO_* on non-Linux
|
||||
syscon sol SOL_IP 0 0 0 0 0 0 0 0 # consensus
|
||||
syscon sol SOL_SOCKET 1 1 0xffff 0xffff 0xffff 0xffff 0xffff 0xffff # yes it's actually 0xffff; bsd+nt consensus (todo: what's up with ipproto_icmp overlap)
|
||||
syscon sol SOL_TCP 6 6 6 6 6 6 6 6 # consensus
|
||||
syscon sol SOL_UDP 17 17 17 17 17 17 17 17 # consensus
|
||||
syscon sol SOL_RAW 255 255 -1 -1 -1 -1 -1 -1
|
||||
syscon sol SOL_IPV6 41 41 41 41 41 41 41 41
|
||||
syscon sol SOL_ICMPV6 58 58 58 58 58 58 58 -1
|
||||
syscon sol SOL_AAL 265 265 -1 -1 -1 -1 -1 -1
|
||||
syscon sol SOL_ALG 279 279 -1 -1 -1 -1 -1 -1
|
||||
syscon sol SOL_ATM 264 264 -1 -1 -1 -1 -1 -1
|
||||
syscon sol SOL_BLUETOOTH 274 274 -1 -1 -1 -1 -1 -1
|
||||
syscon sol SOL_CAIF 278 278 -1 -1 -1 -1 -1 -1
|
||||
syscon sol SOL_DCCP 269 269 -1 -1 -1 -1 -1 -1
|
||||
syscon sol SOL_DECNET 261 261 -1 -1 -1 -1 -1 -1
|
||||
syscon sol SOL_IRDA 266 266 -1 -1 -1 -1 -1 -1
|
||||
syscon sol SOL_IUCV 277 277 -1 -1 -1 -1 -1 -1
|
||||
syscon sol SOL_KCM 281 281 -1 -1 -1 -1 -1 -1
|
||||
syscon sol SOL_LLC 268 268 -1 -1 -1 -1 -1 -1
|
||||
syscon sol SOL_NETBEUI 267 267 -1 -1 -1 -1 -1 -1
|
||||
syscon sol SOL_NETLINK 270 270 -1 -1 -1 -1 -1 -1
|
||||
syscon sol SOL_NFC 280 280 -1 -1 -1 -1 -1 -1
|
||||
syscon sol SOL_PACKET 263 263 -1 -1 -1 -1 -1 -1
|
||||
syscon sol SOL_PNPIPE 275 275 -1 -1 -1 -1 -1 -1
|
||||
syscon sol SOL_PPPOL2TP 273 273 -1 -1 -1 -1 -1 -1
|
||||
syscon sol SOL_RDS 276 276 -1 -1 -1 -1 -1 -1
|
||||
syscon sol SOL_RXRPC 272 272 -1 -1 -1 -1 -1 -1
|
||||
syscon sol SOL_TIPC 271 271 -1 -1 -1 -1 -1 -1
|
||||
syscon sol SOL_X25 262 262 -1 -1 -1 -1 -1 -1
|
||||
|
||||
# IPPROTO_*
|
||||
#
|
||||
# group name GNU/Systemd GNU/Systemd (Aarch64) XNU's Not UNIX! MacOS (Arm64) FreeBSD OpenBSD NetBSD The New Technology Commentary
|
||||
syscon iproto IPPROTO_IP 0 0 0 0 0 0 0 0 # consensus
|
||||
syscon iproto IPPROTO_ICMP 1 1 1 1 1 1 1 1 # consensus
|
||||
syscon iproto IPPROTO_TCP 6 6 6 6 6 6 6 6 # consensus
|
||||
syscon iproto IPPROTO_UDP 17 17 17 17 17 17 17 17 # consensus
|
||||
syscon iproto IPPROTO_RAW 255 255 255 255 255 255 255 255 # consensus
|
||||
syscon iproto IPPROTO_HOPOPTS 0 0 0 0 0 0 0 -1 # consensus
|
||||
syscon iproto IPPROTO_IDP 22 22 22 22 22 22 22 22 # consensus
|
||||
syscon iproto IPPROTO_IGMP 2 2 2 2 2 2 2 2 # consensus
|
||||
syscon iproto IPPROTO_PUP 12 12 12 12 12 12 12 12 # consensus
|
||||
syscon iproto IPPROTO_AH 51 51 51 51 51 51 51 -1 # unix consensus
|
||||
syscon iproto IPPROTO_DSTOPTS 60 60 60 60 60 60 60 -1 # unix consensus
|
||||
syscon iproto IPPROTO_EGP 8 8 8 8 8 8 8 -1 # unix consensus
|
||||
syscon iproto IPPROTO_ENCAP 98 98 98 98 98 98 98 -1 # unix consensus
|
||||
syscon iproto IPPROTO_ESP 50 50 50 50 50 50 50 -1 # unix consensus
|
||||
syscon iproto IPPROTO_FRAGMENT 44 44 44 44 44 44 44 -1 # unix consensus
|
||||
syscon iproto IPPROTO_GRE 47 47 47 47 47 47 47 -1 # unix consensus
|
||||
syscon iproto IPPROTO_ICMPV6 58 58 58 58 58 58 58 -1 # unix consensus
|
||||
syscon iproto IPPROTO_IPIP 4 4 4 4 4 4 4 -1 # unix consensus
|
||||
syscon iproto IPPROTO_IPV6 41 41 41 41 41 41 41 -1 # unix consensus
|
||||
syscon iproto IPPROTO_NONE 59 59 59 59 59 59 59 -1 # unix consensus
|
||||
syscon iproto IPPROTO_PIM 103 103 103 103 103 103 103 -1 # unix consensus
|
||||
syscon iproto IPPROTO_ROUTING 43 43 43 43 43 43 43 -1 # unix consensus
|
||||
syscon iproto IPPROTO_RSVP 46 46 46 46 46 46 46 -1 # unix consensus
|
||||
syscon iproto IPPROTO_TP 29 29 29 29 29 29 29 -1 # unix consensus
|
||||
syscon iproto IPPROTO_MPLS 137 137 -1 -1 137 137 137 -1
|
||||
syscon iproto IPPROTO_MTP 92 92 92 92 92 -1 -1 -1
|
||||
syscon iproto IPPROTO_SCTP 132 132 132 132 132 -1 -1 -1
|
||||
syscon iproto IPPROTO_MH 135 135 -1 -1 135 -1 -1 -1
|
||||
syscon iproto IPPROTO_UDPLITE 136 136 -1 -1 136 -1 -1 -1
|
||||
syscon iproto IPPROTO_BEETPH 94 94 -1 -1 -1 -1 -1 -1
|
||||
syscon iproto IPPROTO_COMP 108 108 -1 -1 -1 -1 -1 -1
|
||||
syscon iproto IPPROTO_DCCP 33 33 -1 -1 -1 -1 -1 -1
|
||||
|
||||
syscon alg ALG_SET_KEY 1 1 0 0 0 0 0 0
|
||||
syscon alg ALG_SET_IV 2 2 0 0 0 0 0 0
|
||||
syscon alg ALG_SET_OP 3 3 0 0 0 0 0 0
|
||||
syscon alg ALG_SET_AEAD_ASSOCLEN 4 4 0 0 0 0 0 0
|
||||
syscon alg ALG_SET_AEAD_AUTHSIZE 5 5 0 0 0 0 0 0
|
||||
syscon alg ALG_SET_DRBG_ENTROPY 6 6 0 0 0 0 0 0
|
||||
|
||||
# {set,get}sockopt(fd, level=SOL_TCP, X, ...)
|
||||
# » most elite of all tuning groups
|
||||
|
@ -1004,48 +867,48 @@ syscon ioctl SIOGIFINDEX 0x8933 0x8933 0 0 0 0 0 0
|
|||
syscon af AF_UNSPEC 0 0 0 0 0 0 0 0 # consensus
|
||||
syscon af AF_UNIX 1 1 1 1 1 1 1 1 # consensus
|
||||
syscon af AF_LOCAL 1 1 1 1 1 1 1 1 # consensus
|
||||
syscon af AF_FILE 1 1 0 0 0 0 0 0
|
||||
syscon af AF_INET 2 2 2 2 2 2 2 2 # consensus
|
||||
syscon af AF_INET6 10 10 30 30 28 24 24 23
|
||||
syscon af AF_AX25 3 3 0 0 0 0 0 0
|
||||
syscon af AF_IPX 4 4 23 23 23 23 23 6 # bsd consensus
|
||||
syscon af AF_APPLETALK 5 5 0x10 0x10 0x10 0x10 0x10 0x10 # bsd consensus
|
||||
syscon af AF_NETROM 6 6 0 0 0 0 0 0
|
||||
syscon af AF_BRIDGE 7 7 0 0 0 0 0 0
|
||||
syscon af AF_ATMPVC 8 8 0 0 0 0 0 0
|
||||
syscon af AF_X25 9 9 0 0 0 0 0 0
|
||||
syscon af AF_ROSE 11 11 0 0 0 0 0 0
|
||||
syscon af AF_NETBEUI 13 13 0 0 0 0 0 0
|
||||
syscon af AF_SECURITY 14 14 0 0 0 0 0 0
|
||||
syscon af AF_KEY 15 15 0 0 0 30 0 0
|
||||
syscon af AF_ROUTE 16 16 17 17 17 17 34 0 # bsd consensus
|
||||
syscon af AF_NETLINK 16 16 0 0 0 0 0 0
|
||||
syscon af AF_PACKET 17 17 0 0 0 0 0 0
|
||||
syscon af AF_LINK 0 0 18 18 18 18 18 0
|
||||
syscon af AF_ASH 18 18 0 0 0 0 0 0
|
||||
syscon af AF_ECONET 19 19 0 0 0 0 0 0
|
||||
syscon af AF_ATMSVC 20 20 0 0 0 0 0 0
|
||||
syscon af AF_RDS 21 21 0 0 0 0 0 0
|
||||
syscon af AF_ROUTE 16 16 17 17 17 17 34 -1 # bsd consensus
|
||||
syscon af AF_LINK -1 -1 18 18 18 18 18 -1
|
||||
syscon af AF_SNA 22 22 11 11 11 11 11 11 # bsd consensus
|
||||
syscon af AF_IRDA 23 23 0 0 0 0 0 0
|
||||
syscon af AF_PPPOX 24 24 0 0 0 0 0 0
|
||||
syscon af AF_WANPIPE 25 25 0 0 0 0 0 0
|
||||
syscon af AF_LLC 26 26 0 0 0 0 0 0
|
||||
syscon af AF_IB 27 27 0 0 0 0 0 0
|
||||
syscon af AF_MPLS 28 28 0 0 0 33 33 0
|
||||
syscon af AF_CAN 29 29 0 0 0 0 35 0
|
||||
syscon af AF_TIPC 30 30 0 0 0 0 0 0
|
||||
syscon af AF_BLUETOOTH 31 31 0 0 36 0x20 31 0
|
||||
syscon af AF_IUCV 0x20 0x20 0 0 0 0 0 0
|
||||
syscon af AF_RXRPC 33 33 0 0 0 0 0 0
|
||||
syscon af AF_ISDN 34 34 28 28 26 26 26 0
|
||||
syscon af AF_PHONET 35 35 0 0 0 0 0 0
|
||||
syscon af AF_IEEE802154 36 36 0 0 0 0 0 0
|
||||
syscon af AF_CAIF 37 37 0 0 0 0 0 0
|
||||
syscon af AF_ALG 38 38 0 0 0 0 0 0
|
||||
syscon af AF_NFC 39 39 0 0 0 0 0 0
|
||||
syscon af AF_VSOCK 40 40 0 0 0 0 0 0
|
||||
syscon af AF_KCM 41 41 0 0 0 0 0 0
|
||||
syscon af AF_FILE 1 1 -1 -1 -1 -1 -1 -1
|
||||
syscon af AF_AX25 3 3 -1 -1 -1 -1 -1 -1
|
||||
syscon af AF_NETROM 6 6 -1 -1 -1 -1 -1 -1
|
||||
syscon af AF_BRIDGE 7 7 -1 -1 -1 -1 -1 -1
|
||||
syscon af AF_ATMPVC 8 8 -1 -1 -1 -1 -1 -1
|
||||
syscon af AF_X25 9 9 -1 -1 -1 -1 -1 -1
|
||||
syscon af AF_ROSE 11 11 -1 -1 -1 -1 -1 -1
|
||||
syscon af AF_NETBEUI 13 13 -1 -1 -1 -1 -1 -1
|
||||
syscon af AF_SECURITY 14 14 -1 -1 -1 -1 -1 -1
|
||||
syscon af AF_KEY 15 15 -1 -1 -1 30 -1 -1
|
||||
syscon af AF_NETLINK 16 16 -1 -1 -1 -1 -1 -1
|
||||
syscon af AF_PACKET 17 17 -1 -1 -1 -1 -1 -1
|
||||
syscon af AF_ASH 18 18 -1 -1 -1 -1 -1 -1
|
||||
syscon af AF_ECONET 19 19 -1 -1 -1 -1 -1 -1
|
||||
syscon af AF_ATMSVC 20 20 -1 -1 -1 -1 -1 -1
|
||||
syscon af AF_RDS 21 21 -1 -1 -1 -1 -1 -1
|
||||
syscon af AF_IRDA 23 23 -1 -1 -1 -1 -1 -1
|
||||
syscon af AF_PPPOX 24 24 -1 -1 -1 -1 -1 -1
|
||||
syscon af AF_WANPIPE 25 25 -1 -1 -1 -1 -1 -1
|
||||
syscon af AF_LLC 26 26 -1 -1 -1 -1 -1 -1
|
||||
syscon af AF_IB 27 27 -1 -1 -1 -1 -1 -1
|
||||
syscon af AF_MPLS 28 28 -1 -1 -1 33 33 -1
|
||||
syscon af AF_CAN 29 29 -1 -1 -1 -1 35 -1
|
||||
syscon af AF_TIPC 30 30 -1 -1 -1 -1 -1 -1
|
||||
syscon af AF_BLUETOOTH 31 31 -1 -1 36 0x20 31 -1
|
||||
syscon af AF_IUCV 0x20 0x20 -1 -1 -1 -1 -1 -1
|
||||
syscon af AF_RXRPC 33 33 -1 -1 -1 -1 -1 -1
|
||||
syscon af AF_ISDN 34 34 28 28 26 26 26 -1
|
||||
syscon af AF_PHONET 35 35 -1 -1 -1 -1 -1 -1
|
||||
syscon af AF_IEEE802154 36 36 -1 -1 -1 -1 -1 -1
|
||||
syscon af AF_CAIF 37 37 -1 -1 -1 -1 -1 -1
|
||||
syscon af AF_ALG 38 38 -1 -1 -1 -1 -1 -1
|
||||
syscon af AF_NFC 39 39 -1 -1 -1 -1 -1 -1
|
||||
syscon af AF_VSOCK 40 40 -1 -1 -1 -1 -1 -1
|
||||
syscon af AF_KCM 41 41 -1 -1 -1 -1 -1 -1
|
||||
syscon af AF_MAX 42 42 40 40 42 36 37 35
|
||||
|
||||
syscon pf PF_UNIX 1 1 1 1 1 1 1 1 # consensus
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon alg,ALG_SET_AEAD_ASSOCLEN,4,4,0,0,0,0,0,0
|
|
@ -1,2 +0,0 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon alg,ALG_SET_AEAD_AUTHSIZE,5,5,0,0,0,0,0,0
|
|
@ -1,2 +0,0 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon alg,ALG_SET_DRBG_ENTROPY,6,6,0,0,0,0,0,0
|
|
@ -1,2 +0,0 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon alg,ALG_SET_IV,2,2,0,0,0,0,0,0
|
|
@ -1,2 +0,0 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon alg,ALG_SET_KEY,1,1,0,0,0,0,0,0
|
|
@ -1,2 +0,0 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon alg,ALG_SET_OP,3,3,0,0,0,0,0,0
|
|
@ -1,2 +0,0 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon epoll,EPOLLERR,8,8,8,8,8,8,8,8
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue