mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 06:53:33 +00:00
Make improvements
- Expand redbean UNIX module - Expand redbean documentation - Ensure Lua copyright is embedded in binary - Increase the PATH_MAX limit especially on NT - Use column major sorting for linenoise completions - Fix some suboptimalities in redbean's new UNIX API - Figured out right flags for Multics newline in raw mode
This commit is contained in:
parent
cf3174dc74
commit
2046c0d2ae
305 changed files with 6602 additions and 4221 deletions
Binary file not shown.
|
@ -169,7 +169,7 @@ DEFAULT_LDFLAGS = \
|
|||
--gc-sections \
|
||||
--build-id=none \
|
||||
--no-dynamic-linker \
|
||||
-zmax-page-size=0x1000
|
||||
-zmax-page-size=0x1000 #--cref -Map=$@.map
|
||||
|
||||
ZIPOBJ_FLAGS = \
|
||||
-b$(IMAGE_BASE_VIRTUAL)
|
||||
|
|
|
@ -31,13 +31,6 @@ int ttysetraw(struct termios *conf, int64_t flags) {
|
|||
conf->c_cflag &= ~(CSIZE | PARENB);
|
||||
conf->c_cflag |= CS8;
|
||||
conf->c_iflag |= IUTF8;
|
||||
/* if (flags & kTtyLfToCrLf) { */
|
||||
/* /\* conf->c_oflag &= ~(OLCUC | OCRNL | ONLRET | OFILL | OFDEL); *\/ */
|
||||
/* /\* conf->c_oflag |= ONLCR | ONOCR; *\/ */
|
||||
/* conf->c_oflag |= ONLCR; */
|
||||
/* } else { */
|
||||
/* conf->c_oflag &= ~OPOST; */
|
||||
/* } */
|
||||
if (!(flags & kTtySigs)) {
|
||||
conf->c_iflag &= ~(IGNBRK | BRKINT);
|
||||
conf->c_lflag &= ~(ISIG);
|
||||
|
|
|
@ -151,14 +151,6 @@ o/$(MODE)/examples/hello.com.dbg: \
|
|||
$(APE_NO_MODIFY_SELF)
|
||||
@$(APELINK)
|
||||
|
||||
o/$(MODE)/examples/printargs.com.dbg: \
|
||||
$(EXAMPLES_DEPS) \
|
||||
o/$(MODE)/examples/printargs.o \
|
||||
o/$(MODE)/examples/examples.pkg \
|
||||
$(CRT) \
|
||||
$(APE_NO_MODIFY_SELF)
|
||||
@$(APELINK)
|
||||
|
||||
o/$(MODE)/examples/nesemu1.o: QUOTA += -M512m
|
||||
|
||||
$(EXAMPLES_OBJS): examples/examples.mk
|
||||
|
|
|
@ -7,30 +7,8 @@
|
|||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
int main() {
|
||||
int pip[2];
|
||||
char buf[PATH_MAX];
|
||||
char *args[2] = {0};
|
||||
if (strcmp(nulltoempty(getenv("TERM")), "dumb") && isatty(0) && isatty(1) &&
|
||||
((args[0] = commandv("less", buf)) ||
|
||||
(args[0] = commandv("more", buf)))) {
|
||||
close(0);
|
||||
close(2);
|
||||
pipe(pip);
|
||||
if (!vfork()) {
|
||||
close(2);
|
||||
execv(args[0], args);
|
||||
_Exit(127);
|
||||
}
|
||||
close(0);
|
||||
__printargs("");
|
||||
close(2);
|
||||
wait(0);
|
||||
} else {
|
||||
__printargs("");
|
||||
}
|
||||
__printargs("");
|
||||
}
|
||||
|
|
|
@ -67,9 +67,9 @@ int main(int argc, char *argv[]) {
|
|||
char *exepath;
|
||||
struct rusage r;
|
||||
long double real;
|
||||
char exebuf[PATH_MAX];
|
||||
char exebuf[PATH_MAX + 1];
|
||||
if (argc >= 2) {
|
||||
if ((exepath = commandv(argv[1], exebuf))) {
|
||||
if ((exepath = commandv(argv[1], exebuf, sizeof(exebuf)))) {
|
||||
real = nowl();
|
||||
argv[1] = exepath;
|
||||
if ((ws = xvspawn(OnChild, argv + 1, &r)) != -1) {
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
int main(int argc, char *argv[]) {
|
||||
int i;
|
||||
for (i = 1; i < argc; ++i) {
|
||||
if (touch(argv[i], 0644) == -1) {
|
||||
if (touch(argv[i], 0666) == -1) {
|
||||
fprintf(stderr, "ERROR: %s: %s\n", argv[i], strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ bool isregularfile(const char *);
|
|||
bool issymlink(const char *);
|
||||
bool32 isatty(int) nosideeffect;
|
||||
bool32 ischardev(int) nosideeffect;
|
||||
char *commandv(const char *, char[hasatleast PATH_MAX]);
|
||||
char *commandv(const char *, char *, size_t);
|
||||
char *get_current_dir_name(void) dontdiscard;
|
||||
char *getcwd(char *, size_t);
|
||||
char *realpath(const char *, char *);
|
||||
|
@ -120,13 +120,16 @@ int ftruncate(int, int64_t);
|
|||
int getdents(unsigned, void *, unsigned, long *);
|
||||
int getdomainname(char *, size_t);
|
||||
int gethostname(char *, size_t);
|
||||
int getloadavg(double *, int);
|
||||
int getpgid(int);
|
||||
int getpgrp(void) nosideeffect;
|
||||
int getpid(void);
|
||||
int gettid(void);
|
||||
int getppid(void);
|
||||
int getpriority(int, unsigned);
|
||||
int getrlimit(int, struct rlimit *);
|
||||
int getrusage(int, struct rusage *);
|
||||
int getsid(int) nosideeffect;
|
||||
int gettid(void);
|
||||
int kill(int, int);
|
||||
int killpg(int, int);
|
||||
int link(const char *, const char *) dontthrow;
|
||||
|
@ -165,11 +168,12 @@ int rmdir(const char *);
|
|||
int sched_getaffinity(int, uint64_t, void *);
|
||||
int sched_setaffinity(int, uint64_t, const void *);
|
||||
int sched_yield(void);
|
||||
int seccomp(unsigned, unsigned, void *);
|
||||
int setegid(uint32_t);
|
||||
int seteuid(uint32_t);
|
||||
int setgid(int);
|
||||
int setpgrp(void);
|
||||
int setpgid(int, int);
|
||||
int setpgrp(void);
|
||||
int setpriority(int, unsigned, int);
|
||||
int setregid(uint32_t, uint32_t);
|
||||
int setresgid(uint32_t, uint32_t, uint32_t);
|
||||
|
@ -206,9 +210,9 @@ long ptrace(int, ...);
|
|||
long telldir(DIR *);
|
||||
long times(struct tms *);
|
||||
size_t GetFileSize(const char *);
|
||||
ssize_t getfiledescriptorsize(int);
|
||||
ssize_t copy_file_range(int, long *, int, long *, size_t, uint32_t);
|
||||
ssize_t copyfd(int, int64_t *, int, int64_t *, size_t, uint32_t);
|
||||
ssize_t getfiledescriptorsize(int);
|
||||
ssize_t lseek(int, int64_t, unsigned);
|
||||
ssize_t pread(int, void *, size_t, int64_t);
|
||||
ssize_t preadv(int, struct iovec *, int, int64_t);
|
||||
|
@ -225,14 +229,11 @@ struct dirent *readdir(DIR *);
|
|||
uint32_t getegid(void) nosideeffect;
|
||||
uint32_t geteuid(void) nosideeffect;
|
||||
uint32_t getgid(void) nosideeffect;
|
||||
uint32_t getpgrp(void) nosideeffect;
|
||||
uint32_t getsid(int) nosideeffect;
|
||||
uint32_t getuid(void) nosideeffect;
|
||||
uint32_t umask(uint32_t);
|
||||
void rewinddir(DIR *);
|
||||
void sync(void);
|
||||
int getloadavg(double *, int);
|
||||
int seccomp(unsigned, unsigned, void *);
|
||||
|
||||
int clone(int (*)(void *), void *, size_t, int, void *, int *, void *, size_t,
|
||||
int *);
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
textwindows int sys_chdir_nt(const char *path) {
|
||||
uint32_t n;
|
||||
int e, ms, err, len;
|
||||
char16_t path16[PATH_MAX], var[4];
|
||||
char16_t path16[PATH_MAX + 1], var[4];
|
||||
if ((len = __mkntpath(path, path16)) == -1) return -1;
|
||||
if (!len) return enoent();
|
||||
if (len && path16[len - 1] != u'\\') {
|
||||
|
|
|
@ -73,7 +73,9 @@ int close(int fd) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!__vforked) __releasefd(fd);
|
||||
if (!__vforked) {
|
||||
__releasefd(fd);
|
||||
}
|
||||
}
|
||||
STRACE("%s(%d) → %d% m", "close", fd, rc);
|
||||
return rc;
|
||||
|
|
|
@ -43,15 +43,16 @@ static bool IsComDbgPath(const char *s, size_t n) {
|
|||
READ64LE(s + n - 8) == READ64LE(".COM.DBG"));
|
||||
}
|
||||
|
||||
static bool AccessCommand(const char *name, char path[hasatleast PATH_MAX],
|
||||
static bool AccessCommand(const char *name, char *path, size_t pathsz,
|
||||
size_t namelen, int *err, const char *suffix,
|
||||
size_t pathlen) {
|
||||
size_t suffixlen;
|
||||
suffixlen = strlen(suffix);
|
||||
if (pathlen + 1 + namelen + suffixlen + 1 > PATH_MAX) return false;
|
||||
if (pathlen + 1 + namelen + suffixlen + 1 > pathsz) return false;
|
||||
if (pathlen && (path[pathlen - 1] != '/' && path[pathlen - 1] != '\\')) {
|
||||
path[pathlen] =
|
||||
!IsWindows() ? '/' : memchr(path, '\\', pathlen) ? '\\' : '/';
|
||||
path[pathlen] = !IsWindows() ? '/'
|
||||
: memchr(path, '\\', pathlen) ? '\\'
|
||||
: '/';
|
||||
pathlen++;
|
||||
}
|
||||
memcpy(path + pathlen, name, namelen);
|
||||
|
@ -61,7 +62,7 @@ static bool AccessCommand(const char *name, char path[hasatleast PATH_MAX],
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool SearchPath(const char *name, char path[hasatleast PATH_MAX],
|
||||
static bool SearchPath(const char *name, char *path, size_t pathsz,
|
||||
size_t namelen, int *err, const char *suffix) {
|
||||
char sep;
|
||||
size_t i;
|
||||
|
@ -70,11 +71,11 @@ static bool SearchPath(const char *name, char path[hasatleast PATH_MAX],
|
|||
sep = IsWindows() && strchr(p, ';') ? ';' : ':';
|
||||
for (;;) {
|
||||
for (i = 0; p[i] && p[i] != sep; ++i) {
|
||||
if (i < PATH_MAX) {
|
||||
if (i < pathsz) {
|
||||
path[i] = p[i];
|
||||
}
|
||||
}
|
||||
if (AccessCommand(name, path, namelen, err, suffix, i)) {
|
||||
if (AccessCommand(name, path, pathsz, namelen, err, suffix, i)) {
|
||||
return true;
|
||||
}
|
||||
if (p[i] == sep) {
|
||||
|
@ -86,36 +87,36 @@ static bool SearchPath(const char *name, char path[hasatleast PATH_MAX],
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool FindCommand(const char *name, char pathbuf[hasatleast PATH_MAX],
|
||||
size_t namelen, bool priorityonly, const char *suffix,
|
||||
int *err) {
|
||||
if (priorityonly &&
|
||||
(memchr(name, '/', namelen) || memchr(name, '\\', namelen))) {
|
||||
pathbuf[0] = 0;
|
||||
return AccessCommand(name, pathbuf, namelen, err, suffix, 0);
|
||||
static bool FindCommand(const char *name, char *pb, size_t pbsz, size_t namelen,
|
||||
bool pri, const char *suffix, int *err) {
|
||||
if (pri && (memchr(name, '/', namelen) || memchr(name, '\\', namelen))) {
|
||||
pb[0] = 0;
|
||||
return AccessCommand(name, pb, pbsz, namelen, err, suffix, 0);
|
||||
}
|
||||
if (IsWindows() && priorityonly) {
|
||||
return AccessCommand(name, pathbuf, namelen, err, suffix,
|
||||
stpcpy(pathbuf, kNtSystemDirectory) - pathbuf) ||
|
||||
AccessCommand(name, pathbuf, namelen, err, suffix,
|
||||
stpcpy(pathbuf, kNtWindowsDirectory) - pathbuf);
|
||||
if (IsWindows() && pri &&
|
||||
pbsz > max(strlen(kNtSystemDirectory), strlen(kNtWindowsDirectory))) {
|
||||
return AccessCommand(name, pb, pbsz, namelen, err, suffix,
|
||||
stpcpy(pb, kNtSystemDirectory) - pb) ||
|
||||
AccessCommand(name, pb, pbsz, namelen, err, suffix,
|
||||
stpcpy(pb, kNtWindowsDirectory) - pb);
|
||||
}
|
||||
return (IsWindows() && AccessCommand(name, pathbuf, namelen, err, suffix,
|
||||
stpcpy(pathbuf, ".") - pathbuf)) ||
|
||||
SearchPath(name, pathbuf, namelen, err, suffix);
|
||||
return (IsWindows() &&
|
||||
(pbsz > 1 && AccessCommand(name, pb, pbsz, namelen, err, suffix,
|
||||
stpcpy(pb, ".") - pb))) ||
|
||||
SearchPath(name, pb, pbsz, namelen, err, suffix);
|
||||
}
|
||||
|
||||
static bool FindVerbatim(const char *name, char pathbuf[hasatleast PATH_MAX],
|
||||
size_t namelen, bool priorityonly, int *err) {
|
||||
return FindCommand(name, pathbuf, namelen, priorityonly, "", err);
|
||||
static bool FindVerbatim(const char *name, char *pb, size_t pbsz,
|
||||
size_t namelen, bool pri, int *err) {
|
||||
return FindCommand(name, pb, pbsz, namelen, pri, "", err);
|
||||
}
|
||||
|
||||
static bool FindSuffixed(const char *name, char pathbuf[hasatleast PATH_MAX],
|
||||
size_t namelen, bool priorityonly, int *err) {
|
||||
static bool FindSuffixed(const char *name, char *pb, size_t pbsz,
|
||||
size_t namelen, bool pri, int *err) {
|
||||
return !IsExePath(name, namelen) && !IsComPath(name, namelen) &&
|
||||
!IsComDbgPath(name, namelen) &&
|
||||
(FindCommand(name, pathbuf, namelen, priorityonly, ".com", err) ||
|
||||
FindCommand(name, pathbuf, namelen, priorityonly, ".exe", err));
|
||||
(FindCommand(name, pb, pbsz, namelen, pri, ".com", err) ||
|
||||
FindCommand(name, pb, pbsz, namelen, pri, ".exe", err));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -127,7 +128,7 @@ static bool FindSuffixed(const char *name, char pathbuf[hasatleast PATH_MAX],
|
|||
* @asyncsignalsafe
|
||||
* @vforksafe
|
||||
*/
|
||||
char *commandv(const char *name, char pathbuf[hasatleast PATH_MAX]) {
|
||||
char *commandv(const char *name, char *pathbuf, size_t pathbufsz) {
|
||||
int e, f;
|
||||
char *res;
|
||||
size_t namelen;
|
||||
|
@ -136,25 +137,27 @@ char *commandv(const char *name, char pathbuf[hasatleast PATH_MAX]) {
|
|||
efault();
|
||||
} else if (!(namelen = strlen(name))) {
|
||||
enoent();
|
||||
} else if (namelen + 1 > PATH_MAX) {
|
||||
} else if (namelen + 1 > pathbufsz) {
|
||||
enametoolong();
|
||||
} else {
|
||||
e = errno;
|
||||
f = ENOENT;
|
||||
if ((IsWindows() && (FindSuffixed(name, pathbuf, namelen, true, &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) ||
|
||||
FindVerbatim(name, pathbuf, namelen, false, &f) ||
|
||||
FindSuffixed(name, pathbuf, namelen, false, &f)))) {
|
||||
if ((IsWindows() &&
|
||||
(FindSuffixed(name, pathbuf, pathbufsz, namelen, true, &f) ||
|
||||
FindVerbatim(name, pathbuf, pathbufsz, namelen, true, &f) ||
|
||||
FindSuffixed(name, pathbuf, pathbufsz, namelen, false, &f) ||
|
||||
FindVerbatim(name, pathbuf, pathbufsz, namelen, false, &f))) ||
|
||||
(!IsWindows() &&
|
||||
(FindVerbatim(name, pathbuf, pathbufsz, namelen, true, &f) ||
|
||||
FindSuffixed(name, pathbuf, pathbufsz, namelen, true, &f) ||
|
||||
FindVerbatim(name, pathbuf, pathbufsz, namelen, false, &f) ||
|
||||
FindSuffixed(name, pathbuf, pathbufsz, namelen, false, &f)))) {
|
||||
errno = e;
|
||||
res = pathbuf;
|
||||
} else {
|
||||
errno = f;
|
||||
}
|
||||
}
|
||||
STRACE("commandv(%#s, %p) → %#s% m", name, pathbuf, res);
|
||||
STRACE("commandv(%#s, %p, %'zu) → %#s% m", name, pathbuf, pathbufsz, res);
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ static textwindows int sys_copyfile_nt(const char *src, const char *dst,
|
|||
int flags) {
|
||||
int64_t fhsrc, fhdst;
|
||||
struct NtFileTime accessed, modified;
|
||||
char16_t src16[PATH_MAX], dst16[PATH_MAX];
|
||||
char16_t src16[PATH_MAX + 1], dst16[PATH_MAX + 1];
|
||||
if (__mkntpath(src, src16) == -1) return -1;
|
||||
if (__mkntpath(dst, dst16) == -1) return -1;
|
||||
if (CopyFile(src16, dst16, !!(flags & COPYFILE_NOCLOBBER))) {
|
||||
|
|
|
@ -39,8 +39,8 @@ int execlp(const char *prog, const char *arg, ... /*, NULL*/) {
|
|||
char *exe;
|
||||
char **argv;
|
||||
va_list va, vb;
|
||||
char pathbuf[PATH_MAX];
|
||||
if (!(exe = commandv(prog, pathbuf))) return -1;
|
||||
char pathbuf[PATH_MAX + 1];
|
||||
if (!(exe = commandv(prog, pathbuf, sizeof(pathbuf)))) return -1;
|
||||
va_copy(vb, va);
|
||||
va_start(va, arg);
|
||||
for (i = 0; va_arg(va, const char *); ++i) donothing;
|
||||
|
|
|
@ -33,7 +33,8 @@ int sys_execve(const char *prog, char *const argv[], char *const envp[]) {
|
|||
shargs = alloca((i + 2) * sizeof(char *));
|
||||
memcpy(shargs + 2, argv + 1, i * sizeof(char *));
|
||||
if (IsFreebsd() || IsNetbsd()) {
|
||||
shargs[0] = firstnonnull(commandv("bash", alloca(PATH_MAX)), _PATH_BSHELL);
|
||||
shargs[0] = firstnonnull(
|
||||
commandv("bash", alloca(PATH_MAX + 1), PATH_MAX + 1), _PATH_BSHELL);
|
||||
} else {
|
||||
shargs[0] = _PATH_BSHELL;
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ int execve(const char *prog, char *const argv[], char *const envp[]) {
|
|||
if (i) kprintf(", ");
|
||||
kprintf("%#s", envp[i]);
|
||||
}
|
||||
kprintf("})%n");
|
||||
kprintf("})\n");
|
||||
}
|
||||
#endif
|
||||
for (i = 3; i < g_fds.n; ++i) {
|
||||
|
|
|
@ -36,8 +36,8 @@
|
|||
*/
|
||||
int execvpe(const char *prog, char *const argv[], char *const *envp) {
|
||||
char *exe;
|
||||
char pathbuf[PATH_MAX];
|
||||
char pathbuf[PATH_MAX + 1];
|
||||
if (IsAsan() && !__asan_is_valid(prog, 1)) return efault();
|
||||
if (!(exe = commandv(prog, pathbuf))) return -1;
|
||||
if (!(exe = commandv(prog, pathbuf, sizeof(pathbuf)))) return -1;
|
||||
return execve(exe, argv, envp);
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
int sys_faccessat_nt(int dirfd, const char *path, int mode, uint32_t flags) {
|
||||
char16_t path16[PATH_MAX];
|
||||
char16_t path16[PATH_MAX + 1];
|
||||
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
|
||||
return __fix_enotdir(ntaccesscheck(path16, mode), path16);
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
textwindows int sys_fchdir_nt(int dirfd) {
|
||||
uint32_t len;
|
||||
char16_t dir[PATH_MAX];
|
||||
char16_t dir[PATH_MAX + 1];
|
||||
if (!__isfdkind(dirfd, kFdFile)) return ebadf();
|
||||
len = GetFinalPathNameByHandle(g_fds.p[dirfd].handle, dir, ARRAYLEN(dir),
|
||||
kNtFileNameNormalized | kNtVolumeNameDos);
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
textwindows int sys_fchmodat_nt(int dirfd, const char *path, uint32_t mode,
|
||||
int flags) {
|
||||
uint32_t attr;
|
||||
uint16_t path16[PATH_MAX];
|
||||
uint16_t path16[PATH_MAX + 1];
|
||||
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
|
||||
if ((attr = GetFileAttributes(path16)) != -1u) {
|
||||
if (mode & 0200) {
|
||||
|
|
|
@ -48,7 +48,7 @@ bool fileexists(const char *path) {
|
|||
bool res;
|
||||
union metastat st;
|
||||
struct ZiposUri zipname;
|
||||
uint16_t path16[PATH_MAX];
|
||||
uint16_t path16[PATH_MAX + 1];
|
||||
e = errno;
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) {
|
||||
efault();
|
||||
|
|
|
@ -29,7 +29,7 @@ textwindows int sys_fstatat_nt(int dirfd, const char *path, struct stat *st,
|
|||
int flags) {
|
||||
int rc;
|
||||
int64_t fh;
|
||||
uint16_t path16[PATH_MAX];
|
||||
uint16_t path16[PATH_MAX + 1];
|
||||
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
|
||||
if ((fh = CreateFile(
|
||||
path16, kNtFileReadAttributes, 0, 0, kNtOpenExisting,
|
||||
|
|
|
@ -28,15 +28,22 @@ textwindows char *sys_getcwd_nt(char *buf, size_t size) {
|
|||
uint64_t w;
|
||||
wint_t x, y;
|
||||
uint32_t n, i, j;
|
||||
char16_t name16[PATH_MAX + 1];
|
||||
if ((n = GetCurrentDirectory(ARRAYLEN(name16), name16))) {
|
||||
if (n <= PATH_MAX) {
|
||||
tprecode16to8(buf, size, name16);
|
||||
for (j = i = 0; i < n;) {
|
||||
x = name16[i++] & 0xffff;
|
||||
char16_t p[PATH_MAX + 1];
|
||||
if ((n = GetCurrentDirectory(ARRAYLEN(p), p))) {
|
||||
if (4 + n + 1 <= size && 4 + n + 1 <= ARRAYLEN(p)) {
|
||||
tprecode16to8(buf, size, p);
|
||||
j = 0;
|
||||
if (n >= 3 && isalpha(p[0]) && p[1] == ':' && p[2] == '\\') {
|
||||
buf[j++] = '/';
|
||||
buf[j++] = '/';
|
||||
buf[j++] = '?';
|
||||
buf[j++] = '/';
|
||||
}
|
||||
for (i = 0; i < n;) {
|
||||
x = p[i++] & 0xffff;
|
||||
if (!IsUcs2(x)) {
|
||||
if (i < n) {
|
||||
y = name16[i++] & 0xffff;
|
||||
y = p[i++] & 0xffff;
|
||||
x = MergeUtf16(x, y);
|
||||
} else {
|
||||
x = 0xfffd;
|
||||
|
|
|
@ -19,13 +19,19 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
|
||||
/**
|
||||
* Returns effective group ID of calling process.
|
||||
* @return group id
|
||||
*/
|
||||
uint32_t getegid(void) {
|
||||
int rc;
|
||||
rc = sys_getegid();
|
||||
if (!IsWindows()) {
|
||||
rc = sys_getegid();
|
||||
} else {
|
||||
rc = getgid();
|
||||
}
|
||||
STRACE("%s() → %d% m", "getegid", rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -22,10 +22,15 @@
|
|||
|
||||
/**
|
||||
* Returns effective user ID of calling process.
|
||||
* @return user id
|
||||
*/
|
||||
uint32_t geteuid(void) {
|
||||
int rc;
|
||||
rc = sys_geteuid();
|
||||
if (!IsWindows()) {
|
||||
rc = sys_geteuid();
|
||||
} else {
|
||||
rc = getuid();
|
||||
}
|
||||
STRACE("%s() → %d% m", "geteuid", rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
/**
|
||||
* Returns process group id of calling process.
|
||||
*/
|
||||
uint32_t getpgrp(void) {
|
||||
int getpgrp(void) {
|
||||
int rc;
|
||||
if (!IsWindows()) {
|
||||
rc = sys_getpgrp();
|
||||
|
|
|
@ -18,11 +18,14 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/calls/struct/rusage.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/intrin/spinlock.h"
|
||||
#include "libc/nt/accounting.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/iocounters.h"
|
||||
#include "libc/nt/struct/processmemorycounters.h"
|
||||
#include "libc/nt/thread.h"
|
||||
#include "libc/str/str.h"
|
||||
|
@ -30,22 +33,32 @@
|
|||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int sys_getrusage_nt(int who, struct rusage *usage) {
|
||||
int64_t me, nsignals;
|
||||
struct NtIoCounters iocount;
|
||||
struct NtProcessMemoryCountersEx memcount;
|
||||
struct NtFileTime ftExit, ftUser, ftKernel, ftCreation;
|
||||
if (!usage) return efault();
|
||||
if (who == 99) return enosys(); // @see libc/sysv/consts.sh
|
||||
if (!usage) return 0;
|
||||
me = GetCurrentProcess();
|
||||
if (!(who == RUSAGE_SELF ? GetProcessTimes : GetThreadTimes)(
|
||||
(who == RUSAGE_SELF ? GetCurrentProcess : GetCurrentThread)(),
|
||||
&ftCreation, &ftExit, &ftKernel, &ftUser) ||
|
||||
!GetProcessMemoryInfo(GetCurrentProcess(), &memcount, sizeof(memcount))) {
|
||||
!GetProcessMemoryInfo(me, &memcount, sizeof(memcount)) ||
|
||||
!GetProcessIoCounters(me, &iocount)) {
|
||||
return __winerr();
|
||||
}
|
||||
_spinlock(&__sig_lock);
|
||||
nsignals = __sig_count;
|
||||
_spunlock(&__sig_lock);
|
||||
*usage = (struct rusage){
|
||||
.ru_utime = WindowsDurationToTimeVal(ReadFileTime(ftUser)),
|
||||
.ru_stime = WindowsDurationToTimeVal(ReadFileTime(ftKernel)),
|
||||
.ru_maxrss = memcount.PeakWorkingSetSize / 1024,
|
||||
.ru_majflt = memcount.PageFaultCount,
|
||||
.ru_inblock = iocount.ReadOperationCount,
|
||||
.ru_oublock = iocount.WriteOperationCount,
|
||||
.ru_nsignals = __sig_count,
|
||||
};
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
/**
|
||||
* Creates session and sets the process group id.
|
||||
*/
|
||||
uint32_t getsid(int pid) {
|
||||
int getsid(int pid) {
|
||||
int rc;
|
||||
rc = sys_getsid(pid);
|
||||
STRACE("%s(%d) → %d% m", "getsid", pid, rc);
|
||||
|
|
|
@ -88,7 +88,7 @@ int __reservefd(int) hidden;
|
|||
void __releasefd(int) hidden;
|
||||
int __ensurefds(int) hidden;
|
||||
int64_t __getfdhandleactual(int) hidden;
|
||||
void __printfds(void);
|
||||
void __printfds(void) hidden;
|
||||
|
||||
forceinline bool __isfdopen(int fd) {
|
||||
return 0 <= fd && fd < g_fds.n && g_fds.p[fd].kind != kFdEmpty;
|
||||
|
@ -165,6 +165,7 @@ i32 sys_getppid(void) hidden;
|
|||
i32 sys_getpriority(i32, u32) hidden;
|
||||
i32 sys_getrlimit(i32, struct rlimit *) hidden;
|
||||
i32 sys_getrusage(i32, struct rusage *) hidden;
|
||||
i32 sys_getsid(int) hidden;
|
||||
i32 sys_ioctl(i32, u64, ...) hidden;
|
||||
i32 sys_kill(i32, i32, i32) hidden;
|
||||
i32 sys_linkat(i32, const char *, i32, const char *, i32) hidden;
|
||||
|
@ -191,8 +192,10 @@ i32 sys_setgid(i32) hidden;
|
|||
i32 sys_setitimer(i32, const struct itimerval *, struct itimerval *) hidden;
|
||||
i32 sys_setpgid(i32, i32) hidden;
|
||||
i32 sys_setpriority(i32, u32, i32) hidden;
|
||||
i32 sys_setregid(u32, u32) hidden;
|
||||
i32 sys_setresgid(uint32_t, uint32_t, uint32_t) hidden;
|
||||
i32 sys_setresuid(uint32_t, uint32_t, uint32_t) hidden;
|
||||
i32 sys_setreuid(u32, u32) hidden;
|
||||
i32 sys_setrlimit(i32, const struct rlimit *) hidden;
|
||||
i32 sys_setsid(void) hidden;
|
||||
i32 sys_setuid(i32) hidden;
|
||||
|
@ -230,7 +233,6 @@ i64 sys_write(i32, const void *, u64) hidden;
|
|||
u32 sys_getegid(void) hidden;
|
||||
u32 sys_geteuid(void) hidden;
|
||||
u32 sys_getgid(void) hidden;
|
||||
u32 sys_getsid(int) hidden;
|
||||
u32 sys_gettid(void) hidden;
|
||||
u32 sys_getuid(void) hidden;
|
||||
u32 sys_umask(u32) hidden;
|
||||
|
@ -337,9 +339,10 @@ bool isregularfile_nt(const char *) hidden;
|
|||
bool issymlink_nt(const char *) hidden;
|
||||
bool32 ntsetprivilege(i64, const char16_t *, u32) hidden;
|
||||
char16_t *CreatePipeName(char16_t *) hidden;
|
||||
int __mkntpath(const char *, char16_t[hasatleast PATH_MAX - 16]) hidden;
|
||||
int __mkntpath2(const char *, char16_t[hasatleast PATH_MAX - 16], int) hidden;
|
||||
int __mkntpathat(int, const char *, int, char16_t[PATH_MAX]) hidden;
|
||||
int __mkntpath(const char *, char16_t[hasatleast PATH_MAX + 1]) hidden;
|
||||
int __mkntpath2(const char *, char16_t[hasatleast PATH_MAX + 1], int) hidden;
|
||||
int __mkntpathat(int, const char *, int,
|
||||
char16_t[hasatleast PATH_MAX + 1]) hidden;
|
||||
int sys_clock_gettime_nt(int, struct timespec *) hidden;
|
||||
int ntaccesscheck(const char16_t *, u32) paramsnonnull() hidden;
|
||||
int sys_getsetpriority_nt(int, int, int, int (*)(int));
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/termios.h"
|
||||
#include "libc/calls/ttydefaults.h"
|
||||
#include "libc/nt/console.h"
|
||||
#include "libc/nt/enum/consolemodeflags.h"
|
||||
#include "libc/nt/struct/consolescreenbufferinfoex.h"
|
||||
|
@ -35,6 +36,23 @@ textwindows int ioctl_tcgets_nt(int ignored, struct termios *tio) {
|
|||
outok = GetConsoleMode((out = __getfdhandleactual(1)), &outmode);
|
||||
if (inok | outok) {
|
||||
bzero(tio, sizeof(*tio));
|
||||
|
||||
tio->c_cflag |= CS8;
|
||||
|
||||
tio->c_cc[VINTR] = CTRL('C');
|
||||
tio->c_cc[VQUIT] = CTRL('\\');
|
||||
tio->c_cc[VERASE] = CTRL('?');
|
||||
tio->c_cc[VKILL] = CTRL('U');
|
||||
tio->c_cc[VEOF] = CTRL('D');
|
||||
tio->c_cc[VMIN] = CTRL('A');
|
||||
tio->c_cc[VSTART] = CTRL('Q');
|
||||
tio->c_cc[VSTOP] = CTRL('S');
|
||||
tio->c_cc[VSUSP] = CTRL('Z');
|
||||
tio->c_cc[VREPRINT] = CTRL('R');
|
||||
tio->c_cc[VDISCARD] = CTRL('O');
|
||||
tio->c_cc[VWERASE] = CTRL('W');
|
||||
tio->c_cc[VLNEXT] = CTRL('V');
|
||||
|
||||
if (inok) {
|
||||
if (inmode & kNtEnableLineInput) {
|
||||
tio->c_lflag |= ICANON;
|
||||
|
@ -44,16 +62,21 @@ textwindows int ioctl_tcgets_nt(int ignored, struct termios *tio) {
|
|||
}
|
||||
if (inmode & kNtEnableProcessedInput) {
|
||||
tio->c_lflag |= IEXTEN | ISIG;
|
||||
if (tio->c_lflag | ECHO) {
|
||||
tio->c_lflag |= ECHOE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (outok) {
|
||||
if (outmode & kNtEnableProcessedOutput) {
|
||||
tio->c_oflag |= OPOST;
|
||||
}
|
||||
if (!(outmode & kNtDisableNewlineAutoReturn)) {
|
||||
tio->c_oflag |= ONLCR;
|
||||
tio->c_oflag |= OPOST | ONLCR;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
return enotty();
|
||||
|
|
|
@ -17,8 +17,10 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/metatermios.internal.h"
|
||||
#include "libc/calls/termios.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/nt/console.h"
|
||||
#include "libc/nt/enum/consolemodeflags.h"
|
||||
#include "libc/nt/enum/version.h"
|
||||
|
@ -29,35 +31,54 @@
|
|||
textwindows int ioctl_tcsets_nt(int ignored, uint64_t request,
|
||||
const struct termios *tio) {
|
||||
int64_t in, out;
|
||||
bool32 inok, outok;
|
||||
bool32 ok, inok, outok;
|
||||
uint32_t inmode, outmode;
|
||||
inok = GetConsoleMode((in = __getfdhandleactual(0)), &inmode);
|
||||
outok = GetConsoleMode((out = __getfdhandleactual(1)), &outmode);
|
||||
if (inok | outok) {
|
||||
|
||||
if (inok) {
|
||||
if (request == TCSETSF) {
|
||||
FlushConsoleInputBuffer(in);
|
||||
}
|
||||
inmode &=
|
||||
~(kNtEnableLineInput | kNtEnableEchoInput | kNtEnableProcessedInput);
|
||||
if (tio->c_lflag & ICANON) inmode |= kNtEnableLineInput;
|
||||
if (tio->c_lflag & ECHO) inmode |= kNtEnableEchoInput;
|
||||
if (tio->c_lflag & (IEXTEN | ISIG)) inmode |= kNtEnableProcessedInput;
|
||||
inmode |= kNtEnableWindowInput;
|
||||
if (tio->c_lflag & ICANON) {
|
||||
inmode |= kNtEnableLineInput;
|
||||
}
|
||||
if (tio->c_lflag & ECHO) {
|
||||
/*
|
||||
* kNtEnableEchoInput can be used only if the ENABLE_LINE_INPUT mode
|
||||
* is also enabled. --Quoth MSDN
|
||||
*/
|
||||
inmode |= kNtEnableEchoInput | kNtEnableLineInput;
|
||||
}
|
||||
if (tio->c_lflag & (IEXTEN | ISIG)) {
|
||||
inmode |= kNtEnableProcessedInput;
|
||||
}
|
||||
if (NtGetVersion() >= kNtVersionWindows10) {
|
||||
inmode |= kNtEnableVirtualTerminalInput;
|
||||
}
|
||||
SetConsoleMode(in, inmode);
|
||||
ok = SetConsoleMode(in, inmode);
|
||||
NTTRACE("SetConsoleMode(%p, %s) → %hhhd", in,
|
||||
DescribeNtConsoleModeInputFlags(inmode), ok);
|
||||
}
|
||||
|
||||
if (outok) {
|
||||
outmode |= kNtEnableWrapAtEolOutput;
|
||||
if (tio->c_oflag & OPOST) outmode |= kNtEnableProcessedOutput;
|
||||
if (!(tio->c_oflag & ONLCR)) outmode |= kNtDisableNewlineAutoReturn;
|
||||
outmode &= ~(kNtDisableNewlineAutoReturn);
|
||||
outmode |= kNtEnableProcessedOutput;
|
||||
if (!(tio->c_oflag & ONLCR)) {
|
||||
outmode |= kNtDisableNewlineAutoReturn;
|
||||
}
|
||||
if (NtGetVersion() >= kNtVersionWindows10) {
|
||||
outmode |= kNtEnableVirtualTerminalProcessing;
|
||||
}
|
||||
SetConsoleMode(out, outmode);
|
||||
ok = SetConsoleMode(out, outmode);
|
||||
NTTRACE("SetConsoleMode(%p, %s) → %hhhd", out,
|
||||
DescribeNtConsoleModeOutputFlags(outmode), ok);
|
||||
}
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
return enotty();
|
||||
|
|
|
@ -83,11 +83,6 @@ int ioctl_tcsets(int fd, uint64_t request, ...) {
|
|||
} else {
|
||||
rc = einval();
|
||||
}
|
||||
if (rc != -1) {
|
||||
if (__nomultics == 0 || __nomultics == 1) {
|
||||
__nomultics = !(tio->c_oflag & OPOST);
|
||||
}
|
||||
}
|
||||
STRACE("ioctl_tcsets(%d, %p, %p) → %d% m", fd, request, tio, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
bool isdirectory_nt(const char *path) {
|
||||
int e;
|
||||
uint32_t x;
|
||||
char16_t path16[PATH_MAX];
|
||||
char16_t path16[PATH_MAX + 1];
|
||||
e = errno;
|
||||
if (__mkntpath(path, path16) == -1) return -1;
|
||||
if ((x = GetFileAttributes(path16)) != -1u) {
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
bool isregularfile_nt(const char *path) {
|
||||
int e;
|
||||
uint32_t x;
|
||||
char16_t path16[PATH_MAX];
|
||||
char16_t path16[PATH_MAX + 1];
|
||||
e = errno;
|
||||
if (__mkntpath(path, path16) == -1) return -1;
|
||||
if ((x = GetFileAttributes(path16)) != -1u) {
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
bool issymlink_nt(const char *path) {
|
||||
int e;
|
||||
uint32_t x;
|
||||
char16_t path16[PATH_MAX];
|
||||
char16_t path16[PATH_MAX + 1];
|
||||
e = errno;
|
||||
if (__mkntpath(path, path16) == -1) return -1;
|
||||
if ((x = GetFileAttributes(path16)) != -1u) {
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
|
||||
textwindows int sys_linkat_nt(int olddirfd, const char *oldpath, int newdirfd,
|
||||
const char *newpath) {
|
||||
char16_t newpath16[PATH_MAX];
|
||||
char16_t oldpath16[PATH_MAX];
|
||||
char16_t newpath16[PATH_MAX + 1];
|
||||
char16_t oldpath16[PATH_MAX + 1];
|
||||
if (__mkntpathat(olddirfd, oldpath, 0, oldpath16) != -1 &&
|
||||
__mkntpathat(newdirfd, newpath, 0, newpath16) != -1) {
|
||||
if (CreateHardLink(newpath16, oldpath16, NULL)) {
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
* @param path is a UTF-8 string, preferably relative w/ forward slashes
|
||||
* @param mode can be, for example, 0755
|
||||
* @return 0 on success or -1 w/ errno
|
||||
* @error EEXIST, ENOTDIR, ENAMETOOLONG, EACCES
|
||||
* @error ENAMETOOLONG if >246 characters on NT
|
||||
* @asyncsignalsafe
|
||||
* @see makedirs()
|
||||
*/
|
||||
|
|
|
@ -18,10 +18,13 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int sys_mkdirat_nt(int dirfd, const char *path, uint32_t mode) {
|
||||
int e;
|
||||
char16_t *p, path16[PATH_MAX];
|
||||
char16_t *p, path16[PATH_MAX + 1];
|
||||
/* if (strlen(path) > 248) return enametoolong(); */
|
||||
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
|
||||
if (CreateDirectory(path16, 0)) return 0;
|
||||
return __fix_enotdir(-1, path16);
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ntmagicpaths.internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/systeminfo.h"
|
||||
#include "libc/str/oldutf16.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
|
@ -49,7 +50,7 @@ textwindows static const char *FixNtMagicPath(const char *path,
|
|||
}
|
||||
|
||||
textwindows int __mkntpath(const char *path,
|
||||
char16_t path16[hasatleast PATH_MAX - 16]) {
|
||||
char16_t path16[hasatleast PATH_MAX + 1]) {
|
||||
return __mkntpath2(path, path16, -1);
|
||||
}
|
||||
|
||||
|
@ -67,14 +68,14 @@ textwindows int __mkntpath(const char *path,
|
|||
* @error ENAMETOOLONG
|
||||
*/
|
||||
textwindows int __mkntpath2(const char *path,
|
||||
char16_t path16[hasatleast PATH_MAX - 16],
|
||||
char16_t path16[hasatleast PATH_MAX + 1],
|
||||
int flags) {
|
||||
/*
|
||||
* 1. Reserve +1 for NUL-terminator
|
||||
* 2. Reserve +1 for UTF-16 overflow
|
||||
* 3. Reserve ≥2 for SetCurrentDirectory trailing slash requirement
|
||||
* 4. Reserve ≥10 for CreateNamedPipe "\\.\pipe\" prefix requirement
|
||||
* 5. Reserve ≥13 for mkdir() i.e. 1+8+3+1, e.g. "\\ffffffff.xxx\0"
|
||||
* 1. Need +1 for NUL-terminator
|
||||
* 2. Need +1 for UTF-16 overflow
|
||||
* 3. Need ≥2 for SetCurrentDirectory trailing slash requirement
|
||||
* 5. Need ≥13 for mkdir() i.e. 1+8+3+1, e.g. "\\ffffffff.xxx\0"
|
||||
* which is an "8.3 filename" from the DOS days
|
||||
*/
|
||||
char16_t *p;
|
||||
const char *q;
|
||||
|
@ -83,7 +84,12 @@ textwindows int __mkntpath2(const char *path,
|
|||
path = FixNtMagicPath(path, flags);
|
||||
p = path16;
|
||||
q = path;
|
||||
z = PATH_MAX - 16;
|
||||
if (IsSlash(path[0]) && IsSlash(path[1]) && path[2] == '?' &&
|
||||
IsSlash(path[3])) {
|
||||
z = MIN(32767, PATH_MAX);
|
||||
} else {
|
||||
z = MIN(260, PATH_MAX);
|
||||
}
|
||||
if (IsSlash(q[0]) && q[1] == 't' && q[2] == 'm' && q[3] == 'p' &&
|
||||
(IsSlash(q[4]) || !q[4])) {
|
||||
m = GetTempPath(z, p);
|
||||
|
|
|
@ -25,9 +25,9 @@
|
|||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
int __mkntpathat(int dirfd, const char *path, int flags,
|
||||
char16_t file[PATH_MAX]) {
|
||||
char16_t dir[PATH_MAX];
|
||||
char16_t file[hasatleast PATH_MAX + 1]) {
|
||||
uint32_t dirlen, filelen;
|
||||
char16_t dir[PATH_MAX + 1];
|
||||
if ((filelen = __mkntpath2(path, file, flags)) == -1) return -1;
|
||||
if (!filelen) return enoent();
|
||||
if (file[0] != u'\\' && dirfd != AT_FDCWD) { /* ProTip: \\?\C:\foo */
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/nt/time.h"
|
||||
|
@ -34,7 +35,7 @@ textwindows noinstrument int sys_nanosleep_nt(const struct timespec *req,
|
|||
int64_t ms, sec, nsec;
|
||||
if (__builtin_mul_overflow(req->tv_sec, 1000, &ms) ||
|
||||
__builtin_add_overflow(ms, req->tv_nsec / 1000000, &ms)) {
|
||||
ms = -1;
|
||||
ms = INT64_MAX;
|
||||
}
|
||||
if (!ms && (req->tv_sec || req->tv_nsec)) {
|
||||
ms = 1;
|
||||
|
|
|
@ -70,7 +70,7 @@ textwindows int ntspawn(
|
|||
int64_t handle;
|
||||
size_t blocksize;
|
||||
struct SpawnBlock *block;
|
||||
char16_t prog16[PATH_MAX];
|
||||
char16_t prog16[PATH_MAX + 1];
|
||||
rc = -1;
|
||||
block = NULL;
|
||||
if (__mkntpath(prog, prog16) == -1) return -1;
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
|
||||
static textwindows int64_t sys_open_nt_impl(int dirfd, const char *path,
|
||||
uint32_t flags, int32_t mode) {
|
||||
char16_t path16[PATH_MAX];
|
||||
char16_t path16[PATH_MAX + 1];
|
||||
uint32_t perm, share, disp, attr;
|
||||
if (__mkntpathat(dirfd, path, flags, path16) == -1) return -1;
|
||||
if (GetNtOpenFlags(flags, mode, &perm, &share, &disp, &attr) == -1) return -1;
|
||||
|
|
|
@ -95,7 +95,7 @@ int poll(struct pollfd *fds, size_t nfds, int timeout_ms) {
|
|||
DescribePollFlags(flagbuf[0], sizeof(flagbuf[0]), fds[i].events),
|
||||
DescribePollFlags(flagbuf[1], sizeof(flagbuf[1]), fds[i].revents));
|
||||
}
|
||||
kprintf("%s}, %'zu, %'d) → %d% lm%n", i == 5 ? "..." : "", nfds,
|
||||
kprintf("%s}, %'zu, %'d) → %d% lm\n", i == 5 ? "..." : "", nfds,
|
||||
timeout_ms, rc);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -118,7 +118,7 @@ ssize_t preadv(int fd, struct iovec *iov, int iovlen, int64_t off) {
|
|||
} else {
|
||||
kprintf(STRACE_PROLOGUE "preadv(%d, [", fd);
|
||||
__strace_iov(iov, iovlen, rc != -1 ? rc : 0);
|
||||
kprintf("], %d, %'ld) → %'ld% m%n", iovlen, off, rc);
|
||||
kprintf("], %d, %'ld) → %'ld% m\n", iovlen, off, rc);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/spinlock.h"
|
||||
|
||||
static const char *__fdkind2str(int x) {
|
||||
switch (x) {
|
||||
|
@ -44,6 +45,7 @@ static const char *__fdkind2str(int x) {
|
|||
|
||||
void __printfds(void) {
|
||||
int i;
|
||||
_spinlock(&__fds_lock);
|
||||
for (i = 0; i < g_fds.n; ++i) {
|
||||
if (!g_fds.p[i].kind) continue;
|
||||
kprintf("%3d %s", i, __fdkind2str(g_fds.p[i].kind));
|
||||
|
@ -53,6 +55,7 @@ void __printfds(void) {
|
|||
if (g_fds.p[i].handle) kprintf(" handle=%ld", g_fds.p[i].handle);
|
||||
if (g_fds.p[i].extra) kprintf(" extra=%ld", g_fds.p[i].extra);
|
||||
if (g_fds.p[i].worker) kprintf(" worker=%p", g_fds.p[i].worker);
|
||||
kprintf("%n", g_fds.p[i].zombie);
|
||||
kprintf("\n");
|
||||
}
|
||||
_spunlock(&__fds_lock);
|
||||
}
|
||||
|
|
|
@ -52,14 +52,21 @@ static textwindows bool GetNtExePath(char exe[SIZE]) {
|
|||
uint64_t w;
|
||||
wint_t x, y;
|
||||
uint32_t i, j;
|
||||
char16_t path16[PATH_MAX + 1];
|
||||
path16[0] = 0;
|
||||
rc = GetModuleFileName(0, path16, ARRAYLEN(path16));
|
||||
NTTRACE("GetModuleFileName(0, [%#hs]) → %hhhd", path16, rc);
|
||||
char16_t p[PATH_MAX + 1];
|
||||
p[0] = 0;
|
||||
rc = GetModuleFileName(0, p, ARRAYLEN(p));
|
||||
NTTRACE("GetModuleFileName(0, [%#hs]) → %hhhd", p, rc);
|
||||
if (!rc) return false;
|
||||
for (i = j = 0; (x = path16[i++] & 0xffff);) {
|
||||
j = 0;
|
||||
if (p[0] != '\\' || p[1] != '\\' || p[2] != '?' || p[3] != '\\') {
|
||||
exe[j++] = '/';
|
||||
exe[j++] = '/';
|
||||
exe[j++] = '?';
|
||||
exe[j++] = '/';
|
||||
}
|
||||
for (i = 0; (x = p[i++] & 0xffff);) {
|
||||
if (!IsUcs2(x)) {
|
||||
y = path16[i++] & 0xffff;
|
||||
y = p[i++] & 0xffff;
|
||||
x = MergeUtf16(x, y);
|
||||
}
|
||||
if (x == '\\') x = '/';
|
||||
|
|
|
@ -123,7 +123,7 @@ ssize_t pwritev(int fd, const struct iovec *iov, int iovlen, int64_t off) {
|
|||
} else {
|
||||
kprintf(STRACE_PROLOGUE "pwritev(%d, ", fd);
|
||||
__strace_iov(iov, iovlen, rc != -1 ? rc : 0);
|
||||
kprintf(", %d, %'ld) → %'ld% m%n", iovlen, off, rc);
|
||||
kprintf(", %d, %'ld) → %'ld% m\n", iovlen, off, rc);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/reparsedatabuffer.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tpenc.h"
|
||||
#include "libc/str/utf16.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
@ -39,7 +40,7 @@ textwindows ssize_t sys_readlinkat_nt(int dirfd, const char *path, char *buf,
|
|||
wint_t x, y;
|
||||
volatile char *memory;
|
||||
uint32_t i, j, n, mem;
|
||||
char16_t path16[PATH_MAX], *p;
|
||||
char16_t path16[PATH_MAX + 1], *p;
|
||||
struct NtReparseDataBuffer *rdb;
|
||||
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
|
||||
mem = 16384;
|
||||
|
@ -56,6 +57,12 @@ textwindows ssize_t sys_readlinkat_nt(int dirfd, const char *path, char *buf,
|
|||
n = rdb->SymbolicLinkReparseBuffer.PrintNameLength / sizeof(char16_t);
|
||||
p = (char16_t *)((char *)rdb->SymbolicLinkReparseBuffer.PathBuffer +
|
||||
rdb->SymbolicLinkReparseBuffer.PrintNameOffset);
|
||||
if (n >= 3 && isalpha(p[0]) && p[1] == ':' && p[2] == '\\') {
|
||||
buf[j++] = '/';
|
||||
buf[j++] = '/';
|
||||
buf[j++] = '?';
|
||||
buf[j++] = '/';
|
||||
}
|
||||
while (i < n) {
|
||||
x = p[i++] & 0xffff;
|
||||
if (!IsUcs2(x)) {
|
||||
|
|
|
@ -72,7 +72,7 @@ ssize_t readv(int fd, const struct iovec *iov, int iovlen) {
|
|||
} else {
|
||||
kprintf(STRACE_PROLOGUE "readv(%d, [", fd);
|
||||
__strace_iov(iov, iovlen, rc != -1 ? rc : 0);
|
||||
kprintf("], %d) → %'ld% m%n", iovlen, rc);
|
||||
kprintf("], %d) → %'ld% m\n", iovlen, rc);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -22,8 +22,8 @@
|
|||
|
||||
textwindows int sys_renameat_nt(int olddirfd, const char *oldpath, int newdirfd,
|
||||
const char *newpath) {
|
||||
char16_t oldpath16[PATH_MAX];
|
||||
char16_t newpath16[PATH_MAX];
|
||||
char16_t oldpath16[PATH_MAX + 1];
|
||||
char16_t newpath16[PATH_MAX + 1];
|
||||
if (__mkntpathat(olddirfd, oldpath, 0, oldpath16) == -1 ||
|
||||
__mkntpathat(newdirfd, newpath, 0, newpath16) == -1) {
|
||||
return -1;
|
||||
|
|
|
@ -22,9 +22,6 @@
|
|||
/**
|
||||
* Sets effective group ID.
|
||||
*/
|
||||
int setegid(unsigned egid) {
|
||||
int rc;
|
||||
rc = setregid(-1, egid);
|
||||
STRACE("%s(%u) → %d% m", "setegid", egid, rc);
|
||||
return rc;
|
||||
int setegid(uint32_t egid) {
|
||||
return setregid(-1, egid);
|
||||
}
|
||||
|
|
|
@ -22,9 +22,6 @@
|
|||
/**
|
||||
* Sets effective user ID.
|
||||
*/
|
||||
int seteuid(unsigned euid) {
|
||||
int rc;
|
||||
rc = setreuid(-1, euid);
|
||||
STRACE("%s(%u) → %d% m", "seteuid", euid, rc);
|
||||
return rc;
|
||||
int seteuid(uint32_t euid) {
|
||||
return setregid(euid, -1);
|
||||
}
|
||||
|
|
|
@ -21,12 +21,16 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
|
||||
/**
|
||||
* Sets effective group id of current process.
|
||||
* Sets group id of current process.
|
||||
* @return 0 on success or -1 w/ errno
|
||||
*/
|
||||
int setgid(int gid) {
|
||||
int rc;
|
||||
rc = sys_setgid(gid);
|
||||
STRACE("%s(%d) → %d% m", "setgid", gid);
|
||||
if (IsWindows() && gid == getgid()) {
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = sys_setgid(gid);
|
||||
}
|
||||
STRACE("setgid(%d) → %d% m", gid, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
35
libc/calls/setregid.c
Normal file
35
libc/calls/setregid.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
|
||||
/**
|
||||
* Sets real and/or effective group ids.
|
||||
*
|
||||
* @param rgid is real group id or -1 to leave it unchanged
|
||||
* @param egid is effective group id or -1 to leave it unchanged
|
||||
* @return 0 on success or -1 w/ errno
|
||||
*/
|
||||
int setregid(uint32_t rgid, uint32_t egid) {
|
||||
int rc;
|
||||
rc = sys_setregid(rgid, egid);
|
||||
STRACE("setregid(%d, %d) → %d% m", rgid, egid, rc);
|
||||
return rc;
|
||||
}
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
|
||||
/**
|
||||
* Sets real, effective, and "saved" group ids.
|
||||
|
@ -25,9 +26,17 @@
|
|||
* @param real sets real group id or -1 to do nothing
|
||||
* @param effective sets effective group id or -1 to do nothing
|
||||
* @param saved sets saved group id or -1 to do nothing
|
||||
* @see setregid(), getauxval(AT_SECURE)
|
||||
* @see setresuid(), getauxval(AT_SECURE)
|
||||
* @raise ENOSYS on Windows NT
|
||||
*/
|
||||
int setresgid(uint32_t real, uint32_t effective, uint32_t saved) {
|
||||
if (saved == -1) return setregid(real, effective);
|
||||
return sys_setresgid(real, effective, saved);
|
||||
int rc;
|
||||
if (saved != -1) {
|
||||
rc = sys_setresgid(real, effective, saved);
|
||||
} else {
|
||||
// polyfill xnu and netbsd
|
||||
rc = sys_setregid(real, effective);
|
||||
}
|
||||
STRACE("setresgid(%d, %d, %d) → %d% m", real, effective, saved, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
|
||||
/**
|
||||
* Sets real, effective, and "saved" user ids.
|
||||
|
@ -25,9 +26,17 @@
|
|||
* @param real sets real user id or -1 to do nothing
|
||||
* @param effective sets effective user id or -1 to do nothing
|
||||
* @param saved sets saved user id or -1 to do nothing
|
||||
* @see setreuid(), getauxval(AT_SECURE)
|
||||
* @see setresgid(), getauxval(AT_SECURE)
|
||||
* @raise ENOSYS on Windows NT
|
||||
*/
|
||||
int setresuid(uint32_t real, uint32_t effective, uint32_t saved) {
|
||||
if (saved == -1) return setreuid(real, effective);
|
||||
return sys_setresuid(real, effective, saved);
|
||||
int rc;
|
||||
if (saved != -1) {
|
||||
rc = sys_setresuid(real, effective, saved);
|
||||
} else {
|
||||
// polyfill xnu and netbsd
|
||||
rc = sys_setreuid(real, effective);
|
||||
}
|
||||
STRACE("setresuid(%d, %d, %d) → %d% m", real, effective, saved, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
35
libc/calls/setreuid.c
Normal file
35
libc/calls/setreuid.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
|
||||
/**
|
||||
* Sets real and/or effective user ids.
|
||||
*
|
||||
* @param ruid is real user id or -1 to leave it unchanged
|
||||
* @param euid is effective user id or -1 to leave it unchanged
|
||||
* @return 0 on success or -1 w/ errno
|
||||
*/
|
||||
int setreuid(uint32_t ruid, uint32_t euid) {
|
||||
int rc;
|
||||
rc = sys_setreuid(ruid, euid);
|
||||
STRACE("setreuid(%d, %d) → %d% m", ruid, euid, rc);
|
||||
return rc;
|
||||
}
|
|
@ -21,12 +21,16 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
|
||||
/**
|
||||
* Sets effective group id of current process.
|
||||
* Sets user id of current process.
|
||||
* @return 0 on success or -1 w/ errno
|
||||
*/
|
||||
int setuid(int uid) {
|
||||
int rc;
|
||||
rc = sys_setuid(uid);
|
||||
STRACE("%s(%d) → %d% m", "setuid", uid);
|
||||
if (IsWindows() && uid == getuid()) {
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = sys_setuid(uid);
|
||||
}
|
||||
STRACE("setuid(%d) → %d% m", uid, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ struct Signals {
|
|||
};
|
||||
|
||||
extern struct Signals __sig; // TODO(jart): Need TLS
|
||||
extern long __sig_count;
|
||||
|
||||
bool __sig_check(bool) hidden;
|
||||
bool __sig_handle(bool, int, int, ucontext_t *) hidden;
|
||||
|
|
|
@ -222,6 +222,7 @@ textwindows int __sig_add(int sig, int si_code) {
|
|||
if (1 <= sig && sig <= NSIG) {
|
||||
STRACE("enqueuing %G", sig);
|
||||
_spinlock(&__sig_lock);
|
||||
++__sig_count;
|
||||
if ((mem = __sig_alloc())) {
|
||||
mem->sig = sig;
|
||||
mem->si_code = si_code;
|
||||
|
|
21
libc/calls/sigcount.c
Normal file
21
libc/calls/sigcount.c
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/sig.internal.h"
|
||||
|
||||
long __sig_count;
|
|
@ -5,8 +5,8 @@
|
|||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
|
||||
#define _KERNTRACE 1 /* not configurable w/ flag yet */
|
||||
#define _POLLTRACE 1 /* not configurable w/ flag yet */
|
||||
#define _KERNTRACE 0 /* not configurable w/ flag yet */
|
||||
#define _POLLTRACE 0 /* not configurable w/ flag yet */
|
||||
#define _DATATRACE 1 /* not configurable w/ flag yet */
|
||||
#define _NTTRACE 1 /* not configurable w/ flag yet */
|
||||
|
||||
|
@ -19,7 +19,7 @@ COSMOPOLITAN_C_START_
|
|||
#define STRACE(FMT, ...) \
|
||||
do { \
|
||||
if (__strace > 0) { \
|
||||
__stracef(STRACE_PROLOGUE FMT "%n", ##__VA_ARGS__); \
|
||||
__stracef(STRACE_PROLOGUE FMT "\n", ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
|
|
|
@ -53,8 +53,8 @@ textwindows int sys_symlinkat_nt(const char *target, int newdirfd,
|
|||
const char *linkpath) {
|
||||
int targetlen;
|
||||
uint32_t attrs, flags;
|
||||
char16_t target16[PATH_MAX];
|
||||
char16_t linkpath16[PATH_MAX];
|
||||
char16_t target16[PATH_MAX + 1];
|
||||
char16_t linkpath16[PATH_MAX + 1];
|
||||
|
||||
// convert the paths
|
||||
if (__mkntpathat(newdirfd, linkpath, 0, linkpath16) == -1) return -1;
|
||||
|
|
|
@ -28,7 +28,7 @@ textwindows int sys_truncate_nt(const char *path, uint64_t length) {
|
|||
int rc;
|
||||
bool32 ok;
|
||||
int64_t fh;
|
||||
uint16_t path16[PATH_MAX];
|
||||
uint16_t path16[PATH_MAX + 1];
|
||||
if (__mkntpath(path, path16) == -1) return -1;
|
||||
if ((fh = CreateFile(path16, kNtGenericWrite, kNtFileShareRead, NULL,
|
||||
kNtOpenExisting, kNtFileAttributeNormal, 0)) != -1) {
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/log/log.h"
|
||||
|
||||
static char ttyname_buf[PATH_MAX];
|
||||
static char ttyname_buf[PATH_MAX + 1];
|
||||
|
||||
/**
|
||||
* Returns name of terminal.
|
||||
|
|
|
@ -63,7 +63,7 @@ static int ttyname_freebsd(int fd, char *buf, size_t size) {
|
|||
static int ttyname_linux(int fd, char *buf, size_t size) {
|
||||
struct stat st1, st2;
|
||||
if (!isatty(fd)) return errno;
|
||||
char name[PATH_MAX];
|
||||
char name[PATH_MAX + 1];
|
||||
FormatInt32(stpcpy(name, "/proc/self/fd/"), fd);
|
||||
ssize_t got;
|
||||
got = readlink(name, buf, size);
|
||||
|
|
|
@ -39,7 +39,8 @@
|
|||
* from failing for no reason at all. For example a unit test that
|
||||
* repeatedly opens and unlinks the same filename.
|
||||
*/
|
||||
static textwindows int SyncDirectory(int df, char16_t path[PATH_MAX], int n) {
|
||||
static textwindows int SyncDirectory(int df, char16_t path[PATH_MAX + 1],
|
||||
int n) {
|
||||
int rc;
|
||||
int64_t fh;
|
||||
char16_t *p;
|
||||
|
@ -128,7 +129,7 @@ static textwindows int sys_unlink_nt(const char16_t *path) {
|
|||
|
||||
textwindows int sys_unlinkat_nt(int dirfd, const char *path, int flags) {
|
||||
int n, rc;
|
||||
char16_t path16[PATH_MAX];
|
||||
char16_t path16[PATH_MAX + 1];
|
||||
if ((n = __mkntpathat(dirfd, path, 0, path16)) == -1) {
|
||||
rc = -1;
|
||||
} else if (flags & AT_REMOVEDIR) {
|
||||
|
|
|
@ -35,7 +35,7 @@ textwindows int sys_utimensat_nt(int dirfd, const char *path,
|
|||
const struct timespec ts[2], int flags) {
|
||||
int i, rc;
|
||||
int64_t fh;
|
||||
uint16_t path16[PATH_MAX];
|
||||
uint16_t path16[PATH_MAX + 1];
|
||||
struct NtFileTime ft[2], *ftp[2];
|
||||
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
|
||||
if ((fh = CreateFile(path16, kNtFileWriteAttributes, kNtFileShareRead, NULL,
|
||||
|
|
|
@ -95,7 +95,11 @@ static textwindows int sys_wait4_nt_impl(int pid, int *opt_out_wstatus,
|
|||
return 0;
|
||||
}
|
||||
} else {
|
||||
i = WaitForMultipleObjects(count, handles, false, -1);
|
||||
i = WaitForMultipleObjects(count, handles, false,
|
||||
__SIG_POLLING_INTERVAL_MS);
|
||||
if (i == kNtWaitTimeout) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (i == kNtWaitFailed) {
|
||||
STRACE("%s failed %u", "WaitForMultipleObjects", GetLastError());
|
||||
|
|
|
@ -79,7 +79,7 @@ ssize_t writev(int fd, const struct iovec *iov, int iovlen) {
|
|||
} else {
|
||||
kprintf(STRACE_PROLOGUE "writev(%d, ", fd);
|
||||
__strace_iov(iov, iovlen, rc != -1 ? rc : 0);
|
||||
kprintf(", %d) → %'ld% m%n", iovlen, rc);
|
||||
kprintf(", %d) → %'ld% m\n", iovlen, rc);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -37,7 +37,7 @@ static struct HostsTxtInitialStaticMemory {
|
|||
} g_hoststxt_init;
|
||||
|
||||
static textwindows dontinline char *GetNtHostsTxtPath(char *pathbuf,
|
||||
uint32_t size) {
|
||||
uint32_t size) {
|
||||
const char *const kWinHostsPath = "\\drivers\\etc\\hosts";
|
||||
uint32_t len = GetSystemDirectoryA(&pathbuf[0], size);
|
||||
if (len && len + strlen(kWinHostsPath) + 1 < size) {
|
||||
|
@ -57,7 +57,7 @@ static textwindows dontinline char *GetNtHostsTxtPath(char *pathbuf,
|
|||
const struct HostsTxt *GetHostsTxt(void) {
|
||||
FILE *f;
|
||||
const char *path;
|
||||
char pathbuf[PATH_MAX];
|
||||
char pathbuf[PATH_MAX + 1];
|
||||
struct HostsTxtInitialStaticMemory *init;
|
||||
init = &g_hoststxt_init;
|
||||
if (!g_hoststxt) {
|
||||
|
|
|
@ -48,10 +48,10 @@ int LookupProtoByName(const char *protoname, char *buf, size_t bufsize,
|
|||
const char *filepath) {
|
||||
FILE *f;
|
||||
char *line;
|
||||
char pathbuf[PATH_MAX];
|
||||
const char *path;
|
||||
size_t linesize;
|
||||
int found, result;
|
||||
char pathbuf[PATH_MAX + 1];
|
||||
char *name, *number, *alias, *comment, *tok;
|
||||
if (!(path = filepath)) {
|
||||
path = "/etc/protocols";
|
||||
|
|
|
@ -52,10 +52,10 @@ int LookupProtoByNumber(const int protonum, char *buf, size_t bufsize,
|
|||
const char *filepath) {
|
||||
FILE *f;
|
||||
char *line;
|
||||
char pathbuf[PATH_MAX];
|
||||
const char *path;
|
||||
size_t linesize;
|
||||
int found;
|
||||
size_t linesize;
|
||||
const char *path;
|
||||
char pathbuf[PATH_MAX + 1];
|
||||
char *name, *number, *comment, *tok;
|
||||
if (!(path = filepath)) {
|
||||
path = "/etc/protocols";
|
||||
|
|
|
@ -53,10 +53,10 @@ int LookupServicesByName(const char *servname, char *servproto,
|
|||
const char *filepath) {
|
||||
FILE *f;
|
||||
char *line;
|
||||
char pathbuf[PATH_MAX];
|
||||
const char *path;
|
||||
size_t linesize;
|
||||
int found, result;
|
||||
char pathbuf[PATH_MAX + 1];
|
||||
char *name, *port, *proto, *alias, *comment, *tok;
|
||||
if (!(path = filepath)) {
|
||||
path = "/etc/services";
|
||||
|
|
|
@ -59,7 +59,7 @@ int LookupServicesByPort(const int servport, char *servproto,
|
|||
const char *filepath) {
|
||||
FILE *f;
|
||||
char *line;
|
||||
char pathbuf[PATH_MAX];
|
||||
char pathbuf[PATH_MAX + 1];
|
||||
const char *path;
|
||||
size_t linesize;
|
||||
int found;
|
||||
|
|
|
@ -18,6 +18,11 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/conv.h"
|
||||
|
||||
int(abs)(int x) {
|
||||
/**
|
||||
* Returns absolute value of 32-bit integer.
|
||||
* @note `labs(LONG_MIN)` returns `LONG_MIN` unless `-ftrapv`
|
||||
* @note consider ABS() to avoid narrowing
|
||||
*/
|
||||
int abs(int x) {
|
||||
return 0 < x ? x : -x;
|
||||
}
|
||||
|
|
|
@ -368,9 +368,6 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
|||
}
|
||||
break;
|
||||
case 'n':
|
||||
// nonstandard %n specifier
|
||||
// used to print newlines that work in raw terminal modes
|
||||
if (__nomultics) __FMT_PUT('\r');
|
||||
__FMT_PUT('\n');
|
||||
break;
|
||||
case 'F':
|
||||
|
|
|
@ -26,10 +26,6 @@ int sscanf(const char *, const char *, ...) scanfesque(2);
|
|||
int vsscanf(const char *, const char *, va_list);
|
||||
int vcscanf(int (*)(void *), int (*)(int, void *), void *, const char *,
|
||||
va_list);
|
||||
int strerror_r(int, char *, size_t) dontthrow nocallback;
|
||||
int strerror_wr(int, uint32_t, char *, size_t) dontthrow nocallback;
|
||||
const char *strerror_short(int) nosideeffect;
|
||||
const char *strerror_long(int) nosideeffect;
|
||||
int __fmt(void *, void *, const char *, va_list) hidden;
|
||||
char *itoa(int, char *, int) compatfn;
|
||||
char *fcvt(double, int, int *, int *);
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
#include "libc/macros.internal.h"
|
||||
|
||||
.macro .e e s
|
||||
.long \e - kErrorNamesLong
|
||||
.long 1f - kErrorNamesLong
|
||||
.long \e - kErrnoDocs
|
||||
.long 1f - kErrnoDocs
|
||||
.rodata.str1.1
|
||||
1: .asciz "\s"
|
||||
.previous
|
||||
|
@ -29,7 +29,7 @@
|
|||
.section .rodata
|
||||
.align 4
|
||||
.underrun
|
||||
kErrorNamesLong:
|
||||
kErrnoDocs:
|
||||
.e EINVAL,"Invalid argument"
|
||||
.e ENOSYS,"Function not implemented"
|
||||
.e EPERM,"Operation not permitted"
|
||||
|
@ -115,6 +115,6 @@ kErrorNamesLong:
|
|||
.e ENOTRECOVERABLE,"State not recoverable"
|
||||
.e ENONET,"Machine is not on the network"
|
||||
.e ERESTART,"Interrupted system call should be restarted"
|
||||
.long 0
|
||||
.endobj kErrorNamesLong,globl,hidden
|
||||
.long -123
|
||||
.endobj kErrnoDocs,globl,hidden
|
||||
.overrun
|
|
@ -19,8 +19,8 @@
|
|||
#include "libc/macros.internal.h"
|
||||
|
||||
.macro .e e
|
||||
.long \e - kErrorNames
|
||||
.long 1f - kErrorNames
|
||||
.long \e - kErrnoNames
|
||||
.long 1f - kErrnoNames
|
||||
.rodata.str1.1
|
||||
1: .string "\e"
|
||||
.previous
|
||||
|
@ -29,7 +29,7 @@
|
|||
.section .rodata
|
||||
.align 4
|
||||
.underrun
|
||||
kErrorNames:
|
||||
kErrnoNames:
|
||||
.e EINVAL
|
||||
.e ENOSYS
|
||||
.e EPERM
|
||||
|
@ -116,6 +116,6 @@ kErrorNames:
|
|||
.e ENONET
|
||||
.e ERESTART
|
||||
.e ENODATA
|
||||
.long 0
|
||||
.endobj kErrorNames,globl,hidden
|
||||
.long -123
|
||||
.endobj kErrnoNames,globl,hidden
|
||||
.overrun
|
|
@ -1,16 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_FMT_KERRORNAMES_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_FMT_KERRORNAMES_INTERNAL_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct ErrorName {
|
||||
int x, s;
|
||||
};
|
||||
|
||||
extern const struct ErrorName kStrSignal[];
|
||||
extern const struct ErrorName kErrorNames[];
|
||||
extern const struct ErrorName kErrorNamesLong[];
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_FMT_KERRORNAMES_INTERNAL_H_ */
|
|
@ -17,8 +17,12 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
long(labs)(long x) {
|
||||
return ABS(x);
|
||||
/**
|
||||
* Returns absolute value of long integer.
|
||||
* @note `labs(LONG_MIN)` returns `LONG_MIN` unless `-ftrapv`
|
||||
* @note consider ABS() to avoid narrowing
|
||||
*/
|
||||
long labs(long x) {
|
||||
return 0 < x ? x : -x;
|
||||
}
|
||||
|
|
|
@ -17,8 +17,12 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
long long(llabs)(long long x) {
|
||||
return ABS(x);
|
||||
/**
|
||||
* Returns absolute value of long long integer.
|
||||
* @note `llabs(LONG_LONG_MIN)` returns `LONG_LONG_MIN` unless `-ftrapv`
|
||||
* @note consider ABS() to avoid narrowing
|
||||
*/
|
||||
long long llabs(long long x) {
|
||||
return 0 < x ? x : -x;
|
||||
}
|
||||
|
|
23
libc/fmt/magnumstrs.internal.h
Normal file
23
libc/fmt/magnumstrs.internal.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_FMT_MAGNUMSTRS_H_
|
||||
#define COSMOPOLITAN_LIBC_FMT_MAGNUMSTRS_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct MagnumStr {
|
||||
int x, s;
|
||||
};
|
||||
|
||||
extern const struct MagnumStr kErrnoDocs[];
|
||||
extern const struct MagnumStr kErrnoNames[];
|
||||
extern const struct MagnumStr kIpOptnames[];
|
||||
extern const struct MagnumStr kSignalNames[];
|
||||
extern const struct MagnumStr kSockOptnames[];
|
||||
extern const struct MagnumStr kTcpOptnames[];
|
||||
|
||||
const char *DescribeSockLevel(int);
|
||||
const char *DescribeSockOptname(int, int);
|
||||
const char *GetMagnumStr(const struct MagnumStr *, int);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_FMT_MAGNUMSTRS_H_ */
|
|
@ -17,23 +17,16 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/fmt/kerrornames.internal.h"
|
||||
#include "libc/fmt/magnumstrs.internal.h"
|
||||
|
||||
/**
|
||||
* Converts errno value to descriptive sentence.
|
||||
* @return non-null rodata string or null if not found
|
||||
*/
|
||||
privileged const char *strerror_long(int x) {
|
||||
/* kprintf() weakly depends on this function */
|
||||
int i;
|
||||
const char *strerdoc(int x) {
|
||||
if (x) {
|
||||
for (i = 0; kErrorNamesLong[i].x; ++i) {
|
||||
if (x ==
|
||||
*(const long *)((uintptr_t)kErrorNamesLong + kErrorNamesLong[i].x)) {
|
||||
return (const char *)((uintptr_t)kErrorNamesLong +
|
||||
kErrorNamesLong[i].s);
|
||||
}
|
||||
}
|
||||
return GetMagnumStr(kErrnoDocs, x);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -16,22 +16,17 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/fmt/kerrornames.internal.h"
|
||||
#include "libc/fmt/magnumstrs.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Converts errno value to symbolic name.
|
||||
* @return non-null rodata string or null if not found
|
||||
*/
|
||||
privileged const char *strerror_short(int x) {
|
||||
/* kprintf() weakly depends on this function */
|
||||
int i;
|
||||
const char *strerrno(int x) {
|
||||
if (x) {
|
||||
for (i = 0; kErrorNames[i].x; ++i) {
|
||||
if (x == *(const int *)((uintptr_t)kErrorNames + kErrorNames[i].x)) {
|
||||
return (const char *)((uintptr_t)kErrorNames + kErrorNames[i].s);
|
||||
}
|
||||
}
|
||||
return GetMagnumStr(kErrnoNames, x);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -23,9 +23,9 @@
|
|||
* Converts errno value to string non-reentrantly.
|
||||
* @see strerror_r()
|
||||
*/
|
||||
noasan char *strerror(int err) {
|
||||
char *strerror(int err) {
|
||||
if (IsTiny()) {
|
||||
return firstnonnull(strerror_short(err), "EUNKNOWN");
|
||||
return firstnonnull(strerrno(err), "EUNKNOWN");
|
||||
} else {
|
||||
_Alignas(1) static char buf[512];
|
||||
strerror_r(err, buf, sizeof(buf));
|
||||
|
|
|
@ -25,6 +25,6 @@
|
|||
* @param err is error number or zero if unknown
|
||||
* @return 0 on success, or error code
|
||||
*/
|
||||
privileged int strerror_r(int err, char *buf, size_t size) {
|
||||
int strerror_r(int err, char *buf, size_t size) {
|
||||
return strerror_wr(err, GetLastError(), buf, size);
|
||||
}
|
||||
|
|
|
@ -32,13 +32,13 @@
|
|||
* @param err is error number or zero if unknown
|
||||
* @return 0 on success, or error code
|
||||
*/
|
||||
privileged int strerror_wr(int err, uint32_t winerr, char *buf, size_t size) {
|
||||
int strerror_wr(int err, uint32_t winerr, char *buf, size_t size) {
|
||||
/* kprintf() weakly depends on this function */
|
||||
int c, n;
|
||||
char16_t winmsg[256];
|
||||
const char *sym, *msg;
|
||||
sym = firstnonnull(strerror_short(err), "EUNKNOWN");
|
||||
msg = firstnonnull(strerror_long(err), "No error information");
|
||||
sym = firstnonnull(strerrno(err), "EUNKNOWN");
|
||||
msg = firstnonnull(strerdoc(err), "No error information");
|
||||
if (IsTiny()) {
|
||||
if (!sym) sym = "EUNKNOWN";
|
||||
for (; (c = *sym++); --size)
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
#define CACHELINE 0x40 /* nexgen32e */
|
||||
#define CHAR_BIT 8 /* b/c von neumann */
|
||||
#define ARG_MAX 0x8000 /* b/c windows */
|
||||
#define PATH_MAX 248 /* b/c win32 apis limit ~248..260 */
|
||||
#define PATH_MAX 512 /* b/c bloat */
|
||||
#define NAME_MAX 63 /* b/c dns */
|
||||
#define CHILD_MAX 25 /* only if malloc isn't linked */
|
||||
#define OPEN_MAX 16 /* only if malloc isn't linked */
|
||||
|
|
|
@ -59,7 +59,7 @@ STATIC_YOINK("_init_asan");
|
|||
|
||||
#define ASAN_MORGUE_ITEMS 512
|
||||
#define ASAN_MORGUE_THRESHOLD 65536 // morgue memory O(ITEMS*THRESHOLD)
|
||||
#define ASAN_TRACE_ITEMS 16 // backtrace limit on malloc origin
|
||||
#define ASAN_TRACE_ITEMS 16 // backtrace limit on malloc origin
|
||||
|
||||
/**
|
||||
* @fileoverview Cosmopolitan Address Sanitizer Runtime.
|
||||
|
@ -102,7 +102,7 @@ STATIC_YOINK("_init_asan");
|
|||
#define REQUIRE(FUNC) \
|
||||
do { \
|
||||
if (!weaken(FUNC)) { \
|
||||
kprintf("error: asan needs %s%n", #FUNC); \
|
||||
kprintf("error: asan needs %s\n", #FUNC); \
|
||||
__asan_die()(); \
|
||||
__asan_unreachable(); \
|
||||
} \
|
||||
|
@ -179,8 +179,7 @@ static uint64_t __asan_roundup2pow(uint64_t x) {
|
|||
static char *__asan_utf8cpy(char *p, unsigned c) {
|
||||
uint64_t z;
|
||||
z = tpenc(c);
|
||||
do
|
||||
*p++ = z;
|
||||
do *p++ = z;
|
||||
while ((z >>= 8));
|
||||
return p;
|
||||
}
|
||||
|
@ -322,9 +321,9 @@ static char *__asan_hexcpy(char *p, uint64_t x, uint8_t k) {
|
|||
}
|
||||
|
||||
static void __asan_exit(void) {
|
||||
kprintf("your asan runtime needs%n"
|
||||
"\tSTATIC_YOINK(\"__die\");%n"
|
||||
"in order to show you backtraces%n");
|
||||
kprintf("your asan runtime needs\n"
|
||||
"\tSTATIC_YOINK(\"__die\");\n"
|
||||
"in order to show you backtraces\n");
|
||||
__restorewintty();
|
||||
_Exit(99);
|
||||
}
|
||||
|
@ -373,6 +372,7 @@ void __asan_unpoison(long p, long n) {
|
|||
}
|
||||
|
||||
static bool __asan_is_mapped(int x) {
|
||||
// xxx: we can't lock because no reentrant locks yet
|
||||
int i;
|
||||
struct MemoryIntervals *m;
|
||||
m = weaken(_mmi);
|
||||
|
@ -609,7 +609,7 @@ const char *__asan_describe_access_poison(signed char kind) {
|
|||
|
||||
dontdiscard static __asan_die_f *__asan_report_invalid_pointer(
|
||||
const void *addr) {
|
||||
kprintf("%n\e[J\e[1;31masan error\e[0m: this corruption at %p shadow %p%n",
|
||||
kprintf("\n\e[J\e[1;31masan error\e[0m: this corruption at %p shadow %p\n",
|
||||
addr, SHADOW(addr));
|
||||
return __asan_die();
|
||||
}
|
||||
|
@ -629,7 +629,6 @@ static char *__asan_format_section(char *p, const void *p1, const void *p2,
|
|||
if (a <= (intptr_t)addr && (intptr_t)addr <= b) {
|
||||
p = __stpcpy(p, " ←address");
|
||||
}
|
||||
if (__nomultics) *p++ = '\r';
|
||||
*p++ = '\n';
|
||||
}
|
||||
return p;
|
||||
|
@ -638,7 +637,7 @@ static char *__asan_format_section(char *p, const void *p1, const void *p2,
|
|||
static void __asan_report_memory_origin_image(intptr_t a, int z) {
|
||||
unsigned l, m, r, n, k;
|
||||
struct SymbolTable *st;
|
||||
kprintf("%nthe memory belongs to image symbols%n");
|
||||
kprintf("\nthe memory belongs to image symbols\n");
|
||||
if (weaken(GetSymbolTable)) {
|
||||
if ((st = weaken(GetSymbolTable)())) {
|
||||
l = 0;
|
||||
|
@ -656,7 +655,7 @@ static void __asan_report_memory_origin_image(intptr_t a, int z) {
|
|||
if ((st->symbols[l].x <= k && k <= st->symbols[l].y) ||
|
||||
(st->symbols[l].x <= k + z && k + z <= st->symbols[l].y) ||
|
||||
(k < st->symbols[l].x && st->symbols[l].y < k + z)) {
|
||||
kprintf("\t%s [%#x,%#x] size %'d%n", st->name_base + st->names[l],
|
||||
kprintf("\t%s [%#x,%#x] size %'d\n", st->name_base + st->names[l],
|
||||
st->addr_base + st->symbols[l].x,
|
||||
st->addr_base + st->symbols[l].y,
|
||||
st->symbols[l].y - st->symbols[l].x + 1);
|
||||
|
@ -665,10 +664,10 @@ static void __asan_report_memory_origin_image(intptr_t a, int z) {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
kprintf("\tunknown please supply .com.dbg symbols or set COMDBG%n");
|
||||
kprintf("\tunknown please supply .com.dbg symbols or set COMDBG\n");
|
||||
}
|
||||
} else {
|
||||
kprintf("\tunknown please STATIC_YOINK(\"GetSymbolTable\");%n");
|
||||
kprintf("\tunknown please STATIC_YOINK(\"GetSymbolTable\");\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -686,13 +685,13 @@ static noasan void OnMemory(void *x, void *y, size_t n, void *a) {
|
|||
|
||||
static void __asan_report_memory_origin_heap(const unsigned char *a, int z) {
|
||||
struct ReportOriginHeap t;
|
||||
kprintf("%nthe memory was allocated by%n");
|
||||
kprintf("\nthe memory was allocated by\n");
|
||||
if (weaken(malloc_inspect_all)) {
|
||||
t.a = a;
|
||||
t.z = z;
|
||||
weaken(malloc_inspect_all)(OnMemory, &t);
|
||||
} else {
|
||||
kprintf("\tunknown please STATIC_YOINK(\"malloc_inspect_all\");%n");
|
||||
kprintf("\tunknown please STATIC_YOINK(\"malloc_inspect_all\");\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -737,7 +736,7 @@ dontdiscard static __asan_die_f *__asan_report(const void *addr, int size,
|
|||
struct MemoryIntervals *m;
|
||||
++g_ftrace;
|
||||
p = __fatalbuf;
|
||||
kprintf("%n\e[J\e[1;31masan error\e[0m: %s %d-byte %s at %p shadow %p%n%s%n",
|
||||
kprintf("\n\e[J\e[1;31masan error\e[0m: %s %d-byte %s at %p shadow %p\n%s\n",
|
||||
__asan_describe_access_poison(kind), size, message, addr,
|
||||
SHADOW(addr), __argv[0]);
|
||||
if (0 < size && size < 80) {
|
||||
|
@ -753,7 +752,6 @@ dontdiscard static __asan_die_f *__asan_report(const void *addr, int size,
|
|||
*p++ = ' ';
|
||||
}
|
||||
}
|
||||
if (__nomultics) *p++ = '\r';
|
||||
*p++ = '\n';
|
||||
for (c = i = 0; i < 80; ++i) {
|
||||
if (!(t = __asan_check(base + i, 1).kind)) {
|
||||
|
@ -771,7 +769,6 @@ dontdiscard static __asan_die_f *__asan_report(const void *addr, int size,
|
|||
}
|
||||
}
|
||||
p = __stpcpy(p, "\e[39m");
|
||||
if (__nomultics) *p++ = '\r';
|
||||
*p++ = '\n';
|
||||
for (i = 0; (intptr_t)(base + i) & 7; ++i) *p++ = ' ';
|
||||
for (; i + 8 <= 80; i += 8) {
|
||||
|
@ -788,19 +785,18 @@ dontdiscard static __asan_die_f *__asan_report(const void *addr, int size,
|
|||
}
|
||||
}
|
||||
for (; i < 80; ++i) *p++ = ' ';
|
||||
if (__nomultics) *p++ = '\r';
|
||||
*p++ = '\n';
|
||||
for (i = 0; i < 80; ++i) {
|
||||
p = __asan_utf8cpy(p, __asan_exists(base + i)
|
||||
? kCp437[((unsigned char *)base)[i]]
|
||||
: L'⋅');
|
||||
}
|
||||
if (__nomultics) *p++ = '\r';
|
||||
*p++ = '\n';
|
||||
}
|
||||
p = __asan_format_section(p, _base, _etext, ".text", addr);
|
||||
p = __asan_format_section(p, _etext, _edata, ".data", addr);
|
||||
p = __asan_format_section(p, _end, _edata, ".bss", addr);
|
||||
// xxx: we can't lock because no reentrant locks yet
|
||||
for (m = weaken(_mmi), i = 0; i < m->i; ++i) {
|
||||
x = m->p[i].x;
|
||||
y = m->p[i].y;
|
||||
|
@ -809,13 +805,12 @@ dontdiscard static __asan_die_f *__asan_report(const void *addr, int size,
|
|||
if (x <= z && z <= y) p = __stpcpy(p, " ←address");
|
||||
z = (((intptr_t)addr >> 3) + 0x7fff8000) >> 16;
|
||||
if (x <= z && z <= y) p = __stpcpy(p, " ←shadow");
|
||||
if (__nomultics) *p++ = '\r';
|
||||
*p++ = '\n';
|
||||
}
|
||||
*p = 0;
|
||||
kprintf("%s", __fatalbuf);
|
||||
__asan_report_memory_origin(addr, size, kind);
|
||||
kprintf("%nthe crash was caused by%n");
|
||||
kprintf("\nthe crash was caused by\n");
|
||||
--g_ftrace;
|
||||
return __asan_die();
|
||||
}
|
||||
|
@ -924,8 +919,7 @@ static void __asan_trace(struct AsanTrace *bt, const struct StackFrame *bp) {
|
|||
if (!__asan_checka(SHADOW(bp), sizeof(*bp) >> 3).kind) {
|
||||
addr = bp->addr;
|
||||
if (addr == weakaddr("__gc") && weakaddr("__gc")) {
|
||||
do
|
||||
--gi;
|
||||
do --gi;
|
||||
while ((addr = garbage->p[gi].ret) == weakaddr("__gc"));
|
||||
}
|
||||
bt->p[i] = addr;
|
||||
|
@ -1018,12 +1012,12 @@ int __asan_print_trace(void *p) {
|
|||
kprintf(" bad cookie");
|
||||
return -1;
|
||||
}
|
||||
kprintf("%n%p %,lu bytes [asan]", (char *)p, n);
|
||||
kprintf("\n%p %,lu bytes [asan]", (char *)p, n);
|
||||
if (!__asan_is_mapped((((intptr_t)p >> 3) + 0x7fff8000) >> 16)) {
|
||||
kprintf(" (shadow not mapped?!)");
|
||||
}
|
||||
for (i = 0; i < ARRAYLEN(e->bt.p) && e->bt.p[i]; ++i) {
|
||||
kprintf("%n%*lx %s", 12, e->bt.p[i],
|
||||
kprintf("\n%*lx %s", 12, e->bt.p[i],
|
||||
weaken(__get_symbol_by_addr)
|
||||
? weaken(__get_symbol_by_addr)(e->bt.p[i])
|
||||
: "please STATIC_YOINK(\"__get_symbol_by_addr\")");
|
||||
|
@ -1203,7 +1197,7 @@ void __asan_evil(uint8_t *addr, int size, const char *s1, const char *s2) {
|
|||
struct AsanTrace tr;
|
||||
__asan_rawtrace(&tr, __builtin_frame_address(0));
|
||||
kprintf(
|
||||
"WARNING: ASAN error during %s bad %d byte %s at %x bt %x %x %x %x %x%n",
|
||||
"WARNING: ASAN error during %s bad %d byte %s at %x bt %x %x %x %x %x\n",
|
||||
s1, size, s2, addr, tr.p[0], tr.p[1], tr.p[2], tr.p[3], tr.p[4], tr.p[5]);
|
||||
}
|
||||
|
||||
|
@ -1281,6 +1275,7 @@ void __asan_install_malloc_hooks(void) {
|
|||
}
|
||||
|
||||
void __asan_map_shadow(uintptr_t p, size_t n) {
|
||||
// assume _mmi.lock is held
|
||||
void *addr;
|
||||
int i, a, b;
|
||||
size_t size;
|
||||
|
@ -1311,7 +1306,7 @@ void __asan_map_shadow(uintptr_t p, size_t n) {
|
|||
m, a, a + i - 1, sm.maphandle, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | *weaken(MAP_ANONYMOUS) | MAP_FIXED, false, false, 0,
|
||||
size) == -1) {
|
||||
kprintf("error: could not map asan shadow memory%n");
|
||||
kprintf("error: could not map asan shadow memory\n");
|
||||
__asan_die()();
|
||||
__asan_unreachable();
|
||||
}
|
||||
|
|
|
@ -35,12 +35,12 @@ relegated wontreturn void __assert_fail(const char *expr, const char *file,
|
|||
static bool noreentry;
|
||||
__strace = 0;
|
||||
g_ftrace = 0;
|
||||
kprintf("%s:%d: assert(%s) failed%n", file, line, expr);
|
||||
kprintf("%s:%d: assert(%s) failed\n", file, line, expr);
|
||||
if (_lockcmpxchg(&noreentry, false, true)) {
|
||||
if (weaken(__die)) {
|
||||
weaken(__die)();
|
||||
} else {
|
||||
kprintf("can't backtrace b/c `__die` not linked%n");
|
||||
kprintf("can't backtrace b/c `__die` not linked\n");
|
||||
}
|
||||
rc = 23;
|
||||
} else {
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(1)));
|
||||
typedef long long xmm_a __attribute__((__vector_size__(16), __aligned__(16)));
|
||||
|
||||
noasan static dontinline antiquity void bzero_sse(char *p, size_t n) {
|
||||
static dontinline antiquity void bzero_sse(char *p, size_t n) {
|
||||
xmm_t v = {0};
|
||||
if (IsAsan()) __asan_verify(p, n);
|
||||
if (n <= 32) {
|
||||
|
@ -43,7 +43,7 @@ noasan static dontinline antiquity void bzero_sse(char *p, size_t n) {
|
|||
}
|
||||
}
|
||||
|
||||
noasan microarchitecture("avx") static void bzero_avx(char *p, size_t n) {
|
||||
microarchitecture("avx") static void bzero_avx(char *p, size_t n) {
|
||||
xmm_t v = {0};
|
||||
if (IsAsan()) __asan_verify(p, n);
|
||||
if (n <= 32) {
|
||||
|
|
36
libc/intrin/getexitcodeprocess.greg.c
Normal file
36
libc/intrin/getexitcodeprocess.greg.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/nt/accounting.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
|
||||
__msabi extern typeof(GetExitCodeProcess) *const __imp_GetExitCodeProcess;
|
||||
|
||||
/**
|
||||
* Obtains exit code for process.
|
||||
* @note this wrapper takes care of ABI, STRACE(), and __winerr()
|
||||
*/
|
||||
textwindows int32_t GetExitCodeProcess(int64_t hProcess, uint32_t *lpExitCode) {
|
||||
int32_t rc;
|
||||
rc = __imp_GetExitCodeProcess(hProcess, lpExitCode);
|
||||
if (!rc) __winerr();
|
||||
NTTRACE("GetExitCodeProcess(%ld, [%u]) → %u% m", hProcess, *lpExitCode, rc);
|
||||
return rc;
|
||||
}
|
29
libc/intrin/getmagnumstr.greg.c
Normal file
29
libc/intrin/getmagnumstr.greg.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/magnumstrs.internal.h"
|
||||
|
||||
const char *GetMagnumStr(const struct MagnumStr *ms, int x) {
|
||||
int i;
|
||||
for (i = 0; ms[i].x != -123; ++i) {
|
||||
if (x == *(const int *)((uintptr_t)ms + ms[i].x)) {
|
||||
return (const char *)((uintptr_t)ms + ms[i].s);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -89,9 +89,12 @@ o/$(MODE)/libc/intrin/flushfilebuffers.greg.o \
|
|||
o/$(MODE)/libc/intrin/terminateprocess.greg.o \
|
||||
o/$(MODE)/libc/intrin/describemapflags.greg.o \
|
||||
o/$(MODE)/libc/intrin/getfileattributes.greg.o \
|
||||
o/$(MODE)/libc/intrin/getexitcodeprocess.greg.o \
|
||||
o/$(MODE)/libc/intrin/waitforsingleobject.greg.o \
|
||||
o/$(MODE)/libc/intrin/setcurrentdirectory.greg.o \
|
||||
o/$(MODE)/libc/intrin/mapviewoffileexnuma.greg.o \
|
||||
o/$(MODE)/libc/intrin/createfilemappingnuma.greg.o \
|
||||
o/$(MODE)/libc/intrin/waitformultipleobjects.greg.o \
|
||||
o/$(MODE)/libc/intrin/generateconsolectrlevent.greg.o \
|
||||
o/$(MODE)/libc/intrin/kstarttsc.o \
|
||||
o/$(MODE)/libc/intrin/nomultics.o \
|
||||
|
|
|
@ -114,7 +114,7 @@ kDos2Errno:
|
|||
.e kNtErrorCrc,EACCES
|
||||
.e kNtErrorDirNotEmpty,ENOTEMPTY
|
||||
.e kNtErrorDupName,EADDRINUSE
|
||||
.e kNtErrorFilenameExcedRange,ENOENT
|
||||
.e kNtErrorFilenameExcedRange,ENAMETOOLONG
|
||||
.e kNtErrorGenFailure,EACCES
|
||||
.e kNtErrorGracefulDisconnect,EPIPE
|
||||
.e kNtErrorHostDown,EHOSTUNREACH
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "libc/intrin/nomultics.internal.h"
|
||||
#include "libc/intrin/spinlock.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nexgen32e/rdtsc.h"
|
||||
#include "libc/nexgen32e/uart.internal.h"
|
||||
|
@ -174,6 +175,7 @@ privileged static inline bool kismemtrackhosed(void) {
|
|||
}
|
||||
|
||||
privileged static bool kismapped(int x) {
|
||||
// xxx: we can't lock because no reentrant locks yet
|
||||
size_t m, r, l = 0;
|
||||
if (!weaken(_mmi)) return true;
|
||||
if (kismemtrackhosed()) return false;
|
||||
|
@ -450,8 +452,7 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, va_list va,
|
|||
i = 0;
|
||||
m = (1 << base) - 1;
|
||||
if (hash && x) sign = hash;
|
||||
do
|
||||
z[i++ & 127] = abet[x & m];
|
||||
do z[i++ & 127] = abet[x & m];
|
||||
while ((x >>= base) || (pdot && i < prec));
|
||||
goto EmitNumber;
|
||||
|
||||
|
@ -556,11 +557,6 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, va_list va,
|
|||
|
||||
case 'n':
|
||||
// nonstandard %n specifier
|
||||
// used to print newlines that work in raw terminal modes
|
||||
if (__nomultics) {
|
||||
if (p < e) *p = '\r';
|
||||
++p;
|
||||
}
|
||||
if (p < e) *p = '\n';
|
||||
++p;
|
||||
break;
|
||||
|
@ -569,7 +565,7 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, va_list va,
|
|||
// undocumented %r specifier
|
||||
// used for good carriage return
|
||||
// helps integrate loggers with repls
|
||||
if (!__replmode) {
|
||||
if (!__replmode || __nocolor) {
|
||||
break;
|
||||
} else {
|
||||
s = "\r\033[K";
|
||||
|
@ -845,12 +841,12 @@ privileged size_t kvsnprintf(char *b, size_t n, const char *fmt, va_list v) {
|
|||
*/
|
||||
privileged void kvprintf(const char *fmt, va_list v) {
|
||||
size_t n;
|
||||
char b[2048];
|
||||
char b[4000];
|
||||
struct Timestamps t;
|
||||
if (!v) return;
|
||||
t = kenter();
|
||||
n = kformat(b, sizeof(b), fmt, v, t);
|
||||
klog(b, MIN(n, sizeof(b)));
|
||||
klog(b, MIN(n, sizeof(b) - 1));
|
||||
kleave(t);
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(1)));
|
||||
typedef long long xmm_a __attribute__((__vector_size__(16), __aligned__(16)));
|
||||
|
||||
noasan static dontinline antiquity void *memset_sse(char *p, char c, size_t n) {
|
||||
static dontinline antiquity void *memset_sse(char *p, char c, size_t n) {
|
||||
xmm_t v = {c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c};
|
||||
if (IsAsan()) __asan_verify(p, n);
|
||||
if (n <= 32) {
|
||||
|
@ -44,8 +44,7 @@ noasan static dontinline antiquity void *memset_sse(char *p, char c, size_t n) {
|
|||
return p;
|
||||
}
|
||||
|
||||
noasan microarchitecture("avx") static void *memset_avx(char *p, char c,
|
||||
size_t n) {
|
||||
microarchitecture("avx") static void *memset_avx(char *p, char c, size_t n) {
|
||||
char *t;
|
||||
xmm_t v = {c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c};
|
||||
if (IsAsan()) __asan_verify(p, n);
|
||||
|
|
|
@ -17,17 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
|
||||
/**
|
||||
* Controls disablement of MULTICS newlines.
|
||||
*
|
||||
* Normally we use `\n` for newlines. If this is `true` then we'll try
|
||||
* our best to use `\r\n`. This is toggled automatically on Windows or
|
||||
* when `ioctl(TCSETS)` disables `OPOST`.
|
||||
*
|
||||
* @see kprintf()
|
||||
*/
|
||||
char __nomultics;
|
||||
|
||||
/**
|
||||
* Controls ANSI prefix for log emissions.
|
||||
*
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue