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 rc, child, wstatus;
/* puts(_gc(xiso8601ts(NULL))); */
PrintMemoryIntervals(2, &_mmi);
CHECK_NE(-1, (child = fork()));
if (!child) {
/* child process */

View file

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

View file

@ -65,8 +65,11 @@ $(LIBC_CALLS_A).pkg: \
$(LIBC_CALLS_A_OBJS) \
$(foreach x,$(LIBC_CALLS_A_DIRECTDEPS),$($(x)_A).pkg)
o/$(MODE)/libc/calls/directmap.o \
o/$(MODE)/libc/calls/directmap-nt.o \
o/$(MODE)/libc/calls/raise.o: \
OVERRIDE_COPTS += \
-ffreestanding \
$(NO_MAGIC)
o/$(MODE)/libc/calls/termios2linux.o \

View file

@ -16,30 +16,42 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/bits/weaken.h"
#include "libc/calls/internal.h"
#include "libc/nt/enum/filetype.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/sock/ntstdin.internal.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h"
textwindows int sys_close_nt(struct Fd *fd) {
int e;
bool32 ok;
bool ok = true;
// if this file descriptor is wrapped in a named pipe worker thread
// then we need to close our copy of the worker thread handle. it's
// also required that whatever install a worker use malloc, so free
if (fd->worker) {
if (!weaken(UnrefNtStdinWorker)(fd->worker)) ok = false;
fd->worker = 0;
}
if (fd->kind == kFdFile && ((fd->flags & O_ACCMODE) != O_RDONLY &&
GetFileType(fd->handle) == kNtFileTypeDisk)) {
/*
* Like Linux, closing a file on Windows doesn't guarantee it's
* immediately synced to disk. But unlike Linux, this could cause
* subsequent operations, e.g. unlink() to break w/ access error.
*/
// Like Linux, closing a file on Windows doesn't guarantee it's
// immediately synced to disk. But unlike Linux, this could cause
// subsequent operations, e.g. unlink() to break w/ access error.
e = errno;
FlushFileBuffers(fd->handle);
errno = e;
}
ok = CloseHandle(fd->handle);
// now we can close the handle
if (!CloseHandle(fd->handle)) ok = false;
if (fd->kind == kFdConsole && fd->extra && fd->extra != -1) {
ok &= CloseHandle(fd->extra);
if (!CloseHandle(fd->extra)) ok = false;
}
return ok ? 0 : -1;
}

View file

@ -73,7 +73,7 @@ int close(int fd) {
}
}
}
__releasefd(fd);
if (!__vforked) __releasefd(fd);
}
STRACE("%s(%d) → %d% m", "close", fd, 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
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/alg/reverse.internal.h"
#include "libc/calls/calls.h"
#include "libc/intrin/lockxadd.h"
#include "libc/nt/process.h"
static const char kPipeNamePrefix[] = "\\\\?\\pipe\\cosmo\\";
static textwindows size_t UintToChar16Array(char16_t *a, uint64_t i) {
size_t j = 0;
static textwindows char16_t *UintToChar16Array(char16_t p[21], uint64_t x) {
char t;
size_t a, b, i = 0;
do {
a[j++] = i % 10 + '0';
i /= 10;
} while (i > 0);
a[j] = 0;
reverse(a, j);
return j;
p[i++] = x % 10 + '0';
x = x / 10;
} while (x > 0);
if (i) {
for (a = 0, b = i - 1; a < b; ++a, --b) {
t = p[a];
p[a] = p[b];
p[b] = t;
}
}
return p + i;
}
textwindows char16_t *CreatePipeName(char16_t *a) {
static long x;
unsigned i;
for (i = 0; kPipeNamePrefix[i]; ++i) a[i] = kPipeNamePrefix[i];
i += UintToChar16Array(a + i, GetCurrentProcessId());
a[i++] = u'-';
i += UintToChar16Array(a + i, GetCurrentProcessId());
a[i++] = u'-';
i += UintToChar16Array(a + i, x++);
a[i] = u'\0';
char16_t *p = a;
const char *q = "\\\\?\\pipe\\cosmo\\";
while (*q) *p++ = *q++;
p = UintToChar16Array(p, GetCurrentProcessId());
*p++ = '-';
p = UintToChar16Array(p, _lockxadd(&x, 1));
*p = 0;
return a;
}

View file

@ -18,18 +18,21 @@
*/
#include "libc/assert.h"
#include "libc/calls/internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/nt/enum/filemapflags.h"
#include "libc/nt/enum/pageflags.h"
#include "libc/nt/memory.h"
#include "libc/nt/process.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/processmemorycounters.h"
#include "libc/runtime/directmap.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
textwindows noasan struct DirectMap sys_mmap_nt(void *addr, size_t size,
int prot, int flags, int fd,
int64_t off) {
textwindows struct DirectMap sys_mmap_nt(void *addr, size_t size, int prot,
int flags, int fd, int64_t off) {
size_t i;
bool iscow;
int64_t handle;
@ -38,6 +41,18 @@ textwindows noasan struct DirectMap sys_mmap_nt(void *addr, size_t size,
struct ProtectNt fl;
const struct NtSecurityAttributes *sec;
#ifndef NDEBUG
struct NtProcessMemoryCountersEx memcount = {
.cb = sizeof(struct NtProcessMemoryCountersEx),
};
if (GetProcessMemoryInfo(GetCurrentProcess(), &memcount, sizeof(memcount))) {
if (memcount.PeakWorkingSetSize > 5ull * 1024 * 1024 * 1024) {
kprintf("error: exceeded 5gb memory limit%n");
_Exit(201);
}
}
#endif
if (fd != -1) {
handle = g_fds.p[fd].handle;
} else {

View file

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

View file

@ -24,38 +24,62 @@
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/sock/internal.h"
#include "libc/sock/ntstdin.internal.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h"
/**
* Implements dup(), dup2(), and dup3() for Windows NT.
* Implements dup(), dup2(), dup3(), and F_DUPFD for Windows.
*/
textwindows int sys_dup_nt(int oldfd, int newfd, int flags) {
int64_t proc;
textwindows int sys_dup_nt(int oldfd, int newfd, int flags, int start) {
int64_t proc, handle;
// validate the api usage
if (oldfd < 0) return einval();
if (flags & ~O_CLOEXEC) return einval();
if (oldfd >= g_fds.n ||
(g_fds.p[oldfd].kind != kFdFile && g_fds.p[oldfd].kind != kFdSocket &&
g_fds.p[oldfd].kind != kFdConsole)) {
return ebadf();
}
// allocate a new file descriptor
if (newfd == -1) {
if ((newfd = __reservefd()) == -1) return -1;
if ((newfd = __reservefd(start)) == -1) {
return -1;
}
} else {
if (__ensurefds(newfd) == -1) return -1;
if (g_fds.p[newfd].kind) close(newfd);
g_fds.p[newfd].kind = kFdReserved;
}
// if this file descriptor is wrapped in a named pipe worker thread
// then we should clone the original authentic handle rather than the
// stdin worker's named pipe. we won't clone the worker, since that
// can always be recreated again on demand.
if (g_fds.p[oldfd].worker) {
handle = g_fds.p[oldfd].worker->reader;
} else {
handle = g_fds.p[oldfd].handle;
}
proc = GetCurrentProcess();
if (DuplicateHandle(proc, g_fds.p[oldfd].handle, proc, &g_fds.p[newfd].handle,
0, true, kNtDuplicateSameAccess)) {
if (DuplicateHandle(proc, handle, proc, &g_fds.p[newfd].handle, 0, true,
kNtDuplicateSameAccess)) {
g_fds.p[newfd].kind = g_fds.p[oldfd].kind;
g_fds.p[newfd].flags = flags;
g_fds.p[newfd].mode = g_fds.p[oldfd].mode;
g_fds.p[newfd].flags = g_fds.p[oldfd].flags & ~O_CLOEXEC;
if (flags & O_CLOEXEC) g_fds.p[newfd].flags |= O_CLOEXEC;
if (g_fds.p[oldfd].kind == kFdSocket && weaken(_dupsockfd)) {
g_fds.p[newfd].extra =
(intptr_t)weaken(_dupsockfd)((struct SockFd *)g_fds.p[oldfd].extra);
} else {
g_fds.p[newfd].extra = g_fds.p[oldfd].extra;
}
if (g_fds.p[oldfd].worker) {
g_fds.p[newfd].worker = weaken(RefNtStdinWorker)(g_fds.p[oldfd].worker);
}
return newfd;
} else {
__releasefd(newfd);

View file

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

View file

@ -38,7 +38,7 @@ int dup2(int oldfd, int newfd) {
} else if (!IsWindows()) {
rc = sys_dup3(oldfd, newfd, 0);
} else {
rc = sys_dup_nt(oldfd, newfd, 0);
rc = sys_dup_nt(oldfd, newfd, 0, -1);
}
STRACE("dup2(%d, %d) → %d% m", oldfd, newfd, rc);
return rc;

View file

@ -40,7 +40,7 @@ int dup3(int oldfd, int newfd, int flags) {
if (!IsWindows()) {
rc = sys_dup3(oldfd, newfd, flags);
} else {
rc = sys_dup_nt(oldfd, newfd, flags);
rc = sys_dup_nt(oldfd, newfd, flags, -1);
}
STRACE("dup3(%d, %d, %d) → %d% m", oldfd, newfd, flags, rc);
return rc;

View file

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

View file

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

View file

@ -20,7 +20,9 @@
#include "libc/calls/internal.h"
#include "libc/calls/struct/flock.h"
#include "libc/intrin/cmpxchg.h"
#include "libc/intrin/kprintf.h"
#include "libc/macros.internal.h"
#include "libc/nt/createfile.h"
#include "libc/nt/enum/accessmask.h"
#include "libc/nt/enum/fileflagandattributes.h"
#include "libc/nt/enum/filelockflags.h"
@ -38,38 +40,8 @@
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h"
static textwindows int sys_fcntl_nt_reservefd(int start) {
int fd;
for (;;) {
fd = start;
if (fd >= g_fds.n) {
if (__ensurefds(fd) == -1) return -1;
}
_cmpxchg(&g_fds.f, fd, fd + 1);
if (_cmpxchg(&g_fds.p[fd].kind, kFdEmpty, kFdReserved)) {
return fd;
}
}
}
static textwindows int sys_fcntl_nt_dupfd(int oldfd, int cmd, int start) {
int newfd;
int64_t proc;
if ((newfd = sys_fcntl_nt_reservefd(start)) != -1) {
proc = GetCurrentProcess();
if (DuplicateHandle(proc, g_fds.p[oldfd].handle, proc,
&g_fds.p[newfd].handle, 0, true,
kNtDuplicateSameAccess)) {
g_fds.p[newfd].kind = g_fds.p[oldfd].kind;
g_fds.p[newfd].flags = cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0;
return newfd;
} else {
__releasefd(newfd);
return __winerr();
}
} else {
return -1;
}
static textwindows int sys_fcntl_nt_dupfd(int fd, int cmd, int start) {
return sys_dup_nt(fd, -1, (cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0), start);
}
static textwindows int sys_fcntl_nt_lock(struct Fd *f, int cmd, uintptr_t arg) {
@ -98,7 +70,7 @@ static textwindows int sys_fcntl_nt_lock(struct Fd *f, int cmd, uintptr_t arg) {
}
if (!len) len = size - off;
if (off < 0 || len < 0) return einval();
_offset2overlap(off, &ov);
_offset2overlap(f->handle, off, &ov);
if (l->l_type == F_RDLCK || l->l_type == F_WRLCK) {
flags = 0;
if (cmd == F_SETLK) flags |= kNtLockfileFailImmediately;
@ -136,11 +108,9 @@ textwindows int sys_fcntl_nt(int fd, int cmd, uintptr_t arg) {
return g_fds.p[fd].flags & (O_ACCMODE | O_APPEND | O_ASYNC | O_DIRECT |
O_NOATIME | O_NONBLOCK);
} else if (cmd == F_SETFL) {
/*
* - O_APPEND doesn't appear to be tunable at cursory glance
* - O_NONBLOCK might require we start doing all i/o in threads
* - O_DSYNC / O_RSYNC / O_SYNC maybe if we fsync() everything
*/
// O_APPEND doesn't appear to be tunable at cursory glance
// O_NONBLOCK might require we start doing all i/o in threads
// O_DSYNC / O_RSYNC / O_SYNC maybe if we fsync() everything
return einval();
} else if (cmd == F_GETFD) {
if (g_fds.p[fd].flags & O_CLOEXEC) {

View file

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

View file

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

View file

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

View file

@ -16,35 +16,16 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/intrin/lockcmpxchg.h"
#include "libc/intrin/spinlock.h"
/**
* Acquires spinlock.
* Returns effective user ID of calling process.
*/
void cthread_spinlock(cthread_spinlock_t *lock) {
#if 0
// TODO(jart): possibly reenable for !NDEBUG when we have TLS
int me = gettid();
if (lock->x && lock->owner == me) {
assert(!"cosmo spinlock not intended to be reentrant");
return;
}
#endif
do
while (lock->x) asm("pause");
while (!_lockcmpxchg(&lock->x, false, true));
#if 0
lock->owner = me;
#endif
}
/**
* Releases spinlock.
*/
void cthread_spunlock(cthread_spinlock_t *lock) {
lock->x = false;
uint32_t geteuid(void) {
int rc;
rc = sys_geteuid();
STRACE("%s() → %d% m", "geteuid", rc);
return rc;
}

View file

@ -1,7 +1,7 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Copyright 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
@ -16,13 +16,13 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.internal.h"
#include "libc/calls/internal.h"
#include "libc/sock/ntstdin.internal.h"
// Sneak ahead ctor list b/c runtime weakly links malloc.
.init.start 800,_init_dlmalloc
push %rdi
push %rsi
call dlmalloc_init
pop %rsi
pop %rdi
.init.end 800,_init_dlmalloc,globl,hidden
int64_t __getfdhandleactual(int fd) {
if (g_fds.p[fd].worker) {
return g_fds.p[fd].worker->reader;
} else {
return g_fds.p[fd].handle;
}
}

View file

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

View file

@ -16,11 +16,11 @@
#include "libc/calls/struct/winsize.h"
#include "libc/calls/ucontext.h"
#include "libc/dce.h"
#include "libc/intrin/spinlock.h"
#include "libc/limits.h"
#include "libc/macros.internal.h"
#include "libc/nt/struct/context.h"
#include "libc/nt/struct/ntexceptionpointers.h"
#include "libc/nt/struct/overlapped.h"
#include "libc/nt/struct/securityattributes.h"
#include "libc/nt/struct/startupinfo.h"
#include "libc/nt/struct/systeminfo.h"
@ -58,8 +58,10 @@ enum FdKind {
struct Fd {
enum FdKind kind;
unsigned flags;
unsigned mode;
int64_t handle;
int64_t extra;
struct NtStdinWorker *worker;
bool zombie;
};
@ -73,16 +75,19 @@ struct Fds {
extern const struct Fd kEmptyFd;
hidden extern int __vforked;
hidden extern char __fds_lock;
hidden extern char __sig_lock;
hidden extern bool __time_critical;
hidden extern cthread_spinlock_t __sig_lock;
hidden extern unsigned __sighandrvas[NSIG];
hidden extern unsigned __sighandflags[NSIG];
hidden extern struct Fds g_fds;
hidden extern const struct NtSecurityAttributes kNtIsInheritable;
int __reservefd(void) hidden;
int __reservefd(int) hidden;
void __releasefd(int) hidden;
int __ensurefds(int) hidden;
int64_t __getfdhandleactual(int) hidden;
void __printfds(void);
forceinline bool __isfdopen(int fd) {
return 0 <= fd && fd < g_fds.n && g_fds.p[fd].kind != kFdEmpty;
@ -178,6 +183,7 @@ i32 sys_posix_openpt(i32) hidden;
i32 sys_renameat(i32, const char *, i32, const char *) hidden;
i32 sys_sched_setaffinity(i32, u64, const void *) hidden;
i32 sys_sched_yield(void) hidden;
i32 sys_setgid(i32) hidden;
i32 sys_setitimer(i32, const struct itimerval *, struct itimerval *) hidden;
i32 sys_setpgid(i32, i32) hidden;
i32 sys_setpriority(i32, u32, i32) hidden;
@ -185,6 +191,7 @@ i32 sys_setresgid(uint32_t, uint32_t, uint32_t) hidden;
i32 sys_setresuid(uint32_t, uint32_t, uint32_t) hidden;
i32 sys_setrlimit(i32, const struct rlimit *) hidden;
i32 sys_setsid(void) hidden;
i32 sys_setuid(i32) hidden;
i32 sys_sigaction(i32, const void *, void *, i64, i64) hidden;
i32 sys_sigaltstack(const void *, void *) hidden;
i32 sys_sigprocmask(i32, const sigset *, sigset *, u64) hidden;
@ -216,6 +223,7 @@ i64 sys_sendfile(i32, i32, i64 *, u64) hidden;
i64 sys_splice(i32, i64 *, i32, i64 *, u64, u32) hidden;
i64 sys_vmsplice(i32, const struct iovec *, i64, u32) hidden;
i64 sys_write(i32, const void *, u64) hidden;
u32 sys_geteuid(void) hidden;
u32 sys_getgid(void) hidden;
u32 sys_getsid(int) hidden;
u32 sys_gettid(void) hidden;
@ -266,7 +274,7 @@ i64 sys_lseek_nt(int, i64, int) hidden;
int sys_chdir_nt(const char *) hidden;
int sys_close_epoll_nt(int) hidden;
int sys_close_nt(struct Fd *) hidden;
int sys_dup_nt(int, int, int) hidden;
int sys_dup_nt(int, int, int, int) hidden;
int sys_execve_nt(const char *, char *const[], char *const[]) hidden;
int sys_faccessat_nt(int, const char *, int, uint32_t) hidden;
int sys_fadvise_nt(int, u64, u64, int) hidden;
@ -331,12 +339,13 @@ int64_t __winerr(void) nocallback privileged;
int64_t ntreturn(uint32_t);
ssize_t sys_readv_nt(struct Fd *, const struct iovec *, int) hidden;
ssize_t sys_writev_nt(int, const struct iovec *, int) hidden;
struct NtOverlapped *_offset2overlap(int64_t, struct NtOverlapped *) hidden;
unsigned __wincrash_nt(struct NtExceptionPointers *);
void *GetProcAddressModule(const char *, const char *) hidden;
void WinMainForked(void) hidden;
void _ntcontext2linux(struct ucontext *, const struct NtContext *) hidden;
void _ntlinux2context(struct NtContext *, const ucontext_t *) hidden;
struct NtOverlapped *_offset2overlap(int64_t, int64_t,
struct NtOverlapped *) hidden;
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § syscalls » metal

View file

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

View file

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

View file

@ -18,9 +18,9 @@
*/
#include "libc/calls/internal.h"
#include "libc/nt/struct/overlapped.h"
#include "libc/str/str.h"
textwindows struct NtOverlapped *_offset2overlap(int64_t opt_offset,
textwindows struct NtOverlapped *_offset2overlap(int64_t handle,
int64_t opt_offset,
struct NtOverlapped *mem) {
if (opt_offset == -1) return NULL;
bzero(mem, sizeof(struct NtOverlapped));

View file

@ -36,89 +36,12 @@
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h"
#define _O_APPEND 0x00000400 /* kNtFileAppendData */
#define _O_CREAT 0x00000040 /* kNtOpenAlways */
#define _O_EXCL 0x00000080 /* kNtCreateNew */
#define _O_TRUNC 0x00000200 /* kNtCreateAlways */
#define _O_DIRECTORY 0x00010000 /* kNtFileFlagBackupSemantics */
#define _O_TMPFILE 0x00410000 /* AttributeTemporary|FlagDeleteOnClose */
#define _O_DIRECT 0x00004000 /* kNtFileFlagNoBuffering */
#define _O_NDELAY 0x00000800 /* kNtFileFlagWriteThrough */
#define _O_RANDOM 0x80000000 /* kNtFileFlagRandomAccess */
#define _O_SEQUENTIAL 0x40000000 /* kNtFileFlagSequentialScan */
#define _O_COMPRESSED 0x20000000 /* kNtFileAttributeCompressed */
#define _O_INDEXED 0x10000000 /* !kNtFileAttributeNotContentIndexed */
#define _O_NONBLOCK 0x00000800
#define _O_CLOEXEC 0x00080000
static textwindows int64_t sys_open_nt_impl(int dirfd, const char *path,
uint32_t flags, int32_t mode) {
int64_t handle;
uint32_t br, err;
char16_t path16[PATH_MAX];
uint32_t perm, share, disp, attr;
if (__mkntpathat(dirfd, path, flags, path16) == -1) return -1;
switch (flags & O_ACCMODE) {
case O_RDONLY:
perm = kNtFileGenericRead | kNtGenericExecute;
break;
case O_WRONLY:
perm = kNtFileGenericWrite | kNtGenericExecute;
break;
case O_RDWR:
perm = kNtFileGenericRead | kNtFileGenericWrite | kNtGenericExecute;
break;
default:
unreachable;
}
if (flags & _O_EXCL) {
share = kNtFileShareExclusive;
} else {
share = kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete;
}
if ((flags & _O_CREAT) && (flags & _O_EXCL)) {
disp = kNtCreateNew;
} else if ((flags & _O_CREAT) && (flags & _O_TRUNC)) {
disp = kNtCreateAlways;
} else if (flags & _O_CREAT) {
disp = kNtOpenAlways;
} else if (flags & _O_TRUNC) {
disp = kNtTruncateExisting;
} else {
disp = kNtOpenExisting;
}
if ((flags & _O_TMPFILE) == _O_TMPFILE) {
attr = kNtFileAttributeTemporary | kNtFileFlagDeleteOnClose;
} else {
attr = kNtFileAttributeNormal;
if (flags & _O_DIRECTORY) attr |= kNtFileFlagBackupSemantics;
if (~mode & 0200) {
attr |= kNtFileAttributeReadonly;
if (!IsTiny() && disp == kNtCreateAlways) {
// iron out esoteric unix/win32 inconsistency (golang #38225)
if ((handle = CreateFile(path16, perm, share, &kNtIsInheritable,
kNtTruncateExisting, kNtFileAttributeNormal,
0)) != -1 ||
(errno != ENOENT && errno != ENOTDIR)) {
return handle;
}
}
}
}
flags |= kNtFileFlagOverlapped;
if (~flags & _O_INDEXED) attr |= kNtFileAttributeNotContentIndexed;
if (flags & _O_COMPRESSED) attr |= kNtFileAttributeCompressed;
if (flags & _O_SEQUENTIAL) attr |= kNtFileFlagSequentialScan;
if (flags & _O_RANDOM) attr |= kNtFileFlagRandomAccess;
if (flags & _O_DIRECT) attr |= kNtFileFlagNoBuffering;
if (flags & _O_NDELAY) attr |= kNtFileFlagWriteThrough;
if (GetNtOpenFlags(flags, mode, &perm, &share, &disp, &attr) == -1) return -1;
return CreateFile(path16, perm, share, &kNtIsInheritable, disp, attr, 0);
}
@ -141,6 +64,7 @@ static textwindows ssize_t sys_open_nt_console(int dirfd,
}
g_fds.p[fd].kind = kFdConsole;
g_fds.p[fd].flags = flags;
g_fds.p[fd].mode = mode;
return fd;
}
@ -150,6 +74,7 @@ static textwindows ssize_t sys_open_nt_file(int dirfd, const char *file,
if ((g_fds.p[fd].handle = sys_open_nt_impl(dirfd, file, flags, mode)) != -1) {
g_fds.p[fd].kind = kFdFile;
g_fds.p[fd].flags = flags;
g_fds.p[fd].mode = mode;
return fd;
} else {
return -1;
@ -160,7 +85,7 @@ textwindows ssize_t sys_open_nt(int dirfd, const char *file, uint32_t flags,
int32_t mode) {
int fd;
ssize_t rc;
if ((fd = __reservefd()) == -1) return -1;
if ((fd = __reservefd(-1)) == -1) return -1;
if ((flags & O_ACCMODE) == O_RDWR && !strcmp(file, kNtMagicPaths.devtty)) {
rc = sys_open_nt_console(dirfd, &kNtMagicPaths, flags, mode, fd);
} else {

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

View file

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

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h"
@ -31,10 +32,18 @@
* @see pipe2()
*/
int pipe(int pipefd[hasatleast 2]) {
if (IsAsan() && !__asan_is_valid(pipefd, sizeof(int) * 2)) return efault();
if (!IsWindows()) {
return sys_pipe(pipefd);
int rc;
if (IsAsan() && !__asan_is_valid(pipefd, sizeof(int) * 2)) {
rc = efault();
} else if (!IsWindows()) {
rc = sys_pipe(pipefd);
} else {
return sys_pipe_nt(pipefd, 0);
rc = sys_pipe_nt(pipefd, 0);
}
if (!rc) {
STRACE("pipe([{%d, %d}]) → %d% m", pipefd[0], pipefd[1], rc);
} else {
STRACE("pipe(%p) → %d% m", pipefd, rc);
}
return rc;
}

View file

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

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

View file

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

View file

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

View file

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

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) {
size_t i;
if ((i = GetFirstIov(iov, iovlen)) != -1) {
while (!IsDataAvailable(fd)) asm("pause");
while (!IsDataAvailable(fd)) {
__builtin_ia32_pause();
}
((char *)iov[i].iov_base)[0] = inb(fd->handle);
return 1;
} else {

View file

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

View file

@ -16,24 +16,98 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/intrin/cmpxchg.h"
#include "libc/calls/strace.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/spinlock.h"
#include "libc/macros.internal.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
/**
* Grows file descriptor array memory if needed.
*/
int __ensurefds(int fd) {
size_t n1, n2;
struct Fd *p1, *p2;
_spinlock(&__fds_lock);
n1 = g_fds.n;
if (fd >= n1) {
STRACE("__ensurefds(%d) extending", fd);
if (weaken(malloc)) {
// TODO(jart): we need a semaphore for this
p1 = g_fds.p;
n2 = fd + (fd >> 1);
if ((p2 = weaken(malloc)(n2 * sizeof(*p1)))) {
memcpy(p2, p1, n1 * sizeof(*p1));
g_fds.p = p2;
g_fds.n = n2;
if (p1 != g_fds.__init_p) {
weaken(free)(p1);
}
} else {
fd = enomem();
}
} else {
fd = emfile();
}
}
_spunlock(&__fds_lock);
return fd;
}
/**
* Finds open file descriptor slot.
*/
int __reservefd(void) {
int __reservefd(int start) {
int fd;
for (;;) {
fd = g_fds.f;
if (fd >= g_fds.n) {
if (__ensurefds(fd) == -1) return -1;
}
_cmpxchg(&g_fds.f, fd, fd + 1);
if (_cmpxchg(&g_fds.p[fd].kind, kFdEmpty, kFdReserved)) {
_spinlock(&__fds_lock);
fd = start < 0 ? g_fds.f : start;
while (fd < g_fds.n && g_fds.p[fd].kind) ++fd;
if (fd < g_fds.n) {
g_fds.f = fd + 1;
bzero(g_fds.p + fd, sizeof(*g_fds.p));
g_fds.p[fd].kind = kFdReserved;
_spunlock(&__fds_lock);
return fd;
} else {
_spunlock(&__fds_lock);
if (__ensurefds(fd) == -1) {
return -1;
}
}
}
}
/**
* Closes non-stdio file descriptors to free dynamic memory.
*/
static void __freefds(void) {
int i;
STRACE("__freefds()");
for (i = 3; i < g_fds.n; ++i) {
if (g_fds.p[i].kind) {
close(i);
}
}
if (g_fds.p != g_fds.__init_p) {
memcpy(g_fds.__init_p, g_fds.p, sizeof(*g_fds.p) * 3);
weaken(free)(g_fds.p);
g_fds.p = g_fds.__init_p;
g_fds.n = ARRAYLEN(g_fds.__init_p);
}
}
static textstartup void __freefds_init(void) {
atexit(__freefds);
}
const void *const __freefds_ctor[] initarray = {
__freefds_init,
};

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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

View file

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

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;
for (i = 0; i < iovlen; ++i) {
for (j = 0; j < iov[i].iov_len; ++j) {
while (!(inb(fd->handle + UART_LSR) & UART_TTYTXR)) asm("pause");
while (!(inb(fd->handle + UART_LSR) & UART_TTYTXR)) {
__builtin_ia32_pause();
}
outb(fd->handle, ((char *)iov[i].iov_base)[j]);
++wrote;
}

View file

@ -27,6 +27,7 @@ int vsscanf(const char *, const char *, va_list);
int vcscanf(int (*)(void *), int (*)(int, void *), void *, const char *,
va_list);
int strerror_r(int, char *, size_t) dontthrow nocallback;
int strerror_wr(int, uint32_t, char *, size_t) dontthrow nocallback;
const char *strerror_short(int) nosideeffect;
const char *strerror_long(int) nosideeffect;
int __fmt(void *, void *, const char *, va_list) hidden;

View file

@ -16,23 +16,8 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#define ShouldUseMsabiAttribute() 1
#include "libc/bits/safemacros.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/fmt/fmt.h"
#include "libc/fmt/itoa.h"
#include "libc/intrin/kprintf.h"
#include "libc/log/libfatal.internal.h"
#include "libc/macros.internal.h"
#include "libc/nexgen32e/bsr.h"
#include "libc/nt/enum/formatmessageflags.h"
#include "libc/nt/enum/lang.h"
#include "libc/nt/memory.h"
#include "libc/nt/process.h"
#include "libc/nt/runtime.h"
#include "libc/str/str.h"
#include "libc/str/tpenc.h"
/**
* Converts errno value to string.
@ -41,32 +26,5 @@
* @return 0 on success, or error code
*/
privileged int strerror_r(int err, char *buf, size_t size) {
/* kprintf() weakly depends on this function */
int c, n, winerr;
char16_t winmsg[256];
const char *sym, *msg;
sym = firstnonnull(strerror_short(err), "EUNKNOWN");
msg = firstnonnull(strerror_long(err), "No error information");
if (IsTiny()) {
if (!sym) sym = "EUNKNOWN";
for (; (c = *sym++); --size)
if (size > 1) *buf++ = c;
if (size) *buf = 0;
} else if (!IsWindows()) {
ksnprintf(buf, size, "%s[%d][%s]", sym, err, msg);
} else {
winerr = __imp_GetLastError();
if ((n = __imp_FormatMessageW(
kNtFormatMessageFromSystem | kNtFormatMessageIgnoreInserts, 0,
winerr, MAKELANGID(kNtLangNeutral, kNtSublangDefault), winmsg,
ARRAYLEN(winmsg), 0))) {
while ((n && winmsg[n - 1] <= ' ') || winmsg[n - 1] == '.') --n;
ksnprintf(buf, size, "%s[%d][%s][%.*hs][%d]", sym, err, msg, n, winmsg,
winerr);
} else {
ksnprintf(buf, size, "%s[%d][%s][%d]", sym, err, msg, winerr);
}
__imp_SetLastError(winerr);
}
return 0;
return strerror_wr(err, GetLastError(), buf, size);
}

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,7 +51,7 @@
#include "libc/sysv/consts/nr.h"
#include "libc/sysv/consts/prot.h"
#include "libc/sysv/errfuns.h"
#include "third_party/dlmalloc/dlmalloc.internal.h"
#include "third_party/dlmalloc/dlmalloc.h"
STATIC_YOINK("_init_asan");
@ -177,8 +177,7 @@ static uint64_t __asan_roundup2pow(uint64_t x) {
static char *__asan_utf8cpy(char *p, unsigned c) {
uint64_t z;
z = tpenc(c);
do
*p++ = z;
do *p++ = z;
while ((z >>= 8));
return p;
}
@ -922,8 +921,7 @@ static void __asan_trace(struct AsanTrace *bt, const struct StackFrame *bp) {
if (!__asan_checka(SHADOW(bp), sizeof(*bp) >> 3).kind) {
addr = bp->addr;
if (addr == weakaddr("__gc") && weakaddr("__gc")) {
do
--gi;
do --gi;
while ((addr = garbage->p[gi].ret) == weakaddr("__gc"));
}
bt->p[i] = addr;

View file

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

View file

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

View file

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

View file

@ -20,27 +20,9 @@
#include "libc/calls/strace.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/nt/createfile.h"
#include "libc/nt/enum/creationdisposition.h"
#include "libc/nt/thunk/msabi.h"
extern typeof(CreateFile) *const __imp_CreateFileW __msabi;
static const char *DescribeDisposition(int x) {
switch (x) {
case kNtCreateNew:
return "kNtCreateNew";
case kNtCreateAlways:
return "kNtCreateAlways";
case kNtOpenExisting:
return "kNtOpenExisting";
case kNtOpenAlways:
return "kNtOpenAlways";
case kNtTruncateExisting:
return "kNtTruncateExisting";
default:
return "wut";
}
}
__msabi extern typeof(CreateFile) *const __imp_CreateFileW;
/**
* Opens file on the New Technology.
@ -58,10 +40,11 @@ textwindows int64_t CreateFile(
opt_lpSecurityAttributes, dwCreationDisposition,
dwFlagsAndAttributes, opt_hTemplateFile);
if (hHandle == -1) __winerr();
STRACE("CreateFile(%#hs, %s, %s, %p, %s, %s, %ld) → %ld% m", lpFileName,
STRACE("CreateFile(%#hs, %s, %s, %s, %s, %s, %ld) → %ld% m", lpFileName,
DescribeNtFileAccessFlags(dwDesiredAccess),
DescribeNtFileShareFlags(dwShareMode), opt_lpSecurityAttributes,
DescribeDisposition(dwCreationDisposition),
DescribeNtFileShareFlags(dwShareMode),
DescribeNtSecurityAttributes(opt_lpSecurityAttributes),
DescribeNtCreationDisposition(dwCreationDisposition),
DescribeNtFileFlagsAndAttributes(dwFlagsAndAttributes),
opt_hTemplateFile, hHandle);
return hHandle;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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) {
static char ntfileaccessflags[256];
static char ntfileaccessflags[512];
return DescribeFlags(ntfileaccessflags, sizeof(ntfileaccessflags),
kFileAccessflags, ARRAYLEN(kFileAccessflags), "kNt", x);
}

View file

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

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/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.

View file

@ -17,16 +17,10 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/errno.h"
#include "libc/intrin/dos2errno.internal.h"
#include "libc/nt/errors.h"
#include "libc/sock/sock.h"
struct thatispacked Dos2Errno {
uint16_t doscode;
int32_t systemv;
};
extern const struct Dos2Errno kDos2Errno[];
/**
* Translates Windows error using superset of consts.sh.
*

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/thunk/msabi.h"
extern typeof(FindFirstFile) *const __imp_FindFirstFileW __msabi;
__msabi extern typeof(FindFirstFile) *const __imp_FindFirstFileW;
/**
* Finds first file in directory.

View file

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

View file

@ -20,7 +20,7 @@
#include "libc/calls/strace.internal.h"
#include "libc/nt/files.h"
extern typeof(FlushFileBuffers) *const __imp_FlushFileBuffers __msabi;
__msabi extern typeof(FlushFileBuffers) *const __imp_FlushFileBuffers;
/**
* Flushes buffers of specified file to disk.

View file

@ -20,7 +20,7 @@
#include "libc/calls/strace.internal.h"
#include "libc/nt/memory.h"
extern typeof(FlushViewOfFile) *const __imp_FlushViewOfFile __msabi;
__msabi extern typeof(FlushViewOfFile) *const __imp_FlushViewOfFile;
/**
* Syncs memory created by MapViewOfFileEx().

View file

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

View file

@ -23,7 +23,7 @@
#include "libc/nt/files.h"
#include "libc/nt/thunk/msabi.h"
extern typeof(GetFileAttributes) *const __imp_GetFileAttributesW __msabi;
__msabi extern typeof(GetFileAttributes) *const __imp_GetFileAttributesW;
/**
* Gets file info on the New Technology.

View file

@ -65,6 +65,7 @@ o/$(MODE)/libc/intrin/kprintf.greg.o: \
$(NO_MAGIC)
o/$(MODE)/libc/intrin/createfile.greg.o \
o/$(MODE)/libc/intrin/reopenfile.greg.o \
o/$(MODE)/libc/intrin/deletefile.greg.o \
o/$(MODE)/libc/intrin/createpipe.greg.o \
o/$(MODE)/libc/intrin/closehandle.greg.o \

View file

@ -29,6 +29,71 @@
.section .rodata
.underrun
kDos2Errno:
// .e kNtErrorInvalidFunction,ENOSYS # in consts.sh
// .e kNtErrorFileNotFound,ENOENT # in consts.sh
// .e kNtErrorPathNotFound,ENOTDIR # in consts.sh
// .e kNtErrorTooManyOpenFiles,EMFILE # in consts.sh
// .e kNtErrorAccessDenied,EACCES # in consts.sh
// .e kNtErrorInvalidHandle,EBADF # in consts.sh
// .e kNtErrorInvalidAccess,EPERM # in consts.sh
// .e kNtErrorSeek,ESPIPE # in consts.sh
// .e kNtErrorNotDosDisk,ENOTBLK # in consts.sh
// .e kNtErrorFileExists,EEXIST # in consts.sh
// .e kNtErrorInvalidParameter,EINVAL # in consts.sh
// .e kNtErrorOutofmemory,ENOMEM # in consts.sh
// .e kNtErrorBrokenPipe,EPIPE # in consts.sh
// .e kNtErrorWaitNoChildren,ECHILD # in consts.sh
// .e kNtErrorPathBusy,ETXTBSY # in consts.sh
// .e kNtErrorBusy,EBUSY # in consts.sh
// .e kNtErrorAlreadyExists,EEXIST # in consts.sh
// .e kNtErrorBadExeFormat,ENOEXEC # in consts.sh
// .e kNtErrorFileTooLarge,EFBIG # in consts.sh
// .e kNtErrorTooManyDescriptors,ENFILE # in consts.sh
// .e kNtErrorDirectoryNotSupported,EISDIR # in consts.sh
// .e kNtErrorInvalidAddress,EFAULT # in consts.sh
// .e kNtErrorThreadNotInProcess,ESRCH # in consts.sh
// .e kNtErrorNoMediaInDrive,ENXIO # in consts.sh
// .e kNtErrorIoDevice,EIO # in consts.sh
// .e kNtErrorSerialNoDevice,ENOTTY # in consts.sh
// .e kNtErrorPossibleDeadlock,EDEADLK # in consts.sh
// .e kNtErrorBadDevice,ENODEV # in consts.sh
// .e kNtErrorInvalidCommandLine,E2BIG # in consts.sh
// .e kNtErrorFileReadOnly,EROFS # in consts.sh
// .e kNtErrorNoData,ENODATA # in consts.sh
// .e WSAEPROCLIM,EPROCLIM # in consts.sh
// .e WSAESHUTDOWN,ESHUTDOWN # in consts.sh
// .e WSAEINPROGRESS,EINPROGRESS # in consts.sh
// .e WSAENETDOWN,ENETDOWN # in consts.sh
// .e WSAENETUNREACH,ENETUNREACH # in consts.sh
// .e WSAENETRESET,ENETRESET # in consts.sh
// .e WSAEUSERS,EUSERS # in consts.sh
// .e WSAENOTSOCK,ENOTSOCK # in consts.sh
// .e WSAEDESTADDRREQ,EDESTADDRREQ # in consts.sh
// .e WSAEMSGSIZE,EMSGSIZE # in consts.sh
// .e WSAEPROTOTYPE,EPROTOTYPE # in consts.sh
// .e WSAENOPROTOOPT,ENOPROTOOPT # in consts.sh
// .e WSAEPROTONOSUPPORT,EPROTONOSUPPORT # in consts.sh
// .e WSAESOCKTNOSUPPORT,ESOCKTNOSUPPORT # in consts.sh
// .e WSAEOPNOTSUPP,ENOTSUP # in consts.sh
// .e WSAEOPNOTSUPP,EOPNOTSUPP # in consts.sh
// .e WSAEPFNOSUPPORT,EPFNOSUPPORT # in consts.sh
// .e WSAEAFNOSUPPORT,EAFNOSUPPORT # in consts.sh
// .e WSAEADDRINUSE,EADDRINUSE # in consts.sh
// .e WSAEADDRNOTAVAIL,EADDRNOTAVAIL # in consts.sh
// .e WSAECONNABORTED,ECONNABORTED # in consts.sh
// .e WSAECONNRESET,ECONNRESET # in consts.sh
// .e WSAENOBUFS,ENOBUFS # in consts.sh
// .e WSAEISCONN,EISCONN # in consts.sh
// .e WSAENOTCONN,ENOTCONN # in consts.sh
// .e WSAESHUTDOWN,ESHUTDOWN # in consts.sh
// .e WSAETOOMANYREFS,ETOOMANYREFS # in consts.sh
// .e WSAETIMEDOUT,ETIMEDOUT # in consts.sh
// .e WSAECONNREFUSED,ECONNREFUSED # in consts.sh
// .e WSAEHOSTDOWN,EHOSTDOWN # in consts.sh
// .e WSAEHOSTUNREACH,EHOSTUNREACH # in consts.sh
// .e WSAEALREADY,EALREADY # in consts.sh
// .e WSAESTALE,ESTALE # in consts.sh
// .e WSAEREMOTE,EREMOTE # in consts.sh
.e kNtErrorModNotFound,ENOSYS
.e kNtErrorBadCommand,EACCES
.e kNtErrorBadLength,EACCES
@ -94,10 +159,8 @@ kDos2Errno:
.e WSAEACCES,EACCES
.e WSAEDISCON,EPIPE
.e WSAEFAULT,EFAULT
.e WSAEINPROGRESS,EBUSY
.e WSAEINVAL,EINVAL
.e WSAEPROCLIM,ENOMEM
.e WSAESHUTDOWN,EPIPE
.e WSANOTINITIALISED,ENETDOWN
.e WSASYSNOTREADY,ENETDOWN
.e WSAVERNOTSUPPORTED,ENOSYS

View file

@ -1,7 +1,7 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Copyright 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
@ -16,7 +16,6 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/nt/struct/securityattributes.h"
hidden const struct NtSecurityAttributes kNtIsInheritable = {

View file

@ -37,6 +37,7 @@
#include "libc/nt/process.h"
#include "libc/nt/runtime.h"
#include "libc/nt/thunk/msabi.h"
#include "libc/nt/winsock.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
@ -438,8 +439,7 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, va_list va,
i = 0;
m = (1 << base) - 1;
if (hash && x) sign = hash;
do
z[i++ & 127] = abet[x & m];
do z[i++ & 127] = abet[x & m];
while ((x >>= base) || (pdot && i < prec));
goto EmitNumber;
@ -487,17 +487,31 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, va_list va,
}
goto EmitChar;
case 'm':
if (!(x = errno) && sign == ' ' /* && */
/* (!IsWindows() || !__imp_GetLastError()) */) {
case 'm': {
int unixerr;
uint32_t winerr;
unixerr = errno;
winerr = 0;
if (IsWindows()) {
if (type == 1 && weaken(WSAGetLastError)) {
winerr = weaken(WSAGetLastError)();
} else if (weaken(GetLastError)) {
winerr = weaken(GetLastError)();
}
}
if (!unixerr && sign == ' ') {
break;
} else if (weaken(strerror_r) &&
!weaken(strerror_r)(x, z, sizeof(z))) {
} else if (weaken(strerror_wr) &&
!weaken(strerror_wr)(unixerr, winerr, z, sizeof(z))) {
s = z;
type = 0;
goto FormatString;
} else {
type = 0;
x = unixerr;
goto FormatDecimal;
}
}
case 'G':
x = va_arg(va, int);
@ -864,6 +878,13 @@ privileged void kvprintf(const char *fmt, va_list v) {
* - ` ` space leftpad if positive (aligns w/ negatives)
* - `#` represent value with literal syntax, e.g. 0x, 0b, quotes
*
* Error numbers:
*
* - `%m` formats error (if strerror_wr if is linked)
* - `%m` formats errno number (if strerror_wr isn't linked)
* - `% m` formats error with leading space if errno isn't zero
* - `%lm` means favor WSAGetLastError() over GetLastError() if linked
*
* @asyncsignalsafe
* @vforksafe
*/

View file

@ -23,7 +23,7 @@
#include "libc/nt/enum/filemapflags.h"
#include "libc/nt/memory.h"
extern typeof(MapViewOfFileEx) *const __imp_MapViewOfFileEx __msabi;
__msabi extern typeof(MapViewOfFileEx) *const __imp_MapViewOfFileEx;
/**
* Maps view of file mapping into memory on the New Technology.
@ -45,8 +45,8 @@ textwindows void *MapViewOfFileEx(int64_t hFileMappingObject,
hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh, dwFileOffsetLow,
dwNumberOfBytesToMap, opt_lpDesiredBaseAddress);
if (!pStartingAddress) __winerr();
STRACE("MapViewOfFileEx(%ld, %s, off:%'ld, size:%'zu, addr:%p) → %p% m",
hFileMappingObject, DescribeNtFileMapFlags(dwDesiredAccess),
STRACE("MapViewOfFileEx(%ld, %s, %'ld, %'zu, %p) → %p% m", hFileMappingObject,
DescribeNtFileMapFlags(dwDesiredAccess),
(uint64_t)dwFileOffsetHigh << 32 | dwFileOffsetLow,
dwNumberOfBytesToMap, opt_lpDesiredBaseAddress, pStartingAddress);
return pStartingAddress;

View file

@ -24,7 +24,7 @@
#include "libc/nt/enum/filemapflags.h"
#include "libc/nt/memory.h"
extern typeof(MapViewOfFileExNuma) *const __imp_MapViewOfFileExNuma __msabi;
__msabi extern typeof(MapViewOfFileExNuma) *const __imp_MapViewOfFileExNuma;
/**
* Maps view of file mapping into memory on the New Technology.
@ -47,7 +47,7 @@ textwindows void *MapViewOfFileExNuma(int64_t hFileMappingObject,
hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh, dwFileOffsetLow,
dwNumberOfBytesToMap, opt_lpDesiredBaseAddress, nndDesiredNumaNode);
if (!pStartingAddress) __winerr();
STRACE("MapViewOfFileExNuma(%ld, %s, off:%'ld, size:%'zu, %p) → %p% m",
STRACE("MapViewOfFileExNuma(%ld, %s, %'ld, %'zu, %p) → %p% m",
hFileMappingObject, DescribeNtFileMapFlags(dwDesiredAccess),
(uint64_t)dwFileOffsetHigh << 32 | dwFileOffsetLow,
dwNumberOfBytesToMap, opt_lpDesiredBaseAddress, pStartingAddress);

View file

@ -24,7 +24,7 @@
#include "libc/nt/struct/securityattributes.h"
#include "libc/nt/thunk/msabi.h"
extern typeof(OpenProcess) *const __imp_OpenProcess __msabi;
__msabi extern typeof(OpenProcess) *const __imp_OpenProcess;
/**
* Creates file mapping object on the New Technology.

View file

@ -22,7 +22,7 @@
#include "libc/nt/memory.h"
#include "libc/nt/thunk/msabi.h"
extern typeof(RemoveDirectory) *const __imp_RemoveDirectoryW __msabi;
__msabi extern typeof(RemoveDirectory) *const __imp_RemoveDirectoryW;
/**
* Deletes existing empty directory.

View file

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

View file

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

View file

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

View file

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

View file

@ -22,7 +22,7 @@
#include "libc/nt/runtime.h"
#include "libc/nt/thunk/msabi.h"
extern typeof(TerminateProcess) *const __imp_TerminateProcess __msabi;
__msabi extern typeof(TerminateProcess) *const __imp_TerminateProcess;
/**
* Terminates the specified process and all of its threads.

Some files were not shown because too many files have changed in this diff Show more