Rewrite special file handling on Windows

This change gets GNU grep working. What caused it to not work, is it
wouldn't write to an output file descriptor when its dev/ino equaled
/dev/null's. So now we invent special dev/ino values for these files
This commit is contained in:
Justine Tunney 2023-10-14 01:06:00 -07:00
parent aca2261cda
commit 2db2f40a98
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
53 changed files with 485 additions and 299 deletions

View file

@ -18,8 +18,8 @@
*/
#include "libc/assert.h"
#include "libc/calls/internal.h"
#include "libc/calls/ntmagicpaths.internal.h"
#include "libc/calls/state.internal.h"
#include "libc/calls/struct/sigset.internal.h"
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/errno.h"
@ -131,24 +131,13 @@ static textwindows int64_t sys_open_nt_impl(int dirfd, const char *path,
return __fix_enotdir(hand, path16);
}
static textwindows int sys_open_nt_console(int dirfd,
const struct NtMagicPaths *mp,
uint32_t flags, int32_t mode,
size_t fd) {
g_fds.p[fd].kind = kFdConsole;
g_fds.p[fd].flags = flags;
g_fds.p[fd].mode = mode;
g_fds.p[fd].handle =
CreateFile(u"CONIN$", kNtGenericRead | kNtGenericWrite, kNtFileShareRead,
&kNtIsInheritable, kNtOpenExisting, 0, 0);
return fd;
}
static textwindows int sys_open_nt_file(int dirfd, const char *file,
uint32_t flags, int32_t mode,
size_t fd) {
if ((g_fds.p[fd].handle = sys_open_nt_impl(dirfd, file, flags, mode,
kNtFileFlagOverlapped)) != -1) {
int64_t handle;
if ((handle = sys_open_nt_impl(dirfd, file, flags, mode,
kNtFileFlagOverlapped)) != -1) {
g_fds.p[fd].handle = handle;
g_fds.p[fd].kind = kFdFile;
g_fds.p[fd].flags = flags;
g_fds.p[fd].mode = mode;
@ -158,15 +147,61 @@ static textwindows int sys_open_nt_file(int dirfd, const char *file,
}
}
static textwindows int sys_open_nt_special(int fd, int flags, int mode,
int kind, const char16_t *name) {
g_fds.p[fd].kind = kind;
g_fds.p[fd].mode = mode;
g_fds.p[fd].flags = flags;
g_fds.p[fd].handle = CreateFile(name, kNtGenericRead | kNtGenericWrite,
kNtFileShareRead | kNtFileShareWrite,
&kNtIsInheritable, kNtOpenExisting, 0, 0);
return fd;
}
static textwindows int sys_open_nt_dup(int fd, int flags, int mode, int oldfd) {
int64_t handle;
if (!__isfdopen(oldfd)) {
return enoent();
}
if (DuplicateHandle(GetCurrentProcess(), g_fds.p[oldfd].handle,
GetCurrentProcess(), &handle, 0, true,
kNtDuplicateSameAccess)) {
g_fds.p[fd] = g_fds.p[oldfd];
g_fds.p[fd].handle = handle;
g_fds.p[fd].mode = mode;
if (!sys_fcntl_nt_setfl(fd, flags)) {
return fd;
} else {
CloseHandle(handle);
return -1;
}
} else {
return __winerr();
}
}
textwindows int sys_open_nt(int dirfd, const char *file, uint32_t flags,
int32_t mode) {
int fd;
ssize_t rc;
BLOCK_SIGNALS;
__fds_lock();
if (!(flags & O_CREAT)) mode = 0;
if ((rc = fd = __reservefd_unlocked(-1)) != -1) {
if (!strcmp(file, kNtMagicPaths.devtty)) {
rc = sys_open_nt_console(dirfd, &kNtMagicPaths, flags, mode, fd);
if (startswith(file, "/dev/")) {
if (!strcmp(file + 5, "tty")) {
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, "stdin")) {
rc = sys_open_nt_dup(fd, flags, mode, STDIN_FILENO);
} else if (!strcmp(file + 5, "stdout")) {
rc = sys_open_nt_dup(fd, flags, mode, STDOUT_FILENO);
} else if (!strcmp(file + 5, "stderr")) {
rc = sys_open_nt_dup(fd, flags, mode, STDERR_FILENO);
} else {
rc = enoent();
}
} else {
rc = sys_open_nt_file(dirfd, file, flags, mode, fd);
}
@ -175,5 +210,6 @@ textwindows int sys_open_nt(int dirfd, const char *file, uint32_t flags,
}
__fds_unlock();
}
ALLOW_SIGNALS;
return rc;
}