Improve ZIP filesystem and change its prefix

The ZIP filesystem has a breaking change. You now need to use /zip/ to
open() / opendir() / etc. assets within the ZIP structure of your APE
binary, instead of the previous convention of using zip: or zip! URIs.
This is needed because Python likes to use absolute paths, and having
ZIP paths encoded like URIs simply broke too many things.

Many more system calls have been updated to be able to operate on ZIP
files and file descriptors. In particular fcntl() and ioctl() since
Python would do things like ask if a ZIP file is a terminal and get
confused when the old implementation mistakenly said yes, because the
fastest way to guarantee native file descriptors is to dup(2). This
change also improves the async signal safety of zipos and ensures it
doesn't maintain any open file descriptors beyond that which the user
has opened.

This change makes a lot of progress towards adding magic numbers that
are specific to platforms other than Linux. The philosophy here is that,
if you use an operating system like FreeBSD, then you should be able to
take advantage of FreeBSD exclusive features, even if we don't polyfill
them on other platforms. For example, you can now open() a file with the
O_VERIFY flag. If your program runs on other platforms, then Cosmo will
automatically set O_VERIFY to zero. This lets you safely use it without
the need for #ifdef or ifstatements which detract from readability.

One of the blindspots of the ASAN memory hardening we use to offer Rust
like assurances has always been that memory passed to the kernel via
system calls (e.g. writev) can't be checked automatically since the
kernel wasn't built with MODE=asan. This change makes more progress
ensuring that each system call will verify the soundness of memory
before it's passed to the kernel. The code for doing these checks is
fast, particularly for buffers, where it can verify 64 bytes a cycle.

- Correct O_LOOP definition on NT
- Introduce program_executable_name
- Add ASAN guards to more system calls
- Improve termios compatibility with BSDs
- Fix bug in Windows auxiliary value encoding
- Add BSD and XNU specific errnos and open flags
- Add check to ensure build doesn't talk to internet
This commit is contained in:
Justine Tunney 2021-08-22 01:04:18 -07:00
parent 2730c66f4a
commit 00611e9b06
319 changed files with 4418 additions and 2599 deletions

View file

@ -35,7 +35,7 @@ STATIC_YOINK("ssl_root_support");
#define DFL_FILENAME "cert.crt" #define DFL_FILENAME "cert.crt"
#define DFL_CA_FILE "" #define DFL_CA_FILE ""
#define DFL_CRL_FILE "" #define DFL_CRL_FILE ""
#define DFL_CA_PATH "zip:usr/share/ssl/root" #define DFL_CA_PATH "/zip/usr/share/ssl/root"
#define DFL_SERVER_NAME "localhost" #define DFL_SERVER_NAME "localhost"
#define DFL_SERVER_PORT "4433" #define DFL_SERVER_PORT "4433"
#define DFL_DEBUG_LEVEL 0 #define DFL_DEBUG_LEVEL 0

View file

@ -69,12 +69,13 @@ EXAMPLES_DIRECTDEPS = \
NET_HTTPS \ NET_HTTPS \
THIRD_PARTY_COMPILER_RT \ THIRD_PARTY_COMPILER_RT \
THIRD_PARTY_DLMALLOC \ THIRD_PARTY_DLMALLOC \
THIRD_PARTY_QUICKJS \
THIRD_PARTY_GDTOA \ THIRD_PARTY_GDTOA \
THIRD_PARTY_GETOPT \ THIRD_PARTY_GETOPT \
THIRD_PARTY_LINENOISE \
THIRD_PARTY_LUA \ THIRD_PARTY_LUA \
THIRD_PARTY_MBEDTLS \ THIRD_PARTY_MBEDTLS \
THIRD_PARTY_MUSL \ THIRD_PARTY_MUSL \
THIRD_PARTY_QUICKJS \
THIRD_PARTY_STB \ THIRD_PARTY_STB \
THIRD_PARTY_XED \ THIRD_PARTY_XED \
THIRD_PARTY_ZLIB \ THIRD_PARTY_ZLIB \

View file

@ -24,7 +24,7 @@ int main(int argc, char *argv[]) {
luaL_openlibs(L); luaL_openlibs(L);
lua_pushcfunction(L, NativeAdd); lua_pushcfunction(L, NativeAdd);
lua_setglobal(L, "NativeAdd"); lua_setglobal(L, "NativeAdd");
luaL_dofile(L, "zip:examples/hellolua.lua"); luaL_dofile(L, "/zip/examples/hellolua.lua");
lua_close(L); lua_close(L);
return 0; return 0;
} }

View file

@ -145,7 +145,7 @@ void SpellChecker(void) {
} }
void LoadWords(void) { void LoadWords(void) {
CHECK_NOTNULL((f = fopen("zip:usr/share/dict/words", "r"))); CHECK_NOTNULL((f = fopen("/zip/usr/share/dict/words", "r")));
while (getline(&line, &linesize, f) > 0) { while (getline(&line, &linesize, f) > 0) {
critbit0_insert(&words, strtolower(chomp(line))); critbit0_insert(&words, strtolower(chomp(line)));
} }

View file

@ -1818,7 +1818,7 @@ size_t FindZipGames(void) {
!memcmp((ZIP_CFILE_NAME(zipos->map + cf) + !memcmp((ZIP_CFILE_NAME(zipos->map + cf) +
ZIP_CFILE_NAMESIZE(zipos->map + cf) - 4), ZIP_CFILE_NAMESIZE(zipos->map + cf) - 4),
".nes", 4) && ".nes", 4) &&
(name = xasprintf("zip:%.*s", ZIP_CFILE_NAMESIZE(zipos->map + cf), (name = xasprintf("/zip/%.*s", ZIP_CFILE_NAMESIZE(zipos->map + cf),
ZIP_CFILE_NAME(zipos->map + cf)))) { ZIP_CFILE_NAME(zipos->map + cf)))) {
APPEND(&zipgames_.p, &zipgames_.i, &zipgames_.n, &name); APPEND(&zipgames_.p, &zipgames_.i, &zipgames_.n, &name);
} }

98
examples/time.c Normal file
View file

@ -0,0 +1,98 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/ │
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/calls/calls.h"
#include "libc/calls/struct/timespec.h"
#include "libc/fmt/itoa.h"
#include "libc/log/log.h"
#include "libc/math.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/ex.h"
#include "libc/time/time.h"
#include "libc/x/x.h"
/**
* @fileoverview command for showing how long a command takes
*
* This offers the following improvements over the existing `time`
* command that's incorporated into most shells:
*
* - This will show microseconds if seconds < 1
* - This will launch APE binaries on systems with broken libc execv()
*/
#define WRITE(FD, STR) write(FD, STR, strlen(STR))
void OnChild(void *arg) {
char **argv = arg;
execv(argv[0], argv);
_exit(127);
}
long double GetTimeval(struct timeval t) {
return t.tv_sec + t.tv_usec * 1e-6l;
}
void PrintMetric(const char *name, long double d) {
char buf[256], *p = buf;
long mins, secs, mils, mics;
mins = d / 60;
secs = fmodl(d, 60);
mils = fmodl(d * 1000, 1000);
mics = fmodl(d * 1000000, 1000);
p = stpcpy(p, name), *p++ = '\t';
p += int64toarray_radix10(mins, p), *p++ = 'm';
p += int64toarray_radix10(secs, p), *p++ = '.';
*p++ = '0' + mils / 100;
*p++ = '0' + mils / 10 % 10;
*p++ = '0' + mils % 10;
if (!secs) {
*p++ = '0' + mics / 100;
*p++ = '0' + mics / 10 % 10;
*p++ = '0' + mics % 10;
}
*p++ = 's';
*p++ = '\n';
write(2, buf, p - buf);
}
int main(int argc, char *argv[]) {
int ws;
char *exepath;
struct rusage r;
long double real;
char exebuf[PATH_MAX];
if (argc >= 2) {
if ((exepath = commandv(argv[1], exebuf))) {
real = nowl();
argv[1] = exepath;
if ((ws = xvspawn(OnChild, argv + 1, &r)) != -1) {
PrintMetric("real", nowl() - real);
PrintMetric("user", GetTimeval(r.ru_utime));
PrintMetric("sys", GetTimeval(r.ru_stime));
if (WIFEXITED(ws)) {
return WEXITSTATUS(ws);
} else {
return 128 + WTERMSIG(ws);
}
} else {
perror("xvspawn");
return 127;
}
} else {
perror(argv[1]);
return 127;
}
} else {
WRITE(2, "Usage: ");
WRITE(2, argv[0]);
WRITE(2, " PROG [ARGS...]\n");
return EX_USAGE;
}
}

View file

@ -111,6 +111,8 @@
*/ */
#include "libc/alg/alg.h" #include "libc/alg/alg.h"
#include "libc/assert.h"
#include "libc/bits/safemacros.internal.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/sigbits.h" #include "libc/calls/sigbits.h"
#include "libc/calls/struct/dirent.h" #include "libc/calls/struct/dirent.h"
@ -125,6 +127,7 @@
#include "libc/fmt/fmt.h" #include "libc/fmt/fmt.h"
#include "libc/limits.h" #include "libc/limits.h"
#include "libc/log/log.h" #include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/mem/alloca.h" #include "libc/mem/alloca.h"
#include "libc/mem/mem.h" #include "libc/mem/mem.h"
#include "libc/paths.h" #include "libc/paths.h"
@ -132,6 +135,7 @@
#include "libc/runtime/sysconf.h" #include "libc/runtime/sysconf.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/sysv/consts/at.h" #include "libc/sysv/consts/at.h"
#include "libc/sysv/consts/dt.h"
#include "libc/sysv/consts/f.h" #include "libc/sysv/consts/f.h"
#include "libc/sysv/consts/fd.h" #include "libc/sysv/consts/fd.h"
#include "libc/sysv/consts/fileno.h" #include "libc/sysv/consts/fileno.h"
@ -141,6 +145,7 @@
#include "libc/sysv/consts/sig.h" #include "libc/sysv/consts/sig.h"
#include "libc/sysv/consts/w.h" #include "libc/sysv/consts/w.h"
#include "third_party/gdtoa/gdtoa.h" #include "third_party/gdtoa/gdtoa.h"
#include "third_party/linenoise/linenoise.h"
#include "third_party/musl/passwd.h" #include "third_party/musl/passwd.h"
#define likely(expr) __builtin_expect(!!(expr), 1) #define likely(expr) __builtin_expect(!!(expr), 1)
@ -1030,6 +1035,7 @@ struct t_op {
cosmopolitan § the unbourne shell » bss cosmopolitan § the unbourne shell » bss
*/ */
static int inter;
static char **argptr; /* argument list for builtin commands */ static char **argptr; /* argument list for builtin commands */
static char **gargv; static char **gargv;
static char **t_wp; static char **t_wp;
@ -1827,7 +1833,7 @@ printfesque(3) static int fmtstr(char *outbuf, unsigned length, const char *fmt,
return ret > (int)length ? length : ret; return ret > (int)length ? length : ret;
} }
printfesque(2) static int xasprintf(char **sp, const char *fmt, ...) { printfesque(2) static int Xasprintf(char **sp, const char *fmt, ...) {
va_list ap; va_list ap;
int ret; int ret;
va_start(ap, fmt); va_start(ap, fmt);
@ -5629,12 +5635,129 @@ static int pgetc2() {
return c; return c;
} }
static void AddUniqueCompletion(linenoiseCompletions *c, char *s) {
size_t i;
if (!s) return;
for (i = 0; i < c->len; ++i) {
if (!strcmp(s, c->cvec[i])) {
return;
}
}
c->cvec = realloc(c->cvec, ++c->len * sizeof(*c->cvec));
c->cvec[c->len - 1] = s;
}
static void CompleteCommand(const char *p, const char *q, const char *b, linenoiseCompletions *c) {
DIR *d;
size_t i;
struct dirent *e;
const char *x, *y, *path;
struct tblentry **pp, *cmdp;
for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
if (cmdp->cmdtype >= 0 && !strncmp(cmdp->cmdname, p, q - p)) {
AddUniqueCompletion(c, strdup(cmdp->cmdname));
}
}
}
for (i = 0; i < ARRAYLEN(kBuiltinCmds); ++i) {
if (!strncmp(kBuiltinCmds[i].name, p, q - p)) {
AddUniqueCompletion(c, strdup(kBuiltinCmds[i].name));
}
}
for (y = x = lookupvar("PATH"); *y; x = y + 1) {
if ((path = strndup(x, (y = strchrnul(x, ':')) - x))) {
if ((d = opendir(path))) {
while ((e = readdir(d))) {
if (e->d_type == DT_REG && !strncmp(e->d_name, p, q - p)) {
AddUniqueCompletion(c, strdup(e->d_name));
}
}
closedir(d);
}
free(path);
}
}
}
static void CompleteFilename(const char *p, const char *q, const char *b, linenoiseCompletions *c) {
DIR *d;
char *buf;
const char *g;
struct dirent *e;
if ((buf = malloc(512))) {
if ((g = memrchr(p, '/', q - p))) {
*(char *)mempcpy(buf, p, MIN(g - p, 511)) = 0;
p = ++g;
} else {
strcpy(buf, ".");
}
if ((d = opendir(buf))) {
while ((e = readdir(d))) {
if (!strcmp(e->d_name, ".")) continue;
if (!strcmp(e->d_name, "..")) continue;
if (!strncmp(e->d_name, p, q - p)) {
snprintf(buf, 512, "%.*s%s%s", p - b, b, e->d_name, e->d_type == DT_DIR ? "/" : "");
AddUniqueCompletion(c, strdup(buf));
}
}
closedir(d);
}
free(buf);
}
}
static void ShellCompletion(const char *p, linenoiseCompletions *c) {
bool slashed;
const char *q, *b;
struct tblentry **pp, *cmdp;
for (slashed = false, b = p, q = (p += strlen(p)); p > b; --p) {
if (p[-1] == '/' && p[-1] == '\\') slashed = true;
if (!isalnum(p[-1]) && (p[-1] != '.' && p[-1] != '_' && p[-1] != '-' && p[-1] != '+' &&
p[-1] != '[' && p[-1] != '/' && p[-1] != '\\')) {
break;
}
}
if (b == p && !slashed) {
CompleteCommand(p, q, b, c);
} else {
CompleteFilename(p, q, b, c);
}
}
static char *ShellHint(const char *p, int *color, int *bold) {
char *h = 0;
linenoiseCompletions c = {0};
ShellCompletion(p, &c);
if (c.len == 1) {
h = strdup(c.cvec[0] + strlen(p));
*bold = 2;
}
linenoiseFreeCompletions(&c);
return h;
}
static ssize_t preadfd(void) { static ssize_t preadfd(void) {
ssize_t nr; ssize_t nr;
char *buf = parsefile->buf; char *p, *buf = parsefile->buf;
parsefile->nextc = buf; parsefile->nextc = buf;
retry: retry:
nr = read(parsefile->fd, buf, IBUFSIZ - 1); if (!parsefile->fd && isatty(0)) {
linenoiseSetFreeHintsCallback(free);
linenoiseSetHintsCallback(ShellHint);
linenoiseSetCompletionCallback(ShellCompletion);
if ((p = ezlinenoise(getprompt(NULL), "unbourne"))) {
nr = min(strlen(p), IBUFSIZ - 2);
memcpy(buf, p, nr);
buf[nr++] = '\n';
free(p);
} else {
write(1, "\n", 1);
nr = 0;
}
} else {
nr = read(parsefile->fd, buf, IBUFSIZ - 1);
}
if (nr < 0) { if (nr < 0) {
if (errno == EINTR) goto retry; if (errno == EINTR) goto retry;
if (parsefile->fd == 0 && errno == EAGAIN) { if (parsefile->fd == 0 && errno == EAGAIN) {
@ -7036,12 +7159,12 @@ static int readcmd(int argc, char **argv) {
if (prompt && isatty(0)) { if (prompt && isatty(0)) {
outstr(prompt, out2); outstr(prompt, out2);
} }
if (*(ap = argptr) == NULL) sh_error("arg count"); if (!*(ap = argptr)) sh_error("arg count");
status = 0; status = 0;
STARTSTACKSTR(p); STARTSTACKSTR(p);
goto start; goto start;
for (;;) { for (;;) {
switch (read(STDIN_FILENO, &c, 1)) { switch (read(0, &c, 1)) {
case 1: case 1:
break; break;
default: default:
@ -7051,7 +7174,7 @@ static int readcmd(int argc, char **argv) {
status = 1; status = 1;
goto out; goto out;
} }
if (c == '\0') continue; if (!c) continue;
if (newloc >= startloc) { if (newloc >= startloc) {
if (c == '\n') goto resetbs; if (c == '\n') goto resetbs;
goto put; goto put;
@ -8820,7 +8943,7 @@ static void setprompt(int which) {
int show; int show;
needprompt = 0; needprompt = 0;
whichprompt = which; whichprompt = which;
show = 1; show = 0;
if (show) { if (show) {
pushstackmark(&smark, stackblocksize()); pushstackmark(&smark, stackblocksize());
outstr(getprompt(NULL), out2); outstr(getprompt(NULL), out2);
@ -9377,13 +9500,13 @@ static void sigblockall(sigset_t *oldmask) {
int ret; \ int ret; \
switch ((char *)param - (char *)array) { \ switch ((char *)param - (char *)array) { \
default: \ default: \
ret = xasprintf(sp, f, array[0], array[1], func); \ ret = Xasprintf(sp, f, array[0], array[1], func); \
break; \ break; \
case sizeof(*param): \ case sizeof(*param): \
ret = xasprintf(sp, f, array[0], func); \ ret = Xasprintf(sp, f, array[0], func); \
break; \ break; \
case 0: \ case 0: \
ret = xasprintf(sp, f, func); \ ret = Xasprintf(sp, f, func); \
break; \ break; \
} \ } \
ret; \ ret; \
@ -10788,8 +10911,6 @@ static int exitcmd(int argc, char **argv) {
* is used to figure out how far we had gotten. * is used to figure out how far we had gotten.
*/ */
int main(int argc, char **argv) { int main(int argc, char **argv) {
showcrashreports();
unsetenv("PS1");
char *shinit; char *shinit;
volatile int state; volatile int state;
struct jmploc jmploc; struct jmploc jmploc;

View file

@ -56,6 +56,7 @@
#define WIFSTOPPED(s) ((short)((((s)&0xffff) * 0x10001) >> 8) > 0x7f00) #define WIFSTOPPED(s) ((short)((((s)&0xffff) * 0x10001) >> 8) > 0x7f00)
#define WSTOPSIG(s) WEXITSTATUS(s) #define WSTOPSIG(s) WEXITSTATUS(s)
#define WTERMSIG(s) ((s)&0x7f) #define WTERMSIG(s) ((s)&0x7f)
#define W_STOPCODE(s) ((s) << 8 | 0177)
#if !(__ASSEMBLER__ + __LINKER__ + 0) #if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_ COSMOPOLITAN_C_START_
@ -88,34 +89,35 @@ int chown(const char *, uint32_t, uint32_t);
int chroot(const char *); int chroot(const char *);
int close(int); int close(int);
int closedir(DIR *); int closedir(DIR *);
int creat(const char *, uint32_t) nodiscard; int creat(const char *, uint32_t);
int dirfd(DIR *); int dirfd(DIR *);
int dup(int) nodiscard; int dup(int);
int dup2(int, int); int dup2(int, int);
int dup3(int, int, int); int dup3(int, int, int);
int execl(const char *, const char *, ...) nullterminated(); int execl(const char *, const char *, ...) nullterminated();
int execle(const char *, const char *, ...) nullterminated((1)); int execle(const char *, const char *, ...) nullterminated((1));
int execlp(const char *, const char *, ...) nullterminated(); int execlp(const char *, const char *, ...) nullterminated();
int execv(const char *, char *const[]) paramsnonnull(); int execv(const char *, char *const[]);
int execve(const char *, char *const[], char *const[]) paramsnonnull(); int execve(const char *, char *const[], char *const[]);
int execvp(const char *, char *const[]) paramsnonnull(); int execvp(const char *, char *const[]);
int execvpe(const char *, char *const[], char *const[]) paramsnonnull(); int execvpe(const char *, char *const[], char *const[]);
int faccessat(int, const char *, int, uint32_t); int faccessat(int, const char *, int, uint32_t);
int fadvise(int, uint64_t, uint64_t, int); int fadvise(int, uint64_t, uint64_t, int);
int fchdir(int); int fchdir(int);
int fchmod(int, uint32_t) nothrow; int fchmod(int, uint32_t) nothrow;
int fchmodat(int, const char *, uint32_t, uint32_t); int fchmodat(int, const char *, uint32_t, int);
int fchown(int, uint32_t, uint32_t); int fchown(int, uint32_t, uint32_t);
int fchownat(int, const char *, uint32_t, uint32_t, uint32_t); int fchownat(int, const char *, uint32_t, uint32_t, int);
int fcntl(int, int, ...); int fcntl(int, int, ...);
int fdatasync(int); int fdatasync(int);
int filecmp(const char *, const char *); int filecmp(const char *, const char *);
int flock(int, int); int flock(int, int);
int fork(void); int fork(void);
int fstat(int, struct stat *); int fstat(int, struct stat *);
int fstatat(int, const char *, struct stat *, uint32_t); int fstatat(int, const char *, struct stat *, int);
int fsync(int); int fsync(int);
int ftruncate(int, int64_t); int ftruncate(int, int64_t);
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 getpgid(int); int getpgid(int);
@ -127,7 +129,7 @@ int getrusage(int, struct rusage *);
int kill(int, int); int kill(int, int);
int killpg(int, int); int killpg(int, int);
int link(const char *, const char *) nothrow; int link(const char *, const char *) nothrow;
int linkat(int, const char *, int, const char *, uint32_t); int linkat(int, const char *, int, const char *, int);
int lstat(const char *, struct stat *); int lstat(const char *, struct stat *);
int lutimes(const char *, const struct timeval[2]); int lutimes(const char *, const struct timeval[2]);
int madvise(void *, uint64_t, int); int madvise(void *, uint64_t, int);
@ -244,10 +246,6 @@ int vdprintf(int, const char *, va_list) paramsnonnull();
*/ */
#if defined(__GNUC__) && !defined(__STRICT_ANSI__) #if defined(__GNUC__) && !defined(__STRICT_ANSI__)
#define getcwd(BUF, SIZE) \
(__builtin_constant_p(BUF) && !(BUF) ? get_current_dir_name() \
: getcwd(BUF, SIZE))
void _init_onntconsoleevent(void); void _init_onntconsoleevent(void);
void _init_wincrash(void); void _init_wincrash(void);

View file

@ -75,6 +75,25 @@ o/$(MODE)/libc/calls/ntcontext2linux.o: \
OVERRIDE_COPTS += \ OVERRIDE_COPTS += \
-O3 -O3
# TODO(jart): make va_arg optimize well in default mode
o//libc/calls/ioctl.o \
o//libc/calls/ioctl_default.o \
o//libc/calls/ioctl_fioclex-nt.o \
o//libc/calls/ioctl_fioclex.o \
o//libc/calls/ioctl_siocgifconf-nt.o \
o//libc/calls/ioctl_siocgifconf.o \
o//libc/calls/ioctl_tcgets-nt.o \
o//libc/calls/ioctl_tcgets.o \
o//libc/calls/ioctl_tcsets-nt.o \
o//libc/calls/ioctl_tcsets.o \
o//libc/calls/ioctl_tiocgwinsz-nt.o \
o//libc/calls/ioctl_tiocgwinsz.o \
o//libc/calls/ioctl_tiocswinsz-nt.o \
o//libc/calls/ioctl_tiocswinsz.o \
o//libc/calls/fcntl.o: \
OVERRIDE_CFLAGS += \
-Os
o/$(MODE)/libc/calls/execl.o \ o/$(MODE)/libc/calls/execl.o \
o/$(MODE)/libc/calls/execle.o \ o/$(MODE)/libc/calls/execle.o \
o/$(MODE)/libc/calls/execlp.o \ o/$(MODE)/libc/calls/execlp.o \

View file

@ -18,14 +18,19 @@
*/ */
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h"
/** /**
* Sets current directory. * Sets current directory.
* *
* This does *not* update the `PWD` environment variable.
*
* @asyncsignalsafe * @asyncsignalsafe
* @see fchdir() * @see fchdir()
*/ */
int chdir(const char *path) { int chdir(const char *path) {
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
if (!IsWindows()) { if (!IsWindows()) {
return sys_chdir(path); return sys_chdir(path);
} else { } else {

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/sysv/consts/at.h" #include "libc/sysv/consts/at.h"
/** /**
@ -42,5 +41,5 @@
* @see fchmod() * @see fchmod()
*/ */
int chmod(const char *pathname, uint32_t mode) { int chmod(const char *pathname, uint32_t mode) {
return sys_fchmodat(AT_FDCWD, pathname, mode, 0); return fchmodat(AT_FDCWD, pathname, mode, 0);
} }

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/sysv/consts/at.h" #include "libc/sysv/consts/at.h"
/** /**
@ -33,5 +32,5 @@
* @asyncsignalsafe * @asyncsignalsafe
*/ */
int chown(const char *pathname, uint32_t uid, uint32_t gid) { int chown(const char *pathname, uint32_t uid, uint32_t gid) {
return sys_fchownat(AT_FDCWD, pathname, uid, gid, 0); return fchownat(AT_FDCWD, pathname, uid, gid, 0);
} }

View file

@ -19,7 +19,9 @@
#include "libc/assert.h" #include "libc/assert.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/struct/timeval.h" #include "libc/calls/struct/timeval.h"
#include "libc/dce.h"
#include "libc/fmt/conv.h" #include "libc/fmt/conv.h"
#include "libc/intrin/asan.internal.h"
#include "libc/nt/synchronization.h" #include "libc/nt/synchronization.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
@ -42,6 +44,7 @@ int clock_gettime(int clockid, struct timespec *ts) {
axdx_t ad; axdx_t ad;
struct NtFileTime ft; struct NtFileTime ft;
if (!ts) return efault(); if (!ts) return efault();
if (IsAsan() && !__asan_is_valid(ts, sizeof(*ts))) return efault();
if (clockid == -1) return einval(); if (clockid == -1) return einval();
if (!IsWindows()) { if (!IsWindows()) {
if ((rc = sys_clock_gettime(clockid, ts)) == -1 && errno == ENOSYS) { if ((rc = sys_clock_gettime(clockid, ts)) == -1 && errno == ENOSYS) {

View file

@ -33,7 +33,7 @@ textwindows int sys_close_nt(struct Fd *fd) {
FlushFileBuffers(fd->handle); FlushFileBuffers(fd->handle);
} }
ok = CloseHandle(fd->handle); ok = CloseHandle(fd->handle);
if (fd->kind == kFdConsole) { if (fd->kind == kFdConsole && fd->extra && fd->extra != -1) {
ok &= CloseHandle(fd->extra); ok &= CloseHandle(fd->extra);
} }
return ok ? 0 : __winerr(); return ok ? 0 : __winerr();

View file

@ -74,6 +74,10 @@ char *commandv(const char *name, char pathbuf[hasatleast PATH_MAX]) {
char *p; char *p;
size_t namelen; size_t namelen;
int rc, olderr; int rc, olderr;
if (!name) {
efault();
return NULL;
}
if (!(namelen = strlen(name))) { if (!(namelen = strlen(name))) {
enoent(); enoent();
return NULL; return NULL;

View file

@ -19,6 +19,7 @@
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/mem/alloca.h" #include "libc/mem/alloca.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/sysv/errfuns.h"
/** /**
* Executes program, with PATH search and current environment. * Executes program, with PATH search and current environment.

View file

@ -30,7 +30,7 @@
#include "libc/sysv/consts/o.h" #include "libc/sysv/consts/o.h"
textwindows int sys_execve_nt(const char *program, char *const argv[], textwindows int sys_execve_nt(const char *program, char *const argv[],
char *const envp[]) { char *const envp[]) {
int rc; int rc;
size_t i; size_t i;
uint32_t dwExitCode; uint32_t dwExitCode;
@ -42,13 +42,7 @@ textwindows int sys_execve_nt(const char *program, char *const argv[],
startinfo.hStdInput = g_fds.p[0].handle; startinfo.hStdInput = g_fds.p[0].handle;
startinfo.hStdOutput = g_fds.p[1].handle; startinfo.hStdOutput = g_fds.p[1].handle;
startinfo.hStdError = g_fds.p[2].handle; startinfo.hStdError = g_fds.p[2].handle;
for (i = 2; i < g_fds.n; ++i) { rc = ntspawn(program, argv, envp, 0, 0, 0, 1, 0, 0, &startinfo, &procinfo);
if (g_fds.p[i].kind != kFdEmpty && (g_fds.p[i].flags & O_CLOEXEC)) {
close(i);
}
}
rc = ntspawn(program, argv, envp, NULL, NULL, NULL, true, 0, NULL, &startinfo,
&procinfo);
if (rc == -1) return -1; if (rc == -1) return -1;
CloseHandle(procinfo.hThread); CloseHandle(procinfo.hThread);
do { do {

View file

@ -19,6 +19,17 @@
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h"
static noasan bool __asan_is_valid_strlist(char *const *p) {
for (;; ++p) {
if (!__asan_is_valid(p, sizeof(char *))) return false;
if (!*p) return true;
if (!__asan_is_valid(*p, 1)) return false;
}
}
/** /**
* Replaces current process with program. * Replaces current process with program.
@ -34,6 +45,18 @@
* @vforksafe * @vforksafe
*/ */
int execve(const char *program, char *const argv[], char *const envp[]) { int execve(const char *program, char *const argv[], char *const envp[]) {
size_t i;
if (!program || !argv || !envp) return efault();
if (IsAsan() &&
(!__asan_is_valid(program, 1) || !__asan_is_valid_strlist(argv) ||
!__asan_is_valid_strlist(envp))) {
return efault();
}
for (i = 3; i < g_fds.n; ++i) {
if (g_fds.p[i].kind != kFdEmpty && (g_fds.p[i].flags & O_CLOEXEC)) {
close(i);
}
}
if (!IsWindows()) { if (!IsWindows()) {
return sys_execve(program, argv, envp); return sys_execve(program, argv, envp);
} else { } else {

View file

@ -17,7 +17,10 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/mem/mem.h" #include "libc/mem/mem.h"
#include "libc/sysv/errfuns.h"
/** /**
* Executes program, with path environment search. * Executes program, with path environment search.
@ -34,6 +37,7 @@
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];
if (IsAsan() && !__asan_is_valid(prog, 1)) return efault();
if (!(exe = commandv(prog, pathbuf))) return -1; if (!(exe = commandv(prog, pathbuf))) return -1;
return execve(exe, argv, envp); return execve(exe, argv, envp);
} }

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/sysv/consts/at.h" #include "libc/sysv/consts/at.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"

View file

@ -16,11 +16,14 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/consts/at.h" #include "libc/sysv/consts/at.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.internal.h"
/** /**
* Checks if effective user can access path in particular ways. * Checks if effective user can access path in particular ways.
@ -34,6 +37,10 @@
* @asyncsignalsafe * @asyncsignalsafe
*/ */
int faccessat(int dirfd, const char *path, int mode, uint32_t flags) { int faccessat(int dirfd, const char *path, int mode, uint32_t flags) {
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
if (weaken(__zipos_notat) && weaken(__zipos_notat)(dirfd, path) == -1) {
return -1; /* TODO(jart): implement me */
}
if (!IsWindows()) { if (!IsWindows()) {
return sys_faccessat(dirfd, path, mode, flags); return sys_faccessat(dirfd, path, mode, flags);
} else { } else {

View file

@ -23,6 +23,8 @@
/** /**
* Sets current directory based on file descriptor. * Sets current directory based on file descriptor.
* *
* This does *not* update the `PWD` environment variable.
*
* @see open(path, O_DIRECTORY) * @see open(path, O_DIRECTORY)
* @asyncsignalsafe * @asyncsignalsafe
*/ */

View file

@ -22,22 +22,9 @@
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
/** /**
* Changes file permissions via open()'d file descriptor, e.g.: * Changes file permissions via open()'d file descriptor.
*
* CHECK_NE(-1, chmod("foo/bar.txt", 0644));
* CHECK_NE(-1, chmod("o/default/program.com", 0755));
* CHECK_NE(-1, chmod("privatefolder/", 0700));
*
* The esoteric bits generally available on System V are:
*
* CHECK_NE(-1, chmod("/opt/", 01000)); // sticky bit
* CHECK_NE(-1, chmod("/usr/bin/sudo", 04755)); // setuid bit
* CHECK_NE(-1, chmod("/usr/bin/wall", 02755)); // setgid bit
*
* This works on Windows NT if you ignore the error ;-)
* *
* @param mode contains octal flags (base 8) * @param mode contains octal flags (base 8)
* @errors ENOSYS
* @asyncsignalsafe * @asyncsignalsafe
* @see chmod() * @see chmod()
*/ */

49
libc/calls/fchmodat.c Normal file
View file

@ -0,0 +1,49 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.internal.h"
/**
* Changes permissions on file, e.g.:
*
* CHECK_NE(-1, fchmodat(AT_FDCWD, "foo/bar.txt", 0644));
* CHECK_NE(-1, fchmodat(AT_FDCWD, "o/default/program.com", 0755));
* CHECK_NE(-1, fchmodat(AT_FDCWD, "privatefolder/", 0700));
*
* This works on Windows NT if you ignore the error ;-)
*
* @param path must exist
* @param mode contains octal flags (base 8)
* @param flags can have `AT_SYMLINK_NOFOLLOW`
* @errors ENOENT, ENOTDIR, ENOSYS
* @asyncsignalsafe
* @see fchmod()
*/
int fchmodat(int dirfd, const char *path, uint32_t mode, int flags) {
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
if (weaken(__zipos_notat) && weaken(__zipos_notat)(dirfd, path) == -1) {
return -1; /* TODO(jart): implement me */
}
return sys_fchmodat(dirfd, path, mode, flags);
}

View file

@ -16,11 +16,16 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.internal.h"
/** /**
* Changes owner and/or group of pathname. * Changes owner and/or group of path.
* *
* @param dirfd is open()'d relative-to directory, or AT_FDCWD, etc. * @param dirfd is open()'d relative-to directory, or AT_FDCWD, etc.
* @param uid is user id, or -1 to not change * @param uid is user id, or -1 to not change
@ -32,7 +37,11 @@
* @see /etc/group for group ids * @see /etc/group for group ids
* @asyncsignalsafe * @asyncsignalsafe
*/ */
int fchownat(int dirfd, const char *pathname, uint32_t uid, uint32_t gid, int fchownat(int dirfd, const char *path, uint32_t uid, uint32_t gid,
uint32_t flags) { int flags) {
return sys_fchownat(dirfd, pathname, uid, gid, flags); if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
if (weaken(__zipos_notat) && weaken(__zipos_notat)(dirfd, path) == -1) {
return -1; /* TODO(jart): implement me */
}
return sys_fchownat(dirfd, path, uid, gid, flags);
} }

View file

@ -16,9 +16,12 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.internal.h"
/** /**
* Does things with file descriptor, via re-imagined hourglass api, e.g. * Does things with file descriptor, via re-imagined hourglass api, e.g.
@ -45,9 +48,15 @@ int fcntl(int fd, int cmd, ...) {
va_start(va, cmd); va_start(va, cmd);
arg = va_arg(va, uintptr_t); arg = va_arg(va, uintptr_t);
va_end(va); va_end(va);
if (!IsWindows()) { if (fd >= 0) {
return sys_fcntl(fd, cmd, arg); if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
return weaken(__zipos_fcntl)(fd, cmd, arg);
} else if (!IsWindows()) {
return sys_fcntl(fd, cmd, arg);
} else {
return sys_fcntl_nt(fd, cmd, arg);
}
} else { } else {
return sys_fcntl_nt(fd, cmd, arg); return einval();
} }
} }

View file

@ -21,6 +21,7 @@
#include "libc/calls/struct/stat.h" #include "libc/calls/struct/stat.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/intrin/asan.internal.h"
#include "libc/nt/files.h" #include "libc/nt/files.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/sysv/consts/at.h" #include "libc/sysv/consts/at.h"
@ -37,6 +38,7 @@ bool fileexists(const char *path) {
int rc, olderr; int rc, olderr;
struct stat st; struct stat st;
uint16_t path16[PATH_MAX]; uint16_t path16[PATH_MAX];
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
if (!IsWindows()) { if (!IsWindows()) {
olderr = errno; olderr = errno;
rc = __sys_fstatat(AT_FDCWD, path, &st, 0); rc = __sys_fstatat(AT_FDCWD, path, &st, 0);

View file

@ -17,24 +17,69 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/bits/safemacros.internal.h" #include "libc/bits/safemacros.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/struct/stat.h" #include "libc/calls/struct/stat.h"
#include "libc/fmt/conv.h" #include "libc/fmt/conv.h"
#include "libc/nexgen32e/bsr.h"
#include "libc/nt/enum/fileflagandattributes.h" #include "libc/nt/enum/fileflagandattributes.h"
#include "libc/nt/enum/fileinfobyhandleclass.h" #include "libc/nt/enum/fileinfobyhandleclass.h"
#include "libc/nt/enum/filetype.h" #include "libc/nt/enum/filetype.h"
#include "libc/nt/enum/fsctl.h"
#include "libc/nt/files.h" #include "libc/nt/files.h"
#include "libc/nt/runtime.h" #include "libc/nt/runtime.h"
#include "libc/nt/struct/byhandlefileinformation.h" #include "libc/nt/struct/byhandlefileinformation.h"
#include "libc/nt/struct/filecompressioninfo.h" #include "libc/nt/struct/filecompressioninfo.h"
#include "libc/nt/struct/reparsedatabuffer.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/str/tpenc.h"
#include "libc/str/utf16.h"
#include "libc/sysv/consts/s.h" #include "libc/sysv/consts/s.h"
#include "libc/sysv/errfuns.h"
#if 0
#define DEBUG(FMT, ...) (dprintf)(2, FMT "\n", ##__VA_ARGS__)
#else
#define DEBUG(FMT, ...) (void)0
#endif
static textwindows uint32_t GetSizeOfReparsePoint(int64_t fh) {
wint_t x, y;
const char16_t *p;
uint32_t mem, i, n, z = 0;
struct NtReparseDataBuffer *rdb;
long buf[(sizeof(*rdb) + PATH_MAX * sizeof(char16_t)) / sizeof(long)];
mem = sizeof(buf);
rdb = (struct NtReparseDataBuffer *)buf;
if (DeviceIoControl(fh, kNtFsctlGetReparsePoint, 0, 0, rdb, mem, &n, 0)) {
i = 0;
n = rdb->SymbolicLinkReparseBuffer.PrintNameLength / sizeof(char16_t);
p = (char16_t *)((char *)rdb->SymbolicLinkReparseBuffer.PathBuffer +
rdb->SymbolicLinkReparseBuffer.PrintNameOffset);
while (i < n) {
x = p[i++] & 0xffff;
if (!IsUcs2(x)) {
if (i < n) {
y = p[i++] & 0xffff;
x = MergeUtf16(x, y);
} else {
x = 0xfffd;
}
}
z += x < 0200 ? 1 : bsrl(tpenc(x)) >> 3;
}
} else {
DEBUG("GetSizeOfReparsePoint failed %d", GetLastError());
}
return z;
}
textwindows int sys_fstat_nt(int64_t handle, struct stat *st) { textwindows int sys_fstat_nt(int64_t handle, struct stat *st) {
int filetype; int filetype;
uint64_t actualsize; uint64_t actualsize;
struct NtFileCompressionInfo fci; struct NtFileCompressionInfo fci;
struct NtByHandleFileInformation wst; struct NtByHandleFileInformation wst;
if (!st) return efault();
if ((filetype = GetFileType(handle))) { if ((filetype = GetFileType(handle))) {
memset(st, 0, sizeof(*st)); memset(st, 0, sizeof(*st));
switch (filetype) { switch (filetype) {
@ -52,7 +97,7 @@ textwindows int sys_fstat_nt(int64_t handle, struct stat *st) {
} }
if (wst.dwFileAttributes & kNtFileAttributeDirectory) { if (wst.dwFileAttributes & kNtFileAttributeDirectory) {
st->st_mode |= S_IFDIR; st->st_mode |= S_IFDIR;
} else if (wst.dwFileAttributes & kNtFileFlagOpenReparsePoint) { } else if (wst.dwFileAttributes & kNtFileAttributeReparsePoint) {
st->st_mode |= S_IFLNK; st->st_mode |= S_IFLNK;
} else { } else {
st->st_mode |= S_IFREG; st->st_mode |= S_IFREG;
@ -66,13 +111,19 @@ textwindows int sys_fstat_nt(int64_t handle, struct stat *st) {
st->st_rdev = wst.dwVolumeSerialNumber; st->st_rdev = wst.dwVolumeSerialNumber;
st->st_ino = (uint64_t)wst.nFileIndexHigh << 32 | wst.nFileIndexLow; st->st_ino = (uint64_t)wst.nFileIndexHigh << 32 | wst.nFileIndexLow;
st->st_nlink = wst.nNumberOfLinks; st->st_nlink = wst.nNumberOfLinks;
if (GetFileInformationByHandleEx(handle, kNtFileCompressionInfo, &fci, if (S_ISLNK(st->st_mode)) {
sizeof(fci))) { if (!st->st_size) {
actualsize = fci.CompressedFileSize; st->st_size = GetSizeOfReparsePoint(handle);
}
} else { } else {
actualsize = st->st_size; actualsize = st->st_size;
if (S_ISREG(st->st_mode) &&
GetFileInformationByHandleEx(handle, kNtFileCompressionInfo,
&fci, sizeof(fci))) {
actualsize = fci.CompressedFileSize;
}
st->st_blocks = roundup(actualsize, PAGESIZE) / 512;
} }
st->st_blocks = roundup(actualsize, PAGESIZE) / 512;
} }
break; break;
default: default:

View file

@ -29,7 +29,7 @@
* @asyncsignalsafe * @asyncsignalsafe
*/ */
int fstat(int fd, struct stat *st) { int fstat(int fd, struct stat *st) {
if (IsAsan() && (!st || !__asan_is_valid(st, sizeof(*st)))) return efault(); if (IsAsan() && !__asan_is_valid(st, sizeof(*st))) return efault();
if (__isfdkind(fd, kFdZip)) { if (__isfdkind(fd, kFdZip)) {
return weaken(__zipos_fstat)( return weaken(__zipos_fstat)(
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, st); (struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, st);

View file

@ -22,12 +22,11 @@
#include "libc/nt/enum/creationdisposition.h" #include "libc/nt/enum/creationdisposition.h"
#include "libc/nt/enum/fileflagandattributes.h" #include "libc/nt/enum/fileflagandattributes.h"
#include "libc/nt/enum/filesharemode.h" #include "libc/nt/enum/filesharemode.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h" #include "libc/nt/runtime.h"
#include "libc/runtime/runtime.h" #include "libc/sysv/consts/at.h"
textwindows int sys_fstatat_nt(int dirfd, const char *path, struct stat *st, textwindows int sys_fstatat_nt(int dirfd, const char *path, struct stat *st,
uint32_t flags) { int flags) {
int rc; int rc;
int64_t fh; int64_t fh;
uint16_t path16[PATH_MAX]; uint16_t path16[PATH_MAX];
@ -35,9 +34,12 @@ textwindows int sys_fstatat_nt(int dirfd, const char *path, struct stat *st,
if ((fh = CreateFile( if ((fh = CreateFile(
path16, kNtFileReadAttributes, path16, kNtFileReadAttributes,
kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete, NULL, kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete, NULL,
kNtOpenExisting, kNtFileAttributeNormal | kNtFileFlagBackupSemantics, kNtOpenExisting,
kNtFileAttributeNormal | kNtFileFlagBackupSemantics |
((flags & AT_SYMLINK_NOFOLLOW) ? kNtFileFlagOpenReparsePoint
: 0),
0)) != -1) { 0)) != -1) {
rc = sys_fstat_nt(fh, st); rc = st ? sys_fstat_nt(fh, st) : 0;
CloseHandle(fh); CloseHandle(fh);
return rc; return rc;
} else { } else {

View file

@ -19,8 +19,11 @@
#include "libc/bits/weaken.h" #include "libc/bits/weaken.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/intrin/asan.internal.h" #include "libc/intrin/asan.internal.h"
#include "libc/log/log.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/at.h" #include "libc/sysv/consts/at.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.internal.h" #include "libc/zipos/zipos.internal.h"
@ -36,9 +39,13 @@
* @see S_ISDIR(st.st_mode), S_ISREG() * @see S_ISDIR(st.st_mode), S_ISREG()
* @asyncsignalsafe * @asyncsignalsafe
*/ */
int fstatat(int dirfd, const char *path, struct stat *st, uint32_t flags) { int fstatat(int dirfd, const char *path, struct stat *st, int flags) {
struct ZiposUri zipname; struct ZiposUri zipname;
if (IsAsan() && (!st || !__asan_is_valid(st, sizeof(*st)))) return efault(); if (IsAsan() && (!__asan_is_valid(path, 1) ||
(st && !__asan_is_valid(st, sizeof(*st))))) {
return efault();
}
if (__isfdkind(dirfd, kFdZip)) return einval(); /* TODO(jart): implement me */
if (weaken(__zipos_stat) && weaken(__zipos_parseuri)(path, &zipname) != -1) { if (weaken(__zipos_stat) && weaken(__zipos_parseuri)(path, &zipname) != -1) {
return weaken(__zipos_stat)(&zipname, st); return weaken(__zipos_stat)(&zipname, st);
} else if (!IsWindows()) { } else if (!IsWindows()) {

View file

@ -16,32 +16,70 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/mem/mem.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
/** /**
* Returns current working directory. * Returns current working directory, e.g.
*
* const char *dirname = gc(getcwd(0,0)); // if malloc is linked
* const char *dirname = getcwd(alloca(PATH_MAX),PATH_MAX);
* *
* @param buf is where UTF-8 NUL-terminated path string gets written, * @param buf is where UTF-8 NUL-terminated path string gets written,
* which may be NULL to ask this function to malloc a buffer * which may be NULL to ask this function to malloc a buffer
* @param size is number of bytes available in buf, e.g. PATH_MAX, * @param size is number of bytes available in buf, e.g. PATH_MAX,
* which may be 0 if buf NULL * which may be 0 if buf NULL
* @return buf containing system-normative path or NULL w/ errno * @return buf containing system-normative path or NULL w/ errno
* @see get_current_dir_name() which is better * @error ERANGE, EINVAL, ENOMEM
* @error ERANGE, EINVAL
*/ */
char *(getcwd)(char *buf, size_t size) { char *getcwd(char *buf, size_t size) {
if (buf && size) buf[0] = '\0'; char *p, *r;
if (!IsWindows()) { if (buf) {
if (IsXnu()) { p = buf;
return sys_getcwd_xnu(buf, size); if (!size) {
} else if (sys_getcwd(buf, size) != (void *)-1) { einval();
return buf; return 0;
} else { }
return NULL; } else if (weaken(malloc)) {
if (!size) size = PATH_MAX + 1;
if (!(p = weaken(malloc)(size))) {
return 0;
} }
} else { } else {
return sys_getcwd_nt(buf, size); einval();
return 0;
} }
*p = '\0';
if (!IsWindows()) {
if (IsMetal()) {
r = size >= 5 ? strcpy(p, "/zip") : 0;
} else if (IsXnu()) {
r = sys_getcwd_xnu(p, size);
} else if (sys_getcwd(p, size) != (void *)-1) {
r = p;
} else {
r = 0;
}
} else {
r = sys_getcwd_nt(p, size);
}
if (!buf) {
if (!r) {
if (weaken(free)) {
weaken(free)(p);
}
} else {
if (weaken(realloc)) {
if ((p = weaken(realloc)(r, strlen(r) + 1))) {
r = p;
}
}
}
}
return r;
} }

View file

@ -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/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
/** /**
@ -28,9 +29,13 @@
* @return 0 on success or -1 w/ errno * @return 0 on success or -1 w/ errno
*/ */
int getitimer(int which, struct itimerval *curvalue) { int getitimer(int which, struct itimerval *curvalue) {
if (IsAsan() && !__asan_is_valid(curvalue, sizeof(*curvalue))) {
return efault();
}
if (!IsWindows()) { if (!IsWindows()) {
return sys_getitimer(which, curvalue); return sys_getitimer(which, curvalue);
} else { } else {
return sys_setitimer_nt(which, NULL, curvalue); if (!curvalue) return efault();
return sys_setitimer_nt(which, 0, curvalue);
} }
} }

View file

@ -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/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
/** /**
@ -30,6 +31,7 @@
* @see libc/sysv/consts.sh * @see libc/sysv/consts.sh
*/ */
int getrlimit(int resource, struct rlimit *rlim) { int getrlimit(int resource, struct rlimit *rlim) {
if (resource == -1) return einval(); if (resource == 127) return einval();
if (IsAsan() && !__asan_is_valid(rlim, sizeof(*rlim))) return efault();
return sys_getrlimit(resource, rlim); return sys_getrlimit(resource, rlim);
} }

View file

@ -18,6 +18,8 @@
*/ */
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
/** /**
@ -27,6 +29,8 @@
* @return 0 on success, or -1 w/ errno * @return 0 on success, or -1 w/ errno
*/ */
int getrusage(int who, struct rusage *usage) { int getrusage(int who, struct rusage *usage) {
if (who == 99) return einval();
if (IsAsan() && !__asan_is_valid(usage, sizeof(*usage))) return efault();
if (!IsWindows()) { if (!IsWindows()) {
return sys_getrusage(who, usage); return sys_getrusage(who, usage);
} else { } else {

View file

@ -28,7 +28,7 @@
int sys_gettimeofday_nt(struct timeval *tv, struct timezone *tz) { int sys_gettimeofday_nt(struct timeval *tv, struct timezone *tz) {
struct NtFileTime ft; struct NtFileTime ft;
GetSystemTimeAsFileTime(&ft); GetSystemTimeAsFileTime(&ft);
*tv = FileTimeToTimeVal(ft); if (tv) *tv = FileTimeToTimeVal(ft);
if (tz) memset(tz, 0, sizeof(*tz)); if (tz) memset(tz, 0, sizeof(*tz));
return 0; return 0;
} }

View file

@ -20,6 +20,7 @@
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/struct/timeval.h" #include "libc/calls/struct/timeval.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
#include "libc/time/struct/timezone.h" #include "libc/time/struct/timezone.h"
#include "libc/time/time.h" #include "libc/time/time.h"
@ -35,6 +36,10 @@
*/ */
int gettimeofday(struct timeval *tv, struct timezone *tz) { int gettimeofday(struct timeval *tv, struct timezone *tz) {
axdx_t ad; axdx_t ad;
if (IsAsan() && ((tv && !__asan_is_valid(tv, sizeof(*tv))) ||
(tz && !__asan_is_valid(tz, sizeof(*tz))))) {
return efault();
}
if (!IsWindows() && !IsMetal()) { if (!IsWindows() && !IsMetal()) {
ad = sys_gettimeofday(tv, tz, NULL); ad = sys_gettimeofday(tv, tz, NULL);
assert(ad.ax != -1); assert(ad.ax != -1);

View file

@ -117,7 +117,6 @@ i32 __sys_openat(i32, const char *, i32, u32) hidden;
i32 __sys_pipe2(i32[hasatleast 2], u32) hidden; i32 __sys_pipe2(i32[hasatleast 2], u32) hidden;
i32 __sys_utimensat(i32, const char *, const struct timespec *, i32) hidden; i32 __sys_utimensat(i32, const char *, const struct timespec *, i32) hidden;
i32 __sys_wait4(i32, i32 *, i32, struct rusage *) hidden; i32 __sys_wait4(i32, i32 *, i32, struct rusage *) hidden;
i32 getdents(i32, void *, u32, i64 *) hidden;
i32 sys_chdir(const char *) hidden; i32 sys_chdir(const char *) hidden;
i32 sys_clock_gettime(i32, struct timespec *) hidden; i32 sys_clock_gettime(i32, struct timespec *) hidden;
i32 sys_close(i32) hidden; i32 sys_close(i32) hidden;
@ -232,6 +231,7 @@ int gethostname_bsd(char *, size_t) hidden;
int gethostname_nt(char *, size_t) hidden; int gethostname_nt(char *, size_t) hidden;
size_t __iovec_size(const struct iovec *, size_t) hidden; size_t __iovec_size(const struct iovec *, size_t) hidden;
void __rusage2linux(struct rusage *) hidden; void __rusage2linux(struct rusage *) hidden;
int __notziposat(int, const char *);
ssize_t WritevUninterruptible(int, struct iovec *, int); ssize_t WritevUninterruptible(int, struct iovec *, int);
void flock2cosmo(uintptr_t); void flock2cosmo(uintptr_t);
void cosmo2flock(uintptr_t); void cosmo2flock(uintptr_t);
@ -264,14 +264,14 @@ int sys_fdatasync_nt(int) hidden;
int sys_flock_nt(int, int) hidden; int sys_flock_nt(int, int) hidden;
int sys_fork_nt(void) hidden; int sys_fork_nt(void) hidden;
int sys_fstat_nt(i64, struct stat *) hidden; int sys_fstat_nt(i64, struct stat *) hidden;
int sys_fstatat_nt(int, const char *, struct stat *, uint32_t) hidden; int sys_fstatat_nt(int, const char *, struct stat *, int) hidden;
int sys_ftruncate_nt(i64, u64) hidden; int sys_ftruncate_nt(i64, u64) hidden;
int sys_getppid_nt(void) hidden; int sys_getppid_nt(void) hidden;
int sys_getpriority_nt(int) hidden; int sys_getpriority_nt(int) hidden;
int sys_getrusage_nt(int, struct rusage *) hidden; int sys_getrusage_nt(int, struct rusage *) hidden;
int sys_gettimeofday_nt(struct timeval *, struct timezone *) hidden; int sys_gettimeofday_nt(struct timeval *, struct timezone *) hidden;
int sys_kill_nt(int, int) hidden; int sys_kill_nt(int, int) hidden;
int sys_link_nt(const char *, const char *) hidden; int sys_linkat_nt(int, const char *, int, const char *) hidden;
int sys_lstat_nt(const char *, struct stat *) hidden; int sys_lstat_nt(const char *, struct stat *) hidden;
int sys_madvise_nt(void *, size_t, int) hidden; int sys_madvise_nt(void *, size_t, int) hidden;
int sys_mkdirat_nt(int, const char *, uint32_t) hidden; int sys_mkdirat_nt(int, const char *, uint32_t) hidden;
@ -287,12 +287,12 @@ int sys_sync_nt(void) hidden;
int sys_sysinfo_nt(struct sysinfo *) hidden; int sys_sysinfo_nt(struct sysinfo *) hidden;
int sys_truncate_nt(const char *, u64) hidden; int sys_truncate_nt(const char *, u64) hidden;
int sys_unlinkat_nt(int, const char *, int) hidden; int sys_unlinkat_nt(int, const char *, int) hidden;
int sys_utimes_nt(const char *, const struct timeval[2]) hidden;
int sys_utimensat_nt(int, const char *, const struct timespec *, int) hidden; int sys_utimensat_nt(int, const char *, const struct timespec *, int) hidden;
int sys_utimes_nt(const char *, const struct timeval[2]) hidden;
ssize_t sys_open_nt(int, const char *, u32, i32) nodiscard hidden; ssize_t sys_open_nt(int, const char *, u32, i32) nodiscard hidden;
ssize_t sys_read_nt(struct Fd *, const struct iovec *, size_t, ssize_t) hidden; ssize_t sys_read_nt(struct Fd *, const struct iovec *, size_t, ssize_t) hidden;
ssize_t sys_write_nt(struct Fd *, const struct iovec *, size_t, ssize_t) hidden;
ssize_t sys_readlinkat_nt(int, const char *, char *, size_t) hidden; ssize_t sys_readlinkat_nt(int, const char *, char *, size_t) hidden;
ssize_t sys_write_nt(struct Fd *, const struct iovec *, size_t, ssize_t) hidden;
/*───────────────────────────────────────────────────────────────────────────│─╗ /*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § syscalls » windows nt » support cosmopolitan § syscalls » windows nt » support

View file

@ -13,10 +13,10 @@ COSMOPOLITAN_C_START_
int ioctl(int, uint64_t, ...); int ioctl(int, uint64_t, ...);
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § system calls » ioctl » undiamonding (size optimization)
*/
#if defined(__GNUC__) && !defined(__STRICT_ANSI__) #if defined(__GNUC__) && !defined(__STRICT_ANSI__)
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § system calls » ioctl » undiamonding
*/
#define ioctl(FD, REQUEST, ...) \ #define ioctl(FD, REQUEST, ...) \
__IOCTL_DISPATCH(__EQUIVALENT, ioctl_default(FD, REQUEST, ##__VA_ARGS__), \ __IOCTL_DISPATCH(__EQUIVALENT, ioctl_default(FD, REQUEST, ##__VA_ARGS__), \
@ -63,22 +63,18 @@ int ioctl(int, uint64_t, ...);
ReZ; \ ReZ; \
}) })
int ioctl_tcgets(int, void *); int ioctl_default(int, uint64_t, ...);
int ioctl_tcgets_nt(int, void *);
int ioctl_tcsets(int, uint64_t, void *);
int ioctl_tcsets_nt(int, uint64_t, void *);
int ioctl_tiocgwinsz(int, void *);
int ioctl_tiocgwinsz_nt(int, void *);
int ioctl_tiocswinsz(int, void *);
int ioctl_tiocswinsz_nt(int, void *);
int ioctl_siocgifconf(int, void *);
int ioctl_siocgifaddr(int, void *);
int ioctl_siocgifdstaddr(int, void *);
int ioctl_siocgifnetmask(int, void *);
int ioctl_siocgifbrdaddr(int, void *);
int ioctl_siocgifflags(int, void *);
int ioctl_default(int, uint64_t, void *);
int ioctl_fioclex(int, int); int ioctl_fioclex(int, int);
int ioctl_siocgifaddr(int, ...);
int ioctl_siocgifbrdaddr(int, ...);
int ioctl_siocgifconf(int, ...);
int ioctl_siocgifdstaddr(int, ...);
int ioctl_siocgifflags(int, ...);
int ioctl_siocgifnetmask(int, ...);
int ioctl_tcgets(int, ...);
int ioctl_tcsets(int, uint64_t, ...);
int ioctl_tiocgwinsz(int, ...);
int ioctl_tiocswinsz(int, ...);
#endif /* GNUC && !ANSI */ #endif /* GNUC && !ANSI */
COSMOPOLITAN_C_END_ COSMOPOLITAN_C_END_

View file

@ -23,15 +23,20 @@
#include "libc/sock/internal.h" #include "libc/sock/internal.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
int ioctl_default(int fd, uint64_t request, void *memory) { int ioctl_default(int fd, uint64_t request, ...) {
int rc; int rc;
void *arg;
va_list va;
int64_t handle; int64_t handle;
va_start(va, request);
arg = va_arg(va, void *);
va_end(va);
if (!IsWindows()) { if (!IsWindows()) {
return sys_ioctl(fd, request, memory); return sys_ioctl(fd, request, arg);
} else if (__isfdopen(fd)) { } else if (__isfdopen(fd)) {
if (g_fds.p[fd].kind == kFdSocket) { if (g_fds.p[fd].kind == kFdSocket) {
handle = g_fds.p[fd].handle; handle = g_fds.p[fd].handle;
if ((rc = weaken(__sys_ioctlsocket_nt)(handle, request, memory)) != -1) { if ((rc = weaken(__sys_ioctlsocket_nt)(handle, request, arg)) != -1) {
return rc; return rc;
} else { } else {
return weaken(__winsockerr)(); return weaken(__winsockerr)();

View file

@ -19,8 +19,8 @@
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/ioctl.h" #include "libc/calls/ioctl.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/sysv/consts/o.h"
int ioctl_fioclex_nt(int, int); #include "libc/sysv/errfuns.h"
/** /**
* Sets "close on exec" on file descriptor the fast way. * Sets "close on exec" on file descriptor the fast way.
@ -28,9 +28,22 @@ int ioctl_fioclex_nt(int, int);
* @see ioctl(fd, FIOCLEX, 0) dispatches here * @see ioctl(fd, FIOCLEX, 0) dispatches here
*/ */
int ioctl_fioclex(int fd, int req) { int ioctl_fioclex(int fd, int req) {
if (!IsWindows()) { if (fd >= 0) {
return sys_ioctl(fd, req, 0); if (IsWindows() || (fd < g_fds.n && g_fds.p[fd].kind == kFdZip)) {
if (__isfdopen(fd)) {
if (req == FIOCLEX) {
g_fds.p[fd].flags |= O_CLOEXEC;
} else {
g_fds.p[fd].flags &= ~O_CLOEXEC;
}
return 0;
} else {
return ebadf();
}
} else {
return sys_ioctl(fd, req);
}
} else { } else {
return ioctl_fioclex_nt(fd, req); return einval();
} }
} }

View file

@ -19,6 +19,7 @@
#include "libc/assert.h" #include "libc/assert.h"
#include "libc/bits/weaken.h" #include "libc/bits/weaken.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/ioctl.h"
#include "libc/sock/internal.h" #include "libc/sock/internal.h"
#include "libc/sock/sock.h" #include "libc/sock/sock.h"
#include "libc/str/str.h" #include "libc/str/str.h"
@ -35,7 +36,6 @@
* The ifc_len is an input/output parameter: set it to the total size of * The ifc_len is an input/output parameter: set it to the total size of
* the ifcu_buf (ifcu_req) buffer on input. * the ifcu_buf (ifcu_req) buffer on input.
*/ */
int ioctl_default(int, uint64_t, void *) hidden;
int ioctl_siocgifconf_nt(int, struct ifconf *) hidden; int ioctl_siocgifconf_nt(int, struct ifconf *) hidden;
int ioctl_siocgifaddr_nt(int, struct ifreq *) hidden; int ioctl_siocgifaddr_nt(int, struct ifreq *) hidden;
int ioctl_siocgifflags_nt(int, struct ifreq *) hidden; int ioctl_siocgifflags_nt(int, struct ifreq *) hidden;
@ -103,41 +103,66 @@ static int ioctl_siocgifaddr_sysv(int fd, uint64_t op, struct ifreq *ifr) {
* *
* @see ioctl(fd, SIOCGIFCONF, tio) dispatches here * @see ioctl(fd, SIOCGIFCONF, tio) dispatches here
*/ */
int ioctl_siocgifconf(int fd, void *ifc) { int ioctl_siocgifconf(int fd, ...) {
va_list va;
struct ifconf *ifc;
va_start(va, fd);
ifc = va_arg(va, struct ifconf *);
va_end(va);
if (!IsWindows()) { if (!IsWindows()) {
return ioctl_siocgifconf_sysv(fd, (struct ifconf *)ifc); return ioctl_siocgifconf_sysv(fd, ifc);
} else { } else {
return ioctl_siocgifconf_nt(fd, ifc); return ioctl_siocgifconf_nt(fd, ifc);
} }
} }
int ioctl_siocgifaddr(int fd, void *ifr) { int ioctl_siocgifaddr(int fd, ...) {
va_list va;
struct ifreq *ifr;
va_start(va, fd);
ifr = va_arg(va, struct ifreq *);
va_end(va);
if (!IsWindows()) { if (!IsWindows()) {
return ioctl_siocgifaddr_sysv(fd, SIOCGIFADDR, (struct ifreq *)ifr); return ioctl_siocgifaddr_sysv(fd, SIOCGIFADDR, ifr);
} else { } else {
return ioctl_siocgifaddr_nt(fd, (struct ifreq *)ifr); return ioctl_siocgifaddr_nt(fd, ifr);
} }
} }
int ioctl_siocgifnetmask(int fd, void *ifr) { int ioctl_siocgifnetmask(int fd, ...) {
va_list va;
struct ifreq *ifr;
va_start(va, fd);
ifr = va_arg(va, struct ifreq *);
va_end(va);
if (!IsWindows()) { if (!IsWindows()) {
return ioctl_siocgifaddr_sysv(fd, SIOCGIFNETMASK, (struct ifreq *)ifr); return ioctl_siocgifaddr_sysv(fd, SIOCGIFNETMASK, ifr);
} else { } else {
return ioctl_siocgifnetmask_nt(fd, (struct ifreq *)ifr); return ioctl_siocgifnetmask_nt(fd, ifr);
} }
} }
int ioctl_siocgifbrdaddr(int fd, void *ifr) { int ioctl_siocgifbrdaddr(int fd, ...) {
va_list va;
struct ifreq *ifr;
va_start(va, fd);
ifr = va_arg(va, struct ifreq *);
va_end(va);
if (!IsWindows()) { if (!IsWindows()) {
return ioctl_siocgifaddr_sysv(fd, SIOCGIFBRDADDR, (struct ifreq *)ifr); return ioctl_siocgifaddr_sysv(fd, SIOCGIFBRDADDR, ifr);
} else { } else {
return ioctl_siocgifbrdaddr_nt(fd, (struct ifreq *)ifr); return ioctl_siocgifbrdaddr_nt(fd, ifr);
} }
} }
int ioctl_siocgifdstaddr(int fd, void *ifr) { int ioctl_siocgifdstaddr(int fd, ...) {
va_list va;
struct ifreq *ifr;
va_start(va, fd);
ifr = va_arg(va, struct ifreq *);
va_end(va);
if (!IsWindows()) { if (!IsWindows()) {
return ioctl_siocgifaddr_sysv(fd, SIOCGIFDSTADDR, (struct ifreq *)ifr); return ioctl_siocgifaddr_sysv(fd, SIOCGIFDSTADDR, ifr);
} else { } else {
return enotsup(); return enotsup();
/* Not supported - Unknown how to find out how to retrieve the destination /* Not supported - Unknown how to find out how to retrieve the destination
@ -149,11 +174,16 @@ int ioctl_siocgifdstaddr(int fd, void *ifr) {
} }
} }
int ioctl_siocgifflags(int fd, void *ifr) { int ioctl_siocgifflags(int fd, ...) {
va_list va;
struct ifreq *ifr;
va_start(va, fd);
ifr = va_arg(va, struct ifreq *);
va_end(va);
if (!IsWindows()) { if (!IsWindows()) {
/* Both XNU and Linux are for once compatible here... */ /* Both XNU and Linux are for once compatible here... */
return ioctl_default(fd, SIOCGIFFLAGS, ifr); return ioctl_default(fd, SIOCGIFFLAGS, ifr);
} else { } else {
return ioctl_siocgifflags_nt(fd, (struct ifreq *)ifr); return ioctl_siocgifflags_nt(fd, ifr);
} }
} }

View file

@ -17,9 +17,13 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/ioctl.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/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/consts/termios.h" #include "libc/sysv/consts/termios.h"
#include "libc/sysv/errfuns.h"
int ioctl_tcgets_nt(int, struct termios *) hidden; int ioctl_tcgets_nt(int, struct termios *) hidden;
@ -39,10 +43,23 @@ static int ioctl_tcgets_sysv(int fd, struct termios *tio) {
* @see ioctl(fd, TCGETS, tio) dispatches here * @see ioctl(fd, TCGETS, tio) dispatches here
* @see ioctl(fd, TIOCGETA, tio) dispatches here * @see ioctl(fd, TIOCGETA, tio) dispatches here
*/ */
int ioctl_tcgets(int fd, struct termios *tio) { int ioctl_tcgets(int fd, ...) {
if (!IsWindows()) { va_list va;
return ioctl_tcgets_sysv(fd, tio); struct termios *tio;
va_start(va, fd);
tio = va_arg(va, struct termios *);
va_end(va);
if (fd >= 0) {
if (!tio) return efault();
if (IsAsan() && !__asan_is_valid(tio, sizeof(*tio))) return efault();
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
return enotty();
} else if (!IsWindows()) {
return ioctl_tcgets_sysv(fd, tio);
} else {
return ioctl_tcgets_nt(fd, tio);
}
} else { } else {
return ioctl_tcgets_nt(fd, tio); return einval();
} }
} }

View file

@ -17,9 +17,11 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/ioctl.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/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/consts/termios.h" #include "libc/sysv/consts/termios.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
@ -38,11 +40,23 @@ static int ioctl_tcsets_sysv(int fd, uint64_t request,
* @see ioctl(fd, TCSETS{,W,F}, tio) dispatches here * @see ioctl(fd, TCSETS{,W,F}, tio) dispatches here
* @see ioctl(fd, TIOCGETA{,W,F}, tio) dispatches here * @see ioctl(fd, TIOCGETA{,W,F}, tio) dispatches here
*/ */
int ioctl_tcsets(int fd, uint64_t request, const struct termios *tio) { int ioctl_tcsets(int fd, uint64_t request, ...) {
va_list va;
const struct termios *tio;
va_start(va, request);
tio = va_arg(va, const struct termios *);
va_end(va);
if (!tio) return efault(); if (!tio) return efault();
if (!IsWindows()) { if (IsAsan() && !__asan_is_valid(tio, sizeof(*tio))) return efault();
return ioctl_tcsets_sysv(fd, request, tio); if (fd >= 0) {
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
return enotty();
} else if (!IsWindows()) {
return ioctl_tcsets_sysv(fd, request, tio);
} else {
return ioctl_tcsets_nt(fd, request, tio);
}
} else { } else {
return ioctl_tcsets_nt(fd, request, tio); return einval();
} }
} }

View file

@ -32,6 +32,7 @@ textwindows int ioctl_tiocgwinsz_nt(int fd, struct winsize *ws) {
uint32_t mode; uint32_t mode;
struct NtStartupInfo startinfo; struct NtStartupInfo startinfo;
struct NtConsoleScreenBufferInfoEx sbinfo; struct NtConsoleScreenBufferInfoEx sbinfo;
if (!ws) return efault();
fds[0] = fd, fds[1] = 1, fds[2] = 0; fds[0] = fd, fds[1] = 1, fds[2] = 0;
GetStartupInfo(&startinfo); GetStartupInfo(&startinfo);
for (i = 0; i < ARRAYLEN(fds); ++i) { for (i = 0; i < ARRAYLEN(fds); ++i) {

View file

@ -17,9 +17,12 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/struct/winsize.h" #include "libc/calls/struct/winsize.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/consts/termios.h" #include "libc/sysv/consts/termios.h"
#include "libc/sysv/errfuns.h"
int ioctl_tiocgwinsz_nt(int, struct winsize *); int ioctl_tiocgwinsz_nt(int, struct winsize *);
@ -28,10 +31,22 @@ int ioctl_tiocgwinsz_nt(int, struct winsize *);
* *
* @see ioctl(fd, TIOCGWINSZ, ws) dispatches here * @see ioctl(fd, TIOCGWINSZ, ws) dispatches here
*/ */
int ioctl_tiocgwinsz(int fd, struct winsize *ws) { int ioctl_tiocgwinsz(int fd, ...) {
if (!IsWindows()) { va_list va;
return sys_ioctl(fd, TIOCGWINSZ, ws); struct winsize *ws;
va_start(va, fd);
ws = va_arg(va, struct winsize *);
va_end(va);
if (IsAsan() && !__asan_is_valid(ws, sizeof(*ws))) return efault();
if (fd >= 0) {
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
return enotty();
} else if (!IsWindows()) {
return sys_ioctl(fd, TIOCGWINSZ, ws);
} else {
return ioctl_tiocgwinsz_nt(fd, ws);
}
} else { } else {
return ioctl_tiocgwinsz_nt(fd, ws); return einval();
} }
} }

View file

@ -17,21 +17,36 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/struct/winsize.h" #include "libc/calls/struct/winsize.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/consts/termios.h" #include "libc/sysv/consts/termios.h"
#include "libc/sysv/errfuns.h"
int ioctl_tiocswinsz_nt(int, const struct winsize *); int ioctl_tiocswinsz_nt(int, const struct winsize *);
/** /**
* Returns width and height of terminal. * Sets width and height of terminal.
* *
* @see ioctl(fd, TIOCSWINSZ, ws) dispatches here * @see ioctl(fd, TIOCSWINSZ, ws) dispatches here
*/ */
int ioctl_tiocswinsz(int fd, const struct winsize *ws) { int ioctl_tiocswinsz(int fd, ...) {
if (!IsWindows()) { va_list va;
return sys_ioctl(fd, TIOCSWINSZ, ws); const struct winsize *ws;
va_start(va, fd);
ws = va_arg(va, const struct winsize *);
va_end(va);
if (IsAsan() && !__asan_is_valid(ws, sizeof(*ws))) return efault();
if (fd >= 0) {
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
return enotty();
} else if (!IsWindows()) {
return sys_ioctl(fd, TIOCSWINSZ, ws);
} else {
return ioctl_tiocswinsz_nt(fd, ws);
}
} else { } else {
return ioctl_tiocswinsz_nt(fd, ws); return einval();
} }
} }

View file

@ -22,6 +22,7 @@
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
textwindows bool32 sys_isatty_nt(int fd) { textwindows bool32 sys_isatty_nt(int fd) {
if (!__isfdkind(fd, kFdFile)) return ebadf(); return __isfdkind(fd, kFdConsole) ||
return GetFileType(g_fds.p[fd].handle) == kNtFileTypeChar; (__isfdkind(fd, kFdFile) &&
GetFileType(g_fds.p[fd].handle) == kNtFileTypeChar);
} }

View file

@ -18,18 +18,30 @@
*/ */
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/struct/winsize.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/errno.h"
#include "libc/sysv/consts/termios.h" #include "libc/sysv/consts/termios.h"
/** /**
* Returns true if file descriptor is backed by a terminal device. * Returns true if file descriptor is backed by a terminal device.
* @asyncsignalsafe
*/ */
bool32 isatty(int fd) { bool32 isatty(int fd) {
_Alignas(short) char buf[sizeof(uint16_t) * 4]; int err;
if (!IsWindows()) { bool32 res;
return sys_ioctl(fd, TIOCGWINSZ, &buf) != -1; struct winsize ws;
if (fd >= 0) {
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
return false;
} else if (!IsWindows()) {
err = errno;
res = sys_ioctl(fd, TIOCGWINSZ, &ws) != -1;
errno = err;
return res;
} else {
return sys_isatty_nt(fd);
}
} else { } else {
return sys_isatty_nt(fd); return false;
} }
} }

View file

@ -21,8 +21,10 @@
#include "libc/calls/struct/stat.h" #include "libc/calls/struct/stat.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/intrin/asan.internal.h"
#include "libc/nt/files.h" #include "libc/nt/files.h"
#include "libc/sysv/consts/at.h" #include "libc/sysv/consts/at.h"
#include "libc/sysv/errfuns.h"
/** /**
* Returns true if file exists and is a directory. * Returns true if file exists and is a directory.
@ -30,6 +32,7 @@
bool isdirectory(const char *path) { bool isdirectory(const char *path) {
struct stat st; struct stat st;
int rc, olderr; int rc, olderr;
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
if (!IsWindows()) { if (!IsWindows()) {
olderr = errno; olderr = errno;
rc = sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW); rc = sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW);

View file

@ -21,7 +21,9 @@
#include "libc/calls/struct/stat.h" #include "libc/calls/struct/stat.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/consts/at.h" #include "libc/sysv/consts/at.h"
#include "libc/sysv/errfuns.h"
/** /**
* Returns true if file exists and is a regular file. * Returns true if file exists and is a regular file.
@ -29,6 +31,7 @@
bool isregularfile(const char *path) { bool isregularfile(const char *path) {
struct stat st; struct stat st;
int rc, olderr; int rc, olderr;
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
if (!IsWindows()) { if (!IsWindows()) {
olderr = errno; olderr = errno;
rc = sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW); rc = sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW);

View file

@ -21,8 +21,10 @@
#include "libc/calls/struct/stat.h" #include "libc/calls/struct/stat.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/intrin/asan.internal.h"
#include "libc/nt/files.h" #include "libc/nt/files.h"
#include "libc/sysv/consts/at.h" #include "libc/sysv/consts/at.h"
#include "libc/sysv/errfuns.h"
/** /**
* Returns true if file exists and is a symbolic link. * Returns true if file exists and is a symbolic link.
@ -30,6 +32,7 @@
bool issymlink(const char *path) { bool issymlink(const char *path) {
struct stat st; struct stat st;
int rc, olderr; int rc, olderr;
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
if (!IsWindows()) { if (!IsWindows()) {
olderr = errno; olderr = errno;
rc = sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW); rc = sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW);

View file

@ -31,5 +31,5 @@
* @see /etc/group for group ids * @see /etc/group for group ids
*/ */
int lchown(const char *pathname, uint32_t uid, uint32_t gid) { int lchown(const char *pathname, uint32_t uid, uint32_t gid) {
return sys_fchownat(AT_FDCWD, pathname, uid, gid, AT_SYMLINK_NOFOLLOW); return fchownat(AT_FDCWD, pathname, uid, gid, AT_SYMLINK_NOFOLLOW);
} }

View file

@ -32,9 +32,5 @@
* @asyncsignalsafe * @asyncsignalsafe
*/ */
int link(const char *existingpath, const char *newpath) { int link(const char *existingpath, const char *newpath) {
if (!IsWindows()) { return linkat(AT_FDCWD, existingpath, AT_FDCWD, newpath, 0);
return sys_linkat(AT_FDCWD, existingpath, AT_FDCWD, newpath, 0);
} else {
return sys_link_nt(existingpath, newpath);
}
} }

View file

@ -21,12 +21,13 @@
#include "libc/nt/files.h" #include "libc/nt/files.h"
#include "libc/nt/runtime.h" #include "libc/nt/runtime.h"
textwindows int sys_link_nt(const char *existingpath, const char *newpath) { textwindows int sys_linkat_nt(int olddirfd, const char *oldpath, int newdirfd,
const char *newpath) {
char16_t newpath16[PATH_MAX]; char16_t newpath16[PATH_MAX];
char16_t existingpath16[PATH_MAX]; char16_t oldpath16[PATH_MAX];
if (__mkntpath(existingpath, existingpath16) != -1 && if (__mkntpathat(olddirfd, oldpath, 0, oldpath16) != -1 &&
__mkntpath(newpath, newpath16) != -1) { __mkntpathat(newdirfd, newpath, 0, newpath16) != -1) {
if (CreateHardLink(newpath16, existingpath16, NULL)) { if (CreateHardLink(newpath16, oldpath16, NULL)) {
return 0; return 0;
} else { } else {
return __winerr(); return __winerr();

53
libc/calls/linkat.c Normal file
View file

@ -0,0 +1,53 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.internal.h"
/**
* Creates hard filesystem link.
*
* This allows two names to point to the same file data on disk. They
* can only be differentiated by examining the inode number.
*
* @param flags can have AT_EMPTY_PATH or AT_SYMLINK_NOFOLLOW
* @return 0 on success, or -1 w/ errno
* @asyncsignalsafe
*/
int linkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath,
int flags) {
if (IsAsan() &&
(!__asan_is_valid(oldpath, 1) || !__asan_is_valid(newpath, 1))) {
return efault();
}
if (weaken(__zipos_notat) &&
(weaken(__zipos_notat)(olddirfd, oldpath) == -1 ||
weaken(__zipos_notat)(newdirfd, newpath) == -1)) {
return -1; /* TODO(jart): implement me */
}
if (!IsWindows()) {
return sys_linkat(olddirfd, oldpath, newdirfd, newpath, flags);
} else {
return sys_linkat_nt(olddirfd, oldpath, newdirfd, newpath);
}
}

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/dce.h"
#include "libc/sysv/consts/at.h" #include "libc/sysv/consts/at.h"
#include "libc/time/time.h" #include "libc/time/time.h"

View file

@ -19,6 +19,8 @@
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h"
/** /**
* Drops hints to O/S about intended access patterns of mmap()'d memory. * Drops hints to O/S about intended access patterns of mmap()'d memory.
@ -29,6 +31,7 @@
* @see fadvise() * @see fadvise()
*/ */
int madvise(void *addr, size_t length, int advice) { int madvise(void *addr, size_t length, int advice) {
if (IsAsan() && !__asan_is_valid(addr, length)) return efault();
if (!IsWindows()) { if (!IsWindows()) {
return sys_madvise(addr, length, advice); return sys_madvise(addr, length, advice);
} else { } else {

34
libc/calls/major.c Normal file
View file

@ -0,0 +1,34 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/makedev.h"
#include "libc/dce.h"
uint32_t(major)(uint64_t x) {
if (IsXnu()) {
return (x >> 24) & 0xff;
} else if (IsNetbsd()) {
return (x & 0x000fff00) >> 8;
} else if (IsOpenbsd()) {
return (x >> 8) & 0xff;
} else if (IsFreebsd()) {
return ((x >> 32) & 0xffffff00) | ((x >> 8) & 0x000000ff);
} else {
return ((x >> 32) & 0xfffff000) | ((x >> 8) & 0x00000fff);
}
}

37
libc/calls/makedev.c Normal file
View file

@ -0,0 +1,37 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/makedev.h"
#include "libc/dce.h"
uint64_t(makedev)(uint32_t x, uint32_t y) {
if (IsXnu()) {
return x << 24 | y;
} else if (IsNetbsd()) {
return ((x << 8) & 0x000fff00) | ((y << 12) & 0xfff00000) |
(y & 0x000000ff);
} else if (IsOpenbsd()) {
return (x & 0xff) << 8 | (y & 0xff) | (y & 0xffff00) << 8;
} else if (IsFreebsd()) {
return (uint64_t)(x & 0xffffff00) << 32 | (x & 0x000000ff) << 8 |
(y & 0x0000ff00) << 24 | (y & 0xffff00ff);
} else {
return (uint64_t)(x & 0xfffff000) << 32 | (x & 0x00000fff) << 8 |
(y & 0xffffff00) << 12 | (y & 0x000000ff);
}
}

View file

@ -1,52 +1,10 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_MAKEDEV_H_ #ifndef COSMOPOLITAN_LIBC_CALLS_MAKEDEV_H_
#define COSMOPOLITAN_LIBC_CALLS_MAKEDEV_H_ #define COSMOPOLITAN_LIBC_CALLS_MAKEDEV_H_
#include "libc/dce.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0) #if !(__ASSEMBLER__ + __LINKER__ + 0)
static inline uint64_t major(uint64_t x) { uint64_t makedev(uint32_t, uint32_t);
if (IsXnu()) { uint32_t major(uint64_t);
return (x >> 24) & 0xff; uint32_t minor(uint64_t);
} else if (IsNetbsd()) {
return (x & 0x000fff00) >> 8;
} else if (IsOpenbsd()) {
return (x >> 8) & 0xff;
} else if (IsFreebsd()) {
return ((x >> 32) & 0xffffff00) | ((x >> 8) & 0x000000ff);
} else {
return ((x >> 32) & 0xfffff000) | ((x >> 8) & 0x00000fff);
}
}
static inline uint64_t minor(uint64_t x) {
if (IsXnu()) {
return x & 0x00ffffff;
} else if (IsNetbsd()) {
return (x & 0x000000ff) | (x & 0xfff00000) >> 12;
} else if (IsOpenbsd()) {
return (x & 0x000000ff) | (x & 0x0ffff000) >> 8;
} else if (IsFreebsd()) {
return ((x >> 24) & 0x0000ff00) | (x & 0xffff00ff);
} else {
return ((x >> 12) & 0xffffff00) | (x & 0x000000ff);
}
}
static inline uint64_t makedev(uint64_t x, uint64_t y) {
if (IsXnu()) {
return x << 24 | y;
} else if (IsNetbsd()) {
return ((x << 8) & 0x000fff00) | ((y << 12) & 0xfff00000u) |
(y & 0x000000ff);
} else if (IsOpenbsd()) {
return (x & 0xff) << 8 | (y & 0xff) | (y & 0xffff00) << 8;
} else if (IsFreebsd()) {
return (x & 0xffffff00) << 32 | (x & 0x000000ff) << 8 |
(y & 0x0000ff00) << 24 | (y & 0xffff00ff);
} else {
return (x & 0xfffff000) << 32 | (x & 0x00000fff) << 8 |
(y & 0xffffff00) << 12 | (y & 0x000000ff);
}
}
#define major(x) major(x) #define major(x) major(x)
#define minor(x) minor(x) #define minor(x) minor(x)

34
libc/calls/minor.c Normal file
View file

@ -0,0 +1,34 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/makedev.h"
#include "libc/dce.h"
uint32_t(minor)(uint64_t x) {
if (IsXnu()) {
return x & 0x00ffffff;
} else if (IsNetbsd()) {
return (x & 0x000000ff) | (x & 0xfff00000) >> 12;
} else if (IsOpenbsd()) {
return (x & 0x000000ff) | (x & 0x0ffff000) >> 8;
} else if (IsFreebsd()) {
return ((x >> 24) & 0x0000ff00) | (x & 0xffff00ff);
} else {
return ((x >> 12) & 0xffffff00) | (x & 0x000000ff);
}
}

View file

@ -16,10 +16,14 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/consts/at.h" #include "libc/sysv/consts/at.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.internal.h"
/** /**
* Creates directory a.k.a. folder. * Creates directory a.k.a. folder.
@ -34,6 +38,10 @@
* @see makedirs() * @see makedirs()
*/ */
int mkdirat(int dirfd, const char *path, unsigned mode) { int mkdirat(int dirfd, const char *path, unsigned mode) {
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
if (weaken(__zipos_notat) && weaken(__zipos_notat)(dirfd, path) == -1) {
return -1; /* TODO(jart): implement me */
}
if (!IsWindows()) { if (!IsWindows()) {
return sys_mkdirat(dirfd, path, mode); return sys_mkdirat(dirfd, path, mode);
} else { } else {

View file

@ -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/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/nt/ipc.h" #include "libc/nt/ipc.h"
#include "libc/sysv/consts/s.h" #include "libc/sysv/consts/s.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
@ -33,6 +34,7 @@
*/ */
int mkfifo(const char *pathname, unsigned mode) { int mkfifo(const char *pathname, unsigned mode) {
/* TODO(jart): Windows? */ /* TODO(jart): Windows? */
if (IsAsan() && !__asan_is_valid(pathname, 1)) return efault();
if (IsLinux()) { if (IsLinux()) {
return sys_mknod(pathname, mode | S_IFIFO, 0); return sys_mknod(pathname, mode | S_IFIFO, 0);
} else { } else {

View file

@ -16,11 +16,12 @@
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/dce.h"
#include "libc/calls/internal.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/sysv/errfuns.h" #include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/consts/s.h" #include "libc/sysv/consts/s.h"
#include "libc/sysv/errfuns.h"
/** /**
* Creates filesystem inode. * Creates filesystem inode.
@ -37,6 +38,7 @@
* @asyncsignalsafe * @asyncsignalsafe
*/ */
int mknod(const char *path, uint32_t mode, uint64_t dev) { int mknod(const char *path, uint32_t mode, uint64_t dev) {
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
if (mode & S_IFREG) return creat(path, mode & ~S_IFREG); if (mode & S_IFREG) return creat(path, mode & ~S_IFREG);
if (mode & S_IFDIR) return mkdir(path, mode & ~S_IFDIR); if (mode & S_IFDIR) return mkdir(path, mode & ~S_IFDIR);
if (mode & S_IFIFO) return mkfifo(path, mode & ~S_IFIFO); if (mode & S_IFIFO) return mkfifo(path, mode & ~S_IFIFO);

View file

@ -16,8 +16,10 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/mem/mem.h"
#include "libc/nt/enum/accessmask.h" #include "libc/nt/enum/accessmask.h"
#include "libc/nt/enum/securityimpersonationlevel.h" #include "libc/nt/enum/securityimpersonationlevel.h"
#include "libc/nt/enum/securityinformation.h" #include "libc/nt/enum/securityinformation.h"
@ -30,6 +32,13 @@
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/sysv/consts/ok.h" #include "libc/sysv/consts/ok.h"
#include "libc/sysv/errfuns.h"
#if 0
#define DEBUG(FMT, ...) (dprintf)(2, FMT "\n", ##__VA_ARGS__)
#else
#define DEBUG(FMT, ...) (void)0
#endif
/** /**
* Asks Microsoft if we're authorized to use a folder or file. * Asks Microsoft if we're authorized to use a folder or file.
@ -44,19 +53,20 @@
* @see libc/sysv/consts.sh * @see libc/sysv/consts.sh
*/ */
textwindows int ntaccesscheck(const char16_t *pathname, uint32_t flags) { textwindows int ntaccesscheck(const char16_t *pathname, uint32_t flags) {
int rc; int rc, e;
void *freeme;
bool32 result; bool32 result;
struct NtSecurityDescriptor *s;
struct NtGenericMapping mapping; struct NtGenericMapping mapping;
struct NtPrivilegeSet privileges; struct NtPrivilegeSet privileges;
int64_t hToken, hImpersonatedToken; int64_t hToken, hImpersonatedToken;
uint32_t secsize, granted, privsize; uint32_t secsize, granted, privsize;
union NtSecurityDescriptorLol { intptr_t buffer[1024 / sizeof(intptr_t)];
struct NtSecurityDescriptor s; freeme = 0;
char b[1024];
} security;
granted = 0; granted = 0;
result = false; result = false;
secsize = sizeof(security); s = (void *)buffer;
secsize = sizeof(buffer);
privsize = sizeof(privileges); privsize = sizeof(privileges);
memset(&privileges, 0, sizeof(privileges)); memset(&privileges, 0, sizeof(privileges));
mapping.GenericRead = kNtFileGenericRead; mapping.GenericRead = kNtFileGenericRead;
@ -65,24 +75,55 @@ textwindows int ntaccesscheck(const char16_t *pathname, uint32_t flags) {
mapping.GenericAll = kNtFileAllAccess; mapping.GenericAll = kNtFileAllAccess;
MapGenericMask(&flags, &mapping); MapGenericMask(&flags, &mapping);
hImpersonatedToken = hToken = -1; hImpersonatedToken = hToken = -1;
TryAgain:
if (GetFileSecurity(pathname, if (GetFileSecurity(pathname,
kNtOwnerSecurityInformation | kNtOwnerSecurityInformation |
kNtGroupSecurityInformation | kNtGroupSecurityInformation |
kNtDaclSecurityInformation, kNtDaclSecurityInformation,
&security.s, 0, &secsize) && s, secsize, &secsize)) {
OpenProcessToken(GetCurrentProcess(), if (OpenProcessToken(GetCurrentProcess(),
kNtTokenImpersonate | kNtTokenQuery | kNtTokenDuplicate | kNtTokenImpersonate | kNtTokenQuery |
kNtStandardRightsRead, kNtTokenDuplicate | kNtStandardRightsRead,
&hToken) && &hToken)) {
DuplicateToken(hToken, kNtSecurityImpersonation, &hImpersonatedToken) && if (DuplicateToken(hToken, kNtSecurityImpersonation,
AccessCheck(&security.s, hImpersonatedToken, flags, &mapping, &privileges, &hImpersonatedToken)) {
&privsize, &granted, &result) && if (AccessCheck(s, hImpersonatedToken, flags, &mapping, &privileges,
(result || flags == F_OK)) { &privsize, &granted, &result)) {
rc = 0; if (result || flags == F_OK) {
rc = 0;
} else {
DEBUG("ntaccesscheck finale failed %d %d", result, flags);
rc = eacces();
}
} else {
rc = __winerr();
DEBUG("AccessCheck failed: %m");
}
} else {
rc = __winerr();
DEBUG("DuplicateToken failed: %m");
}
} else {
rc = __winerr();
DEBUG("OpenProcessToken failed: %m");
}
} else { } else {
rc = __winerr(); e = GetLastError();
DEBUG("GetFileSecurity failed: %d %d", e, secsize);
if (!IsTiny() && e == kNtErrorInsufficientBuffer) {
if (!freeme && weaken(malloc) && (freeme = weaken(malloc)(secsize))) {
s = freeme;
goto TryAgain;
} else {
rc = enomem();
}
} else {
errno = e;
rc = -1;
}
} }
close(hImpersonatedToken); if (freeme && weaken(free)) weaken(free)(freeme);
close(hToken); if (hImpersonatedToken != -1) CloseHandle(hImpersonatedToken);
if (hToken != -1) CloseHandle(hToken);
return rc; return rc;
} }

View file

@ -20,6 +20,8 @@
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/log/log.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/sysv/consts/at.h" #include "libc/sysv/consts/at.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
@ -43,13 +45,19 @@ int openat(int dirfd, const char *file, int flags, ...) {
va_list va; va_list va;
unsigned mode; unsigned mode;
struct ZiposUri zipname; struct ZiposUri zipname;
if (strstr(file, "0/o/dbg/test")) {
(dprintf)(2, "-- wut %`'s\n", file);
if (weaken(__die)) weaken(__die)();
}
va_start(va, flags); va_start(va, flags);
mode = va_arg(va, unsigned); mode = va_arg(va, unsigned);
va_end(va); va_end(va);
if (!file) return efault(); if (!file) return efault();
if (IsAsan() && !__asan_is_valid(file, 1)) return efault();
if (__isfdkind(dirfd, kFdZip)) return einval(); /* TODO(jart): implement me */
if (weaken(__zipos_open) && weaken(__zipos_parseuri)(file, &zipname) != -1) { if (weaken(__zipos_open) && weaken(__zipos_parseuri)(file, &zipname) != -1) {
if (__vforked) return einval(); if (__vforked) return eopnotsupp();
if (dirfd != AT_FDCWD) return einval(); if (dirfd != AT_FDCWD) return eopnotsupp();
return weaken(__zipos_open)(&zipname, flags, mode); return weaken(__zipos_open)(&zipname, flags, mode);
} else if (!IsWindows() && !IsMetal()) { } else if (!IsWindows() && !IsMetal()) {
return sys_openat(dirfd, file, flags, mode); return sys_openat(dirfd, file, flags, mode);

View file

@ -22,11 +22,13 @@
#include "libc/nt/enum/creationdisposition.h" #include "libc/nt/enum/creationdisposition.h"
#include "libc/nt/ipc.h" #include "libc/nt/ipc.h"
#include "libc/nt/runtime.h" #include "libc/nt/runtime.h"
#include "libc/sysv/errfuns.h"
textwindows int sys_pipe_nt(int pipefd[2], unsigned flags) { textwindows int sys_pipe_nt(int pipefd[2], unsigned flags) {
int64_t hin, hout; int64_t hin, hout;
int reader, writer; int reader, writer;
char16_t pipename[64]; char16_t pipename[64];
if (!pipefd) return efault();
CreatePipeName(pipename); CreatePipeName(pipename);
if ((reader = __reservefd()) == -1) return -1; if ((reader = __reservefd()) == -1) return -1;
if ((writer = __reservefd()) == -1) { if ((writer = __reservefd()) == -1) {

View file

@ -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/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
/** /**
@ -30,7 +31,7 @@
* @see pipe2() * @see pipe2()
*/ */
int pipe(int pipefd[hasatleast 2]) { int pipe(int pipefd[hasatleast 2]) {
if (!pipefd) return efault(); if (IsAsan() && !__asan_is_valid(pipefd, sizeof(int) * 2)) return efault();
if (!IsWindows()) { if (!IsWindows()) {
return sys_pipe(pipefd); return sys_pipe(pipefd);
} else { } else {

View file

@ -17,6 +17,8 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
/** /**
@ -28,6 +30,7 @@
*/ */
int pipe2(int pipefd[hasatleast 2], int flags) { int pipe2(int pipefd[hasatleast 2], int flags) {
if (!pipefd) return efault(); if (!pipefd) return efault();
if (IsAsan() && !__asan_is_valid(pipefd, sizeof(int) * 2)) return efault();
if (!IsWindows()) { if (!IsWindows()) {
return sys_pipe2(pipefd, flags); return sys_pipe2(pipefd, flags);
} else { } else {

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/calls.h"
#include "libc/calls/struct/iovec.h" #include "libc/calls/struct/iovec.h"
#include "libc/sock/sock.h" #include "libc/sock/sock.h"

View file

@ -60,13 +60,14 @@
* @see ECMA-48 * @see ECMA-48
*/ */
ssize_t readansi(int fd, char *buf, size_t size) { ssize_t readansi(int fd, char *buf, size_t size) {
int i, j; wint_t x;
uint8_t c; uint8_t c;
int i, j, rc;
enum { kAscii, kUtf8, kEsc, kCsi, kSs } t; enum { kAscii, kUtf8, kEsc, kCsi, kSs } t;
if (size) buf[0] = 0; if (size) buf[0] = 0;
for (j = i = 0, t = kAscii;;) { for (j = i = 0, t = kAscii;;) {
if (i + 2 >= size) return enomem(); if (i + 2 >= size) return enomem();
if (read(fd, &c, 1) != 1) return -1; if ((rc = read(fd, &c, 1)) != 1) return rc;
buf[i++] = c; buf[i++] = c;
buf[i] = 0; buf[i] = 0;
switch (t) { switch (t) {
@ -79,11 +80,24 @@ ssize_t readansi(int fd, char *buf, size_t size) {
} }
} else if (c >= 0300) { } else if (c >= 0300) {
t = kUtf8; t = kUtf8;
x = ThomPikeByte(c);
j = ThomPikeLen(c) - 1; j = ThomPikeLen(c) - 1;
} }
break; break;
case kUtf8: case kUtf8:
if (!--j) return i; x = ThomPikeMerge(x, c);
if (!--j) {
switch (x) {
case '\e':
t = kEsc;
break;
case 0x9b:
t = kCsi;
break;
default:
return i;
}
}
break; break;
case kEsc: case kEsc:
switch (c) { switch (c) {

View file

@ -37,11 +37,12 @@
static textwindows ssize_t sys_readlinkat_nt_error(void) { static textwindows ssize_t sys_readlinkat_nt_error(void) {
uint32_t e; uint32_t e;
if ((e = GetLastError()) == kNtErrorNotAReparsePoint) { switch ((e = GetLastError())) {
return einval(); case kNtErrorNotAReparsePoint:
} else { return einval();
errno = e; default:
return -1; errno = e;
return -1;
} }
} }
@ -55,6 +56,7 @@ textwindows ssize_t sys_readlinkat_nt(int dirfd, const char *path, char *buf,
uint32_t e, i, j, n, mem; uint32_t e, i, j, n, mem;
char16_t path16[PATH_MAX], *p; char16_t path16[PATH_MAX], *p;
struct NtReparseDataBuffer *rdb; struct NtReparseDataBuffer *rdb;
if (!buf) return efault();
if (weaken(malloc)) { if (weaken(malloc)) {
mem = 16384; mem = 16384;
rdb = weaken(malloc)(mem); rdb = weaken(malloc)(mem);

View file

@ -48,8 +48,8 @@
ssize_t readlinkat(int dirfd, const char *path, char *buf, size_t bufsiz) { ssize_t readlinkat(int dirfd, const char *path, char *buf, size_t bufsiz) {
struct ZiposUri zipname; struct ZiposUri zipname;
if (IsAsan() && !__asan_is_valid(buf, bufsiz)) return efault(); if (IsAsan() && !__asan_is_valid(buf, bufsiz)) return efault();
if (weaken(__zipos_open) && weaken(__zipos_parseuri)(path, &zipname) != -1) { if (weaken(__zipos_notat) && __zipos_notat(dirfd, path) == -1) {
return einval(); return -1; /* TODO(jart): code me */
} }
if (!IsWindows()) { if (!IsWindows()) {
return sys_readlinkat(dirfd, path, buf, bufsiz); return sys_readlinkat(dirfd, path, buf, bufsiz);

View file

@ -90,8 +90,8 @@ char *realpath(const char *filename, char *resolved)
return 0; return 0;
} }
if (l >= PATH_MAX) goto toolong; if (l >= PATH_MAX) goto toolong;
if (l > 4 && (READ32LE(filename) == READ32LE("zip:") || if (l >= 4 && READ32LE(filename) == READ32LE("/zip") &&
READ32LE(filename) == READ32LE("zip!"))) { (!filename[4] || filename[4] == '/')) {
return ResolvePath(resolved, filename, l); return ResolvePath(resolved, filename, l);
} }
p = sizeof stack - l - 1; p = sizeof stack - l - 1;

View file

@ -16,10 +16,14 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/consts/at.h" #include "libc/sysv/consts/at.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.internal.h"
/** /**
* Renames files relative to directories. * Renames files relative to directories.
@ -32,6 +36,15 @@
*/ */
int renameat(int olddirfd, const char *oldpath, int newdirfd, int renameat(int olddirfd, const char *oldpath, int newdirfd,
const char *newpath) { const char *newpath) {
if (IsAsan() &&
(!__asan_is_valid(oldpath, 1) || !__asan_is_valid(newpath, 1))) {
return efault();
}
if (weaken(__zipos_notat) &&
(weaken(__zipos_notat)(olddirfd, oldpath) == -1 ||
weaken(__zipos_notat)(newdirfd, newpath) == -1)) {
return -1; /* TODO(jart): implement me */
}
if (!IsWindows()) { if (!IsWindows()) {
return sys_renameat(olddirfd, oldpath, newdirfd, newpath); return sys_renameat(olddirfd, oldpath, newdirfd, newpath);
} else { } else {

View file

@ -61,7 +61,7 @@ static uint32_t ItimerWorker(void *arg) {
} }
textwindows int sys_setitimer_nt(int which, const struct itimerval *newvalue, textwindows int sys_setitimer_nt(int which, const struct itimerval *newvalue,
struct itimerval *out_opt_oldvalue) { struct itimerval *out_opt_oldvalue) {
int32_t period; int32_t period;
int64_t ith, duetime; int64_t ith, duetime;
if (which != ITIMER_REAL) return einval(); if (which != ITIMER_REAL) return einval();

View file

@ -19,6 +19,7 @@
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/struct/itimerval.h" #include "libc/calls/struct/itimerval.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
#include "libc/time/time.h" #include "libc/time/time.h"
@ -62,14 +63,19 @@
* @return 0 on success or -1 w/ errno * @return 0 on success or -1 w/ errno
*/ */
int setitimer(int which, const struct itimerval *newvalue, int setitimer(int which, const struct itimerval *newvalue,
struct itimerval *out_opt_oldvalue) { struct itimerval *oldvalue) {
if (IsAsan() &&
((newvalue && !__asan_is_valid(newvalue, sizeof(*newvalue))) ||
(oldvalue && !__asan_is_valid(oldvalue, sizeof(*oldvalue))))) {
return efault();
}
if (!IsWindows()) { if (!IsWindows()) {
if (newvalue) { if (newvalue) {
return sys_setitimer(which, newvalue, out_opt_oldvalue); return sys_setitimer(which, newvalue, oldvalue);
} else { } else {
return sys_getitimer(which, out_opt_oldvalue); return sys_getitimer(which, oldvalue);
} }
} else { } else {
return sys_setitimer_nt(which, newvalue, out_opt_oldvalue); return sys_setitimer_nt(which, newvalue, oldvalue);
} }
} }

View file

@ -18,6 +18,8 @@
*/ */
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
/** /**
@ -31,9 +33,6 @@
*/ */
int setrlimit(int resource, const struct rlimit *rlim) { int setrlimit(int resource, const struct rlimit *rlim) {
if (resource == 127) return einval(); if (resource == 127) return einval();
if (!IsWindows()) { if (IsAsan() && !__asan_is_valid(rlim, sizeof(*rlim))) return efault();
return sys_setrlimit(resource, rlim); return sys_setrlimit(resource, rlim);
} else {
return enosys(); /* TODO(jart): Implement me! */
}
} }

View file

@ -30,6 +30,7 @@
#include "libc/calls/typedef/sigaction_f.h" #include "libc/calls/typedef/sigaction_f.h"
#include "libc/calls/ucontext.h" #include "libc/calls/ucontext.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/limits.h" #include "libc/limits.h"
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
#include "libc/mem/mem.h" #include "libc/mem/mem.h"
@ -141,18 +142,23 @@ static void sigaction_native2cosmo(union metasigaction *sa) {
* @vforksafe * @vforksafe
*/ */
int(sigaction)(int sig, const struct sigaction *act, struct sigaction *oldact) { int(sigaction)(int sig, const struct sigaction *act, struct sigaction *oldact) {
_Static_assert((sizeof(struct sigaction) > sizeof(struct sigaction_linux) &&
sizeof(struct sigaction) > sizeof(struct sigaction_xnu_in) &&
sizeof(struct sigaction) > sizeof(struct sigaction_xnu_out) &&
sizeof(struct sigaction) > sizeof(struct sigaction_freebsd) &&
sizeof(struct sigaction) > sizeof(struct sigaction_openbsd) &&
sizeof(struct sigaction) > sizeof(struct sigaction_netbsd)),
"sigaction cosmo abi needs tuning");
int64_t arg4, arg5; int64_t arg4, arg5;
int rc, rva, oldrva; int rc, rva, oldrva;
struct sigaction *ap, copy; struct sigaction *ap, copy;
assert(sizeof(struct sigaction) > sizeof(struct sigaction_linux) &&
sizeof(struct sigaction) > sizeof(struct sigaction_xnu_in) &&
sizeof(struct sigaction) > sizeof(struct sigaction_xnu_out) &&
sizeof(struct sigaction) > sizeof(struct sigaction_freebsd) &&
sizeof(struct sigaction) > sizeof(struct sigaction_openbsd) &&
sizeof(struct sigaction) > sizeof(struct sigaction_netbsd));
if (IsMetal()) return enosys(); /* TODO: Signals on Metal */ if (IsMetal()) return enosys(); /* TODO: Signals on Metal */
if (!(0 < sig && sig < NSIG)) return einval(); if (!(0 < sig && sig < NSIG)) return einval();
if (sig == SIGKILL || sig == SIGSTOP) return einval(); if (sig == SIGKILL || sig == SIGSTOP) return einval();
if (IsAsan() && ((act && !__asan_is_valid(act, sizeof(*act))) ||
(oldact && !__asan_is_valid(oldact, sizeof(*oldact))))) {
return efault();
}
if (!act) { if (!act) {
rva = (int32_t)(intptr_t)SIG_DFL; rva = (int32_t)(intptr_t)SIG_DFL;
} else if ((intptr_t)act->sa_handler < kSigactionMinRva) { } else if ((intptr_t)act->sa_handler < kSigactionMinRva) {

View file

@ -20,6 +20,7 @@
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/struct/sigset.h" #include "libc/calls/struct/sigset.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
@ -40,6 +41,12 @@
*/ */
int sigprocmask(int how, const sigset_t *opt_set, sigset_t *opt_out_oldset) { int sigprocmask(int how, const sigset_t *opt_set, sigset_t *opt_out_oldset) {
int32_t x; int32_t x;
if (IsAsan() &&
((opt_set && !__asan_is_valid(opt_set, sizeof(*opt_set))) ||
(opt_out_oldset &&
!__asan_is_valid(opt_out_oldset, sizeof(*opt_out_oldset))))) {
return efault();
}
if (!IsWindows() && !IsOpenbsd()) { if (!IsWindows() && !IsOpenbsd()) {
return sys_sigprocmask(how, opt_set, opt_out_oldset, 8); return sys_sigprocmask(how, opt_set, opt_out_oldset, 8);
} else if (IsOpenbsd()) { } else if (IsOpenbsd()) {

View file

@ -20,6 +20,7 @@
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/struct/sigset.h" #include "libc/calls/struct/sigset.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
/** /**
@ -31,6 +32,7 @@
*/ */
int sigsuspend(const sigset_t *ignore) { int sigsuspend(const sigset_t *ignore) {
unsigned x; unsigned x;
if (IsAsan() && !__asan_is_valid(ignore, sizeof(*ignore))) return efault();
if (!IsWindows()) { if (!IsWindows()) {
if (IsOpenbsd()) ignore = (sigset_t *)(uintptr_t)(*(uint32_t *)ignore); if (IsOpenbsd()) ignore = (sigset_t *)(uintptr_t)(*(uint32_t *)ignore);
return sys_sigsuspend(ignore, 8); return sys_sigsuspend(ignore, 8);

View file

@ -19,7 +19,9 @@
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/consts/at.h" #include "libc/sysv/consts/at.h"
#include "libc/sysv/errfuns.h"
/** /**
* Creates symbolic link. * Creates symbolic link.
@ -35,6 +37,10 @@
* @asyncsignalsafe * @asyncsignalsafe
*/ */
int symlinkat(const char *target, int newdirfd, const char *linkpath) { int symlinkat(const char *target, int newdirfd, const char *linkpath) {
if (IsAsan() &&
(!__asan_is_valid(target, 1) || !__asan_is_valid(linkpath, 1))) {
return efault();
}
if (!IsWindows()) { if (!IsWindows()) {
return sys_symlinkat(target, newdirfd, linkpath); return sys_symlinkat(target, newdirfd, linkpath);
} else { } else {

View file

@ -17,10 +17,29 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/struct/termios.h"
#include "libc/calls/termios.h" #include "libc/calls/termios.h"
#include "libc/sysv/consts/termios.h" #include "libc/sysv/consts/termios.h"
#include "libc/sysv/errfuns.h"
/**
* Changes flow of teletypewriter data.
*
* - `TCOOFF` suspends output
* - `TCOON` resumes output
* - `TCIOFF` transmits a STOP character
* - `TCION` transmits a START character
*/
int tcflow(int fd, int action) { int tcflow(int fd, int action) {
/* TODO(jart): BSD support */ uint8_t c;
return sys_ioctl(fd, TCXONC, (void *)(intptr_t)action); struct termios t;
if (!IsBsd()) return sys_ioctl(fd, TCXONC, action);
if (action == TCOOFF) return sys_ioctl(fd, TIOCSTOP, 0);
if (action == TCOON) return sys_ioctl(fd, TIOCSTART, 0);
if (action != TCIOFF && action != TCION) return einval();
if (tcgetattr(fd, &t) == -1) return -1;
if ((c = t.c_cc[action == TCIOFF ? VSTOP : VSTART]) != 255) {
if (sys_write(fd, &c, 1) == -1) return -1;
}
return 0;
} }

View file

@ -18,9 +18,15 @@
*/ */
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/termios.h" #include "libc/calls/termios.h"
#include "libc/sysv/consts/termios.h"
int tcflush(int fd, int x) { /**
/* TODO(jart): BSD Support */ * Flushes teletypewriter data.
return sys_ioctl(fd, TCFLSH, x); *
* - `TCIFLUSH` flushes data received but not read
* - `TCOFLUSH` flushes data written but not transmitted
* - `TCIOFLUSH` does both `TCOFLUSH` and `TCIFLUSH`
*/
int tcflush(int fd, int queue) {
/* TODO(jart): Windows? */
return sys_ioctl(fd, TCFLSH, queue);
} }

View file

@ -16,10 +16,14 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/consts/at.h" #include "libc/sysv/consts/at.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.internal.h"
/** /**
* Deletes inode and maybe the file too. * Deletes inode and maybe the file too.
@ -31,6 +35,10 @@
* @return 0 on success, or -1 w/ errno * @return 0 on success, or -1 w/ errno
*/ */
int unlinkat(int dirfd, const char *path, int flags) { int unlinkat(int dirfd, const char *path, int flags) {
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
if (weaken(__zipos_notat) && weaken(__zipos_notat)(dirfd, path) == -1) {
return -1; /* TODO(jart): implement me */
}
if (!IsWindows()) { if (!IsWindows()) {
return sys_unlinkat(dirfd, path, flags); return sys_unlinkat(dirfd, path, flags);
} else { } else {

View file

@ -16,10 +16,12 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/bits/weaken.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/sysv/consts/at.h" #include "libc/sysv/consts/at.h"
#include "libc/time/time.h" #include "libc/time/time.h"
#include "libc/zipos/zipos.internal.h"
#define __NR_utimensat_linux 0x118 /*RHEL5:CVE-2010-3301*/ #define __NR_utimensat_linux 0x118 /*RHEL5:CVE-2010-3301*/
@ -27,6 +29,9 @@ int sys_utimensat(int dirfd, const char *path, const struct timespec ts[2],
int flags) { int flags) {
int rc, olderr; int rc, olderr;
struct timeval tv[2]; struct timeval tv[2];
if (weaken(__zipos_notat) && weaken(__zipos_notat)(dirfd, path) == -1) {
return -1; /* TODO(jart): implement me */
}
if (!IsXnu()) { if (!IsXnu()) {
olderr = errno; olderr = errno;
rc = __sys_utimensat(dirfd, path, ts, flags); rc = __sys_utimensat(dirfd, path, ts, flags);

View file

@ -16,8 +16,13 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.internal.h"
/** /**
* Sets atime/mtime on file, the modern way. * Sets atime/mtime on file, the modern way.
@ -29,6 +34,13 @@
*/ */
int utimensat(int dirfd, const char *path, const struct timespec ts[2], int utimensat(int dirfd, const char *path, const struct timespec ts[2],
int flags) { int flags) {
if (IsAsan() && (!__asan_is_valid(path, 1) ||
(ts && !__asan_is_valid(ts, sizeof(struct timespec) * 2)))) {
return efault();
}
if (weaken(__zipos_notat) && weaken(__zipos_notat)(dirfd, path) == -1) {
return -1; /* TODO(jart): implement me */
}
if (!IsWindows()) { if (!IsWindows()) {
return sys_utimensat(dirfd, path, ts, flags); return sys_utimensat(dirfd, path, ts, flags);
} else { } else {

View file

@ -37,15 +37,12 @@
*/ */
int wait4(int pid, int *opt_out_wstatus, int options, int wait4(int pid, int *opt_out_wstatus, int options,
struct rusage *opt_out_rusage) { struct rusage *opt_out_rusage) {
if (IsAsan()) { if (IsAsan() &&
if (opt_out_wstatus && ((opt_out_wstatus &&
!__asan_is_valid(opt_out_wstatus, sizeof(*opt_out_wstatus))) { !__asan_is_valid(opt_out_wstatus, sizeof(*opt_out_wstatus))) ||
return efault(); (opt_out_rusage &&
} !__asan_is_valid(opt_out_rusage, sizeof(*opt_out_rusage))))) {
if (opt_out_rusage && return efault();
!__asan_is_valid(opt_out_rusage, sizeof(*opt_out_rusage))) {
return efault();
}
} }
if (!IsWindows()) { if (!IsWindows()) {
return sys_wait4(pid, opt_out_wstatus, options, opt_out_rusage); return sys_wait4(pid, opt_out_wstatus, options, opt_out_rusage);

View file

@ -26,6 +26,7 @@
#include "libc/mem/mem.h" #include "libc/mem/mem.h"
#include "libc/rand/rand.h" #include "libc/rand/rand.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/sock/internal.h"
#include "libc/sock/sock.h" #include "libc/sock/sock.h"
#include "libc/stdio/stdio.h" #include "libc/stdio/stdio.h"
#include "libc/str/str.h" #include "libc/str/str.h"
@ -100,6 +101,7 @@ int ResolveDns(const struct ResolvConf *resolvconf, int af, const char *name,
a4 = (struct sockaddr_in *)addr; a4 = (struct sockaddr_in *)addr;
a4->sin_family = AF_INET; a4->sin_family = AF_INET;
memcpy(&a4->sin_addr.s_addr, p + 10, 4); memcpy(&a4->sin_addr.s_addr, p + 10, 4);
_firewall(a4, sizeof(struct sockaddr_in));
break; break;
} }
p += 10 + rdlength; p += 10 + rdlength;

View file

@ -1,280 +1,690 @@
#ifndef COSMOPOLITAN_LIBC_ERRNO_H_ #ifndef COSMOPOLITAN_LIBC_ERRNO_H_
#define COSMOPOLITAN_LIBC_ERRNO_H_ #define COSMOPOLITAN_LIBC_ERRNO_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
/** /**
* @fileoverview System error codes. * @fileoverview System error codes.
* @see libc/sysv/consts.sh for numbers * @see libc/sysv/consts.sh for numbers
*/ */
#define EPERM EPERM /* operation not permitted */
#define ENOENT ENOENT /* no such file or directory */
#define ESRCH ESRCH /* no such process */
#define EINTR EINTR /* interrupted system call */
#define EIO EIO /* input/output error */
#define ENXIO ENXIO /* no such device or address */
#define E2BIG E2BIG /* argument list too long */
#define ENOEXEC ENOEXEC /* exec format error */
#define EBADF EBADF /* bad file descriptor */
#define ECHILD ECHILD /* no child processes */
#define EAGAIN EAGAIN /* resource temporarily unavailable */
#define ENOMEM ENOMEM /* not enough space */
#define EACCES EACCES /* permission denied */
#define EFAULT EFAULT /* bad address */
#define ENOTBLK ENOTBLK /* block device required */
#define EBUSY EBUSY /* device or resource busy */
#define EEXIST EEXIST /* file exists */
#define EXDEV EXDEV /* improper link */
#define ENODEV ENODEV /* no such device */
#define ENOTDIR ENOTDIR /* not a directory */
#define EISDIR EISDIR /* is a directory */
#define EINVAL EINVAL /* invalid argument */
#define ENFILE ENFILE /* too many open files in system */
#define EMFILE EMFILE /* too many open files */
#define ENOTTY ENOTTY /* inappropriate I/O control op */
#define ETXTBSY ETXTBSY /* text file busy */
#define EFBIG EFBIG /* file too large */
#define ENOSPC ENOSPC /* no space left on device */
#define ESPIPE ESPIPE /* invalid seek */
#define EROFS EROFS /* read-only filesystem */
#define EMLINK EMLINK /* too many links */
#define EPIPE EPIPE /* broken pipe */
#define EDOM EDOM /* argument out of function domain */
#define ERANGE ERANGE /* result too large */
#define EDEADLK EDEADLK /* resource deadlock avoided */
#define ENAMETOOLONG ENAMETOOLONG /* filename too long */
#define ENOLCK ENOLCK /* no locks available */
#define ENOSYS ENOSYS /* system call not implemented */
#define ENOTEMPTY ENOTEMPTY /* directory not empty */
#define ELOOP ELOOP /* too many levels of symbolic links */
#define ENOMSG ENOMSG /* no message of the desired type */
#define EIDRM EIDRM /* identifier removed */
#define ECHRNG ECHRNG /* channel number out of range */
#define EL2NSYNC EL2NSYNC /* level 2 not synchronized */
#define EL3HLT EL3HLT /* level 3 halted */
#define EL3RST EL3RST /* level 3 halted */
#define ELNRNG ELNRNG /* link number out of range */
#define EUNATCH EUNATCH /* protocol driver not attached */
#define ENOCSI ENOCSI /* no csi structure available */
#define EL2HLT EL2HLT /* level 2 halted */
#define EBADE EBADE /* invalid exchange */
#define EBADR EBADR /* invalid request descriptor */
#define EXFULL EXFULL /* exchange full */
#define ENOANO ENOANO /* no anode */
#define EBADRQC EBADRQC /* invalid request code */
#define EBADSLT EBADSLT /* invalid slot */
#define ENOSTR ENOSTR /* no string */
#define ENODATA ENODATA /* no data */
#define ETIME ETIME /* timer expired */
#define ENOSR ENOSR /* out of streams resources */
#define ENONET ENONET /* no network */
#define ENOPKG ENOPKG /* package not installed */
#define EREMOTE EREMOTE /* object is remote */
#define ENOLINK ENOLINK /* link severed */
#define EADV EADV /* todo */
#define ESRMNT ESRMNT /* todo */
#define ECOMM ECOMM /* communication error on send */
#define EPROTO EPROTO /* protocol error */
#define EMULTIHOP EMULTIHOP /* multihop attempted */
#define EDOTDOT EDOTDOT /* todo */
#define EBADMSG EBADMSG /* bad message */
#define EOVERFLOW EOVERFLOW /* value too large for type */
#define ENOTUNIQ ENOTUNIQ /* name not unique on network */
#define EBADFD EBADFD /* fd in bad *state* (cf. EBADF) */
#define EREMCHG EREMCHG /* remote address changed */
#define ELIBACC ELIBACC /* cannot access dso */
#define ELIBBAD ELIBBAD /* corrupted shared library */
#define ELIBSCN ELIBSCN /* a.out section corrupted */
#define ELIBMAX ELIBMAX /* too many shared libraries */
#define ELIBEXEC ELIBEXEC /* cannot exec a dso directly */
#define EILSEQ EILSEQ /* invalid wide character */
#define ERESTART ERESTART /* please restart syscall */
#define ESTRPIPE ESTRPIPE /* streams pipe error */
#define EUSERS EUSERS /* too many users */
#define ENOTSOCK ENOTSOCK /* not a socket */
#define EDESTADDRREQ EDESTADDRREQ /* dest address needed */
#define EMSGSIZE EMSGSIZE /* message too long */
#define EPROTOTYPE EPROTOTYPE /* protocol wrong for socket */
#define ENOPROTOOPT ENOPROTOOPT /* protocol not available */
#define EPROTONOSUPPORT EPROTONOSUPPORT /* protocol not supported */
#define ESOCKTNOSUPPORT ESOCKTNOSUPPORT /* socket type not supported */
#define EOPNOTSUPP EOPNOTSUPP /* operation not supported on socket */
#define EPFNOSUPPORT EPFNOSUPPORT /* protocol family not supported */
#define EAFNOSUPPORT EAFNOSUPPORT /* address family not supported */
#define EADDRINUSE EADDRINUSE /* address already in use */
#define EADDRNOTAVAIL EADDRNOTAVAIL /* address not available */
#define ENETDOWN ENETDOWN /* network is down */
#define ENETUNREACH ENETUNREACH /* network unreachable */
#define ENETRESET ENETRESET /* connection aborted by network */
#define ECONNABORTED ECONNABORTED /* connection aborted */
#define ECONNRESET ECONNRESET /* connection reset */
#define ENOBUFS ENOBUFS /* no buffer space available */
#define EISCONN EISCONN /* socket is connected */
#define ENOTCONN ENOTCONN /* the socket is not connected */
#define ESHUTDOWN ESHUTDOWN /* no send after endpoint shutdown */
#define ETOOMANYREFS ETOOMANYREFS /* too many refs */
#define ETIMEDOUT ETIMEDOUT /* connection timed out */
#define ECONNREFUSED ECONNREFUSED /* connection refused */
#define EHOSTDOWN EHOSTDOWN /* host is down */
#define EHOSTUNREACH EHOSTUNREACH /* host is unreachable */
#define EALREADY EALREADY /* connection already in progress */
#define EINPROGRESS EINPROGRESS /* operation in progress */
#define ESTALE ESTALE /* stale file handle */
#define EUCLEAN EUCLEAN /* structure needs cleaning */
#define ENOTNAM ENOTNAM /* todo */
#define ENAVAIL ENAVAIL /* todo */
#define EISNAM EISNAM /* is a named type file */
#define EREMOTEIO EREMOTEIO /* remote i/o error */
#define EDQUOT EDQUOT /* disk quota exceeded */
#define ENOMEDIUM ENOMEDIUM /* no medium found */
#define EMEDIUMTYPE EMEDIUMTYPE /* wrong medium type */
#define ECANCELED ECANCELED /* operation canceled */
#define ENOKEY ENOKEY /* required key not available */
#define EKEYEXPIRED EKEYEXPIRED /* key has expired */
#define EKEYREVOKED EKEYREVOKED /* key has been revoked */
#define EKEYREJECTED EKEYREJECTED /* key was rejected by service */
#define EOWNERDEAD EOWNERDEAD /* owner died */
#define ENOTRECOVERABLE ENOTRECOVERABLE /* state not recoverable */
#define ERFKILL ERFKILL /* can't op b/c RF-kill */
#define EHWPOISON EHWPOISON /* mempage has h/w error */
#define EWOULDBLOCK EAGAIN /* poll fd and try again */
#define ENOTSUP ENOTSUP
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
extern errno_t errno; extern errno_t errno;
hidden extern const long EPERM; /**
hidden extern const long ENOENT; * System call unavailable.
hidden extern const long ESRCH; * @note kNtErrorInvalidFunction on NT
hidden extern const long EINTR; */
hidden extern const long EIO; extern const long ENOSYS;
hidden extern const long ENXIO;
hidden extern const long E2BIG; /**
hidden extern const long ENOEXEC; * Operation not permitted.
hidden extern const long EBADF; * @note kNtErrorInvalidAccess on NT
hidden extern const long ECHILD; */
hidden extern const long EAGAIN; extern const long EPERM;
hidden extern const long ENOMEM;
hidden extern const long EACCES; /**
hidden extern const long EFAULT; * No such file or directory.
hidden extern const long ENOTBLK; */
hidden extern const long EBUSY; extern const long ENOENT;
hidden extern const long EEXIST;
hidden extern const long EXDEV; /**
hidden extern const long ENODEV; * No such process.
hidden extern const long ENOTDIR; */
hidden extern const long EISDIR; extern const long ESRCH;
hidden extern const long EINVAL;
hidden extern const long ENFILE; /**
hidden extern const long EMFILE; * The greatest of all errnos.
hidden extern const long ENOTTY; */
hidden extern const long ETXTBSY; extern const long EINTR;
hidden extern const long EFBIG;
hidden extern const long ENOSPC; /**
hidden extern const long ESPIPE; * Unix consensus.
hidden extern const long EROFS; */
hidden extern const long EMLINK; extern const long EIO;
hidden extern const long EPIPE;
hidden extern const long EDOM; /**
hidden extern const long ERANGE; * No such device or address.
hidden extern const long EDEADLK; */
hidden extern const long ENAMETOOLONG; extern const long ENXIO;
hidden extern const long ENOLCK;
hidden extern const long ENOSYS; /**
hidden extern const long ENOTEMPTY; * Argument list too long.
hidden extern const long ELOOP; */
hidden extern const long ENOMSG; extern const long E2BIG;
hidden extern const long EIDRM;
hidden extern const long ECHRNG; /**
hidden extern const long EL2NSYNC; * Exec format error.
hidden extern const long EL3HLT; */
hidden extern const long EL3RST; extern const long ENOEXEC;
hidden extern const long ELNRNG;
hidden extern const long EUNATCH; /**
hidden extern const long ENOCSI; * Bad file descriptor.
hidden extern const long EL2HLT; */
hidden extern const long EBADE; extern const long EBADF;
hidden extern const long EBADR;
hidden extern const long EXFULL; /**
hidden extern const long ENOANO; * No child process.
hidden extern const long EBADRQC; */
hidden extern const long EBADSLT; extern const long ECHILD;
hidden extern const long ENOSTR;
hidden extern const long ENODATA; /**
hidden extern const long ETIME; * Resource temporarily unavailable (e.g. SO_RCVTIMEO expired, too many
hidden extern const long ENOSR; * processes, too much memory locked, read or write with O_NONBLOCK needs
hidden extern const long ENONET; * polling, etc.).
hidden extern const long ENOPKG; */
hidden extern const long EREMOTE; extern const long EAGAIN;
hidden extern const long ENOLINK;
hidden extern const long EADV; /**
hidden extern const long ESRMNT; * We require more vespene gas.
hidden extern const long ECOMM; */
hidden extern const long EPROTO; extern const long ENOMEM;
hidden extern const long EMULTIHOP;
hidden extern const long EDOTDOT; /**
hidden extern const long EBADMSG; * Permission denied.
hidden extern const long EOVERFLOW; */
hidden extern const long ENOTUNIQ; extern const long EACCES;
hidden extern const long EBADFD;
hidden extern const long EREMCHG; /**
hidden extern const long ELIBACC; * Pointer passed to system call that would otherwise segfault.
hidden extern const long ELIBBAD; */
hidden extern const long ELIBSCN; extern const long EFAULT;
hidden extern const long ELIBMAX;
hidden extern const long ELIBEXEC; /**
hidden extern const long EILSEQ; * Block device required.
hidden extern const long ERESTART; */
hidden extern const long ESTRPIPE; extern const long ENOTBLK;
hidden extern const long EUSERS;
hidden extern const long ENOTSOCK; /**
hidden extern const long EDESTADDRREQ; * Device or resource busy.
hidden extern const long EMSGSIZE; */
hidden extern const long EPROTOTYPE; extern const long EBUSY;
hidden extern const long ENOPROTOOPT;
hidden extern const long EPROTONOSUPPORT; /**
hidden extern const long ESOCKTNOSUPPORT; * File exists.
hidden extern const long EOPNOTSUPP; */
hidden extern const long EPFNOSUPPORT; extern const long EEXIST;
hidden extern const long EAFNOSUPPORT;
hidden extern const long EADDRINUSE; /**
hidden extern const long EADDRNOTAVAIL; * Improper link.
hidden extern const long ENETDOWN; */
hidden extern const long ENETUNREACH; extern const long EXDEV;
hidden extern const long ENETRESET;
hidden extern const long ECONNABORTED; /**
hidden extern const long ECONNRESET; * No such device.
hidden extern const long ENOBUFS; */
hidden extern const long EISCONN; extern const long ENODEV;
hidden extern const long ENOTCONN;
hidden extern const long ESHUTDOWN; /**
hidden extern const long ETOOMANYREFS; * Not a directory.
hidden extern const long ETIMEDOUT; */
hidden extern const long ECONNREFUSED; extern const long ENOTDIR;
hidden extern const long EHOSTDOWN;
hidden extern const long EHOSTUNREACH; /**
hidden extern const long EALREADY; * Is a a directory.
hidden extern const long EINPROGRESS; */
hidden extern const long ESTALE; extern const long EISDIR;
hidden extern const long EUCLEAN;
hidden extern const long ENOTNAM; /**
hidden extern const long ENAVAIL; * Invalid argument.
hidden extern const long EISNAM; */
hidden extern const long EREMOTEIO; extern const long EINVAL;
hidden extern const long EDQUOT;
hidden extern const long ENOMEDIUM; /**
hidden extern const long EMEDIUMTYPE; * Too many open files in system.
hidden extern const long ECANCELED; */
hidden extern const long ENOKEY; extern const long ENFILE;
hidden extern const long EKEYEXPIRED;
hidden extern const long EKEYREVOKED; /**
hidden extern const long EKEYREJECTED; * Too many open files.
hidden extern const long EOWNERDEAD; */
hidden extern const long ENOTRECOVERABLE; extern const long EMFILE;
hidden extern const long ERFKILL;
hidden extern const long EHWPOISON; /**
hidden extern const long ENOTSUP; * Inappropriate i/o control operation.
*/
extern const long ENOTTY;
/**
* Won't open executable that's executing in write mode.
*/
extern const long ETXTBSY;
/**
* File too large.
*/
extern const long EFBIG;
/**
* No space left on device.
*/
extern const long ENOSPC;
/**
* Disk quota exceeded.
*/
extern const long EDQUOT;
/**
* Invalid seek.
*/
extern const long ESPIPE;
/**
* Read-only filesystem.
*/
extern const long EROFS;
/**
* Too many links.
*/
extern const long EMLINK;
/**
* Broken pipe.
*/
extern const long EPIPE;
/**
* Mathematics argument out of domain of function.
*/
extern const long EDOM;
/**
* Result too large.
*/
extern const long ERANGE;
/**
* Resource deadlock avoided.
*/
extern const long EDEADLK;
/**
* Filename too long.
*/
extern const long ENAMETOOLONG;
/**
* No locks available.
*/
extern const long ENOLCK;
/**
* Directory not empty.
*/
extern const long ENOTEMPTY;
/**
* Too many levels of symbolic links.
*/
extern const long ELOOP;
/**
* No message error.
*/
extern const long ENOMSG;
/**
* Identifier removed.
*/
extern const long EIDRM;
/**
* Timer expired.
*/
extern const long ETIME;
/**
* Protocol error.
*/
extern const long EPROTO;
/**
* Overflow error.
*/
extern const long EOVERFLOW;
/**
* Unicode decoding error.
*/
extern const long EILSEQ;
/**
* Too many users.
*/
extern const long EUSERS;
/**
* Not a socket.
*/
extern const long ENOTSOCK;
/**
* Destination address required.
*/
extern const long EDESTADDRREQ;
/**
* Message too long.
*/
extern const long EMSGSIZE;
/**
* Protocol wrong type for socket.
*/
extern const long EPROTOTYPE;
/**
* Protocol not available.
*/
extern const long ENOPROTOOPT;
/**
* Protocol not supported.
*/
extern const long EPROTONOSUPPORT;
/**
* Socket type not supported.
*/
extern const long ESOCKTNOSUPPORT;
/**
* Operation not supported.
*/
extern const long ENOTSUP;
/**
* Socket operation not supported.
*/
extern const long EOPNOTSUPP;
/**
* Protocol family not supported.
*/
extern const long EPFNOSUPPORT;
/**
* Address family not supported.
*/
extern const long EAFNOSUPPORT;
/**
* Address already in use.
*/
extern const long EADDRINUSE;
/**
* Address not available.
*/
extern const long EADDRNOTAVAIL;
/**
* Network is down.
*/
extern const long ENETDOWN;
/**
* Host is unreachable.
*/
extern const long ENETUNREACH;
/**
* Connection reset by network.
*/
extern const long ENETRESET;
/**
* Connection reset before accept.
*/
extern const long ECONNABORTED;
/**
* Connection reset by client.
*/
extern const long ECONNRESET;
/**
* No buffer space available.
*/
extern const long ENOBUFS;
/**
* Socket is connected.
*/
extern const long EISCONN;
/**
* Socket is not connected.
*/
extern const long ENOTCONN;
/**
* Cannot send after transport endpoint shutdown.
*/
extern const long ESHUTDOWN;
/**
* Too many references: cannot splice.
*/
extern const long ETOOMANYREFS;
/**
* Connection timed out.
*/
extern const long ETIMEDOUT;
/**
* Connection refused error.
*/
extern const long ECONNREFUSED;
/**
* Host down error.
*/
extern const long EHOSTDOWN;
/**
* Host unreachable error.
*/
extern const long EHOSTUNREACH;
/**
* Connection already in progress.
*/
extern const long EALREADY;
/**
* Operation already in progress.
*/
extern const long EINPROGRESS;
/**
* Stale error.
*/
extern const long ESTALE;
/**
* Remote error.
*/
extern const long EREMOTE;
/**
* Bad message.
*/
extern const long EBADMSG;
/**
* Operation canceled.
*/
extern const long ECANCELED;
/**
* Owner died.
*/
extern const long EOWNERDEAD;
/**
* State not recoverable.
*/
extern const long ENOTRECOVERABLE;
/**
* No network.
*/
extern const long ENONET;
/**
* Please restart syscall.
*/
extern const long ERESTART;
/**
* Out of streams resources.
*/
extern const long ENOSR;
/**
* No string.
*/
extern const long ENOSTR;
/**
* No data.
*/
extern const long ENODATA;
/**
* Multihop attempted.
*/
extern const long EMULTIHOP;
/**
* Link severed.
*/
extern const long ENOLINK;
/**
* No medium found.
*/
extern const long ENOMEDIUM;
/**
* Wrong medium type.
*/
extern const long EMEDIUMTYPE;
/**
* Inappropriate file type or format. (BSD only)
*/
extern const long EFTYPE;
extern const long EAUTH;
extern const long EBADARCH;
extern const long EBADEXEC;
extern const long EBADMACHO;
extern const long EBADRPC;
extern const long EDEVERR;
extern const long ENEEDAUTH;
extern const long ENOATTR;
extern const long ENOPOLICY;
extern const long EPROCLIM;
extern const long EPROCUNAVAIL;
extern const long EPROGMISMATCH;
extern const long EPROGUNAVAIL;
extern const long EPWROFF;
extern const long ERPCMISMATCH;
extern const long ESHLIBVERS;
extern const long EADV;
extern const long EBADE;
extern const long EBADFD;
extern const long EBADR;
extern const long EBADRQC;
extern const long EBADSLT;
extern const long ECHRNG;
extern const long ECOMM;
extern const long EDOTDOT;
extern const long EHWPOISON;
extern const long EISNAM;
extern const long EKEYEXPIRED;
extern const long EKEYREJECTED;
extern const long EKEYREVOKED;
extern const long EL2HLT;
extern const long EL2NSYNC;
extern const long EL3HLT;
extern const long EL3RST;
extern const long ELIBACC;
extern const long ELIBBAD;
extern const long ELIBEXEC;
extern const long ELIBMAX;
extern const long ELIBSCN;
extern const long ELNRNG;
extern const long ENAVAIL;
extern const long ENOANO;
extern const long ENOCSI;
extern const long ENOKEY;
extern const long ENOPKG;
extern const long ENOTNAM;
extern const long ENOTUNIQ;
extern const long EREMCHG;
extern const long EREMOTEIO;
extern const long ERFKILL;
extern const long ESRMNT;
extern const long ESTRPIPE;
extern const long EUCLEAN;
extern const long EUNATCH;
extern const long EXFULL;
#define E2BIG E2BIG
#define EACCES EACCES
#define EADDRINUSE EADDRINUSE
#define EADDRNOTAVAIL EADDRNOTAVAIL
#define EADV EADV
#define EAFNOSUPPORT EAFNOSUPPORT
#define EAGAIN EAGAIN
#define EALREADY EALREADY
#define EAUTH EAUTH
#define EBADARCH EBADARCH
#define EBADE EBADE
#define EBADEXEC EBADEXEC
#define EBADF EBADF
#define EBADFD EBADFD
#define EBADMACHO EBADMACHO
#define EBADMSG EBADMSG
#define EBADR EBADR
#define EBADRPC EBADRPC
#define EBADRQC EBADRQC
#define EBADSLT EBADSLT
#define EBUSY EBUSY
#define ECANCELED ECANCELED
#define ECHILD ECHILD
#define ECHRNG ECHRNG
#define ECOMM ECOMM
#define ECONNABORTED ECONNABORTED
#define ECONNREFUSED ECONNREFUSED
#define ECONNRESET ECONNRESET
#define EDEADLK EDEADLK
#define EDESTADDRREQ EDESTADDRREQ
#define EDEVERR EDEVERR
#define EDOM EDOM
#define EDOTDOT EDOTDOT
#define EDQUOT EDQUOT
#define EEXIST EEXIST
#define EFAULT EFAULT
#define EFBIG EFBIG
#define EFTYPE EFTYPE
#define EHOSTDOWN EHOSTDOWN
#define EHOSTUNREACH EHOSTUNREACH
#define EHWPOISON EHWPOISON
#define EIDRM EIDRM
#define EILSEQ EILSEQ
#define EINPROGRESS EINPROGRESS
#define EINTR EINTR
#define EINVAL EINVAL
#define EIO EIO
#define EISCONN EISCONN
#define EISDIR EISDIR
#define EISNAM EISNAM
#define EKEYEXPIRED EKEYEXPIRED
#define EKEYREJECTED EKEYREJECTED
#define EKEYREVOKED EKEYREVOKED
#define EL2HLT EL2HLT
#define EL2NSYNC EL2NSYNC
#define EL3HLT EL3HLT
#define EL3RST EL3RST
#define ELIBACC ELIBACC
#define ELIBBAD ELIBBAD
#define ELIBEXEC ELIBEXEC
#define ELIBMAX ELIBMAX
#define ELIBSCN ELIBSCN
#define ELNRNG ELNRNG
#define ELOOP ELOOP
#define EMEDIUMTYPE EMEDIUMTYPE
#define EMFILE EMFILE
#define EMLINK EMLINK
#define EMSGSIZE EMSGSIZE
#define EMULTIHOP EMULTIHOP
#define ENAMETOOLONG ENAMETOOLONG
#define ENAVAIL ENAVAIL
#define ENEEDAUTH ENEEDAUTH
#define ENETDOWN ENETDOWN
#define ENETRESET ENETRESET
#define ENETUNREACH ENETUNREACH
#define ENFILE ENFILE
#define ENOANO ENOANO
#define ENOATTR ENOATTR
#define ENOBUFS ENOBUFS
#define ENOCSI ENOCSI
#define ENODATA ENODATA
#define ENODEV ENODEV
#define ENOENT ENOENT
#define ENOEXEC ENOEXEC
#define ENOKEY ENOKEY
#define ENOLCK ENOLCK
#define ENOLINK ENOLINK
#define ENOMEDIUM ENOMEDIUM
#define ENOMEM ENOMEM
#define ENOMSG ENOMSG
#define ENONET ENONET
#define ENOPKG ENOPKG
#define ENOPOLICY ENOPOLICY
#define ENOPROTOOPT ENOPROTOOPT
#define ENOSPC ENOSPC
#define ENOSR ENOSR
#define ENOSTR ENOSTR
#define ENOSYS ENOSYS
#define ENOTBLK ENOTBLK
#define ENOTCONN ENOTCONN
#define ENOTDIR ENOTDIR
#define ENOTEMPTY ENOTEMPTY
#define ENOTNAM ENOTNAM
#define ENOTRECOVERABLE ENOTRECOVERABLE
#define ENOTSOCK ENOTSOCK
#define ENOTSUP ENOTSUP
#define ENOTTY ENOTTY
#define ENOTUNIQ ENOTUNIQ
#define ENXIO ENXIO
#define EOPNOTSUPP EOPNOTSUPP
#define EOVERFLOW EOVERFLOW
#define EOWNERDEAD EOWNERDEAD
#define EPERM EPERM
#define EPFNOSUPPORT EPFNOSUPPORT
#define EPIPE EPIPE
#define EPROCLIM EPROCLIM
#define EPROCUNAVAIL EPROCUNAVAIL
#define EPROGMISMATCH EPROGMISMATCH
#define EPROGUNAVAIL EPROGUNAVAIL
#define EPROTO EPROTO
#define EPROTONOSUPPORT EPROTONOSUPPORT
#define EPROTOTYPE EPROTOTYPE
#define EPWROFF EPWROFF
#define ERANGE ERANGE
#define EREMCHG EREMCHG
#define EREMOTE EREMOTE
#define EREMOTEIO EREMOTEIO
#define ERESTART ERESTART
#define ERFKILL ERFKILL
#define EROFS EROFS
#define ERPCMISMATCH ERPCMISMATCH
#define ESHLIBVERS ESHLIBVERS
#define ESHUTDOWN ESHUTDOWN
#define ESOCKTNOSUPPORT ESOCKTNOSUPPORT
#define ESPIPE ESPIPE
#define ESRCH ESRCH
#define ESRMNT ESRMNT
#define ESTALE ESTALE
#define ESTRPIPE ESTRPIPE
#define ETIME ETIME
#define ETIMEDOUT ETIMEDOUT
#define ETOOMANYREFS ETOOMANYREFS
#define ETXTBSY ETXTBSY
#define EUCLEAN EUCLEAN
#define EUNATCH EUNATCH
#define EUSERS EUSERS
#define EWOULDBLOCK EAGAIN
#define EXDEV EXDEV
#define EXFULL EXFULL
COSMOPOLITAN_C_END_ COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -48,7 +48,7 @@ struct timeval WindowsDurationToTimeVal(int64_t) nothrow;
struct timespec WindowsDurationToTimeSpec(int64_t) nothrow; struct timespec WindowsDurationToTimeSpec(int64_t) nothrow;
static inline struct NtFileTime MakeFileTime(int64_t x) { static inline struct NtFileTime MakeFileTime(int64_t x) {
return (struct NtFileTime){(uint32_t)x, x >> 32}; return (struct NtFileTime){(uint32_t)x, (uint32_t)(x >> 32)};
} }
static inline int64_t ReadFileTime(struct NtFileTime t) { static inline int64_t ReadFileTime(struct NtFileTime t) {

View file

@ -348,35 +348,41 @@ void __asan_unpoison(uintptr_t p, size_t n) {
bool __asan_is_valid(const void *p, size_t n) { bool __asan_is_valid(const void *p, size_t n) {
signed char k, *s, *e; signed char k, *s, *e;
if (n) { if (n) {
k = (uintptr_t)p & 7; if (p) {
s = (signed char *)(((uintptr_t)p >> 3) + 0x7fff8000); k = (uintptr_t)p & 7;
if (UNLIKELY(k)) { s = (signed char *)(((uintptr_t)p >> 3) + 0x7fff8000);
if (n && !(!*s || *s >= k + n)) return false; if (UNLIKELY(k)) {
++s, n -= MIN(8 - k, n); if (n && !(!*s || *s >= k + n)) return false;
} ++s, n -= MIN(8 - k, n);
e = s;
k = n & 7;
e += n >> 3;
for (; s + 8 <= e; s += 8) {
if ((uint64_t)(255 & s[0]) << 000 | (uint64_t)(255 & s[1]) << 010 |
(uint64_t)(255 & s[2]) << 020 | (uint64_t)(255 & s[3]) << 030 |
(uint64_t)(255 & s[4]) << 040 | (uint64_t)(255 & s[5]) << 050 |
(uint64_t)(255 & s[6]) << 060 | (uint64_t)(255 & s[7]) << 070) {
return false;
} }
} e = s;
while (s < e) { k = n & 7;
if (*s++) { e += n >> 3;
return false; for (; s + 8 <= e; s += 8) {
if ((uint64_t)(255 & s[0]) << 000 | (uint64_t)(255 & s[1]) << 010 |
(uint64_t)(255 & s[2]) << 020 | (uint64_t)(255 & s[3]) << 030 |
(uint64_t)(255 & s[4]) << 040 | (uint64_t)(255 & s[5]) << 050 |
(uint64_t)(255 & s[6]) << 060 | (uint64_t)(255 & s[7]) << 070) {
return false;
}
} }
} while (s < e) {
if (k) { if (*s++) {
if (!(!*s || *s >= k)) { return false;
return false; }
} }
if (k) {
if (!(!*s || *s >= k)) {
return false;
}
}
return true;
} else {
return false;
} }
} else {
return true;
} }
return true;
} }
bool __asan_is_valid_iov(const struct iovec *iov, int iovlen) { bool __asan_is_valid_iov(const struct iovec *iov, int iovlen) {

View file

@ -69,7 +69,7 @@ relegated void __check_fail(const char *suffix, const char *opstr,
} }
(dprintf)(STDERR_FILENO, "\t%s\n\t%s%s%s%s\n", strerror(lasterr), SUBTLE, (dprintf)(STDERR_FILENO, "\t%s\n\t%s%s%s%s\n", strerror(lasterr), SUBTLE,
getauxval(AT_EXECFN), __argc > 1 ? " \\" : "", RESET); program_invocation_name, __argc > 1 ? " \\" : "", RESET);
for (i = 1; i < __argc; ++i) { for (i = 1; i < __argc; ++i) {
(dprintf)(STDERR_FILENO, "\t\t%s%s\n", __argv[i], (dprintf)(STDERR_FILENO, "\t\t%s%s\n", __argv[i],

View file

@ -201,7 +201,7 @@ relegated static void ShowCrashReport(int err, int fd, int sig,
" %s\n", " %s\n",
RED2, RESET, TinyStrSignal(sig), RED2, RESET, TinyStrSignal(sig),
si ? GetSiCodeName(sig, si->si_code) : "???", hostname, si ? GetSiCodeName(sig, si->si_code) : "???", hostname,
getauxval(AT_EXECFN), strerror(err)); program_invocation_name, strerror(err));
if (uname(&names) != -1) { if (uname(&names) != -1) {
dprintf(fd, " %s %s %s %s\n", names.sysname, names.nodename, names.release, dprintf(fd, " %s %s %s %s\n", names.sysname, names.nodename, names.release,
names.version); names.version);

View file

@ -57,7 +57,6 @@ extern const unsigned char __oncrash_thunks[8][11];
void ShowCrashReports(void) { void ShowCrashReports(void) {
size_t i; size_t i;
struct sigaction sa; struct sigaction sa;
FindDebugBinary();
/* <SYNC-LIST>: showcrashreports.c, oncrashthunks.S, oncrash.c */ /* <SYNC-LIST>: showcrashreports.c, oncrashthunks.S, oncrash.c */
kCrashSigs[0] = SIGQUIT; /* ctrl+\ aka ctrl+break */ kCrashSigs[0] = SIGQUIT; /* ctrl+\ aka ctrl+break */
kCrashSigs[1] = SIGFPE; /* 1 / 0 */ kCrashSigs[1] = SIGFPE; /* 1 / 0 */

View file

@ -68,9 +68,11 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0) #if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_ COSMOPOLITAN_C_START_
#define NAN __builtin_nanf("") #define NAN __builtin_nanf("")
#define INFINITY __builtin_inff() #define INFINITY __builtin_inff()
#define HUGE_VAL __builtin_inff() #define HUGE_VAL __builtin_inf()
#define HUGE_VALF __builtin_inff()
#define HUGE_VALL __builtin_infl()
#if __FLT_EVAL_METHOD__ + 0 == 2 #if __FLT_EVAL_METHOD__ + 0 == 2
typedef long double float_t; typedef long double float_t;

View file

@ -16,23 +16,23 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/bits/safemacros.internal.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/mem/mem.h" #include "libc/mem/mem.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/sysv/errfuns.h"
/** /**
* Returns current working directory. * Returns current working directory.
* *
* If the PWD environment variable is set, that'll be returned (since * If the `PWD` environment variable is set, and it seems legit, then
* it's faster than issuing a system call). * that'll be returned.
* *
* @return pointer that must be free()'d, or NULL w/ errno * @return pointer that must be free()'d, or NULL w/ errno
*/ */
nodiscard char *get_current_dir_name(void) { nodiscard char *get_current_dir_name(void) {
char *buf, *res; const char *p;
if (!(buf = malloc(PATH_MAX))) return NULL; if ((p = getenv("PWD")) && _isabspath(p)) {
if (!(res = (getcwd)(buf, PATH_MAX))) free(buf); return strdup(p);
return res; } else {
return getcwd(0, 0);
}
} }

View file

@ -7,39 +7,39 @@
* @see GetFileInformationByHandle() * @see GetFileInformationByHandle()
* @see libc/sysv/consts.sh * @see libc/sysv/consts.sh
*/ */
#define kNtFileAttributeReadonly 0x00000001u #define kNtFileAttributeReadonly 0x00000001u
#define kNtFileAttributeHidden 0x00000002u #define kNtFileAttributeHidden 0x00000002u
#define kNtFileAttributeSystem 0x00000004u #define kNtFileAttributeSystem 0x00000004u
#define kNtFileAttributeVolumelabel 0x00000008u #define kNtFileAttributeVolumelabel 0x00000008u
#define kNtFileAttributeDirectory 0x00000010u #define kNtFileAttributeDirectory 0x00000010u
#define kNtFileAttributeArchive 0x00000020u #define kNtFileAttributeArchive 0x00000020u
/** /**
* NT File Attributes. * NT File Attributes.
*/ */
#define kNtFileAttributeDevice 0x00000040u #define kNtFileAttributeDevice 0x00000040u
#define kNtFileAttributeNormal 0x00000080u #define kNtFileAttributeNormal 0x00000080u
#define kNtFileAttributeTemporary 0x00000100u #define kNtFileAttributeTemporary 0x00000100u
#define kNtFileAttributeSparseFile 0x00000200u #define kNtFileAttributeSparseFile 0x00000200u
#define kNtFileAttributeReparsePoint 0x00000400u #define kNtFileAttributeReparsePoint 0x00000400u
#define kNtFileAttributeCompressed 0x00000800u #define kNtFileAttributeCompressed 0x00000800u
#define kNtFileAttributeOffline 0x00001000u #define kNtFileAttributeOffline 0x00001000u
#define kNtFileAttributeNotContentIndexed 0x00002000u #define kNtFileAttributeNotContentIndexed 0x00002000u
#define kNtFileAttributeEncrypted 0x00004000u #define kNtFileAttributeEncrypted 0x00004000u
/** /**
* NT File Flags. * NT File Flags.
*/ */
#define kNtFileFlagWriteThrough 0x80000000u #define kNtFileFlagWriteThrough 0x80000000u
#define kNtFileFlagOverlapped 0x40000000u #define kNtFileFlagOverlapped 0x40000000u
#define kNtFileFlagNoBuffering 0x20000000u #define kNtFileFlagNoBuffering 0x20000000u
#define kNtFileFlagRandomAccess 0x10000000u #define kNtFileFlagRandomAccess 0x10000000u
#define kNtFileFlagSequentialScan 0x08000000u #define kNtFileFlagSequentialScan 0x08000000u
#define kNtFileFlagDeleteOnClose 0x04000000u #define kNtFileFlagDeleteOnClose 0x04000000u
#define kNtFileFlagBackupSemantics 0x02000000u #define kNtFileFlagBackupSemantics 0x02000000u
#define kNtFileFlagPosixSemantics 0x01000000u #define kNtFileFlagPosixSemantics 0x01000000u
#define kNtFileFlagOpenReparsePoint 0x00200000u /* or symlink */ #define kNtFileFlagOpenReparsePoint 0x00200000u
#define kNtFileFlagOpenNoRecall 0x00100000u #define kNtFileFlagOpenNoRecall 0x00100000u
#define kNtFileFlagFirstPipeInstance 0x00080000u #define kNtFileFlagFirstPipeInstance 0x00080000u
#endif /* COSMOPOLITAN_LIBC_NT_ENUM_FILEFLAGANDATTRIBUTES_H_ */ #endif /* COSMOPOLITAN_LIBC_NT_ENUM_FILEFLAGANDATTRIBUTES_H_ */

Some files were not shown because too many files have changed in this diff Show more