mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-31 23:10:27 +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 = 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 {
|
||||
errno = olderr;
|
||||
return false;
|
||||
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;
|
||||
}
|
||||
}
|
||||
} 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 fd;
|
||||
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,33 +41,28 @@ 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;
|
||||
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;
|
||||
sockfd2->event = WSACreateEvent();
|
||||
g_fds.p[client].kind = kFdSocket;
|
||||
g_fds.p[client].flags = oflags;
|
||||
g_fds.p[client].handle = h;
|
||||
g_fds.p[client].extra = (uintptr_t)sockfd2;
|
||||
return client;
|
||||
}
|
||||
free(sockfd2);
|
||||
}
|
||||
sockfd2 = calloc(1, sizeof(struct SockFd));
|
||||
sockfd2->family = sockfd->family;
|
||||
sockfd2->type = sockfd->type;
|
||||
sockfd2->protocol = sockfd->protocol;
|
||||
sockfd2->event = WSACreateEvent();
|
||||
g_fds.p[client].kind = kFdSocket;
|
||||
g_fds.p[client].flags = oflags;
|
||||
g_fds.p[client].handle = h;
|
||||
g_fds.p[client].extra = (uintptr_t)sockfd2;
|
||||
return client;
|
||||
} else {
|
||||
__releasefd(client);
|
||||
return __winsockerr();
|
||||
__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();
|
||||
ntfds[i].handle = g_fds.p[fds[i].fd].handle;
|
||||
ntfds[i].events = fds[i].events & (POLLPRI | POLLIN | POLLOUT);
|
||||
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);
|
||||
}
|
||||
free(path);
|
||||
if (rc == -1) {
|
||||
free(path);
|
||||
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;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue