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:
Justine Tunney 2022-03-19 03:37:00 -07:00
parent 10a766ebd0
commit 39688a73e4
69 changed files with 460 additions and 1976 deletions

View file

@ -39,6 +39,6 @@ int chdir(const char *path) {
} else { } else {
rc = sys_chdir_nt(path); rc = sys_chdir_nt(path);
} }
STRACE("chdir(%#s) → %d% m", path, rc); STRACE("%s(%#s) → %d% m", "chdir", path, rc);
return rc; return rc;
} }

View file

@ -31,7 +31,16 @@
* This function may be used for file descriptors returned by socket, * This function may be used for file descriptors returned by socket,
* accept, epoll_create, and zipos file descriptors too. * 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 * @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 * @asyncsignalsafe
* @vforksafe * @vforksafe
*/ */
@ -56,6 +65,7 @@ int close(int fd) {
g_fds.p[fd].kind == kFdProcess)) { g_fds.p[fd].kind == kFdProcess)) {
rc = sys_close_nt(g_fds.p + fd); rc = sys_close_nt(g_fds.p + fd);
} else { } else {
STRACE("close(%d) unknown kind: %d", fd, g_fds.p[fd].kind);
rc = ebadf(); rc = ebadf();
} }
} }

View file

@ -146,8 +146,8 @@ noasan char *commandv(const char *name, char pathbuf[hasatleast PATH_MAX]) {
e = errno; e = errno;
f = ENOENT; f = ENOENT;
if ((IsWindows() && (FindSuffixed(name, pathbuf, namelen, true, &f) || if ((IsWindows() && (FindSuffixed(name, pathbuf, namelen, true, &f) ||
FindSuffixed(name, pathbuf, namelen, true, &f) || FindVerbatim(name, pathbuf, namelen, true, &f) ||
FindVerbatim(name, pathbuf, namelen, false, &f) || FindSuffixed(name, pathbuf, namelen, false, &f) ||
FindVerbatim(name, pathbuf, namelen, false, &f))) || FindVerbatim(name, pathbuf, namelen, false, &f))) ||
(!IsWindows() && (FindVerbatim(name, pathbuf, namelen, true, &f) || (!IsWindows() && (FindVerbatim(name, pathbuf, namelen, true, &f) ||
FindSuffixed(name, pathbuf, namelen, true, &f) || FindSuffixed(name, pathbuf, namelen, true, &f) ||

View file

@ -33,11 +33,17 @@ static noasan char DescribeMapType(int flags) {
} }
} }
noasan char *DescribeMapping(int prot, int flags, char p[hasatleast 8]) { noasan char *DescribeProt(int prot, char p[hasatleast 4]) {
/* asan runtime depends on this function */
p[0] = (prot & PROT_READ) ? 'r' : '-'; p[0] = (prot & PROT_READ) ? 'r' : '-';
p[1] = (prot & PROT_WRITE) ? 'w' : '-'; p[1] = (prot & PROT_WRITE) ? 'w' : '-';
p[2] = (prot & PROT_EXEC) ? 'x' : '-'; 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[3] = DescribeMapType(flags);
p[4] = (flags & MAP_ANONYMOUS) ? 'a' : '-'; p[4] = (flags & MAP_ANONYMOUS) ? 'a' : '-';
p[5] = (flags & MAP_GROWSDOWN) ? 'S' : '-'; p[5] = (flags & MAP_GROWSDOWN) ? 'S' : '-';

View file

@ -33,6 +33,7 @@ textwindows noasan struct DirectMap sys_mmap_nt(void *addr, size_t size,
int prot, int flags, int prot, int flags,
int64_t handle, int64_t off) { int64_t handle, int64_t off) {
/* asan runtime depends on this function */ /* asan runtime depends on this function */
bool32 rc;
uint32_t got; uint32_t got;
size_t i, upsize; size_t i, upsize;
struct DirectMap dm; struct DirectMap dm;
@ -68,9 +69,11 @@ textwindows noasan struct DirectMap sys_mmap_nt(void *addr, size_t size,
if (i == size) { if (i == size) {
return dm; 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 { } else {
dm.maphandle = CreateFileMappingNuma( dm.maphandle = CreateFileMappingNuma(
@ -91,7 +94,8 @@ textwindows noasan struct DirectMap sys_mmap_nt(void *addr, size_t size,
if (dm.addr) { if (dm.addr) {
return dm; return dm;
} else { } else {
CloseHandle(dm.maphandle); rc = CloseHandle(dm.maphandle);
STRACE("%s(%p) → %d% m", "CloseHandle", dm.maphandle, rc);
} }
} }
} }

View file

@ -19,6 +19,7 @@
#include "libc/bits/weaken.h" #include "libc/bits/weaken.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h" #include "libc/intrin/asan.internal.h"
#include "libc/sysv/consts/at.h" #include "libc/sysv/consts/at.h"
@ -37,13 +38,17 @@
* @asyncsignalsafe * @asyncsignalsafe
*/ */
int faccessat(int dirfd, const char *path, int mode, uint32_t flags) { int faccessat(int dirfd, const char *path, int mode, uint32_t flags) {
if (IsAsan() && !__asan_is_valid(path, 1)) return efault(); int rc;
if (weaken(__zipos_notat) && weaken(__zipos_notat)(dirfd, path) == -1) { if (IsAsan() && !__asan_is_valid(path, 1)) {
return -1; /* TODO(jart): implement me */ rc = efault();
} } else if (weaken(__zipos_notat) &&
if (!IsWindows()) { weaken(__zipos_notat)(dirfd, path) == -1) {
return sys_faccessat(dirfd, path, mode, flags); rc = -1; /* TODO(jart): implement me */
} else if (!IsWindows()) {
rc = sys_faccessat(dirfd, path, mode, flags);
} else { } 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;
} }

View file

@ -19,6 +19,7 @@
#include "libc/bits/weaken.h" #include "libc/bits/weaken.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/metastat.internal.h" #include "libc/calls/struct/metastat.internal.h"
#include "libc/calls/struct/stat.h" #include "libc/calls/struct/stat.h"
#include "libc/dce.h" #include "libc/dce.h"
@ -49,8 +50,11 @@ bool fileexists(const char *path) {
struct ZiposUri zipname; struct ZiposUri zipname;
uint16_t path16[PATH_MAX]; uint16_t path16[PATH_MAX];
e = errno; e = errno;
if (IsAsan() && !__asan_is_valid(path, 1)) return efault(); if (IsAsan() && !__asan_is_valid(path, 1)) {
if (weaken(__zipos_open) && weaken(__zipos_parseuri)(path, &zipname) != -1) { efault();
res = false;
} else if (weaken(__zipos_open) &&
weaken(__zipos_parseuri)(path, &zipname) != -1) {
if (weaken(__zipos_stat)(&zipname, &st.cosmo) != -1) { if (weaken(__zipos_stat)(&zipname, &st.cosmo) != -1) {
res = true; res = true;
} else { } else {
@ -69,7 +73,7 @@ bool fileexists(const char *path) {
} else { } else {
res = false; res = false;
} }
STRACE("fileexists(%#s) → %hhhd% m", path, res); STRACE("%s(%#s) → %hhhd% m", "fileexists", path, res);
if (!res && (errno == ENOENT || errno == ENOTDIR)) { if (!res && (errno == ENOENT || errno == ENOTDIR)) {
errno = e; errno = e;
} }

View file

@ -18,6 +18,7 @@
*/ */
#include "libc/bits/pushpop.h" #include "libc/bits/pushpop.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/nt/runtime.h" #include "libc/nt/runtime.h"
#include "libc/sysv/consts/fileno.h" #include "libc/sysv/consts/fileno.h"
@ -25,6 +26,13 @@ STATIC_YOINK("_init_g_fds");
hidden struct Fds 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) { hidden textstartup void InitializeFileDescriptors(void) {
struct Fds *fds; struct Fds *fds;
fds = VEIL("r", &g_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[STDOUT_FILENO].kind = pushpop(kFdFile);
fds->__init_p[STDERR_FILENO].kind = pushpop(kFdFile); fds->__init_p[STDERR_FILENO].kind = pushpop(kFdFile);
fds->__init_p[STDIN_FILENO].handle = fds->__init_p[STDIN_FILENO].handle =
GetStdHandle(pushpop(kNtStdInputHandle)); GetHandleNt(pushpop(kNtStdInputHandle));
fds->__init_p[STDOUT_FILENO].handle = fds->__init_p[STDOUT_FILENO].handle =
GetStdHandle(pushpop(kNtStdOutputHandle)); GetHandleNt(pushpop(kNtStdOutputHandle));
fds->__init_p[STDERR_FILENO].handle = fds->__init_p[STDERR_FILENO].handle =
GetStdHandle(pushpop(kNtStdErrorHandle)); GetHandleNt(pushpop(kNtStdErrorHandle));
} }
} }

View file

@ -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_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_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_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; 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 __winerr(void) nocallback privileged;
int64_t ntreturn(uint32_t); int64_t ntreturn(uint32_t);
ssize_t sys_readv_nt(struct Fd *, const struct iovec *, int) hidden; 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; struct NtOverlapped *offset2overlap(int64_t, struct NtOverlapped *) hidden;
unsigned __wincrash_nt(struct NtExceptionPointers *); unsigned __wincrash_nt(struct NtExceptionPointers *);
void *GetProcAddressModule(const char *, const char *) hidden; void *GetProcAddressModule(const char *, const char *) hidden;

View file

@ -18,6 +18,7 @@
*/ */
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/ioctl.h" #include "libc/calls/ioctl.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/sysv/consts/o.h" #include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
@ -28,6 +29,7 @@
* @see ioctl(fd, FIOCLEX, 0) dispatches here * @see ioctl(fd, FIOCLEX, 0) dispatches here
*/ */
int ioctl_fioclex(int fd, int req) { int ioctl_fioclex(int fd, int req) {
int rc;
if (fd >= 0) { if (fd >= 0) {
if (IsWindows() || (fd < g_fds.n && g_fds.p[fd].kind == kFdZip)) { if (IsWindows() || (fd < g_fds.n && g_fds.p[fd].kind == kFdZip)) {
if (__isfdopen(fd)) { if (__isfdopen(fd)) {
@ -36,14 +38,16 @@ int ioctl_fioclex(int fd, int req) {
} else { } else {
g_fds.p[fd].flags &= ~O_CLOEXEC; g_fds.p[fd].flags &= ~O_CLOEXEC;
} }
return 0; rc = 0;
} else { } else {
return ebadf(); rc = ebadf();
} }
} else { } else {
return sys_ioctl(fd, req); rc = sys_ioctl(fd, req);
} }
} else { } else {
return einval(); rc = einval();
} }
STRACE("%s(%d, %d) → %d% m", "ioctl_fioclex", fd, req, rc);
return rc;
} }

View file

@ -21,6 +21,7 @@
#include "libc/bits/weaken.h" #include "libc/bits/weaken.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/ioctl.h" #include "libc/calls/ioctl.h"
#include "libc/calls/strace.internal.h"
#include "libc/sock/internal.h" #include "libc/sock/internal.h"
#include "libc/sock/sock.h" #include "libc/sock/sock.h"
#include "libc/str/str.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 * @see ioctl(fd, SIOCGIFCONF, tio) dispatches here
*/ */
int ioctl_siocgifconf(int fd, ...) { int ioctl_siocgifconf(int fd, ...) {
int rc;
va_list va; va_list va;
struct ifconf *ifc; struct ifconf *ifc;
va_start(va, fd); va_start(va, fd);
ifc = va_arg(va, struct ifconf *); ifc = va_arg(va, struct ifconf *);
va_end(va); va_end(va);
if (!IsWindows()) { if (!IsWindows()) {
return ioctl_siocgifconf_sysv(fd, ifc); rc = ioctl_siocgifconf_sysv(fd, ifc);
} else { } 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, ...) { int ioctl_siocgifaddr(int fd, ...) {

View file

@ -16,10 +16,13 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/termios.h" #include "libc/calls/struct/termios.h"
#include "libc/calls/struct/winsize.h" #include "libc/calls/struct/winsize.h"
#include "libc/log/log.h"
#include "libc/nt/console.h" #include "libc/nt/console.h"
#include "libc/nt/enum/startf.h" #include "libc/nt/enum/startf.h"
#include "libc/nt/startupinfo.h" #include "libc/nt/startupinfo.h"
@ -57,6 +60,7 @@ textwindows int ioctl_tiocgwinsz_nt(struct Fd *fd, struct winsize *ws) {
__winerr(); __winerr();
} }
} else { } else {
STRACE("%s() failed %m", "GetConsoleMode");
enotty(); enotty();
} }
} else { } else {

View file

@ -18,6 +18,7 @@
*/ */
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/ioctl.h" #include "libc/calls/ioctl.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/winsize.h" #include "libc/calls/struct/winsize.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h" #include "libc/intrin/asan.internal.h"
@ -30,21 +31,25 @@
* @see ioctl(fd, TIOCGWINSZ, ws) dispatches here * @see ioctl(fd, TIOCGWINSZ, ws) dispatches here
*/ */
int ioctl_tiocgwinsz(int fd, ...) { int ioctl_tiocgwinsz(int fd, ...) {
int rc;
va_list va; va_list va;
struct winsize *ws; struct winsize *ws;
va_start(va, fd); va_start(va, fd);
ws = va_arg(va, struct winsize *); ws = va_arg(va, struct winsize *);
va_end(va); va_end(va);
if (IsAsan() && !__asan_is_valid(ws, sizeof(*ws))) return efault(); if (IsAsan() && !__asan_is_valid(ws, sizeof(*ws))) {
if (fd >= 0) { rc = efault();
} else if (fd >= 0) {
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) { if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
return enotty(); rc = enotty();
} else if (!IsWindows()) { } else if (!IsWindows()) {
return sys_ioctl(fd, TIOCGWINSZ, ws); rc = sys_ioctl(fd, TIOCGWINSZ, ws);
} else { } else {
return ioctl_tiocgwinsz_nt(g_fds.p + fd, ws); rc = ioctl_tiocgwinsz_nt(g_fds.p + fd, ws);
} }
} else { } else {
return einval(); rc = einval();
} }
STRACE("%s(%d) → %d% m", "ioctl_tiocgwinsz", fd, rc);
return rc;
} }

View file

@ -39,7 +39,7 @@
* return fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW) != -1 && * return fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW) != -1 &&
* S_ISDIR(st.st_mode); * S_ISDIR(st.st_mode);
* *
* Except faster and with fewer dependencies. * Except faster, with fewer dependencies, and less errno clobbering.
* *
* @see isregularfile(), issymlink(), ischardev() * @see isregularfile(), issymlink(), ischardev()
*/ */
@ -49,8 +49,11 @@ bool isdirectory(const char *path) {
union metastat st; union metastat st;
struct ZiposUri zipname; struct ZiposUri zipname;
e = errno; e = errno;
if (IsAsan() && !__asan_is_valid(path, 1)) return efault(); if (IsAsan() && !__asan_is_valid(path, 1)) {
if (weaken(__zipos_open) && weaken(__zipos_parseuri)(path, &zipname) != -1) { efault();
res = false;
} else if (weaken(__zipos_open) &&
weaken(__zipos_parseuri)(path, &zipname) != -1) {
if (weaken(__zipos_stat)(&zipname, &st.cosmo) != -1) { if (weaken(__zipos_stat)(&zipname, &st.cosmo) != -1) {
res = S_ISDIR(st.cosmo.st_mode); res = S_ISDIR(st.cosmo.st_mode);
} else { } else {
@ -59,7 +62,6 @@ bool isdirectory(const char *path) {
} else if (IsMetal()) { } else if (IsMetal()) {
res = false; res = false;
} else if (!IsWindows()) { } else if (!IsWindows()) {
e = errno;
if (__sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW) != -1) { if (__sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW) != -1) {
res = S_ISDIR(METASTAT(st, st_mode)); res = S_ISDIR(METASTAT(st, st_mode));
} else { } else {
@ -68,7 +70,7 @@ bool isdirectory(const char *path) {
} else { } else {
res = isdirectory_nt(path); 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)) { if (!res && (errno == ENOENT || errno == ENOTDIR)) {
errno = e; errno = e;
} }

View file

@ -19,6 +19,7 @@
#include "libc/bits/weaken.h" #include "libc/bits/weaken.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/metastat.internal.h" #include "libc/calls/struct/metastat.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/errno.h" #include "libc/errno.h"
@ -35,34 +36,40 @@
* return fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW) != -1 && * return fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW) != -1 &&
* S_ISREG(st.st_mode); * S_ISREG(st.st_mode);
* *
* Except faster and with fewer dependencies. * Except faster, with fewer dependencies, and less errno clobbering.
* *
* @see isdirectory(), ischardev(), issymlink() * @see isdirectory(), ischardev(), issymlink()
*/ */
bool isregularfile(const char *path) { bool isregularfile(const char *path) {
int e; int e;
bool res;
union metastat st; union metastat st;
struct ZiposUri zipname; struct ZiposUri zipname;
if (IsAsan() && !__asan_is_valid(path, 1)) return efault(); e = errno;
if (weaken(__zipos_open) && weaken(__zipos_parseuri)(path, &zipname) != -1) { if (IsAsan() && !__asan_is_valid(path, 1)) {
e = errno; efault();
res = false;
} else if (weaken(__zipos_open) &&
weaken(__zipos_parseuri)(path, &zipname) != -1) {
if (weaken(__zipos_stat)(&zipname, &st.cosmo) != -1) { if (weaken(__zipos_stat)(&zipname, &st.cosmo) != -1) {
return S_ISREG(st.cosmo.st_mode); res = !!S_ISREG(st.cosmo.st_mode);
} else { } else {
errno = e; res = false;
return false;
} }
} else if (IsMetal()) { } else if (IsMetal()) {
return false; res = false;
} else if (!IsWindows()) { } else if (!IsWindows()) {
e = errno;
if (__sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW) != -1) { 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 { } else {
errno = e; res = false;
return false;
} }
} else { } 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;
} }

View file

@ -19,6 +19,7 @@
#include "libc/bits/weaken.h" #include "libc/bits/weaken.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/metastat.internal.h" #include "libc/calls/struct/metastat.internal.h"
#include "libc/calls/struct/stat.h" #include "libc/calls/struct/stat.h"
#include "libc/dce.h" #include "libc/dce.h"
@ -44,22 +45,30 @@
*/ */
bool issymlink(const char *path) { bool issymlink(const char *path) {
int e; int e;
bool res;
union metastat st; union metastat st;
struct ZiposUri zipname; struct ZiposUri zipname;
if (IsAsan() && !__asan_is_valid(path, 1)) return efault(); e = errno;
if (weaken(__zipos_open) && weaken(__zipos_parseuri)(path, &zipname) != -1) { if (IsAsan() && !__asan_is_valid(path, 1)) {
return false; efault();
res = false;
} else if (weaken(__zipos_open) &&
weaken(__zipos_parseuri)(path, &zipname) != -1) {
res = false;
} else if (IsMetal()) { } else if (IsMetal()) {
return false; res = false;
} else if (!IsWindows()) { } else if (!IsWindows()) {
e = errno;
if (__sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW) != -1) { 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 { } else {
errno = e; res = false;
return false;
} }
} else { } 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;
} }

View file

@ -19,10 +19,12 @@
#define ShouldUseMsabiAttribute() 1 #define ShouldUseMsabiAttribute() 1
#include "libc/bits/bits.h" #include "libc/bits/bits.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/nt/memory.h" #include "libc/nt/memory.h"
#include "libc/nt/thunk/msabi.h" #include "libc/nt/thunk/msabi.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/sysv/consts/nr.h" #include "libc/sysv/consts/nr.h"
/** /**
@ -32,10 +34,11 @@
* @return 0 on success, or -1 w/ errno * @return 0 on success, or -1 w/ errno
* @see mmap() * @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; bool cf;
int64_t rc; int64_t rc;
uint32_t oldprot; uint32_t oldprot;
char protbuf[4];
if (!IsWindows()) { if (!IsWindows()) {
asm volatile(CFLAG_ASM("clc\n\tsyscall") asm volatile(CFLAG_ASM("clc\n\tsyscall")
: CFLAG_CONSTRAINT(cf), "=a"(rc) : CFLAG_CONSTRAINT(cf), "=a"(rc)
@ -48,12 +51,14 @@ noasan noubsan privileged int mprotect(void *addr, uint64_t len, int prot) {
errno = -rc; errno = -rc;
rc = -1; rc = -1;
} }
return rc;
} else { } else {
if (__imp_VirtualProtect(addr, len, __prot2nt(prot, 0), &oldprot)) { if (__imp_VirtualProtect(addr, len, __prot2nt(prot, 0), &oldprot)) {
return 0; rc = 0;
} else { } else {
return __winerr(); rc = __winerr();
} }
} }
STRACE("mprotect(%p, %'zu, %s[%#x]) → %d% m", addr, len,
DescribeProt(prot, protbuf), prot, rc);
return rc;
} }

View file

@ -20,6 +20,7 @@
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h" #include "libc/calls/strace.internal.h"
#include "libc/fmt/fmt.h"
#include "libc/mem/mem.h" #include "libc/mem/mem.h"
#include "libc/nt/enum/accessmask.h" #include "libc/nt/enum/accessmask.h"
#include "libc/nt/enum/securityimpersonationlevel.h" #include "libc/nt/enum/securityimpersonationlevel.h"
@ -31,6 +32,7 @@
#include "libc/nt/struct/privilegeset.h" #include "libc/nt/struct/privilegeset.h"
#include "libc/nt/struct/securitydescriptor.h" #include "libc/nt/struct/securitydescriptor.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/sock/internal.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/sysv/consts/ok.h" #include "libc/sysv/consts/ok.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
@ -104,7 +106,6 @@ TryAgain:
} }
} else { } else {
e = GetLastError(); e = GetLastError();
STRACE("GetFileSecurity failed: %d %u", e, secsize);
if (!IsTiny() && e == kNtErrorInsufficientBuffer) { if (!IsTiny() && e == kNtErrorInsufficientBuffer) {
if (!freeme && weaken(malloc) && (freeme = weaken(malloc)(secsize))) { if (!freeme && weaken(malloc) && (freeme = weaken(malloc)(secsize))) {
s = freeme; s = freeme;

View file

@ -19,6 +19,7 @@
#include "libc/assert.h" #include "libc/assert.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/ntmagicpaths.internal.h" #include "libc/calls/ntmagicpaths.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/nt/createfile.h" #include "libc/nt/createfile.h"
#include "libc/nt/enum/accessmask.h" #include "libc/nt/enum/accessmask.h"
#include "libc/nt/enum/creationdisposition.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 | kNtFileFlagBackupSemantics | kNtFileFlagPosixSemantics |
kNtFileAttributeTemporary)))), kNtFileAttributeTemporary)))),
0)) != -1) { 0)) != -1) {
return handle;
} else if (GetLastError() == kNtErrorFileExists && } else if (GetLastError() == kNtErrorFileExists &&
((flags & O_CREAT) && ((flags & O_CREAT) &&
(flags & O_TRUNC))) { /* TODO(jart): What was this? */ (flags & O_TRUNC))) { /* TODO(jart): What was this? */
return eisdir(); handle = eisdir();
} else { } else {
return __winerr(); handle = __winerr();
} }
STRACE("CreateFile() → %ld% m", handle);
return handle;
} }
static textwindows ssize_t sys_open_nt_console(int dirfd, static textwindows ssize_t sys_open_nt_console(int dirfd,

View file

@ -61,11 +61,15 @@
char program_executable_name[SIZE]; char program_executable_name[SIZE];
static textwindows bool GetNtExePath(char executable[SIZE]) { static textwindows bool GetNtExePath(char executable[SIZE]) {
bool32 rc;
uint64_t w; uint64_t w;
wint_t x, y; wint_t x, y;
uint32_t i, j; uint32_t i, j;
char16_t path16[PATH_MAX + 1]; 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);) { for (i = j = 0; (x = path16[i++] & 0xffff);) {
if (!IsUcs2(x)) { if (!IsUcs2(x)) {
y = path16[i++] & 0xffff; y = path16[i++] & 0xffff;

View file

@ -45,7 +45,7 @@ ssize_t pwrite(int fd, const void *buf, size_t size, int64_t offset) {
if (!IsWindows()) { if (!IsWindows()) {
rc = sys_pwrite(fd, buf, size, offset, offset); rc = sys_pwrite(fd, buf, size, offset, offset);
} else if (__isfdkind(fd, kFdFile)) { } 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 { } else {
return ebadf(); return ebadf();
} }

View file

@ -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); (struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, off);
} else if (IsWindows()) { } else if (IsWindows()) {
if (fd < g_fds.n) { 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 { } else {
return ebadf(); return ebadf();
} }

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h" #include "libc/calls/strace.internal.h"
@ -23,6 +24,8 @@
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/fmt/itoa.h" #include "libc/fmt/itoa.h"
#include "libc/intrin/asan.internal.h" #include "libc/intrin/asan.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/log/log.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/sysv/consts/sig.h" #include "libc/sysv/consts/sig.h"
#include "libc/sysv/errfuns.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 howbuf[12];
char buf[2][41]; char buf[2][41];
sigset_t old, *oldp; sigset_t old, *oldp;
const sigset_t *arg;
if (!(IsAsan() && if (!(IsAsan() &&
((opt_set && !__asan_is_valid(opt_set, sizeof(*opt_set))) || ((opt_set && !__asan_is_valid(opt_set, sizeof(*opt_set))) ||
(opt_out_oldset && (opt_out_oldset &&
@ -75,9 +79,14 @@ int sigprocmask(int how, const sigset_t *opt_set, sigset_t *opt_out_oldset) {
rc = -1; rc = -1;
} }
} else if (IsOpenbsd()) { } else if (IsOpenbsd()) {
if (!opt_set) how = 1; if (opt_set) {
if (opt_set) opt_set = (sigset_t *)(uintptr_t)(*(uint32_t *)opt_set); /* openbsd only supports 32 signals so it passses them in a reg */
if ((x = sys_sigprocmask(how, opt_set, 0, 0)) != -1) { 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) { if (opt_out_oldset) {
bzero(opt_out_oldset, sizeof(*opt_out_oldset)); bzero(opt_out_oldset, sizeof(*opt_out_oldset));
memcpy(opt_out_oldset, &x, sizeof(x)); memcpy(opt_out_oldset, &x, sizeof(x));

View file

@ -16,12 +16,16 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/assert.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/stat.h" #include "libc/calls/struct/stat.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/errno.h"
#include "libc/fmt/fmt.h" #include "libc/fmt/fmt.h"
#include "libc/fmt/itoa.h" #include "libc/fmt/itoa.h"
#include "libc/intrin/kprintf.h"
#include "libc/log/log.h" #include "libc/log/log.h"
#include "libc/nt/console.h" #include "libc/nt/console.h"
#include "libc/nt/enum/consolemodeflags.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. * Returns name of terminal, reentrantly.
*/ */
int ttyname_r(int fd, char *buf, size_t size) { int ttyname_r(int fd, char *buf, size_t size) {
int rc;
if (IsLinux()) { if (IsLinux()) {
return ttyname_linux(fd, buf, size); rc = ttyname_linux(fd, buf, size);
} else if (IsFreebsd()) { } else if (IsFreebsd()) {
return ttyname_freebsd(fd, buf, size); rc = ttyname_freebsd(fd, buf, size);
} else if (IsWindows()) { } else if (IsWindows()) {
if (__isfdkind(fd, kFdFile)) { if (__isfdkind(fd, kFdFile)) {
return sys_ttyname_nt(fd, buf, size); rc = sys_ttyname_nt(fd, buf, size);
} else { } else {
return ebadf(); rc = ebadf();
} }
} else { } else {
return enosys(); rc = enosys();
} }
STRACE("ttyname_r(%d, %s) → %d% m", fd, buf, rc);
return rc;
} }

View file

@ -19,6 +19,7 @@
#include "libc/bits/weaken.h" #include "libc/bits/weaken.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h" #include "libc/intrin/asan.internal.h"
#include "libc/sysv/consts/at.h" #include "libc/sysv/consts/at.h"
@ -35,13 +36,16 @@
* @return 0 on success, or -1 w/ errno * @return 0 on success, or -1 w/ errno
*/ */
int unlinkat(int dirfd, const char *path, int flags) { int unlinkat(int dirfd, const char *path, int flags) {
if (IsAsan() && !__asan_is_valid(path, 1)) return efault(); int rc;
if (weaken(__zipos_notat) && weaken(__zipos_notat)(dirfd, path) == -1) { if (IsAsan() && !__asan_is_valid(path, 1)) {
return -1; /* TODO(jart): implement me */ rc = efault();
} } else if (weaken(__zipos_notat) && (rc = __zipos_notat(dirfd, path)) == -1) {
if (!IsWindows()) { STRACE("zipos unlinkat not supported yet");
return sys_unlinkat(dirfd, path, flags); } else if (!IsWindows()) {
rc = sys_unlinkat(dirfd, path, flags);
} else { } 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;
} }

View file

@ -19,6 +19,7 @@
#include "libc/bits/weaken.h" #include "libc/bits/weaken.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h" #include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
@ -34,16 +35,23 @@
*/ */
int utimensat(int dirfd, const char *path, const struct timespec ts[2], int utimensat(int dirfd, const char *path, const struct timespec ts[2],
int flags) { int flags) {
int rc;
if (IsAsan() && (!__asan_is_valid(path, 1) || if (IsAsan() && (!__asan_is_valid(path, 1) ||
(ts && !__asan_is_valid(ts, sizeof(struct timespec) * 2)))) { (ts && !__asan_is_valid(ts, sizeof(struct timespec) * 2)))) {
return efault(); rc = efault();
} } else if (weaken(__zipos_notat) && (rc = __zipos_notat(dirfd, path)) == -1) {
if (weaken(__zipos_notat) && weaken(__zipos_notat)(dirfd, path) == -1) { STRACE("zipos mkdirat not supported yet");
return -1; /* TODO(jart): implement me */ } else if (!IsWindows()) {
} rc = sys_utimensat(dirfd, path, ts, flags);
if (!IsWindows()) {
return sys_utimensat(dirfd, path, ts, flags);
} else { } 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;
} }

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#define ShouldUseMsabiAttribute() 1
#include "libc/bits/weaken.h" #include "libc/bits/weaken.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/errno.h" #include "libc/errno.h"
@ -30,16 +31,16 @@
* @return -1 w/ few exceptions * @return -1 w/ few exceptions
* @note this is a code-size saving device * @note this is a code-size saving device
*/ */
privileged noasan int64_t __winerr(void) { privileged int64_t __winerr(void) {
errno_t e; errno_t e;
if (IsWindows()) { if (IsWindows()) {
e = GetLastError(); e = __imp_GetLastError();
if (weaken(__dos2errno)) { if (weaken(__dos2errno)) {
e = weaken(__dos2errno)(e); e = weaken(__dos2errno)(e);
} }
errno = e;
return -1;
} else { } else {
return enosys(); e = ENOSYS;
} }
errno = e;
return -1;
} }

View file

@ -18,28 +18,47 @@
*/ */
#include "libc/assert.h" #include "libc/assert.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/iovec.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/limits.h"
#include "libc/nt/errors.h"
#include "libc/nt/files.h" #include "libc/nt/files.h"
#include "libc/nt/runtime.h" #include "libc/nt/runtime.h"
#include "libc/nt/struct/overlapped.h" #include "libc/nt/struct/overlapped.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
static textwindows ssize_t sys_write_nt_impl(struct Fd *fd, void *data, static textwindows ssize_t sys_write_nt_epipe(int fd) {
size_t size, ssize_t offset) { 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; uint32_t sent;
struct NtOverlapped overlap; 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))) { offset2overlap(offset, &overlap))) {
/* TODO(jart): Trigger SIGPIPE on kNtErrorBrokenPipe */
return sent; return sent;
} else if (GetLastError() == kNtErrorBrokenPipe) {
return sys_write_nt_epipe(fd);
} else { } else {
return __winerr(); return __winerr();
} }
} }
textwindows ssize_t sys_write_nt(struct Fd *fd, const struct iovec *iov, textwindows ssize_t sys_write_nt(int fd, const struct iovec *iov, size_t iovlen,
size_t iovlen, ssize_t opt_offset) { ssize_t opt_offset) {
ssize_t rc; ssize_t rc;
size_t i, total; size_t i, total;
uint32_t size, wrote; uint32_t size, wrote;

View file

@ -50,7 +50,7 @@ ssize_t write(int fd, const void *buf, size_t size) {
} else if (IsMetal()) { } else if (IsMetal()) {
return sys_writev_metal(g_fds.p + fd, &(struct iovec){buf, size}, 1); return sys_writev_metal(g_fds.p + fd, &(struct iovec){buf, size}, 1);
} else { } 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 { } else {
return einval(); return einval();

View file

@ -21,9 +21,8 @@
#include "libc/sock/internal.h" #include "libc/sock/internal.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
textwindows ssize_t sys_writev_nt(struct Fd *fd, const struct iovec *iov, textwindows ssize_t sys_writev_nt(int fd, const struct iovec *iov, int iovlen) {
int iovlen) { switch (g_fds.p[fd].kind) {
switch (fd->kind) {
case kFdFile: case kFdFile:
case kFdConsole: case kFdConsole:
return sys_write_nt(fd, iov, iovlen, -1); return sys_write_nt(fd, iov, iovlen, -1);

View file

@ -47,7 +47,7 @@ ssize_t writev(int fd, const struct iovec *iov, int iovlen) {
} else if (IsMetal()) { } else if (IsMetal()) {
return sys_writev_metal(g_fds.p + fd, iov, iovlen); return sys_writev_metal(g_fds.p + fd, iov, iovlen);
} else { } else {
return sys_writev_nt(g_fds.p + fd, iov, iovlen); return sys_writev_nt(fd, iov, iovlen);
} }
} else { } else {
return einval(); return einval();

View file

@ -18,6 +18,7 @@
*/ */
#include "libc/assert.h" #include "libc/assert.h"
#include "libc/bits/weaken.h" #include "libc/bits/weaken.h"
#include "libc/calls/strace.internal.h"
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
#include "libc/mem/mem.h" #include "libc/mem/mem.h"
#include "libc/nexgen32e/bsr.h" #include "libc/nexgen32e/bsr.h"

View file

@ -29,12 +29,21 @@ extern const struct Dos2Errno kDos2Errno[];
/** /**
* Translates Windows error using superset of consts.sh. * Translates Windows error using superset of consts.sh.
*
* This function is called by __winerr(). It can only be used on
* Windows, because it returns an errno. Normally, errnos will be
* programmed to be the same as DOS errnos, per consts.sh. But since
* there's so many more errors in DOS, this function provides an added
* optional benefit mapping additional constants onto the errnos in
* consts.sh.
*/ */
privileged errno_t __dos2errno(uint32_t error) { privileged errno_t __dos2errno(uint32_t error) {
int i; int i;
for (i = 0; kDos2Errno[i].doscode; ++i) { if (error) {
if (error == kDos2Errno[i].doscode) { for (i = 0; kDos2Errno[i].doscode; ++i) {
return *(const int *)((intptr_t)kDos2Errno + kDos2Errno[i].systemv); if (error == kDos2Errno[i].doscode) {
return *(const int *)((intptr_t)kDos2Errno + kDos2Errno[i].systemv);
}
} }
} }
return error; return error;

View file

@ -16,8 +16,11 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/assert.h"
#include "libc/calls/strace.internal.h" #include "libc/calls/strace.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/kprintf.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
forceinline int Identity(int c) { forceinline int Identity(int c) {

View file

@ -18,20 +18,6 @@
*/ */
#include "libc/log/log.h" #include "libc/log/log.h"
static const char *__addr2line;
static textstartup void __addr2line_init() {
static bool once;
if (!once) {
__addr2line = commandvenv("ADDR2LINE", "addr2line");
once = true;
}
}
const char *GetAddr2linePath(void) { const char *GetAddr2linePath(void) {
return __addr2line; return commandvenv("ADDR2LINE", "addr2line");
} }
const void *const __addr2line_ctor[] initarray = {
__addr2line_init,
};

View file

@ -76,13 +76,11 @@ static int PrintBacktraceUsingAddr2line(int fd, const struct StackFrame *bp) {
} }
/* /*
* DWARF is a weak standard. If we build on Linux then only the * DWARF is a weak standard. Platforms that use LLVM or old GNU
* precice same version of the same tools on Linux can be counted upon * usually can't be counted upon to print backtraces correctly.
* to work reliably. So if it's not Linux, we fall back to our builtin
* tooling which can be counted upon.
*/ */
if (!IsLinux()) { if (!IsLinux() /* && !IsWindows() */) {
ShowHint("won't print addr2line backtrace on non-linux"); ShowHint("won't print addr2line backtrace because probably llvm");
return -1; return -1;
} }

View file

@ -242,6 +242,20 @@ forceinline char *__strstr(const char *haystack, const char *needle) {
return 0; return 0;
} }
forceinline char16_t *__strstr16(const char16_t *haystack,
const char16_t *needle) {
size_t i;
for (;;) {
for (i = 0;; ++i) {
if (!needle[i]) return (/*unconst*/ char16_t *)haystack;
if (!haystack[i]) break;
if (needle[i] != haystack[i]) break;
}
if (!*haystack++) break;
}
return 0;
}
forceinline char *__getenv(char **p, const char *s) { forceinline char *__getenv(char **p, const char *s) {
size_t i, j; size_t i, j;
if (p) { if (p) {

View file

@ -19,6 +19,7 @@
#include "libc/bits/bits.h" #include "libc/bits/bits.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/nexgen32e/kcpuids.h" #include "libc/nexgen32e/kcpuids.h"
@ -67,18 +68,21 @@ ssize_t getrandom(void *p, size_t n, unsigned f) {
char cf; char cf;
ssize_t rc; ssize_t rc;
uint64_t x; uint64_t x;
size_t i, j, m;
int fd, cmd[2]; int fd, cmd[2];
size_t i, j, m;
const char *via;
sigset_t neu, old; sigset_t neu, old;
if (n > 256) n = 256; if (n > 256) n = 256;
if ((f & ~(GRND_RANDOM | GRND_NONBLOCK))) return einval(); if ((f & ~(GRND_RANDOM | GRND_NONBLOCK))) return einval();
if (IsWindows()) { if (IsWindows()) {
via = "RtlGenRandom";
if (RtlGenRandom(p, n)) { if (RtlGenRandom(p, n)) {
rc = n; rc = n;
} else { } else {
return __winerr(); rc = __winerr();
} }
} else if (IsFreebsd() || IsNetbsd()) { } else if (IsFreebsd() || IsNetbsd()) {
via = "KERN_ARND";
if (IsFreebsd()) { if (IsFreebsd()) {
cmd[0] = 1; /* CTL_KERN */ cmd[0] = 1; /* CTL_KERN */
cmd[1] = 37; /* KERN_ARND */ cmd[1] = 37; /* KERN_ARND */
@ -91,27 +95,34 @@ ssize_t getrandom(void *p, size_t n, unsigned f) {
rc = m; rc = m;
} }
} else if (have_getrandom) { } else if (have_getrandom) {
via = "getrandom";
if ((rc = sys_getrandom(p, n, f & (GRND_RANDOM | GRND_NONBLOCK))) != -1) { if ((rc = sys_getrandom(p, n, f & (GRND_RANDOM | GRND_NONBLOCK))) != -1) {
if (!rc && (IsXnu() || IsOpenbsd())) { if (!rc && (IsXnu() || IsOpenbsd())) {
rc = n; rc = n;
} }
} }
} else if ((fd = __sys_openat( } else if ((fd = __sys_openat(
AT_FDCWD, (f & GRND_RANDOM) ? "/dev/random" : "/dev/urandom", AT_FDCWD,
(via = (f & GRND_RANDOM) ? "/dev/random" : "/dev/urandom"),
O_RDONLY | ((f & GRND_NONBLOCK) ? O_NONBLOCK : 0), 0)) != O_RDONLY | ((f & GRND_NONBLOCK) ? O_NONBLOCK : 0), 0)) !=
-1) { -1) {
rc = sys_read(fd, p, n); rc = sys_read(fd, p, n);
sys_close(fd); sys_close(fd);
} else { } else {
return enosys(); rc = enosys();
} }
STRACE("getrandom(%p, %'zu, %#x) via %s → %'ld% m", p, n, f, via, rc);
return rc; return rc;
} }
static textstartup void getrandom_init(void) { static textstartup void getrandom_init(void) {
if (sys_getrandom(0, 0, 0) == 0) { int e, rc;
e = errno;
if (!(rc = sys_getrandom(0, 0, 0))) {
have_getrandom = true; have_getrandom = true;
} }
STRACE("sys_getrandom(0,0,0) → %d% m");
errno = e;
} }
const void *const g_getrandom_init[] initarray = {getrandom_init}; const void *const g_getrandom_init[] initarray = {getrandom_init};

View file

@ -46,6 +46,7 @@ extern hidden struct MemoryIntervals _mmi;
const char *DescribeFrame(int); const char *DescribeFrame(int);
void PrintSystemMappings(int) hidden; void PrintSystemMappings(int) hidden;
char *DescribeProt(int, char[hasatleast 4]);
char *DescribeMapping(int, int, char[hasatleast 8]) hidden; char *DescribeMapping(int, int, char[hasatleast 8]) hidden;
bool AreMemoryIntervalsOk(const struct MemoryIntervals *) nosideeffect hidden; bool AreMemoryIntervalsOk(const struct MemoryIntervals *) nosideeffect hidden;
void PrintMemoryIntervals(int, const struct MemoryIntervals *) hidden; void PrintMemoryIntervals(int, const struct MemoryIntervals *) hidden;

View file

@ -109,7 +109,7 @@ static noasan void *MapMemory(void *addr, size_t size, int prot, int flags,
dm = sys_mmap(addr, size, prot, f, fd, off); dm = sys_mmap(addr, size, prot, f, fd, off);
if (UNLIKELY(dm.addr == MAP_FAILED)) { if (UNLIKELY(dm.addr == MAP_FAILED)) {
if (IsWindows() && (flags & MAP_FIXED)) { if (IsWindows() && (flags & MAP_FIXED)) {
STRACE("mmap(%.12p, %'ld) → %s (%s)", addr, size, strerror(errno), STRACE("mmap(%.12p, %'ld) → %m (%s)", addr, size,
"can't recover from MAP_FIXED errors on Windows"); "can't recover from MAP_FIXED errors on Windows");
assert(!"MapMemory() failed"); assert(!"MapMemory() failed");
Die(); Die();
@ -123,14 +123,14 @@ static noasan void *MapMemory(void *addr, size_t size, int prot, int flags,
} }
if (!IsWindows() && (flags & MAP_FIXED)) { if (!IsWindows() && (flags & MAP_FIXED)) {
if (UntrackMemoryIntervals(addr, size)) { if (UntrackMemoryIntervals(addr, size)) {
STRACE("FIXED UNTRACK FAILED %s", strerror(errno)); STRACE("FIXED UNTRACK FAILED %m");
assert(!"MapMemory() failed"); assert(!"MapMemory() failed");
Die(); Die();
} }
} }
if (TrackMemoryInterval(&_mmi, x, x + (n - 1), dm.maphandle, prot, flags)) { if (TrackMemoryInterval(&_mmi, x, x + (n - 1), dm.maphandle, prot, flags)) {
if (sys_munmap(addr, n) == -1) { if (sys_munmap(addr, n) == -1) {
STRACE("TRACK MUNMAP FAILED %s", strerror(errno)); STRACE("TRACK MUNMAP FAILED %m");
assert(!"MapMemory() failed"); assert(!"MapMemory() failed");
Die(); Die();
} }

View file

@ -187,7 +187,7 @@ RaiseEnobufs:
RaiseEnoexec: RaiseEnoexec:
errno = ENOEXEC; errno = ENOEXEC;
SystemError: SystemError:
STRACE("OpenSymbolTable() %m"); STRACE("OpenSymbolTable()% m");
if (map != MAP_FAILED) { if (map != MAP_FAILED) {
munmap(map, st.st_size); munmap(map, st.st_size);
} }

View file

@ -22,6 +22,7 @@
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h" #include "libc/calls/strace.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/errno.h"
#include "libc/fmt/fmt.h" #include "libc/fmt/fmt.h"
#include "libc/intrin/kprintf.h" #include "libc/intrin/kprintf.h"
#include "libc/log/libfatal.internal.h" #include "libc/log/libfatal.internal.h"
@ -100,7 +101,9 @@ forceinline void MakeLongDoubleLongAgain(void) {
asm volatile("fldcw\t%0" : /* no outputs */ : "m"(x87cw)); asm volatile("fldcw\t%0" : /* no outputs */ : "m"(x87cw));
} }
static noasan textwindows wontreturn noinstrument void WinMainNew(void) { static noasan textwindows wontreturn noinstrument void WinMainNew(
const char16_t *cmdline) {
bool32 rc;
int64_t h; int64_t h;
int version; int version;
int i, count; int i, count;
@ -112,13 +115,17 @@ static noasan textwindows wontreturn noinstrument void WinMainNew(void) {
version = NtGetPeb()->OSMajorVersion; version = NtGetPeb()->OSMajorVersion;
__oldstack = (intptr_t)__builtin_frame_address(0); __oldstack = (intptr_t)__builtin_frame_address(0);
if ((intptr_t)v_ntsubsystem == kNtImageSubsystemWindowsCui && version >= 10) { if ((intptr_t)v_ntsubsystem == kNtImageSubsystemWindowsCui && version >= 10) {
SetConsoleCP(kNtCpUtf8); rc = SetConsoleCP(kNtCpUtf8);
SetConsoleOutputCP(kNtCpUtf8); STRACE("SetConsoleCP(kNtCpUtf8) → %hhhd", rc);
rc = SetConsoleOutputCP(kNtCpUtf8);
STRACE("SetConsoleOutputCP(kNtCpUtf8) → %hhhd", rc);
SetEnvironmentVariable(u"TERM", u"xterm-truecolor"); SetEnvironmentVariable(u"TERM", u"xterm-truecolor");
for (i = 0; i < 2; ++i) { for (i = 0; i < 2; ++i) {
hand = GetStdHandle(kConsoleHandles[i]); hand = GetStdHandle(kConsoleHandles[i]);
GetConsoleMode(hand, __ntconsolemode + i); rc = GetConsoleMode(hand, __ntconsolemode + i);
SetConsoleMode(hand, kConsoleModes[i]); STRACE("GetConsoleMode(%p, [%#x]) → %hhhd", hand, __ntconsolemode[i], rc);
rc = SetConsoleMode(hand, kConsoleModes[i]);
STRACE("SetConsoleMode(%p, %#x) → %hhhd", hand, kConsoleModes[i], rc);
} }
} }
_mmi.p = _mmi.s; _mmi.p = _mmi.s;
@ -128,7 +135,8 @@ static noasan textwindows wontreturn noinstrument void WinMainNew(void) {
stacksize = GetStackSize(); stacksize = GetStackSize();
allocsize = argsize + stacksize; allocsize = argsize + stacksize;
allocaddr = stackaddr - argsize; allocaddr = stackaddr - argsize;
STRACE("WinMainNew() mapping arg block / stack"); STRACE("WinMainNew() mapping %'zu byte arg block + stack at %p", allocsize,
allocaddr);
MapViewOfFileExNuma( MapViewOfFileExNuma(
(_mmi.p[0].h = CreateFileMappingNuma( (_mmi.p[0].h = CreateFileMappingNuma(
-1, &kNtIsInheritable, kNtPageExecuteReadwrite, allocsize >> 32, -1, &kNtIsInheritable, kNtPageExecuteReadwrite, allocsize >> 32,
@ -142,8 +150,8 @@ static noasan textwindows wontreturn noinstrument void WinMainNew(void) {
_mmi.i = 1; _mmi.i = 1;
wa = (struct WinArgs *)allocaddr; wa = (struct WinArgs *)allocaddr;
STRACE("WinMainNew() loading arg block"); STRACE("WinMainNew() loading arg block");
count = GetDosArgv(GetCommandLine(), wa->argblock, ARRAYLEN(wa->argblock), count = GetDosArgv(cmdline, wa->argblock, ARRAYLEN(wa->argblock), wa->argv,
wa->argv, ARRAYLEN(wa->argv)); ARRAYLEN(wa->argv));
for (i = 0; wa->argv[0][i]; ++i) { for (i = 0; wa->argv[0][i]; ++i) {
if (wa->argv[0][i] == '\\') { if (wa->argv[0][i] == '\\') {
wa->argv[0][i] = '/'; wa->argv[0][i] = '/';
@ -197,15 +205,21 @@ noasan textwindows noinstrument int64_t WinMain(int64_t hInstance,
int64_t hPrevInstance, int64_t hPrevInstance,
const char *lpCmdLine, const char *lpCmdLine,
int nCmdShow) { int nCmdShow) {
const char16_t *cmdline;
extern char os asm("__hostos"); extern char os asm("__hostos");
extern uint64_t ts asm("kStartTsc"); extern uint64_t ts asm("kStartTsc");
os = WINDOWS; /* madness https://news.ycombinator.com/item?id=21019722 */ os = WINDOWS; /* madness https://news.ycombinator.com/item?id=21019722 */
ts = rdtsc(); ts = rdtsc();
__nomultics = true; __nomultics = true;
__pid = GetCurrentProcessId(); __pid = GetCurrentProcessId();
cmdline = GetCommandLine();
#ifdef SYSDEBUG
/* sloppy flag-only check for early initialization */
if (__strstr16(cmdline, u"--strace")) ++__strace;
#endif
STRACE("WinMain()"); STRACE("WinMain()");
MakeLongDoubleLongAgain(); MakeLongDoubleLongAgain();
if (weaken(WinSockInit)) weaken(WinSockInit)(); if (weaken(WinSockInit)) weaken(WinSockInit)();
if (weaken(WinMainForked)) weaken(WinMainForked)(); if (weaken(WinMainForked)) weaken(WinMainForked)();
WinMainNew(); WinMainNew(cmdline);
} }

View file

@ -130,8 +130,8 @@ int sys_setsockopt_nt(struct Fd *, int, int, const void *, uint32_t) hidden;
size_t __iovec2nt(struct NtIovec[hasatleast 16], const struct iovec *, size_t __iovec2nt(struct NtIovec[hasatleast 16], const struct iovec *,
size_t) hidden; size_t) hidden;
ssize_t sys_sendto_nt(struct Fd *, const struct iovec *, size_t, uint32_t, ssize_t sys_sendto_nt(int, const struct iovec *, size_t, uint32_t, void *,
void *, uint32_t) hidden; uint32_t) hidden;
ssize_t sys_recvfrom_nt(struct Fd *, const struct iovec *, size_t, uint32_t, ssize_t sys_recvfrom_nt(struct Fd *, const struct iovec *, size_t, uint32_t,
void *, uint32_t *) hidden; void *, uint32_t *) hidden;

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/strace.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/nt/runtime.h" #include "libc/nt/runtime.h"
#include "libc/nt/winsock.h" #include "libc/nt/winsock.h"
@ -40,6 +41,7 @@ static textwindows void WinSockCleanup(void) {
textwindows noasan void WinSockInit(void) { textwindows noasan void WinSockInit(void) {
int rc; int rc;
atexit(WinSockCleanup); atexit(WinSockCleanup);
STRACE("WSAStartup()");
if ((rc = WSAStartup(VERSION, &kNtWsaData)) != 0 || if ((rc = WSAStartup(VERSION, &kNtWsaData)) != 0 ||
kNtWsaData.wVersion != VERSION) { kNtWsaData.wVersion != VERSION) {
ExitProcess(123); ExitProcess(123);

View file

@ -58,10 +58,10 @@ ssize_t sendmsg(int fd, const struct msghdr *msg, int flags) {
if (__isfdopen(fd)) { if (__isfdopen(fd)) {
if (msg->msg_control) return einval(); /* control msg not supported */ if (msg->msg_control) return einval(); /* control msg not supported */
if (__isfdkind(fd, kFdSocket)) { if (__isfdkind(fd, kFdSocket)) {
return sys_sendto_nt(&g_fds.p[fd], msg->msg_iov, msg->msg_iovlen, flags, return sys_sendto_nt(fd, msg->msg_iov, msg->msg_iovlen, flags,
msg->msg_name, msg->msg_namelen); msg->msg_name, msg->msg_namelen);
} else if (__isfdkind(fd, kFdFile)) { } else if (__isfdkind(fd, kFdFile)) {
return sys_write_nt(&g_fds.p[fd], msg->msg_iov, msg->msg_iovlen, -1); return sys_write_nt(fd, msg->msg_iov, msg->msg_iovlen, -1);
} else { } else {
return enotsock(); return enotsock();
} }

View file

@ -30,13 +30,13 @@
* @param fd must be a socket * @param fd must be a socket
* @return number of bytes handed off, or -1 w/ errno * @return number of bytes handed off, or -1 w/ errno
*/ */
textwindows ssize_t sys_sendto_nt(struct Fd *fd, const struct iovec *iov, textwindows ssize_t sys_sendto_nt(int fd, const struct iovec *iov,
size_t iovlen, uint32_t flags, size_t iovlen, uint32_t flags,
void *opt_in_addr, uint32_t in_addrsize) { void *opt_in_addr, uint32_t in_addrsize) {
uint32_t sent; uint32_t sent;
struct NtIovec iovnt[16]; struct NtIovec iovnt[16];
if (WSASendTo(fd->handle, iovnt, __iovec2nt(iovnt, iov, iovlen), &sent, flags, if (WSASendTo(g_fds.p[fd].handle, iovnt, __iovec2nt(iovnt, iov, iovlen),
opt_in_addr, in_addrsize, NULL, NULL) != -1) { &sent, flags, opt_in_addr, in_addrsize, NULL, NULL) != -1) {
return sent; return sent;
} else { } else {
return __winsockerr(); return __winsockerr();

View file

@ -67,12 +67,12 @@ ssize_t sendto(int fd, const void *buf, size_t size, uint32_t flags,
} else { } else {
if (__isfdopen(fd)) { if (__isfdopen(fd)) {
if (__isfdkind(fd, kFdSocket)) { if (__isfdkind(fd, kFdSocket)) {
return sys_sendto_nt(&g_fds.p[fd], (struct iovec[]){{buf, size}}, 1, return sys_sendto_nt(fd, (struct iovec[]){{buf, size}}, 1, flags,
flags, opt_addr, addrsize); opt_addr, addrsize);
} else if (__isfdkind(fd, kFdFile)) { /* e.g. socketpair() */ } else if (__isfdkind(fd, kFdFile)) { /* e.g. socketpair() */
if (flags) return einval(); if (flags) return einval();
if (opt_addr) return eisconn(); if (opt_addr) return eisconn();
return sys_write_nt(&g_fds.p[fd], (struct iovec[]){{buf, size}}, 1, -1); return sys_write_nt(fd, (struct iovec[]){{buf, size}}, 1, -1);
} else { } else {
return enotsock(); return enotsock();
} }

View file

@ -21,6 +21,7 @@
#include "libc/bits/weaken.h" #include "libc/bits/weaken.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/dirent.h" #include "libc/calls/struct/dirent.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
@ -234,7 +235,6 @@ DIR *opendir(const char *name) {
struct Zipos *zip; struct Zipos *zip;
struct ZiposUri zipname; struct ZiposUri zipname;
if (weaken(__zipos_get) && weaken(__zipos_parseuri)(name, &zipname) != -1) { if (weaken(__zipos_get) && weaken(__zipos_parseuri)(name, &zipname) != -1) {
ZTRACE("__zipos_opendir(%`'s)", name);
if (weaken(__zipos_stat)(&zipname, &st) != -1) { if (weaken(__zipos_stat)(&zipname, &st) != -1) {
if (S_ISDIR(st.st_mode)) { if (S_ISDIR(st.st_mode)) {
zip = weaken(__zipos_get)(); zip = weaken(__zipos_get)();
@ -250,25 +250,25 @@ DIR *opendir(const char *name) {
} }
res->zip.prefix[zipname.len] = '\0'; res->zip.prefix[zipname.len] = '\0';
res->zip.prefixlen = zipname.len; res->zip.prefixlen = zipname.len;
return res;
} else { } else {
errno = ENOTDIR; errno = ENOTDIR;
return 0; res = 0;
} }
} else { } else {
return 0; res = 0;
} }
} else if (!IsWindows()) { } else if (!IsWindows()) {
res = NULL; res = 0;
if ((fd = open(name, O_RDONLY | O_DIRECTORY | O_CLOEXEC)) != -1) { if ((fd = open(name, O_RDONLY | O_DIRECTORY | O_CLOEXEC)) != -1) {
if (!(res = fdopendir(fd))) { if (!(res = fdopendir(fd))) {
close(fd); close(fd);
} }
} }
return res;
} else { } else {
return opendir_nt(name); res = opendir_nt(name);
} }
STRACE("opendir(%#s) → %p% m", name, res);
return res;
} }
/** /**
@ -284,10 +284,11 @@ DIR *fdopendir(int fd) {
if (!IsWindows()) { if (!IsWindows()) {
if (!(dir = calloc(1, sizeof(*dir)))) return NULL; if (!(dir = calloc(1, sizeof(*dir)))) return NULL;
dir->fd = fd; dir->fd = fd;
return dir;
} else { } else {
return fdopendir_nt(fd); dir = fdopendir_nt(fd);
} }
STRACE("fdopendir(%d) → %p% m", fd, dir);
return dir;
} }
/** /**
@ -403,6 +404,7 @@ int closedir(DIR *dir) {
} else { } else {
rc = 0; rc = 0;
} }
STRACE("closedir(%p) → %d% m", dir, rc);
return rc; return rc;
} }
@ -410,6 +412,7 @@ int closedir(DIR *dir) {
* Returns offset into directory data. * Returns offset into directory data.
*/ */
long telldir(DIR *dir) { long telldir(DIR *dir) {
STRACE("telldir(%p) → %d", dir, dir->tell);
return dir->tell; return dir->tell;
} }
@ -417,9 +420,16 @@ long telldir(DIR *dir) {
* Returns file descriptor associated with DIR object. * Returns file descriptor associated with DIR object.
*/ */
int dirfd(DIR *dir) { int dirfd(DIR *dir) {
if (dir->iszip) return eopnotsupp(); int rc;
if (IsWindows()) return eopnotsupp(); if (dir->iszip) {
return dir->fd; rc = eopnotsupp();
} else if (IsWindows()) {
rc = eopnotsupp();
} else {
rc = dir->fd;
}
STRACE("dirfd(%p) → %d% m", dir, rc);
return rc;
} }
/** /**
@ -443,4 +453,5 @@ void rewinddir(DIR *dir) {
dir->isdone = true; dir->isdone = true;
} }
} }
STRACE("rewinddir(%p)", dir);
} }

View file

@ -56,9 +56,9 @@ textstartup int __fflush_register(FILE *f) {
struct StdioFlush *sf; struct StdioFlush *sf;
sf = &__fflush; sf = &__fflush;
if (!sf->handles.p) { if (!sf->handles.p) {
sf->handles.p = &sf->handles_initmem[0]; sf->handles.p = sf->handles_initmem;
pushmov(&sf->handles.n, ARRAYLEN(sf->handles_initmem)); pushmov(&sf->handles.n, ARRAYLEN(sf->handles_initmem));
__cxa_atexit(fflush, NULL, NULL); __cxa_atexit(fflush, 0, 0);
} }
for (i = sf->handles.i; i; --i) { for (i = sf->handles.i; i; --i) {
if (!sf->handles.p[i - 1]) { if (!sf->handles.p[i - 1]) {
@ -76,7 +76,7 @@ void __fflush_unregister(FILE *f) {
sf = pushpop(sf); sf = pushpop(sf);
for (i = sf->handles.i; i; --i) { for (i = sf->handles.i; i; --i) {
if (sf->handles.p[i - 1] == f) { if (sf->handles.p[i - 1] == f) {
pushmov(&sf->handles.p[i - 1], NULL); pushmov(&sf->handles.p[i - 1], 0);
return; return;
} }
} }

View file

@ -46,7 +46,7 @@ FILE *popen(const char *cmdline, const char *mode) {
if (pipe(pipefds) == -1) return NULL; if (pipe(pipefds) == -1) return NULL;
fcntl(pipefds[dir], F_SETFD, FD_CLOEXEC); fcntl(pipefds[dir], F_SETFD, FD_CLOEXEC);
if ((f = fdopen(pipefds[dir], mode))) { if ((f = fdopen(pipefds[dir], mode))) {
switch ((pid = vfork())) { switch ((pid = fork())) {
case 0: case 0:
dup2(pipefds[!dir], !dir); dup2(pipefds[!dir], !dir);
systemexec(cmdline); systemexec(cmdline);

View file

@ -45,7 +45,7 @@ int posix_spawn(int *pid, const char *path,
if (!(*pid = vfork())) { if (!(*pid = vfork())) {
if (attrp) { if (attrp) {
if (attrp->posix_attr_flags & POSIX_SPAWN_SETPGROUP) { if (attrp->posix_attr_flags & POSIX_SPAWN_SETPGROUP) {
if (setpgid(0, attrp->posix_attr_pgroup)) _exit(127); if (setpgid(0, attrp->posix_attr_pgroup)) _Exit(127);
} }
if (attrp->posix_attr_flags & POSIX_SPAWN_SETSIGMASK) { if (attrp->posix_attr_flags & POSIX_SPAWN_SETSIGMASK) {
sigprocmask(SIG_SETMASK, &attrp->posix_attr_sigmask, NULL); sigprocmask(SIG_SETMASK, &attrp->posix_attr_sigmask, NULL);
@ -60,7 +60,7 @@ int posix_spawn(int *pid, const char *path,
sigfillset(&allsigs); sigfillset(&allsigs);
for (s = 0; sigismember(&allsigs, s); s++) { for (s = 0; sigismember(&allsigs, s); s++) {
if (sigismember(&attrp->posix_attr_sigdefault, s)) { if (sigismember(&attrp->posix_attr_sigdefault, s)) {
if (sigaction(s, &dfl, NULL) == -1) _exit(127); if (sigaction(s, &dfl, NULL) == -1) _Exit(127);
} }
} }
} }
@ -68,28 +68,28 @@ int posix_spawn(int *pid, const char *path,
if (file_actions) { if (file_actions) {
for (p = *file_actions; *p; p = strchr(p, ')') + 1) { for (p = *file_actions; *p; p = strchr(p, ')') + 1) {
if (!strncmp(p, "close(", 6)) { if (!strncmp(p, "close(", 6)) {
if (sscanf(p + 6, "%d)", &fd) != 1) _exit(127); if (sscanf(p + 6, "%d)", &fd) != 1) _Exit(127);
if (close(fd) == -1) _exit(127); if (close(fd) == -1) _Exit(127);
} else if (!strncmp(p, "dup2(", 5)) { } else if (!strncmp(p, "dup2(", 5)) {
if (sscanf(p + 5, "%d,%d)", &fd, &newfd) != 2) _exit(127); if (sscanf(p + 5, "%d,%d)", &fd, &newfd) != 2) _Exit(127);
if (dup2(fd, newfd) == -1) _exit(127); if (dup2(fd, newfd) == -1) _Exit(127);
} else if (!strncmp(p, "open(", 5)) { } else if (!strncmp(p, "open(", 5)) {
if (sscanf(p + 5, "%d,", &fd) != 1) _exit(127); if (sscanf(p + 5, "%d,", &fd) != 1) _Exit(127);
p = strchr(p, ',') + 1; p = strchr(p, ',') + 1;
q = strchr(p, '*'); q = strchr(p, '*');
if (!q || q - p + 1 > PATH_MAX) _exit(127); if (!q || q - p + 1 > PATH_MAX) _Exit(127);
strncpy(opath, p, q - p); strncpy(opath, p, q - p);
opath[q - p] = '\0'; opath[q - p] = '\0';
if (sscanf(q + 1, "%o,%o)", &oflag, &mode) != 2) _exit(127); if (sscanf(q + 1, "%o,%o)", &oflag, &mode) != 2) _Exit(127);
if (close(fd) == -1 && errno != EBADF) _exit(127); if (close(fd) == -1 && errno != EBADF) _Exit(127);
tempfd = open(opath, oflag, mode); tempfd = open(opath, oflag, mode);
if (tempfd == -1) _exit(127); if (tempfd == -1) _Exit(127);
if (tempfd != fd) { if (tempfd != fd) {
if (dup2(tempfd, fd) == -1) _exit(127); if (dup2(tempfd, fd) == -1) _Exit(127);
if (close(tempfd) == -1) _exit(127); if (close(tempfd) == -1) _Exit(127);
} }
} else { } else {
_exit(127); _Exit(127);
} }
} }
} }
@ -97,17 +97,17 @@ int posix_spawn(int *pid, const char *path,
if (attrp->posix_attr_flags & POSIX_SPAWN_SETSCHEDULER) { if (attrp->posix_attr_flags & POSIX_SPAWN_SETSCHEDULER) {
if (sched_setscheduler(0, attrp->posix_attr_schedpolicy, if (sched_setscheduler(0, attrp->posix_attr_schedpolicy,
&attrp->posix_attr_schedparam) == -1) { &attrp->posix_attr_schedparam) == -1) {
_exit(127); _Exit(127);
} }
} }
if (attrp->posix_attr_flags & POSIX_SPAWN_SETSCHEDPARAM) { if (attrp->posix_attr_flags & POSIX_SPAWN_SETSCHEDPARAM) {
if (sched_setparam(0, &attrp->posix_attr_schedparam) == -1) { if (sched_setparam(0, &attrp->posix_attr_schedparam) == -1) {
_exit(127); _Exit(127);
} }
} }
} }
execve(path, argv, envp); execve(path, argv, envp);
_exit(127); _Exit(127);
} else { } else {
if (*pid == -1) return errno; if (*pid == -1) return errno;
return 0; return 0;

View file

@ -29,19 +29,17 @@
* @param fd is vetted by close() * @param fd is vetted by close()
*/ */
int __zipos_close(int fd) { int __zipos_close(int fd) {
int rc;
struct ZiposHandle *h; struct ZiposHandle *h;
h = (struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle; h = (struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle;
ZTRACE("__zipos_close(%.*s)",
ZIP_CFILE_NAMESIZE(__zipos_get()->map + h->cfile),
ZIP_CFILE_NAME(__zipos_get()->map + h->cfile));
if (!IsWindows()) { if (!IsWindows()) {
sys_close(fd); rc = sys_close(fd);
} else { } else {
CloseHandle(h->handle); rc = 0; /* no system file descriptor needed on nt */
} }
if (!__vforked) { if (!__vforked) {
free(h->freeme); free(h->freeme);
free(h); free(h);
} }
return 0; return rc;
} }

View file

@ -28,30 +28,23 @@
#define HANDLE ((struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle) #define HANDLE ((struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle)
int __zipos_fcntl(int fd, int cmd, uintptr_t arg) { int __zipos_fcntl(int fd, int cmd, uintptr_t arg) {
int rc;
if (cmd == F_GETFD) { if (cmd == F_GETFD) {
ZTRACE("__zipos_fcntl(%.*s, %s)",
ZIP_CFILE_NAMESIZE(ZIPOS->map + HANDLE->cfile),
ZIP_CFILE_NAME(ZIPOS->map + HANDLE->cfile), "F_GETFD");
if (g_fds.p[fd].flags & O_CLOEXEC) { if (g_fds.p[fd].flags & O_CLOEXEC) {
return FD_CLOEXEC; rc = FD_CLOEXEC;
} else { } else {
return 0; rc = 0;
} }
} else if (cmd == F_SETFD) { } else if (cmd == F_SETFD) {
ZTRACE("__zipos_fcntl(%.*s, %s, 0x%x)",
ZIP_CFILE_NAMESIZE(ZIPOS->map + HANDLE->cfile),
ZIP_CFILE_NAME(ZIPOS->map + HANDLE->cfile), "F_SETFD", arg);
if (arg & FD_CLOEXEC) { if (arg & FD_CLOEXEC) {
g_fds.p[fd].flags |= O_CLOEXEC; g_fds.p[fd].flags |= O_CLOEXEC;
return FD_CLOEXEC; rc = FD_CLOEXEC;
} else { } else {
g_fds.p[fd].flags &= ~O_CLOEXEC; g_fds.p[fd].flags &= ~O_CLOEXEC;
return 0; rc = 0;
} }
} else { } else {
ZTRACE("__zipos_fcntl(%.*s, %d, 0x%x) → EINVAL", rc = einval();
ZIP_CFILE_NAMESIZE(ZIPOS->map + HANDLE->cfile),
ZIP_CFILE_NAME(ZIPOS->map + HANDLE->cfile), cmd, arg);
return einval();
} }
return rc;
} }

View file

@ -29,13 +29,10 @@
*/ */
int __zipos_fstat(const struct ZiposHandle *h, struct stat *st) { int __zipos_fstat(const struct ZiposHandle *h, struct stat *st) {
int rc; int rc;
if (!st) return efault(); if (st) {
if (!(rc = __zipos_stat_impl(__zipos_get(), h->cfile, st))) { rc = __zipos_stat_impl(__zipos_get(), h->cfile, st);
ZTRACE("__zipos_fstat(%.*s) → %d",
ZIP_CFILE_NAMESIZE(__zipos_get()->map + h->cfile),
ZIP_CFILE_NAME(__zipos_get()->map + h->cfile), st->st_size);
return 0;
} else { } else {
return rc; rc = efault();
} }
return rc;
} }

View file

@ -19,10 +19,11 @@
#include "libc/bits/safemacros.internal.h" #include "libc/bits/safemacros.internal.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/sigbits.h" #include "libc/calls/sigbits.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/stat.h" #include "libc/calls/struct/stat.h"
#include "libc/dce.h"
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/limits.h" #include "libc/limits.h"
#include "libc/log/libfatal.internal.h"
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
#include "libc/mem/alloca.h" #include "libc/mem/alloca.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
@ -84,16 +85,10 @@ struct Zipos *__zipos_get(void) {
zipos.cdir = cdir; zipos.cdir = cdir;
} else { } else {
munmap(map, size); munmap(map, size);
ZTRACE("__zipos_get(%s) → eocd not found", program_executable_name); STRACE("__zipos_get(%#s) → eocd not found", program_executable_name);
} }
} else {
ZTRACE("__zipos_get(%s) → stat/mmap %s", program_executable_name,
strerror(errno));
} }
close(fd); close(fd);
} else {
ZTRACE("__zipos_get(%s) → open %s", program_executable_name,
strerror(errno));
} }
once = true; once = true;
sigprocmask(SIG_SETMASK, &old, 0); sigprocmask(SIG_SETMASK, &old, 0);

View file

@ -30,26 +30,25 @@
* @asyncsignalsafe * @asyncsignalsafe
*/ */
int64_t __zipos_lseek(struct ZiposHandle *h, int64_t offset, unsigned whence) { int64_t __zipos_lseek(struct ZiposHandle *h, int64_t offset, unsigned whence) {
int64_t i; int64_t rc;
switch (whence) { switch (whence) {
case SEEK_SET: case SEEK_SET:
i = offset; rc = offset;
break; break;
case SEEK_CUR: case SEEK_CUR:
i = h->pos + offset; rc = h->pos + offset;
break; break;
case SEEK_END: case SEEK_END:
i = h->size - offset; rc = h->size - offset;
break; break;
default: default:
return einval(); rc = -1;
break;
} }
if (i < 0) { if (rc >= 0) {
return einval(); h->pos = rc;
} else {
rc = einval();
} }
h->pos = i; return rc;
ZTRACE("__zipos_lseek(%.*s, %d)",
ZIP_CFILE_NAMESIZE(__zipos_get()->map + h->cfile),
ZIP_CFILE_NAME(__zipos_get()->map + h->cfile), i);
return i;
} }

View file

@ -25,7 +25,6 @@ int __zipos_notat(int dirfd, const char *path) {
struct ZiposUri zipname; struct ZiposUri zipname;
if (!path) return efault(); if (!path) return efault();
if (__isfdkind(dirfd, kFdZip) || __zipos_parseuri(path, &zipname) != -1) { if (__isfdkind(dirfd, kFdZip) || __zipos_parseuri(path, &zipname) != -1) {
ZTRACE("__zipos_notat(%d, %s) → EINVAL", dirfd, path);
return einval(); return einval();
} }
return 0; return 0;

View file

@ -124,7 +124,7 @@ static int __zipos_load(struct Zipos *zipos, size_t cf, unsigned flags,
h->mem = NULL; h->mem = NULL;
} }
if (h->mem) { if (h->mem) {
if ((fd = dup(2)) != -1) { if ((fd = IsWindows() ? __reservefd() : dup(2)) != -1) {
if (__ensurefds(fd) != -1) { if (__ensurefds(fd) != -1) {
h->handle = g_fds.p[fd].handle; h->handle = g_fds.p[fd].handle;
g_fds.p[fd].kind = kFdZip; g_fds.p[fd].kind = kFdZip;
@ -147,22 +147,22 @@ static int __zipos_load(struct Zipos *zipos, size_t cf, unsigned flags,
* @note don't call open() from signal handlers * @note don't call open() from signal handlers
*/ */
int __zipos_open(const struct ZiposUri *name, unsigned flags, int mode) { int __zipos_open(const struct ZiposUri *name, unsigned flags, int mode) {
int fd; int rc;
ssize_t cf; ssize_t cf;
sigset_t oldmask; sigset_t oldmask;
struct Zipos *zipos; struct Zipos *zipos;
if ((flags & O_ACCMODE) != O_RDONLY) return einval(); if ((flags & O_ACCMODE) == O_RDONLY) {
if ((zipos = __zipos_get())) { if ((zipos = __zipos_get())) {
if ((cf = __zipos_find(zipos, name)) != -1) { if ((cf = __zipos_find(zipos, name)) != -1) {
fd = __zipos_load(zipos, cf, flags, mode); rc = __zipos_load(zipos, cf, flags, mode);
ZTRACE("__zipos_open(%.*s)", name->len, name->path); } else {
rc = enoent();
}
} else { } else {
ZTRACE("__zipos_open(%.*s) enoent", name->len, name->path); rc = enoexec();
fd = enoent();
} }
} else { } else {
fd = enoexec(); rc = einval();
ZTRACE("__zipos_open(%.*s) enoexec", name->len, name->path);
} }
return fd; return rc;
} }

View file

@ -46,9 +46,5 @@ ssize_t __zipos_read(struct ZiposHandle *h, const struct iovec *iov,
memcpy(iov[i].iov_base, h->mem + y, b); memcpy(iov[i].iov_base, h->mem + y, b);
} }
if (opt_offset == -1) h->pos = y; if (opt_offset == -1) h->pos = y;
ZTRACE("__zipos_read(%.*s, cap=%d, off=%d) -> %d",
ZIP_CFILE_NAMESIZE(__zipos_get()->map + h->cfile),
ZIP_CFILE_NAME(__zipos_get()->map + h->cfile), GetIovSize(iov, iovlen),
x, y - x);
return y - x; return y - x;
} }

View file

@ -28,18 +28,21 @@
* @asyncsignalsafe * @asyncsignalsafe
*/ */
int __zipos_stat(const struct ZiposUri *name, struct stat *st) { int __zipos_stat(const struct ZiposUri *name, struct stat *st) {
int rc;
ssize_t cf; ssize_t cf;
struct Zipos *zipos; struct Zipos *zipos;
if (!st) return efault(); if (st) {
if ((zipos = __zipos_get())) { if ((zipos = __zipos_get())) {
if ((cf = __zipos_find(zipos, name)) != -1) { if ((cf = __zipos_find(zipos, name)) != -1) {
return __zipos_stat_impl(zipos, cf, st); rc = __zipos_stat_impl(zipos, cf, st);
} else {
rc = enoent();
}
} else { } else {
ZTRACE("__zipos_stat(%.*s) -> enoent", name->len, name->path); rc = enoexec();
return enoent();
} }
} else { } else {
ZTRACE("__zipos_stat(%.*s) → enoexec", name->len, name->path); rc = efault();
return enoexec();
} }
return rc;
} }

View file

@ -1,16 +1,9 @@
#ifndef COSMOPOLITAN_LIBC_ZIPOS_ZIPOS_H_ #ifndef COSMOPOLITAN_LIBC_ZIPOS_ZIPOS_H_
#define COSMOPOLITAN_LIBC_ZIPOS_ZIPOS_H_ #define COSMOPOLITAN_LIBC_ZIPOS_ZIPOS_H_
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/strace.internal.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0) #if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_ COSMOPOLITAN_C_START_
#if DEBUGSYS
#define ZTRACE(FMT, ...) kprintf("ZIP: " FMT "\n", ##__VA_ARGS__)
#else
#define ZTRACE(FMT, ...) (void)0
#endif
struct stat; struct stat;
struct iovec; struct iovec;

View file

@ -17,12 +17,15 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/fmt/fmt.h"
#include "libc/nt/errors.h" #include "libc/nt/errors.h"
#include "libc/sock/internal.h" #include "libc/sock/internal.h"
#include "libc/sock/sock.h" #include "libc/sock/sock.h"
#include "libc/stdio/stdio.h"
#include "libc/testlib/testlib.h" #include "libc/testlib/testlib.h"
TEST(__dos2errno, test) { TEST(__dos2errno, test) {
EXPECT_EQ(0, __dos2errno(0));
EXPECT_EQ(EACCES, __dos2errno(kNtErrorSectorNotFound)); EXPECT_EQ(EACCES, __dos2errno(kNtErrorSectorNotFound));
EXPECT_EQ(EADDRNOTAVAIL, __dos2errno(kNtErrorInvalidNetname)); EXPECT_EQ(EADDRNOTAVAIL, __dos2errno(kNtErrorInvalidNetname));
} }

View file

@ -28,19 +28,6 @@
# if defined _WIN32 && ! defined __CYGWIN__ # if defined _WIN32 && ! defined __CYGWIN__
/* Get declarations of the native Windows API functions. */
# define WIN32_LEAN_AND_MEAN
# if HAVE_MSVC_INVALID_PARAMETER_HANDLER
# include "msvc-inval.h"
# endif
/* Get _get_osfhandle. */
# if GNULIB_MSVC_NOTHROW
# include "msvc-nothrow.h"
# else
# endif
# if HAVE_MSVC_INVALID_PARAMETER_HANDLER # if HAVE_MSVC_INVALID_PARAMETER_HANDLER
static int static int
dup2_nothrow (int fd, int desired_fd) dup2_nothrow (int fd, int desired_fd)

View file

@ -1,4 +1,3 @@
/* clang-format off */
/* Program name management. /* Program name management.
Copyright (C) 2016-2020 Free Software Foundation, Inc. Copyright (C) 2016-2020 Free Software Foundation, Inc.
@ -15,228 +14,17 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */ along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* clang-format off */
#include "third_party/make/src/config.h" #include "third_party/make/src/config.h"
/* Specification. */
#include "third_party/make/lib/getprogname.h" #include "third_party/make/lib/getprogname.h"
#ifdef _AIX
#endif
#ifdef __MVS__
# ifndef _OPEN_SYS
# define _OPEN_SYS
# endif
#endif
#ifdef __hpux
#endif
#ifdef __sgi
#endif
#include "third_party/make/lib/dirname.h" #include "third_party/make/lib/dirname.h"
#ifndef HAVE_GETPROGNAME /* not Mac OS X, FreeBSD, NetBSD, OpenBSD >= 5.4, Cygwin */
char const * char const *
getprogname (void) getprogname (void)
{ {
# if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME /* glibc, BeOS */
/* https://www.gnu.org/software/libc/manual/html_node/Error-Messages.html */
return program_invocation_short_name; return program_invocation_short_name;
# elif HAVE_DECL_PROGRAM_INVOCATION_NAME /* glibc, BeOS */
/* https://www.gnu.org/software/libc/manual/html_node/Error-Messages.html */
return last_component (program_invocation_name);
# elif HAVE_GETEXECNAME /* Solaris */
/* https://docs.oracle.com/cd/E19253-01/816-5168/6mbb3hrb1/index.html */
const char *p = getexecname ();
if (!p)
p = "?";
return last_component (p);
# elif HAVE_DECL___ARGV /* mingw, MSVC */
/* https://docs.microsoft.com/en-us/cpp/c-runtime-library/argc-argv-wargv */
const char *p = __argv && __argv[0] ? __argv[0] : "?";
return last_component (p);
# elif HAVE_VAR___PROGNAME /* OpenBSD, Android, QNX */
/* https://man.openbsd.org/style.9 */
/* http://www.qnx.de/developers/docs/6.5.0/index.jsp?topic=%2Fcom.qnx.doc.neutrino_lib_ref%2Fp%2F__progname.html */
/* Be careful to declare this only when we absolutely need it
(OpenBSD 5.1), rather than when it's available. Otherwise,
its mere declaration makes program_invocation_short_name
malfunction (have zero length) with Fedora 25's glibc. */
extern char *__progname;
const char *p = __progname;
# if defined __ANDROID__
return last_component (p);
# else
return p && p[0] ? p : "?";
# endif
# elif _AIX /* AIX */
/* Idea by Bastien ROUCARIÈS,
https://lists.gnu.org/r/bug-gnulib/2010-12/msg00095.html
Reference: https://www.ibm.com/support/knowledgecenter/en/ssw_aix_61/com.ibm.aix.basetrf1/getprocs.htm
*/
static char *p;
static int first = 1;
if (first)
{
first = 0;
pid_t pid = getpid ();
struct procentry64 procs;
p = (0 < getprocs64 (&procs, sizeof procs, NULL, 0, &pid, 1)
? strdup (procs.pi_comm)
: NULL);
if (!p)
p = "?";
}
return p;
# elif defined __hpux
static char *p;
static int first = 1;
if (first)
{
first = 0;
pid_t pid = getpid ();
struct pst_status status;
if (pstat_getproc (&status, sizeof status, 0, pid) > 0)
{
char *ucomm = status.pst_ucomm;
char *cmd = status.pst_cmd;
if (strlen (ucomm) < PST_UCOMMLEN - 1)
p = ucomm;
else
{
/* ucomm is truncated to length PST_UCOMMLEN - 1.
Look at cmd instead. */
char *space = strchr (cmd, ' ');
if (space != NULL)
*space = '\0';
p = strrchr (cmd, '/');
if (p != NULL)
p++;
else
p = cmd;
if (strlen (p) > PST_UCOMMLEN - 1
&& memcmp (p, ucomm, PST_UCOMMLEN - 1) == 0)
/* p is less truncated than ucomm. */
;
else
p = ucomm;
}
p = strdup (p);
}
else
{
# if !defined __LP64__
/* Support for 32-bit programs running in 64-bit HP-UX.
The documented way to do this is to use the same source code
as above, but in a compilation unit where '#define _PSTAT64 1'
is in effect. I prefer a single compilation unit; the struct
size and the offsets are not going to change. */
char status64[1216];
if (__pstat_getproc64 (status64, sizeof status64, 0, pid) > 0)
{
char *ucomm = status64 + 288;
char *cmd = status64 + 168;
if (strlen (ucomm) < PST_UCOMMLEN - 1)
p = ucomm;
else
{
/* ucomm is truncated to length PST_UCOMMLEN - 1.
Look at cmd instead. */
char *space = strchr (cmd, ' ');
if (space != NULL)
*space = '\0';
p = strrchr (cmd, '/');
if (p != NULL)
p++;
else
p = cmd;
if (strlen (p) > PST_UCOMMLEN - 1
&& memcmp (p, ucomm, PST_UCOMMLEN - 1) == 0)
/* p is less truncated than ucomm. */
;
else
p = ucomm;
}
p = strdup (p);
}
else
# endif
p = NULL;
}
if (!p)
p = "?";
}
return p;
# elif __MVS__ /* z/OS */
/* https://www.ibm.com/support/knowledgecenter/SSLTBW_2.1.0/com.ibm.zos.v2r1.bpxbd00/rtwgetp.htm */
static char *p = "?";
static int first = 1;
if (first)
{
pid_t pid = getpid ();
int token;
W_PSPROC buf;
first = 0;
memset (&buf, 0, sizeof(buf));
buf.ps_cmdptr = (char *) malloc (buf.ps_cmdlen = PS_CMDBLEN_LONG);
buf.ps_conttyptr = (char *) malloc (buf.ps_conttylen = PS_CONTTYBLEN);
buf.ps_pathptr = (char *) malloc (buf.ps_pathlen = PS_PATHBLEN);
if (buf.ps_cmdptr && buf.ps_conttyptr && buf.ps_pathptr)
{
for (token = 0; token >= 0;
token = w_getpsent (token, &buf, sizeof(buf)))
{
if (token > 0 && buf.ps_pid == pid)
{
char *s = strdup (last_component (buf.ps_pathptr));
if (s)
p = s;
break;
}
}
}
free (buf.ps_cmdptr);
free (buf.ps_conttyptr);
free (buf.ps_pathptr);
}
return p;
# elif defined __sgi /* IRIX */
char filename[50];
int fd;
sprintf (filename, "/proc/pinfo/%d", (int) getpid ());
fd = open (filename, O_RDONLY);
if (0 <= fd)
{
prpsinfo_t buf;
int ioctl_ok = 0 <= ioctl (fd, PIOCPSINFO, &buf);
close (fd);
if (ioctl_ok)
{
char *name = buf.pr_fname;
size_t namesize = sizeof buf.pr_fname;
/* It may not be NUL-terminated. */
char *namenul = memchr (name, '\0', namesize);
size_t namelen = namenul ? namenul - name : namesize;
char *namecopy = malloc (namelen + 1);
if (namecopy)
{
namecopy[namelen] = '\0';
return memcpy (namecopy, name, namelen);
}
}
}
return NULL;
# else
# error "getprogname module not ported to this OS"
# endif
} }
#endif
/* /*
* Hey Emacs! * Hey Emacs!
* Local Variables: * Local Variables:

File diff suppressed because it is too large Load diff

View file

@ -1,54 +0,0 @@
/* clang-format off */
/* malloc() function that is glibc compatible.
Copyright (C) 1997-1998, 2006-2007, 2009-2020 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <https://www.gnu.org/licenses/>. */
/* written by Jim Meyering and Bruno Haible */
#define _GL_USE_STDLIB_ALLOC 1
/* Only the AC_FUNC_MALLOC macro defines 'malloc' already in config.h. */
#ifdef malloc
# define NEED_MALLOC_GNU 1
# undef malloc
/* Whereas the gnulib module 'malloc-gnu' defines HAVE_MALLOC_GNU. */
#elif GNULIB_MALLOC_GNU && !HAVE_MALLOC_GNU
# define NEED_MALLOC_GNU 1
#endif
/* Allocate an N-byte block of memory from the heap.
If N is zero, allocate a 1-byte block. */
void *
rpl_malloc (size_t n)
{
void *result;
#if NEED_MALLOC_GNU
if (n == 0)
n = 1;
#endif
result = malloc (n);
#if !HAVE_MALLOC_POSIX
if (result == NULL)
errno = ENOMEM;
#endif
return result;
}

View file

@ -477,7 +477,6 @@ int SpawnSubprocesses(int argc, char *argv[]) {
LOGIFNEG1(sigaction(SIGQUIT, &savequit, NULL)); LOGIFNEG1(sigaction(SIGQUIT, &savequit, NULL));
LOGIFNEG1(sigprocmask(SIG_SETMASK, &savemask, NULL)); LOGIFNEG1(sigprocmask(SIG_SETMASK, &savemask, NULL));
free(pids); free(pids);
kprintf("nocommit%n");
return exitcode; return exitcode;
} }

View file

@ -1240,7 +1240,10 @@ static void WaitAll(void) {
if ((pid = wait4(-1, &ws, 0, &ru)) != -1) { if ((pid = wait4(-1, &ws, 0, &ru)) != -1) {
HandleWorkerExit(pid, ws, &ru); HandleWorkerExit(pid, ws, &ru);
} else { } else {
if (errno == ECHILD) break; if (errno == ECHILD) {
errno = 0;
break;
}
if (errno == EINTR) { if (errno == EINTR) {
if (killed) { if (killed) {
killed = false; killed = false;
@ -1248,6 +1251,7 @@ static void WaitAll(void) {
WARNF("(srvr) redbean shall terminate harder"); WARNF("(srvr) redbean shall terminate harder");
LOGIFNEG1(kill(0, SIGTERM)); LOGIFNEG1(kill(0, SIGTERM));
} }
errno = 0;
continue; continue;
} }
DIEF("(srvr) wait error: %m"); DIEF("(srvr) wait error: %m");
@ -1267,8 +1271,14 @@ static void ReapZombies(void) {
break; break;
} }
} else { } else {
if (errno == ECHILD) break; if (errno == ECHILD) {
if (errno == EINTR) continue; errno = 0;
break;
}
if (errno == EINTR) {
errno = 0;
continue;
}
DIEF("(srvr) wait error: %m"); DIEF("(srvr) wait error: %m");
} }
} while (!terminated); } while (!terminated);
@ -1298,6 +1308,7 @@ static ssize_t WritevAll(int fd, struct iovec *iov, int iovlen) {
} }
} while (wrote); } while (wrote);
} else if (errno == EINTR) { } else if (errno == EINTR) {
errno = 0;
LockInc(&shared->c.writeinterruputs); LockInc(&shared->c.writeinterruputs);
if (killed || (meltdown && nowl() - startread > 2)) { if (killed || (meltdown && nowl() - startread > 2)) {
return total ? total : -1; return total ? total : -1;
@ -1319,8 +1330,10 @@ static int TlsFlush(struct TlsBio *bio, const unsigned char *buf, size_t len) {
if (WritevAll(bio->fd, v, 2) != -1) { if (WritevAll(bio->fd, v, 2) != -1) {
if (bio->c > 0) bio->c = 0; if (bio->c > 0) bio->c = 0;
} else if (errno == EINTR) { } else if (errno == EINTR) {
errno = 0;
return MBEDTLS_ERR_NET_CONN_RESET; return MBEDTLS_ERR_NET_CONN_RESET;
} else if (errno == EAGAIN) { } else if (errno == EAGAIN) {
errno = 0;
return MBEDTLS_ERR_SSL_TIMEOUT; return MBEDTLS_ERR_SSL_TIMEOUT;
} else if (errno == EPIPE || errno == ECONNRESET || errno == ENETRESET) { } else if (errno == EPIPE || errno == ECONNRESET || errno == ENETRESET) {
return MBEDTLS_ERR_NET_CONN_RESET; return MBEDTLS_ERR_NET_CONN_RESET;
@ -1363,8 +1376,10 @@ static int TlsRecvImpl(void *ctx, unsigned char *p, size_t n, uint32_t o) {
v[1].iov_len = sizeof(bio->t); v[1].iov_len = sizeof(bio->t);
while ((r = readv(bio->fd, v, 2)) == -1) { while ((r = readv(bio->fd, v, 2)) == -1) {
if (errno == EINTR) { if (errno == EINTR) {
errno = 0;
return MBEDTLS_ERR_SSL_WANT_READ; return MBEDTLS_ERR_SSL_WANT_READ;
} else if (errno == EAGAIN) { } else if (errno == EAGAIN) {
errno = 0;
return MBEDTLS_ERR_SSL_TIMEOUT; return MBEDTLS_ERR_SSL_TIMEOUT;
} else if (errno == EPIPE || errno == ECONNRESET || errno == ENETRESET) { } else if (errno == EPIPE || errno == ECONNRESET || errno == ENETRESET) {
return MBEDTLS_ERR_NET_CONN_RESET; return MBEDTLS_ERR_NET_CONN_RESET;
@ -1406,6 +1421,7 @@ static ssize_t SslRead(int fd, void *buf, size_t size) {
} else if (rc == MBEDTLS_ERR_SSL_WANT_READ) { } else if (rc == MBEDTLS_ERR_SSL_WANT_READ) {
errno = EINTR; errno = EINTR;
rc = -1; rc = -1;
errno = 0;
} else { } else {
WARNF("(ssl) %s SslRead error -0x%04x", DescribeClient(), -rc); WARNF("(ssl) %s SslRead error -0x%04x", DescribeClient(), -rc);
errno = EIO; errno = EIO;
@ -2249,6 +2265,7 @@ static ssize_t Send(struct iovec *iov, int iovlen) {
} else if (errno == EAGAIN) { } else if (errno == EAGAIN) {
LockInc(&shared->c.writetimeouts); LockInc(&shared->c.writetimeouts);
WARNF("(rsp) %s write timeout", DescribeClient()); WARNF("(rsp) %s write timeout", DescribeClient());
errno = 0;
} else { } else {
LockInc(&shared->c.writeerrors); LockInc(&shared->c.writeerrors);
WARNF("(rsp) %s write error: %m", DescribeClient()); WARNF("(rsp) %s write error: %m", DescribeClient());
@ -2662,6 +2679,7 @@ static void LaunchBrowser(const char *path) {
} }
while (wait4(pid, &ws, 0, 0) == -1) { while (wait4(pid, &ws, 0, 0) == -1) {
CHECK_EQ(EINTR, errno); CHECK_EQ(EINTR, errno);
errno = 0;
} }
sigaction(SIGINT, &saveint, 0); sigaction(SIGINT, &saveint, 0);
sigaction(SIGQUIT, &savequit, 0); sigaction(SIGQUIT, &savequit, 0);
@ -5941,6 +5959,7 @@ static ssize_t SendString(const char *s) {
if ((rc = writer(client, &iov, 1)) != -1 || errno != EINTR) { if ((rc = writer(client, &iov, 1)) != -1 || errno != EINTR) {
return rc; return rc;
} }
errno = 0;
} }
} }
@ -6132,6 +6151,7 @@ static char *OpenAsset(struct Asset *a) {
return HandleMapFailed(a, fd); return HandleMapFailed(a, fd);
} }
} else if (errno == EINTR) { } else if (errno == EINTR) {
errno = 0;
goto OpenAgain; goto OpenAgain;
} else { } else {
return HandleOpenFail(a); return HandleOpenFail(a);
@ -6639,7 +6659,6 @@ static bool StreamResponse(char *p) {
static bool HandleMessageAcutal(void) { static bool HandleMessageAcutal(void) {
int rc; int rc;
char *p; char *p;
g_syscount = 0;
if ((rc = ParseHttpMessage(&msg, inbuf.p, amtread)) != -1) { if ((rc = ParseHttpMessage(&msg, inbuf.p, amtread)) != -1) {
if (!rc) return false; if (!rc) return false;
hdrsize = rc; hdrsize = rc;
@ -6769,6 +6788,7 @@ static void HandleMessages(void) {
} }
} else if (errno == EINTR) { } else if (errno == EINTR) {
LockInc(&shared->c.readinterrupts); LockInc(&shared->c.readinterrupts);
errno = 0;
} else if (errno == EAGAIN) { } else if (errno == EAGAIN) {
LockInc(&shared->c.readtimeouts); LockInc(&shared->c.readtimeouts);
if (amtread) SendTimeout(); if (amtread) SendTimeout();
@ -6943,6 +6963,7 @@ static void HandleConnection(size_t i) {
} else { } else {
DIEF("(srvr) %s accept error: %m", DescribeServer()); DIEF("(srvr) %s accept error: %m", DescribeServer());
} }
errno = 0;
} }
static void HandlePoll(void) { static void HandlePoll(void) {
@ -6965,6 +6986,7 @@ static void HandlePoll(void) {
} else { } else {
DIEF("(srvr) poll error: %m"); DIEF("(srvr) poll error: %m");
} }
errno = 0;
} }
static void RestoreApe(void) { static void RestoreApe(void) {