mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-03-02 23:18:44 +00:00
Add /dev/(u)random on NT (#1163)
This commit is contained in:
parent
8f6bc9dabc
commit
b6e40a3a58
17 changed files with 97 additions and 22 deletions
|
@ -332,7 +332,8 @@ textwindows int sys_fcntl_nt(int fd, int cmd, uintptr_t arg) {
|
|||
if (__isfdkind(fd, kFdFile) || //
|
||||
__isfdkind(fd, kFdSocket) || //
|
||||
__isfdkind(fd, kFdConsole) || //
|
||||
__isfdkind(fd, kFdDevNull)) {
|
||||
__isfdkind(fd, kFdDevNull) || //
|
||||
__isfdkind(fd, kFdDevRandom)) {
|
||||
if (cmd == F_GETFL) {
|
||||
rc = g_fds.p[fd].flags & (O_ACCMODE | _O_APPEND | _O_DIRECT |
|
||||
_O_NONBLOCK | _O_RANDOM | _O_SEQUENTIAL);
|
||||
|
|
|
@ -104,6 +104,7 @@ textwindows int sys_fstat_nt(int fd, struct stat *st) {
|
|||
return ebadf();
|
||||
case kFdConsole:
|
||||
case kFdDevNull:
|
||||
case kFdDevRandom:
|
||||
return sys_fstat_nt_special(g_fds.p[fd].kind, st);
|
||||
case kFdSocket:
|
||||
return sys_fstat_nt_socket(g_fds.p[fd].kind, st);
|
||||
|
|
|
@ -59,6 +59,8 @@ textwindows int sys_fstatat_nt(int dirfd, const char *path, struct stat *st,
|
|||
return sys_fstat_nt_special(kFdConsole, st);
|
||||
} else if (!strcmp(path + 5, "null")) {
|
||||
return sys_fstat_nt_special(kFdDevNull, st);
|
||||
} else if (!strcmp(path + 5, "random") || !strcmp(path + 5, "urandom")) {
|
||||
return sys_fstat_nt_special(kFdDevRandom, st);
|
||||
} else if (!strcmp(path + 5, "stdin")) {
|
||||
return sys_fstat_nt(STDIN_FILENO, st);
|
||||
} else if (!strcmp(path + 5, "stdout")) {
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include "libc/calls/termios.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/serialize.h"
|
||||
#include "libc/intrin/cmpxchg.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
|
@ -42,6 +41,7 @@
|
|||
#include "libc/nt/winsock.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/stack.h"
|
||||
#include "libc/serialize.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/struct/ifconf.h"
|
||||
#include "libc/sock/struct/ifreq.h"
|
||||
|
@ -66,7 +66,7 @@ static struct HostAdapterInfoNode {
|
|||
struct sockaddr netmask;
|
||||
struct sockaddr broadcast;
|
||||
short flags;
|
||||
} *__hostInfo;
|
||||
} * __hostInfo;
|
||||
|
||||
static int ioctl_default(int fd, unsigned long request, void *arg) {
|
||||
int rc;
|
||||
|
@ -107,8 +107,9 @@ static int ioctl_fionread(int fd, uint32_t *arg) {
|
|||
*arg = MAX(0, bytes);
|
||||
return 0;
|
||||
} else if (g_fds.p[fd].kind == kFdDevNull) {
|
||||
*arg = 1;
|
||||
return 0;
|
||||
return enotty();
|
||||
} else if (g_fds.p[fd].kind == kFdDevRandom) {
|
||||
return einval();
|
||||
} else if (GetFileType(handle) == kNtFileTypePipe) {
|
||||
uint32_t avail;
|
||||
if (PeekNamedPipe(handle, 0, 0, 0, &avail, 0)) {
|
||||
|
|
|
@ -55,6 +55,7 @@ bool32 ischardev(int fd) {
|
|||
}
|
||||
} else {
|
||||
return __isfdkind(fd, kFdConsole) || __isfdkind(fd, kFdDevNull) ||
|
||||
__isfdkind(fd, kFdDevRandom) ||
|
||||
(__isfdkind(fd, kFdFile) &&
|
||||
GetFileType(g_fds.p[fd].handle) == kNtFileTypeChar);
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ static textwindows int64_t Seek(struct Fd *f, int64_t offset, int whence) {
|
|||
}
|
||||
|
||||
textwindows int64_t sys_lseek_nt(int fd, int64_t offset, int whence) {
|
||||
if (__isfdkind(fd, kFdDevNull)) {
|
||||
if (__isfdkind(fd, kFdDevNull) || __isfdkind(fd, kFdDevRandom)) {
|
||||
return offset;
|
||||
} else if (__isfdkind(fd, kFdFile)) {
|
||||
struct Fd *f = g_fds.p + fd;
|
||||
|
|
|
@ -159,6 +159,15 @@ static textwindows int sys_open_nt_special(int fd, int flags, int mode,
|
|||
return fd;
|
||||
}
|
||||
|
||||
static textwindows int sys_open_nt_no_handle(int fd, int flags, int mode,
|
||||
int kind) {
|
||||
g_fds.p[fd].kind = kind;
|
||||
g_fds.p[fd].mode = mode;
|
||||
g_fds.p[fd].flags = flags;
|
||||
g_fds.p[fd].handle = -1;
|
||||
return fd;
|
||||
}
|
||||
|
||||
static textwindows int sys_open_nt_dup(int fd, int flags, int mode, int oldfd) {
|
||||
int64_t handle;
|
||||
if (!__isfdopen(oldfd)) {
|
||||
|
@ -211,6 +220,8 @@ textwindows int sys_open_nt(int dirfd, const char *file, uint32_t flags,
|
|||
rc = sys_open_nt_special(fd, flags, mode, kFdConsole, u"CONIN$");
|
||||
} else if (!strcmp(file + 5, "null")) {
|
||||
rc = sys_open_nt_special(fd, flags, mode, kFdDevNull, u"NUL");
|
||||
} else if (!strcmp(file + 5, "urandom") || !strcmp(file + 5, "random")) {
|
||||
rc = sys_open_nt_no_handle(fd, flags, mode, kFdDevRandom);
|
||||
} else if (!strcmp(file + 5, "stdin")) {
|
||||
rc = sys_open_nt_dup(fd, flags, mode, STDIN_FILENO);
|
||||
} else if (!strcmp(file + 5, "stdout")) {
|
||||
|
|
|
@ -72,7 +72,8 @@ ssize_t pread(int fd, void *buf, size_t size, int64_t offset) {
|
|||
rc = sys_pread(fd, buf, size, offset, offset);
|
||||
} else if (__isfdkind(fd, kFdSocket)) {
|
||||
rc = espipe();
|
||||
} else if (__isfdkind(fd, kFdFile) || __isfdkind(fd, kFdDevNull)) {
|
||||
} else if (__isfdkind(fd, kFdFile) || __isfdkind(fd, kFdDevNull) ||
|
||||
__isfdkind(fd, kFdDevRandom)) {
|
||||
rc = sys_read_nt(fd, (struct iovec[]){{buf, size}}, 1, offset);
|
||||
} else {
|
||||
rc = ebadf();
|
||||
|
|
|
@ -40,6 +40,8 @@ static const char *__fdkind2str(int x) {
|
|||
return "kFdZip";
|
||||
case kFdEpoll:
|
||||
return "kFdEpoll";
|
||||
case kFdDevRandom:
|
||||
return "kFdRandom";
|
||||
default:
|
||||
return "kFdWut";
|
||||
}
|
||||
|
|
|
@ -65,7 +65,8 @@ ssize_t pwrite(int fd, const void *buf, size_t size, int64_t offset) {
|
|||
rc = sys_pwrite(fd, buf, size, offset, offset);
|
||||
} else if (__isfdkind(fd, kFdSocket)) {
|
||||
rc = espipe();
|
||||
} else if (__isfdkind(fd, kFdFile) || __isfdkind(fd, kFdDevNull)) {
|
||||
} else if (__isfdkind(fd, kFdFile) || __isfdkind(fd, kFdDevNull) ||
|
||||
__isfdkind(fd, kFdDevRandom)) {
|
||||
rc = sys_write_nt(fd, (struct iovec[]){{(void *)buf, size}}, 1, offset);
|
||||
} else {
|
||||
return ebadf();
|
||||
|
|
|
@ -786,6 +786,10 @@ textwindows ssize_t ReadBuffer(int fd, void *data, size_t size, int64_t offset,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (f->kind == kFdDevRandom) {
|
||||
return ProcessPrng(data, size) ? size : __winerr();
|
||||
}
|
||||
|
||||
if (f->kind == kFdConsole) {
|
||||
return ReadFromConsole(f, data, size, waitmask);
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ textwindows ssize_t sys_readv_nt(int fd, const struct iovec *iov, int iovlen) {
|
|||
case kFdFile:
|
||||
case kFdConsole:
|
||||
case kFdDevNull:
|
||||
case kFdDevRandom:
|
||||
return sys_read_nt(fd, iov, iovlen, -1);
|
||||
case kFdSocket:
|
||||
return _weaken(sys_recv_nt)(fd, iov, iovlen, 0);
|
||||
|
|
|
@ -61,7 +61,7 @@ sys_readwrite_nt(int fd, void *data, size_t size, ssize_t offset,
|
|||
bool pwriting = offset != -1;
|
||||
bool seekable =
|
||||
(f->kind == kFdFile && GetFileType(handle) == kNtFileTypeDisk) ||
|
||||
f->kind == kFdDevNull;
|
||||
f->kind == kFdDevNull || f->kind == kFdDevRandom;
|
||||
if (pwriting && !seekable) {
|
||||
return espipe();
|
||||
}
|
||||
|
|
|
@ -2,15 +2,16 @@
|
|||
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_FD_INTERNAL_H_
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#define kFdEmpty 0
|
||||
#define kFdFile 1
|
||||
#define kFdSocket 2
|
||||
#define kFdConsole 4
|
||||
#define kFdSerial 5
|
||||
#define kFdZip 6
|
||||
#define kFdEpoll 7
|
||||
#define kFdReserved 8
|
||||
#define kFdDevNull 9
|
||||
#define kFdEmpty 0
|
||||
#define kFdFile 1
|
||||
#define kFdSocket 2
|
||||
#define kFdConsole 4
|
||||
#define kFdSerial 5
|
||||
#define kFdZip 6
|
||||
#define kFdEpoll 7
|
||||
#define kFdReserved 8
|
||||
#define kFdDevNull 9
|
||||
#define kFdDevRandom 10
|
||||
|
||||
struct Fd {
|
||||
char kind;
|
||||
|
|
|
@ -52,6 +52,11 @@ static textwindows ssize_t sys_write_nt_impl(int fd, void *data, size_t size,
|
|||
struct Fd *f = g_fds.p + fd;
|
||||
bool isconsole = f->kind == kFdConsole;
|
||||
|
||||
// not implemented, XNU returns eperm();
|
||||
if (f->kind == kFdDevRandom) {
|
||||
return eperm();
|
||||
}
|
||||
|
||||
// determine win32 handle for writing
|
||||
int64_t handle = f->handle;
|
||||
if (isconsole && _weaken(GetConsoleOutputHandle)) {
|
||||
|
|
|
@ -28,6 +28,7 @@ textwindows ssize_t sys_writev_nt(int fd, const struct iovec *iov, int iovlen) {
|
|||
case kFdFile:
|
||||
case kFdConsole:
|
||||
case kFdDevNull:
|
||||
case kFdDevRandom:
|
||||
return sys_write_nt(fd, iov, iovlen, -1);
|
||||
case kFdSocket:
|
||||
return _weaken(sys_send_nt)(fd, iov, iovlen, 0);
|
||||
|
|
|
@ -20,15 +20,19 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
int pipefd[2];
|
||||
int stdoutBack;
|
||||
int allowMask;
|
||||
|
||||
void SetUpOnce(void) {
|
||||
testlib_enable_tmp_setup_teardown();
|
||||
// qemu-aarch64 defines o_largefile wrong
|
||||
allowMask = ~(O_LARGEFILE | 0x00008000);
|
||||
}
|
||||
|
||||
void CaptureStdout(void) {
|
||||
|
@ -46,8 +50,7 @@ void RestoreStdout(void) {
|
|||
|
||||
TEST(specialfile, devNull) {
|
||||
ASSERT_SYS(0, 3, creat("/dev/null", 0644));
|
||||
// qemu-aarch64 defines o_largefile wrong
|
||||
ASSERT_EQ(O_WRONLY, fcntl(3, F_GETFL) & ~(O_LARGEFILE | 0x00008000));
|
||||
ASSERT_EQ(O_WRONLY, fcntl(3, F_GETFL) & allowMask);
|
||||
ASSERT_SYS(0, 2, write(3, "hi", 2));
|
||||
ASSERT_SYS(0, 2, pwrite(3, "hi", 2, 0));
|
||||
ASSERT_SYS(0, 2, pwrite(3, "hi", 2, 2));
|
||||
|
@ -64,12 +67,51 @@ TEST(specialfile, devNull) {
|
|||
TEST(specialfile, devNullRead) {
|
||||
char buf[8] = {0};
|
||||
ASSERT_SYS(0, 3, open("/dev/null", O_RDONLY));
|
||||
// qemu-aarch64 defines o_largefile wrong
|
||||
ASSERT_EQ(O_RDONLY, fcntl(3, F_GETFL) & ~(O_LARGEFILE | 0x00008000));
|
||||
ASSERT_EQ(O_RDONLY, fcntl(3, F_GETFL) & allowMask);
|
||||
ASSERT_SYS(0, 0, read(3, buf, 8));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
TEST(specialfile, devRandomRead) {
|
||||
char buf[8] = {0};
|
||||
ASSERT_SYS(0, 3, open("/dev/random", O_RDONLY));
|
||||
ASSERT_EQ(O_RDONLY, fcntl(3, F_GETFL) & allowMask);
|
||||
ASSERT_SYS(0, 8, read(3, buf, 8));
|
||||
ASSERT_NE(0, memcmp(buf, " ", 8));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
TEST(specialfile, devUrandomRead) {
|
||||
char buf[8] = {0};
|
||||
ASSERT_SYS(0, 3, open("/dev/urandom", O_RDONLY));
|
||||
ASSERT_EQ(O_RDONLY, fcntl(3, F_GETFL) & allowMask);
|
||||
ASSERT_SYS(0, 8, read(3, buf, 8));
|
||||
ASSERT_NE(0, memcmp(buf, " ", 8));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
TEST(specialfile, devRandomWrite_fails_on_nt) {
|
||||
if (!IsWindows()) {
|
||||
return;
|
||||
}
|
||||
char buf[8] = {0};
|
||||
ASSERT_SYS(0, 3, creat("/dev/random", 0644));
|
||||
ASSERT_EQ(O_WRONLY, fcntl(3, F_GETFL) & allowMask);
|
||||
ASSERT_SYS(EPERM, -1, write(3, buf, 8));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
TEST(specialfile, devUrandomWrite_fails_on_nt) {
|
||||
if (!IsWindows()) {
|
||||
return;
|
||||
}
|
||||
char buf[8] = {0};
|
||||
ASSERT_SYS(0, 3, creat("/dev/urandom", 0644));
|
||||
ASSERT_EQ(O_WRONLY, fcntl(3, F_GETFL) & allowMask);
|
||||
ASSERT_SYS(EPERM, -1, write(3, buf, 8));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
TEST(specialfile, devStdout) {
|
||||
char buf[8] = {8};
|
||||
CaptureStdout();
|
||||
|
|
Loading…
Add table
Reference in a new issue