mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-10 23:54:42 +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 \
|
--gc-sections \
|
||||||
--build-id=none \
|
--build-id=none \
|
||||||
--no-dynamic-linker \
|
--no-dynamic-linker \
|
||||||
-zmax-page-size=0x1000
|
-zmax-page-size=0x1000 #--cref -Map=$@.map
|
||||||
|
|
||||||
ZIPOBJ_FLAGS = \
|
ZIPOBJ_FLAGS = \
|
||||||
-b$(IMAGE_BASE_VIRTUAL)
|
-b$(IMAGE_BASE_VIRTUAL)
|
||||||
|
|
|
@ -31,13 +31,6 @@ int ttysetraw(struct termios *conf, int64_t flags) {
|
||||||
conf->c_cflag &= ~(CSIZE | PARENB);
|
conf->c_cflag &= ~(CSIZE | PARENB);
|
||||||
conf->c_cflag |= CS8;
|
conf->c_cflag |= CS8;
|
||||||
conf->c_iflag |= IUTF8;
|
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)) {
|
if (!(flags & kTtySigs)) {
|
||||||
conf->c_iflag &= ~(IGNBRK | BRKINT);
|
conf->c_iflag &= ~(IGNBRK | BRKINT);
|
||||||
conf->c_lflag &= ~(ISIG);
|
conf->c_lflag &= ~(ISIG);
|
||||||
|
|
|
@ -151,14 +151,6 @@ o/$(MODE)/examples/hello.com.dbg: \
|
||||||
$(APE_NO_MODIFY_SELF)
|
$(APE_NO_MODIFY_SELF)
|
||||||
@$(APELINK)
|
@$(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
|
o/$(MODE)/examples/nesemu1.o: QUOTA += -M512m
|
||||||
|
|
||||||
$(EXAMPLES_OBJS): examples/examples.mk
|
$(EXAMPLES_OBJS): examples/examples.mk
|
||||||
|
|
|
@ -7,30 +7,8 @@
|
||||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||||
╚─────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────*/
|
||||||
#endif
|
#endif
|
||||||
#include "libc/bits/safemacros.internal.h"
|
|
||||||
#include "libc/calls/calls.h"
|
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
|
|
||||||
int main() {
|
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;
|
char *exepath;
|
||||||
struct rusage r;
|
struct rusage r;
|
||||||
long double real;
|
long double real;
|
||||||
char exebuf[PATH_MAX];
|
char exebuf[PATH_MAX + 1];
|
||||||
if (argc >= 2) {
|
if (argc >= 2) {
|
||||||
if ((exepath = commandv(argv[1], exebuf))) {
|
if ((exepath = commandv(argv[1], exebuf, sizeof(exebuf)))) {
|
||||||
real = nowl();
|
real = nowl();
|
||||||
argv[1] = exepath;
|
argv[1] = exepath;
|
||||||
if ((ws = xvspawn(OnChild, argv + 1, &r)) != -1) {
|
if ((ws = xvspawn(OnChild, argv + 1, &r)) != -1) {
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
int i;
|
int i;
|
||||||
for (i = 1; i < argc; ++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));
|
fprintf(stderr, "ERROR: %s: %s\n", argv[i], strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,7 +75,7 @@ bool isregularfile(const char *);
|
||||||
bool issymlink(const char *);
|
bool issymlink(const char *);
|
||||||
bool32 isatty(int) nosideeffect;
|
bool32 isatty(int) nosideeffect;
|
||||||
bool32 ischardev(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 *get_current_dir_name(void) dontdiscard;
|
||||||
char *getcwd(char *, size_t);
|
char *getcwd(char *, size_t);
|
||||||
char *realpath(const char *, char *);
|
char *realpath(const char *, char *);
|
||||||
|
@ -120,13 +120,16 @@ int ftruncate(int, int64_t);
|
||||||
int getdents(unsigned, void *, unsigned, long *);
|
int getdents(unsigned, void *, unsigned, long *);
|
||||||
int getdomainname(char *, size_t);
|
int getdomainname(char *, size_t);
|
||||||
int gethostname(char *, size_t);
|
int gethostname(char *, size_t);
|
||||||
|
int getloadavg(double *, int);
|
||||||
int getpgid(int);
|
int getpgid(int);
|
||||||
|
int getpgrp(void) nosideeffect;
|
||||||
int getpid(void);
|
int getpid(void);
|
||||||
int gettid(void);
|
|
||||||
int getppid(void);
|
int getppid(void);
|
||||||
int getpriority(int, unsigned);
|
int getpriority(int, unsigned);
|
||||||
int getrlimit(int, struct rlimit *);
|
int getrlimit(int, struct rlimit *);
|
||||||
int getrusage(int, struct rusage *);
|
int getrusage(int, struct rusage *);
|
||||||
|
int getsid(int) nosideeffect;
|
||||||
|
int gettid(void);
|
||||||
int kill(int, int);
|
int kill(int, int);
|
||||||
int killpg(int, int);
|
int killpg(int, int);
|
||||||
int link(const char *, const char *) dontthrow;
|
int link(const char *, const char *) dontthrow;
|
||||||
|
@ -165,11 +168,12 @@ int rmdir(const char *);
|
||||||
int sched_getaffinity(int, uint64_t, void *);
|
int sched_getaffinity(int, uint64_t, void *);
|
||||||
int sched_setaffinity(int, uint64_t, const void *);
|
int sched_setaffinity(int, uint64_t, const void *);
|
||||||
int sched_yield(void);
|
int sched_yield(void);
|
||||||
|
int seccomp(unsigned, unsigned, void *);
|
||||||
int setegid(uint32_t);
|
int setegid(uint32_t);
|
||||||
int seteuid(uint32_t);
|
int seteuid(uint32_t);
|
||||||
int setgid(int);
|
int setgid(int);
|
||||||
int setpgrp(void);
|
|
||||||
int setpgid(int, int);
|
int setpgid(int, int);
|
||||||
|
int setpgrp(void);
|
||||||
int setpriority(int, unsigned, int);
|
int setpriority(int, unsigned, int);
|
||||||
int setregid(uint32_t, uint32_t);
|
int setregid(uint32_t, uint32_t);
|
||||||
int setresgid(uint32_t, uint32_t, uint32_t);
|
int setresgid(uint32_t, uint32_t, uint32_t);
|
||||||
|
@ -206,9 +210,9 @@ long ptrace(int, ...);
|
||||||
long telldir(DIR *);
|
long telldir(DIR *);
|
||||||
long times(struct tms *);
|
long times(struct tms *);
|
||||||
size_t GetFileSize(const char *);
|
size_t GetFileSize(const char *);
|
||||||
ssize_t getfiledescriptorsize(int);
|
|
||||||
ssize_t copy_file_range(int, long *, int, long *, size_t, uint32_t);
|
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 copyfd(int, int64_t *, int, int64_t *, size_t, uint32_t);
|
||||||
|
ssize_t getfiledescriptorsize(int);
|
||||||
ssize_t lseek(int, int64_t, unsigned);
|
ssize_t lseek(int, int64_t, unsigned);
|
||||||
ssize_t pread(int, void *, size_t, int64_t);
|
ssize_t pread(int, void *, size_t, int64_t);
|
||||||
ssize_t preadv(int, struct iovec *, int, 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 getegid(void) nosideeffect;
|
||||||
uint32_t geteuid(void) nosideeffect;
|
uint32_t geteuid(void) nosideeffect;
|
||||||
uint32_t getgid(void) nosideeffect;
|
uint32_t getgid(void) nosideeffect;
|
||||||
uint32_t getpgrp(void) nosideeffect;
|
|
||||||
uint32_t getsid(int) nosideeffect;
|
|
||||||
uint32_t getuid(void) nosideeffect;
|
uint32_t getuid(void) nosideeffect;
|
||||||
uint32_t umask(uint32_t);
|
uint32_t umask(uint32_t);
|
||||||
void rewinddir(DIR *);
|
void rewinddir(DIR *);
|
||||||
void sync(void);
|
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 clone(int (*)(void *), void *, size_t, int, void *, int *, void *, size_t,
|
||||||
int *);
|
int *);
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
textwindows int sys_chdir_nt(const char *path) {
|
textwindows int sys_chdir_nt(const char *path) {
|
||||||
uint32_t n;
|
uint32_t n;
|
||||||
int e, ms, err, len;
|
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 = __mkntpath(path, path16)) == -1) return -1;
|
||||||
if (!len) return enoent();
|
if (!len) return enoent();
|
||||||
if (len && path16[len - 1] != u'\\') {
|
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);
|
STRACE("%s(%d) → %d% m", "close", fd, rc);
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -43,15 +43,16 @@ static bool IsComDbgPath(const char *s, size_t n) {
|
||||||
READ64LE(s + n - 8) == READ64LE(".COM.DBG"));
|
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 namelen, int *err, const char *suffix,
|
||||||
size_t pathlen) {
|
size_t pathlen) {
|
||||||
size_t suffixlen;
|
size_t suffixlen;
|
||||||
suffixlen = strlen(suffix);
|
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] != '\\')) {
|
if (pathlen && (path[pathlen - 1] != '/' && path[pathlen - 1] != '\\')) {
|
||||||
path[pathlen] =
|
path[pathlen] = !IsWindows() ? '/'
|
||||||
!IsWindows() ? '/' : memchr(path, '\\', pathlen) ? '\\' : '/';
|
: memchr(path, '\\', pathlen) ? '\\'
|
||||||
|
: '/';
|
||||||
pathlen++;
|
pathlen++;
|
||||||
}
|
}
|
||||||
memcpy(path + pathlen, name, namelen);
|
memcpy(path + pathlen, name, namelen);
|
||||||
|
@ -61,7 +62,7 @@ static bool AccessCommand(const char *name, char path[hasatleast PATH_MAX],
|
||||||
return false;
|
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) {
|
size_t namelen, int *err, const char *suffix) {
|
||||||
char sep;
|
char sep;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
@ -70,11 +71,11 @@ static bool SearchPath(const char *name, char path[hasatleast PATH_MAX],
|
||||||
sep = IsWindows() && strchr(p, ';') ? ';' : ':';
|
sep = IsWindows() && strchr(p, ';') ? ';' : ':';
|
||||||
for (;;) {
|
for (;;) {
|
||||||
for (i = 0; p[i] && p[i] != sep; ++i) {
|
for (i = 0; p[i] && p[i] != sep; ++i) {
|
||||||
if (i < PATH_MAX) {
|
if (i < pathsz) {
|
||||||
path[i] = p[i];
|
path[i] = p[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (AccessCommand(name, path, namelen, err, suffix, i)) {
|
if (AccessCommand(name, path, pathsz, namelen, err, suffix, i)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (p[i] == sep) {
|
if (p[i] == sep) {
|
||||||
|
@ -86,36 +87,36 @@ static bool SearchPath(const char *name, char path[hasatleast PATH_MAX],
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool FindCommand(const char *name, char pathbuf[hasatleast PATH_MAX],
|
static bool FindCommand(const char *name, char *pb, size_t pbsz, size_t namelen,
|
||||||
size_t namelen, bool priorityonly, const char *suffix,
|
bool pri, const char *suffix, int *err) {
|
||||||
int *err) {
|
if (pri && (memchr(name, '/', namelen) || memchr(name, '\\', namelen))) {
|
||||||
if (priorityonly &&
|
pb[0] = 0;
|
||||||
(memchr(name, '/', namelen) || memchr(name, '\\', namelen))) {
|
return AccessCommand(name, pb, pbsz, namelen, err, suffix, 0);
|
||||||
pathbuf[0] = 0;
|
|
||||||
return AccessCommand(name, pathbuf, namelen, err, suffix, 0);
|
|
||||||
}
|
}
|
||||||
if (IsWindows() && priorityonly) {
|
if (IsWindows() && pri &&
|
||||||
return AccessCommand(name, pathbuf, namelen, err, suffix,
|
pbsz > max(strlen(kNtSystemDirectory), strlen(kNtWindowsDirectory))) {
|
||||||
stpcpy(pathbuf, kNtSystemDirectory) - pathbuf) ||
|
return AccessCommand(name, pb, pbsz, namelen, err, suffix,
|
||||||
AccessCommand(name, pathbuf, namelen, err, suffix,
|
stpcpy(pb, kNtSystemDirectory) - pb) ||
|
||||||
stpcpy(pathbuf, kNtWindowsDirectory) - pathbuf);
|
AccessCommand(name, pb, pbsz, namelen, err, suffix,
|
||||||
|
stpcpy(pb, kNtWindowsDirectory) - pb);
|
||||||
}
|
}
|
||||||
return (IsWindows() && AccessCommand(name, pathbuf, namelen, err, suffix,
|
return (IsWindows() &&
|
||||||
stpcpy(pathbuf, ".") - pathbuf)) ||
|
(pbsz > 1 && AccessCommand(name, pb, pbsz, namelen, err, suffix,
|
||||||
SearchPath(name, pathbuf, namelen, err, suffix);
|
stpcpy(pb, ".") - pb))) ||
|
||||||
|
SearchPath(name, pb, pbsz, namelen, err, suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool FindVerbatim(const char *name, char pathbuf[hasatleast PATH_MAX],
|
static bool FindVerbatim(const char *name, char *pb, size_t pbsz,
|
||||||
size_t namelen, bool priorityonly, int *err) {
|
size_t namelen, bool pri, int *err) {
|
||||||
return FindCommand(name, pathbuf, namelen, priorityonly, "", err);
|
return FindCommand(name, pb, pbsz, namelen, pri, "", err);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool FindSuffixed(const char *name, char pathbuf[hasatleast PATH_MAX],
|
static bool FindSuffixed(const char *name, char *pb, size_t pbsz,
|
||||||
size_t namelen, bool priorityonly, int *err) {
|
size_t namelen, bool pri, int *err) {
|
||||||
return !IsExePath(name, namelen) && !IsComPath(name, namelen) &&
|
return !IsExePath(name, namelen) && !IsComPath(name, namelen) &&
|
||||||
!IsComDbgPath(name, namelen) &&
|
!IsComDbgPath(name, namelen) &&
|
||||||
(FindCommand(name, pathbuf, namelen, priorityonly, ".com", err) ||
|
(FindCommand(name, pb, pbsz, namelen, pri, ".com", err) ||
|
||||||
FindCommand(name, pathbuf, namelen, priorityonly, ".exe", 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
|
* @asyncsignalsafe
|
||||||
* @vforksafe
|
* @vforksafe
|
||||||
*/
|
*/
|
||||||
char *commandv(const char *name, char pathbuf[hasatleast PATH_MAX]) {
|
char *commandv(const char *name, char *pathbuf, size_t pathbufsz) {
|
||||||
int e, f;
|
int e, f;
|
||||||
char *res;
|
char *res;
|
||||||
size_t namelen;
|
size_t namelen;
|
||||||
|
@ -136,25 +137,27 @@ char *commandv(const char *name, char pathbuf[hasatleast PATH_MAX]) {
|
||||||
efault();
|
efault();
|
||||||
} else if (!(namelen = strlen(name))) {
|
} else if (!(namelen = strlen(name))) {
|
||||||
enoent();
|
enoent();
|
||||||
} else if (namelen + 1 > PATH_MAX) {
|
} else if (namelen + 1 > pathbufsz) {
|
||||||
enametoolong();
|
enametoolong();
|
||||||
} else {
|
} else {
|
||||||
e = errno;
|
e = errno;
|
||||||
f = ENOENT;
|
f = ENOENT;
|
||||||
if ((IsWindows() && (FindSuffixed(name, pathbuf, namelen, true, &f) ||
|
if ((IsWindows() &&
|
||||||
FindVerbatim(name, pathbuf, namelen, true, &f) ||
|
(FindSuffixed(name, pathbuf, pathbufsz, namelen, true, &f) ||
|
||||||
FindSuffixed(name, pathbuf, namelen, false, &f) ||
|
FindVerbatim(name, pathbuf, pathbufsz, namelen, true, &f) ||
|
||||||
FindVerbatim(name, pathbuf, namelen, false, &f))) ||
|
FindSuffixed(name, pathbuf, pathbufsz, namelen, false, &f) ||
|
||||||
(!IsWindows() && (FindVerbatim(name, pathbuf, namelen, true, &f) ||
|
FindVerbatim(name, pathbuf, pathbufsz, namelen, false, &f))) ||
|
||||||
FindSuffixed(name, pathbuf, namelen, true, &f) ||
|
(!IsWindows() &&
|
||||||
FindVerbatim(name, pathbuf, namelen, false, &f) ||
|
(FindVerbatim(name, pathbuf, pathbufsz, namelen, true, &f) ||
|
||||||
FindSuffixed(name, pathbuf, namelen, false, &f)))) {
|
FindSuffixed(name, pathbuf, pathbufsz, namelen, true, &f) ||
|
||||||
|
FindVerbatim(name, pathbuf, pathbufsz, namelen, false, &f) ||
|
||||||
|
FindSuffixed(name, pathbuf, pathbufsz, namelen, false, &f)))) {
|
||||||
errno = e;
|
errno = e;
|
||||||
res = pathbuf;
|
res = pathbuf;
|
||||||
} else {
|
} else {
|
||||||
errno = f;
|
errno = f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
STRACE("commandv(%#s, %p) → %#s% m", name, pathbuf, res);
|
STRACE("commandv(%#s, %p, %'zu) → %#s% m", name, pathbuf, pathbufsz, res);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ static textwindows int sys_copyfile_nt(const char *src, const char *dst,
|
||||||
int flags) {
|
int flags) {
|
||||||
int64_t fhsrc, fhdst;
|
int64_t fhsrc, fhdst;
|
||||||
struct NtFileTime accessed, modified;
|
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(src, src16) == -1) return -1;
|
||||||
if (__mkntpath(dst, dst16) == -1) return -1;
|
if (__mkntpath(dst, dst16) == -1) return -1;
|
||||||
if (CopyFile(src16, dst16, !!(flags & COPYFILE_NOCLOBBER))) {
|
if (CopyFile(src16, dst16, !!(flags & COPYFILE_NOCLOBBER))) {
|
||||||
|
|
|
@ -39,8 +39,8 @@ int execlp(const char *prog, const char *arg, ... /*, NULL*/) {
|
||||||
char *exe;
|
char *exe;
|
||||||
char **argv;
|
char **argv;
|
||||||
va_list va, vb;
|
va_list va, vb;
|
||||||
char pathbuf[PATH_MAX];
|
char pathbuf[PATH_MAX + 1];
|
||||||
if (!(exe = commandv(prog, pathbuf))) return -1;
|
if (!(exe = commandv(prog, pathbuf, sizeof(pathbuf)))) return -1;
|
||||||
va_copy(vb, va);
|
va_copy(vb, va);
|
||||||
va_start(va, arg);
|
va_start(va, arg);
|
||||||
for (i = 0; va_arg(va, const char *); ++i) donothing;
|
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 *));
|
shargs = alloca((i + 2) * sizeof(char *));
|
||||||
memcpy(shargs + 2, argv + 1, i * sizeof(char *));
|
memcpy(shargs + 2, argv + 1, i * sizeof(char *));
|
||||||
if (IsFreebsd() || IsNetbsd()) {
|
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 {
|
} else {
|
||||||
shargs[0] = _PATH_BSHELL;
|
shargs[0] = _PATH_BSHELL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ int execve(const char *prog, char *const argv[], char *const envp[]) {
|
||||||
if (i) kprintf(", ");
|
if (i) kprintf(", ");
|
||||||
kprintf("%#s", envp[i]);
|
kprintf("%#s", envp[i]);
|
||||||
}
|
}
|
||||||
kprintf("})%n");
|
kprintf("})\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
for (i = 3; i < g_fds.n; ++i) {
|
for (i = 3; i < g_fds.n; ++i) {
|
||||||
|
|
|
@ -36,8 +36,8 @@
|
||||||
*/
|
*/
|
||||||
int execvpe(const char *prog, char *const argv[], char *const *envp) {
|
int execvpe(const char *prog, char *const argv[], char *const *envp) {
|
||||||
char *exe;
|
char *exe;
|
||||||
char pathbuf[PATH_MAX];
|
char pathbuf[PATH_MAX + 1];
|
||||||
if (IsAsan() && !__asan_is_valid(prog, 1)) return efault();
|
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);
|
return execve(exe, argv, envp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
int sys_faccessat_nt(int dirfd, const char *path, int mode, uint32_t flags) {
|
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;
|
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
|
||||||
return __fix_enotdir(ntaccesscheck(path16, mode), path16);
|
return __fix_enotdir(ntaccesscheck(path16, mode), path16);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
textwindows int sys_fchdir_nt(int dirfd) {
|
textwindows int sys_fchdir_nt(int dirfd) {
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
char16_t dir[PATH_MAX];
|
char16_t dir[PATH_MAX + 1];
|
||||||
if (!__isfdkind(dirfd, kFdFile)) return ebadf();
|
if (!__isfdkind(dirfd, kFdFile)) return ebadf();
|
||||||
len = GetFinalPathNameByHandle(g_fds.p[dirfd].handle, dir, ARRAYLEN(dir),
|
len = GetFinalPathNameByHandle(g_fds.p[dirfd].handle, dir, ARRAYLEN(dir),
|
||||||
kNtFileNameNormalized | kNtVolumeNameDos);
|
kNtFileNameNormalized | kNtVolumeNameDos);
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
textwindows int sys_fchmodat_nt(int dirfd, const char *path, uint32_t mode,
|
textwindows int sys_fchmodat_nt(int dirfd, const char *path, uint32_t mode,
|
||||||
int flags) {
|
int flags) {
|
||||||
uint32_t attr;
|
uint32_t attr;
|
||||||
uint16_t path16[PATH_MAX];
|
uint16_t path16[PATH_MAX + 1];
|
||||||
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
|
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
|
||||||
if ((attr = GetFileAttributes(path16)) != -1u) {
|
if ((attr = GetFileAttributes(path16)) != -1u) {
|
||||||
if (mode & 0200) {
|
if (mode & 0200) {
|
||||||
|
|
|
@ -48,7 +48,7 @@ bool fileexists(const char *path) {
|
||||||
bool res;
|
bool res;
|
||||||
union metastat st;
|
union metastat st;
|
||||||
struct ZiposUri zipname;
|
struct ZiposUri zipname;
|
||||||
uint16_t path16[PATH_MAX];
|
uint16_t path16[PATH_MAX + 1];
|
||||||
e = errno;
|
e = errno;
|
||||||
if (IsAsan() && !__asan_is_valid(path, 1)) {
|
if (IsAsan() && !__asan_is_valid(path, 1)) {
|
||||||
efault();
|
efault();
|
||||||
|
|
|
@ -29,7 +29,7 @@ textwindows int sys_fstatat_nt(int dirfd, const char *path, struct stat *st,
|
||||||
int flags) {
|
int flags) {
|
||||||
int rc;
|
int rc;
|
||||||
int64_t fh;
|
int64_t fh;
|
||||||
uint16_t path16[PATH_MAX];
|
uint16_t path16[PATH_MAX + 1];
|
||||||
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
|
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
|
||||||
if ((fh = CreateFile(
|
if ((fh = CreateFile(
|
||||||
path16, kNtFileReadAttributes, 0, 0, kNtOpenExisting,
|
path16, kNtFileReadAttributes, 0, 0, kNtOpenExisting,
|
||||||
|
|
|
@ -28,15 +28,22 @@ textwindows char *sys_getcwd_nt(char *buf, size_t size) {
|
||||||
uint64_t w;
|
uint64_t w;
|
||||||
wint_t x, y;
|
wint_t x, y;
|
||||||
uint32_t n, i, j;
|
uint32_t n, i, j;
|
||||||
char16_t name16[PATH_MAX + 1];
|
char16_t p[PATH_MAX + 1];
|
||||||
if ((n = GetCurrentDirectory(ARRAYLEN(name16), name16))) {
|
if ((n = GetCurrentDirectory(ARRAYLEN(p), p))) {
|
||||||
if (n <= PATH_MAX) {
|
if (4 + n + 1 <= size && 4 + n + 1 <= ARRAYLEN(p)) {
|
||||||
tprecode16to8(buf, size, name16);
|
tprecode16to8(buf, size, p);
|
||||||
for (j = i = 0; i < n;) {
|
j = 0;
|
||||||
x = name16[i++] & 0xffff;
|
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 (!IsUcs2(x)) {
|
||||||
if (i < n) {
|
if (i < n) {
|
||||||
y = name16[i++] & 0xffff;
|
y = p[i++] & 0xffff;
|
||||||
x = MergeUtf16(x, y);
|
x = MergeUtf16(x, y);
|
||||||
} else {
|
} else {
|
||||||
x = 0xfffd;
|
x = 0xfffd;
|
||||||
|
|
|
@ -19,13 +19,19 @@
|
||||||
#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/dce.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns effective group ID of calling process.
|
* Returns effective group ID of calling process.
|
||||||
|
* @return group id
|
||||||
*/
|
*/
|
||||||
uint32_t getegid(void) {
|
uint32_t getegid(void) {
|
||||||
int rc;
|
int rc;
|
||||||
|
if (!IsWindows()) {
|
||||||
rc = sys_getegid();
|
rc = sys_getegid();
|
||||||
|
} else {
|
||||||
|
rc = getgid();
|
||||||
|
}
|
||||||
STRACE("%s() → %d% m", "getegid", rc);
|
STRACE("%s() → %d% m", "getegid", rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,10 +22,15 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns effective user ID of calling process.
|
* Returns effective user ID of calling process.
|
||||||
|
* @return user id
|
||||||
*/
|
*/
|
||||||
uint32_t geteuid(void) {
|
uint32_t geteuid(void) {
|
||||||
int rc;
|
int rc;
|
||||||
|
if (!IsWindows()) {
|
||||||
rc = sys_geteuid();
|
rc = sys_geteuid();
|
||||||
|
} else {
|
||||||
|
rc = getuid();
|
||||||
|
}
|
||||||
STRACE("%s() → %d% m", "geteuid", rc);
|
STRACE("%s() → %d% m", "geteuid", rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
/**
|
/**
|
||||||
* Returns process group id of calling process.
|
* Returns process group id of calling process.
|
||||||
*/
|
*/
|
||||||
uint32_t getpgrp(void) {
|
int getpgrp(void) {
|
||||||
int rc;
|
int rc;
|
||||||
if (!IsWindows()) {
|
if (!IsWindows()) {
|
||||||
rc = sys_getpgrp();
|
rc = sys_getpgrp();
|
||||||
|
|
|
@ -18,11 +18,14 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
|
#include "libc/calls/sig.internal.h"
|
||||||
#include "libc/calls/struct/rusage.h"
|
#include "libc/calls/struct/rusage.h"
|
||||||
#include "libc/fmt/conv.h"
|
#include "libc/fmt/conv.h"
|
||||||
|
#include "libc/intrin/spinlock.h"
|
||||||
#include "libc/nt/accounting.h"
|
#include "libc/nt/accounting.h"
|
||||||
#include "libc/nt/process.h"
|
#include "libc/nt/process.h"
|
||||||
#include "libc/nt/runtime.h"
|
#include "libc/nt/runtime.h"
|
||||||
|
#include "libc/nt/struct/iocounters.h"
|
||||||
#include "libc/nt/struct/processmemorycounters.h"
|
#include "libc/nt/struct/processmemorycounters.h"
|
||||||
#include "libc/nt/thread.h"
|
#include "libc/nt/thread.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
|
@ -30,22 +33,32 @@
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
textwindows int sys_getrusage_nt(int who, struct rusage *usage) {
|
textwindows int sys_getrusage_nt(int who, struct rusage *usage) {
|
||||||
|
int64_t me, nsignals;
|
||||||
|
struct NtIoCounters iocount;
|
||||||
struct NtProcessMemoryCountersEx memcount;
|
struct NtProcessMemoryCountersEx memcount;
|
||||||
struct NtFileTime ftExit, ftUser, ftKernel, ftCreation;
|
struct NtFileTime ftExit, ftUser, ftKernel, ftCreation;
|
||||||
if (!usage) return efault();
|
if (!usage) return efault();
|
||||||
if (who == 99) return enosys(); // @see libc/sysv/consts.sh
|
if (who == 99) return enosys(); // @see libc/sysv/consts.sh
|
||||||
if (!usage) return 0;
|
if (!usage) return 0;
|
||||||
|
me = GetCurrentProcess();
|
||||||
if (!(who == RUSAGE_SELF ? GetProcessTimes : GetThreadTimes)(
|
if (!(who == RUSAGE_SELF ? GetProcessTimes : GetThreadTimes)(
|
||||||
(who == RUSAGE_SELF ? GetCurrentProcess : GetCurrentThread)(),
|
(who == RUSAGE_SELF ? GetCurrentProcess : GetCurrentThread)(),
|
||||||
&ftCreation, &ftExit, &ftKernel, &ftUser) ||
|
&ftCreation, &ftExit, &ftKernel, &ftUser) ||
|
||||||
!GetProcessMemoryInfo(GetCurrentProcess(), &memcount, sizeof(memcount))) {
|
!GetProcessMemoryInfo(me, &memcount, sizeof(memcount)) ||
|
||||||
|
!GetProcessIoCounters(me, &iocount)) {
|
||||||
return __winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
|
_spinlock(&__sig_lock);
|
||||||
|
nsignals = __sig_count;
|
||||||
|
_spunlock(&__sig_lock);
|
||||||
*usage = (struct rusage){
|
*usage = (struct rusage){
|
||||||
.ru_utime = WindowsDurationToTimeVal(ReadFileTime(ftUser)),
|
.ru_utime = WindowsDurationToTimeVal(ReadFileTime(ftUser)),
|
||||||
.ru_stime = WindowsDurationToTimeVal(ReadFileTime(ftKernel)),
|
.ru_stime = WindowsDurationToTimeVal(ReadFileTime(ftKernel)),
|
||||||
.ru_maxrss = memcount.PeakWorkingSetSize / 1024,
|
.ru_maxrss = memcount.PeakWorkingSetSize / 1024,
|
||||||
.ru_majflt = memcount.PageFaultCount,
|
.ru_majflt = memcount.PageFaultCount,
|
||||||
|
.ru_inblock = iocount.ReadOperationCount,
|
||||||
|
.ru_oublock = iocount.WriteOperationCount,
|
||||||
|
.ru_nsignals = __sig_count,
|
||||||
};
|
};
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
/**
|
/**
|
||||||
* Creates session and sets the process group id.
|
* Creates session and sets the process group id.
|
||||||
*/
|
*/
|
||||||
uint32_t getsid(int pid) {
|
int getsid(int pid) {
|
||||||
int rc;
|
int rc;
|
||||||
rc = sys_getsid(pid);
|
rc = sys_getsid(pid);
|
||||||
STRACE("%s(%d) → %d% m", "getsid", pid, rc);
|
STRACE("%s(%d) → %d% m", "getsid", pid, rc);
|
||||||
|
|
|
@ -88,7 +88,7 @@ int __reservefd(int) hidden;
|
||||||
void __releasefd(int) hidden;
|
void __releasefd(int) hidden;
|
||||||
int __ensurefds(int) hidden;
|
int __ensurefds(int) hidden;
|
||||||
int64_t __getfdhandleactual(int) hidden;
|
int64_t __getfdhandleactual(int) hidden;
|
||||||
void __printfds(void);
|
void __printfds(void) hidden;
|
||||||
|
|
||||||
forceinline bool __isfdopen(int fd) {
|
forceinline bool __isfdopen(int fd) {
|
||||||
return 0 <= fd && fd < g_fds.n && g_fds.p[fd].kind != kFdEmpty;
|
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_getpriority(i32, u32) hidden;
|
||||||
i32 sys_getrlimit(i32, struct rlimit *) hidden;
|
i32 sys_getrlimit(i32, struct rlimit *) hidden;
|
||||||
i32 sys_getrusage(i32, struct rusage *) hidden;
|
i32 sys_getrusage(i32, struct rusage *) hidden;
|
||||||
|
i32 sys_getsid(int) hidden;
|
||||||
i32 sys_ioctl(i32, u64, ...) hidden;
|
i32 sys_ioctl(i32, u64, ...) hidden;
|
||||||
i32 sys_kill(i32, i32, i32) hidden;
|
i32 sys_kill(i32, i32, i32) hidden;
|
||||||
i32 sys_linkat(i32, const char *, i32, const char *, 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_setitimer(i32, const struct itimerval *, struct itimerval *) hidden;
|
||||||
i32 sys_setpgid(i32, i32) hidden;
|
i32 sys_setpgid(i32, i32) hidden;
|
||||||
i32 sys_setpriority(i32, u32, 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_setresgid(uint32_t, uint32_t, uint32_t) hidden;
|
||||||
i32 sys_setresuid(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_setrlimit(i32, const struct rlimit *) hidden;
|
||||||
i32 sys_setsid(void) hidden;
|
i32 sys_setsid(void) hidden;
|
||||||
i32 sys_setuid(i32) 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_getegid(void) hidden;
|
||||||
u32 sys_geteuid(void) hidden;
|
u32 sys_geteuid(void) hidden;
|
||||||
u32 sys_getgid(void) hidden;
|
u32 sys_getgid(void) hidden;
|
||||||
u32 sys_getsid(int) hidden;
|
|
||||||
u32 sys_gettid(void) hidden;
|
u32 sys_gettid(void) hidden;
|
||||||
u32 sys_getuid(void) hidden;
|
u32 sys_getuid(void) hidden;
|
||||||
u32 sys_umask(u32) hidden;
|
u32 sys_umask(u32) hidden;
|
||||||
|
@ -337,9 +339,10 @@ bool isregularfile_nt(const char *) hidden;
|
||||||
bool issymlink_nt(const char *) hidden;
|
bool issymlink_nt(const char *) hidden;
|
||||||
bool32 ntsetprivilege(i64, const char16_t *, u32) hidden;
|
bool32 ntsetprivilege(i64, const char16_t *, u32) hidden;
|
||||||
char16_t *CreatePipeName(char16_t *) hidden;
|
char16_t *CreatePipeName(char16_t *) hidden;
|
||||||
int __mkntpath(const char *, char16_t[hasatleast PATH_MAX - 16]) hidden;
|
int __mkntpath(const char *, char16_t[hasatleast PATH_MAX + 1]) hidden;
|
||||||
int __mkntpath2(const char *, char16_t[hasatleast PATH_MAX - 16], int) hidden;
|
int __mkntpath2(const char *, char16_t[hasatleast PATH_MAX + 1], int) hidden;
|
||||||
int __mkntpathat(int, const char *, int, char16_t[PATH_MAX]) hidden;
|
int __mkntpathat(int, const char *, int,
|
||||||
|
char16_t[hasatleast PATH_MAX + 1]) hidden;
|
||||||
int sys_clock_gettime_nt(int, struct timespec *) hidden;
|
int sys_clock_gettime_nt(int, struct timespec *) hidden;
|
||||||
int ntaccesscheck(const char16_t *, u32) paramsnonnull() hidden;
|
int ntaccesscheck(const char16_t *, u32) paramsnonnull() hidden;
|
||||||
int sys_getsetpriority_nt(int, int, int, int (*)(int));
|
int sys_getsetpriority_nt(int, int, int, int (*)(int));
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
#include "libc/calls/struct/termios.h"
|
#include "libc/calls/struct/termios.h"
|
||||||
|
#include "libc/calls/ttydefaults.h"
|
||||||
#include "libc/nt/console.h"
|
#include "libc/nt/console.h"
|
||||||
#include "libc/nt/enum/consolemodeflags.h"
|
#include "libc/nt/enum/consolemodeflags.h"
|
||||||
#include "libc/nt/struct/consolescreenbufferinfoex.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);
|
outok = GetConsoleMode((out = __getfdhandleactual(1)), &outmode);
|
||||||
if (inok | outok) {
|
if (inok | outok) {
|
||||||
bzero(tio, sizeof(*tio));
|
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 (inok) {
|
||||||
if (inmode & kNtEnableLineInput) {
|
if (inmode & kNtEnableLineInput) {
|
||||||
tio->c_lflag |= ICANON;
|
tio->c_lflag |= ICANON;
|
||||||
|
@ -44,16 +62,21 @@ textwindows int ioctl_tcgets_nt(int ignored, struct termios *tio) {
|
||||||
}
|
}
|
||||||
if (inmode & kNtEnableProcessedInput) {
|
if (inmode & kNtEnableProcessedInput) {
|
||||||
tio->c_lflag |= IEXTEN | ISIG;
|
tio->c_lflag |= IEXTEN | ISIG;
|
||||||
|
if (tio->c_lflag | ECHO) {
|
||||||
|
tio->c_lflag |= ECHOE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (outok) {
|
if (outok) {
|
||||||
if (outmode & kNtEnableProcessedOutput) {
|
if (outmode & kNtEnableProcessedOutput) {
|
||||||
tio->c_oflag |= OPOST;
|
tio->c_oflag |= OPOST;
|
||||||
}
|
}
|
||||||
if (!(outmode & kNtDisableNewlineAutoReturn)) {
|
if (!(outmode & kNtDisableNewlineAutoReturn)) {
|
||||||
tio->c_oflag |= ONLCR;
|
tio->c_oflag |= OPOST | ONLCR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return enotty();
|
return enotty();
|
||||||
|
|
|
@ -17,8 +17,10 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
|
#include "libc/calls/strace.internal.h"
|
||||||
#include "libc/calls/struct/metatermios.internal.h"
|
#include "libc/calls/struct/metatermios.internal.h"
|
||||||
#include "libc/calls/termios.internal.h"
|
#include "libc/calls/termios.internal.h"
|
||||||
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/nt/console.h"
|
#include "libc/nt/console.h"
|
||||||
#include "libc/nt/enum/consolemodeflags.h"
|
#include "libc/nt/enum/consolemodeflags.h"
|
||||||
#include "libc/nt/enum/version.h"
|
#include "libc/nt/enum/version.h"
|
||||||
|
@ -29,35 +31,54 @@
|
||||||
textwindows int ioctl_tcsets_nt(int ignored, uint64_t request,
|
textwindows int ioctl_tcsets_nt(int ignored, uint64_t request,
|
||||||
const struct termios *tio) {
|
const struct termios *tio) {
|
||||||
int64_t in, out;
|
int64_t in, out;
|
||||||
bool32 inok, outok;
|
bool32 ok, inok, outok;
|
||||||
uint32_t inmode, outmode;
|
uint32_t inmode, outmode;
|
||||||
inok = GetConsoleMode((in = __getfdhandleactual(0)), &inmode);
|
inok = GetConsoleMode((in = __getfdhandleactual(0)), &inmode);
|
||||||
outok = GetConsoleMode((out = __getfdhandleactual(1)), &outmode);
|
outok = GetConsoleMode((out = __getfdhandleactual(1)), &outmode);
|
||||||
if (inok | outok) {
|
if (inok | outok) {
|
||||||
|
|
||||||
if (inok) {
|
if (inok) {
|
||||||
if (request == TCSETSF) {
|
if (request == TCSETSF) {
|
||||||
FlushConsoleInputBuffer(in);
|
FlushConsoleInputBuffer(in);
|
||||||
}
|
}
|
||||||
inmode &=
|
inmode &=
|
||||||
~(kNtEnableLineInput | kNtEnableEchoInput | kNtEnableProcessedInput);
|
~(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;
|
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) {
|
if (NtGetVersion() >= kNtVersionWindows10) {
|
||||||
inmode |= kNtEnableVirtualTerminalInput;
|
inmode |= kNtEnableVirtualTerminalInput;
|
||||||
}
|
}
|
||||||
SetConsoleMode(in, inmode);
|
ok = SetConsoleMode(in, inmode);
|
||||||
|
NTTRACE("SetConsoleMode(%p, %s) → %hhhd", in,
|
||||||
|
DescribeNtConsoleModeInputFlags(inmode), ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (outok) {
|
if (outok) {
|
||||||
outmode |= kNtEnableWrapAtEolOutput;
|
outmode &= ~(kNtDisableNewlineAutoReturn);
|
||||||
if (tio->c_oflag & OPOST) outmode |= kNtEnableProcessedOutput;
|
outmode |= kNtEnableProcessedOutput;
|
||||||
if (!(tio->c_oflag & ONLCR)) outmode |= kNtDisableNewlineAutoReturn;
|
if (!(tio->c_oflag & ONLCR)) {
|
||||||
|
outmode |= kNtDisableNewlineAutoReturn;
|
||||||
|
}
|
||||||
if (NtGetVersion() >= kNtVersionWindows10) {
|
if (NtGetVersion() >= kNtVersionWindows10) {
|
||||||
outmode |= kNtEnableVirtualTerminalProcessing;
|
outmode |= kNtEnableVirtualTerminalProcessing;
|
||||||
}
|
}
|
||||||
SetConsoleMode(out, outmode);
|
ok = SetConsoleMode(out, outmode);
|
||||||
|
NTTRACE("SetConsoleMode(%p, %s) → %hhhd", out,
|
||||||
|
DescribeNtConsoleModeOutputFlags(outmode), ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return enotty();
|
return enotty();
|
||||||
|
|
|
@ -83,11 +83,6 @@ int ioctl_tcsets(int fd, uint64_t request, ...) {
|
||||||
} else {
|
} else {
|
||||||
rc = einval();
|
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);
|
STRACE("ioctl_tcsets(%d, %p, %p) → %d% m", fd, request, tio, rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
bool isdirectory_nt(const char *path) {
|
bool isdirectory_nt(const char *path) {
|
||||||
int e;
|
int e;
|
||||||
uint32_t x;
|
uint32_t x;
|
||||||
char16_t path16[PATH_MAX];
|
char16_t path16[PATH_MAX + 1];
|
||||||
e = errno;
|
e = errno;
|
||||||
if (__mkntpath(path, path16) == -1) return -1;
|
if (__mkntpath(path, path16) == -1) return -1;
|
||||||
if ((x = GetFileAttributes(path16)) != -1u) {
|
if ((x = GetFileAttributes(path16)) != -1u) {
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
bool isregularfile_nt(const char *path) {
|
bool isregularfile_nt(const char *path) {
|
||||||
int e;
|
int e;
|
||||||
uint32_t x;
|
uint32_t x;
|
||||||
char16_t path16[PATH_MAX];
|
char16_t path16[PATH_MAX + 1];
|
||||||
e = errno;
|
e = errno;
|
||||||
if (__mkntpath(path, path16) == -1) return -1;
|
if (__mkntpath(path, path16) == -1) return -1;
|
||||||
if ((x = GetFileAttributes(path16)) != -1u) {
|
if ((x = GetFileAttributes(path16)) != -1u) {
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
bool issymlink_nt(const char *path) {
|
bool issymlink_nt(const char *path) {
|
||||||
int e;
|
int e;
|
||||||
uint32_t x;
|
uint32_t x;
|
||||||
char16_t path16[PATH_MAX];
|
char16_t path16[PATH_MAX + 1];
|
||||||
e = errno;
|
e = errno;
|
||||||
if (__mkntpath(path, path16) == -1) return -1;
|
if (__mkntpath(path, path16) == -1) return -1;
|
||||||
if ((x = GetFileAttributes(path16)) != -1u) {
|
if ((x = GetFileAttributes(path16)) != -1u) {
|
||||||
|
|
|
@ -23,8 +23,8 @@
|
||||||
|
|
||||||
textwindows int sys_linkat_nt(int olddirfd, const char *oldpath, int newdirfd,
|
textwindows int sys_linkat_nt(int olddirfd, const char *oldpath, int newdirfd,
|
||||||
const char *newpath) {
|
const char *newpath) {
|
||||||
char16_t newpath16[PATH_MAX];
|
char16_t newpath16[PATH_MAX + 1];
|
||||||
char16_t oldpath16[PATH_MAX];
|
char16_t oldpath16[PATH_MAX + 1];
|
||||||
if (__mkntpathat(olddirfd, oldpath, 0, oldpath16) != -1 &&
|
if (__mkntpathat(olddirfd, oldpath, 0, oldpath16) != -1 &&
|
||||||
__mkntpathat(newdirfd, newpath, 0, newpath16) != -1) {
|
__mkntpathat(newdirfd, newpath, 0, newpath16) != -1) {
|
||||||
if (CreateHardLink(newpath16, oldpath16, NULL)) {
|
if (CreateHardLink(newpath16, oldpath16, NULL)) {
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
* @param path is a UTF-8 string, preferably relative w/ forward slashes
|
* @param path is a UTF-8 string, preferably relative w/ forward slashes
|
||||||
* @param mode can be, for example, 0755
|
* @param mode can be, for example, 0755
|
||||||
* @return 0 on success or -1 w/ errno
|
* @return 0 on success or -1 w/ errno
|
||||||
* @error EEXIST, ENOTDIR, ENAMETOOLONG, EACCES
|
* @error ENAMETOOLONG if >246 characters on NT
|
||||||
* @asyncsignalsafe
|
* @asyncsignalsafe
|
||||||
* @see makedirs()
|
* @see makedirs()
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -18,10 +18,13 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
#include "libc/nt/files.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) {
|
textwindows int sys_mkdirat_nt(int dirfd, const char *path, uint32_t mode) {
|
||||||
int e;
|
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 (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
|
||||||
if (CreateDirectory(path16, 0)) return 0;
|
if (CreateDirectory(path16, 0)) return 0;
|
||||||
return __fix_enotdir(-1, path16);
|
return __fix_enotdir(-1, path16);
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#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/calls/strace.internal.h"
|
||||||
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/nt/systeminfo.h"
|
#include "libc/nt/systeminfo.h"
|
||||||
#include "libc/str/oldutf16.internal.h"
|
#include "libc/str/oldutf16.internal.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
|
@ -49,7 +50,7 @@ textwindows static const char *FixNtMagicPath(const char *path,
|
||||||
}
|
}
|
||||||
|
|
||||||
textwindows int __mkntpath(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);
|
return __mkntpath2(path, path16, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,14 +68,14 @@ textwindows int __mkntpath(const char *path,
|
||||||
* @error ENAMETOOLONG
|
* @error ENAMETOOLONG
|
||||||
*/
|
*/
|
||||||
textwindows int __mkntpath2(const char *path,
|
textwindows int __mkntpath2(const char *path,
|
||||||
char16_t path16[hasatleast PATH_MAX - 16],
|
char16_t path16[hasatleast PATH_MAX + 1],
|
||||||
int flags) {
|
int flags) {
|
||||||
/*
|
/*
|
||||||
* 1. Reserve +1 for NUL-terminator
|
* 1. Need +1 for NUL-terminator
|
||||||
* 2. Reserve +1 for UTF-16 overflow
|
* 2. Need +1 for UTF-16 overflow
|
||||||
* 3. Reserve ≥2 for SetCurrentDirectory trailing slash requirement
|
* 3. Need ≥2 for SetCurrentDirectory trailing slash requirement
|
||||||
* 4. Reserve ≥10 for CreateNamedPipe "\\.\pipe\" prefix requirement
|
* 5. Need ≥13 for mkdir() i.e. 1+8+3+1, e.g. "\\ffffffff.xxx\0"
|
||||||
* 5. Reserve ≥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;
|
char16_t *p;
|
||||||
const char *q;
|
const char *q;
|
||||||
|
@ -83,7 +84,12 @@ textwindows int __mkntpath2(const char *path,
|
||||||
path = FixNtMagicPath(path, flags);
|
path = FixNtMagicPath(path, flags);
|
||||||
p = path16;
|
p = path16;
|
||||||
q = path;
|
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' &&
|
if (IsSlash(q[0]) && q[1] == 't' && q[2] == 'm' && q[3] == 'p' &&
|
||||||
(IsSlash(q[4]) || !q[4])) {
|
(IsSlash(q[4]) || !q[4])) {
|
||||||
m = GetTempPath(z, p);
|
m = GetTempPath(z, p);
|
||||||
|
|
|
@ -25,9 +25,9 @@
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
int __mkntpathat(int dirfd, const char *path, int flags,
|
int __mkntpathat(int dirfd, const char *path, int flags,
|
||||||
char16_t file[PATH_MAX]) {
|
char16_t file[hasatleast PATH_MAX + 1]) {
|
||||||
char16_t dir[PATH_MAX];
|
|
||||||
uint32_t dirlen, filelen;
|
uint32_t dirlen, filelen;
|
||||||
|
char16_t dir[PATH_MAX + 1];
|
||||||
if ((filelen = __mkntpath2(path, file, flags)) == -1) return -1;
|
if ((filelen = __mkntpath2(path, file, flags)) == -1) return -1;
|
||||||
if (!filelen) return enoent();
|
if (!filelen) return enoent();
|
||||||
if (file[0] != u'\\' && dirfd != AT_FDCWD) { /* ProTip: \\?\C:\foo */
|
if (file[0] != u'\\' && dirfd != AT_FDCWD) { /* ProTip: \\?\C:\foo */
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "libc/calls/sig.internal.h"
|
#include "libc/calls/sig.internal.h"
|
||||||
#include "libc/calls/strace.internal.h"
|
#include "libc/calls/strace.internal.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
|
#include "libc/limits.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/nt/errors.h"
|
#include "libc/nt/errors.h"
|
||||||
#include "libc/nt/nt/time.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;
|
int64_t ms, sec, nsec;
|
||||||
if (__builtin_mul_overflow(req->tv_sec, 1000, &ms) ||
|
if (__builtin_mul_overflow(req->tv_sec, 1000, &ms) ||
|
||||||
__builtin_add_overflow(ms, req->tv_nsec / 1000000, &ms)) {
|
__builtin_add_overflow(ms, req->tv_nsec / 1000000, &ms)) {
|
||||||
ms = -1;
|
ms = INT64_MAX;
|
||||||
}
|
}
|
||||||
if (!ms && (req->tv_sec || req->tv_nsec)) {
|
if (!ms && (req->tv_sec || req->tv_nsec)) {
|
||||||
ms = 1;
|
ms = 1;
|
||||||
|
|
|
@ -70,7 +70,7 @@ textwindows int ntspawn(
|
||||||
int64_t handle;
|
int64_t handle;
|
||||||
size_t blocksize;
|
size_t blocksize;
|
||||||
struct SpawnBlock *block;
|
struct SpawnBlock *block;
|
||||||
char16_t prog16[PATH_MAX];
|
char16_t prog16[PATH_MAX + 1];
|
||||||
rc = -1;
|
rc = -1;
|
||||||
block = NULL;
|
block = NULL;
|
||||||
if (__mkntpath(prog, prog16) == -1) return -1;
|
if (__mkntpath(prog, prog16) == -1) return -1;
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
|
|
||||||
static textwindows int64_t sys_open_nt_impl(int dirfd, const char *path,
|
static textwindows int64_t sys_open_nt_impl(int dirfd, const char *path,
|
||||||
uint32_t flags, int32_t mode) {
|
uint32_t flags, int32_t mode) {
|
||||||
char16_t path16[PATH_MAX];
|
char16_t path16[PATH_MAX + 1];
|
||||||
uint32_t perm, share, disp, attr;
|
uint32_t perm, share, disp, attr;
|
||||||
if (__mkntpathat(dirfd, path, flags, path16) == -1) return -1;
|
if (__mkntpathat(dirfd, path, flags, path16) == -1) return -1;
|
||||||
if (GetNtOpenFlags(flags, mode, &perm, &share, &disp, &attr) == -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[0], sizeof(flagbuf[0]), fds[i].events),
|
||||||
DescribePollFlags(flagbuf[1], sizeof(flagbuf[1]), fds[i].revents));
|
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);
|
timeout_ms, rc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,7 +118,7 @@ ssize_t preadv(int fd, struct iovec *iov, int iovlen, int64_t off) {
|
||||||
} else {
|
} else {
|
||||||
kprintf(STRACE_PROLOGUE "preadv(%d, [", fd);
|
kprintf(STRACE_PROLOGUE "preadv(%d, [", fd);
|
||||||
__strace_iov(iov, iovlen, rc != -1 ? rc : 0);
|
__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
|
#endif
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
#include "libc/intrin/kprintf.h"
|
#include "libc/intrin/kprintf.h"
|
||||||
|
#include "libc/intrin/spinlock.h"
|
||||||
|
|
||||||
static const char *__fdkind2str(int x) {
|
static const char *__fdkind2str(int x) {
|
||||||
switch (x) {
|
switch (x) {
|
||||||
|
@ -44,6 +45,7 @@ static const char *__fdkind2str(int x) {
|
||||||
|
|
||||||
void __printfds(void) {
|
void __printfds(void) {
|
||||||
int i;
|
int i;
|
||||||
|
_spinlock(&__fds_lock);
|
||||||
for (i = 0; i < g_fds.n; ++i) {
|
for (i = 0; i < g_fds.n; ++i) {
|
||||||
if (!g_fds.p[i].kind) continue;
|
if (!g_fds.p[i].kind) continue;
|
||||||
kprintf("%3d %s", i, __fdkind2str(g_fds.p[i].kind));
|
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].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].extra) kprintf(" extra=%ld", g_fds.p[i].extra);
|
||||||
if (g_fds.p[i].worker) kprintf(" worker=%p", g_fds.p[i].worker);
|
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;
|
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 p[PATH_MAX + 1];
|
||||||
path16[0] = 0;
|
p[0] = 0;
|
||||||
rc = GetModuleFileName(0, path16, ARRAYLEN(path16));
|
rc = GetModuleFileName(0, p, ARRAYLEN(p));
|
||||||
NTTRACE("GetModuleFileName(0, [%#hs]) → %hhhd", path16, rc);
|
NTTRACE("GetModuleFileName(0, [%#hs]) → %hhhd", p, rc);
|
||||||
if (!rc) return false;
|
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)) {
|
if (!IsUcs2(x)) {
|
||||||
y = path16[i++] & 0xffff;
|
y = p[i++] & 0xffff;
|
||||||
x = MergeUtf16(x, y);
|
x = MergeUtf16(x, y);
|
||||||
}
|
}
|
||||||
if (x == '\\') x = '/';
|
if (x == '\\') x = '/';
|
||||||
|
|
|
@ -123,7 +123,7 @@ ssize_t pwritev(int fd, const struct iovec *iov, int iovlen, int64_t off) {
|
||||||
} else {
|
} else {
|
||||||
kprintf(STRACE_PROLOGUE "pwritev(%d, ", fd);
|
kprintf(STRACE_PROLOGUE "pwritev(%d, ", fd);
|
||||||
__strace_iov(iov, iovlen, rc != -1 ? rc : 0);
|
__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
|
#endif
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "libc/nt/files.h"
|
#include "libc/nt/files.h"
|
||||||
#include "libc/nt/runtime.h"
|
#include "libc/nt/runtime.h"
|
||||||
#include "libc/nt/struct/reparsedatabuffer.h"
|
#include "libc/nt/struct/reparsedatabuffer.h"
|
||||||
|
#include "libc/str/str.h"
|
||||||
#include "libc/str/tpenc.h"
|
#include "libc/str/tpenc.h"
|
||||||
#include "libc/str/utf16.h"
|
#include "libc/str/utf16.h"
|
||||||
#include "libc/sysv/errfuns.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;
|
wint_t x, y;
|
||||||
volatile char *memory;
|
volatile char *memory;
|
||||||
uint32_t i, j, n, mem;
|
uint32_t i, j, n, mem;
|
||||||
char16_t path16[PATH_MAX], *p;
|
char16_t path16[PATH_MAX + 1], *p;
|
||||||
struct NtReparseDataBuffer *rdb;
|
struct NtReparseDataBuffer *rdb;
|
||||||
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
|
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
|
||||||
mem = 16384;
|
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);
|
n = rdb->SymbolicLinkReparseBuffer.PrintNameLength / sizeof(char16_t);
|
||||||
p = (char16_t *)((char *)rdb->SymbolicLinkReparseBuffer.PathBuffer +
|
p = (char16_t *)((char *)rdb->SymbolicLinkReparseBuffer.PathBuffer +
|
||||||
rdb->SymbolicLinkReparseBuffer.PrintNameOffset);
|
rdb->SymbolicLinkReparseBuffer.PrintNameOffset);
|
||||||
|
if (n >= 3 && isalpha(p[0]) && p[1] == ':' && p[2] == '\\') {
|
||||||
|
buf[j++] = '/';
|
||||||
|
buf[j++] = '/';
|
||||||
|
buf[j++] = '?';
|
||||||
|
buf[j++] = '/';
|
||||||
|
}
|
||||||
while (i < n) {
|
while (i < n) {
|
||||||
x = p[i++] & 0xffff;
|
x = p[i++] & 0xffff;
|
||||||
if (!IsUcs2(x)) {
|
if (!IsUcs2(x)) {
|
||||||
|
|
|
@ -72,7 +72,7 @@ ssize_t readv(int fd, const struct iovec *iov, int iovlen) {
|
||||||
} else {
|
} else {
|
||||||
kprintf(STRACE_PROLOGUE "readv(%d, [", fd);
|
kprintf(STRACE_PROLOGUE "readv(%d, [", fd);
|
||||||
__strace_iov(iov, iovlen, rc != -1 ? rc : 0);
|
__strace_iov(iov, iovlen, rc != -1 ? rc : 0);
|
||||||
kprintf("], %d) → %'ld% m%n", iovlen, rc);
|
kprintf("], %d) → %'ld% m\n", iovlen, rc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -22,8 +22,8 @@
|
||||||
|
|
||||||
textwindows int sys_renameat_nt(int olddirfd, const char *oldpath, int newdirfd,
|
textwindows int sys_renameat_nt(int olddirfd, const char *oldpath, int newdirfd,
|
||||||
const char *newpath) {
|
const char *newpath) {
|
||||||
char16_t oldpath16[PATH_MAX];
|
char16_t oldpath16[PATH_MAX + 1];
|
||||||
char16_t newpath16[PATH_MAX];
|
char16_t newpath16[PATH_MAX + 1];
|
||||||
if (__mkntpathat(olddirfd, oldpath, 0, oldpath16) == -1 ||
|
if (__mkntpathat(olddirfd, oldpath, 0, oldpath16) == -1 ||
|
||||||
__mkntpathat(newdirfd, newpath, 0, newpath16) == -1) {
|
__mkntpathat(newdirfd, newpath, 0, newpath16) == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -22,9 +22,6 @@
|
||||||
/**
|
/**
|
||||||
* Sets effective group ID.
|
* Sets effective group ID.
|
||||||
*/
|
*/
|
||||||
int setegid(unsigned egid) {
|
int setegid(uint32_t egid) {
|
||||||
int rc;
|
return setregid(-1, egid);
|
||||||
rc = setregid(-1, egid);
|
|
||||||
STRACE("%s(%u) → %d% m", "setegid", egid, rc);
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,9 +22,6 @@
|
||||||
/**
|
/**
|
||||||
* Sets effective user ID.
|
* Sets effective user ID.
|
||||||
*/
|
*/
|
||||||
int seteuid(unsigned euid) {
|
int seteuid(uint32_t euid) {
|
||||||
int rc;
|
return setregid(euid, -1);
|
||||||
rc = setreuid(-1, euid);
|
|
||||||
STRACE("%s(%u) → %d% m", "seteuid", euid, rc);
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,12 +21,16 @@
|
||||||
#include "libc/calls/strace.internal.h"
|
#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
|
* @return 0 on success or -1 w/ errno
|
||||||
*/
|
*/
|
||||||
int setgid(int gid) {
|
int setgid(int gid) {
|
||||||
int rc;
|
int rc;
|
||||||
|
if (IsWindows() && gid == getgid()) {
|
||||||
|
rc = 0;
|
||||||
|
} else {
|
||||||
rc = sys_setgid(gid);
|
rc = sys_setgid(gid);
|
||||||
STRACE("%s(%d) → %d% m", "setgid", gid);
|
}
|
||||||
|
STRACE("setgid(%d) → %d% m", gid, rc);
|
||||||
return 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/calls.h"
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
|
#include "libc/calls/strace.internal.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets real, effective, and "saved" group ids.
|
* Sets real, effective, and "saved" group ids.
|
||||||
|
@ -25,9 +26,17 @@
|
||||||
* @param real sets real group id or -1 to do nothing
|
* @param real sets real group id or -1 to do nothing
|
||||||
* @param effective sets effective 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
|
* @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) {
|
int setresgid(uint32_t real, uint32_t effective, uint32_t saved) {
|
||||||
if (saved == -1) return setregid(real, effective);
|
int rc;
|
||||||
return sys_setresgid(real, effective, saved);
|
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/calls.h"
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
|
#include "libc/calls/strace.internal.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets real, effective, and "saved" user ids.
|
* Sets real, effective, and "saved" user ids.
|
||||||
|
@ -25,9 +26,17 @@
|
||||||
* @param real sets real user id or -1 to do nothing
|
* @param real sets real user id or -1 to do nothing
|
||||||
* @param effective sets effective 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
|
* @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) {
|
int setresuid(uint32_t real, uint32_t effective, uint32_t saved) {
|
||||||
if (saved == -1) return setreuid(real, effective);
|
int rc;
|
||||||
return sys_setresuid(real, effective, saved);
|
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"
|
#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
|
* @return 0 on success or -1 w/ errno
|
||||||
*/
|
*/
|
||||||
int setuid(int uid) {
|
int setuid(int uid) {
|
||||||
int rc;
|
int rc;
|
||||||
|
if (IsWindows() && uid == getuid()) {
|
||||||
|
rc = 0;
|
||||||
|
} else {
|
||||||
rc = sys_setuid(uid);
|
rc = sys_setuid(uid);
|
||||||
STRACE("%s(%d) → %d% m", "setuid", uid);
|
}
|
||||||
|
STRACE("setuid(%d) → %d% m", uid, rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ struct Signals {
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct Signals __sig; // TODO(jart): Need TLS
|
extern struct Signals __sig; // TODO(jart): Need TLS
|
||||||
|
extern long __sig_count;
|
||||||
|
|
||||||
bool __sig_check(bool) hidden;
|
bool __sig_check(bool) hidden;
|
||||||
bool __sig_handle(bool, int, int, ucontext_t *) 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) {
|
if (1 <= sig && sig <= NSIG) {
|
||||||
STRACE("enqueuing %G", sig);
|
STRACE("enqueuing %G", sig);
|
||||||
_spinlock(&__sig_lock);
|
_spinlock(&__sig_lock);
|
||||||
|
++__sig_count;
|
||||||
if ((mem = __sig_alloc())) {
|
if ((mem = __sig_alloc())) {
|
||||||
mem->sig = sig;
|
mem->sig = sig;
|
||||||
mem->si_code = si_code;
|
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/sigaction.h"
|
||||||
#include "libc/calls/struct/stat.h"
|
#include "libc/calls/struct/stat.h"
|
||||||
|
|
||||||
#define _KERNTRACE 1 /* not configurable w/ flag yet */
|
#define _KERNTRACE 0 /* not configurable w/ flag yet */
|
||||||
#define _POLLTRACE 1 /* not configurable w/ flag yet */
|
#define _POLLTRACE 0 /* not configurable w/ flag yet */
|
||||||
#define _DATATRACE 1 /* not configurable w/ flag yet */
|
#define _DATATRACE 1 /* not configurable w/ flag yet */
|
||||||
#define _NTTRACE 1 /* not configurable w/ flag yet */
|
#define _NTTRACE 1 /* not configurable w/ flag yet */
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ COSMOPOLITAN_C_START_
|
||||||
#define STRACE(FMT, ...) \
|
#define STRACE(FMT, ...) \
|
||||||
do { \
|
do { \
|
||||||
if (__strace > 0) { \
|
if (__strace > 0) { \
|
||||||
__stracef(STRACE_PROLOGUE FMT "%n", ##__VA_ARGS__); \
|
__stracef(STRACE_PROLOGUE FMT "\n", ##__VA_ARGS__); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -53,8 +53,8 @@ textwindows int sys_symlinkat_nt(const char *target, int newdirfd,
|
||||||
const char *linkpath) {
|
const char *linkpath) {
|
||||||
int targetlen;
|
int targetlen;
|
||||||
uint32_t attrs, flags;
|
uint32_t attrs, flags;
|
||||||
char16_t target16[PATH_MAX];
|
char16_t target16[PATH_MAX + 1];
|
||||||
char16_t linkpath16[PATH_MAX];
|
char16_t linkpath16[PATH_MAX + 1];
|
||||||
|
|
||||||
// convert the paths
|
// convert the paths
|
||||||
if (__mkntpathat(newdirfd, linkpath, 0, linkpath16) == -1) return -1;
|
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;
|
int rc;
|
||||||
bool32 ok;
|
bool32 ok;
|
||||||
int64_t fh;
|
int64_t fh;
|
||||||
uint16_t path16[PATH_MAX];
|
uint16_t path16[PATH_MAX + 1];
|
||||||
if (__mkntpath(path, path16) == -1) return -1;
|
if (__mkntpath(path, path16) == -1) return -1;
|
||||||
if ((fh = CreateFile(path16, kNtGenericWrite, kNtFileShareRead, NULL,
|
if ((fh = CreateFile(path16, kNtGenericWrite, kNtFileShareRead, NULL,
|
||||||
kNtOpenExisting, kNtFileAttributeNormal, 0)) != -1) {
|
kNtOpenExisting, kNtFileAttributeNormal, 0)) != -1) {
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/log/log.h"
|
#include "libc/log/log.h"
|
||||||
|
|
||||||
static char ttyname_buf[PATH_MAX];
|
static char ttyname_buf[PATH_MAX + 1];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns name of terminal.
|
* 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) {
|
static int ttyname_linux(int fd, char *buf, size_t size) {
|
||||||
struct stat st1, st2;
|
struct stat st1, st2;
|
||||||
if (!isatty(fd)) return errno;
|
if (!isatty(fd)) return errno;
|
||||||
char name[PATH_MAX];
|
char name[PATH_MAX + 1];
|
||||||
FormatInt32(stpcpy(name, "/proc/self/fd/"), fd);
|
FormatInt32(stpcpy(name, "/proc/self/fd/"), fd);
|
||||||
ssize_t got;
|
ssize_t got;
|
||||||
got = readlink(name, buf, size);
|
got = readlink(name, buf, size);
|
||||||
|
|
|
@ -39,7 +39,8 @@
|
||||||
* from failing for no reason at all. For example a unit test that
|
* from failing for no reason at all. For example a unit test that
|
||||||
* repeatedly opens and unlinks the same filename.
|
* 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;
|
int rc;
|
||||||
int64_t fh;
|
int64_t fh;
|
||||||
char16_t *p;
|
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) {
|
textwindows int sys_unlinkat_nt(int dirfd, const char *path, int flags) {
|
||||||
int n, rc;
|
int n, rc;
|
||||||
char16_t path16[PATH_MAX];
|
char16_t path16[PATH_MAX + 1];
|
||||||
if ((n = __mkntpathat(dirfd, path, 0, path16)) == -1) {
|
if ((n = __mkntpathat(dirfd, path, 0, path16)) == -1) {
|
||||||
rc = -1;
|
rc = -1;
|
||||||
} else if (flags & AT_REMOVEDIR) {
|
} 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) {
|
const struct timespec ts[2], int flags) {
|
||||||
int i, rc;
|
int i, rc;
|
||||||
int64_t fh;
|
int64_t fh;
|
||||||
uint16_t path16[PATH_MAX];
|
uint16_t path16[PATH_MAX + 1];
|
||||||
struct NtFileTime ft[2], *ftp[2];
|
struct NtFileTime ft[2], *ftp[2];
|
||||||
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
|
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
|
||||||
if ((fh = CreateFile(path16, kNtFileWriteAttributes, kNtFileShareRead, NULL,
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
i = WaitForMultipleObjects(count, handles, false, -1);
|
i = WaitForMultipleObjects(count, handles, false,
|
||||||
|
__SIG_POLLING_INTERVAL_MS);
|
||||||
|
if (i == kNtWaitTimeout) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (i == kNtWaitFailed) {
|
if (i == kNtWaitFailed) {
|
||||||
STRACE("%s failed %u", "WaitForMultipleObjects", GetLastError());
|
STRACE("%s failed %u", "WaitForMultipleObjects", GetLastError());
|
||||||
|
|
|
@ -79,7 +79,7 @@ ssize_t writev(int fd, const struct iovec *iov, int iovlen) {
|
||||||
} else {
|
} else {
|
||||||
kprintf(STRACE_PROLOGUE "writev(%d, ", fd);
|
kprintf(STRACE_PROLOGUE "writev(%d, ", fd);
|
||||||
__strace_iov(iov, iovlen, rc != -1 ? rc : 0);
|
__strace_iov(iov, iovlen, rc != -1 ? rc : 0);
|
||||||
kprintf(", %d) → %'ld% m%n", iovlen, rc);
|
kprintf(", %d) → %'ld% m\n", iovlen, rc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -57,7 +57,7 @@ static textwindows dontinline char *GetNtHostsTxtPath(char *pathbuf,
|
||||||
const struct HostsTxt *GetHostsTxt(void) {
|
const struct HostsTxt *GetHostsTxt(void) {
|
||||||
FILE *f;
|
FILE *f;
|
||||||
const char *path;
|
const char *path;
|
||||||
char pathbuf[PATH_MAX];
|
char pathbuf[PATH_MAX + 1];
|
||||||
struct HostsTxtInitialStaticMemory *init;
|
struct HostsTxtInitialStaticMemory *init;
|
||||||
init = &g_hoststxt_init;
|
init = &g_hoststxt_init;
|
||||||
if (!g_hoststxt) {
|
if (!g_hoststxt) {
|
||||||
|
|
|
@ -48,10 +48,10 @@ int LookupProtoByName(const char *protoname, char *buf, size_t bufsize,
|
||||||
const char *filepath) {
|
const char *filepath) {
|
||||||
FILE *f;
|
FILE *f;
|
||||||
char *line;
|
char *line;
|
||||||
char pathbuf[PATH_MAX];
|
|
||||||
const char *path;
|
const char *path;
|
||||||
size_t linesize;
|
size_t linesize;
|
||||||
int found, result;
|
int found, result;
|
||||||
|
char pathbuf[PATH_MAX + 1];
|
||||||
char *name, *number, *alias, *comment, *tok;
|
char *name, *number, *alias, *comment, *tok;
|
||||||
if (!(path = filepath)) {
|
if (!(path = filepath)) {
|
||||||
path = "/etc/protocols";
|
path = "/etc/protocols";
|
||||||
|
|
|
@ -52,10 +52,10 @@ int LookupProtoByNumber(const int protonum, char *buf, size_t bufsize,
|
||||||
const char *filepath) {
|
const char *filepath) {
|
||||||
FILE *f;
|
FILE *f;
|
||||||
char *line;
|
char *line;
|
||||||
char pathbuf[PATH_MAX];
|
|
||||||
const char *path;
|
|
||||||
size_t linesize;
|
|
||||||
int found;
|
int found;
|
||||||
|
size_t linesize;
|
||||||
|
const char *path;
|
||||||
|
char pathbuf[PATH_MAX + 1];
|
||||||
char *name, *number, *comment, *tok;
|
char *name, *number, *comment, *tok;
|
||||||
if (!(path = filepath)) {
|
if (!(path = filepath)) {
|
||||||
path = "/etc/protocols";
|
path = "/etc/protocols";
|
||||||
|
|
|
@ -53,10 +53,10 @@ int LookupServicesByName(const char *servname, char *servproto,
|
||||||
const char *filepath) {
|
const char *filepath) {
|
||||||
FILE *f;
|
FILE *f;
|
||||||
char *line;
|
char *line;
|
||||||
char pathbuf[PATH_MAX];
|
|
||||||
const char *path;
|
const char *path;
|
||||||
size_t linesize;
|
size_t linesize;
|
||||||
int found, result;
|
int found, result;
|
||||||
|
char pathbuf[PATH_MAX + 1];
|
||||||
char *name, *port, *proto, *alias, *comment, *tok;
|
char *name, *port, *proto, *alias, *comment, *tok;
|
||||||
if (!(path = filepath)) {
|
if (!(path = filepath)) {
|
||||||
path = "/etc/services";
|
path = "/etc/services";
|
||||||
|
|
|
@ -59,7 +59,7 @@ int LookupServicesByPort(const int servport, char *servproto,
|
||||||
const char *filepath) {
|
const char *filepath) {
|
||||||
FILE *f;
|
FILE *f;
|
||||||
char *line;
|
char *line;
|
||||||
char pathbuf[PATH_MAX];
|
char pathbuf[PATH_MAX + 1];
|
||||||
const char *path;
|
const char *path;
|
||||||
size_t linesize;
|
size_t linesize;
|
||||||
int found;
|
int found;
|
||||||
|
|
|
@ -18,6 +18,11 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/fmt/conv.h"
|
#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;
|
return 0 < x ? x : -x;
|
||||||
}
|
}
|
||||||
|
|
|
@ -368,9 +368,6 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
// nonstandard %n specifier
|
|
||||||
// used to print newlines that work in raw terminal modes
|
|
||||||
if (__nomultics) __FMT_PUT('\r');
|
|
||||||
__FMT_PUT('\n');
|
__FMT_PUT('\n');
|
||||||
break;
|
break;
|
||||||
case 'F':
|
case 'F':
|
||||||
|
|
|
@ -26,10 +26,6 @@ int sscanf(const char *, const char *, ...) scanfesque(2);
|
||||||
int vsscanf(const char *, const char *, va_list);
|
int vsscanf(const char *, const char *, va_list);
|
||||||
int vcscanf(int (*)(void *), int (*)(int, void *), void *, const char *,
|
int vcscanf(int (*)(void *), int (*)(int, void *), void *, const char *,
|
||||||
va_list);
|
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;
|
int __fmt(void *, void *, const char *, va_list) hidden;
|
||||||
char *itoa(int, char *, int) compatfn;
|
char *itoa(int, char *, int) compatfn;
|
||||||
char *fcvt(double, int, int *, int *);
|
char *fcvt(double, int, int *, int *);
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
|
|
||||||
.macro .e e s
|
.macro .e e s
|
||||||
.long \e - kErrorNamesLong
|
.long \e - kErrnoDocs
|
||||||
.long 1f - kErrorNamesLong
|
.long 1f - kErrnoDocs
|
||||||
.rodata.str1.1
|
.rodata.str1.1
|
||||||
1: .asciz "\s"
|
1: .asciz "\s"
|
||||||
.previous
|
.previous
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
.section .rodata
|
.section .rodata
|
||||||
.align 4
|
.align 4
|
||||||
.underrun
|
.underrun
|
||||||
kErrorNamesLong:
|
kErrnoDocs:
|
||||||
.e EINVAL,"Invalid argument"
|
.e EINVAL,"Invalid argument"
|
||||||
.e ENOSYS,"Function not implemented"
|
.e ENOSYS,"Function not implemented"
|
||||||
.e EPERM,"Operation not permitted"
|
.e EPERM,"Operation not permitted"
|
||||||
|
@ -115,6 +115,6 @@ kErrorNamesLong:
|
||||||
.e ENOTRECOVERABLE,"State not recoverable"
|
.e ENOTRECOVERABLE,"State not recoverable"
|
||||||
.e ENONET,"Machine is not on the network"
|
.e ENONET,"Machine is not on the network"
|
||||||
.e ERESTART,"Interrupted system call should be restarted"
|
.e ERESTART,"Interrupted system call should be restarted"
|
||||||
.long 0
|
.long -123
|
||||||
.endobj kErrorNamesLong,globl,hidden
|
.endobj kErrnoDocs,globl,hidden
|
||||||
.overrun
|
.overrun
|
|
@ -19,8 +19,8 @@
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
|
|
||||||
.macro .e e
|
.macro .e e
|
||||||
.long \e - kErrorNames
|
.long \e - kErrnoNames
|
||||||
.long 1f - kErrorNames
|
.long 1f - kErrnoNames
|
||||||
.rodata.str1.1
|
.rodata.str1.1
|
||||||
1: .string "\e"
|
1: .string "\e"
|
||||||
.previous
|
.previous
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
.section .rodata
|
.section .rodata
|
||||||
.align 4
|
.align 4
|
||||||
.underrun
|
.underrun
|
||||||
kErrorNames:
|
kErrnoNames:
|
||||||
.e EINVAL
|
.e EINVAL
|
||||||
.e ENOSYS
|
.e ENOSYS
|
||||||
.e EPERM
|
.e EPERM
|
||||||
|
@ -116,6 +116,6 @@ kErrorNames:
|
||||||
.e ENONET
|
.e ENONET
|
||||||
.e ERESTART
|
.e ERESTART
|
||||||
.e ENODATA
|
.e ENODATA
|
||||||
.long 0
|
.long -123
|
||||||
.endobj kErrorNames,globl,hidden
|
.endobj kErrnoNames,globl,hidden
|
||||||
.overrun
|
.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. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/fmt/conv.h"
|
#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. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/fmt/conv.h"
|
#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. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/fmt/fmt.h"
|
#include "libc/fmt/fmt.h"
|
||||||
#include "libc/fmt/kerrornames.internal.h"
|
#include "libc/fmt/magnumstrs.internal.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts errno value to descriptive sentence.
|
* Converts errno value to descriptive sentence.
|
||||||
* @return non-null rodata string or null if not found
|
* @return non-null rodata string or null if not found
|
||||||
*/
|
*/
|
||||||
privileged const char *strerror_long(int x) {
|
const char *strerdoc(int x) {
|
||||||
/* kprintf() weakly depends on this function */
|
|
||||||
int i;
|
|
||||||
if (x) {
|
if (x) {
|
||||||
for (i = 0; kErrorNamesLong[i].x; ++i) {
|
return GetMagnumStr(kErrnoDocs, x);
|
||||||
if (x ==
|
} else {
|
||||||
*(const long *)((uintptr_t)kErrorNamesLong + kErrorNamesLong[i].x)) {
|
|
||||||
return (const char *)((uintptr_t)kErrorNamesLong +
|
|
||||||
kErrorNamesLong[i].s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
}
|
|
@ -16,22 +16,17 @@
|
||||||
│ 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/fmt/fmt.h"
|
#include "libc/fmt/magnumstrs.internal.h"
|
||||||
#include "libc/fmt/kerrornames.internal.h"
|
#include "libc/str/str.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts errno value to symbolic name.
|
* Converts errno value to symbolic name.
|
||||||
* @return non-null rodata string or null if not found
|
* @return non-null rodata string or null if not found
|
||||||
*/
|
*/
|
||||||
privileged const char *strerror_short(int x) {
|
const char *strerrno(int x) {
|
||||||
/* kprintf() weakly depends on this function */
|
|
||||||
int i;
|
|
||||||
if (x) {
|
if (x) {
|
||||||
for (i = 0; kErrorNames[i].x; ++i) {
|
return GetMagnumStr(kErrnoNames, x);
|
||||||
if (x == *(const int *)((uintptr_t)kErrorNames + kErrorNames[i].x)) {
|
} else {
|
||||||
return (const char *)((uintptr_t)kErrorNames + kErrorNames[i].s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
}
|
|
@ -23,9 +23,9 @@
|
||||||
* Converts errno value to string non-reentrantly.
|
* Converts errno value to string non-reentrantly.
|
||||||
* @see strerror_r()
|
* @see strerror_r()
|
||||||
*/
|
*/
|
||||||
noasan char *strerror(int err) {
|
char *strerror(int err) {
|
||||||
if (IsTiny()) {
|
if (IsTiny()) {
|
||||||
return firstnonnull(strerror_short(err), "EUNKNOWN");
|
return firstnonnull(strerrno(err), "EUNKNOWN");
|
||||||
} else {
|
} else {
|
||||||
_Alignas(1) static char buf[512];
|
_Alignas(1) static char buf[512];
|
||||||
strerror_r(err, buf, sizeof(buf));
|
strerror_r(err, buf, sizeof(buf));
|
||||||
|
|
|
@ -25,6 +25,6 @@
|
||||||
* @param err is error number or zero if unknown
|
* @param err is error number or zero if unknown
|
||||||
* @return 0 on success, or error code
|
* @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);
|
return strerror_wr(err, GetLastError(), buf, size);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,13 +32,13 @@
|
||||||
* @param err is error number or zero if unknown
|
* @param err is error number or zero if unknown
|
||||||
* @return 0 on success, or error code
|
* @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 */
|
/* kprintf() weakly depends on this function */
|
||||||
int c, n;
|
int c, n;
|
||||||
char16_t winmsg[256];
|
char16_t winmsg[256];
|
||||||
const char *sym, *msg;
|
const char *sym, *msg;
|
||||||
sym = firstnonnull(strerror_short(err), "EUNKNOWN");
|
sym = firstnonnull(strerrno(err), "EUNKNOWN");
|
||||||
msg = firstnonnull(strerror_long(err), "No error information");
|
msg = firstnonnull(strerdoc(err), "No error information");
|
||||||
if (IsTiny()) {
|
if (IsTiny()) {
|
||||||
if (!sym) sym = "EUNKNOWN";
|
if (!sym) sym = "EUNKNOWN";
|
||||||
for (; (c = *sym++); --size)
|
for (; (c = *sym++); --size)
|
||||||
|
|
|
@ -71,7 +71,7 @@
|
||||||
#define CACHELINE 0x40 /* nexgen32e */
|
#define CACHELINE 0x40 /* nexgen32e */
|
||||||
#define CHAR_BIT 8 /* b/c von neumann */
|
#define CHAR_BIT 8 /* b/c von neumann */
|
||||||
#define ARG_MAX 0x8000 /* b/c windows */
|
#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 NAME_MAX 63 /* b/c dns */
|
||||||
#define CHILD_MAX 25 /* only if malloc isn't linked */
|
#define CHILD_MAX 25 /* only if malloc isn't linked */
|
||||||
#define OPEN_MAX 16 /* only if malloc isn't linked */
|
#define OPEN_MAX 16 /* only if malloc isn't linked */
|
||||||
|
|
|
@ -102,7 +102,7 @@ STATIC_YOINK("_init_asan");
|
||||||
#define REQUIRE(FUNC) \
|
#define REQUIRE(FUNC) \
|
||||||
do { \
|
do { \
|
||||||
if (!weaken(FUNC)) { \
|
if (!weaken(FUNC)) { \
|
||||||
kprintf("error: asan needs %s%n", #FUNC); \
|
kprintf("error: asan needs %s\n", #FUNC); \
|
||||||
__asan_die()(); \
|
__asan_die()(); \
|
||||||
__asan_unreachable(); \
|
__asan_unreachable(); \
|
||||||
} \
|
} \
|
||||||
|
@ -179,8 +179,7 @@ static uint64_t __asan_roundup2pow(uint64_t x) {
|
||||||
static char *__asan_utf8cpy(char *p, unsigned c) {
|
static char *__asan_utf8cpy(char *p, unsigned c) {
|
||||||
uint64_t z;
|
uint64_t z;
|
||||||
z = tpenc(c);
|
z = tpenc(c);
|
||||||
do
|
do *p++ = z;
|
||||||
*p++ = z;
|
|
||||||
while ((z >>= 8));
|
while ((z >>= 8));
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
@ -322,9 +321,9 @@ static char *__asan_hexcpy(char *p, uint64_t x, uint8_t k) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __asan_exit(void) {
|
static void __asan_exit(void) {
|
||||||
kprintf("your asan runtime needs%n"
|
kprintf("your asan runtime needs\n"
|
||||||
"\tSTATIC_YOINK(\"__die\");%n"
|
"\tSTATIC_YOINK(\"__die\");\n"
|
||||||
"in order to show you backtraces%n");
|
"in order to show you backtraces\n");
|
||||||
__restorewintty();
|
__restorewintty();
|
||||||
_Exit(99);
|
_Exit(99);
|
||||||
}
|
}
|
||||||
|
@ -373,6 +372,7 @@ void __asan_unpoison(long p, long n) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool __asan_is_mapped(int x) {
|
static bool __asan_is_mapped(int x) {
|
||||||
|
// xxx: we can't lock because no reentrant locks yet
|
||||||
int i;
|
int i;
|
||||||
struct MemoryIntervals *m;
|
struct MemoryIntervals *m;
|
||||||
m = weaken(_mmi);
|
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(
|
dontdiscard static __asan_die_f *__asan_report_invalid_pointer(
|
||||||
const void *addr) {
|
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));
|
addr, SHADOW(addr));
|
||||||
return __asan_die();
|
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) {
|
if (a <= (intptr_t)addr && (intptr_t)addr <= b) {
|
||||||
p = __stpcpy(p, " ←address");
|
p = __stpcpy(p, " ←address");
|
||||||
}
|
}
|
||||||
if (__nomultics) *p++ = '\r';
|
|
||||||
*p++ = '\n';
|
*p++ = '\n';
|
||||||
}
|
}
|
||||||
return p;
|
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) {
|
static void __asan_report_memory_origin_image(intptr_t a, int z) {
|
||||||
unsigned l, m, r, n, k;
|
unsigned l, m, r, n, k;
|
||||||
struct SymbolTable *st;
|
struct SymbolTable *st;
|
||||||
kprintf("%nthe memory belongs to image symbols%n");
|
kprintf("\nthe memory belongs to image symbols\n");
|
||||||
if (weaken(GetSymbolTable)) {
|
if (weaken(GetSymbolTable)) {
|
||||||
if ((st = weaken(GetSymbolTable)())) {
|
if ((st = weaken(GetSymbolTable)())) {
|
||||||
l = 0;
|
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) ||
|
if ((st->symbols[l].x <= k && k <= st->symbols[l].y) ||
|
||||||
(st->symbols[l].x <= k + z && k + z <= 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)) {
|
(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].x,
|
||||||
st->addr_base + st->symbols[l].y,
|
st->addr_base + st->symbols[l].y,
|
||||||
st->symbols[l].y - st->symbols[l].x + 1);
|
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 {
|
} else {
|
||||||
kprintf("\tunknown please supply .com.dbg symbols or set COMDBG%n");
|
kprintf("\tunknown please supply .com.dbg symbols or set COMDBG\n");
|
||||||
}
|
}
|
||||||
} else {
|
} 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) {
|
static void __asan_report_memory_origin_heap(const unsigned char *a, int z) {
|
||||||
struct ReportOriginHeap t;
|
struct ReportOriginHeap t;
|
||||||
kprintf("%nthe memory was allocated by%n");
|
kprintf("\nthe memory was allocated by\n");
|
||||||
if (weaken(malloc_inspect_all)) {
|
if (weaken(malloc_inspect_all)) {
|
||||||
t.a = a;
|
t.a = a;
|
||||||
t.z = z;
|
t.z = z;
|
||||||
weaken(malloc_inspect_all)(OnMemory, &t);
|
weaken(malloc_inspect_all)(OnMemory, &t);
|
||||||
} else {
|
} 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;
|
struct MemoryIntervals *m;
|
||||||
++g_ftrace;
|
++g_ftrace;
|
||||||
p = __fatalbuf;
|
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,
|
__asan_describe_access_poison(kind), size, message, addr,
|
||||||
SHADOW(addr), __argv[0]);
|
SHADOW(addr), __argv[0]);
|
||||||
if (0 < size && size < 80) {
|
if (0 < size && size < 80) {
|
||||||
|
@ -753,7 +752,6 @@ dontdiscard static __asan_die_f *__asan_report(const void *addr, int size,
|
||||||
*p++ = ' ';
|
*p++ = ' ';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (__nomultics) *p++ = '\r';
|
|
||||||
*p++ = '\n';
|
*p++ = '\n';
|
||||||
for (c = i = 0; i < 80; ++i) {
|
for (c = i = 0; i < 80; ++i) {
|
||||||
if (!(t = __asan_check(base + i, 1).kind)) {
|
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");
|
p = __stpcpy(p, "\e[39m");
|
||||||
if (__nomultics) *p++ = '\r';
|
|
||||||
*p++ = '\n';
|
*p++ = '\n';
|
||||||
for (i = 0; (intptr_t)(base + i) & 7; ++i) *p++ = ' ';
|
for (i = 0; (intptr_t)(base + i) & 7; ++i) *p++ = ' ';
|
||||||
for (; i + 8 <= 80; i += 8) {
|
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++ = ' ';
|
for (; i < 80; ++i) *p++ = ' ';
|
||||||
if (__nomultics) *p++ = '\r';
|
|
||||||
*p++ = '\n';
|
*p++ = '\n';
|
||||||
for (i = 0; i < 80; ++i) {
|
for (i = 0; i < 80; ++i) {
|
||||||
p = __asan_utf8cpy(p, __asan_exists(base + i)
|
p = __asan_utf8cpy(p, __asan_exists(base + i)
|
||||||
? kCp437[((unsigned char *)base)[i]]
|
? kCp437[((unsigned char *)base)[i]]
|
||||||
: L'⋅');
|
: L'⋅');
|
||||||
}
|
}
|
||||||
if (__nomultics) *p++ = '\r';
|
|
||||||
*p++ = '\n';
|
*p++ = '\n';
|
||||||
}
|
}
|
||||||
p = __asan_format_section(p, _base, _etext, ".text", addr);
|
p = __asan_format_section(p, _base, _etext, ".text", addr);
|
||||||
p = __asan_format_section(p, _etext, _edata, ".data", addr);
|
p = __asan_format_section(p, _etext, _edata, ".data", addr);
|
||||||
p = __asan_format_section(p, _end, _edata, ".bss", 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) {
|
for (m = weaken(_mmi), i = 0; i < m->i; ++i) {
|
||||||
x = m->p[i].x;
|
x = m->p[i].x;
|
||||||
y = m->p[i].y;
|
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");
|
if (x <= z && z <= y) p = __stpcpy(p, " ←address");
|
||||||
z = (((intptr_t)addr >> 3) + 0x7fff8000) >> 16;
|
z = (((intptr_t)addr >> 3) + 0x7fff8000) >> 16;
|
||||||
if (x <= z && z <= y) p = __stpcpy(p, " ←shadow");
|
if (x <= z && z <= y) p = __stpcpy(p, " ←shadow");
|
||||||
if (__nomultics) *p++ = '\r';
|
|
||||||
*p++ = '\n';
|
*p++ = '\n';
|
||||||
}
|
}
|
||||||
*p = 0;
|
*p = 0;
|
||||||
kprintf("%s", __fatalbuf);
|
kprintf("%s", __fatalbuf);
|
||||||
__asan_report_memory_origin(addr, size, kind);
|
__asan_report_memory_origin(addr, size, kind);
|
||||||
kprintf("%nthe crash was caused by%n");
|
kprintf("\nthe crash was caused by\n");
|
||||||
--g_ftrace;
|
--g_ftrace;
|
||||||
return __asan_die();
|
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) {
|
if (!__asan_checka(SHADOW(bp), sizeof(*bp) >> 3).kind) {
|
||||||
addr = bp->addr;
|
addr = bp->addr;
|
||||||
if (addr == weakaddr("__gc") && weakaddr("__gc")) {
|
if (addr == weakaddr("__gc") && weakaddr("__gc")) {
|
||||||
do
|
do --gi;
|
||||||
--gi;
|
|
||||||
while ((addr = garbage->p[gi].ret) == weakaddr("__gc"));
|
while ((addr = garbage->p[gi].ret) == weakaddr("__gc"));
|
||||||
}
|
}
|
||||||
bt->p[i] = addr;
|
bt->p[i] = addr;
|
||||||
|
@ -1018,12 +1012,12 @@ int __asan_print_trace(void *p) {
|
||||||
kprintf(" bad cookie");
|
kprintf(" bad cookie");
|
||||||
return -1;
|
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)) {
|
if (!__asan_is_mapped((((intptr_t)p >> 3) + 0x7fff8000) >> 16)) {
|
||||||
kprintf(" (shadow not mapped?!)");
|
kprintf(" (shadow not mapped?!)");
|
||||||
}
|
}
|
||||||
for (i = 0; i < ARRAYLEN(e->bt.p) && e->bt.p[i]; ++i) {
|
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)
|
||||||
? weaken(__get_symbol_by_addr)(e->bt.p[i])
|
? weaken(__get_symbol_by_addr)(e->bt.p[i])
|
||||||
: "please STATIC_YOINK(\"__get_symbol_by_addr\")");
|
: "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;
|
struct AsanTrace tr;
|
||||||
__asan_rawtrace(&tr, __builtin_frame_address(0));
|
__asan_rawtrace(&tr, __builtin_frame_address(0));
|
||||||
kprintf(
|
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]);
|
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) {
|
void __asan_map_shadow(uintptr_t p, size_t n) {
|
||||||
|
// assume _mmi.lock is held
|
||||||
void *addr;
|
void *addr;
|
||||||
int i, a, b;
|
int i, a, b;
|
||||||
size_t size;
|
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,
|
m, a, a + i - 1, sm.maphandle, PROT_READ | PROT_WRITE,
|
||||||
MAP_PRIVATE | *weaken(MAP_ANONYMOUS) | MAP_FIXED, false, false, 0,
|
MAP_PRIVATE | *weaken(MAP_ANONYMOUS) | MAP_FIXED, false, false, 0,
|
||||||
size) == -1) {
|
size) == -1) {
|
||||||
kprintf("error: could not map asan shadow memory%n");
|
kprintf("error: could not map asan shadow memory\n");
|
||||||
__asan_die()();
|
__asan_die()();
|
||||||
__asan_unreachable();
|
__asan_unreachable();
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,12 +35,12 @@ relegated wontreturn void __assert_fail(const char *expr, const char *file,
|
||||||
static bool noreentry;
|
static bool noreentry;
|
||||||
__strace = 0;
|
__strace = 0;
|
||||||
g_ftrace = 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 (_lockcmpxchg(&noreentry, false, true)) {
|
||||||
if (weaken(__die)) {
|
if (weaken(__die)) {
|
||||||
weaken(__die)();
|
weaken(__die)();
|
||||||
} else {
|
} else {
|
||||||
kprintf("can't backtrace b/c `__die` not linked%n");
|
kprintf("can't backtrace b/c `__die` not linked\n");
|
||||||
}
|
}
|
||||||
rc = 23;
|
rc = 23;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(1)));
|
typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(1)));
|
||||||
typedef long long xmm_a __attribute__((__vector_size__(16), __aligned__(16)));
|
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};
|
xmm_t v = {0};
|
||||||
if (IsAsan()) __asan_verify(p, n);
|
if (IsAsan()) __asan_verify(p, n);
|
||||||
if (n <= 32) {
|
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};
|
xmm_t v = {0};
|
||||||
if (IsAsan()) __asan_verify(p, n);
|
if (IsAsan()) __asan_verify(p, n);
|
||||||
if (n <= 32) {
|
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/terminateprocess.greg.o \
|
||||||
o/$(MODE)/libc/intrin/describemapflags.greg.o \
|
o/$(MODE)/libc/intrin/describemapflags.greg.o \
|
||||||
o/$(MODE)/libc/intrin/getfileattributes.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/setcurrentdirectory.greg.o \
|
||||||
o/$(MODE)/libc/intrin/mapviewoffileexnuma.greg.o \
|
o/$(MODE)/libc/intrin/mapviewoffileexnuma.greg.o \
|
||||||
o/$(MODE)/libc/intrin/createfilemappingnuma.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/generateconsolectrlevent.greg.o \
|
||||||
o/$(MODE)/libc/intrin/kstarttsc.o \
|
o/$(MODE)/libc/intrin/kstarttsc.o \
|
||||||
o/$(MODE)/libc/intrin/nomultics.o \
|
o/$(MODE)/libc/intrin/nomultics.o \
|
||||||
|
|
|
@ -114,7 +114,7 @@ kDos2Errno:
|
||||||
.e kNtErrorCrc,EACCES
|
.e kNtErrorCrc,EACCES
|
||||||
.e kNtErrorDirNotEmpty,ENOTEMPTY
|
.e kNtErrorDirNotEmpty,ENOTEMPTY
|
||||||
.e kNtErrorDupName,EADDRINUSE
|
.e kNtErrorDupName,EADDRINUSE
|
||||||
.e kNtErrorFilenameExcedRange,ENOENT
|
.e kNtErrorFilenameExcedRange,ENAMETOOLONG
|
||||||
.e kNtErrorGenFailure,EACCES
|
.e kNtErrorGenFailure,EACCES
|
||||||
.e kNtErrorGracefulDisconnect,EPIPE
|
.e kNtErrorGracefulDisconnect,EPIPE
|
||||||
.e kNtErrorHostDown,EHOSTUNREACH
|
.e kNtErrorHostDown,EHOSTUNREACH
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "libc/intrin/nomultics.internal.h"
|
#include "libc/intrin/nomultics.internal.h"
|
||||||
#include "libc/intrin/spinlock.h"
|
#include "libc/intrin/spinlock.h"
|
||||||
#include "libc/limits.h"
|
#include "libc/limits.h"
|
||||||
|
#include "libc/log/internal.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/nexgen32e/rdtsc.h"
|
#include "libc/nexgen32e/rdtsc.h"
|
||||||
#include "libc/nexgen32e/uart.internal.h"
|
#include "libc/nexgen32e/uart.internal.h"
|
||||||
|
@ -174,6 +175,7 @@ privileged static inline bool kismemtrackhosed(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
privileged static bool kismapped(int x) {
|
privileged static bool kismapped(int x) {
|
||||||
|
// xxx: we can't lock because no reentrant locks yet
|
||||||
size_t m, r, l = 0;
|
size_t m, r, l = 0;
|
||||||
if (!weaken(_mmi)) return true;
|
if (!weaken(_mmi)) return true;
|
||||||
if (kismemtrackhosed()) return false;
|
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;
|
i = 0;
|
||||||
m = (1 << base) - 1;
|
m = (1 << base) - 1;
|
||||||
if (hash && x) sign = hash;
|
if (hash && x) sign = hash;
|
||||||
do
|
do z[i++ & 127] = abet[x & m];
|
||||||
z[i++ & 127] = abet[x & m];
|
|
||||||
while ((x >>= base) || (pdot && i < prec));
|
while ((x >>= base) || (pdot && i < prec));
|
||||||
goto EmitNumber;
|
goto EmitNumber;
|
||||||
|
|
||||||
|
@ -556,11 +557,6 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, va_list va,
|
||||||
|
|
||||||
case 'n':
|
case 'n':
|
||||||
// nonstandard %n specifier
|
// 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';
|
if (p < e) *p = '\n';
|
||||||
++p;
|
++p;
|
||||||
break;
|
break;
|
||||||
|
@ -569,7 +565,7 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, va_list va,
|
||||||
// undocumented %r specifier
|
// undocumented %r specifier
|
||||||
// used for good carriage return
|
// used for good carriage return
|
||||||
// helps integrate loggers with repls
|
// helps integrate loggers with repls
|
||||||
if (!__replmode) {
|
if (!__replmode || __nocolor) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
s = "\r\033[K";
|
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) {
|
privileged void kvprintf(const char *fmt, va_list v) {
|
||||||
size_t n;
|
size_t n;
|
||||||
char b[2048];
|
char b[4000];
|
||||||
struct Timestamps t;
|
struct Timestamps t;
|
||||||
if (!v) return;
|
if (!v) return;
|
||||||
t = kenter();
|
t = kenter();
|
||||||
n = kformat(b, sizeof(b), fmt, v, t);
|
n = kformat(b, sizeof(b), fmt, v, t);
|
||||||
klog(b, MIN(n, sizeof(b)));
|
klog(b, MIN(n, sizeof(b) - 1));
|
||||||
kleave(t);
|
kleave(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(1)));
|
typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(1)));
|
||||||
typedef long long xmm_a __attribute__((__vector_size__(16), __aligned__(16)));
|
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};
|
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 (IsAsan()) __asan_verify(p, n);
|
||||||
if (n <= 32) {
|
if (n <= 32) {
|
||||||
|
@ -44,8 +44,7 @@ noasan static dontinline antiquity void *memset_sse(char *p, char c, size_t n) {
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
noasan microarchitecture("avx") static void *memset_avx(char *p, char c,
|
microarchitecture("avx") static void *memset_avx(char *p, char c, size_t n) {
|
||||||
size_t n) {
|
|
||||||
char *t;
|
char *t;
|
||||||
xmm_t v = {c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c};
|
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 (IsAsan()) __asan_verify(p, n);
|
||||||
|
|
|
@ -17,17 +17,6 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ 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.
|
* Controls ANSI prefix for log emissions.
|
||||||
*
|
*
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue