mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 06:53:33 +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
|
@ -33,8 +33,6 @@ dontinline void dostuff(const char *s) {
|
|||
|
||||
int main(int argc, char *argv[]) {
|
||||
int rc, child, wstatus;
|
||||
/* puts(_gc(xiso8601ts(NULL))); */
|
||||
PrintMemoryIntervals(2, &_mmi);
|
||||
CHECK_NE(-1, (child = fork()));
|
||||
if (!child) {
|
||||
/* child process */
|
||||
|
|
|
@ -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);
|
||||
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;
|
||||
}
|
||||
g_fds.p[fd].flags = flags;
|
||||
return 0;
|
||||
}
|
||||
return __winerr();
|
||||
} else if (status == kNtStatusDllNotFound) {
|
||||
return enosys();
|
||||
} 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];
|
||||
|
|
|
@ -16,35 +16,16 @@
|
|||
│ 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/calls/strace.internal.h"
|
||||
#include "libc/intrin/lockcmpxchg.h"
|
||||
#include "libc/intrin/spinlock.h"
|
||||
|
||||
/**
|
||||
* Acquires spinlock.
|
||||
* Returns effective user ID of calling process.
|
||||
*/
|
||||
void cthread_spinlock(cthread_spinlock_t *lock) {
|
||||
#if 0
|
||||
// TODO(jart): possibly reenable for !NDEBUG when we have TLS
|
||||
int me = gettid();
|
||||
if (lock->x && lock->owner == me) {
|
||||
assert(!"cosmo spinlock not intended to be reentrant");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
do
|
||||
while (lock->x) asm("pause");
|
||||
while (!_lockcmpxchg(&lock->x, false, true));
|
||||
#if 0
|
||||
lock->owner = me;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases spinlock.
|
||||
*/
|
||||
void cthread_spunlock(cthread_spinlock_t *lock) {
|
||||
lock->x = false;
|
||||
uint32_t geteuid(void) {
|
||||
int rc;
|
||||
rc = sys_geteuid();
|
||||
STRACE("%s() → %d% m", "geteuid", rc);
|
||||
return rc;
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
/*-*- 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,13 +16,13 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/sock/ntstdin.internal.h"
|
||||
|
||||
// Sneak ahead ctor list b/c runtime weakly links malloc.
|
||||
.init.start 800,_init_dlmalloc
|
||||
push %rdi
|
||||
push %rsi
|
||||
call dlmalloc_init
|
||||
pop %rsi
|
||||
pop %rdi
|
||||
.init.end 800,_init_dlmalloc,globl,hidden
|
||||
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,31 +20,49 @@
|
|||
#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,
|
||||
size_t iovlen, ssize_t opt_offset) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ int vsscanf(const char *, const char *, va_list);
|
|||
int vcscanf(int (*)(void *), int (*)(int, void *), void *, const char *,
|
||||
va_list);
|
||||
int strerror_r(int, char *, size_t) dontthrow nocallback;
|
||||
int strerror_wr(int, uint32_t, char *, size_t) dontthrow nocallback;
|
||||
const char *strerror_short(int) nosideeffect;
|
||||
const char *strerror_long(int) nosideeffect;
|
||||
int __fmt(void *, void *, const char *, va_list) hidden;
|
||||
|
|
|
@ -16,23 +16,8 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#define ShouldUseMsabiAttribute() 1
|
||||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nexgen32e/bsr.h"
|
||||
#include "libc/nt/enum/formatmessageflags.h"
|
||||
#include "libc/nt/enum/lang.h"
|
||||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tpenc.h"
|
||||
|
||||
/**
|
||||
* Converts errno value to string.
|
||||
|
@ -41,32 +26,5 @@
|
|||
* @return 0 on success, or error code
|
||||
*/
|
||||
privileged int strerror_r(int err, char *buf, size_t size) {
|
||||
/* kprintf() weakly depends on this function */
|
||||
int c, n, winerr;
|
||||
char16_t winmsg[256];
|
||||
const char *sym, *msg;
|
||||
sym = firstnonnull(strerror_short(err), "EUNKNOWN");
|
||||
msg = firstnonnull(strerror_long(err), "No error information");
|
||||
if (IsTiny()) {
|
||||
if (!sym) sym = "EUNKNOWN";
|
||||
for (; (c = *sym++); --size)
|
||||
if (size > 1) *buf++ = c;
|
||||
if (size) *buf = 0;
|
||||
} else if (!IsWindows()) {
|
||||
ksnprintf(buf, size, "%s[%d][%s]", sym, err, msg);
|
||||
} else {
|
||||
winerr = __imp_GetLastError();
|
||||
if ((n = __imp_FormatMessageW(
|
||||
kNtFormatMessageFromSystem | kNtFormatMessageIgnoreInserts, 0,
|
||||
winerr, MAKELANGID(kNtLangNeutral, kNtSublangDefault), winmsg,
|
||||
ARRAYLEN(winmsg), 0))) {
|
||||
while ((n && winmsg[n - 1] <= ' ') || winmsg[n - 1] == '.') --n;
|
||||
ksnprintf(buf, size, "%s[%d][%s][%.*hs][%d]", sym, err, msg, n, winmsg,
|
||||
winerr);
|
||||
} else {
|
||||
ksnprintf(buf, size, "%s[%d][%s][%d]", sym, err, msg, winerr);
|
||||
}
|
||||
__imp_SetLastError(winerr);
|
||||
}
|
||||
return 0;
|
||||
return strerror_wr(err, GetLastError(), buf, size);
|
||||
}
|
||||
|
|
62
libc/fmt/strerror_wr.greg.c
Normal file
62
libc/fmt/strerror_wr.greg.c
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*-*- 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. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#define ShouldUseMsabiAttribute() 1
|
||||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/enum/formatmessageflags.h"
|
||||
#include "libc/nt/enum/lang.h"
|
||||
#include "libc/nt/process.h"
|
||||
|
||||
/**
|
||||
* Converts errno value to string with explicit windows errno too.
|
||||
*
|
||||
* @param err is error number or zero if unknown
|
||||
* @return 0 on success, or error code
|
||||
*/
|
||||
privileged int strerror_wr(int err, uint32_t winerr, char *buf, size_t size) {
|
||||
/* kprintf() weakly depends on this function */
|
||||
int c, n;
|
||||
char16_t winmsg[256];
|
||||
const char *sym, *msg;
|
||||
sym = firstnonnull(strerror_short(err), "EUNKNOWN");
|
||||
msg = firstnonnull(strerror_long(err), "No error information");
|
||||
if (IsTiny()) {
|
||||
if (!sym) sym = "EUNKNOWN";
|
||||
for (; (c = *sym++); --size)
|
||||
if (size > 1) *buf++ = c;
|
||||
if (size) *buf = 0;
|
||||
} else if (!IsWindows()) {
|
||||
ksnprintf(buf, size, "%s[%d][%s]", sym, err, msg);
|
||||
} else {
|
||||
if ((n = __imp_FormatMessageW(
|
||||
kNtFormatMessageFromSystem | kNtFormatMessageIgnoreInserts, 0,
|
||||
winerr, MAKELANGID(kNtLangNeutral, kNtSublangDefault), winmsg,
|
||||
ARRAYLEN(winmsg), 0))) {
|
||||
while ((n && winmsg[n - 1] <= ' ') || winmsg[n - 1] == '.') --n;
|
||||
ksnprintf(buf, size, "%s[%d][%s][%.*hs][%d]", sym, err, msg, n, winmsg,
|
||||
winerr);
|
||||
} else {
|
||||
ksnprintf(buf, size, "%s[%d][%s][%d]", sym, err, msg, winerr);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -51,7 +51,7 @@
|
|||
#include "libc/sysv/consts/nr.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "third_party/dlmalloc/dlmalloc.internal.h"
|
||||
#include "third_party/dlmalloc/dlmalloc.h"
|
||||
|
||||
STATIC_YOINK("_init_asan");
|
||||
|
||||
|
@ -177,8 +177,7 @@ static uint64_t __asan_roundup2pow(uint64_t x) {
|
|||
static char *__asan_utf8cpy(char *p, unsigned c) {
|
||||
uint64_t z;
|
||||
z = tpenc(c);
|
||||
do
|
||||
*p++ = z;
|
||||
do *p++ = z;
|
||||
while ((z >>= 8));
|
||||
return p;
|
||||
}
|
||||
|
@ -922,8 +921,7 @@ static void __asan_trace(struct AsanTrace *bt, const struct StackFrame *bp) {
|
|||
if (!__asan_checka(SHADOW(bp), sizeof(*bp) >> 3).kind) {
|
||||
addr = bp->addr;
|
||||
if (addr == weakaddr("__gc") && weakaddr("__gc")) {
|
||||
do
|
||||
--gi;
|
||||
do --gi;
|
||||
while ((addr = garbage->p[gi].ret) == weakaddr("__gc"));
|
||||
}
|
||||
bt->p[i] = addr;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/intrin/cmpxchg.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/lockcmpxchg.h"
|
||||
|
@ -32,6 +33,8 @@ relegated wontreturn void __assert_fail(const char *expr, const char *file,
|
|||
int line) {
|
||||
int rc;
|
||||
static bool noreentry;
|
||||
__strace = 0;
|
||||
g_ftrace = 0;
|
||||
kprintf("%s:%d: assert(%s) failed%n", file, line, expr);
|
||||
if (_lockcmpxchg(&noreentry, false, true)) {
|
||||
if (weaken(__die)) {
|
||||
|
|
|
@ -16,12 +16,14 @@
|
|||
│ 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/calls/strace.internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
|
||||
extern typeof(CloseHandle) *const __imp_CloseHandle __msabi;
|
||||
__msabi extern typeof(CloseHandle) *const __imp_CloseHandle;
|
||||
|
||||
/**
|
||||
* Closes an open object handle.
|
||||
|
@ -30,7 +32,10 @@ extern typeof(CloseHandle) *const __imp_CloseHandle __msabi;
|
|||
textwindows bool32 CloseHandle(int64_t hObject) {
|
||||
bool32 ok;
|
||||
ok = __imp_CloseHandle(hObject);
|
||||
if (!ok) __winerr();
|
||||
if (!ok) {
|
||||
__winerr();
|
||||
if (weaken(__die)) weaken(__die)();
|
||||
}
|
||||
STRACE("CloseHandle(%ld) → %hhhd% m", hObject, ok);
|
||||
return ok;
|
||||
}
|
||||
|
|
|
@ -18,10 +18,11 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
|
||||
extern typeof(CreateDirectory) *const __imp_CreateDirectoryW __msabi;
|
||||
__msabi extern typeof(CreateDirectory) *const __imp_CreateDirectoryW;
|
||||
|
||||
/**
|
||||
* Creates directory on the New Technology.
|
||||
|
@ -35,7 +36,7 @@ CreateDirectory(const char16_t *lpPathName,
|
|||
bool32 ok;
|
||||
ok = __imp_CreateDirectoryW(lpPathName, lpSecurityAttributes);
|
||||
if (!ok) __winerr();
|
||||
STRACE("CreateDirectory(%#hs, %p) → %hhhd% m", lpPathName,
|
||||
lpSecurityAttributes, ok);
|
||||
STRACE("CreateDirectory(%#hs, %s) → %hhhd% m", lpPathName,
|
||||
DescribeNtSecurityAttributes(lpSecurityAttributes), ok);
|
||||
return ok;
|
||||
}
|
||||
|
|
|
@ -20,27 +20,9 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/nt/createfile.h"
|
||||
#include "libc/nt/enum/creationdisposition.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
|
||||
extern typeof(CreateFile) *const __imp_CreateFileW __msabi;
|
||||
|
||||
static const char *DescribeDisposition(int x) {
|
||||
switch (x) {
|
||||
case kNtCreateNew:
|
||||
return "kNtCreateNew";
|
||||
case kNtCreateAlways:
|
||||
return "kNtCreateAlways";
|
||||
case kNtOpenExisting:
|
||||
return "kNtOpenExisting";
|
||||
case kNtOpenAlways:
|
||||
return "kNtOpenAlways";
|
||||
case kNtTruncateExisting:
|
||||
return "kNtTruncateExisting";
|
||||
default:
|
||||
return "wut";
|
||||
}
|
||||
}
|
||||
__msabi extern typeof(CreateFile) *const __imp_CreateFileW;
|
||||
|
||||
/**
|
||||
* Opens file on the New Technology.
|
||||
|
@ -58,10 +40,11 @@ textwindows int64_t CreateFile(
|
|||
opt_lpSecurityAttributes, dwCreationDisposition,
|
||||
dwFlagsAndAttributes, opt_hTemplateFile);
|
||||
if (hHandle == -1) __winerr();
|
||||
STRACE("CreateFile(%#hs, %s, %s, %p, %s, %s, %ld) → %ld% m", lpFileName,
|
||||
STRACE("CreateFile(%#hs, %s, %s, %s, %s, %s, %ld) → %ld% m", lpFileName,
|
||||
DescribeNtFileAccessFlags(dwDesiredAccess),
|
||||
DescribeNtFileShareFlags(dwShareMode), opt_lpSecurityAttributes,
|
||||
DescribeDisposition(dwCreationDisposition),
|
||||
DescribeNtFileShareFlags(dwShareMode),
|
||||
DescribeNtSecurityAttributes(opt_lpSecurityAttributes),
|
||||
DescribeNtCreationDisposition(dwCreationDisposition),
|
||||
DescribeNtFileFlagsAndAttributes(dwFlagsAndAttributes),
|
||||
opt_hTemplateFile, hHandle);
|
||||
return hHandle;
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include "libc/nt/struct/securityattributes.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
|
||||
extern typeof(CreateFileMapping) *const __imp_CreateFileMappingW __msabi;
|
||||
__msabi extern typeof(CreateFileMapping) *const __imp_CreateFileMappingW;
|
||||
|
||||
/**
|
||||
* Creates file mapping object on the New Technology.
|
||||
|
@ -43,7 +43,8 @@ textwindows int64_t CreateFileMapping(
|
|||
flProtect, dwMaximumSizeHigh,
|
||||
dwMaximumSizeLow, opt_lpName);
|
||||
if (!hHandle) __winerr();
|
||||
STRACE("CreateFileMapping(%ld, %s, max:%'zu, name:%#hs) → %ld% m", opt_hFile,
|
||||
STRACE("CreateFileMapping(%ld, %s, %s, %'zu, %#hs) → %ld% m", opt_hFile,
|
||||
DescribeNtSecurityAttributes(opt_lpFileMappingAttributes),
|
||||
DescribeNtPageFlags(flProtect),
|
||||
(uint64_t)dwMaximumSizeHigh << 32 | dwMaximumSizeLow, opt_lpName,
|
||||
hHandle);
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/struct/securityattributes.h"
|
||||
|
||||
extern typeof(CreateFileMappingNuma) *const
|
||||
__imp_CreateFileMappingNumaW __msabi;
|
||||
__msabi extern typeof(CreateFileMappingNuma) *const
|
||||
__imp_CreateFileMappingNumaW;
|
||||
|
||||
/**
|
||||
* Creates file mapping object on the New Technology.
|
||||
|
@ -44,8 +44,9 @@ textwindows int64_t CreateFileMappingNuma(
|
|||
opt_hFile, opt_lpFileMappingAttributes, flProtect, dwMaximumSizeHigh,
|
||||
dwMaximumSizeLow, opt_lpName, nndDesiredNumaNode);
|
||||
if (!hHandle) __winerr();
|
||||
STRACE("CreateFileMappingNuma(%ld, %s, max:%'zu, name:%#hs) → %ld% m",
|
||||
opt_hFile, DescribeNtPageFlags(flProtect),
|
||||
STRACE("CreateFileMappingNuma(%ld, %s, %s, %'zu, %#hs) → %ld% m", opt_hFile,
|
||||
DescribeNtSecurityAttributes(opt_lpFileMappingAttributes),
|
||||
DescribeNtPageFlags(flProtect),
|
||||
(uint64_t)dwMaximumSizeHigh << 32 | dwMaximumSizeLow, opt_lpName,
|
||||
hHandle);
|
||||
return hHandle;
|
||||
|
|
|
@ -18,11 +18,12 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/nt/ipc.h"
|
||||
#include "libc/nt/struct/securityattributes.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
|
||||
extern typeof(CreateNamedPipe) *const __imp_CreateNamedPipeW __msabi;
|
||||
__msabi extern typeof(CreateNamedPipe) *const __imp_CreateNamedPipeW;
|
||||
|
||||
/**
|
||||
* Creates pipe.
|
||||
|
@ -40,16 +41,10 @@ textwindows int64_t CreateNamedPipe(
|
|||
nMaxInstances, nOutBufferSize, nInBufferSize,
|
||||
nDefaultTimeOutMs, opt_lpSecurityAttributes);
|
||||
if (hServer == -1) __winerr();
|
||||
STRACE("CreateNamedPipe(%#hs,"
|
||||
" dwOpenMode=%u,"
|
||||
" dwPipeMode=%u,"
|
||||
" nMaxInstances=%u,"
|
||||
" nOutBufferSize=%'u,"
|
||||
" nInBufferSize=%'u,"
|
||||
" nDefaultTimeOutMs=%'u,"
|
||||
" lpSecurity=%p) → "
|
||||
"%ld% m",
|
||||
lpName, dwOpenMode, dwPipeMode, nMaxInstances, nOutBufferSize,
|
||||
nInBufferSize, nDefaultTimeOutMs, opt_lpSecurityAttributes, hServer);
|
||||
STRACE("CreateNamedPipe(%#hs, %s, %s, %u, %'u, %'u, %'u, %s) → %ld% m",
|
||||
lpName, DescribeNtPipeOpenFlags(dwOpenMode),
|
||||
DescribeNtPipeModeFlags(dwPipeMode), nMaxInstances, nOutBufferSize,
|
||||
nInBufferSize, nDefaultTimeOutMs,
|
||||
DescribeNtSecurityAttributes(opt_lpSecurityAttributes), hServer);
|
||||
return hServer;
|
||||
}
|
||||
|
|
|
@ -18,11 +18,12 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/nt/ipc.h"
|
||||
#include "libc/nt/struct/securityattributes.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
|
||||
extern typeof(CreatePipe) *const __imp_CreatePipe __msabi;
|
||||
__msabi extern typeof(CreatePipe) *const __imp_CreatePipe;
|
||||
|
||||
/**
|
||||
* Creates anonymous pipe.
|
||||
|
@ -35,7 +36,8 @@ textwindows bool32 CreatePipe(
|
|||
ok = __imp_CreatePipe(out_hReadPipe, out_hWritePipe, opt_lpPipeAttributes,
|
||||
nSize);
|
||||
if (!ok) __winerr();
|
||||
STRACE("CreatePipe([%ld], [%ld], %p, %'zu) → %hhhd% m", *out_hReadPipe,
|
||||
*out_hWritePipe, opt_lpPipeAttributes, nSize, ok);
|
||||
STRACE("CreatePipe([%ld], [%ld], %s, %'zu) → %hhhd% m", *out_hReadPipe,
|
||||
*out_hWritePipe, DescribeNtSecurityAttributes(opt_lpPipeAttributes),
|
||||
nSize, ok);
|
||||
return ok;
|
||||
}
|
||||
|
|
|
@ -18,10 +18,11 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
|
||||
extern typeof(CreateProcess) *const __imp_CreateProcessW __msabi;
|
||||
__msabi extern typeof(CreateProcess) *const __imp_CreateProcessW;
|
||||
|
||||
/**
|
||||
* Creates process on the New Technology.
|
||||
|
@ -44,10 +45,11 @@ CreateProcess(const char16_t *opt_lpApplicationName, char16_t *lpCommandLine,
|
|||
opt_out_lpProcessInformation);
|
||||
if (!ok) __winerr();
|
||||
STRACE(
|
||||
"CreateFile(%#hs, %#hs, %p, %p, %hhhd, %u, %p, %#hs, %p, %p) → %hhhd% m",
|
||||
opt_lpApplicationName, lpCommandLine, opt_lpProcessAttributes,
|
||||
opt_lpThreadAttributes, bInheritHandles, dwCreationFlags,
|
||||
opt_lpEnvironment, opt_lpCurrentDirectory, lpStartupInfo,
|
||||
"CreateFile(%#hs, %#hs, %s, %s, %hhhd, %u, %p, %#hs, %p, %p) → %hhhd% m",
|
||||
opt_lpApplicationName, lpCommandLine,
|
||||
DescribeNtSecurityAttributes(opt_lpProcessAttributes),
|
||||
DescribeNtSecurityAttributes(opt_lpThreadAttributes), bInheritHandles,
|
||||
dwCreationFlags, opt_lpEnvironment, opt_lpCurrentDirectory, lpStartupInfo,
|
||||
opt_out_lpProcessInformation, ok);
|
||||
return ok;
|
||||
}
|
||||
|
|
|
@ -18,10 +18,11 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/nt/struct/securityattributes.h"
|
||||
#include "libc/nt/thread.h"
|
||||
|
||||
extern typeof(CreateThread) *const __imp_CreateThread __msabi;
|
||||
__msabi extern typeof(CreateThread) *const __imp_CreateThread;
|
||||
|
||||
/**
|
||||
* Opens file on the New Technology.
|
||||
|
@ -38,9 +39,8 @@ textwindows int64_t CreateThread(
|
|||
hHandle = __imp_CreateThread(lpThreadAttributes, dwStackSize, lpStartAddress,
|
||||
lpParameter, dwCreationFlags, opt_lpThreadId);
|
||||
if (hHandle == -1) __winerr();
|
||||
STRACE("CreateThread(sec=%p, stack=%'zu, start=%p, param=%p, flags=%s, "
|
||||
"id=%p) → %ld% m",
|
||||
lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter,
|
||||
dwCreationFlags, opt_lpThreadId, hHandle);
|
||||
STRACE("CreateThread(%s, %'zu, %p, %p, %s, %p) → %ld% m",
|
||||
DescribeNtSecurityAttributes(lpThreadAttributes), dwStackSize,
|
||||
lpStartAddress, lpParameter, dwCreationFlags, opt_lpThreadId, hHandle);
|
||||
return hHandle;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
|
||||
extern typeof(DeleteFile) *const __imp_DeleteFileW __msabi;
|
||||
__msabi extern typeof(DeleteFile) *const __imp_DeleteFileW;
|
||||
|
||||
/**
|
||||
* Deletes existing file.
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define COSMOPOLITAN_LIBC_INTRIN_DESCRIBEFLAGS_INTERNAL_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
#include "libc/nt/struct/securityattributes.h"
|
||||
|
||||
struct thatispacked DescribeFlags {
|
||||
unsigned flag;
|
||||
|
@ -16,14 +17,19 @@ const char *DescribeProtFlags(int);
|
|||
const char *DescribeRemapFlags(int);
|
||||
|
||||
const char *DescribeNtPageFlags(uint32_t);
|
||||
const char *DescribeNtStartFlags(uint32_t);
|
||||
const char *DescribeNtFileMapFlags(uint32_t);
|
||||
const char *DescribeNtFiletypeFlags(uint32_t);
|
||||
const char *DescribeNtFileFlagsAndAttributes(uint32_t);
|
||||
const char *DescribeNtPipeOpenFlags(uint32_t);
|
||||
const char *DescribeNtPipeModeFlags(uint32_t);
|
||||
const char *DescribeNtFileShareFlags(uint32_t);
|
||||
const char *DescribeNtFileAccessFlags(uint32_t);
|
||||
const char *DescribeNtProcessAccessFlags(uint32_t);
|
||||
const char *DescribeNtCreationDisposition(uint32_t);
|
||||
const char *DescribeNtConsoleModeInputFlags(uint32_t);
|
||||
const char *DescribeNtConsoleModeOutputFlags(uint32_t);
|
||||
const char *DescribeNtFileFlagsAndAttributes(uint32_t);
|
||||
const char *DescribeNtSecurityAttributes(struct NtSecurityAttributes *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
37
libc/intrin/describentcreationdisposition.greg.c
Normal file
37
libc/intrin/describentcreationdisposition.greg.c
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*-*- 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/intrin/describeflags.internal.h"
|
||||
#include "libc/nt/enum/creationdisposition.h"
|
||||
|
||||
const char *DescribeNtCreationDisposition(uint32_t x) {
|
||||
switch (x) {
|
||||
case kNtCreateNew:
|
||||
return "kNtCreateNew";
|
||||
case kNtCreateAlways:
|
||||
return "kNtCreateAlways";
|
||||
case kNtOpenExisting:
|
||||
return "kNtOpenExisting";
|
||||
case kNtOpenAlways:
|
||||
return "kNtOpenAlways";
|
||||
case kNtTruncateExisting:
|
||||
return "kNtTruncateExisting";
|
||||
default:
|
||||
return "wut";
|
||||
}
|
||||
}
|
|
@ -64,7 +64,7 @@ static const struct DescribeFlags kFileAccessflags[] = {
|
|||
};
|
||||
|
||||
const char *DescribeNtFileAccessFlags(uint32_t x) {
|
||||
static char ntfileaccessflags[256];
|
||||
static char ntfileaccessflags[512];
|
||||
return DescribeFlags(ntfileaccessflags, sizeof(ntfileaccessflags),
|
||||
kFileAccessflags, ARRAYLEN(kFileAccessflags), "kNt", x);
|
||||
}
|
||||
|
|
|
@ -17,8 +17,10 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/enum/fileflagandattributes.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
static const struct DescribeFlags kFileFlags[] = {
|
||||
{kNtFileAttributeReadonly, "AttributeReadonly"}, //
|
||||
|
|
39
libc/intrin/describentpipemodeflags.greg.c
Normal file
39
libc/intrin/describentpipemodeflags.greg.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*-*- 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/intrin/describeflags.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/enum/filemapflags.h"
|
||||
#include "libc/nt/ipc.h"
|
||||
|
||||
static const struct DescribeFlags kPipeModeFlags[] = {
|
||||
{kNtPipeNowait, "Nowait"}, // 0x0000000001
|
||||
{kNtPipeReadmodeMessage, "ReadmodeMessage"}, // 0x0000000002
|
||||
{kNtPipeTypeMessage, "TypeMessage"}, // 0x0000000004
|
||||
{kNtPipeRejectRemoteClients, "RejectRemoteClients"}, // 0x0000000008
|
||||
//{kNtPipeAcceptRemoteClients, "AcceptRemoteClients"}, // 0x00000000
|
||||
//{kNtPipeReadmodeByte, "ReadmodeByte"}, // 0x00000000
|
||||
//{kNtPipeWait, "Wait"}, // 0x00000000
|
||||
//{kNtPipeTypeByte, "TypeByte"}, // 0x00000000
|
||||
};
|
||||
|
||||
const char *DescribeNtPipeModeFlags(uint32_t x) {
|
||||
static char pipemodeflags[64];
|
||||
return DescribeFlags(pipemodeflags, sizeof(pipemodeflags), kPipeModeFlags,
|
||||
ARRAYLEN(kPipeModeFlags), "kNtPipe", x);
|
||||
}
|
34
libc/intrin/describentpipeopenflags.greg.c
Normal file
34
libc/intrin/describentpipeopenflags.greg.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*-*- 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/intrin/describeflags.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/enum/filemapflags.h"
|
||||
#include "libc/nt/ipc.h"
|
||||
|
||||
static const struct DescribeFlags kPipeOpenFlags[] = {
|
||||
{kNtPipeAccessDuplex, "Duplex"}, // 0x00000003
|
||||
{kNtPipeAccessOutbound, "Outbound"}, // 0x00000002
|
||||
{kNtPipeAccessInbound, "Inbound"}, // 0x00000001
|
||||
};
|
||||
|
||||
const char *DescribeNtPipeOpenFlags(uint32_t x) {
|
||||
static char pipeopenflags[64];
|
||||
return DescribeFlags(pipeopenflags, sizeof(pipeopenflags), kPipeOpenFlags,
|
||||
ARRAYLEN(kPipeOpenFlags), "kNtPipeAccess", x);
|
||||
}
|
26
libc/intrin/describentsecurityattributes.greg.c
Normal file
26
libc/intrin/describentsecurityattributes.greg.c
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*-*- 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/describeflags.internal.h"
|
||||
#include "libc/nt/struct/securityattributes.h"
|
||||
|
||||
const char *DescribeNtSecurityAttributes(struct NtSecurityAttributes *p) {
|
||||
if (p == &kNtIsInheritable) return "&kNtIsInheritable";
|
||||
return "0";
|
||||
}
|
45
libc/intrin/describentstartflags.greg.c
Normal file
45
libc/intrin/describentstartflags.greg.c
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*-*- 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/intrin/describeflags.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/enum/startf.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
||||
static const struct DescribeFlags kNtStartFlags[] = {
|
||||
{kNtStartfUseshowwindow, "Useshowwindow"}, //
|
||||
{kNtStartfUsesize, "Usesize"}, //
|
||||
{kNtStartfUseposition, "Useposition"}, //
|
||||
{kNtStartfUsecountchars, "Usecountchars"}, //
|
||||
{kNtStartfUsefillattribute, "Usefillattribute"}, //
|
||||
{kNtStartfRunfullscreen, "Runfullscreen"}, //
|
||||
{kNtStartfForceonfeedback, "Forceonfeedback"}, //
|
||||
{kNtStartfForceofffeedback, "Forceofffeedback"}, //
|
||||
{kNtStartfUsestdhandles, "Usestdhandles"}, //
|
||||
{kNtStartfUsehotkey, "Usehotkey"}, //
|
||||
{kNtStartfTitleislinkname, "Titleislinkname"}, //
|
||||
{kNtStartfTitleisappid, "Titleisappid"}, //
|
||||
{kNtStartfPreventpinning, "Preventpinning"}, //
|
||||
{kNtStartfUntrustedsource, "Untrustedsource"}, //
|
||||
};
|
||||
|
||||
const char *DescribeNtStartFlags(uint32_t x) {
|
||||
static char startflags[128];
|
||||
return DescribeFlags(startflags, sizeof(startflags), kNtStartFlags,
|
||||
ARRAYLEN(kNtStartFlags), "kNtStartf", x);
|
||||
}
|
|
@ -22,7 +22,7 @@
|
|||
#include "libc/nt/struct/overlapped.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
|
||||
extern typeof(DeviceIoControl) *const __imp_DeviceIoControl __msabi;
|
||||
__msabi extern typeof(DeviceIoControl) *const __imp_DeviceIoControl;
|
||||
|
||||
/**
|
||||
* Does device file stuff on the New Technology.
|
||||
|
|
|
@ -17,16 +17,10 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/dos2errno.internal.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/sock/sock.h"
|
||||
|
||||
struct thatispacked Dos2Errno {
|
||||
uint16_t doscode;
|
||||
int32_t systemv;
|
||||
};
|
||||
|
||||
extern const struct Dos2Errno kDos2Errno[];
|
||||
|
||||
/**
|
||||
* Translates Windows error using superset of consts.sh.
|
||||
*
|
||||
|
|
15
libc/intrin/dos2errno.internal.h
Normal file
15
libc/intrin/dos2errno.internal.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_INTRIN_DOS2ERRNO_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_INTRIN_DOS2ERRNO_INTERNAL_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct thatispacked Dos2Errno {
|
||||
uint16_t doscode;
|
||||
int32_t systemv;
|
||||
};
|
||||
|
||||
extern const struct Dos2Errno kDos2Errno[];
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_INTRIN_DOS2ERRNO_INTERNAL_H_ */
|
36
libc/intrin/findclose.greg.c
Normal file
36
libc/intrin/findclose.greg.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*-*- 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/calls/strace.internal.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
|
||||
__msabi extern typeof(FindClose) *const __imp_FindClose;
|
||||
|
||||
/**
|
||||
* Finds more files in directory.
|
||||
* @note this wrapper takes care of ABI, STRACE(), and __winerr()
|
||||
*/
|
||||
textwindows bool32 FindClose(int64_t hFindFile) {
|
||||
bool32 ok;
|
||||
ok = __imp_FindClose(hFindFile);
|
||||
if (!ok) __winerr();
|
||||
STRACE("FindClose(%ld) → %hhhd% m", hFindFile, ok);
|
||||
return ok;
|
||||
}
|
|
@ -24,7 +24,7 @@
|
|||
#include "libc/nt/struct/win32finddata.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
|
||||
extern typeof(FindFirstFile) *const __imp_FindFirstFileW __msabi;
|
||||
__msabi extern typeof(FindFirstFile) *const __imp_FindFirstFileW;
|
||||
|
||||
/**
|
||||
* Finds first file in directory.
|
||||
|
|
|
@ -19,12 +19,14 @@
|
|||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/win32finddata.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
|
||||
extern typeof(FindNextFile) *const __imp_FindNextFileW __msabi;
|
||||
__msabi extern typeof(FindNextFile) *const __imp_FindNextFileW;
|
||||
|
||||
/**
|
||||
* Finds more files in directory.
|
||||
|
@ -45,8 +47,8 @@ textwindows bool32 FindNextFile(int64_t hFindFile,
|
|||
DescribeNtFileFlagsAndAttributes(out_lpFindFileData->dwFileAttributes),
|
||||
DescribeNtFiletypeFlags(out_lpFindFileData->dwFileType), ok);
|
||||
} else {
|
||||
__winerr();
|
||||
STRACE("FindNextFile(%ld, [n/a]) → %hhhd% m", hFindFile, ok);
|
||||
if (GetLastError() != kNtErrorNoMoreFiles) __winerr();
|
||||
STRACE("FindNextFile(%ld) → %hhhd% m", hFindFile, ok);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/nt/files.h"
|
||||
|
||||
extern typeof(FlushFileBuffers) *const __imp_FlushFileBuffers __msabi;
|
||||
__msabi extern typeof(FlushFileBuffers) *const __imp_FlushFileBuffers;
|
||||
|
||||
/**
|
||||
* Flushes buffers of specified file to disk.
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/nt/memory.h"
|
||||
|
||||
extern typeof(FlushViewOfFile) *const __imp_FlushViewOfFile __msabi;
|
||||
__msabi extern typeof(FlushViewOfFile) *const __imp_FlushViewOfFile;
|
||||
|
||||
/**
|
||||
* Syncs memory created by MapViewOfFileEx().
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
#include "libc/nt/console.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
|
||||
extern typeof(GenerateConsoleCtrlEvent) *const
|
||||
__imp_GenerateConsoleCtrlEvent __msabi;
|
||||
__msabi extern typeof(GenerateConsoleCtrlEvent) *const
|
||||
__imp_GenerateConsoleCtrlEvent;
|
||||
|
||||
/**
|
||||
* Sends signal to process group that shares console w/ calling process.
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
|
||||
extern typeof(GetFileAttributes) *const __imp_GetFileAttributesW __msabi;
|
||||
__msabi extern typeof(GetFileAttributes) *const __imp_GetFileAttributesW;
|
||||
|
||||
/**
|
||||
* Gets file info on the New Technology.
|
||||
|
|
|
@ -65,6 +65,7 @@ o/$(MODE)/libc/intrin/kprintf.greg.o: \
|
|||
$(NO_MAGIC)
|
||||
|
||||
o/$(MODE)/libc/intrin/createfile.greg.o \
|
||||
o/$(MODE)/libc/intrin/reopenfile.greg.o \
|
||||
o/$(MODE)/libc/intrin/deletefile.greg.o \
|
||||
o/$(MODE)/libc/intrin/createpipe.greg.o \
|
||||
o/$(MODE)/libc/intrin/closehandle.greg.o \
|
||||
|
|
|
@ -29,6 +29,71 @@
|
|||
.section .rodata
|
||||
.underrun
|
||||
kDos2Errno:
|
||||
// .e kNtErrorInvalidFunction,ENOSYS # in consts.sh
|
||||
// .e kNtErrorFileNotFound,ENOENT # in consts.sh
|
||||
// .e kNtErrorPathNotFound,ENOTDIR # in consts.sh
|
||||
// .e kNtErrorTooManyOpenFiles,EMFILE # in consts.sh
|
||||
// .e kNtErrorAccessDenied,EACCES # in consts.sh
|
||||
// .e kNtErrorInvalidHandle,EBADF # in consts.sh
|
||||
// .e kNtErrorInvalidAccess,EPERM # in consts.sh
|
||||
// .e kNtErrorSeek,ESPIPE # in consts.sh
|
||||
// .e kNtErrorNotDosDisk,ENOTBLK # in consts.sh
|
||||
// .e kNtErrorFileExists,EEXIST # in consts.sh
|
||||
// .e kNtErrorInvalidParameter,EINVAL # in consts.sh
|
||||
// .e kNtErrorOutofmemory,ENOMEM # in consts.sh
|
||||
// .e kNtErrorBrokenPipe,EPIPE # in consts.sh
|
||||
// .e kNtErrorWaitNoChildren,ECHILD # in consts.sh
|
||||
// .e kNtErrorPathBusy,ETXTBSY # in consts.sh
|
||||
// .e kNtErrorBusy,EBUSY # in consts.sh
|
||||
// .e kNtErrorAlreadyExists,EEXIST # in consts.sh
|
||||
// .e kNtErrorBadExeFormat,ENOEXEC # in consts.sh
|
||||
// .e kNtErrorFileTooLarge,EFBIG # in consts.sh
|
||||
// .e kNtErrorTooManyDescriptors,ENFILE # in consts.sh
|
||||
// .e kNtErrorDirectoryNotSupported,EISDIR # in consts.sh
|
||||
// .e kNtErrorInvalidAddress,EFAULT # in consts.sh
|
||||
// .e kNtErrorThreadNotInProcess,ESRCH # in consts.sh
|
||||
// .e kNtErrorNoMediaInDrive,ENXIO # in consts.sh
|
||||
// .e kNtErrorIoDevice,EIO # in consts.sh
|
||||
// .e kNtErrorSerialNoDevice,ENOTTY # in consts.sh
|
||||
// .e kNtErrorPossibleDeadlock,EDEADLK # in consts.sh
|
||||
// .e kNtErrorBadDevice,ENODEV # in consts.sh
|
||||
// .e kNtErrorInvalidCommandLine,E2BIG # in consts.sh
|
||||
// .e kNtErrorFileReadOnly,EROFS # in consts.sh
|
||||
// .e kNtErrorNoData,ENODATA # in consts.sh
|
||||
// .e WSAEPROCLIM,EPROCLIM # in consts.sh
|
||||
// .e WSAESHUTDOWN,ESHUTDOWN # in consts.sh
|
||||
// .e WSAEINPROGRESS,EINPROGRESS # in consts.sh
|
||||
// .e WSAENETDOWN,ENETDOWN # in consts.sh
|
||||
// .e WSAENETUNREACH,ENETUNREACH # in consts.sh
|
||||
// .e WSAENETRESET,ENETRESET # in consts.sh
|
||||
// .e WSAEUSERS,EUSERS # in consts.sh
|
||||
// .e WSAENOTSOCK,ENOTSOCK # in consts.sh
|
||||
// .e WSAEDESTADDRREQ,EDESTADDRREQ # in consts.sh
|
||||
// .e WSAEMSGSIZE,EMSGSIZE # in consts.sh
|
||||
// .e WSAEPROTOTYPE,EPROTOTYPE # in consts.sh
|
||||
// .e WSAENOPROTOOPT,ENOPROTOOPT # in consts.sh
|
||||
// .e WSAEPROTONOSUPPORT,EPROTONOSUPPORT # in consts.sh
|
||||
// .e WSAESOCKTNOSUPPORT,ESOCKTNOSUPPORT # in consts.sh
|
||||
// .e WSAEOPNOTSUPP,ENOTSUP # in consts.sh
|
||||
// .e WSAEOPNOTSUPP,EOPNOTSUPP # in consts.sh
|
||||
// .e WSAEPFNOSUPPORT,EPFNOSUPPORT # in consts.sh
|
||||
// .e WSAEAFNOSUPPORT,EAFNOSUPPORT # in consts.sh
|
||||
// .e WSAEADDRINUSE,EADDRINUSE # in consts.sh
|
||||
// .e WSAEADDRNOTAVAIL,EADDRNOTAVAIL # in consts.sh
|
||||
// .e WSAECONNABORTED,ECONNABORTED # in consts.sh
|
||||
// .e WSAECONNRESET,ECONNRESET # in consts.sh
|
||||
// .e WSAENOBUFS,ENOBUFS # in consts.sh
|
||||
// .e WSAEISCONN,EISCONN # in consts.sh
|
||||
// .e WSAENOTCONN,ENOTCONN # in consts.sh
|
||||
// .e WSAESHUTDOWN,ESHUTDOWN # in consts.sh
|
||||
// .e WSAETOOMANYREFS,ETOOMANYREFS # in consts.sh
|
||||
// .e WSAETIMEDOUT,ETIMEDOUT # in consts.sh
|
||||
// .e WSAECONNREFUSED,ECONNREFUSED # in consts.sh
|
||||
// .e WSAEHOSTDOWN,EHOSTDOWN # in consts.sh
|
||||
// .e WSAEHOSTUNREACH,EHOSTUNREACH # in consts.sh
|
||||
// .e WSAEALREADY,EALREADY # in consts.sh
|
||||
// .e WSAESTALE,ESTALE # in consts.sh
|
||||
// .e WSAEREMOTE,EREMOTE # in consts.sh
|
||||
.e kNtErrorModNotFound,ENOSYS
|
||||
.e kNtErrorBadCommand,EACCES
|
||||
.e kNtErrorBadLength,EACCES
|
||||
|
@ -94,10 +159,8 @@ kDos2Errno:
|
|||
.e WSAEACCES,EACCES
|
||||
.e WSAEDISCON,EPIPE
|
||||
.e WSAEFAULT,EFAULT
|
||||
.e WSAEINPROGRESS,EBUSY
|
||||
.e WSAEINVAL,EINVAL
|
||||
.e WSAEPROCLIM,ENOMEM
|
||||
.e WSAESHUTDOWN,EPIPE
|
||||
.e WSANOTINITIALISED,ENETDOWN
|
||||
.e WSASYSNOTREADY,ENETDOWN
|
||||
.e WSAVERNOTSUPPORTED,ENOSYS
|
||||
|
|
|
@ -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,7 +16,6 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/nt/struct/securityattributes.h"
|
||||
|
||||
hidden const struct NtSecurityAttributes kNtIsInheritable = {
|
|
@ -37,6 +37,7 @@
|
|||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
|
@ -438,8 +439,7 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, va_list va,
|
|||
i = 0;
|
||||
m = (1 << base) - 1;
|
||||
if (hash && x) sign = hash;
|
||||
do
|
||||
z[i++ & 127] = abet[x & m];
|
||||
do z[i++ & 127] = abet[x & m];
|
||||
while ((x >>= base) || (pdot && i < prec));
|
||||
goto EmitNumber;
|
||||
|
||||
|
@ -487,17 +487,31 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, va_list va,
|
|||
}
|
||||
goto EmitChar;
|
||||
|
||||
case 'm':
|
||||
if (!(x = errno) && sign == ' ' /* && */
|
||||
/* (!IsWindows() || !__imp_GetLastError()) */) {
|
||||
case 'm': {
|
||||
int unixerr;
|
||||
uint32_t winerr;
|
||||
unixerr = errno;
|
||||
winerr = 0;
|
||||
if (IsWindows()) {
|
||||
if (type == 1 && weaken(WSAGetLastError)) {
|
||||
winerr = weaken(WSAGetLastError)();
|
||||
} else if (weaken(GetLastError)) {
|
||||
winerr = weaken(GetLastError)();
|
||||
}
|
||||
}
|
||||
if (!unixerr && sign == ' ') {
|
||||
break;
|
||||
} else if (weaken(strerror_r) &&
|
||||
!weaken(strerror_r)(x, z, sizeof(z))) {
|
||||
} else if (weaken(strerror_wr) &&
|
||||
!weaken(strerror_wr)(unixerr, winerr, z, sizeof(z))) {
|
||||
s = z;
|
||||
type = 0;
|
||||
goto FormatString;
|
||||
} else {
|
||||
type = 0;
|
||||
x = unixerr;
|
||||
goto FormatDecimal;
|
||||
}
|
||||
}
|
||||
|
||||
case 'G':
|
||||
x = va_arg(va, int);
|
||||
|
@ -864,6 +878,13 @@ privileged void kvprintf(const char *fmt, va_list v) {
|
|||
* - ` ` space leftpad if positive (aligns w/ negatives)
|
||||
* - `#` represent value with literal syntax, e.g. 0x, 0b, quotes
|
||||
*
|
||||
* Error numbers:
|
||||
*
|
||||
* - `%m` formats error (if strerror_wr if is linked)
|
||||
* - `%m` formats errno number (if strerror_wr isn't linked)
|
||||
* - `% m` formats error with leading space if errno isn't zero
|
||||
* - `%lm` means favor WSAGetLastError() over GetLastError() if linked
|
||||
*
|
||||
* @asyncsignalsafe
|
||||
* @vforksafe
|
||||
*/
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include "libc/nt/enum/filemapflags.h"
|
||||
#include "libc/nt/memory.h"
|
||||
|
||||
extern typeof(MapViewOfFileEx) *const __imp_MapViewOfFileEx __msabi;
|
||||
__msabi extern typeof(MapViewOfFileEx) *const __imp_MapViewOfFileEx;
|
||||
|
||||
/**
|
||||
* Maps view of file mapping into memory on the New Technology.
|
||||
|
@ -45,8 +45,8 @@ textwindows void *MapViewOfFileEx(int64_t hFileMappingObject,
|
|||
hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh, dwFileOffsetLow,
|
||||
dwNumberOfBytesToMap, opt_lpDesiredBaseAddress);
|
||||
if (!pStartingAddress) __winerr();
|
||||
STRACE("MapViewOfFileEx(%ld, %s, off:%'ld, size:%'zu, addr:%p) → %p% m",
|
||||
hFileMappingObject, DescribeNtFileMapFlags(dwDesiredAccess),
|
||||
STRACE("MapViewOfFileEx(%ld, %s, %'ld, %'zu, %p) → %p% m", hFileMappingObject,
|
||||
DescribeNtFileMapFlags(dwDesiredAccess),
|
||||
(uint64_t)dwFileOffsetHigh << 32 | dwFileOffsetLow,
|
||||
dwNumberOfBytesToMap, opt_lpDesiredBaseAddress, pStartingAddress);
|
||||
return pStartingAddress;
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "libc/nt/enum/filemapflags.h"
|
||||
#include "libc/nt/memory.h"
|
||||
|
||||
extern typeof(MapViewOfFileExNuma) *const __imp_MapViewOfFileExNuma __msabi;
|
||||
__msabi extern typeof(MapViewOfFileExNuma) *const __imp_MapViewOfFileExNuma;
|
||||
|
||||
/**
|
||||
* Maps view of file mapping into memory on the New Technology.
|
||||
|
@ -47,7 +47,7 @@ textwindows void *MapViewOfFileExNuma(int64_t hFileMappingObject,
|
|||
hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh, dwFileOffsetLow,
|
||||
dwNumberOfBytesToMap, opt_lpDesiredBaseAddress, nndDesiredNumaNode);
|
||||
if (!pStartingAddress) __winerr();
|
||||
STRACE("MapViewOfFileExNuma(%ld, %s, off:%'ld, size:%'zu, %p) → %p% m",
|
||||
STRACE("MapViewOfFileExNuma(%ld, %s, %'ld, %'zu, %p) → %p% m",
|
||||
hFileMappingObject, DescribeNtFileMapFlags(dwDesiredAccess),
|
||||
(uint64_t)dwFileOffsetHigh << 32 | dwFileOffsetLow,
|
||||
dwNumberOfBytesToMap, opt_lpDesiredBaseAddress, pStartingAddress);
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "libc/nt/struct/securityattributes.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
|
||||
extern typeof(OpenProcess) *const __imp_OpenProcess __msabi;
|
||||
__msabi extern typeof(OpenProcess) *const __imp_OpenProcess;
|
||||
|
||||
/**
|
||||
* Creates file mapping object on the New Technology.
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
|
||||
extern typeof(RemoveDirectory) *const __imp_RemoveDirectoryW __msabi;
|
||||
__msabi extern typeof(RemoveDirectory) *const __imp_RemoveDirectoryW;
|
||||
|
||||
/**
|
||||
* Deletes existing empty directory.
|
||||
|
|
|
@ -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,29 @@
|
|||
│ 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/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"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
|
||||
static void __ensurefds_destroy(void) {
|
||||
weaken(free)(g_fds.p);
|
||||
}
|
||||
__msabi extern typeof(ReOpenFile) *const __imp_ReOpenFile;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Reopens file on the New Technology.
|
||||
*
|
||||
* @return handle, or -1 on failure
|
||||
* @note this wrapper takes care of ABI, STRACE(), and __winerr()
|
||||
*/
|
||||
int64_t ReOpenFile(int64_t hOriginalFile, uint32_t dwDesiredAccess,
|
||||
uint32_t dwShareMode, uint32_t dwFlagsAndAttributes) {
|
||||
int64_t hHandle;
|
||||
hHandle = __imp_ReOpenFile(hOriginalFile, dwDesiredAccess, dwShareMode,
|
||||
dwFlagsAndAttributes);
|
||||
if (hHandle == -1) __winerr();
|
||||
STRACE("ReOpenFile(%ld, %s, %s, %s) → %ld% m", hOriginalFile,
|
||||
DescribeNtFileAccessFlags(dwDesiredAccess),
|
||||
DescribeNtFileShareFlags(dwShareMode),
|
||||
DescribeNtFileFlagsAndAttributes(dwFlagsAndAttributes), hHandle);
|
||||
return hHandle;
|
||||
}
|
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nt/console.h"
|
||||
#include "libc/nt/process.h"
|
||||
|
@ -35,7 +36,9 @@ const char kConsoleHandles[3] = {
|
|||
*/
|
||||
noasan void __restorewintty(void) {
|
||||
int i;
|
||||
if (IsWindows() && GetCurrentProcessId() == __winmainpid) {
|
||||
if (!IsWindows()) return;
|
||||
STRACE("__restorewintty()");
|
||||
if (GetCurrentProcessId() == __winmainpid) {
|
||||
for (i = 0; i < 3; ++i) {
|
||||
SetConsoleMode(GetStdHandle(kConsoleHandles[i]), __ntconsolemode[i]);
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
|
||||
extern typeof(SetCurrentDirectory) *const __imp_SetCurrentDirectoryW __msabi;
|
||||
__msabi extern typeof(SetCurrentDirectory) *const __imp_SetCurrentDirectoryW;
|
||||
|
||||
/**
|
||||
* Sets current directory.
|
||||
|
|
|
@ -1,22 +1,24 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_INTRIN_SPINLOCK_H_
|
||||
#define COSMOPOLITAN_LIBC_INTRIN_SPINLOCK_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
#if (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 401 && \
|
||||
!defined(__STRICT_ANSI__)
|
||||
|
||||
/* "Place each synchronization variable alone,
|
||||
separated by 128 bytes or in a separate cache line."
|
||||
──Intel Optimization Manual §8.3.1 */
|
||||
struct cthread_spinlock_t {
|
||||
bool x;
|
||||
int owner;
|
||||
char __ignore[128 - 1 - 4];
|
||||
} forcealign(128);
|
||||
#define _spinlock(lock) \
|
||||
do { \
|
||||
for (;;) { \
|
||||
typeof(*(lock)) x; \
|
||||
__atomic_load(lock, &x, __ATOMIC_RELAXED); \
|
||||
if (!x && !__sync_lock_test_and_set(lock, __ATOMIC_CONSUME)) { \
|
||||
break; \
|
||||
} else { \
|
||||
__builtin_ia32_pause(); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
typedef struct cthread_spinlock_t cthread_spinlock_t;
|
||||
#define _spunlock(lock) __sync_lock_release(lock)
|
||||
|
||||
void cthread_spinlock(cthread_spinlock_t *) dontthrow;
|
||||
void cthread_spunlock(cthread_spinlock_t *) dontthrow;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* GNU 4.1+ */
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_INTRIN_SPINLOCK_H_ */
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
|
||||
extern typeof(TerminateProcess) *const __imp_TerminateProcess __msabi;
|
||||
__msabi extern typeof(TerminateProcess) *const __imp_TerminateProcess;
|
||||
|
||||
/**
|
||||
* Terminates the specified process and all of its threads.
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue