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:
Justine Tunney 2022-04-14 23:39:48 -07:00
parent 233144b19d
commit 933411ba99
266 changed files with 8761 additions and 4344 deletions

View file

@ -33,8 +33,6 @@ dontinline void dostuff(const char *s) {
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
int rc, child, wstatus; int rc, child, wstatus;
/* puts(_gc(xiso8601ts(NULL))); */
PrintMemoryIntervals(2, &_mmi);
CHECK_NE(-1, (child = fork())); CHECK_NE(-1, (child = fork()));
if (!child) { if (!child) {
/* child process */ /* child process */

View file

@ -148,7 +148,6 @@ int munlock(const void *, size_t);
int munlockall(void); int munlockall(void);
int nice(int); int nice(int);
int open(const char *, int, ...); int open(const char *, int, ...);
int openanon(char *, unsigned);
int openat(int, const char *, int, ...); int openat(int, const char *, int, ...);
int pause(void); int pause(void);
int personality(uint64_t); int personality(uint64_t);
@ -169,7 +168,7 @@ int sched_setaffinity(int, uint64_t, const void *);
int sched_yield(void); int sched_yield(void);
int setegid(uint32_t); int setegid(uint32_t);
int seteuid(uint32_t); int seteuid(uint32_t);
int setgid(uint32_t); int setgid(int);
int setpgid(int, int); int setpgid(int, int);
int setpriority(int, unsigned, int); int setpriority(int, unsigned, int);
int setregid(uint32_t, uint32_t); 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 setreuid(uint32_t, uint32_t);
int setrlimit(int, const struct rlimit *); int setrlimit(int, const struct rlimit *);
int setsid(void); int setsid(void);
int setuid(uint32_t); int setuid(int);
int sigignore(int); int sigignore(int);
int siginterrupt(int, int); int siginterrupt(int, int);
int sigprocmask(int, const struct sigset *, struct sigset *); int sigprocmask(int, const struct sigset *, struct sigset *);

View file

@ -65,8 +65,11 @@ $(LIBC_CALLS_A).pkg: \
$(LIBC_CALLS_A_OBJS) \ $(LIBC_CALLS_A_OBJS) \
$(foreach x,$(LIBC_CALLS_A_DIRECTDEPS),$($(x)_A).pkg) $(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: \ o/$(MODE)/libc/calls/raise.o: \
OVERRIDE_COPTS += \ OVERRIDE_COPTS += \
-ffreestanding \
$(NO_MAGIC) $(NO_MAGIC)
o/$(MODE)/libc/calls/termios2linux.o \ o/$(MODE)/libc/calls/termios2linux.o \

View file

@ -16,30 +16,42 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/bits/weaken.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/nt/enum/filetype.h" #include "libc/nt/enum/filetype.h"
#include "libc/nt/files.h" #include "libc/nt/files.h"
#include "libc/nt/runtime.h" #include "libc/nt/runtime.h"
#include "libc/sock/ntstdin.internal.h"
#include "libc/sysv/consts/o.h" #include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
textwindows int sys_close_nt(struct Fd *fd) { textwindows int sys_close_nt(struct Fd *fd) {
int e; 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 && if (fd->kind == kFdFile && ((fd->flags & O_ACCMODE) != O_RDONLY &&
GetFileType(fd->handle) == kNtFileTypeDisk)) { GetFileType(fd->handle) == kNtFileTypeDisk)) {
/* // Like Linux, closing a file on Windows doesn't guarantee it's
* Like Linux, closing a file on Windows doesn't guarantee it's // immediately synced to disk. But unlike Linux, this could cause
* immediately synced to disk. But unlike Linux, this could cause // subsequent operations, e.g. unlink() to break w/ access error.
* subsequent operations, e.g. unlink() to break w/ access error.
*/
e = errno; e = errno;
FlushFileBuffers(fd->handle); FlushFileBuffers(fd->handle);
errno = e; 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) { if (fd->kind == kFdConsole && fd->extra && fd->extra != -1) {
ok &= CloseHandle(fd->extra); if (!CloseHandle(fd->extra)) ok = false;
} }
return ok ? 0 : -1; return ok ? 0 : -1;
} }

View file

@ -73,7 +73,7 @@ int close(int fd) {
} }
} }
} }
__releasefd(fd); if (!__vforked) __releasefd(fd);
} }
STRACE("%s(%d) → %d% m", "close", fd, rc); STRACE("%s(%d) → %d% m", "close", fd, rc);
return rc; return rc;

View 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;
}

View file

@ -16,32 +16,35 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/alg/reverse.internal.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/intrin/lockxadd.h"
#include "libc/nt/process.h" #include "libc/nt/process.h"
static const char kPipeNamePrefix[] = "\\\\?\\pipe\\cosmo\\"; static textwindows char16_t *UintToChar16Array(char16_t p[21], uint64_t x) {
char t;
static textwindows size_t UintToChar16Array(char16_t *a, uint64_t i) { size_t a, b, i = 0;
size_t j = 0;
do { do {
a[j++] = i % 10 + '0'; p[i++] = x % 10 + '0';
i /= 10; x = x / 10;
} while (i > 0); } while (x > 0);
a[j] = 0; if (i) {
reverse(a, j); for (a = 0, b = i - 1; a < b; ++a, --b) {
return j; t = p[a];
p[a] = p[b];
p[b] = t;
}
}
return p + i;
} }
textwindows char16_t *CreatePipeName(char16_t *a) { textwindows char16_t *CreatePipeName(char16_t *a) {
static long x; static long x;
unsigned i; char16_t *p = a;
for (i = 0; kPipeNamePrefix[i]; ++i) a[i] = kPipeNamePrefix[i]; const char *q = "\\\\?\\pipe\\cosmo\\";
i += UintToChar16Array(a + i, GetCurrentProcessId()); while (*q) *p++ = *q++;
a[i++] = u'-'; p = UintToChar16Array(p, GetCurrentProcessId());
i += UintToChar16Array(a + i, GetCurrentProcessId()); *p++ = '-';
a[i++] = u'-'; p = UintToChar16Array(p, _lockxadd(&x, 1));
i += UintToChar16Array(a + i, x++); *p = 0;
a[i] = u'\0';
return a; return a;
} }

View file

@ -18,18 +18,21 @@
*/ */
#include "libc/assert.h" #include "libc/assert.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/nt/enum/filemapflags.h" #include "libc/nt/enum/filemapflags.h"
#include "libc/nt/enum/pageflags.h" #include "libc/nt/enum/pageflags.h"
#include "libc/nt/memory.h" #include "libc/nt/memory.h"
#include "libc/nt/process.h"
#include "libc/nt/runtime.h" #include "libc/nt/runtime.h"
#include "libc/nt/struct/processmemorycounters.h"
#include "libc/runtime/directmap.internal.h" #include "libc/runtime/directmap.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/map.h" #include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h" #include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h" #include "libc/sysv/consts/prot.h"
textwindows noasan struct DirectMap sys_mmap_nt(void *addr, size_t size, textwindows struct DirectMap sys_mmap_nt(void *addr, size_t size, int prot,
int prot, int flags, int fd, int flags, int fd, int64_t off) {
int64_t off) {
size_t i; size_t i;
bool iscow; bool iscow;
int64_t handle; int64_t handle;
@ -38,6 +41,18 @@ textwindows noasan struct DirectMap sys_mmap_nt(void *addr, size_t size,
struct ProtectNt fl; struct ProtectNt fl;
const struct NtSecurityAttributes *sec; 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) { if (fd != -1) {
handle = g_fds.p[fd].handle; handle = g_fds.p[fd].handle;
} else { } else {

View file

@ -33,8 +33,8 @@
* bypassed by calling this function. However the caller is responsible * bypassed by calling this function. However the caller is responsible
* for passing the magic memory handle on Windows NT to CloseHandle(). * 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, struct DirectMap sys_mmap(void *addr, size_t size, int prot, int flags, int fd,
int fd, int64_t off) { int64_t off) {
/* asan runtime depends on this function */ /* asan runtime depends on this function */
struct DirectMap d; struct DirectMap d;
if (!IsWindows() && !IsMetal()) { if (!IsWindows() && !IsMetal()) {

View file

@ -24,38 +24,62 @@
#include "libc/nt/files.h" #include "libc/nt/files.h"
#include "libc/nt/runtime.h" #include "libc/nt/runtime.h"
#include "libc/sock/internal.h" #include "libc/sock/internal.h"
#include "libc/sock/ntstdin.internal.h"
#include "libc/sysv/consts/o.h" #include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.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) { textwindows int sys_dup_nt(int oldfd, int newfd, int flags, int start) {
int64_t proc; int64_t proc, handle;
// validate the api usage
if (oldfd < 0) return einval(); if (oldfd < 0) return einval();
if (flags & ~O_CLOEXEC) return einval();
if (oldfd >= g_fds.n || if (oldfd >= g_fds.n ||
(g_fds.p[oldfd].kind != kFdFile && g_fds.p[oldfd].kind != kFdSocket && (g_fds.p[oldfd].kind != kFdFile && g_fds.p[oldfd].kind != kFdSocket &&
g_fds.p[oldfd].kind != kFdConsole)) { g_fds.p[oldfd].kind != kFdConsole)) {
return ebadf(); return ebadf();
} }
// allocate a new file descriptor
if (newfd == -1) { if (newfd == -1) {
if ((newfd = __reservefd()) == -1) return -1; if ((newfd = __reservefd(start)) == -1) {
return -1;
}
} else { } else {
if (__ensurefds(newfd) == -1) return -1; if (__ensurefds(newfd) == -1) return -1;
if (g_fds.p[newfd].kind) close(newfd); if (g_fds.p[newfd].kind) close(newfd);
g_fds.p[newfd].kind = kFdReserved; 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(); proc = GetCurrentProcess();
if (DuplicateHandle(proc, g_fds.p[oldfd].handle, proc, &g_fds.p[newfd].handle, if (DuplicateHandle(proc, handle, proc, &g_fds.p[newfd].handle, 0, true,
0, true, kNtDuplicateSameAccess)) { kNtDuplicateSameAccess)) {
g_fds.p[newfd].kind = g_fds.p[oldfd].kind; 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)) { if (g_fds.p[oldfd].kind == kFdSocket && weaken(_dupsockfd)) {
g_fds.p[newfd].extra = g_fds.p[newfd].extra =
(intptr_t)weaken(_dupsockfd)((struct SockFd *)g_fds.p[oldfd].extra); (intptr_t)weaken(_dupsockfd)((struct SockFd *)g_fds.p[oldfd].extra);
} else { } else {
g_fds.p[newfd].extra = g_fds.p[oldfd].extra; 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; return newfd;
} else { } else {
__releasefd(newfd); __releasefd(newfd);

View file

@ -34,7 +34,7 @@ int dup(int fd) {
if (!IsWindows()) { if (!IsWindows()) {
fd2 = sys_dup(fd); fd2 = sys_dup(fd);
} else { } else {
fd2 = sys_dup_nt(fd, -1, 0); fd2 = sys_dup_nt(fd, -1, 0, -1);
} }
STRACE("%s(%d) → %d% m", "dup", fd, fd2); STRACE("%s(%d) → %d% m", "dup", fd, fd2);
return fd2; return fd2;

View file

@ -38,7 +38,7 @@ int dup2(int oldfd, int newfd) {
} else if (!IsWindows()) { } else if (!IsWindows()) {
rc = sys_dup3(oldfd, newfd, 0); rc = sys_dup3(oldfd, newfd, 0);
} else { } 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); STRACE("dup2(%d, %d) → %d% m", oldfd, newfd, rc);
return rc; return rc;

View file

@ -40,7 +40,7 @@ int dup3(int oldfd, int newfd, int flags) {
if (!IsWindows()) { if (!IsWindows()) {
rc = sys_dup3(oldfd, newfd, flags); rc = sys_dup3(oldfd, newfd, flags);
} else { } 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); STRACE("dup3(%d, %d, %d) → %d% m", oldfd, newfd, flags, rc);
return rc; return rc;

View file

@ -41,9 +41,9 @@ textwindows int sys_execve_nt(const char *program, char *const argv[],
bzero(&startinfo, sizeof(startinfo)); bzero(&startinfo, sizeof(startinfo));
startinfo.cb = sizeof(struct NtStartupInfo); startinfo.cb = sizeof(struct NtStartupInfo);
startinfo.dwFlags = kNtStartfUsestdhandles; startinfo.dwFlags = kNtStartfUsestdhandles;
startinfo.hStdInput = g_fds.p[0].handle; startinfo.hStdInput = __getfdhandleactual(0);
startinfo.hStdOutput = g_fds.p[1].handle; startinfo.hStdOutput = __getfdhandleactual(1);
startinfo.hStdError = g_fds.p[2].handle; startinfo.hStdError = __getfdhandleactual(2);
rc = ntspawn(program, argv, envp, 0, 0, 0, 1, 0, 0, &startinfo, &procinfo); rc = ntspawn(program, argv, envp, 0, 0, 0, 1, 0, 0, &startinfo, &procinfo);
if (rc == -1) return -1; if (rc == -1) return -1;
CloseHandle(g_fds.p[0].handle); CloseHandle(g_fds.p[0].handle);

View file

@ -17,49 +17,52 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/nt/createfile.h"
#include "libc/nt/enum/fileflagandattributes.h" #include "libc/nt/enum/fileflagandattributes.h"
#include "libc/nt/enum/filesharemode.h" #include "libc/nt/enum/filesharemode.h"
#include "libc/nt/enum/status.h" #include "libc/nt/enum/status.h"
#include "libc/nt/files.h" #include "libc/nt/files.h"
#include "libc/nt/nt/file.h" #include "libc/nt/nt/file.h"
#include "libc/nt/ntdll.h"
#include "libc/nt/runtime.h" #include "libc/nt/runtime.h"
#include "libc/nt/struct/fileaccessinformation.h" #include "libc/nt/struct/fileaccessinformation.h"
#include "libc/nt/struct/filebasicinformation.h" #include "libc/nt/struct/filebasicinformation.h"
#include "libc/nt/struct/iostatusblock.h" #include "libc/nt/struct/iostatusblock.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/sysv/consts/madv.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
textwindows int sys_fadvise_nt(int fd, uint64_t offset, uint64_t len, textwindows int sys_fadvise_nt(int fd, uint64_t offset, uint64_t len,
int advice) { int advice) {
int64_t h2; int64_t h1, h2;
NtStatus status; int flags, mode;
uint32_t sharemode; uint32_t perm, share, attr;
struct NtIoStatusBlock iostatus;
struct NtFileBasicInformation basicinfo;
struct NtFileAccessInformation accessinfo;
if (!__isfdkind(fd, kFdFile)) return ebadf(); if (!__isfdkind(fd, kFdFile)) return ebadf();
sharemode = /* xxx: no clue how to query this */ h1 = g_fds.p[fd].handle;
kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete; mode = g_fds.p[fd].mode;
/* TODO(jart): can we do it in one call w/ NtQueryObject? */ flags = g_fds.p[fd].flags;
if (!NtError(status = NtQueryInformationFile(g_fds.p[fd].handle, &iostatus, flags &= ~(O_SEQUENTIAL | O_RANDOM);
&basicinfo, sizeof(basicinfo), switch (advice) {
kNtFileBasicInformation)) && case MADV_NORMAL:
!NtError(status = NtQueryInformationFile(g_fds.p[fd].handle, &iostatus, break;
&accessinfo, sizeof(accessinfo), case MADV_RANDOM:
kNtFileAccessInformation))) { flags |= O_RANDOM;
if ((h2 = ReOpenFile(g_fds.p[fd].handle, accessinfo.AccessFlags, sharemode, break;
advice | basicinfo.FileAttributes)) != -1) { case MADV_SEQUENTIAL:
if (h2 != g_fds.p[fd].handle) { flags |= O_SEQUENTIAL;
CloseHandle(g_fds.p[fd].handle); break;
g_fds.p[fd].handle = h2; default:
} return einval();
return 0; }
if (GetNtOpenFlags(flags, mode, &perm, &share, 0, &attr) == -1) return -1;
if ((h2 = ReOpenFile(h1, perm, share, attr)) != -1) {
if (h2 != h1) {
CloseHandle(h1);
g_fds.p[fd].handle = h2;
} }
return __winerr(); g_fds.p[fd].flags = flags;
} else if (status == kNtStatusDllNotFound) { return 0;
return enosys();
} else { } else {
return ntreturn(status); return __winerr();
} }
} }

View file

@ -20,7 +20,9 @@
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/struct/flock.h" #include "libc/calls/struct/flock.h"
#include "libc/intrin/cmpxchg.h" #include "libc/intrin/cmpxchg.h"
#include "libc/intrin/kprintf.h"
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
#include "libc/nt/createfile.h"
#include "libc/nt/enum/accessmask.h" #include "libc/nt/enum/accessmask.h"
#include "libc/nt/enum/fileflagandattributes.h" #include "libc/nt/enum/fileflagandattributes.h"
#include "libc/nt/enum/filelockflags.h" #include "libc/nt/enum/filelockflags.h"
@ -38,38 +40,8 @@
#include "libc/sysv/consts/o.h" #include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
static textwindows int sys_fcntl_nt_reservefd(int start) { static textwindows int sys_fcntl_nt_dupfd(int fd, int cmd, int start) {
int fd; return sys_dup_nt(fd, -1, (cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0), start);
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_lock(struct Fd *f, int cmd, uintptr_t arg) { 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 (!len) len = size - off;
if (off < 0 || len < 0) return einval(); 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) { if (l->l_type == F_RDLCK || l->l_type == F_WRLCK) {
flags = 0; flags = 0;
if (cmd == F_SETLK) flags |= kNtLockfileFailImmediately; 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 | return g_fds.p[fd].flags & (O_ACCMODE | O_APPEND | O_ASYNC | O_DIRECT |
O_NOATIME | O_NONBLOCK); O_NOATIME | O_NONBLOCK);
} else if (cmd == F_SETFL) { } else if (cmd == F_SETFL) {
/* // O_APPEND doesn't appear to be tunable at cursory glance
* - O_APPEND doesn't appear to be tunable at cursory glance // O_NONBLOCK might require we start doing all i/o in threads
* - O_NONBLOCK might require we start doing all i/o in threads // O_DSYNC / O_RSYNC / O_SYNC maybe if we fsync() everything
* - O_DSYNC / O_RSYNC / O_SYNC maybe if we fsync() everything
*/
return einval(); return einval();
} else if (cmd == F_GETFD) { } else if (cmd == F_GETFD) {
if (g_fds.p[fd].flags & O_CLOEXEC) { if (g_fds.p[fd].flags & O_CLOEXEC) {

View file

@ -21,6 +21,7 @@
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
textwindows int sys_fdatasync_nt(int fd) { textwindows int sys_fdatasync_nt(int fd) {
// TODO(jart): what should we do with worker pipes?
if (!__isfdkind(fd, kFdFile)) return ebadf(); if (!__isfdkind(fd, kFdFile)) return ebadf();
return FlushFileBuffers(g_fds.p[fd].handle) ? 0 : -1; return FlushFileBuffers(g_fds.p[fd].handle) ? 0 : -1;
} }

View file

@ -20,42 +20,32 @@
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h" #include "libc/calls/strace.internal.h"
#include "libc/nt/runtime.h" #include "libc/nt/runtime.h"
#include "libc/sysv/consts/fileno.h"
STATIC_YOINK("_init_g_fds"); 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) { textstartup void InitializeFileDescriptors(void) {
int64_t b;
b = GetStdHandle(a);
STRACE("GetStdHandle(%ld) → %ld% m", a, b);
return b;
}
hidden textstartup void InitializeFileDescriptors(void) {
struct Fds *fds; struct Fds *fds;
fds = VEIL("r", &g_fds); fds = VEIL("r", &g_fds);
pushmov(&fds->n, ARRAYLEN(fds->__init_p)); pushmov(&fds->n, ARRAYLEN(fds->__init_p));
fds->p = fds->__init_p; fds->p = fds->__init_p;
if (IsMetal()) { if (IsMetal()) {
pushmov(&fds->f, 3ull); pushmov(&fds->f, 3ull);
fds->__init_p[STDIN_FILENO].kind = pushpop(kFdSerial); fds->__init_p[0].kind = pushpop(kFdSerial);
fds->__init_p[STDOUT_FILENO].kind = pushpop(kFdSerial); fds->__init_p[1].kind = pushpop(kFdSerial);
fds->__init_p[STDERR_FILENO].kind = pushpop(kFdSerial); fds->__init_p[2].kind = pushpop(kFdSerial);
fds->__init_p[STDIN_FILENO].handle = VEIL("r", 0x3F8ull); fds->__init_p[0].handle = VEIL("r", 0x3F8ull);
fds->__init_p[STDOUT_FILENO].handle = VEIL("r", 0x3F8ull); fds->__init_p[1].handle = VEIL("r", 0x3F8ull);
fds->__init_p[STDERR_FILENO].handle = VEIL("r", 0x3F8ull); fds->__init_p[2].handle = VEIL("r", 0x3F8ull);
} else if (IsWindows()) { } else if (IsWindows()) {
pushmov(&fds->f, 3ull); pushmov(&fds->f, 3ull);
fds->__init_p[STDIN_FILENO].kind = pushpop(kFdFile); fds->__init_p[0].kind = pushpop(kFdFile);
fds->__init_p[STDOUT_FILENO].kind = pushpop(kFdFile); fds->__init_p[1].kind = pushpop(kFdFile);
fds->__init_p[STDERR_FILENO].kind = pushpop(kFdFile); fds->__init_p[2].kind = pushpop(kFdFile);
fds->__init_p[STDIN_FILENO].handle = fds->__init_p[0].handle = GetStdHandle(pushpop(kNtStdInputHandle));
GetHandleNt(pushpop(kNtStdInputHandle)); fds->__init_p[1].handle = GetStdHandle(pushpop(kNtStdOutputHandle));
fds->__init_p[STDOUT_FILENO].handle = fds->__init_p[2].handle = GetStdHandle(pushpop(kNtStdErrorHandle));
GetHandleNt(pushpop(kNtStdOutputHandle));
fds->__init_p[STDERR_FILENO].handle =
GetHandleNt(pushpop(kNtStdErrorHandle));
} }
} }

View file

@ -18,6 +18,6 @@
*/ */
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
cthread_spinlock_t __sig_lock; _Alignas(64) char __sig_lock;
unsigned __sighandrvas[NSIG]; unsigned __sighandrvas[NSIG];
unsigned __sighandflags[NSIG]; unsigned __sighandflags[NSIG];

View file

@ -16,35 +16,16 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/assert.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.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) { uint32_t geteuid(void) {
#if 0 int rc;
// TODO(jart): possibly reenable for !NDEBUG when we have TLS rc = sys_geteuid();
int me = gettid(); STRACE("%s() → %d% m", "geteuid", rc);
if (lock->x && lock->owner == me) { return rc;
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;
} }

View file

@ -1,7 +1,7 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi 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 Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the 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 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. 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. int64_t __getfdhandleactual(int fd) {
.init.start 800,_init_dlmalloc if (g_fds.p[fd].worker) {
push %rdi return g_fds.p[fd].worker->reader;
push %rsi } else {
call dlmalloc_init return g_fds.p[fd].handle;
pop %rsi }
pop %rdi }
.init.end 800,_init_dlmalloc,globl,hidden

View file

@ -47,6 +47,8 @@ textwindows int sys_getrusage_nt(int who, struct rusage *usage) {
} else { } else {
return __winerr(); return __winerr();
} }
bzero(&memcount, sizeof(memcount));
memcount.cb = sizeof(struct NtProcessMemoryCountersEx);
if (GetProcessMemoryInfo(GetCurrentProcess(), &memcount, sizeof(memcount))) { if (GetProcessMemoryInfo(GetCurrentProcess(), &memcount, sizeof(memcount))) {
usage->ru_maxrss = memcount.PeakWorkingSetSize / 1024; usage->ru_maxrss = memcount.PeakWorkingSetSize / 1024;
usage->ru_majflt = memcount.PageFaultCount; usage->ru_majflt = memcount.PageFaultCount;

View file

@ -16,11 +16,11 @@
#include "libc/calls/struct/winsize.h" #include "libc/calls/struct/winsize.h"
#include "libc/calls/ucontext.h" #include "libc/calls/ucontext.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/spinlock.h"
#include "libc/limits.h" #include "libc/limits.h"
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
#include "libc/nt/struct/context.h" #include "libc/nt/struct/context.h"
#include "libc/nt/struct/ntexceptionpointers.h" #include "libc/nt/struct/ntexceptionpointers.h"
#include "libc/nt/struct/overlapped.h"
#include "libc/nt/struct/securityattributes.h" #include "libc/nt/struct/securityattributes.h"
#include "libc/nt/struct/startupinfo.h" #include "libc/nt/struct/startupinfo.h"
#include "libc/nt/struct/systeminfo.h" #include "libc/nt/struct/systeminfo.h"
@ -58,8 +58,10 @@ enum FdKind {
struct Fd { struct Fd {
enum FdKind kind; enum FdKind kind;
unsigned flags; unsigned flags;
unsigned mode;
int64_t handle; int64_t handle;
int64_t extra; int64_t extra;
struct NtStdinWorker *worker;
bool zombie; bool zombie;
}; };
@ -73,16 +75,19 @@ struct Fds {
extern const struct Fd kEmptyFd; extern const struct Fd kEmptyFd;
hidden extern int __vforked; hidden extern int __vforked;
hidden extern char __fds_lock;
hidden extern char __sig_lock;
hidden extern bool __time_critical; hidden extern bool __time_critical;
hidden extern cthread_spinlock_t __sig_lock;
hidden extern unsigned __sighandrvas[NSIG]; hidden extern unsigned __sighandrvas[NSIG];
hidden extern unsigned __sighandflags[NSIG]; hidden extern unsigned __sighandflags[NSIG];
hidden extern struct Fds g_fds; hidden extern struct Fds g_fds;
hidden extern const struct NtSecurityAttributes kNtIsInheritable; hidden extern const struct NtSecurityAttributes kNtIsInheritable;
int __reservefd(void) hidden; int __reservefd(int) hidden;
void __releasefd(int) hidden; void __releasefd(int) hidden;
int __ensurefds(int) hidden; int __ensurefds(int) hidden;
int64_t __getfdhandleactual(int) hidden;
void __printfds(void);
forceinline bool __isfdopen(int fd) { forceinline bool __isfdopen(int fd) {
return 0 <= fd && fd < g_fds.n && g_fds.p[fd].kind != kFdEmpty; 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_renameat(i32, const char *, i32, const char *) hidden;
i32 sys_sched_setaffinity(i32, u64, const void *) hidden; i32 sys_sched_setaffinity(i32, u64, const void *) hidden;
i32 sys_sched_yield(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_setitimer(i32, const struct itimerval *, struct itimerval *) hidden;
i32 sys_setpgid(i32, i32) hidden; i32 sys_setpgid(i32, i32) hidden;
i32 sys_setpriority(i32, u32, 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_setresuid(uint32_t, uint32_t, uint32_t) hidden;
i32 sys_setrlimit(i32, const struct rlimit *) hidden; i32 sys_setrlimit(i32, const struct rlimit *) hidden;
i32 sys_setsid(void) hidden; i32 sys_setsid(void) hidden;
i32 sys_setuid(i32) hidden;
i32 sys_sigaction(i32, const void *, void *, i64, i64) hidden; i32 sys_sigaction(i32, const void *, void *, i64, i64) hidden;
i32 sys_sigaltstack(const void *, void *) hidden; i32 sys_sigaltstack(const void *, void *) hidden;
i32 sys_sigprocmask(i32, const sigset *, sigset *, u64) 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_splice(i32, i64 *, i32, i64 *, u64, u32) hidden;
i64 sys_vmsplice(i32, const struct iovec *, i64, u32) hidden; i64 sys_vmsplice(i32, const struct iovec *, i64, u32) hidden;
i64 sys_write(i32, const void *, u64) hidden; i64 sys_write(i32, const void *, u64) hidden;
u32 sys_geteuid(void) hidden;
u32 sys_getgid(void) hidden; u32 sys_getgid(void) hidden;
u32 sys_getsid(int) hidden; u32 sys_getsid(int) hidden;
u32 sys_gettid(void) 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_chdir_nt(const char *) hidden;
int sys_close_epoll_nt(int) hidden; int sys_close_epoll_nt(int) hidden;
int sys_close_nt(struct Fd *) 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_execve_nt(const char *, char *const[], char *const[]) hidden;
int sys_faccessat_nt(int, const char *, int, uint32_t) hidden; int sys_faccessat_nt(int, const char *, int, uint32_t) hidden;
int sys_fadvise_nt(int, u64, u64, int) 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); int64_t ntreturn(uint32_t);
ssize_t sys_readv_nt(struct Fd *, const struct iovec *, int) hidden; ssize_t sys_readv_nt(struct Fd *, const struct iovec *, int) hidden;
ssize_t sys_writev_nt(int, 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 *); unsigned __wincrash_nt(struct NtExceptionPointers *);
void *GetProcAddressModule(const char *, const char *) hidden; void *GetProcAddressModule(const char *, const char *) hidden;
void WinMainForked(void) hidden; void WinMainForked(void) hidden;
void _ntcontext2linux(struct ucontext *, const struct NtContext *) hidden; void _ntcontext2linux(struct ucontext *, const struct NtContext *) hidden;
void _ntlinux2context(struct NtContext *, const ucontext_t *) hidden; void _ntlinux2context(struct NtContext *, const ucontext_t *) hidden;
struct NtOverlapped *_offset2overlap(int64_t, int64_t,
struct NtOverlapped *) hidden;
/*───────────────────────────────────────────────────────────────────────────│─╗ /*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § syscalls » metal cosmopolitan § syscalls » metal

View file

@ -92,4 +92,6 @@ static textstartup void LoadavgNtInit(void) {
LoadavgNtPoll(hCounter, 0); LoadavgNtPoll(hCounter, 0);
} }
const void *const LoadavgNtCtor[] initarray = {LoadavgNtInit}; const void *const LoadavgNtCtor[] initarray = {
LoadavgNtInit,
};

View file

@ -18,6 +18,7 @@
*/ */
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h" #include "libc/intrin/asan.internal.h"
#include "libc/nt/ipc.h" #include "libc/nt/ipc.h"
@ -33,11 +34,15 @@
* @asyncsignalsafe * @asyncsignalsafe
*/ */
int mkfifo(const char *pathname, unsigned mode) { int mkfifo(const char *pathname, unsigned mode) {
/* TODO(jart): Windows? */ // TODO(jart): Windows?
if (IsAsan() && !__asan_is_valid(pathname, 1)) return efault(); int rc;
if (IsLinux()) { if (IsAsan() && !__asan_is_valid(pathname, 1)) {
return sys_mknod(pathname, mode | S_IFIFO, 0); rc = efault();
} else if (IsLinux()) {
rc = sys_mknod(pathname, mode | S_IFIFO, 0);
} else { } else {
return sys_mkfifo(pathname, mode); rc = sys_mkfifo(pathname, mode);
} }
STRACE("mkfifo(%#s, %#o) → %d% m", pathname, mode, rc);
return rc;
} }

View file

@ -49,10 +49,8 @@ textwindows noinstrument int sys_nanosleep_nt(const struct timespec *req,
} else { } else {
slice = ms; slice = ms;
} }
if (!__time_critical) {
STRACE("SleepEx(%u, true)", slice);
}
if (SleepEx(slice, true) == kNtWaitIoCompletion) { if (SleepEx(slice, true) == kNtWaitIoCompletion) {
STRACE("IOCP TRIGGERED EINTR");
rc = eintr(); rc = eintr();
break; break;
} }

View file

@ -18,9 +18,9 @@
*/ */
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/nt/struct/overlapped.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) { struct NtOverlapped *mem) {
if (opt_offset == -1) return NULL; if (opt_offset == -1) return NULL;
bzero(mem, sizeof(struct NtOverlapped)); bzero(mem, sizeof(struct NtOverlapped));

View file

@ -36,89 +36,12 @@
#include "libc/sysv/consts/o.h" #include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.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, static textwindows int64_t sys_open_nt_impl(int dirfd, const char *path,
uint32_t flags, int32_t mode) { uint32_t flags, int32_t mode) {
int64_t handle;
uint32_t br, err;
char16_t path16[PATH_MAX]; char16_t path16[PATH_MAX];
uint32_t perm, share, disp, attr; uint32_t perm, share, disp, attr;
if (__mkntpathat(dirfd, path, flags, path16) == -1) return -1; if (__mkntpathat(dirfd, path, flags, path16) == -1) return -1;
if (GetNtOpenFlags(flags, mode, &perm, &share, &disp, &attr) == -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;
return CreateFile(path16, perm, share, &kNtIsInheritable, disp, attr, 0); 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].kind = kFdConsole;
g_fds.p[fd].flags = flags; g_fds.p[fd].flags = flags;
g_fds.p[fd].mode = mode;
return fd; 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) { 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].kind = kFdFile;
g_fds.p[fd].flags = flags; g_fds.p[fd].flags = flags;
g_fds.p[fd].mode = mode;
return fd; return fd;
} else { } else {
return -1; return -1;
@ -160,7 +85,7 @@ textwindows ssize_t sys_open_nt(int dirfd, const char *file, uint32_t flags,
int32_t mode) { int32_t mode) {
int fd; int fd;
ssize_t rc; 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)) { if ((flags & O_ACCMODE) == O_RDWR && !strcmp(file, kNtMagicPaths.devtty)) {
rc = sys_open_nt_console(dirfd, &kNtMagicPaths, flags, mode, fd); rc = sys_open_nt_console(dirfd, &kNtMagicPaths, flags, mode, fd);
} else { } else {

View file

@ -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);
}

View file

@ -29,12 +29,13 @@ int sys_openat_metal(int dirfd, const char *file, int flags, unsigned mode) {
struct MetalFile *state; struct MetalFile *state;
if (strcmp(file, "ape.com")) return enoent(); if (strcmp(file, "ape.com")) return enoent();
if (!weaken(calloc)) return enomem(); 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 = weaken(calloc)(1, sizeof(struct MetalFile));
state->base = (char *)_base; state->base = (char *)_base;
state->size = _end - _base; state->size = _end - _base;
g_fds.p[fd].kind = kFdFile; g_fds.p[fd].kind = kFdFile;
g_fds.p[fd].flags = flags; g_fds.p[fd].flags = flags;
g_fds.p[fd].mode = mode;
g_fds.p[fd].handle = (intptr_t)state; g_fds.p[fd].handle = (intptr_t)state;
return fd; return fd;
} }

View file

@ -20,31 +20,41 @@
#include "libc/nt/createfile.h" #include "libc/nt/createfile.h"
#include "libc/nt/enum/accessmask.h" #include "libc/nt/enum/accessmask.h"
#include "libc/nt/enum/creationdisposition.h" #include "libc/nt/enum/creationdisposition.h"
#include "libc/nt/enum/fileflagandattributes.h"
#include "libc/nt/ipc.h" #include "libc/nt/ipc.h"
#include "libc/nt/runtime.h" #include "libc/nt/runtime.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
textwindows int sys_pipe_nt(int pipefd[2], unsigned flags) { textwindows int sys_pipe_nt(int pipefd[2], unsigned flags) {
uint32_t mode;
int64_t hin, hout; int64_t hin, hout;
int reader, writer; int reader, writer;
char16_t pipename[64]; char16_t pipename[64];
if (!pipefd) return efault(); if (!pipefd) return efault();
CreatePipeName(pipename); CreatePipeName(pipename);
if ((reader = __reservefd()) == -1) return -1; if ((reader = __reservefd(-1)) == -1) return -1;
if ((writer = __reservefd()) == -1) { if ((writer = __reservefd(-1)) == -1) {
__releasefd(reader); __releasefd(reader);
return -1; return -1;
} }
if ((hin = CreateNamedPipe(pipename, kNtPipeAccessInbound, if (~flags & O_DIRECT) {
kNtPipeWait | kNtPipeReadmodeByte, 1, 65536, 65536, mode = kNtPipeTypeByte | kNtPipeReadmodeByte;
0, &kNtIsInheritable)) != -1) { } else {
mode = kNtPipeTypeMessage | kNtPipeReadmodeMessage;
}
if ((hin = CreateNamedPipe(pipename,
kNtPipeAccessInbound | kNtFileFlagOverlapped, mode,
1, 512, 512, 0, &kNtIsInheritable)) != -1) {
if ((hout = CreateFile(pipename, kNtGenericWrite, 0, &kNtIsInheritable, 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].kind = kFdFile;
g_fds.p[reader].flags = flags; g_fds.p[reader].flags = flags;
g_fds.p[reader].mode = 0010444;
g_fds.p[reader].handle = hin; g_fds.p[reader].handle = hin;
g_fds.p[writer].kind = kFdFile; g_fds.p[writer].kind = kFdFile;
g_fds.p[writer].flags = flags; g_fds.p[writer].flags = flags;
g_fds.p[writer].mode = 0010222;
g_fds.p[writer].handle = hout; g_fds.p[writer].handle = hout;
pipefd[0] = reader; pipefd[0] = reader;
pipefd[1] = writer; pipefd[1] = writer;

View file

@ -18,6 +18,7 @@
*/ */
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h" #include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
@ -31,10 +32,18 @@
* @see pipe2() * @see pipe2()
*/ */
int pipe(int pipefd[hasatleast 2]) { int pipe(int pipefd[hasatleast 2]) {
if (IsAsan() && !__asan_is_valid(pipefd, sizeof(int) * 2)) return efault(); int rc;
if (!IsWindows()) { if (IsAsan() && !__asan_is_valid(pipefd, sizeof(int) * 2)) {
return sys_pipe(pipefd); rc = efault();
} else if (!IsWindows()) {
rc = sys_pipe(pipefd);
} else { } 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;
} }

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h" #include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
@ -29,11 +30,20 @@
* @return 0 on success, or -1 w/ errno and pipefd isn't modified * @return 0 on success, or -1 w/ errno and pipefd isn't modified
*/ */
int pipe2(int pipefd[hasatleast 2], int flags) { int pipe2(int pipefd[hasatleast 2], int flags) {
if (!pipefd) return efault(); int rc;
if (IsAsan() && !__asan_is_valid(pipefd, sizeof(int) * 2)) return efault(); if (!pipefd) {
if (!IsWindows()) { rc = efault();
return sys_pipe2(pipefd, flags); } else if (IsAsan() && !__asan_is_valid(pipefd, sizeof(int) * 2)) {
rc = efault();
} else if (!IsWindows()) {
rc = sys_pipe2(pipefd, flags);
} else { } 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
View 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);
}
}

View file

@ -23,6 +23,7 @@
#include "libc/calls/strace.internal.h" #include "libc/calls/strace.internal.h"
#include "libc/intrin/kprintf.h" #include "libc/intrin/kprintf.h"
#include "libc/nt/console.h" #include "libc/nt/console.h"
#include "libc/nt/errors.h"
#include "libc/nt/process.h" #include "libc/nt/process.h"
#include "libc/nt/runtime.h" #include "libc/nt/runtime.h"
#include "libc/nt/synchronization.h" #include "libc/nt/synchronization.h"
@ -65,7 +66,9 @@ int raise(int sig) {
// doesn't make any sense and it's so evil. // doesn't make any sense and it's so evil.
if (GenerateConsoleCtrlEvent(event, 0)) { if (GenerateConsoleCtrlEvent(event, 0)) {
// XXX: we shouldn't need to sleep here ctrl-c is evil on nt // 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); __sig_check(false);
rc = 0; rc = 0;
} else { } else {

View file

@ -20,30 +20,48 @@
#include "libc/bits/bits.h" #include "libc/bits/bits.h"
#include "libc/bits/weaken.h" #include "libc/bits/weaken.h"
#include "libc/calls/internal.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/calls/struct/iovec.h"
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/intrin/kprintf.h"
#include "libc/limits.h" #include "libc/limits.h"
#include "libc/nt/enum/wait.h"
#include "libc/nt/errors.h" #include "libc/nt/errors.h"
#include "libc/nt/files.h"
#include "libc/nt/ipc.h"
#include "libc/nt/runtime.h" #include "libc/nt/runtime.h"
#include "libc/nt/struct/overlapped.h" #include "libc/nt/struct/overlapped.h"
#include "libc/nt/synchronization.h"
#include "libc/sock/internal.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
static textwindows ssize_t sys_read_nt_impl(struct Fd *fd, void *data, static textwindows ssize_t sys_read_nt_impl(struct Fd *fd, void *data,
size_t size, ssize_t offset) { size_t size, ssize_t offset) {
uint32_t got; uint32_t err, got, avail;
struct NtOverlapped overlap; struct NtOverlapped overlap;
if (ReadFile(fd->handle, data, _clampio(size), &got, if (fd->worker) {
_offset2overlap(offset, &overlap))) { for (;;) {
return got; if (!PeekNamedPipe(fd->handle, 0, 0, 0, &avail, 0)) break;
} else if ( if (avail) break;
// make sure read() returns 0 on broken pipe if (SleepEx(__SIG_POLLING_INTERVAL_MS, true) == kNtWaitIoCompletion ||
GetLastError() == kNtErrorBrokenPipe || _check_interrupts(true, g_fds.p)) {
// make sure pread() returns 0 if we start reading after EOF return eintr();
GetLastError() == kNtErrorHandleEof) { }
return 0; }
} else {
return __winerr();
} }
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, textwindows ssize_t sys_read_nt(struct Fd *fd, const struct iovec *iov,

View file

@ -23,6 +23,7 @@
#include "libc/calls/struct/iovec.h" #include "libc/calls/struct/iovec.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h" #include "libc/intrin/asan.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/sock/internal.h" #include "libc/sock/internal.h"
#include "libc/sock/sock.h" #include "libc/sock/sock.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"

View file

@ -28,7 +28,7 @@ textwindows ssize_t sys_readv_nt(struct Fd *fd, const struct iovec *iov,
case kFdConsole: case kFdConsole:
return sys_read_nt(fd, iov, iovlen, -1); return sys_read_nt(fd, iov, iovlen, -1);
case kFdSocket: case kFdSocket:
return weaken(sys_recvfrom_nt)(fd, iov, iovlen, 0, NULL, 0); return weaken(sys_recv_nt)(fd, iov, iovlen, 0);
default: default:
return ebadf(); return ebadf();
} }

View file

@ -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) { ssize_t sys_readv_serial(struct Fd *fd, const struct iovec *iov, int iovlen) {
size_t i; size_t i;
if ((i = GetFirstIov(iov, iovlen)) != -1) { 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); ((char *)iov[i].iov_base)[0] = inb(fd->handle);
return 1; return 1;
} else { } else {

View file

@ -17,16 +17,14 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/intrin/cmpxchg.h" #include "libc/intrin/spinlock.h"
#include "libc/intrin/lockcmpxchg.h" #include "libc/macros.internal.h"
void __releasefd(int fd) { void __releasefd(int fd) {
int x; if (0 <= fd && fd < g_fds.n) {
if (!__vforked && 0 <= fd && fd < g_fds.n) { _spinlock(&__fds_lock);
bzero(g_fds.p + fd, sizeof(*g_fds.p)); g_fds.p[fd].kind = 0;
do { g_fds.f = MIN(fd, g_fds.f);
x = g_fds.f; _spunlock(&__fds_lock);
if (fd >= x) break;
} while (!_lockcmpxchg(&g_fds.f, x, fd));
} }
} }

View file

@ -16,24 +16,98 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. 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/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/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.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. * Finds open file descriptor slot.
*/ */
int __reservefd(void) { int __reservefd(int start) {
int fd; int fd;
for (;;) { for (;;) {
fd = g_fds.f; _spinlock(&__fds_lock);
if (fd >= g_fds.n) { fd = start < 0 ? g_fds.f : start;
if (__ensurefds(fd) == -1) return -1; while (fd < g_fds.n && g_fds.p[fd].kind) ++fd;
} if (fd < g_fds.n) {
_cmpxchg(&g_fds.f, fd, fd + 1); g_fds.f = fd + 1;
if (_cmpxchg(&g_fds.p[fd].kind, kFdEmpty, kFdReserved)) { bzero(g_fds.p + fd, sizeof(*g_fds.p));
g_fds.p[fd].kind = kFdReserved;
_spunlock(&__fds_lock);
return fd; 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
View 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
View 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;
}

View file

@ -38,7 +38,7 @@ textwindows int __sig_mask(int how, const sigset_t *neu, sigset_t *old) {
int i; int i;
uint64_t a, b; uint64_t a, b;
if (how == SIG_BLOCK || how == SIG_UNBLOCK || how == SIG_SETMASK) { if (how == SIG_BLOCK || how == SIG_UNBLOCK || how == SIG_SETMASK) {
cthread_spinlock(&__sig_lock); _spinlock(&__sig_lock);
if (old) { if (old) {
*old = __sig.mask; *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); __sig.mask.__bits[0] &= ~(SIGKILL | SIGSTOP);
} }
cthread_spunlock(&__sig_lock); _spunlock(&__sig_lock);
return 0; return 0;
} else { } else {
return einval(); return einval();

View file

@ -64,7 +64,7 @@ static textwindows void __sig_free(struct Signal *mem) {
static textwindows struct Signal *__sig_remove(void) { static textwindows struct Signal *__sig_remove(void) {
struct Signal *prev, *res; struct Signal *prev, *res;
if (__sig.queue) { if (__sig.queue) {
cthread_spinlock(&__sig_lock); _spinlock(&__sig_lock);
for (prev = 0, res = __sig.queue; res; prev = res, res = res->next) { for (prev = 0, res = __sig.queue; res; prev = res, res = res->next) {
if (!sigismember(&__sig.mask, res->sig)) { if (!sigismember(&__sig.mask, res->sig)) {
if (res == __sig.queue) { if (res == __sig.queue) {
@ -78,7 +78,7 @@ static textwindows struct Signal *__sig_remove(void) {
STRACE("%G is masked", res->sig); STRACE("%G is masked", res->sig);
} }
} }
cthread_spunlock(&__sig_lock); _spunlock(&__sig_lock);
} else { } else {
res = 0; res = 0;
} }
@ -97,7 +97,7 @@ static textwindows bool __sig_deliver(bool restartable, int sig, int si_code,
STRACE("delivering %G", sig); STRACE("delivering %G", sig);
// enter the signal // enter the signal
cthread_spinlock(&__sig_lock); _spinlock(&__sig_lock);
rva = __sighandrvas[sig]; rva = __sighandrvas[sig];
flags = __sighandflags[sig]; flags = __sighandflags[sig];
if ((~flags & SA_NODEFER) || (flags & SA_RESETHAND)) { 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. // signal handler. in that case you must use SA_NODEFER.
__sighandrvas[sig] = (int32_t)(intptr_t)SIG_DFL; __sighandrvas[sig] = (int32_t)(intptr_t)SIG_DFL;
} }
cthread_spunlock(&__sig_lock); _spunlock(&__sig_lock);
// setup the somewhat expensive information args // setup the somewhat expensive information args
// only if they're requested by the user in sigaction() // 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 // since sigaction() is @asyncsignalsafe we only restore it if the
// user didn't change it during the signal handler. we also don't // 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. // 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); _cmpxchg(__sighandrvas + sig, (int32_t)(intptr_t)SIG_DFL, rva);
cthread_spunlock(&__sig_lock); _spunlock(&__sig_lock);
} }
if (!restartable) { 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) { textwindows int __sig_raise(int sig, int si_code) {
int rc; int rc;
int candeliver; int candeliver;
cthread_spinlock(&__sig_lock); _spinlock(&__sig_lock);
candeliver = !sigismember(&__sig.mask, sig); candeliver = !sigismember(&__sig.mask, sig);
cthread_spunlock(&__sig_lock); _spunlock(&__sig_lock);
switch (candeliver) { switch (candeliver) {
case 1: case 1:
__sig_handle(false, sig, si_code, 0); __sig_handle(false, sig, si_code, 0);
@ -217,7 +217,7 @@ textwindows int __sig_add(int sig, int si_code) {
struct Signal *mem; struct Signal *mem;
if (1 <= sig && sig <= NSIG) { if (1 <= sig && sig <= NSIG) {
STRACE("enqueuing %G", sig); STRACE("enqueuing %G", sig);
cthread_spinlock(&__sig_lock); _spinlock(&__sig_lock);
if ((mem = __sig_alloc())) { if ((mem = __sig_alloc())) {
mem->sig = sig; mem->sig = sig;
mem->si_code = si_code; mem->si_code = si_code;
@ -227,7 +227,7 @@ textwindows int __sig_add(int sig, int si_code) {
} else { } else {
rc = enomem(); rc = enomem();
} }
cthread_spunlock(&__sig_lock); _spunlock(&__sig_lock);
} else { } else {
rc = einval(); rc = einval();
} }

View file

@ -213,7 +213,7 @@ static int __sigaction(int sig, const struct sigaction *act,
rc = 0; rc = 0;
} }
if (rc != -1 && !__vforked) { if (rc != -1 && !__vforked) {
cthread_spinlock(&__sig_lock); _spinlock(&__sig_lock);
if (oldact) { if (oldact) {
oldrva = __sighandrvas[sig]; oldrva = __sighandrvas[sig];
oldact->sa_sigaction = (sigaction_f)( oldact->sa_sigaction = (sigaction_f)(
@ -223,7 +223,7 @@ static int __sigaction(int sig, const struct sigaction *act,
__sighandrvas[sig] = rva; __sighandrvas[sig] = rva;
__sighandflags[sig] = act->sa_flags; __sighandflags[sig] = act->sa_flags;
} }
cthread_spunlock(&__sig_lock); _spunlock(&__sig_lock);
} }
return rc; return rc;
} }

View file

@ -26,6 +26,7 @@
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h" #include "libc/intrin/asan.internal.h"
#include "libc/log/backtrace.internal.h" #include "libc/log/backtrace.internal.h"
#include "libc/nt/errors.h"
#include "libc/nt/synchronization.h" #include "libc/nt/synchronization.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
@ -76,7 +77,11 @@ int sigsuspend(const sigset_t *ignore) {
rc = eintr(); rc = eintr();
break; break;
} }
SleepEx(__SIG_POLLING_INTERVAL_MS, true); if (SleepEx(__SIG_POLLING_INTERVAL_MS, true) == kNtWaitIoCompletion) {
STRACE("IOCP TRIGGERED EINTR");
rc = eintr();
break;
}
#ifdef SYSDEBUG #ifdef SYSDEBUG
ms += __SIG_POLLING_INTERVAL_MS; ms += __SIG_POLLING_INTERVAL_MS;
if (ms >= __SIG_LOGGING_INTERVAL_MS) { if (ms >= __SIG_LOGGING_INTERVAL_MS) {

View file

@ -67,7 +67,7 @@ static textwindows int sys_wait4_nt_impl(int pid, int *opt_out_wstatus,
if (!__isfdopen(pid) && if (!__isfdopen(pid) &&
(handle = OpenProcess(kNtSynchronize | kNtProcessQueryInformation, (handle = OpenProcess(kNtSynchronize | kNtProcessQueryInformation,
true, pid))) { true, pid))) {
if ((pid = __reservefd()) != -1) { if ((pid = __reservefd(-1)) != -1) {
g_fds.p[pid].kind = kFdProcess; g_fds.p[pid].kind = kFdProcess;
g_fds.p[pid].handle = handle; g_fds.p[pid].handle = handle;
g_fds.p[pid].flags = O_CLOEXEC; 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) { if (opt_out_rusage) {
bzero(opt_out_rusage, sizeof(*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))) { if (GetProcessMemoryInfo(handles[i], &memcount, sizeof(memcount))) {
opt_out_rusage->ru_maxrss = memcount.PeakWorkingSetSize / 1024; opt_out_rusage->ru_maxrss = memcount.PeakWorkingSetSize / 1024;
opt_out_rusage->ru_majflt = memcount.PageFaultCount; opt_out_rusage->ru_majflt = memcount.PageFaultCount;

View file

@ -18,6 +18,7 @@
*/ */
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/sig.internal.h" #include "libc/calls/sig.internal.h"
#include "libc/calls/sigbits.h"
#include "libc/calls/strace.internal.h" #include "libc/calls/strace.internal.h"
#include "libc/calls/typedef/sigaction_f.h" #include "libc/calls/typedef/sigaction_f.h"
#include "libc/calls/ucontext.h" #include "libc/calls/ucontext.h"

View file

@ -19,6 +19,8 @@
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
.init.start 300,_init_wincrash .init.start 300,_init_wincrash
mov __wincrashearly(%rip),%rcx
ntcall __imp_RemoveVectoredExceptionHandler
pushpop 1,%rcx pushpop 1,%rcx
ezlea __wincrash_nt,dx ezlea __wincrash_nt,dx
ntcall __imp_AddVectoredExceptionHandler ntcall __imp_AddVectoredExceptionHandler

View 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;

View file

@ -23,12 +23,14 @@
#include "libc/calls/struct/iovec.h" #include "libc/calls/struct/iovec.h"
#include "libc/calls/struct/siginfo.h" #include "libc/calls/struct/siginfo.h"
#include "libc/calls/typedef/sigaction_f.h" #include "libc/calls/typedef/sigaction_f.h"
#include "libc/intrin/kprintf.h"
#include "libc/limits.h" #include "libc/limits.h"
#include "libc/nt/errors.h" #include "libc/nt/errors.h"
#include "libc/nt/files.h" #include "libc/nt/files.h"
#include "libc/nt/runtime.h" #include "libc/nt/runtime.h"
#include "libc/nt/struct/overlapped.h" #include "libc/nt/struct/overlapped.h"
#include "libc/runtime/internal.h" #include "libc/runtime/internal.h"
#include "libc/sock/internal.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/sysv/consts/sicode.h" #include "libc/sysv/consts/sicode.h"
#include "libc/sysv/consts/sig.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, static textwindows ssize_t sys_write_nt_impl(int fd, void *data, size_t size,
ssize_t offset) { ssize_t offset) {
uint32_t sent; uint32_t err, sent;
struct NtOverlapped overlap; struct NtOverlapped overlap;
if (WriteFile(g_fds.p[fd].handle, data, _clampio(size), &sent, if (WriteFile(g_fds.p[fd].handle, data, _clampio(size), &sent,
_offset2overlap(offset, &overlap))) { _offset2overlap(g_fds.p[fd].handle, offset, &overlap))) {
return sent; 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); __sig_raise(SIGPIPE, SI_KERNEL);
return epipe(); return epipe();
} else {
return __winerr();
} }
return __winerr();
} }
textwindows ssize_t sys_write_nt(int fd, const struct iovec *iov, size_t iovlen, textwindows ssize_t sys_write_nt(int fd, const struct iovec *iov, size_t iovlen,

View file

@ -27,7 +27,7 @@ textwindows ssize_t sys_writev_nt(int fd, const struct iovec *iov, int iovlen) {
case kFdConsole: case kFdConsole:
return sys_write_nt(fd, iov, iovlen, -1); return sys_write_nt(fd, iov, iovlen, -1);
case kFdSocket: case kFdSocket:
return weaken(sys_sendto_nt)(fd, iov, iovlen, 0, NULL, 0); return weaken(sys_send_nt)(fd, iov, iovlen, 0);
default: default:
return ebadf(); return ebadf();
} }

View file

@ -24,7 +24,9 @@ ssize_t sys_writev_serial(struct Fd *fd, const struct iovec *iov, int iovlen) {
size_t i, j, wrote = 0; size_t i, j, wrote = 0;
for (i = 0; i < iovlen; ++i) { for (i = 0; i < iovlen; ++i) {
for (j = 0; j < iov[i].iov_len; ++j) { 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]); outb(fd->handle, ((char *)iov[i].iov_base)[j]);
++wrote; ++wrote;
} }

View file

@ -27,6 +27,7 @@ int vsscanf(const char *, const char *, va_list);
int vcscanf(int (*)(void *), int (*)(int, void *), void *, const char *, int vcscanf(int (*)(void *), int (*)(int, void *), void *, const char *,
va_list); va_list);
int strerror_r(int, char *, size_t) dontthrow nocallback; 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_short(int) nosideeffect;
const char *strerror_long(int) nosideeffect; const char *strerror_long(int) nosideeffect;
int __fmt(void *, void *, const char *, va_list) hidden; int __fmt(void *, void *, const char *, va_list) hidden;

View file

@ -16,23 +16,8 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. 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/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/nt/runtime.h"
#include "libc/str/str.h"
#include "libc/str/tpenc.h"
/** /**
* Converts errno value to string. * Converts errno value to string.
@ -41,32 +26,5 @@
* @return 0 on success, or error code * @return 0 on success, or error code
*/ */
privileged int strerror_r(int err, char *buf, size_t size) { privileged int strerror_r(int err, char *buf, size_t size) {
/* kprintf() weakly depends on this function */ return strerror_wr(err, GetLastError(), buf, size);
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;
} }

View 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;
}

View file

@ -51,13 +51,13 @@
#include "libc/sysv/consts/nr.h" #include "libc/sysv/consts/nr.h"
#include "libc/sysv/consts/prot.h" #include "libc/sysv/consts/prot.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
#include "third_party/dlmalloc/dlmalloc.internal.h" #include "third_party/dlmalloc/dlmalloc.h"
STATIC_YOINK("_init_asan"); STATIC_YOINK("_init_asan");
#define ASAN_MORGUE_ITEMS 512 #define ASAN_MORGUE_ITEMS 512
#define ASAN_MORGUE_THRESHOLD 65536 // morgue memory O(ITEMS*THRESHOLD) #define ASAN_MORGUE_THRESHOLD 65536 // morgue memory O(ITEMS*THRESHOLD)
#define ASAN_TRACE_ITEMS 16 // backtrace limit on malloc origin #define ASAN_TRACE_ITEMS 16 // backtrace limit on malloc origin
/** /**
* @fileoverview Cosmopolitan Address Sanitizer Runtime. * @fileoverview Cosmopolitan Address Sanitizer Runtime.
@ -177,8 +177,7 @@ static uint64_t __asan_roundup2pow(uint64_t x) {
static char *__asan_utf8cpy(char *p, unsigned c) { static char *__asan_utf8cpy(char *p, unsigned c) {
uint64_t z; uint64_t z;
z = tpenc(c); z = tpenc(c);
do do *p++ = z;
*p++ = z;
while ((z >>= 8)); while ((z >>= 8));
return p; 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) { if (!__asan_checka(SHADOW(bp), sizeof(*bp) >> 3).kind) {
addr = bp->addr; addr = bp->addr;
if (addr == weakaddr("__gc") && weakaddr("__gc")) { if (addr == weakaddr("__gc") && weakaddr("__gc")) {
do do --gi;
--gi;
while ((addr = garbage->p[gi].ret) == weakaddr("__gc")); while ((addr = garbage->p[gi].ret) == weakaddr("__gc"));
} }
bt->p[i] = addr; bt->p[i] = addr;

View file

@ -18,6 +18,7 @@
*/ */
#include "libc/assert.h" #include "libc/assert.h"
#include "libc/bits/weaken.h" #include "libc/bits/weaken.h"
#include "libc/calls/strace.internal.h"
#include "libc/intrin/cmpxchg.h" #include "libc/intrin/cmpxchg.h"
#include "libc/intrin/kprintf.h" #include "libc/intrin/kprintf.h"
#include "libc/intrin/lockcmpxchg.h" #include "libc/intrin/lockcmpxchg.h"
@ -32,6 +33,8 @@ relegated wontreturn void __assert_fail(const char *expr, const char *file,
int line) { int line) {
int rc; int rc;
static bool noreentry; static bool noreentry;
__strace = 0;
g_ftrace = 0;
kprintf("%s:%d: assert(%s) failed%n", file, line, expr); kprintf("%s:%d: assert(%s) failed%n", file, line, expr);
if (_lockcmpxchg(&noreentry, false, true)) { if (_lockcmpxchg(&noreentry, false, true)) {
if (weaken(__die)) { if (weaken(__die)) {

View file

@ -16,12 +16,14 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/bits/weaken.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h" #include "libc/calls/strace.internal.h"
#include "libc/log/log.h"
#include "libc/nt/runtime.h" #include "libc/nt/runtime.h"
#include "libc/nt/thunk/msabi.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. * Closes an open object handle.
@ -30,7 +32,10 @@ extern typeof(CloseHandle) *const __imp_CloseHandle __msabi;
textwindows bool32 CloseHandle(int64_t hObject) { textwindows bool32 CloseHandle(int64_t hObject) {
bool32 ok; bool32 ok;
ok = __imp_CloseHandle(hObject); ok = __imp_CloseHandle(hObject);
if (!ok) __winerr(); if (!ok) {
__winerr();
if (weaken(__die)) weaken(__die)();
}
STRACE("CloseHandle(%ld) → %hhhd% m", hObject, ok); STRACE("CloseHandle(%ld) → %hhhd% m", hObject, ok);
return ok; return ok;
} }

View file

@ -18,10 +18,11 @@
*/ */
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h" #include "libc/calls/strace.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/nt/files.h" #include "libc/nt/files.h"
#include "libc/nt/thunk/msabi.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. * Creates directory on the New Technology.
@ -35,7 +36,7 @@ CreateDirectory(const char16_t *lpPathName,
bool32 ok; bool32 ok;
ok = __imp_CreateDirectoryW(lpPathName, lpSecurityAttributes); ok = __imp_CreateDirectoryW(lpPathName, lpSecurityAttributes);
if (!ok) __winerr(); if (!ok) __winerr();
STRACE("CreateDirectory(%#hs, %p) → %hhhd% m", lpPathName, STRACE("CreateDirectory(%#hs, %s) → %hhhd% m", lpPathName,
lpSecurityAttributes, ok); DescribeNtSecurityAttributes(lpSecurityAttributes), ok);
return ok; return ok;
} }

View file

@ -20,27 +20,9 @@
#include "libc/calls/strace.internal.h" #include "libc/calls/strace.internal.h"
#include "libc/intrin/describeflags.internal.h" #include "libc/intrin/describeflags.internal.h"
#include "libc/nt/createfile.h" #include "libc/nt/createfile.h"
#include "libc/nt/enum/creationdisposition.h"
#include "libc/nt/thunk/msabi.h" #include "libc/nt/thunk/msabi.h"
extern typeof(CreateFile) *const __imp_CreateFileW __msabi; __msabi extern typeof(CreateFile) *const __imp_CreateFileW;
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";
}
}
/** /**
* Opens file on the New Technology. * Opens file on the New Technology.
@ -58,10 +40,11 @@ textwindows int64_t CreateFile(
opt_lpSecurityAttributes, dwCreationDisposition, opt_lpSecurityAttributes, dwCreationDisposition,
dwFlagsAndAttributes, opt_hTemplateFile); dwFlagsAndAttributes, opt_hTemplateFile);
if (hHandle == -1) __winerr(); 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), DescribeNtFileAccessFlags(dwDesiredAccess),
DescribeNtFileShareFlags(dwShareMode), opt_lpSecurityAttributes, DescribeNtFileShareFlags(dwShareMode),
DescribeDisposition(dwCreationDisposition), DescribeNtSecurityAttributes(opt_lpSecurityAttributes),
DescribeNtCreationDisposition(dwCreationDisposition),
DescribeNtFileFlagsAndAttributes(dwFlagsAndAttributes), DescribeNtFileFlagsAndAttributes(dwFlagsAndAttributes),
opt_hTemplateFile, hHandle); opt_hTemplateFile, hHandle);
return hHandle; return hHandle;

View file

@ -23,7 +23,7 @@
#include "libc/nt/struct/securityattributes.h" #include "libc/nt/struct/securityattributes.h"
#include "libc/nt/thunk/msabi.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. * Creates file mapping object on the New Technology.
@ -43,7 +43,8 @@ textwindows int64_t CreateFileMapping(
flProtect, dwMaximumSizeHigh, flProtect, dwMaximumSizeHigh,
dwMaximumSizeLow, opt_lpName); dwMaximumSizeLow, opt_lpName);
if (!hHandle) __winerr(); 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), DescribeNtPageFlags(flProtect),
(uint64_t)dwMaximumSizeHigh << 32 | dwMaximumSizeLow, opt_lpName, (uint64_t)dwMaximumSizeHigh << 32 | dwMaximumSizeLow, opt_lpName,
hHandle); hHandle);

View file

@ -23,8 +23,8 @@
#include "libc/nt/memory.h" #include "libc/nt/memory.h"
#include "libc/nt/struct/securityattributes.h" #include "libc/nt/struct/securityattributes.h"
extern typeof(CreateFileMappingNuma) *const __msabi extern typeof(CreateFileMappingNuma) *const
__imp_CreateFileMappingNumaW __msabi; __imp_CreateFileMappingNumaW;
/** /**
* Creates file mapping object on the New Technology. * Creates file mapping object on the New Technology.
@ -44,8 +44,9 @@ textwindows int64_t CreateFileMappingNuma(
opt_hFile, opt_lpFileMappingAttributes, flProtect, dwMaximumSizeHigh, opt_hFile, opt_lpFileMappingAttributes, flProtect, dwMaximumSizeHigh,
dwMaximumSizeLow, opt_lpName, nndDesiredNumaNode); dwMaximumSizeLow, opt_lpName, nndDesiredNumaNode);
if (!hHandle) __winerr(); if (!hHandle) __winerr();
STRACE("CreateFileMappingNuma(%ld, %s, max:%'zu, name:%#hs) → %ld% m", STRACE("CreateFileMappingNuma(%ld, %s, %s, %'zu, %#hs) → %ld% m", opt_hFile,
opt_hFile, DescribeNtPageFlags(flProtect), DescribeNtSecurityAttributes(opt_lpFileMappingAttributes),
DescribeNtPageFlags(flProtect),
(uint64_t)dwMaximumSizeHigh << 32 | dwMaximumSizeLow, opt_lpName, (uint64_t)dwMaximumSizeHigh << 32 | dwMaximumSizeLow, opt_lpName,
hHandle); hHandle);
return hHandle; return hHandle;

View file

@ -18,11 +18,12 @@
*/ */
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h" #include "libc/calls/strace.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/nt/ipc.h" #include "libc/nt/ipc.h"
#include "libc/nt/struct/securityattributes.h" #include "libc/nt/struct/securityattributes.h"
#include "libc/nt/thunk/msabi.h" #include "libc/nt/thunk/msabi.h"
extern typeof(CreateNamedPipe) *const __imp_CreateNamedPipeW __msabi; __msabi extern typeof(CreateNamedPipe) *const __imp_CreateNamedPipeW;
/** /**
* Creates pipe. * Creates pipe.
@ -40,16 +41,10 @@ textwindows int64_t CreateNamedPipe(
nMaxInstances, nOutBufferSize, nInBufferSize, nMaxInstances, nOutBufferSize, nInBufferSize,
nDefaultTimeOutMs, opt_lpSecurityAttributes); nDefaultTimeOutMs, opt_lpSecurityAttributes);
if (hServer == -1) __winerr(); if (hServer == -1) __winerr();
STRACE("CreateNamedPipe(%#hs," STRACE("CreateNamedPipe(%#hs, %s, %s, %u, %'u, %'u, %'u, %s) → %ld% m",
" dwOpenMode=%u," lpName, DescribeNtPipeOpenFlags(dwOpenMode),
" dwPipeMode=%u," DescribeNtPipeModeFlags(dwPipeMode), nMaxInstances, nOutBufferSize,
" nMaxInstances=%u," nInBufferSize, nDefaultTimeOutMs,
" nOutBufferSize=%'u," DescribeNtSecurityAttributes(opt_lpSecurityAttributes), hServer);
" nInBufferSize=%'u,"
" nDefaultTimeOutMs=%'u,"
" lpSecurity=%p) → "
"%ld% m",
lpName, dwOpenMode, dwPipeMode, nMaxInstances, nOutBufferSize,
nInBufferSize, nDefaultTimeOutMs, opt_lpSecurityAttributes, hServer);
return hServer; return hServer;
} }

View file

@ -18,11 +18,12 @@
*/ */
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h" #include "libc/calls/strace.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/nt/ipc.h" #include "libc/nt/ipc.h"
#include "libc/nt/struct/securityattributes.h" #include "libc/nt/struct/securityattributes.h"
#include "libc/nt/thunk/msabi.h" #include "libc/nt/thunk/msabi.h"
extern typeof(CreatePipe) *const __imp_CreatePipe __msabi; __msabi extern typeof(CreatePipe) *const __imp_CreatePipe;
/** /**
* Creates anonymous pipe. * Creates anonymous pipe.
@ -35,7 +36,8 @@ textwindows bool32 CreatePipe(
ok = __imp_CreatePipe(out_hReadPipe, out_hWritePipe, opt_lpPipeAttributes, ok = __imp_CreatePipe(out_hReadPipe, out_hWritePipe, opt_lpPipeAttributes,
nSize); nSize);
if (!ok) __winerr(); if (!ok) __winerr();
STRACE("CreatePipe([%ld], [%ld], %p, %'zu) → %hhhd% m", *out_hReadPipe, STRACE("CreatePipe([%ld], [%ld], %s, %'zu) → %hhhd% m", *out_hReadPipe,
*out_hWritePipe, opt_lpPipeAttributes, nSize, ok); *out_hWritePipe, DescribeNtSecurityAttributes(opt_lpPipeAttributes),
nSize, ok);
return ok; return ok;
} }

View file

@ -18,10 +18,11 @@
*/ */
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h" #include "libc/calls/strace.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/nt/process.h" #include "libc/nt/process.h"
#include "libc/nt/thunk/msabi.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. * Creates process on the New Technology.
@ -44,10 +45,11 @@ CreateProcess(const char16_t *opt_lpApplicationName, char16_t *lpCommandLine,
opt_out_lpProcessInformation); opt_out_lpProcessInformation);
if (!ok) __winerr(); if (!ok) __winerr();
STRACE( STRACE(
"CreateFile(%#hs, %#hs, %p, %p, %hhhd, %u, %p, %#hs, %p, %p) → %hhhd% m", "CreateFile(%#hs, %#hs, %s, %s, %hhhd, %u, %p, %#hs, %p, %p) → %hhhd% m",
opt_lpApplicationName, lpCommandLine, opt_lpProcessAttributes, opt_lpApplicationName, lpCommandLine,
opt_lpThreadAttributes, bInheritHandles, dwCreationFlags, DescribeNtSecurityAttributes(opt_lpProcessAttributes),
opt_lpEnvironment, opt_lpCurrentDirectory, lpStartupInfo, DescribeNtSecurityAttributes(opt_lpThreadAttributes), bInheritHandles,
dwCreationFlags, opt_lpEnvironment, opt_lpCurrentDirectory, lpStartupInfo,
opt_out_lpProcessInformation, ok); opt_out_lpProcessInformation, ok);
return ok; return ok;
} }

View file

@ -18,10 +18,11 @@
*/ */
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h" #include "libc/calls/strace.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/nt/struct/securityattributes.h" #include "libc/nt/struct/securityattributes.h"
#include "libc/nt/thread.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. * Opens file on the New Technology.
@ -38,9 +39,8 @@ textwindows int64_t CreateThread(
hHandle = __imp_CreateThread(lpThreadAttributes, dwStackSize, lpStartAddress, hHandle = __imp_CreateThread(lpThreadAttributes, dwStackSize, lpStartAddress,
lpParameter, dwCreationFlags, opt_lpThreadId); lpParameter, dwCreationFlags, opt_lpThreadId);
if (hHandle == -1) __winerr(); if (hHandle == -1) __winerr();
STRACE("CreateThread(sec=%p, stack=%'zu, start=%p, param=%p, flags=%s, " STRACE("CreateThread(%s, %'zu, %p, %p, %s, %p) → %ld% m",
"id=%p) → %ld% m", DescribeNtSecurityAttributes(lpThreadAttributes), dwStackSize,
lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, lpStartAddress, lpParameter, dwCreationFlags, opt_lpThreadId, hHandle);
dwCreationFlags, opt_lpThreadId, hHandle);
return hHandle; return hHandle;
} }

View file

@ -22,7 +22,7 @@
#include "libc/nt/memory.h" #include "libc/nt/memory.h"
#include "libc/nt/thunk/msabi.h" #include "libc/nt/thunk/msabi.h"
extern typeof(DeleteFile) *const __imp_DeleteFileW __msabi; __msabi extern typeof(DeleteFile) *const __imp_DeleteFileW;
/** /**
* Deletes existing file. * Deletes existing file.

View file

@ -2,6 +2,7 @@
#define COSMOPOLITAN_LIBC_INTRIN_DESCRIBEFLAGS_INTERNAL_H_ #define COSMOPOLITAN_LIBC_INTRIN_DESCRIBEFLAGS_INTERNAL_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0) #if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_ COSMOPOLITAN_C_START_
#include "libc/nt/struct/securityattributes.h"
struct thatispacked DescribeFlags { struct thatispacked DescribeFlags {
unsigned flag; unsigned flag;
@ -16,14 +17,19 @@ const char *DescribeProtFlags(int);
const char *DescribeRemapFlags(int); const char *DescribeRemapFlags(int);
const char *DescribeNtPageFlags(uint32_t); const char *DescribeNtPageFlags(uint32_t);
const char *DescribeNtStartFlags(uint32_t);
const char *DescribeNtFileMapFlags(uint32_t); const char *DescribeNtFileMapFlags(uint32_t);
const char *DescribeNtFiletypeFlags(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 *DescribeNtFileShareFlags(uint32_t);
const char *DescribeNtFileAccessFlags(uint32_t); const char *DescribeNtFileAccessFlags(uint32_t);
const char *DescribeNtProcessAccessFlags(uint32_t); const char *DescribeNtProcessAccessFlags(uint32_t);
const char *DescribeNtCreationDisposition(uint32_t);
const char *DescribeNtConsoleModeInputFlags(uint32_t); const char *DescribeNtConsoleModeInputFlags(uint32_t);
const char *DescribeNtConsoleModeOutputFlags(uint32_t); const char *DescribeNtConsoleModeOutputFlags(uint32_t);
const char *DescribeNtFileFlagsAndAttributes(uint32_t);
const char *DescribeNtSecurityAttributes(struct NtSecurityAttributes *);
COSMOPOLITAN_C_END_ COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View 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";
}
}

View file

@ -64,7 +64,7 @@ static const struct DescribeFlags kFileAccessflags[] = {
}; };
const char *DescribeNtFileAccessFlags(uint32_t x) { const char *DescribeNtFileAccessFlags(uint32_t x) {
static char ntfileaccessflags[256]; static char ntfileaccessflags[512];
return DescribeFlags(ntfileaccessflags, sizeof(ntfileaccessflags), return DescribeFlags(ntfileaccessflags, sizeof(ntfileaccessflags),
kFileAccessflags, ARRAYLEN(kFileAccessflags), "kNt", x); kFileAccessflags, ARRAYLEN(kFileAccessflags), "kNt", x);
} }

View file

@ -17,8 +17,10 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/intrin/describeflags.internal.h" #include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
#include "libc/nt/enum/fileflagandattributes.h" #include "libc/nt/enum/fileflagandattributes.h"
#include "libc/runtime/runtime.h"
static const struct DescribeFlags kFileFlags[] = { static const struct DescribeFlags kFileFlags[] = {
{kNtFileAttributeReadonly, "AttributeReadonly"}, // {kNtFileAttributeReadonly, "AttributeReadonly"}, //

View 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);
}

View 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);
}

View 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";
}

View 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);
}

View file

@ -22,7 +22,7 @@
#include "libc/nt/struct/overlapped.h" #include "libc/nt/struct/overlapped.h"
#include "libc/nt/thunk/msabi.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. * Does device file stuff on the New Technology.

View file

@ -17,16 +17,10 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/intrin/dos2errno.internal.h"
#include "libc/nt/errors.h" #include "libc/nt/errors.h"
#include "libc/sock/sock.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. * Translates Windows error using superset of consts.sh.
* *

View 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_ */

View 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;
}

View file

@ -24,7 +24,7 @@
#include "libc/nt/struct/win32finddata.h" #include "libc/nt/struct/win32finddata.h"
#include "libc/nt/thunk/msabi.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. * Finds first file in directory.

View file

@ -19,12 +19,14 @@
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h" #include "libc/calls/strace.internal.h"
#include "libc/intrin/describeflags.internal.h" #include "libc/intrin/describeflags.internal.h"
#include "libc/nt/errors.h"
#include "libc/nt/files.h" #include "libc/nt/files.h"
#include "libc/nt/memory.h" #include "libc/nt/memory.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/win32finddata.h" #include "libc/nt/struct/win32finddata.h"
#include "libc/nt/thunk/msabi.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. * Finds more files in directory.
@ -45,8 +47,8 @@ textwindows bool32 FindNextFile(int64_t hFindFile,
DescribeNtFileFlagsAndAttributes(out_lpFindFileData->dwFileAttributes), DescribeNtFileFlagsAndAttributes(out_lpFindFileData->dwFileAttributes),
DescribeNtFiletypeFlags(out_lpFindFileData->dwFileType), ok); DescribeNtFiletypeFlags(out_lpFindFileData->dwFileType), ok);
} else { } else {
__winerr(); if (GetLastError() != kNtErrorNoMoreFiles) __winerr();
STRACE("FindNextFile(%ld, [n/a]) → %hhhd% m", hFindFile, ok); STRACE("FindNextFile(%ld) → %hhhd% m", hFindFile, ok);
} }
return ok; return ok;
} }

View file

@ -20,7 +20,7 @@
#include "libc/calls/strace.internal.h" #include "libc/calls/strace.internal.h"
#include "libc/nt/files.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. * Flushes buffers of specified file to disk.

View file

@ -20,7 +20,7 @@
#include "libc/calls/strace.internal.h" #include "libc/calls/strace.internal.h"
#include "libc/nt/memory.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(). * Syncs memory created by MapViewOfFileEx().

View file

@ -21,8 +21,8 @@
#include "libc/nt/console.h" #include "libc/nt/console.h"
#include "libc/nt/thunk/msabi.h" #include "libc/nt/thunk/msabi.h"
extern typeof(GenerateConsoleCtrlEvent) *const __msabi extern typeof(GenerateConsoleCtrlEvent) *const
__imp_GenerateConsoleCtrlEvent __msabi; __imp_GenerateConsoleCtrlEvent;
/** /**
* Sends signal to process group that shares console w/ calling process. * Sends signal to process group that shares console w/ calling process.

View file

@ -23,7 +23,7 @@
#include "libc/nt/files.h" #include "libc/nt/files.h"
#include "libc/nt/thunk/msabi.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. * Gets file info on the New Technology.

View file

@ -65,6 +65,7 @@ o/$(MODE)/libc/intrin/kprintf.greg.o: \
$(NO_MAGIC) $(NO_MAGIC)
o/$(MODE)/libc/intrin/createfile.greg.o \ 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/deletefile.greg.o \
o/$(MODE)/libc/intrin/createpipe.greg.o \ o/$(MODE)/libc/intrin/createpipe.greg.o \
o/$(MODE)/libc/intrin/closehandle.greg.o \ o/$(MODE)/libc/intrin/closehandle.greg.o \

View file

@ -29,6 +29,71 @@
.section .rodata .section .rodata
.underrun .underrun
kDos2Errno: 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 kNtErrorModNotFound,ENOSYS
.e kNtErrorBadCommand,EACCES .e kNtErrorBadCommand,EACCES
.e kNtErrorBadLength,EACCES .e kNtErrorBadLength,EACCES
@ -94,10 +159,8 @@ kDos2Errno:
.e WSAEACCES,EACCES .e WSAEACCES,EACCES
.e WSAEDISCON,EPIPE .e WSAEDISCON,EPIPE
.e WSAEFAULT,EFAULT .e WSAEFAULT,EFAULT
.e WSAEINPROGRESS,EBUSY
.e WSAEINVAL,EINVAL .e WSAEINVAL,EINVAL
.e WSAEPROCLIM,ENOMEM .e WSAEPROCLIM,ENOMEM
.e WSAESHUTDOWN,EPIPE
.e WSANOTINITIALISED,ENETDOWN .e WSANOTINITIALISED,ENETDOWN
.e WSASYSNOTREADY,ENETDOWN .e WSASYSNOTREADY,ENETDOWN
.e WSAVERNOTSUPPORTED,ENOSYS .e WSAVERNOTSUPPORTED,ENOSYS

View file

@ -1,7 +1,7 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ /*-*- 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 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 Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the 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 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/internal.h"
#include "libc/nt/struct/securityattributes.h" #include "libc/nt/struct/securityattributes.h"
hidden const struct NtSecurityAttributes kNtIsInheritable = { hidden const struct NtSecurityAttributes kNtIsInheritable = {

View file

@ -37,6 +37,7 @@
#include "libc/nt/process.h" #include "libc/nt/process.h"
#include "libc/nt/runtime.h" #include "libc/nt/runtime.h"
#include "libc/nt/thunk/msabi.h" #include "libc/nt/thunk/msabi.h"
#include "libc/nt/winsock.h"
#include "libc/runtime/memtrack.internal.h" #include "libc/runtime/memtrack.internal.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/str/str.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; i = 0;
m = (1 << base) - 1; m = (1 << base) - 1;
if (hash && x) sign = hash; if (hash && x) sign = hash;
do do z[i++ & 127] = abet[x & m];
z[i++ & 127] = abet[x & m];
while ((x >>= base) || (pdot && i < prec)); while ((x >>= base) || (pdot && i < prec));
goto EmitNumber; goto EmitNumber;
@ -487,17 +487,31 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, va_list va,
} }
goto EmitChar; goto EmitChar;
case 'm': case 'm': {
if (!(x = errno) && sign == ' ' /* && */ int unixerr;
/* (!IsWindows() || !__imp_GetLastError()) */) { 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; break;
} else if (weaken(strerror_r) && } else if (weaken(strerror_wr) &&
!weaken(strerror_r)(x, z, sizeof(z))) { !weaken(strerror_wr)(unixerr, winerr, z, sizeof(z))) {
s = z; s = z;
type = 0;
goto FormatString; goto FormatString;
} else { } else {
type = 0;
x = unixerr;
goto FormatDecimal; goto FormatDecimal;
} }
}
case 'G': case 'G':
x = va_arg(va, int); 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) * - ` ` space leftpad if positive (aligns w/ negatives)
* - `#` represent value with literal syntax, e.g. 0x, 0b, quotes * - `#` 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 * @asyncsignalsafe
* @vforksafe * @vforksafe
*/ */

View file

@ -23,7 +23,7 @@
#include "libc/nt/enum/filemapflags.h" #include "libc/nt/enum/filemapflags.h"
#include "libc/nt/memory.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. * 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, hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh, dwFileOffsetLow,
dwNumberOfBytesToMap, opt_lpDesiredBaseAddress); dwNumberOfBytesToMap, opt_lpDesiredBaseAddress);
if (!pStartingAddress) __winerr(); if (!pStartingAddress) __winerr();
STRACE("MapViewOfFileEx(%ld, %s, off:%'ld, size:%'zu, addr:%p) → %p% m", STRACE("MapViewOfFileEx(%ld, %s, %'ld, %'zu, %p) → %p% m", hFileMappingObject,
hFileMappingObject, DescribeNtFileMapFlags(dwDesiredAccess), DescribeNtFileMapFlags(dwDesiredAccess),
(uint64_t)dwFileOffsetHigh << 32 | dwFileOffsetLow, (uint64_t)dwFileOffsetHigh << 32 | dwFileOffsetLow,
dwNumberOfBytesToMap, opt_lpDesiredBaseAddress, pStartingAddress); dwNumberOfBytesToMap, opt_lpDesiredBaseAddress, pStartingAddress);
return pStartingAddress; return pStartingAddress;

View file

@ -24,7 +24,7 @@
#include "libc/nt/enum/filemapflags.h" #include "libc/nt/enum/filemapflags.h"
#include "libc/nt/memory.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. * 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, hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh, dwFileOffsetLow,
dwNumberOfBytesToMap, opt_lpDesiredBaseAddress, nndDesiredNumaNode); dwNumberOfBytesToMap, opt_lpDesiredBaseAddress, nndDesiredNumaNode);
if (!pStartingAddress) __winerr(); 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), hFileMappingObject, DescribeNtFileMapFlags(dwDesiredAccess),
(uint64_t)dwFileOffsetHigh << 32 | dwFileOffsetLow, (uint64_t)dwFileOffsetHigh << 32 | dwFileOffsetLow,
dwNumberOfBytesToMap, opt_lpDesiredBaseAddress, pStartingAddress); dwNumberOfBytesToMap, opt_lpDesiredBaseAddress, pStartingAddress);

View file

@ -24,7 +24,7 @@
#include "libc/nt/struct/securityattributes.h" #include "libc/nt/struct/securityattributes.h"
#include "libc/nt/thunk/msabi.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. * Creates file mapping object on the New Technology.

View file

@ -22,7 +22,7 @@
#include "libc/nt/memory.h" #include "libc/nt/memory.h"
#include "libc/nt/thunk/msabi.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. * Deletes existing empty directory.

View file

@ -1,7 +1,7 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ /*-*- 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 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 Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the 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 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/assert.h"
#include "libc/bits/weaken.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/intrin/cmpxchg.h" #include "libc/calls/strace.internal.h"
#include "libc/mem/mem.h" #include "libc/intrin/describeflags.internal.h"
#include "libc/str/str.h" #include "libc/nt/files.h"
#include "libc/sysv/errfuns.h" #include "libc/nt/thunk/msabi.h"
static void __ensurefds_destroy(void) { __msabi extern typeof(ReOpenFile) *const __imp_ReOpenFile;
weaken(free)(g_fds.p);
}
int __ensurefds(int fd) { /**
size_t n1, n2; * Reopens file on the New Technology.
struct Fd *p1, *p2; *
for (;;) { * @return handle, or -1 on failure
p1 = g_fds.p; * @note this wrapper takes care of ABI, STRACE(), and __winerr()
n1 = g_fds.n; */
if (fd < n1) return fd; int64_t ReOpenFile(int64_t hOriginalFile, uint32_t dwDesiredAccess,
if (weaken(malloc)) { uint32_t dwShareMode, uint32_t dwFlagsAndAttributes) {
n2 = MAX(fd + 1, n1 + (n1 << 1)); int64_t hHandle;
if ((p2 = weaken(malloc)(n2 * sizeof(*p1)))) { hHandle = __imp_ReOpenFile(hOriginalFile, dwDesiredAccess, dwShareMode,
memcpy(p2, p1, n1 * sizeof(*p1)); dwFlagsAndAttributes);
bzero(p2 + n1, (n2 - n1) * sizeof(*p1)); if (hHandle == -1) __winerr();
if (_cmpxchg(&g_fds.p, p1, p2)) { STRACE("ReOpenFile(%ld, %s, %s, %s) → %ld% m", hOriginalFile,
g_fds.n = n2; DescribeNtFileAccessFlags(dwDesiredAccess),
if (weaken(free)) { DescribeNtFileShareFlags(dwShareMode),
if (p1 == g_fds.__init_p) { DescribeNtFileFlagsAndAttributes(dwFlagsAndAttributes), hHandle);
atexit(__ensurefds_destroy); return hHandle;
} else {
weaken(free)(p1);
}
}
return fd;
} else if (weaken(free)) {
weaken(free)(p2);
}
} else {
return enomem();
}
} else {
return emfile();
}
}
} }

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/strace.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/nt/console.h" #include "libc/nt/console.h"
#include "libc/nt/process.h" #include "libc/nt/process.h"
@ -35,7 +36,9 @@ const char kConsoleHandles[3] = {
*/ */
noasan void __restorewintty(void) { noasan void __restorewintty(void) {
int i; int i;
if (IsWindows() && GetCurrentProcessId() == __winmainpid) { if (!IsWindows()) return;
STRACE("__restorewintty()");
if (GetCurrentProcessId() == __winmainpid) {
for (i = 0; i < 3; ++i) { for (i = 0; i < 3; ++i) {
SetConsoleMode(GetStdHandle(kConsoleHandles[i]), __ntconsolemode[i]); SetConsoleMode(GetStdHandle(kConsoleHandles[i]), __ntconsolemode[i]);
} }

View file

@ -22,7 +22,7 @@
#include "libc/nt/memory.h" #include "libc/nt/memory.h"
#include "libc/nt/thunk/msabi.h" #include "libc/nt/thunk/msabi.h"
extern typeof(SetCurrentDirectory) *const __imp_SetCurrentDirectoryW __msabi; __msabi extern typeof(SetCurrentDirectory) *const __imp_SetCurrentDirectoryW;
/** /**
* Sets current directory. * Sets current directory.

View file

@ -1,22 +1,24 @@
#ifndef COSMOPOLITAN_LIBC_INTRIN_SPINLOCK_H_ #ifndef COSMOPOLITAN_LIBC_INTRIN_SPINLOCK_H_
#define COSMOPOLITAN_LIBC_INTRIN_SPINLOCK_H_ #define COSMOPOLITAN_LIBC_INTRIN_SPINLOCK_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0) #if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_ #if (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 401 && \
!defined(__STRICT_ANSI__)
/* "Place each synchronization variable alone, #define _spinlock(lock) \
separated by 128 bytes or in a separate cache line." do { \
Intel Optimization Manual §8.3.1 */ for (;;) { \
struct cthread_spinlock_t { typeof(*(lock)) x; \
bool x; __atomic_load(lock, &x, __ATOMIC_RELAXED); \
int owner; if (!x && !__sync_lock_test_and_set(lock, __ATOMIC_CONSUME)) { \
char __ignore[128 - 1 - 4]; break; \
} forcealign(128); } 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; #endif /* GNU 4.1+ */
void cthread_spunlock(cthread_spinlock_t *) dontthrow;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_INTRIN_SPINLOCK_H_ */ #endif /* COSMOPOLITAN_LIBC_INTRIN_SPINLOCK_H_ */

View file

@ -22,7 +22,7 @@
#include "libc/nt/runtime.h" #include "libc/nt/runtime.h"
#include "libc/nt/thunk/msabi.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. * 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