mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-14 06:59:10 +00:00
Polish recent changes and make improvements
- Simulate SIGPIPE on Windows NT - Fix commandv() regression on Windows NT - Fix sigprocmask() strace bug on OpenBSD - Add many more system calls to --strace logging - Make errno state more pristine in redbean strace
This commit is contained in:
parent
10a766ebd0
commit
39688a73e4
69 changed files with 460 additions and 1976 deletions
|
@ -39,6 +39,6 @@ int chdir(const char *path) {
|
|||
} else {
|
||||
rc = sys_chdir_nt(path);
|
||||
}
|
||||
STRACE("chdir(%#s) → %d% m", path, rc);
|
||||
STRACE("%s(%#s) → %d% m", "chdir", path, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -31,7 +31,16 @@
|
|||
* This function may be used for file descriptors returned by socket,
|
||||
* accept, epoll_create, and zipos file descriptors too.
|
||||
*
|
||||
* This function should never be called twice for the same file
|
||||
* descriptor, regardless of whether or not an error happened. However
|
||||
* that doesn't mean the error should be ignored.
|
||||
*
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @error EINTR means a signal was received while closing (possibly
|
||||
* because linger is enabled) in which case close() does not need to
|
||||
* be called again, since the fd will close in the background, and
|
||||
* chances are that on linux, the fd is already closed, even if the
|
||||
* underlying resource isn't closed yet
|
||||
* @asyncsignalsafe
|
||||
* @vforksafe
|
||||
*/
|
||||
|
@ -56,6 +65,7 @@ int close(int fd) {
|
|||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -146,8 +146,8 @@ noasan char *commandv(const char *name, char pathbuf[hasatleast PATH_MAX]) {
|
|||
e = errno;
|
||||
f = ENOENT;
|
||||
if ((IsWindows() && (FindSuffixed(name, pathbuf, namelen, true, &f) ||
|
||||
FindSuffixed(name, pathbuf, namelen, true, &f) ||
|
||||
FindVerbatim(name, pathbuf, namelen, false, &f) ||
|
||||
FindVerbatim(name, pathbuf, namelen, true, &f) ||
|
||||
FindSuffixed(name, pathbuf, namelen, false, &f) ||
|
||||
FindVerbatim(name, pathbuf, namelen, false, &f))) ||
|
||||
(!IsWindows() && (FindVerbatim(name, pathbuf, namelen, true, &f) ||
|
||||
FindSuffixed(name, pathbuf, namelen, true, &f) ||
|
||||
|
|
|
@ -33,11 +33,17 @@ static noasan char DescribeMapType(int flags) {
|
|||
}
|
||||
}
|
||||
|
||||
noasan char *DescribeMapping(int prot, int flags, char p[hasatleast 8]) {
|
||||
/* asan runtime depends on this function */
|
||||
noasan char *DescribeProt(int prot, char p[hasatleast 4]) {
|
||||
p[0] = (prot & PROT_READ) ? 'r' : '-';
|
||||
p[1] = (prot & PROT_WRITE) ? 'w' : '-';
|
||||
p[2] = (prot & PROT_EXEC) ? 'x' : '-';
|
||||
p[3] = 0;
|
||||
return p;
|
||||
}
|
||||
|
||||
noasan char *DescribeMapping(int prot, int flags, char p[hasatleast 8]) {
|
||||
/* asan runtime depends on this function */
|
||||
DescribeProt(prot, p);
|
||||
p[3] = DescribeMapType(flags);
|
||||
p[4] = (flags & MAP_ANONYMOUS) ? 'a' : '-';
|
||||
p[5] = (flags & MAP_GROWSDOWN) ? 'S' : '-';
|
||||
|
|
|
@ -33,6 +33,7 @@ textwindows noasan struct DirectMap sys_mmap_nt(void *addr, size_t size,
|
|||
int prot, int flags,
|
||||
int64_t handle, int64_t off) {
|
||||
/* asan runtime depends on this function */
|
||||
bool32 rc;
|
||||
uint32_t got;
|
||||
size_t i, upsize;
|
||||
struct DirectMap dm;
|
||||
|
@ -68,9 +69,11 @@ textwindows noasan struct DirectMap sys_mmap_nt(void *addr, size_t size,
|
|||
if (i == size) {
|
||||
return dm;
|
||||
}
|
||||
UnmapViewOfFile(dm.addr);
|
||||
rc = UnmapViewOfFile(dm.addr);
|
||||
STRACE("%s(addr:%p) → %hhhd% m", "UnmapViewOfFile", dm.maphandle, rc);
|
||||
}
|
||||
CloseHandle(dm.maphandle);
|
||||
rc = CloseHandle(dm.maphandle);
|
||||
STRACE("%s(%p) → %hhhd% m", "CloseHandle", dm.maphandle, rc);
|
||||
}
|
||||
} else {
|
||||
dm.maphandle = CreateFileMappingNuma(
|
||||
|
@ -91,7 +94,8 @@ textwindows noasan struct DirectMap sys_mmap_nt(void *addr, size_t size,
|
|||
if (dm.addr) {
|
||||
return dm;
|
||||
} else {
|
||||
CloseHandle(dm.maphandle);
|
||||
rc = CloseHandle(dm.maphandle);
|
||||
STRACE("%s(%p) → %d% m", "CloseHandle", dm.maphandle, rc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/bits/weaken.h"
|
||||
#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,17 @@
|
|||
* @asyncsignalsafe
|
||||
*/
|
||||
int faccessat(int dirfd, const char *path, int mode, uint32_t flags) {
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
|
||||
if (weaken(__zipos_notat) && weaken(__zipos_notat)(dirfd, path) == -1) {
|
||||
return -1; /* TODO(jart): implement me */
|
||||
}
|
||||
if (!IsWindows()) {
|
||||
return sys_faccessat(dirfd, path, mode, flags);
|
||||
int rc;
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) {
|
||||
rc = efault();
|
||||
} else if (weaken(__zipos_notat) &&
|
||||
weaken(__zipos_notat)(dirfd, path) == -1) {
|
||||
rc = -1; /* TODO(jart): implement me */
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_faccessat(dirfd, path, mode, flags);
|
||||
} else {
|
||||
return sys_faccessat_nt(dirfd, path, mode, flags);
|
||||
rc = sys_faccessat_nt(dirfd, path, mode, flags);
|
||||
}
|
||||
STRACE("faccessat(%d, %#s, %#o, %#x) → %d% m", dirfd, path, mode, flags, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/metastat.internal.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/dce.h"
|
||||
|
@ -49,8 +50,11 @@ bool fileexists(const char *path) {
|
|||
struct ZiposUri zipname;
|
||||
uint16_t path16[PATH_MAX];
|
||||
e = errno;
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
|
||||
if (weaken(__zipos_open) && weaken(__zipos_parseuri)(path, &zipname) != -1) {
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) {
|
||||
efault();
|
||||
res = false;
|
||||
} else if (weaken(__zipos_open) &&
|
||||
weaken(__zipos_parseuri)(path, &zipname) != -1) {
|
||||
if (weaken(__zipos_stat)(&zipname, &st.cosmo) != -1) {
|
||||
res = true;
|
||||
} else {
|
||||
|
@ -69,7 +73,7 @@ bool fileexists(const char *path) {
|
|||
} else {
|
||||
res = false;
|
||||
}
|
||||
STRACE("fileexists(%#s) → %hhhd% m", path, res);
|
||||
STRACE("%s(%#s) → %hhhd% m", "fileexists", path, res);
|
||||
if (!res && (errno == ENOENT || errno == ENOTDIR)) {
|
||||
errno = e;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/pushpop.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
|
||||
|
@ -25,6 +26,13 @@ STATIC_YOINK("_init_g_fds");
|
|||
|
||||
hidden struct Fds g_fds;
|
||||
|
||||
static textwindows int64_t GetHandleNt(long a) {
|
||||
int64_t b;
|
||||
b = GetStdHandle(a);
|
||||
STRACE("GetStdHandle(%ld) → %p% m", a, b);
|
||||
return b;
|
||||
}
|
||||
|
||||
hidden textstartup void InitializeFileDescriptors(void) {
|
||||
struct Fds *fds;
|
||||
fds = VEIL("r", &g_fds);
|
||||
|
@ -44,10 +52,10 @@ hidden textstartup void InitializeFileDescriptors(void) {
|
|||
fds->__init_p[STDOUT_FILENO].kind = pushpop(kFdFile);
|
||||
fds->__init_p[STDERR_FILENO].kind = pushpop(kFdFile);
|
||||
fds->__init_p[STDIN_FILENO].handle =
|
||||
GetStdHandle(pushpop(kNtStdInputHandle));
|
||||
GetHandleNt(pushpop(kNtStdInputHandle));
|
||||
fds->__init_p[STDOUT_FILENO].handle =
|
||||
GetStdHandle(pushpop(kNtStdOutputHandle));
|
||||
GetHandleNt(pushpop(kNtStdOutputHandle));
|
||||
fds->__init_p[STDERR_FILENO].handle =
|
||||
GetStdHandle(pushpop(kNtStdErrorHandle));
|
||||
GetHandleNt(pushpop(kNtStdErrorHandle));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -299,7 +299,7 @@ int sys_utimes_nt(const char *, const struct timeval[2]) hidden;
|
|||
ssize_t sys_open_nt(int, const char *, u32, i32) nodiscard hidden;
|
||||
ssize_t sys_read_nt(struct Fd *, const struct iovec *, size_t, ssize_t) hidden;
|
||||
ssize_t sys_readlinkat_nt(int, const char *, char *, size_t) hidden;
|
||||
ssize_t sys_write_nt(struct Fd *, const struct iovec *, size_t, ssize_t) hidden;
|
||||
ssize_t sys_write_nt(int, const struct iovec *, size_t, ssize_t) hidden;
|
||||
int ioctl_tiocgwinsz_nt(struct Fd *, struct winsize *) hidden;
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
|
@ -320,7 +320,7 @@ int sys_getsetpriority_nt(int, int, int, int (*)(int));
|
|||
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(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;
|
||||
unsigned __wincrash_nt(struct NtExceptionPointers *);
|
||||
void *GetProcAddressModule(const char *, const char *) hidden;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
@ -28,6 +29,7 @@
|
|||
* @see ioctl(fd, FIOCLEX, 0) dispatches here
|
||||
*/
|
||||
int ioctl_fioclex(int fd, int req) {
|
||||
int rc;
|
||||
if (fd >= 0) {
|
||||
if (IsWindows() || (fd < g_fds.n && g_fds.p[fd].kind == kFdZip)) {
|
||||
if (__isfdopen(fd)) {
|
||||
|
@ -36,14 +38,16 @@ int ioctl_fioclex(int fd, int req) {
|
|||
} else {
|
||||
g_fds.p[fd].flags &= ~O_CLOEXEC;
|
||||
}
|
||||
return 0;
|
||||
rc = 0;
|
||||
} else {
|
||||
return ebadf();
|
||||
rc = ebadf();
|
||||
}
|
||||
} else {
|
||||
return sys_ioctl(fd, req);
|
||||
rc = sys_ioctl(fd, req);
|
||||
}
|
||||
} else {
|
||||
return einval();
|
||||
rc = einval();
|
||||
}
|
||||
STRACE("%s(%d, %d) → %d% m", "ioctl_fioclex", fd, req, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/str/str.h"
|
||||
|
@ -105,16 +106,19 @@ static int ioctl_siocgifaddr_sysv(int fd, uint64_t op, struct ifreq *ifr) {
|
|||
* @see ioctl(fd, SIOCGIFCONF, tio) dispatches here
|
||||
*/
|
||||
int ioctl_siocgifconf(int fd, ...) {
|
||||
int rc;
|
||||
va_list va;
|
||||
struct ifconf *ifc;
|
||||
va_start(va, fd);
|
||||
ifc = va_arg(va, struct ifconf *);
|
||||
va_end(va);
|
||||
if (!IsWindows()) {
|
||||
return ioctl_siocgifconf_sysv(fd, ifc);
|
||||
rc = ioctl_siocgifconf_sysv(fd, ifc);
|
||||
} else {
|
||||
return ioctl_siocgifconf_nt(fd, ifc);
|
||||
rc = ioctl_siocgifconf_nt(fd, ifc);
|
||||
}
|
||||
STRACE("%s(%d) → %d% m", "ioctl_siocgifconf", fd, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int ioctl_siocgifaddr(int fd, ...) {
|
||||
|
|
|
@ -16,10 +16,13 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/termios.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/nt/console.h"
|
||||
#include "libc/nt/enum/startf.h"
|
||||
#include "libc/nt/startupinfo.h"
|
||||
|
@ -57,6 +60,7 @@ 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/internal.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
|
@ -30,21 +31,25 @@
|
|||
* @see ioctl(fd, TIOCGWINSZ, ws) dispatches here
|
||||
*/
|
||||
int ioctl_tiocgwinsz(int fd, ...) {
|
||||
int rc;
|
||||
va_list va;
|
||||
struct winsize *ws;
|
||||
va_start(va, fd);
|
||||
ws = va_arg(va, struct winsize *);
|
||||
va_end(va);
|
||||
if (IsAsan() && !__asan_is_valid(ws, sizeof(*ws))) return efault();
|
||||
if (fd >= 0) {
|
||||
if (IsAsan() && !__asan_is_valid(ws, sizeof(*ws))) {
|
||||
rc = efault();
|
||||
} else if (fd >= 0) {
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
return enotty();
|
||||
rc = enotty();
|
||||
} else if (!IsWindows()) {
|
||||
return sys_ioctl(fd, TIOCGWINSZ, ws);
|
||||
rc = sys_ioctl(fd, TIOCGWINSZ, ws);
|
||||
} else {
|
||||
return ioctl_tiocgwinsz_nt(g_fds.p + fd, ws);
|
||||
rc = ioctl_tiocgwinsz_nt(g_fds.p + fd, ws);
|
||||
}
|
||||
} else {
|
||||
return einval();
|
||||
rc = einval();
|
||||
}
|
||||
STRACE("%s(%d) → %d% m", "ioctl_tiocgwinsz", fd, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
* return fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW) != -1 &&
|
||||
* S_ISDIR(st.st_mode);
|
||||
*
|
||||
* Except faster and with fewer dependencies.
|
||||
* Except faster, with fewer dependencies, and less errno clobbering.
|
||||
*
|
||||
* @see isregularfile(), issymlink(), ischardev()
|
||||
*/
|
||||
|
@ -49,8 +49,11 @@ bool isdirectory(const char *path) {
|
|||
union metastat st;
|
||||
struct ZiposUri zipname;
|
||||
e = errno;
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
|
||||
if (weaken(__zipos_open) && weaken(__zipos_parseuri)(path, &zipname) != -1) {
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) {
|
||||
efault();
|
||||
res = false;
|
||||
} else if (weaken(__zipos_open) &&
|
||||
weaken(__zipos_parseuri)(path, &zipname) != -1) {
|
||||
if (weaken(__zipos_stat)(&zipname, &st.cosmo) != -1) {
|
||||
res = S_ISDIR(st.cosmo.st_mode);
|
||||
} else {
|
||||
|
@ -59,7 +62,6 @@ bool isdirectory(const char *path) {
|
|||
} else if (IsMetal()) {
|
||||
res = false;
|
||||
} else if (!IsWindows()) {
|
||||
e = errno;
|
||||
if (__sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW) != -1) {
|
||||
res = S_ISDIR(METASTAT(st, st_mode));
|
||||
} else {
|
||||
|
@ -68,7 +70,7 @@ bool isdirectory(const char *path) {
|
|||
} else {
|
||||
res = isdirectory_nt(path);
|
||||
}
|
||||
STRACE("isdirectory(%#s) → %hhhd% m", path, res);
|
||||
STRACE("%s(%#s) → %hhhd% m", "isdirectory", path, res);
|
||||
if (!res && (errno == ENOENT || errno == ENOTDIR)) {
|
||||
errno = e;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/metastat.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
|
@ -35,34 +36,40 @@
|
|||
* return fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW) != -1 &&
|
||||
* S_ISREG(st.st_mode);
|
||||
*
|
||||
* Except faster and with fewer dependencies.
|
||||
* Except faster, with fewer dependencies, and less errno clobbering.
|
||||
*
|
||||
* @see isdirectory(), ischardev(), issymlink()
|
||||
*/
|
||||
bool isregularfile(const char *path) {
|
||||
int e;
|
||||
bool res;
|
||||
union metastat st;
|
||||
struct ZiposUri zipname;
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
|
||||
if (weaken(__zipos_open) && weaken(__zipos_parseuri)(path, &zipname) != -1) {
|
||||
e = errno;
|
||||
e = errno;
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) {
|
||||
efault();
|
||||
res = false;
|
||||
} else if (weaken(__zipos_open) &&
|
||||
weaken(__zipos_parseuri)(path, &zipname) != -1) {
|
||||
if (weaken(__zipos_stat)(&zipname, &st.cosmo) != -1) {
|
||||
return S_ISREG(st.cosmo.st_mode);
|
||||
res = !!S_ISREG(st.cosmo.st_mode);
|
||||
} else {
|
||||
errno = e;
|
||||
return false;
|
||||
res = false;
|
||||
}
|
||||
} else if (IsMetal()) {
|
||||
return false;
|
||||
res = false;
|
||||
} else if (!IsWindows()) {
|
||||
e = errno;
|
||||
if (__sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW) != -1) {
|
||||
return S_ISREG(METASTAT(st, st_mode));
|
||||
res = S_ISREG(METASTAT(st, st_mode));
|
||||
} else {
|
||||
errno = e;
|
||||
return false;
|
||||
res = false;
|
||||
}
|
||||
} else {
|
||||
return isregularfile_nt(path);
|
||||
res = isregularfile_nt(path);
|
||||
}
|
||||
STRACE("%s(%#s) → %hhhd% m", "isregularfile", path, res);
|
||||
if (!res && (errno == ENOENT || errno == ENOTDIR)) {
|
||||
errno = e;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/metastat.internal.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/dce.h"
|
||||
|
@ -44,22 +45,30 @@
|
|||
*/
|
||||
bool issymlink(const char *path) {
|
||||
int e;
|
||||
bool res;
|
||||
union metastat st;
|
||||
struct ZiposUri zipname;
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
|
||||
if (weaken(__zipos_open) && weaken(__zipos_parseuri)(path, &zipname) != -1) {
|
||||
return false;
|
||||
e = errno;
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) {
|
||||
efault();
|
||||
res = false;
|
||||
} else if (weaken(__zipos_open) &&
|
||||
weaken(__zipos_parseuri)(path, &zipname) != -1) {
|
||||
res = false;
|
||||
} else if (IsMetal()) {
|
||||
return false;
|
||||
res = false;
|
||||
} else if (!IsWindows()) {
|
||||
e = errno;
|
||||
if (__sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW) != -1) {
|
||||
return S_ISLNK(METASTAT(st, st_mode));
|
||||
res = S_ISLNK(METASTAT(st, st_mode));
|
||||
} else {
|
||||
errno = e;
|
||||
return false;
|
||||
res = false;
|
||||
}
|
||||
} else {
|
||||
return issymlink_nt(path);
|
||||
res = issymlink_nt(path);
|
||||
}
|
||||
STRACE("%s(%#s) → %hhhd% m", "issymlink", path, res);
|
||||
if (!res && (errno == ENOENT || errno == ENOTDIR)) {
|
||||
errno = e;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -19,10 +19,12 @@
|
|||
#define ShouldUseMsabiAttribute() 1
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/sysv/consts/nr.h"
|
||||
|
||||
/**
|
||||
|
@ -32,10 +34,11 @@
|
|||
* @return 0 on success, or -1 w/ errno
|
||||
* @see mmap()
|
||||
*/
|
||||
noasan noubsan privileged int mprotect(void *addr, uint64_t len, int prot) {
|
||||
noasan noubsan privileged int mprotect(void *addr, size_t len, int prot) {
|
||||
bool cf;
|
||||
int64_t rc;
|
||||
uint32_t oldprot;
|
||||
char protbuf[4];
|
||||
if (!IsWindows()) {
|
||||
asm volatile(CFLAG_ASM("clc\n\tsyscall")
|
||||
: CFLAG_CONSTRAINT(cf), "=a"(rc)
|
||||
|
@ -48,12 +51,14 @@ noasan noubsan privileged int mprotect(void *addr, uint64_t len, int prot) {
|
|||
errno = -rc;
|
||||
rc = -1;
|
||||
}
|
||||
return rc;
|
||||
} else {
|
||||
if (__imp_VirtualProtect(addr, len, __prot2nt(prot, 0), &oldprot)) {
|
||||
return 0;
|
||||
rc = 0;
|
||||
} else {
|
||||
return __winerr();
|
||||
rc = __winerr();
|
||||
}
|
||||
}
|
||||
STRACE("mprotect(%p, %'zu, %s[%#x]) → %d% m", addr, len,
|
||||
DescribeProt(prot, protbuf), prot, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nt/enum/accessmask.h"
|
||||
#include "libc/nt/enum/securityimpersonationlevel.h"
|
||||
|
@ -31,6 +32,7 @@
|
|||
#include "libc/nt/struct/privilegeset.h"
|
||||
#include "libc/nt/struct/securitydescriptor.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/ok.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
@ -104,7 +106,6 @@ TryAgain:
|
|||
}
|
||||
} else {
|
||||
e = GetLastError();
|
||||
STRACE("GetFileSecurity failed: %d %u", e, secsize);
|
||||
if (!IsTiny() && e == kNtErrorInsufficientBuffer) {
|
||||
if (!freeme && weaken(malloc) && (freeme = weaken(malloc)(secsize))) {
|
||||
s = freeme;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/assert.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ntmagicpaths.internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/nt/createfile.h"
|
||||
#include "libc/nt/enum/accessmask.h"
|
||||
#include "libc/nt/enum/creationdisposition.h"
|
||||
|
@ -63,14 +64,15 @@ static textwindows int64_t sys_open_nt_impl(int dirfd, const char *path,
|
|||
kNtFileFlagBackupSemantics | kNtFileFlagPosixSemantics |
|
||||
kNtFileAttributeTemporary)))),
|
||||
0)) != -1) {
|
||||
return handle;
|
||||
} else if (GetLastError() == kNtErrorFileExists &&
|
||||
((flags & O_CREAT) &&
|
||||
(flags & O_TRUNC))) { /* TODO(jart): What was this? */
|
||||
return eisdir();
|
||||
handle = eisdir();
|
||||
} else {
|
||||
return __winerr();
|
||||
handle = __winerr();
|
||||
}
|
||||
STRACE("CreateFile() → %ld% m", handle);
|
||||
return handle;
|
||||
}
|
||||
|
||||
static textwindows ssize_t sys_open_nt_console(int dirfd,
|
||||
|
|
|
@ -61,11 +61,15 @@
|
|||
char program_executable_name[SIZE];
|
||||
|
||||
static textwindows bool GetNtExePath(char executable[SIZE]) {
|
||||
bool32 rc;
|
||||
uint64_t w;
|
||||
wint_t x, y;
|
||||
uint32_t i, j;
|
||||
char16_t path16[PATH_MAX + 1];
|
||||
if (!GetModuleFileName(0, path16, ARRAYLEN(path16))) return 0;
|
||||
path16[0] = 0;
|
||||
rc = GetModuleFileName(0, path16, ARRAYLEN(path16));
|
||||
STRACE("GetModuleFileName(0, [%#hs]) → %hhhd", path16, rc);
|
||||
if (!rc) return false;
|
||||
for (i = j = 0; (x = path16[i++] & 0xffff);) {
|
||||
if (!IsUcs2(x)) {
|
||||
y = path16[i++] & 0xffff;
|
||||
|
|
|
@ -45,7 +45,7 @@ ssize_t pwrite(int fd, const void *buf, size_t size, int64_t offset) {
|
|||
if (!IsWindows()) {
|
||||
rc = sys_pwrite(fd, buf, size, offset, offset);
|
||||
} else if (__isfdkind(fd, kFdFile)) {
|
||||
rc = sys_write_nt(&g_fds.p[fd], (struct iovec[]){{buf, size}}, 1, offset);
|
||||
rc = sys_write_nt(fd, (struct iovec[]){{buf, size}}, 1, offset);
|
||||
} else {
|
||||
return ebadf();
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ ssize_t pwritev(int fd, const struct iovec *iov, int iovlen, int64_t off) {
|
|||
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, off);
|
||||
} else if (IsWindows()) {
|
||||
if (fd < g_fds.n) {
|
||||
return sys_write_nt(g_fds.p + fd, iov, iovlen, off);
|
||||
return sys_write_nt(fd, iov, iovlen, off);
|
||||
} else {
|
||||
return ebadf();
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
|
@ -23,6 +24,8 @@
|
|||
#include "libc/dce.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/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
@ -55,6 +58,7 @@ int sigprocmask(int how, const sigset_t *opt_set, sigset_t *opt_out_oldset) {
|
|||
char howbuf[12];
|
||||
char buf[2][41];
|
||||
sigset_t old, *oldp;
|
||||
const sigset_t *arg;
|
||||
if (!(IsAsan() &&
|
||||
((opt_set && !__asan_is_valid(opt_set, sizeof(*opt_set))) ||
|
||||
(opt_out_oldset &&
|
||||
|
@ -75,9 +79,14 @@ int sigprocmask(int how, const sigset_t *opt_set, sigset_t *opt_out_oldset) {
|
|||
rc = -1;
|
||||
}
|
||||
} else if (IsOpenbsd()) {
|
||||
if (!opt_set) how = 1;
|
||||
if (opt_set) opt_set = (sigset_t *)(uintptr_t)(*(uint32_t *)opt_set);
|
||||
if ((x = sys_sigprocmask(how, opt_set, 0, 0)) != -1) {
|
||||
if (opt_set) {
|
||||
/* openbsd only supports 32 signals so it passses them in a reg */
|
||||
arg = (sigset_t *)(uintptr_t)(*(uint32_t *)opt_set);
|
||||
} else {
|
||||
how = 1; /* SIG_BLOCK */
|
||||
arg = 0; /* changes nothing */
|
||||
}
|
||||
if ((x = sys_sigprocmask(how, arg, 0, 0)) != -1) {
|
||||
if (opt_out_oldset) {
|
||||
bzero(opt_out_oldset, sizeof(*opt_out_oldset));
|
||||
memcpy(opt_out_oldset, &x, sizeof(x));
|
||||
|
|
|
@ -16,12 +16,16 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/nt/console.h"
|
||||
#include "libc/nt/enum/consolemodeflags.h"
|
||||
|
@ -75,17 +79,20 @@ static int ttyname_linux(int fd, char *buf, size_t size) {
|
|||
* Returns name of terminal, reentrantly.
|
||||
*/
|
||||
int ttyname_r(int fd, char *buf, size_t size) {
|
||||
int rc;
|
||||
if (IsLinux()) {
|
||||
return ttyname_linux(fd, buf, size);
|
||||
rc = ttyname_linux(fd, buf, size);
|
||||
} else if (IsFreebsd()) {
|
||||
return ttyname_freebsd(fd, buf, size);
|
||||
rc = ttyname_freebsd(fd, buf, size);
|
||||
} else if (IsWindows()) {
|
||||
if (__isfdkind(fd, kFdFile)) {
|
||||
return sys_ttyname_nt(fd, buf, size);
|
||||
rc = sys_ttyname_nt(fd, buf, size);
|
||||
} else {
|
||||
return ebadf();
|
||||
rc = ebadf();
|
||||
}
|
||||
} else {
|
||||
return enosys();
|
||||
rc = enosys();
|
||||
}
|
||||
STRACE("ttyname_r(%d, %s) → %d% m", fd, buf, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/bits/weaken.h"
|
||||
#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"
|
||||
|
@ -35,13 +36,16 @@
|
|||
* @return 0 on success, or -1 w/ errno
|
||||
*/
|
||||
int unlinkat(int dirfd, const char *path, int flags) {
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
|
||||
if (weaken(__zipos_notat) && weaken(__zipos_notat)(dirfd, path) == -1) {
|
||||
return -1; /* TODO(jart): implement me */
|
||||
}
|
||||
if (!IsWindows()) {
|
||||
return sys_unlinkat(dirfd, path, flags);
|
||||
int rc;
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) {
|
||||
rc = efault();
|
||||
} else if (weaken(__zipos_notat) && (rc = __zipos_notat(dirfd, path)) == -1) {
|
||||
STRACE("zipos unlinkat not supported yet");
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_unlinkat(dirfd, path, flags);
|
||||
} else {
|
||||
return sys_unlinkat_nt(dirfd, path, flags);
|
||||
rc = sys_unlinkat_nt(dirfd, path, flags);
|
||||
}
|
||||
STRACE("unlinkat(%d, %#s, %#b) → %d% m", dirfd, path, flags, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/bits/weaken.h"
|
||||
#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/errfuns.h"
|
||||
|
@ -34,16 +35,23 @@
|
|||
*/
|
||||
int utimensat(int dirfd, const char *path, const struct timespec ts[2],
|
||||
int flags) {
|
||||
int rc;
|
||||
if (IsAsan() && (!__asan_is_valid(path, 1) ||
|
||||
(ts && !__asan_is_valid(ts, sizeof(struct timespec) * 2)))) {
|
||||
return efault();
|
||||
}
|
||||
if (weaken(__zipos_notat) && weaken(__zipos_notat)(dirfd, path) == -1) {
|
||||
return -1; /* TODO(jart): implement me */
|
||||
}
|
||||
if (!IsWindows()) {
|
||||
return sys_utimensat(dirfd, path, ts, flags);
|
||||
rc = efault();
|
||||
} else if (weaken(__zipos_notat) && (rc = __zipos_notat(dirfd, path)) == -1) {
|
||||
STRACE("zipos mkdirat not supported yet");
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_utimensat(dirfd, path, ts, flags);
|
||||
} else {
|
||||
return sys_utimensat_nt(dirfd, path, ts, flags);
|
||||
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);
|
||||
} else {
|
||||
STRACE("utimensat(%d, %#s, 0, %#b) → %d% m", dirfd, path, flags, rc);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#define ShouldUseMsabiAttribute() 1
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
|
@ -30,16 +31,16 @@
|
|||
* @return -1 w/ few exceptions
|
||||
* @note this is a code-size saving device
|
||||
*/
|
||||
privileged noasan int64_t __winerr(void) {
|
||||
privileged int64_t __winerr(void) {
|
||||
errno_t e;
|
||||
if (IsWindows()) {
|
||||
e = GetLastError();
|
||||
e = __imp_GetLastError();
|
||||
if (weaken(__dos2errno)) {
|
||||
e = weaken(__dos2errno)(e);
|
||||
}
|
||||
errno = e;
|
||||
return -1;
|
||||
} else {
|
||||
return enosys();
|
||||
e = ENOSYS;
|
||||
}
|
||||
errno = e;
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -18,28 +18,47 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/calls/struct/siginfo.h"
|
||||
#include "libc/calls/typedef/sigaction_f.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/overlapped.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static textwindows ssize_t sys_write_nt_impl(struct Fd *fd, void *data,
|
||||
size_t size, ssize_t offset) {
|
||||
static textwindows ssize_t sys_write_nt_epipe(int fd) {
|
||||
siginfo_t info;
|
||||
STRACE("WriteFile(%d:%p) → %m", fd, g_fds.p[fd].handle);
|
||||
if (!__sighandrvas[SIGPIPE]) {
|
||||
_Exit(128 + SIGPIPE);
|
||||
} else if (__sighandrvas[SIGPIPE] >= kSigactionMinRva) {
|
||||
bzero(&info, sizeof(info));
|
||||
((sigaction_f)(_base + __sighandrvas[SIGPIPE]))(SIGPIPE, &info, 0);
|
||||
}
|
||||
return epipe();
|
||||
}
|
||||
|
||||
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(fd->handle, data, clampio(size), &sent,
|
||||
if (WriteFile(g_fds.p[fd].handle, data, clampio(size), &sent,
|
||||
offset2overlap(offset, &overlap))) {
|
||||
/* TODO(jart): Trigger SIGPIPE on kNtErrorBrokenPipe */
|
||||
return sent;
|
||||
} else if (GetLastError() == kNtErrorBrokenPipe) {
|
||||
return sys_write_nt_epipe(fd);
|
||||
} else {
|
||||
return __winerr();
|
||||
}
|
||||
}
|
||||
|
||||
textwindows ssize_t sys_write_nt(struct Fd *fd, const struct iovec *iov,
|
||||
size_t iovlen, ssize_t opt_offset) {
|
||||
textwindows ssize_t sys_write_nt(int fd, const struct iovec *iov, size_t iovlen,
|
||||
ssize_t opt_offset) {
|
||||
ssize_t rc;
|
||||
size_t i, total;
|
||||
uint32_t size, wrote;
|
||||
|
|
|
@ -50,7 +50,7 @@ ssize_t write(int fd, const void *buf, size_t size) {
|
|||
} else if (IsMetal()) {
|
||||
return sys_writev_metal(g_fds.p + fd, &(struct iovec){buf, size}, 1);
|
||||
} else {
|
||||
return sys_writev_nt(g_fds.p + fd, &(struct iovec){buf, size}, 1);
|
||||
return sys_writev_nt(fd, &(struct iovec){buf, size}, 1);
|
||||
}
|
||||
} else {
|
||||
return einval();
|
||||
|
|
|
@ -21,9 +21,8 @@
|
|||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows ssize_t sys_writev_nt(struct Fd *fd, const struct iovec *iov,
|
||||
int iovlen) {
|
||||
switch (fd->kind) {
|
||||
textwindows ssize_t sys_writev_nt(int fd, const struct iovec *iov, int iovlen) {
|
||||
switch (g_fds.p[fd].kind) {
|
||||
case kFdFile:
|
||||
case kFdConsole:
|
||||
return sys_write_nt(fd, iov, iovlen, -1);
|
||||
|
|
|
@ -47,7 +47,7 @@ ssize_t writev(int fd, const struct iovec *iov, int iovlen) {
|
|||
} else if (IsMetal()) {
|
||||
return sys_writev_metal(g_fds.p + fd, iov, iovlen);
|
||||
} else {
|
||||
return sys_writev_nt(g_fds.p + fd, iov, iovlen);
|
||||
return sys_writev_nt(fd, iov, iovlen);
|
||||
}
|
||||
} else {
|
||||
return einval();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue