mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-07 11:48:30 +00:00
Improve ZIP filesystem and change its prefix
The ZIP filesystem has a breaking change. You now need to use /zip/ to open() / opendir() / etc. assets within the ZIP structure of your APE binary, instead of the previous convention of using zip: or zip! URIs. This is needed because Python likes to use absolute paths, and having ZIP paths encoded like URIs simply broke too many things. Many more system calls have been updated to be able to operate on ZIP files and file descriptors. In particular fcntl() and ioctl() since Python would do things like ask if a ZIP file is a terminal and get confused when the old implementation mistakenly said yes, because the fastest way to guarantee native file descriptors is to dup(2). This change also improves the async signal safety of zipos and ensures it doesn't maintain any open file descriptors beyond that which the user has opened. This change makes a lot of progress towards adding magic numbers that are specific to platforms other than Linux. The philosophy here is that, if you use an operating system like FreeBSD, then you should be able to take advantage of FreeBSD exclusive features, even if we don't polyfill them on other platforms. For example, you can now open() a file with the O_VERIFY flag. If your program runs on other platforms, then Cosmo will automatically set O_VERIFY to zero. This lets you safely use it without the need for #ifdef or ifstatements which detract from readability. One of the blindspots of the ASAN memory hardening we use to offer Rust like assurances has always been that memory passed to the kernel via system calls (e.g. writev) can't be checked automatically since the kernel wasn't built with MODE=asan. This change makes more progress ensuring that each system call will verify the soundness of memory before it's passed to the kernel. The code for doing these checks is fast, particularly for buffers, where it can verify 64 bytes a cycle. - Correct O_LOOP definition on NT - Introduce program_executable_name - Add ASAN guards to more system calls - Improve termios compatibility with BSDs - Fix bug in Windows auxiliary value encoding - Add BSD and XNU specific errnos and open flags - Add check to ensure build doesn't talk to internet
This commit is contained in:
parent
2730c66f4a
commit
00611e9b06
319 changed files with 4418 additions and 2599 deletions
|
@ -56,6 +56,7 @@
|
|||
#define WIFSTOPPED(s) ((short)((((s)&0xffff) * 0x10001) >> 8) > 0x7f00)
|
||||
#define WSTOPSIG(s) WEXITSTATUS(s)
|
||||
#define WTERMSIG(s) ((s)&0x7f)
|
||||
#define W_STOPCODE(s) ((s) << 8 | 0177)
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
@ -88,34 +89,35 @@ int chown(const char *, uint32_t, uint32_t);
|
|||
int chroot(const char *);
|
||||
int close(int);
|
||||
int closedir(DIR *);
|
||||
int creat(const char *, uint32_t) nodiscard;
|
||||
int creat(const char *, uint32_t);
|
||||
int dirfd(DIR *);
|
||||
int dup(int) nodiscard;
|
||||
int dup(int);
|
||||
int dup2(int, int);
|
||||
int dup3(int, int, int);
|
||||
int execl(const char *, const char *, ...) nullterminated();
|
||||
int execle(const char *, const char *, ...) nullterminated((1));
|
||||
int execlp(const char *, const char *, ...) nullterminated();
|
||||
int execv(const char *, char *const[]) paramsnonnull();
|
||||
int execve(const char *, char *const[], char *const[]) paramsnonnull();
|
||||
int execvp(const char *, char *const[]) paramsnonnull();
|
||||
int execvpe(const char *, char *const[], char *const[]) paramsnonnull();
|
||||
int execv(const char *, char *const[]);
|
||||
int execve(const char *, char *const[], char *const[]);
|
||||
int execvp(const char *, char *const[]);
|
||||
int execvpe(const char *, char *const[], char *const[]);
|
||||
int faccessat(int, const char *, int, uint32_t);
|
||||
int fadvise(int, uint64_t, uint64_t, int);
|
||||
int fchdir(int);
|
||||
int fchmod(int, uint32_t) nothrow;
|
||||
int fchmodat(int, const char *, uint32_t, uint32_t);
|
||||
int fchmodat(int, const char *, uint32_t, int);
|
||||
int fchown(int, uint32_t, uint32_t);
|
||||
int fchownat(int, const char *, uint32_t, uint32_t, uint32_t);
|
||||
int fchownat(int, const char *, uint32_t, uint32_t, int);
|
||||
int fcntl(int, int, ...);
|
||||
int fdatasync(int);
|
||||
int filecmp(const char *, const char *);
|
||||
int flock(int, int);
|
||||
int fork(void);
|
||||
int fstat(int, struct stat *);
|
||||
int fstatat(int, const char *, struct stat *, uint32_t);
|
||||
int fstatat(int, const char *, struct stat *, int);
|
||||
int fsync(int);
|
||||
int ftruncate(int, int64_t);
|
||||
int getdents(unsigned, void *, unsigned, long *);
|
||||
int getdomainname(char *, size_t);
|
||||
int gethostname(char *, size_t);
|
||||
int getpgid(int);
|
||||
|
@ -127,7 +129,7 @@ int getrusage(int, struct rusage *);
|
|||
int kill(int, int);
|
||||
int killpg(int, int);
|
||||
int link(const char *, const char *) nothrow;
|
||||
int linkat(int, const char *, int, const char *, uint32_t);
|
||||
int linkat(int, const char *, int, const char *, int);
|
||||
int lstat(const char *, struct stat *);
|
||||
int lutimes(const char *, const struct timeval[2]);
|
||||
int madvise(void *, uint64_t, int);
|
||||
|
@ -244,10 +246,6 @@ int vdprintf(int, const char *, va_list) paramsnonnull();
|
|||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
|
||||
#define getcwd(BUF, SIZE) \
|
||||
(__builtin_constant_p(BUF) && !(BUF) ? get_current_dir_name() \
|
||||
: getcwd(BUF, SIZE))
|
||||
|
||||
void _init_onntconsoleevent(void);
|
||||
void _init_wincrash(void);
|
||||
|
||||
|
|
|
@ -75,6 +75,25 @@ o/$(MODE)/libc/calls/ntcontext2linux.o: \
|
|||
OVERRIDE_COPTS += \
|
||||
-O3
|
||||
|
||||
# TODO(jart): make va_arg optimize well in default mode
|
||||
o//libc/calls/ioctl.o \
|
||||
o//libc/calls/ioctl_default.o \
|
||||
o//libc/calls/ioctl_fioclex-nt.o \
|
||||
o//libc/calls/ioctl_fioclex.o \
|
||||
o//libc/calls/ioctl_siocgifconf-nt.o \
|
||||
o//libc/calls/ioctl_siocgifconf.o \
|
||||
o//libc/calls/ioctl_tcgets-nt.o \
|
||||
o//libc/calls/ioctl_tcgets.o \
|
||||
o//libc/calls/ioctl_tcsets-nt.o \
|
||||
o//libc/calls/ioctl_tcsets.o \
|
||||
o//libc/calls/ioctl_tiocgwinsz-nt.o \
|
||||
o//libc/calls/ioctl_tiocgwinsz.o \
|
||||
o//libc/calls/ioctl_tiocswinsz-nt.o \
|
||||
o//libc/calls/ioctl_tiocswinsz.o \
|
||||
o//libc/calls/fcntl.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-Os
|
||||
|
||||
o/$(MODE)/libc/calls/execl.o \
|
||||
o/$(MODE)/libc/calls/execle.o \
|
||||
o/$(MODE)/libc/calls/execlp.o \
|
||||
|
|
|
@ -18,14 +18,19 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Sets current directory.
|
||||
*
|
||||
* This does *not* update the `PWD` environment variable.
|
||||
*
|
||||
* @asyncsignalsafe
|
||||
* @see fchdir()
|
||||
*/
|
||||
int chdir(const char *path) {
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
|
||||
if (!IsWindows()) {
|
||||
return sys_chdir(path);
|
||||
} else {
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
|
||||
/**
|
||||
|
@ -42,5 +41,5 @@
|
|||
* @see fchmod()
|
||||
*/
|
||||
int chmod(const char *pathname, uint32_t mode) {
|
||||
return sys_fchmodat(AT_FDCWD, pathname, mode, 0);
|
||||
return fchmodat(AT_FDCWD, pathname, mode, 0);
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
|
||||
/**
|
||||
|
@ -33,5 +32,5 @@
|
|||
* @asyncsignalsafe
|
||||
*/
|
||||
int chown(const char *pathname, uint32_t uid, uint32_t gid) {
|
||||
return sys_fchownat(AT_FDCWD, pathname, uid, gid, 0);
|
||||
return fchownat(AT_FDCWD, pathname, uid, gid, 0);
|
||||
}
|
||||
|
|
|
@ -19,7 +19,9 @@
|
|||
#include "libc/assert.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
|
@ -42,6 +44,7 @@ int clock_gettime(int clockid, struct timespec *ts) {
|
|||
axdx_t ad;
|
||||
struct NtFileTime ft;
|
||||
if (!ts) return efault();
|
||||
if (IsAsan() && !__asan_is_valid(ts, sizeof(*ts))) return efault();
|
||||
if (clockid == -1) return einval();
|
||||
if (!IsWindows()) {
|
||||
if ((rc = sys_clock_gettime(clockid, ts)) == -1 && errno == ENOSYS) {
|
||||
|
|
|
@ -33,7 +33,7 @@ textwindows int sys_close_nt(struct Fd *fd) {
|
|||
FlushFileBuffers(fd->handle);
|
||||
}
|
||||
ok = CloseHandle(fd->handle);
|
||||
if (fd->kind == kFdConsole) {
|
||||
if (fd->kind == kFdConsole && fd->extra && fd->extra != -1) {
|
||||
ok &= CloseHandle(fd->extra);
|
||||
}
|
||||
return ok ? 0 : __winerr();
|
||||
|
|
|
@ -74,6 +74,10 @@ char *commandv(const char *name, char pathbuf[hasatleast PATH_MAX]) {
|
|||
char *p;
|
||||
size_t namelen;
|
||||
int rc, olderr;
|
||||
if (!name) {
|
||||
efault();
|
||||
return NULL;
|
||||
}
|
||||
if (!(namelen = strlen(name))) {
|
||||
enoent();
|
||||
return NULL;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Executes program, with PATH search and current environment.
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include "libc/sysv/consts/o.h"
|
||||
|
||||
textwindows int sys_execve_nt(const char *program, char *const argv[],
|
||||
char *const envp[]) {
|
||||
char *const envp[]) {
|
||||
int rc;
|
||||
size_t i;
|
||||
uint32_t dwExitCode;
|
||||
|
@ -42,13 +42,7 @@ textwindows int sys_execve_nt(const char *program, char *const argv[],
|
|||
startinfo.hStdInput = g_fds.p[0].handle;
|
||||
startinfo.hStdOutput = g_fds.p[1].handle;
|
||||
startinfo.hStdError = g_fds.p[2].handle;
|
||||
for (i = 2; i < g_fds.n; ++i) {
|
||||
if (g_fds.p[i].kind != kFdEmpty && (g_fds.p[i].flags & O_CLOEXEC)) {
|
||||
close(i);
|
||||
}
|
||||
}
|
||||
rc = ntspawn(program, argv, envp, NULL, NULL, NULL, true, 0, NULL, &startinfo,
|
||||
&procinfo);
|
||||
rc = ntspawn(program, argv, envp, 0, 0, 0, 1, 0, 0, &startinfo, &procinfo);
|
||||
if (rc == -1) return -1;
|
||||
CloseHandle(procinfo.hThread);
|
||||
do {
|
||||
|
|
|
@ -19,6 +19,17 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static noasan bool __asan_is_valid_strlist(char *const *p) {
|
||||
for (;; ++p) {
|
||||
if (!__asan_is_valid(p, sizeof(char *))) return false;
|
||||
if (!*p) return true;
|
||||
if (!__asan_is_valid(*p, 1)) return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces current process with program.
|
||||
|
@ -34,6 +45,18 @@
|
|||
* @vforksafe
|
||||
*/
|
||||
int execve(const char *program, char *const argv[], char *const envp[]) {
|
||||
size_t i;
|
||||
if (!program || !argv || !envp) return efault();
|
||||
if (IsAsan() &&
|
||||
(!__asan_is_valid(program, 1) || !__asan_is_valid_strlist(argv) ||
|
||||
!__asan_is_valid_strlist(envp))) {
|
||||
return efault();
|
||||
}
|
||||
for (i = 3; i < g_fds.n; ++i) {
|
||||
if (g_fds.p[i].kind != kFdEmpty && (g_fds.p[i].flags & O_CLOEXEC)) {
|
||||
close(i);
|
||||
}
|
||||
}
|
||||
if (!IsWindows()) {
|
||||
return sys_execve(program, argv, envp);
|
||||
} else {
|
||||
|
|
|
@ -17,7 +17,10 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Executes program, with path environment search.
|
||||
|
@ -34,6 +37,7 @@
|
|||
int execvpe(const char *prog, char *const argv[], char *const *envp) {
|
||||
char *exe;
|
||||
char pathbuf[PATH_MAX];
|
||||
if (IsAsan() && !__asan_is_valid(prog, 1)) return efault();
|
||||
if (!(exe = commandv(prog, pathbuf))) return -1;
|
||||
return execve(exe, argv, envp);
|
||||
}
|
||||
|
|
|
@ -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/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
|
|
@ -16,11 +16,14 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
/**
|
||||
* Checks if effective user can access path in particular ways.
|
||||
|
@ -34,6 +37,10 @@
|
|||
* @asyncsignalsafe
|
||||
*/
|
||||
int faccessat(int dirfd, const char *path, int mode, uint32_t flags) {
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
|
||||
if (weaken(__zipos_notat) && weaken(__zipos_notat)(dirfd, path) == -1) {
|
||||
return -1; /* TODO(jart): implement me */
|
||||
}
|
||||
if (!IsWindows()) {
|
||||
return sys_faccessat(dirfd, path, mode, flags);
|
||||
} else {
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
/**
|
||||
* Sets current directory based on file descriptor.
|
||||
*
|
||||
* This does *not* update the `PWD` environment variable.
|
||||
*
|
||||
* @see open(path, O_DIRECTORY)
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
|
|
|
@ -22,22 +22,9 @@
|
|||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Changes file permissions via open()'d file descriptor, e.g.:
|
||||
*
|
||||
* CHECK_NE(-1, chmod("foo/bar.txt", 0644));
|
||||
* CHECK_NE(-1, chmod("o/default/program.com", 0755));
|
||||
* CHECK_NE(-1, chmod("privatefolder/", 0700));
|
||||
*
|
||||
* The esoteric bits generally available on System V are:
|
||||
*
|
||||
* CHECK_NE(-1, chmod("/opt/", 01000)); // sticky bit
|
||||
* CHECK_NE(-1, chmod("/usr/bin/sudo", 04755)); // setuid bit
|
||||
* CHECK_NE(-1, chmod("/usr/bin/wall", 02755)); // setgid bit
|
||||
*
|
||||
* This works on Windows NT if you ignore the error ;-)
|
||||
* Changes file permissions via open()'d file descriptor.
|
||||
*
|
||||
* @param mode contains octal flags (base 8)
|
||||
* @errors ENOSYS
|
||||
* @asyncsignalsafe
|
||||
* @see chmod()
|
||||
*/
|
||||
|
|
49
libc/calls/fchmodat.c
Normal file
49
libc/calls/fchmodat.c
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
/**
|
||||
* Changes permissions on file, e.g.:
|
||||
*
|
||||
* CHECK_NE(-1, fchmodat(AT_FDCWD, "foo/bar.txt", 0644));
|
||||
* CHECK_NE(-1, fchmodat(AT_FDCWD, "o/default/program.com", 0755));
|
||||
* CHECK_NE(-1, fchmodat(AT_FDCWD, "privatefolder/", 0700));
|
||||
*
|
||||
* This works on Windows NT if you ignore the error ;-)
|
||||
*
|
||||
* @param path must exist
|
||||
* @param mode contains octal flags (base 8)
|
||||
* @param flags can have `AT_SYMLINK_NOFOLLOW`
|
||||
* @errors ENOENT, ENOTDIR, ENOSYS
|
||||
* @asyncsignalsafe
|
||||
* @see fchmod()
|
||||
*/
|
||||
int fchmodat(int dirfd, const char *path, uint32_t mode, int flags) {
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
|
||||
if (weaken(__zipos_notat) && weaken(__zipos_notat)(dirfd, path) == -1) {
|
||||
return -1; /* TODO(jart): implement me */
|
||||
}
|
||||
return sys_fchmodat(dirfd, path, mode, flags);
|
||||
}
|
|
@ -16,11 +16,16 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
/**
|
||||
* Changes owner and/or group of pathname.
|
||||
* Changes owner and/or group of path.
|
||||
*
|
||||
* @param dirfd is open()'d relative-to directory, or AT_FDCWD, etc.
|
||||
* @param uid is user id, or -1 to not change
|
||||
|
@ -32,7 +37,11 @@
|
|||
* @see /etc/group for group ids
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int fchownat(int dirfd, const char *pathname, uint32_t uid, uint32_t gid,
|
||||
uint32_t flags) {
|
||||
return sys_fchownat(dirfd, pathname, uid, gid, flags);
|
||||
int fchownat(int dirfd, const char *path, uint32_t uid, uint32_t gid,
|
||||
int flags) {
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
|
||||
if (weaken(__zipos_notat) && weaken(__zipos_notat)(dirfd, path) == -1) {
|
||||
return -1; /* TODO(jart): implement me */
|
||||
}
|
||||
return sys_fchownat(dirfd, path, uid, gid, flags);
|
||||
}
|
||||
|
|
|
@ -16,9 +16,12 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
/**
|
||||
* Does things with file descriptor, via re-imagined hourglass api, e.g.
|
||||
|
@ -45,9 +48,15 @@ int fcntl(int fd, int cmd, ...) {
|
|||
va_start(va, cmd);
|
||||
arg = va_arg(va, uintptr_t);
|
||||
va_end(va);
|
||||
if (!IsWindows()) {
|
||||
return sys_fcntl(fd, cmd, arg);
|
||||
if (fd >= 0) {
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
return weaken(__zipos_fcntl)(fd, cmd, arg);
|
||||
} else if (!IsWindows()) {
|
||||
return sys_fcntl(fd, cmd, arg);
|
||||
} else {
|
||||
return sys_fcntl_nt(fd, cmd, arg);
|
||||
}
|
||||
} else {
|
||||
return sys_fcntl_nt(fd, cmd, arg);
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
|
@ -37,6 +38,7 @@ bool fileexists(const char *path) {
|
|||
int rc, olderr;
|
||||
struct stat st;
|
||||
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);
|
||||
|
|
|
@ -17,24 +17,69 @@
|
|||
│ 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/fmt/conv.h"
|
||||
#include "libc/nexgen32e/bsr.h"
|
||||
#include "libc/nt/enum/fileflagandattributes.h"
|
||||
#include "libc/nt/enum/fileinfobyhandleclass.h"
|
||||
#include "libc/nt/enum/filetype.h"
|
||||
#include "libc/nt/enum/fsctl.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/byhandlefileinformation.h"
|
||||
#include "libc/nt/struct/filecompressioninfo.h"
|
||||
#include "libc/nt/struct/reparsedatabuffer.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tpenc.h"
|
||||
#include "libc/str/utf16.h"
|
||||
#include "libc/sysv/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;
|
||||
uint32_t mem, i, n, z = 0;
|
||||
struct NtReparseDataBuffer *rdb;
|
||||
long buf[(sizeof(*rdb) + PATH_MAX * sizeof(char16_t)) / sizeof(long)];
|
||||
mem = sizeof(buf);
|
||||
rdb = (struct NtReparseDataBuffer *)buf;
|
||||
if (DeviceIoControl(fh, kNtFsctlGetReparsePoint, 0, 0, rdb, mem, &n, 0)) {
|
||||
i = 0;
|
||||
n = rdb->SymbolicLinkReparseBuffer.PrintNameLength / sizeof(char16_t);
|
||||
p = (char16_t *)((char *)rdb->SymbolicLinkReparseBuffer.PathBuffer +
|
||||
rdb->SymbolicLinkReparseBuffer.PrintNameOffset);
|
||||
while (i < n) {
|
||||
x = p[i++] & 0xffff;
|
||||
if (!IsUcs2(x)) {
|
||||
if (i < n) {
|
||||
y = p[i++] & 0xffff;
|
||||
x = MergeUtf16(x, y);
|
||||
} else {
|
||||
x = 0xfffd;
|
||||
}
|
||||
}
|
||||
z += x < 0200 ? 1 : bsrl(tpenc(x)) >> 3;
|
||||
}
|
||||
} else {
|
||||
DEBUG("GetSizeOfReparsePoint failed %d", GetLastError());
|
||||
}
|
||||
return z;
|
||||
}
|
||||
|
||||
textwindows int sys_fstat_nt(int64_t handle, struct stat *st) {
|
||||
int filetype;
|
||||
uint64_t actualsize;
|
||||
struct NtFileCompressionInfo fci;
|
||||
struct NtByHandleFileInformation wst;
|
||||
if (!st) return efault();
|
||||
if ((filetype = GetFileType(handle))) {
|
||||
memset(st, 0, sizeof(*st));
|
||||
switch (filetype) {
|
||||
|
@ -52,7 +97,7 @@ textwindows int sys_fstat_nt(int64_t handle, struct stat *st) {
|
|||
}
|
||||
if (wst.dwFileAttributes & kNtFileAttributeDirectory) {
|
||||
st->st_mode |= S_IFDIR;
|
||||
} else if (wst.dwFileAttributes & kNtFileFlagOpenReparsePoint) {
|
||||
} else if (wst.dwFileAttributes & kNtFileAttributeReparsePoint) {
|
||||
st->st_mode |= S_IFLNK;
|
||||
} else {
|
||||
st->st_mode |= S_IFREG;
|
||||
|
@ -66,13 +111,19 @@ textwindows int sys_fstat_nt(int64_t handle, struct stat *st) {
|
|||
st->st_rdev = wst.dwVolumeSerialNumber;
|
||||
st->st_ino = (uint64_t)wst.nFileIndexHigh << 32 | wst.nFileIndexLow;
|
||||
st->st_nlink = wst.nNumberOfLinks;
|
||||
if (GetFileInformationByHandleEx(handle, kNtFileCompressionInfo, &fci,
|
||||
sizeof(fci))) {
|
||||
actualsize = fci.CompressedFileSize;
|
||||
if (S_ISLNK(st->st_mode)) {
|
||||
if (!st->st_size) {
|
||||
st->st_size = GetSizeOfReparsePoint(handle);
|
||||
}
|
||||
} else {
|
||||
actualsize = st->st_size;
|
||||
if (S_ISREG(st->st_mode) &&
|
||||
GetFileInformationByHandleEx(handle, kNtFileCompressionInfo,
|
||||
&fci, sizeof(fci))) {
|
||||
actualsize = fci.CompressedFileSize;
|
||||
}
|
||||
st->st_blocks = roundup(actualsize, PAGESIZE) / 512;
|
||||
}
|
||||
st->st_blocks = roundup(actualsize, PAGESIZE) / 512;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
* @asyncsignalsafe
|
||||
*/
|
||||
int fstat(int fd, struct stat *st) {
|
||||
if (IsAsan() && (!st || !__asan_is_valid(st, sizeof(*st)))) return efault();
|
||||
if (IsAsan() && !__asan_is_valid(st, sizeof(*st))) return efault();
|
||||
if (__isfdkind(fd, kFdZip)) {
|
||||
return weaken(__zipos_fstat)(
|
||||
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, st);
|
||||
|
|
|
@ -22,12 +22,11 @@
|
|||
#include "libc/nt/enum/creationdisposition.h"
|
||||
#include "libc/nt/enum/fileflagandattributes.h"
|
||||
#include "libc/nt/enum/filesharemode.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
|
||||
textwindows int sys_fstatat_nt(int dirfd, const char *path, struct stat *st,
|
||||
uint32_t flags) {
|
||||
int flags) {
|
||||
int rc;
|
||||
int64_t fh;
|
||||
uint16_t path16[PATH_MAX];
|
||||
|
@ -35,9 +34,12 @@ textwindows int sys_fstatat_nt(int dirfd, const char *path, struct stat *st,
|
|||
if ((fh = CreateFile(
|
||||
path16, kNtFileReadAttributes,
|
||||
kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete, NULL,
|
||||
kNtOpenExisting, kNtFileAttributeNormal | kNtFileFlagBackupSemantics,
|
||||
kNtOpenExisting,
|
||||
kNtFileAttributeNormal | kNtFileFlagBackupSemantics |
|
||||
((flags & AT_SYMLINK_NOFOLLOW) ? kNtFileFlagOpenReparsePoint
|
||||
: 0),
|
||||
0)) != -1) {
|
||||
rc = sys_fstat_nt(fh, st);
|
||||
rc = st ? sys_fstat_nt(fh, st) : 0;
|
||||
CloseHandle(fh);
|
||||
return rc;
|
||||
} else {
|
||||
|
|
|
@ -19,8 +19,11 @@
|
|||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
@ -36,9 +39,13 @@
|
|||
* @see S_ISDIR(st.st_mode), S_ISREG()
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int fstatat(int dirfd, const char *path, struct stat *st, uint32_t flags) {
|
||||
int fstatat(int dirfd, const char *path, struct stat *st, int flags) {
|
||||
struct ZiposUri zipname;
|
||||
if (IsAsan() && (!st || !__asan_is_valid(st, sizeof(*st)))) return efault();
|
||||
if (IsAsan() && (!__asan_is_valid(path, 1) ||
|
||||
(st && !__asan_is_valid(st, sizeof(*st))))) {
|
||||
return efault();
|
||||
}
|
||||
if (__isfdkind(dirfd, kFdZip)) return einval(); /* TODO(jart): implement me */
|
||||
if (weaken(__zipos_stat) && weaken(__zipos_parseuri)(path, &zipname) != -1) {
|
||||
return weaken(__zipos_stat)(&zipname, st);
|
||||
} else if (!IsWindows()) {
|
||||
|
|
|
@ -16,32 +16,70 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Returns current working directory.
|
||||
* Returns current working directory, e.g.
|
||||
*
|
||||
* const char *dirname = gc(getcwd(0,0)); // if malloc is linked
|
||||
* const char *dirname = getcwd(alloca(PATH_MAX),PATH_MAX);
|
||||
*
|
||||
* @param buf is where UTF-8 NUL-terminated path string gets written,
|
||||
* which may be NULL to ask this function to malloc a buffer
|
||||
* @param size is number of bytes available in buf, e.g. PATH_MAX,
|
||||
* which may be 0 if buf NULL
|
||||
* @return buf containing system-normative path or NULL w/ errno
|
||||
* @see get_current_dir_name() which is better
|
||||
* @error ERANGE, EINVAL
|
||||
* @error ERANGE, EINVAL, ENOMEM
|
||||
*/
|
||||
char *(getcwd)(char *buf, size_t size) {
|
||||
if (buf && size) buf[0] = '\0';
|
||||
if (!IsWindows()) {
|
||||
if (IsXnu()) {
|
||||
return sys_getcwd_xnu(buf, size);
|
||||
} else if (sys_getcwd(buf, size) != (void *)-1) {
|
||||
return buf;
|
||||
} else {
|
||||
return NULL;
|
||||
char *getcwd(char *buf, size_t size) {
|
||||
char *p, *r;
|
||||
if (buf) {
|
||||
p = buf;
|
||||
if (!size) {
|
||||
einval();
|
||||
return 0;
|
||||
}
|
||||
} else if (weaken(malloc)) {
|
||||
if (!size) size = PATH_MAX + 1;
|
||||
if (!(p = weaken(malloc)(size))) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
return sys_getcwd_nt(buf, size);
|
||||
einval();
|
||||
return 0;
|
||||
}
|
||||
*p = '\0';
|
||||
if (!IsWindows()) {
|
||||
if (IsMetal()) {
|
||||
r = size >= 5 ? strcpy(p, "/zip") : 0;
|
||||
} else if (IsXnu()) {
|
||||
r = sys_getcwd_xnu(p, size);
|
||||
} else if (sys_getcwd(p, size) != (void *)-1) {
|
||||
r = p;
|
||||
} else {
|
||||
r = 0;
|
||||
}
|
||||
} else {
|
||||
r = sys_getcwd_nt(p, size);
|
||||
}
|
||||
if (!buf) {
|
||||
if (!r) {
|
||||
if (weaken(free)) {
|
||||
weaken(free)(p);
|
||||
}
|
||||
} else {
|
||||
if (weaken(realloc)) {
|
||||
if ((p = weaken(realloc)(r, strlen(r) + 1))) {
|
||||
r = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
|
@ -28,9 +29,13 @@
|
|||
* @return 0 on success or -1 w/ errno
|
||||
*/
|
||||
int getitimer(int which, struct itimerval *curvalue) {
|
||||
if (IsAsan() && !__asan_is_valid(curvalue, sizeof(*curvalue))) {
|
||||
return efault();
|
||||
}
|
||||
if (!IsWindows()) {
|
||||
return sys_getitimer(which, curvalue);
|
||||
} else {
|
||||
return sys_setitimer_nt(which, NULL, curvalue);
|
||||
if (!curvalue) return efault();
|
||||
return sys_setitimer_nt(which, 0, curvalue);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
|
@ -30,6 +31,7 @@
|
|||
* @see libc/sysv/consts.sh
|
||||
*/
|
||||
int getrlimit(int resource, struct rlimit *rlim) {
|
||||
if (resource == -1) return einval();
|
||||
if (resource == 127) return einval();
|
||||
if (IsAsan() && !__asan_is_valid(rlim, sizeof(*rlim))) return efault();
|
||||
return sys_getrlimit(resource, rlim);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
|
@ -27,6 +29,8 @@
|
|||
* @return 0 on success, or -1 w/ errno
|
||||
*/
|
||||
int getrusage(int who, struct rusage *usage) {
|
||||
if (who == 99) return einval();
|
||||
if (IsAsan() && !__asan_is_valid(usage, sizeof(*usage))) return efault();
|
||||
if (!IsWindows()) {
|
||||
return sys_getrusage(who, usage);
|
||||
} else {
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
int sys_gettimeofday_nt(struct timeval *tv, struct timezone *tz) {
|
||||
struct NtFileTime ft;
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
*tv = FileTimeToTimeVal(ft);
|
||||
if (tv) *tv = FileTimeToTimeVal(ft);
|
||||
if (tz) memset(tz, 0, sizeof(*tz));
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/time/struct/timezone.h"
|
||||
#include "libc/time/time.h"
|
||||
|
@ -35,6 +36,10 @@
|
|||
*/
|
||||
int gettimeofday(struct timeval *tv, struct timezone *tz) {
|
||||
axdx_t ad;
|
||||
if (IsAsan() && ((tv && !__asan_is_valid(tv, sizeof(*tv))) ||
|
||||
(tz && !__asan_is_valid(tz, sizeof(*tz))))) {
|
||||
return efault();
|
||||
}
|
||||
if (!IsWindows() && !IsMetal()) {
|
||||
ad = sys_gettimeofday(tv, tz, NULL);
|
||||
assert(ad.ax != -1);
|
||||
|
|
|
@ -117,7 +117,6 @@ i32 __sys_openat(i32, const char *, i32, u32) hidden;
|
|||
i32 __sys_pipe2(i32[hasatleast 2], u32) hidden;
|
||||
i32 __sys_utimensat(i32, const char *, const struct timespec *, i32) hidden;
|
||||
i32 __sys_wait4(i32, i32 *, i32, struct rusage *) hidden;
|
||||
i32 getdents(i32, void *, u32, i64 *) hidden;
|
||||
i32 sys_chdir(const char *) hidden;
|
||||
i32 sys_clock_gettime(i32, struct timespec *) hidden;
|
||||
i32 sys_close(i32) hidden;
|
||||
|
@ -232,6 +231,7 @@ int gethostname_bsd(char *, size_t) hidden;
|
|||
int gethostname_nt(char *, size_t) hidden;
|
||||
size_t __iovec_size(const struct iovec *, size_t) hidden;
|
||||
void __rusage2linux(struct rusage *) hidden;
|
||||
int __notziposat(int, const char *);
|
||||
ssize_t WritevUninterruptible(int, struct iovec *, int);
|
||||
void flock2cosmo(uintptr_t);
|
||||
void cosmo2flock(uintptr_t);
|
||||
|
@ -264,14 +264,14 @@ int sys_fdatasync_nt(int) hidden;
|
|||
int sys_flock_nt(int, int) hidden;
|
||||
int sys_fork_nt(void) hidden;
|
||||
int sys_fstat_nt(i64, struct stat *) hidden;
|
||||
int sys_fstatat_nt(int, const char *, struct stat *, uint32_t) hidden;
|
||||
int sys_fstatat_nt(int, const char *, struct stat *, int) hidden;
|
||||
int sys_ftruncate_nt(i64, u64) hidden;
|
||||
int sys_getppid_nt(void) hidden;
|
||||
int sys_getpriority_nt(int) hidden;
|
||||
int sys_getrusage_nt(int, struct rusage *) hidden;
|
||||
int sys_gettimeofday_nt(struct timeval *, struct timezone *) hidden;
|
||||
int sys_kill_nt(int, int) hidden;
|
||||
int sys_link_nt(const char *, const char *) hidden;
|
||||
int sys_linkat_nt(int, const char *, int, const char *) hidden;
|
||||
int sys_lstat_nt(const char *, struct stat *) hidden;
|
||||
int sys_madvise_nt(void *, size_t, int) hidden;
|
||||
int sys_mkdirat_nt(int, const char *, uint32_t) hidden;
|
||||
|
@ -287,12 +287,12 @@ int sys_sync_nt(void) hidden;
|
|||
int sys_sysinfo_nt(struct sysinfo *) hidden;
|
||||
int sys_truncate_nt(const char *, u64) hidden;
|
||||
int sys_unlinkat_nt(int, const char *, int) hidden;
|
||||
int sys_utimes_nt(const char *, const struct timeval[2]) hidden;
|
||||
int sys_utimensat_nt(int, const char *, const struct timespec *, int) hidden;
|
||||
int sys_utimes_nt(const char *, const struct timeval[2]) hidden;
|
||||
ssize_t sys_open_nt(int, const char *, u32, i32) nodiscard hidden;
|
||||
ssize_t sys_read_nt(struct Fd *, const struct iovec *, size_t, ssize_t) hidden;
|
||||
ssize_t sys_write_nt(struct Fd *, const struct iovec *, size_t, ssize_t) hidden;
|
||||
ssize_t sys_readlinkat_nt(int, const char *, char *, size_t) hidden;
|
||||
ssize_t sys_write_nt(struct Fd *, const struct iovec *, size_t, ssize_t) hidden;
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § syscalls » windows nt » support ─╬─│┼
|
||||
|
|
|
@ -13,10 +13,10 @@ COSMOPOLITAN_C_START_
|
|||
|
||||
int ioctl(int, uint64_t, ...);
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § system calls » ioctl » undiamonding (size optimization) ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § system calls » ioctl » undiamonding ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
#define ioctl(FD, REQUEST, ...) \
|
||||
__IOCTL_DISPATCH(__EQUIVALENT, ioctl_default(FD, REQUEST, ##__VA_ARGS__), \
|
||||
|
@ -63,22 +63,18 @@ int ioctl(int, uint64_t, ...);
|
|||
ReZ; \
|
||||
})
|
||||
|
||||
int ioctl_tcgets(int, void *);
|
||||
int ioctl_tcgets_nt(int, void *);
|
||||
int ioctl_tcsets(int, uint64_t, void *);
|
||||
int ioctl_tcsets_nt(int, uint64_t, void *);
|
||||
int ioctl_tiocgwinsz(int, void *);
|
||||
int ioctl_tiocgwinsz_nt(int, void *);
|
||||
int ioctl_tiocswinsz(int, void *);
|
||||
int ioctl_tiocswinsz_nt(int, void *);
|
||||
int ioctl_siocgifconf(int, void *);
|
||||
int ioctl_siocgifaddr(int, void *);
|
||||
int ioctl_siocgifdstaddr(int, void *);
|
||||
int ioctl_siocgifnetmask(int, void *);
|
||||
int ioctl_siocgifbrdaddr(int, void *);
|
||||
int ioctl_siocgifflags(int, void *);
|
||||
int ioctl_default(int, uint64_t, void *);
|
||||
int ioctl_default(int, uint64_t, ...);
|
||||
int ioctl_fioclex(int, int);
|
||||
int ioctl_siocgifaddr(int, ...);
|
||||
int ioctl_siocgifbrdaddr(int, ...);
|
||||
int ioctl_siocgifconf(int, ...);
|
||||
int ioctl_siocgifdstaddr(int, ...);
|
||||
int ioctl_siocgifflags(int, ...);
|
||||
int ioctl_siocgifnetmask(int, ...);
|
||||
int ioctl_tcgets(int, ...);
|
||||
int ioctl_tcsets(int, uint64_t, ...);
|
||||
int ioctl_tiocgwinsz(int, ...);
|
||||
int ioctl_tiocswinsz(int, ...);
|
||||
|
||||
#endif /* GNUC && !ANSI */
|
||||
COSMOPOLITAN_C_END_
|
||||
|
|
|
@ -23,15 +23,20 @@
|
|||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
int ioctl_default(int fd, uint64_t request, void *memory) {
|
||||
int ioctl_default(int fd, uint64_t request, ...) {
|
||||
int rc;
|
||||
void *arg;
|
||||
va_list va;
|
||||
int64_t handle;
|
||||
va_start(va, request);
|
||||
arg = va_arg(va, void *);
|
||||
va_end(va);
|
||||
if (!IsWindows()) {
|
||||
return sys_ioctl(fd, request, memory);
|
||||
return sys_ioctl(fd, request, arg);
|
||||
} else if (__isfdopen(fd)) {
|
||||
if (g_fds.p[fd].kind == kFdSocket) {
|
||||
handle = g_fds.p[fd].handle;
|
||||
if ((rc = weaken(__sys_ioctlsocket_nt)(handle, request, memory)) != -1) {
|
||||
if ((rc = weaken(__sys_ioctlsocket_nt)(handle, request, arg)) != -1) {
|
||||
return rc;
|
||||
} else {
|
||||
return weaken(__winsockerr)();
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/dce.h"
|
||||
|
||||
int ioctl_fioclex_nt(int, int);
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Sets "close on exec" on file descriptor the fast way.
|
||||
|
@ -28,9 +28,22 @@ int ioctl_fioclex_nt(int, int);
|
|||
* @see ioctl(fd, FIOCLEX, 0) dispatches here
|
||||
*/
|
||||
int ioctl_fioclex(int fd, int req) {
|
||||
if (!IsWindows()) {
|
||||
return sys_ioctl(fd, req, 0);
|
||||
if (fd >= 0) {
|
||||
if (IsWindows() || (fd < g_fds.n && g_fds.p[fd].kind == kFdZip)) {
|
||||
if (__isfdopen(fd)) {
|
||||
if (req == FIOCLEX) {
|
||||
g_fds.p[fd].flags |= O_CLOEXEC;
|
||||
} else {
|
||||
g_fds.p[fd].flags &= ~O_CLOEXEC;
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
return ebadf();
|
||||
}
|
||||
} else {
|
||||
return sys_ioctl(fd, req);
|
||||
}
|
||||
} else {
|
||||
return ioctl_fioclex_nt(fd, req);
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/assert.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/str/str.h"
|
||||
|
@ -35,7 +36,6 @@
|
|||
* The ifc_len is an input/output parameter: set it to the total size of
|
||||
* the ifcu_buf (ifcu_req) buffer on input.
|
||||
*/
|
||||
int ioctl_default(int, uint64_t, void *) hidden;
|
||||
int ioctl_siocgifconf_nt(int, struct ifconf *) hidden;
|
||||
int ioctl_siocgifaddr_nt(int, struct ifreq *) hidden;
|
||||
int ioctl_siocgifflags_nt(int, struct ifreq *) hidden;
|
||||
|
@ -103,41 +103,66 @@ static int ioctl_siocgifaddr_sysv(int fd, uint64_t op, struct ifreq *ifr) {
|
|||
*
|
||||
* @see ioctl(fd, SIOCGIFCONF, tio) dispatches here
|
||||
*/
|
||||
int ioctl_siocgifconf(int fd, void *ifc) {
|
||||
int ioctl_siocgifconf(int fd, ...) {
|
||||
va_list va;
|
||||
struct ifconf *ifc;
|
||||
va_start(va, fd);
|
||||
ifc = va_arg(va, struct ifconf *);
|
||||
va_end(va);
|
||||
if (!IsWindows()) {
|
||||
return ioctl_siocgifconf_sysv(fd, (struct ifconf *)ifc);
|
||||
return ioctl_siocgifconf_sysv(fd, ifc);
|
||||
} else {
|
||||
return ioctl_siocgifconf_nt(fd, ifc);
|
||||
}
|
||||
}
|
||||
|
||||
int ioctl_siocgifaddr(int fd, void *ifr) {
|
||||
int ioctl_siocgifaddr(int fd, ...) {
|
||||
va_list va;
|
||||
struct ifreq *ifr;
|
||||
va_start(va, fd);
|
||||
ifr = va_arg(va, struct ifreq *);
|
||||
va_end(va);
|
||||
if (!IsWindows()) {
|
||||
return ioctl_siocgifaddr_sysv(fd, SIOCGIFADDR, (struct ifreq *)ifr);
|
||||
return ioctl_siocgifaddr_sysv(fd, SIOCGIFADDR, ifr);
|
||||
} else {
|
||||
return ioctl_siocgifaddr_nt(fd, (struct ifreq *)ifr);
|
||||
return ioctl_siocgifaddr_nt(fd, ifr);
|
||||
}
|
||||
}
|
||||
|
||||
int ioctl_siocgifnetmask(int fd, void *ifr) {
|
||||
int ioctl_siocgifnetmask(int fd, ...) {
|
||||
va_list va;
|
||||
struct ifreq *ifr;
|
||||
va_start(va, fd);
|
||||
ifr = va_arg(va, struct ifreq *);
|
||||
va_end(va);
|
||||
if (!IsWindows()) {
|
||||
return ioctl_siocgifaddr_sysv(fd, SIOCGIFNETMASK, (struct ifreq *)ifr);
|
||||
return ioctl_siocgifaddr_sysv(fd, SIOCGIFNETMASK, ifr);
|
||||
} else {
|
||||
return ioctl_siocgifnetmask_nt(fd, (struct ifreq *)ifr);
|
||||
return ioctl_siocgifnetmask_nt(fd, ifr);
|
||||
}
|
||||
}
|
||||
|
||||
int ioctl_siocgifbrdaddr(int fd, void *ifr) {
|
||||
int ioctl_siocgifbrdaddr(int fd, ...) {
|
||||
va_list va;
|
||||
struct ifreq *ifr;
|
||||
va_start(va, fd);
|
||||
ifr = va_arg(va, struct ifreq *);
|
||||
va_end(va);
|
||||
if (!IsWindows()) {
|
||||
return ioctl_siocgifaddr_sysv(fd, SIOCGIFBRDADDR, (struct ifreq *)ifr);
|
||||
return ioctl_siocgifaddr_sysv(fd, SIOCGIFBRDADDR, ifr);
|
||||
} else {
|
||||
return ioctl_siocgifbrdaddr_nt(fd, (struct ifreq *)ifr);
|
||||
return ioctl_siocgifbrdaddr_nt(fd, ifr);
|
||||
}
|
||||
}
|
||||
|
||||
int ioctl_siocgifdstaddr(int fd, void *ifr) {
|
||||
int ioctl_siocgifdstaddr(int fd, ...) {
|
||||
va_list va;
|
||||
struct ifreq *ifr;
|
||||
va_start(va, fd);
|
||||
ifr = va_arg(va, struct ifreq *);
|
||||
va_end(va);
|
||||
if (!IsWindows()) {
|
||||
return ioctl_siocgifaddr_sysv(fd, SIOCGIFDSTADDR, (struct ifreq *)ifr);
|
||||
return ioctl_siocgifaddr_sysv(fd, SIOCGIFDSTADDR, ifr);
|
||||
} else {
|
||||
return enotsup();
|
||||
/* Not supported - Unknown how to find out how to retrieve the destination
|
||||
|
@ -149,11 +174,16 @@ int ioctl_siocgifdstaddr(int fd, void *ifr) {
|
|||
}
|
||||
}
|
||||
|
||||
int ioctl_siocgifflags(int fd, void *ifr) {
|
||||
int ioctl_siocgifflags(int fd, ...) {
|
||||
va_list va;
|
||||
struct ifreq *ifr;
|
||||
va_start(va, fd);
|
||||
ifr = va_arg(va, struct ifreq *);
|
||||
va_end(va);
|
||||
if (!IsWindows()) {
|
||||
/* Both XNU and Linux are for once compatible here... */
|
||||
return ioctl_default(fd, SIOCGIFFLAGS, ifr);
|
||||
} else {
|
||||
return ioctl_siocgifflags_nt(fd, (struct ifreq *)ifr);
|
||||
return ioctl_siocgifflags_nt(fd, ifr);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,9 +17,13 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/metatermios.internal.h"
|
||||
#include "libc/calls/termios.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
int ioctl_tcgets_nt(int, struct termios *) hidden;
|
||||
|
||||
|
@ -39,10 +43,23 @@ static int ioctl_tcgets_sysv(int fd, struct termios *tio) {
|
|||
* @see ioctl(fd, TCGETS, tio) dispatches here
|
||||
* @see ioctl(fd, TIOCGETA, tio) dispatches here
|
||||
*/
|
||||
int ioctl_tcgets(int fd, struct termios *tio) {
|
||||
if (!IsWindows()) {
|
||||
return ioctl_tcgets_sysv(fd, tio);
|
||||
int ioctl_tcgets(int fd, ...) {
|
||||
va_list va;
|
||||
struct termios *tio;
|
||||
va_start(va, fd);
|
||||
tio = va_arg(va, struct termios *);
|
||||
va_end(va);
|
||||
if (fd >= 0) {
|
||||
if (!tio) return efault();
|
||||
if (IsAsan() && !__asan_is_valid(tio, sizeof(*tio))) return efault();
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
return enotty();
|
||||
} else if (!IsWindows()) {
|
||||
return ioctl_tcgets_sysv(fd, tio);
|
||||
} else {
|
||||
return ioctl_tcgets_nt(fd, tio);
|
||||
}
|
||||
} else {
|
||||
return ioctl_tcgets_nt(fd, tio);
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,9 +17,11 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/metatermios.internal.h"
|
||||
#include "libc/calls/termios.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
|
@ -38,11 +40,23 @@ static int ioctl_tcsets_sysv(int fd, uint64_t request,
|
|||
* @see ioctl(fd, TCSETS{,W,F}, tio) dispatches here
|
||||
* @see ioctl(fd, TIOCGETA{,W,F}, tio) dispatches here
|
||||
*/
|
||||
int ioctl_tcsets(int fd, uint64_t request, const struct termios *tio) {
|
||||
int ioctl_tcsets(int fd, uint64_t request, ...) {
|
||||
va_list va;
|
||||
const struct termios *tio;
|
||||
va_start(va, request);
|
||||
tio = va_arg(va, const struct termios *);
|
||||
va_end(va);
|
||||
if (!tio) return efault();
|
||||
if (!IsWindows()) {
|
||||
return ioctl_tcsets_sysv(fd, request, tio);
|
||||
if (IsAsan() && !__asan_is_valid(tio, sizeof(*tio))) return efault();
|
||||
if (fd >= 0) {
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
return enotty();
|
||||
} else if (!IsWindows()) {
|
||||
return ioctl_tcsets_sysv(fd, request, tio);
|
||||
} else {
|
||||
return ioctl_tcsets_nt(fd, request, tio);
|
||||
}
|
||||
} else {
|
||||
return ioctl_tcsets_nt(fd, request, tio);
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ textwindows int ioctl_tiocgwinsz_nt(int fd, struct winsize *ws) {
|
|||
uint32_t mode;
|
||||
struct NtStartupInfo startinfo;
|
||||
struct NtConsoleScreenBufferInfoEx sbinfo;
|
||||
if (!ws) return efault();
|
||||
fds[0] = fd, fds[1] = 1, fds[2] = 0;
|
||||
GetStartupInfo(&startinfo);
|
||||
for (i = 0; i < ARRAYLEN(fds); ++i) {
|
||||
|
|
|
@ -17,9 +17,12 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
int ioctl_tiocgwinsz_nt(int, struct winsize *);
|
||||
|
||||
|
@ -28,10 +31,22 @@ int ioctl_tiocgwinsz_nt(int, struct winsize *);
|
|||
*
|
||||
* @see ioctl(fd, TIOCGWINSZ, ws) dispatches here
|
||||
*/
|
||||
int ioctl_tiocgwinsz(int fd, struct winsize *ws) {
|
||||
if (!IsWindows()) {
|
||||
return sys_ioctl(fd, TIOCGWINSZ, ws);
|
||||
int ioctl_tiocgwinsz(int fd, ...) {
|
||||
va_list va;
|
||||
struct winsize *ws;
|
||||
va_start(va, fd);
|
||||
ws = va_arg(va, struct winsize *);
|
||||
va_end(va);
|
||||
if (IsAsan() && !__asan_is_valid(ws, sizeof(*ws))) return efault();
|
||||
if (fd >= 0) {
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
return enotty();
|
||||
} else if (!IsWindows()) {
|
||||
return sys_ioctl(fd, TIOCGWINSZ, ws);
|
||||
} else {
|
||||
return ioctl_tiocgwinsz_nt(fd, ws);
|
||||
}
|
||||
} else {
|
||||
return ioctl_tiocgwinsz_nt(fd, ws);
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,21 +17,36 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
int ioctl_tiocswinsz_nt(int, const struct winsize *);
|
||||
|
||||
/**
|
||||
* Returns width and height of terminal.
|
||||
* Sets width and height of terminal.
|
||||
*
|
||||
* @see ioctl(fd, TIOCSWINSZ, ws) dispatches here
|
||||
*/
|
||||
int ioctl_tiocswinsz(int fd, const struct winsize *ws) {
|
||||
if (!IsWindows()) {
|
||||
return sys_ioctl(fd, TIOCSWINSZ, ws);
|
||||
int ioctl_tiocswinsz(int fd, ...) {
|
||||
va_list va;
|
||||
const struct winsize *ws;
|
||||
va_start(va, fd);
|
||||
ws = va_arg(va, const struct winsize *);
|
||||
va_end(va);
|
||||
if (IsAsan() && !__asan_is_valid(ws, sizeof(*ws))) return efault();
|
||||
if (fd >= 0) {
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
return enotty();
|
||||
} else if (!IsWindows()) {
|
||||
return sys_ioctl(fd, TIOCSWINSZ, ws);
|
||||
} else {
|
||||
return ioctl_tiocswinsz_nt(fd, ws);
|
||||
}
|
||||
} else {
|
||||
return ioctl_tiocswinsz_nt(fd, ws);
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows bool32 sys_isatty_nt(int fd) {
|
||||
if (!__isfdkind(fd, kFdFile)) return ebadf();
|
||||
return GetFileType(g_fds.p[fd].handle) == kNtFileTypeChar;
|
||||
return __isfdkind(fd, kFdConsole) ||
|
||||
(__isfdkind(fd, kFdFile) &&
|
||||
GetFileType(g_fds.p[fd].handle) == kNtFileTypeChar);
|
||||
}
|
||||
|
|
|
@ -18,18 +18,30 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
|
||||
/**
|
||||
* Returns true if file descriptor is backed by a terminal device.
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
bool32 isatty(int fd) {
|
||||
_Alignas(short) char buf[sizeof(uint16_t) * 4];
|
||||
if (!IsWindows()) {
|
||||
return sys_ioctl(fd, TIOCGWINSZ, &buf) != -1;
|
||||
int err;
|
||||
bool32 res;
|
||||
struct winsize ws;
|
||||
if (fd >= 0) {
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
return false;
|
||||
} else if (!IsWindows()) {
|
||||
err = errno;
|
||||
res = sys_ioctl(fd, TIOCGWINSZ, &ws) != -1;
|
||||
errno = err;
|
||||
return res;
|
||||
} else {
|
||||
return sys_isatty_nt(fd);
|
||||
}
|
||||
} else {
|
||||
return sys_isatty_nt(fd);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,8 +21,10 @@
|
|||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Returns true if file exists and is a directory.
|
||||
|
@ -30,6 +32,7 @@
|
|||
bool isdirectory(const char *path) {
|
||||
struct stat st;
|
||||
int rc, olderr;
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
|
||||
if (!IsWindows()) {
|
||||
olderr = errno;
|
||||
rc = sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW);
|
||||
|
|
|
@ -21,7 +21,9 @@
|
|||
#include "libc/calls/struct/stat.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"
|
||||
|
||||
/**
|
||||
* Returns true if file exists and is a regular file.
|
||||
|
@ -29,6 +31,7 @@
|
|||
bool isregularfile(const char *path) {
|
||||
struct stat st;
|
||||
int rc, olderr;
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
|
||||
if (!IsWindows()) {
|
||||
olderr = errno;
|
||||
rc = sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW);
|
||||
|
|
27
libc/calls/isrunningundermake.c
Normal file
27
libc/calls/isrunningundermake.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
/**
|
||||
* Returns true if current process was spawned by GNU Make.
|
||||
*/
|
||||
bool IsRunningUnderMake(void) {
|
||||
return !!getenv("MAKEFLAGS");
|
||||
}
|
|
@ -21,8 +21,10 @@
|
|||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Returns true if file exists and is a symbolic link.
|
||||
|
@ -30,6 +32,7 @@
|
|||
bool issymlink(const char *path) {
|
||||
struct stat st;
|
||||
int rc, olderr;
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
|
||||
if (!IsWindows()) {
|
||||
olderr = errno;
|
||||
rc = sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW);
|
||||
|
|
|
@ -31,5 +31,5 @@
|
|||
* @see /etc/group for group ids
|
||||
*/
|
||||
int lchown(const char *pathname, uint32_t uid, uint32_t gid) {
|
||||
return sys_fchownat(AT_FDCWD, pathname, uid, gid, AT_SYMLINK_NOFOLLOW);
|
||||
return fchownat(AT_FDCWD, pathname, uid, gid, AT_SYMLINK_NOFOLLOW);
|
||||
}
|
||||
|
|
|
@ -32,9 +32,5 @@
|
|||
* @asyncsignalsafe
|
||||
*/
|
||||
int link(const char *existingpath, const char *newpath) {
|
||||
if (!IsWindows()) {
|
||||
return sys_linkat(AT_FDCWD, existingpath, AT_FDCWD, newpath, 0);
|
||||
} else {
|
||||
return sys_link_nt(existingpath, newpath);
|
||||
}
|
||||
return linkat(AT_FDCWD, existingpath, AT_FDCWD, newpath, 0);
|
||||
}
|
||||
|
|
|
@ -21,12 +21,13 @@
|
|||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
|
||||
textwindows int sys_link_nt(const char *existingpath, const char *newpath) {
|
||||
textwindows int sys_linkat_nt(int olddirfd, const char *oldpath, int newdirfd,
|
||||
const char *newpath) {
|
||||
char16_t newpath16[PATH_MAX];
|
||||
char16_t existingpath16[PATH_MAX];
|
||||
if (__mkntpath(existingpath, existingpath16) != -1 &&
|
||||
__mkntpath(newpath, newpath16) != -1) {
|
||||
if (CreateHardLink(newpath16, existingpath16, NULL)) {
|
||||
char16_t oldpath16[PATH_MAX];
|
||||
if (__mkntpathat(olddirfd, oldpath, 0, oldpath16) != -1 &&
|
||||
__mkntpathat(newdirfd, newpath, 0, newpath16) != -1) {
|
||||
if (CreateHardLink(newpath16, oldpath16, NULL)) {
|
||||
return 0;
|
||||
} else {
|
||||
return __winerr();
|
53
libc/calls/linkat.c
Normal file
53
libc/calls/linkat.c
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
/**
|
||||
* Creates hard filesystem link.
|
||||
*
|
||||
* This allows two names to point to the same file data on disk. They
|
||||
* can only be differentiated by examining the inode number.
|
||||
*
|
||||
* @param flags can have AT_EMPTY_PATH or AT_SYMLINK_NOFOLLOW
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int linkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath,
|
||||
int flags) {
|
||||
if (IsAsan() &&
|
||||
(!__asan_is_valid(oldpath, 1) || !__asan_is_valid(newpath, 1))) {
|
||||
return efault();
|
||||
}
|
||||
if (weaken(__zipos_notat) &&
|
||||
(weaken(__zipos_notat)(olddirfd, oldpath) == -1 ||
|
||||
weaken(__zipos_notat)(newdirfd, newpath) == -1)) {
|
||||
return -1; /* TODO(jart): implement me */
|
||||
}
|
||||
if (!IsWindows()) {
|
||||
return sys_linkat(olddirfd, oldpath, newdirfd, newpath, flags);
|
||||
} else {
|
||||
return sys_linkat_nt(olddirfd, oldpath, newdirfd, newpath);
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Drops hints to O/S about intended access patterns of mmap()'d memory.
|
||||
|
@ -29,6 +31,7 @@
|
|||
* @see fadvise()
|
||||
*/
|
||||
int madvise(void *addr, size_t length, int advice) {
|
||||
if (IsAsan() && !__asan_is_valid(addr, length)) return efault();
|
||||
if (!IsWindows()) {
|
||||
return sys_madvise(addr, length, advice);
|
||||
} else {
|
||||
|
|
|
@ -16,21 +16,19 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/sysv/consts/fio.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/calls/makedev.h"
|
||||
#include "libc/dce.h"
|
||||
|
||||
textwindows int ioctl_fioclex_nt(int fd, int req) {
|
||||
if (__isfdopen(fd)) {
|
||||
if (req == FIOCLEX) {
|
||||
g_fds.p[fd].flags |= O_CLOEXEC;
|
||||
} else {
|
||||
g_fds.p[fd].flags &= ~O_CLOEXEC;
|
||||
}
|
||||
return 0;
|
||||
uint32_t(major)(uint64_t x) {
|
||||
if (IsXnu()) {
|
||||
return (x >> 24) & 0xff;
|
||||
} else if (IsNetbsd()) {
|
||||
return (x & 0x000fff00) >> 8;
|
||||
} else if (IsOpenbsd()) {
|
||||
return (x >> 8) & 0xff;
|
||||
} else if (IsFreebsd()) {
|
||||
return ((x >> 32) & 0xffffff00) | ((x >> 8) & 0x000000ff);
|
||||
} else {
|
||||
return ebadf();
|
||||
return ((x >> 32) & 0xfffff000) | ((x >> 8) & 0x00000fff);
|
||||
}
|
||||
}
|
37
libc/calls/makedev.c
Normal file
37
libc/calls/makedev.c
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/makedev.h"
|
||||
#include "libc/dce.h"
|
||||
|
||||
uint64_t(makedev)(uint32_t x, uint32_t y) {
|
||||
if (IsXnu()) {
|
||||
return x << 24 | y;
|
||||
} else if (IsNetbsd()) {
|
||||
return ((x << 8) & 0x000fff00) | ((y << 12) & 0xfff00000) |
|
||||
(y & 0x000000ff);
|
||||
} else if (IsOpenbsd()) {
|
||||
return (x & 0xff) << 8 | (y & 0xff) | (y & 0xffff00) << 8;
|
||||
} else if (IsFreebsd()) {
|
||||
return (uint64_t)(x & 0xffffff00) << 32 | (x & 0x000000ff) << 8 |
|
||||
(y & 0x0000ff00) << 24 | (y & 0xffff00ff);
|
||||
} else {
|
||||
return (uint64_t)(x & 0xfffff000) << 32 | (x & 0x00000fff) << 8 |
|
||||
(y & 0xffffff00) << 12 | (y & 0x000000ff);
|
||||
}
|
||||
}
|
|
@ -1,52 +1,10 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_MAKEDEV_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_MAKEDEV_H_
|
||||
#include "libc/dce.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
static inline uint64_t major(uint64_t x) {
|
||||
if (IsXnu()) {
|
||||
return (x >> 24) & 0xff;
|
||||
} else if (IsNetbsd()) {
|
||||
return (x & 0x000fff00) >> 8;
|
||||
} else if (IsOpenbsd()) {
|
||||
return (x >> 8) & 0xff;
|
||||
} else if (IsFreebsd()) {
|
||||
return ((x >> 32) & 0xffffff00) | ((x >> 8) & 0x000000ff);
|
||||
} else {
|
||||
return ((x >> 32) & 0xfffff000) | ((x >> 8) & 0x00000fff);
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint64_t minor(uint64_t x) {
|
||||
if (IsXnu()) {
|
||||
return x & 0x00ffffff;
|
||||
} else if (IsNetbsd()) {
|
||||
return (x & 0x000000ff) | (x & 0xfff00000) >> 12;
|
||||
} else if (IsOpenbsd()) {
|
||||
return (x & 0x000000ff) | (x & 0x0ffff000) >> 8;
|
||||
} else if (IsFreebsd()) {
|
||||
return ((x >> 24) & 0x0000ff00) | (x & 0xffff00ff);
|
||||
} else {
|
||||
return ((x >> 12) & 0xffffff00) | (x & 0x000000ff);
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint64_t makedev(uint64_t x, uint64_t y) {
|
||||
if (IsXnu()) {
|
||||
return x << 24 | y;
|
||||
} else if (IsNetbsd()) {
|
||||
return ((x << 8) & 0x000fff00) | ((y << 12) & 0xfff00000u) |
|
||||
(y & 0x000000ff);
|
||||
} else if (IsOpenbsd()) {
|
||||
return (x & 0xff) << 8 | (y & 0xff) | (y & 0xffff00) << 8;
|
||||
} else if (IsFreebsd()) {
|
||||
return (x & 0xffffff00) << 32 | (x & 0x000000ff) << 8 |
|
||||
(y & 0x0000ff00) << 24 | (y & 0xffff00ff);
|
||||
} else {
|
||||
return (x & 0xfffff000) << 32 | (x & 0x00000fff) << 8 |
|
||||
(y & 0xffffff00) << 12 | (y & 0x000000ff);
|
||||
}
|
||||
}
|
||||
uint64_t makedev(uint32_t, uint32_t);
|
||||
uint32_t major(uint64_t);
|
||||
uint32_t minor(uint64_t);
|
||||
|
||||
#define major(x) major(x)
|
||||
#define minor(x) minor(x)
|
||||
|
|
34
libc/calls/minor.c
Normal file
34
libc/calls/minor.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*-*- 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/makedev.h"
|
||||
#include "libc/dce.h"
|
||||
|
||||
uint32_t(minor)(uint64_t x) {
|
||||
if (IsXnu()) {
|
||||
return x & 0x00ffffff;
|
||||
} else if (IsNetbsd()) {
|
||||
return (x & 0x000000ff) | (x & 0xfff00000) >> 12;
|
||||
} else if (IsOpenbsd()) {
|
||||
return (x & 0x000000ff) | (x & 0x0ffff000) >> 8;
|
||||
} else if (IsFreebsd()) {
|
||||
return ((x >> 24) & 0x0000ff00) | (x & 0xffff00ff);
|
||||
} else {
|
||||
return ((x >> 12) & 0xffffff00) | (x & 0x000000ff);
|
||||
}
|
||||
}
|
|
@ -16,10 +16,14 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
/**
|
||||
* Creates directory a.k.a. folder.
|
||||
|
@ -34,6 +38,10 @@
|
|||
* @see makedirs()
|
||||
*/
|
||||
int mkdirat(int dirfd, const char *path, unsigned mode) {
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
|
||||
if (weaken(__zipos_notat) && weaken(__zipos_notat)(dirfd, path) == -1) {
|
||||
return -1; /* TODO(jart): implement me */
|
||||
}
|
||||
if (!IsWindows()) {
|
||||
return sys_mkdirat(dirfd, path, mode);
|
||||
} else {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/nt/ipc.h"
|
||||
#include "libc/sysv/consts/s.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
@ -33,6 +34,7 @@
|
|||
*/
|
||||
int mkfifo(const char *pathname, unsigned mode) {
|
||||
/* TODO(jart): Windows? */
|
||||
if (IsAsan() && !__asan_is_valid(pathname, 1)) return efault();
|
||||
if (IsLinux()) {
|
||||
return sys_mknod(pathname, mode | S_IFIFO, 0);
|
||||
} else {
|
||||
|
|
|
@ -16,11 +16,12 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/consts/s.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Creates filesystem inode.
|
||||
|
@ -37,6 +38,7 @@
|
|||
* @asyncsignalsafe
|
||||
*/
|
||||
int mknod(const char *path, uint32_t mode, uint64_t dev) {
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
|
||||
if (mode & S_IFREG) return creat(path, mode & ~S_IFREG);
|
||||
if (mode & S_IFDIR) return mkdir(path, mode & ~S_IFDIR);
|
||||
if (mode & S_IFIFO) return mkfifo(path, mode & ~S_IFIFO);
|
||||
|
|
|
@ -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/mem/mem.h"
|
||||
#include "libc/nt/enum/accessmask.h"
|
||||
#include "libc/nt/enum/securityimpersonationlevel.h"
|
||||
#include "libc/nt/enum/securityinformation.h"
|
||||
|
@ -30,6 +32,13 @@
|
|||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#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.
|
||||
|
@ -44,19 +53,20 @@
|
|||
* @see libc/sysv/consts.sh
|
||||
*/
|
||||
textwindows int ntaccesscheck(const char16_t *pathname, uint32_t flags) {
|
||||
int rc;
|
||||
int rc, e;
|
||||
void *freeme;
|
||||
bool32 result;
|
||||
struct NtSecurityDescriptor *s;
|
||||
struct NtGenericMapping mapping;
|
||||
struct NtPrivilegeSet privileges;
|
||||
int64_t hToken, hImpersonatedToken;
|
||||
uint32_t secsize, granted, privsize;
|
||||
union NtSecurityDescriptorLol {
|
||||
struct NtSecurityDescriptor s;
|
||||
char b[1024];
|
||||
} security;
|
||||
intptr_t buffer[1024 / sizeof(intptr_t)];
|
||||
freeme = 0;
|
||||
granted = 0;
|
||||
result = false;
|
||||
secsize = sizeof(security);
|
||||
s = (void *)buffer;
|
||||
secsize = sizeof(buffer);
|
||||
privsize = sizeof(privileges);
|
||||
memset(&privileges, 0, sizeof(privileges));
|
||||
mapping.GenericRead = kNtFileGenericRead;
|
||||
|
@ -65,24 +75,55 @@ textwindows int ntaccesscheck(const char16_t *pathname, uint32_t flags) {
|
|||
mapping.GenericAll = kNtFileAllAccess;
|
||||
MapGenericMask(&flags, &mapping);
|
||||
hImpersonatedToken = hToken = -1;
|
||||
TryAgain:
|
||||
if (GetFileSecurity(pathname,
|
||||
kNtOwnerSecurityInformation |
|
||||
kNtGroupSecurityInformation |
|
||||
kNtDaclSecurityInformation,
|
||||
&security.s, 0, &secsize) &&
|
||||
OpenProcessToken(GetCurrentProcess(),
|
||||
kNtTokenImpersonate | kNtTokenQuery | kNtTokenDuplicate |
|
||||
kNtStandardRightsRead,
|
||||
&hToken) &&
|
||||
DuplicateToken(hToken, kNtSecurityImpersonation, &hImpersonatedToken) &&
|
||||
AccessCheck(&security.s, hImpersonatedToken, flags, &mapping, &privileges,
|
||||
&privsize, &granted, &result) &&
|
||||
(result || flags == F_OK)) {
|
||||
rc = 0;
|
||||
s, secsize, &secsize)) {
|
||||
if (OpenProcessToken(GetCurrentProcess(),
|
||||
kNtTokenImpersonate | kNtTokenQuery |
|
||||
kNtTokenDuplicate | kNtStandardRightsRead,
|
||||
&hToken)) {
|
||||
if (DuplicateToken(hToken, kNtSecurityImpersonation,
|
||||
&hImpersonatedToken)) {
|
||||
if (AccessCheck(s, hImpersonatedToken, flags, &mapping, &privileges,
|
||||
&privsize, &granted, &result)) {
|
||||
if (result || flags == F_OK) {
|
||||
rc = 0;
|
||||
} else {
|
||||
DEBUG("ntaccesscheck finale failed %d %d", result, flags);
|
||||
rc = eacces();
|
||||
}
|
||||
} else {
|
||||
rc = __winerr();
|
||||
DEBUG("AccessCheck failed: %m");
|
||||
}
|
||||
} else {
|
||||
rc = __winerr();
|
||||
DEBUG("DuplicateToken failed: %m");
|
||||
}
|
||||
} else {
|
||||
rc = __winerr();
|
||||
DEBUG("OpenProcessToken failed: %m");
|
||||
}
|
||||
} else {
|
||||
rc = __winerr();
|
||||
e = GetLastError();
|
||||
DEBUG("GetFileSecurity failed: %d %d", e, secsize);
|
||||
if (!IsTiny() && e == kNtErrorInsufficientBuffer) {
|
||||
if (!freeme && weaken(malloc) && (freeme = weaken(malloc)(secsize))) {
|
||||
s = freeme;
|
||||
goto TryAgain;
|
||||
} else {
|
||||
rc = enomem();
|
||||
}
|
||||
} else {
|
||||
errno = e;
|
||||
rc = -1;
|
||||
}
|
||||
}
|
||||
close(hImpersonatedToken);
|
||||
close(hToken);
|
||||
if (freeme && weaken(free)) weaken(free)(freeme);
|
||||
if (hImpersonatedToken != -1) CloseHandle(hImpersonatedToken);
|
||||
if (hToken != -1) CloseHandle(hToken);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
@ -43,13 +45,19 @@ 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);
|
||||
if (!file) return efault();
|
||||
if (IsAsan() && !__asan_is_valid(file, 1)) return efault();
|
||||
if (__isfdkind(dirfd, kFdZip)) return einval(); /* TODO(jart): implement me */
|
||||
if (weaken(__zipos_open) && weaken(__zipos_parseuri)(file, &zipname) != -1) {
|
||||
if (__vforked) return einval();
|
||||
if (dirfd != AT_FDCWD) return einval();
|
||||
if (__vforked) return eopnotsupp();
|
||||
if (dirfd != AT_FDCWD) return eopnotsupp();
|
||||
return weaken(__zipos_open)(&zipname, flags, mode);
|
||||
} else if (!IsWindows() && !IsMetal()) {
|
||||
return sys_openat(dirfd, file, flags, mode);
|
||||
|
|
|
@ -22,11 +22,13 @@
|
|||
#include "libc/nt/enum/creationdisposition.h"
|
||||
#include "libc/nt/ipc.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int sys_pipe_nt(int pipefd[2], unsigned flags) {
|
||||
int64_t hin, hout;
|
||||
int reader, writer;
|
||||
char16_t pipename[64];
|
||||
if (!pipefd) return efault();
|
||||
CreatePipeName(pipename);
|
||||
if ((reader = __reservefd()) == -1) return -1;
|
||||
if ((writer = __reservefd()) == -1) {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
|
@ -30,7 +31,7 @@
|
|||
* @see pipe2()
|
||||
*/
|
||||
int pipe(int pipefd[hasatleast 2]) {
|
||||
if (!pipefd) return efault();
|
||||
if (IsAsan() && !__asan_is_valid(pipefd, sizeof(int) * 2)) return efault();
|
||||
if (!IsWindows()) {
|
||||
return sys_pipe(pipefd);
|
||||
} else {
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
|
@ -28,6 +30,7 @@
|
|||
*/
|
||||
int pipe2(int pipefd[hasatleast 2], int flags) {
|
||||
if (!pipefd) return efault();
|
||||
if (IsAsan() && !__asan_is_valid(pipefd, sizeof(int) * 2)) return efault();
|
||||
if (!IsWindows()) {
|
||||
return sys_pipe2(pipefd, flags);
|
||||
} 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/struct/iovec.h"
|
||||
#include "libc/sock/sock.h"
|
||||
|
||||
|
|
|
@ -60,13 +60,14 @@
|
|||
* @see ECMA-48
|
||||
*/
|
||||
ssize_t readansi(int fd, char *buf, size_t size) {
|
||||
int i, j;
|
||||
wint_t x;
|
||||
uint8_t c;
|
||||
int i, j, rc;
|
||||
enum { kAscii, kUtf8, kEsc, kCsi, kSs } t;
|
||||
if (size) buf[0] = 0;
|
||||
for (j = i = 0, t = kAscii;;) {
|
||||
if (i + 2 >= size) return enomem();
|
||||
if (read(fd, &c, 1) != 1) return -1;
|
||||
if ((rc = read(fd, &c, 1)) != 1) return rc;
|
||||
buf[i++] = c;
|
||||
buf[i] = 0;
|
||||
switch (t) {
|
||||
|
@ -79,11 +80,24 @@ ssize_t readansi(int fd, char *buf, size_t size) {
|
|||
}
|
||||
} else if (c >= 0300) {
|
||||
t = kUtf8;
|
||||
x = ThomPikeByte(c);
|
||||
j = ThomPikeLen(c) - 1;
|
||||
}
|
||||
break;
|
||||
case kUtf8:
|
||||
if (!--j) return i;
|
||||
x = ThomPikeMerge(x, c);
|
||||
if (!--j) {
|
||||
switch (x) {
|
||||
case '\e':
|
||||
t = kEsc;
|
||||
break;
|
||||
case 0x9b:
|
||||
t = kCsi;
|
||||
break;
|
||||
default:
|
||||
return i;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case kEsc:
|
||||
switch (c) {
|
||||
|
|
|
@ -37,11 +37,12 @@
|
|||
|
||||
static textwindows ssize_t sys_readlinkat_nt_error(void) {
|
||||
uint32_t e;
|
||||
if ((e = GetLastError()) == kNtErrorNotAReparsePoint) {
|
||||
return einval();
|
||||
} else {
|
||||
errno = e;
|
||||
return -1;
|
||||
switch ((e = GetLastError())) {
|
||||
case kNtErrorNotAReparsePoint:
|
||||
return einval();
|
||||
default:
|
||||
errno = e;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,6 +56,7 @@ textwindows ssize_t sys_readlinkat_nt(int dirfd, const char *path, char *buf,
|
|||
uint32_t e, i, j, n, mem;
|
||||
char16_t path16[PATH_MAX], *p;
|
||||
struct NtReparseDataBuffer *rdb;
|
||||
if (!buf) return efault();
|
||||
if (weaken(malloc)) {
|
||||
mem = 16384;
|
||||
rdb = weaken(malloc)(mem);
|
||||
|
|
|
@ -48,8 +48,8 @@
|
|||
ssize_t readlinkat(int dirfd, const char *path, char *buf, size_t bufsiz) {
|
||||
struct ZiposUri zipname;
|
||||
if (IsAsan() && !__asan_is_valid(buf, bufsiz)) return efault();
|
||||
if (weaken(__zipos_open) && weaken(__zipos_parseuri)(path, &zipname) != -1) {
|
||||
return einval();
|
||||
if (weaken(__zipos_notat) && __zipos_notat(dirfd, path) == -1) {
|
||||
return -1; /* TODO(jart): code me */
|
||||
}
|
||||
if (!IsWindows()) {
|
||||
return sys_readlinkat(dirfd, path, buf, bufsiz);
|
||||
|
|
|
@ -90,8 +90,8 @@ char *realpath(const char *filename, char *resolved)
|
|||
return 0;
|
||||
}
|
||||
if (l >= PATH_MAX) goto toolong;
|
||||
if (l > 4 && (READ32LE(filename) == READ32LE("zip:") ||
|
||||
READ32LE(filename) == READ32LE("zip!"))) {
|
||||
if (l >= 4 && READ32LE(filename) == READ32LE("/zip") &&
|
||||
(!filename[4] || filename[4] == '/')) {
|
||||
return ResolvePath(resolved, filename, l);
|
||||
}
|
||||
p = sizeof stack - l - 1;
|
||||
|
|
|
@ -16,10 +16,14 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
/**
|
||||
* Renames files relative to directories.
|
||||
|
@ -32,6 +36,15 @@
|
|||
*/
|
||||
int renameat(int olddirfd, const char *oldpath, int newdirfd,
|
||||
const char *newpath) {
|
||||
if (IsAsan() &&
|
||||
(!__asan_is_valid(oldpath, 1) || !__asan_is_valid(newpath, 1))) {
|
||||
return efault();
|
||||
}
|
||||
if (weaken(__zipos_notat) &&
|
||||
(weaken(__zipos_notat)(olddirfd, oldpath) == -1 ||
|
||||
weaken(__zipos_notat)(newdirfd, newpath) == -1)) {
|
||||
return -1; /* TODO(jart): implement me */
|
||||
}
|
||||
if (!IsWindows()) {
|
||||
return sys_renameat(olddirfd, oldpath, newdirfd, newpath);
|
||||
} else {
|
||||
|
|
|
@ -61,7 +61,7 @@ static uint32_t ItimerWorker(void *arg) {
|
|||
}
|
||||
|
||||
textwindows int sys_setitimer_nt(int which, const struct itimerval *newvalue,
|
||||
struct itimerval *out_opt_oldvalue) {
|
||||
struct itimerval *out_opt_oldvalue) {
|
||||
int32_t period;
|
||||
int64_t ith, duetime;
|
||||
if (which != ITIMER_REAL) return einval();
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/itimerval.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
|
@ -62,14 +63,19 @@
|
|||
* @return 0 on success or -1 w/ errno
|
||||
*/
|
||||
int setitimer(int which, const struct itimerval *newvalue,
|
||||
struct itimerval *out_opt_oldvalue) {
|
||||
struct itimerval *oldvalue) {
|
||||
if (IsAsan() &&
|
||||
((newvalue && !__asan_is_valid(newvalue, sizeof(*newvalue))) ||
|
||||
(oldvalue && !__asan_is_valid(oldvalue, sizeof(*oldvalue))))) {
|
||||
return efault();
|
||||
}
|
||||
if (!IsWindows()) {
|
||||
if (newvalue) {
|
||||
return sys_setitimer(which, newvalue, out_opt_oldvalue);
|
||||
return sys_setitimer(which, newvalue, oldvalue);
|
||||
} else {
|
||||
return sys_getitimer(which, out_opt_oldvalue);
|
||||
return sys_getitimer(which, oldvalue);
|
||||
}
|
||||
} else {
|
||||
return sys_setitimer_nt(which, newvalue, out_opt_oldvalue);
|
||||
return sys_setitimer_nt(which, newvalue, oldvalue);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
|
@ -31,9 +33,6 @@
|
|||
*/
|
||||
int setrlimit(int resource, const struct rlimit *rlim) {
|
||||
if (resource == 127) return einval();
|
||||
if (!IsWindows()) {
|
||||
return sys_setrlimit(resource, rlim);
|
||||
} else {
|
||||
return enosys(); /* TODO(jart): Implement me! */
|
||||
}
|
||||
if (IsAsan() && !__asan_is_valid(rlim, sizeof(*rlim))) return efault();
|
||||
return sys_setrlimit(resource, rlim);
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "libc/calls/typedef/sigaction_f.h"
|
||||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
|
@ -141,18 +142,23 @@ static void sigaction_native2cosmo(union metasigaction *sa) {
|
|||
* @vforksafe
|
||||
*/
|
||||
int(sigaction)(int sig, const struct sigaction *act, struct sigaction *oldact) {
|
||||
_Static_assert((sizeof(struct sigaction) > sizeof(struct sigaction_linux) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction_xnu_in) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction_xnu_out) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction_freebsd) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction_openbsd) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction_netbsd)),
|
||||
"sigaction cosmo abi needs tuning");
|
||||
int64_t arg4, arg5;
|
||||
int rc, rva, oldrva;
|
||||
struct sigaction *ap, copy;
|
||||
assert(sizeof(struct sigaction) > sizeof(struct sigaction_linux) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction_xnu_in) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction_xnu_out) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction_freebsd) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction_openbsd) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction_netbsd));
|
||||
if (IsMetal()) return enosys(); /* TODO: Signals on Metal */
|
||||
if (!(0 < sig && sig < NSIG)) return einval();
|
||||
if (sig == SIGKILL || sig == SIGSTOP) return einval();
|
||||
if (IsAsan() && ((act && !__asan_is_valid(act, sizeof(*act))) ||
|
||||
(oldact && !__asan_is_valid(oldact, sizeof(*oldact))))) {
|
||||
return efault();
|
||||
}
|
||||
if (!act) {
|
||||
rva = (int32_t)(intptr_t)SIG_DFL;
|
||||
} else if ((intptr_t)act->sa_handler < kSigactionMinRva) {
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
|
@ -40,6 +41,12 @@
|
|||
*/
|
||||
int sigprocmask(int how, const sigset_t *opt_set, sigset_t *opt_out_oldset) {
|
||||
int32_t x;
|
||||
if (IsAsan() &&
|
||||
((opt_set && !__asan_is_valid(opt_set, sizeof(*opt_set))) ||
|
||||
(opt_out_oldset &&
|
||||
!__asan_is_valid(opt_out_oldset, sizeof(*opt_out_oldset))))) {
|
||||
return efault();
|
||||
}
|
||||
if (!IsWindows() && !IsOpenbsd()) {
|
||||
return sys_sigprocmask(how, opt_set, opt_out_oldset, 8);
|
||||
} else if (IsOpenbsd()) {
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
|
@ -31,6 +32,7 @@
|
|||
*/
|
||||
int sigsuspend(const sigset_t *ignore) {
|
||||
unsigned x;
|
||||
if (IsAsan() && !__asan_is_valid(ignore, sizeof(*ignore))) return efault();
|
||||
if (!IsWindows()) {
|
||||
if (IsOpenbsd()) ignore = (sigset_t *)(uintptr_t)(*(uint32_t *)ignore);
|
||||
return sys_sigsuspend(ignore, 8);
|
||||
|
|
|
@ -19,7 +19,9 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Creates symbolic link.
|
||||
|
@ -35,6 +37,10 @@
|
|||
* @asyncsignalsafe
|
||||
*/
|
||||
int symlinkat(const char *target, int newdirfd, const char *linkpath) {
|
||||
if (IsAsan() &&
|
||||
(!__asan_is_valid(target, 1) || !__asan_is_valid(linkpath, 1))) {
|
||||
return efault();
|
||||
}
|
||||
if (!IsWindows()) {
|
||||
return sys_symlinkat(target, newdirfd, linkpath);
|
||||
} else {
|
||||
|
|
|
@ -17,10 +17,29 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/termios.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Changes flow of teletypewriter data.
|
||||
*
|
||||
* - `TCOOFF` suspends output
|
||||
* - `TCOON` resumes output
|
||||
* - `TCIOFF` transmits a STOP character
|
||||
* - `TCION` transmits a START character
|
||||
*/
|
||||
int tcflow(int fd, int action) {
|
||||
/* TODO(jart): BSD support */
|
||||
return sys_ioctl(fd, TCXONC, (void *)(intptr_t)action);
|
||||
uint8_t c;
|
||||
struct termios t;
|
||||
if (!IsBsd()) return sys_ioctl(fd, TCXONC, action);
|
||||
if (action == TCOOFF) return sys_ioctl(fd, TIOCSTOP, 0);
|
||||
if (action == TCOON) return sys_ioctl(fd, TIOCSTART, 0);
|
||||
if (action != TCIOFF && action != TCION) return einval();
|
||||
if (tcgetattr(fd, &t) == -1) return -1;
|
||||
if ((c = t.c_cc[action == TCIOFF ? VSTOP : VSTART]) != 255) {
|
||||
if (sys_write(fd, &c, 1) == -1) return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -18,9 +18,15 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
|
||||
int tcflush(int fd, int x) {
|
||||
/* TODO(jart): BSD Support */
|
||||
return sys_ioctl(fd, TCFLSH, x);
|
||||
/**
|
||||
* Flushes teletypewriter data.
|
||||
*
|
||||
* - `TCIFLUSH` flushes data received but not read
|
||||
* - `TCOFLUSH` flushes data written but not transmitted
|
||||
* - `TCIOFLUSH` does both `TCOFLUSH` and `TCIFLUSH`
|
||||
*/
|
||||
int tcflush(int fd, int queue) {
|
||||
/* TODO(jart): Windows? */
|
||||
return sys_ioctl(fd, TCFLSH, queue);
|
||||
}
|
||||
|
|
|
@ -16,10 +16,14 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
/**
|
||||
* Deletes inode and maybe the file too.
|
||||
|
@ -31,6 +35,10 @@
|
|||
* @return 0 on success, or -1 w/ errno
|
||||
*/
|
||||
int unlinkat(int dirfd, const char *path, int flags) {
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
|
||||
if (weaken(__zipos_notat) && weaken(__zipos_notat)(dirfd, path) == -1) {
|
||||
return -1; /* TODO(jart): implement me */
|
||||
}
|
||||
if (!IsWindows()) {
|
||||
return sys_unlinkat(dirfd, path, flags);
|
||||
} else {
|
||||
|
|
|
@ -16,10 +16,12 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/time/time.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
#define __NR_utimensat_linux 0x118 /*RHEL5:CVE-2010-3301*/
|
||||
|
||||
|
@ -27,6 +29,9 @@ int sys_utimensat(int dirfd, const char *path, const struct timespec ts[2],
|
|||
int flags) {
|
||||
int rc, olderr;
|
||||
struct timeval tv[2];
|
||||
if (weaken(__zipos_notat) && weaken(__zipos_notat)(dirfd, path) == -1) {
|
||||
return -1; /* TODO(jart): implement me */
|
||||
}
|
||||
if (!IsXnu()) {
|
||||
olderr = errno;
|
||||
rc = __sys_utimensat(dirfd, path, ts, flags);
|
||||
|
|
|
@ -16,8 +16,13 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
/**
|
||||
* Sets atime/mtime on file, the modern way.
|
||||
|
@ -29,6 +34,13 @@
|
|||
*/
|
||||
int utimensat(int dirfd, const char *path, const struct timespec ts[2],
|
||||
int flags) {
|
||||
if (IsAsan() && (!__asan_is_valid(path, 1) ||
|
||||
(ts && !__asan_is_valid(ts, sizeof(struct timespec) * 2)))) {
|
||||
return efault();
|
||||
}
|
||||
if (weaken(__zipos_notat) && weaken(__zipos_notat)(dirfd, path) == -1) {
|
||||
return -1; /* TODO(jart): implement me */
|
||||
}
|
||||
if (!IsWindows()) {
|
||||
return sys_utimensat(dirfd, path, ts, flags);
|
||||
} else {
|
||||
|
|
|
@ -37,15 +37,12 @@
|
|||
*/
|
||||
int wait4(int pid, int *opt_out_wstatus, int options,
|
||||
struct rusage *opt_out_rusage) {
|
||||
if (IsAsan()) {
|
||||
if (opt_out_wstatus &&
|
||||
!__asan_is_valid(opt_out_wstatus, sizeof(*opt_out_wstatus))) {
|
||||
return efault();
|
||||
}
|
||||
if (opt_out_rusage &&
|
||||
!__asan_is_valid(opt_out_rusage, sizeof(*opt_out_rusage))) {
|
||||
return efault();
|
||||
}
|
||||
if (IsAsan() &&
|
||||
((opt_out_wstatus &&
|
||||
!__asan_is_valid(opt_out_wstatus, sizeof(*opt_out_wstatus))) ||
|
||||
(opt_out_rusage &&
|
||||
!__asan_is_valid(opt_out_rusage, sizeof(*opt_out_rusage))))) {
|
||||
return efault();
|
||||
}
|
||||
if (!IsWindows()) {
|
||||
return sys_wait4(pid, opt_out_wstatus, options, opt_out_rusage);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue