Make improvements

- You can now run `make -j8 toolchain` on Windows
- You can now run `make -j` on MacOS ARM64 and BSD OSes
- You can now use our Emacs dev environment on MacOS/Windows
- Fix bug where the x16 register was being corrupted by --ftrace
- The programs under build/bootstrap/ are updated as fat binaries
- The Makefile now explains how to download cosmocc-0.0.12 toolchain
- The build scripts under bin/ now support "cosmo" branded toolchains
- stat() now goes faster on Windows (shaves 100ms off `make` latency)
- Code cleanup and added review on the Windows signal checking code
- posix_spawnattr_setrlimit() now works around MacOS ARM64 bugs
- Landlock Make now favors posix_spawn() on non-Linux/OpenBSD
- posix_spawn() now has better --strace logging on Windows
- fstatat() can now avoid EACCES in more cases on Windows
- fchmod() can now change the readonly bit on Windows
This commit is contained in:
Justine Tunney 2023-10-14 20:57:15 -07:00
parent 06c6baaf50
commit c9fecf3a55
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
109 changed files with 1188 additions and 454 deletions

View file

@ -18,6 +18,7 @@
*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/sigset.internal.h"
#include "libc/errno.h"
#include "libc/fmt/itoa.h"
#include "libc/intrin/describebacktrace.internal.h"
@ -28,9 +29,11 @@
*/
void __assert_fail(const char *expr, const char *file, int line) {
char ibuf[12];
sigset_t m = __sig_block();
FormatInt32(ibuf, line);
tinyprint(2, file, ":", ibuf, ": assert(", expr, ") failed (",
program_invocation_short_name, " ",
DescribeBacktrace(__builtin_frame_address(0)), ")\n", NULL);
__sig_unblock(m);
abort();
}

View file

@ -1,6 +1,5 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_BLOCKCANCEL_H_
#define COSMOPOLITAN_LIBC_CALLS_BLOCKCANCEL_H_
#include "libc/thread/thread.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_

View file

@ -18,6 +18,7 @@
*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/createfileflags.internal.h"
#include "libc/nt/createfile.h"
#include "libc/nt/enum/accessmask.h"
#include "libc/nt/enum/creationdisposition.h"
@ -26,23 +27,6 @@
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h"
// code size optimization
// <sync libc/sysv/consts.sh>
#define _O_APPEND 0x00000400 // kNtFileAppendData
#define _O_CREAT 0x00000040 // kNtOpenAlways
#define _O_EXCL 0x00000080 // kNtCreateNew
#define _O_TRUNC 0x00000200 // kNtCreateAlways
#define _O_DIRECTORY 0x00010000 // kNtFileFlagBackupSemantics
#define _O_UNLINK 0x04000100 // kNtFileAttributeTemporary|DeleteOnClose
#define _O_DIRECT 0x00004000 // kNtFileFlagNoBuffering
#define _O_NONBLOCK 0x00000800 // kNtFileFlagWriteThrough (not sent to win32)
#define _O_RANDOM 0x80000000 // kNtFileFlagRandomAccess
#define _O_SEQUENTIAL 0x40000000 // kNtFileFlagSequentialScan
#define _O_COMPRESSED 0x20000000 // kNtFileAttributeCompressed
#define _O_INDEXED 0x10000000 // !kNtFileAttributeNotContentIndexed
#define _O_CLOEXEC 0x00080000
// </sync libc/sysv/consts.sh>
textwindows int GetNtOpenFlags(int flags, int mode, uint32_t *out_perm,
uint32_t *out_share, uint32_t *out_disp,
uint32_t *out_attr) {

View file

@ -0,0 +1,22 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_CREATEFILEFLAGS_INTERNAL_H_
#define COSMOPOLITAN_LIBC_CALLS_CREATEFILEFLAGS_INTERNAL_H_
// code size optimization
// <sync libc/sysv/consts.sh>
#define _O_APPEND 0x00000400 // kNtFileAppendData
#define _O_CREAT 0x00000040 // kNtOpenAlways
#define _O_EXCL 0x00000080 // kNtCreateNew
#define _O_TRUNC 0x00000200 // kNtCreateAlways
#define _O_DIRECTORY 0x00010000 // kNtFileFlagBackupSemantics
#define _O_UNLINK 0x04000100 // kNtFileAttributeTemporary|DeleteOnClose
#define _O_DIRECT 0x00004000 // kNtFileFlagNoBuffering
#define _O_NONBLOCK 0x00000800 // kNtFileFlagWriteThrough (not sent to win32)
#define _O_RANDOM 0x80000000 // kNtFileFlagRandomAccess
#define _O_SEQUENTIAL 0x40000000 // kNtFileFlagSequentialScan
#define _O_COMPRESSED 0x20000000 // kNtFileAttributeCompressed
#define _O_INDEXED 0x10000000 // !kNtFileAttributeNotContentIndexed
#define _O_NOFOLLOW 0x00020000 // kNtFileFlagOpenReparsePoint
#define _O_CLOEXEC 0x00080000
// </sync libc/sysv/consts.sh>
#endif /* COSMOPOLITAN_LIBC_CALLS_CREATEFILEFLAGS_INTERNAL_H_ */

View file

@ -18,6 +18,7 @@
*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/createfileflags.internal.h"
#include "libc/calls/internal.h"
#include "libc/calls/state.internal.h"
#include "libc/calls/struct/sigset.internal.h"
@ -65,10 +66,10 @@ static textwindows int sys_dup_nt_impl(int oldfd, int newfd, int flags,
kNtDuplicateSameAccess)) {
g_fds.p[newfd] = g_fds.p[oldfd];
g_fds.p[newfd].handle = handle;
if (flags & O_CLOEXEC) {
g_fds.p[newfd].flags |= O_CLOEXEC;
if (flags & _O_CLOEXEC) {
g_fds.p[newfd].flags |= _O_CLOEXEC;
} else {
g_fds.p[newfd].flags &= ~O_CLOEXEC;
g_fds.p[newfd].flags &= ~_O_CLOEXEC;
}
rc = newfd;
} else {

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/createfileflags.internal.h"
#include "libc/calls/internal.h"
#include "libc/calls/sig.internal.h"
#include "libc/calls/state.internal.h"
@ -41,17 +42,17 @@ static textwindows int sys_fadvise_nt_impl(int fd, uint64_t offset,
h1 = g_fds.p[fd].handle;
mode = g_fds.p[fd].mode;
flags = g_fds.p[fd].flags;
flags &= ~(O_SEQUENTIAL | O_RANDOM);
flags &= ~(_O_SEQUENTIAL | _O_RANDOM);
switch (advice) {
case MADV_NORMAL:
break;
case MADV_RANDOM:
flags |= O_RANDOM;
flags |= _O_RANDOM;
break;
case MADV_WILLNEED:
case MADV_SEQUENTIAL:
flags |= O_SEQUENTIAL;
flags |= _O_SEQUENTIAL;
break;
default:
return einval();

57
libc/calls/fchmod-nt.c Normal file
View file

@ -0,0 +1,57 @@
/*-*- 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 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
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/calls/struct/fd.internal.h"
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/nt/enum/fileflagandattributes.h"
#include "libc/nt/enum/fileinfobyhandleclass.h"
#include "libc/nt/files.h"
#include "libc/nt/struct/filebasicinfo.h"
#include "libc/sysv/errfuns.h"
textwindows int sys_fchmod_nt(int fd, uint32_t mode) {
// validate file descriptor
if (fd + 0u >= g_fds.n) return ebadf();
if (g_fds.p[fd].kind == kFdEmpty) return ebadf();
// get current information
struct NtFileBasicInfo fbi;
if (!GetFileInformationByHandleEx(g_fds.p[fd].handle, kNtFileBasicInfo, &fbi,
sizeof(fbi))) {
return __winerr();
}
// change attributes
if (mode & 0222) {
fbi.FileAttributes &= ~kNtFileAttributeReadonly;
} else {
fbi.FileAttributes |= kNtFileAttributeReadonly;
}
// set new attributes
if (!SetFileInformationByHandle(g_fds.p[fd].handle, kNtFileBasicInfo, &fbi,
sizeof(fbi))) {
return __winerr();
}
// all good
return 0;
}

View file

@ -17,18 +17,32 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/strace.internal.h"
#include "libc/sysv/errfuns.h"
/**
* Changes file permissions via open()'d file descriptor.
*
* @param mode contains octal flags (base 8)
* @raise EROFS if `fd` is a `/zip/...` file
* @asyncsignalsafe
* @see chmod()
*/
int fchmod(int fd, uint32_t mode) {
// TODO(jart): Windows
return sys_fchmod(fd, mode);
int rc;
if (__isfdkind(fd, kFdZip)) {
rc = erofs();
} else if (IsLinux() || IsXnu() || IsFreebsd() || IsOpenbsd() || IsNetbsd()) {
rc = sys_fchmod(fd, mode);
} else if (IsWindows()) {
rc = sys_fchmod_nt(fd, mode);
} else {
rc = enosys();
}
STRACE("fchmod(%d, %#o) → %d% m", fd, mode, rc);
return rc;
}

View file

@ -18,6 +18,7 @@
*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/createfileflags.internal.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/fd.internal.h"
#include "libc/calls/struct/flock.h"
@ -318,7 +319,7 @@ static textwindows int sys_fcntl_nt_lock(struct Fd *f, int fd, int cmd,
static textwindows int sys_fcntl_nt_dupfd(int fd, int cmd, int start) {
if (start < 0) return einval();
return sys_dup_nt(fd, -1, (cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0), start);
return sys_dup_nt(fd, -1, (cmd == F_DUPFD_CLOEXEC ? _O_CLOEXEC : 0), start);
}
textwindows int sys_fcntl_nt(int fd, int cmd, uintptr_t arg) {
@ -329,21 +330,21 @@ textwindows int sys_fcntl_nt(int fd, int cmd, uintptr_t arg) {
__isfdkind(fd, kFdConsole) || //
__isfdkind(fd, kFdDevNull)) {
if (cmd == F_GETFL) {
rc = g_fds.p[fd].flags & (O_ACCMODE | O_APPEND | O_DIRECT | O_NONBLOCK |
O_RANDOM | O_SEQUENTIAL);
rc = g_fds.p[fd].flags & (O_ACCMODE | _O_APPEND | _O_DIRECT |
_O_NONBLOCK | _O_RANDOM | _O_SEQUENTIAL);
} else if (cmd == F_SETFL) {
rc = sys_fcntl_nt_setfl(fd, arg);
} else if (cmd == F_GETFD) {
if (g_fds.p[fd].flags & O_CLOEXEC) {
if (g_fds.p[fd].flags & _O_CLOEXEC) {
rc = FD_CLOEXEC;
} else {
rc = 0;
}
} else if (cmd == F_SETFD) {
if (arg & FD_CLOEXEC) {
g_fds.p[fd].flags |= O_CLOEXEC;
g_fds.p[fd].flags |= _O_CLOEXEC;
} else {
g_fds.p[fd].flags &= ~O_CLOEXEC;
g_fds.p[fd].flags &= ~_O_CLOEXEC;
}
rc = 0;
} else if (cmd == F_SETLK || cmd == F_SETLKW || cmd == F_GETLK) {

View file

@ -36,9 +36,8 @@ textwindows int sys_fdatasync_nt(int fd, bool fake) {
// kNtGenericWrite access, and MSDN doesn't document it.
return 0;
}
if (_check_cancel() == -1) return -1;
if (_check_signal(false) == -1) return -1;
if (fake) return 0;
if (_check_signal(false) == -1) return -1;
return FlushFileBuffers(g_fds.p[fd].handle) ? 0 : __winerr();
}

View file

@ -107,11 +107,12 @@ textwindows int sys_fstat_nt(int fd, struct stat *st) {
case kFdSocket:
return sys_fstat_nt_socket(g_fds.p[fd].kind, st);
default:
return sys_fstat_nt_handle(g_fds.p[fd].handle, st);
return sys_fstat_nt_handle(g_fds.p[fd].handle, 0, st);
}
}
textwindows int sys_fstat_nt_handle(int64_t handle, struct stat *out_st) {
textwindows int sys_fstat_nt_handle(int64_t handle, const char16_t *path,
struct stat *out_st) {
struct stat st = {0};
// Always set st_blksize to avoid divide by zero issues.
@ -143,7 +144,7 @@ textwindows int sys_fstat_nt_handle(int64_t handle, struct stat *out_st) {
}
st.st_mode = 0444 & ~umask;
if ((wst.dwFileAttributes & kNtFileAttributeDirectory) ||
IsWindowsExecutable(handle)) {
IsWindowsExecutable(handle, path)) {
st.st_mode |= 0111 & ~umask;
}
st.st_flags = wst.dwFileAttributes;

View file

@ -74,10 +74,11 @@ TryAgain:
((flags & AT_SYMLINK_NOFOLLOW) ? kNtFileFlagOpenReparsePoint
: 0),
0)) != -1) {
rc = st ? sys_fstat_nt_handle(fh, st) : 0;
rc = st ? sys_fstat_nt_handle(fh, path16, st) : 0;
CloseHandle(fh);
} else if (dwDesiredAccess == kNtFileGenericRead &&
GetLastError() == kNtErrorSharingViolation) {
(GetLastError() == kNtErrorAccessDenied ||
GetLastError() == kNtErrorSharingViolation)) {
dwDesiredAccess = kNtFileReadAttributes;
errno = e;
goto TryAgain;

View file

@ -0,0 +1,94 @@
/*-*- 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 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
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/asmflag.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/sysv/consts/grnd.h"
#include "libc/sysv/errfuns.h"
#ifdef __x86_64__
static bool GetRandomRdseed(uint64_t *out) {
int i;
char cf;
uint64_t x;
for (i = 0; i < 10; ++i) {
asm volatile(CFLAG_ASM("rdseed\t%1")
: CFLAG_CONSTRAINT(cf), "=r"(x)
: /* no inputs */
: "cc");
if (cf) {
*out = x;
return true;
}
asm volatile("pause");
}
return false;
}
static bool GetRandomRdrand(uint64_t *out) {
int i;
char cf;
uint64_t x;
for (i = 0; i < 10; ++i) {
asm volatile(CFLAG_ASM("rdrand\t%1")
: CFLAG_CONSTRAINT(cf), "=r"(x)
: /* no inputs */
: "cc");
if (cf) {
*out = x;
return true;
}
asm volatile("pause");
}
return false;
}
static ssize_t GetRandomCpu(char *p, size_t n, int f, bool impl(uint64_t *)) {
uint64_t x;
size_t i, j;
for (i = 0; i < n; i += j) {
TryAgain:
if (!impl(&x)) {
if (f || i >= 256) break;
goto TryAgain;
}
for (j = 0; j < 8 && i + j < n; ++j) {
p[i + j] = x;
x >>= 8;
}
}
return n;
}
ssize_t sys_getrandom_metal(char *p, size_t n, int f) {
if (f & GRND_RANDOM) {
if (X86_HAVE(RDSEED)) {
return GetRandomCpu(p, n, f, GetRandomRdseed);
} else {
return enosys();
}
} else {
if (X86_HAVE(RDRND)) {
return GetRandomCpu(p, n, f, GetRandomRdrand);
} else {
return enosys();
}
}
}
#endif /* __x86_64__ */

View file

@ -55,78 +55,10 @@
__static_yoink("rdrand_init");
int sys_getentropy(void *, size_t) asm("sys_getrandom");
ssize_t sys_getrandom_metal(char *, size_t, int);
static bool have_getrandom;
static bool GetRandomRdseed(uint64_t *out) {
int i;
char cf;
uint64_t x;
for (i = 0; i < 10; ++i) {
asm volatile(CFLAG_ASM("rdseed\t%1")
: CFLAG_CONSTRAINT(cf), "=r"(x)
: /* no inputs */
: "cc");
if (cf) {
*out = x;
return true;
}
asm volatile("pause");
}
return false;
}
static bool GetRandomRdrand(uint64_t *out) {
int i;
char cf;
uint64_t x;
for (i = 0; i < 10; ++i) {
asm volatile(CFLAG_ASM("rdrand\t%1")
: CFLAG_CONSTRAINT(cf), "=r"(x)
: /* no inputs */
: "cc");
if (cf) {
*out = x;
return true;
}
asm volatile("pause");
}
return false;
}
static ssize_t GetRandomCpu(char *p, size_t n, int f, bool impl(uint64_t *)) {
uint64_t x;
size_t i, j;
for (i = 0; i < n; i += j) {
TryAgain:
if (!impl(&x)) {
if (f || i >= 256) break;
goto TryAgain;
}
for (j = 0; j < 8 && i + j < n; ++j) {
p[i + j] = x;
x >>= 8;
}
}
return n;
}
static ssize_t GetRandomMetal(char *p, size_t n, int f) {
if (f & GRND_RANDOM) {
if (X86_HAVE(RDSEED)) {
return GetRandomCpu(p, n, f, GetRandomRdseed);
} else {
return enosys();
}
} else {
if (X86_HAVE(RDRND)) {
return GetRandomCpu(p, n, f, GetRandomRdrand);
} else {
return enosys();
}
}
}
static void GetRandomEntropy(char *p, size_t n) {
unassert(n <= 256);
if (sys_getentropy(p, n)) notpossible;
@ -181,8 +113,10 @@ ssize_t __getrandom(void *p, size_t n, unsigned f) {
}
} else if (IsFreebsd() || IsNetbsd()) {
rc = GetRandomBsd(p, n, GetRandomArnd);
#ifdef __x86_64__
} else if (IsMetal()) {
rc = GetRandomMetal(p, n, f);
rc = sys_getrandom_metal(p, n, f);
#endif
} else {
BEGIN_CANCELATION_POINT;
rc = GetDevUrandom(p, n);

View file

@ -24,11 +24,11 @@ int __ensurefds(int);
uint32_t sys_getuid_nt(void);
int __ensurefds_unlocked(int);
void __printfds(struct Fd *, size_t);
int IsWindowsExecutable(int64_t);
int CountConsoleInputBytes(void);
int FlushConsoleInputBytes(void);
int64_t GetConsoleInputHandle(void);
int64_t GetConsoleOutputHandle(void);
int IsWindowsExecutable(int64_t, const char16_t *);
void InterceptTerminalCommands(const char *, size_t);
forceinline int64_t __getfdhandleactual(int fd) {

View file

@ -36,8 +36,10 @@ textwindows int _check_cancel(void) {
textwindows int _check_signal(bool restartable) {
int status;
if (_check_cancel() == -1) return -1;
if (!_weaken(__sig_check)) return 0;
if (!(status = _weaken(__sig_check)())) return 0;
if (_check_cancel() == -1) return -1;
if (status == 2 && restartable) return 0;
return eintr();
}

View file

@ -115,6 +115,7 @@ static int ioctl_fionread(int fd, uint32_t *arg) {
*arg = avail;
return 0;
} else if (GetLastError() == kNtErrorBrokenPipe) {
*arg = 0; // win32 can give epipe on reader end
return 0;
} else {
return __winerr();

View file

@ -108,7 +108,7 @@ textwindows int ntaccesscheck(const char16_t *pathname, uint32_t flags) {
0)) != -1) {
unassert(GetFileInformationByHandle(hFile, &wst));
if ((wst.dwFileAttributes & kNtFileAttributeDirectory) ||
IsWindowsExecutable(hFile)) {
IsWindowsExecutable(hFile, pathname)) {
rc = 0;
} else {
rc = eacces();

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/calls/createfileflags.internal.h"
#include "libc/calls/internal.h"
#include "libc/calls/state.internal.h"
#include "libc/calls/struct/sigset.internal.h"
@ -56,31 +57,31 @@ static textwindows int64_t sys_open_nt_impl(int dirfd, const char *path,
// implement no follow flag
// you can't open symlinks; use readlink
// this flag only applies to the final path component
// if O_NOFOLLOW_ANY is passed (-1 on NT) it'll be rejected later
// if _O_NOFOLLOW_ANY is passed (-1 on NT) it'll be rejected later
uint32_t fattr = GetFileAttributes(path16);
if (flags & O_NOFOLLOW) {
if (flags & _O_NOFOLLOW) {
if (fattr != -1u && (fattr & kNtFileAttributeReparsePoint)) {
return eloop();
}
flags &= ~O_NOFOLLOW; // don't actually pass this to win32
flags &= ~_O_NOFOLLOW; // don't actually pass this to win32
}
// handle some obvious cases while we have the attributes
// we should ideally resolve symlinks ourself before doing this
if (fattr != -1u) {
if (fattr & kNtFileAttributeDirectory) {
if ((flags & O_ACCMODE) != O_RDONLY || (flags & O_CREAT)) {
if ((flags & O_ACCMODE) != O_RDONLY || (flags & _O_CREAT)) {
// tried to open directory for writing. note that our
// undocumented O_TMPFILE support on windows requires that a
// undocumented _O_TMPFILE support on windows requires that a
// filename be passed, rather than a directory like linux.
return eisdir();
}
// on posix, the o_directory flag is an advisory safeguard that
// isn't required. on windows, it's mandatory for opening a dir
flags |= O_DIRECTORY;
flags |= _O_DIRECTORY;
} else if (!(fattr & kNtFileAttributeReparsePoint)) {
// we know for certain file isn't a directory
if (flags & O_DIRECTORY) {
if (flags & _O_DIRECTORY) {
return enotdir();
}
}
@ -186,7 +187,7 @@ textwindows int sys_open_nt(int dirfd, const char *file, uint32_t flags,
ssize_t rc;
BLOCK_SIGNALS;
__fds_lock();
if (!(flags & O_CREAT)) mode = 0;
if (!(flags & _O_CREAT)) mode = 0;
if ((rc = fd = __reservefd_unlocked(-1)) != -1) {
if (startswith(file, "/dev/")) {
if (!strcmp(file + 5, "tty")) {

View file

@ -20,6 +20,7 @@
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/sigset.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/errno.h"
#include "libc/intrin/atomic.h"
#include "libc/nt/enum/wait.h"
@ -45,11 +46,13 @@ static textwindows int _park_thread(uint32_t msdelay, sigset_t waitmask,
pthread_cleanup_push((void *)CloseHandle, (void *)sem);
atomic_store_explicit(&pt->pt_blocker, PT_BLOCKER_SEM, memory_order_release);
om = __sig_beginwait(waitmask);
if ((rc = _check_cancel()) != -1 && (rc = _check_signal(restartable)) != -1) {
unassert((wi = WaitForSingleObject(sem, msdelay)) != -1u);
if (restartable && !(pt->pt_flags & PT_RESTARTABLE)) rc = eintr();
rc |= _check_signal(restartable);
if (rc == -1 && errno == EINTR) _check_cancel();
if ((rc = _check_signal(restartable)) != -1) {
if ((wi = WaitForSingleObject(sem, msdelay)) != -1u) {
if (restartable && !(pt->pt_flags & PT_RESTARTABLE)) rc = eintr();
rc |= _check_signal(restartable);
} else {
rc = __winerr();
}
}
__sig_finishwait(om);
atomic_store_explicit(&pt->pt_blocker, PT_BLOCKER_CPU, memory_order_release);

View file

@ -18,6 +18,7 @@
*/
#include "libc/assert.h"
#include "libc/atomic.h"
#include "libc/calls/createfileflags.internal.h"
#include "libc/calls/internal.h"
#include "libc/calls/sig.internal.h"
#include "libc/calls/state.internal.h"
@ -729,7 +730,7 @@ static textwindows int WaitForConsole(struct Fd *f, sigset_t waitmask) {
ms = __ttyconf.vtime * 100;
}
}
if (f->flags & O_NONBLOCK) {
if (f->flags & _O_NONBLOCK) {
return eagain(); // standard unix non-blocking
}
pt = _pthread_self();
@ -738,12 +739,14 @@ static textwindows int WaitForConsole(struct Fd *f, sigset_t waitmask) {
pthread_cleanup_push((void *)CloseHandle, (void *)sem);
atomic_store_explicit(&pt->pt_blocker, PT_BLOCKER_SEM, memory_order_release);
m = __sig_beginwait(waitmask);
if ((rc = _check_cancel()) != -1 && (rc = _check_signal(true)) != -1) {
if ((rc = _check_signal(true)) != -1) {
int64_t hands[2] = {sem, __keystroke.cin};
unassert(WaitForMultipleObjects(2, hands, 0, ms) != -1u);
if (~pt->pt_flags & PT_RESTARTABLE) rc = eintr();
rc |= _check_signal(true);
if (rc == -1 && errno == EINTR) _check_cancel();
if (WaitForMultipleObjects(2, hands, 0, ms) != -1u) {
if (!(pt->pt_flags & PT_RESTARTABLE)) rc = eintr();
rc |= _check_signal(true);
} else {
rc = __winerr();
}
}
__sig_finishwait(m);
atomic_store_explicit(&pt->pt_blocker, PT_BLOCKER_CPU, memory_order_release);

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/createfileflags.internal.h"
#include "libc/calls/internal.h"
#include "libc/calls/sig.internal.h"
#include "libc/calls/struct/fd.internal.h"
@ -140,15 +141,16 @@ sys_readwrite_nt(int fd, void *data, size_t size, ssize_t offset,
pt->pt_flags |= PT_RESTARTABLE;
atomic_store_explicit(&pt->pt_blocker, PT_BLOCKER_IO, memory_order_release);
m = __sig_beginwait(waitmask);
if (f->flags & O_NONBLOCK) {
if (f->flags & _O_NONBLOCK) {
CancelIoEx(handle, &overlap);
eagained = true;
} else if (_check_cancel()) {
CancelIoEx(handle, &overlap);
canceled = true;
} else if (_check_signal(true)) {
CancelIoEx(handle, &overlap);
eintered = true;
if (errno == ECANCELED) {
canceled = true;
} else {
eintered = true;
}
} else {
WaitForSingleObject(overlap.hEvent, -1u);
}
@ -197,7 +199,7 @@ sys_readwrite_nt(int fd, void *data, size_t size, ssize_t offset,
// it's also fine to do nothing here; punt to next cancelation point
if (GetLastError() == kNtErrorOperationAborted) {
if (_check_cancel() == -1) return ecanceled();
if (!eintered && _check_signal(false)) return eintr();
if (!eintered && _check_signal(false)) return -1;
}
// if we chose to process a pending signal earlier then we preserve

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/createfileflags.internal.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/fd.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
@ -36,8 +37,9 @@ textwindows int sys_fcntl_nt_setfl(int fd, unsigned flags) {
// - O_DIRECT works but haven't tested
//
// the other bits are ignored.
unsigned allowed = O_APPEND | O_SEQUENTIAL | O_RANDOM | O_DIRECT | O_NONBLOCK;
unsigned needreo = O_APPEND | O_SEQUENTIAL | O_RANDOM | O_DIRECT;
unsigned allowed =
_O_APPEND | _O_SEQUENTIAL | _O_RANDOM | _O_DIRECT | _O_NONBLOCK;
unsigned needreo = _O_APPEND | _O_SEQUENTIAL | _O_RANDOM | _O_DIRECT;
unsigned newflag = (g_fds.p[fd].flags & ~allowed) | (flags & allowed);
if (g_fds.p[fd].kind == kFdFile &&

View file

@ -33,9 +33,7 @@
#include "libc/fmt/itoa.h"
#include "libc/intrin/atomic.h"
#include "libc/intrin/bsf.h"
#include "libc/intrin/bsr.h"
#include "libc/intrin/describebacktrace.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/popcnt.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
@ -105,7 +103,7 @@ static textwindows int __sig_getter(struct CosmoTib *tib, atomic_ulong *sigs) {
pending = atomic_load_explicit(sigs, memory_order_acquire);
masked = atomic_load_explicit(&tib->tib_sigmask, memory_order_acquire);
if ((deliverable = pending & ~masked)) {
sig = _bsf(deliverable) + 1;
sig = _bsfl(deliverable) + 1;
bit = 1ull << (sig - 1);
if (atomic_fetch_and_explicit(sigs, ~bit, memory_order_acq_rel) & bit) {
return sig;
@ -263,7 +261,7 @@ textwindows void __sig_cancel(struct PosixThread *pt, int sig, unsigned flags) {
WakeByAddressSingle(blocker);
}
// the user's signal handler callback is composed with this trampoline
// the user's signal handler callback is wrapped with this trampoline
static textwindows wontreturn void __sig_tramp(struct SignalFrame *sf) {
int sig = sf->si.si_signo;
struct CosmoTib *tib = __get_tls();

View file

@ -9,7 +9,7 @@ int sys_fstat(int, struct stat *);
int sys_fstatat(int, const char *, struct stat *, int);
int sys_fstat_nt(int, struct stat *);
int sys_fstat_nt_special(int, struct stat *);
int sys_fstat_nt_handle(int64_t, struct stat *);
int sys_fstat_nt_handle(int64_t, const char16_t *, struct stat *);
int sys_fstatat_nt(int, const char *, struct stat *, int);
int sys_lstat_nt(const char *, struct stat *);
int sys_fstat_metal(int, struct stat *);

View file

@ -1,7 +1,7 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_UTSNAME_H_
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_UTSNAME_H_
#define SYS_NMLN 321
#define SYS_NMLN 150
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_

View file

@ -12,6 +12,7 @@ int sys_execve_nt(const char *, char *const[], char *const[]);
int sys_faccessat_nt(int, const char *, int, uint32_t);
int sys_fadvise_nt(int, uint64_t, uint64_t, int);
int sys_fchdir_nt(int);
int sys_fchmod_nt(int, uint32_t);
int sys_fchmodat_nt(int, const char *, uint32_t, int);
int sys_fcntl_nt(int, int, uintptr_t);
int sys_fdatasync_nt(int, bool);

View file

@ -91,7 +91,12 @@ errno_t ttyname_r(int fd, char *buf, size_t size) {
} else if (IsWindows()) {
res = sys_ttyname_nt(fd, buf, size);
} else {
res = ENOSYS;
// TODO(jart): Use that fstat(dev/ino) + readdir(/dev/) trick.
if (strlcpy(buf, "/dev/tty", size) < size) {
res = 0;
} else {
res = ERANGE;
}
}
errno = e;
STRACE("ttyname_r(%d, %#.*hhs) → %s", fd, (int)size, buf,

View file

@ -18,14 +18,57 @@
*/
#include "libc/calls/internal.h"
#include "libc/calls/struct/sigset.internal.h"
#include "libc/intrin/bits.h"
#include "libc/nt/errors.h"
#include "libc/nt/events.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/overlapped.h"
#include "libc/str/str.h"
#include "libc/str/tab.internal.h"
#include "third_party/linenoise/linenoise.h"
#define EXT(s) READ32LE(s "\0\0")
static bool IsGraph(wint_t c) {
return 0x21 <= c && c <= 0x7E;
}
static uint32_t GetFileExtension(const char16_t *s) {
uint32_t w;
size_t i, n;
n = s ? strlen16(s) : 0;
for (i = w = 0; n--;) {
wint_t c = s[n];
if (!IsGraph(c)) return 0;
if (c == '.') break;
if (++i > 4) return 0;
w <<= 8;
w |= kToLower[c];
}
return w;
}
// checks if file should be considered an executable on windows
textwindows int IsWindowsExecutable(int64_t handle) {
textwindows int IsWindowsExecutable(int64_t handle, const char16_t *path) {
// fast path known file extensions
// shaves away 100ms of gnu make latency in cosmo monorepo
uint32_t ext;
if (!IsTiny() && (ext = GetFileExtension(path))) {
if (ext == EXT("c") || // c code
ext == EXT("cc") || // c++ code
ext == EXT("h") || // c/c++ header
ext == EXT("s") || // assembly code
ext == EXT("o")) { // object file
return false;
}
if (ext == EXT("com") || // mz executable
ext == EXT("exe") || // mz executable
ext == EXT("sh")) { // bourne shells
return true;
}
}
// read first two bytes of file
// access() and stat() aren't cancelation points

View file

@ -146,7 +146,6 @@ typedef struct {
} axdx_t;
#endif
#ifndef __chibicc__
#define va_list __builtin_va_list
#define va_arg(ap, type) __builtin_va_arg(ap, type)
@ -620,12 +619,6 @@ void abort(void) wontreturn;
do { \
} while (0)
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
#define _Vector_size(k) __attribute__((__vector_size__(k)))
#else
#define _Vector_size(k) [k]
#endif
#ifndef __STRICT_ANSI__
#define textstartup _Section(".text.startup")
#define textexit _Section(".text.exit")

View file

@ -48,10 +48,25 @@ CreateFile(const char16_t *lpFileName, //
int64_t opt_hTemplateFile) {
int64_t hHandle;
uint32_t micros = 1;
char buf_accessflags[512];
(void)buf_accessflags;
char buf_shareflags[64];
(void)buf_shareflags;
char buf_secattr[32];
(void)buf_secattr;
char buf_flagattr[256];
(void)buf_flagattr;
TryAgain:
hHandle = __imp_CreateFileW(lpFileName, dwDesiredAccess, dwShareMode,
opt_lpSecurity, dwCreationDisposition,
dwFlagsAndAttributes, opt_hTemplateFile);
NTTRACE("CreateFile(%#hs, %s, %s, %s, %s, %s, %ld) → {%ld, %d}", lpFileName,
(DescribeNtFileAccessFlags)(buf_accessflags, dwDesiredAccess),
(DescribeNtFileShareFlags)(buf_shareflags, dwShareMode),
(DescribeNtSecurityAttributes)(buf_secattr, opt_lpSecurity),
DescribeNtCreationDisposition(dwCreationDisposition),
(DescribeNtFileFlagAttr)(buf_flagattr, dwFlagsAndAttributes),
opt_hTemplateFile, hHandle, __imp_GetLastError());
if (hHandle == -1) {
switch (__imp_GetLastError()) {
case kNtErrorPipeBusy:
@ -77,12 +92,5 @@ TryAgain:
}
__winerr();
}
NTTRACE("CreateFile(%#hs, %s, %s, %s, %s, %s, %ld) → %ld% m", lpFileName,
DescribeNtFileAccessFlags(dwDesiredAccess),
DescribeNtFileShareFlags(dwShareMode),
DescribeNtSecurityAttributes(opt_lpSecurity),
DescribeNtCreationDisposition(dwCreationDisposition),
DescribeNtFileFlagAttr(dwFlagsAndAttributes), opt_hTemplateFile,
hHandle);
return hHandle;
}

View file

@ -19,10 +19,12 @@
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/securityattributes.h"
#include "libc/nt/thread.h"
__msabi extern typeof(CreateThread) *const __imp_CreateThread;
__msabi extern typeof(GetLastError) *const __imp_GetLastError;
/**
* Opens file on the New Technology.
@ -41,9 +43,10 @@ CreateThread(const struct NtSecurityAttributes *lpThreadAttributes,
int64_t hHandle;
hHandle = __imp_CreateThread(lpThreadAttributes, dwStackSize, lpStartAddress,
lpParameter, dwCreationFlags, opt_lpThreadId);
NTTRACE("CreateThread(%s, %'zu, %t, %p, %s, %p) → %ld% m",
NTTRACE("CreateThread(%s, %'zu, %t, %p, %s, %p) → {%ld, %d}",
DescribeNtSecurityAttributes(lpThreadAttributes), dwStackSize,
lpStartAddress, lpParameter,
DescribeThreadCreateFlags(dwCreationFlags), opt_lpThreadId, hHandle);
DescribeThreadCreateFlags(dwCreationFlags), opt_lpThreadId, hHandle,
__imp_GetLastError());
return hHandle;
}

View file

@ -19,8 +19,10 @@
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
__msabi extern typeof(FlushFileBuffers) *const __imp_FlushFileBuffers;
__msabi extern typeof(GetLastError) *const __imp_GetLastError;
/**
* Flushes buffers of specified file to disk.
@ -36,6 +38,7 @@ __msabi extern typeof(FlushFileBuffers) *const __imp_FlushFileBuffers;
textwindows bool32 FlushFileBuffers(int64_t hFile) {
bool32 ok;
ok = __imp_FlushFileBuffers(hFile);
NTTRACE("FlushFileBuffers(%ld) → %hhhd% m", hFile, ok);
NTTRACE("FlushFileBuffers(%ld) → {%hhhd, %d}", hFile, ok,
__imp_GetLastError());
return ok;
}

View file

@ -33,7 +33,11 @@
#define kPid "TracerPid:\t"
static textwindows bool IsBeingDebugged(void) {
#ifdef __x86_64__
return !!NtGetPeb()->BeingDebugged;
#else
return false;
#endif
}
/**

View file

@ -9,7 +9,8 @@
#if defined(__x86_64__) && !defined(__STRICT_ANSI__)
typedef char __intrin_xmm_t _Vector_size(16) forcealign(16) mayalias;
typedef char __intrin_xmm_t
__attribute__((__vector_size__(16), __aligned__(16), __may_alias__));
#define INTRIN_SSEVEX_X_X_X_(PURE, ISA, OP, FLAGS, A, B, C) \
do { \

View file

@ -20,9 +20,11 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/nt/thunk/msabi.h"
__msabi extern typeof(ReOpenFile) *const __imp_ReOpenFile;
__msabi extern typeof(GetLastError) *const __imp_GetLastError;
/**
* Reopens file on the New Technology.
@ -34,9 +36,10 @@ int64_t ReOpenFile(int64_t hOriginalFile, uint32_t dwDesiredAccess,
int64_t hHandle;
hHandle = __imp_ReOpenFile(hOriginalFile, dwDesiredAccess, dwShareMode,
dwFlagsAndAttributes);
NTTRACE("ReOpenFile(%ld, %s, %s, %s) → %ld% m", hOriginalFile,
NTTRACE("ReOpenFile(%ld, %s, %s, %s) → {%ld, %d}", hOriginalFile,
DescribeNtFileAccessFlags(dwDesiredAccess),
DescribeNtFileShareFlags(dwShareMode),
DescribeNtFileFlagAttr(dwFlagsAndAttributes), hHandle);
DescribeNtFileFlagAttr(dwFlagsAndAttributes), hHandle,
__imp_GetLastError());
return hHandle;
}

View file

@ -23,6 +23,7 @@
#include "libc/nt/thunk/msabi.h"
__msabi extern typeof(TerminateProcess) *const __imp_TerminateProcess;
__msabi extern typeof(GetLastError) *const __imp_GetLastError;
/**
* Terminates the specified process and all of its threads.
@ -30,6 +31,7 @@ __msabi extern typeof(TerminateProcess) *const __imp_TerminateProcess;
textwindows bool32 TerminateProcess(int64_t hProcess, uint32_t uWaitStatus) {
bool32 ok;
ok = __imp_TerminateProcess(hProcess, uWaitStatus);
NTTRACE("TerminateProcess(%ld, %u) → %hhhd% m", hProcess, uWaitStatus, ok);
NTTRACE("TerminateProcess(%ld, %u) → {%hhhd, %d}", hProcess, uWaitStatus, ok,
__imp_GetLastError());
return ok;
}

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/nt/runtime.h"
#include "libc/nt/synchronization.h"
#include "libc/nt/thunk/msabi.h"
@ -26,14 +27,15 @@ __msabi extern typeof(WaitForMultipleObjects)
/**
* Waits for handles to change status.
* @note this wrapper takes care of ABI, STRACE(), and __winerr()
*
* @return -1u on error w/ GetLastError()
* @raise kNtErrorInvalidParameter if `bWaitAll` and `lpHandles` has dupes
*/
uint32_t WaitForMultipleObjects(uint32_t nCount, const int64_t *lpHandles,
bool32 bWaitAll, uint32_t dwMilliseconds) {
uint32_t x;
x = __imp_WaitForMultipleObjects(nCount, lpHandles, bWaitAll, dwMilliseconds);
if (x == -1u) __winerr();
POLLTRACE("WaitForMultipleObjects(%ld, %p, %hhhd, %'d) → %d% m", nCount,
lpHandles, bWaitAll, dwMilliseconds, x);
POLLTRACE("WaitForMultipleObjects(%ld, %p, %hhhd, %'d) → %d %d", nCount,
lpHandles, bWaitAll, dwMilliseconds, x, GetLastError());
return x;
}

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/nt/runtime.h"
#include "libc/nt/synchronization.h"
#include "libc/nt/thunk/msabi.h"
@ -30,7 +31,7 @@ __msabi extern typeof(WaitForSingleObject) *const __imp_WaitForSingleObject;
uint32_t WaitForSingleObject(int64_t hHandle, uint32_t dwMilliseconds) {
uint32_t rc;
rc = __imp_WaitForSingleObject(hHandle, dwMilliseconds);
POLLTRACE("WaitForSingleObject(%ld, %'d) → %d% m", hHandle, dwMilliseconds,
rc);
POLLTRACE("WaitForSingleObject(%ld, %'d) → %d %d", hHandle, dwMilliseconds,
rc, GetLastError());
return rc;
}

View file

@ -366,7 +366,7 @@ static relegated void __oncrash_impl(int sig, struct siginfo *si,
free(mem);
}
b->p[b->n - 1] = '\n';
sys_write(2, b->p, MIN(b->i, b->n));
klog(b->p, MIN(b->i, b->n));
}
relegated void __oncrash(int sig, struct siginfo *si, void *arg) {

View file

@ -37,6 +37,7 @@
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/atomic.h"
#include "libc/intrin/bsf.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/dll.h"
#include "libc/intrin/strace.internal.h"
@ -151,10 +152,11 @@ static textwindows bool spawnfds_exists(struct SpawnFds *fds, int fildes) {
return fildes + 0u < fds->n && fds->p[fildes].kind;
}
static textwindows void spawnfds_close(struct SpawnFds *fds, int fildes) {
static textwindows errno_t spawnfds_close(struct SpawnFds *fds, int fildes) {
if (spawnfds_exists(fds, fildes)) {
fds->p[fildes] = (struct Fd){0};
}
return 0;
}
static textwindows errno_t spawnfds_dup2(struct SpawnFds *fds, int fildes,
@ -181,8 +183,8 @@ static textwindows errno_t spawnfds_dup2(struct SpawnFds *fds, int fildes,
}
static textwindows errno_t spawnfds_open(struct SpawnFds *fds, int64_t dirhand,
int fildes, const char *path,
int oflag, int mode) {
const char *path, int oflag, int mode,
int fildes) {
int64_t h;
errno_t err;
char16_t path16[PATH_MAX];
@ -283,42 +285,47 @@ static textwindows errno_t posix_spawn_nt_impl(
// apply user file actions
if (file_actions) {
for (struct _posix_faction *a = *file_actions; a && !err; a = a->next) {
char errno_buf[30];
char oflags_buf[128];
char openmode_buf[15];
(void)errno_buf;
(void)oflags_buf;
(void)openmode_buf;
switch (a->action) {
case _POSIX_SPAWN_CLOSE:
spawnfds_close(&fds, a->fildes);
err = spawnfds_close(&fds, a->fildes);
STRACE("spawnfds_close(%d) → %s", a->fildes,
(DescribeErrno)(errno_buf, err));
break;
case _POSIX_SPAWN_DUP2:
err = spawnfds_dup2(&fds, a->fildes, a->newfildes);
if (err) {
STRACE("spawnfds_dup2(%d, %d) failed", a->fildes, a->newfildes);
goto ReturnErr;
}
STRACE("spawnfds_dup2(%d, %d) → %s", a->fildes, a->newfildes,
(DescribeErrno)(errno_buf, err));
break;
case _POSIX_SPAWN_OPEN:
err = spawnfds_open(&fds, dirhand, a->fildes, a->path, a->oflag,
a->mode);
if (err) {
STRACE("spawnfds_open(%d, %#s) failed", a->fildes, a->path);
goto ReturnErr;
}
err = spawnfds_open(&fds, dirhand, a->path, a->oflag, a->mode,
a->fildes);
STRACE("spawnfds_open(%#s, %s, %s, %d) → %s", a->path,
(DescribeOpenFlags)(oflags_buf, a->oflag),
(DescribeOpenMode)(openmode_buf, a->oflag, a->mode), a->fildes,
(DescribeErrno)(errno_buf, err));
break;
case _POSIX_SPAWN_CHDIR:
err = spawnfds_chdir(&fds, dirhand, a->path, &dirhand);
if (err) {
STRACE("spawnfds_chdir(%#s) failed", a->path);
goto ReturnErr;
}
STRACE("spawnfds_chdir(%#s) → %s", a->path,
(DescribeErrno)(errno_buf, err));
break;
case _POSIX_SPAWN_FCHDIR:
err = spawnfds_fchdir(&fds, a->fildes, &dirhand);
if (err) {
STRACE("spawnfds_fchdir(%d) failed", a->fildes);
goto ReturnErr;
}
STRACE("spawnfds_fchdir(%d) → %s", a->fildes,
(DescribeErrno)(errno_buf, err));
break;
default:
__builtin_unreachable();
}
if (err) {
goto ReturnErr;
}
}
}
@ -572,9 +579,13 @@ errno_t posix_spawn(int *pid, const char *path,
}
}
if (flags & POSIX_SPAWN_SETRLIMIT) {
for (int rez = 0; rez <= ARRAYLEN((*attrp)->rlim); ++rez) {
if ((*attrp)->rlimset & (1u << rez)) {
if (setrlimit(rez, (*attrp)->rlim + rez)) {
int rlimset = (*attrp)->rlimset;
while (rlimset) {
int resource = _bsf(rlimset);
rlimset &= ~(1u << resource);
if (setrlimit(resource, (*attrp)->rlim + resource)) {
// MacOS ARM64 RLIMIT_STACK always returns EINVAL
if (!IsXnuSilicon()) {
goto ChildFailed;
}
}

View file

@ -19,8 +19,8 @@ struct _posix_spawna {
bool schedparam_isset;
bool schedpolicy_isset;
int pgroup;
int rlimset;
int schedpolicy;
int rlimset;
struct sched_param schedparam;
sigset_t sigmask;
sigset_t sigdefault;

View file

@ -32,7 +32,6 @@
int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *file_actions,
int fildes) {
if (fildes < 0) return EBADF;
if (IsWindows() && fildes > 2) return 0;
return __posix_spawn_add_file_action(file_actions,
(struct _posix_faction){
.action = _POSIX_SPAWN_CLOSE,

View file

@ -26,14 +26,12 @@
*
* @param file_actions was initialized by posix_spawn_file_actions_init()
* @return 0 on success, or errno on error
* @raise ENOMEM if we require more vespene gas
* @raise EBADF if 'fildes' or `newfildes` is negative
* @raise ENOTSUP if `newfildes` isn't 0, 1, or 2 on Windows
* @raise ENOMEM if insufficient memory was available
*/
int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *file_actions,
int fildes, int newfildes) {
if (fildes < 0 || newfildes < 0) return EBADF;
if (IsWindows() && newfildes > 2) return ENOTSUP;
return __posix_spawn_add_file_action(file_actions,
(struct _posix_faction){
.action = _POSIX_SPAWN_DUP2,

View file

@ -21,6 +21,8 @@
#include "libc/macros.internal.h"
#include "libc/proc/posix_spawn.h"
#include "libc/proc/posix_spawn.internal.h"
#include "libc/stdio/sysparam.h"
#include "libc/sysv/consts/rlim.h"
/**
* Gets resource limit for spawned process.
@ -31,7 +33,7 @@
*/
int posix_spawnattr_getrlimit(const posix_spawnattr_t *attr, int resource,
struct rlimit *rlim) {
if ((0 <= resource && resource < ARRAYLEN((*attr)->rlim))) {
if (0 <= resource && resource < MIN(RLIM_NLIMITS, ARRAYLEN((*attr)->rlim))) {
if (((*attr)->rlimset & (1u << resource))) {
*rlim = (*attr)->rlim[resource];
return 0;

View file

@ -37,9 +37,10 @@
*/
int posix_spawnattr_setflags(posix_spawnattr_t *attr, short flags) {
if (flags &
~(POSIX_SPAWN_RESETIDS | POSIX_SPAWN_SETPGROUP | POSIX_SPAWN_SETSIGDEF |
POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSCHEDPARAM |
POSIX_SPAWN_SETSCHEDULER | POSIX_SPAWN_SETSID)) {
~(POSIX_SPAWN_USEVFORK | POSIX_SPAWN_RESETIDS | POSIX_SPAWN_SETPGROUP |
POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK |
POSIX_SPAWN_SETSCHEDPARAM | POSIX_SPAWN_SETSCHEDULER |
POSIX_SPAWN_SETSID | POSIX_SPAWN_SETRLIMIT)) {
return EINVAL;
}
(*attr)->flags = flags;

View file

@ -21,6 +21,7 @@
#include "libc/macros.internal.h"
#include "libc/proc/posix_spawn.h"
#include "libc/proc/posix_spawn.internal.h"
#include "libc/sysv/consts/rlim.h"
/**
* Sets resource limit on spawned process.
@ -32,7 +33,7 @@
*/
int posix_spawnattr_setrlimit(posix_spawnattr_t *attr, int resource,
const struct rlimit *rlim) {
if (0 <= resource && resource < ARRAYLEN((*attr)->rlim)) {
if (0 <= resource && resource < MIN(RLIM_NLIMITS, ARRAYLEN((*attr)->rlim))) {
(*attr)->flags |= POSIX_SPAWN_SETRLIMIT;
(*attr)->rlimset |= 1u << resource;
(*attr)->rlim[resource] = *rlim;

View file

@ -103,12 +103,8 @@ static textwindows dontinstrument uint32_t __proc_worker(void *arg) {
__proc_unlock();
// wait for win32 to report any status change
millis = n == 64 ? __SIG_PROC_INTERVAL_MS : -1u;
i = WaitForMultipleObjects(n, handles, false, millis);
if (i == -1u) {
STRACE("PROC WORKER DYING: WAIT FAILED: %s", strerror(errno));
break;
}
millis = n == 64 ? 20 : -1u;
unassert((i = WaitForMultipleObjects(n, handles, false, millis)) != -1u);
i &= ~kNtWaitAbandoned;
if (!i || i == kNtWaitTimeout) continue;
GetExitCodeProcess(handles[i], &status);

View file

@ -68,14 +68,15 @@ ftrace_hook:
#elif defined(__aarch64__)
adrp x16,__ftrace
ldr w16,[x16,#:lo12:__ftrace]
cmp w16,0
ble 1f
stp x29,x30,[sp,-384]!
mov x29,sp
stp x0,x1,[sp,16]
adrp x0,__ftrace
ldr w0,[x0,#:lo12:__ftrace]
cmp w0,0
ble 1f
stp x2,x3,[sp,32]
stp x4,x5,[sp,48]
stp x6,x7,[sp,64]
@ -83,12 +84,12 @@ ftrace_hook:
stp x10,x11,[sp,96]
stp x12,x13,[sp,112]
stp x14,x15,[sp,128]
str x19,[sp,160]
stp x16,x19,[sp,160]
stp x20,x21,[sp,176]
stp x22,x23,[sp,192]
stp x24,x25,[sp,208]
stp x26,x27,[sp,224]
str x28,[sp,240]
stp x17,x28,[sp,240]
stp q0,q1,[sp,256]
stp q2,q3,[sp,288]
stp q4,q5,[sp,320]
@ -96,27 +97,27 @@ ftrace_hook:
bl ftracer
ldp x0,x1,[sp,16]
ldp x2,x3,[sp,32]
ldp x4,x5,[sp,48]
ldp x6,x7,[sp,64]
ldp x8,x9,[sp,80]
ldp x10,x11,[sp,96]
ldp x12,x13,[sp,112]
ldp x14,x15,[sp,128]
ldr x19,[sp,160]
ldp x20,x21,[sp,176]
ldp x22,x23,[sp,192]
ldp x24,x25,[sp,208]
ldp x26,x27,[sp,224]
ldr x28,[sp,240]
ldp q0,q1,[sp,256]
ldp q2,q3,[sp,288]
ldp q4,q5,[sp,320]
ldp q6,q7,[sp,352]
ldp q4,q5,[sp,320]
ldp q2,q3,[sp,288]
ldp q0,q1,[sp,256]
ldp x17,x28,[sp,240]
ldp x26,x27,[sp,224]
ldp x24,x25,[sp,208]
ldp x22,x23,[sp,192]
ldp x20,x21,[sp,176]
ldp x16,x19,[sp,160]
ldp x14,x15,[sp,128]
ldp x12,x13,[sp,112]
ldp x10,x11,[sp,96]
ldp x8,x9,[sp,80]
ldp x6,x7,[sp,64]
ldp x4,x5,[sp,48]
ldp x2,x3,[sp,32]
1: ldp x0,x1,[sp,16]
ldp x29,x30,[sp],384
1: ret
ret
#endif /* __x86_64__ */
.endfn ftrace_hook,globl,hidden

View file

@ -90,12 +90,13 @@ __winsock_block(int64_t handle, uint32_t flags, bool nonblock,
if (nonblock) {
CancelWinsockBlock(handle, &overlap);
eagained = true;
} else if (_check_cancel()) {
CancelWinsockBlock(handle, &overlap);
canceled = true;
} else if (_check_signal(true)) {
CancelWinsockBlock(handle, &overlap);
eintered = true;
if (errno == ECANCELED) {
canceled = true;
} else {
eintered = true;
}
} else {
status = WSAWaitForMultipleEvents(1, &overlap.hEvent, 0,
srwtimeout ? srwtimeout : -1u, 0);
@ -142,7 +143,7 @@ __winsock_block(int64_t handle, uint32_t flags, bool nonblock,
}
if (GetLastError() == kNtErrorOperationAborted) {
if (_check_cancel() == -1) return ecanceled();
if (!eintered && _check_signal(false)) return eintr();
if (!eintered && _check_signal(false)) return -1;
}
if (eintered) {
return eintr();

View file

@ -57,7 +57,7 @@ dontinline long systemfive_cancellable(void) {
return systemfive_cancel();
}
#if IsModeDbg()
if (!(pth->flags & PT_INCANCEL)) {
if (!(pth->pt_flags & PT_INCANCEL)) {
if (_weaken(report_cancelation_point)) {
_weaken(report_cancelation_point)();
}