Improve Libc by making Python work even better

Actually Portable Python is now outperforming the Python binaries
that come bundled with Linux distros, at things like HTTP serving.
You can now have a fully featured Python install in just one .com
file that runs on six operating systems and is about 10mb in size.
With tuning, the tiniest is ~1mb. We've got most of the libraries
working, including pysqlite, and the repl now feels very pleasant.
The things you can't do quite yet are: threads and shared objects
but that can happen in the future, if the community falls in love
with this project and wants to see it developed further. Changes:

- Add siginterrupt()
- Add sqlite3 to Python
- Add issymlink() helper
- Make GetZipCdir() faster
- Add tgamma() and finite()
- Add legacy function lutimes()
- Add readlink() and realpath()
- Use heap allocations when appropriate
- Reorganize Python into two-stage build
- Save Lua / Python shell history to dotfile
- Integrate Python Lib embedding into linkage
- Make isregularfile() and isdirectory() go faster
- Make Python shell auto-completion work perfectly
- Make crash reports work better if changed directory
- Fix Python+NT open() / access() flag overflow error
- Disable Python tests relating to \N{LONG NAME} syntax
- Have Python REPL copyright() show all notice embeddings

The biggest technical challenge at the moment is working around
when Python tries to be too clever about filenames.
This commit is contained in:
Justine Tunney 2021-08-18 14:21:30 -07:00
parent 98ccbf44b1
commit 8af197560e
179 changed files with 6728 additions and 10430 deletions

View file

@ -1549,6 +1549,7 @@ kernel: movabs $ape_stack_vaddr,%rsp
.type __test_end,@object
.section .commentprologue,"a",@progbits
.globl kLegalNotices
.type kLegalNotices,@object
.hidden kLegalNotices
kLegalNotices:/*

Binary file not shown.

View file

@ -78,8 +78,10 @@ o/$(MODE)/%.pkg: ; @$(COMPILE) -APACKAGE -T$@ $(PKG) $(OUTPUT_
o/$(MODE)/%.zip.o: % ; @$(COMPILE) -AZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $<
o/$(MODE)/%-gcc.asm: %.c ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $<
o/$(MODE)/%-clang.asm: %.c ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $< || echo / need $(CLANG) >$@
o/$(MODE)/%.lua: %.lua o/$(MODE)/third_party/lua/luac.com
@$(COMPILE) -ALUAC -T$@ o/$(MODE)/third_party/lua/luac.com -s -o $@ $<
o/$(MODE)/%-clang.asm: CC = $(CLANG)
o/$(MODE)/%.pyc: %.py o/$(MODE)/third_party/python/pycomp
@$(COMPILE) -APYCOMP o/$(MODE)/third_party/python/pycomp $(PYFLAGS) -o $@ $<
o/$(MODE)/%.lua: %.lua o/$(MODE)/third_party/lua/luac
@$(COMPILE) -ALUAC -T$@ o/$(MODE)/third_party/lua/luac.com -s -o $@ $<

View file

@ -71,6 +71,7 @@ bool fileexists(const char *);
bool isdirectory(const char *);
bool isexecutable(const char *);
bool isregularfile(const char *);
bool issymlink(const char *);
bool32 isatty(int) nosideeffect;
bool32 ischardev(int) nosideeffect;
char *commandv(const char *, char[hasatleast PATH_MAX]);
@ -128,6 +129,7 @@ int killpg(int, int);
int link(const char *, const char *) nothrow;
int linkat(int, const char *, int, const char *, uint32_t);
int lstat(const char *, struct stat *);
int lutimes(const char *, const struct timeval[2]);
int madvise(void *, uint64_t, int);
int mkdir(const char *, uint32_t);
int mkdirat(int, const char *, uint32_t);
@ -152,7 +154,6 @@ int posix_fadvise(int, uint64_t, uint64_t, int);
int posix_madvise(void *, uint64_t, int);
int prctl();
int raise(int);
int readlink(const char *, char *, size_t);
int reboot(int);
int remove(const char *);
int rename(const char *, const char *);
@ -176,6 +177,7 @@ int setsid(void);
int setuid(uint32_t);
int sigaction(int, const struct sigaction *, struct sigaction *);
int sigignore(int);
int siginterrupt(int, int);
int sigprocmask(int, const struct sigset *, struct sigset *);
int sigqueue(int, int, const union sigval);
int sigsuspend(const struct sigset *);
@ -213,6 +215,7 @@ ssize_t pwrite(int, const void *, size_t, int64_t);
ssize_t pwritev(int, const struct iovec *, int, int64_t);
ssize_t read(int, void *, size_t);
ssize_t readansi(int, char *, size_t);
ssize_t readlink(const char *, char *, size_t);
ssize_t readlinkat(int, const char *, char *, size_t);
ssize_t splice(int, int64_t *, int, int64_t *, size_t, uint32_t);
ssize_t vmsplice(int, const struct iovec *, int64_t, uint32_t);

View file

@ -23,6 +23,7 @@
#include "libc/errno.h"
#include "libc/nt/files.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/errfuns.h"
/**
@ -38,7 +39,7 @@ bool fileexists(const char *path) {
uint16_t path16[PATH_MAX];
if (!IsWindows()) {
olderr = errno;
rc = stat(path, &st);
rc = __sys_fstatat(AT_FDCWD, path, &st, 0);
if (rc == -1 && (errno == ENOENT || errno == ENOTDIR)) {
errno = olderr;
}

View file

@ -20,13 +20,50 @@
#include "libc/macros.internal.h"
#include "libc/nt/files.h"
#include "libc/str/str.h"
#include "libc/str/tpenc.h"
#include "libc/str/utf16.h"
#include "libc/sysv/errfuns.h"
textwindows char *sys_getcwd_nt(char *buf, size_t size) {
char16_t name16[PATH_MAX];
if (GetCurrentDirectory(ARRAYLEN(name16), name16)) {
tprecode16to8(buf, size, name16);
return buf;
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;
if (!IsUcs2(x)) {
if (i < n) {
y = name16[i++] & 0xffff;
x = MergeUtf16(x, y);
} else {
x = 0xfffd;
}
}
if (x < 0200) {
if (x == '\\') {
x = '/';
}
w = x;
} else {
w = tpenc(x);
}
do {
if (j < size) {
buf[j++] = w;
}
w >>= 8;
} while (w);
}
if (j < size) {
buf[j] = 0;
return buf;
}
}
erange();
return NULL;
} else {
__winerr();
return NULL;

View file

@ -26,7 +26,7 @@ textwindows int gethostname_nt(char *name, size_t len) {
uint32_t nSize;
char16_t name16[256];
nSize = ARRAYLEN(name16);
if (GetComputerNameEx(kNtComputerNameDnsHostname, name16, &nSize)) {
if (GetComputerNameEx(kNtComputerNamePhysicalDnsHostname, name16, &nSize)) {
tprecode16to8(name, len, name16);
return 0;
} else {

View file

@ -199,6 +199,8 @@ i64 sys_ptrace(int, i32, void *, void *) hidden;
i64 sys_pwrite(i32, const void *, u64, i64, i64) hidden;
i64 sys_pwritev(i32, const struct iovec *, i32, i64, i64) hidden;
i64 sys_read(i32, void *, u64) hidden;
i64 sys_readlink(const char *, char *, u64) hidden;
i64 sys_readlinkat(int, const char *, char *, u64) hidden;
i64 sys_sendfile(i32, i32, i64 *, u64) hidden;
i64 sys_splice(i32, i64 *, i32, i64 *, u64, u32) hidden;
i64 sys_vmsplice(i32, const struct iovec *, i64, u32) hidden;
@ -290,6 +292,7 @@ int sys_utimensat_nt(int, const char *, const struct timespec *, int) 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_write_nt(struct Fd *, const struct iovec *, size_t, ssize_t) hidden;
ssize_t sys_readlinkat_nt(int, const char *, char *, size_t) hidden;
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § syscalls » windows nt » support
@ -312,6 +315,9 @@ unsigned __wincrash_nt(struct NtExceptionPointers *);
ssize_t sys_readv_nt(struct Fd *, const struct iovec *, int) hidden;
ssize_t sys_writev_nt(struct Fd *, const struct iovec *, int) hidden;
char16_t *CreatePipeName(char16_t *) hidden;
bool isdirectory_nt(const char *) hidden;
bool isregularfile_nt(const char *) hidden;
bool issymlink_nt(const char *) hidden;
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § syscalls » metal

View file

@ -51,10 +51,12 @@ int ioctl(int, uint64_t, ...);
ReZ = ioctl_siocgifdstaddr(FD, __VA_ARGS__); \
} else if (CMP(REQUEST, SIOCGIFFLAGS)) { \
ReZ = ioctl_siocgifflags(FD, __VA_ARGS__); \
} else if (CMP(REQUEST, FIONBIO)) { \
ReZ = ioctl_default(FD, REQUEST, __VA_ARGS__); \
} else if (CMP(REQUEST, FIOCLEX)) { \
ReZ = ioctl_fioclex(FD); \
ReZ = ioctl_fioclex(FD, REQUEST); \
} else if (CMP(REQUEST, FIONCLEX)) { \
ReZ = ioctl_fionclex(FD); \
ReZ = ioctl_fioclex(FD, REQUEST); \
} else { \
ReZ = DEFAULT; \
} \
@ -76,8 +78,7 @@ 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 ioctl_fionclex(int);
int ioctl_fioclex(int, int);
#endif /* GNUC && !ANSI */
COSMOPOLITAN_C_END_

View file

