mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-08 04:08:32 +00:00
Improve system call support on NT
- Improve i/o perf on New Technology - Code cleanup on read() for New Technology - Fix bad bug with dup() of socket on New Technology - Clean up some more strace errors on New Technology
This commit is contained in:
parent
29bf8b1a30
commit
4f98ad1054
79 changed files with 707 additions and 197 deletions
|
@ -20,17 +20,22 @@
|
|||
#include "libc/nt/enum/filetype.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int sys_close_nt(struct Fd *fd) {
|
||||
int e;
|
||||
bool32 ok;
|
||||
if (fd->kind == kFdFile && GetFileType(fd->handle) == kNtFileTypeDisk) {
|
||||
if (fd->kind == kFdFile && ((fd->flags & O_ACCMODE) != O_RDONLY &&
|
||||
GetFileType(fd->handle) == kNtFileTypeDisk)) {
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
e = errno;
|
||||
FlushFileBuffers(fd->handle);
|
||||
errno = e;
|
||||
}
|
||||
ok = CloseHandle(fd->handle);
|
||||
if (fd->kind == kFdConsole && fd->extra && fd->extra != -1) {
|
||||
|
|
|
@ -46,31 +46,35 @@
|
|||
*/
|
||||
int close(int fd) {
|
||||
int rc;
|
||||
if (fd == -1) return 0;
|
||||
if (fd < 0) return einval();
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
rc = weaken(__zipos_close)(fd);
|
||||
if (fd == -1) {
|
||||
rc = 0;
|
||||
} else if (fd < 0) {
|
||||
rc = einval();
|
||||
} else {
|
||||
if (!IsWindows() && !IsMetal()) {
|
||||
rc = sys_close(fd);
|
||||
} else if (IsMetal()) {
|
||||
rc = 0;
|
||||
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(sys_close_epoll_nt)(fd);
|
||||
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdSocket) {
|
||||
rc = weaken(sys_closesocket_nt)(g_fds.p + fd);
|
||||
} else if (fd < g_fds.n && (g_fds.p[fd].kind == kFdFile ||
|
||||
g_fds.p[fd].kind == kFdConsole ||
|
||||
g_fds.p[fd].kind == kFdProcess)) {
|
||||
rc = sys_close_nt(g_fds.p + fd);
|
||||
if (!IsWindows() && !IsMetal()) {
|
||||
rc = sys_close(fd);
|
||||
} else if (IsMetal()) {
|
||||
rc = 0;
|
||||
} else {
|
||||
STRACE("close(%d) unknown kind: %d", fd, g_fds.p[fd].kind);
|
||||
rc = ebadf();
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdEpoll) {
|
||||
rc = weaken(sys_close_epoll_nt)(fd);
|
||||
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdSocket) {
|
||||
rc = weaken(sys_closesocket_nt)(g_fds.p + fd);
|
||||
} else if (fd < g_fds.n && (g_fds.p[fd].kind == kFdFile ||
|
||||
g_fds.p[fd].kind == kFdConsole ||
|
||||
g_fds.p[fd].kind == kFdProcess)) {
|
||||
rc = sys_close_nt(g_fds.p + fd);
|
||||
} else {
|
||||
STRACE("close(%d) unknown kind: %d", fd, g_fds.p[fd].kind);
|
||||
rc = ebadf();
|
||||
}
|
||||
}
|
||||
}
|
||||
__releasefd(fd);
|
||||
}
|
||||
__releasefd(fd);
|
||||
STRACE("%s(%d) → %d% m", "close", fd, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -17,11 +17,13 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
|
@ -47,8 +49,13 @@ textwindows int sys_dup_nt(int oldfd, int newfd, int flags) {
|
|||
if (DuplicateHandle(proc, g_fds.p[oldfd].handle, proc, &g_fds.p[newfd].handle,
|
||||
0, true, kNtDuplicateSameAccess)) {
|
||||
g_fds.p[newfd].kind = g_fds.p[oldfd].kind;
|
||||
g_fds.p[newfd].extra = g_fds.p[oldfd].extra;
|
||||
g_fds.p[newfd].flags = flags;
|
||||
if (g_fds.p[oldfd].kind == kFdSocket && weaken(_dupsockfd)) {
|
||||
g_fds.p[newfd].extra =
|
||||
(intptr_t)weaken(_dupsockfd)((struct SockFd *)g_fds.p[oldfd].extra);
|
||||
} else {
|
||||
g_fds.p[newfd].extra = g_fds.p[oldfd].extra;
|
||||
}
|
||||
return newfd;
|
||||
} else {
|
||||
__releasefd(newfd);
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
*/
|
||||
int faccessat(int dirfd, const char *path, int mode, uint32_t flags) {
|
||||
int rc;
|
||||
char buf[12];
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) {
|
||||
rc = efault();
|
||||
} else if (weaken(__zipos_notat) &&
|
||||
|
@ -49,6 +50,7 @@ int faccessat(int dirfd, const char *path, int mode, uint32_t flags) {
|
|||
} else {
|
||||
rc = sys_faccessat_nt(dirfd, path, mode, flags);
|
||||
}
|
||||
STRACE("faccessat(%d, %#s, %#o, %#x) → %d% m", dirfd, path, mode, flags, rc);
|
||||
STRACE("faccessat(%s, %#s, %#o, %#x) → %d% m", __strace_dirfd(buf, dirfd),
|
||||
path, mode, flags, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
|
||||
/**
|
||||
|
@ -31,9 +32,12 @@
|
|||
* @return -1 on error
|
||||
*/
|
||||
int fadvise(int fd, uint64_t offset, uint64_t len, int advice) {
|
||||
int rc;
|
||||
if (!IsWindows()) {
|
||||
return sys_fadvise(fd, offset, len, advice); /* linux & freebsd */
|
||||
rc = sys_fadvise(fd, offset, len, advice); /* linux & freebsd */
|
||||
} else {
|
||||
return sys_fadvise_nt(fd, offset, len, advice);
|
||||
rc = sys_fadvise_nt(fd, offset, len, advice);
|
||||
}
|
||||
STRACE("fadvise(%d, %'lu, %'lu, %d) → %d% m", fd, offset, len, advice, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ textwindows int sys_fchmodat_nt(int dirfd, const char *path, uint32_t mode,
|
|||
uint32_t attr;
|
||||
uint16_t path16[PATH_MAX];
|
||||
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
|
||||
if ((attr = GetFileAttributes(path16)) != -1) {
|
||||
if ((attr = GetFileAttributes(path16)) != -1u) {
|
||||
if (mode & 0200) {
|
||||
attr &= ~kNtFileAttributeReadonly;
|
||||
} else {
|
||||
|
|
|
@ -41,14 +41,17 @@
|
|||
*/
|
||||
int fchmodat(int dirfd, const char *path, uint32_t mode, int flags) {
|
||||
int rc;
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
|
||||
if (weaken(__zipos_notat) && (rc = __zipos_notat(dirfd, path)) == -1) {
|
||||
STRACE("zipos fchmodat not supported yet");
|
||||
char buf[12];
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) {
|
||||
rc = efault();
|
||||
} else if (weaken(__zipos_notat) && (rc = __zipos_notat(dirfd, path)) == -1) {
|
||||
rc = eopnotsupp();
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_fchmodat(dirfd, path, mode, flags);
|
||||
} else {
|
||||
rc = sys_fchmodat_nt(dirfd, path, mode, flags);
|
||||
}
|
||||
STRACE("fchmodat(%d, %#s, %#o, %d) → %d% m", dirfd, path, mode, flags, rc);
|
||||
STRACE("fchmodat(%s, %#s, %#o, %d) → %d% m", __strace_dirfd(buf, dirfd), path,
|
||||
mode, flags, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
int fchownat(int dirfd, const char *path, uint32_t uid, uint32_t gid,
|
||||
int flags) {
|
||||
int rc;
|
||||
char sb[12];
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) {
|
||||
rc = efault();
|
||||
} else if (weaken(__zipos_notat) && (rc = __zipos_notat(dirfd, path)) == -1) {
|
||||
|
@ -48,7 +49,7 @@ int fchownat(int dirfd, const char *path, uint32_t uid, uint32_t gid,
|
|||
} else {
|
||||
rc = sys_fchownat(dirfd, path, uid, gid, flags);
|
||||
}
|
||||
STRACE("fchownat(%d, %#s, %d, %d, %#b) → %d% m", dirfd, path, uid, gid, flags,
|
||||
rc);
|
||||
STRACE("fchownat(%s, %#s, %d, %d, %#b) → %d% m", __strace_dirfd(sb, dirfd),
|
||||
path, uid, gid, flags, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ static textwindows int sys_fcntl_nt_lock(struct Fd *f, int cmd, uintptr_t arg) {
|
|||
}
|
||||
if (!len) len = size - off;
|
||||
if (off < 0 || len < 0) return einval();
|
||||
offset2overlap(off, &ov);
|
||||
_offset2overlap(off, &ov);
|
||||
if (l->l_type == F_RDLCK || l->l_type == F_WRLCK) {
|
||||
flags = 0;
|
||||
if (cmd == F_SETLK) flags |= kNtLockfileFailImmediately;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nexgen32e/bsr.h"
|
||||
#include "libc/nt/enum/fileflagandattributes.h"
|
||||
|
|
|
@ -22,20 +22,29 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
static inline const char *__strace_fstatat_flags(int flags) {
|
||||
static char buf[12];
|
||||
if (flags == AT_SYMLINK_NOFOLLOW) return "AT_SYMLINK_NOFOLLOW";
|
||||
FormatInt32(buf, flags);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information about thing.
|
||||
*
|
||||
* @param dirfd is normally AT_FDCWD but if it's an open directory and
|
||||
* file is a relative path, then file becomes relative to dirfd
|
||||
* @param st is where result is stored
|
||||
* @param flags can have AT_{EMPTY_PATH,NO_AUTOMOUNT,SYMLINK_NOFOLLOW}
|
||||
* @param flags can have AT_SYMLINK_NOFOLLOW
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @see S_ISDIR(st.st_mode), S_ISREG()
|
||||
* @asyncsignalsafe
|
||||
|
@ -44,6 +53,7 @@
|
|||
int fstatat(int dirfd, const char *path, struct stat *st, int flags) {
|
||||
/* execve() depends on this */
|
||||
int rc;
|
||||
char buf[12];
|
||||
struct ZiposUri zipname;
|
||||
if (__isfdkind(dirfd, kFdZip)) {
|
||||
STRACE("zipos dirfd not supported yet");
|
||||
|
@ -60,7 +70,7 @@ int fstatat(int dirfd, const char *path, struct stat *st, int flags) {
|
|||
} else {
|
||||
rc = sys_fstatat_nt(dirfd, path, st, flags);
|
||||
}
|
||||
STRACE("fstatat(%d, %#s, [%s], %#b) → %d% m", dirfd, path,
|
||||
__strace_stat(rc, st), flags, rc);
|
||||
STRACE("fstatat(%s, %#s, [%s], %s) → %d% m", __strace_dirfd(buf, dirfd), path,
|
||||
__strace_stat(rc, st), __strace_fstatat_flags(flags), rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ forceinline bool __isfdkind(int fd, int kind) {
|
|||
return 0 <= fd && fd < g_fds.n && g_fds.p[fd].kind == kind;
|
||||
}
|
||||
|
||||
forceinline size_t clampio(size_t size) {
|
||||
forceinline size_t _clampio(size_t size) {
|
||||
if (!IsTrustworthy()) {
|
||||
return MIN(size, 0x7ffff000);
|
||||
} else {
|
||||
|
@ -326,7 +326,7 @@ int64_t __winerr(void) nocallback privileged;
|
|||
int64_t ntreturn(uint32_t);
|
||||
ssize_t sys_readv_nt(struct Fd *, const struct iovec *, int) hidden;
|
||||
ssize_t sys_writev_nt(int, const struct iovec *, int) hidden;
|
||||
struct NtOverlapped *offset2overlap(int64_t, struct NtOverlapped *) hidden;
|
||||
struct NtOverlapped *_offset2overlap(int64_t, struct NtOverlapped *) hidden;
|
||||
unsigned __wincrash_nt(struct NtExceptionPointers *);
|
||||
void *GetProcAddressModule(const char *, const char *) hidden;
|
||||
void WinMainForked(void) hidden;
|
||||
|
|
|
@ -63,7 +63,6 @@ textwindows int ioctl_tiocgwinsz_nt(struct Fd *fd, struct winsize *ws) {
|
|||
__winerr();
|
||||
}
|
||||
} else {
|
||||
STRACE("%s() failed %m", "GetConsoleMode");
|
||||
enotty();
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
|
@ -27,23 +28,24 @@
|
|||
* Returns true if file descriptor is backed by a terminal device.
|
||||
*/
|
||||
bool32 isatty(int fd) {
|
||||
int err;
|
||||
int e;
|
||||
bool32 res;
|
||||
struct winsize ws;
|
||||
e = errno;
|
||||
if (fd >= 0) {
|
||||
if (__isfdkind(fd, kFdZip)) {
|
||||
return false;
|
||||
res = false;
|
||||
} else if (IsMetal()) {
|
||||
return false;
|
||||
res = false;
|
||||
} else if (!IsWindows()) {
|
||||
err = errno;
|
||||
res = sys_ioctl(fd, TIOCGWINSZ, &ws) != -1;
|
||||
errno = err;
|
||||
return res;
|
||||
} else {
|
||||
return sys_isatty_nt(fd);
|
||||
res = sys_isatty_nt(fd);
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
res = false;
|
||||
}
|
||||
STRACE("isatty(%d) → %hhhd% m", fd, res);
|
||||
errno = e;
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/nt/enum/fileflagandattributes.h"
|
||||
#include "libc/nt/files.h"
|
||||
|
||||
|
@ -25,12 +26,15 @@
|
|||
* Returns true if file exists and is a directory on Windows NT.
|
||||
*/
|
||||
bool isdirectory_nt(const char *path) {
|
||||
int e;
|
||||
uint32_t x;
|
||||
char16_t path16[PATH_MAX];
|
||||
e = errno;
|
||||
if (__mkntpath(path, path16) == -1) return -1;
|
||||
if ((x = GetFileAttributes(path16)) != -1u) {
|
||||
return !!(x & kNtFileAttributeDirectory);
|
||||
} else {
|
||||
errno = e;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/nt/enum/fileflagandattributes.h"
|
||||
#include "libc/nt/files.h"
|
||||
|
||||
|
@ -25,12 +26,15 @@
|
|||
* Returns true if file exists and is a regular file on Windows NT.
|
||||
*/
|
||||
bool isregularfile_nt(const char *path) {
|
||||
int e;
|
||||
uint32_t x;
|
||||
char16_t path16[PATH_MAX];
|
||||
e = errno;
|
||||
if (__mkntpath(path, path16) == -1) return -1;
|
||||
if ((x = GetFileAttributes(path16)) != -1u) {
|
||||
return !(x & (kNtFileAttributeDirectory | kNtFileAttributeReparsePoint));
|
||||
} else {
|
||||
errno = e;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/nt/enum/fileflagandattributes.h"
|
||||
#include "libc/nt/files.h"
|
||||
|
||||
|
@ -25,12 +26,15 @@
|
|||
* Returns true if file exists and is a symbolic link on Windows NT.
|
||||
*/
|
||||
bool issymlink_nt(const char *path) {
|
||||
int e;
|
||||
uint32_t x;
|
||||
char16_t path16[PATH_MAX];
|
||||
e = errno;
|
||||
if (__mkntpath(path, path16) == -1) return -1;
|
||||
if ((x = GetFileAttributes(path16)) != -1u) {
|
||||
return !!(x & kNtFileAttributeReparsePoint);
|
||||
} else {
|
||||
errno = e;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
int linkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath,
|
||||
int flags) {
|
||||
int rc;
|
||||
char buf[2][12];
|
||||
if (IsAsan() &&
|
||||
(!__asan_is_valid(oldpath, 1) || !__asan_is_valid(newpath, 1))) {
|
||||
rc = efault();
|
||||
|
@ -50,7 +51,8 @@ int linkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath,
|
|||
} else {
|
||||
rc = sys_linkat_nt(olddirfd, oldpath, newdirfd, newpath);
|
||||
}
|
||||
STRACE("linkat(%d, %#s, %d, %#s, %#b) → %d% m", olddirfd, oldpath, newdirfd,
|
||||
newpath, flags, rc);
|
||||
STRACE("linkat(%s, %#s, %s, %#s, %#b) → %d% m",
|
||||
__strace_dirfd(buf[0], olddirfd), oldpath,
|
||||
__strace_dirfd(buf[1], newdirfd), newpath, flags, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -24,13 +24,20 @@
|
|||
#include "libc/str/str.h"
|
||||
|
||||
static textwindows bool SubpathExistsThatsNotDirectory(char16_t *path) {
|
||||
int e;
|
||||
char16_t *p;
|
||||
uint32_t attrs;
|
||||
e = errno;
|
||||
while ((p = strrchr16(path, '\\'))) {
|
||||
*p = u'\0';
|
||||
if ((attrs = GetFileAttributes(path)) != -1u) {
|
||||
if (attrs & kNtFileAttributeDirectory) return false;
|
||||
return true;
|
||||
if (attrs & kNtFileAttributeDirectory) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
errno = e;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -40,10 +47,20 @@ textwindows int sys_mkdirat_nt(int dirfd, const char *path, uint32_t mode) {
|
|||
int e;
|
||||
char16_t *p, path16[PATH_MAX];
|
||||
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
|
||||
if (CreateDirectory(path16, NULL)) return 0;
|
||||
e = GetLastError();
|
||||
/* WIN32 doesn't distinguish between ENOTDIR and ENOENT */
|
||||
if (e == ENOTDIR && !SubpathExistsThatsNotDirectory(path16)) e = ENOENT;
|
||||
errno = e;
|
||||
if (CreateDirectory(path16, 0)) return 0;
|
||||
|
||||
// WIN32 doesn't distinguish between ENOTDIR and ENOENT
|
||||
//
|
||||
// - ENOTDIR: A component used as a directory in pathname is not, in
|
||||
// fact, a directory. -or- pathname is relative and dirfd is a file
|
||||
// descriptor referring to a file other than a directory.
|
||||
//
|
||||
// - ENOENT: A directory component in pathname does not exist or is a
|
||||
// dangling symbolic link.
|
||||
if (errno == ENOTDIR) {
|
||||
if (!SubpathExistsThatsNotDirectory(path16)) {
|
||||
errno = ENOENT;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
*/
|
||||
int mkdirat(int dirfd, const char *path, unsigned mode) {
|
||||
int rc;
|
||||
char buf[12];
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) {
|
||||
rc = efault();
|
||||
} else if (weaken(__zipos_notat) && (rc = __zipos_notat(dirfd, path)) == -1) {
|
||||
|
@ -49,6 +50,7 @@ int mkdirat(int dirfd, const char *path, unsigned mode) {
|
|||
} else {
|
||||
rc = sys_mkdirat_nt(dirfd, path, mode);
|
||||
}
|
||||
STRACE("mkdirat(%d, %#s, %#o) → %d% m", dirfd, path, mode, rc);
|
||||
STRACE("mkdirat(%s, %#s, %#o) → %d% m", __strace_dirfd(buf, dirfd), path,
|
||||
mode, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -81,23 +81,15 @@ textwindows int ntspawn(
|
|||
NULL, false},
|
||||
pushpop(kNtPageReadwrite), 0, blocksize, NULL)) &&
|
||||
(block = MapViewOfFileEx(handle, kNtFileMapRead | kNtFileMapWrite, 0, 0,
|
||||
blocksize, NULL))) {
|
||||
if (mkntcmdline(block->cmdline, prog, argv) != -1 &&
|
||||
mkntenvblock(block->envvars, envp, extravar) != -1) {
|
||||
if (CreateProcess(prog16, block->cmdline, opt_lpProcessAttributes,
|
||||
opt_lpThreadAttributes, bInheritHandles,
|
||||
dwCreationFlags | kNtCreateUnicodeEnvironment,
|
||||
block->envvars, opt_lpCurrentDirectory, lpStartupInfo,
|
||||
opt_out_lpProcessInformation)) {
|
||||
rc = 0;
|
||||
} else {
|
||||
__winerr();
|
||||
}
|
||||
STRACE("CreateProcess(%#hs, %!#hs) → %d% m", prog16, block->cmdline, rc);
|
||||
}
|
||||
} else {
|
||||
__winerr();
|
||||
STRACE("ntspawn() alloc failed %m");
|
||||
blocksize, NULL)) &&
|
||||
mkntcmdline(block->cmdline, prog, argv) != -1 &&
|
||||
mkntenvblock(block->envvars, envp, extravar) != -1 &&
|
||||
CreateProcess(prog16, block->cmdline, opt_lpProcessAttributes,
|
||||
opt_lpThreadAttributes, bInheritHandles,
|
||||
dwCreationFlags | kNtCreateUnicodeEnvironment,
|
||||
block->envvars, opt_lpCurrentDirectory, lpStartupInfo,
|
||||
opt_out_lpProcessInformation)) {
|
||||
rc = 0;
|
||||
}
|
||||
if (block) UnmapViewOfFile(block);
|
||||
if (handle) CloseHandle(handle);
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
#include "libc/nt/struct/overlapped.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
textwindows struct NtOverlapped *offset2overlap(int64_t opt_offset,
|
||||
struct NtOverlapped *mem) {
|
||||
textwindows struct NtOverlapped *_offset2overlap(int64_t opt_offset,
|
||||
struct NtOverlapped *mem) {
|
||||
if (opt_offset == -1) return NULL;
|
||||
bzero(mem, sizeof(struct NtOverlapped));
|
||||
mem->Pointer = (void *)(uintptr_t)opt_offset;
|
||||
|
|
|
@ -57,6 +57,7 @@ static textwindows int64_t sys_open_nt_impl(int dirfd, const char *path,
|
|||
uint32_t br, err;
|
||||
char16_t path16[PATH_MAX];
|
||||
uint32_t perm, share, disp, attr;
|
||||
|
||||
if (__mkntpathat(dirfd, path, flags, path16) == -1) return -1;
|
||||
|
||||
switch (flags & O_ACCMODE) {
|
||||
|
@ -109,6 +110,7 @@ static textwindows int64_t sys_open_nt_impl(int dirfd, const char *path,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
flags |= kNtFileFlagOverlapped;
|
||||
if (~flags & _O_INDEXED) attr |= kNtFileAttributeNotContentIndexed;
|
||||
if (flags & _O_COMPRESSED) attr |= kNtFileAttributeCompressed;
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
int openat(int dirfd, const char *file, int flags, ...) {
|
||||
int rc;
|
||||
va_list va;
|
||||
char buf[12];
|
||||
unsigned mode;
|
||||
struct ZiposUri zipname;
|
||||
va_start(va, flags);
|
||||
|
@ -73,7 +74,7 @@ int openat(int dirfd, const char *file, int flags, ...) {
|
|||
} else {
|
||||
rc = efault();
|
||||
}
|
||||
STRACE("openat(%d, %#s, %#x, %#o) → %d% m", dirfd, file, flags,
|
||||
(flags & (O_CREAT | O_TMPFILE)) ? mode : 0, rc);
|
||||
STRACE("openat(%s, %#s, %#x, %#o) → %d% m", __strace_dirfd(buf, dirfd), file,
|
||||
flags, (flags & (O_CREAT | O_TMPFILE)) ? mode : 0, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -32,8 +32,8 @@ static textwindows ssize_t sys_read_nt_impl(struct Fd *fd, void *data,
|
|||
size_t size, ssize_t offset) {
|
||||
uint32_t got;
|
||||
struct NtOverlapped overlap;
|
||||
if (ReadFile(fd->handle, data, clampio(size), &got,
|
||||
offset2overlap(offset, &overlap))) {
|
||||
if (ReadFile(fd->handle, data, _clampio(size), &got,
|
||||
_offset2overlap(offset, &overlap))) {
|
||||
return got;
|
||||
} else if (
|
||||
// make sure read() returns 0 on broken pipe
|
||||
|
|
|
@ -16,11 +16,14 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nexgen32e/bsr.h"
|
||||
#include "libc/nt/createfile.h"
|
||||
|
@ -36,19 +39,6 @@
|
|||
#include "libc/str/utf16.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static textwindows ssize_t sys_readlinkat_nt_error(void) {
|
||||
uint32_t e;
|
||||
e = GetLastError();
|
||||
STRACE("sys_readlinkat_nt() error %d", e);
|
||||
switch (e) {
|
||||
case kNtErrorNotAReparsePoint:
|
||||
return einval();
|
||||
default:
|
||||
errno = e;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
textwindows ssize_t sys_readlinkat_nt(int dirfd, const char *path, char *buf,
|
||||
size_t bufsiz) {
|
||||
int64_t h;
|
||||
|
@ -60,7 +50,6 @@ textwindows ssize_t sys_readlinkat_nt(int dirfd, const char *path, char *buf,
|
|||
char16_t path16[PATH_MAX], *p;
|
||||
struct NtReparseDataBuffer *rdb;
|
||||
if (__mkntpathat(dirfd, path, 0, path16) == -1) {
|
||||
STRACE("sys_readlinkat_nt() failed b/c __mkntpathat() failed");
|
||||
return -1;
|
||||
}
|
||||
if (weaken(malloc)) {
|
||||
|
@ -121,12 +110,12 @@ textwindows ssize_t sys_readlinkat_nt(int dirfd, const char *path, char *buf,
|
|||
rc = einval();
|
||||
}
|
||||
} else {
|
||||
STRACE("%s failed %m", "DeviceIoControl(kNtFsctlGetReparsePoint)");
|
||||
rc = sys_readlinkat_nt_error();
|
||||
assert(errno == EINVAL);
|
||||
rc = -1;
|
||||
}
|
||||
CloseHandle(h);
|
||||
} else {
|
||||
rc = sys_readlinkat_nt_error();
|
||||
rc = -1;
|
||||
}
|
||||
if (freeme && weaken(free)) {
|
||||
weaken(free)(freeme);
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
* @asyncsignalsafe
|
||||
*/
|
||||
ssize_t readlinkat(int dirfd, const char *path, char *buf, size_t bufsiz) {
|
||||
char sb[12];
|
||||
ssize_t bytes;
|
||||
if ((IsAsan() && !__asan_is_valid(buf, bufsiz)) || (bufsiz && !buf)) {
|
||||
bytes = efault();
|
||||
|
@ -60,7 +61,7 @@ ssize_t readlinkat(int dirfd, const char *path, char *buf, size_t bufsiz) {
|
|||
} else {
|
||||
bytes = sys_readlinkat_nt(dirfd, path, buf, bufsiz);
|
||||
}
|
||||
STRACE("readlinkat(%d, %#s, [%#.*s]) → %d% m", dirfd, path, MAX(0, bytes),
|
||||
buf, bytes);
|
||||
STRACE("readlinkat(%s, %#s, [%#.*s]) → %d% m", __strace_dirfd(sb, dirfd),
|
||||
path, MAX(0, bytes), buf, bytes);
|
||||
return bytes;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
int renameat(int olddirfd, const char *oldpath, int newdirfd,
|
||||
const char *newpath) {
|
||||
int rc;
|
||||
char buf[2][12];
|
||||
if (IsAsan() &&
|
||||
(!__asan_is_valid(oldpath, 1) || !__asan_is_valid(newpath, 1))) {
|
||||
rc = efault();
|
||||
|
@ -50,7 +51,7 @@ int renameat(int olddirfd, const char *oldpath, int newdirfd,
|
|||
} else {
|
||||
rc = sys_renameat_nt(olddirfd, oldpath, newdirfd, newpath);
|
||||
}
|
||||
STRACE("renameat(%d, %#s, %d, %#s) → %d% m", olddirfd, oldpath, newdirfd,
|
||||
newpath, rc);
|
||||
STRACE("renameat(%s, %#s, %s, %#s) → %d% m", __strace_dirfd(buf[0], olddirfd),
|
||||
oldpath, __strace_dirfd(buf[1], newdirfd), newpath, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -38,8 +38,8 @@ textwindows void _check_sigwinch(struct Fd *fd) {
|
|||
struct winsize ws, old;
|
||||
struct NtConsoleScreenBufferInfoEx sbinfo;
|
||||
old = __ws;
|
||||
e = errno;
|
||||
if (old.ws_row != 0xffff) {
|
||||
e = errno;
|
||||
if (ioctl_tiocgwinsz_nt(fd, &ws) != -1) {
|
||||
if (old.ws_col != ws.ws_col || old.ws_row != ws.ws_row) {
|
||||
__ws = ws;
|
||||
|
@ -48,10 +48,10 @@ textwindows void _check_sigwinch(struct Fd *fd) {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
errno = e;
|
||||
if (!old.ws_row && !old.ws_col) {
|
||||
__ws.ws_row = 0xffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
errno = e;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ const char *__strace_sigset(char[41], size_t, int, const sigset_t *);
|
|||
const char *__strace_rlimit_name(int);
|
||||
const char *__strace_rlimit(char[41], size_t, int, const struct rlimit *);
|
||||
const char *__strace_timespec(char[45], size_t, int, const struct timespec *);
|
||||
const char *__strace_dirfd(char[12], int);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
27
libc/calls/strace_dirfd.greg.c
Normal file
27
libc/calls/strace_dirfd.greg.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*-*- 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 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
|
||||
privileged const char *__strace_dirfd(char buf[12], int dirfd) {
|
||||
if (dirfd == AT_FDCWD) return "AT_FDCWD";
|
||||
FormatInt32(buf, dirfd);
|
||||
return buf;
|
||||
}
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
|
@ -37,13 +38,18 @@
|
|||
* @asyncsignalsafe
|
||||
*/
|
||||
int symlinkat(const char *target, int newdirfd, const char *linkpath) {
|
||||
int rc;
|
||||
char buf[12];
|
||||
if (IsAsan() &&
|
||||
(!__asan_is_valid(target, 1) || !__asan_is_valid(linkpath, 1))) {
|
||||
return efault();
|
||||
rc = efault();
|
||||
}
|
||||
if (!IsWindows()) {
|
||||
return sys_symlinkat(target, newdirfd, linkpath);
|
||||
rc = sys_symlinkat(target, newdirfd, linkpath);
|
||||
} else {
|
||||
return sys_symlinkat_nt(target, newdirfd, linkpath);
|
||||
rc = sys_symlinkat_nt(target, newdirfd, linkpath);
|
||||
}
|
||||
STRACE("symlinkat(%#s, %s, %#s) → %d% m", target,
|
||||
__strace_dirfd(buf, newdirfd), linkpath);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -75,9 +75,11 @@ static textwindows int SyncDirectory(int df, char16_t path[PATH_MAX], int n) {
|
|||
}
|
||||
|
||||
static textwindows bool IsDirectorySymlink(const char16_t *path) {
|
||||
int e;
|
||||
int64_t h;
|
||||
struct NtWin32FindData data;
|
||||
struct NtWin32FileAttributeData info;
|
||||
e = errno;
|
||||
if (GetFileAttributesEx(path, 0, &info) &&
|
||||
((info.dwFileAttributes & kNtFileAttributeDirectory) &&
|
||||
(info.dwFileAttributes & kNtFileAttributeReparsePoint)) &&
|
||||
|
@ -86,6 +88,7 @@ static textwindows bool IsDirectorySymlink(const char16_t *path) {
|
|||
return data.dwReserved0 == kNtIoReparseTagSymlink ||
|
||||
data.dwReserved0 == kNtIoReparseTagMountPoint;
|
||||
} else {
|
||||
errno = e;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
*/
|
||||
int unlinkat(int dirfd, const char *path, int flags) {
|
||||
int rc;
|
||||
char buf[12];
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) {
|
||||
rc = efault();
|
||||
} else if (weaken(__zipos_notat) && (rc = __zipos_notat(dirfd, path)) == -1) {
|
||||
|
@ -48,6 +49,7 @@ int unlinkat(int dirfd, const char *path, int flags) {
|
|||
} else {
|
||||
rc = sys_unlinkat_nt(dirfd, path, flags);
|
||||
}
|
||||
STRACE("unlinkat(%d, %#s, %#b) → %d% m", dirfd, path, flags, rc);
|
||||
STRACE("unlinkat(%s, %#s, %#b) → %d% m", __strace_dirfd(buf, dirfd), path,
|
||||
flags, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
int utimensat(int dirfd, const char *path, const struct timespec ts[2],
|
||||
int flags) {
|
||||
int rc;
|
||||
char buf[12];
|
||||
if (IsAsan() && (!__asan_is_valid(path, 1) ||
|
||||
(ts && !__asan_is_valid(ts, sizeof(struct timespec) * 2)))) {
|
||||
rc = efault();
|
||||
|
@ -47,11 +48,12 @@ int utimensat(int dirfd, const char *path, const struct timespec ts[2],
|
|||
rc = sys_utimensat_nt(dirfd, path, ts, flags);
|
||||
}
|
||||
if (ts) {
|
||||
STRACE("utimensat(%d, %#s, {{%,ld, %,ld}, {%,ld, %,ld}}, %#b) → %d% m",
|
||||
dirfd, path, ts[0].tv_sec, ts[0].tv_nsec, ts[1].tv_sec,
|
||||
ts[1].tv_nsec, flags, rc);
|
||||
STRACE("utimensat(%s, %#s, {{%,ld, %,ld}, {%,ld, %,ld}}, %#b) → %d% m",
|
||||
__strace_dirfd(buf, dirfd), path, ts[0].tv_sec, ts[0].tv_nsec,
|
||||
ts[1].tv_sec, ts[1].tv_nsec, flags, rc);
|
||||
} else {
|
||||
STRACE("utimensat(%d, %#s, 0, %#b) → %d% m", dirfd, path, flags, rc);
|
||||
STRACE("utimensat(%s, %#s, 0, %#b) → %d% m", __strace_dirfd(buf, dirfd),
|
||||
path, flags, rc);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -49,8 +49,8 @@ static textwindows ssize_t sys_write_nt_impl(int fd, void *data, size_t size,
|
|||
ssize_t offset) {
|
||||
uint32_t sent;
|
||||
struct NtOverlapped overlap;
|
||||
if (WriteFile(g_fds.p[fd].handle, data, clampio(size), &sent,
|
||||
offset2overlap(offset, &overlap))) {
|
||||
if (WriteFile(g_fds.p[fd].handle, data, _clampio(size), &sent,
|
||||
_offset2overlap(offset, &overlap))) {
|
||||
return sent;
|
||||
} else if (GetLastError() == kNtErrorBrokenPipe) {
|
||||
return sys_write_nt_epipe(fd);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue