Add epoll and do more release readiness changes

This change also pays off some of the remaining technical debt with
stdio, file descriptors, and memory managemnt polyfills.
This commit is contained in:
Justine Tunney 2020-11-28 12:01:51 -08:00
parent a9ea949df8
commit 3e4fd4b0ad
271 changed files with 5706 additions and 1365 deletions

View file

@ -277,27 +277,17 @@ unsigned long hamming(unsigned long, unsigned long) pureconst;
* @return true if value was exchanged, otherwise false
* @see lockcmpxchg()
*/
#define cmpxchg(IFTHING, ISEQUALTOME, REPLACEITWITHME) \
({ \
bool DidIt; \
asm(ZFLAG_ASM("cmpxchg\t%3,%1") \
: ZFLAG_CONSTRAINT(DidIt), "+m"(*(IFTHING)), "+a"(*(ISEQUALTOME)) \
: "r"((typeof(*(IFTHING)))(REPLACEITWITHME)) \
: "cc"); \
DidIt; \
})
#define ezcmpxchg(IFTHING, ISEQUALTOME, REPLACEITWITHME) \
({ \
bool DidIt; \
autotype(IFTHING) IfThing = (IFTHING); \
typeof(*IfThing) IsEqualToMe = (ISEQUALTOME); \
typeof(*IfThing) ReplaceItWithMe = (REPLACEITWITHME); \
asm(ZFLAG_ASM("cmpxchg\t%3,%1") \
: ZFLAG_CONSTRAINT(DidIt), "+m"(*IfThing), "+a"(IsEqualToMe) \
: "r"(ReplaceItWithMe) \
: "cc"); \
DidIt; \
#define cmpxchg(IFTHING, ISEQUALTOME, REPLACEITWITHME) \
({ \
bool DidIt; \
autotype(IFTHING) IfThing = (IFTHING); \
typeof(*IfThing) IsEqualToMe = (ISEQUALTOME); \
typeof(*IfThing) ReplaceItWithMe = (REPLACEITWITHME); \
asm volatile(ZFLAG_ASM("cmpxchg\t%3,%1") \
: ZFLAG_CONSTRAINT(DidIt), "+m"(*IfThing), "+a"(IsEqualToMe) \
: "r"(ReplaceItWithMe) \
: "cc"); \
DidIt; \
})
/**
@ -307,14 +297,17 @@ unsigned long hamming(unsigned long, unsigned long) pureconst;
* @return true if value was exchanged, otherwise false
* @see lockcmpxchg()
*/
#define lockcmpxchg(IFTHING, ISEQUALTOME, REPLACEITWITHME) \
({ \
bool DidIt; \
asm(ZFLAG_ASM("lock cmpxchg\t%3,%1") \
: ZFLAG_CONSTRAINT(DidIt), "+m"(*(IFTHING)), "+a"(*(ISEQUALTOME)) \
: "r"((typeof(*(IFTHING)))(REPLACEITWITHME)) \
: "cc"); \
DidIt; \
#define lockcmpxchg(IFTHING, ISEQUALTOME, REPLACEITWITHME) \
({ \
bool DidIt; \
autotype(IFTHING) IfThing = (IFTHING); \
typeof(*IfThing) IsEqualToMe = (ISEQUALTOME); \
typeof(*IfThing) ReplaceItWithMe = (REPLACEITWITHME); \
asm volatile(ZFLAG_ASM("lock cmpxchg\t%3,%1") \
: ZFLAG_CONSTRAINT(DidIt), "+m"(*IfThing), "+a"(IsEqualToMe) \
: "r"(ReplaceItWithMe) \
: "cc"); \
DidIt; \
})
/**

View file

@ -33,6 +33,6 @@ textwindows int chdir$nt(const char *path) {
if (SetCurrentDirectory(path16)) {
return 0;
} else {
return winerr();
return __winerr();
}
}

View file

@ -24,7 +24,7 @@
textwindows int close$nt(int fd) {
bool32 ok;
if (isfdopen(fd)) {
if (__isfdopen(fd)) {
if (g_fds.p[fd].kind == kFdFile) {
/*
* Like Linux, closing a file on Windows doesn't guarantee it's
@ -37,8 +37,8 @@ textwindows int close$nt(int fd) {
if (g_fds.p[fd].kind == kFdConsole) {
ok &= CloseHandle(g_fds.p[fd].extra);
}
removefd(fd);
return ok ? 0 : winerr();
__removefd(fd);
return ok ? 0 : __winerr();
} else {
return ebadf();
}

View file

@ -20,9 +20,10 @@
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/macros.h"
#include "libc/sock/internal.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.h"
#include "libc/zipos/zipos.internal.h"
/**
* Closes file descriptor.
@ -32,17 +33,24 @@
*/
int close(int fd) {
int rc;
if (fd == -1) return einval();
if (isfdkind(fd, kFdZip)) {
rc = weaken(__zipos_close)(
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle);
if (fd < 0) return einval();
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
rc = weaken(__zipos_close)(fd);
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdEpoll) {
rc = weaken(close$epoll)(fd);
} else if (!IsWindows()) {
rc = close$sysv(fd);
} else if (isfdkind(fd, kFdSocket)) {
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdSocket) {
rc = weaken(closesocket$nt)(fd);
} else {
} else if (fd < g_fds.n &&
(g_fds.p[fd].kind == kFdFile || g_fds.p[fd].kind == kFdConsole)) {
rc = close$nt(fd);
} else {
rc = ebadf();
}
if (fd < g_fds.n) {
g_fds.p[fd].kind = kFdEmpty;
g_fds.f = MIN(g_fds.f, fd);
}
removefd(fd);
return rc;
}

View file

@ -30,17 +30,17 @@
* Implements dup(), dup2(), and dup3() for Windows NT.
*/
textwindows int dup$nt(int oldfd, int newfd, int flags) {
if (!isfdkind(oldfd, kFdFile)) return ebadf();
if (!__isfdkind(oldfd, kFdFile)) return ebadf();
if (newfd == -1) {
if ((newfd = createfd()) == -1) return -1;
} else if (isfdindex(newfd)) {
if ((newfd = __getemptyfd()) == -1) {
return -1;
}
} else if (__ensurefds(newfd) != -1) {
if (g_fds.p[newfd].kind != kFdEmpty) {
close(newfd);
}
} else {
do {
if (growfds() == -1) return -1;
} while (newfd >= g_fds.n);
return -1;
}
if (DuplicateHandle(GetCurrentProcess(), g_fds.p[oldfd].handle,
GetCurrentProcess(), &g_fds.p[newfd].handle, 0,
@ -49,6 +49,6 @@ textwindows int dup$nt(int oldfd, int newfd, int flags) {
g_fds.p[newfd].flags = flags;
return newfd;
} else {
return winerr();
return __winerr();
}
}

View file

@ -38,7 +38,7 @@ textwindows int fadvise$nt(int fd, uint64_t offset, uint64_t len, int advice) {
struct NtIoStatusBlock iostatus;
struct NtFileBasicInformation basicinfo;
struct NtFileAccessInformation accessinfo;
if (!isfdkind(fd, kFdFile)) return ebadf();
if (!__isfdkind(fd, kFdFile)) return ebadf();
sharemode = /* xxx: no clue how to query this */
kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete;
/* TODO(jart): can we do it in one call w/ NtQueryObject? */
@ -56,7 +56,7 @@ textwindows int fadvise$nt(int fd, uint64_t offset, uint64_t len, int advice) {
}
return 0;
}
return winerr();
return __winerr();
} else if (status == kNtStatusDllNotFound) {
return enosys();
} else {

View file

@ -51,7 +51,7 @@ int fallocate(int fd, int32_t mode, int64_t offset, int64_t length) {
} else if (!IsWindows()) {
return posix_fallocate$sysv(fd, offset, length);
} else if (IsWindows()) {
if (!isfdkind(fd, kFdFile)) return ebadf();
if (!__isfdkind(fd, kFdFile)) return ebadf();
if (mode == FALLOC_FL_ZERO_RANGE) {
if (DeviceIoControl(
g_fds.p[fd].handle, kNtFsctlSetZeroData,
@ -59,7 +59,7 @@ int fallocate(int fd, int32_t mode, int64_t offset, int64_t length) {
sizeof(struct NtFileZeroDataInformation), NULL, 0, &br, NULL)) {
return 0;
} else {
return winerr();
return __winerr();
}
} else if (!mode && !offset) {
/*

View file

@ -21,20 +21,31 @@
#include "libc/nt/files.h"
#include "libc/sysv/consts/f.h"
#include "libc/sysv/consts/fd.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h"
textwindows int fcntl$nt(int fd, int cmd, unsigned arg) {
uint32_t flags;
if (!isfdkind(fd, kFdFile)) return ebadf();
if (!__isfdkind(fd, kFdFile)) return ebadf();
switch (cmd) {
case F_GETFL:
return g_fds.p[fd].flags;
case F_SETFL:
return (g_fds.p[fd].flags = arg);
case F_GETFD:
if (!GetHandleInformation(g_fds.p[fd].handle, &flags)) return -1;
arg = (flags & FD_CLOEXEC) ^ FD_CLOEXEC;
return arg;
if (g_fds.p[fd].flags & O_CLOEXEC) {
return FD_CLOEXEC;
} else {
return 0;
}
case F_SETFD:
arg ^= FD_CLOEXEC;
if (!SetHandleInformation(g_fds.p[fd].handle, FD_CLOEXEC, arg)) return -1;
return 0;
if (arg & O_CLOEXEC) {
g_fds.p[fd].flags |= O_CLOEXEC;
return FD_CLOEXEC;
} else {
g_fds.p[fd].flags &= ~O_CLOEXEC;
return 0;
}
default:
return 0; /* TODO(jart): Implement me. */
}

View file

@ -22,11 +22,11 @@
#include "libc/sysv/errfuns.h"
textwindows int fdatasync$nt(int fd) {
if (!isfdkind(fd, kFdFile)) return ebadf();
if (!__isfdkind(fd, kFdFile)) return ebadf();
/*
* XXX: On Windows NT this might be more analagous to fflush() and
* Microsoft docs say to do manual block i/o for database-ish
* guarantees on disk persistence. Consider: Really good UPS.
*/
return FlushFileBuffers(g_fds.p[fd].handle) ? 0 : winerr();
return FlushFileBuffers(g_fds.p[fd].handle) ? 0 : __winerr();
}

View file

@ -20,7 +20,7 @@
#include "libc/calls/internal.h"
enum FdKind fdkind(int fd) {
if (isfdindex(fd)) {
if (0 <= fd && fd <= g_fds.n) {
return g_fds.p[fd].kind;
} else {
return kFdEmpty;

View file

@ -29,7 +29,7 @@
textwindows int flock$nt(int fd, int op) {
struct NtOverlapped ov;
struct NtByHandleFileInformation info;
if (!isfdkind(fd, kFdFile)) return ebadf();
if (!__isfdkind(fd, kFdFile)) return ebadf();
memset(&ov, 0, sizeof(ov));
if (GetFileInformationByHandle(g_fds.p[fd].handle, &info) &&
((!(op & LOCK_UN) &&
@ -39,6 +39,6 @@ textwindows int flock$nt(int fd, int op) {
info.nFileSizeHigh, &ov)))) {
return 0;
} else {
return winerr();
return __winerr();
}
}

View file

@ -66,6 +66,6 @@ textwindows int fstat$nt(int64_t handle, struct stat *st) {
st->st_blocks = roundup(actualsize, PAGESIZE) / 512;
return 0;
} else {
return winerr();
return __winerr();
}
}

View file

@ -22,20 +22,20 @@
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.h"
#include "libc/zipos/zipos.internal.h"
/**
* Returns information about file, via open()'d descriptor.
* @asyncsignalsafe
*/
int fstat(int fd, struct stat *st) {
if (isfdkind(fd, kFdZip)) {
if (__isfdkind(fd, kFdZip)) {
return weaken(__zipos_fstat)(
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, st);
} else if (!IsWindows()) {
return fstat$sysv(fd, st);
} else {
if (!isfdkind(fd, kFdFile)) return ebadf();
if (!__isfdkind(fd, kFdFile)) return ebadf();
return fstat$nt(g_fds.p[fd].handle, st);
}
}

View file

@ -25,14 +25,14 @@
textwindows int ftruncate$nt(int fd, uint64_t length) {
bool32 ok;
int64_t tell;
if (!isfdkind(fd, kFdFile)) return ebadf();
if (!__isfdkind(fd, kFdFile)) return ebadf();
tell = -1;
if (SetFilePointerEx(g_fds.p[fd].handle, 0, &tell, kNtFileCurrent)) {
ok = SetFilePointerEx(g_fds.p[fd].handle, length, NULL, kNtFileBegin) &&
SetEndOfFile(g_fds.p[fd].handle);
SetFilePointerEx(g_fds.p[fd].handle, tell, NULL, kNtFileBegin);
return ok ? 0 : winerr();
return ok ? 0 : __winerr();
} else {
return winerr();
return __winerr();
}
}

View file

@ -33,12 +33,22 @@ void InitializeFileDescriptors(void) {
pushmov(&fds->f, 3ul);
pushmov(&fds->n, ARRAYLEN(fds->__init_p));
fds->p = fds->__init_p;
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 = GetStdHandle(pushpop(kNtStdInputHandle));
fds->__init_p[STDOUT_FILENO].handle =
GetStdHandle(pushpop(kNtStdOutputHandle));
fds->__init_p[STDERR_FILENO].handle =
GetStdHandle(pushpop(kNtStdErrorHandle));
if (!IsMetal()) {
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 =
GetStdHandle(pushpop(kNtStdInputHandle));
fds->__init_p[STDOUT_FILENO].handle =
GetStdHandle(pushpop(kNtStdOutputHandle));
fds->__init_p[STDERR_FILENO].handle =
GetStdHandle(pushpop(kNtStdErrorHandle));
} else {
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 = 0x3F8;
fds->__init_p[STDOUT_FILENO].handle = 0x3F8;
fds->__init_p[STDERR_FILENO].handle = 0x3F8;
}
}

View file

@ -31,7 +31,7 @@ textwindows char *getcwd$nt(char *buf, size_t size) {
erange();
}
} else {
winerr();
__winerr();
}
return NULL;
}

View file

@ -45,7 +45,7 @@ int getdomainname(char *name, size_t len) {
} else {
nSize = ARRAYLEN(name16);
if (!GetComputerNameEx(kNtComputerNameDnsFullyQualified, name16, &nSize)) {
return winerr();
return __winerr();
}
tprecode16to8(name, MIN(MIN(ARRAYLEN(name16), nSize + 1), len), name16);
return 0;

View file

@ -25,14 +25,11 @@
/**
* Finds open file descriptor slot.
*/
ssize_t createfd(void) {
size_t fd;
for (;;) {
while (g_fds.f < g_fds.n) {
if (g_fds.p[(fd = g_fds.f++)].kind == kFdEmpty) {
return fd;
}
ssize_t __getemptyfd(void) {
for (; g_fds.f < g_fds.n; ++g_fds.f) {
if (g_fds.p[g_fds.f].kind == kFdEmpty) {
return g_fds.f;
}
if (growfds() == -1) return -1;
}
return __ensurefds(g_fds.f);
}

View file

@ -50,7 +50,7 @@ int gethostname(char *name, size_t len) {
} else {
nSize = ARRAYLEN(name16);
if (!GetComputerNameEx(kNtComputerNameDnsHostname, name16, &nSize)) {
return winerr();
return __winerr();
}
tprecode16to8(name, MIN(MIN(ARRAYLEN(name16), nSize + 1), len), name16);
return 0;

View file

@ -46,6 +46,6 @@ textwindows int getpriority$nt(int ignored) {
}
abort();
} else {
return winerr();
return __winerr();
}
}

View file

@ -40,6 +40,6 @@ textwindows int getrusage$nt(int who, struct rusage *usage) {
FileTimeToTimeVal(&usage->ru_stime, KernelFileTime);
return 0;
} else {
return winerr();
return __winerr();
}
}

View file

@ -23,18 +23,20 @@
#include "libc/mem/mem.h"
#include "libc/sysv/errfuns.h"
int growfds(void) {
int __ensurefds(int fd) {
size_t i, n;
struct Fd *p;
if (fd < g_fds.n) return fd;
if (weaken(realloc)) {
if ((p = weaken(realloc)(g_fds.p != g_fds.__init_p ? g_fds.p : NULL,
(n = (i = g_fds.n) << 1) * sizeof(*p)))) {
if ((p = weaken(realloc)(
g_fds.p != g_fds.__init_p ? g_fds.p : NULL,
(n = MAX(fd + 1, (i = g_fds.n) << 1)) * sizeof(*p)))) {
do {
p[i++].kind = kFdEmpty;
} while (i < n);
g_fds.p = p;
g_fds.n = n;
return 0;
return fd;
} else {
return enomem();
}

View file

@ -55,7 +55,7 @@ static textwindows int copyfile$nt(const char *src, const char *dst,
}
return 0;
} else {
return winerr();
return __winerr();
}
}

View file

@ -74,7 +74,7 @@ static textwindows noinline DIR *opendir$nt(const char *name) {
if ((res->fd = FindFirstFile(name16, &res->windata)) != -1) {
return res;
} else {
winerr();
__winerr();
free(res);
return NULL;
}
@ -220,7 +220,7 @@ int closedir(DIR *dir) {
if (!IsWindows()) {
rc = close(dir->fd);
} else {
rc = FindClose(dir->fd) ? 0 : winerr();
rc = FindClose(dir->fd) ? 0 : __winerr();
}
free(dir);
} else {

View file

@ -67,7 +67,7 @@ textwindows void WinMainForked(void) {
char16_t *p;
uint64_t size;
char16_t var[21 + 1 + 21 + 1];
uint32_t i, varlen, protect, access;
uint32_t i, varlen, protect, access, oldprot;
varlen = GetEnvironmentVariable(u"_FORK", var, ARRAYLEN(var));
if (!varlen || varlen >= ARRAYLEN(var)) return;
p = var;
@ -98,11 +98,13 @@ textwindows void WinMainForked(void) {
break;
}
if (_mmi.p[i].flags & MAP_PRIVATE) {
MapViewOfFileExNuma(
(_mmi.p[i].h = CreateFileMappingNuma(-1, NULL, protect, 0, size, NULL,
kNtNumaNoPreferredNode)),
access, 0, 0, size, addr, kNtNumaNoPreferredNode);
MapViewOfFileExNuma((_mmi.p[i].h = CreateFileMappingNuma(
-1, NULL, kNtPageExecuteReadwrite, 0, size, NULL,
kNtNumaNoPreferredNode)),
kNtFileMapRead | kNtFileMapWrite | kNtFileMapExecute,
0, 0, size, addr, kNtNumaNoPreferredNode);
ReadAll(h, addr, size);
VirtualProtect(addr, size, protect, &oldprot);
} else {
MapViewOfFileExNuma(_mmi.p[i].h, access, 0, 0, size, addr,
kNtNumaNoPreferredNode);
@ -148,7 +150,7 @@ textwindows int fork$nt(void) {
}
unsetenv("_FORK");
} else {
rc = winerr();
rc = __winerr();
}
} else {
rc = 0;

View file

@ -78,7 +78,7 @@ textwindows int ntspawn(
opt_out_lpProcessInformation)) {
rc = 0;
} else {
rc = winerr();
rc = __winerr();
}
} else {
rc = -1;

View file

@ -49,14 +49,14 @@ textwindows int spawnve$nt(unsigned flags, int stdiofds[3], const char *program,
sti.cb = sizeof(sti);
sti.dwFlags = kNtStartfUsestdhandles;
if ((pid = createfd()) == -1) return -1;
if ((pid = __getemptyfd()) == -1) return -1;
for (i = 0; i < 3; ++i) {
if (stdiofds[i] == -1) {
x = &h;
y = &sti.stdiofds[i];
if (kIoMotion[i]) xchg(&x, &y);
if ((tubes[i] = createfd()) != -1 &&
if ((tubes[i] = __getemptyfd()) != -1 &&
CreatePipe(x, y, &kNtIsInheritable, 0)) {
g_fds.p[tubes[i]].handle = h;
} else {

View file

@ -76,7 +76,7 @@ int ttyname_r(int fd, char *buf, size_t size) {
} else if (IsFreebsd()) {
return ttyname$freebsd(fd, buf, size);
} else if (IsWindows()) {
if (isfdkind(fd, kFdFile)) {
if (__isfdkind(fd, kFdFile)) {
return ttyname$nt(fd, buf, size);
} else {
return ebadf();

View file

@ -2,6 +2,7 @@
#define COSMOPOLITAN_LIBC_CALLS_INTERNAL_H_
#ifndef __STRICT_ANSI__
#include "libc/calls/calls.h"
#include "libc/calls/struct/iovec.h"
#include "libc/calls/struct/itimerval.h"
#include "libc/calls/struct/timespec.h"
#include "libc/calls/struct/timeval.h"
@ -37,7 +38,7 @@ struct IoctlPtmGet {
struct Fds {
size_t f; // arbitrary free slot start search index
size_t n; // capacity
size_t n; // monotonic capacity
struct Fd {
int64_t handle;
int64_t extra;
@ -47,7 +48,9 @@ struct Fds {
kFdSocket,
kFdProcess,
kFdConsole,
kFdSerial,
kFdZip,
kFdEpoll,
} kind;
unsigned flags;
} * p;
@ -62,20 +65,12 @@ hidden extern struct NtSystemInfo g_ntsysteminfo;
hidden extern struct NtStartupInfo g_ntstartupinfo;
hidden extern const struct NtSecurityAttributes kNtIsInheritable;
ssize_t createfd(void) hidden;
int growfds(void) hidden;
void removefd(int) hidden;
ssize_t __getemptyfd(void) hidden;
int __ensurefds(int) hidden;
void __removefd(int) hidden;
enum FdKind fdkind(int) hidden nosideeffect;
bool isfdopen(int) hidden nosideeffect;
bool isfdkind(int, enum FdKind) hidden nosideeffect;
forceinline bool isfdindex(int fd) {
if (!IsTrustworthy()) {
return (0 <= fd && fd < g_fds.n);
} else {
return true;
}
}
bool __isfdopen(int) hidden nosideeffect;
bool __isfdkind(int, enum FdKind) hidden nosideeffect;
forceinline size_t clampio(size_t size) {
if (!IsTrustworthy()) {
@ -267,7 +262,7 @@ bool32 onntconsoleevent$nt(u32) hidden;
void __winalarm(void *, uint32_t, uint32_t) hidden;
int ntaccesscheck(const char16_t *, u32) paramsnonnull() hidden;
i64 ntreturn(u32);
i64 winerr(void) nocallback privileged;
i64 __winerr(void) nocallback privileged;
#define mkntpath(PATH, PATH16) mkntpath2(PATH, -1u, PATH16)
#define mkntpath2(PATH, FLAGS, PATH16) \
@ -280,6 +275,13 @@ i64 winerr(void) nocallback privileged;
Count; \
})
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § syscalls » drivers
*/
ssize_t readv$serial(struct Fd *, const struct iovec *, int) hidden;
ssize_t writev$serial(struct Fd *, const struct iovec *, int) hidden;
#undef sigset
#undef i32
#undef i64

View file

@ -29,13 +29,13 @@ int ioctl$default(int fd, uint64_t request, void *memory) {
int64_t handle;
if (!IsWindows()) {
return ioctl$sysv(fd, request, memory);
} else if (isfdopen(fd)) {
} else if (__isfdopen(fd)) {
if (g_fds.p[fd].kind == kFdSocket) {
handle = g_fds.p[fd].handle;
if ((rc = weaken(__ioctlsocket$nt)(handle, request, memory)) != -1) {
return rc;
} else {
return weaken(winsockerr)();
return weaken(__winsockerr)();
}
} else {
return eopnotsupp();

View file

@ -33,7 +33,7 @@ textwindows int ioctl$tiocgwinsz$nt(int fd, struct winsize *ws) {
struct NtConsoleScreenBufferInfoEx sbinfo;
fds[0] = fd, fds[1] = 1, fds[2] = 0;
for (i = 0; i < ARRAYLEN(fds); ++i) {
if (isfdkind(fds[i], kFdFile) || isfdkind(fds[i], kFdConsole)) {
if (__isfdkind(fds[i], kFdFile) || __isfdkind(fds[i], kFdConsole)) {
if (GetConsoleMode(g_fds.p[fds[i]].handle, &mode)) {
memset(&sbinfo, 0, sizeof(sbinfo));
sbinfo.cbSize = sizeof(sbinfo);
@ -50,7 +50,7 @@ textwindows int ioctl$tiocgwinsz$nt(int fd, struct winsize *ws) {
ws->ws_ypixel = 0;
return 0;
} else {
winerr();
__winerr();
}
} else {
enotty();

View file

@ -29,10 +29,10 @@ textwindows int ioctl$tiocswinsz$nt(int fd, const struct winsize *ws) {
uint32_t mode;
struct NtCoord coord;
if (!ws) return efault();
if (!isfdkind(fd, kFdFile)) return ebadf();
if (!__isfdkind(fd, kFdFile)) return ebadf();
if (!GetConsoleMode(g_fds.p[fd].handle, &mode)) return enotty();
coord.X = ws->ws_col;
coord.Y = ws->ws_row;
if (!SetConsoleScreenBufferSize(g_fds.p[fd].handle, coord)) return winerr();
if (!SetConsoleScreenBufferSize(g_fds.p[fd].handle, coord)) return __winerr();
return 0;
}

View file

@ -23,6 +23,6 @@
#include "libc/sysv/errfuns.h"
textwindows bool32 isatty$nt(int fd) {
if (!isfdkind(fd, kFdFile)) return ebadf();
if (!__isfdkind(fd, kFdFile)) return ebadf();
return GetFileType(g_fds.p[fd].handle) == kNtFileTypeChar;
}

View file

@ -40,7 +40,7 @@ textstartup bool32 ischardev(int fd) {
return false;
}
} else {
return isfdkind(fd, kFdFile) &&
return __isfdkind(fd, kFdFile) &&
GetFileType(g_fds.p[fd].handle) == kNtFileTypeChar;
}
}

View file

@ -19,6 +19,6 @@
*/
#include "libc/calls/internal.h"
bool isfdkind(int fd, enum FdKind kind) {
return isfdindex(fd) && g_fds.p[fd].kind == kind;
bool __isfdkind(int fd, enum FdKind kind) {
return 0 <= fd && fd < g_fds.n && g_fds.p[fd].kind == kind;
}

View file

@ -19,6 +19,6 @@
*/
#include "libc/calls/internal.h"
bool isfdopen(int fd) {
return isfdindex(fd) && g_fds.p[fd].kind != kFdEmpty;
bool __isfdopen(int fd) {
return 0 <= fd && fd < g_fds.n && g_fds.p[fd].kind != kFdEmpty;
}

View file

@ -17,10 +17,10 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/calls/internal.h"
#include "libc/calls/calls.h"
textwindows int link$nt(const char *existingpath, const char *newpath) {
char16_t newpath16[PATH_MAX];
@ -30,7 +30,7 @@ textwindows int link$nt(const char *existingpath, const char *newpath) {
if (CreateHardLink(newpath16, existingpath16, NULL)) {
return 0;
} else {
return winerr();
return __winerr();
}
} else {
return -1;

View file

@ -23,10 +23,10 @@
textwindows int64_t lseek$nt(int fd, int64_t offset, int whence) {
int64_t res;
if (!isfdkind(fd, kFdFile)) return ebadf();
if (!__isfdkind(fd, kFdFile)) return ebadf();
if (SetFilePointerEx(g_fds.p[fd].handle, offset, &res, whence)) {
return res;
} else {
return winerr();
return __winerr();
}
}

View file

@ -61,7 +61,7 @@ textwindows int madvise$nt(void *addr, size_t length, int advice) {
if (fn(GetCurrentProcess(), &rangecount, ranges, 0)) {
return 0;
} else {
return winerr();
return __winerr();
}
} else {
return enosys();
@ -72,7 +72,7 @@ textwindows int madvise$nt(void *addr, size_t length, int advice) {
if (fn(addr, length, kNtVmOfferPriorityNormal)) {
return 0;
} else {
return winerr();
return __winerr();
}
} else {
return enosys();

View file

@ -31,7 +31,7 @@ static textwindows noinline int mkdir$nt(const char *path, uint32_t mode) {
if (CreateDirectory(path16, NULL)) {
return 0;
} else {
return winerr();
return __winerr();
}
}

View file

@ -55,7 +55,7 @@ int mprotect(void *addr, uint64_t len, int prot) {
if (__imp_VirtualProtect(addr, len, prot2nt(prot, 0), &oldprot)) {
return 0;
} else {
return winerr();
return __winerr();
}
}
}

View file

@ -22,7 +22,6 @@
#include "libc/macros.h"
#include "libc/nexgen32e/nexgen32e.h"
#include "libc/sock/internal.h"
#include "libc/sock/select.internal.h"
int nanosleep$xnu(const struct timespec *req, struct timespec *rem) {
long millis;

View file

@ -81,7 +81,7 @@ textwindows int ntaccesscheck(const char16_t *pathname, uint32_t flags) {
(result || flags == F_OK)) {
rc = 0;
} else {
rc = winerr();
rc = __winerr();
}
close(hImpersonatedToken);
close(hToken);

View file

@ -49,7 +49,7 @@ static textwindows int64_t open$nt$impl(const char *file, uint32_t flags,
(flags & O_EXCL)
? kNtFileShareExclusive
: kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete,
(flags & O_CLOEXEC) ? &kNtIsInheritable : NULL,
&kNtIsInheritable,
(flags & O_CREAT) && (flags & O_EXCL)
? kNtCreateNew
: (flags & O_CREAT) && (flags & O_TRUNC)
@ -94,7 +94,7 @@ static textwindows ssize_t open$nt$console(const struct NtMagicPaths *mp,
open$nt$impl(mp->conout, (flags & ~O_ACCMODE) | O_WRONLY, mode);
assert(g_fds.p[fd].extra != -1);
} else {
return winerr();
return __winerr();
}
g_fds.p[fd].kind = kFdConsole;
g_fds.p[fd].flags = flags;
@ -111,13 +111,13 @@ static textwindows ssize_t open$nt$file(const char *file, uint32_t flags,
((flags & O_CREAT) && (flags & O_TRUNC))) {
return eisdir();
} else {
return winerr();
return __winerr();
}
}
textwindows ssize_t open$nt(const char *file, uint32_t flags, int32_t mode) {
size_t fd;
if ((fd = createfd()) == -1) return -1;
if ((fd = __getemptyfd()) == -1) return -1;
if ((flags & O_ACCMODE) == O_RDWR &&
tinystrcmp(file, kNtMagicPaths.devtty) == 0) {
return open$nt$console(&kNtMagicPaths, flags, mode, fd);

View file

@ -24,7 +24,7 @@
#include "libc/str/str.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.h"
#include "libc/zipos/zipos.internal.h"
/**
* Opens file.

View file

@ -61,24 +61,25 @@ static int openanon$impl(const char *name, unsigned flags,
char pathbuf[hasatleast PATH_MAX]) {
int fd;
openanon$genpath(name, state, pathbuf);
flags |= O_RDWR | O_CREAT | O_EXCL | O_TRUNC;
if (!IsWindows()) {
flags |= O_RDWR | O_CREAT | O_EXCL | O_TRUNC;
if ((fd = openat$sysv(AT_FDCWD, pathbuf, flags, 0600)) != -1) {
unlink(pathbuf);
}
return fd;
} else {
if ((fd = createfd()) != -1 &&
if ((fd = __getemptyfd()) != -1 &&
(g_fds.p[fd].handle = CreateFileA(
pathbuf, kNtGenericRead | kNtGenericWrite, kNtFileShareExclusive,
(flags & O_CLOEXEC) ? &kNtIsInheritable : NULL, kNtCreateAlways,
&kNtIsInheritable, kNtCreateAlways,
(kNtFileAttributeNotContentIndexed | kNtFileAttributeNormal |
kNtFileAttributeTemporary | kNtFileFlagDeleteOnClose),
0)) != -1) {
g_fds.p[fd].kind = kFdFile;
g_fds.p[fd].flags = flags;
return fd;
} else {
return winerr();
return __winerr();
}
}
}

View file

@ -24,11 +24,10 @@
textwindows int pipe$nt(int pipefd[2], unsigned flags) {
int reader, writer;
if ((reader = createfd()) == -1) return -1;
if ((writer = createfd()) == -1) return -1;
if ((reader = __getemptyfd()) == -1) return -1;
if ((writer = __getemptyfd()) == -1) return -1;
if (CreatePipe(&g_fds.p[reader].handle, &g_fds.p[writer].handle,
(flags & O_CLOEXEC) ? NULL : &kNtIsInheritable,
0 /* let NT pick buffer size */)) {
&kNtIsInheritable, 0)) {
g_fds.p[reader].kind = kFdFile;
g_fds.p[reader].flags = flags;
g_fds.p[writer].kind = kFdFile;
@ -37,6 +36,6 @@ textwindows int pipe$nt(int pipefd[2], unsigned flags) {
pipefd[1] = writer;
return 0;
} else {
return winerr();
return __winerr();
}
}

View file

@ -26,7 +26,7 @@
#include "libc/macros.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.h"
#include "libc/zipos/zipos.internal.h"
/**
* Reads from file at offset, thus avoiding superfluous lseek().
@ -42,12 +42,12 @@
ssize_t pread(int fd, void *buf, size_t size, int64_t offset) {
ssize_t rc;
if (fd == -1 || offset < 0) return einval();
if (isfdkind(fd, kFdZip)) {
if (__isfdkind(fd, kFdZip)) {
rc = weaken(__zipos_read)(
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, buf, size, offset);
} else if (!IsWindows()) {
rc = pread$sysv(fd, buf, size, offset);
} else if (isfdkind(fd, kFdFile)) {
} else if (__isfdkind(fd, kFdFile)) {
rc = read$nt(&g_fds.p[fd], (struct iovec[]){{buf, size}}, 1, offset);
} else {
rc = ebadf();

View file

@ -43,7 +43,7 @@ ssize_t pwrite(int fd, const void *buf, size_t size, int64_t offset) {
size = MIN(size, 0x7ffff000);
if (!IsWindows()) {
rc = pwrite$sysv(fd, buf, size, offset);
} else if (isfdkind(fd, kFdFile)) {
} else if (__isfdkind(fd, kFdFile)) {
rc = write$nt(&g_fds.p[fd], (struct iovec[]){{buf, size}}, 1, offset);
} else {
return ebadf();

View file

@ -60,7 +60,7 @@ int raise(int sig) {
if (GenerateConsoleCtrlEvent(GetCtrlEvent(sig), 0)) {
return 0;
} else {
return winerr();
return __winerr();
}
}
}

View file

@ -40,6 +40,6 @@ textwindows ssize_t read$nt(struct Fd *fd, const struct iovec *iov,
} else if (NtGetErr() == kNtErrorBrokenPipe) {
return 0; /* read() doesn't EPIPE lool */
} else {
return winerr();
return __winerr();
}
}

View file

@ -17,17 +17,8 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/assert.h"
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/iovec.h"
#include "libc/dce.h"
#include "libc/macros.h"
#include "libc/runtime/runtime.h"
#include "libc/sock/internal.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.h"
#include "libc/sock/sock.h"
/**
* Reads data from file descriptor.
@ -41,24 +32,5 @@
* @asyncsignalsafe
*/
ssize_t read(int fd, void *buf, size_t size) {
ssize_t rc;
if (fd == -1) return einval();
if (isfdkind(fd, kFdZip)) {
rc =
weaken(__zipos_read)((struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle,
(struct iovec[]){{buf, size}}, 1, -1);
} else if (!IsWindows()) {
rc = read$sysv(fd, buf, size);
} else if (isfdkind(fd, kFdFile) || isfdkind(fd, kFdConsole)) {
rc = read$nt(&g_fds.p[fd], (struct iovec[]){{buf, size}}, 1, -1);
} else if (isfdkind(fd, kFdSocket)) {
rc = weaken(recvfrom$nt)(&g_fds.p[fd], (struct iovec[]){{buf, size}}, 1, 0,
NULL, NULL);
} else {
rc = ebadf();
}
if (!IsTrustworthy() && rc != -1) {
if ((size_t)rc > size) abort();
}
return rc;
return readv(fd, &(struct iovec){buf, size}, 1);
}

View file

@ -18,39 +18,39 @@
02110-1301 USA
*/
#include "ape/lib/pc.h"
#include "libc/calls/internal.h"
#include "libc/nexgen32e/uart.internal.h"
#include "libc/stdio/internal.h"
#include "libc/stdio/stdio.h"
static void fin(FILE *f) {
f->buf[f->end] = inb(0x3F8);
f->end = (f->end + 1) & (f->size - 1);
static bool IsDataAvailable(struct Fd *fd) {
return inb(fd->handle + UART_LSR) & UART_TTYDA;
}
static void fout(FILE *f) {
outb(0x3F8, f->buf[f->beg]);
f->beg = (f->beg + 1) & (f->size - 1);
}
static int serialstdio(FILE *f, unsigned char status, void action(FILE *)) {
int block = 1;
unsigned tally = 0;
while (f->end != f->beg) {
if (!(inb(0x3F8 + UART_LSR) & status)) {
if (!block) break;
asm("pause");
} else {
action(f);
tally++;
static int GetFirstIov(struct iovec *iov, int iovlen) {
int i;
for (i = 0; i < iovlen; ++i) {
if (iov[i].iov_len) {
return i;
}
}
return (int)tally;
return -1;
}
int fsreadbuf(FILE *f) {
return serialstdio(f, UART_TTYDA, fin);
}
int fswritebuf(FILE *f) {
return serialstdio(f, UART_TTYTXR, fout);
ssize_t readv$serial(struct Fd *fd, const struct iovec *iov, int iovlen) {
size_t i, j, got = 0;
if ((i = GetFirstIov(iov, iovlen)) != -1) {
while (!IsDataAvailable(fd)) asm("pause");
i = 0;
j = 0;
do {
++got;
((char *)iov[i].iov_base)[j] = inb(fd->handle);
if (++j == iov[i].iov_len) {
j = 0;
if (++i == iovlen) {
break;
}
}
} while (IsDataAvailable(fd));
}
return got;
}

View file

@ -23,7 +23,7 @@
#include "libc/calls/struct/iovec.h"
#include "libc/sock/internal.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.h"
#include "libc/zipos/zipos.internal.h"
/**
* Reads data to multiple buffers.
@ -31,19 +31,19 @@
* @return number of bytes actually read, or -1 w/ errno
*/
ssize_t readv(int fd, const struct iovec *iov, int iovlen) {
if (!IsTrustworthy()) {
if (fd == -1) return einval();
if (iovlen < 0) return einval();
}
if (isfdkind(fd, kFdZip)) {
if (fd < 0) return einval();
if (iovlen < 0) return einval();
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
return weaken(__zipos_read)(
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, -1);
}
if (!IsWindows()) {
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdSerial) {
return readv$serial(&g_fds.p[fd], iov, iovlen);
} else if (!IsWindows()) {
return readv$sysv(fd, iov, iovlen);
} else if (isfdkind(fd, kFdFile) || isfdkind(fd, kFdConsole)) {
} else if (fd < g_fds.n &&
(g_fds.p[fd].kind == kFdFile || g_fds.p[fd].kind == kFdConsole)) {
return read$nt(&g_fds.p[fd], iov, iovlen, -1);
} else if (isfdkind(fd, kFdSocket)) {
} else if (fd < g_fds.n && (g_fds.p[fd].kind == kFdSocket)) {
return weaken(recvfrom$nt)(&g_fds.p[fd], iov, iovlen, 0, NULL, 0);
} else {
return ebadf();

View file

@ -20,8 +20,8 @@
#include "libc/calls/internal.h"
#include "libc/macros.h"
void removefd(int fd) {
if (isfdopen(fd)) {
void __removefd(int fd) {
if (__isfdopen(fd)) {
g_fds.p[fd].kind = kFdEmpty;
g_fds.f = MIN(g_fds.f, fd);
}

View file

@ -34,6 +34,6 @@ textwindows int rename$nt(const char *oldpath, const char *newpath) {
if (MoveFileEx(oldpath16, newpath16, kNtMovefileReplaceExisting)) {
return 0;
} else {
return winerr();
return __winerr();
}
}

View file

@ -27,6 +27,6 @@ textwindows int rmdir$nt(const char *path) {
if (RemoveDirectory(path16)) {
return 0;
} else {
return winerr();
return __winerr();
}
}

View file

@ -56,7 +56,7 @@ static textwindows noinline int sched_setaffinity$nt(int pid,
}
}
}
rc = SetAffinityMask(handle ? handle : pid, mask) ? 0 : winerr();
rc = SetAffinityMask(handle ? handle : pid, mask) ? 0 : __winerr();
if (handle) CloseHandle(handle);
return rc;
}

View file

@ -69,7 +69,7 @@ textwindows int setitimer$nt(int which, const struct itimerval *newvalue,
if (newvalue) {
if (newvalue->it_value.tv_sec && newvalue->it_value.tv_usec) {
if (!(ith = CreateWaitableTimer(NULL, false, NULL))) {
return winerr();
return __winerr();
}
duetime = -(newvalue->it_value.tv_sec * HECTONANOSECONDS +
newvalue->it_value.tv_usec * 10);

View file

@ -48,6 +48,6 @@ textwindows int setpriority$nt(int nice) {
SetThreadPriority(GetCurrentThread(), p.wut)) {
return p.nice;
} else {
return winerr();
return __winerr();
}
}

View file

@ -81,7 +81,7 @@ static void sigaction$cosmo2native(union metasigaction *sa) {
sa_mask);
break;
default:
abort();
break;
}
}
@ -105,7 +105,7 @@ static void sigaction$native2cosmo(union metasigaction *sa) {
sa_mask);
break;
default:
abort();
break;
}
}

View file

@ -41,6 +41,6 @@ textwindows int stat$nt(const char *path, struct stat *st) {
CloseHandle(fh);
return rc;
} else {
return winerr();
return __winerr();
}
}

View file

@ -24,7 +24,7 @@
#include "libc/str/str.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.h"
#include "libc/zipos/zipos.internal.h"
/**
* Returns information about thing.

View file

@ -29,6 +29,6 @@ textwindows int symlink$nt(const char *target, const char *linkpath) {
if (CreateSymbolicLink(linkpath16, target16, flags)) {
return 0;
} else {
return winerr();
return __winerr();
}
}

View file

@ -34,6 +34,6 @@ textwindows int sysinfo$nt(struct sysinfo *info) {
info->mem_unit = 1;
return 0;
} else {
return winerr();
return __winerr();
}
}

View file

@ -36,5 +36,5 @@ textwindows int truncate$nt(const char *path, uint64_t length) {
CloseHandle(fh);
if (ok) return 0;
}
return winerr();
return __winerr();
}

View file

@ -27,6 +27,6 @@ textwindows int unlink$nt(const char *name) {
if (DeleteFile(name16)) {
return 0;
} else {
return winerr();
return __winerr();
}
}

View file

@ -48,7 +48,7 @@ textwindows int utimensat$nt(int dirfd, const char *path,
-1) {
closeme = true;
} else {
return winerr();
return __winerr();
}
} else {
return einval();
@ -77,7 +77,7 @@ textwindows int utimensat$nt(int dirfd, const char *path,
if (SetFileTime(fh, NULL, ftp[0], ftp[1])) {
rc = 0;
} else {
rc = winerr();
rc = __winerr();
}
if (closeme) {
CloseHandle(fh);

View file

@ -41,7 +41,7 @@ textwindows int wait4$nt(int pid, int *opt_out_wstatus, int options,
uint32_t i, count, timeout;
struct NtFileTime createfiletime, exitfiletime, kernelfiletime, userfiletime;
if (pid != -1) {
if (!isfdkind(pid, kFdProcess)) {
if (!__isfdkind(pid, kFdProcess)) {
return echild();
}
handles[0] = g_fds.p[pid].handle;
@ -67,8 +67,8 @@ textwindows int wait4$nt(int pid, int *opt_out_wstatus, int options,
} else {
i = WaitForMultipleObjects(count, handles, false, -1);
}
if (i == kNtWaitFailed) return winerr();
if (!GetExitCodeProcess(handles[i], &dwExitCode)) return winerr();
if (i == kNtWaitFailed) return __winerr();
if (!GetExitCodeProcess(handles[i], &dwExitCode)) return __winerr();
if (dwExitCode == kNtStillActive) continue;
if (opt_out_wstatus) { /* @see WEXITSTATUS() */
*opt_out_wstatus = (dwExitCode & 0xff) << 8;
@ -80,6 +80,8 @@ textwindows int wait4$nt(int pid, int *opt_out_wstatus, int options,
FileTimeToTimeVal(&opt_out_rusage->ru_utime, userfiletime);
FileTimeToTimeVal(&opt_out_rusage->ru_stime, kernelfiletime);
}
CloseHandle(g_fds.p[pids[i]].handle);
g_fds.p[pids[i]].kind = kFdEmpty;
return pids[i];
}
}

View file

@ -29,7 +29,7 @@
* @return -1 w/ few exceptions
* @note this is a code-size saving device
*/
privileged int64_t winerr(void) {
privileged int64_t __winerr(void) {
if (IsWindows()) {
errno = GetLastError();
return -1;

View file

@ -46,6 +46,6 @@ textwindows ssize_t write$nt(struct Fd *fd, const struct iovec *iov,
FlushFileBuffers(fd->handle);
return wrote;
} else {
return winerr();
return __winerr();
}
}

View file

@ -17,15 +17,8 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/assert.h"
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/iovec.h"
#include "libc/dce.h"
#include "libc/sock/internal.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.h"
#include "libc/sock/sock.h"
/**
* Writes data to file descriptor.
@ -39,34 +32,5 @@
* @asyncsignalsafe
*/
ssize_t write(int fd, const void *buf, size_t size) {
ssize_t rc;
size_t wrote;
if (fd == -1) return einval();
if (isfdkind(fd, kFdZip)) {
rc = weaken(__zipos_write)(
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle,
(struct iovec[]){{buf, size}}, 1, -1);
} else if (!IsWindows()) {
rc = write$sysv(fd, buf, size);
} else if (isfdkind(fd, kFdSocket)) {
rc = weaken(sendto$nt)(&g_fds.p[fd], (struct iovec[]){{buf, size}}, 1, 0,
NULL, 0);
} else if (isfdkind(fd, kFdFile) || isfdkind(fd, kFdConsole)) {
rc = write$nt(&g_fds.p[fd], (struct iovec[]){{buf, size}}, 1, -1);
} else {
return ebadf();
}
if (rc != -1) {
wrote = (size_t)rc;
if (wrote == 0) {
assert(size == 0);
} else {
assert(wrote <= size);
}
}
if (!IsTrustworthy() && rc != -1) {
if (!rc && size) abort();
if ((size_t)rc > size) abort();
}
return rc;
return writev(fd, &(struct iovec){buf, size}, 1);
}

View file

@ -17,16 +17,18 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/stdio/internal.h"
#include "libc/stdio/stdio.h"
#include "ape/lib/pc.h"
#include "libc/calls/internal.h"
#include "libc/nexgen32e/uart.internal.h"
int __getc_moar(FILE *f) {
int b;
if (f->beg == f->end) {
if (!f->reader) return fseteof(f);
if (f->reader(f) == -1) return -1;
ssize_t 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");
outb(fd->handle, ((char *)iov[i].iov_base)[j]);
++wrote;
}
}
b = f->buf[f->beg];
f->beg = (f->beg + 1) & (f->size - 1);
return b;
return wrote;
}

View file

@ -22,7 +22,7 @@
#include "libc/calls/internal.h"
#include "libc/sock/internal.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.h"
#include "libc/zipos/zipos.internal.h"
/**
* Writes data from multiple buffers.
@ -35,19 +35,19 @@
* @return number of bytes actually handed off, or -1 w/ errno
*/
ssize_t writev(int fd, const struct iovec *iov, int iovlen) {
if (!IsTrustworthy()) {
if (fd == -1) return einval();
if (iovlen < 0) return einval();
}
if (isfdkind(fd, kFdZip)) {
if (fd < 0) return einval();
if (iovlen < 0) return einval();
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
return weaken(__zipos_write)(
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, -1);
}
if (!IsWindows()) {
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdSerial) {
return writev$serial(&g_fds.p[fd], iov, iovlen);
} else if (!IsWindows()) {
return writev$sysv(fd, iov, iovlen);
} else if (isfdkind(fd, kFdFile) || isfdkind(fd, kFdConsole)) {
} else if (fd < g_fds.n &&
(g_fds.p[fd].kind == kFdFile || g_fds.p[fd].kind == kFdConsole)) {
return write$nt(&g_fds.p[fd], iov, iovlen, -1);
} else if (isfdkind(fd, kFdSocket)) {
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdSocket) {
return weaken(sendto$nt)(&g_fds.p[fd], iov, iovlen, 0, NULL, 0);
} else {
return ebadf();

View file

@ -82,7 +82,7 @@ textwindows int getntnameservers(struct ResolvConf *resolv) {
}
}
} else {
rc = winerr();
rc = __winerr();
}
RegCloseKey(hkInterfaces);
return rc;

View file

@ -24,7 +24,8 @@ int vsprintf(char *, const char *, va_list)
paramsnonnull((2)) nothrow nocallback frownedupon(vsnprintf);
int sscanf(const char *, const char *, ...) scanfesque(2);
int vsscanf(const char *, const char *, va_list);
int vcscanf(int callback(void *), void *, const char *, va_list);
int vcscanf(int (*)(void *), int (*)(int, void *), void *, const char *,
va_list);
char *strerror(int) returnsnonnull nothrow nocallback;
int strerror_r(int, char *, size_t) nothrow nocallback;
int palandprintf(void *, void *, const char *, va_list) hidden;

View file

@ -44,7 +44,8 @@
* @param va points to the variadic argument state
* @see libc/fmt/pflink.h (dynamic memory is not a requirement)
*/
int vcscanf(int callback(void *), void *arg, const char *fmt, va_list va) {
int vcscanf(int callback(void *), int unget(int, void *), void *arg,
const char *fmt, va_list va) {
struct FreeMe {
struct FreeMe *next;
void *ptr;
@ -56,13 +57,18 @@ int vcscanf(int callback(void *), void *arg, const char *fmt, va_list va) {
while (c != -1) {
switch (p[i++]) {
case '\0':
return items;
if (c != -1 && unget) {
unget(c, arg);
}
goto Done;
case ' ':
case '\t':
case '\n':
case '\r':
case '\v':
while (isspace(c)) c = callback(arg);
while (isspace(c)) {
c = callback(arg);
}
break;
case '%': {
uintmax_t number;

View file

@ -47,5 +47,5 @@ static int vsscanfcb(void *arg) {
*/
int(vsscanf)(const char *str, const char *fmt, va_list va) {
struct StringScannerState state = {(const unsigned char *)str, 0};
return vcscanf(vsscanfcb, &state, fmt, va);
return vcscanf(vsscanfcb, NULL, &state, fmt, va);
}

View file

@ -100,71 +100,72 @@
#define PKAFFINITY KAFFINITY*
#define KPRIORITY LONG
#define PWCHAR WCHAR*
#define LPWCH WCHAR*
#define PWCH WCHAR*
#define LPCWCH CONST WCHAR*
#define PCWCH CONST WCHAR*
#define NWPSTR WCHAR*
#define LPWSTR WCHAR*
#define PWSTR WCHAR*
#define PZPWSTR PWSTR*
#define PCZPWSTR CONST PWSTR*
#define LPUWSTR WCHAR aligned(1)*
#define PUWSTR WCHAR aligned(1)*
#define LPCWSTR CONST WCHAR*
#define PCWSTR CONST WCHAR*
#define PZPCWSTR PCWSTR*
#define LPCUWSTR CONST WCHAR aligned(1)*
#define PCUWSTR CONST WCHAR aligned(1)*
#define PCHAR CHAR*
#define LPCH CHAR*
#define PCH CHAR*
#define LPCCH CONST CHAR*
#define PCCH CONST CHAR*
#define NPSTR CHAR*
#define LPSTR CHAR*
#define PSTR CHAR*
#define PZPSTR PSTR*
#define PCZPSTR CONST PSTR*
#define LPCSTR CONST CHAR*
#define PCSTR CONST CHAR*
#define PZPCSTR PCSTR*
#define TCHAR WCHAR
#define PTCHAR WCHAR*
#define TBYTE WCHAR
#define PTBYTE WCHAR*
#define LPTCH LPWSTR
#define PTCH LPWSTR
#define PTSTR LPWSTR
#define LPTSTR LPWSTR
#define PCTSTR LPCWSTR
#define LPCTSTR LPCWSTR
#define PUTSTR LPUWSTR
#define LPUTSTR LPUWSTR
#define PCUTSTR LPCUWSTR
#define LPCUTSTR LPCUWSTR
#define LP LPWSTR
#define PSHORT int16_t*
#define PLONG int32_t*
#define HANDLE int64_t
#define PHANDLE HANDLE*
#define FCHAR BYTE
#define FSHORT WORD
#define FLONG DWORD
#define HRESULT LONG
#define CCHAR char
#define LCID DWORD
#define PLCID PDWORD
#define LANGID WORD
#define LONGLONG int64_t
#define ULONGLONG uint64_t
#define USN LONGLONG
#define PLONGLONG LONGLONG*
#define PULONGLONG ULONGLONG*
#define DWORDLONG ULONGLONG
#define PDWORDLONG DWORDLONG*
#define LARGE_INTEGER int64_t
#define PWCHAR WCHAR*
#define LPWCH WCHAR*
#define PWCH WCHAR*
#define LPCWCH CONST WCHAR*
#define PCWCH CONST WCHAR*
#define NWPSTR WCHAR*
#define LPWSTR WCHAR*
#define PWSTR WCHAR*
#define PZPWSTR PWSTR*
#define PCZPWSTR CONST PWSTR*
#define LPUWSTR WCHAR aligned(1)*
#define PUWSTR WCHAR aligned(1)*
#define LPCWSTR CONST WCHAR*
#define PCWSTR CONST WCHAR*
#define PZPCWSTR PCWSTR*
#define LPCUWSTR CONST WCHAR aligned(1)*
#define PCUWSTR CONST WCHAR aligned(1)*
#define PCHAR CHAR*
#define LPCH CHAR*
#define PCH CHAR*
#define LPCCH CONST CHAR*
#define PCCH CONST CHAR*
#define NPSTR CHAR*
#define LPSTR CHAR*
#define PSTR CHAR*
#define PZPSTR PSTR*
#define PCZPSTR CONST PSTR*
#define LPCSTR CONST CHAR*
#define PCSTR CONST CHAR*
#define PZPCSTR PCSTR*
#define TCHAR WCHAR
#define PTCHAR WCHAR*
#define TBYTE WCHAR
#define PTBYTE WCHAR*
#define LPTCH LPWSTR
#define PTCH LPWSTR
#define PTSTR LPWSTR
#define LPTSTR LPWSTR
#define PCTSTR LPCWSTR
#define LPCTSTR LPCWSTR
#define PUTSTR LPUWSTR
#define LPUTSTR LPUWSTR
#define PCUTSTR LPCUWSTR
#define LPCUTSTR LPCUWSTR
#define LP LPWSTR
#define PSHORT int16_t*
#define PLONG int32_t*
#define HANDLE int64_t
#define PHANDLE HANDLE*
#define FCHAR BYTE
#define FSHORT WORD
#define FLONG DWORD
#define HRESULT LONG
#define CCHAR char
#define LCID DWORD
#define PLCID PDWORD
#define LANGID WORD
#define LONGLONG int64_t
#define ULONGLONG uint64_t
#define USN LONGLONG
#define PLONGLONG LONGLONG*
#define PULONGLONG ULONGLONG*
#define DWORDLONG ULONGLONG
#define PDWORDLONG DWORDLONG*
#define LARGE_INTEGER int64_t
#define PLARGE_INTEGER int64_t*
#define ULONG uint32_t
#define PULONG ULONG*
@ -1273,9 +1274,9 @@
#define WSAPROTOCOL_INFO struct NtWsaProtocolInfo
#define LPWSAPROTOCOL_INFO struct NtWsaProtocolInfo*
#define _WSABUF iovec$nt
#define WSABUF struct iovec$nt
#define LPWSABUF struct iovec$nt*
#define _WSABUF NtIovec
#define WSABUF struct NtIovec
#define LPWSABUF struct NtIovec*
#define _GUID NtGuid
#define GUID struct NtGuid
@ -1320,9 +1321,9 @@
#define SD_SEND SHUT_WR
#define SD_BOTH SHUT_RDWR
#define WSAMSG struct msghdr$nt
#define PWSAMSG struct msghdr$nt*
#define LPWSAMSG struct msghdr$nt*
#define WSAMSG struct NtMsgHdr
#define PWSAMSG struct NtMsgHdr*
#define LPWSAMSG struct NtMsgHdr*
#define _MEMORYSTATUSEX NtMemoryStatusEx
#define MEMORYSTATUSEX struct NtMemoryStatusEx

View file

@ -4,7 +4,7 @@
PKGS += LIBC
LIBC_HDRS = $(filter %.h,$(LIBC_FILES))
LIBC_FILES := $(wildcard libc/*) $(wildcard libc/internal/*)
LIBC_FILES := $(wildcard libc/*)
LIBC_CHECKS = $(LIBC_HDRS:%=o/$(MODE)/%.ok)
.PHONY: o/$(MODE)/libc

View file

@ -1,24 +1,7 @@
#ifndef COSMOPOLITAN_LIBC_NEXGEN32E_UART_H_
#define COSMOPOLITAN_LIBC_NEXGEN32E_UART_H_
/**
* @fileoverview PC Serial Line Helpers (8250 UART 16550+).
*
* <p>These functions provide the baseline of PC telecommunications
* support that doesn't require switching context or cpu mode.
*
* <p>Example use cases:
* <ul>
* <li>Qemu stdio
* <li>Bare metal stdio
* <li>FIPS-170-2 SSH alternative
* <li>NIC for key-signing servers
* </ul>
*
* @see www.lammertbies.nl/comm/info/serial-uart.html
*/
#define COM1 0x0 /* offset in pc bios data area with port number (0x400) */
#define COM1 0x0
#define COM2 0x2
#define COM3 0x4
#define COM4 0x6
@ -40,16 +23,4 @@
#define UART_TTYIDL (1 << 6) /* serial thr empty and line idle */
#define UART_TTYEDF (1 << 7) /* erroneous data in fifo */
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
void sinit(unsigned short *ports, unsigned count, const char *config);
void sputc(unsigned char ch, int port);
int sgetc(int port);
void sputs(const char *s, int port);
void sflush(unsigned short *ports, unsigned count);
unsigned char slsr(int port);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_NEXGEN32E_UART_H_ */

View file

@ -0,0 +1,15 @@
.include "o/libc/nt/codegen.inc"
.imp KernelBase,__imp_AcquireSRWLockExclusive,AcquireSRWLockExclusive,683
.text.windows
AcquireSRWLockExclusive:
push %rbp
mov %rsp,%rbp
.profilable
mov %rdi,%rcx
sub $32,%rsp
call *__imp_AcquireSRWLockExclusive(%rip)
leave
ret
.endfn AcquireSRWLockExclusive,globl
.previous

View file

@ -0,0 +1,15 @@
.include "o/libc/nt/codegen.inc"
.imp KernelBase,__imp_AcquireSRWLockShared,AcquireSRWLockShared,684
.text.windows
AcquireSRWLockShared:
push %rbp
mov %rsp,%rbp
.profilable
mov %rdi,%rcx
sub $32,%rsp
call *__imp_AcquireSRWLockShared(%rip)
leave
ret
.endfn AcquireSRWLockShared,globl
.previous

View file

@ -0,0 +1,15 @@
.include "o/libc/nt/codegen.inc"
.imp KernelBase,__imp_DeleteCriticalSection,DeleteCriticalSection,0
.text.windows
DeleteCriticalSection:
push %rbp
mov %rsp,%rbp
.profilable
mov %rdi,%rcx
sub $32,%rsp
call *__imp_DeleteCriticalSection(%rip)
leave
ret
.endfn DeleteCriticalSection,globl
.previous

View file

@ -0,0 +1,15 @@
.include "o/libc/nt/codegen.inc"
.imp KernelBase,__imp_EnterCriticalSection,EnterCriticalSection,0
.text.windows
EnterCriticalSection:
push %rbp
mov %rsp,%rbp
.profilable
mov %rdi,%rcx
sub $32,%rsp
call *__imp_EnterCriticalSection(%rip)
leave
ret
.endfn EnterCriticalSection,globl
.previous

View file

@ -1,2 +1,14 @@
.include "o/libc/nt/codegen.inc"
.imp KernelBase,__imp_GetTickCount64,GetTickCount64,780
.text.windows
GetTickCount64:
push %rbp
mov %rsp,%rbp
.profilable
sub $32,%rsp
call *__imp_GetTickCount64(%rip)
leave
ret
.endfn GetTickCount64,globl
.previous

View file

@ -0,0 +1,15 @@
.include "o/libc/nt/codegen.inc"
.imp KernelBase,__imp_InitializeCriticalSection,InitializeCriticalSection,0
.text.windows
InitializeCriticalSection:
push %rbp
mov %rsp,%rbp
.profilable
mov %rdi,%rcx
sub $32,%rsp
call *__imp_InitializeCriticalSection(%rip)
leave
ret
.endfn InitializeCriticalSection,globl
.previous

View file

@ -1,5 +1,5 @@
.include "o/libc/nt/codegen.inc"
.imp KernelBase,__imp_InitializeCriticalSectionAndSpinCount,InitializeCriticalSectionAndSpinCount,856
.imp KernelBase,__imp_InitializeCriticalSectionAndSpinCount,InitializeCriticalSectionAndSpinCount,0
.text.windows
InitializeCriticalSectionAndSpinCount:

View file

@ -0,0 +1,15 @@
.include "o/libc/nt/codegen.inc"
.imp KernelBase,__imp_InitializeSRWLock,InitializeSRWLock,1128
.text.windows
InitializeSRWLock:
push %rbp
mov %rsp,%rbp
.profilable
mov %rdi,%rcx
sub $32,%rsp
call *__imp_InitializeSRWLock(%rip)
leave
ret
.endfn InitializeSRWLock,globl
.previous

View file

@ -0,0 +1,15 @@
.include "o/libc/nt/codegen.inc"
.imp KernelBase,__imp_LeaveCriticalSection,LeaveCriticalSection,0
.text.windows
LeaveCriticalSection:
push %rbp
mov %rsp,%rbp
.profilable
mov %rdi,%rcx
sub $32,%rsp
call *__imp_LeaveCriticalSection(%rip)
leave
ret
.endfn LeaveCriticalSection,globl
.previous

View file

@ -0,0 +1,15 @@
.include "o/libc/nt/codegen.inc"
.imp KernelBase,__imp_ReleaseSRWLockExclusive,ReleaseSRWLockExclusive,1341
.text.windows
ReleaseSRWLockExclusive:
push %rbp
mov %rsp,%rbp
.profilable
mov %rdi,%rcx
sub $32,%rsp
call *__imp_ReleaseSRWLockExclusive(%rip)
leave
ret
.endfn ReleaseSRWLockExclusive,globl
.previous

View file

@ -0,0 +1,15 @@
.include "o/libc/nt/codegen.inc"
.imp KernelBase,__imp_ReleaseSRWLockShared,ReleaseSRWLockShared,1342
.text.windows
ReleaseSRWLockShared:
push %rbp
mov %rsp,%rbp
.profilable
mov %rdi,%rcx
sub $32,%rsp
call *__imp_ReleaseSRWLockShared(%rip)
leave
ret
.endfn ReleaseSRWLockShared,globl
.previous

View file

@ -0,0 +1,12 @@
.include "o/libc/nt/codegen.inc"
.imp KernelBase,__imp_SetCriticalSectionSpinCount,SetCriticalSectionSpinCount,0
.text.windows
SetCriticalSectionSpinCount:
push %rbp
mov %rsp,%rbp
.profilable
mov __imp_SetCriticalSectionSpinCount(%rip),%rax
jmp __sysv2nt
.endfn SetCriticalSectionSpinCount,globl
.previous

View file

@ -0,0 +1,15 @@
.include "o/libc/nt/codegen.inc"
.imp KernelBase,__imp_TryAcquireSRWLockExclusive,TryAcquireSRWLockExclusive,1467
.text.windows
TryAcquireSRWLockExclusive:
push %rbp
mov %rsp,%rbp
.profilable
mov %rdi,%rcx
sub $32,%rsp
call *__imp_TryAcquireSRWLockExclusive(%rip)
leave
ret
.endfn TryAcquireSRWLockExclusive,globl
.previous

View file

@ -0,0 +1,15 @@
.include "o/libc/nt/codegen.inc"
.imp KernelBase,__imp_TryAcquireSRWLockShared,TryAcquireSRWLockShared,1468
.text.windows
TryAcquireSRWLockShared:
push %rbp
mov %rsp,%rbp
.profilable
mov %rdi,%rcx
sub $32,%rsp
call *__imp_TryAcquireSRWLockShared(%rip)
leave
ret
.endfn TryAcquireSRWLockShared,globl
.previous

View file

@ -0,0 +1,15 @@
.include "o/libc/nt/codegen.inc"
.imp KernelBase,__imp_TryEnterCriticalSection,TryEnterCriticalSection,0
.text.windows
TryEnterCriticalSection:
push %rbp
mov %rsp,%rbp
.profilable
mov %rdi,%rcx
sub $32,%rsp
call *__imp_TryEnterCriticalSection(%rip)
leave
ret
.endfn TryEnterCriticalSection,globl
.previous

13
libc/nt/enum/afd.h Normal file
View file

@ -0,0 +1,13 @@
#ifndef COSMOPOLITAN_LIBC_NT_ENUM_AFD_H_
#define COSMOPOLITAN_LIBC_NT_ENUM_AFD_H_
#define kNtAfdPollReceive 0x0001
#define kNtAfdPollReceiveExpedited 0x0002
#define kNtAfdPollSend 0x0004
#define kNtAfdPollDisconnect 0x0008
#define kNtAfdPollAbort 0x0010
#define kNtAfdPollLocalClose 0x0020
#define kNtAfdPollAccept 0x0080
#define kNtAfdPollConnectFail 0x0100
#endif /* COSMOPOLITAN_LIBC_NT_ENUM_AFD_H_ */

View file

@ -1,13 +1,12 @@
#ifndef COSMOPOLITAN_LIBC_NT_ENUM_FILEMAPFLAGS_H_
#define COSMOPOLITAN_LIBC_NT_ENUM_FILEMAPFLAGS_H_
/* Choose subset of NtPageFlags passed earlier. */
#define kNtFileMapCopy 0x00000001u
#define kNtFileMapWrite 0x00000002u
#define kNtFileMapRead 0x00000004u
#define kNtFileMapExecute 0x00000020u
#define kNtFileMapReserve 0x80000000u
#define kNtFileMapCopy 0x00000001u
#define kNtFileMapWrite 0x00000002u
#define kNtFileMapRead 0x00000004u
#define kNtFileMapExecute 0x00000020u
#define kNtFileMapReserve 0x80000000u
#define kNtFileMapTargetsInvalid 0x40000000u
#define kNtFileMapLargePages 0x20000000u
#define kNtFileMapLargePages 0x20000000u
#endif /* COSMOPOLITAN_LIBC_NT_ENUM_FILEMAPFLAGS_H_ */

View file

@ -2,5 +2,6 @@
#define COSMOPOLITAN_LIBC_NT_ENUM_IOCTL_H_
#define kNtIoctlDiskGetDriveGeometry 0x00070000u
#define kNtIoctlAfdPoll 0x00012024u
#endif /* COSMOPOLITAN_LIBC_NT_ENUM_IOCTL_H_ */

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