@ -18,12 +18,17 @@
*/
#include "libc/calls/internal.h"
#include "libc/calls/ioctl.h"
#include "libc/sysv/consts/fio.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h"
textwindows int ioctl_fioclex_nt(int fd) {
textwindows int ioctl_fioclex_nt(int fd, int req) {
if (__isfdopen(fd)) {
g_fds.p[fd].flags |= O_CLOEXEC;
if (req == FIOCLEX) {
g_fds.p[fd].flags |= O_CLOEXEC;
} else {
g_fds.p[fd].flags &= ~O_CLOEXEC;
}
return 0;
} else {
return ebadf();

View file

@ -20,17 +20,17 @@
#include "libc/calls/ioctl.h"
#include "libc/dce.h"
int ioctl_fioclex_nt(int);
int ioctl_fioclex_nt(int, int);
/**
* Sets "close on exec" on file descriptor the fast way.
*
* @see ioctl(fd, FIOCLEX, 0) dispatches here
*/
int ioctl_fioclex(int fd) {
int ioctl_fioclex(int fd, int req) {
if (!IsWindows()) {
return sys_ioctl(fd, FIOCLEX, 0);
return sys_ioctl(fd, req, 0);
} else {
return ioctl_fioclex_nt(fd);
return ioctl_fioclex_nt(fd, req);
}
}

View file

@ -0,0 +1,36 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 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/calls.h"
#include "libc/calls/internal.h"
#include "libc/nt/enum/fileflagandattributes.h"
#include "libc/nt/files.h"
/**
* Returns true if file exists and is a directory on Windows NT.
*/
bool isdirectory_nt(const char *path) {
uint32_t x;
char16_t path16[PATH_MAX];
if (__mkntpath(path, path16) == -1) return -1;
if ((x = GetFileAttributes(path16)) != -1u) {
return !!(x & kNtFileAttributeDirectory);
} else {
return false;
}
}

View file

@ -17,8 +17,12 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/stat.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/nt/files.h"
#include "libc/sysv/consts/at.h"
/**
* Returns true if file exists and is a directory.
@ -26,8 +30,12 @@
bool isdirectory(const char *path) {
struct stat st;
int rc, olderr;
olderr = errno;
rc = stat(path, &st);
if (rc == -1 && (errno == ENOENT || errno == ENOTDIR)) errno = olderr;
return rc != -1 && S_ISDIR(st.st_mode);
if (!IsWindows()) {
olderr = errno;
rc = sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW);
if (rc == -1 && (errno == ENOENT || errno == ENOTDIR)) errno = olderr;
return rc != -1 && S_ISDIR(st.st_mode);
} else {
return isdirectory_nt(path);
}
}

View file

@ -0,0 +1,36 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 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/calls.h"
#include "libc/calls/internal.h"
#include "libc/nt/enum/fileflagandattributes.h"
#include "libc/nt/files.h"
/**
* Returns true if file exists and is a regular file on Windows NT.
*/
bool isregularfile_nt(const char *path) {
uint32_t x;
char16_t path16[PATH_MAX];
if (__mkntpath(path, path16) == -1) return -1;
if ((x = GetFileAttributes(path16)) != -1u) {
return !(x & (kNtFileAttributeDirectory | kNtFileAttributeReparsePoint));
} else {
return false;
}
}

View file

@ -16,20 +16,27 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/errno.h"
#include "libc/calls/struct/stat.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/stat.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/sysv/consts/at.h"
/**
* Returns true if file exists and is a regular file
* Returns true if file exists and is a regular file.
*/
bool isregularfile(const char *path) {
/* TODO(jart): Use fast path on NT? */
struct stat st;
int olderr = errno;
int rc = stat(path, &st);
if (rc == -1 && (errno == ENOENT || errno == ENOTDIR)) {
errno = olderr;
int rc, olderr;
if (!IsWindows()) {
olderr = errno;
rc = sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW);
if (rc == -1 && (errno == ENOENT || errno == ENOTDIR)) {
errno = olderr;
}
return rc != -1 && S_ISREG(st.st_mode);
} else {
return isregularfile_nt(path);
}
return rc != -1 && S_ISREG(st.st_mode);
}

36
libc/calls/issymlink-nt.c Normal file
View file

@ -0,0 +1,36 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 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/calls.h"
#include "libc/calls/internal.h"
#include "libc/nt/enum/fileflagandattributes.h"
#include "libc/nt/files.h"
/**
* Returns true if file exists and is a symbolic link on Windows NT.
*/
bool issymlink_nt(const char *path) {
uint32_t x;
char16_t path16[PATH_MAX];
if (__mkntpath(path, path16) == -1) return -1;
if ((x = GetFileAttributes(path16)) != -1u) {
return !!(x & kNtFileAttributeReparsePoint);
} else {
return false;
}
}

41
libc/calls/issymlink.c Normal file
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 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/struct/stat.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/nt/files.h"
#include "libc/sysv/consts/at.h"
/**
* Returns true if file exists and is a symbolic link.
*/
bool issymlink(const char *path) {
struct stat st;
int rc, olderr;
if (!IsWindows()) {
olderr = errno;
rc = sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW);
if (rc == -1 && (errno == ENOENT || errno == ENOTDIR)) errno = olderr;
return rc != -1 && S_ISLNK(st.st_mode);
} else {
return issymlink_nt(path);
}
}

37
libc/calls/lutimes.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/calls.h"
#include "libc/sysv/consts/at.h"
#include "libc/time/time.h"
/**
* Changes file timestamps, the legacy way.
*/
int lutimes(const char *filename, const struct timeval tv[2]) {
struct timespec ts[2];
if (tv) {
ts[0].tv_sec = tv[0].tv_sec;
ts[0].tv_nsec = tv[0].tv_usec * 1000;
ts[1].tv_sec = tv[1].tv_sec;
ts[1].tv_nsec = tv[1].tv_usec * 1000;
return utimensat(AT_FDCWD, filename, ts, AT_SYMLINK_NOFOLLOW);
} else {
return utimensat(AT_FDCWD, filename, 0, AT_SYMLINK_NOFOLLOW);
}
}

View file

@ -25,11 +25,15 @@
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h"
static inline bool IsSlash(char c) {
return c == '/' || c == '\\';
}
textwindows static const char *FixNtMagicPath(const char *path,
unsigned flags) {
const struct NtMagicPaths *mp = &kNtMagicPaths;
asm("" : "+r"(mp));
if (path[0] != '/') return path;
if (!IsSlash(path[0])) return path;
if (strcmp(path, mp->devtty) == 0) {
if ((flags & O_ACCMODE) == O_RDONLY) {
return mp->conin;
@ -79,8 +83,8 @@ textwindows int __mkntpath2(const char *path,
p = path16;
q = path;
z = PATH_MAX - 16;
if (q[0] == '/' && q[1] == 't' && q[2] == 'm' && q[3] == 'p' &&
(q[4] == '/' || !q[4])) {
if (IsSlash(q[0]) && q[1] == 't' && q[2] == 'm' && q[3] == 'p' &&
(IsSlash(q[4]) || !q[4])) {
m = GetTempPath(z, p);
if (!q[4]) return m;
q += 5;

43
libc/calls/readlink.c Normal file
View file

@ -0,0 +1,43 @@
/*-*- 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/calls.h"
#include "libc/sysv/consts/at.h"
/**
* Reads symbolic link.
*
* This does *not* nul-terminate the buffer.
*
* It is recommended that malloc() be linked into your program when
* using this function. Otherwise the buffer should be larger. It should
* also be noted that, without malloc, long names with many astral plane
* characters might not decode properly.
*
* @param path must be a symbolic link pathname
* @param buf will receive symbolic link contents, and won't be modified
* unless the function succeeds (with the exception of no-malloc nt)
* @return number of bytes written to buf, or -1 w/ errno; if the
* return is equal to bufsiz then truncation may have occurred
* @see readlinkat(AT_FDCWD, ...) for modern version of this
* @error EINVAL if path isn't a symbolic link
* @asyncsignalsafe
*/
ssize_t readlink(const char *path, char *buf, size_t bufsiz) {
return readlinkat(AT_FDCWD, path, buf, bufsiz);
}

124
libc/calls/readlinkat-nt.c Normal file
View file

@ -0,0 +1,124 @@
/*-*- 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/bits.h"
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/mem/mem.h"
#include "libc/nexgen32e/bsr.h"
#include "libc/nt/createfile.h"
#include "libc/nt/enum/creationdisposition.h"
#include "libc/nt/enum/fileflagandattributes.h"
#include "libc/nt/enum/fsctl.h"
#include "libc/nt/enum/io.h"
#include "libc/nt/errors.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/reparsedatabuffer.h"
#include "libc/str/tpenc.h"
#include "libc/str/utf16.h"
#include "libc/sysv/errfuns.h"
static textwindows ssize_t sys_readlinkat_nt_error(void) {
uint32_t e;
if ((e = GetLastError()) == kNtErrorNotAReparsePoint) {
return einval();
} else {
errno = e;
return -1;
}
}
textwindows ssize_t sys_readlinkat_nt(int dirfd, const char *path, char *buf,
size_t bufsiz) {
int64_t h;
ssize_t rc;
uint64_t w;
wint_t x, y;
void *freeme;
uint32_t e, i, j, n, mem;
char16_t path16[PATH_MAX], *p;
struct NtReparseDataBuffer *rdb;
if (weaken(malloc)) {
mem = 16384;
rdb = weaken(malloc)(mem);
freeme = rdb;
} else if (bufsiz >= sizeof(struct NtReparseDataBuffer) + 16) {
mem = bufsiz;
rdb = (struct NtReparseDataBuffer *)buf;
freeme = 0;
} else {
return enomem();
}
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
if ((h = CreateFile(path16, 0, 0, 0, kNtOpenExisting,
kNtFileFlagOpenReparsePoint | kNtFileFlagBackupSemantics,
0)) != -1) {
if (DeviceIoControl(h, kNtFsctlGetReparsePoint, 0, 0, rdb, mem, &n, 0)) {
if (rdb->ReparseTag == kNtIoReparseTagSymlink) {
i = 0;
j = 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;
}
}
if (x < 0200) {
if (x == '\\') {
x = '/';
}
w = x;
} else {
w = tpenc(x);
}
do {
if (j < bufsiz) {
buf[j++] = w;
}
w >>= 8;
} while (w);
}
if (freeme || (intptr_t)(buf + j) <= (intptr_t)(p + i)) {
rc = j;
} else {
rc = enametoolong();
}
} else {
rc = einval();
}
} else {
rc = sys_readlinkat_nt_error();
}
CloseHandle(h);
} else {
rc = sys_readlinkat_nt_error();
}
if (freeme && weaken(free)) {
weaken(free)(freeme);
}
return rc;
}

59
libc/calls/readlinkat.c Normal file
View file

@ -0,0 +1,59 @@
/*-*- 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/consts/at.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.internal.h"
/**
* Reads symbolic link.
*
* This does *not* nul-terminate the buffer.
*
* It is recommended that malloc() be linked into your program when
* using this function. Otherwise the buffer should be larger. It should
* also be noted that, without malloc, long names with many astral plane
* characters might not decode properly.
*
* @param dirfd is normally AT_FDCWD but if it's an open directory and
* file is a relative path, then file is opened relative to dirfd
* @param path must be a symbolic link pathname
* @param buf will receive symbolic link contents, and won't be modified
* unless the function succeeds (with the exception of no-malloc nt)
* @return number of bytes written to buf, or -1 w/ errno; if the
* return is equal to bufsiz then truncation may have occurred
* @error EINVAL if path isn't a symbolic link
* @asyncsignalsafe
*/
ssize_t readlinkat(int dirfd, const char *path, char *buf, size_t bufsiz) {
struct ZiposUri zipname;
if (IsAsan() && !__asan_is_valid(buf, bufsiz)) return efault();
if (weaken(__zipos_open) && weaken(__zipos_parseuri)(path, &zipname) != -1) {
return einval();
}
if (!IsWindows()) {
return sys_readlinkat(dirfd, path, buf, bufsiz);
} else {
return sys_readlinkat_nt(dirfd, path, buf, bufsiz);
}
}

View file

@ -1,25 +1,225 @@
/*-*- 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
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=8 tw=8 fenc=utf-8 :vi
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.
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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/safemacros.internal.h"
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/errno.h"
#include "libc/limits.h"
#include "libc/mem/mem.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
char *realpath(const char *path, char *resolved_path) {
enotsup();
return NULL;
#define SYMLOOP_MAX 40
asm(".ident\t\"\\n\\n\
Musl libc (MIT License)\\n\
Copyright 2005-2014 Rich Felker, et. al.\"");
asm(".include \"libc/disclaimer.inc\"");
/* clang-format off */
static inline bool IsSlash(char c)
{
return c == '/' || c == '\\';
}
static size_t GetSlashLen(const char *s)
{
const char *s0 = s;
while (IsSlash(*s)) s++;
return s-s0;
}
static char *ResolvePath(char *d, const char *s, size_t n)
{
if (d || (weaken(malloc) && (d = weaken(malloc)(n+1)))) {
return memmove(d, s, n+1);
} else {
enomem();
return 0;
}
}
/**
* Returns absolute pathname.
*
* This function removes `/./` and `/../` components. IF the path is a
* symbolic link then it's resolved.
*
* @param resolved needs PATH_MAX bytes or NULL to use malloc()
*/
char *realpath(const char *filename, char *resolved)
{
ssize_t k;
int up, check_dir=0;
size_t p, q, l, l0, cnt=0, nup=0;
char output[PATH_MAX], stack[PATH_MAX+1], *z;
if (!filename) {
einval();
return 0;
}
l = strnlen(filename, sizeof stack);
if (!l) {
enoent();
return 0;
}
if (l >= PATH_MAX) goto toolong;
if (l > 4 && (READ32LE(filename) == READ32LE("zip:") ||
READ32LE(filename) == READ32LE("zip!"))) {
return ResolvePath(resolved, filename, l);
}
p = sizeof stack - l - 1;
q = 0;
memcpy(stack+p, filename, l+1);
/* Main loop. Each iteration pops the next part from stack of
* remaining path components and consumes any slashes that follow.
* If not a link, it's moved to output; if a link, contents are
* pushed to the stack. */
restart:
for (; ; p+=GetSlashLen(stack+p)) {
/* If stack starts with /, the whole component is / or //
* and the output state must be reset. */
if (IsSlash(stack[p])) {
check_dir=0;
nup=0;
q=0;
output[q++] = '/';
p++;
/* Initial // is special. */
if (IsSlash(stack[p]) && !IsSlash(stack[p+1]))
output[q++] = '/';
continue;
}
z = (char *)min((intptr_t)strchrnul(stack+p, '/'),
(intptr_t)strchrnul(stack+p, '\\'));
l0 = l = z-(stack+p);
if (!l && !check_dir) break;
/* Skip any . component but preserve check_dir status. */
if (l==1 && stack[p]=='.') {
p += l;
continue;
}
/* Copy next component onto output at least temporarily, to
* call readlink, but wait to advance output position until
* determining it's not a link. */
if (q && !IsSlash(output[q-1])) {
if (!p) goto toolong;
stack[--p] = '/';
l++;
}
if (q+l >= PATH_MAX) goto toolong;
memcpy(output+q, stack+p, l);
output[q+l] = 0;
p += l;
up = 0;
if (l0==2 && stack[p-2]=='.' && stack[p-1]=='.') {
up = 1;
/* Any non-.. path components we could cancel start
* after nup repetitions of the 3-byte string "../";
* if there are none, accumulate .. components to
* later apply to cwd, if needed. */
if (q <= 3*nup) {
nup++;
q += l;
continue;
}
/* When previous components are already known to be
* directories, processing .. can skip readlink. */
if (!check_dir) goto skip_readlink;
}
k = readlink(output, stack, p);
if (k==p) goto toolong;
if (!k) {
errno = ENOENT;
return 0;
}
if (k<0) {
if (errno != EINVAL) return 0;
skip_readlink:
check_dir = 0;
if (up) {
while(q && !IsSlash(output[q-1])) q--;
if (q>1 && (q>2 || !IsSlash(output[0]))) q--;
continue;
}
if (l0) q += l;
check_dir = stack[p];
continue;
}
if (++cnt == SYMLOOP_MAX) {
errno = ELOOP;
return 0;
}
/* If link contents end in /, strip any slashes already on
* stack to avoid /->// or //->/// or spurious toolong. */
if (IsSlash(stack[k-1])) {
while (IsSlash(stack[p]))
p++;
}
p -= k;
memmove(stack+p, stack, k);
/* Skip the stack advancement in case we have a new
* absolute base path. */
goto restart;
}
output[q] = 0;
if (!IsSlash(output[0])) {
if (!getcwd(stack, sizeof(stack))) return 0;
l = strlen(stack);
/* Cancel any initial .. components. */
p = 0;
while (nup--) {
while(l>1 && !IsSlash(stack[l-1])) l--;
if (l>1) l--;
p += 2;
if (p<q) p++;
}
if (q-p && !IsSlash(stack[l-1])) stack[l++] = '/';
if (l + (q-p) + 1 >= PATH_MAX) goto toolong;
memmove(output + l, output + p, q - p + 1);
memcpy(output, stack, l);
q = l + q-p;
}
return ResolvePath(resolved, output, q);
toolong:
enametoolong();
return 0;
}

38
libc/calls/siginterrupt.c Normal file
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 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/calls.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/sysv/consts/sa.h"
/**
* Tunes whether signal can interrupt restartable system calls.
*/
int siginterrupt(int sig, int flag) {
struct sigaction sa;
if (sigaction(sig, 0, &sa) != -1) {
if (flag) {
sa.sa_flags &= ~SA_RESTART;
} else {
sa.sa_flags |= SA_RESTART;
}
return sigaction(sig, &sa, 0);
} else {
return -1;
}
}

View file

@ -27,6 +27,7 @@
#define CBRK CEOL
#define CRPRNT CREPRINT
#define CFLUSH CDISCARD
#define CEOL 255
#define CMIN 1
#define CTIME 0

View file

@ -1,8 +0,0 @@
.ident "\n
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."

View file

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

View file

@ -0,0 +1,5 @@
#ifndef COSMOPOLITAN_LIBC_ISYSTEM_SYS_SENDFILE_H_
#define COSMOPOLITAN_LIBC_ISYSTEM_SYS_SENDFILE_H_
#include "libc/calls/weirdtypes.h"
#include "libc/sock/sock.h"
#endif /* COSMOPOLITAN_LIBC_ISYSTEM_SYS_SENDFILE_H_ */

4
libc/isystem/sys/xattr.h Normal file
View file

@ -0,0 +1,4 @@
#ifndef COSMOPOLITAN_LIBC_ISYSTEM_SYS_XATTR_H_
#define COSMOPOLITAN_LIBC_ISYSTEM_SYS_XATTR_H_
#include "libc/calls/xattr.h"
#endif /* COSMOPOLITAN_LIBC_ISYSTEM_SYS_XATTR_H_ */

View file

@ -1280,6 +1280,10 @@
#define PSOCKET_ADDRESS struct NtSocketAddress*
#define LPSOCKET_ADDRESS struct NtSocketAddress*
#define REPARSE_DATA_BUFFER struct NtReparseDataBuffer
#define PREPARSE_DATA_BUFFER struct NtReparseDataBuffer*
#define LPREPARSE_DATA_BUFFER struct NtReparseDataBuffer*
#define SOCKET_ADDRESS_LIST struct NtSocketAddressList
#define PSOCKET_ADDRESS_LIST struct NtSocketAddressList*
#define LPSOCKET_ADDRESS_LIST struct NtSocketAddressList*

View file

@ -49,13 +49,15 @@ const char *GetAddr2linePath(void);
const char *GetGdbPath(void);
const char *GetCallerName(const struct StackFrame *);
void showcrashreports(void);
void ShowCrashReports(void);
void callexitontermination(struct sigset *);
bool32 IsDebuggerPresent(bool);
bool IsRunningUnderMake(void);
const char *GetSiCodeName(int, int);
void AppendResourceReport(char **, struct rusage *, const char *);
#define showcrashreports() ShowCrashReports()
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § liblog » logging
*/

View file

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

View file

@ -147,8 +147,10 @@ double sqrt(double);
double tan(double);
double tanh(double);
double trunc(double);
double tgamma(double);
double lgamma(double);
double lgamma_r(double, int *);
int finite(double);
float acosf(float);
float acoshf(float);
@ -202,6 +204,8 @@ float sqrtf(float);
float tanf(float);
float tanhf(float);
float truncf(float);
float tgammaf(float);
int finitef(float);
long double acoshl(long double);
long double acosl(long double);
@ -255,6 +259,7 @@ long double sqrtl(long double);
long double tanhl(long double);
long double tanl(long double);
long double truncl(long double);
int finitel(long double);
long lrint(double);
long lrintf(float);

View file

@ -13,5 +13,5 @@ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL\n\
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR\n\
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER\n\
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\n\
PERFORMANCE OF THIS SOFTWARE.\n\
PERFORMANCE OF THIS SOFTWARE.\
"

View file

@ -1,16 +1,17 @@
#ifndef COSMOPOLITAN_LIBC_NT_ENUM_FSCTL_H_
#define COSMOPOLITAN_LIBC_NT_ENUM_FSCTL_H_
#define kNtFsctlDisableLocalBuffering 0x000902B8u
#define kNtFsctlFilePrefetch 0x00090120u
#define kNtFsctlDisableLocalBuffering 0x000902B8u
#define kNtFsctlFilePrefetch 0x00090120u
#define kNtFsctlFilesystemGetStatistics 0x00090060u
#define kNtFsctlGetCompression 0x0009003Cu
#define kNtFsctlGetNtfsFileRecord 0x00090068u
#define kNtFsctlGetNtfsVolumeData 0x00090064u
#define kNtFsctlQueryAllocatedRanges 0x000940CFu
#define kNtFsctlScrubData 0x000902B0u
#define kNtFsctlSetCompression 0x0009C040u
#define kNtFsctlSetSparse 0x000900C4u
#define kNtFsctlSetZeroData 0x000980C8u
#define kNtFsctlGetCompression 0x0009003Cu
#define kNtFsctlGetNtfsFileRecord 0x00090068u
#define kNtFsctlGetNtfsVolumeData 0x00090064u
#define kNtFsctlQueryAllocatedRanges 0x000940CFu
#define kNtFsctlScrubData 0x000902B0u
#define kNtFsctlSetCompression 0x0009C040u
#define kNtFsctlSetSparse 0x000900C4u
#define kNtFsctlSetZeroData 0x000980C8u
#define kNtFsctlGetReparsePoint 0x000900a8u
#endif /* COSMOPOLITAN_LIBC_NT_ENUM_FSCTL_H_ */

6
libc/nt/enum/io.h Normal file
View file

@ -0,0 +1,6 @@
#ifndef COSMOPOLITAN_LIBC_NT_ENUM_IO_H_
#define COSMOPOLITAN_LIBC_NT_ENUM_IO_H_
#define kNtIoReparseTagSymlink 0xa000000c
#endif /* COSMOPOLITAN_LIBC_NT_ENUM_IO_H_ */

View file

@ -208,6 +208,9 @@ bool32 WriteFileGather(int64_t hFileOpenedWithOverlappedAndNoBuffering,
uint32_t GetFinalPathNameByHandle(int64_t hFile, char16_t *out_path,
uint32_t arraylen, uint32_t flags);
uint32_t GetFullPathName(const char16_t *lpFileName, uint32_t nBufferLength,
char16_t *lpBuffer, char16_t **lpFilePart);
#if ShouldUseMsabiAttribute()
#include "libc/nt/thunk/files.inc"
#endif /* ShouldUseMsabiAttribute() */

View file

@ -1,2 +1,12 @@
.include "o/libc/nt/codegen.inc"
.imp kernel32,__imp_GetFullPathNameA,GetFullPathNameA,0
.text.windows
GetFullPathNameA:
push %rbp
mov %rsp,%rbp
.profilable
mov __imp_GetFullPathNameA(%rip),%rax
jmp __sysv2nt
.endfn GetFullPathNameA,globl
.previous

View file

@ -1,2 +1,12 @@
.include "o/libc/nt/codegen.inc"
.imp kernel32,__imp_GetFullPathNameW,GetFullPathNameW,0
.text.windows
GetFullPathName:
push %rbp
mov %rsp,%rbp
.profilable
mov __imp_GetFullPathNameW(%rip),%rax
jmp __sysv2nt
.endfn GetFullPathName,globl
.previous

View file

@ -2190,10 +2190,10 @@ imp 'GetFontRealizationInfo' GetFontRealizationInfo gdi32 1652
imp 'GetFontResourceInfo' GetFontResourceInfoW gdi32 1653
imp 'GetFontUnicodeRanges' GetFontUnicodeRanges gdi32 1654
imp 'GetForegroundWindow' GetForegroundWindow user32 1850
imp 'GetFullPathNameA' GetFullPathNameA kernel32 0 # KernelBase
imp 'GetFullPathName' GetFullPathNameW kernel32 0 4 # KernelBase
imp 'GetFullPathNameA' GetFullPathNameA kernel32 0 4 # KernelBase
imp 'GetFullPathNameTransactedA' GetFullPathNameTransactedA kernel32 603
imp 'GetFullPathNameTransacted' GetFullPathNameTransactedW kernel32 604
imp 'GetFullPathName' GetFullPathNameW kernel32 0 # KernelBase
imp 'GetGPOListInternalA' GetGPOListInternalA KernelBase 569
imp 'GetGPOListInternal' GetGPOListInternalW KernelBase 570
imp 'GetGUIThreadInfo' GetGUIThreadInfo user32 1851

View file

@ -0,0 +1,34 @@
#ifndef COSMOPOLITAN_LIBC_NT_STRUCT_REPARSEDATABUFFER_H_
#define COSMOPOLITAN_LIBC_NT_STRUCT_REPARSEDATABUFFER_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct NtReparseDataBuffer {
uint32_t ReparseTag;
uint16_t ReparseDataLength;
uint16_t Reserved;
union {
struct {
uint16_t SubstituteNameOffset;
uint16_t SubstituteNameLength;
uint16_t PrintNameOffset;
uint16_t PrintNameLength;
uint32_t Flags;
char16_t PathBuffer[1];
} SymbolicLinkReparseBuffer;
struct {
uint16_t SubstituteNameOffset;
uint16_t SubstituteNameLength;
uint16_t PrintNameOffset;
uint16_t PrintNameLength;
char16_t PathBuffer[1];
} MountPointReparseBuffer;
struct {
uint8_t DataBuffer[1];
} GenericReparseBuffer;
};
};
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_NT_STRUCT_REPARSEDATABUFFER_H_ */

View file

@ -43,13 +43,22 @@ const char *FindDebugBinary(void) {
n = strlen(p);
if (n > 4 && !memcmp(p + n - 4, ".dbg", 4)) {
res = p;
} else if (n + 4 <= PATH_MAX) {
} else if (n > 4 && READ32LE(p + n - 4) == READ32LE(".com") &&
n + 4 <= PATH_MAX) {
mempcpy(mempcpy(buf, p, n), ".dbg", 5);
if (fileexists(buf)) {
res = buf;
}
} else if (n + 8 <= PATH_MAX) {
mempcpy(mempcpy(buf, p, n), ".com.dbg", 9);
if (fileexists(buf)) {
res = buf;
}
}
}
if (res) {
res = realpath(res, buf);
}
once = true;
}
return res;

View file

@ -17,20 +17,21 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/calls/ioctl.h"
#include "libc/dce.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/rlimit.h"
int ioctl_fionclex_nt(int);
#define F_MAXFD 11
/**
* Clears "close on exec" on file descriptor the fast way.
*
* @see ioctl(fd, FIONCLEX, 0) dispatches here
* Returns maximum number of open files.
*/
int ioctl_fionclex(int fd) {
if (!IsWindows()) {
return sys_ioctl(fd, FIONCLEX, 0);
} else {
return ioctl_fionclex_nt(fd);
long GetMaxFd(void) {
int rc;
if (IsNetbsd()) {
if ((rc = __sys_fcntl(0, F_MAXFD, 0)) != -1) {
return rc;
}
}
return GetResourceLimit(RLIMIT_NOFILE);
}

View file

@ -0,0 +1,30 @@
/*-*- 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/calls.h"
#include "libc/limits.h"
#include "libc/macros.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/rlim.h"
long GetResourceLimit(int resource) {
struct rlimit rl;
getrlimit(resource, &rl);
if (rl.rlim_cur == RLIM_INFINITY) return -1;
return MIN(rl.rlim_cur, LONG_MAX);
}

View file

@ -90,6 +90,8 @@ void free_s(void *) paramsnonnull() libcesque;
int close_s(int *) paramsnonnull() libcesque;
int OpenExecutable(void);
void ftrace_install(void);
long GetResourceLimit(int);
long GetMaxFd(void);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -25,13 +25,6 @@
#include "libc/sysv/consts/rlim.h"
#include "libc/sysv/consts/rlimit.h"
static long GetResourceLimit(int resource) {
struct rlimit rl;
getrlimit(resource, &rl);
if (rl.rlim_cur == RLIM_INFINITY) return -1;
return MIN(rl.rlim_cur, LONG_MAX);
}
/**
* Returns configuration value about system.
*
@ -41,11 +34,9 @@ static long GetResourceLimit(int resource) {
* - `_SC_ARG_MAX` currently always returns 32768 due to Windows
* - `_SC_PAGESIZE` currently always returns 65536 due to Windows
* - `_SC_NPROCESSORS_ONLN` returns number of CPUs in the system
* - `_SC_OPEN_MAX` returns maximum number of open files
* - `_SC_CHILD_MAX` returns maximum number of processes
*
* Some suggestions:
*
* - `CLK_TCK` should be favored over `getconf(_SC_CLK_TCK)`
* - Use `PAGESIZE` or `FRAMESIZE` instead of `getconf(_SC_PAGESIZE)`
*/
long sysconf(int name) {
int n;
@ -57,7 +48,7 @@ long sysconf(int name) {
case _SC_CLK_TCK:
return CLK_TCK;
case _SC_OPEN_MAX:
return GetResourceLimit(RLIMIT_NOFILE);
return GetMaxFd();
case _SC_PAGESIZE:
return FRAMESIZE;
case _SC_NPROCESSORS_ONLN:

View file

@ -181,6 +181,8 @@ static textwindows uint8_t GetNtDirentType(struct NtWin32FindData *w) {
default:
if (w->dwFileAttributes & kNtFileAttributeDirectory) {
return DT_DIR;
} else if (w->dwFileAttributes & kNtFileAttributeReparsePoint) {
return DT_LNK;
} else {
return DT_REG;
}

View file

@ -47,7 +47,7 @@ void *GetZipCdir(const uint8_t *p, size_t n) {
IsZipCdir64(p, n, ZIP_LOCATE64_OFFSET(p + j))) {
return (void *)(p + ZIP_LOCATE64_OFFSET(p + j));
}
} while (j-- && i - j < 64 * 1024);
} while (j-- && i - j < 1024);
return (void *)(p + i);
}
} while (i--);

View file

@ -1,2 +0,0 @@
.include "o/libc/sysv/macros.internal.inc"
.scall lutimes,0x1a8fff114fffffff,globl

View file

@ -1,2 +0,0 @@
.include "o/libc/sysv/macros.internal.inc"
.scall readlink,0x03a03a03a203a059,globl

View file

@ -0,0 +1,2 @@
.include "o/libc/sysv/macros.internal.inc"
.scall sys_lutimes,0x1a8fff114fffffff,globl,hidden

View file

@ -0,0 +1,2 @@
.include "o/libc/sysv/macros.internal.inc"
.scall sys_readlink,0x03a03a03a203a059,globl,hidden

View file

@ -173,6 +173,8 @@ syscon open O_CREAT 0x00000040 0x00000200 0x00000200 0x00000200 0x000002
syscon open O_EXCL 0x00000080 0x00000800 0x00000800 0x00000800 0x00000800 0x00000080 # bsd consensus & NT faked as Linux
syscon open O_TRUNC 0x00000200 0x00000400 0x00000400 0x00000400 0x00000400 0x00000200 # bsd consensus & NT faked as Linux
syscon open O_DIRECTORY 0x00010000 0x00100000 0x00020000 0x00020000 0x00200000 0x02000000 # useful hint on UNIX, but required on NT (see kNtFileFlagBackupSemantics)
syscon open O_RANDOM 0 0 0 0 0 0x10000000 # kNtFileFlagRandomAccess
syscon open O_SEQUENTIAL 0 0 0 0 0 0x08000000 # kNtFileFlagSequentialScan
syscon open O_DIRECT 0x00004000 0 0x00010000 0 0x00080000 0x00200000 # kNtFileFlagNoBuffering>>8
syscon open O_CLOEXEC 0x00080000 0x01000000 0x00100000 0x00010000 0x00400000 0x00080000 # NT faked as Linux
syscon open O_TMPFILE 0x00410000 0 0 0 0 0x04000100 # Linux 3.11+ (c. 2013) & kNtFileAttributeTemporary|kNtFileFlagDeleteOnClose
@ -306,9 +308,9 @@ syscon lock LOCK_UN 8 8 8 8 8 8 # unlock [unix consensus & faked
# waitpid() / wait4() options
#
# group name GNU/Systemd XNU's Not UNIX! FreeBSD OpenBSD NetBSD The New Technology Commentary
syscon waitpid WNOHANG 1 1 1 1 1 0 # helps you reap zombies; unix consensus
syscon waitpid WNOHANG 1 1 1 1 1 1 # helps you reap zombies; unix consensus; fake nt
syscon waitpid WUNTRACED 2 2 2 2 2 0 # unix consensus
syscon waitpid WCONTINUED 8 0x10 4 8 16 0
syscon waitpid WCONTINUED 8 0x10 4 8 16 0 #
# waitid() options
# no dice on openbsd >:\
@ -362,6 +364,7 @@ syscon fcntl2 F_FULLFSYNC 0 51 0 0 0 0 #
syscon fcntl2 F_NOCACHE 0 48 0 0 0 0 #
syscon fcntl3 FD_CLOEXEC 1 1 1 1 1 1 # unix consensus & faked nt
syscon fcntl F_DUPFD_CLOEXEC 0x0406 67 17 10 12 0x0406 # faked nt
syscon fcntl F_MAXFD 0 0 0 0 11 0 #
# fcntl3 O_NONBLOCK
# fcntl3 O_APPEND
@ -382,6 +385,7 @@ syscon fcntl F_RDLCK 0 1 1 1 1 0 # polyfilled nt; bsd consensus
syscon fcntl F_WRLCK 1 3 3 3 3 1 # polyfilled nt; bsd consensus
syscon fcntl F_UNLCK 2 2 2 2 2 2 # polyfilled nt; unix consensus
syscon fcntl F_ULOCK 0 0 0 0 0 0 # TODO: specified by posix but not kernels?
syscon fcntl F_LOCK 1 1 1 1 1 0 # unix consensus
syscon fcntl F_TLOCK 2 2 2 2 2 0 # unix consensus
syscon fcntl F_TEST 3 3 3 3 3 0 # unix consensus
@ -397,7 +401,6 @@ syscon fcntl F_GETLEASE 0x0401 0 0 0 0 0
syscon fcntl F_NOTIFY 0x0402 0 0 0 0 0
syscon fcntl F_SETPIPE_SZ 0x0407 0 0 0 0 0
syscon fcntl F_GETPIPE_SZ 0x0408 0 0 0 0 0
syscon fcntl F_ULOCK 0 0 0 0 0 0 # TODO: specified by posix but not kernels?
syscon ioctl FIONBIO 0x5421 0x8004667e 0x8004667e 0x8004667e 0x8004667e 0x8004667e # BSD-The New Technology consensus; FIONBIO is traditional O_NONBLOCK; see F_SETFL for re-imagined api
syscon ioctl FIOASYNC 0x5452 0x8004667d 0x8004667d 0x8004667d 0x8004667d 0x8004667d # BSD-The New Technology consensus
@ -577,12 +580,13 @@ syscon ss SIGSTKSZ 0x2000 0x020000 0x8800 0x7000 0x7000 0x2000
# group name GNU/Systemd XNU's Not UNIX! FreeBSD OpenBSD NetBSD The New Technology Commentary
syscon clock CLOCK_REALTIME 0 0 0 0 0 0 # consensus
syscon clock CLOCK_MONOTONIC 1 1 4 3 3 1 # XNU/NT faked; could move backwards if NTP introduces negative leap second
syscon clock CLOCK_PROCESS_CPUTIME_ID 2 -1 15 2 0x40000000 -1
syscon clock CLOCK_THREAD_CPUTIME_ID 3 -1 14 4 0x20000000 -1
syscon clock CLOCK_PROCESS_CPUTIME_ID 2 -1 15 2 0x40000000 -1 #
syscon clock CLOCK_THREAD_CPUTIME_ID 3 -1 14 4 0x20000000 -1 #
syscon clock CLOCK_MONOTONIC_RAW 4 4 0x4000 0x4000 0x4000 4 # actually monotonic; not subject to NTP adjustments; Linux 2.6.28+; XNU/NT/FreeBSD/OpenBSD faked; not available on RHEL5
syscon clock CLOCK_REALTIME_COARSE 5 -1 -1 -1 -1 -1 # Linux 2.6.32+; bsd consensus; not available on RHEL5
syscon clock CLOCK_MONOTONIC_COARSE 6 -1 -1 -1 -1 -1 # Linux 2.6.32+; bsd consensus; not available on RHEL5
syscon clock CLOCK_BOOTTIME 7 -1 -1 6 6 -1
syscon clock CLOCK_PROF -1 -1 2 -1 2 -1 #
syscon clock CLOCK_BOOTTIME 7 -1 -1 6 6 -1 #
syscon clock CLOCK_REALTIME_ALARM 8 -1 -1 -1 -1 -1 # bsd consensus
syscon clock CLOCK_BOOTTIME_ALARM 9 -1 -1 -1 -1 -1 # bsd consensus
syscon clock CLOCK_TAI 11 -1 -1 -1 -1 -1 # bsd consensus
@ -1495,22 +1499,22 @@ syscon termios CS8 0b0000000000110000 0b0000001100000000 0b0000001100000000
syscon termios CSIZE 0b0000000000110000 0b0000001100000000 0b0000001100000000 0b0000001100000000 0b0000001100000000 0b0000000000110000 # mask for CS𝑥 flags
syscon termios NCCS 32 32 32 32 20 32 # ARRAYLEN(termios.c_cc); faked xnu/freebsd/openbsd (originally 20) and faked nt
syscon termios VINTR 0 8 8 8 8 0 # termios.c_cc[VINTR]=𝑥
syscon termios VQUIT 1 9 9 9 9 0 # termios.c_cc[VQUIT]=𝑥
syscon termios VERASE 2 3 3 3 3 0 # termios.c_cc[VERASE]=𝑥
syscon termios VKILL 3 5 5 5 5 0 # termios.c_cc[VKILL]=𝑥
syscon termios VEOF 4 0 0 0 0 0 # termios.c_cc[VEOF]=𝑥
syscon termios VTIME 5 17 17 17 17 0 # termios.c_cc[VTIME]=𝑥 sets non-canonical read timeout to 𝑥×𝟷𝟶𝟶ms which is needed when entering escape sequences manually with the escape key
syscon termios VMIN 6 16 16 16 16 0 # termios.c_cc[VMIN]=𝑥 in non-canonical mode can be set to 0 for non-blocking reads, 1 for single character raw mode reads, or higher to buffer
syscon termios VSWTC 7 0 0 0 0 0 # termios.c_cc[VSWTC]=𝑥
syscon termios VSTART 8 12 12 12 12 0 # termios.c_cc[VSTART]=𝑥
syscon termios VSTOP 9 13 13 13 13 0 # termios.c_cc[VSTOP]=𝑥
syscon termios VSUSP 10 10 10 10 10 0 # termios.c_cc[VSUSP]=𝑥 defines suspend, i.e. Ctrl-Z (a.k.a. →, ^Z, SUB, 26, 032, 0x1A, ord('Z')^0b01000000); unix consensus
syscon termios VEOL 11 1 1 1 1 0 # termios.c_cc[VEOL]=𝑥
syscon termios VEOL2 16 2 2 2 2 0 # termios.c_cc[VEOL2]=𝑥
syscon termios VREPRINT 12 6 6 6 6 0 # termios.c_cc[VREPRINT]=𝑥
syscon termios VDISCARD 13 15 15 15 15 0 # termios.c_cc[VDISCARD]=𝑥
syscon termios VWERASE 14 4 4 4 4 0 # termios.c_cc[VWERASE]=𝑥
syscon termios VLNEXT 15 14 14 14 14 0 # termios.c_cc[VLNEXT]=𝑥
syscon termios VQUIT 1 9 9 9 9 1 # termios.c_cc[VQUIT]=𝑥
syscon termios VERASE 2 3 3 3 3 2 # termios.c_cc[VERASE]=𝑥
syscon termios VKILL 3 5 5 5 5 3 # termios.c_cc[VKILL]=𝑥
syscon termios VEOF 4 0 0 0 0 4 # termios.c_cc[VEOF]=𝑥
syscon termios VTIME 5 17 17 17 17 5 # termios.c_cc[VTIME]=𝑥 sets non-canonical read timeout to 𝑥×𝟷𝟶𝟶ms which is needed when entering escape sequences manually with the escape key
syscon termios VMIN 6 16 16 16 16 6 # termios.c_cc[VMIN]=𝑥 in non-canonical mode can be set to 0 for non-blocking reads, 1 for single character raw mode reads, or higher to buffer
syscon termios VSWTC 7 0 0 0 0 7 # termios.c_cc[VSWTC]=𝑥
syscon termios VSTART 8 12 12 12 12 8 # termios.c_cc[VSTART]=𝑥
syscon termios VSTOP 9 13 13 13 13 9 # termios.c_cc[VSTOP]=𝑥
syscon termios VSUSP 10 10 10 10 10 10 # termios.c_cc[VSUSP]=𝑥 defines suspend, i.e. Ctrl-Z (a.k.a. →, ^Z, SUB, 26, 032, 0x1A, ord('Z')^0b01000000); unix consensus
syscon termios VEOL 11 1 1 1 1 11 # termios.c_cc[VEOL]=𝑥
syscon termios VEOL2 16 2 2 2 2 16 # termios.c_cc[VEOL2]=𝑥
syscon termios VREPRINT 12 6 6 6 6 12 # termios.c_cc[VREPRINT]=𝑥
syscon termios VDISCARD 13 15 15 15 15 13 # termios.c_cc[VDISCARD]=𝑥
syscon termios VWERASE 14 4 4 4 4 14 # termios.c_cc[VWERASE]=𝑥
syscon termios VLNEXT 15 14 14 14 14 15 # termios.c_cc[VLNEXT]=𝑥
syscon termios TIOCSERGETLSR 0x5459 0 0 0 0 0 #
syscon termios TIOCSERGETMULTI 0x545a 0 0 0 0 0 #
syscon termios TIOCSERSETMULTI 0x545b 0 0 0 0 0 #
@ -1525,7 +1529,6 @@ syscon termios BUSY 4 0 0 0 0 0
syscon termios CANBSIZ 255 0 0 0 0 0
syscon termios CBAUD 0x100f 0 0 0 0 0
syscon termios CBAUDEX 0x1000 0 0 0 0 0
syscon termios CEOL 0 255 255 255 255 0 #
syscon termios EXTA 14 0x4b00 0x4b00 0x4b00 0x4b00 0 # bsd consensus
syscon termios EXTB 15 0x9600 0x9600 0x9600 0x9600 0 # bsd consensus
syscon termios ERA 0x02002c 45 45 0 0 0
@ -1921,13 +1924,9 @@ syscon misc UDP_NO_CHECK6_TX 101 0 0 0 0 0
syscon misc ACK 4 4 4 4 4 0 # unix consensus
syscon misc CDISCARD 15 15 15 15 15 0 # unix consensus
syscon misc CDSUSP 25 25 25 25 25 0 # unix consensus
syscon misc CEOF 4 4 4 4 4 0 # unix consensus
syscon misc CEOT 4 4 4 4 4 0 # unix consensus
syscon misc CERASE 127 127 127 127 127 0 # unix consensus
syscon misc CFLUSH 15 15 15 15 15 0 # unix consensus
syscon misc CHRTYPE 51 51 51 51 51 0 # unix consensus
syscon misc CINTR 3 3 3 3 3 0 # unix consensus
syscon misc CKILL 21 21 21 21 21 0 # unix consensus
syscon misc CLNEXT 22 22 22 22 22 0 # unix consensus
syscon misc CMIN 1 1 1 1 1 0 # unix consensus

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,CFLUSH,15,15,15,15,15,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,CINTR,3,3,3,3,3,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,CDSUSP,25,25,25,25,25,0
.syscon clock,CLOCK_PROF,-1,-1,2,-1,2,-1

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,CEOF,4,4,4,4,4,0
.syscon fcntl,F_MAXFD,0,0,0,0,11,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,CEOL,0,255,255,255,255,0
.syscon open,O_RANDOM,0,0,0,0,0,0x10000000

View file

@ -0,0 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon open,O_SEQUENTIAL,0,0,0,0,0,0x08000000

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VDISCARD,13,15,15,15,15,0
.syscon termios,VDISCARD,13,15,15,15,15,13

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VEOF,4,0,0,0,0,0
.syscon termios,VEOF,4,0,0,0,0,4

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VEOL,11,1,1,1,1,0
.syscon termios,VEOL,11,1,1,1,1,11

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VEOL2,16,2,2,2,2,0
.syscon termios,VEOL2,16,2,2,2,2,16

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VERASE,2,3,3,3,3,0
.syscon termios,VERASE,2,3,3,3,3,2

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VKILL,3,5,5,5,5,0
.syscon termios,VKILL,3,5,5,5,5,3

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VLNEXT,15,14,14,14,14,0
.syscon termios,VLNEXT,15,14,14,14,14,15

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VMIN,6,16,16,16,16,0
.syscon termios,VMIN,6,16,16,16,16,6

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VQUIT,1,9,9,9,9,0
.syscon termios,VQUIT,1,9,9,9,9,1

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VREPRINT,12,6,6,6,6,0
.syscon termios,VREPRINT,12,6,6,6,6,12

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VSTART,8,12,12,12,12,0
.syscon termios,VSTART,8,12,12,12,12,8

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VSTOP,9,13,13,13,13,0
.syscon termios,VSTOP,9,13,13,13,13,9

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VSUSP,10,10,10,10,10,0
.syscon termios,VSUSP,10,10,10,10,10,10

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VSWTC,7,0,0,0,0,0
.syscon termios,VSWTC,7,0,0,0,0,7

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VTIME,5,17,17,17,17,0
.syscon termios,VTIME,5,17,17,17,17,5

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VWERASE,14,4,4,4,4,0
.syscon termios,VWERASE,14,4,4,4,4,14

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon waitpid,WNOHANG,1,1,1,1,1,0
.syscon waitpid,WNOHANG,1,1,1,1,1,1

View file

@ -1,19 +1,6 @@
#ifndef COSMOPOLITAN_LIBC_SYSV_CONSTS_CLOCK_H_
#define COSMOPOLITAN_LIBC_SYSV_CONSTS_CLOCK_H_
#include "libc/runtime/symbolic.h"
#define CLOCK_BOOTTIME SYMBOLIC(CLOCK_BOOTTIME)
#define CLOCK_BOOTTIME_ALARM SYMBOLIC(CLOCK_BOOTTIME_ALARM)
#define CLOCK_MONOTONIC SYMBOLIC(CLOCK_MONOTONIC)
#define CLOCK_MONOTONIC_COARSE SYMBOLIC(CLOCK_MONOTONIC_COARSE)
#define CLOCK_MONOTONIC_RAW SYMBOLIC(CLOCK_MONOTONIC_RAW)
#define CLOCK_PROCESS_CPUTIME_ID SYMBOLIC(CLOCK_PROCESS_CPUTIME_ID)
#define CLOCK_REALTIME SYMBOLIC(CLOCK_REALTIME)
#define CLOCK_REALTIME_ALARM SYMBOLIC(CLOCK_REALTIME_ALARM)
#define CLOCK_REALTIME_COARSE SYMBOLIC(CLOCK_REALTIME_COARSE)
#define CLOCK_TAI SYMBOLIC(CLOCK_TAI)
#define CLOCK_THREAD_CPUTIME_ID SYMBOLIC(CLOCK_THREAD_CPUTIME_ID)
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
@ -23,6 +10,7 @@ extern const long CLOCK_MONOTONIC;
extern const long CLOCK_MONOTONIC_COARSE;
extern const long CLOCK_MONOTONIC_RAW;
extern const long CLOCK_PROCESS_CPUTIME_ID;
extern const long CLOCK_PROF;
extern const long CLOCK_REALTIME;
extern const long CLOCK_REALTIME_ALARM;
extern const long CLOCK_REALTIME_COARSE;
@ -31,4 +19,18 @@ extern const long CLOCK_THREAD_CPUTIME_ID;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#define CLOCK_BOOTTIME SYMBOLIC(CLOCK_BOOTTIME)
#define CLOCK_BOOTTIME_ALARM SYMBOLIC(CLOCK_BOOTTIME_ALARM)
#define CLOCK_MONOTONIC SYMBOLIC(CLOCK_MONOTONIC)
#define CLOCK_MONOTONIC_COARSE SYMBOLIC(CLOCK_MONOTONIC_COARSE)
#define CLOCK_MONOTONIC_RAW SYMBOLIC(CLOCK_MONOTONIC_RAW)
#define CLOCK_PROCESS_CPUTIME_ID SYMBOLIC(CLOCK_PROCESS_CPUTIME_ID)
#define CLOCK_PROF SYMBOLIC(CLOCK_PROF)
#define CLOCK_REALTIME SYMBOLIC(CLOCK_REALTIME)
#define CLOCK_REALTIME_ALARM SYMBOLIC(CLOCK_REALTIME_ALARM)
#define CLOCK_REALTIME_COARSE SYMBOLIC(CLOCK_REALTIME_COARSE)
#define CLOCK_TAI SYMBOLIC(CLOCK_TAI)
#define CLOCK_THREAD_CPUTIME_ID SYMBOLIC(CLOCK_THREAD_CPUTIME_ID)
#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_CLOCK_H_ */

View file

@ -22,10 +22,12 @@ extern const long O_NOCTTY;
extern const long O_NOFOLLOW;
extern const long O_NONBLOCK;
extern const long O_PATH;
extern const long O_RANDOM;
extern const long O_RDONLY;
extern const long O_RDWR;
extern const long O_RSYNC;
extern const long O_SEARCH;
extern const long O_SEQUENTIAL;
extern const long O_SHLOCK;
extern const long O_SPARSE;
extern const long O_SYNC;
@ -37,34 +39,36 @@ extern const long O_WRONLY;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#define O_ACCMODE SYMBOLIC(O_ACCMODE)
#define O_APPEND SYMBOLIC(O_APPEND)
#define O_ASYNC SYMBOLIC(O_ASYNC)
#define O_CLOEXEC SYMBOLIC(O_CLOEXEC)
#define O_CREAT SYMBOLIC(O_CREAT)
#define O_DIRECT SYMBOLIC(O_DIRECT)
#define O_DIRECTORY SYMBOLIC(O_DIRECTORY)
#define O_DSYNC SYMBOLIC(O_DSYNC)
#define O_EXCL SYMBOLIC(O_EXCL)
#define O_EXEC SYMBOLIC(O_EXEC)
#define O_EXLOCK SYMBOLIC(O_EXLOCK)
#define O_LARGEFILE SYMBOLIC(O_LARGEFILE)
#define O_NDELAY SYMBOLIC(O_NDELAY)
#define O_NOATIME SYMBOLIC(O_NOATIME)
#define O_NOCTTY SYMBOLIC(O_NOCTTY)
#define O_NOFOLLOW SYMBOLIC(O_NOFOLLOW)
#define O_NONBLOCK SYMBOLIC(O_NONBLOCK)
#define O_PATH SYMBOLIC(O_PATH)
#define O_RDONLY SYMBOLIC(O_RDONLY)
#define O_RDWR SYMBOLIC(O_RDWR)
#define O_RSYNC SYMBOLIC(O_RSYNC)
#define O_SEARCH SYMBOLIC(O_SEARCH)
#define O_SHLOCK SYMBOLIC(O_SHLOCK)
#define O_SPARSE SYMBOLIC(O_SPARSE)
#define O_SYNC SYMBOLIC(O_SYNC)
#define O_TMPFILE SYMBOLIC(O_TMPFILE)
#define O_TRUNC SYMBOLIC(O_TRUNC)
#define O_TTY_INIT SYMBOLIC(O_TTY_INIT)
#define O_WRONLY SYMBOLIC(O_WRONLY)
#define O_ACCMODE SYMBOLIC(O_ACCMODE)
#define O_APPEND SYMBOLIC(O_APPEND)
#define O_ASYNC SYMBOLIC(O_ASYNC)
#define O_CLOEXEC SYMBOLIC(O_CLOEXEC)
#define O_CREAT SYMBOLIC(O_CREAT)
#define O_DIRECT SYMBOLIC(O_DIRECT)
#define O_DIRECTORY SYMBOLIC(O_DIRECTORY)
#define O_DSYNC SYMBOLIC(O_DSYNC)
#define O_EXCL SYMBOLIC(O_EXCL)
#define O_EXEC SYMBOLIC(O_EXEC)
#define O_EXLOCK SYMBOLIC(O_EXLOCK)
#define O_LARGEFILE SYMBOLIC(O_LARGEFILE)
#define O_NDELAY SYMBOLIC(O_NDELAY)
#define O_NOATIME SYMBOLIC(O_NOATIME)
#define O_NOCTTY SYMBOLIC(O_NOCTTY)
#define O_NOFOLLOW SYMBOLIC(O_NOFOLLOW)
#define O_NONBLOCK SYMBOLIC(O_NONBLOCK)
#define O_PATH SYMBOLIC(O_PATH)
#define O_RANDOM SYMBOLIC(O_RANDOM)
#define O_RDONLY SYMBOLIC(O_RDONLY)
#define O_RDWR SYMBOLIC(O_RDWR)
#define O_RSYNC SYMBOLIC(O_RSYNC)
#define O_SEARCH SYMBOLIC(O_SEARCH)
#define O_SEQUENTIAL SYMBOLIC(O_SEQUENTIAL)
#define O_SHLOCK SYMBOLIC(O_SHLOCK)
#define O_SPARSE SYMBOLIC(O_SPARSE)
#define O_SYNC SYMBOLIC(O_SYNC)
#define O_TMPFILE SYMBOLIC(O_TMPFILE)
#define O_TRUNC SYMBOLIC(O_TRUNC)
#define O_TTY_INIT SYMBOLIC(O_TTY_INIT)
#define O_WRONLY SYMBOLIC(O_WRONLY)
#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_O_H_ */

View file

@ -12,7 +12,6 @@ extern const long BUSY;
extern const long CANBSIZ;
extern const long CBAUD;
extern const long CBAUDEX;
extern const long CEOL;
extern const long CIBAUD;
extern const long CLOCAL;
extern const long CMSPAR;
@ -35,6 +34,8 @@ extern const long ECHOKE;
extern const long ECHONL;
extern const long ECHOPRT;
extern const long ENDRUNDISC;
extern const long EXTA;
extern const long EXTB;
extern const long EXTPROC;
extern const long FF1;
extern const long FF2;
@ -222,7 +223,6 @@ COSMOPOLITAN_C_END_
#define CANBSIZ SYMBOLIC(CANBSIZ)
#define CBAUD SYMBOLIC(CBAUD)
#define CBAUDEX SYMBOLIC(CBAUDEX)
#define CEOL SYMBOLIC(CEOL)
#define CIBAUD SYMBOLIC(CIBAUD)
#define CLOCAL SYMBOLIC(CLOCAL)
#define CMSPAR SYMBOLIC(CMSPAR)
@ -241,6 +241,8 @@ COSMOPOLITAN_C_END_
#define ECHONL SYMBOLIC(ECHONL)
#define ECHOPRT SYMBOLIC(ECHOPRT)
#define ENDRUNDISC SYMBOLIC(ENDRUNDISC)
#define EXTA SYMBOLIC(EXTA)
#define EXTB SYMBOLIC(EXTB)
#define EXTPROC SYMBOLIC(EXTPROC)
#define FLUSHO SYMBOLIC(FLUSHO)
#define H4DISC SYMBOLIC(H4DISC)

View file

@ -1,11 +1,6 @@
#ifndef COSMOPOLITAN_LIBC_SYSV_CONSTS_W_H_
#define COSMOPOLITAN_LIBC_SYSV_CONSTS_W_H_
#include "libc/runtime/symbolic.h"
#define WNOHANG SYMBOLIC(WNOHANG)
#define WUNTRACED SYMBOLIC(WUNTRACED)
#define WCONTINUED SYMBOLIC(WCONTINUED)
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
@ -15,4 +10,9 @@ extern const long WCONTINUED;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#define WNOHANG LITERALLY(1)
#define WUNTRACED SYMBOLIC(WUNTRACED)
#define WCONTINUED SYMBOLIC(WCONTINUED)
#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_W_H_ */

View file

@ -128,7 +128,7 @@ scall sys_creat 0xffffff008ffff055 globl hidden
scall sys_link 0x0090090092009056 globl hidden
scall sys_unlink 0x00a00a00a200a057 globl hidden
scall sys_symlink 0x0390390392039058 globl hidden
scall readlink 0x03a03a03a203a059 globl # usually an anti-pattern
scall sys_readlink 0x03a03a03a203a059 globl hidden # usually an anti-pattern
scall sys_chmod 0x00f00f00f200f05a globl hidden
scall sys_fchmod 0x07c07c07c207c05b globl hidden
scall sys_chown 0x010010010201005c globl hidden # impl. w/ fchownat() @asyncsignalsafe
@ -162,7 +162,7 @@ scall sys_setresuid 0xfff11a137ffff075 globl hidden # polyfilled for xnu
scall sys_setresgid 0xfff11c138ffff077 globl hidden # polyfilled for xnu
scall getresuid 0xfff119168ffff076 globl # semantics aren't well-defined
scall getresgid 0xfff11b169ffff078 globl # semantics aren't well-defined
scall sigpending 0x124034034203407f globl
scall sigpending 0x124034034203407f globl # rt_sigpending on linux
scall sys_sigsuspend 0x12606f155206f082 globl hidden # openbsd:byvalue
scall sigaltstack 0x1191200352035083 globl
scall sys_mknod 0x1c200e00e200e085 globl hidden
@ -700,7 +700,7 @@ scall lchflags 0x130fff187fffffff globl
scall lchmod 0x112fff112fffffff globl
scall lgetfh 0xffffff0a0fffffff globl
scall lpathconf 0x1f3fff201fffffff globl
scall lutimes 0x1a8fff114fffffff globl
scall sys_lutimes 0x1a8fff114fffffff globl hidden
scall mac_syscall 0xffffff18afffffff globl
scall modfind 0xffffff12ffffffff globl
scall modfnext 0xffffff12efffffff globl

View file

@ -293,6 +293,8 @@ struct TestFixture {
};
extern char g_fixturename[256];
extern char g_testlib_olddir[PATH_MAX];
extern char g_testlib_tmpdir[PATH_MAX];
extern bool g_testlib_shoulddebugbreak; /* set by testmain */
extern unsigned g_testlib_ran; /* set by wrappers */
extern unsigned g_testlib_failed; /* set by wrappers */

View file

@ -74,7 +74,7 @@ testonly int main(int argc, char *argv[]) {
const char *comdbg;
__log_level = kLogInfo;
GetOpts(argc, argv);
showcrashreports();
ShowCrashReports();
if ((comdbg = FindDebugBinary())) {
setenv("COMDBG", comdbg, true);
}

View file

@ -31,8 +31,8 @@
#include "libc/x/x.h"
static int x;
static char cwd[PATH_MAX];
static char tmp[PATH_MAX];
char g_testlib_olddir[PATH_MAX];
char g_testlib_tmpdir[PATH_MAX];
void testlib_finish(void) {
if (g_testlib_failed) {
@ -48,15 +48,18 @@ wontreturn void testlib_abort(void) {
}
static void SetupTmpDir(void) {
snprintf(tmp, sizeof(tmp), "o/tmp/%s.%d.%d", program_invocation_short_name,
getpid(), x++);
CHECK_NE(-1, makedirs(tmp, 0755), "tmp=%s", tmp);
CHECK_NE(-1, chdir(tmp), "tmp=%s", tmp);
snprintf(g_testlib_tmpdir, sizeof(g_testlib_tmpdir), "o/tmp/%s.%d.%d",
program_invocation_short_name, getpid(), x++);
CHECK_NE(-1, makedirs(g_testlib_tmpdir, 0755), "%s", g_testlib_tmpdir);
CHECK_EQ(1, isdirectory(g_testlib_tmpdir), "%s", g_testlib_tmpdir);
CHECK_NOTNULL(realpath(g_testlib_tmpdir, g_testlib_tmpdir), "%`'s",
g_testlib_tmpdir);
CHECK_NE(-1, chdir(g_testlib_tmpdir), "%s", g_testlib_tmpdir);
}
static void TearDownTmpDir(void) {
CHECK_NE(-1, chdir(cwd));
CHECK_NE(-1, rmrf(tmp));
CHECK_NE(-1, chdir(g_testlib_olddir));
CHECK_NE(-1, rmrf(g_testlib_tmpdir));
}
/**
@ -80,7 +83,7 @@ testonly void testlib_runtestcases(testfn_t *start, testfn_t *end,
* @see ape/ape.lds
*/
const testfn_t *fn;
CHECK_NOTNULL(getcwd(cwd, sizeof(cwd)));
CHECK_NOTNULL(getcwd(g_testlib_olddir, sizeof(g_testlib_olddir)));
if (weaken(testlib_enable_tmp_setup_teardown_once)) SetupTmpDir();
if (weaken(SetUpOnce)) weaken(SetUpOnce)();
for (x = 0, fn = start; fn != end; ++fn) {

View file

@ -16,16 +16,11 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/calls/ioctl.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h"
#include "libc/math.h"
textwindows int ioctl_fionclex_nt(int fd) {
if (__isfdopen(fd)) {
g_fds.p[fd].flags &= ~O_CLOEXEC;
return 0;
} else {
return ebadf();
}
/**
* Returns nonzero if 𝑥 isn't INFINITY or NAN.
*/
int finite(double x) {
return isfinite(x);
}

26
libc/tinymath/finitef.c Normal file
View file

@ -0,0 +1,26 @@
/*-*- 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/math.h"
/**
* Returns nonzero if 𝑥 isn't INFINITY or NAN.
*/
int finitef(float x) {
return isfinite(x);
}

26
libc/tinymath/finitel.c Normal file
View file

@ -0,0 +1,26 @@
/*-*- 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/math.h"
/**
* Returns nonzero if 𝑥 isn't INFINITY or NAN.
*/
int finitel(long double x) {
return isfinite(x);
}

View file

@ -26,6 +26,7 @@
*/
#include "libc/math.h"
#include "libc/tinymath/kernel.internal.h"
asm(".ident\t\"\\n\\n\
fdlibm (fdlibm license)\\n\
@ -35,9 +36,6 @@ Musl libc (MIT License)\\n\
Copyright 2005-2014 Rich Felker, et. al.\"");
asm(".include \"libc/disclaimer.inc\"");
double __sin(double, double, int);
double __cos(double, double);
/* clang-format off */
/* origin: FreeBSD /usr/src/lib/msun/src/e_lgamma_r.c */
/*

View file

@ -26,6 +26,7 @@
*/
#include "libc/math.h"
#include "libc/tinymath/feval.internal.h"
asm(".ident\t\"\\n\\n\
Musl libc (MIT License)\\n\
@ -33,12 +34,6 @@ Copyright 2005-2014 Rich Felker, et. al.\"");
asm(".include \"libc/disclaimer.inc\"");
/* clang-format off */
static inline void force_eval(double x)
{
volatile double y;
y = x;
}
double nextafter(double x, double y)
{
union {double f; uint64_t i;} ux={x}, uy={y};
@ -62,9 +57,9 @@ double nextafter(double x, double y)
e = ux.i >> 52 & 0x7ff;
/* raise overflow if ux.f is infinite and x is finite */
if (e == 0x7ff)
force_eval(x+x);
feval(x+x);
/* raise underflow if ux.f is subnormal or zero */
if (e == 0)
force_eval(x*x + ux.f*ux.f);
feval(x*x + ux.f*ux.f);
return ux.f;
}

View file

@ -26,6 +26,7 @@
*/
#include "libc/math.h"
#include "libc/tinymath/feval.internal.h"
asm(".ident\t\"\\n\\n\
Musl libc (MIT License)\\n\
@ -33,12 +34,6 @@ Copyright 2005-2020 Rich Felker, et. al.\"");
asm(".include \"libc/disclaimer.inc\"");
/* clang-format off */
static inline void fp_force_eval(double x)
{
volatile double y;
y = x;
}
double nexttoward(double x, long double y)
{
union {double f; uint64_t i;} ux = {x};
@ -66,9 +61,9 @@ double nexttoward(double x, long double y)
e = ux.i>>52 & 0x7ff;
/* raise overflow if ux.f is infinite and x is finite */
if (e == 0x7ff)
fp_force_eval(x+x);
feval(x+x);
/* raise underflow if ux.f is subnormal or zero */
if (e == 0)
fp_force_eval(x*x + ux.f*ux.f);
feval(x*x + ux.f*ux.f);
return ux.f;
}

207
libc/tinymath/tgamma.c Normal file
View file

@ -0,0 +1,207 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=8 tw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/math.h"
#include "libc/tinymath/feval.internal.h"
#include "libc/tinymath/kernel.internal.h"
asm(".ident\t\"\\n\\n\
Musl libc (MIT License)\\n\
Copyright 2005-2014 Rich Felker, et. al.\"");
asm(".include \"libc/disclaimer.inc\"");
/* clang-format off */
/*
"A Precision Approximation of the Gamma Function" - Cornelius Lanczos (1964)
"Lanczos Implementation of the Gamma Function" - Paul Godfrey (2001)
"An Analysis of the Lanczos Gamma Approximation" - Glendon Ralph Pugh (2004)
approximation method:
(x - 0.5) S(x)
Gamma(x) = (x + g - 0.5) * ----------------
exp(x + g - 0.5)
with
a1 a2 a3 aN
S(x) ~= [ a0 + ----- + ----- + ----- + ... + ----- ]
x + 1 x + 2 x + 3 x + N
with a0, a1, a2, a3,.. aN constants which depend on g.
for x < 0 the following reflection formula is used:
Gamma(x)*Gamma(-x) = -pi/(x sin(pi x))
most ideas and constants are from boost and python
*/
static const double pi = 3.141592653589793238462643383279502884;
/* sin(pi x) with x > 0x1p-100, if sin(pi*x)==0 the sign is arbitrary */
static double sinpi(double x)
{
int n;
/* argument reduction: x = |x| mod 2 */
/* spurious inexact when x is odd int */
x = x * 0.5;
x = 2 * (x - floor(x));
/* reduce x into [-.25,.25] */
n = 4 * x;
n = (n+1)/2;
x -= n * 0.5;
x *= pi;
switch (n) {
default: /* case 4 */
case 0:
return __sin(x, 0, 0);
case 1:
return __cos(x, 0);
case 2:
return __sin(-x, 0, 0);
case 3:
return -__cos(x, 0);
}
}
#define N 12
//static const double g = 6.024680040776729583740234375;
static const double gmhalf = 5.524680040776729583740234375;
static const double Snum[N+1] = {
23531376880.410759688572007674451636754734846804940,
42919803642.649098768957899047001988850926355848959,
35711959237.355668049440185451547166705960488635843,
17921034426.037209699919755754458931112671403265390,
6039542586.3520280050642916443072979210699388420708,
1439720407.3117216736632230727949123939715485786772,
248874557.86205415651146038641322942321632125127801,
31426415.585400194380614231628318205362874684987640,
2876370.6289353724412254090516208496135991145378768,
186056.26539522349504029498971604569928220784236328,
8071.6720023658162106380029022722506138218516325024,
210.82427775157934587250973392071336271166969580291,
2.5066282746310002701649081771338373386264310793408,
};
static const double Sden[N+1] = {
0, 39916800, 120543840, 150917976, 105258076, 45995730, 13339535,
2637558, 357423, 32670, 1925, 66, 1,
};
/* n! for small integer n */
static const double fact[] = {
1, 1, 2, 6, 24, 120, 720, 5040.0, 40320.0, 362880.0, 3628800.0, 39916800.0,
479001600.0, 6227020800.0, 87178291200.0, 1307674368000.0, 20922789888000.0,
355687428096000.0, 6402373705728000.0, 121645100408832000.0,
2432902008176640000.0, 51090942171709440000.0, 1124000727777607680000.0,
};
/* S(x) rational function for positive x */
static double S(double x)
{
double_t num = 0, den = 0;
int i;
/* to avoid overflow handle large x differently */
if (x < 8)
for (i = N; i >= 0; i--) {
num = num * x + Snum[i];
den = den * x + Sden[i];
}
else
for (i = 0; i <= N; i++) {
num = num / x + Snum[i];
den = den / x + Sden[i];
}
return num/den;
}
double tgamma(double x)
{
union {double f; uint64_t i;} u = {x};
double absx, y;
double_t dy, z, r;
uint32_t ix = u.i>>32 & 0x7fffffff;
int sign = u.i>>63;
/* special cases */
if (ix >= 0x7ff00000)
/* tgamma(nan)=nan, tgamma(inf)=inf, tgamma(-inf)=nan with invalid */
return x + INFINITY;
if (ix < (0x3ff-54)<<20)
/* |x| < 2^-54: tgamma(x) ~ 1/x, +-0 raises div-by-zero */
return 1/x;
/* integer arguments */
/* raise inexact when non-integer */
if (x == floor(x)) {
if (sign)
return 0/0.0;
if (x <= sizeof fact/sizeof *fact)
return fact[(int)x - 1];
}
/* x >= 172: tgamma(x)=inf with overflow */
/* x =< -184: tgamma(x)=+-0 with underflow */
if (ix >= 0x40670000) { /* |x| >= 184 */
if (sign) {
fevalf(0x1p-126/x);
if (floor(x) * 0.5 == floor(x * 0.5))
return 0;
return -0.0;
}
x *= 0x1p1023;
return x;
}
absx = sign ? -x : x;
/* handle the error of x + g - 0.5 */
y = absx + gmhalf;
if (absx > gmhalf) {
dy = y - absx;
dy -= gmhalf;
} else {
dy = y - gmhalf;
dy -= absx;
}
z = absx - 0.5;
r = S(absx) * exp(-y);
if (x < 0) {
/* reflection formula for negative x */
/* sinpi(absx) is not 0, integers are already handled */
r = -pi / (sinpi(absx) * absx * r);
dy = -dy;
z = -z;
}
r += dy * (gmhalf+0.5) * r / y;
z = pow(y, 0.5*z);
y = r * z * z;
return y;
}

23
libc/tinymath/tgammaf.c Normal file
View file

@ -0,0 +1,23 @@
/*-*- 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/math.h"
float tgammaf(float x) {
return tgamma(x);
}

View file

@ -36,7 +36,7 @@ int xbarf(const char *path, const void *data, size_t size) {
size_t i, wrote;
res = 0;
p = data;
if (size == -1) size = strlen(p);
if (size == -1) size = data ? strlen(data) : 0;
if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644)) != -1) {
if (ftruncate(fd, size) != -1) {
if (size > 2 * 1024 * 1024) {

View file

@ -37,7 +37,7 @@ char *xjoinpaths(const char *path, const char *other) {
return xstrdup(path);
} else if (!*path) {
return xstrdup(other);
} else if (startswith(other, "/") || !strcmp(path, ".")) {
} else if (*other == '/' || !strcmp(path, ".")) {
return xstrdup(other);
} else if (endswith(path, "/")) {
return xstrcat(path, other);

View file

@ -0,0 +1,48 @@
/*-*- 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/calls.h"
#include "libc/log/log.h"
#include "libc/runtime/gc.internal.h"
#include "libc/str/str.h"
#include "libc/testlib/testlib.h"
#include "libc/x/x.h"
char testlib_enable_tmp_setup_teardown;
TEST(readlinkat, test) {
ssize_t rc;
char *p, *q;
char buf[128];
memset(buf, -1, sizeof(buf));
ASSERT_NE(-1, xbarf("hello→", "hi", -1));
ASSERT_STREQ("hi", gc(xslurp("hello→", 0)));
ASSERT_NE(-1, symlink("hello→", "there→"));
ASSERT_TRUE(isregularfile("hello→"));
ASSERT_TRUE(issymlink("there→"));
ASSERT_FALSE(isregularfile("there→"));
ASSERT_NE(-1, (rc = readlink("there→", buf, sizeof(buf))));
ASSERT_LT(rc, sizeof(buf));
EXPECT_EQ(-1, buf[rc]);
buf[rc] = 0;
EXPECT_EQ(8, rc);
EXPECT_STREQ("hello→", buf);
p = gc(xjoinpaths(g_testlib_tmpdir, "hello→"));
q = gc(realpath("there→", 0));
EXPECT_EQ(0, strcmp(p, q), "%`'s\n\t%`'s", p, q);
}

View file

@ -0,0 +1,48 @@
/*-*- 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/str/str.h"
#include "libc/testlib/testlib.h"
forceinline void *Memmove(void *restrict d, const void *restrict s, size_t n) {
return __builtin___memmove_chk(d, s, n, __builtin_object_size(d, 0));
}
void foo1(void *p, void *q) {
Memmove(p, q, 19);
}
TEST(memmove, supposedPythonBug_test1) {
char a[32] = "123456789000000000";
foo1(&a[9], a);
EXPECT_STREQ("123456789123456789000000000", a);
foo1(a, &a[9]);
EXPECT_STREQ("123456789000000000", a);
}
void foo2(void *p, void *q) {
memmove(p, q, 19);
}
TEST(memmove, supposedPythonBug_test2) {
char a[32] = "123456789000000000";
foo2(&a[9], a);
EXPECT_STREQ("123456789123456789000000000", a);
foo2(a, &a[9]);
EXPECT_STREQ("123456789000000000", a);
}

View file

@ -68,6 +68,10 @@ $(TEST_LIBC_STR_OBJS): \
DEFAULT_CCFLAGS += \
-fno-builtin
o/$(MODE)/test/libc/str/memmove_test.o: \
OVERRIDE_CFLAGS += \
-O2 -D_FORTIFY_SOURCE=2
.PHONY: o/$(MODE)/test/libc/str
o/$(MODE)/test/libc/str: \
$(TEST_LIBC_STR_BINS) \

View file

@ -0,0 +1,47 @@
/*-*- 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/math.h"
#include "libc/runtime/gc.internal.h"
#include "libc/testlib/testlib.h"
#include "libc/x/x.h"
TEST(tgamma, test) {
EXPECT_STREQ("inf", gc(xasprintf("%.15g", tgamma(0.))));
EXPECT_STREQ("-inf", gc(xasprintf("%.15g", tgamma(-0.))));
EXPECT_STREQ("9.51350769866873", gc(xasprintf("%.15g", tgamma(.1))));
EXPECT_STREQ("-10.6862870211932", gc(xasprintf("%.15g", tgamma(-.1))));
EXPECT_STREQ("1.77245385090552", gc(xasprintf("%.15g", tgamma(.5))));
EXPECT_STREQ("-3.54490770181103", gc(xasprintf("%.15g", tgamma(-.5))));
EXPECT_STREQ("1", gc(xasprintf("%.15g", tgamma(1.))));
EXPECT_TRUE(isnan(tgamma(-1.)));
EXPECT_STREQ("0.886226925452758", gc(xasprintf("%.15g", tgamma(1.5))));
EXPECT_STREQ("2.36327180120735", gc(xasprintf("%.15g", tgamma(-1.5))));
EXPECT_STREQ("1", gc(xasprintf("%.15g", tgamma(2.))));
EXPECT_TRUE(isnan(tgamma(NAN)));
EXPECT_TRUE(isnan(tgamma(-NAN)));
EXPECT_STREQ("inf", gc(xasprintf("%.15g", tgamma(INFINITY))));
EXPECT_TRUE(isnan(tgamma(-INFINITY)));
EXPECT_STREQ("4.49423283715579e+307",
gc(xasprintf("%.15g", tgamma(__DBL_MIN__))));
EXPECT_STREQ("inf", gc(xasprintf("%.15g", tgamma(__DBL_MAX__))));
EXPECT_STREQ("4.5035996273705e+15",
gc(xasprintf("%.14g", tgamma(-1.0000000000000002))));
EXPECT_STREQ("-47453133.3893415",
gc(xasprintf("%.15g", tgamma(-2.1073424255447e-08))));
}

View file

@ -35,7 +35,7 @@
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
asm(".ident\t\"\\n\\n\
asm(".ident\t\"\\n\
getopt (BSD-3)\\n\
Copyright 1987, 1993, 1994 The Regents of the University of California\"");
asm(".include \"libc/disclaimer.inc\"");

37
third_party/linenoise/ezlinenoise.c vendored 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/runtime/gc.internal.h"
#include "libc/x/x.h"
#include "third_party/linenoise/linenoise.h"
/**
* Reads line of input from terminal w/ history file.
*/
char *ezlinenoise(const char *prompt, const char *prog) {
char *p, *h;
h = gc(xasprintf("%s/.%s_history", gc(xhomedir()), prog));
linenoiseHistoryLoad(h);
p = linenoise(prompt);
if (p && *p) {
linenoiseHistoryLoad(h);
linenoiseHistoryAdd(p);
linenoiseHistorySave(h);
}
return p;
}

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