mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-14 06:59:10 +00:00
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:
parent
a9ea949df8
commit
3e4fd4b0ad
271 changed files with 5706 additions and 1365 deletions
|
@ -33,6 +33,6 @@ textwindows int chdir$nt(const char *path) {
|
|||
if (SetCurrentDirectory(path16)) {
|
||||
return 0;
|
||||
} else {
|
||||
return winerr();
|
||||
return __winerr();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
/*
|
||||
|
|
|
@ -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. */
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ textwindows char *getcwd$nt(char *buf, size_t size) {
|
|||
erange();
|
||||
}
|
||||
} else {
|
||||
winerr();
|
||||
__winerr();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -46,6 +46,6 @@ textwindows int getpriority$nt(int ignored) {
|
|||
}
|
||||
abort();
|
||||
} else {
|
||||
return winerr();
|
||||
return __winerr();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ static textwindows int copyfile$nt(const char *src, const char *dst,
|
|||
}
|
||||
return 0;
|
||||
} else {
|
||||
return winerr();
|
||||
return __winerr();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -78,7 +78,7 @@ textwindows int ntspawn(
|
|||
opt_out_lpProcessInformation)) {
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = winerr();
|
||||
rc = __winerr();
|
||||
}
|
||||
} else {
|
||||
rc = -1;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -60,7 +60,7 @@ int raise(int sig) {
|
|||
if (GenerateConsoleCtrlEvent(GetCtrlEvent(sig), 0)) {
|
||||
return 0;
|
||||
} else {
|
||||
return winerr();
|
||||
return __winerr();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
56
libc/calls/readv-serial.c
Normal file
56
libc/calls/readv-serial.c
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/lib/pc.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/nexgen32e/uart.internal.h"
|
||||
|
||||
static bool IsDataAvailable(struct Fd *fd) {
|
||||
return inb(fd->handle + UART_LSR) & UART_TTYDA;
|
||||
}
|
||||
|
||||
static int GetFirstIov(struct iovec *iov, int iovlen) {
|
||||
int i;
|
||||
for (i = 0; i < iovlen; ++i) {
|
||||
if (iov[i].iov_len) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,6 @@ textwindows int rmdir$nt(const char *path) {
|
|||
if (RemoveDirectory(path16)) {
|
||||
return 0;
|
||||
} else {
|
||||
return winerr();
|
||||
return __winerr();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -48,6 +48,6 @@ textwindows int setpriority$nt(int nice) {
|
|||
SetThreadPriority(GetCurrentThread(), p.wut)) {
|
||||
return p.nice;
|
||||
} else {
|
||||
return winerr();
|
||||
return __winerr();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,6 @@ textwindows int stat$nt(const char *path, struct stat *st) {
|
|||
CloseHandle(fh);
|
||||
return rc;
|
||||
} else {
|
||||
return winerr();
|
||||
return __winerr();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,6 @@ textwindows int sysinfo$nt(struct sysinfo *info) {
|
|||
info->mem_unit = 1;
|
||||
return 0;
|
||||
} else {
|
||||
return winerr();
|
||||
return __winerr();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,5 +36,5 @@ textwindows int truncate$nt(const char *path, uint64_t length) {
|
|||
CloseHandle(fh);
|
||||
if (ok) return 0;
|
||||
}
|
||||
return winerr();
|
||||
return __winerr();
|
||||
}
|
||||
|
|
|
@ -27,6 +27,6 @@ textwindows int unlink$nt(const char *name) {
|
|||
if (DeleteFile(name16)) {
|
||||
return 0;
|
||||
} else {
|
||||
return winerr();
|
||||
return __winerr();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
34
libc/calls/writev-serial.c
Normal file
34
libc/calls/writev-serial.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/lib/pc.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/nexgen32e/uart.internal.h"
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
return wrote;
|
||||
}
|
|
@ -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();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue