mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-24 19:40:28 +00:00
Make improvements
This commit is contained in:
parent
3e4fd4b0ad
commit
e44a0cf6f8
256 changed files with 23100 additions and 2294 deletions
|
@ -32,12 +32,12 @@
|
|||
* @asyncsignalsafe
|
||||
*/
|
||||
int access(const char *path, int mode) {
|
||||
char16_t path16[PATH_MAX];
|
||||
if (!path) return efault();
|
||||
if (!IsWindows()) {
|
||||
return faccessat$sysv(AT_FDCWD, path, mode, 0);
|
||||
} else {
|
||||
char16_t path16[PATH_MAX];
|
||||
if (mkntpath(path, path16) == -1) return -1;
|
||||
if (__mkntpath(path, path16) == -1) return -1;
|
||||
return ntaccesscheck(path16, mode);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
textwindows int chdir$nt(const char *path) {
|
||||
int len;
|
||||
char16_t path16[PATH_MAX];
|
||||
if ((len = mkntpath(path, path16)) == -1) return -1;
|
||||
if ((len = __mkntpath(path, path16)) == -1) return -1;
|
||||
if (path16[len - 1] != u'/' && path16[len - 1] != u'\\') {
|
||||
path16[len + 0] = u'/';
|
||||
path16[len + 1] = u'\0';
|
||||
|
|
|
@ -24,22 +24,15 @@
|
|||
|
||||
textwindows int close$nt(int fd) {
|
||||
bool32 ok;
|
||||
if (__isfdopen(fd)) {
|
||||
if (g_fds.p[fd].kind == kFdFile) {
|
||||
/*
|
||||
* Like Linux, closing a file on Windows doesn't guarantee it's
|
||||
* immediately synced to disk. But unlike Linux, this could cause
|
||||
* subsequent operations, e.g. unlink() to break w/ access error.
|
||||
*/
|
||||
FlushFileBuffers(g_fds.p[fd].handle);
|
||||
}
|
||||
ok = CloseHandle(g_fds.p[fd].handle);
|
||||
if (g_fds.p[fd].kind == kFdConsole) {
|
||||
ok &= CloseHandle(g_fds.p[fd].extra);
|
||||
}
|
||||
__removefd(fd);
|
||||
return ok ? 0 : __winerr();
|
||||
} else {
|
||||
return ebadf();
|
||||
if (g_fds.p[fd].kind == kFdFile) {
|
||||
/*
|
||||
* Like Linux, closing a file on Windows doesn't guarantee it's
|
||||
* immediately synced to disk. But unlike Linux, this could cause
|
||||
* subsequent operations, e.g. unlink() to break w/ access error.
|
||||
*/
|
||||
FlushFileBuffers(g_fds.p[fd].handle);
|
||||
}
|
||||
ok = CloseHandle(g_fds.p[fd].handle);
|
||||
if (g_fds.p[fd].kind == kFdConsole) ok &= CloseHandle(g_fds.p[fd].extra);
|
||||
return ok ? 0 : __winerr();
|
||||
}
|
||||
|
|
|
@ -43,7 +43,8 @@ int close(int fd) {
|
|||
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdSocket) {
|
||||
rc = weaken(closesocket$nt)(fd);
|
||||
} else if (fd < g_fds.n &&
|
||||
(g_fds.p[fd].kind == kFdFile || g_fds.p[fd].kind == kFdConsole)) {
|
||||
(g_fds.p[fd].kind == kFdFile || g_fds.p[fd].kind == kFdConsole ||
|
||||
g_fds.p[fd].kind == kFdProcess)) {
|
||||
rc = close$nt(fd);
|
||||
} else {
|
||||
rc = ebadf();
|
||||
|
|
|
@ -25,6 +25,6 @@
|
|||
int faccessat$nt(int dirfd, const char *path, int mode, uint32_t flags) {
|
||||
char16_t path16[PATH_MAX];
|
||||
if (dirfd != AT_FDCWD || flags) return einval();
|
||||
if (mkntpath(path, path16) == -1) return -1;
|
||||
if (__mkntpath(path, path16) == -1) return -1;
|
||||
return ntaccesscheck(path16, mode);
|
||||
}
|
||||
|
|
|
@ -18,18 +18,16 @@
|
|||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows char *getcwd$nt(char *buf, size_t size) {
|
||||
uint16_t name16[PATH_MAX];
|
||||
if (GetCurrentDirectory(PATH_MAX, name16)) {
|
||||
if (tprecode16to8(buf, size, name16) < size - 1) {
|
||||
return buf;
|
||||
} else {
|
||||
erange();
|
||||
}
|
||||
uint16_t name16[PATH_MAX + 1];
|
||||
if (GetCurrentDirectory(ARRAYLEN(name16), name16)) {
|
||||
tprecode16to8(buf, size, name16);
|
||||
return buf;
|
||||
} else {
|
||||
__winerr();
|
||||
}
|
||||
|
|
|
@ -31,8 +31,8 @@
|
|||
|
||||
int getdomainname(char *name, size_t len) {
|
||||
uint32_t nSize;
|
||||
char16_t name16[256];
|
||||
struct utsname u;
|
||||
char16_t name16[256];
|
||||
if (len < 1) return einval();
|
||||
if (!name) return efault();
|
||||
if (!IsWindows()) {
|
||||
|
@ -44,10 +44,11 @@ int getdomainname(char *name, size_t len) {
|
|||
return 0;
|
||||
} else {
|
||||
nSize = ARRAYLEN(name16);
|
||||
if (!GetComputerNameEx(kNtComputerNameDnsFullyQualified, name16, &nSize)) {
|
||||
if (GetComputerNameEx(kNtComputerNameDnsFullyQualified, name16, &nSize)) {
|
||||
tprecode16to8(name, len, name16);
|
||||
return 0;
|
||||
} else {
|
||||
return __winerr();
|
||||
}
|
||||
tprecode16to8(name, MIN(MIN(ARRAYLEN(name16), nSize + 1), len), name16);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,10 +49,11 @@ int gethostname(char *name, size_t len) {
|
|||
return 0;
|
||||
} else {
|
||||
nSize = ARRAYLEN(name16);
|
||||
if (!GetComputerNameEx(kNtComputerNameDnsHostname, name16, &nSize)) {
|
||||
if (GetComputerNameEx(kNtComputerNameDnsHostname, name16, &nSize)) {
|
||||
tprecode16to8(name, len, name16);
|
||||
return 0;
|
||||
} else {
|
||||
return __winerr();
|
||||
}
|
||||
tprecode16to8(name, MIN(MIN(ARRAYLEN(name16), nSize + 1), len), name16);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include "libc/macros.h"
|
||||
#include "libc/nt/accounting.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/knuthmultiplicativehash.h"
|
||||
#include "libc/str/knuthmultiplicativehash.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
|
||||
|
|
|
@ -38,8 +38,8 @@ static textwindows int copyfile$nt(const char *src, const char *dst,
|
|||
int64_t fhsrc, fhdst;
|
||||
struct NtFileTime accessed, modified;
|
||||
char16_t src16[PATH_MAX], dst16[PATH_MAX];
|
||||
if (mkntpath(src, src16) == -1) return -1;
|
||||
if (mkntpath(dst, dst16) == -1) return -1;
|
||||
if (__mkntpath(src, src16) == -1) return -1;
|
||||
if (__mkntpath(dst, dst16) == -1) return -1;
|
||||
if (CopyFile(src16, dst16, !!(flags & COPYFILE_NOCLOBBER))) {
|
||||
if (flags & COPYFILE_PRESERVE_TIMESTAMPS) {
|
||||
fhsrc = CreateFile(src16, kNtFileReadAttributes, kNtFileShareRead, NULL,
|
||||
|
|
|
@ -62,7 +62,7 @@ static textwindows noinline DIR *opendir$nt(const char *name) {
|
|||
int len;
|
||||
DIR *res;
|
||||
char16_t name16[PATH_MAX];
|
||||
if ((len = mkntpath(name, name16)) == -1) return NULL;
|
||||
if ((len = __mkntpath(name, name16)) == -1) return NULL;
|
||||
if (len + 2 + 1 > PATH_MAX) return PROGN(enametoolong(), NULL);
|
||||
if (name16[len - 1] == u'/' || name16[len - 1] == u'\\') {
|
||||
name16[--len] = u'\0';
|
||||
|
@ -87,7 +87,8 @@ static textwindows noinline struct dirent *readdir$nt(DIR *dir) {
|
|||
dir->ent.d_off = dir->tell++;
|
||||
dir->ent.d_reclen = sizeof(dir->ent) +
|
||||
tprecode16to8(dir->ent.d_name, sizeof(dir->ent.d_name),
|
||||
dir->windata.cFileName) +
|
||||
dir->windata.cFileName)
|
||||
.ax +
|
||||
1;
|
||||
switch (dir->windata.dwFileType) {
|
||||
case kNtFileTypeDisk:
|
||||
|
|
|
@ -20,36 +20,49 @@
|
|||
#include "libc/calls/hefty/internal.h"
|
||||
#include "libc/calls/hefty/ntspawn.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/nt/accounting.h"
|
||||
#include "libc/nt/enum/startf.h"
|
||||
#include "libc/nt/enum/status.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/processinformation.h"
|
||||
#include "libc/nt/struct/startupinfo.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/sock.h"
|
||||
|
||||
static textwindows int64_t passstdhand$nt(int fd) {
|
||||
if (g_fds.p[fd].kind != kFdEmpty &&
|
||||
!(g_fds.p[fd].flags &
|
||||
(g_fds.p[fd].kind == kFdSocket ? SOCK_CLOEXEC : O_CLOEXEC))) {
|
||||
return g_fds.p[fd].handle;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
textwindows int execve$nt(const char *program, char *const argv[],
|
||||
char *const envp[]) {
|
||||
int i;
|
||||
uint32_t dwExitCode;
|
||||
struct NtStartupInfo startinfo;
|
||||
struct NtProcessInformation procinfo;
|
||||
memset(&startinfo, 0, sizeof(startinfo));
|
||||
startinfo.cb = sizeof(struct NtStartupInfo);
|
||||
startinfo.dwFlags = kNtStartfUsestdhandles;
|
||||
startinfo.hStdInput = passstdhand$nt(STDIN_FILENO);
|
||||
startinfo.hStdOutput = passstdhand$nt(STDOUT_FILENO);
|
||||
startinfo.hStdError = passstdhand$nt(STDERR_FILENO);
|
||||
if (ntspawn(program, argv, envp, NULL, NULL, true, 0, NULL, &startinfo,
|
||||
NULL) != -1) {
|
||||
for (;;) TerminateProcess(GetCurrentProcess(), 0);
|
||||
startinfo.hStdInput = g_fds.p[0].handle;
|
||||
startinfo.hStdOutput = g_fds.p[1].handle;
|
||||
startinfo.hStdError = g_fds.p[2].handle;
|
||||
for (i = 2; i < g_fds.n; ++i) {
|
||||
if (g_fds.p[i].kind != kFdEmpty && (g_fds.p[i].flags & O_CLOEXEC)) {
|
||||
close(i);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
if (ntspawn(program, argv, envp, NULL, NULL, true, 0, NULL, &startinfo,
|
||||
&procinfo) == -1) {
|
||||
return -1;
|
||||
}
|
||||
CloseHandle(procinfo.hThread);
|
||||
for (i = 0; i < g_fds.n; ++i) {
|
||||
if (g_fds.p[i].kind != kFdEmpty) {
|
||||
close(i);
|
||||
}
|
||||
}
|
||||
do {
|
||||
WaitForSingleObject(procinfo.hProcess, -1);
|
||||
dwExitCode = kNtStillActive;
|
||||
GetExitCodeProcess(procinfo.hProcess, &dwExitCode);
|
||||
} while (dwExitCode == kNtStillActive);
|
||||
ExitProcess(dwExitCode);
|
||||
}
|
||||
|
|
|
@ -17,20 +17,26 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/hefty/ntspawn.h"
|
||||
#include "libc/calls/hefty/spawn.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/conv/itoa.h"
|
||||
#include "libc/nt/enum/filemapflags.h"
|
||||
#include "libc/nt/enum/pageflags.h"
|
||||
#include "libc/nt/enum/startf.h"
|
||||
#include "libc/nt/ipc.h"
|
||||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/runtime/memtrack.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static textwindows int64_t ParseInt(char16_t **p) {
|
||||
|
@ -42,8 +48,8 @@ static textwindows int64_t ParseInt(char16_t **p) {
|
|||
return x;
|
||||
}
|
||||
|
||||
static noinline textwindows void DoAll(int64_t h, void *buf, size_t n,
|
||||
bool32 (*f)()) {
|
||||
static noinline textwindows void ForkIo(int64_t h, void *buf, size_t n,
|
||||
bool32 (*f)()) {
|
||||
char *p;
|
||||
size_t i;
|
||||
uint32_t x;
|
||||
|
@ -53,11 +59,11 @@ static noinline textwindows void DoAll(int64_t h, void *buf, size_t n,
|
|||
}
|
||||
|
||||
static noinline textwindows void WriteAll(int64_t h, void *buf, size_t n) {
|
||||
DoAll(h, buf, n, WriteFile);
|
||||
ForkIo(h, buf, n, WriteFile);
|
||||
}
|
||||
|
||||
static noinline textwindows void ReadAll(int64_t h, void *buf, size_t n) {
|
||||
DoAll(h, buf, n, ReadFile);
|
||||
ForkIo(h, buf, n, ReadFile);
|
||||
}
|
||||
|
||||
textwindows void WinMainForked(void) {
|
||||
|
@ -79,7 +85,7 @@ textwindows void WinMainForked(void) {
|
|||
ReadAll(h, &_mmi.p[i], sizeof(_mmi.p[i]));
|
||||
addr = (void *)((uint64_t)_mmi.p[i].x << 16);
|
||||
size = ((uint64_t)(_mmi.p[i].y - _mmi.p[i].x) << 16) + FRAMESIZE;
|
||||
switch (_mmi.p[i].prot) {
|
||||
switch (_mmi.p[i].prot & (PROT_READ | PROT_WRITE | PROT_EXEC)) {
|
||||
case PROT_READ | PROT_WRITE | PROT_EXEC:
|
||||
protect = kNtPageExecuteReadwrite;
|
||||
access = kNtFileMapRead | kNtFileMapWrite | kNtFileMapExecute;
|
||||
|
@ -117,9 +123,12 @@ textwindows void WinMainForked(void) {
|
|||
|
||||
textwindows int fork$nt(void) {
|
||||
jmp_buf jb;
|
||||
int i, rc, pid;
|
||||
int64_t reader, writer;
|
||||
int i, rc, pid, fds[3];
|
||||
char *p, buf[21 + 1 + 21 + 1];
|
||||
struct NtStartupInfo startinfo;
|
||||
struct NtProcessInformation procinfo;
|
||||
if ((pid = __getemptyfd()) == -1) return -1;
|
||||
if (!setjmp(jb)) {
|
||||
if (CreatePipe(&reader, &writer, &kNtIsInheritable, 0)) {
|
||||
p = buf;
|
||||
|
@ -127,12 +136,19 @@ textwindows int fork$nt(void) {
|
|||
*p++ = ' ';
|
||||
p += uint64toarray_radix10(writer, p);
|
||||
setenv("_FORK", buf, true);
|
||||
fds[0] = 0;
|
||||
fds[1] = 1;
|
||||
fds[2] = 2;
|
||||
/* TODO: CloseHandle(g_fds.p[pid].h) if SIGCHLD is SIG_IGN */
|
||||
if ((pid = spawnve(0, fds, g_argv[0], g_argv, environ)) != -1) {
|
||||
memset(&startinfo, 0, sizeof(startinfo));
|
||||
startinfo.cb = sizeof(struct NtStartupInfo);
|
||||
startinfo.dwFlags = kNtStartfUsestdhandles;
|
||||
startinfo.hStdInput = g_fds.p[0].handle;
|
||||
startinfo.hStdOutput = g_fds.p[1].handle;
|
||||
startinfo.hStdError = g_fds.p[2].handle;
|
||||
if (ntspawn(g_argv[0], g_argv, environ, &kNtIsInheritable, NULL, true, 0,
|
||||
NULL, &startinfo, &procinfo) != -1) {
|
||||
CloseHandle(reader);
|
||||
CloseHandle(procinfo.hThread);
|
||||
g_fds.p[pid].kind = kFdProcess;
|
||||
g_fds.p[pid].handle = procinfo.hProcess;
|
||||
g_fds.p[pid].flags = O_CLOEXEC;
|
||||
WriteAll(writer, jb, sizeof(jb));
|
||||
WriteAll(writer, &_mmi.i, sizeof(_mmi.i));
|
||||
for (i = 0; i < _mmi.i; ++i) {
|
||||
|
@ -144,11 +160,11 @@ textwindows int fork$nt(void) {
|
|||
}
|
||||
WriteAll(writer, _edata, _end - _edata);
|
||||
CloseHandle(writer);
|
||||
rc = pid;
|
||||
} else {
|
||||
rc = -1;
|
||||
}
|
||||
unsetenv("_FORK");
|
||||
rc = pid;
|
||||
} else {
|
||||
rc = __winerr();
|
||||
}
|
||||
|
|
|
@ -96,5 +96,3 @@ error:
|
|||
free(cmdline_p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#undef APPENDCHAR
|
||||
|
|
|
@ -68,8 +68,8 @@ textwindows int ntspawn(
|
|||
char16_t program16[PATH_MAX], *lpCommandLine, *lpEnvironment;
|
||||
lpCommandLine = NULL;
|
||||
lpEnvironment = NULL;
|
||||
if (mkntpath(program, program16) != -1 &&
|
||||
(lpCommandLine = mkntcmdline(argv)) &&
|
||||
if (__mkntpath(program, program16) != -1 &&
|
||||
(lpCommandLine = mkntcmdline(&argv[1])) &&
|
||||
(lpEnvironment = mkntenvblock(envp))) {
|
||||
if (CreateProcess(program16, lpCommandLine, opt_lpProcessAttributes,
|
||||
opt_lpThreadAttributes, bInheritHandles,
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include "libc/alg/arraylist.internal.h"
|
||||
#include "libc/calls/hefty/ntspawn.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nexgen32e/tinystrcmp.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
static int CompareStrings(const char *l, const char *r) {
|
||||
|
|
|
@ -94,6 +94,6 @@ textwindows int spawnve$nt(unsigned flags, int stdiofds[3], const char *program,
|
|||
|
||||
g_fds.p[pid].kind = kFdProcess;
|
||||
g_fds.p[pid].handle = handle;
|
||||
g_fds.p[pid].flags = flags;
|
||||
g_fds.p[pid].flags = O_CLOEXEC;
|
||||
return pid;
|
||||
}
|
||||
|
|
|
@ -252,6 +252,7 @@ int nanosleep$nt(const struct timespec *, struct timespec *) hidden;
|
|||
│ cosmopolitan § syscalls » windows nt » support ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
int64_t ntreturn(uint32_t);
|
||||
void WinMainForked(void) hidden;
|
||||
void *GetProcAddressModule(const char *, const char *) hidden;
|
||||
int getsetpriority$nt(int, unsigned, int, int (*)(int));
|
||||
|
@ -261,19 +262,9 @@ bool32 ntsetprivilege(i64, const char16_t *, u32) hidden;
|
|||
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;
|
||||
|
||||
#define mkntpath(PATH, PATH16) mkntpath2(PATH, -1u, PATH16)
|
||||
#define mkntpath2(PATH, FLAGS, PATH16) \
|
||||
({ \
|
||||
int Count; \
|
||||
asm("call\tmkntpath" \
|
||||
: "=a"(Count), "=m"(*PATH16) \
|
||||
: "D"(PATH), "S"(FLAGS), "d"(&PATH16[0]), "m"((PATH)[0]) \
|
||||
: "cc"); \
|
||||
Count; \
|
||||
})
|
||||
int64_t __winerr(void) nocallback privileged;
|
||||
int __mkntpath(const char *, char16_t[hasatleast PATH_MAX - 16]) hidden;
|
||||
int __mkntpath2(const char *, char16_t[hasatleast PATH_MAX - 16], int) hidden;
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § syscalls » drivers ─╬─│┼
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
textwindows int link$nt(const char *existingpath, const char *newpath) {
|
||||
char16_t newpath16[PATH_MAX];
|
||||
char16_t existingpath16[PATH_MAX];
|
||||
if (mkntpath(existingpath, existingpath16) != -1 &&
|
||||
mkntpath(newpath, newpath16) != -1) {
|
||||
if (__mkntpath(existingpath, existingpath16) != -1 &&
|
||||
__mkntpath(newpath, newpath16) != -1) {
|
||||
if (CreateHardLink(newpath16, existingpath16, NULL)) {
|
||||
return 0;
|
||||
} else {
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
static textwindows noinline int mkdir$nt(const char *path, uint32_t mode) {
|
||||
uint16_t path16[PATH_MAX];
|
||||
if (mkntpath(path, path16) == -1) return -1;
|
||||
if (__mkntpath(path, path16) == -1) return -1;
|
||||
if (CreateDirectory(path16, NULL)) {
|
||||
return 0;
|
||||
} else {
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ntmagicpaths.internal.h"
|
||||
#include "libc/nexgen32e/tinystrcmp.internal.h"
|
||||
#include "libc/str/oldutf16.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tpdecode.internal.h"
|
||||
|
@ -30,19 +30,24 @@ textwindows static const char *FixNtMagicPath(const char *path,
|
|||
const struct NtMagicPaths *mp = &kNtMagicPaths;
|
||||
asm("" : "+r"(mp));
|
||||
if (path[0] != '/') return path;
|
||||
if (tinystrcmp(path, mp->devtty) == 0) {
|
||||
if (strcmp(path, mp->devtty) == 0) {
|
||||
if ((flags & O_ACCMODE) == O_RDONLY) {
|
||||
return mp->conin;
|
||||
} else if ((flags & O_ACCMODE) == O_WRONLY) {
|
||||
return mp->conout;
|
||||
}
|
||||
}
|
||||
if (tinystrcmp(path, mp->devnull) == 0) return mp->nul;
|
||||
if (tinystrcmp(path, mp->devstdin) == 0) return mp->conin;
|
||||
if (tinystrcmp(path, mp->devstdout) == 0) return mp->conout;
|
||||
if (strcmp(path, mp->devnull) == 0) return mp->nul;
|
||||
if (strcmp(path, mp->devstdin) == 0) return mp->conin;
|
||||
if (strcmp(path, mp->devstdout) == 0) return mp->conout;
|
||||
return path;
|
||||
}
|
||||
|
||||
textwindows int __mkntpath(const char *path,
|
||||
char16_t path16[hasatleast PATH_MAX - 16]) {
|
||||
return __mkntpath2(path, path16, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies path for Windows NT.
|
||||
*
|
||||
|
@ -56,9 +61,9 @@ textwindows static const char *FixNtMagicPath(const char *path,
|
|||
* @return short count excluding NUL on success, or -1 w/ errno
|
||||
* @error ENAMETOOLONG
|
||||
*/
|
||||
forcealignargpointer textwindows int mkntpath(
|
||||
const char *path, unsigned flags,
|
||||
char16_t path16[hasatleast PATH_MAX - 16]) {
|
||||
textwindows int __mkntpath2(const char *path,
|
||||
char16_t path16[hasatleast PATH_MAX - 16],
|
||||
int flags) {
|
||||
/*
|
||||
* 1. Reserve +1 for NUL-terminator
|
||||
* 2. Reserve +1 for UTF-16 overflow
|
||||
|
@ -66,31 +71,14 @@ forcealignargpointer textwindows int mkntpath(
|
|||
* 4. Reserve ≥10 for CreateNamedPipe "\\.\pipe\" prefix requirement
|
||||
* 5. Reserve ≥13 for mkdir() i.e. 1+8+3+1, e.g. "\\ffffffff.xxx\0"
|
||||
*/
|
||||
int rc;
|
||||
wint_t wc;
|
||||
size_t i, j;
|
||||
size_t i, n;
|
||||
path = FixNtMagicPath(path, flags);
|
||||
i = 0;
|
||||
j = 0;
|
||||
for (;;) {
|
||||
if ((rc = tpdecode(&path[i], &wc)) == -1) {
|
||||
path16[0] = u'\0';
|
||||
return -1;
|
||||
}
|
||||
if (!wc) break;
|
||||
i += (size_t)rc;
|
||||
if (wc == '/') wc = '\\';
|
||||
if (j + 1 /* utf-16 */ + 1 /* chdir() */ + 1 /* NUL */ < PATH_MAX - 16) {
|
||||
if ((rc = pututf16(&path16[j], 2, wc, false)) == -1) {
|
||||
path16[0] = u'\0';
|
||||
return -1;
|
||||
}
|
||||
j += (size_t)rc;
|
||||
} else {
|
||||
path16[0] = u'\0';
|
||||
return enametoolong();
|
||||
n = tprecode8to16(path16, PATH_MAX - 16, path).ax;
|
||||
if (n == PATH_MAX - 16 - 1) return enametoolong();
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (path16[i] == '/') {
|
||||
path16[i] = '\\';
|
||||
}
|
||||
}
|
||||
path16[j] = u'\0';
|
||||
return j;
|
||||
return n;
|
||||
}
|
|
@ -20,7 +20,6 @@
|
|||
#include "libc/assert.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ntmagicpaths.internal.h"
|
||||
#include "libc/nexgen32e/tinystrcmp.internal.h"
|
||||
#include "libc/nt/createfile.h"
|
||||
#include "libc/nt/enum/accessmask.h"
|
||||
#include "libc/nt/enum/creationdisposition.h"
|
||||
|
@ -31,6 +30,7 @@
|
|||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
@ -40,7 +40,7 @@ static textwindows int64_t open$nt$impl(const char *file, uint32_t flags,
|
|||
uint32_t br;
|
||||
int64_t handle;
|
||||
char16_t file16[PATH_MAX];
|
||||
if (mkntpath2(file, flags, file16) == -1) return -1;
|
||||
if (__mkntpath2(file, file16, flags) == -1) return -1;
|
||||
if ((handle = CreateFile(
|
||||
file16,
|
||||
(flags & 0xf000000f) | (/* this is needed if we mmap(rwx+cow)
|
||||
|
@ -119,7 +119,7 @@ textwindows ssize_t open$nt(const char *file, uint32_t flags, int32_t mode) {
|
|||
size_t fd;
|
||||
if ((fd = __getemptyfd()) == -1) return -1;
|
||||
if ((flags & O_ACCMODE) == O_RDWR &&
|
||||
tinystrcmp(file, kNtMagicPaths.devtty) == 0) {
|
||||
strcmp(file, kNtMagicPaths.devtty) == 0) {
|
||||
return open$nt$console(&kNtMagicPaths, flags, mode, fd);
|
||||
} else {
|
||||
return open$nt$file(file, flags, mode, fd);
|
||||
|
|
|
@ -27,8 +27,8 @@
|
|||
textwindows int rename$nt(const char *oldpath, const char *newpath) {
|
||||
char16_t oldpath16[PATH_MAX];
|
||||
char16_t newpath16[PATH_MAX];
|
||||
if (mkntpath(oldpath, oldpath16) == -1 ||
|
||||
mkntpath(newpath, newpath16) == -1) {
|
||||
if (__mkntpath(oldpath, oldpath16) == -1 ||
|
||||
__mkntpath(newpath, newpath16) == -1) {
|
||||
return -1;
|
||||
}
|
||||
if (MoveFileEx(oldpath16, newpath16, kNtMovefileReplaceExisting)) {
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
textwindows int rmdir$nt(const char *path) {
|
||||
uint16_t path16[PATH_MAX];
|
||||
if (mkntpath(path, path16) == -1) return -1;
|
||||
if (__mkntpath(path, path16) == -1) return -1;
|
||||
if (RemoveDirectory(path16)) {
|
||||
return 0;
|
||||
} else {
|
||||
|
|
|
@ -31,7 +31,7 @@ textwindows int stat$nt(const char *path, struct stat *st) {
|
|||
int rc;
|
||||
int64_t fh;
|
||||
uint16_t path16[PATH_MAX];
|
||||
if (mkntpath(path, path16) == -1) return -1;
|
||||
if (__mkntpath(path, path16) == -1) return -1;
|
||||
if ((fh = CreateFile(
|
||||
path16, kNtFileReadAttributes,
|
||||
kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete, NULL,
|
||||
|
|
|
@ -24,8 +24,8 @@
|
|||
textwindows int symlink$nt(const char *target, const char *linkpath) {
|
||||
char16_t linkpath16[PATH_MAX], target16[PATH_MAX];
|
||||
uint32_t flags = isdirectory(target) ? kNtSymbolicLinkFlagDirectory : 0;
|
||||
if (mkntpath(linkpath, linkpath16) == -1) return -1;
|
||||
if (mkntpath(target, target16) == -1) return -1;
|
||||
if (__mkntpath(linkpath, linkpath16) == -1) return -1;
|
||||
if (__mkntpath(target, target16) == -1) return -1;
|
||||
if (CreateSymbolicLink(linkpath16, target16, flags)) {
|
||||
return 0;
|
||||
} else {
|
||||
|
|
|
@ -29,7 +29,7 @@ textwindows int truncate$nt(const char *path, uint64_t length) {
|
|||
bool32 ok;
|
||||
int64_t fh;
|
||||
uint16_t path16[PATH_MAX];
|
||||
if (mkntpath(path, path16) == -1) return -1;
|
||||
if (__mkntpath(path, path16) == -1) return -1;
|
||||
if ((fh = CreateFile(path16, kNtGenericWrite, kNtFileShareRead, NULL,
|
||||
kNtOpenExisting, kNtFileAttributeNormal, 0)) != -1) {
|
||||
ok = ftruncate$nt(fh, length);
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
textwindows int unlink$nt(const char *name) {
|
||||
uint16_t name16[PATH_MAX];
|
||||
if (mkntpath(name, name16) == -1) return -1;
|
||||
if (__mkntpath(name, name16) == -1) return -1;
|
||||
if (DeleteFile(name16)) {
|
||||
return 0;
|
||||
} else {
|
||||
|
|
|
@ -42,7 +42,7 @@ textwindows int utimensat$nt(int dirfd, const char *path,
|
|||
if (flags) return einval();
|
||||
if (path) {
|
||||
if (dirfd == AT_FDCWD) {
|
||||
if (mkntpath(path, path16) == -1) return -1;
|
||||
if (__mkntpath(path, path16) == -1) return -1;
|
||||
if ((fh = CreateFile(path16, kNtFileWriteAttributes, kNtFileShareRead,
|
||||
NULL, kNtOpenExisting, kNtFileAttributeNormal, 0)) !=
|
||||
-1) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue