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:
Justine Tunney 2022-04-07 20:30:04 -07:00
parent 29bf8b1a30
commit 4f98ad1054
79 changed files with 707 additions and 197 deletions

View file

@ -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) {

View file

@ -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;
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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 {

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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"

View file

@ -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;
}

View file

@ -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;

View file

@ -63,7 +63,6 @@ textwindows int ioctl_tiocgwinsz_nt(struct Fd *fd, struct winsize *ws) {
__winerr();
}
} else {
STRACE("%s() failed %m", "GetConsoleMode");
enotty();
}
} else {

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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

View file

@ -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);

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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) */

View 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;
}

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);