mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-08 20:28:30 +00:00
Improve synchronization
- Fix bugs in kDos2Errno definition - malloc() should now be thread safe - Fix bug in rollup.com header generator - Fix open(O_APPEND) on the New Technology - Fix select() on the New Technology and test it - Work towards refactoring i/o for thread safety - Socket reads and writes on NT now poll for signals - Work towards i/o completion ports on the New Technology - Make read() and write() intermittently check for signals - Blinkenlights keyboard i/o so much better on NT w/ poll() - You can now poll() files and sockets at the same time on NT - Fix bug in appendr() that manifests with dlmalloc footers off
This commit is contained in:
parent
233144b19d
commit
933411ba99
266 changed files with 8761 additions and 4344 deletions
|
@ -148,7 +148,6 @@ int munlock(const void *, size_t);
|
|||
int munlockall(void);
|
||||
int nice(int);
|
||||
int open(const char *, int, ...);
|
||||
int openanon(char *, unsigned);
|
||||
int openat(int, const char *, int, ...);
|
||||
int pause(void);
|
||||
int personality(uint64_t);
|
||||
|
@ -169,7 +168,7 @@ int sched_setaffinity(int, uint64_t, const void *);
|
|||
int sched_yield(void);
|
||||
int setegid(uint32_t);
|
||||
int seteuid(uint32_t);
|
||||
int setgid(uint32_t);
|
||||
int setgid(int);
|
||||
int setpgid(int, int);
|
||||
int setpriority(int, unsigned, int);
|
||||
int setregid(uint32_t, uint32_t);
|
||||
|
@ -178,7 +177,7 @@ int setresuid(uint32_t, uint32_t, uint32_t);
|
|||
int setreuid(uint32_t, uint32_t);
|
||||
int setrlimit(int, const struct rlimit *);
|
||||
int setsid(void);
|
||||
int setuid(uint32_t);
|
||||
int setuid(int);
|
||||
int sigignore(int);
|
||||
int siginterrupt(int, int);
|
||||
int sigprocmask(int, const struct sigset *, struct sigset *);
|
||||
|
|
|
@ -65,8 +65,11 @@ $(LIBC_CALLS_A).pkg: \
|
|||
$(LIBC_CALLS_A_OBJS) \
|
||||
$(foreach x,$(LIBC_CALLS_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
o/$(MODE)/libc/calls/directmap.o \
|
||||
o/$(MODE)/libc/calls/directmap-nt.o \
|
||||
o/$(MODE)/libc/calls/raise.o: \
|
||||
OVERRIDE_COPTS += \
|
||||
-ffreestanding \
|
||||
$(NO_MAGIC)
|
||||
|
||||
o/$(MODE)/libc/calls/termios2linux.o \
|
||||
|
|
|
@ -16,30 +16,42 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/nt/enum/filetype.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/sock/ntstdin.internal.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int sys_close_nt(struct Fd *fd) {
|
||||
int e;
|
||||
bool32 ok;
|
||||
bool ok = true;
|
||||
|
||||
// if this file descriptor is wrapped in a named pipe worker thread
|
||||
// then we need to close our copy of the worker thread handle. it's
|
||||
// also required that whatever install a worker use malloc, so free
|
||||
if (fd->worker) {
|
||||
if (!weaken(UnrefNtStdinWorker)(fd->worker)) ok = false;
|
||||
fd->worker = 0;
|
||||
}
|
||||
|
||||
if (fd->kind == kFdFile && ((fd->flags & O_ACCMODE) != O_RDONLY &&
|
||||
GetFileType(fd->handle) == kNtFileTypeDisk)) {
|
||||
/*
|
||||
* Like Linux, closing a file on Windows doesn't guarantee it's
|
||||
* immediately synced to disk. But unlike Linux, this could cause
|
||||
* subsequent operations, e.g. unlink() to break w/ access error.
|
||||
*/
|
||||
// Like Linux, closing a file on Windows doesn't guarantee it's
|
||||
// immediately synced to disk. But unlike Linux, this could cause
|
||||
// subsequent operations, e.g. unlink() to break w/ access error.
|
||||
e = errno;
|
||||
FlushFileBuffers(fd->handle);
|
||||
errno = e;
|
||||
}
|
||||
ok = CloseHandle(fd->handle);
|
||||
|
||||
// now we can close the handle
|
||||
if (!CloseHandle(fd->handle)) ok = false;
|
||||
if (fd->kind == kFdConsole && fd->extra && fd->extra != -1) {
|
||||
ok &= CloseHandle(fd->extra);
|
||||
if (!CloseHandle(fd->extra)) ok = false;
|
||||
}
|
||||
|
||||
return ok ? 0 : -1;
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ int close(int fd) {
|
|||
}
|
||||
}
|
||||
}
|
||||
__releasefd(fd);
|
||||
if (!__vforked) __releasefd(fd);
|
||||
}
|
||||
STRACE("%s(%d) → %d% m", "close", fd, rc);
|
||||
return rc;
|
||||
|
|
110
libc/calls/createfileflags.c
Normal file
110
libc/calls/createfileflags.c
Normal file
|
@ -0,0 +1,110 @@
|
|||
/*-*- 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 2022 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/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/nt/createfile.h"
|
||||
#include "libc/nt/enum/accessmask.h"
|
||||
#include "libc/nt/enum/creationdisposition.h"
|
||||
#include "libc/nt/enum/fileflagandattributes.h"
|
||||
#include "libc/nt/enum/filesharemode.h"
|
||||
#include "libc/sysv/consts/o.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_TMPFILE 0x00410000 // AttributeTemporary|FlagDeleteOnClose
|
||||
#define _O_DIRECT 0x00004000 // kNtFileFlagNoBuffering
|
||||
#define _O_NDELAY 0x00000800 // kNtFileFlagWriteThrough
|
||||
#define _O_RANDOM 0x80000000 // kNtFileFlagRandomAccess
|
||||
#define _O_SEQUENTIAL 0x40000000 // kNtFileFlagSequentialScan
|
||||
#define _O_COMPRESSED 0x20000000 // kNtFileAttributeCompressed
|
||||
#define _O_INDEXED 0x10000000 // !kNtFileAttributeNotContentIndexed
|
||||
#define _O_NONBLOCK 0x00000800
|
||||
#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) {
|
||||
uint32_t perm, share, disp, attr;
|
||||
|
||||
switch (flags & O_ACCMODE) {
|
||||
case O_RDONLY:
|
||||
perm = kNtFileGenericRead | kNtGenericExecute;
|
||||
break;
|
||||
case O_WRONLY:
|
||||
perm = kNtFileGenericWrite | kNtGenericExecute;
|
||||
break;
|
||||
case O_RDWR:
|
||||
perm = kNtFileGenericRead | kNtFileGenericWrite | kNtGenericExecute;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
if (flags & _O_APPEND) {
|
||||
perm = kNtFileAppendData;
|
||||
}
|
||||
|
||||
if (flags & _O_EXCL) {
|
||||
share = kNtFileShareExclusive;
|
||||
} else {
|
||||
share = kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete;
|
||||
}
|
||||
|
||||
if ((flags & _O_CREAT) && (flags & _O_EXCL)) {
|
||||
disp = kNtCreateNew;
|
||||
} else if ((flags & _O_CREAT) && (flags & _O_TRUNC)) {
|
||||
disp = kNtCreateAlways;
|
||||
} else if (flags & _O_CREAT) {
|
||||
disp = kNtOpenAlways;
|
||||
} else if (flags & _O_TRUNC) {
|
||||
disp = kNtTruncateExisting;
|
||||
} else {
|
||||
disp = kNtOpenExisting;
|
||||
}
|
||||
|
||||
if ((flags & _O_TMPFILE) == _O_TMPFILE) {
|
||||
attr = kNtFileAttributeTemporary | kNtFileFlagDeleteOnClose;
|
||||
} else {
|
||||
attr = kNtFileAttributeNormal;
|
||||
if (flags & _O_DIRECTORY) {
|
||||
attr |= kNtFileFlagBackupSemantics;
|
||||
}
|
||||
if (~mode & 0200) {
|
||||
attr |= kNtFileAttributeReadonly;
|
||||
}
|
||||
}
|
||||
|
||||
if (~flags & _O_INDEXED) attr |= kNtFileAttributeNotContentIndexed;
|
||||
if (flags & _O_COMPRESSED) attr |= kNtFileAttributeCompressed;
|
||||
if (flags & _O_SEQUENTIAL) attr |= kNtFileFlagSequentialScan;
|
||||
if (flags & _O_RANDOM) attr |= kNtFileFlagRandomAccess;
|
||||
if (flags & _O_DIRECT) attr |= kNtFileFlagNoBuffering;
|
||||
if (flags & _O_NDELAY) attr |= kNtFileFlagWriteThrough;
|
||||
|
||||
if (out_perm) *out_perm = perm;
|
||||
if (out_share) *out_share = share;
|
||||
if (out_disp) *out_disp = disp;
|
||||
if (out_attr) *out_attr = attr;
|
||||
return 0;
|
||||
}
|
|
@ -16,32 +16,35 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/reverse.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/intrin/lockxadd.h"
|
||||
#include "libc/nt/process.h"
|
||||
|
||||
static const char kPipeNamePrefix[] = "\\\\?\\pipe\\cosmo\\";
|
||||
|
||||
static textwindows size_t UintToChar16Array(char16_t *a, uint64_t i) {
|
||||
size_t j = 0;
|
||||
static textwindows char16_t *UintToChar16Array(char16_t p[21], uint64_t x) {
|
||||
char t;
|
||||
size_t a, b, i = 0;
|
||||
do {
|
||||
a[j++] = i % 10 + '0';
|
||||
i /= 10;
|
||||
} while (i > 0);
|
||||
a[j] = 0;
|
||||
reverse(a, j);
|
||||
return j;
|
||||
p[i++] = x % 10 + '0';
|
||||
x = x / 10;
|
||||
} while (x > 0);
|
||||
if (i) {
|
||||
for (a = 0, b = i - 1; a < b; ++a, --b) {
|
||||
t = p[a];
|
||||
p[a] = p[b];
|
||||
p[b] = t;
|
||||
}
|
||||
}
|
||||
return p + i;
|
||||
}
|
||||
|
||||
textwindows char16_t *CreatePipeName(char16_t *a) {
|
||||
static long x;
|
||||
unsigned i;
|
||||
for (i = 0; kPipeNamePrefix[i]; ++i) a[i] = kPipeNamePrefix[i];
|
||||
i += UintToChar16Array(a + i, GetCurrentProcessId());
|
||||
a[i++] = u'-';
|
||||
i += UintToChar16Array(a + i, GetCurrentProcessId());
|
||||
a[i++] = u'-';
|
||||
i += UintToChar16Array(a + i, x++);
|
||||
a[i] = u'\0';
|
||||
char16_t *p = a;
|
||||
const char *q = "\\\\?\\pipe\\cosmo\\";
|
||||
while (*q) *p++ = *q++;
|
||||
p = UintToChar16Array(p, GetCurrentProcessId());
|
||||
*p++ = '-';
|
||||
p = UintToChar16Array(p, _lockxadd(&x, 1));
|
||||
*p = 0;
|
||||
return a;
|
||||
}
|
||||
|
|
|
@ -18,18 +18,21 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/nt/enum/filemapflags.h"
|
||||
#include "libc/nt/enum/pageflags.h"
|
||||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/processmemorycounters.h"
|
||||
#include "libc/runtime/directmap.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
||||
textwindows noasan struct DirectMap sys_mmap_nt(void *addr, size_t size,
|
||||
int prot, int flags, int fd,
|
||||
int64_t off) {
|
||||
textwindows struct DirectMap sys_mmap_nt(void *addr, size_t size, int prot,
|
||||
int flags, int fd, int64_t off) {
|
||||
size_t i;
|
||||
bool iscow;
|
||||
int64_t handle;
|
||||
|
@ -38,6 +41,18 @@ textwindows noasan struct DirectMap sys_mmap_nt(void *addr, size_t size,
|
|||
struct ProtectNt fl;
|
||||
const struct NtSecurityAttributes *sec;
|
||||
|
||||
#ifndef NDEBUG
|
||||
struct NtProcessMemoryCountersEx memcount = {
|
||||
.cb = sizeof(struct NtProcessMemoryCountersEx),
|
||||
};
|
||||
if (GetProcessMemoryInfo(GetCurrentProcess(), &memcount, sizeof(memcount))) {
|
||||
if (memcount.PeakWorkingSetSize > 5ull * 1024 * 1024 * 1024) {
|
||||
kprintf("error: exceeded 5gb memory limit%n");
|
||||
_Exit(201);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (fd != -1) {
|
||||
handle = g_fds.p[fd].handle;
|
||||
} else {
|
||||
|
|
|
@ -33,8 +33,8 @@
|
|||
* bypassed by calling this function. However the caller is responsible
|
||||
* for passing the magic memory handle on Windows NT to CloseHandle().
|
||||
*/
|
||||
noasan struct DirectMap sys_mmap(void *addr, size_t size, int prot, int flags,
|
||||
int fd, int64_t off) {
|
||||
struct DirectMap sys_mmap(void *addr, size_t size, int prot, int flags, int fd,
|
||||
int64_t off) {
|
||||
/* asan runtime depends on this function */
|
||||
struct DirectMap d;
|
||||
if (!IsWindows() && !IsMetal()) {
|
||||
|
|
|
@ -24,38 +24,62 @@
|
|||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/ntstdin.internal.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Implements dup(), dup2(), and dup3() for Windows NT.
|
||||
* Implements dup(), dup2(), dup3(), and F_DUPFD for Windows.
|
||||
*/
|
||||
textwindows int sys_dup_nt(int oldfd, int newfd, int flags) {
|
||||
int64_t proc;
|
||||
textwindows int sys_dup_nt(int oldfd, int newfd, int flags, int start) {
|
||||
int64_t proc, handle;
|
||||
|
||||
// validate the api usage
|
||||
if (oldfd < 0) return einval();
|
||||
if (flags & ~O_CLOEXEC) return einval();
|
||||
if (oldfd >= g_fds.n ||
|
||||
(g_fds.p[oldfd].kind != kFdFile && g_fds.p[oldfd].kind != kFdSocket &&
|
||||
g_fds.p[oldfd].kind != kFdConsole)) {
|
||||
return ebadf();
|
||||
}
|
||||
|
||||
// allocate a new file descriptor
|
||||
if (newfd == -1) {
|
||||
if ((newfd = __reservefd()) == -1) return -1;
|
||||
if ((newfd = __reservefd(start)) == -1) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (__ensurefds(newfd) == -1) return -1;
|
||||
if (g_fds.p[newfd].kind) close(newfd);
|
||||
g_fds.p[newfd].kind = kFdReserved;
|
||||
}
|
||||
|
||||
// if this file descriptor is wrapped in a named pipe worker thread
|
||||
// then we should clone the original authentic handle rather than the
|
||||
// stdin worker's named pipe. we won't clone the worker, since that
|
||||
// can always be recreated again on demand.
|
||||
if (g_fds.p[oldfd].worker) {
|
||||
handle = g_fds.p[oldfd].worker->reader;
|
||||
} else {
|
||||
handle = g_fds.p[oldfd].handle;
|
||||
}
|
||||
|
||||
proc = GetCurrentProcess();
|
||||
if (DuplicateHandle(proc, g_fds.p[oldfd].handle, proc, &g_fds.p[newfd].handle,
|
||||
0, true, kNtDuplicateSameAccess)) {
|
||||
if (DuplicateHandle(proc, handle, proc, &g_fds.p[newfd].handle, 0, true,
|
||||
kNtDuplicateSameAccess)) {
|
||||
g_fds.p[newfd].kind = g_fds.p[oldfd].kind;
|
||||
g_fds.p[newfd].flags = flags;
|
||||
g_fds.p[newfd].mode = g_fds.p[oldfd].mode;
|
||||
g_fds.p[newfd].flags = g_fds.p[oldfd].flags & ~O_CLOEXEC;
|
||||
if (flags & O_CLOEXEC) g_fds.p[newfd].flags |= O_CLOEXEC;
|
||||
if (g_fds.p[oldfd].kind == kFdSocket && weaken(_dupsockfd)) {
|
||||
g_fds.p[newfd].extra =
|
||||
(intptr_t)weaken(_dupsockfd)((struct SockFd *)g_fds.p[oldfd].extra);
|
||||
} else {
|
||||
g_fds.p[newfd].extra = g_fds.p[oldfd].extra;
|
||||
}
|
||||
if (g_fds.p[oldfd].worker) {
|
||||
g_fds.p[newfd].worker = weaken(RefNtStdinWorker)(g_fds.p[oldfd].worker);
|
||||
}
|
||||
return newfd;
|
||||
} else {
|
||||
__releasefd(newfd);
|
||||
|
|
|
@ -34,7 +34,7 @@ int dup(int fd) {
|
|||
if (!IsWindows()) {
|
||||
fd2 = sys_dup(fd);
|
||||
} else {
|
||||
fd2 = sys_dup_nt(fd, -1, 0);
|
||||
fd2 = sys_dup_nt(fd, -1, 0, -1);
|
||||
}
|
||||
STRACE("%s(%d) → %d% m", "dup", fd, fd2);
|
||||
return fd2;
|
||||
|
|
|
@ -38,7 +38,7 @@ int dup2(int oldfd, int newfd) {
|
|||
} else if (!IsWindows()) {
|
||||
rc = sys_dup3(oldfd, newfd, 0);
|
||||
} else {
|
||||
rc = sys_dup_nt(oldfd, newfd, 0);
|
||||
rc = sys_dup_nt(oldfd, newfd, 0, -1);
|
||||
}
|
||||
STRACE("dup2(%d, %d) → %d% m", oldfd, newfd, rc);
|
||||
return rc;
|
||||
|
|
|
@ -40,7 +40,7 @@ int dup3(int oldfd, int newfd, int flags) {
|
|||
if (!IsWindows()) {
|
||||
rc = sys_dup3(oldfd, newfd, flags);
|
||||
} else {
|
||||
rc = sys_dup_nt(oldfd, newfd, flags);
|
||||
rc = sys_dup_nt(oldfd, newfd, flags, -1);
|
||||
}
|
||||
STRACE("dup3(%d, %d, %d) → %d% m", oldfd, newfd, flags, rc);
|
||||
return rc;
|
||||
|
|
|
@ -41,9 +41,9 @@ textwindows int sys_execve_nt(const char *program, char *const argv[],
|
|||
bzero(&startinfo, sizeof(startinfo));
|
||||
startinfo.cb = sizeof(struct NtStartupInfo);
|
||||
startinfo.dwFlags = kNtStartfUsestdhandles;
|
||||
startinfo.hStdInput = g_fds.p[0].handle;
|
||||
startinfo.hStdOutput = g_fds.p[1].handle;
|
||||
startinfo.hStdError = g_fds.p[2].handle;
|
||||
startinfo.hStdInput = __getfdhandleactual(0);
|
||||
startinfo.hStdOutput = __getfdhandleactual(1);
|
||||
startinfo.hStdError = __getfdhandleactual(2);
|
||||
rc = ntspawn(program, argv, envp, 0, 0, 0, 1, 0, 0, &startinfo, &procinfo);
|
||||
if (rc == -1) return -1;
|
||||
CloseHandle(g_fds.p[0].handle);
|
||||
|
|
|
@ -17,49 +17,52 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/nt/createfile.h"
|
||||
#include "libc/nt/enum/fileflagandattributes.h"
|
||||
#include "libc/nt/enum/filesharemode.h"
|
||||
#include "libc/nt/enum/status.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/nt/file.h"
|
||||
#include "libc/nt/ntdll.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/fileaccessinformation.h"
|
||||
#include "libc/nt/struct/filebasicinformation.h"
|
||||
#include "libc/nt/struct/iostatusblock.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/madv.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int sys_fadvise_nt(int fd, uint64_t offset, uint64_t len,
|
||||
int advice) {
|
||||
int64_t h2;
|
||||
NtStatus status;
|
||||
uint32_t sharemode;
|
||||
struct NtIoStatusBlock iostatus;
|
||||
struct NtFileBasicInformation basicinfo;
|
||||
struct NtFileAccessInformation accessinfo;
|
||||
int64_t h1, h2;
|
||||
int flags, mode;
|
||||
uint32_t perm, share, attr;
|
||||
if (!__isfdkind(fd, kFdFile)) return ebadf();
|
||||
sharemode = /* xxx: no clue how to query this */
|
||||
kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete;
|
||||
/* TODO(jart): can we do it in one call w/ NtQueryObject? */
|
||||
if (!NtError(status = NtQueryInformationFile(g_fds.p[fd].handle, &iostatus,
|
||||
&basicinfo, sizeof(basicinfo),
|
||||
kNtFileBasicInformation)) &&
|
||||
!NtError(status = NtQueryInformationFile(g_fds.p[fd].handle, &iostatus,
|
||||
&accessinfo, sizeof(accessinfo),
|
||||
kNtFileAccessInformation))) {
|
||||
if ((h2 = ReOpenFile(g_fds.p[fd].handle, accessinfo.AccessFlags, sharemode,
|
||||
advice | basicinfo.FileAttributes)) != -1) {
|
||||
if (h2 != g_fds.p[fd].handle) {
|
||||
CloseHandle(g_fds.p[fd].handle);
|
||||
g_fds.p[fd].handle = h2;
|
||||
}
|
||||
return 0;
|
||||
h1 = g_fds.p[fd].handle;
|
||||
mode = g_fds.p[fd].mode;
|
||||
flags = g_fds.p[fd].flags;
|
||||
flags &= ~(O_SEQUENTIAL | O_RANDOM);
|
||||
switch (advice) {
|
||||
case MADV_NORMAL:
|
||||
break;
|
||||
case MADV_RANDOM:
|
||||
flags |= O_RANDOM;
|
||||
break;
|
||||
case MADV_SEQUENTIAL:
|
||||
flags |= O_SEQUENTIAL;
|
||||
break;
|
||||
default:
|
||||
return einval();
|
||||
}
|
||||
if (GetNtOpenFlags(flags, mode, &perm, &share, 0, &attr) == -1) return -1;
|
||||
if ((h2 = ReOpenFile(h1, perm, share, attr)) != -1) {
|
||||
if (h2 != h1) {
|
||||
CloseHandle(h1);
|
||||
g_fds.p[fd].handle = h2;
|
||||
}
|
||||
return __winerr();
|
||||
} else if (status == kNtStatusDllNotFound) {
|
||||
return enosys();
|
||||
g_fds.p[fd].flags = flags;
|
||||
return 0;
|
||||
} else {
|
||||
return ntreturn(status);
|
||||
return __winerr();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/flock.h"
|
||||
#include "libc/intrin/cmpxchg.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/createfile.h"
|
||||
#include "libc/nt/enum/accessmask.h"
|
||||
#include "libc/nt/enum/fileflagandattributes.h"
|
||||
#include "libc/nt/enum/filelockflags.h"
|
||||
|
@ -38,38 +40,8 @@
|
|||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static textwindows int sys_fcntl_nt_reservefd(int start) {
|
||||
int fd;
|
||||
for (;;) {
|
||||
fd = start;
|
||||
if (fd >= g_fds.n) {
|
||||
if (__ensurefds(fd) == -1) return -1;
|
||||
}
|
||||
_cmpxchg(&g_fds.f, fd, fd + 1);
|
||||
if (_cmpxchg(&g_fds.p[fd].kind, kFdEmpty, kFdReserved)) {
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static textwindows int sys_fcntl_nt_dupfd(int oldfd, int cmd, int start) {
|
||||
int newfd;
|
||||
int64_t proc;
|
||||
if ((newfd = sys_fcntl_nt_reservefd(start)) != -1) {
|
||||
proc = GetCurrentProcess();
|
||||
if (DuplicateHandle(proc, g_fds.p[oldfd].handle, proc,
|
||||
&g_fds.p[newfd].handle, 0, true,
|
||||
kNtDuplicateSameAccess)) {
|
||||
g_fds.p[newfd].kind = g_fds.p[oldfd].kind;
|
||||
g_fds.p[newfd].flags = cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0;
|
||||
return newfd;
|
||||
} else {
|
||||
__releasefd(newfd);
|
||||
return __winerr();
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
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_lock(struct Fd *f, int cmd, uintptr_t arg) {
|
||||
|
@ -98,7 +70,7 @@ static textwindows int sys_fcntl_nt_lock(struct Fd *f, int cmd, uintptr_t arg) {
|
|||
}
|
||||
if (!len) len = size - off;
|
||||
if (off < 0 || len < 0) return einval();
|
||||
_offset2overlap(off, &ov);
|
||||
_offset2overlap(f->handle, off, &ov);
|
||||
if (l->l_type == F_RDLCK || l->l_type == F_WRLCK) {
|
||||
flags = 0;
|
||||
if (cmd == F_SETLK) flags |= kNtLockfileFailImmediately;
|
||||
|
@ -136,11 +108,9 @@ textwindows int sys_fcntl_nt(int fd, int cmd, uintptr_t arg) {
|
|||
return g_fds.p[fd].flags & (O_ACCMODE | O_APPEND | O_ASYNC | O_DIRECT |
|
||||
O_NOATIME | O_NONBLOCK);
|
||||
} else if (cmd == F_SETFL) {
|
||||
/*
|
||||
* - O_APPEND doesn't appear to be tunable at cursory glance
|
||||
* - O_NONBLOCK might require we start doing all i/o in threads
|
||||
* - O_DSYNC / O_RSYNC / O_SYNC maybe if we fsync() everything
|
||||
*/
|
||||
// O_APPEND doesn't appear to be tunable at cursory glance
|
||||
// O_NONBLOCK might require we start doing all i/o in threads
|
||||
// O_DSYNC / O_RSYNC / O_SYNC maybe if we fsync() everything
|
||||
return einval();
|
||||
} else if (cmd == F_GETFD) {
|
||||
if (g_fds.p[fd].flags & O_CLOEXEC) {
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int sys_fdatasync_nt(int fd) {
|
||||
// TODO(jart): what should we do with worker pipes?
|
||||
if (!__isfdkind(fd, kFdFile)) return ebadf();
|
||||
return FlushFileBuffers(g_fds.p[fd].handle) ? 0 : -1;
|
||||
}
|
||||
|
|
|
@ -20,42 +20,32 @@
|
|||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
|
||||
STATIC_YOINK("_init_g_fds");
|
||||
|
||||
hidden struct Fds g_fds;
|
||||
struct Fds g_fds;
|
||||
_Alignas(64) char __fds_lock;
|
||||
|
||||
static textwindows int64_t GetHandleNt(long a) {
|
||||
int64_t b;
|
||||
b = GetStdHandle(a);
|
||||
STRACE("GetStdHandle(%ld) → %ld% m", a, b);
|
||||
return b;
|
||||
}
|
||||
|
||||
hidden textstartup void InitializeFileDescriptors(void) {
|
||||
textstartup void InitializeFileDescriptors(void) {
|
||||
struct Fds *fds;
|
||||
fds = VEIL("r", &g_fds);
|
||||
pushmov(&fds->n, ARRAYLEN(fds->__init_p));
|
||||
fds->p = fds->__init_p;
|
||||
if (IsMetal()) {
|
||||
pushmov(&fds->f, 3ull);
|
||||
fds->__init_p[STDIN_FILENO].kind = pushpop(kFdSerial);
|
||||
fds->__init_p[STDOUT_FILENO].kind = pushpop(kFdSerial);
|
||||
fds->__init_p[STDERR_FILENO].kind = pushpop(kFdSerial);
|
||||
fds->__init_p[STDIN_FILENO].handle = VEIL("r", 0x3F8ull);
|
||||
fds->__init_p[STDOUT_FILENO].handle = VEIL("r", 0x3F8ull);
|
||||
fds->__init_p[STDERR_FILENO].handle = VEIL("r", 0x3F8ull);
|
||||
fds->__init_p[0].kind = pushpop(kFdSerial);
|
||||
fds->__init_p[1].kind = pushpop(kFdSerial);
|
||||
fds->__init_p[2].kind = pushpop(kFdSerial);
|
||||
fds->__init_p[0].handle = VEIL("r", 0x3F8ull);
|
||||
fds->__init_p[1].handle = VEIL("r", 0x3F8ull);
|
||||
fds->__init_p[2].handle = VEIL("r", 0x3F8ull);
|
||||
} else if (IsWindows()) {
|
||||
pushmov(&fds->f, 3ull);
|
||||
fds->__init_p[STDIN_FILENO].kind = pushpop(kFdFile);
|
||||
fds->__init_p[STDOUT_FILENO].kind = pushpop(kFdFile);
|
||||
fds->__init_p[STDERR_FILENO].kind = pushpop(kFdFile);
|
||||
fds->__init_p[STDIN_FILENO].handle =
|
||||
GetHandleNt(pushpop(kNtStdInputHandle));
|
||||
fds->__init_p[STDOUT_FILENO].handle =
|
||||
GetHandleNt(pushpop(kNtStdOutputHandle));
|
||||
fds->__init_p[STDERR_FILENO].handle =
|
||||
GetHandleNt(pushpop(kNtStdErrorHandle));
|
||||
fds->__init_p[0].kind = pushpop(kFdFile);
|
||||
fds->__init_p[1].kind = pushpop(kFdFile);
|
||||
fds->__init_p[2].kind = pushpop(kFdFile);
|
||||
fds->__init_p[0].handle = GetStdHandle(pushpop(kNtStdInputHandle));
|
||||
fds->__init_p[1].handle = GetStdHandle(pushpop(kNtStdOutputHandle));
|
||||
fds->__init_p[2].handle = GetStdHandle(pushpop(kNtStdErrorHandle));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,6 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
|
||||
cthread_spinlock_t __sig_lock;
|
||||
_Alignas(64) char __sig_lock;
|
||||
unsigned __sighandrvas[NSIG];
|
||||
unsigned __sighandflags[NSIG];
|
||||
|
|
|
@ -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 2022 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,48 +16,16 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/intrin/cmpxchg.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
|
||||
static void __ensurefds_destroy(void) {
|
||||
weaken(free)(g_fds.p);
|
||||
}
|
||||
|
||||
int __ensurefds(int fd) {
|
||||
size_t n1, n2;
|
||||
struct Fd *p1, *p2;
|
||||
for (;;) {
|
||||
p1 = g_fds.p;
|
||||
n1 = g_fds.n;
|
||||
if (fd < n1) return fd;
|
||||
if (weaken(malloc)) {
|
||||
n2 = MAX(fd + 1, n1 + (n1 << 1));
|
||||
if ((p2 = weaken(malloc)(n2 * sizeof(*p1)))) {
|
||||
memcpy(p2, p1, n1 * sizeof(*p1));
|
||||
bzero(p2 + n1, (n2 - n1) * sizeof(*p1));
|
||||
if (_cmpxchg(&g_fds.p, p1, p2)) {
|
||||
g_fds.n = n2;
|
||||
if (weaken(free)) {
|
||||
if (p1 == g_fds.__init_p) {
|
||||
atexit(__ensurefds_destroy);
|
||||
} else {
|
||||
weaken(free)(p1);
|
||||
}
|
||||
}
|
||||
return fd;
|
||||
} else if (weaken(free)) {
|
||||
weaken(free)(p2);
|
||||
}
|
||||
} else {
|
||||
return enomem();
|
||||
}
|
||||
} else {
|
||||
return emfile();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns effective user ID of calling process.
|
||||
*/
|
||||
uint32_t geteuid(void) {
|
||||
int rc;
|
||||
rc = sys_geteuid();
|
||||
STRACE("%s() → %d% m", "geteuid", rc);
|
||||
return rc;
|
||||
}
|
|
@ -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 2022 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 │
|
||||
|
@ -17,10 +17,12 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/nt/struct/securityattributes.h"
|
||||
#include "libc/sock/ntstdin.internal.h"
|
||||
|
||||
hidden const struct NtSecurityAttributes kNtIsInheritable = {
|
||||
sizeof(struct NtSecurityAttributes),
|
||||
NULL,
|
||||
true,
|
||||
};
|
||||
int64_t __getfdhandleactual(int fd) {
|
||||
if (g_fds.p[fd].worker) {
|
||||
return g_fds.p[fd].worker->reader;
|
||||
} else {
|
||||
return g_fds.p[fd].handle;
|
||||
}
|
||||
}
|
|
@ -47,6 +47,8 @@ textwindows int sys_getrusage_nt(int who, struct rusage *usage) {
|
|||
} else {
|
||||
return __winerr();
|
||||
}
|
||||
bzero(&memcount, sizeof(memcount));
|
||||
memcount.cb = sizeof(struct NtProcessMemoryCountersEx);
|
||||
if (GetProcessMemoryInfo(GetCurrentProcess(), &memcount, sizeof(memcount))) {
|
||||
usage->ru_maxrss = memcount.PeakWorkingSetSize / 1024;
|
||||
usage->ru_majflt = memcount.PageFaultCount;
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/spinlock.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/struct/context.h"
|
||||
#include "libc/nt/struct/ntexceptionpointers.h"
|
||||
#include "libc/nt/struct/overlapped.h"
|
||||
#include "libc/nt/struct/securityattributes.h"
|
||||
#include "libc/nt/struct/startupinfo.h"
|
||||
#include "libc/nt/struct/systeminfo.h"
|
||||
|
@ -58,8 +58,10 @@ enum FdKind {
|
|||
struct Fd {
|
||||
enum FdKind kind;
|
||||
unsigned flags;
|
||||
unsigned mode;
|
||||
int64_t handle;
|
||||
int64_t extra;
|
||||
struct NtStdinWorker *worker;
|
||||
bool zombie;
|
||||
};
|
||||
|
||||
|
@ -73,16 +75,19 @@ struct Fds {
|
|||
extern const struct Fd kEmptyFd;
|
||||
|
||||
hidden extern int __vforked;
|
||||
hidden extern char __fds_lock;
|
||||
hidden extern char __sig_lock;
|
||||
hidden extern bool __time_critical;
|
||||
hidden extern cthread_spinlock_t __sig_lock;
|
||||
hidden extern unsigned __sighandrvas[NSIG];
|
||||
hidden extern unsigned __sighandflags[NSIG];
|
||||
hidden extern struct Fds g_fds;
|
||||
hidden extern const struct NtSecurityAttributes kNtIsInheritable;
|
||||
|
||||
int __reservefd(void) hidden;
|
||||
int __reservefd(int) hidden;
|
||||
void __releasefd(int) hidden;
|
||||
int __ensurefds(int) hidden;
|
||||
int64_t __getfdhandleactual(int) hidden;
|
||||
void __printfds(void);
|
||||
|
||||
forceinline bool __isfdopen(int fd) {
|
||||
return 0 <= fd && fd < g_fds.n && g_fds.p[fd].kind != kFdEmpty;
|
||||
|
@ -178,6 +183,7 @@ i32 sys_posix_openpt(i32) hidden;
|
|||
i32 sys_renameat(i32, const char *, i32, const char *) hidden;
|
||||
i32 sys_sched_setaffinity(i32, u64, const void *) hidden;
|
||||
i32 sys_sched_yield(void) hidden;
|
||||
i32 sys_setgid(i32) hidden;
|
||||
i32 sys_setitimer(i32, const struct itimerval *, struct itimerval *) hidden;
|
||||
i32 sys_setpgid(i32, i32) hidden;
|
||||
i32 sys_setpriority(i32, u32, i32) hidden;
|
||||
|
@ -185,6 +191,7 @@ i32 sys_setresgid(uint32_t, uint32_t, uint32_t) hidden;
|
|||
i32 sys_setresuid(uint32_t, uint32_t, uint32_t) hidden;
|
||||
i32 sys_setrlimit(i32, const struct rlimit *) hidden;
|
||||
i32 sys_setsid(void) hidden;
|
||||
i32 sys_setuid(i32) hidden;
|
||||
i32 sys_sigaction(i32, const void *, void *, i64, i64) hidden;
|
||||
i32 sys_sigaltstack(const void *, void *) hidden;
|
||||
i32 sys_sigprocmask(i32, const sigset *, sigset *, u64) hidden;
|
||||
|
@ -216,6 +223,7 @@ i64 sys_sendfile(i32, i32, i64 *, u64) hidden;
|
|||
i64 sys_splice(i32, i64 *, i32, i64 *, u64, u32) hidden;
|
||||
i64 sys_vmsplice(i32, const struct iovec *, i64, u32) hidden;
|
||||
i64 sys_write(i32, const void *, u64) hidden;
|
||||
u32 sys_geteuid(void) hidden;
|
||||
u32 sys_getgid(void) hidden;
|
||||
u32 sys_getsid(int) hidden;
|
||||
u32 sys_gettid(void) hidden;
|
||||
|
@ -266,7 +274,7 @@ i64 sys_lseek_nt(int, i64, int) hidden;
|
|||
int sys_chdir_nt(const char *) hidden;
|
||||
int sys_close_epoll_nt(int) hidden;
|
||||
int sys_close_nt(struct Fd *) hidden;
|
||||
int sys_dup_nt(int, int, int) hidden;
|
||||
int sys_dup_nt(int, int, int, int) hidden;
|
||||
int sys_execve_nt(const char *, char *const[], char *const[]) hidden;
|
||||
int sys_faccessat_nt(int, const char *, int, uint32_t) hidden;
|
||||
int sys_fadvise_nt(int, u64, u64, int) hidden;
|
||||
|
@ -331,12 +339,13 @@ int64_t __winerr(void) nocallback privileged;
|
|||
int64_t ntreturn(uint32_t);
|
||||
ssize_t sys_readv_nt(struct Fd *, const struct iovec *, int) hidden;
|
||||
ssize_t sys_writev_nt(int, const struct iovec *, int) hidden;
|
||||
struct NtOverlapped *_offset2overlap(int64_t, struct NtOverlapped *) hidden;
|
||||
unsigned __wincrash_nt(struct NtExceptionPointers *);
|
||||
void *GetProcAddressModule(const char *, const char *) hidden;
|
||||
void WinMainForked(void) hidden;
|
||||
void _ntcontext2linux(struct ucontext *, const struct NtContext *) hidden;
|
||||
void _ntlinux2context(struct NtContext *, const ucontext_t *) hidden;
|
||||
struct NtOverlapped *_offset2overlap(int64_t, int64_t,
|
||||
struct NtOverlapped *) hidden;
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § syscalls » metal ─╬─│┼
|
||||
|
|
|
@ -92,4 +92,6 @@ static textstartup void LoadavgNtInit(void) {
|
|||
LoadavgNtPoll(hCounter, 0);
|
||||
}
|
||||
|
||||
const void *const LoadavgNtCtor[] initarray = {LoadavgNtInit};
|
||||
const void *const LoadavgNtCtor[] initarray = {
|
||||
LoadavgNtInit,
|
||||
};
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/nt/ipc.h"
|
||||
|
@ -33,11 +34,15 @@
|
|||
* @asyncsignalsafe
|
||||
*/
|
||||
int mkfifo(const char *pathname, unsigned mode) {
|
||||
/* TODO(jart): Windows? */
|
||||
if (IsAsan() && !__asan_is_valid(pathname, 1)) return efault();
|
||||
if (IsLinux()) {
|
||||
return sys_mknod(pathname, mode | S_IFIFO, 0);
|
||||
// TODO(jart): Windows?
|
||||
int rc;
|
||||
if (IsAsan() && !__asan_is_valid(pathname, 1)) {
|
||||
rc = efault();
|
||||
} else if (IsLinux()) {
|
||||
rc = sys_mknod(pathname, mode | S_IFIFO, 0);
|
||||
} else {
|
||||
return sys_mkfifo(pathname, mode);
|
||||
rc = sys_mkfifo(pathname, mode);
|
||||
}
|
||||
STRACE("mkfifo(%#s, %#o) → %d% m", pathname, mode, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -49,10 +49,8 @@ textwindows noinstrument int sys_nanosleep_nt(const struct timespec *req,
|
|||
} else {
|
||||
slice = ms;
|
||||
}
|
||||
if (!__time_critical) {
|
||||
STRACE("SleepEx(%u, true)", slice);
|
||||
}
|
||||
if (SleepEx(slice, true) == kNtWaitIoCompletion) {
|
||||
STRACE("IOCP TRIGGERED EINTR");
|
||||
rc = eintr();
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -18,9 +18,9 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/nt/struct/overlapped.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
textwindows struct NtOverlapped *_offset2overlap(int64_t opt_offset,
|
||||
textwindows struct NtOverlapped *_offset2overlap(int64_t handle,
|
||||
int64_t opt_offset,
|
||||
struct NtOverlapped *mem) {
|
||||
if (opt_offset == -1) return NULL;
|
||||
bzero(mem, sizeof(struct NtOverlapped));
|
||||
|
|
|
@ -36,89 +36,12 @@
|
|||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
#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_TMPFILE 0x00410000 /* AttributeTemporary|FlagDeleteOnClose */
|
||||
#define _O_DIRECT 0x00004000 /* kNtFileFlagNoBuffering */
|
||||
#define _O_NDELAY 0x00000800 /* kNtFileFlagWriteThrough */
|
||||
#define _O_RANDOM 0x80000000 /* kNtFileFlagRandomAccess */
|
||||
#define _O_SEQUENTIAL 0x40000000 /* kNtFileFlagSequentialScan */
|
||||
#define _O_COMPRESSED 0x20000000 /* kNtFileAttributeCompressed */
|
||||
#define _O_INDEXED 0x10000000 /* !kNtFileAttributeNotContentIndexed */
|
||||
#define _O_NONBLOCK 0x00000800
|
||||
#define _O_CLOEXEC 0x00080000
|
||||
|
||||
static textwindows int64_t sys_open_nt_impl(int dirfd, const char *path,
|
||||
uint32_t flags, int32_t mode) {
|
||||
int64_t handle;
|
||||
uint32_t br, err;
|
||||
char16_t path16[PATH_MAX];
|
||||
uint32_t perm, share, disp, attr;
|
||||
|
||||
if (__mkntpathat(dirfd, path, flags, path16) == -1) return -1;
|
||||
|
||||
switch (flags & O_ACCMODE) {
|
||||
case O_RDONLY:
|
||||
perm = kNtFileGenericRead | kNtGenericExecute;
|
||||
break;
|
||||
case O_WRONLY:
|
||||
perm = kNtFileGenericWrite | kNtGenericExecute;
|
||||
break;
|
||||
case O_RDWR:
|
||||
perm = kNtFileGenericRead | kNtFileGenericWrite | kNtGenericExecute;
|
||||
break;
|
||||
default:
|
||||
unreachable;
|
||||
}
|
||||
|
||||
if (flags & _O_EXCL) {
|
||||
share = kNtFileShareExclusive;
|
||||
} else {
|
||||
share = kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete;
|
||||
}
|
||||
|
||||
if ((flags & _O_CREAT) && (flags & _O_EXCL)) {
|
||||
disp = kNtCreateNew;
|
||||
} else if ((flags & _O_CREAT) && (flags & _O_TRUNC)) {
|
||||
disp = kNtCreateAlways;
|
||||
} else if (flags & _O_CREAT) {
|
||||
disp = kNtOpenAlways;
|
||||
} else if (flags & _O_TRUNC) {
|
||||
disp = kNtTruncateExisting;
|
||||
} else {
|
||||
disp = kNtOpenExisting;
|
||||
}
|
||||
|
||||
if ((flags & _O_TMPFILE) == _O_TMPFILE) {
|
||||
attr = kNtFileAttributeTemporary | kNtFileFlagDeleteOnClose;
|
||||
} else {
|
||||
attr = kNtFileAttributeNormal;
|
||||
if (flags & _O_DIRECTORY) attr |= kNtFileFlagBackupSemantics;
|
||||
if (~mode & 0200) {
|
||||
attr |= kNtFileAttributeReadonly;
|
||||
if (!IsTiny() && disp == kNtCreateAlways) {
|
||||
// iron out esoteric unix/win32 inconsistency (golang #38225)
|
||||
if ((handle = CreateFile(path16, perm, share, &kNtIsInheritable,
|
||||
kNtTruncateExisting, kNtFileAttributeNormal,
|
||||
0)) != -1 ||
|
||||
(errno != ENOENT && errno != ENOTDIR)) {
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flags |= kNtFileFlagOverlapped;
|
||||
if (~flags & _O_INDEXED) attr |= kNtFileAttributeNotContentIndexed;
|
||||
if (flags & _O_COMPRESSED) attr |= kNtFileAttributeCompressed;
|
||||
if (flags & _O_SEQUENTIAL) attr |= kNtFileFlagSequentialScan;
|
||||
if (flags & _O_RANDOM) attr |= kNtFileFlagRandomAccess;
|
||||
if (flags & _O_DIRECT) attr |= kNtFileFlagNoBuffering;
|
||||
if (flags & _O_NDELAY) attr |= kNtFileFlagWriteThrough;
|
||||
|
||||
if (GetNtOpenFlags(flags, mode, &perm, &share, &disp, &attr) == -1) return -1;
|
||||
return CreateFile(path16, perm, share, &kNtIsInheritable, disp, attr, 0);
|
||||
}
|
||||
|
||||
|
@ -141,6 +64,7 @@ static textwindows ssize_t sys_open_nt_console(int dirfd,
|
|||
}
|
||||
g_fds.p[fd].kind = kFdConsole;
|
||||
g_fds.p[fd].flags = flags;
|
||||
g_fds.p[fd].mode = mode;
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
@ -150,6 +74,7 @@ static textwindows ssize_t sys_open_nt_file(int dirfd, const char *file,
|
|||
if ((g_fds.p[fd].handle = sys_open_nt_impl(dirfd, file, flags, mode)) != -1) {
|
||||
g_fds.p[fd].kind = kFdFile;
|
||||
g_fds.p[fd].flags = flags;
|
||||
g_fds.p[fd].mode = mode;
|
||||
return fd;
|
||||
} else {
|
||||
return -1;
|
||||
|
@ -160,7 +85,7 @@ textwindows ssize_t sys_open_nt(int dirfd, const char *file, uint32_t flags,
|
|||
int32_t mode) {
|
||||
int fd;
|
||||
ssize_t rc;
|
||||
if ((fd = __reservefd()) == -1) return -1;
|
||||
if ((fd = __reservefd(-1)) == -1) return -1;
|
||||
if ((flags & O_ACCMODE) == O_RDWR && !strcmp(file, kNtMagicPaths.devtty)) {
|
||||
rc = sys_open_nt_console(dirfd, &kNtMagicPaths, flags, mode, fd);
|
||||
} else {
|
||||
|
|
|
@ -1,99 +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/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/nt/createfile.h"
|
||||
#include "libc/nt/enum/accessmask.h"
|
||||
#include "libc/nt/enum/creationdisposition.h"
|
||||
#include "libc/nt/enum/fileflagandattributes.h"
|
||||
#include "libc/nt/enum/filesharemode.h"
|
||||
#include "libc/str/path.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
||||
static struct OpenAnon { int count; } g_openanon;
|
||||
|
||||
static void openanon_genpath(const char *name, struct OpenAnon *state,
|
||||
char pathbuf[hasatleast PATH_MAX]) {
|
||||
char c;
|
||||
size_t i;
|
||||
char *p, *pe;
|
||||
p = stpcpy(pathbuf, kTmpPath);
|
||||
pe = pathbuf + PATH_MAX - 8 - 10 - 1 - 10 - 1;
|
||||
if (!name) name = "openanon";
|
||||
for (i = 0; p < pe; ++i) {
|
||||
if (!(c = name[i])) break;
|
||||
if (_isdirsep(c)) c = '_';
|
||||
*p++ = c;
|
||||
}
|
||||
*p++ = '.';
|
||||
p += uint64toarray_radix10(getpid(), p);
|
||||
*p++ = '.';
|
||||
p += uint64toarray_radix10(++state->count, p);
|
||||
*p = '\0';
|
||||
assert(p < pe);
|
||||
}
|
||||
|
||||
static int openanon_impl(const char *name, unsigned flags,
|
||||
struct OpenAnon *state,
|
||||
char pathbuf[hasatleast PATH_MAX]) {
|
||||
int fd;
|
||||
openanon_genpath(name, state, pathbuf);
|
||||
flags |= O_RDWR | O_CREAT | O_EXCL | O_TRUNC;
|
||||
if (!IsWindows()) {
|
||||
if ((fd = sys_openat(AT_FDCWD, pathbuf, flags, 0600)) != -1) {
|
||||
unlink(pathbuf);
|
||||
}
|
||||
return fd;
|
||||
} else {
|
||||
if ((fd = __reservefd()) == -1) return -1;
|
||||
if ((g_fds.p[fd].handle = CreateFileA(
|
||||
pathbuf, kNtGenericRead | kNtGenericWrite, kNtFileShareExclusive,
|
||||
&kNtIsInheritable, kNtCreateAlways,
|
||||
(kNtFileAttributeNotContentIndexed | kNtFileAttributeNormal |
|
||||
kNtFileAttributeTemporary | kNtFileFlagDeleteOnClose),
|
||||
0)) != -1) {
|
||||
g_fds.p[fd].kind = kFdFile;
|
||||
g_fds.p[fd].flags = flags;
|
||||
return fd;
|
||||
} else {
|
||||
__releasefd(fd);
|
||||
return __winerr();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates anonymous file.
|
||||
*
|
||||
* @param name is purely informative
|
||||
* @param flags can have O_CLOEXEC
|
||||
* @return fd of file with no name, needing close(), or -1 w/ errno
|
||||
* @see memfd_create() if disk-paranoid
|
||||
* @see mkostempsm() for named files
|
||||
*/
|
||||
int openanon(char *name, unsigned flags) {
|
||||
char pathbuf[PATH_MAX];
|
||||
return openanon_impl(name, flags, &g_openanon, pathbuf);
|
||||
}
|
|
@ -29,12 +29,13 @@ int sys_openat_metal(int dirfd, const char *file, int flags, unsigned mode) {
|
|||
struct MetalFile *state;
|
||||
if (strcmp(file, "ape.com")) return enoent();
|
||||
if (!weaken(calloc)) return enomem();
|
||||
if ((fd = __reservefd()) == -1) return -1;
|
||||
if ((fd = __reservefd(-1)) == -1) return -1;
|
||||
state = weaken(calloc)(1, sizeof(struct MetalFile));
|
||||
state->base = (char *)_base;
|
||||
state->size = _end - _base;
|
||||
g_fds.p[fd].kind = kFdFile;
|
||||
g_fds.p[fd].flags = flags;
|
||||
g_fds.p[fd].mode = mode;
|
||||
g_fds.p[fd].handle = (intptr_t)state;
|
||||
return fd;
|
||||
}
|
||||
|
|
|
@ -20,31 +20,41 @@
|
|||
#include "libc/nt/createfile.h"
|
||||
#include "libc/nt/enum/accessmask.h"
|
||||
#include "libc/nt/enum/creationdisposition.h"
|
||||
#include "libc/nt/enum/fileflagandattributes.h"
|
||||
#include "libc/nt/ipc.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int sys_pipe_nt(int pipefd[2], unsigned flags) {
|
||||
uint32_t mode;
|
||||
int64_t hin, hout;
|
||||
int reader, writer;
|
||||
char16_t pipename[64];
|
||||
if (!pipefd) return efault();
|
||||
CreatePipeName(pipename);
|
||||
if ((reader = __reservefd()) == -1) return -1;
|
||||
if ((writer = __reservefd()) == -1) {
|
||||
if ((reader = __reservefd(-1)) == -1) return -1;
|
||||
if ((writer = __reservefd(-1)) == -1) {
|
||||
__releasefd(reader);
|
||||
return -1;
|
||||
}
|
||||
if ((hin = CreateNamedPipe(pipename, kNtPipeAccessInbound,
|
||||
kNtPipeWait | kNtPipeReadmodeByte, 1, 65536, 65536,
|
||||
0, &kNtIsInheritable)) != -1) {
|
||||
if (~flags & O_DIRECT) {
|
||||
mode = kNtPipeTypeByte | kNtPipeReadmodeByte;
|
||||
} else {
|
||||
mode = kNtPipeTypeMessage | kNtPipeReadmodeMessage;
|
||||
}
|
||||
if ((hin = CreateNamedPipe(pipename,
|
||||
kNtPipeAccessInbound | kNtFileFlagOverlapped, mode,
|
||||
1, 512, 512, 0, &kNtIsInheritable)) != -1) {
|
||||
if ((hout = CreateFile(pipename, kNtGenericWrite, 0, &kNtIsInheritable,
|
||||
kNtOpenExisting, 0, 0)) != -1) {
|
||||
kNtOpenExisting, kNtFileFlagOverlapped, 0)) != -1) {
|
||||
g_fds.p[reader].kind = kFdFile;
|
||||
g_fds.p[reader].flags = flags;
|
||||
g_fds.p[reader].mode = 0010444;
|
||||
g_fds.p[reader].handle = hin;
|
||||
g_fds.p[writer].kind = kFdFile;
|
||||
g_fds.p[writer].flags = flags;
|
||||
g_fds.p[writer].mode = 0010222;
|
||||
g_fds.p[writer].handle = hout;
|
||||
pipefd[0] = reader;
|
||||
pipefd[1] = writer;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
@ -31,10 +32,18 @@
|
|||
* @see pipe2()
|
||||
*/
|
||||
int pipe(int pipefd[hasatleast 2]) {
|
||||
if (IsAsan() && !__asan_is_valid(pipefd, sizeof(int) * 2)) return efault();
|
||||
if (!IsWindows()) {
|
||||
return sys_pipe(pipefd);
|
||||
int rc;
|
||||
if (IsAsan() && !__asan_is_valid(pipefd, sizeof(int) * 2)) {
|
||||
rc = efault();
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_pipe(pipefd);
|
||||
} else {
|
||||
return sys_pipe_nt(pipefd, 0);
|
||||
rc = sys_pipe_nt(pipefd, 0);
|
||||
}
|
||||
if (!rc) {
|
||||
STRACE("pipe([{%d, %d}]) → %d% m", pipefd[0], pipefd[1], rc);
|
||||
} else {
|
||||
STRACE("pipe(%p) → %d% m", pipefd, rc);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
@ -29,11 +30,20 @@
|
|||
* @return 0 on success, or -1 w/ errno and pipefd isn't modified
|
||||
*/
|
||||
int pipe2(int pipefd[hasatleast 2], int flags) {
|
||||
if (!pipefd) return efault();
|
||||
if (IsAsan() && !__asan_is_valid(pipefd, sizeof(int) * 2)) return efault();
|
||||
if (!IsWindows()) {
|
||||
return sys_pipe2(pipefd, flags);
|
||||
int rc;
|
||||
if (!pipefd) {
|
||||
rc = efault();
|
||||
} else if (IsAsan() && !__asan_is_valid(pipefd, sizeof(int) * 2)) {
|
||||
rc = efault();
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_pipe2(pipefd, flags);
|
||||
} else {
|
||||
return sys_pipe_nt(pipefd, flags);
|
||||
rc = sys_pipe_nt(pipefd, flags);
|
||||
}
|
||||
if (!rc) {
|
||||
STRACE("pipe2([{%d, %d}], %#o) → %d% m", pipefd[0], pipefd[1], flags, rc);
|
||||
} else {
|
||||
STRACE("pipe2(%p, %#o) → %d% m", pipefd, flags, rc);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
|
58
libc/calls/printfds.c
Normal file
58
libc/calls/printfds.c
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*-*- 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 2022 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/intrin/kprintf.h"
|
||||
|
||||
static const char *__fdkind2str(int x) {
|
||||
switch (x) {
|
||||
case kFdEmpty:
|
||||
return "kFdEmpty";
|
||||
case kFdFile:
|
||||
return "kFdFile";
|
||||
case kFdSocket:
|
||||
return "kFdSocket";
|
||||
case kFdProcess:
|
||||
return "kFdProcess";
|
||||
case kFdConsole:
|
||||
return "kFdConsole";
|
||||
case kFdSerial:
|
||||
return "kFdSerial";
|
||||
case kFdZip:
|
||||
return "kFdZip";
|
||||
case kFdEpoll:
|
||||
return "kFdEpoll";
|
||||
default:
|
||||
return "kFdWut";
|
||||
}
|
||||
}
|
||||
|
||||
void __printfds(void) {
|
||||
int i;
|
||||
for (i = 0; i < g_fds.n; ++i) {
|
||||
if (!g_fds.p[i].kind) continue;
|
||||
kprintf("%3d %s", i, __fdkind2str(g_fds.p[i].kind));
|
||||
if (g_fds.p[i].zombie) kprintf(" zombie");
|
||||
if (g_fds.p[i].flags) kprintf(" flags=%#x", g_fds.p[i].flags);
|
||||
if (g_fds.p[i].mode) kprintf(" mode=%#o", g_fds.p[i].mode);
|
||||
if (g_fds.p[i].handle) kprintf(" handle=%ld", g_fds.p[i].handle);
|
||||
if (g_fds.p[i].extra) kprintf(" extra=%ld", g_fds.p[i].extra);
|
||||
if (g_fds.p[i].worker) kprintf(" worker=%p", g_fds.p[i].worker);
|
||||
kprintf("%n", g_fds.p[i].zombie);
|
||||
}
|
||||
}
|
|
@ -23,6 +23,7 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/nt/console.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
|
@ -65,7 +66,9 @@ int raise(int sig) {
|
|||
// doesn't make any sense and it's so evil.
|
||||
if (GenerateConsoleCtrlEvent(event, 0)) {
|
||||
// XXX: we shouldn't need to sleep here ctrl-c is evil on nt
|
||||
SleepEx(100, false);
|
||||
if (SleepEx(100, true) == kNtWaitIoCompletion) {
|
||||
STRACE("IOCP TRIGGERED EINTR");
|
||||
}
|
||||
__sig_check(false);
|
||||
rc = 0;
|
||||
} else {
|
||||
|
|
|
@ -20,30 +20,48 @@
|
|||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/nt/enum/wait.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/ipc.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/overlapped.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static textwindows ssize_t sys_read_nt_impl(struct Fd *fd, void *data,
|
||||
size_t size, ssize_t offset) {
|
||||
uint32_t got;
|
||||
uint32_t err, got, avail;
|
||||
struct NtOverlapped overlap;
|
||||
if (ReadFile(fd->handle, data, _clampio(size), &got,
|
||||
_offset2overlap(offset, &overlap))) {
|
||||
return got;
|
||||
} else if (
|
||||
// make sure read() returns 0 on broken pipe
|
||||
GetLastError() == kNtErrorBrokenPipe ||
|
||||
// make sure pread() returns 0 if we start reading after EOF
|
||||
GetLastError() == kNtErrorHandleEof) {
|
||||
return 0;
|
||||
} else {
|
||||
return __winerr();
|
||||
if (fd->worker) {
|
||||
for (;;) {
|
||||
if (!PeekNamedPipe(fd->handle, 0, 0, 0, &avail, 0)) break;
|
||||
if (avail) break;
|
||||
if (SleepEx(__SIG_POLLING_INTERVAL_MS, true) == kNtWaitIoCompletion ||
|
||||
_check_interrupts(true, g_fds.p)) {
|
||||
return eintr();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ReadFile(fd->handle, data, _clampio(size), &got,
|
||||
_offset2overlap(fd->handle, offset, &overlap))) {
|
||||
return got;
|
||||
}
|
||||
err = GetLastError();
|
||||
// make sure read() returns 0 on broken pipe
|
||||
if (err == kNtErrorBrokenPipe) return 0;
|
||||
// make sure read() returns 0 on closing named pipe
|
||||
if (err == kNtErrorNoData) return 0;
|
||||
// make sure pread() returns 0 if we start reading after EOF
|
||||
if (err == kNtErrorHandleEof) return 0;
|
||||
return __winerr();
|
||||
}
|
||||
|
||||
textwindows ssize_t sys_read_nt(struct Fd *fd, const struct iovec *iov,
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
|
|
@ -28,7 +28,7 @@ textwindows ssize_t sys_readv_nt(struct Fd *fd, const struct iovec *iov,
|
|||
case kFdConsole:
|
||||
return sys_read_nt(fd, iov, iovlen, -1);
|
||||
case kFdSocket:
|
||||
return weaken(sys_recvfrom_nt)(fd, iov, iovlen, 0, NULL, 0);
|
||||
return weaken(sys_recv_nt)(fd, iov, iovlen, 0);
|
||||
default:
|
||||
return ebadf();
|
||||
}
|
||||
|
|
|
@ -37,7 +37,9 @@ static int GetFirstIov(struct iovec *iov, int iovlen) {
|
|||
ssize_t sys_readv_serial(struct Fd *fd, const struct iovec *iov, int iovlen) {
|
||||
size_t i;
|
||||
if ((i = GetFirstIov(iov, iovlen)) != -1) {
|
||||
while (!IsDataAvailable(fd)) asm("pause");
|
||||
while (!IsDataAvailable(fd)) {
|
||||
__builtin_ia32_pause();
|
||||
}
|
||||
((char *)iov[i].iov_base)[0] = inb(fd->handle);
|
||||
return 1;
|
||||
} else {
|
||||
|
|
|
@ -17,16 +17,14 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/intrin/cmpxchg.h"
|
||||
#include "libc/intrin/lockcmpxchg.h"
|
||||
#include "libc/intrin/spinlock.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
void __releasefd(int fd) {
|
||||
int x;
|
||||
if (!__vforked && 0 <= fd && fd < g_fds.n) {
|
||||
bzero(g_fds.p + fd, sizeof(*g_fds.p));
|
||||
do {
|
||||
x = g_fds.f;
|
||||
if (fd >= x) break;
|
||||
} while (!_lockcmpxchg(&g_fds.f, x, fd));
|
||||
if (0 <= fd && fd < g_fds.n) {
|
||||
_spinlock(&__fds_lock);
|
||||
g_fds.p[fd].kind = 0;
|
||||
g_fds.f = MIN(fd, g_fds.f);
|
||||
_spunlock(&__fds_lock);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,24 +16,98 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/intrin/cmpxchg.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/spinlock.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Grows file descriptor array memory if needed.
|
||||
*/
|
||||
int __ensurefds(int fd) {
|
||||
size_t n1, n2;
|
||||
struct Fd *p1, *p2;
|
||||
_spinlock(&__fds_lock);
|
||||
n1 = g_fds.n;
|
||||
if (fd >= n1) {
|
||||
STRACE("__ensurefds(%d) extending", fd);
|
||||
if (weaken(malloc)) {
|
||||
// TODO(jart): we need a semaphore for this
|
||||
p1 = g_fds.p;
|
||||
n2 = fd + (fd >> 1);
|
||||
if ((p2 = weaken(malloc)(n2 * sizeof(*p1)))) {
|
||||
memcpy(p2, p1, n1 * sizeof(*p1));
|
||||
g_fds.p = p2;
|
||||
g_fds.n = n2;
|
||||
if (p1 != g_fds.__init_p) {
|
||||
weaken(free)(p1);
|
||||
}
|
||||
} else {
|
||||
fd = enomem();
|
||||
}
|
||||
} else {
|
||||
fd = emfile();
|
||||
}
|
||||
}
|
||||
_spunlock(&__fds_lock);
|
||||
return fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds open file descriptor slot.
|
||||
*/
|
||||
int __reservefd(void) {
|
||||
int __reservefd(int start) {
|
||||
int fd;
|
||||
for (;;) {
|
||||
fd = g_fds.f;
|
||||
if (fd >= g_fds.n) {
|
||||
if (__ensurefds(fd) == -1) return -1;
|
||||
}
|
||||
_cmpxchg(&g_fds.f, fd, fd + 1);
|
||||
if (_cmpxchg(&g_fds.p[fd].kind, kFdEmpty, kFdReserved)) {
|
||||
_spinlock(&__fds_lock);
|
||||
fd = start < 0 ? g_fds.f : start;
|
||||
while (fd < g_fds.n && g_fds.p[fd].kind) ++fd;
|
||||
if (fd < g_fds.n) {
|
||||
g_fds.f = fd + 1;
|
||||
bzero(g_fds.p + fd, sizeof(*g_fds.p));
|
||||
g_fds.p[fd].kind = kFdReserved;
|
||||
_spunlock(&__fds_lock);
|
||||
return fd;
|
||||
} else {
|
||||
_spunlock(&__fds_lock);
|
||||
if (__ensurefds(fd) == -1) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes non-stdio file descriptors to free dynamic memory.
|
||||
*/
|
||||
static void __freefds(void) {
|
||||
int i;
|
||||
STRACE("__freefds()");
|
||||
for (i = 3; i < g_fds.n; ++i) {
|
||||
if (g_fds.p[i].kind) {
|
||||
close(i);
|
||||
}
|
||||
}
|
||||
if (g_fds.p != g_fds.__init_p) {
|
||||
memcpy(g_fds.__init_p, g_fds.p, sizeof(*g_fds.p) * 3);
|
||||
weaken(free)(g_fds.p);
|
||||
g_fds.p = g_fds.__init_p;
|
||||
g_fds.n = ARRAYLEN(g_fds.__init_p);
|
||||
}
|
||||
}
|
||||
|
||||
static textstartup void __freefds_init(void) {
|
||||
atexit(__freefds);
|
||||
}
|
||||
|
||||
const void *const __freefds_ctor[] initarray = {
|
||||
__freefds_init,
|
||||
};
|
||||
|
|
32
libc/calls/setgid.c
Normal file
32
libc/calls/setgid.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- 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 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
|
||||
/**
|
||||
* Sets effective group id of current process.
|
||||
* @return 0 on success or -1 w/ errno
|
||||
*/
|
||||
int setgid(int gid) {
|
||||
int rc;
|
||||
rc = sys_setgid(gid);
|
||||
STRACE("%s(%d) → %d% m", "setgid", gid);
|
||||
return rc;
|
||||
}
|
32
libc/calls/setuid.c
Normal file
32
libc/calls/setuid.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- 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 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
|
||||
/**
|
||||
* Sets effective group id of current process.
|
||||
* @return 0 on success or -1 w/ errno
|
||||
*/
|
||||
int setuid(int uid) {
|
||||
int rc;
|
||||
rc = sys_setuid(uid);
|
||||
STRACE("%s(%d) → %d% m", "setuid", uid);
|
||||
return rc;
|
||||
}
|
|
@ -38,7 +38,7 @@ textwindows int __sig_mask(int how, const sigset_t *neu, sigset_t *old) {
|
|||
int i;
|
||||
uint64_t a, b;
|
||||
if (how == SIG_BLOCK || how == SIG_UNBLOCK || how == SIG_SETMASK) {
|
||||
cthread_spinlock(&__sig_lock);
|
||||
_spinlock(&__sig_lock);
|
||||
if (old) {
|
||||
*old = __sig.mask;
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ textwindows int __sig_mask(int how, const sigset_t *neu, sigset_t *old) {
|
|||
}
|
||||
__sig.mask.__bits[0] &= ~(SIGKILL | SIGSTOP);
|
||||
}
|
||||
cthread_spunlock(&__sig_lock);
|
||||
_spunlock(&__sig_lock);
|
||||
return 0;
|
||||
} else {
|
||||
return einval();
|
||||
|
|
|
@ -64,7 +64,7 @@ static textwindows void __sig_free(struct Signal *mem) {
|
|||
static textwindows struct Signal *__sig_remove(void) {
|
||||
struct Signal *prev, *res;
|
||||
if (__sig.queue) {
|
||||
cthread_spinlock(&__sig_lock);
|
||||
_spinlock(&__sig_lock);
|
||||
for (prev = 0, res = __sig.queue; res; prev = res, res = res->next) {
|
||||
if (!sigismember(&__sig.mask, res->sig)) {
|
||||
if (res == __sig.queue) {
|
||||
|
@ -78,7 +78,7 @@ static textwindows struct Signal *__sig_remove(void) {
|
|||
STRACE("%G is masked", res->sig);
|
||||
}
|
||||
}
|
||||
cthread_spunlock(&__sig_lock);
|
||||
_spunlock(&__sig_lock);
|
||||
} else {
|
||||
res = 0;
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ static textwindows bool __sig_deliver(bool restartable, int sig, int si_code,
|
|||
STRACE("delivering %G", sig);
|
||||
|
||||
// enter the signal
|
||||
cthread_spinlock(&__sig_lock);
|
||||
_spinlock(&__sig_lock);
|
||||
rva = __sighandrvas[sig];
|
||||
flags = __sighandflags[sig];
|
||||
if ((~flags & SA_NODEFER) || (flags & SA_RESETHAND)) {
|
||||
|
@ -108,7 +108,7 @@ static textwindows bool __sig_deliver(bool restartable, int sig, int si_code,
|
|||
// signal handler. in that case you must use SA_NODEFER.
|
||||
__sighandrvas[sig] = (int32_t)(intptr_t)SIG_DFL;
|
||||
}
|
||||
cthread_spunlock(&__sig_lock);
|
||||
_spunlock(&__sig_lock);
|
||||
|
||||
// setup the somewhat expensive information args
|
||||
// only if they're requested by the user in sigaction()
|
||||
|
@ -130,9 +130,9 @@ static textwindows bool __sig_deliver(bool restartable, int sig, int si_code,
|
|||
// since sigaction() is @asyncsignalsafe we only restore it if the
|
||||
// user didn't change it during the signal handler. we also don't
|
||||
// need to do anything if this was a oneshot signal or nodefer.
|
||||
cthread_spinlock(&__sig_lock);
|
||||
_spinlock(&__sig_lock);
|
||||
_cmpxchg(__sighandrvas + sig, (int32_t)(intptr_t)SIG_DFL, rva);
|
||||
cthread_spunlock(&__sig_lock);
|
||||
_spunlock(&__sig_lock);
|
||||
}
|
||||
|
||||
if (!restartable) {
|
||||
|
@ -192,9 +192,9 @@ textwindows bool __sig_handle(bool restartable, int sig, int si_code,
|
|||
textwindows int __sig_raise(int sig, int si_code) {
|
||||
int rc;
|
||||
int candeliver;
|
||||
cthread_spinlock(&__sig_lock);
|
||||
_spinlock(&__sig_lock);
|
||||
candeliver = !sigismember(&__sig.mask, sig);
|
||||
cthread_spunlock(&__sig_lock);
|
||||
_spunlock(&__sig_lock);
|
||||
switch (candeliver) {
|
||||
case 1:
|
||||
__sig_handle(false, sig, si_code, 0);
|
||||
|
@ -217,7 +217,7 @@ textwindows int __sig_add(int sig, int si_code) {
|
|||
struct Signal *mem;
|
||||
if (1 <= sig && sig <= NSIG) {
|
||||
STRACE("enqueuing %G", sig);
|
||||
cthread_spinlock(&__sig_lock);
|
||||
_spinlock(&__sig_lock);
|
||||
if ((mem = __sig_alloc())) {
|
||||
mem->sig = sig;
|
||||
mem->si_code = si_code;
|
||||
|
@ -227,7 +227,7 @@ textwindows int __sig_add(int sig, int si_code) {
|
|||
} else {
|
||||
rc = enomem();
|
||||
}
|
||||
cthread_spunlock(&__sig_lock);
|
||||
_spunlock(&__sig_lock);
|
||||
} else {
|
||||
rc = einval();
|
||||
}
|
||||
|
|
|
@ -213,7 +213,7 @@ static int __sigaction(int sig, const struct sigaction *act,
|
|||
rc = 0;
|
||||
}
|
||||
if (rc != -1 && !__vforked) {
|
||||
cthread_spinlock(&__sig_lock);
|
||||
_spinlock(&__sig_lock);
|
||||
if (oldact) {
|
||||
oldrva = __sighandrvas[sig];
|
||||
oldact->sa_sigaction = (sigaction_f)(
|
||||
|
@ -223,7 +223,7 @@ static int __sigaction(int sig, const struct sigaction *act,
|
|||
__sighandrvas[sig] = rva;
|
||||
__sighandflags[sig] = act->sa_flags;
|
||||
}
|
||||
cthread_spunlock(&__sig_lock);
|
||||
_spunlock(&__sig_lock);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/log/backtrace.internal.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
|
@ -76,7 +77,11 @@ int sigsuspend(const sigset_t *ignore) {
|
|||
rc = eintr();
|
||||
break;
|
||||
}
|
||||
SleepEx(__SIG_POLLING_INTERVAL_MS, true);
|
||||
if (SleepEx(__SIG_POLLING_INTERVAL_MS, true) == kNtWaitIoCompletion) {
|
||||
STRACE("IOCP TRIGGERED EINTR");
|
||||
rc = eintr();
|
||||
break;
|
||||
}
|
||||
#ifdef SYSDEBUG
|
||||
ms += __SIG_POLLING_INTERVAL_MS;
|
||||
if (ms >= __SIG_LOGGING_INTERVAL_MS) {
|
||||
|
|
|
@ -67,7 +67,7 @@ static textwindows int sys_wait4_nt_impl(int pid, int *opt_out_wstatus,
|
|||
if (!__isfdopen(pid) &&
|
||||
(handle = OpenProcess(kNtSynchronize | kNtProcessQueryInformation,
|
||||
true, pid))) {
|
||||
if ((pid = __reservefd()) != -1) {
|
||||
if ((pid = __reservefd(-1)) != -1) {
|
||||
g_fds.p[pid].kind = kFdProcess;
|
||||
g_fds.p[pid].handle = handle;
|
||||
g_fds.p[pid].flags = O_CLOEXEC;
|
||||
|
@ -111,6 +111,8 @@ static textwindows int sys_wait4_nt_impl(int pid, int *opt_out_wstatus,
|
|||
}
|
||||
if (opt_out_rusage) {
|
||||
bzero(opt_out_rusage, sizeof(*opt_out_rusage));
|
||||
bzero(&memcount, sizeof(memcount));
|
||||
memcount.cb = sizeof(struct NtProcessMemoryCountersEx);
|
||||
if (GetProcessMemoryInfo(handles[i], &memcount, sizeof(memcount))) {
|
||||
opt_out_rusage->ru_maxrss = memcount.PeakWorkingSetSize / 1024;
|
||||
opt_out_rusage->ru_majflt = memcount.PageFaultCount;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/calls/sigbits.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/typedef/sigaction_f.h"
|
||||
#include "libc/calls/ucontext.h"
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include "libc/macros.internal.h"
|
||||
|
||||
.init.start 300,_init_wincrash
|
||||
mov __wincrashearly(%rip),%rcx
|
||||
ntcall __imp_RemoveVectoredExceptionHandler
|
||||
pushpop 1,%rcx
|
||||
ezlea __wincrash_nt,dx
|
||||
ntcall __imp_AddVectoredExceptionHandler
|
||||
|
|
20
libc/calls/wincrashearly.c
Normal file
20
libc/calls/wincrashearly.c
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*-*- 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 2022 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. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
|
||||
int64_t __wincrashearly;
|
|
@ -23,12 +23,14 @@
|
|||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/calls/struct/siginfo.h"
|
||||
#include "libc/calls/typedef/sigaction_f.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/overlapped.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/sicode.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
|
@ -36,17 +38,20 @@
|
|||
|
||||
static textwindows ssize_t sys_write_nt_impl(int fd, void *data, size_t size,
|
||||
ssize_t offset) {
|
||||
uint32_t sent;
|
||||
uint32_t err, sent;
|
||||
struct NtOverlapped overlap;
|
||||
if (WriteFile(g_fds.p[fd].handle, data, _clampio(size), &sent,
|
||||
_offset2overlap(offset, &overlap))) {
|
||||
_offset2overlap(g_fds.p[fd].handle, offset, &overlap))) {
|
||||
return sent;
|
||||
} else if (GetLastError() == kNtErrorBrokenPipe) {
|
||||
}
|
||||
err = GetLastError();
|
||||
// make sure write() raises SIGPIPE on broken pipe
|
||||
// make sure write() raises SIGPIPE on closing named pipe
|
||||
if (err == kNtErrorBrokenPipe || err == kNtErrorNoData) {
|
||||
__sig_raise(SIGPIPE, SI_KERNEL);
|
||||
return epipe();
|
||||
} else {
|
||||
return __winerr();
|
||||
}
|
||||
return __winerr();
|
||||
}
|
||||
|
||||
textwindows ssize_t sys_write_nt(int fd, const struct iovec *iov, size_t iovlen,
|
||||
|
|
|
@ -27,7 +27,7 @@ textwindows ssize_t sys_writev_nt(int fd, const struct iovec *iov, int iovlen) {
|
|||
case kFdConsole:
|
||||
return sys_write_nt(fd, iov, iovlen, -1);
|
||||
case kFdSocket:
|
||||
return weaken(sys_sendto_nt)(fd, iov, iovlen, 0, NULL, 0);
|
||||
return weaken(sys_send_nt)(fd, iov, iovlen, 0);
|
||||
default:
|
||||
return ebadf();
|
||||
}
|
||||
|
|
|
@ -24,7 +24,9 @@ ssize_t sys_writev_serial(struct Fd *fd, const struct iovec *iov, int iovlen) {
|
|||
size_t i, j, wrote = 0;
|
||||
for (i = 0; i < iovlen; ++i) {
|
||||
for (j = 0; j < iov[i].iov_len; ++j) {
|
||||
while (!(inb(fd->handle + UART_LSR) & UART_TTYTXR)) asm("pause");
|
||||
while (!(inb(fd->handle + UART_LSR) & UART_TTYTXR)) {
|
||||
__builtin_ia32_pause();
|
||||
}
|
||||
outb(fd->handle, ((char *)iov[i].iov_base)[j]);
|
||||
++wrote;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue