mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-30 22:40:30 +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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue