mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 15:03:34 +00:00
Improve system call support
This commit is contained in:
parent
63b867bd2f
commit
3085ac7837
65 changed files with 900 additions and 544 deletions
|
@ -87,6 +87,7 @@ int chdir(const char *);
|
|||
int chmod(const char *, uint32_t);
|
||||
int chown(const char *, uint32_t, uint32_t);
|
||||
int chroot(const char *);
|
||||
int clone(int (*)(void *), void *, int, void *, ...);
|
||||
int close(int);
|
||||
int closedir(DIR *);
|
||||
int creat(const char *, uint32_t);
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
* @asyncsignalsafe
|
||||
* @vforksafe
|
||||
*/
|
||||
nodiscard int dup(int fd) {
|
||||
int dup(int fd) {
|
||||
if (!IsWindows()) {
|
||||
return sys_dup(fd);
|
||||
} else {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
│ 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/ntspawn.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
|
@ -44,6 +45,8 @@ textwindows int sys_execve_nt(const char *program, char *const argv[],
|
|||
startinfo.hStdError = g_fds.p[2].handle;
|
||||
rc = ntspawn(program, argv, envp, 0, 0, 0, 1, 0, 0, &startinfo, &procinfo);
|
||||
if (rc == -1) return -1;
|
||||
CloseHandle(g_fds.p[0].handle);
|
||||
CloseHandle(g_fds.p[1].handle);
|
||||
CloseHandle(procinfo.hThread);
|
||||
do {
|
||||
WaitForSingleObject(procinfo.hProcess, -1);
|
||||
|
|
|
@ -30,7 +30,8 @@
|
|||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int sys_fadvise_nt(int fd, uint64_t offset, uint64_t len, int advice) {
|
||||
textwindows int sys_fadvise_nt(int fd, uint64_t offset, uint64_t len,
|
||||
int advice) {
|
||||
int64_t h2;
|
||||
NtStatus status;
|
||||
uint32_t sharemode;
|
||||
|
|
|
@ -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/struct/stat.h"
|
||||
|
@ -26,26 +27,44 @@
|
|||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
/**
|
||||
* Returns true if file exists at path.
|
||||
*
|
||||
* This function is equivalent to:
|
||||
*
|
||||
* struct stat st;
|
||||
* return stat(path, &st) != -1;
|
||||
*
|
||||
* Please note that things which aren't strictly files, e.g. directories
|
||||
* or sockets, could be considered files for the purposes of this
|
||||
* function. The stat() function may be used to differentiate them.
|
||||
*/
|
||||
bool fileexists(const char *path) {
|
||||
int rc, olderr;
|
||||
int e;
|
||||
struct stat st;
|
||||
struct ZiposUri zipname;
|
||||
uint16_t path16[PATH_MAX];
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
|
||||
if (!IsWindows()) {
|
||||
olderr = errno;
|
||||
rc = __sys_fstatat(AT_FDCWD, path, &st, 0);
|
||||
if (rc == -1 && (errno == ENOENT || errno == ENOTDIR)) {
|
||||
errno = olderr;
|
||||
if (weaken(__zipos_open) && weaken(__zipos_parseuri)(path, &zipname) != -1) {
|
||||
e = errno;
|
||||
if (weaken(__zipos_stat)(&zipname, &st) != -1) {
|
||||
return true;
|
||||
} else {
|
||||
errno = e;
|
||||
return false;
|
||||
}
|
||||
} else if (IsMetal()) {
|
||||
return false;
|
||||
} else if (!IsWindows()) {
|
||||
e = errno;
|
||||
if (__sys_fstatat(AT_FDCWD, path, &st, 0) != -1) {
|
||||
return true;
|
||||
} else {
|
||||
errno = e;
|
||||
return false;
|
||||
}
|
||||
return rc != -1;
|
||||
} else {
|
||||
if (__mkntpath(path, path16) == -1) return -1;
|
||||
return GetFileAttributes(path16) != -1u;
|
||||
|
|
|
@ -16,11 +16,12 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/sysdebug.internal.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nexgen32e/bsr.h"
|
||||
#include "libc/nt/enum/fileflagandattributes.h"
|
||||
#include "libc/nt/enum/fileinfobyhandleclass.h"
|
||||
|
@ -37,12 +38,6 @@
|
|||
#include "libc/sysv/consts/s.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
#if 0
|
||||
#define DEBUG(FMT, ...) (dprintf)(2, FMT "\n", ##__VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG(FMT, ...) (void)0
|
||||
#endif
|
||||
|
||||
static textwindows uint32_t GetSizeOfReparsePoint(int64_t fh) {
|
||||
wint_t x, y;
|
||||
const char16_t *p;
|
||||
|
@ -69,7 +64,7 @@ static textwindows uint32_t GetSizeOfReparsePoint(int64_t fh) {
|
|||
z += x < 0200 ? 1 : bsrl(tpenc(x)) >> 3;
|
||||
}
|
||||
} else {
|
||||
DEBUG("GetSizeOfReparsePoint failed %d", GetLastError());
|
||||
SYSDEBUG("GetSizeOfReparsePoint failed %d", GetLastError());
|
||||
}
|
||||
return z;
|
||||
}
|
||||
|
@ -122,8 +117,10 @@ textwindows int sys_fstat_nt(int64_t handle, struct stat *st) {
|
|||
&fci, sizeof(fci))) {
|
||||
actualsize = fci.CompressedFileSize;
|
||||
}
|
||||
st->st_blocks = roundup(actualsize, PAGESIZE) / 512;
|
||||
st->st_blocks = ROUNDUP(actualsize, PAGESIZE) / 512;
|
||||
}
|
||||
} else {
|
||||
SYSDEBUG("GetFileInformationByHandle failed %d", GetLastError());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -131,6 +128,7 @@ textwindows int sys_fstat_nt(int64_t handle, struct stat *st) {
|
|||
}
|
||||
return 0;
|
||||
} else {
|
||||
SYSDEBUG("GetFileType failed %d", GetLastError());
|
||||
return __winerr();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,9 +109,9 @@ char *sys_getcwd(char *, u64) hidden;
|
|||
char *sys_getcwd_xnu(char *, u64) hidden;
|
||||
i32 __sys_dup3(i32, i32, i32) hidden;
|
||||
i32 __sys_execve(const char *, char *const[], char *const[]) hidden;
|
||||
i32 __sys_fcntl(i32, i32, u64) hidden;
|
||||
i32 __sys_fstat(i32, struct stat *) hidden;
|
||||
i32 __sys_fstatat(i32, const char *, struct stat *, i32) hidden;
|
||||
i32 __sys_fcntl(i32, i32, ...) hidden;
|
||||
i32 __sys_fstat(i32, void *) hidden;
|
||||
i32 __sys_fstatat(i32, const char *, void *, i32) hidden;
|
||||
i32 __sys_getrusage(i32, struct rusage *) hidden;
|
||||
i32 __sys_openat(i32, const char *, i32, u32) hidden;
|
||||
i32 __sys_pipe2(i32[hasatleast 2], u32) hidden;
|
||||
|
|
|
@ -16,21 +16,56 @@
|
|||
│ 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/struct/metastat.internal.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/nt/enum/filetype.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
/**
|
||||
* Returns true if file descriptor is backed by character i/o.
|
||||
*
|
||||
* This function is equivalent to:
|
||||
*
|
||||
* struct stat st;
|
||||
* return stat(path, &st) != -1 && S_ISCHR(st.st_mode);
|
||||
*
|
||||
* Except faster and with fewer dependencies.
|
||||
*
|
||||
* @see isregularfile(), isdirectory(), issymlink(), fileexists()
|
||||
*/
|
||||
textstartup bool32 ischardev(int fd) {
|
||||
int olderr;
|
||||
struct stat st;
|
||||
olderr = errno;
|
||||
if (fstat(fd, &st) != -1) {
|
||||
return S_ISCHR(st.st_mode);
|
||||
bool32 ischardev(int fd) {
|
||||
int e;
|
||||
union metastat st;
|
||||
if (__isfdkind(fd, kFdZip)) {
|
||||
e = errno;
|
||||
if (weaken(__zipos_fstat)(
|
||||
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, &st.linux) !=
|
||||
-1) {
|
||||
return S_ISCHR(st.linux.st_mode);
|
||||
} else {
|
||||
errno = olderr;
|
||||
errno = e;
|
||||
return false;
|
||||
}
|
||||
} else if (IsMetal()) {
|
||||
return true;
|
||||
} else if (!IsWindows()) {
|
||||
e = errno;
|
||||
if (__sys_fstat(fd, &st) != -1) {
|
||||
return S_ISCHR(METASTAT(st, st_mode));
|
||||
} else {
|
||||
errno = e;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return __isfdkind(fd, kFdConsole) ||
|
||||
(__isfdkind(fd, kFdFile) &&
|
||||
GetFileType(g_fds.p[fd].handle) == kNtFileTypeChar);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,8 +16,10 @@
|
|||
│ 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/struct/metastat.internal.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
|
@ -25,19 +27,44 @@
|
|||
#include "libc/nt/files.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
/**
|
||||
* Returns true if file exists and is a directory.
|
||||
*
|
||||
* This function is equivalent to:
|
||||
*
|
||||
* struct stat st;
|
||||
* return fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW) != -1 &&
|
||||
* S_ISDIR(st.st_mode);
|
||||
*
|
||||
* Except faster and with fewer dependencies.
|
||||
*
|
||||
* @see isregularfile(), issymlink(), ischardev()
|
||||
*/
|
||||
bool isdirectory(const char *path) {
|
||||
struct stat st;
|
||||
int rc, olderr;
|
||||
int rc, e;
|
||||
union metastat st;
|
||||
struct ZiposUri zipname;
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
|
||||
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);
|
||||
if (weaken(__zipos_open) && weaken(__zipos_parseuri)(path, &zipname) != -1) {
|
||||
e = errno;
|
||||
if (weaken(__zipos_stat)(&zipname, &st.linux) != -1) {
|
||||
return S_ISDIR(st.linux.st_mode);
|
||||
} else {
|
||||
errno = e;
|
||||
return false;
|
||||
}
|
||||
} else if (IsMetal()) {
|
||||
return false;
|
||||
} else if (!IsWindows()) {
|
||||
e = errno;
|
||||
if (__sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW) != -1) {
|
||||
return S_ISDIR(METASTAT(st, st_mode));
|
||||
} else {
|
||||
errno = e;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return isdirectory_nt(path);
|
||||
}
|
||||
|
|
|
@ -16,29 +16,52 @@
|
|||
│ 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/struct/stat.h"
|
||||
#include "libc/calls/struct/metastat.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
/**
|
||||
* Returns true if file exists and is a regular file.
|
||||
*
|
||||
* This function is equivalent to:
|
||||
*
|
||||
* return fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW) != -1 &&
|
||||
* S_ISREG(st.st_mode);
|
||||
*
|
||||
* Except faster and with fewer dependencies.
|
||||
*
|
||||
* @see isdirectory(), ischardev(), issymlink()
|
||||
*/
|
||||
bool isregularfile(const char *path) {
|
||||
struct stat st;
|
||||
int rc, olderr;
|
||||
int rc, e;
|
||||
union metastat st;
|
||||
struct ZiposUri zipname;
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
|
||||
if (!IsWindows()) {
|
||||
olderr = errno;
|
||||
rc = sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW);
|
||||
if (rc == -1 && (errno == ENOENT || errno == ENOTDIR)) {
|
||||
errno = olderr;
|
||||
if (weaken(__zipos_open) && weaken(__zipos_parseuri)(path, &zipname) != -1) {
|
||||
e = errno;
|
||||
if (weaken(__zipos_stat)(&zipname, &st.linux) != -1) {
|
||||
return S_ISREG(st.linux.st_mode);
|
||||
} else {
|
||||
errno = e;
|
||||
return false;
|
||||
}
|
||||
} else if (IsMetal()) {
|
||||
return false;
|
||||
} else if (!IsWindows()) {
|
||||
e = errno;
|
||||
if (__sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW) != -1) {
|
||||
return S_ISREG(METASTAT(st, st_mode));
|
||||
} else {
|
||||
errno = e;
|
||||
return false;
|
||||
}
|
||||
return rc != -1 && S_ISREG(st.st_mode);
|
||||
} else {
|
||||
return isregularfile_nt(path);
|
||||
}
|
||||
|
|
|
@ -16,8 +16,10 @@
|
|||
│ 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/struct/metastat.internal.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
|
@ -25,19 +27,38 @@
|
|||
#include "libc/nt/files.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
/**
|
||||
* Returns true if file exists and is a symbolic link.
|
||||
*
|
||||
* This function is equivalent to:
|
||||
*
|
||||
* struct stat st;
|
||||
* return fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW) != -1 &&
|
||||
* S_ISLNK(st.st_mode);
|
||||
*
|
||||
* Except faster and with fewer dependencies.
|
||||
*
|
||||
* @see isregularfile(), isdirectory(), fileexists(), ischardev()
|
||||
*/
|
||||
bool issymlink(const char *path) {
|
||||
struct stat st;
|
||||
int rc, olderr;
|
||||
int e;
|
||||
union metastat st;
|
||||
struct ZiposUri zipname;
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
|
||||
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);
|
||||
if (weaken(__zipos_open) && weaken(__zipos_parseuri)(path, &zipname) != -1) {
|
||||
return false;
|
||||
} else if (IsMetal()) {
|
||||
return false;
|
||||
} else if (!IsWindows()) {
|
||||
e = errno;
|
||||
if (__sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW) != -1) {
|
||||
return S_ISLNK(METASTAT(st, st_mode));
|
||||
} else {
|
||||
errno = e;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return issymlink_nt(path);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sysdebug.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nt/enum/accessmask.h"
|
||||
#include "libc/nt/enum/securityimpersonationlevel.h"
|
||||
|
@ -34,12 +35,6 @@
|
|||
#include "libc/sysv/consts/ok.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
#if 0
|
||||
#define DEBUG(FMT, ...) (dprintf)(2, FMT "\n", ##__VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG(FMT, ...) (void)0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Asks Microsoft if we're authorized to use a folder or file.
|
||||
*
|
||||
|
@ -92,24 +87,24 @@ TryAgain:
|
|||
if (result || flags == F_OK) {
|
||||
rc = 0;
|
||||
} else {
|
||||
DEBUG("ntaccesscheck finale failed %d %d", result, flags);
|
||||
SYSDEBUG("ntaccesscheck finale failed %d %d", result, flags);
|
||||
rc = eacces();
|
||||
}
|
||||
} else {
|
||||
rc = __winerr();
|
||||
DEBUG("AccessCheck failed: %m");
|
||||
SYSDEBUG("AccessCheck failed: %m");
|
||||
}
|
||||
} else {
|
||||
rc = __winerr();
|
||||
DEBUG("DuplicateToken failed: %m");
|
||||
SYSDEBUG("DuplicateToken failed: %m");
|
||||
}
|
||||
} else {
|
||||
rc = __winerr();
|
||||
DEBUG("OpenProcessToken failed: %m");
|
||||
SYSDEBUG("OpenProcessToken failed: %m");
|
||||
}
|
||||
} else {
|
||||
e = GetLastError();
|
||||
DEBUG("GetFileSecurity failed: %d %d", e, secsize);
|
||||
SYSDEBUG("GetFileSecurity failed: %d %d", e, secsize);
|
||||
if (!IsTiny() && e == kNtErrorInsufficientBuffer) {
|
||||
if (!freeme && weaken(malloc) && (freeme = weaken(malloc)(secsize))) {
|
||||
s = freeme;
|
||||
|
|
|
@ -17,28 +17,45 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/fd.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
||||
int sys_openat(int dirfd, const char *file, int flags, unsigned mode) {
|
||||
int fd, err;
|
||||
err = errno;
|
||||
fd = __sys_openat(dirfd, file, flags, mode);
|
||||
|
||||
static bool once, modernize;
|
||||
int d, e, f;
|
||||
/*
|
||||
* RHEL5 doesn't support O_CLOEXEC
|
||||
* What on earth is it doing here?
|
||||
* It returns -530!
|
||||
* RHEL5 doesn't support O_CLOEXEC. It's hard to test for this.
|
||||
* Sometimes the system call succeeds and it just doesn't set the
|
||||
* flag. Other times, it return -530 which makes no sense.
|
||||
*/
|
||||
if (IsLinux() && fd == -1 && errno > 255) {
|
||||
errno = err;
|
||||
fd = __sys_openat(dirfd, file, flags & ~O_CLOEXEC, mode);
|
||||
if (fd != -1 && (flags & O_CLOEXEC)) {
|
||||
__sys_fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||
if (!IsLinux() || !(flags & O_CLOEXEC) || modernize) {
|
||||
return __sys_openat(dirfd, file, flags, mode);
|
||||
} else if (once) {
|
||||
if ((d = __sys_openat(dirfd, file, flags & ~O_CLOEXEC, mode)) != -1) {
|
||||
e = errno;
|
||||
if (__sys_fcntl(d, F_SETFD, FD_CLOEXEC) == -1) {
|
||||
errno = e;
|
||||
}
|
||||
}
|
||||
|
||||
return fd;
|
||||
} else {
|
||||
e = errno;
|
||||
if ((d = __sys_openat(dirfd, file, flags, mode)) != -1) {
|
||||
if ((f = __sys_fcntl(d, F_GETFD)) != -1) {
|
||||
if (f & FD_CLOEXEC) {
|
||||
modernize = true;
|
||||
} else {
|
||||
__sys_fcntl(d, F_SETFD, FD_CLOEXEC);
|
||||
}
|
||||
}
|
||||
errno = e;
|
||||
once = true;
|
||||
} else if (errno > 255) {
|
||||
once = true;
|
||||
return sys_openat(dirfd, file, flags, mode);
|
||||
}
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
|
|
@ -45,10 +45,6 @@ int openat(int dirfd, const char *file, int flags, ...) {
|
|||
va_list va;
|
||||
unsigned mode;
|
||||
struct ZiposUri zipname;
|
||||
if (strstr(file, "0/o/dbg/test")) {
|
||||
(dprintf)(2, "-- wut %`'s\n", file);
|
||||
if (weaken(__die)) weaken(__die)();
|
||||
}
|
||||
va_start(va, flags);
|
||||
mode = va_arg(va, unsigned);
|
||||
va_end(va);
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/framebuffervirtualscreeninfo.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nt/enum/version.h"
|
||||
#include "libc/nt/system.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
@ -70,9 +71,9 @@ int reboot(int howto) {
|
|||
if (howto == 0xD000FCE2u) {
|
||||
ok = !!SetSuspendState(0, 0, 0);
|
||||
} else {
|
||||
howto |= kNtShutdownForceOthers;
|
||||
howto |= kNtShutdownForceSelf;
|
||||
if (NtGetVersion() >= 8) {
|
||||
howto |= kNtShutdownForceOthers;
|
||||
if (NtGetVersion() >= kNtVersionWindows8) {
|
||||
howto |= kNtShutdownHybrid;
|
||||
}
|
||||
if (immediately) {
|
||||
|
|
|
@ -5,6 +5,14 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#define METASTAT(x, field) \
|
||||
(IsLinux() || IsMetal() ? x.linux.field \
|
||||
: IsXnu() ? x.xnu.field \
|
||||
: IsFreebsd() ? x.freebsd.field \
|
||||
: IsOpenbsd() ? x.openbsd.field \
|
||||
: IsNetbsd() ? x.netbsd.field \
|
||||
: 0)
|
||||
|
||||
struct stat_xnu {
|
||||
int32_t st_dev;
|
||||
uint16_t st_mode, st_nlink;
|
||||
|
|
11
libc/calls/sysdebug.internal.h
Normal file
11
libc/calls/sysdebug.internal.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_SYSDEBUG_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_SYSDEBUG_INTERNAL_H_
|
||||
#include "libc/calls/calls.h"
|
||||
|
||||
#if 0
|
||||
#define SYSDEBUG(FMT, ...) (dprintf)(2, FMT "\n", ##__VA_ARGS__)
|
||||
#else
|
||||
#define SYSDEBUG(FMT, ...) (void)0
|
||||
#endif
|
||||
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_SYSDEBUG_INTERNAL_H_ */
|
|
@ -16,9 +16,11 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/rusage.h"
|
||||
#include "libc/calls/sysdebug.internal.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/accounting.h"
|
||||
|
@ -62,12 +64,21 @@ textwindows int sys_wait4_nt(int pid, int *opt_out_wstatus, int options,
|
|||
dwExitCode = kNtStillActive;
|
||||
if (options & WNOHANG) {
|
||||
i = WaitForMultipleObjects(count, handles, false, 0);
|
||||
if (i == kNtWaitTimeout) return 0;
|
||||
if (i == kNtWaitTimeout) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
i = WaitForMultipleObjects(count, handles, false, -1);
|
||||
}
|
||||
if (i == kNtWaitFailed) return __winerr();
|
||||
if (!GetExitCodeProcess(handles[i], &dwExitCode)) return __winerr();
|
||||
if (i == kNtWaitFailed) {
|
||||
SYSDEBUG("WaitForMultipleObjects failed %d", GetLastError());
|
||||
return __winerr();
|
||||
}
|
||||
assert(__isfdkind(pids[i], kFdProcess));
|
||||
if (!GetExitCodeProcess(handles[i], &dwExitCode)) {
|
||||
SYSDEBUG("GetExitCodeProcess failed %d", GetLastError());
|
||||
return __winerr();
|
||||
}
|
||||
if (dwExitCode == kNtStillActive) continue;
|
||||
if (opt_out_wstatus) { /* @see WEXITSTATUS() */
|
||||
*opt_out_wstatus = (dwExitCode & 0xff) << 8;
|
||||
|
@ -76,14 +87,12 @@ textwindows int sys_wait4_nt(int pid, int *opt_out_wstatus, int options,
|
|||
memset(opt_out_rusage, 0, sizeof(*opt_out_rusage));
|
||||
if (GetProcessTimes(g_fds.p[pids[i]].handle, &createfiletime,
|
||||
&exitfiletime, &kernelfiletime, &userfiletime)) {
|
||||
opt_out_rusage->ru_utime.tv_sec =
|
||||
ReadFileTime(userfiletime) / HECTONANOSECONDS;
|
||||
opt_out_rusage->ru_utime.tv_usec =
|
||||
ReadFileTime(userfiletime) % HECTONANOSECONDS;
|
||||
opt_out_rusage->ru_stime.tv_sec =
|
||||
ReadFileTime(kernelfiletime) / HECTONANOSECONDS;
|
||||
opt_out_rusage->ru_stime.tv_usec =
|
||||
ReadFileTime(kernelfiletime) % HECTONANOSECONDS;
|
||||
opt_out_rusage->ru_utime =
|
||||
WindowsDurationToTimeVal(ReadFileTime(userfiletime));
|
||||
opt_out_rusage->ru_stime =
|
||||
WindowsDurationToTimeVal(ReadFileTime(kernelfiletime));
|
||||
} else {
|
||||
SYSDEBUG("GetProcessTimes failed %d", GetLastError());
|
||||
}
|
||||
}
|
||||
CloseHandle(g_fds.p[pids[i]].handle);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sysdebug.internal.h"
|
||||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/nt/enum/exceptionhandleractions.h"
|
||||
#include "libc/nt/enum/signal.h"
|
||||
|
@ -29,6 +30,7 @@ textwindows unsigned __wincrash(struct NtExceptionPointers *ep) {
|
|||
ucontext_t ctx;
|
||||
struct siginfo si;
|
||||
} g;
|
||||
SYSDEBUG("__wincrash");
|
||||
switch (ep->ExceptionRecord->ExceptionCode) {
|
||||
case kNtSignalBreakpoint:
|
||||
sig = SIGTRAP;
|
||||
|
|
|
@ -19,6 +19,13 @@
|
|||
#include "libc/nt/struct/teb.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
/**
|
||||
* Returns New Technology version, e.g.
|
||||
*
|
||||
* if (IsWindows() && NtGetVersion() >= kNtVersionWindows10) {...}
|
||||
*
|
||||
* This can only be called on Windows.
|
||||
*/
|
||||
textwindows noasan int NtGetVersion(void) {
|
||||
return (NtGetPeb()->OSMajorVersion & 0xff) << 8 | NtGetPeb()->OSMinorVersion;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,9 @@
|
|||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/color.internal.h"
|
||||
#include "libc/log/gdb.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/nexgen32e/stackframe.h"
|
||||
#include "libc/nexgen32e/vendor.internal.h"
|
||||
|
@ -32,8 +34,6 @@
|
|||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/w.h"
|
||||
|
||||
#define RESTORE_TTY "\e[?1000;1002;1015;1006l\e[?25h"
|
||||
|
||||
/**
|
||||
* Launches GDB debugger GUI for current process.
|
||||
*
|
||||
|
@ -59,7 +59,7 @@ relegated int(attachdebugger)(intptr_t continuetoaddr) {
|
|||
(ttyfd = open(_PATH_TTY, O_RDWR | O_CLOEXEC)) == -1) {
|
||||
return -1;
|
||||
}
|
||||
write(ttyfd, RESTORE_TTY, strlen(RESTORE_TTY));
|
||||
__restore_tty(ttyfd);
|
||||
snprintf(pidstr, sizeof(pidstr), "%u", getpid());
|
||||
layout = "layout asm";
|
||||
if ((elf = FindDebugBinary())) {
|
||||
|
|
|
@ -17,9 +17,11 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/log/color.internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/nt/enum/version.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
|
@ -47,7 +49,9 @@ bool cancolor(void) {
|
|||
static bool once;
|
||||
static bool result;
|
||||
if (!once) {
|
||||
result = !!strcmp(nulltoempty(getenv("DONTANSIMEBRO")), "1") &&
|
||||
result = (!IsWindows() || NtGetVersion() >= kNtVersionWindows10 ||
|
||||
!ischardev(1)) &&
|
||||
!!strcmp(nulltoempty(getenv("DONTANSIMEBRO")), "1") &&
|
||||
!!strcmp(nulltoempty(getenv("TERM")), "dumb");
|
||||
once = true;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
relegated wontreturn void __die(void) {
|
||||
static bool once;
|
||||
if (cmpxchg(&once, false, true)) {
|
||||
__restore_tty();
|
||||
__restore_tty(1);
|
||||
if (IsDebuggerPresent(false)) DebugBreak();
|
||||
ShowBacktrace(2, NULL);
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ extern struct sigaction g_oldcrashacts[8] hidden;
|
|||
void __start_fatal(const char *, int) hidden;
|
||||
void __start_fatal_ndebug(void) hidden;
|
||||
void __oncrash(int, struct siginfo *, struct ucontext *) relegated;
|
||||
void __restore_tty(void);
|
||||
void __restore_tty(int);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -265,7 +265,7 @@ relegated void __oncrash(int sig, struct siginfo *si, ucontext_t *ctx) {
|
|||
: 0);
|
||||
}
|
||||
if (gdbpid > 0 && (sig == SIGTRAP || sig == SIGQUIT)) return;
|
||||
__restore_tty();
|
||||
__restore_tty(1);
|
||||
ShowCrashReport(err, STDERR_FILENO, sig, si, ctx);
|
||||
exit(128 + sig);
|
||||
unreachable;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/log/color.internal.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
|
@ -36,9 +37,9 @@ const void *const g_oldtermios_ctor[] initarray = {
|
|||
g_oldtermios_init,
|
||||
};
|
||||
|
||||
void __restore_tty(void) {
|
||||
if (g_oldtermios.c_lflag && isatty(1)) {
|
||||
write(1, ANSI_RESTORE, strlen(ANSI_RESTORE));
|
||||
tcsetattr(1, TCSAFLUSH, &g_oldtermios);
|
||||
void __restore_tty(int fd) {
|
||||
if (g_oldtermios.c_lflag && isatty(fd) && cancolor()) {
|
||||
write(fd, ANSI_RESTORE, strlen(ANSI_RESTORE));
|
||||
tcsetattr(fd, TCSAFLUSH, &g_oldtermios);
|
||||
}
|
||||
}
|
|
@ -32,7 +32,7 @@
|
|||
relegated void __start_fatal(const char *file, int line) {
|
||||
bool colorful;
|
||||
char s[16 + 16 + 16 + 16 + PATH_MAX + 16 + NAME_MAX + 16], *p = s;
|
||||
__restore_tty();
|
||||
__restore_tty(1);
|
||||
colorful = cancolor();
|
||||
*p++ = '\r';
|
||||
if (colorful) p = stpcpy(p, "\e[J\e[30;101m");
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
*/
|
||||
relegated void __start_fatal_ndebug(void) {
|
||||
char s[16 + 16 + 16 + 16 + PATH_MAX + 16], *p = s;
|
||||
__restore_tty();
|
||||
__restore_tty(1);
|
||||
*p++ = '\r';
|
||||
if (cancolor()) p = stpcpy(p, "\e[J");
|
||||
p = stpcpy(p, "error:");
|
||||
|
|
107
libc/runtime/clone.c
Normal file
107
libc/runtime/clone.c
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*-*- 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/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nexgen32e/nt2sysv.h"
|
||||
#include "libc/nexgen32e/stackframe.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/thread.h"
|
||||
#include "libc/sysv/consts/clone.h"
|
||||
#include "libc/sysv/consts/nr.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
struct WinThread {
|
||||
int (*func)(void *);
|
||||
void *param;
|
||||
void *stack;
|
||||
};
|
||||
|
||||
static noasan textwindows uint32_t winthread(void *param) {
|
||||
struct WinThread *wt = param;
|
||||
asm volatile("mov\t%%rbp,%%r14\n\t"
|
||||
"mov\t%%rsp,%%r15\n\t"
|
||||
"xor\t%%ebp,%%ebp\n\t"
|
||||
"mov\t%2,%%rsp\n\t"
|
||||
"call\t*%0\n\t"
|
||||
"mov\t%%r14,%%rbp\n\t"
|
||||
"mov\t%%r15,%%rsp"
|
||||
: /* no outputs */
|
||||
: "m"(wt->func), "D"(wt->param), "m"(wt->stack)
|
||||
: "r14", "r15", "memory");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates thread.
|
||||
*
|
||||
* @note CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND creates thread
|
||||
* @note CLONE_VFORK|CLONE_VM|SIGCHLD does vfork()
|
||||
* @note SIGCHLD does fork()
|
||||
*/
|
||||
privileged int clone(int (*f)(void *), void *stack, int flags, void *arg, ...) {
|
||||
int64_t h;
|
||||
va_list va;
|
||||
intptr_t ax;
|
||||
uint32_t tid;
|
||||
int32_t *ptid;
|
||||
register void *tls asm("r8");
|
||||
register int32_t *ctid asm("r10");
|
||||
register int (*func)(void *) asm("r9");
|
||||
if (IsLinux() || IsNetbsd()) {
|
||||
va_start(va, arg);
|
||||
ptid = va_arg(va, int32_t *);
|
||||
tls = va_arg(va, void *);
|
||||
ctid = va_arg(va, int32_t *);
|
||||
va_end(va);
|
||||
func = f;
|
||||
stack = (void *)(((uintptr_t)stack & -16) - 8);
|
||||
*(intptr_t *)stack = (intptr_t)arg;
|
||||
asm volatile("syscall"
|
||||
: "=a"(ax)
|
||||
: "0"(__NR_clone), "D"(flags), "S"(stack), "d"(ptid),
|
||||
"r"(ctid), "r"(tls), "r"(func)
|
||||
: "rcx", "r11", "memory");
|
||||
if (ax) return ax;
|
||||
asm volatile("xor\t%%ebp,%%ebp\n\t"
|
||||
"pop\t%%rdi\n\t"
|
||||
"call\t%1"
|
||||
: "=a"(ax)
|
||||
: "r"(func)
|
||||
: "memory");
|
||||
asm volatile("syscall"
|
||||
: /* no outputs */
|
||||
: "a"(__NR_exit), "D"(ax)
|
||||
: "memory");
|
||||
unreachable;
|
||||
} else if (IsWindows()) {
|
||||
if (flags == (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND)) {
|
||||
if ((h = CreateThread(0, PAGESIZE, NT2SYSV(winthread),
|
||||
&(struct WinThread){f, arg, stack}, 0, &tid))) {
|
||||
CloseHandle(h);
|
||||
return tid;
|
||||
} else {
|
||||
return __winerr();
|
||||
}
|
||||
} else {
|
||||
return einval();
|
||||
}
|
||||
} else {
|
||||
return enosys();
|
||||
}
|
||||
}
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sysdebug.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
@ -90,7 +91,10 @@ void *mmap(void *addr, size_t size, int prot, int flags, int fd, int64_t off) {
|
|||
f = flags | MAP_FIXED;
|
||||
if (IsOpenbsd() && (f & MAP_GROWSDOWN)) { /* openbsd:dubstack */
|
||||
dm = sys_mmap(addr, size, prot, f & ~MAP_GROWSDOWN, fd, off);
|
||||
if (dm.addr == MAP_FAILED) return MAP_FAILED;
|
||||
if (dm.addr == MAP_FAILED) {
|
||||
SYSDEBUG("sys_mmap failed");
|
||||
return MAP_FAILED;
|
||||
}
|
||||
}
|
||||
dm = sys_mmap(addr, size, prot, f, fd, off);
|
||||
if (dm.addr == MAP_FAILED || dm.addr != addr) {
|
||||
|
|
|
@ -24,9 +24,12 @@
|
|||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/yoink.inc"
|
||||
#include "libc/sysv/consts/fio.h"
|
||||
#include "libc/sysv/consts/ipproto.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/poll.h"
|
||||
#include "libc/sysv/consts/so.h"
|
||||
#include "libc/sysv/consts/sock.h"
|
||||
#include "libc/sysv/consts/sol.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int sys_accept_nt(struct Fd *fd, void *addr, uint32_t *addrsize,
|
||||
|
@ -38,21 +41,14 @@ textwindows int sys_accept_nt(struct Fd *fd, void *addr, uint32_t *addrsize,
|
|||
for (;;) {
|
||||
if (!WSAPoll(&(struct sys_pollfd_nt){fd->handle, POLLIN}, 1, 1000))
|
||||
continue;
|
||||
if ((client = __reservefd()) == -1) return -1;
|
||||
if ((h = WSAAccept(fd->handle, addr, (int32_t *)addrsize, 0, 0)) != -1) {
|
||||
oflags = 0;
|
||||
if (flags & SOCK_CLOEXEC) oflags |= O_CLOEXEC;
|
||||
if (flags & SOCK_NONBLOCK) oflags |= O_NONBLOCK;
|
||||
if (flags & SOCK_NONBLOCK) {
|
||||
if (__sys_ioctlsocket_nt(g_fds.p[client].handle, FIONBIO,
|
||||
(uint32_t[]){1}) == -1) {
|
||||
__winsockerr();
|
||||
__sys_closesocket_nt(g_fds.p[client].handle);
|
||||
__releasefd(client);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
sockfd2 = calloc(1, sizeof(struct SockFd));
|
||||
if ((!(flags & SOCK_NONBLOCK) ||
|
||||
__sys_ioctlsocket_nt(h, FIONBIO, (uint32_t[]){1}) != -1) &&
|
||||
(sockfd2 = calloc(1, sizeof(struct SockFd)))) {
|
||||
if ((client = __reservefd()) != -1) {
|
||||
sockfd2->family = sockfd->family;
|
||||
sockfd2->type = sockfd->type;
|
||||
sockfd2->protocol = sockfd->protocol;
|
||||
|
@ -62,9 +58,11 @@ textwindows int sys_accept_nt(struct Fd *fd, void *addr, uint32_t *addrsize,
|
|||
g_fds.p[client].handle = h;
|
||||
g_fds.p[client].extra = (uintptr_t)sockfd2;
|
||||
return client;
|
||||
} else {
|
||||
__releasefd(client);
|
||||
}
|
||||
free(sockfd2);
|
||||
}
|
||||
__sys_closesocket_nt(h);
|
||||
}
|
||||
return __winsockerr();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,24 +26,27 @@
|
|||
#include "libc/sysv/consts/poll.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int sys_poll_nt(struct pollfd *fds, uint64_t nfds, uint64_t timeoutms) {
|
||||
int got;
|
||||
size_t i;
|
||||
uint64_t waitfor;
|
||||
textwindows int sys_poll_nt(struct pollfd *fds, uint64_t nfds, uint64_t ms) {
|
||||
int i, got, waitfor;
|
||||
struct sys_pollfd_nt ntfds[64];
|
||||
if (nfds > 64) return einval();
|
||||
if (nfds >= ARRAYLEN(ntfds)) return einval();
|
||||
for (i = 0; i < nfds; ++i) {
|
||||
if (!__isfdkind(fds[i].fd, kFdSocket)) return ebadf();
|
||||
if (fds[i].fd >= 0) {
|
||||
if (!__isfdkind(fds[i].fd, kFdSocket)) return enotsock();
|
||||
ntfds[i].handle = g_fds.p[fds[i].fd].handle;
|
||||
ntfds[i].events = fds[i].events & (POLLPRI | POLLIN | POLLOUT);
|
||||
} else {
|
||||
ntfds[i].handle = -1;
|
||||
ntfds[i].events = POLLIN;
|
||||
}
|
||||
}
|
||||
for (;;) {
|
||||
if (cmpxchg(&__interrupted, true, false)) return eintr();
|
||||
waitfor = MIN(1000, timeoutms); /* for ctrl+c */
|
||||
waitfor = MIN(1000, ms); /* for ctrl+c */
|
||||
if ((got = WSAPoll(ntfds, nfds, waitfor)) != -1) {
|
||||
if (!got && (timeoutms -= waitfor)) continue;
|
||||
if (!got && (ms -= waitfor) > 0) continue;
|
||||
for (i = 0; i < nfds; ++i) {
|
||||
fds[i].revents = ntfds[i].revents;
|
||||
fds[i].revents = ntfds[i].handle < 0 ? 0 : ntfds[i].revents;
|
||||
}
|
||||
return got;
|
||||
} else {
|
||||
|
|
|
@ -18,16 +18,21 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/nt/iphlpapi.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/yoink.inc"
|
||||
#include "libc/sysv/consts/fio.h"
|
||||
#include "libc/sysv/consts/ipproto.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/so.h"
|
||||
#include "libc/sysv/consts/sock.h"
|
||||
#include "libc/sysv/consts/sol.h"
|
||||
|
||||
/* ioctl(SIOCGIFCONFIG) for Windows need to access the following functions through
|
||||
* weak reference. This ensure those symbols are not stripped during final link
|
||||
/*
|
||||
* ioctl(SIOCGIFCONFIG) for Windows need to access the following
|
||||
* functions through weak reference. This ensure those symbols are not
|
||||
* stripped during final link.
|
||||
*/
|
||||
STATIC_YOINK("GetAdaptersAddresses");
|
||||
STATIC_YOINK("tprecode16to8");
|
||||
|
|
|
@ -23,7 +23,9 @@
|
|||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Creates new system resource for network communication.
|
||||
* Creates new system resource for network communication, e.g.
|
||||
*
|
||||
* int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
*
|
||||
* @param family can be AF_UNIX, AF_INET, etc.
|
||||
* @param type can be SOCK_STREAM (for TCP), SOCK_DGRAM (e.g. UDP), or
|
||||
|
|
|
@ -67,7 +67,7 @@ struct dirstream {
|
|||
struct {
|
||||
unsigned buf_pos;
|
||||
unsigned buf_end;
|
||||
uint64_t buf[BUFSIZ / 8];
|
||||
uint64_t buf[(BUFSIZ + 256) / 8];
|
||||
};
|
||||
struct {
|
||||
bool isdone;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/sysdebug.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
|
@ -58,6 +59,7 @@ FILE *fopen(const char *pathname, const char *mode) {
|
|||
FILE *f;
|
||||
bool noclose;
|
||||
int fd, flags;
|
||||
SYSDEBUG("fopen(%`'s)", pathname);
|
||||
flags = fopenflags(mode);
|
||||
pathname = fixpathname(pathname, flags);
|
||||
if ((fd = openpathname(pathname, flags, &noclose)) != -1) {
|
||||
|
|
|
@ -2057,7 +2057,7 @@ syscon nr __NR_execve 0x003b 0x200003b 0x003b 0x003b 0x03b 0xfff # D
|
|||
syscon nr __NR_wait4 0x003d 0x2000007 0x0007 0x000b 0x1c1 0xfff
|
||||
syscon nr __NR_kill 0x003e 0x2000025 0x0025 0x007a 0x025 0xfff
|
||||
syscon nr __NR_killpg 0xfff 0xfff 0x0092 0xfff 0xfff 0xfff
|
||||
syscon nr __NR_clone 0x0038 0xfff 0xfff 0xfff 0xfff 0xfff
|
||||
syscon nr __NR_clone 0x0038 0xfff 0xfff 0xfff 0x11f 0xfff
|
||||
syscon nr __NR_tkill 0x00c8 0xfff 0xfff 0xfff 0xfff 0xfff
|
||||
syscon nr __NR_futex 0x00ca 0xfff 0xfff 0x0053 0xfff 0xfff
|
||||
syscon nr __NR_set_robust_list 0x0111 0xfff 0xfff 0xfff 0xfff 0xfff
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon nr,__NR_clone,0x0038,0xfff,0xfff,0xfff,0xfff,0xfff
|
||||
.syscon nr,__NR_clone,0x0038,0xfff,0xfff,0xfff,0x11f,0xfff
|
||||
|
|
26
libc/sysv/consts/clone.h
Normal file
26
libc/sysv/consts/clone.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_SYSV_CONSTS_CLONE_H_
|
||||
#define COSMOPOLITAN_LIBC_SYSV_CONSTS_CLONE_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#define CLONE_VM 0x00000100
|
||||
#define CLONE_FS 0x00000200
|
||||
#define CLONE_FILES 0x00000400
|
||||
#define CLONE_SIGHAND 0x00000800
|
||||
#define CLONE_PTRACE 0x00002000
|
||||
#define CLONE_VFORK 0x00004000
|
||||
#define CLONE_PARENT 0x00008000
|
||||
#define CLONE_THREAD 0x00010000
|
||||
#define CLONE_NEWNS 0x00020000
|
||||
#define CLONE_SYSVSEM 0x00040000
|
||||
#define CLONE_SETTLS 0x00080000
|
||||
#define CLONE_PARENT_SETTID 0x00100000
|
||||
#define CLONE_CHILD_CLEARTID 0x00200000
|
||||
#define CLONE_DETACHED 0x00400000
|
||||
#define CLONE_UNTRACED 0x00800000
|
||||
#define CLONE_CHILD_SETTID 0x01000000
|
||||
#define CLONE_STOPPED 0x02000000
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_CLONE_H_ */
|
|
@ -1,32 +1,32 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_SYSV_CONSTS_S_H_
|
||||
#define COSMOPOLITAN_LIBC_SYSV_CONSTS_S_H_
|
||||
|
||||
#define S_ISVTX 01000 /* THE STICKY BIT */
|
||||
#define S_ISGID 02000 /* the setgid bit */
|
||||
#define S_ISUID 04000 /* the setuid bit */
|
||||
#define S_IXUSR 00100 /* user --x; just use octal */
|
||||
#define S_IWUSR 00200 /* user -w-; just use octal */
|
||||
#define S_IRUSR 00400 /* user r--; just use octal */
|
||||
#define S_IRWXU 00700 /* user rwx; just use octal */
|
||||
#define S_IXGRP 00010 /* group --x; just use octal */
|
||||
#define S_IWGRP 00020 /* group -w-; just use octal */
|
||||
#define S_IRGRP 00040 /* group r--; just use octal */
|
||||
#define S_IRWXG 00070 /* group rwx; just use octal */
|
||||
#define S_IXOTH 00001 /* other --x; just use octal */
|
||||
#define S_IWOTH 00002 /* other -w-; just use octal */
|
||||
#define S_IROTH 00004 /* other r--; just use octal */
|
||||
#define S_IRWXO 00007 /* other rwx; just use octal */
|
||||
#define S_IREAD 00400 /* just use octal */
|
||||
#define S_IEXEC 00100 /* just use octal */
|
||||
#define S_IWRITE 00200 /* just use octal */
|
||||
#define S_IFIFO 0010000 /* pipe */
|
||||
#define S_IFCHR 0020000 /* character device */
|
||||
#define S_IFDIR 0040000 /* directory */
|
||||
#define S_IFBLK 0060000 /* block device */
|
||||
#define S_IFREG 0100000 /* regular file */
|
||||
#define S_IFLNK 0120000 /* symbolic link */
|
||||
#define S_IFSOCK 0140000 /* socket */
|
||||
#define S_IFMT 0170000 /* mask of file types above */
|
||||
|
||||
#define S_IFIFO (1 << 12) /* pipe */
|
||||
#define S_IFCHR (2 << 12) /* character device */
|
||||
#define S_IFDIR (4 << 12) /* directory */
|
||||
#define S_IFBLK (6 << 12) /* block device */
|
||||
#define S_IFREG (8 << 12) /* regular file */
|
||||
#define S_IFLNK (10 << 12) /* symbolic link */
|
||||
#define S_IFSOCK (12 << 12) /* socket */
|
||||
#define S_IFMT (15 << 12) /* mask of file types above */
|
||||
#define S_ISVTX 0001000 /* THE STICKY BIT */
|
||||
#define S_ISGID 0002000 /* the setgid bit */
|
||||
#define S_ISUID 0004000 /* the setuid bit */
|
||||
#define S_IXUSR 0000100 /* user --x; just use octal */
|
||||
#define S_IWUSR 0000200 /* user -w-; just use octal */
|
||||
#define S_IRUSR 0000400 /* user r--; just use octal */
|
||||
#define S_IRWXU 0000700 /* user rwx; just use octal */
|
||||
#define S_IXGRP 0000010 /* group --x; just use octal */
|
||||
#define S_IWGRP 0000020 /* group -w-; just use octal */
|
||||
#define S_IRGRP 0000040 /* group r--; just use octal */
|
||||
#define S_IRWXG 0000070 /* group rwx; just use octal */
|
||||
#define S_IXOTH 0000001 /* other --x; just use octal */
|
||||
#define S_IWOTH 0000002 /* other -w-; just use octal */
|
||||
#define S_IROTH 0000004 /* other r--; just use octal */
|
||||
#define S_IRWXO 0000007 /* other rwx; just use octal */
|
||||
#define S_IREAD 0000400 /* just use octal */
|
||||
#define S_IEXEC 0000100 /* just use octal */
|
||||
#define S_IWRITE 0000200 /* just use octal */
|
||||
|
||||
#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_S_H_ */
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/dirent.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
|
@ -35,19 +36,18 @@ static int rmrfdir(const char *dirpath) {
|
|||
while ((e = readdir(d))) {
|
||||
if (!strcmp(e->d_name, ".")) continue;
|
||||
if (!strcmp(e->d_name, "..")) continue;
|
||||
if (strchr(e->d_name, '/')) abort();
|
||||
assert(!strchr(e->d_name, '/'));
|
||||
path = xjoinpaths(dirpath, e->d_name);
|
||||
if (e->d_type == DT_DIR) {
|
||||
rc = rmrfdir(path);
|
||||
} else {
|
||||
rc = unlink(path);
|
||||
}
|
||||
if (rc == -1) {
|
||||
free(path);
|
||||
if (rc == -1) {
|
||||
closedir(d);
|
||||
return -1;
|
||||
}
|
||||
free(path);
|
||||
}
|
||||
rc = closedir(d);
|
||||
rc |= rmdir(dirpath);
|
||||
|
|
|
@ -45,7 +45,7 @@ wchar_t *utf8toutf32(const char *p, size_t n, size_t *z) {
|
|||
if (n == -1) n = p ? strlen(p) : 0;
|
||||
if ((q = r = malloc(n * sizeof(wchar_t) + sizeof(wchar_t)))) {
|
||||
for (i = 0; i < n;) {
|
||||
if (0 && i + 16 < n) { /* 10x speedup for ascii */
|
||||
if (i + 16 < n) { /* 10x speedup for ascii */
|
||||
memset(vz, 0, 16);
|
||||
do {
|
||||
memcpy(v1, p + i, 16);
|
||||
|
|
|
@ -66,6 +66,8 @@ int rmrf(const char *);
|
|||
int makedirs(const char *, unsigned);
|
||||
char *xdirname(const char *) paramsnonnull() _XMAL;
|
||||
char *xjoinpaths(const char *, const char *) paramsnonnull() _XMAL;
|
||||
char *xreadlink(const char *) paramsnonnull() _XMAL;
|
||||
char *xreadlinkat(int, const char *) paramsnonnull() _XMAL;
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § eXtended apis » time ─╬─│┼
|
||||
|
|
30
libc/x/xreadlink.c
Normal file
30
libc/x/xreadlink.c
Normal 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/sysv/consts/at.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
/**
|
||||
* Reads symbolic link.
|
||||
*
|
||||
* @return nul-terminated string, or null w/ errno
|
||||
* @see readlink()
|
||||
*/
|
||||
char *xreadlink(const char *path) {
|
||||
return xreadlinkat(AT_FDCWD, path);
|
||||
}
|
47
libc/x/xreadlinkat.c
Normal file
47
libc/x/xreadlinkat.c
Normal 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/calls/calls.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
/**
|
||||
* Reads symbolic link.
|
||||
*
|
||||
* @return nul-terminated string, or null w/ errno
|
||||
* @see readlinkat()
|
||||
*/
|
||||
char *xreadlinkat(int dirfd, const char *path) {
|
||||
ssize_t rc;
|
||||
size_t n, c;
|
||||
char *p, *q;
|
||||
c = PAGESIZE;
|
||||
p = xmalloc(c);
|
||||
if ((rc = readlinkat(dirfd, path, p, c)) != -1) {
|
||||
if ((n = rc) < c) {
|
||||
p[n] = 0;
|
||||
if ((q = realloc(p, n + 1))) p = q;
|
||||
return p;
|
||||
} else {
|
||||
enametoolong();
|
||||
}
|
||||
}
|
||||
free(p);
|
||||
return 0;
|
||||
}
|
60
test/libc/calls/dup_test.c
Normal file
60
test/libc/calls/dup_test.c
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*-*- 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/calls/struct/stat.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/fd.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
char testlib_enable_tmp_setup_teardown;
|
||||
|
||||
static textstartup void TestInit(int argc, char **argv) {
|
||||
int fd;
|
||||
if (argc == 2 && !strcmp(argv[1], "boop")) {
|
||||
if ((fd = open("/dev/null", O_RDWR | O_CLOEXEC)) == 3) {
|
||||
_exit(72);
|
||||
} else {
|
||||
_exit(fd + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const void *const TestCtor[] initarray = {TestInit};
|
||||
|
||||
TEST(dup, clearsCloexecFlag) {
|
||||
int ws;
|
||||
ASSERT_SYS(0, 0, close(creat("file", 0644)));
|
||||
ASSERT_SYS(0, 3, open("file", O_RDWR | O_CLOEXEC));
|
||||
ASSERT_NE(-1, (ws = xspawn(0)));
|
||||
if (ws == -2) {
|
||||
dup2(3, 0);
|
||||
execv(program_executable_name,
|
||||
(char *const[]){program_executable_name, "boop", 0});
|
||||
_exit(127);
|
||||
}
|
||||
ASSERT_EQ(72, WEXITSTATUS(ws));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
|
@ -22,6 +22,7 @@
|
|||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/fd.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
|
@ -53,3 +54,12 @@ TEST(fcntl_setfl, testChangeAppendStatus) {
|
|||
EXPECT_STREQ("foobar", buf);
|
||||
EXPECT_NE(-1, close(fd));
|
||||
}
|
||||
|
||||
TEST(fcntl, getfd) {
|
||||
ASSERT_SYS(0, 3, open("/dev/null", O_RDWR));
|
||||
ASSERT_SYS(0, 0, fcntl(3, F_GETFD));
|
||||
ASSERT_SYS(0, 4, open("/dev/null", O_RDWR | O_CLOEXEC));
|
||||
ASSERT_SYS(0, FD_CLOEXEC, fcntl(4, F_GETFD));
|
||||
ASSERT_SYS(0, 0, close(4));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
|
41
test/libc/calls/fileexists_test.c
Normal file
41
test/libc/calls/fileexists_test.c
Normal 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 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/stat.h"
|
||||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
char testlib_enable_tmp_setup_teardown;
|
||||
|
||||
TEST(fileexists, test) {
|
||||
EXPECT_SYS(0, 0, fileexists("doge"));
|
||||
EXPECT_SYS(0, 0, isdirectory("doge"));
|
||||
EXPECT_SYS(0, 0, close(creat("doge", 0644)));
|
||||
EXPECT_SYS(0, 1, fileexists("doge"));
|
||||
EXPECT_SYS(0, 0, isdirectory("doge"));
|
||||
}
|
||||
|
||||
BENCH(fileexists, bench) {
|
||||
struct stat st;
|
||||
EZBENCH2("!stat", donothing, stat("doge", &st));
|
||||
EZBENCH2("!fileexists", donothing, fileexists("doge"));
|
||||
EXPECT_SYS(0, 0, close(creat("doge", 0644)));
|
||||
EZBENCH2("stat", donothing, stat("doge", &st));
|
||||
EZBENCH2("fileexists", donothing, fileexists("doge"));
|
||||
}
|
|
@ -1,10 +1,12 @@
|
|||
#!/bin/sh
|
||||
|
||||
if [ "$MODE" = dbg ]; then
|
||||
touch o/$MODE/test/libc/release/emulate.ok
|
||||
exit # TODO
|
||||
fi
|
||||
|
||||
if [ "$MODE" = opt ]; then
|
||||
touch o/$MODE/test/libc/release/emulate.ok
|
||||
exit
|
||||
fi
|
||||
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
#!/bin/sh
|
||||
|
||||
if [ "$MODE" = dbg ]; then
|
||||
touch o/$MODE/test/libc/release/metal.ok
|
||||
exit # TODO
|
||||
fi
|
||||
|
||||
if [ "$MODE" = opt ]; then
|
||||
touch o/$MODE/test/libc/release/metal.ok
|
||||
exit
|
||||
fi
|
||||
|
||||
|
|
48
test/libc/runtime/clone_test.c
Normal file
48
test/libc/runtime/clone_test.c
Normal 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/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/log/backtrace.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/gc.internal.h"
|
||||
#include "libc/runtime/symbols.internal.h"
|
||||
#include "libc/sysv/consts/clone.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
volatile int x;
|
||||
|
||||
int thread(void *arg) {
|
||||
return (x = 42);
|
||||
}
|
||||
|
||||
TEST(clone, test) {
|
||||
if (!IsLinux() && !IsNetbsd() && !IsWindows()) return;
|
||||
char *stack;
|
||||
long double t;
|
||||
int tid, ptid, ctid, tls, ws;
|
||||
t = nowl();
|
||||
stack = gc(malloc(FRAMESIZE));
|
||||
EXPECT_NE(-1, (tid = clone(thread, stack + FRAMESIZE,
|
||||
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
|
||||
0, &ptid, &tls, &ctid)));
|
||||
while ((nowl() - t) < 1 && !x) asm("pause");
|
||||
ASSERT_EQ(42, x);
|
||||
}
|
|
@ -16,64 +16,33 @@
|
|||
│ 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/macros.internal.h"
|
||||
#include "libc/runtime/gc.internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/limits.h"
|
||||
#include "libc/sysv/consts/poll.h"
|
||||
#include "libc/sysv/consts/af.h"
|
||||
#include "libc/sysv/consts/inaddr.h"
|
||||
#include "libc/sysv/consts/ipproto.h"
|
||||
#include "libc/sysv/consts/sock.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "tool/decode/lib/flagger.h"
|
||||
#include "tool/decode/lib/pollnames.h"
|
||||
|
||||
#if 0 /* todo(jart): fix me */
|
||||
|
||||
#define POLL(FDS, TIMEOUT) \
|
||||
poll(((struct pollfd[])FDS), ARRAYLEN(((struct pollfd[])FDS)), TIMOUT)
|
||||
|
||||
nodiscard char *FormatPollFd(struct pollfd *pol) {
|
||||
return xasprintf("fd:%d revents:%s", pol->fd,
|
||||
gc(recreateflags(kPollNames, pol->revents)));
|
||||
nodiscard char *FormatPollFd(struct pollfd p[2]) {
|
||||
return xasprintf("fd:%d revents:%s\n"
|
||||
"fd:%d revents:%s\n",
|
||||
p[0].fd, gc(RecreateFlags(kPollNames, p[0].revents)),
|
||||
p[1].fd, gc(RecreateFlags(kPollNames, p[1].revents)));
|
||||
}
|
||||
|
||||
TEST(poll, testNegativeOneFd_completelyIgnored) {
|
||||
struct pollfd fds[] = {{-1}};
|
||||
EXPECT_EQ(0, poll(fds, ARRAYLEN(fds), 0));
|
||||
EXPECT_STREQ("fd:-1 revents:0", gc(FormatPollFd(&fds[0])));
|
||||
TEST(poll, testNegativeOneFd_isIgnored) {
|
||||
ASSERT_SYS(0, 3, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
|
||||
struct sockaddr_in addr = {AF_INET, 0, {htonl(INADDR_LOOPBACK)}};
|
||||
ASSERT_SYS(0, 0, bind(3, &addr, sizeof(addr)));
|
||||
ASSERT_SYS(0, 0, listen(3, 10));
|
||||
struct pollfd fds[] = {{-1}, {3}};
|
||||
EXPECT_SYS(0, 0, poll(fds, ARRAYLEN(fds), 1));
|
||||
EXPECT_STREQ("fd:-1 revents:0\n"
|
||||
"fd:3 revents:0\n",
|
||||
gc(FormatPollFd(&fds[0])));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
TEST(poll, demo) {
|
||||
int rw[2];
|
||||
char buf[2] = "hi";
|
||||
ASSERT_NE(-1, pipe(rw));
|
||||
ASSERT_EQ(2, write(rw[1], buf, sizeof(buf))); /* produce */
|
||||
{
|
||||
struct pollfd fds[] = {{rw[0], POLLIN}, {rw[1], POLLOUT}};
|
||||
EXPECT_EQ(2, poll(fds, ARRAYLEN(fds), 0));
|
||||
system(gc(xasprintf("ls -l /proc/%d/fd", getpid())));
|
||||
EXPECT_STREQ("fd:3 revents:POLLIN", gc(FormatPollFd(fds + 0)));
|
||||
EXPECT_STREQ("fd:4 revents:POLLOUT", gc(FormatPollFd(&fds[1])));
|
||||
}
|
||||
ASSERT_EQ(2, read(rw[0], buf, sizeof(buf))); /* consume */
|
||||
{
|
||||
struct pollfd fds[] = {{rw[0], POLLIN}, {rw[1], POLLOUT}};
|
||||
EXPECT_EQ(1, poll(fds, ARRAYLEN(fds), 0));
|
||||
EXPECT_STREQ("fd:3 revents:0", gc(FormatPollFd(&fds[0])));
|
||||
EXPECT_STREQ("fd:4 revents:POLLOUT", gc(FormatPollFd(&fds[1])));
|
||||
}
|
||||
ASSERT_NE(-1, close(rw[1])); /* close producer */
|
||||
{
|
||||
struct pollfd fds[] = {{rw[0], POLLIN}, {rw[1], POLLOUT}};
|
||||
EXPECT_EQ(2, poll(fds, ARRAYLEN(fds), 0));
|
||||
EXPECT_STREQ("fd:3 revents:POLLHUP", gc(FormatPollFd(&fds[0])));
|
||||
EXPECT_STREQ("fd:4 revents:POLLNVAL", gc(FormatPollFd(&fds[1])));
|
||||
}
|
||||
ASSERT_NE(-1, close(rw[0])); /* close consumer */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -94,15 +94,18 @@ TEST(highwayhash64, test) {
|
|||
}
|
||||
|
||||
BENCH(highwayhash64, bench) {
|
||||
EZBENCH2("crc32c small", donothing, crc32c(0, "hello", 5));
|
||||
EZBENCH2("knuth small", donothing,
|
||||
EXPROPRIATE(KnuthMultiplicativeHash32(VEIL("r", "hello"), 5)));
|
||||
EZBENCH2("crc32c small", donothing, crc32c(0, "hello", 5));
|
||||
EZBENCH2("crc32 small", donothing,
|
||||
EXPROPRIATE(crc32_z(0, VEIL("r", "hello"), 5)));
|
||||
EZBENCH2("highwayhash64 small", donothing,
|
||||
HighwayHash64((void *)"hello", 5, kTestKey1));
|
||||
EZBENCH2("crc32 big", donothing, crc32_z(0, kHyperion, kHyperionSize));
|
||||
EZBENCH2("crc32c big", donothing, crc32c(0, kHyperion, kHyperionSize));
|
||||
EZBENCH2("highwayhash64 big", donothing,
|
||||
HighwayHash64((void *)kHyperion, kHyperionSize, kTestKey1));
|
||||
EZBENCH2("knuth big", donothing,
|
||||
EXPROPRIATE(
|
||||
KnuthMultiplicativeHash32(VEIL("r", kHyperion), kHyperionSize)));
|
||||
EZBENCH2("highwayhash64 big", donothing,
|
||||
HighwayHash64((void *)kHyperion, kHyperionSize, kTestKey1));
|
||||
}
|
||||
|
|
7
third_party/linenoise/linenoise.c
vendored
7
third_party/linenoise/linenoise.c
vendored
|
@ -193,6 +193,13 @@
|
|||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "third_party/linenoise/linenoise.h"
|
||||
|
||||
asm(".ident\t\"\\n\\n\
|
||||
linenoise (BSD-2)\\n\
|
||||
Copyright (c) 2010-2016, Salvatore Sanfilippo <antirez at gmail dot com>\n\
|
||||
Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n\
|
||||
Copyright (c) 2018-2020, Justine Tunney <jtunney at gmail dot com>\"");
|
||||
asm(".include \"libc/disclaimer.inc\"");
|
||||
/* clang-format off */
|
||||
|
||||
#define LINENOISE_MAX_LINE 4096
|
||||
|
|
8
third_party/mbedtls/test/lib.c
vendored
8
third_party/mbedtls/test/lib.c
vendored
|
@ -17,10 +17,14 @@
|
|||
#include "libc/assert.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/backtrace.internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nexgen32e/vendor.internal.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/symbols.internal.h"
|
||||
|
@ -28,6 +32,8 @@
|
|||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/exit.h"
|
||||
#include "libc/sysv/consts/nr.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "third_party/mbedtls/config.h"
|
||||
#include "third_party/mbedtls/endian.h"
|
||||
#include "third_party/mbedtls/error.h"
|
||||
|
@ -93,7 +99,7 @@ void mbedtls_test_platform_teardown(void) {
|
|||
}
|
||||
|
||||
wontreturn void exit(int rc) {
|
||||
if (rc) fwrite(output, 1, appendz(output).i, stderr);
|
||||
if (rc) xwrite(1, output, appendz(output).i);
|
||||
free(output);
|
||||
__cxa_finalize(0);
|
||||
_Exit(rc);
|
||||
|
|
5
third_party/mbedtls/test/test.mk
vendored
5
third_party/mbedtls/test/test.mk
vendored
|
@ -101,6 +101,7 @@ THIRD_PARTY_MBEDTLS_TEST_DIRECTDEPS = \
|
|||
LIBC_LOG \
|
||||
LIBC_MEM \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_NT_KERNEL32 \
|
||||
LIBC_RAND \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_STDIO \
|
||||
|
@ -153,6 +154,10 @@ o/$(MODE)/third_party/mbedtls/test/lib.o: \
|
|||
o/$(MODE)/third_party/mbedtls/test: \
|
||||
$(THIRD_PARTY_MBEDTLS_TEST_CHECKS)
|
||||
|
||||
.PHONY: o/$(MODE)/third_party/mbedtls/test/TESTS
|
||||
o/$(MODE)/third_party/mbedtls/test/TESTS: \
|
||||
$(THIRD_PARTY_MBEDTLS_TEST_TESTS)
|
||||
|
||||
o/$(MODE)/third_party/mbedtls/test/test_suite_aes.cbc.com: o/$(MODE)/third_party/mbedtls/test/test_suite_aes.cbc.com.dbg
|
||||
o/$(MODE)/third_party/mbedtls/test/test_suite_aes.cbc.com.dbg: \
|
||||
$(THIRD_PARTY_MBEDTLS_TEST_DEPS) \
|
||||
|
|
220
third_party/python/Modules/expat/xmlparse.c
vendored
220
third_party/python/Modules/expat/xmlparse.c
vendored
|
@ -1,3 +1,16 @@
|
|||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/grnd.h"
|
||||
#include "libc/time/time.h"
|
||||
#include "third_party/python/Modules/expat/expat.h"
|
||||
#include "third_party/python/Modules/expat/expat_config.h"
|
||||
/* clang-format off */
|
||||
/* f2d0ab6d1d4422a08cf1cf3bbdfba96b49dea42fb5ff4615e03a2a25c306e769 (2.2.8+)
|
||||
__ __ _
|
||||
|
@ -39,24 +52,7 @@ asm(".include \"libc/disclaimer.inc\"");
|
|||
|
||||
#define XML_BUILDING_EXPAT 1
|
||||
|
||||
#ifdef HAVE_EXPAT_CONFIG_H
|
||||
#include "libc/sysv/consts/grnd.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/time/time.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/limits.h"
|
||||
#include "third_party/python/Modules/expat/expat_config.h"
|
||||
#endif
|
||||
|
||||
#include "third_party/python/Modules/expat/ascii.inc"
|
||||
#include "third_party/python/Modules/expat/expat.h"
|
||||
#include "third_party/python/Modules/expat/siphash.inc"
|
||||
|
||||
#if defined(_WIN32) && !defined(LOAD_LIBRARY_SEARCH_SYSTEM32)
|
||||
|
@ -442,7 +438,6 @@ static ELEMENT_TYPE *getElementType(XML_Parser parser, const ENCODING *enc,
|
|||
static XML_Char *copyString(const XML_Char *s,
|
||||
const XML_Memory_Handling_Suite *memsuite);
|
||||
|
||||
static unsigned long generate_hash_secret_salt(XML_Parser parser);
|
||||
static XML_Bool startParsing(XML_Parser parser);
|
||||
|
||||
static XML_Parser parserCreate(const XML_Char *encodingName,
|
||||
|
@ -592,193 +587,6 @@ static const XML_Char implicitContext[] = {
|
|||
ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e,
|
||||
'\0'};
|
||||
|
||||
/* To avoid warnings about unused functions: */
|
||||
#if !defined(HAVE_ARC4RANDOM_BUF) && !defined(HAVE_ARC4RANDOM)
|
||||
|
||||
#if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
|
||||
|
||||
/* Obtain entropy on Linux 3.17+ */
|
||||
static int writeRandomBytes_getrandom_nonblock(void *target, size_t count) {
|
||||
int success = 0; /* full count bytes written? */
|
||||
size_t bytesWrittenTotal = 0;
|
||||
const unsigned int getrandomFlags = GRND_NONBLOCK;
|
||||
|
||||
do {
|
||||
void *const currentTarget = (void *)((char *)target + bytesWrittenTotal);
|
||||
const size_t bytesToWrite = count - bytesWrittenTotal;
|
||||
|
||||
const int bytesWrittenMore =
|
||||
#if defined(HAVE_GETRANDOM)
|
||||
getrandom(currentTarget, bytesToWrite, getrandomFlags);
|
||||
#else
|
||||
syscall(SYS_getrandom, currentTarget, bytesToWrite, getrandomFlags);
|
||||
#endif
|
||||
|
||||
if (bytesWrittenMore > 0) {
|
||||
bytesWrittenTotal += bytesWrittenMore;
|
||||
if (bytesWrittenTotal >= count) success = 1;
|
||||
}
|
||||
} while (!success && (errno == EINTR));
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
#endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */
|
||||
|
||||
#if !defined(_WIN32) && defined(XML_DEV_URANDOM)
|
||||
|
||||
/* Extract entropy from /dev/urandom */
|
||||
static int writeRandomBytes_dev_urandom(void *target, size_t count) {
|
||||
int success = 0; /* full count bytes written? */
|
||||
size_t bytesWrittenTotal = 0;
|
||||
|
||||
const int fd = open("/dev/urandom", O_RDONLY);
|
||||
if (fd < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
do {
|
||||
void *const currentTarget = (void *)((char *)target + bytesWrittenTotal);
|
||||
const size_t bytesToWrite = count - bytesWrittenTotal;
|
||||
|
||||
const ssize_t bytesWrittenMore = read(fd, currentTarget, bytesToWrite);
|
||||
|
||||
if (bytesWrittenMore > 0) {
|
||||
bytesWrittenTotal += bytesWrittenMore;
|
||||
if (bytesWrittenTotal >= count) success = 1;
|
||||
}
|
||||
} while (!success && (errno == EINTR));
|
||||
|
||||
close(fd);
|
||||
return success;
|
||||
}
|
||||
|
||||
#endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */
|
||||
|
||||
#endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */
|
||||
|
||||
#if defined(HAVE_ARC4RANDOM) && !defined(HAVE_ARC4RANDOM_BUF)
|
||||
|
||||
static void writeRandomBytes_arc4random(void *target, size_t count) {
|
||||
size_t bytesWrittenTotal = 0;
|
||||
|
||||
while (bytesWrittenTotal < count) {
|
||||
const uint32_t random32 = arc4random();
|
||||
size_t i = 0;
|
||||
|
||||
for (; (i < sizeof(random32)) && (bytesWrittenTotal < count);
|
||||
i++, bytesWrittenTotal++) {
|
||||
const uint8_t random8 = (uint8_t)(random32 >> (i * 8));
|
||||
((uint8_t *)target)[bytesWrittenTotal] = random8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* defined(HAVE_ARC4RANDOM) && ! defined(HAVE_ARC4RANDOM_BUF) */
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
/* Obtain entropy on Windows using the rand_s() function which
|
||||
* generates cryptographically secure random numbers. Internally it
|
||||
* uses RtlGenRandom API which is present in Windows XP and later.
|
||||
*/
|
||||
static int writeRandomBytes_rand_s(void *target, size_t count) {
|
||||
size_t bytesWrittenTotal = 0;
|
||||
|
||||
while (bytesWrittenTotal < count) {
|
||||
unsigned int random32 = 0;
|
||||
size_t i = 0;
|
||||
|
||||
if (rand_s(&random32)) return 0; /* failure */
|
||||
|
||||
for (; (i < sizeof(random32)) && (bytesWrittenTotal < count);
|
||||
i++, bytesWrittenTotal++) {
|
||||
const uint8_t random8 = (uint8_t)(random32 >> (i * 8));
|
||||
((uint8_t *)target)[bytesWrittenTotal] = random8;
|
||||
}
|
||||
}
|
||||
return 1; /* success */
|
||||
}
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#if !defined(HAVE_ARC4RANDOM_BUF) && !defined(HAVE_ARC4RANDOM)
|
||||
|
||||
static unsigned long gather_time_entropy(void) {
|
||||
#ifdef _WIN32
|
||||
FILETIME ft;
|
||||
GetSystemTimeAsFileTime(&ft); /* never fails */
|
||||
return ft.dwHighDateTime ^ ft.dwLowDateTime;
|
||||
#else
|
||||
struct timeval tv;
|
||||
int gettimeofday_res;
|
||||
|
||||
gettimeofday_res = gettimeofday(&tv, NULL);
|
||||
|
||||
#if defined(NDEBUG)
|
||||
(void)gettimeofday_res;
|
||||
#else
|
||||
assert(gettimeofday_res == 0);
|
||||
#endif /* defined(NDEBUG) */
|
||||
|
||||
/* Microseconds time is <20 bits entropy */
|
||||
return tv.tv_usec;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */
|
||||
|
||||
static unsigned long ENTROPY_DEBUG(const char *label, unsigned long entropy) {
|
||||
const char *const EXPAT_ENTROPY_DEBUG = getenv("EXPAT_ENTROPY_DEBUG");
|
||||
if (EXPAT_ENTROPY_DEBUG && !strcmp(EXPAT_ENTROPY_DEBUG, "1")) {
|
||||
fprintf(stderr, "Entropy: %s --> 0x%0*lx (%lu bytes)\n", label,
|
||||
(int)sizeof(entropy) * 2, entropy, (unsigned long)sizeof(entropy));
|
||||
}
|
||||
return entropy;
|
||||
}
|
||||
|
||||
static unsigned long generate_hash_secret_salt(XML_Parser parser) {
|
||||
unsigned long entropy;
|
||||
(void)parser;
|
||||
|
||||
/* "Failproof" high quality providers: */
|
||||
#if defined(HAVE_ARC4RANDOM_BUF)
|
||||
arc4random_buf(&entropy, sizeof(entropy));
|
||||
return ENTROPY_DEBUG("arc4random_buf", entropy);
|
||||
#elif defined(HAVE_ARC4RANDOM)
|
||||
writeRandomBytes_arc4random((void *)&entropy, sizeof(entropy));
|
||||
return ENTROPY_DEBUG("arc4random", entropy);
|
||||
#else
|
||||
/* Try high quality providers first .. */
|
||||
#ifdef _WIN32
|
||||
if (writeRandomBytes_rand_s((void *)&entropy, sizeof(entropy))) {
|
||||
return ENTROPY_DEBUG("rand_s", entropy);
|
||||
}
|
||||
#elif defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
|
||||
if (writeRandomBytes_getrandom_nonblock((void *)&entropy, sizeof(entropy))) {
|
||||
return ENTROPY_DEBUG("getrandom", entropy);
|
||||
}
|
||||
#endif
|
||||
#if !defined(_WIN32) && defined(XML_DEV_URANDOM)
|
||||
if (writeRandomBytes_dev_urandom((void *)&entropy, sizeof(entropy))) {
|
||||
return ENTROPY_DEBUG("/dev/urandom", entropy);
|
||||
}
|
||||
#endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */
|
||||
/* .. and self-made low quality for backup: */
|
||||
|
||||
/* Process ID is 0 bits entropy if attacker has local access */
|
||||
entropy = gather_time_entropy() ^ getpid();
|
||||
|
||||
/* Factors are 2^31-1 and 2^61-1 (Mersenne primes M31 and M61) */
|
||||
if (sizeof(unsigned long) == 4) {
|
||||
return ENTROPY_DEBUG("fallback(4)", entropy * 2147483647);
|
||||
} else {
|
||||
return ENTROPY_DEBUG("fallback(8)",
|
||||
entropy * (unsigned long)2305843009213693951ULL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static unsigned long get_hash_secret_salt(XML_Parser parser) {
|
||||
if (parser->m_parentParser != NULL)
|
||||
return get_hash_secret_salt(parser->m_parentParser);
|
||||
|
@ -789,7 +597,7 @@ static XML_Bool /* only valid for root parser */
|
|||
startParsing(XML_Parser parser) {
|
||||
/* hash functions must be initialized before setContext() is called */
|
||||
if (parser->m_hash_secret_salt == 0)
|
||||
parser->m_hash_secret_salt = generate_hash_secret_salt(parser);
|
||||
parser->m_hash_secret_salt = rand64();
|
||||
if (parser->m_ns) {
|
||||
/* implicit context only set for root parser, since child
|
||||
parsers (i.e. external entity parsers) will inherit it
|
||||
|
|
8
third_party/python/Modules/socketmodule.c
vendored
8
third_party/python/Modules/socketmodule.c
vendored
|
@ -11,6 +11,7 @@
|
|||
#include "libc/dns/dns.h"
|
||||
#include "libc/dns/ent.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/nt/enum/version.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sysv/consts/af.h"
|
||||
|
@ -6803,8 +6804,7 @@ PyInit__socket(void)
|
|||
PyModule_AddIntMacro(m, INADDR_BROADCAST);
|
||||
PyModule_AddIntMacro(m, INADDR_LOOPBACK);
|
||||
PyModule_AddIntMacro(m, INADDR_UNSPEC_GROUP);
|
||||
PyModule_AddIntConstant(m, "INADDR_ALLHOSTS_GROUP",
|
||||
INADDR_ALLHOSTS_GROUP);
|
||||
PyModule_AddIntMacro(m, INADDR_ALLHOSTS_GROUP);
|
||||
PyModule_AddIntMacro(m, INADDR_MAX_LOCAL_GROUP);
|
||||
PyModule_AddIntMacro(m, INADDR_NONE);
|
||||
|
||||
|
@ -6930,9 +6930,9 @@ PyInit__socket(void)
|
|||
if (TCP_USER_TIMEOUT) PyModule_AddIntMacro(m, TCP_USER_TIMEOUT);
|
||||
if (TCP_SAVE_SYN) PyModule_AddIntMacro(m, TCP_SAVE_SYN);
|
||||
if (TCP_SAVED_SYN) PyModule_AddIntMacro(m, TCP_SAVED_SYN);
|
||||
if (TCP_KEEPCNT && (!IsWindows() || NtGetVersion() >= 10))
|
||||
if (TCP_KEEPCNT && (!IsWindows() || NtGetVersion() >= kNtVersionWindows10))
|
||||
PyModule_AddIntMacro(m, TCP_KEEPCNT);
|
||||
if (TCP_FASTOPEN && (!IsWindows() || NtGetVersion() >= 10))
|
||||
if (TCP_FASTOPEN && (!IsWindows() || NtGetVersion() >= kNtVersionWindows10))
|
||||
PyModule_AddIntMacro(m, TCP_FASTOPEN);
|
||||
if (TCP_FASTOPEN_CONNECT)
|
||||
PyModule_AddIntMacro(m, TCP_FASTOPEN_CONNECT);
|
||||
|
|
6
third_party/python/Programs/freeze.c
vendored
6
third_party/python/Programs/freeze.c
vendored
|
@ -27,7 +27,7 @@
|
|||
\n\
|
||||
/*\n\
|
||||
* Auto-generated by\n\
|
||||
* %s \\\n\
|
||||
* o/third_party/python/freeze \\\n\
|
||||
* %s \\\n\
|
||||
* %s\n\
|
||||
*/\n\
|
||||
|
@ -46,6 +46,8 @@ main(int argc, char *argv[])
|
|||
PyObject *code = NULL, *marshalled = NULL;
|
||||
int is_bootstrap = 1;
|
||||
|
||||
if (argc == 2 && !strcmp(argv[1], "-n")) return 0;
|
||||
|
||||
if (argc != 3) {
|
||||
fprintf(stderr, "need to specify input and output paths\n");
|
||||
return 2;
|
||||
|
@ -115,7 +117,7 @@ main(int argc, char *argv[])
|
|||
fprintf(stderr, "cannot open '%s' for writing\n", outpath);
|
||||
goto error;
|
||||
}
|
||||
fprintf(outfile, HEADER, argv[0], argv[1], argv[2]);
|
||||
fprintf(outfile, HEADER, argv[1], argv[2]);
|
||||
if (is_bootstrap)
|
||||
fprintf(outfile, "const unsigned char _Py_M__importlib[] = {\n");
|
||||
else
|
||||
|
|
2
third_party/python/Python/importlib.inc
vendored
2
third_party/python/Python/importlib.inc
vendored
|
@ -8,7 +8,7 @@
|
|||
|
||||
/*
|
||||
* Auto-generated by
|
||||
* o/third_party/python/freeze.com \
|
||||
* o/third_party/python/freeze \
|
||||
* third_party/python/Lib/importlib/_bootstrap.py \
|
||||
* third_party/python/Python/importlib.inc
|
||||
*/
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
/*
|
||||
* Auto-generated by
|
||||
* o/third_party/python/freeze.com \
|
||||
* o/third_party/python/freeze \
|
||||
* third_party/python/Lib/importlib/_bootstrap_external.py \
|
||||
* third_party/python/Python/importlib_external.inc
|
||||
*/
|
||||
|
|
28
third_party/python/python.mk
vendored
28
third_party/python/python.mk
vendored
|
@ -235,8 +235,6 @@ THIRD_PARTY_PYTHON_INCS = \
|
|||
third_party/python/Python/wordcode_helpers.inc \
|
||||
third_party/python/Python/ceval_gil.inc \
|
||||
third_party/python/Python/thread_nt.inc \
|
||||
third_party/python/Python/importlib_external.inc \
|
||||
third_party/python/Python/importlib.inc \
|
||||
third_party/python/Python/clinic/import.inc \
|
||||
third_party/python/Python/clinic/bltinmodule.inc \
|
||||
third_party/python/Modules/expat/asciitab.inc \
|
||||
|
@ -2266,6 +2264,16 @@ o/$(MODE)/third_party/python/freeze: \
|
|||
@cp -f $< $@
|
||||
@$@ -n
|
||||
|
||||
third_party/python/Python/importlib.inc: \
|
||||
o/$(MODE)/third_party/python/freeze \
|
||||
third_party/python/Lib/importlib/_bootstrap.py
|
||||
@$(COMPILE) -AFREEZE $^ $@
|
||||
|
||||
third_party/python/Python/importlib_external.inc: \
|
||||
o/$(MODE)/third_party/python/freeze \
|
||||
third_party/python/Lib/importlib/_bootstrap_external.py
|
||||
@$(COMPILE) -AFREEZE $^ $@
|
||||
|
||||
$(THIRD_PARTY_PYTHON_STAGE1_A): \
|
||||
third_party/python \
|
||||
$(THIRD_PARTY_PYTHON_STAGE1_A).pkg \
|
||||
|
@ -2311,20 +2319,6 @@ o/$(MODE)/third_party/python/Modules/getbuildinfo.o: \
|
|||
-DGITTAG='"3.6"' \
|
||||
-DGITBRANCH='"cosmo"'
|
||||
|
||||
o/$(MODE)/third_party/python/Modules/_elementtree.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-DUSE_PYEXPAT_CAPI \
|
||||
-DHAVE_EXPAT_CONFIG_H
|
||||
|
||||
o/$(MODE)/third_party/python/Modules/expat/xmlparse.o \
|
||||
o/$(MODE)/third_party/python/Modules/expat/xmlrole.o \
|
||||
o/$(MODE)/third_party/python/Modules/expat/xmltok.o \
|
||||
o/$(MODE)/third_party/python/Modules/pyexpat.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-DXML_POOR_ENTROPY \
|
||||
-DHAVE_EXPAT_CONFIG_H \
|
||||
-DUSE_PYEXPAT_CAPI
|
||||
|
||||
o/$(MODE)/third_party/python/Modules/_decimal/libmpdec/transpose.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-DSTACK_FRAME_UNLIMITED
|
||||
|
@ -2340,7 +2334,7 @@ $(THIRD_PARTY_PYTHON_STDLIB_PYS_OBJS): ZIPOBJ_FLAGS += -P.python -C3
|
|||
$(THIRD_PARTY_PYTHON_STDLIB_DIRS_OBJS): ZIPOBJ_FLAGS += -P.python -C3
|
||||
$(THIRD_PARTY_PYTHON_STDLIB_DATA_OBJS): ZIPOBJ_FLAGS += -P.python -C3
|
||||
$(THIRD_PARTY_PYTHON_STDLIB_PYCS_OBJS): ZIPOBJ_FLAGS += -P.python -C5
|
||||
.PRECIOUS: $(THIRD_PARTY_PYTHON_STDLIB_PYCS_OBJS)
|
||||
.PRECIOUS: $(THIRD_PARTY_PYTHON_STDLIB_PYCS)
|
||||
|
||||
o/$(MODE)/third_party/python/Python/ceval.o: QUOTA = -M512m
|
||||
o/$(MODE)/third_party/python/Objects/unicodeobject.o: QUOTA += -C16
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
│ 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/bits/safemacros.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
|
@ -27,6 +28,7 @@
|
|||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nexgen32e/crc32.h"
|
||||
#include "libc/runtime/gc.internal.h"
|
||||
#include "libc/sock/ipclassify.internal.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
@ -135,7 +137,6 @@ nodiscard char *MakeDeployScript(struct addrinfo *remotenic, size_t combytes) {
|
|||
const char *ip4 = (const char *)&remotenic->ai_addr4->sin_addr;
|
||||
return xasprintf("mkdir -p o/ && "
|
||||
"dd bs=%zu count=%zu of=o/runitd.$$.com 2>/dev/null && "
|
||||
"exec <&- && "
|
||||
"chmod +x o/runitd.$$.com && "
|
||||
"o/runitd.$$.com -rdl%hhu.%hhu.%hhu.%hhu -p %hu && "
|
||||
"rm -f o/runitd.$$.com",
|
||||
|
@ -293,9 +294,10 @@ void SendRequest(void) {
|
|||
char *p;
|
||||
size_t i;
|
||||
ssize_t rc;
|
||||
uint32_t crc;
|
||||
struct stat st;
|
||||
const char *name;
|
||||
unsigned char *hdr;
|
||||
unsigned char *hdr, *q;
|
||||
size_t progsize, namesize, hdrsize;
|
||||
DEBUGF("running %s on %s", g_prog, g_hostname);
|
||||
CHECK_NE(-1, (fd = open(g_prog, O_RDONLY)));
|
||||
|
@ -303,21 +305,16 @@ void SendRequest(void) {
|
|||
CHECK_NE(MAP_FAILED, (p = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0)));
|
||||
CHECK_LE((namesize = strlen((name = basename(g_prog)))), PATH_MAX);
|
||||
CHECK_LE((progsize = st.st_size), INT_MAX);
|
||||
CHECK_NOTNULL((hdr = gc(calloc(1, (hdrsize = 4 + 1 + 4 + 4 + namesize)))));
|
||||
hdr[0 + 0] = (unsigned char)((unsigned)RUNITD_MAGIC >> 030);
|
||||
hdr[0 + 1] = (unsigned char)((unsigned)RUNITD_MAGIC >> 020);
|
||||
hdr[0 + 2] = (unsigned char)((unsigned)RUNITD_MAGIC >> 010);
|
||||
hdr[0 + 3] = (unsigned char)((unsigned)RUNITD_MAGIC >> 000);
|
||||
hdr[4 + 0] = kRunitExecute;
|
||||
hdr[5 + 0] = (unsigned char)((unsigned)namesize >> 030);
|
||||
hdr[5 + 1] = (unsigned char)((unsigned)namesize >> 020);
|
||||
hdr[5 + 2] = (unsigned char)((unsigned)namesize >> 010);
|
||||
hdr[5 + 3] = (unsigned char)((unsigned)namesize >> 000);
|
||||
hdr[9 + 0] = (unsigned char)((unsigned)progsize >> 030);
|
||||
hdr[9 + 1] = (unsigned char)((unsigned)progsize >> 020);
|
||||
hdr[9 + 2] = (unsigned char)((unsigned)progsize >> 010);
|
||||
hdr[9 + 3] = (unsigned char)((unsigned)progsize >> 000);
|
||||
memcpy(&hdr[4 + 1 + 4 + 4], name, namesize);
|
||||
CHECK_NOTNULL((hdr = gc(calloc(1, (hdrsize = 17 + namesize)))));
|
||||
crc = crc32_z(0, p, st.st_size);
|
||||
q = hdr;
|
||||
q = WRITE32BE(q, RUNITD_MAGIC);
|
||||
*q++ = kRunitExecute;
|
||||
q = WRITE32BE(q, namesize);
|
||||
q = WRITE32BE(q, progsize);
|
||||
q = WRITE32BE(q, crc);
|
||||
q = mempcpy(q, name, namesize);
|
||||
assert(hdrsize == q - hdr);
|
||||
CHECK_EQ(hdrsize, mbedtls_ssl_write(&ezssl, hdr, hdrsize));
|
||||
for (i = 0; i < progsize; i += rc) {
|
||||
CHECK_GT((rc = mbedtls_ssl_write(&ezssl, p + i, progsize - i)), 0);
|
||||
|
@ -454,7 +451,7 @@ int RunRemoteTestsInParallel(char *hosts[], int count) {
|
|||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
showcrashreports();
|
||||
ShowCrashReports();
|
||||
SetupPresharedKeySsl(MBEDTLS_SSL_IS_CLIENT, GetRunitPsk());
|
||||
/* __log_level = kLogDebug; */
|
||||
if (argc > 1 &&
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "libc/fmt/conv.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/nexgen32e/crc32.h"
|
||||
#include "libc/runtime/gc.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sock/sock.h"
|
||||
|
@ -179,7 +180,16 @@ nodiscard char *DescribeAddress(struct sockaddr_in *addr) {
|
|||
void StartTcpServer(void) {
|
||||
int yes = true;
|
||||
uint32_t asize;
|
||||
|
||||
/*
|
||||
* TODO: How can we make close(serversocket) on Windows go fast?
|
||||
* That way we can put back SOCK_CLOEXEC.
|
||||
*/
|
||||
CHECK_NE(-1, (g_servfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)));
|
||||
CHECK_NE(-1, dup2(g_servfd, 10));
|
||||
CHECK_NE(-1, close(g_servfd));
|
||||
g_servfd = 10;
|
||||
|
||||
LOGIFNEG1(setsockopt(g_servfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)));
|
||||
LOGIFNEG1(setsockopt(g_servfd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes)));
|
||||
if (bind(g_servfd, &g_servaddr, sizeof(g_servaddr)) == -1) {
|
||||
|
@ -194,7 +204,6 @@ void StartTcpServer(void) {
|
|||
CHECK_NE(-1, listen(g_servfd, 10));
|
||||
asize = sizeof(g_servaddr);
|
||||
CHECK_NE(-1, getsockname(g_servfd, &g_servaddr, &asize));
|
||||
CHECK_NE(-1, fcntl(g_servfd, F_SETFD, FD_CLOEXEC));
|
||||
LOGF("%s:%s", "listening on tcp", gc(DescribeAddress(&g_servaddr)));
|
||||
if (g_sendready) {
|
||||
printf("ready %hu\n", ntohs(g_servaddr.sin_port));
|
||||
|
@ -252,15 +261,27 @@ void SetDeadline(int seconds, int micros) {
|
|||
ITIMER_REAL, &(const struct itimerval){{0, 0}, {seconds, micros}}, NULL));
|
||||
}
|
||||
|
||||
void Recv(void *p, size_t n) {
|
||||
size_t i, rc;
|
||||
for (i = 0; i < n; i += rc) {
|
||||
do {
|
||||
rc = mbedtls_ssl_read(&ezssl, (char *)p + i, n - i);
|
||||
DEBUGF("read(%ld)", rc);
|
||||
} while (rc == MBEDTLS_ERR_SSL_WANT_READ);
|
||||
if (rc <= 0) TlsDie("read failed", rc);
|
||||
}
|
||||
DEBUGF("Recv(%ld)", n);
|
||||
}
|
||||
|
||||
void HandleClient(void) {
|
||||
const size_t kMinMsgSize = 4 + 1 + 4 + 4;
|
||||
const size_t kMaxNameSize = 128;
|
||||
const size_t kMaxFileSize = 10 * 1024 * 1024;
|
||||
unsigned char *p;
|
||||
uint32_t crc;
|
||||
ssize_t got, wrote;
|
||||
struct sockaddr_in addr;
|
||||
char *addrstr, *exename;
|
||||
sigset_t chldmask, savemask;
|
||||
char *addrstr, *exename, *exe;
|
||||
unsigned char msg[4 + 1 + 4 + 4 + 4];
|
||||
struct sigaction ignore, saveint, savequit;
|
||||
int rc, exitcode, wstatus, child, pipefds[2];
|
||||
uint32_t addrsize, namesize, filesize, remaining;
|
||||
|
@ -276,57 +297,26 @@ void HandleClient(void) {
|
|||
EzHandshake();
|
||||
addrstr = gc(DescribeAddress(&addr));
|
||||
DEBUGF("%s %s %s", gc(DescribeAddress(&g_servaddr)), "accepted", addrstr);
|
||||
while ((got = mbedtls_ssl_read(&ezssl, (p = g_buf), sizeof(g_buf))) < 0) {
|
||||
if (got != MBEDTLS_ERR_SSL_WANT_READ) {
|
||||
TlsDie("ssl read failed", got);
|
||||
}
|
||||
}
|
||||
CHECK_GE(got, kMinMsgSize);
|
||||
CHECK_LE(got, sizeof(g_buf));
|
||||
CHECK_EQ(RUNITD_MAGIC, READ32BE(p));
|
||||
p += 4, got -= 4;
|
||||
CHECK_EQ(kRunitExecute, *p++);
|
||||
got--;
|
||||
namesize = READ32BE(p), p += 4, got -= 4;
|
||||
filesize = READ32BE(p), p += 4, got -= 4;
|
||||
CHECK_GE(got, namesize);
|
||||
CHECK_LE(namesize, kMaxNameSize);
|
||||
CHECK_LE(filesize, kMaxFileSize);
|
||||
exename = gc(xasprintf("%.*s", namesize, p));
|
||||
Recv(msg, sizeof(msg));
|
||||
CHECK_EQ(RUNITD_MAGIC, READ32BE(msg));
|
||||
CHECK_EQ(kRunitExecute, msg[4]);
|
||||
namesize = READ32BE(msg + 5);
|
||||
filesize = READ32BE(msg + 9);
|
||||
crc = READ32BE(msg + 13);
|
||||
exename = gc(calloc(1, namesize + 1));
|
||||
Recv(exename, namesize);
|
||||
g_exepath = gc(xasprintf("o/%d.%s", getpid(), basename(exename)));
|
||||
LOGF("%s asked we run %`'s (%,u bytes @ %`'s)", addrstr, exename, filesize,
|
||||
g_exepath);
|
||||
p += namesize, got -= namesize;
|
||||
|
||||
/* write the file to disk */
|
||||
remaining = filesize;
|
||||
exe = malloc(filesize);
|
||||
Recv(exe, filesize);
|
||||
if (crc32_z(0, exe, filesize) != crc) {
|
||||
FATALF("%s crc mismatch! %`'s", addrstr, exename);
|
||||
}
|
||||
CHECK_NE(-1, (g_exefd = creat(g_exepath, 0700)));
|
||||
ftruncate(g_exefd, filesize);
|
||||
if (got) {
|
||||
CHECK_EQ(got, write(g_exefd, p, got));
|
||||
CHECK_LE(got, remaining);
|
||||
remaining -= got;
|
||||
}
|
||||
while (remaining) {
|
||||
while ((got = mbedtls_ssl_read(&ezssl, g_buf, sizeof(g_buf))) < 0) {
|
||||
if (got != MBEDTLS_ERR_SSL_WANT_READ) {
|
||||
TlsDie("ssl read failed", got);
|
||||
}
|
||||
}
|
||||
CHECK_LE(got, remaining);
|
||||
if (!got) {
|
||||
LOGF("%s %s %,u/%,u %s", addrstr, "sent", remaining, filesize,
|
||||
"bytes before hangup");
|
||||
unlink(g_exepath);
|
||||
_exit(0);
|
||||
}
|
||||
remaining -= got;
|
||||
p = g_buf;
|
||||
do {
|
||||
CHECK_GT((wrote = write(g_exefd, g_buf, got)), 0);
|
||||
CHECK_LE(wrote, got);
|
||||
} while ((got -= wrote));
|
||||
}
|
||||
LOGIFNEG1(ftruncate(g_exefd, filesize));
|
||||
CHECK_NE(-1, xwrite(g_exefd, exe, filesize));
|
||||
LOGIFNEG1(close(g_exefd));
|
||||
|
||||
/* run program, tee'ing stderr to both log and client */
|
||||
|
@ -346,6 +336,8 @@ void HandleClient(void) {
|
|||
sigaction(SIGINT, &saveint, NULL);
|
||||
sigaction(SIGQUIT, &savequit, NULL);
|
||||
sigprocmask(SIG_SETMASK, &savemask, NULL);
|
||||
dup2(g_devnullfd, 0);
|
||||
dup2(pipefds[1], 1);
|
||||
dup2(pipefds[1], 2);
|
||||
execv(g_exepath, (char *const[]){g_exepath, NULL});
|
||||
_exit(127);
|
||||
|
@ -353,7 +345,8 @@ void HandleClient(void) {
|
|||
LOGIFNEG1(close(pipefds[1]));
|
||||
DEBUGF("communicating %s[%d]", exename, child);
|
||||
while (!g_alarmed) {
|
||||
if ((got = read(pipefds[0], g_buf, sizeof(g_buf))) != -1) {
|
||||
got = read(pipefds[0], g_buf, sizeof(g_buf));
|
||||
if (got != -1) {
|
||||
if (!got) {
|
||||
close(pipefds[0]);
|
||||
break;
|
||||
|
@ -377,10 +370,14 @@ void HandleClient(void) {
|
|||
}
|
||||
}
|
||||
if (WIFEXITED(wstatus)) {
|
||||
if (WEXITSTATUS(wstatus)) {
|
||||
WARNF("%s exited with %d", exename, WEXITSTATUS(wstatus));
|
||||
} else {
|
||||
DEBUGF("%s exited with %d", exename, WEXITSTATUS(wstatus));
|
||||
}
|
||||
exitcode = WEXITSTATUS(wstatus);
|
||||
} else {
|
||||
DEBUGF("%s terminated with %s", exename, strsignal(WTERMSIG(wstatus)));
|
||||
WARNF("%s terminated with %s", exename, strsignal(WTERMSIG(wstatus)));
|
||||
exitcode = 128 + WTERMSIG(wstatus);
|
||||
}
|
||||
LOGIFNEG1(sigaction(SIGINT, &saveint, NULL));
|
||||
|
@ -452,11 +449,11 @@ void Daemonize(void) {
|
|||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
showcrashreports();
|
||||
ShowCrashReports();
|
||||
SetupPresharedKeySsl(MBEDTLS_SSL_IS_SERVER, GetRunitPsk());
|
||||
/* __log_level = kLogDebug; */
|
||||
GetOpts(argc, argv);
|
||||
CHECK_NE(-1, (g_devnullfd = open("/dev/null", O_RDWR)));
|
||||
CHECK_EQ(3, (g_devnullfd = open("/dev/null", O_RDWR | O_CLOEXEC)));
|
||||
defer(close_s, &g_devnullfd);
|
||||
if (!isdirectory("o")) CHECK_NE(-1, mkdir("o", 0700));
|
||||
if (g_daemonize) Daemonize();
|
||||
|
|
Loading…
Reference in a new issue