Merge branch 'master' into import-mod

merging a85406da4c
This commit is contained in:
ahgamut 2022-04-30 11:59:42 +05:30
commit b60fb4fb6f
551 changed files with 15948 additions and 7664 deletions

Binary file not shown.

View file

@ -169,7 +169,7 @@ DEFAULT_LDFLAGS = \
--gc-sections \
--build-id=none \
--no-dynamic-linker \
-zmax-page-size=0x1000
-zmax-page-size=0x1000 #--cref -Map=$@.map
ZIPOBJ_FLAGS = \
-b$(IMAGE_BASE_VIRTUAL)

View file

@ -31,13 +31,6 @@ int ttysetraw(struct termios *conf, int64_t flags) {
conf->c_cflag &= ~(CSIZE | PARENB);
conf->c_cflag |= CS8;
conf->c_iflag |= IUTF8;
/* if (flags & kTtyLfToCrLf) { */
/* /\* conf->c_oflag &= ~(OLCUC | OCRNL | ONLRET | OFILL | OFDEL); *\/ */
/* /\* conf->c_oflag |= ONLCR | ONOCR; *\/ */
/* conf->c_oflag |= ONLCR; */
/* } else { */
/* conf->c_oflag &= ~OPOST; */
/* } */
if (!(flags & kTtySigs)) {
conf->c_iflag &= ~(IGNBRK | BRKINT);
conf->c_lflag &= ~(ISIG);

View file

@ -14,7 +14,7 @@
#include "libc/runtime/symbols.internal.h"
int main(int argc, char *argv[]) {
// ShowCrashReports();
ShowCrashReports();
if (IsDebuggerPresent(false)) {
kprintf("debugger found!%n");

View file

@ -43,7 +43,6 @@ void PrintUri(const char *path) {
}
int main(int argc, char *argv[]) {
ShowCrashReports();
int i;
while ((i = getopt(argc, argv, "?h")) != -1) {
switch (i) {

View file

@ -140,7 +140,7 @@ o/$(MODE)/examples/nesemu1.com: \
@$(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -S -O binary $< $@
@$(COMPILE) -ASYMTAB o/$(MODE)/tool/build/symtab.com \
-o o/$(MODE)/examples/.nesemu1/.symtab $<
@$(COMPILE) -AZIP -T$@ o/$(MODE)/third_party/zip/zip.com -9qj $@ \
@$(COMPILE) -AZIP -T$@ o/$(MODE)/third_party/zip/zip.com -0qj $@ \
o/$(MODE)/examples/.nesemu1/.symtab
o/$(MODE)/examples/hello.com.dbg: \
@ -151,14 +151,6 @@ o/$(MODE)/examples/hello.com.dbg: \
$(APE_NO_MODIFY_SELF)
@$(APELINK)
o/$(MODE)/examples/printargs.com.dbg: \
$(EXAMPLES_DEPS) \
o/$(MODE)/examples/printargs.o \
o/$(MODE)/examples/examples.pkg \
$(CRT) \
$(APE_NO_MODIFY_SELF)
@$(APELINK)
o/$(MODE)/examples/nesemu1.o: QUOTA += -M512m
$(EXAMPLES_OBJS): examples/examples.mk

View file

@ -7,6 +7,7 @@
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/dce.h"
#include "libc/log/log.h"
#include "libc/runtime/gc.internal.h"
#include "libc/stdio/stdio.h"
@ -67,7 +68,7 @@ void PrintImg(const char *path) {
}
int main(int argc, char *argv[]) {
ShowCrashReports();
if (!NoDebug()) ShowCrashReports();
int i;
while ((i = getopt(argc, argv, "?huas01234")) != -1) {
switch (i) {

View file

@ -153,7 +153,7 @@ void LoadWords(void) {
}
int main(int argc, char *argv[]) {
ShowCrashReports();
if (!NoDebug()) ShowCrashReports();
LoadWords();
SpellChecker();
return 0;

View file

@ -12,6 +12,7 @@
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/termios.h"
#include "libc/calls/struct/winsize.h"
#include "libc/dce.h"
#include "libc/log/check.h"
#include "libc/log/gdb.h"
#include "libc/log/log.h"
@ -152,7 +153,7 @@ void Draw(void) {
int main(int argc, char *argv[]) {
struct sigaction sa[2] = {{.sa_handler = OnShutdown},
{.sa_handler = OnInvalidate}};
ShowCrashReports();
if (!NoDebug()) ShowCrashReports();
Setup();
Enter();
GetTtySize();

View file

@ -7,30 +7,8 @@
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/bits/safemacros.internal.h"
#include "libc/calls/calls.h"
#include "libc/runtime/runtime.h"
int main() {
int pip[2];
char buf[PATH_MAX];
char *args[2] = {0};
if (strcmp(nulltoempty(getenv("TERM")), "dumb") && isatty(0) && isatty(1) &&
((args[0] = commandv("less", buf)) ||
(args[0] = commandv("more", buf)))) {
close(0);
close(2);
pipe(pip);
if (!vfork()) {
close(2);
execv(args[0], args);
_Exit(127);
}
close(0);
__printargs("");
close(2);
wait(0);
} else {
__printargs("");
}
}

View file

@ -36,12 +36,12 @@ static void SetLimit(int resource, uint64_t soft, uint64_t hard) {
lim.rlim_max = MIN(hard, old.rlim_max);
lim.rlim_cur = MIN(soft, lim.rlim_max);
if (!setrlimit(resource, &lim)) {
fprintf(stderr, "%snote: setrlimit(%s) downgraded to {%,ld, %,ld}\n",
fprintf(stderr, "%sNOTE: SETRLIMIT(%s) DOWNGRADED TO {%,ld, %,ld}\n",
__strace_rlimit_name(resource), lim.rlim_cur, lim.rlim_max);
return;
}
}
fprintf(stderr, "error: setrlimit(%s, %,ld, %,ld) failed %m%n",
fprintf(stderr, "ERROR: SETRLIMIT(%s, %,ld, %,ld) FAILED %m%n",
__strace_rlimit_name(resource), soft, hard);
exit(1);
}
@ -63,7 +63,7 @@ int main(int argc, char *argv[]) {
for (i = 0; i < RLIM_NLIMITS; ++i) {
rc = getrlimit(i, &rlim);
printf("setrlimit(%-20s, %,16ld, %,16ld) → %d %s\n",
printf("SETRLIMIT(%-20s, %,16ld, %,16ld) → %d %s\n",
__strace_rlimit_name(i), rlim.rlim_cur, rlim.rlim_max, rc,
!rc ? "" : strerror(errno));
}

View file

@ -7,8 +7,9 @@
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/calls/calls.h"
#include "libc/fmt/conv.h"
#include "libc/stdio/stdio.h"
#include "libc/fmt/itoa.h"
/**
* @fileoverview Prints sequence of numbers.
@ -16,6 +17,7 @@
int main(int argc, char *argv[]) {
long a, b, i;
char buf[21], *p;
switch (argc) {
case 2:
a = 1;
@ -29,6 +31,9 @@ int main(int argc, char *argv[]) {
return 1;
}
for (i = a; i <= b; ++i) {
printf("%ld\n", i);
p = buf;
p = FormatInt64(p, i);
*p++ = '\n';
write(1, buf, p - buf);
}
}

View file

@ -69,7 +69,7 @@ int main(int argc, char *argv[]) {
long double real;
char exebuf[PATH_MAX];
if (argc >= 2) {
if ((exepath = commandv(argv[1], exebuf))) {
if ((exepath = commandv(argv[1], exebuf, sizeof(exebuf)))) {
real = nowl();
argv[1] = exepath;
if ((ws = xvspawn(OnChild, argv + 1, &r)) != -1) {

View file

@ -20,7 +20,7 @@
int main(int argc, char *argv[]) {
int i;
for (i = 1; i < argc; ++i) {
if (touch(argv[i], 0644) == -1) {
if (touch(argv[i], 0666) == -1) {
fprintf(stderr, "ERROR: %s: %s\n", argv[i], strerror(errno));
exit(1);
}

View file

@ -17,6 +17,10 @@
#include "libc/sysv/consts/s.h"
#include "libc/sysv/consts/sig.h"
#define _POSIX_VERSION 200809L
#define _POSIX2_VERSION _POSIX_VERSION
#define _XOPEN_VERSION 700
#define EOF -1 /* end of file */
#define WEOF -1u /* end of file (multibyte) */
#define _IOFBF 0 /* fully buffered */
@ -48,14 +52,14 @@
#define S_ISLNK(mode) (((mode)&S_IFMT) == S_IFLNK)
#define S_ISSOCK(mode) (((mode)&S_IFMT) == S_IFSOCK)
#define WCOREDUMP(s) ((s)&0x80)
#define WEXITSTATUS(s) (((s)&0xff00) >> 8)
#define WCOREDUMP(s) (0x80 & (s))
#define WEXITSTATUS(s) ((0xff00 & (s)) >> 8)
#define WIFCONTINUED(s) ((s) == 0xffff)
#define WIFEXITED(s) (!WTERMSIG(s))
#define WIFSIGNALED(s) (((s)&0xffff) - 1u < 0xffu)
#define WIFSTOPPED(s) ((short)((((s)&0xffff) * 0x10001) >> 8) > 0x7f00)
#define WIFSIGNALED(s) ((0xffff & (s)) - 1u < 0xffu)
#define WIFSTOPPED(s) ((short)(((0xffff & (s)) * 0x10001) >> 8) > 0x7f00)
#define WSTOPSIG(s) WEXITSTATUS(s)
#define WTERMSIG(s) ((s)&0x7f)
#define WTERMSIG(s) (127 & (s))
#define W_STOPCODE(s) ((s) << 8 | 0177)
#if !(__ASSEMBLER__ + __LINKER__ + 0)
@ -75,7 +79,7 @@ bool isregularfile(const char *);
bool issymlink(const char *);
bool32 isatty(int) nosideeffect;
bool32 ischardev(int) nosideeffect;
char *commandv(const char *, char[hasatleast PATH_MAX]);
char *commandv(const char *, char *, size_t);
char *get_current_dir_name(void) dontdiscard;
char *getcwd(char *, size_t);
char *realpath(const char *, char *);
@ -119,14 +123,21 @@ int fsync(int);
int ftruncate(int, int64_t);
int getdents(unsigned, void *, unsigned, long *);
int getdomainname(char *, size_t);
int getegid(void) nosideeffect;
int geteuid(void) nosideeffect;
int getgid(void) nosideeffect;
int gethostname(char *, size_t);
int getloadavg(double *, int);
int getpgid(int);
int getpgrp(void) nosideeffect;
int getpid(void);
int gettid(void);
int getppid(void);
int getpriority(int, unsigned);
int getrlimit(int, struct rlimit *);
int getrusage(int, struct rusage *);
int getsid(int) nosideeffect;
int gettid(void);
int getuid(void) nosideeffect;
int kill(int, int);
int killpg(int, int);
int link(const char *, const char *) dontthrow;
@ -165,15 +176,18 @@ int rmdir(const char *);
int sched_getaffinity(int, uint64_t, void *);
int sched_setaffinity(int, uint64_t, const void *);
int sched_yield(void);
int seccomp(unsigned, unsigned, void *);
int setegid(uint32_t);
int seteuid(uint32_t);
int setgid(int);
int setpgrp(void);
int setpgid(int, int);
int setpgrp(void);
int setpriority(int, unsigned, int);
int setregid(uint32_t, uint32_t);
int setresgid(uint32_t, uint32_t, uint32_t);
int setresuid(uint32_t, uint32_t, uint32_t);
int getresgid(uint32_t *, uint32_t *, uint32_t *);
int getresuid(uint32_t *, uint32_t *, uint32_t *);
int setreuid(uint32_t, uint32_t);
int setrlimit(int, const struct rlimit *);
int setsid(void);
@ -192,6 +206,7 @@ int sysinfo(struct sysinfo *);
int touch(const char *, uint32_t);
int truncate(const char *, uint64_t);
int ttyname_r(int, char *, size_t);
int umask(int);
int uname(struct utsname *);
int unlink(const char *);
int unlink_s(const char **);
@ -206,9 +221,9 @@ long ptrace(int, ...);
long telldir(DIR *);
long times(struct tms *);
size_t GetFileSize(const char *);
ssize_t getfiledescriptorsize(int);
ssize_t copy_file_range(int, long *, int, long *, size_t, uint32_t);
ssize_t copyfd(int, int64_t *, int, int64_t *, size_t, uint32_t);
ssize_t getfiledescriptorsize(int);
ssize_t lseek(int, int64_t, unsigned);
ssize_t pread(int, void *, size_t, int64_t);
ssize_t preadv(int, struct iovec *, int, int64_t);
@ -222,17 +237,10 @@ ssize_t splice(int, int64_t *, int, int64_t *, size_t, uint32_t);
ssize_t vmsplice(int, const struct iovec *, int64_t, uint32_t);
ssize_t write(int, const void *, size_t);
struct dirent *readdir(DIR *);
uint32_t getegid(void) nosideeffect;
uint32_t geteuid(void) nosideeffect;
uint32_t getgid(void) nosideeffect;
uint32_t getpgrp(void) nosideeffect;
uint32_t getsid(int) nosideeffect;
uint32_t getuid(void) nosideeffect;
uint32_t umask(uint32_t);
void rewinddir(DIR *);
void sync(void);
int getloadavg(double *, int);
int seccomp(unsigned, unsigned, void *);
int pledge(const char *, const char *);
int clone(int (*)(void *), void *, size_t, int, void *, int *, void *, size_t,
int *);

View file

@ -65,6 +65,7 @@ $(LIBC_CALLS_A).pkg: \
$(LIBC_CALLS_A_OBJS) \
$(foreach x,$(LIBC_CALLS_A_DIRECTDEPS),$($(x)_A).pkg)
o/$(MODE)/libc/calls/vdsofunc.greg.o \
o/$(MODE)/libc/calls/directmap.o \
o/$(MODE)/libc/calls/directmap-nt.o \
o/$(MODE)/libc/calls/raise.o: \
@ -108,9 +109,12 @@ o//libc/calls/fcntl.o: \
o/$(MODE)/libc/calls/execl.o \
o/$(MODE)/libc/calls/execle.o \
o/$(MODE)/libc/calls/execlp.o \
o/$(MODE)/libc/calls/copyfile.o \
o/$(MODE)/libc/calls/execve-nt.o \
o/$(MODE)/libc/calls/execve-sysv.o \
o/$(MODE)/libc/calls/symlinkat-nt.o \
o/$(MODE)/libc/calls/readlinkat-nt.o \
o/$(MODE)/libc/calls/describeopenflags.greg.o \
o/$(MODE)/libc/calls/mkntenvblock.o: \
OVERRIDE_CPPFLAGS += \
-DSTACK_FRAME_UNLIMITED

View file

@ -26,6 +26,8 @@
#include "libc/nt/synchronization.h"
#include "libc/sysv/errfuns.h"
static typeof(sys_clock_gettime) *__clock_gettime = sys_clock_gettime;
/**
* Returns nanosecond time.
*
@ -52,7 +54,7 @@ noinstrument int clock_gettime(int clockid, struct timespec *ts) {
rc = einval();
} else if (!IsWindows()) {
e = errno;
if ((rc = sys_clock_gettime(clockid, ts))) {
if ((rc = __clock_gettime(clockid, ts))) {
errno = e;
ad = sys_gettimeofday((struct timeval *)ts, NULL, NULL);
assert(ad.ax != -1);
@ -72,3 +74,23 @@ noinstrument int clock_gettime(int clockid, struct timespec *ts) {
}
return rc;
}
/**
* Returns fast system clock_gettime() if it exists.
*/
void *__get_clock_gettime(void) {
void *vdso;
static bool once;
static void *result;
if (!once) {
if ((vdso = __vdsofunc("__vdso_clock_gettime"))) {
__clock_gettime = result = vdso;
}
once = true;
}
return result;
}
const void *const __clock_gettime_ctor[] initarray = {
__get_clock_gettime,
};

View file

@ -73,7 +73,9 @@ int close(int fd) {
}
}
}
if (!__vforked) __releasefd(fd);
if (!__vforked) {
__releasefd(fd);
}
}
STRACE("%s(%d) → %d% m", "close", fd, rc);
return rc;

View file

@ -43,15 +43,16 @@ static bool IsComDbgPath(const char *s, size_t n) {
READ64LE(s + n - 8) == READ64LE(".COM.DBG"));
}
static bool AccessCommand(const char *name, char path[hasatleast PATH_MAX],
static bool AccessCommand(const char *name, char *path, size_t pathsz,
size_t namelen, int *err, const char *suffix,
size_t pathlen) {
size_t suffixlen;
suffixlen = strlen(suffix);
if (pathlen + 1 + namelen + suffixlen + 1 > PATH_MAX) return false;
if (pathlen + 1 + namelen + suffixlen + 1 > pathsz) return false;
if (pathlen && (path[pathlen - 1] != '/' && path[pathlen - 1] != '\\')) {
path[pathlen] =
!IsWindows() ? '/' : memchr(path, '\\', pathlen) ? '\\' : '/';
path[pathlen] = !IsWindows() ? '/'
: memchr(path, '\\', pathlen) ? '\\'
: '/';
pathlen++;
}
memcpy(path + pathlen, name, namelen);
@ -61,7 +62,7 @@ static bool AccessCommand(const char *name, char path[hasatleast PATH_MAX],
return false;
}
static bool SearchPath(const char *name, char path[hasatleast PATH_MAX],
static bool SearchPath(const char *name, char *path, size_t pathsz,
size_t namelen, int *err, const char *suffix) {
char sep;
size_t i;
@ -70,11 +71,11 @@ static bool SearchPath(const char *name, char path[hasatleast PATH_MAX],
sep = IsWindows() && strchr(p, ';') ? ';' : ':';
for (;;) {
for (i = 0; p[i] && p[i] != sep; ++i) {
if (i < PATH_MAX) {
if (i < pathsz) {
path[i] = p[i];
}
}
if (AccessCommand(name, path, namelen, err, suffix, i)) {
if (AccessCommand(name, path, pathsz, namelen, err, suffix, i)) {
return true;
}
if (p[i] == sep) {
@ -86,36 +87,36 @@ static bool SearchPath(const char *name, char path[hasatleast PATH_MAX],
return false;
}
static bool FindCommand(const char *name, char pathbuf[hasatleast PATH_MAX],
size_t namelen, bool priorityonly, const char *suffix,
int *err) {
if (priorityonly &&
(memchr(name, '/', namelen) || memchr(name, '\\', namelen))) {
pathbuf[0] = 0;
return AccessCommand(name, pathbuf, namelen, err, suffix, 0);
static bool FindCommand(const char *name, char *pb, size_t pbsz, size_t namelen,
bool pri, const char *suffix, int *err) {
if (pri && (memchr(name, '/', namelen) || memchr(name, '\\', namelen))) {
pb[0] = 0;
return AccessCommand(name, pb, pbsz, namelen, err, suffix, 0);
}
if (IsWindows() && priorityonly) {
return AccessCommand(name, pathbuf, namelen, err, suffix,
stpcpy(pathbuf, kNtSystemDirectory) - pathbuf) ||
AccessCommand(name, pathbuf, namelen, err, suffix,
stpcpy(pathbuf, kNtWindowsDirectory) - pathbuf);
if (IsWindows() && pri &&
pbsz > max(strlen(kNtSystemDirectory), strlen(kNtWindowsDirectory))) {
return AccessCommand(name, pb, pbsz, namelen, err, suffix,
stpcpy(pb, kNtSystemDirectory) - pb) ||
AccessCommand(name, pb, pbsz, namelen, err, suffix,
stpcpy(pb, kNtWindowsDirectory) - pb);
}
return (IsWindows() && AccessCommand(name, pathbuf, namelen, err, suffix,
stpcpy(pathbuf, ".") - pathbuf)) ||
SearchPath(name, pathbuf, namelen, err, suffix);
return (IsWindows() &&
(pbsz > 1 && AccessCommand(name, pb, pbsz, namelen, err, suffix,
stpcpy(pb, ".") - pb))) ||
SearchPath(name, pb, pbsz, namelen, err, suffix);
}
static bool FindVerbatim(const char *name, char pathbuf[hasatleast PATH_MAX],
size_t namelen, bool priorityonly, int *err) {
return FindCommand(name, pathbuf, namelen, priorityonly, "", err);
static bool FindVerbatim(const char *name, char *pb, size_t pbsz,
size_t namelen, bool pri, int *err) {
return FindCommand(name, pb, pbsz, namelen, pri, "", err);
}
static bool FindSuffixed(const char *name, char pathbuf[hasatleast PATH_MAX],
size_t namelen, bool priorityonly, int *err) {
static bool FindSuffixed(const char *name, char *pb, size_t pbsz,
size_t namelen, bool pri, int *err) {
return !IsExePath(name, namelen) && !IsComPath(name, namelen) &&
!IsComDbgPath(name, namelen) &&
(FindCommand(name, pathbuf, namelen, priorityonly, ".com", err) ||
FindCommand(name, pathbuf, namelen, priorityonly, ".exe", err));
(FindCommand(name, pb, pbsz, namelen, pri, ".com", err) ||
FindCommand(name, pb, pbsz, namelen, pri, ".exe", err));
}
/**
@ -127,7 +128,7 @@ static bool FindSuffixed(const char *name, char pathbuf[hasatleast PATH_MAX],
* @asyncsignalsafe
* @vforksafe
*/
char *commandv(const char *name, char pathbuf[hasatleast PATH_MAX]) {
char *commandv(const char *name, char *pathbuf, size_t pathbufsz) {
int e, f;
char *res;
size_t namelen;
@ -136,25 +137,27 @@ char *commandv(const char *name, char pathbuf[hasatleast PATH_MAX]) {
efault();
} else if (!(namelen = strlen(name))) {
enoent();
} else if (namelen + 1 > PATH_MAX) {
} else if (namelen + 1 > pathbufsz) {
enametoolong();
} else {
e = errno;
f = ENOENT;
if ((IsWindows() && (FindSuffixed(name, pathbuf, namelen, true, &f) ||
FindVerbatim(name, pathbuf, namelen, true, &f) ||
FindSuffixed(name, pathbuf, namelen, false, &f) ||
FindVerbatim(name, pathbuf, namelen, false, &f))) ||
(!IsWindows() && (FindVerbatim(name, pathbuf, namelen, true, &f) ||
FindSuffixed(name, pathbuf, namelen, true, &f) ||
FindVerbatim(name, pathbuf, namelen, false, &f) ||
FindSuffixed(name, pathbuf, namelen, false, &f)))) {
if ((IsWindows() &&
(FindSuffixed(name, pathbuf, pathbufsz, namelen, true, &f) ||
FindVerbatim(name, pathbuf, pathbufsz, namelen, true, &f) ||
FindSuffixed(name, pathbuf, pathbufsz, namelen, false, &f) ||
FindVerbatim(name, pathbuf, pathbufsz, namelen, false, &f))) ||
(!IsWindows() &&
(FindVerbatim(name, pathbuf, pathbufsz, namelen, true, &f) ||
FindSuffixed(name, pathbuf, pathbufsz, namelen, true, &f) ||
FindVerbatim(name, pathbuf, pathbufsz, namelen, false, &f) ||
FindSuffixed(name, pathbuf, pathbufsz, namelen, false, &f)))) {
errno = e;
res = pathbuf;
} else {
errno = f;
}
}
STRACE("commandv(%#s, %p) → %#s% m", name, pathbuf, res);
STRACE("commandv(%#s, %p, %'zu) → %#s% m", name, pathbuf, pathbufsz, res);
return res;
}

View file

@ -28,6 +28,7 @@
#include "libc/nt/enum/filesharemode.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/filetime.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/consts/madv.h"
#include "libc/sysv/consts/o.h"

View file

@ -0,0 +1,38 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/itoa.h"
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/sol.h"
/**
* Describes clock_gettime() clock argument.
*/
char *DescribeClockName(int x) {
int i;
char *s;
_Alignas(char) static char buf[32];
if ((s = GetMagnumStr(kClockNames, x))) {
stpcpy(stpcpy(buf, "CLOCK_"), s);
return buf;
} else {
FormatInt32(buf, x);
return buf;
}
}

View file

@ -0,0 +1,41 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/itoa.h"
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/mem/alloca.h"
#include "libc/sysv/consts/sol.h"
/**
* Describes clock_gettime() clock argument.
*/
char *DescribeOpenFlags(int x) {
char *s;
int i, n;
struct DescribeFlags *d;
_Alignas(char) static char openflags[128];
// TODO(jart): unify DescribeFlags and MagnumStr data structures
for (n = 0; kOpenFlags[n].x != MAGNUM_TERMINATOR;) ++n;
d = alloca(n * sizeof(struct DescribeFlags));
for (i = 0; i < n; ++i) {
d[i].flag = MAGNUM_NUMBER(kOpenFlags, i);
d[i].name = MAGNUM_STRING(kOpenFlags, i);
}
return DescribeFlags(openflags, sizeof(openflags), d, n, "O_", x);
}

View file

@ -40,7 +40,7 @@ int execlp(const char *prog, const char *arg, ... /*, NULL*/) {
char **argv;
va_list va, vb;
char pathbuf[PATH_MAX];
if (!(exe = commandv(prog, pathbuf))) return -1;
if (!(exe = commandv(prog, pathbuf, sizeof(pathbuf)))) return -1;
va_copy(vb, va);
va_start(va, arg);
for (i = 0; va_arg(va, const char *); ++i) donothing;

View file

@ -33,7 +33,8 @@ int sys_execve(const char *prog, char *const argv[], char *const envp[]) {
shargs = alloca((i + 2) * sizeof(char *));
memcpy(shargs + 2, argv + 1, i * sizeof(char *));
if (IsFreebsd() || IsNetbsd()) {
shargs[0] = firstnonnull(commandv("bash", alloca(PATH_MAX)), _PATH_BSHELL);
shargs[0] = firstnonnull(commandv("bash", alloca(PATH_MAX), PATH_MAX),
_PATH_BSHELL);
} else {
shargs[0] = _PATH_BSHELL;
}

View file

@ -60,7 +60,7 @@ int execve(const char *prog, char *const argv[], char *const envp[]) {
if (i) kprintf(", ");
kprintf("%#s", envp[i]);
}
kprintf("})%n");
kprintf("})\n");
}
#endif
for (i = 3; i < g_fds.n; ++i) {

View file

@ -38,6 +38,6 @@ int execvpe(const char *prog, char *const argv[], char *const *envp) {
char *exe;
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, sizeof(pathbuf)))) return -1;
return execve(exe, argv, envp);
}

View file

@ -21,7 +21,8 @@
#include "libc/sysv/consts/at.h"
#include "libc/sysv/errfuns.h"
int sys_faccessat_nt(int dirfd, const char *path, int mode, uint32_t flags) {
textwindows int sys_faccessat_nt(int dirfd, const char *path, int mode,
uint32_t flags) {
char16_t path16[PATH_MAX];
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
return __fix_enotdir(ntaccesscheck(path16, mode), path16);

View file

@ -33,7 +33,7 @@
* file is a relative path, then file is opened relative to dirfd
* @param path is a filename or directory
* @param mode can be R_OK, W_OK, X_OK, F_OK
* @param flags should be 0
* @param flags can have AT_EACCESS, AT_SYMLINK_NOFOLLOW
* @return 0 if ok, or -1 and sets errno
* @asyncsignalsafe
*/

View file

@ -106,7 +106,7 @@ textwindows int sys_fstat_nt(int64_t handle, struct stat *st) {
st->st_size = (uint64_t)wst.nFileSizeHigh << 32 | wst.nFileSizeLow;
st->st_blksize = PAGESIZE;
st->st_dev = wst.dwVolumeSerialNumber;
st->st_rdev = wst.dwVolumeSerialNumber;
st->st_rdev = 0;
st->st_ino = (uint64_t)wst.nFileIndexHigh << 32 | wst.nFileIndexLow;
st->st_nlink = wst.nNumberOfLinks;
if (S_ISLNK(st->st_mode)) {

View file

@ -28,6 +28,7 @@
*/
int32_t sys_fstatat(int32_t dirfd, const char *path, struct stat *st,
int32_t flags) {
int rc;
void *p;
union metastat ms;
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();

View file

@ -28,15 +28,22 @@ textwindows char *sys_getcwd_nt(char *buf, size_t size) {
uint64_t w;
wint_t x, y;
uint32_t n, i, j;
char16_t name16[PATH_MAX + 1];
if ((n = GetCurrentDirectory(ARRAYLEN(name16), name16))) {
if (n <= PATH_MAX) {
tprecode16to8(buf, size, name16);
for (j = i = 0; i < n;) {
x = name16[i++] & 0xffff;
char16_t p[PATH_MAX];
if ((n = GetCurrentDirectory(ARRAYLEN(p), p))) {
if (4 + n + 1 <= size && 4 + n + 1 <= ARRAYLEN(p)) {
tprecode16to8(buf, size, p);
j = 0;
if (n >= 3 && isalpha(p[0]) && p[1] == ':' && p[2] == '\\') {
buf[j++] = '/';
buf[j++] = '/';
buf[j++] = '?';
buf[j++] = '/';
}
for (i = 0; i < n;) {
x = p[i++] & 0xffff;
if (!IsUcs2(x)) {
if (i < n) {
y = name16[i++] & 0xffff;
y = p[i++] & 0xffff;
x = MergeUtf16(x, y);
} else {
x = 0xfffd;

View file

@ -51,7 +51,7 @@ char *getcwd(char *buf, size_t size) {
}
} else if (weaken(malloc)) {
assert(!__vforked);
if (!size) size = PATH_MAX + 1;
if (!size) size = PATH_MAX;
if (!(p = weaken(malloc)(size))) {
STRACE("getcwd(%p, %'zu) %m", buf, size);
return 0;

View file

@ -19,13 +19,19 @@
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
/**
* Returns effective group ID of calling process.
* @return group id
*/
uint32_t getegid(void) {
int getegid(void) {
int rc;
if (!IsWindows()) {
rc = sys_getegid();
} else {
rc = getgid();
}
STRACE("%s() → %d% m", "getegid", rc);
return rc;
}

View file

@ -22,10 +22,15 @@
/**
* Returns effective user ID of calling process.
* @return user id
*/
uint32_t geteuid(void) {
int geteuid(void) {
int rc;
if (!IsWindows()) {
rc = sys_geteuid();
} else {
rc = getuid();
}
STRACE("%s() → %d% m", "geteuid", rc);
return rc;
}

View file

@ -16,28 +16,15 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/bits/bits.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/spinlock.h"
#include "libc/log/libfatal.internal.h"
#include "libc/macros.internal.h"
#include "libc/mem/alloca.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/runtime.h"
#include "libc/str/path.h"
#include "libc/str/str.h"
#include "libc/str/tpenc.h"
#include "libc/str/utf16.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/consts/auxv.h"
#include "libc/sysv/consts/ok.h"
#include "libc/sysv/consts/prot.h"
#define SIZE 1024
#define CTL_KERN 1
@ -45,97 +32,90 @@
#define KERN_PROC_PATHNAME_FREEBSD 12
#define KERN_PROC_PATHNAME_NETBSD 5
char program_executable_name[SIZE];
char program_executable_name[PATH_MAX];
static textwindows bool GetNtExePath(char exe[SIZE]) {
bool32 rc;
uint64_t w;
wint_t x, y;
uint32_t i, j;
char16_t path16[PATH_MAX + 1];
path16[0] = 0;
rc = GetModuleFileName(0, path16, ARRAYLEN(path16));
NTTRACE("GetModuleFileName(0, [%#hs]) → %hhhd", path16, rc);
if (!rc) return false;
for (i = j = 0; (x = path16[i++] & 0xffff);) {
if (!IsUcs2(x)) {
y = path16[i++] & 0xffff;
x = MergeUtf16(x, y);
}
if (x == '\\') x = '/';
w = tpenc(x);
do {
exe[j] = w;
if (++j == SIZE) {
return false;
}
} while ((w >>= 8));
}
exe[j] = 0;
return true;
}
static void ReadProgramExecutableName(char exe[SIZE], char *argv0,
uintptr_t *auxv) {
int e;
size_t m;
ssize_t n;
static inline void GetProgramExecutableNameImpl(char *p, char *e) {
char *q;
ssize_t rc;
size_t i, n;
union {
int cmd[4];
char *p, *t;
e = errno;
if (!IsWindows() || !GetNtExePath(exe)) {
for (p = 0; *auxv; auxv += 2) {
if (*auxv == AT_EXECFN) {
p = (char *)auxv[1];
break;
char16_t path16[PATH_MAX];
} u;
if (IsWindows()) {
n = GetModuleFileName(0, u.path16, ARRAYLEN(u.path16));
for (i = 0; i < n; ++i) {
if (u.path16[i] == '\\') {
u.path16[i] = '/';
}
}
n = 0;
if (!p) p = argv0;
if (p) {
if (!_isabspath(p)) {
if (getcwd(exe, SIZE - 1)) {
n = strlen(exe);
exe[n++] = '/';
if (isalpha(u.path16[0]) && u.path16[1] == ':' && u.path16[2] == '/') {
p[0] = '/';
p[1] = '/';
p[2] = '?';
p[3] = '/';
p += 4;
}
tprecode16to8(p, e - p, u.path16);
return;
}
if (__argc && (q = __argv[0]) && !sys_faccessat(AT_FDCWD, q, F_OK, 0)) {
if (*q != '/') {
if (q[0] == '.' && q[1] == '/') {
q += 2;
}
if (getcwd(p, e - p)) {
while (*p) ++p;
*p++ = '/';
}
}
for (; *p; ++p) {
if (n + 1 < SIZE) {
exe[n++] = *p;
for (i = 0; *q && p + 1 < e; ++p, ++q) {
*p = *q;
}
*p = 0;
return;
}
if ((rc = sys_readlinkat(AT_FDCWD, "/proc/self/exe", p, e - p - 1)) > 0 ||
(rc = sys_readlinkat(AT_FDCWD, "/proc/curproc/file", p, e - p - 1)) > 0) {
p[rc] = 0;
return;
}
if (IsFreebsd() || IsNetbsd()) {
u.cmd[0] = CTL_KERN;
u.cmd[1] = KERN_PROC;
if (IsFreebsd()) {
u.cmd[2] = KERN_PROC_PATHNAME_FREEBSD;
} else {
u.cmd[2] = KERN_PROC_PATHNAME_NETBSD;
}
u.cmd[3] = -1; // current process
n = e - p;
if (sysctl(u.cmd, ARRAYLEN(u.cmd), p, &n, 0, 0) != -1) {
return;
}
}
}
exe[n] = 0;
}
errno = e;
}
/**
* Returns absolute path of executable.
*
* This variable is initialized automatically at startup. The path is
* basically `argv[0]` except some extra vetting is done to provide
* stronger assurance that the path can be counted upon to exist.
*
* For example, if your program is executed as a relative path and then
* your program calls `chdir()`, then `argv[0]` will be incorrect; but
* `program_executable_name` will work, because it prefixed `getcwd()`
* early in the initialization phase.
*
* @see GetInterpreterExecutableName()
* @see program_invocation_short_name
* @see program_invocation_name
*/
char *GetProgramExecutableName(void) {
int e;
static bool once;
if (!once) {
ReadProgramExecutableName(program_executable_name, __argv[0], __auxv);
once = true;
e = errno;
GetProgramExecutableNameImpl(
program_executable_name,
program_executable_name + sizeof(program_executable_name));
errno = e;
}
return program_executable_name;
}
// try our best to memoize it before a chdir() happens
const void *const program_executable_name_init_ctor[] initarray = {
const void *const GetProgramExecutableNameCtor[] initarray = {
GetProgramExecutableName,
};

View file

@ -24,7 +24,7 @@
/**
* Returns process group id of calling process.
*/
uint32_t getpgrp(void) {
int getpgrp(void) {
int rc;
if (!IsWindows()) {
rc = sys_getpgrp();

51
libc/calls/getresgid.c Normal file
View file

@ -0,0 +1,51 @@
/*-*- 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 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
/**
* Gets real, effective, and "saved" group ids.
*
* @param real receives real user id, or null to do nothing
* @param effective receives effective user id, or null to do nothing
* @param saved receives saved user id, or null to do nothing
* @return 0 on success or -1 w/ errno
* @see setresuid()
*/
int getresgid(uint32_t *real, uint32_t *effective, uint32_t *saved) {
int rc, gid;
if (IsWindows()) {
gid = getgid();
if (real) *real = gid;
if (effective) *effective = gid;
if (saved) *saved = gid;
rc = 0;
} else if (saved) {
rc = sys_getresgid(real, effective, saved);
} else {
if (real) *real = sys_getgid();
if (effective) *effective = sys_getegid();
rc = 0;
}
STRACE("getresgid([%d], [%d], [%d]) → %d% m", real ? *real : 0,
effective ? *effective : 0, saved ? *saved : 0, rc);
return rc;
}

51
libc/calls/getresuid.c Normal file
View file

@ -0,0 +1,51 @@
/*-*- 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 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
/**
* Gets real, effective, and "saved" user ids.
*
* @param real receives real user id, or null to do nothing
* @param effective receives effective user id, or null to do nothing
* @param saved receives saved user id, or null to do nothing
* @return 0 on success or -1 w/ errno
* @see setresuid()
*/
int getresuid(uint32_t *real, uint32_t *effective, uint32_t *saved) {
int rc, uid;
if (IsWindows()) {
uid = getuid();
if (real) *real = uid;
if (effective) *effective = uid;
if (saved) *saved = uid;
rc = 0;
} else if (saved) {
rc = sys_getresuid(real, effective, saved);
} else {
if (real) *real = sys_getuid();
if (effective) *effective = sys_geteuid();
rc = 0;
}
STRACE("getresuid([%d], [%d], [%d]) → %d% m", real ? *real : 0,
effective ? *effective : 0, saved ? *saved : 0, rc);
return rc;
}

View file

@ -18,11 +18,14 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/sig.internal.h"
#include "libc/calls/struct/rusage.h"
#include "libc/fmt/conv.h"
#include "libc/intrin/spinlock.h"
#include "libc/nt/accounting.h"
#include "libc/nt/process.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/iocounters.h"
#include "libc/nt/struct/processmemorycounters.h"
#include "libc/nt/thread.h"
#include "libc/str/str.h"
@ -30,22 +33,32 @@
#include "libc/sysv/errfuns.h"
textwindows int sys_getrusage_nt(int who, struct rusage *usage) {
int64_t me, nsignals;
struct NtIoCounters iocount;
struct NtProcessMemoryCountersEx memcount;
struct NtFileTime ftExit, ftUser, ftKernel, ftCreation;
if (!usage) return efault();
if (who == 99) return enosys(); // @see libc/sysv/consts.sh
if (!usage) return 0;
me = GetCurrentProcess();
if (!(who == RUSAGE_SELF ? GetProcessTimes : GetThreadTimes)(
(who == RUSAGE_SELF ? GetCurrentProcess : GetCurrentThread)(),
&ftCreation, &ftExit, &ftKernel, &ftUser) ||
!GetProcessMemoryInfo(GetCurrentProcess(), &memcount, sizeof(memcount))) {
!GetProcessMemoryInfo(me, &memcount, sizeof(memcount)) ||
!GetProcessIoCounters(me, &iocount)) {
return __winerr();
}
_spinlock(&__sig_lock);
nsignals = __sig_count;
_spunlock(&__sig_lock);
*usage = (struct rusage){
.ru_utime = WindowsDurationToTimeVal(ReadFileTime(ftUser)),
.ru_stime = WindowsDurationToTimeVal(ReadFileTime(ftKernel)),
.ru_maxrss = memcount.PeakWorkingSetSize / 1024,
.ru_majflt = memcount.PageFaultCount,
.ru_inblock = iocount.ReadOperationCount,
.ru_oublock = iocount.WriteOperationCount,
.ru_nsignals = __sig_count,
};
return 0;
}

View file

@ -23,7 +23,7 @@
/**
* Creates session and sets the process group id.
*/
uint32_t getsid(int pid) {
int getsid(int pid) {
int rc;
rc = sys_getsid(pid);
STRACE("%s(%d) → %d% m", "getsid", pid, rc);

View file

@ -25,7 +25,7 @@
#include "libc/str/str.h"
#include "libc/time/struct/timezone.h"
int sys_gettimeofday_nt(struct timeval *tv, struct timezone *tz) {
textwindows int sys_gettimeofday_nt(struct timeval *tv, struct timezone *tz) {
struct NtFileTime ft;
GetSystemTimeAsFileTime(&ft);
if (tv) *tv = FileTimeToTimeVal(ft);

View file

@ -25,6 +25,8 @@
#include "libc/time/struct/timezone.h"
#include "libc/time/time.h"
static typeof(sys_gettimeofday) *__gettimeofday = sys_gettimeofday;
/**
* Returns system wall time in microseconds.
*
@ -40,7 +42,7 @@ int gettimeofday(struct timeval *tv, struct timezone *tz) {
return efault();
}
if (!IsWindows() && !IsMetal()) {
ad = sys_gettimeofday(tv, tz, NULL);
ad = __gettimeofday(tv, tz, NULL);
assert(ad.ax != -1);
if (SupportsXnu() && ad.ax && tv) {
tv->tv_sec = ad.ax;
@ -53,3 +55,14 @@ int gettimeofday(struct timeval *tv, struct timezone *tz) {
return sys_gettimeofday_nt(tv, tz);
}
}
static textstartup void __gettimeofday_init(void) {
void *vdso;
if ((vdso = __vdsofunc("__vdso_gettimeofday"))) {
__gettimeofday = vdso;
}
}
const void *const __gettimeofday_ctor[] initarray = {
__gettimeofday_init,
};

View file

@ -51,7 +51,7 @@ static textwindows dontinline uint32_t GetUserNameHash(void) {
* @asyncsignalsafe
* @vforksafe
*/
uint32_t getuid(void) {
int getuid(void) {
int rc;
if (!IsWindows()) {
rc = sys_getuid();
@ -71,7 +71,7 @@ uint32_t getuid(void) {
* @asyncsignalsafe
* @vforksafe
*/
uint32_t getgid(void) {
int getgid(void) {
int rc;
if (!IsWindows()) {
rc = sys_getgid();

View file

@ -88,7 +88,7 @@ int __reservefd(int) hidden;
void __releasefd(int) hidden;
int __ensurefds(int) hidden;
int64_t __getfdhandleactual(int) hidden;
void __printfds(void);
void __printfds(void) hidden;
forceinline bool __isfdopen(int fd) {
return 0 <= fd && fd < g_fds.n && g_fds.p[fd].kind != kFdEmpty;
@ -163,8 +163,11 @@ i32 sys_getpgid(i32) hidden;
i32 sys_getpgrp(void) hidden;
i32 sys_getppid(void) hidden;
i32 sys_getpriority(i32, u32) hidden;
i32 sys_getresgid(u32 *, u32 *, u32 *);
i32 sys_getresuid(u32 *, u32 *, u32 *);
i32 sys_getrlimit(i32, struct rlimit *) hidden;
i32 sys_getrusage(i32, struct rusage *) hidden;
i32 sys_getsid(int) hidden;
i32 sys_ioctl(i32, u64, ...) hidden;
i32 sys_kill(i32, i32, i32) hidden;
i32 sys_linkat(i32, const char *, i32, const char *, i32) hidden;
@ -183,6 +186,7 @@ i32 sys_openat(i32, const char *, i32, u32) hidden;
i32 sys_pause(void) hidden;
i32 sys_pipe(i32[hasatleast 2]) hidden;
i32 sys_pipe2(i32[hasatleast 2], u32) hidden;
i32 sys_pledge(const char *, const char *) hidden;
i32 sys_posix_openpt(i32) hidden;
i32 sys_renameat(i32, const char *, i32, const char *) hidden;
i32 sys_sched_setaffinity(i32, u64, const void *) hidden;
@ -191,8 +195,10 @@ i32 sys_setgid(i32) hidden;
i32 sys_setitimer(i32, const struct itimerval *, struct itimerval *) hidden;
i32 sys_setpgid(i32, i32) hidden;
i32 sys_setpriority(i32, u32, i32) hidden;
i32 sys_setresgid(uint32_t, uint32_t, uint32_t) hidden;
i32 sys_setresuid(uint32_t, uint32_t, uint32_t) hidden;
i32 sys_setregid(u32, u32) hidden;
i32 sys_setresgid(u32, u32, u32) hidden;
i32 sys_setresuid(u32, u32, u32) hidden;
i32 sys_setreuid(u32, u32) hidden;
i32 sys_setrlimit(i32, const struct rlimit *) hidden;
i32 sys_setsid(void) hidden;
i32 sys_setuid(i32) hidden;
@ -230,7 +236,6 @@ i64 sys_write(i32, const void *, u64) hidden;
u32 sys_getegid(void) hidden;
u32 sys_geteuid(void) hidden;
u32 sys_getgid(void) hidden;
u32 sys_getsid(int) hidden;
u32 sys_gettid(void) hidden;
u32 sys_getuid(void) hidden;
u32 sys_umask(u32) hidden;
@ -243,6 +248,8 @@ void sys_exit(int) hidden;
*/
void __onfork(void) hidden;
void *__vdsofunc(const char *) hidden;
void *__get_clock_gettime(void) hidden;
i32 __fixupnewfd(i32, i32) hidden;
void __restore_rt() hidden;
int sys_utimensat_xnu(int, const char *, const struct timespec *, int) hidden;
@ -326,6 +333,7 @@ int ioctl_tiocgwinsz_nt(struct Fd *, struct winsize *) hidden;
cosmopolitan § syscalls » windows nt » support
*/
bool __is_linux_2_6_23(void) hidden;
int64_t __fix_enotdir(int64_t, char16_t *) hidden;
int64_t __fix_enotdir3(int64_t, char16_t *, char16_t *) hidden;
bool _check_interrupts(bool, struct Fd *) hidden;
@ -337,9 +345,9 @@ bool isregularfile_nt(const char *) hidden;
bool issymlink_nt(const char *) hidden;
bool32 ntsetprivilege(i64, const char16_t *, u32) hidden;
char16_t *CreatePipeName(char16_t *) hidden;
int __mkntpath(const char *, char16_t[hasatleast PATH_MAX - 16]) hidden;
int __mkntpath2(const char *, char16_t[hasatleast PATH_MAX - 16], int) hidden;
int __mkntpathat(int, const char *, int, char16_t[PATH_MAX]) hidden;
int __mkntpath(const char *, char16_t[hasatleast PATH_MAX]) hidden;
int __mkntpath2(const char *, char16_t[hasatleast PATH_MAX], int) hidden;
int __mkntpathat(int, const char *, int, char16_t[hasatleast PATH_MAX]) hidden;
int sys_clock_gettime_nt(int, struct timespec *) hidden;
int ntaccesscheck(const char16_t *, u32) paramsnonnull() hidden;
int sys_getsetpriority_nt(int, int, int, int (*)(int));

View file

@ -19,6 +19,7 @@
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/termios.h"
#include "libc/calls/ttydefaults.h"
#include "libc/nt/console.h"
#include "libc/nt/enum/consolemodeflags.h"
#include "libc/nt/struct/consolescreenbufferinfoex.h"
@ -35,6 +36,23 @@ textwindows int ioctl_tcgets_nt(int ignored, struct termios *tio) {
outok = GetConsoleMode((out = __getfdhandleactual(1)), &outmode);
if (inok | outok) {
bzero(tio, sizeof(*tio));
tio->c_cflag |= CS8;
tio->c_cc[VINTR] = CTRL('C');
tio->c_cc[VQUIT] = CTRL('\\');
tio->c_cc[VERASE] = CTRL('?');
tio->c_cc[VKILL] = CTRL('U');
tio->c_cc[VEOF] = CTRL('D');
tio->c_cc[VMIN] = CTRL('A');
tio->c_cc[VSTART] = CTRL('Q');
tio->c_cc[VSTOP] = CTRL('S');
tio->c_cc[VSUSP] = CTRL('Z');
tio->c_cc[VREPRINT] = CTRL('R');
tio->c_cc[VDISCARD] = CTRL('O');
tio->c_cc[VWERASE] = CTRL('W');
tio->c_cc[VLNEXT] = CTRL('V');
if (inok) {
if (inmode & kNtEnableLineInput) {
tio->c_lflag |= ICANON;
@ -44,16 +62,21 @@ textwindows int ioctl_tcgets_nt(int ignored, struct termios *tio) {
}
if (inmode & kNtEnableProcessedInput) {
tio->c_lflag |= IEXTEN | ISIG;
if (tio->c_lflag | ECHO) {
tio->c_lflag |= ECHOE;
}
}
}
if (outok) {
if (outmode & kNtEnableProcessedOutput) {
tio->c_oflag |= OPOST;
}
if (!(outmode & kNtDisableNewlineAutoReturn)) {
tio->c_oflag |= ONLCR;
tio->c_oflag |= OPOST | ONLCR;
}
}
return 0;
} else {
return enotty();

View file

@ -17,8 +17,10 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/metatermios.internal.h"
#include "libc/calls/termios.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/nt/console.h"
#include "libc/nt/enum/consolemodeflags.h"
#include "libc/nt/enum/version.h"
@ -29,35 +31,54 @@
textwindows int ioctl_tcsets_nt(int ignored, uint64_t request,
const struct termios *tio) {
int64_t in, out;
bool32 inok, outok;
bool32 ok, inok, outok;
uint32_t inmode, outmode;
inok = GetConsoleMode((in = __getfdhandleactual(0)), &inmode);
outok = GetConsoleMode((out = __getfdhandleactual(1)), &outmode);
if (inok | outok) {
if (inok) {
if (request == TCSETSF) {
FlushConsoleInputBuffer(in);
}
inmode &=
~(kNtEnableLineInput | kNtEnableEchoInput | kNtEnableProcessedInput);
if (tio->c_lflag & ICANON) inmode |= kNtEnableLineInput;
if (tio->c_lflag & ECHO) inmode |= kNtEnableEchoInput;
if (tio->c_lflag & (IEXTEN | ISIG)) inmode |= kNtEnableProcessedInput;
inmode |= kNtEnableWindowInput;
if (tio->c_lflag & ICANON) {
inmode |= kNtEnableLineInput;
}
if (tio->c_lflag & ECHO) {
/*
* kNtEnableEchoInput can be used only if the ENABLE_LINE_INPUT mode
* is also enabled. --Quoth MSDN
*/
inmode |= kNtEnableEchoInput | kNtEnableLineInput;
}
if (tio->c_lflag & (IEXTEN | ISIG)) {
inmode |= kNtEnableProcessedInput;
}
if (NtGetVersion() >= kNtVersionWindows10) {
inmode |= kNtEnableVirtualTerminalInput;
}
SetConsoleMode(in, inmode);
ok = SetConsoleMode(in, inmode);
NTTRACE("SetConsoleMode(%p, %s) → %hhhd", in,
DescribeNtConsoleModeInputFlags(inmode), ok);
}
if (outok) {
outmode |= kNtEnableWrapAtEolOutput;
if (tio->c_oflag & OPOST) outmode |= kNtEnableProcessedOutput;
if (!(tio->c_oflag & ONLCR)) outmode |= kNtDisableNewlineAutoReturn;
outmode &= ~(kNtDisableNewlineAutoReturn);
outmode |= kNtEnableProcessedOutput;
if (!(tio->c_oflag & ONLCR)) {
outmode |= kNtDisableNewlineAutoReturn;
}
if (NtGetVersion() >= kNtVersionWindows10) {
outmode |= kNtEnableVirtualTerminalProcessing;
}
SetConsoleMode(out, outmode);
ok = SetConsoleMode(out, outmode);
NTTRACE("SetConsoleMode(%p, %s) → %hhhd", out,
DescribeNtConsoleModeOutputFlags(outmode), ok);
}
return 0;
} else {
return enotty();

View file

@ -83,11 +83,6 @@ int ioctl_tcsets(int fd, uint64_t request, ...) {
} else {
rc = einval();
}
if (rc != -1) {
if (__nomultics == 0 || __nomultics == 1) {
__nomultics = !(tio->c_oflag & OPOST);
}
}
STRACE("ioctl_tcsets(%d, %p, %p) → %d% m", fd, request, tio, rc);
return rc;
}

32
libc/calls/islinux.c Normal file
View file

@ -0,0 +1,32 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/sysv/consts/pr.h"
bool __is_linux_2_6_23(void) {
int rc;
if (!IsLinux()) return false;
asm volatile("syscall"
: "=a"(rc)
: "0"(157), "D"(PR_GET_SECCOMP)
: "rcx", "r11", "memory");
return rc != -EINVAL;
}

47
libc/calls/kclocknames.S Normal file
View file

@ -0,0 +1,47 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 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/fmt/magnumstrs.internal.h"
#include "libc/macros.internal.h"
.macro .e e s
.long \e - kClockNames
.long 1f - kClockNames
.rodata.str1.1
1: .string "\s"
.previous
.endm
.section .rodata
.align 4
.underrun
kClockNames:
.e CLOCK_REALTIME,"REALTIME"
.e CLOCK_MONOTONIC,"MONOTONIC"
.e CLOCK_MONOTONIC_RAW,"MONOTONIC_RAW"
.e CLOCK_REALTIME_COARSE,"REALTIME_COARSE"
.e CLOCK_MONOTONIC_COARSE,"MONOTONIC_COARSE"
.e CLOCK_PROCESS_CPUTIME_ID,"PROCESS_CPUTIME_ID"
.e CLOCK_TAI,"TAI"
.e CLOCK_PROF,"PROF"
.e CLOCK_BOOTTIME,"BOOTTIME"
.e CLOCK_REALTIME_ALARM,"REALTIME_ALARM"
.e CLOCK_BOOTTIME_ALARM,"BOOTTIME_ALARM"
.long MAGNUM_TERMINATOR
.endobj kClockNames,globl,hidden
.overrun

65
libc/calls/kopenflags.S Normal file
View file

@ -0,0 +1,65 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 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/fmt/magnumstrs.internal.h"
#include "libc/macros.internal.h"
.macro .e e s
.long \e - kOpenFlags
.long 1f - kOpenFlags
.rodata.str1.1
1: .string "\s"
.previous
.endm
.section .rodata
.align 4
.underrun
kOpenFlags:
.e O_RDWR,"RDWR" // order matters
.e O_RDONLY,"RDONLY" //
.e O_WRONLY,"WRONLY" //
.e O_ACCMODE,"ACCMODE" // mask of prev three
.e O_CREAT,"CREAT" //
.e O_EXCL,"EXCL" //
.e O_TRUNC,"TRUNC" //
.e O_CLOEXEC,"CLOEXEC" //
.e O_NONBLOCK,"NONBLOCK" //
.e O_DIRECT,"DIRECT" // no-op on xnu/openbsd
.e O_APPEND,"APPEND" // weird on nt
.e O_TMPFILE,"TMPFILE" // linux, windows
.e O_NOFOLLOW,"NOFOLLOW" // unix
.e O_SYNC,"SYNC" // unix
.e O_ASYNC,"ASYNC" // unix
.e O_NOCTTY,"NOCTTY" // unix
.e O_NOATIME,"NOATIME" // linux
.e O_EXEC,"EXEC" // free/openbsd
.e O_SEARCH,"SEARCH" // free/netbsd
.e O_DSYNC,"DSYNC" // linux/xnu/open/netbsd
.e O_RSYNC,"RSYNC" // linux/open/netbsd
.e O_PATH,"PATH" // linux
.e O_VERIFY,"VERIFY" // freebsd
.e O_SHLOCK,"SHLOCK" // bsd
.e O_EXLOCK,"EXLOCK" // bsd
.e O_RANDOM,"RANDOM" // windows
.e O_SEQUENTIAL,"SEQUENTIAL" // windows
.e O_COMPRESSED,"COMPRESSED" // windows
.e O_INDEXED,"INDEXED" // windows
.long MAGNUM_TERMINATOR
.endobj kOpenFlags,globl,hidden
.overrun

View file

@ -36,7 +36,7 @@
* @param path is a UTF-8 string, preferably relative w/ forward slashes
* @param mode can be, for example, 0755
* @return 0 on success or -1 w/ errno
* @error EEXIST, ENOTDIR, ENAMETOOLONG, EACCES
* @error ENAMETOOLONG if >246 characters on NT
* @asyncsignalsafe
* @see makedirs()
*/

View file

@ -18,10 +18,13 @@
*/
#include "libc/calls/internal.h"
#include "libc/nt/files.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
textwindows int sys_mkdirat_nt(int dirfd, const char *path, uint32_t mode) {
int e;
char16_t *p, path16[PATH_MAX];
/* if (strlen(path) > 248) return enametoolong(); */
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
if (CreateDirectory(path16, 0)) return 0;
return __fix_enotdir(-1, path16);

View file

@ -26,7 +26,9 @@
#define APPEND(c) \
do { \
cmdline[k++] = c; \
if (k == ARG_MAX) return e2big(); \
if (k == ARG_MAX / 2) { \
return e2big(); \
} \
} while (0)
static noasan bool NeedsQuotes(const char *s) {
@ -52,8 +54,8 @@ static noasan bool NeedsQuotes(const char *s) {
* @return freshly allocated lpCommandLine or NULL w/ errno
* @see libc/runtime/dosargv.c
*/
textwindows noasan int mkntcmdline(char16_t cmdline[ARG_MAX], const char *prog,
char *const argv[]) {
textwindows noasan int mkntcmdline(char16_t cmdline[ARG_MAX / 2],
const char *prog, char *const argv[]) {
char *arg;
uint64_t w;
wint_t x, y;

View file

@ -55,9 +55,9 @@ static noasan void InsertString(char **a, size_t i, char *s) {
* @param envp is an a NULL-terminated array of UTF-8 strings
* @param extravar is a VAR=val string we consider part of envp or NULL
* @return 0 on success, or -1 w/ errno
* @error E2BIG if total number of shorts exceeded ARG_MAX (0x8000)
* @error E2BIG if total number of shorts exceeded ARG_MAX/2 (32767)
*/
textwindows noasan int mkntenvblock(char16_t envvars[ARG_MAX],
textwindows noasan int mkntenvblock(char16_t envvars[ARG_MAX / 2],
char *const envp[], const char *extravar) {
bool v;
char *t;
@ -98,7 +98,9 @@ textwindows noasan int mkntenvblock(char16_t envvars[ARG_MAX],
w = EncodeUtf16(x);
do {
envvars[k++] = w & 0xffff;
if (k == ARG_MAX) return e2big();
if (k == ARG_MAX / 2) {
return e2big();
}
} while ((w >>= 16));
} while (x);
}

View file

@ -19,6 +19,7 @@
#include "libc/calls/internal.h"
#include "libc/calls/ntmagicpaths.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/macros.internal.h"
#include "libc/nt/systeminfo.h"
#include "libc/str/oldutf16.internal.h"
#include "libc/str/str.h"
@ -49,7 +50,7 @@ textwindows static const char *FixNtMagicPath(const char *path,
}
textwindows int __mkntpath(const char *path,
char16_t path16[hasatleast PATH_MAX - 16]) {
char16_t path16[hasatleast PATH_MAX]) {
return __mkntpath2(path, path16, -1);
}
@ -67,14 +68,13 @@ textwindows int __mkntpath(const char *path,
* @error ENAMETOOLONG
*/
textwindows int __mkntpath2(const char *path,
char16_t path16[hasatleast PATH_MAX - 16],
int flags) {
char16_t path16[hasatleast PATH_MAX], int flags) {
/*
* 1. Reserve +1 for NUL-terminator
* 2. Reserve +1 for UTF-16 overflow
* 3. Reserve 2 for SetCurrentDirectory trailing slash requirement
* 4. Reserve 10 for CreateNamedPipe "\\.\pipe\" prefix requirement
* 5. Reserve 13 for mkdir() i.e. 1+8+3+1, e.g. "\\ffffffff.xxx\0"
* 1. Need +1 for NUL-terminator
* 2. Need +1 for UTF-16 overflow
* 3. Need 2 for SetCurrentDirectory trailing slash requirement
* 5. Need 13 for mkdir() i.e. 1+8+3+1, e.g. "\\ffffffff.xxx\0"
* which is an "8.3 filename" from the DOS days
*/
char16_t *p;
const char *q;
@ -83,7 +83,12 @@ textwindows int __mkntpath2(const char *path,
path = FixNtMagicPath(path, flags);
p = path16;
q = path;
z = PATH_MAX - 16;
if (IsSlash(path[0]) && IsSlash(path[1]) && path[2] == '?' &&
IsSlash(path[3])) {
z = MIN(32767, PATH_MAX);
} else {
z = MIN(260, PATH_MAX);
}
if (IsSlash(q[0]) && q[1] == 't' && q[2] == 'm' && q[3] == 'p' &&
(IsSlash(q[4]) || !q[4])) {
m = GetTempPath(z, p);
@ -95,7 +100,7 @@ textwindows int __mkntpath2(const char *path,
m = 0;
}
n = tprecode8to16(p, z, q).ax;
if (n == z - 1) {
if (n >= z - 1) {
STRACE("path too long for windows: %#s", path);
return enametoolong();
}

View file

@ -25,7 +25,7 @@
#include "libc/sysv/errfuns.h"
int __mkntpathat(int dirfd, const char *path, int flags,
char16_t file[PATH_MAX]) {
char16_t file[hasatleast PATH_MAX]) {
char16_t dir[PATH_MAX];
uint32_t dirlen, filelen;
if ((filelen = __mkntpath2(path, file, flags)) == -1) return -1;

View file

@ -20,6 +20,7 @@
#include "libc/calls/sig.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/errno.h"
#include "libc/limits.h"
#include "libc/macros.internal.h"
#include "libc/nt/errors.h"
#include "libc/nt/nt/time.h"
@ -34,7 +35,7 @@ textwindows noinstrument int sys_nanosleep_nt(const struct timespec *req,
int64_t ms, sec, nsec;
if (__builtin_mul_overflow(req->tv_sec, 1000, &ms) ||
__builtin_add_overflow(ms, req->tv_nsec / 1000000, &ms)) {
ms = -1;
ms = INT64_MAX;
}
if (!ms && (req->tv_sec || req->tv_nsec)) {
ms = 1;

View file

@ -31,9 +31,9 @@
#include "libc/time/time.h"
static struct Now {
bool once;
uint64_t k0;
long double r0, cpn;
typeof(sys_clock_gettime) *clock_gettime;
} g_now;
static long double GetTimeSample(void) {
@ -73,22 +73,39 @@ void RefreshTime(void) {
now.cpn = MeasureNanosPerCycle();
now.r0 = dtime(CLOCK_REALTIME);
now.k0 = rdtsc();
now.once = true;
memcpy(&g_now, &now, sizeof(now));
}
long double ConvertTicksToNanos(uint64_t ticks) {
if (!g_now.once) RefreshTime();
return ticks * g_now.cpn; /* pico scale */
}
long double nowl_sys(void) {
static long double nowl_sys(void) {
return dtime(CLOCK_REALTIME);
}
long double nowl_art(void) {
uint64_t ticks;
if (!g_now.once) RefreshTime();
ticks = unsignedsubtract(rdtsc(), g_now.k0);
static long double nowl_art(void) {
uint64_t ticks = rdtsc() - g_now.k0;
return g_now.r0 + (1 / 1e9L * (ticks * g_now.cpn));
}
static long double nowl_vdso(void) {
long double secs;
struct timespec tv;
g_now.clock_gettime(CLOCK_REALTIME, &tv);
secs = tv.tv_nsec;
secs *= 1 / 1e9L;
secs += tv.tv_sec;
return secs;
}
long double nowl_setup(void) {
uint64_t ticks;
if ((g_now.clock_gettime = __get_clock_gettime())) {
nowl = nowl_vdso;
} else if (X86_HAVE(INVTSC)) {
RefreshTime();
nowl = nowl_art;
} else {
nowl = nowl_sys;
}
return nowl();
}
long double (*nowl)(void) = nowl_setup;

View file

@ -32,8 +32,13 @@
#include "libc/nt/struct/startupinfo.h"
struct SpawnBlock {
char16_t cmdline[ARG_MAX];
char16_t envvars[ARG_MAX];
union {
struct {
char16_t cmdline[ARG_MAX / 2];
char16_t envvars[ARG_MAX / 2];
};
char __pad[ROUNDUP(ARG_MAX / 2 * 2 * sizeof(char16_t), FRAMESIZE)];
};
};
/**
@ -68,20 +73,15 @@ textwindows int ntspawn(
struct NtProcessInformation *opt_out_lpProcessInformation) {
int rc;
int64_t handle;
size_t blocksize;
struct SpawnBlock *block;
char16_t prog16[PATH_MAX];
rc = -1;
block = NULL;
if (__mkntpath(prog, prog16) == -1) return -1;
blocksize = ROUNDUP(sizeof(*block), FRAMESIZE);
if ((handle = CreateFileMapping(
-1,
&(struct NtSecurityAttributes){sizeof(struct NtSecurityAttributes),
NULL, false},
pushpop(kNtPageReadwrite), 0, blocksize, NULL)) &&
if ((handle = CreateFileMapping(-1, 0, pushpop(kNtPageReadwrite), 0,
sizeof(*block), 0)) &&
(block = MapViewOfFileEx(handle, kNtFileMapRead | kNtFileMapWrite, 0, 0,
blocksize, NULL)) &&
sizeof(*block), 0)) &&
mkntcmdline(block->cmdline, prog, argv) != -1 &&
mkntenvblock(block->envvars, envp, extravar) != -1 &&
CreateProcess(prog16, block->cmdline, opt_lpProcessAttributes,

View file

@ -6,8 +6,8 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
int mkntcmdline(char16_t[ARG_MAX], const char *, char *const[]) hidden;
int mkntenvblock(char16_t[ARG_MAX], char *const[], const char *) hidden;
int mkntcmdline(char16_t[ARG_MAX / 2], const char *, char *const[]) hidden;
int mkntenvblock(char16_t[ARG_MAX / 2], char *const[], const char *) hidden;
int ntspawn(const char *, char *const[], char *const[], const char *,
struct NtSecurityAttributes *, struct NtSecurityAttributes *,
bool32, uint32_t, const char16_t *, const struct NtStartupInfo *,

83
libc/calls/oldbench.c Normal file
View file

@ -0,0 +1,83 @@
/*-*- 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 2020 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/bits.h"
#include "libc/bits/initializer.internal.h"
#include "libc/bits/safemacros.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/macros.internal.h"
#include "libc/nexgen32e/rdtsc.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/clock.h"
#include "libc/time/time.h"
static struct Now {
bool once;
uint64_t k0;
long double r0, cpn;
} g_now;
static long double GetTimeSample(void) {
uint64_t tick1, tick2;
long double time1, time2;
sched_yield();
time1 = dtime(CLOCK_REALTIME);
tick1 = rdtsc();
nanosleep(&(struct timespec){0, 1000000}, NULL);
time2 = dtime(CLOCK_REALTIME);
tick2 = rdtsc();
return (time2 - time1) * 1e9 / MAX(1, tick2 - tick1);
}
static long double MeasureNanosPerCycle(void) {
bool tc;
int i, n;
long double avg, samp;
tc = __time_critical;
__time_critical = true;
if (IsWindows()) {
n = 30;
} else {
n = 20;
}
for (avg = 1.0L, i = 1; i < n; ++i) {
samp = GetTimeSample();
avg += (samp - avg) / i;
}
__time_critical = tc;
STRACE("MeasureNanosPerCycle cpn*1000=%d", (long)(avg * 1000));
return avg;
}
static void Refresh(void) {
struct Now now;
now.cpn = MeasureNanosPerCycle();
now.r0 = dtime(CLOCK_REALTIME);
now.k0 = rdtsc();
now.once = true;
memcpy(&g_now, &now, sizeof(now));
}
long double ConvertTicksToNanos(uint64_t ticks) {
if (!g_now.once) Refresh();
return ticks * g_now.cpn; /* pico scale */
}

View file

@ -21,6 +21,7 @@
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/intrin/asan.internal.h"
#include "libc/log/log.h"
#include "libc/str/str.h"
@ -74,7 +75,8 @@ int openat(int dirfd, const char *file, int flags, ...) {
} else {
rc = efault();
}
STRACE("openat(%s, %#s, %#x, %#o) → %d% m", __strace_dirfd(buf, dirfd), file,
flags, (flags & (O_CREAT | O_TMPFILE)) ? mode : 0, rc);
STRACE("openat(%s, %#s, %s, %#o) → %d% m", __strace_dirfd(buf, dirfd), file,
DescribeOpenFlags(flags), (flags & (O_CREAT | O_TMPFILE)) ? mode : 0,
rc);
return rc;
}

View file

@ -8,8 +8,6 @@ COSMOPOLITAN_C_START_
typedef unsigned char u_char;
int pledge(const char *promises, const char *execpromises);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_COMPAT_OPENBSD_H_ */

View file

@ -23,6 +23,7 @@
#include "libc/nt/enum/fileflagandattributes.h"
#include "libc/nt/ipc.h"
#include "libc/nt/runtime.h"
#include "libc/sysv/consts/limits.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h"
@ -42,9 +43,9 @@ textwindows int sys_pipe_nt(int pipefd[2], unsigned flags) {
} else {
mode = kNtPipeTypeMessage | kNtPipeReadmodeMessage;
}
if ((hin = CreateNamedPipe(pipename,
kNtPipeAccessInbound | kNtFileFlagOverlapped, mode,
1, 512, 512, 0, &kNtIsInheritable)) != -1) {
if ((hin = CreateNamedPipe(
pipename, kNtPipeAccessInbound | kNtFileFlagOverlapped, mode, 1,
PIPE_BUF, PIPE_BUF, 0, &kNtIsInheritable)) != -1) {
if ((hout = CreateFile(pipename, kNtGenericWrite, 0, &kNtIsInheritable,
kNtOpenExisting, kNtFileFlagOverlapped, 0)) != -1) {
g_fds.p[reader].kind = kFdFile;

View file

@ -95,7 +95,7 @@ int poll(struct pollfd *fds, size_t nfds, int timeout_ms) {
DescribePollFlags(flagbuf[0], sizeof(flagbuf[0]), fds[i].events),
DescribePollFlags(flagbuf[1], sizeof(flagbuf[1]), fds[i].revents));
}
kprintf("%s}, %'zu, %'d) → %d% lm%n", i == 5 ? "..." : "", nfds,
kprintf("%s}, %'zu, %'d) → %d% lm\n", i == 5 ? "..." : "", nfds,
timeout_ms, rc);
}
}

View file

@ -118,7 +118,7 @@ ssize_t preadv(int fd, struct iovec *iov, int iovlen, int64_t off) {
} else {
kprintf(STRACE_PROLOGUE "preadv(%d, [", fd);
__strace_iov(iov, iovlen, rc != -1 ? rc : 0);
kprintf("], %d, %'ld) → %'ld% m%n", iovlen, off, rc);
kprintf("], %d, %'ld) → %'ld% m\n", iovlen, off, rc);
}
}
#endif

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/spinlock.h"
static const char *__fdkind2str(int x) {
switch (x) {
@ -44,6 +45,7 @@ static const char *__fdkind2str(int x) {
void __printfds(void) {
int i;
_spinlock(&__fds_lock);
for (i = 0; i < g_fds.n; ++i) {
if (!g_fds.p[i].kind) continue;
kprintf("%3d %s", i, __fdkind2str(g_fds.p[i].kind));
@ -53,6 +55,7 @@ void __printfds(void) {
if (g_fds.p[i].handle) kprintf(" handle=%ld", g_fds.p[i].handle);
if (g_fds.p[i].extra) kprintf(" extra=%ld", g_fds.p[i].extra);
if (g_fds.p[i].worker) kprintf(" worker=%p", g_fds.p[i].worker);
kprintf("%n", g_fds.p[i].zombie);
kprintf("\n");
}
_spunlock(&__fds_lock);
}

View file

@ -123,7 +123,7 @@ ssize_t pwritev(int fd, const struct iovec *iov, int iovlen, int64_t off) {
} else {
kprintf(STRACE_PROLOGUE "pwritev(%d, ", fd);
__strace_iov(iov, iovlen, rc != -1 ? rc : 0);
kprintf(", %d, %'ld) → %'ld% m%n", iovlen, off, rc);
kprintf(", %d, %'ld) → %'ld% m\n", iovlen, off, rc);
}
}
#endif

View file

@ -27,6 +27,7 @@
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/reparsedatabuffer.h"
#include "libc/str/str.h"
#include "libc/str/tpenc.h"
#include "libc/str/utf16.h"
#include "libc/sysv/errfuns.h"
@ -56,6 +57,12 @@ textwindows ssize_t sys_readlinkat_nt(int dirfd, const char *path, char *buf,
n = rdb->SymbolicLinkReparseBuffer.PrintNameLength / sizeof(char16_t);
p = (char16_t *)((char *)rdb->SymbolicLinkReparseBuffer.PathBuffer +
rdb->SymbolicLinkReparseBuffer.PrintNameOffset);
if (n >= 3 && isalpha(p[0]) && p[1] == ':' && p[2] == '\\') {
buf[j++] = '/';
buf[j++] = '/';
buf[j++] = '?';
buf[j++] = '/';
}
while (i < n) {
x = p[i++] & 0xffff;
if (!IsUcs2(x)) {

View file

@ -72,7 +72,7 @@ ssize_t readv(int fd, const struct iovec *iov, int iovlen) {
} else {
kprintf(STRACE_PROLOGUE "readv(%d, [", fd);
__strace_iov(iov, iovlen, rc != -1 ? rc : 0);
kprintf("], %d) → %'ld% m%n", iovlen, rc);
kprintf("], %d) → %'ld% m\n", iovlen, rc);
}
}
#endif

View file

@ -81,7 +81,7 @@ char *realpath(const char *filename, char *resolved)
ssize_t rc;
int e, up, check_dir=0;
size_t k, p, q, l, l0, cnt=0, nup=0;
char output[PATH_MAX], stack[PATH_MAX+1], *z;
char output[PATH_MAX], stack[PATH_MAX], *z;
if (!filename) {
einval();

View file

@ -88,9 +88,9 @@ int __reservefd(int start) {
/**
* Closes non-stdio file descriptors to free dynamic memory.
*/
static void __freefds(void) {
static void FreeFds(void) {
int i;
NTTRACE("__freefds()");
NTTRACE("FreeFds()");
for (i = 3; i < g_fds.n; ++i) {
if (g_fds.p[i].kind) {
close(i);
@ -104,10 +104,10 @@ static void __freefds(void) {
}
}
static textstartup void __freefds_init(void) {
atexit(__freefds);
static textstartup void FreeFdsInit(void) {
atexit(FreeFds);
}
const void *const __freefds_ctor[] initarray = {
__freefds_init,
const void *const FreeFdsCtor[] initarray = {
FreeFdsInit,
};

View file

@ -22,9 +22,6 @@
/**
* Sets effective group ID.
*/
int setegid(unsigned egid) {
int rc;
rc = setregid(-1, egid);
STRACE("%s(%u) → %d% m", "setegid", egid, rc);
return rc;
int setegid(uint32_t egid) {
return setregid(-1, egid);
}

View file

@ -22,9 +22,6 @@
/**
* Sets effective user ID.
*/
int seteuid(unsigned euid) {
int rc;
rc = setreuid(-1, euid);
STRACE("%s(%u) → %d% m", "seteuid", euid, rc);
return rc;
int seteuid(uint32_t euid) {
return setregid(euid, -1);
}

View file

@ -21,12 +21,16 @@
#include "libc/calls/strace.internal.h"
/**
* Sets effective group id of current process.
* Sets group id of current process.
* @return 0 on success or -1 w/ errno
*/
int setgid(int gid) {
int rc;
if (IsWindows() && gid == getgid()) {
rc = 0;
} else {
rc = sys_setgid(gid);
STRACE("%s(%d) → %d% m", "setgid", gid);
}
STRACE("setgid(%d) → %d% m", gid, rc);
return rc;
}

35
libc/calls/setregid.c Normal file
View file

@ -0,0 +1,35 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
/**
* Sets real and/or effective group ids.
*
* @param rgid is real group id or -1 to leave it unchanged
* @param egid is effective group id or -1 to leave it unchanged
* @return 0 on success or -1 w/ errno
*/
int setregid(uint32_t rgid, uint32_t egid) {
int rc;
rc = sys_setregid(rgid, egid);
STRACE("setregid(%d, %d) → %d% m", rgid, egid, rc);
return rc;
}

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
/**
* Sets real, effective, and "saved" group ids.
@ -25,9 +26,17 @@
* @param real sets real group id or -1 to do nothing
* @param effective sets effective group id or -1 to do nothing
* @param saved sets saved group id or -1 to do nothing
* @see setregid(), getauxval(AT_SECURE)
* @see setresuid(), getauxval(AT_SECURE)
* @raise ENOSYS on Windows NT
*/
int setresgid(uint32_t real, uint32_t effective, uint32_t saved) {
if (saved == -1) return setregid(real, effective);
return sys_setresgid(real, effective, saved);
int rc;
if (saved != -1) {
rc = sys_setresgid(real, effective, saved);
} else {
// polyfill xnu and netbsd
rc = sys_setregid(real, effective);
}
STRACE("setresgid(%d, %d, %d) → %d% m", real, effective, saved, rc);
return rc;
}

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
/**
* Sets real, effective, and "saved" user ids.
@ -25,9 +26,17 @@
* @param real sets real user id or -1 to do nothing
* @param effective sets effective user id or -1 to do nothing
* @param saved sets saved user id or -1 to do nothing
* @see setreuid(), getauxval(AT_SECURE)
* @see setresgid(), getauxval(AT_SECURE)
* @raise ENOSYS on Windows NT
*/
int setresuid(uint32_t real, uint32_t effective, uint32_t saved) {
if (saved == -1) return setreuid(real, effective);
return sys_setresuid(real, effective, saved);
int rc;
if (saved != -1) {
rc = sys_setresuid(real, effective, saved);
} else {
// polyfill xnu and netbsd
rc = sys_setreuid(real, effective);
}
STRACE("setresuid(%d, %d, %d) → %d% m", real, effective, saved, rc);
return rc;
}

35
libc/calls/setreuid.c Normal file
View file

@ -0,0 +1,35 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
/**
* Sets real and/or effective user ids.
*
* @param ruid is real user id or -1 to leave it unchanged
* @param euid is effective user id or -1 to leave it unchanged
* @return 0 on success or -1 w/ errno
*/
int setreuid(uint32_t ruid, uint32_t euid) {
int rc;
rc = sys_setreuid(ruid, euid);
STRACE("setreuid(%d, %d) → %d% m", ruid, euid, rc);
return rc;
}

View file

@ -21,12 +21,16 @@
#include "libc/calls/strace.internal.h"
/**
* Sets effective group id of current process.
* Sets user id of current process.
* @return 0 on success or -1 w/ errno
*/
int setuid(int uid) {
int rc;
if (IsWindows() && uid == getuid()) {
rc = 0;
} else {
rc = sys_setuid(uid);
STRACE("%s(%d) → %d% m", "setuid", uid);
}
STRACE("setuid(%d) → %d% m", uid, rc);
return rc;
}

View file

@ -24,6 +24,7 @@ struct Signals {
};
extern struct Signals __sig; // TODO(jart): Need TLS
extern long __sig_count;
bool __sig_check(bool) hidden;
bool __sig_handle(bool, int, int, ucontext_t *) hidden;

View file

@ -222,6 +222,7 @@ textwindows int __sig_add(int sig, int si_code) {
if (1 <= sig && sig <= NSIG) {
STRACE("enqueuing %G", sig);
_spinlock(&__sig_lock);
++__sig_count;
if ((mem = __sig_alloc())) {
mem->sig = sig;
mem->si_code = si_code;

View file

@ -18,6 +18,7 @@
*/
#include "libc/assert.h"
#include "libc/bits/bits.h"
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/sigbits.h"
@ -34,6 +35,8 @@
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/spinlock.h"
#include "libc/limits.h"
#include "libc/log/backtrace.internal.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"

View file

@ -22,13 +22,14 @@
/**
* Adds signal to set.
*
* @return true, false, or -1 w/ errno
* @return 0 on success, or -1 w/ errno
* @raises EINVAL if `1 sig NSIG` isn't the case
* @asyncsignalsafe
*/
int sigaddset(sigset_t *set, int sig) {
unsigned i = sig - 1;
if (i < sizeof(set->__bits) * 8) {
set->__bits[i >> 6] |= 1ull << (i & 63);
_Static_assert(sizeof(set->__bits[0]) * CHAR_BIT == 64, "");
if (1 <= sig && sig <= NSIG) {
set->__bits[(sig - 1) >> 6] |= 1ull << ((sig - 1) & 63);
return 0;
} else {
return einval();

21
libc/calls/sigcount.c Normal file
View file

@ -0,0 +1,21 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/sig.internal.h"
long __sig_count;

View file

@ -23,12 +23,13 @@
* Removes signal from set.
*
* @return 0 on success, or -1 w/ errno
* @raises EINVAL if `1 sig NSIG` isn't the case
* @asyncsignalsafe
*/
int sigdelset(sigset_t *set, int sig) {
unsigned i = sig - 1;
if (i < sizeof(set->__bits) * 8) {
set->__bits[i >> 6] &= ~(1ull << (i & 63));
_Static_assert(sizeof(set->__bits[0]) * CHAR_BIT == 64, "");
if (1 <= sig && sig <= NSIG) {
set->__bits[(sig - 1) >> 6] &= ~(1ull << ((sig - 1) & 63));
return 0;
} else {
return einval();

View file

@ -22,14 +22,15 @@
/**
* Returns true if signal is member of set.
*
* @return true, false, or -1 w/ errno
* @return 1 if set, 0 if not set, or -1 w/ errno
* @raises EINVAL if `1 sig NSIG` isn't the case
* @asyncsignalsafe
* @vforksafe
*/
int sigismember(const sigset_t *set, int sig) {
unsigned i = sig - 1;
if (i < sizeof(set->__bits) * 8) {
return (set->__bits[i >> 6] >> (i & 63)) & 1;
_Static_assert(sizeof(set->__bits[0]) * CHAR_BIT == 64, "");
if (1 <= sig && sig <= NSIG) {
return !!(set->__bits[(sig - 1) >> 6] & (1ull << ((sig - 1) & 63)));
} else {
return einval();
}

View file

@ -5,10 +5,10 @@
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/stat.h"
#define _KERNTRACE 1 /* not configurable w/ flag yet */
#define _POLLTRACE 1 /* not configurable w/ flag yet */
#define _KERNTRACE 0 /* not configurable w/ flag yet */
#define _POLLTRACE 0 /* not configurable w/ flag yet */
#define _DATATRACE 1 /* not configurable w/ flag yet */
#define _NTTRACE 1 /* not configurable w/ flag yet */
#define _NTTRACE 0 /* not configurable w/ flag yet */
#define STRACE_PROLOGUE "%rSYS %5P %'18T "
@ -19,7 +19,7 @@ COSMOPOLITAN_C_START_
#define STRACE(FMT, ...) \
do { \
if (__strace > 0) { \
__stracef(STRACE_PROLOGUE FMT "%n", ##__VA_ARGS__); \
__stracef(STRACE_PROLOGUE FMT "\n", ##__VA_ARGS__); \
} \
} while (0)
#else

View file

@ -10,7 +10,7 @@ struct stat { /* cosmo abi */
uint32_t st_mode; /* 24: octal file mask thing */
uint32_t st_uid; /* 28: user id of owner */
uint32_t st_gid; /* group id of owning group */
uint32_t st_flags; /* flags (bsd-only) */
uint32_t st_flags; /* nt/xnu/bsd-only */
uint64_t st_rdev; /* id of device if a special file */
int64_t st_size; /* bytes in file */
int64_t st_blksize; /* preferred chunking for underlying filesystem */
@ -19,7 +19,7 @@ struct stat { /* cosmo abi */
struct timespec st_mtim; /* modified time */
struct timespec st_ctim; /* complicated time */
struct timespec st_birthtim;
uint64_t st_gen;
uint64_t st_gen; /* xnu/bsd only */
};
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -29,7 +29,7 @@
/**
* Flushes all open file handles and, if possible, all disk drives.
*/
int sys_sync_nt(void) {
textwindows int sys_sync_nt(void) {
unsigned i;
int64_t volume;
uint32_t drives;

View file

@ -27,8 +27,8 @@
* @return previous mask
* @note always succeeds
*/
unsigned umask(unsigned newmask) {
unsigned oldmask;
int umask(int newmask) {
int oldmask;
if (!IsWindows()) {
oldmask = sys_umask(newmask);
} else {

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
@ -23,6 +24,7 @@
#include "libc/dce.h"
#include "libc/fmt/itoa.h"
#include "libc/intrin/asan.internal.h"
#include "libc/log/log.h"
#include "libc/nt/enum/computernameformat.h"
#include "libc/nt/struct/teb.h"
#include "libc/runtime/runtime.h"

View file

@ -0,0 +1,94 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/bits/bits.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/elf/scalar.h"
#include "libc/elf/struct/ehdr.h"
#include "libc/elf/struct/shdr.h"
#include "libc/elf/struct/sym.h"
#include "libc/log/libfatal.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/auxv.h"
#define LAZY_RHEL7_RELOCATION 0xfffff
#define GetStr(tab, rva) ((char *)(tab) + (rva))
#define GetSection(e, s) ((void *)((intptr_t)(e) + (size_t)(s)->sh_offset))
#define GetShstrtab(e) GetSection(e, GetShdr(e, (e)->e_shstrndx))
#define GetSectionName(e, s) GetStr(GetShstrtab(e), (s)->sh_name)
#define GetPhdr(e, i) \
((Elf64_Phdr *)((intptr_t)(e) + (e)->e_phoff + \
(size_t)(e)->e_phentsize * (i)))
#define GetShdr(e, i) \
((Elf64_Shdr *)((intptr_t)(e) + (e)->e_shoff + \
(size_t)(e)->e_shentsize * (i)))
static char *GetDynamicStringTable(Elf64_Ehdr *e, size_t *n) {
char *name;
Elf64_Half i;
Elf64_Shdr *shdr;
for (i = 0; i < e->e_shnum; ++i) {
shdr = GetShdr(e, i);
name = GetSectionName(e, GetShdr(e, i));
if (shdr->sh_type == SHT_STRTAB) {
name = GetSectionName(e, GetShdr(e, i));
if (name && READ64LE(name) == READ64LE(".dynstr")) {
if (n) *n = shdr->sh_size;
return GetSection(e, shdr);
}
}
}
return 0;
}
static Elf64_Sym *GetDynamicSymbolTable(Elf64_Ehdr *e, Elf64_Xword *n) {
Elf64_Half i;
Elf64_Shdr *shdr;
for (i = e->e_shnum; i > 0; --i) {
shdr = GetShdr(e, i - 1);
if (shdr->sh_type == SHT_DYNSYM) {
if (shdr->sh_entsize != sizeof(Elf64_Sym)) continue;
if (n) *n = shdr->sh_size / shdr->sh_entsize;
return GetSection(e, shdr);
}
}
return 0;
}
/**
* Returns Linux Kernel Virtual Dynamic Shared Object function address.
*/
void *__vdsofunc(const char *name) {
size_t m;
char *names;
Elf64_Ehdr *ehdr;
Elf64_Xword i, n;
Elf64_Sym *symtab, *sym;
if ((ehdr = (Elf64_Ehdr *)getauxval(AT_SYSINFO_EHDR)) &&
(names = GetDynamicStringTable(ehdr, &m)) &&
(symtab = GetDynamicSymbolTable(ehdr, &n))) {
for (i = 0; i < n; ++i) {
if (!__strcmp(names + symtab[i].st_name, name)) {
return (char *)ehdr + (symtab[i].st_value & LAZY_RHEL7_RELOCATION);
}
}
}
return 0;
}

View file

@ -95,7 +95,11 @@ static textwindows int sys_wait4_nt_impl(int pid, int *opt_out_wstatus,
return 0;
}
} else {
i = WaitForMultipleObjects(count, handles, false, -1);
i = WaitForMultipleObjects(count, handles, false,
__SIG_POLLING_INTERVAL_MS);
if (i == kNtWaitTimeout) {
continue;
}
}
if (i == kNtWaitFailed) {
STRACE("%s failed %u", "WaitForMultipleObjects", GetLastError());

View file

@ -48,6 +48,26 @@ typedef __UINT_FAST32_TYPE__ uint_fast32_t;
typedef __INT_FAST64_TYPE__ int_fast64_t;
typedef __UINT_FAST64_TYPE__ uint_fast64_t;
#define TIME_T_MAX __INT64_MAX__
#define UINT_FAST64_MAX __UINT_FAST64_MAX__
#define UINT_FAST8_MAX __UINT_FAST8_MAX__
#define INT_FAST32_MAX __INT_FAST32_MAX__
#define INT_FAST16_MAX __INT_FAST16_MAX__
#define UINT_FAST32_MAX __UINT_FAST32_MAX__
#define INT_FAST8_MAX __INT_FAST8_MAX__
#define INT_FAST64_MAX __INT_FAST64_MAX__
#define UINT_FAST16_MAX __UINT_FAST16_MAX__
#define TIME_T_MIN (-TIME_T_MAX - 1)
#define UINT_FAST64_MIN (-UINT_FAST64_MAX - 1)
#define UINT_FAST8_MIN (-UINT_FAST8_MAX - 1)
#define INT_FAST32_MIN (-INT_FAST32_MAX - 1)
#define INT_FAST16_MIN (-INT_FAST16_MAX - 1)
#define UINT_FAST32_MIN (-UINT_FAST32_MAX - 1)
#define INT_FAST8_MIN (-INT_FAST8_MAX - 1)
#define INT_FAST64_MIN (-INT_FAST64_MAX - 1)
#define UINT_FAST16_MIN (-UINT_FAST16_MAX - 1)
#define atomic_bool _Atomic(_Bool)
#define atomic_bool32 atomic_int_fast32_t
#define atomic_char _Atomic(char)

View file

@ -79,7 +79,7 @@ ssize_t writev(int fd, const struct iovec *iov, int iovlen) {
} else {
kprintf(STRACE_PROLOGUE "writev(%d, ", fd);
__strace_iov(iov, iovlen, rc != -1 ? rc : 0);
kprintf(", %d) → %'ld% m%n", iovlen, rc);
kprintf(", %d) → %'ld% m\n", iovlen, rc);
}
}
#endif

View file

@ -82,6 +82,39 @@ complex long double clogl(complex long double);
complex long double conjl(complex long double);
complex long double cpowl(complex long double, complex long double);
#ifndef __cplusplus
#define __CIMAG(x, t) \
(+(union { \
_Complex t __z; \
t __xy[2]; \
}){(_Complex t)(x)} \
.__xy[1])
#define creal(x) ((double)(x))
#define crealf(x) ((float)(x))
#define creall(x) ((long double)(x))
#define cimag(x) __CIMAG(x, double)
#define cimagf(x) __CIMAG(x, float)
#define cimagl(x) __CIMAG(x, long double)
#endif
#ifdef __GNUC__
#define _Complex_I (__extension__(0.0f + 1.0fi))
#else
#define _Complex_I (0.0f + 1.0fi)
#endif
#ifdef _Imaginary_I
#define __CMPLX(x, y, t) ((t)(x) + _Imaginary_I * (t)(y))
#elif defined(__clang__)
#define __CMPLX(x, y, t) (+(_Complex t){(t)(x), (t)(y)})
#else
#define __CMPLX(x, y, t) (__builtin_complex((t)(x), (t)(y)))
#endif
#define CMPLX(x, y) __CMPLX(x, y, double)
#define CMPLXF(x, y) __CMPLX(x, y, float)
#define CMPLXL(x, y) __CMPLX(x, y, long double)
#endif /* C11 */
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -48,10 +48,10 @@ int LookupProtoByName(const char *protoname, char *buf, size_t bufsize,
const char *filepath) {
FILE *f;
char *line;
char pathbuf[PATH_MAX];
const char *path;
size_t linesize;
int found, result;
char pathbuf[PATH_MAX];
char *name, *number, *alias, *comment, *tok;
if (!(path = filepath)) {
path = "/etc/protocols";

View file

@ -52,10 +52,10 @@ int LookupProtoByNumber(const int protonum, char *buf, size_t bufsize,
const char *filepath) {
FILE *f;
char *line;
char pathbuf[PATH_MAX];
const char *path;
size_t linesize;
int found;
size_t linesize;
const char *path;
char pathbuf[PATH_MAX];
char *name, *number, *comment, *tok;
if (!(path = filepath)) {
path = "/etc/protocols";

View file

@ -53,10 +53,10 @@ int LookupServicesByName(const char *servname, char *servproto,
const char *filepath) {
FILE *f;
char *line;
char pathbuf[PATH_MAX];
const char *path;
size_t linesize;
int found, result;
char pathbuf[PATH_MAX];
char *name, *port, *proto, *alias, *comment, *tok;
if (!(path = filepath)) {
path = "/etc/services";

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