mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-26 22:38:30 +00:00
Rewrite special file handling on Windows
This change gets GNU grep working. What caused it to not work, is it wouldn't write to an output file descriptor when its dev/ino equaled /dev/null's. So now we invent special dev/ino values for these files
This commit is contained in:
parent
aca2261cda
commit
2db2f40a98
53 changed files with 485 additions and 299 deletions
|
@ -33,9 +33,7 @@
|
|||
* @noreturn
|
||||
*/
|
||||
wontreturn void abort(void) {
|
||||
sigset_t m;
|
||||
sigemptyset(&m);
|
||||
sigaddset(&m, SIGABRT);
|
||||
sigset_t m = 1ull << (SIGABRT - 1);
|
||||
sigprocmask(SIG_UNBLOCK, &m, 0);
|
||||
raise(SIGABRT);
|
||||
signal(SIGABRT, SIG_DFL);
|
||||
|
|
|
@ -321,63 +321,18 @@ static textwindows int sys_fcntl_nt_dupfd(int fd, int cmd, int start) {
|
|||
return sys_dup_nt(fd, -1, (cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0), start);
|
||||
}
|
||||
|
||||
static textwindows int sys_fcntl_nt_setfl(int fd, unsigned *flags,
|
||||
unsigned mode, unsigned arg,
|
||||
intptr_t *handle) {
|
||||
|
||||
// you may change the following:
|
||||
//
|
||||
// - O_NONBLOCK make read() raise EAGAIN
|
||||
// - O_APPEND for toggling append mode
|
||||
// - O_RANDOM alt. for posix_fadvise()
|
||||
// - O_SEQUENTIAL alt. for posix_fadvise()
|
||||
// - 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 newflag = (*flags & ~allowed) | (arg & allowed);
|
||||
|
||||
if ((*flags & needreo) ^ (arg & needreo)) {
|
||||
unsigned perm, share, attr;
|
||||
if (GetNtOpenFlags(newflag, mode, &perm, &share, 0, &attr) == -1) {
|
||||
return -1;
|
||||
}
|
||||
// MSDN says only these are allowed, otherwise it returns EINVAL.
|
||||
attr &= kNtFileFlagBackupSemantics | kNtFileFlagDeleteOnClose |
|
||||
kNtFileFlagNoBuffering | kNtFileFlagOpenNoRecall |
|
||||
kNtFileFlagOpenReparsePoint | kNtFileFlagOverlapped |
|
||||
kNtFileFlagPosixSemantics | kNtFileFlagRandomAccess |
|
||||
kNtFileFlagSequentialScan | kNtFileFlagWriteThrough;
|
||||
intptr_t hand;
|
||||
if ((hand = ReOpenFile(*handle, perm, share, attr)) != -1) {
|
||||
if (hand != *handle) {
|
||||
CloseHandle(*handle);
|
||||
*handle = hand;
|
||||
}
|
||||
} else {
|
||||
return __winerr();
|
||||
}
|
||||
}
|
||||
|
||||
// 1. ignore flags that aren't access mode flags
|
||||
// 2. return zero if nothing's changed
|
||||
*flags = newflag;
|
||||
return 0;
|
||||
}
|
||||
|
||||
textwindows int sys_fcntl_nt(int fd, int cmd, uintptr_t arg) {
|
||||
int rc;
|
||||
BLOCK_SIGNALS;
|
||||
if (__isfdkind(fd, kFdFile) || //
|
||||
__isfdkind(fd, kFdSocket) || //
|
||||
__isfdkind(fd, kFdConsole)) {
|
||||
if (__isfdkind(fd, kFdFile) || //
|
||||
__isfdkind(fd, kFdSocket) || //
|
||||
__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);
|
||||
} else if (cmd == F_SETFL) {
|
||||
rc = sys_fcntl_nt_setfl(fd, &g_fds.p[fd].flags, g_fds.p[fd].mode, arg,
|
||||
&g_fds.p[fd].handle);
|
||||
rc = sys_fcntl_nt_setfl(fd, arg);
|
||||
} else if (cmd == F_GETFD) {
|
||||
if (g_fds.p[fd].flags & O_CLOEXEC) {
|
||||
rc = FD_CLOEXEC;
|
||||
|
|
|
@ -19,7 +19,9 @@
|
|||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/fd.internal.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/struct/stat.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/fmt/wintime.internal.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
|
@ -76,13 +78,47 @@ static textwindows long GetSizeOfReparsePoint(int64_t fh) {
|
|||
return z;
|
||||
}
|
||||
|
||||
textwindows int sys_fstat_nt(int64_t handle, struct stat *out_st) {
|
||||
static textwindows int sys_fstat_nt_socket(int kind, struct stat *st) {
|
||||
bzero(st, sizeof(*st));
|
||||
st->st_blksize = 512;
|
||||
st->st_mode = S_IFSOCK | 0666;
|
||||
st->st_dev = 0x44444444;
|
||||
st->st_ino = kind;
|
||||
return 0;
|
||||
}
|
||||
|
||||
textwindows int sys_fstat_nt_special(int kind, struct stat *st) {
|
||||
bzero(st, sizeof(*st));
|
||||
st->st_blksize = 512;
|
||||
st->st_mode = S_IFCHR | 0666;
|
||||
st->st_dev = 0x77777777;
|
||||
st->st_ino = kind;
|
||||
return 0;
|
||||
}
|
||||
|
||||
textwindows int sys_fstat_nt(int fd, struct stat *st) {
|
||||
if (fd + 0u >= g_fds.n) return ebadf();
|
||||
switch (g_fds.p[fd].kind) {
|
||||
case kFdEmpty:
|
||||
return ebadf();
|
||||
case kFdConsole:
|
||||
case kFdDevNull:
|
||||
return sys_fstat_nt_special(g_fds.p[fd].kind, 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);
|
||||
}
|
||||
}
|
||||
|
||||
textwindows int sys_fstat_nt_handle(int64_t handle, struct stat *out_st) {
|
||||
struct stat st = {0};
|
||||
|
||||
// Always set st_blksize to avoid divide by zero issues.
|
||||
// The Linux kernel sets this for /dev/tty and similar too.
|
||||
// TODO(jart): GetVolumeInformationByHandle?
|
||||
st.st_blksize = 4096;
|
||||
st.st_gid = st.st_uid = sys_getuid_nt();
|
||||
|
||||
// We'll use the "umask" to fake out the mode bits.
|
||||
uint32_t umask = atomic_load_explicit(&__umask, memory_order_acquire);
|
||||
|
@ -92,9 +128,13 @@ textwindows int sys_fstat_nt(int64_t handle, struct stat *out_st) {
|
|||
break;
|
||||
case kNtFileTypeChar:
|
||||
st.st_mode = S_IFCHR | (0666 & ~umask);
|
||||
st.st_dev = 0x66666666;
|
||||
st.st_ino = handle;
|
||||
break;
|
||||
case kNtFileTypePipe:
|
||||
st.st_mode = S_IFIFO | (0666 & ~umask);
|
||||
st.st_dev = 0x55555555;
|
||||
st.st_ino = handle;
|
||||
break;
|
||||
case kNtFileTypeDisk: {
|
||||
struct NtByHandleFileInformation wst;
|
||||
|
@ -126,7 +166,6 @@ textwindows int sys_fstat_nt(int64_t handle, struct stat *out_st) {
|
|||
} else {
|
||||
st.st_ctim = st.st_mtim;
|
||||
}
|
||||
st.st_gid = st.st_uid = sys_getuid_nt();
|
||||
st.st_size = (wst.nFileSizeHigh + 0ull) << 32 | wst.nFileSizeLow;
|
||||
st.st_dev = wst.dwVolumeSerialNumber;
|
||||
st.st_ino = (wst.nFileIndexHigh + 0ull) << 32 | wst.nFileIndexLow;
|
||||
|
|
|
@ -52,7 +52,7 @@ int fstat(int fd, struct stat *st) {
|
|||
} else if (IsMetal()) {
|
||||
rc = sys_fstat_metal(fd, st);
|
||||
} else if (IsWindows()) {
|
||||
rc = sys_fstat_nt(__getfdhandleactual(fd), st);
|
||||
rc = sys_fstat_nt(fd, st);
|
||||
} else {
|
||||
rc = enosys();
|
||||
}
|
||||
|
|
|
@ -16,9 +16,8 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/calls/struct/fd.internal.h"
|
||||
#include "libc/calls/struct/sigset.internal.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/struct/stat.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/errno.h"
|
||||
|
@ -29,18 +28,43 @@
|
|||
#include "libc/nt/enum/filesharemode.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int sys_fstatat_nt(int dirfd, const char *path, struct stat *st,
|
||||
int flags) {
|
||||
int rc, e;
|
||||
int64_t fh;
|
||||
uint32_t dwDesiredAccess;
|
||||
|
||||
// handle special files
|
||||
if (startswith(path, "/dev/")) {
|
||||
if (!strcmp(path + 5, "tty")) {
|
||||
return sys_fstat_nt_special(kFdConsole, st);
|
||||
} else if (!strcmp(path + 5, "null")) {
|
||||
return sys_fstat_nt_special(kFdDevNull, st);
|
||||
} else if (!strcmp(path + 5, "stdin")) {
|
||||
return sys_fstat_nt(STDIN_FILENO, st);
|
||||
} else if (!strcmp(path + 5, "stdout")) {
|
||||
return sys_fstat_nt(STDOUT_FILENO, st);
|
||||
} else if (!strcmp(path + 5, "stderr")) {
|
||||
return sys_fstat_nt(STDERR_FILENO, st);
|
||||
} else {
|
||||
return enoent();
|
||||
}
|
||||
}
|
||||
|
||||
// convert path from utf-8 to utf-16
|
||||
uint16_t path16[PATH_MAX];
|
||||
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
|
||||
if (__mkntpathat(dirfd, path, 0, path16) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// open an actual file
|
||||
int rc;
|
||||
int64_t fh;
|
||||
int e = errno;
|
||||
uint32_t dwDesiredAccess = kNtFileGenericRead;
|
||||
BLOCK_SIGNALS;
|
||||
e = errno;
|
||||
dwDesiredAccess = kNtFileGenericRead;
|
||||
TryAgain:
|
||||
if ((fh = CreateFile(
|
||||
path16, dwDesiredAccess,
|
||||
|
@ -50,7 +74,7 @@ TryAgain:
|
|||
((flags & AT_SYMLINK_NOFOLLOW) ? kNtFileFlagOpenReparsePoint
|
||||
: 0),
|
||||
0)) != -1) {
|
||||
rc = st ? sys_fstat_nt(fh, st) : 0;
|
||||
rc = st ? sys_fstat_nt_handle(fh, st) : 0;
|
||||
CloseHandle(fh);
|
||||
} else if (dwDesiredAccess == kNtFileGenericRead &&
|
||||
GetLastError() == kNtErrorSharingViolation) {
|
||||
|
@ -61,5 +85,7 @@ TryAgain:
|
|||
rc = __winerr();
|
||||
}
|
||||
ALLOW_SIGNALS;
|
||||
|
||||
// mop up errors
|
||||
return __fix_enotdir(rc, path16);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/sigset.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
|
@ -36,6 +37,7 @@ textwindows int sys_getloadavg_nt(double *a, int n) {
|
|||
int i, rc;
|
||||
uint64_t elapsed, used;
|
||||
struct NtFileTime idle, kern, user;
|
||||
BLOCK_SIGNALS;
|
||||
pthread_spin_lock(&lock);
|
||||
if (GetSystemTimes(&idle, &kern, &user)) {
|
||||
elapsed = (FT(kern) - FT(kern1)) + (FT(user) - FT(user1));
|
||||
|
@ -53,6 +55,7 @@ textwindows int sys_getloadavg_nt(double *a, int n) {
|
|||
rc = __winerr();
|
||||
}
|
||||
pthread_spin_unlock(&lock);
|
||||
ALLOW_SIGNALS;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,15 +20,7 @@
|
|||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/accounting.h"
|
||||
|
||||
static textwindows uint32_t __kmp32(const void *buf, size_t size) {
|
||||
size_t i;
|
||||
uint32_t h;
|
||||
const uint32_t kPhiPrime = 0x9e3779b1;
|
||||
const unsigned char *p = (const unsigned char *)buf;
|
||||
for (h = i = 0; i < size; i++) h = (p[i] + h) * kPhiPrime;
|
||||
return h;
|
||||
}
|
||||
#include "libc/str/str.h"
|
||||
|
||||
textwindows uint32_t sys_getuid_nt(void) {
|
||||
char16_t buf[257];
|
||||
|
@ -36,7 +28,7 @@ textwindows uint32_t sys_getuid_nt(void) {
|
|||
uint32_t tmp, size = ARRAYLEN(buf);
|
||||
if (!(tmp = atomic_load_explicit(&uid, memory_order_acquire))) {
|
||||
GetUserName(&buf, &size);
|
||||
tmp = __kmp32(buf, size >> 1) & 32767;
|
||||
tmp = __fnv(buf, size >> 1) & 32767;
|
||||
if (!tmp) ++tmp;
|
||||
atomic_store_explicit(&uid, tmp, memory_order_release);
|
||||
}
|
||||
|
|
|
@ -106,6 +106,9 @@ static int ioctl_fionread(int fd, uint32_t *arg) {
|
|||
int bytes = CountConsoleInputBytes();
|
||||
*arg = MAX(0, bytes);
|
||||
return 0;
|
||||
} else if (g_fds.p[fd].kind == kFdDevNull) {
|
||||
*arg = 1;
|
||||
return 0;
|
||||
} else if (GetFileType(handle) == kNtFileTypePipe) {
|
||||
uint32_t avail;
|
||||
if (PeekNamedPipe(handle, 0, 0, 0, &avail, 0)) {
|
||||
|
|
|
@ -54,7 +54,7 @@ bool32 ischardev(int fd) {
|
|||
return false;
|
||||
}
|
||||
} else {
|
||||
return __isfdkind(fd, kFdConsole) ||
|
||||
return __isfdkind(fd, kFdConsole) || __isfdkind(fd, kFdDevNull) ||
|
||||
(__isfdkind(fd, kFdFile) &&
|
||||
GetFileType(__getfdhandleactual(fd)) == kNtFileTypeChar);
|
||||
}
|
||||
|
|
|
@ -62,7 +62,9 @@ static textwindows int64_t Seek(struct Fd *f, int64_t offset, int whence) {
|
|||
}
|
||||
|
||||
textwindows int64_t sys_lseek_nt(int fd, int64_t offset, int whence) {
|
||||
if (__isfdkind(fd, kFdFile)) {
|
||||
if (__isfdkind(fd, kFdDevNull)) {
|
||||
return offset;
|
||||
} else if (__isfdkind(fd, kFdFile)) {
|
||||
struct Fd *f = g_fds.p + fd;
|
||||
int filetype = GetFileType(f->handle);
|
||||
if (filetype != kNtFileTypePipe && filetype != kNtFileTypeChar) {
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/ntmagicpaths.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
|
@ -36,24 +35,6 @@ static inline int IsAlpha(int c) {
|
|||
return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z');
|
||||
}
|
||||
|
||||
textwindows static const char *FixNtMagicPath(const char *path,
|
||||
unsigned flags) {
|
||||
const struct NtMagicPaths *mp = &kNtMagicPaths;
|
||||
asm("" : "+r"(mp));
|
||||
if (!IsSlash(path[0])) return path;
|
||||
if (strcmp(path, mp->devtty) == 0) {
|
||||
if ((flags & O_ACCMODE) == O_RDONLY) {
|
||||
return mp->conin;
|
||||
} else if ((flags & O_ACCMODE) == O_WRONLY) {
|
||||
return mp->conout;
|
||||
}
|
||||
}
|
||||
if (strcmp(path, mp->devnull) == 0) return mp->nul;
|
||||
if (strcmp(path, mp->devstdin) == 0) return mp->conin;
|
||||
if (strcmp(path, mp->devstdout) == 0) return mp->conout;
|
||||
return path;
|
||||
}
|
||||
|
||||
textwindows size_t __normntpath(char16_t *p, size_t n) {
|
||||
size_t i, j;
|
||||
for (j = i = 0; i < n; ++i) {
|
||||
|
@ -116,7 +97,6 @@ textwindows int __mkntpath2(const char *path,
|
|||
if (!path || (IsAsan() && !__asan_is_valid_str(path))) {
|
||||
return efault();
|
||||
}
|
||||
path = FixNtMagicPath(path, flags);
|
||||
|
||||
size_t x, z;
|
||||
char16_t *p = path16;
|
||||
|
|
|
@ -1,25 +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/calls/ntmagicpaths.internal.h"
|
||||
|
||||
const struct NtMagicPaths kNtMagicPaths = {
|
||||
#define TAB(NAME, STRING) STRING,
|
||||
#include "libc/calls/ntmagicpaths.inc"
|
||||
#undef TAB
|
||||
};
|
|
@ -1,7 +0,0 @@
|
|||
TAB(devtty, "/dev/tty")
|
||||
TAB(devnull, "/dev/null")
|
||||
TAB(devstdin, "/dev/stdin")
|
||||
TAB(devstdout, "/dev/stdout")
|
||||
TAB(nul, "NUL")
|
||||
TAB(conin, "CONIN$")
|
||||
TAB(conout, "CONOUT$")
|
|
@ -1,16 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_NTMAGICPATHS_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_NTMAGICPATHS_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct NtMagicPaths {
|
||||
#define TAB(NAME, STRING) char NAME[sizeof(STRING)];
|
||||
#include "libc/calls/ntmagicpaths.inc"
|
||||
#undef TAB
|
||||
};
|
||||
|
||||
extern const struct NtMagicPaths kNtMagicPaths;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_NTMAGICPATHS_H_ */
|
|
@ -18,8 +18,8 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ntmagicpaths.internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/calls/struct/sigset.internal.h"
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/errno.h"
|
||||
|
@ -131,24 +131,13 @@ static textwindows int64_t sys_open_nt_impl(int dirfd, const char *path,
|
|||
return __fix_enotdir(hand, path16);
|
||||
}
|
||||
|
||||
static textwindows int sys_open_nt_console(int dirfd,
|
||||
const struct NtMagicPaths *mp,
|
||||
uint32_t flags, int32_t mode,
|
||||
size_t fd) {
|
||||
g_fds.p[fd].kind = kFdConsole;
|
||||
g_fds.p[fd].flags = flags;
|
||||
g_fds.p[fd].mode = mode;
|
||||
g_fds.p[fd].handle =
|
||||
CreateFile(u"CONIN$", kNtGenericRead | kNtGenericWrite, kNtFileShareRead,
|
||||
&kNtIsInheritable, kNtOpenExisting, 0, 0);
|
||||
return fd;
|
||||
}
|
||||
|
||||
static textwindows int sys_open_nt_file(int dirfd, const char *file,
|
||||
uint32_t flags, int32_t mode,
|
||||
size_t fd) {
|
||||
if ((g_fds.p[fd].handle = sys_open_nt_impl(dirfd, file, flags, mode,
|
||||
kNtFileFlagOverlapped)) != -1) {
|
||||
int64_t handle;
|
||||
if ((handle = sys_open_nt_impl(dirfd, file, flags, mode,
|
||||
kNtFileFlagOverlapped)) != -1) {
|
||||
g_fds.p[fd].handle = handle;
|
||||
g_fds.p[fd].kind = kFdFile;
|
||||
g_fds.p[fd].flags = flags;
|
||||
g_fds.p[fd].mode = mode;
|
||||
|
@ -158,15 +147,61 @@ static textwindows int sys_open_nt_file(int dirfd, const char *file,
|
|||
}
|
||||
}
|
||||
|
||||
static textwindows int sys_open_nt_special(int fd, int flags, int mode,
|
||||
int kind, const char16_t *name) {
|
||||
g_fds.p[fd].kind = kind;
|
||||
g_fds.p[fd].mode = mode;
|
||||
g_fds.p[fd].flags = flags;
|
||||
g_fds.p[fd].handle = CreateFile(name, kNtGenericRead | kNtGenericWrite,
|
||||
kNtFileShareRead | kNtFileShareWrite,
|
||||
&kNtIsInheritable, kNtOpenExisting, 0, 0);
|
||||
return fd;
|
||||
}
|
||||
|
||||
static textwindows int sys_open_nt_dup(int fd, int flags, int mode, int oldfd) {
|
||||
int64_t handle;
|
||||
if (!__isfdopen(oldfd)) {
|
||||
return enoent();
|
||||
}
|
||||
if (DuplicateHandle(GetCurrentProcess(), g_fds.p[oldfd].handle,
|
||||
GetCurrentProcess(), &handle, 0, true,
|
||||
kNtDuplicateSameAccess)) {
|
||||
g_fds.p[fd] = g_fds.p[oldfd];
|
||||
g_fds.p[fd].handle = handle;
|
||||
g_fds.p[fd].mode = mode;
|
||||
if (!sys_fcntl_nt_setfl(fd, flags)) {
|
||||
return fd;
|
||||
} else {
|
||||
CloseHandle(handle);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return __winerr();
|
||||
}
|
||||
}
|
||||
|
||||
textwindows int sys_open_nt(int dirfd, const char *file, uint32_t flags,
|
||||
int32_t mode) {
|
||||
int fd;
|
||||
ssize_t rc;
|
||||
BLOCK_SIGNALS;
|
||||
__fds_lock();
|
||||
if (!(flags & O_CREAT)) mode = 0;
|
||||
if ((rc = fd = __reservefd_unlocked(-1)) != -1) {
|
||||
if (!strcmp(file, kNtMagicPaths.devtty)) {
|
||||
rc = sys_open_nt_console(dirfd, &kNtMagicPaths, flags, mode, fd);
|
||||
if (startswith(file, "/dev/")) {
|
||||
if (!strcmp(file + 5, "tty")) {
|
||||
rc = sys_open_nt_special(fd, flags, mode, kFdConsole, u"CONIN$");
|
||||
} else if (!strcmp(file + 5, "null")) {
|
||||
rc = sys_open_nt_special(fd, flags, mode, kFdDevNull, u"NUL");
|
||||
} else if (!strcmp(file + 5, "stdin")) {
|
||||
rc = sys_open_nt_dup(fd, flags, mode, STDIN_FILENO);
|
||||
} else if (!strcmp(file + 5, "stdout")) {
|
||||
rc = sys_open_nt_dup(fd, flags, mode, STDOUT_FILENO);
|
||||
} else if (!strcmp(file + 5, "stderr")) {
|
||||
rc = sys_open_nt_dup(fd, flags, mode, STDERR_FILENO);
|
||||
} else {
|
||||
rc = enoent();
|
||||
}
|
||||
} else {
|
||||
rc = sys_open_nt_file(dirfd, file, flags, mode, fd);
|
||||
}
|
||||
|
@ -175,5 +210,6 @@ textwindows int sys_open_nt(int dirfd, const char *file, uint32_t flags,
|
|||
}
|
||||
__fds_unlock();
|
||||
}
|
||||
ALLOW_SIGNALS;
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -27,11 +27,9 @@
|
|||
int sys_openat(int dirfd, const char *file, int flags, unsigned mode) {
|
||||
static bool once, modernize;
|
||||
int d, e, f;
|
||||
/*
|
||||
* RHEL5 doesn't support O_CLOEXEC. It's hard to test for this.
|
||||
* Sometimes the system call succeeds and it just doesn't set the
|
||||
* flag. Other times, it return -530 which makes no sense.
|
||||
*/
|
||||
// RHEL5 doesn't support O_CLOEXEC. It's hard to test for this.
|
||||
// Sometimes the system call succeeds and it just doesn't set the
|
||||
// flag. Other times, it return -530 which makes no sense.
|
||||
if (!IsLinux() || !(flags & O_CLOEXEC) || modernize) {
|
||||
d = __sys_openat(dirfd, file, flags, mode);
|
||||
} else if (once) {
|
||||
|
|
|
@ -47,13 +47,9 @@ static textwindows int _park_thread(uint32_t msdelay, sigset_t waitmask,
|
|||
om = __sig_beginwait(waitmask);
|
||||
if ((rc = _check_cancel()) != -1 && (rc = _check_signal(restartable)) != -1) {
|
||||
unassert((wi = WaitForSingleObject(sem, msdelay)) != -1u);
|
||||
if (wi != kNtWaitTimeout) {
|
||||
_check_signal(false);
|
||||
rc = eintr();
|
||||
_check_cancel();
|
||||
} else if ((rc = _check_signal(restartable))) {
|
||||
_check_cancel();
|
||||
}
|
||||
if (restartable && !(pt->pt_flags & PT_RESTARTABLE)) rc = eintr();
|
||||
rc |= _check_signal(restartable);
|
||||
if (rc == -1 && errno == EINTR) _check_cancel();
|
||||
}
|
||||
__sig_finishwait(om);
|
||||
atomic_store_explicit(&pt->pt_blocker, PT_BLOCKER_CPU, memory_order_release);
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#ifdef __x86_64__
|
||||
|
||||
|
|
|
@ -58,10 +58,10 @@
|
|||
// Polls on the New Technology.
|
||||
//
|
||||
// This function is used to implement poll() and select(). You may poll
|
||||
// on both sockets and files at the same time. We also poll for signals
|
||||
// while poll is polling.
|
||||
textwindows int sys_poll_nt(struct pollfd *fds, uint64_t nfds, uint32_t *ms,
|
||||
const sigset_t *sigmask) {
|
||||
// on sockets, files and the console at the same time. We also poll for
|
||||
// both signals and posix thread cancelation, while the poll is polling
|
||||
static textwindows int sys_poll_nt_impl(struct pollfd *fds, uint64_t nfds,
|
||||
uint32_t *ms, sigset_t sigmask) {
|
||||
bool ok;
|
||||
uint64_t millis;
|
||||
uint32_t cm, avail, waitfor;
|
||||
|
@ -72,7 +72,6 @@ textwindows int sys_poll_nt(struct pollfd *fds, uint64_t nfds, uint32_t *ms,
|
|||
struct timespec started, deadline, remain, now;
|
||||
int i, rc, sn, pn, gotinvals, gotpipes, gotsocks;
|
||||
|
||||
BLOCK_SIGNALS;
|
||||
started = timespec_real();
|
||||
deadline = timespec_add(started, timespec_frommillis(ms ? *ms : -1u));
|
||||
|
||||
|
@ -128,7 +127,7 @@ textwindows int sys_poll_nt(struct pollfd *fds, uint64_t nfds, uint32_t *ms,
|
|||
__fds_unlock();
|
||||
if (rc) {
|
||||
// failed to create a polling solution
|
||||
goto Finished;
|
||||
return rc;
|
||||
}
|
||||
|
||||
// perform the i/o and sleeping and looping
|
||||
|
@ -170,8 +169,7 @@ textwindows int sys_poll_nt(struct pollfd *fds, uint64_t nfds, uint32_t *ms,
|
|||
// compute a small time slice we don't mind sleeping for
|
||||
if (sn) {
|
||||
if ((gotsocks = WSAPoll(sockfds, sn, 0)) == -1) {
|
||||
rc = __winsockerr();
|
||||
goto Finished;
|
||||
return __winsockerr();
|
||||
}
|
||||
} else {
|
||||
gotsocks = 0;
|
||||
|
@ -190,8 +188,8 @@ textwindows int sys_poll_nt(struct pollfd *fds, uint64_t nfds, uint32_t *ms,
|
|||
if (waitfor) {
|
||||
POLLTRACE("poll() sleeping for %'d out of %'lu ms", waitfor,
|
||||
timespec_tomillis(remain));
|
||||
if ((rc = _park_norestart(waitfor, sigmask ? *sigmask : 0)) == -1) {
|
||||
goto Finished; // eintr, ecanceled, etc.
|
||||
if ((rc = _park_norestart(waitfor, sigmask)) == -1) {
|
||||
return -1; // eintr, ecanceled, etc.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -221,9 +219,14 @@ textwindows int sys_poll_nt(struct pollfd *fds, uint64_t nfds, uint32_t *ms,
|
|||
}
|
||||
|
||||
// and finally return
|
||||
rc = gotinvals + gotpipes + gotsocks;
|
||||
return gotinvals + gotpipes + gotsocks;
|
||||
}
|
||||
|
||||
Finished:
|
||||
textwindows int sys_poll_nt(struct pollfd *fds, uint64_t nfds, uint32_t *ms,
|
||||
const sigset_t *sigmask) {
|
||||
int rc;
|
||||
BLOCK_SIGNALS;
|
||||
rc = sys_poll_nt_impl(fds, nfds, ms, sigmask ? *sigmask : 0);
|
||||
ALLOW_SIGNALS;
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ ssize_t pread(int fd, void *buf, size_t size, int64_t offset) {
|
|||
rc = sys_pread(fd, buf, size, offset, offset);
|
||||
} else if (__isfdkind(fd, kFdSocket)) {
|
||||
rc = espipe();
|
||||
} else if (__isfdkind(fd, kFdFile)) {
|
||||
} else if (__isfdkind(fd, kFdFile) || __isfdkind(fd, kFdDevNull)) {
|
||||
rc = sys_read_nt(fd, (struct iovec[]){{buf, size}}, 1, offset);
|
||||
} else {
|
||||
rc = ebadf();
|
||||
|
|
|
@ -32,6 +32,8 @@ static const char *__fdkind2str(int x) {
|
|||
return "kFdSocket";
|
||||
case kFdConsole:
|
||||
return "kFdConsole";
|
||||
case kFdDevNull:
|
||||
return "kFdDevNull";
|
||||
case kFdSerial:
|
||||
return "kFdSerial";
|
||||
case kFdZip:
|
||||
|
|
|
@ -65,7 +65,7 @@ ssize_t pwrite(int fd, const void *buf, size_t size, int64_t offset) {
|
|||
rc = sys_pwrite(fd, buf, size, offset, offset);
|
||||
} else if (__isfdkind(fd, kFdSocket)) {
|
||||
rc = espipe();
|
||||
} else if (__isfdkind(fd, kFdFile)) {
|
||||
} else if (__isfdkind(fd, kFdFile) || __isfdkind(fd, kFdDevNull)) {
|
||||
rc = sys_write_nt(fd, (struct iovec[]){{(void *)buf, size}}, 1, offset);
|
||||
} else {
|
||||
return ebadf();
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/atomic.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
|
@ -733,8 +734,10 @@ static textwindows int WaitForConsole(struct Fd *f, sigset_t waitmask) {
|
|||
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) {
|
||||
WaitForMultipleObjects(2, (int64_t[2]){sem, __keystroke.cin}, 0, ms);
|
||||
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();
|
||||
}
|
||||
__sig_finishwait(m);
|
||||
|
@ -763,6 +766,11 @@ textwindows ssize_t sys_read_nt_impl(int fd, void *data, size_t size,
|
|||
|
||||
// switch to terminal polyfill if reading from win32 console
|
||||
struct Fd *f = g_fds.p + fd;
|
||||
|
||||
if (f->kind == kFdDevNull) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (f->kind == kFdConsole) {
|
||||
return ReadFromConsole(f, data, size, waitmask);
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ textwindows ssize_t sys_readv_nt(int fd, const struct iovec *iov, int iovlen) {
|
|||
switch (g_fds.p[fd].kind) {
|
||||
case kFdFile:
|
||||
case kFdConsole:
|
||||
case kFdDevNull:
|
||||
return sys_read_nt(fd, iov, iovlen, -1);
|
||||
case kFdSocket:
|
||||
return _weaken(sys_recv_nt)(fd, iov, iovlen, 0);
|
||||
|
|
|
@ -83,7 +83,9 @@ sys_readwrite_nt(int fd, void *data, size_t size, ssize_t offset,
|
|||
// similar to the lseek() system call, they too raise ESPIPE when
|
||||
// operating on a non-seekable file.
|
||||
bool pwriting = offset != -1;
|
||||
bool seekable = f->kind == kFdFile && GetFileType(handle) == kNtFileTypeDisk;
|
||||
bool seekable =
|
||||
(f->kind == kFdFile && GetFileType(handle) == kNtFileTypeDisk) ||
|
||||
f->kind == kFdDevNull;
|
||||
if (pwriting && !seekable) {
|
||||
return espipe();
|
||||
}
|
||||
|
|
71
libc/calls/setfl.c
Normal file
71
libc/calls/setfl.c
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*-*- 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_support-nt.internal.h"
|
||||
#include "libc/nt/createfile.h"
|
||||
#include "libc/nt/enum/fileflagandattributes.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
||||
textwindows int sys_fcntl_nt_setfl(int fd, unsigned flags) {
|
||||
|
||||
// you may change the following:
|
||||
//
|
||||
// - O_NONBLOCK make read() raise EAGAIN
|
||||
// - O_APPEND for toggling append mode
|
||||
// - O_RANDOM alt. for posix_fadvise()
|
||||
// - O_SEQUENTIAL alt. for posix_fadvise()
|
||||
// - 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 newflag = (g_fds.p[fd].flags & ~allowed) | (flags & allowed);
|
||||
|
||||
if (g_fds.p[fd].kind == kFdFile &&
|
||||
((g_fds.p[fd].flags & needreo) ^ (flags & needreo))) {
|
||||
unsigned perm, share, attr;
|
||||
if (GetNtOpenFlags(newflag, g_fds.p[fd].mode, &perm, &share, 0, &attr) ==
|
||||
-1) {
|
||||
return -1;
|
||||
}
|
||||
// MSDN says only these are allowed, otherwise it returns EINVAL.
|
||||
attr &= kNtFileFlagBackupSemantics | kNtFileFlagDeleteOnClose |
|
||||
kNtFileFlagNoBuffering | kNtFileFlagOpenNoRecall |
|
||||
kNtFileFlagOpenReparsePoint | kNtFileFlagOverlapped |
|
||||
kNtFileFlagPosixSemantics | kNtFileFlagRandomAccess |
|
||||
kNtFileFlagSequentialScan | kNtFileFlagWriteThrough;
|
||||
intptr_t hand;
|
||||
if ((hand = ReOpenFile(g_fds.p[fd].handle, perm, share, attr)) != -1) {
|
||||
if (hand != g_fds.p[fd].handle) {
|
||||
CloseHandle(g_fds.p[fd].handle);
|
||||
g_fds.p[fd].handle = hand;
|
||||
}
|
||||
} else {
|
||||
return __winerr();
|
||||
}
|
||||
}
|
||||
|
||||
// 1. ignore flags that aren't access mode flags
|
||||
// 2. return zero if nothing's changed
|
||||
g_fds.p[fd].flags = newflag;
|
||||
return 0;
|
||||
}
|
|
@ -88,11 +88,13 @@ textwindows bool __sig_ignored(int sig) {
|
|||
textwindows void __sig_delete(int sig) {
|
||||
struct Dll *e;
|
||||
__sig.pending &= ~(1ull << (sig - 1));
|
||||
BLOCK_SIGNALS;
|
||||
_pthread_lock();
|
||||
for (e = dll_last(_pthread_list); e; e = dll_prev(_pthread_list, e)) {
|
||||
POSIXTHREAD_CONTAINER(e)->tib->tib_sigpending &= ~(1ull << (sig - 1));
|
||||
}
|
||||
_pthread_unlock();
|
||||
ALLOW_SIGNALS;
|
||||
}
|
||||
|
||||
static textwindows bool __sig_should_use_altstack(unsigned flags,
|
||||
|
@ -219,7 +221,7 @@ textwindows void __sig_cancel(struct PosixThread *pt, int sig, unsigned flags) {
|
|||
}
|
||||
|
||||
static textwindows wontreturn void __sig_tramp(struct SignalFrame *sf) {
|
||||
++__sig.count;
|
||||
atomic_fetch_add_explicit(&__sig.count, 1, memory_order_relaxed);
|
||||
int sig = sf->si.si_signo;
|
||||
sigset_t blocksigs = __sighandmask[sig];
|
||||
if (!(sf->flags & SA_NODEFER)) blocksigs |= 1ull << (sig - 1);
|
||||
|
@ -309,7 +311,9 @@ static int __sig_killer(struct PosixThread *pt, int sig, int sic) {
|
|||
textwindows int __sig_kill(struct PosixThread *pt, int sig, int sic) {
|
||||
int rc;
|
||||
BLOCK_SIGNALS;
|
||||
_pthread_ref(pt);
|
||||
rc = __sig_killer(pt, sig, sic);
|
||||
_pthread_unref(pt);
|
||||
ALLOW_SIGNALS;
|
||||
return rc;
|
||||
}
|
||||
|
@ -333,7 +337,7 @@ textwindows void __sig_generate(int sig, int sic) {
|
|||
atomic_load_explicit(&pt->pt_status, memory_order_acquire) <
|
||||
kPosixThreadTerminated &&
|
||||
!(pt->tib->tib_sigmask & (1ull << (sig - 1)))) {
|
||||
mark = pt;
|
||||
_pthread_ref((mark = pt));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -345,6 +349,7 @@ textwindows void __sig_generate(int sig, int sic) {
|
|||
STRACE("all threads block %G so adding to pending signals of process", sig);
|
||||
__sig.pending |= 1ull << (sig - 1);
|
||||
}
|
||||
_pthread_unref(mark);
|
||||
ALLOW_SIGNALS;
|
||||
}
|
||||
|
||||
|
@ -411,7 +416,7 @@ static void __sig_unmaskable(struct NtExceptionPointers *ep, int code, int sig,
|
|||
struct CosmoTib *tib) {
|
||||
|
||||
// increment the signal count for getrusage()
|
||||
++__sig.count;
|
||||
atomic_fetch_add_explicit(&__sig.count, 1, memory_order_relaxed);
|
||||
|
||||
// log vital crash information reliably for --strace before doing much
|
||||
// we don't print this without the flag since raw numbers scare people
|
||||
|
|
|
@ -18,14 +18,11 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Configures process to ignore signal.
|
||||
*/
|
||||
int sigignore(int sig) {
|
||||
struct sigaction sa;
|
||||
bzero(&sa, sizeof(sa));
|
||||
sa.sa_handler = SIG_IGN;
|
||||
struct sigaction sa = {.sa_handler = SIG_IGN};
|
||||
return sigaction(sig, &sa, 0);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/calls/struct/sigset.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
@ -53,7 +54,8 @@ int sigpending(sigset_t *pending) {
|
|||
}
|
||||
rc = 0;
|
||||
} else if (IsWindows()) {
|
||||
*pending = __sig.pending | __get_tls()->tib_sigpending;
|
||||
*pending = atomic_load_explicit(&__sig.pending, memory_order_acquire) |
|
||||
__get_tls()->tib_sigpending;
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = enosys();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_STATE_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_STATE_INTERNAL_H_
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/nt/struct/securityattributes.h"
|
||||
#include "libc/thread/thread.h"
|
||||
#include "libc/thread/tls.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
|
|
@ -11,6 +11,7 @@ COSMOPOLITAN_C_START_
|
|||
#define kFdZip 6
|
||||
#define kFdEpoll 7
|
||||
#define kFdReserved 8
|
||||
#define kFdDevNull 9
|
||||
|
||||
struct Fd {
|
||||
char kind;
|
||||
|
|
|
@ -7,7 +7,9 @@ COSMOPOLITAN_C_START_
|
|||
|
||||
int sys_fstat(int, struct stat *);
|
||||
int sys_fstatat(int, const char *, struct stat *, int);
|
||||
int sys_fstat_nt(int64_t, struct stat *);
|
||||
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_fstatat_nt(int, const char *, struct stat *, int);
|
||||
int sys_lstat_nt(const char *, struct stat *);
|
||||
int sys_fstat_metal(int, struct stat *);
|
||||
|
|
|
@ -16,6 +16,7 @@ int __mkntpath2(const char *, char16_t[hasatleast PATH_MAX], int);
|
|||
int __mkntpathat(int, const char *, int, char16_t[hasatleast PATH_MAX]);
|
||||
int __mkntpathath(int64_t, const char *, int, char16_t[hasatleast PATH_MAX]);
|
||||
int ntaccesscheck(const char16_t *, uint32_t) paramsnonnull();
|
||||
int sys_fcntl_nt_setfl(int, unsigned);
|
||||
int sys_pause_nt(void);
|
||||
int64_t __fix_enotdir(int64_t, char16_t *);
|
||||
int64_t __fix_enotdir3(int64_t, char16_t *, char16_t *);
|
||||
|
|
|
@ -27,6 +27,7 @@ textwindows ssize_t sys_writev_nt(int fd, const struct iovec *iov, int iovlen) {
|
|||
switch (g_fds.p[fd].kind) {
|
||||
case kFdFile:
|
||||
case kFdConsole:
|
||||
case kFdDevNull:
|
||||
return sys_write_nt(fd, iov, iovlen, -1);
|
||||
case kFdSocket:
|
||||
return _weaken(sys_send_nt)(fd, iov, iovlen, 0);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue