Initial import

This commit is contained in:
Justine Tunney 2020-06-15 07:18:57 -07:00
commit c91b3c5006
14915 changed files with 590219 additions and 0 deletions

56
libc/calls/atfork.c Normal file
View file

@ -0,0 +1,56 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/calls/internal.h"
#include "libc/macros.h"
#include "libc/runtime/internal.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/errfuns.h"
static struct AtFork {
size_t i;
struct AtForkCallback {
void (*fn)(void *);
void *arg;
} p[ATEXIT_MAX];
} g_atfork;
/**
* Registers function to be called when PID changes.
*
* @return 0 on success, or -1 w/ errno
*/
int atfork(void *fn, void *arg) {
if (g_atfork.i == ARRAYLEN(g_atfork.p)) return enomem();
g_atfork.p[g_atfork.i++] = (struct AtForkCallback){.fn = fn, .arg = arg};
return 0;
}
/**
* Triggers atfork() callbacks.
*
* Only fork() should call this.
*/
void __onfork(void) {
size_t i;
for (i = 0; i < g_atfork.i; ++i) {
g_atfork.p[i].fn(g_atfork.p[i].arg);
}
}

292
libc/calls/calls.h Normal file
View file

@ -0,0 +1,292 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_SYSCALLS_H_
#define COSMOPOLITAN_LIBC_CALLS_SYSCALLS_H_
#include "libc/calls/struct/timespec.h"
#include "libc/calls/typedef/sighandler_t.h"
#include "libc/dce.h"
#include "libc/fmt/pflink.h"
#include "libc/sysv/consts/s.h"
#include "libc/sysv/consts/sig.h"
#define EOF -1 /* end of file */
#define WEOF -1u /* end of file (multibyte) */
#define _IOFBF 0 /* fully buffered */
#define _IOLBF 1 /* line buffered */
#define _IONBF 2 /* no buffering */
#define SEEK_SET 0 /* relative to beginning */
#define SEEK_CUR 1 /* relative to current position */
#define SEEK_END 2 /* relative to end */
#define SIG_ERR ((void (*)(int))(-1))
#define SIG_DFL ((void *)0)
#define SIG_IGN ((void *)1)
#define MAP_FAILED ((void *)__SIZE_MAX__)
#define ARCH_SET_GS 0x1001
#define ARCH_SET_FS 0x1002
#define ARCH_GET_FS 0x1003
#define ARCH_GET_GS 0x1004
#define MAP_HUGE_2MB (21 << MAP_HUGE_SHIFT)
#define MAP_HUGE_1GB (30 << MAP_HUGE_SHIFT)
#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
#define S_ISCHR(mode) (((mode)&S_IFMT) == S_IFCHR)
#define S_ISBLK(mode) (((mode)&S_IFMT) == S_IFBLK)
#define S_ISREG(mode) (((mode)&S_IFMT) == S_IFREG)
#define S_ISFIFO(mode) (((mode)&S_IFMT) == S_IFIFO)
#define S_ISLNK(mode) (((mode)&S_IFMT) == S_IFLNK)
#define S_ISSOCK(mode) (((mode)&S_IFMT) == S_IFSOCK)
#define WCOREDUMP(s) ((s)&0x80)
#define WEXITSTATUS(s) (((s)&0xff00) >> 8)
#define WIFCONTINUED(s) ((s) == 0xffff)
#define WIFEXITED(s) (!WTERMSIG(s))
#define WIFSIGNALED(s) (((s)&0xffff) - 1U < 0xffu)
#define WIFSTOPPED(s) ((short)((((s)&0xffff) * 0x10001) >> 8) > 0x7f00)
#define WSTOPSIG(s) WEXITSTATUS(s)
#define WTERMSIG(s) ((s)&0x7f)
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § system calls
*/
struct dirstream;
struct iovec;
struct rlimit;
struct rusage;
struct sigaction;
struct siginfo;
struct sigset;
struct stat;
struct sysinfo;
struct tms;
struct ucontext;
struct utsname;
typedef int sig_atomic_t;
typedef struct dirstream DIR;
extern const struct sigset kSigsetFull;
extern const struct sigset kSigsetEmpty;
DIR *fdopendir(int) nodiscard;
DIR *opendir(const char *) nodiscard;
bool fileexists(const char *);
bool isdirectory(const char *);
bool isexecutable(const char *);
bool isregularfile(const char *);
bool32 isatty(int) nosideeffect;
bool32 ischardev(int) nosideeffect;
char *get_current_dir_name(void) nodiscard;
char *getcwd(char *, size_t) paramsnonnull();
char *realpath(const char *, char *);
char *replaceuser(const char *) nodiscard;
char *slurp(const char *, size_t *) nodiscard;
char *ttyname(int);
const char *commandv(const char *);
int access(const char *, int) nothrow paramsnonnull();
int arch_prctl();
int chdir(const char *) paramsnonnull();
int chmod(const char *, uint32_t);
int chown(const char *, uint32_t, uint32_t) paramsnonnull();
int close(int);
int closedir(DIR *);
int copyfile(const char *, const char *, bool);
int creat(const char *, uint32_t) nodiscard;
int dirfd(DIR *);
int dup(int) nodiscard;
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 faccessat(int, const char *, int, uint32_t);
int fadvise(int, uint64_t, uint64_t, int);
int fallocate(int, int32_t, int64_t, int64_t);
int fchmod(int, uint32_t) nothrow;
int fchmodat(int, const char *, uint32_t, uint32_t);
int fchown(int, uint32_t, uint32_t);
int fchownat(int, const char *, uint32_t, uint32_t, uint32_t);
int fcntl();
int fdatasync(int);
int filecmp(const char *, const char *);
int flock(int, int);
int fork(void);
int fstat(int, struct stat *) paramsnonnull();
int fstatat(int, const char *, struct stat *, uint32_t);
int fsync(int);
int ftruncate(int, int64_t);
int getppid(void);
int getpriority(int, unsigned);
int getrlimit(int, struct rlimit *);
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 lstat(const char *, struct stat *) paramsnonnull();
int madvise(void *, uint64_t, int);
int mkdir(const char *, uint32_t);
int mkdirat(int, const char *, uint32_t);
int mkfifo(const char *, uint32_t);
int mknod(const char *, uint32_t, uint64_t);
int mknodat(int, const char *, int32_t, uint64_t);
int mlock(const void *, size_t);
int mlock2(const void *, size_t, int);
int mlockall(int);
int mprotect(void *, uint64_t, int) paramsnonnull() privileged;
int msync(void *, size_t, int);
int munlock(const void *, size_t);
int munlockall(void);
int munmap(void *, uint64_t);
int munmap_s(void *, uint64_t);
int nice(int);
int open(const char *, int, ...) nodiscard;
int openanon(char *, unsigned) nodiscard;
int openat();
int pause(void);
int personality(uint64_t);
int pipe(int[hasatleast 2]) paramsnonnull() nodiscard;
int pipe2(int[hasatleast 2], int) paramsnonnull() nodiscard;
int posix_fadvise(int, uint64_t, uint64_t, int);
int posix_fallocate(int, int64_t, int64_t);
int posix_madvise(void *, uint64_t, int);
int raise(int);
int readlink(const char *, char *, size_t);
int remove(const char *);
int rename(const char *, const char *);
int renameat(int, const char *, int, const char *);
int renameat2(long, const char *, long, const char *, int);
int rmdir(const char *);
int sched_getaffinity(int, uint64_t, void *);
int sched_setaffinity(int, uint64_t, const void *);
int sched_yield(void);
int setpgid(int, int);
int setpriority(int, unsigned, int);
int setrlimit(int, const struct rlimit *);
int setsid(void);
int setuid(uint32_t);
int setgid(uint32_t);
int seteuid(uint32_t);
int setegid(uint32_t);
int setreuid(uint32_t, uint32_t);
int setregid(uint32_t, uint32_t);
int setresuid(uint32_t, uint32_t, uint32_t);
int setresgid(uint32_t, uint32_t, uint32_t);
int sigaction(int, const struct sigaction *, struct sigaction *);
int sigignore(int);
int sigprocmask(int, const struct sigset *, struct sigset *);
int sigsuspend(const struct sigset *);
int stat(const char *, struct stat *) paramsnonnull();
int symlink(const char *, const char *);
int symlinkat(const char *, int, const char *);
int sync_file_range(int, int64_t, int64_t, unsigned);
int sysinfo(struct sysinfo *) paramsnonnull();
int touch(const char *, uint32_t);
int truncate(const char *, uint64_t);
int ttyname_r(int, char *, size_t);
int uname(struct utsname *);
int unlink(const char *);
int unlink_s(const char **);
int unlinkat(int, const char *, int);
int vfork(void);
int wait(int *);
int wait3(int *, int, struct rusage *);
int wait4(int, int *, int, struct rusage *);
int waitpid(int, int *, int);
int64_t lseek(int, int64_t, int);
int64_t pread(int, void *, size_t, int64_t);
int64_t preadv(int, struct iovec *, int, int64_t);
int64_t pwrite(int, const void *, size_t, int64_t);
int64_t pwritev(int, const struct iovec *, int, int64_t);
int64_t syscall();
long telldir(DIR *);
int getpid(void);
long times(struct tms *);
sighandler_t signal(int, sighandler_t);
size_t GetFileSize(const char *);
size_t getfiledescriptorsize(int);
ssize_t copy_file_range(int, long *, int, long *, size_t, uint32_t);
ssize_t copyfd(int, int64_t *, int, int64_t *, size_t, uint32_t);
ssize_t read(int, void *, size_t);
ssize_t readlinkat(int, const char *, char *, size_t);
ssize_t splice(int, int64_t *, int, int64_t *, size_t, uint32_t);
ssize_t vmsplice(int, const struct iovec *, int64_t, uint32_t);
ssize_t write(int, const void *, size_t);
struct dirent *readdir(DIR *);
uint32_t getegid(void) nosideeffect;
uint32_t geteuid(void) nosideeffect;
uint32_t getgid(void) nosideeffect;
uint32_t getpgrp(void) nosideeffect;
uint32_t getsid(int) nosideeffect;
uint32_t gettid(void) nosideeffect;
uint32_t getuid(void) nosideeffect;
uint32_t umask(int32_t);
void *getprocaddressmodule(const char *, const char *);
void *mmap(void *, uint64_t, int32_t, int32_t, int32_t, int64_t) vallocesque;
void *mremap(void *, uint64_t, uint64_t, int32_t, void *);
#define getcwd(BUF, SIZE) \
(isconstant(BUF) && (&(BUF)[0] == NULL) ? get_current_dir_name() \
: getcwd(BUF, SIZE))
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § system calls » formatting
*/
int dprintf(int, const char *, ...) printfesque(2) paramsnonnull((2));
int vdprintf(int, const char *, va_list) paramsnonnull();
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § system calls » link-time optimizations
*/
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
void _init_onntconsoleevent(void);
void _init_onwincrash(void);
#define __SIGACTION(FN, SIG, ...) \
({ \
if (SupportsWindows()) { \
if (isconstant(SIG)) { \
switch (SIG) { \
case SIGINT: \
case SIGQUIT: \
case SIGHUP: \
case SIGTERM: \
YOINK(_init_onntconsoleevent); \
break; \
case SIGTRAP: \
case SIGILL: \
case SIGSEGV: \
case SIGABRT: \
case SIGFPE: \
YOINK(_init_onwincrash); \
break; \
default: \
break; \
} \
} else { \
YOINK(_init_onntconsoleevent); \
YOINK(_init_onwincrash); \
} \
} \
(FN)(SIG, __VA_ARGS__); \
})
#define dprintf(FD, FMT, ...) (dprintf)(FD, PFLINK(FMT), ##__VA_ARGS__)
#define sigaction(SIG, ACT, OLD) __SIGACTION(sigaction, SIG, ACT, OLD)
#define signal(SIG, HAND) __SIGACTION(signal, SIG, HAND)
#define vdprintf(FD, FMT, VA) (vdprintf)(FD, PFLINK(FMT), VA)
#endif /* GNU && !ANSI */
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_SYSCALLS_H_ */

90
libc/calls/calls.mk Normal file
View file

@ -0,0 +1,90 @@
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
#
# SYNOPSIS
#
# System Call Compatibility Layer
#
# DESCRIPTION
#
# This package exports a familiar system call interface that works
# across platforms.
PKGS += LIBC_CALLS
LIBC_CALLS_ARTIFACTS += LIBC_CALLS_A
LIBC_CALLS = $(LIBC_CALLS_A_DEPS) $(LIBC_CALLS_A)
LIBC_CALLS_A = o/$(MODE)/libc/calls/syscalls.a
LIBC_CALLS_A_FILES := \
$(wildcard libc/calls/typedef/*) \
$(wildcard libc/calls/thunks/*) \
$(wildcard libc/calls/struct/*) \
$(wildcard libc/calls/*)
LIBC_CALLS_A_HDRS = $(filter %.h,$(LIBC_CALLS_A_FILES))
LIBC_CALLS_A_SRCS_S = $(filter %.S,$(LIBC_CALLS_A_FILES))
LIBC_CALLS_A_SRCS_C = $(filter %.c,$(LIBC_CALLS_A_FILES))
LIBC_CALLS_A_SRCS = \
$(LIBC_CALLS_A_SRCS_S) \
$(LIBC_CALLS_A_SRCS_C)
LIBC_CALLS_A_OBJS = \
$(LIBC_CALLS_A_SRCS:%=o/$(MODE)/%.zip.o) \
$(LIBC_CALLS_A_SRCS_S:%.S=o/$(MODE)/%.o) \
$(LIBC_CALLS_A_SRCS_C:%.c=o/$(MODE)/%.o)
LIBC_CALLS_A_CHECKS = \
$(LIBC_CALLS_A).pkg \
$(LIBC_CALLS_A_HDRS:%=o/$(MODE)/%.ok)
LIBC_CALLS_A_DIRECTDEPS = \
LIBC_FMT \
LIBC_STR \
LIBC_RAND \
LIBC_CONV \
LIBC_STUBS \
LIBC_NEXGEN32E \
LIBC_NT_NTDLL \
LIBC_NT_ADVAPI32 \
LIBC_NT_KERNEL32 \
LIBC_NT_KERNELBASE \
LIBC_SYSV_CALLS \
LIBC_SYSV
LIBC_CALLS_A_DEPS := \
$(call uniq,$(foreach x,$(LIBC_CALLS_A_DIRECTDEPS),$($(x))))
$(LIBC_CALLS_A): \
libc/calls/ \
$(LIBC_CALLS_A).pkg \
$(LIBC_CALLS_A_OBJS)
$(LIBC_CALLS_A).pkg: \
$(LIBC_CALLS_A_OBJS) \
$(foreach x,$(LIBC_CALLS_A_DIRECTDEPS),$($(x)_A).pkg)
o/$(MODE)/libc/calls/raise.o: \
OVERRIDE_COPTS += \
$(NO_MAGIC)
o/$(MODE)/libc/calls/siggy.o: \
OVERRIDE_COPTS += \
-ffunction-sections
o/$(MODE)/libc/calls/xnutrampoline.o \
o/$(MODE)/libc/calls/ntcontext2linux.o: \
OVERRIDE_COPTS += \
-O3
LIBC_CALLS_LIBS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)))
LIBC_CALLS_SRCS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)_SRCS))
LIBC_CALLS_HDRS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)_HDRS))
LIBC_CALLS_BINS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)_BINS))
LIBC_CALLS_CHECKS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)_CHECKS))
LIBC_CALLS_OBJS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)_OBJS))
LIBC_CALLS_TESTS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)_TESTS))
.PHONY: o/$(MODE)/libc/calls
o/$(MODE)/libc/calls: \
o/$(MODE)/libc/calls/hefty \
$(LIBC_CALLS_CHECKS)

38
libc/calls/chdir-nt.c Normal file
View file

@ -0,0 +1,38 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/internal.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/sysv/errfuns.h"
textwindows int chdir$nt(const char *path) {
int len;
char16_t path16[PATH_MAX];
if ((len = mkntpath(path, path16)) == -1) return -1;
if (path16[len - 1] != u'/' && path16[len - 1] != u'\\') {
path16[len + 0] = u'/';
path16[len + 1] = u'\0';
}
if (SetCurrentDirectory(path16)) {
return 0;
} else {
return winerr();
}
}

34
libc/calls/chdir.c Normal file
View 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 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
/**
* Sets current directory.
* @asyncsignalsafe
*/
int chdir(const char *path) {
if (!IsWindows()) {
return chdir$sysv(path);
} else {
return chdir$nt(path);
}
}

49
libc/calls/chmod.c Normal file
View 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 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/errfuns.h"
/**
* Changes permissions on file, 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 Five 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 ;-)
*
* @param pathname must exist
* @param mode contains octal flags (base 8)
* @errors ENOENT, ENOTDIR, ENOSYS
* @asyncsignalsafe
* @see fchmod()
*/
int chmod(const char *pathname, uint32_t mode) {
return fchmodat$sysv(AT_FDCWD, pathname, mode, 0);
}

38
libc/calls/chown.c Normal file
View file

@ -0,0 +1,38 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/sysv/consts/at.h"
/**
* Changes owner and/or group of pathname.
*
* @param uid is user id, or -1u to not change
* @param gid is group id, or -1u to not change
* @return 0 on success, or -1 w/ errno
* @see fchown() if pathname is already open()'d
* @see lchown() which does not dereference symbolic links
* @see /etc/passwd for user ids
* @see /etc/group for group ids
* @asyncsignalsafe
*/
int chown(const char *pathname, uint32_t uid, uint32_t gid) {
return fchownat$sysv(AT_FDCWD, pathname, uid, gid, 0);
}

45
libc/calls/close-nt.c Normal file
View file

@ -0,0 +1,45 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/internal.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/sysv/errfuns.h"
textwindows int close$nt(int fd) {
bool32 ok;
if (isfdindex(fd)) {
if (g_fds.p[fd].kind == kFdFile) {
/*
* Like Linux, closing a file on Windows doesn't guarantee it's
* immediately synced to disk. But unlike Linux, this could cause
* subsequent operations, e.g. unlink() to break w/ access error.
*/
FlushFileBuffers(g_fds.p[fd].handle);
}
ok = CloseHandle(g_fds.p[fd].handle);
if (g_fds.p[fd].kind == kFdConsole) {
ok &= CloseHandle(g_fds.p[fd].extra);
}
removefd(fd);
return ok ? 0 : winerr();
} else {
return ebadf();
}
}

49
libc/calls/close.c Normal file
View 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 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/sock/internal.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.h"
/**
* Closes file descriptor.
*
* @return 0 on success, or -1 w/ errno
* @asyncsignalsafe
*/
int close(int fd) {
int rc;
if (fd == -1) return 0;
if (isfdkind(fd, kFdZip)) {
rc = weaken(__zipos_close)(
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle);
} else if (!IsWindows()) {
rc = close$sysv(fd);
} else if (isfdkind(fd, kFdSocket)) {
rc = weaken(closesocket$nt)(fd);
} else {
rc = close$nt(fd);
}
removefd(fd);
return rc;
}

73
libc/calls/copyfd.c Normal file
View file

@ -0,0 +1,73 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/assert.h"
#include "libc/bits/bits.h"
#include "libc/bits/safemacros.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/errno.h"
#include "libc/sysv/errfuns.h"
/**
* Copies data between file descriptors the slow way.
*
* @return -1 on error/interrupt, 0 on eof, or [1..uptobytes] on success
* @see copy_file_range() for file file
* @see sendfile() for seekable socket
* @see splice() for fd pipe
*/
ssize_t copyfd(int infd, int64_t *inopt_out_inoffset, int to_fd,
int64_t *inopt_out_outoffset, size_t uptobytes, uint32_t flags) {
size_t i;
int64_t offset;
ssize_t got, wrote;
static unsigned char buf[1024 * 64];
/* unsigned char buf[1024 * 3]; */
uptobytes = min(sizeof(buf), uptobytes);
if (inopt_out_inoffset) {
got = pread(infd, buf, uptobytes, *inopt_out_inoffset);
} else {
got = read(infd, buf, uptobytes);
}
if (got == -1) return -1;
offset = inopt_out_outoffset ? *inopt_out_outoffset : -1;
for (i = 0; i < got; i += wrote) {
tryagain:
if (inopt_out_outoffset) {
wrote = pwrite(to_fd, buf, got - i, offset + i);
} else {
wrote = write(to_fd, buf, got - i);
}
if (wrote != -1) continue;
if (errno == EINTR) {
if (inopt_out_inoffset != NULL) {
return -1;
}
goto tryagain;
}
if (errno == EWOULDBLOCK) {
assert(inopt_out_inoffset != NULL); /* or caller is nuts */
}
return -1;
}
if (inopt_out_inoffset) *inopt_out_inoffset += got;
if (inopt_out_outoffset) *inopt_out_outoffset += got;
return got;
}

64
libc/calls/copyfile.c Normal file
View file

@ -0,0 +1,64 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/stat.h"
#include "libc/dce.h"
#include "libc/nt/files.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/consts/madv.h"
#include "libc/sysv/consts/o.h"
int copyfile(const char *frompath, const char *topath, bool dontoverwrite) {
if (IsWindows()) {
char16_t frompath16[PATH_MAX], topath16[PATH_MAX];
if (mkntpath(frompath, frompath16) == -1) return -1;
if (mkntpath(topath, topath16) == -1) return -1;
if (CopyFile(frompath16, topath16, dontoverwrite)) {
return 0;
} else {
return winerr();
}
} else {
struct stat st;
ssize_t transferred;
int rc, fromfd, tofd;
int64_t inoffset, outoffset;
rc = -1;
if ((fromfd = openat$sysv(AT_FDCWD, frompath, O_RDONLY, 0)) != -1) {
if (fstat$sysv(fromfd, &st) != -1 &&
(tofd = openat$sysv(AT_FDCWD, topath,
O_WRONLY | O_CREAT | (dontoverwrite ? O_EXCL : 0),
st.st_mode & 0777)) != -1) {
inoffset = 0;
outoffset = 0;
while (st.st_size && (transferred = copy_file_range(
fromfd, &inoffset, tofd, &outoffset,
st.st_size, 0)) != -1) {
st.st_size -= transferred;
}
if (!st.st_size) rc = 0;
rc |= close$sysv(tofd);
}
rc |= close$sysv(fromfd);
}
return rc;
}
}

36
libc/calls/creat.c Normal file
View file

@ -0,0 +1,36 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/sysv/consts/o.h"
/**
* Creates new file, returning open()'d file descriptor.
*
* @param file is a UTF-8 string, which is truncated if it exists
* @param mode is an octal user/group/other permission, e.g. 0755
* @return a number registered with the system to track the open file,
* which must be stored using a 64-bit type in order to support both
* System V and Windows, and must be closed later on using close()
* @see touch()
* @asyncsignalsafe
*/
nodiscard int creat(const char *file, uint32_t mode) {
return open(file, O_CREAT | O_WRONLY | O_TRUNC, mode);
}

38
libc/calls/createfd.c Normal file
View file

@ -0,0 +1,38 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/calls/internal.h"
#include "libc/mem/mem.h"
#include "libc/sysv/errfuns.h"
/**
* Finds open file descriptor slot.
*/
ssize_t createfd(void) {
size_t fd;
for (;;) {
while (g_fds.f < g_fds.n) {
if (g_fds.p[(fd = g_fds.f++)].kind == kFdEmpty) {
return fd;
}
}
if (growfds() == -1) return -1;
}
}

32
libc/calls/dprintf.c Normal file
View file

@ -0,0 +1,32 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
/**
* Formats string directly to system i/o device.
*/
int(dprintf)(int fd, const char *fmt, ...) {
int rc;
va_list va;
va_start(va, fmt);
rc = (vdprintf)(fd, fmt, va);
va_end(va);
return rc;
}

54
libc/calls/dup-nt.c Normal file
View file

@ -0,0 +1,54 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/mem/mem.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h"
/**
* Implements dup(), dup2(), and dup3() for Windows NT.
*/
textwindows int dup$nt(int oldfd, int newfd, int flags) {
if (!isfdkind(oldfd, kFdFile)) return ebadf();
if (newfd == -1) {
if ((newfd = createfd()) == -1) return -1;
} else if (isfdindex(newfd)) {
close(newfd);
} else if (isfdlegal(newfd)) {
do {
if (growfds() == -1) return -1;
} while (newfd >= g_fds.n);
} else {
return ebadf();
}
if (DuplicateHandle(GetCurrentProcess(), g_fds.p[oldfd].handle,
GetCurrentProcess(), &g_fds.p[newfd].handle, 0,
(flags & O_CLOEXEC), kNtDuplicateSameAccess)) {
g_fds.p[newfd].kind = g_fds.p[oldfd].kind;
g_fds.p[newfd].flags = flags;
return newfd;
} else {
return winerr();
}
}

37
libc/calls/dup.c Normal file
View file

@ -0,0 +1,37 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
/**
* Duplicates file descriptor/handle.
*
* @param fd remains open afterwards
* @return some arbitrary new number for fd
* @asyncsignalsafe
*/
nodiscard int dup(int fd) {
if (!IsWindows()) {
return dup$sysv(fd);
} else {
return dup$nt(fd, -1, 0);
}
}

40
libc/calls/dup2.c Normal file
View file

@ -0,0 +1,40 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
/**
* Duplicates file descriptor, granting it specific number.
*
* @param oldfd isn't closed afterwards
* @param newfd if already assigned, is silently closed beforehand;
* unless it's equal to oldfd, in which case dup2() is a no-op
* @return new file descriptor, or -1 w/ errno
* @asyncsignalsafe
*/
int dup2(int oldfd, int newfd) {
if (oldfd == newfd) return newfd;
if (!IsWindows()) {
return dup3$sysv(oldfd, newfd, 0);
} else {
return dup$nt(oldfd, newfd, 0);
}
}

47
libc/calls/dup3-sysv.c Normal file
View file

@ -0,0 +1,47 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/internal.h"
#include "libc/errno.h"
#define __NR_dup3_linux 0x0124 /*RHEL5:CVE-2010-3301*/
int32_t dup3$sysv(int32_t oldfd, int32_t newfd, int flags) {
static bool once, demodernize;
int olderr, fd;
if (!once) {
once = true;
olderr = errno;
fd = __dup3$sysv(oldfd, newfd, flags);
if ((fd == -1 && errno == ENOSYS) || fd == __NR_dup3_linux) {
demodernize = true;
errno = olderr;
goto OldSkool;
}
} else if (demodernize) {
goto OldSkool;
} else {
fd = __dup3$sysv(oldfd, newfd, flags);
}
return fd;
OldSkool:
fd = dup2$sysv(oldfd, newfd);
if (flags) fd = fixupnewfd$sysv(fd, flags);
return fd;
}

44
libc/calls/dup3.c Normal file
View file

@ -0,0 +1,44 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/sysv/errfuns.h"
/**
* Duplicates file descriptor/handle.
*
* On Windows, we can't guarantee the desired file descriptor is used.
* We can however remap the standard handles (non-atomically) if their
* symbolic names are used.
*
* @param oldfd isn't closed afterwards
* @param newfd if already assigned, is silently closed beforehand;
* unless it's equal to oldfd, in which case dup2() is a no-op
* @flags can have O_CLOEXEC
*/
int dup3(int oldfd, int newfd, int flags) {
if (oldfd == newfd) return einval();
if (!IsWindows()) {
return dup3$sysv(oldfd, newfd, flags);
} else {
return dup$nt(oldfd, newfd, flags);
}
}

65
libc/calls/fadvise-nt.c Normal file
View file

@ -0,0 +1,65 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/internal.h"
#include "libc/nt/enum/fileflagandattributes.h"
#include "libc/nt/enum/filesharemode.h"
#include "libc/nt/enum/status.h"
#include "libc/nt/files.h"
#include "libc/nt/nt/file.h"
#include "libc/nt/ntdll.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/fileaccessinformation.h"
#include "libc/nt/struct/filebasicinformation.h"
#include "libc/nt/struct/iostatusblock.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/errfuns.h"
textwindows int fadvise$nt(int fd, uint64_t offset, uint64_t len, int advice) {
int64_t h2;
NtStatus status;
uint32_t sharemode;
struct NtIoStatusBlock iostatus;
struct NtFileBasicInformation basicinfo;
struct NtFileAccessInformation accessinfo;
if (!isfdkind(fd, kFdFile)) return ebadf();
sharemode = /* xxx: no clue how to query this */
kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete;
/* TODO(jart): can we do it in one call w/ NtQueryObject? */
if (!NtError(status = NtQueryInformationFile(g_fds.p[fd].handle, &iostatus,
&basicinfo, sizeof(basicinfo),
kNtFileBasicInformation)) &&
!NtError(status = NtQueryInformationFile(g_fds.p[fd].handle, &iostatus,
&accessinfo, sizeof(accessinfo),
kNtFileAccessInformation))) {
if ((h2 = ReOpenFile(g_fds.p[fd].handle, accessinfo.AccessFlags, sharemode,
advice | basicinfo.FileAttributes)) != -1) {
if (h2 != g_fds.p[fd].handle) {
CloseHandle(g_fds.p[fd].handle);
g_fds.p[fd].handle = h2;
}
return 0;
}
return winerr();
} else if (status == kNtStatusDllNotFound) {
return enosys();
} else {
return ntreturn(status);
}
}

40
libc/calls/fadvise.c Normal file
View file

@ -0,0 +1,40 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
/**
* Drops hints to O/S about intended I/O behavior.
*
* It makes a huge difference. For example, when copying a large file,
* it can stop the system from persisting GBs of useless memory content.
*
* @param len 0 means til end of file
* @param advice can be MADV_SEQUENTIAL, MADV_RANDOM, etc.
* @return -1 on error
*/
int fadvise(int fd, uint64_t offset, uint64_t len, int advice) {
if (!IsWindows()) {
return fadvise$sysv(fd, offset, len, advice); /* linux & freebsd */
} else {
return fadvise$nt(fd, offset, len, advice);
}
}

76
libc/calls/fallocate.c Normal file
View file

@ -0,0 +1,76 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/nt/enum/fsctl.h"
#include "libc/nt/files.h"
#include "libc/nt/struct/filezerodatainformation.h"
#include "libc/sysv/consts/falloc.h"
#include "libc/sysv/errfuns.h"
/**
* Manipulates underlying physical medium of file.
*
* This system call generalizes to many powerful use cases on Linux,
* such as creating gigantic sparse files that take up little space.
* This API can polyfill a certain subset of parameters safely, e.g.
* ones identical to ftruncate(), but errs on the side of caution.
*
* @param fd must be open for writing
* @param mode can be 0, FALLOC_xxx
* @param length is how much physical space to reserve / commit
* @return 0 on success, or -1 w/ errno
* @see ftruncate()
*/
int fallocate(int fd, int32_t mode, int64_t offset, int64_t length) {
int rc;
uint32_t br;
if (mode == -1 /* our sysvconsts definition */) return eopnotsupp();
if (!mode && !length) return ftruncate(fd, offset);
if (IsLinux()) {
rc = fallocate$sysv(fd, mode, offset, length);
if (rc == 0x011d) rc = enosys(); /*RHEL5:CVE-2010-3301*/
return rc;
} else if (!IsWindows()) {
return posix_fallocate$sysv(fd, offset, length);
} else if (IsWindows()) {
if (!isfdkind(fd, kFdFile)) return ebadf();
if (mode == FALLOC_FL_ZERO_RANGE) {
if (DeviceIoControl(
g_fds.p[fd].handle, kNtFsctlSetZeroData,
&(struct NtFileZeroDataInformation){offset, offset + length},
sizeof(struct NtFileZeroDataInformation), NULL, 0, &br, NULL)) {
return 0;
} else {
return winerr();
}
} else if (!mode && !offset) {
/*
* this should commit physical space
* but not guaranteed zero'd like linux
*/
return ftruncate$nt(fd, length);
} else {
return eopnotsupp();
}
} else {
return enosys();
}
}

48
libc/calls/fchmod.c Normal file
View file

@ -0,0 +1,48 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
#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 ;-)
*
* @param mode contains octal flags (base 8)
* @errors ENOSYS
* @asyncsignalsafe
* @see chmod()
*/
int fchmod(int fd, uint32_t mode) {
/* TODO(jart): Windows */
return fchmod$sysv(fd, mode);
}

36
libc/calls/fchown.c Normal file
View file

@ -0,0 +1,36 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/sysv/consts/at.h"
/**
* Changes owner and/or group of file, via open()'d descriptor.
*
* @param uid is user id, or -1u to not change
* @param gid is group id, or -1u to not change
* @return 0 on success, or -1 w/ errno
* @see /etc/passwd for user ids
* @see /etc/group for group ids
*/
int fchown(int fd, uint32_t uid, uint32_t gid) {
/* TODO(jart): Windows? */
return fchown$sysv(fd, uid, gid);
}

40
libc/calls/fchownat.c Normal file
View file

@ -0,0 +1,40 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
/**
* Changes owner and/or group of pathname.
*
* @param dirfd is open()'d relative-to directory, or AT_FDCWD, etc.
* @param uid is user id, or -1 to not change
* @param gid is group id, or -1 to not change
* @param flags can have AT_SYMLINK_NOFOLLOW, etc.
* @return 0 on success, or -1 w/ errno
* @see chown(), lchown() for shorthand notation
* @see /etc/passwd for user ids
* @see /etc/group for group ids
* @asyncsignalsafe
*/
int fchownat(int dirfd, const char *pathname, uint32_t uid, uint32_t gid,
uint32_t flags) {
/* TODO(jart): Windows? */
return fchownat$sysv(dirfd, pathname, uid, gid, flags);
}

40
libc/calls/fcntl-nt.c Normal file
View file

@ -0,0 +1,40 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/internal.h"
#include "libc/nt/files.h"
#include "libc/sysv/consts/f.h"
#include "libc/sysv/consts/fd.h"
#include "libc/sysv/errfuns.h"
textwindows int fcntl$nt(int fd, int cmd, unsigned arg) {
if (!isfdindex(fd)) return ebadf();
switch (cmd) {
case F_GETFD:
return GetHandleInformation(g_fds.p[fd].handle, &arg) ? (arg ^ FD_CLOEXEC)
: -1;
case F_SETFD:
return SetHandleInformation(g_fds.p[fd].handle, FD_CLOEXEC,
arg ^ FD_CLOEXEC)
? 0
: -1;
default:
return 0; /* TODO(jart): Implement me. */
}
}

40
libc/calls/fcntl.c Normal file
View file

@ -0,0 +1,40 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
/**
* Does things with file descriptor, via re-imagined hourglass api, e.g.
*
* CHECK_NE(-1, fcntl(fd, F_SETFD, FD_CLOEXEC));
*
* @param cmd can be F_{GET,SET}{FD,FL}, etc.
* @param arg can be FD_CLOEXEC, etc. depending
* @return 0 on success, or -1 w/ errno
* @asyncsignalsafe
*/
int fcntl(int fd, int cmd, int arg) {
if (!IsWindows()) {
return fcntl$sysv(fd, cmd, arg);
} else {
return fcntl$nt(fd, cmd, arg);
}
}

32
libc/calls/fdatasync-nt.c Normal file
View file

@ -0,0 +1,32 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/internal.h"
#include "libc/nt/files.h"
#include "libc/sysv/errfuns.h"
textwindows int fdatasync$nt(int fd) {
if (!isfdkind(fd, kFdFile)) return ebadf();
/*
* XXX: On Windows NT this might be more analagous to fflush() and
* Microsoft docs say to do manual block i/o for database-ish
* guarantees on disk persistence. Consider: Really good UPS.
*/
return FlushFileBuffers(g_fds.p[fd].handle) ? 0 : winerr();
}

37
libc/calls/fdatasync.c Normal file
View file

@ -0,0 +1,37 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
/**
* Blocks until kernel flushes non-metadata buffers for fd to disk.
*
* @return 0 on success, or -1 w/ errno
* @see fsync(), sync_file_range()
* @asyncsignalsafe
*/
int fdatasync(int fd) {
if (!IsWindows()) {
return fdatasync$sysv(fd);
} else {
return fdatasync$nt(fd);
}
}

28
libc/calls/fdkind.c Normal file
View file

@ -0,0 +1,28 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/internal.h"
enum FdKind fdkind(int fd) {
if (isfdindex(fd)) {
return g_fds.p[fd].kind;
} else {
return kFdEmpty;
}
}

44
libc/calls/fileexists.c Normal file
View file

@ -0,0 +1,44 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/nt/files.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
/**
* Returns true if file exists at path.
*
* Please note that things which aren't strictly files, e.g. directories
* or sockets, could be considered files for the purposes of this
* function. The stat() function may be used to differentiate them.
*/
bool fileexists(const char *path) {
/* TODO(jart): Use fast path on NT? */
struct stat st;
int olderr = errno;
int rc = stat(path, &st);
if (rc == -1 && (errno == ENOENT || errno == ENOTDIR)) {
errno = olderr;
}
return rc != -1;
}

View file

@ -0,0 +1,40 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/internal.h"
#include "libc/calls/ntmagicpaths.h"
#include "libc/nexgen32e/tinystrcmp.h"
#include "libc/sysv/consts/o.h"
textwindows const char *(fixntmagicpath)(const char *path, unsigned flags) {
const struct NtMagicPaths *mp = &kNtMagicPaths;
asm("" : "+r"(mp));
if (path[0] != '/') return path;
if (tinystrcmp(path, mp->devtty) == 0) {
if ((flags & O_ACCMODE) == O_RDONLY) {
return mp->conin;
} else if ((flags & O_ACCMODE) == O_WRONLY) {
return mp->conout;
}
}
if (tinystrcmp(path, mp->devnull) == 0) return mp->nul;
if (tinystrcmp(path, mp->devstdin) == 0) return mp->conin;
if (tinystrcmp(path, mp->devstdout) == 0) return mp->conout;
return path;
}

36
libc/calls/fixupnewfd.c Normal file
View file

@ -0,0 +1,36 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/internal.h"
#include "libc/sysv/consts/f.h"
#include "libc/sysv/consts/fd.h"
#include "libc/sysv/consts/o.h"
/**
* Applies file descriptor fixups on XNU or old Linux.
* @see fixupnewsockfd$sysv() for socket file descriptors
*/
int fixupnewfd$sysv(int fd, int flags) {
if (fd != -1) {
if (flags & O_CLOEXEC) fcntl$sysv(fd, F_SETFD, FD_CLOEXEC);
fcntl$sysv(fd, F_SETFL,
(fcntl$sysv(fd, F_GETFL, 0) ^ (flags & O_NONBLOCK)));
}
return fd;
}

44
libc/calls/flock-nt.c Normal file
View file

@ -0,0 +1,44 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/internal.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/byhandlefileinformation.h"
#include "libc/nt/struct/overlapped.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/lock.h"
#include "libc/sysv/errfuns.h"
textwindows int flock$nt(int fd, int op) {
struct NtOverlapped ov;
struct NtByHandleFileInformation info;
if (!isfdkind(fd, kFdFile)) return ebadf();
memset(&ov, 0, sizeof(ov));
if (GetFileInformationByHandle(g_fds.p[fd].handle, &info) &&
((!(op & LOCK_UN) &&
LockFileEx(g_fds.p[fd].handle, op, 0, info.nFileSizeLow,
info.nFileSizeHigh, &ov)) ||
((op & LOCK_UN) && UnlockFileEx(g_fds.p[fd].handle, 0, info.nFileSizeLow,
info.nFileSizeHigh, &ov)))) {
return 0;
} else {
return winerr();
}
}

37
libc/calls/flock.c Normal file
View file

@ -0,0 +1,37 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
/**
* Acquires lock on file.
*
* @param op can have LOCK_{SH,EX,NB,UN} for shared, exclusive,
* non-blocking, and unlocking
* @return 0 on success, or -1 w/ errno
*/
int flock(int fd, int op) {
if (!IsWindows()) {
return flock$sysv(fd, op);
} else {
return flock$nt(fd, op);
}
}

35
libc/calls/fork.c Normal file
View file

@ -0,0 +1,35 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
/**
* Creates new process zygote style.
*
* @return 0 to child, child pid to parent, or -1 on error
* @asyncsignalsafe
*/
int fork(void) {
int rc;
rc = fork$sysv();
if (rc == 0) __onfork();
return rc;
}

39
libc/calls/fprot2nt.c Normal file
View file

@ -0,0 +1,39 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/internal.h"
#include "libc/nt/enum/filemapflags.h"
#include "libc/nt/memory.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/prot.h"
#define HAS(X, BITS) (((X) & (BITS)) == (BITS))
/**
* Converts System Five memory protection flags to Windows NT, Part 2.
* @see libc/sysv/consts.sh
*/
uint32_t fprot2nt(int prot, int flags) {
return (HAS(prot, PROT_READ) ? kNtFileMapRead : 0) |
(HAS(prot, PROT_WRITE) ? kNtFileMapWrite : 0) |
(HAS(prot, PROT_EXEC) ? kNtFileMapExecute : 0) |
(HAS(flags, MAP_PRIVATE) ? kNtFileMapCopy : 0) |
(HAS(flags, kNtSecLargePages) ? kNtFileMapLargePages : 0) |
(HAS(flags, kNtSecReserve) ? kNtFileMapReserve : 0);
}

71
libc/calls/fstat-nt.c Normal file
View file

@ -0,0 +1,71 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/safemacros.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/stat.h"
#include "libc/conv/conv.h"
#include "libc/nt/enum/fileflagandattributes.h"
#include "libc/nt/enum/fileinfobyhandleclass.h"
#include "libc/nt/enum/filetype.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/str/str.h"
#include "libc/sysv/consts/s.h"
textwindows int fstat$nt(int64_t handle, struct stat *st) {
uint64_t actualsize;
enum NtFileType filetype;
struct NtByHandleFileInformation wst;
struct NtFileCompressionInfo fci;
if (GetFileInformationByHandle(handle, &wst)) {
memset(st, 0, sizeof(*st));
filetype = GetFileType(handle);
st->st_mode =
(S_IRUSR | S_IXUSR |
(!(wst.dwFileAttributes & kNtFileAttributeReadonly) ? S_IWUSR : 0) |
((wst.dwFileAttributes & kNtFileAttributeNormal) ? S_IFREG : 0) |
((wst.dwFileAttributes & kNtFileFlagOpenReparsePoint) ? S_IFLNK : 0) |
((wst.dwFileAttributes & kNtFileAttributeDirectory)
? S_IFDIR
: (((filetype == kNtFileTypeDisk) ? S_IFBLK : 0) |
((filetype == kNtFileTypeChar) ? S_IFCHR : 0) |
((filetype == kNtFileTypePipe) ? S_IFIFO : 0))));
filetimetotimespec(&st->st_atim, wst.ftLastAccessFileTime);
filetimetotimespec(&st->st_mtim, wst.ftLastWriteFileTime);
filetimetotimespec(&st->st_ctim, wst.ftCreationFileTime);
st->st_size = (uint64_t)wst.nFileSizeHigh << 32 | wst.nFileSizeLow;
st->st_blksize = PAGESIZE;
st->st_dev = 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;
} else {
actualsize = st->st_size;
}
st->st_blocks = roundup(actualsize, PAGESIZE) / 512;
return 0;
} else {
return winerr();
}
}

32
libc/calls/fstat-sysv.c Normal file
View file

@ -0,0 +1,32 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/internal.h"
/**
* Supports fstat(), etc. implementations.
* @asyncsignalsafe
*/
int32_t fstat$sysv(int32_t fd, struct stat *st) {
int res;
if ((res = __fstat$sysv(fd, st)) != -1) {
stat2linux(st);
}
return res;
}

41
libc/calls/fstat.c Normal file
View file

@ -0,0 +1,41 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.h"
/**
* Returns information about file, via open()'d descriptor.
* @asyncsignalsafe
*/
int fstat(int fd, struct stat *st) {
if (isfdkind(fd, kFdZip)) {
return weaken(__zipos_fstat)(
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, st);
} else if (!IsWindows()) {
return fstat$sysv(fd, st);
} else {
if (!isfdkind(fd, kFdFile)) return ebadf();
return fstat$nt(g_fds.p[fd].handle, st);
}
}

33
libc/calls/fstatat-sysv.c Normal file
View file

@ -0,0 +1,33 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/internal.h"
/**
* Supports stat(), lstat(), fstatat(), etc. implementations.
* @asyncsignalsafe
*/
int32_t fstatat$sysv(int32_t dirfd, const char *pathname, struct stat *st,
int32_t flags) {
int32_t rc;
if ((rc = __fstatat$sysv(dirfd, pathname, st, flags)) != -1) {
stat2linux(st);
}
return rc;
}

49
libc/calls/fstatat.c Normal file
View 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 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/errno.h"
#include "libc/sysv/consts/at.h"
/**
* Performs stat() w/ features for threaded apps.
*
* @param dirfd can be AT_FDCWD or an open directory descriptor, and is
* ignored if pathname is absolute
* @param flags can have AT_{EMPTY_PATH,NO_AUTOMOUNT,SYMLINK_NOFOLLOW}
* @return 0 on success, or -1 w/ errno
* @asyncsignalsafe
*/
int fstatat(int dirfd, const char *pathname, struct stat *st, uint32_t flags) {
int olderr = errno;
int rc = fstatat$sysv(dirfd, pathname, st, flags);
if (rc != -1) {
stat2linux(st);
} else if (errno == ENOSYS && dirfd == AT_FDCWD) {
if (!flags) {
errno = olderr;
rc = stat(pathname, st);
} else if (flags == AT_SYMLINK_NOFOLLOW) {
errno = olderr;
rc = lstat(pathname, st);
}
}
return rc;
}

37
libc/calls/fsync.c Normal file
View file

@ -0,0 +1,37 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
/**
* Blocks until kernel flushes buffers for fd to disk.
*
* @return 0 on success, or -1 w/ errno
* @see fdatasync(), sync_file_range()
* @asyncsignalsafe
*/
int fsync(int fd) {
if (!IsWindows()) {
return fsync$sysv(fd);
} else {
return fdatasync$nt(fd);
}
}

38
libc/calls/ftruncate-nt.c Normal file
View file

@ -0,0 +1,38 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/internal.h"
#include "libc/nt/enum/filemovemethod.h"
#include "libc/nt/files.h"
#include "libc/sysv/errfuns.h"
textwindows int ftruncate$nt(int fd, uint64_t length) {
bool32 ok;
int64_t tell;
if (!isfdkind(fd, kFdFile)) return ebadf();
tell = -1;
if (SetFilePointerEx(g_fds.p[fd].handle, 0, &tell, kNtFileCurrent)) {
ok = SetFilePointerEx(g_fds.p[fd].handle, length, NULL, kNtFileBegin) &&
SetEndOfFile(g_fds.p[fd].handle);
SetFilePointerEx(g_fds.p[fd].handle, tell, NULL, kNtFileBegin);
return ok ? 0 : winerr();
} else {
return winerr();
}
}

41
libc/calls/ftruncate.c Normal file
View file

@ -0,0 +1,41 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
/**
* Changes size of file.
*
* @param fd must be open for writing
* @param length may be greater than current current file size, in which
* case System V guarantees it'll be zero'd but Windows NT doesn't;
* since the prior extends logically and the latter physically
* @return 0 on success, or -1 w/ errno
* @asyncsignalsafe
* @see fallocate()
*/
int ftruncate(int fd, int64_t length) {
if (!IsWindows()) {
return ftruncate$sysv(fd, length);
} else {
return ftruncate$nt(fd, length);
}
}

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

@ -0,0 +1,43 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/bits/pushpop.h"
#include "libc/calls/internal.h"
#include "libc/macros.h"
#include "libc/nt/runtime.h"
#include "libc/sysv/consts/fileno.h"
struct Fds g_fds;
INITIALIZER(300, _init_g_fds, {
struct Fds *fds;
fds = VEIL("D", &g_fds);
pushmov(&fds->f, 3ul);
pushmov(&fds->n, ARRAYLEN(fds->__init_p));
fds->p = fds->__init_p;
fds->__init_p[STDIN_FILENO].kind = pushpop(kFdFile);
fds->__init_p[STDOUT_FILENO].kind = pushpop(kFdFile);
fds->__init_p[STDERR_FILENO].kind = pushpop(kFdFile);
fds->__init_p[STDIN_FILENO].handle = GetStdHandle(pushpop(kNtStdInputHandle));
fds->__init_p[STDOUT_FILENO].handle =
GetStdHandle(pushpop(kNtStdOutputHandle));
fds->__init_p[STDERR_FILENO].handle =
GetStdHandle(pushpop(kNtStdErrorHandle));
})

View file

@ -0,0 +1,30 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/internal.h"
#include "libc/nt/startupinfo.h"
#include "libc/nt/struct/startupinfo.h"
/**
* GetStartupInfo() singleton.
* @see libc/runtime/winmain.c
*/
struct NtStartupInfo g_ntstartupinfo;
STATIC_YOINK("_init_g_ntstartupinfo");

View file

@ -0,0 +1,27 @@
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
.yoink __FILE__
.init.start 400,_init_g_ntstartupinfo
ezlea g_ntstartupinfo,cx
mov %rsp,%rbp
ntcall __imp_GetStartupInfoW
.init.end 400,_init_g_ntstartupinfo,globl,hidden

View file

@ -0,0 +1,30 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/internal.h"
#include "libc/nt/struct/systeminfo.h"
#include "libc/nt/systeminfo.h"
/**
* GetSystemInfo() singleton.
* @see libc/runtime/winmain.c
*/
struct NtSystemInfo g_ntsysteminfo;
STATIC_YOINK("_init_g_ntsysteminfo");

View file

@ -0,0 +1,27 @@
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
.yoink __FILE__
.init.start 400,_init_g_ntsysteminfo
ezlea g_ntsysteminfo,cx
mov %rsp,%rbp
ntcall __imp_GetSystemInfo
.init.end 400,_init_g_ntsysteminfo,globl,hidden

View file

@ -0,0 +1,22 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/internal.h"
int g_sighandrvas[NSIG];

70
libc/calls/getauxval.c Normal file
View file

@ -0,0 +1,70 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/dce.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/auxv.h"
/**
* Returns auxiliary value, or zero if kernel didn't provide it.
*
* This function is typically regarded as a libc implementation detail;
* thus, the source code is the documentation.
*
* @see libc/sysv/consts.sh
* @see System Five Application Binary Interface § 3.4.3
* @asyncsignalsafe
*/
unsigned long getauxval(unsigned long at) {
unsigned long res = 0;
if (at != -1) {
if (!IsWindows()) {
if (!g_auxv) return 0;
if (IsXnu()) {
if (at) {
const char *name =
at == AT_EXECFN ? "executable_path" : (const char *)at;
const char **auxv = (const char **)g_auxv;
unsigned namelen = strlen(name);
for (int i = 0; auxv[i]; ++i) {
if (strncmp(auxv[i], name, namelen) == 0 &&
auxv[i][namelen] == '=') {
res = (intptr_t)&auxv[i][namelen + 1];
break;
}
}
}
} else {
for (const unsigned long *ap = g_auxv; *ap; ap += 2) {
if (ap[0] == at) {
res = ap[1];
break;
}
}
}
} else {
/* TODO(jart): GetProcessImageFileName */
}
if (res == 0 && at == AT_EXECFN) {
res = (uintptr_t)program_invocation_name;
}
}
return res;
}

37
libc/calls/getcwd-nt.c Normal file
View file

@ -0,0 +1,37 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/internal.h"
#include "libc/nt/files.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
textwindows char *getcwd$nt(char *buf, size_t size) {
uint16_t name16[PATH_MAX];
if (GetCurrentDirectory(PATH_MAX, name16)) {
if (tprecode16to8(buf, size, name16) < size - 1) {
return buf;
} else {
erange();
}
} else {
winerr();
}
return NULL;
}

57
libc/calls/getcwd.c Normal file
View file

@ -0,0 +1,57 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/sysv/errfuns.h"
/**
* Returns current working directory.
*
* @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
*/
char *(getcwd)(char *buf, size_t size) {
buf[0] = '\0';
if (!IsWindows()) {
int olderr = errno;
if (getcwd$sysv(buf, size) != NULL) {
return buf;
} else if (IsXnu() && errno == ENOSYS) {
if (size >= 2) {
buf[0] = '.'; /* XXX: could put forth more effort */
buf[1] = '\0';
errno = olderr;
return buf;
} else {
erange();
}
}
return NULL;
} else {
return getcwd$nt(buf, size);
}
}

38
libc/calls/getenv.c Normal file
View file

@ -0,0 +1,38 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/bits/safemacros.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
/**
* Returns value of environment variable, or NULL if not found.
*/
char *getenv(const char *name) {
char *empty[1] = {NULL};
char **ep = firstnonnull(environ, empty);
unsigned namelen = strlen(name);
for (int i = 0; ep[i]; ++i) {
if (strncmp(ep[i], name, namelen) == 0 && ep[i][namelen] == '=') {
return &ep[i][namelen + 1];
}
}
return NULL;
}

View file

@ -0,0 +1,36 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h"
#include "libc/dce.h"
#include "libc/limits.h"
#include "libc/nt/files.h"
/**
* Determines size of open file.
*
* @return file byte length, or -1ul w/ errno
* @asyncsignalsafe
*/
size_t getfiledescriptorsize(int fd) {
struct stat st;
if (fstat(fd, &st) == -1) return SIZE_MAX;
return st.st_size;
}

38
libc/calls/getfilesize.c Normal file
View file

@ -0,0 +1,38 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/stat.h"
#include "libc/dce.h"
#include "libc/limits.h"
#include "libc/nt/files.h"
#include "libc/str/str.h"
/**
* Returns the byte length of file by path.
*
* @return number of bytes, or -1ul w/ errno
* @see getfiledescriptorsize
*/
size_t GetFileSize(const char *pathname) {
struct stat st;
if (stat(pathname, &st) == -1) return SIZE_MAX;
return st.st_size;
}

55
libc/calls/getntsyspath.S Normal file
View file

@ -0,0 +1,55 @@
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
.yoink __FILE__
/ Obtains WIN32 magic path, e.g. GetTempPathA.
/
/ @param rax is address of ANSI path provider function
/ @param rdi is output buffer
/ @param rdx is output buffer size in bytes that's >0
/ @return eax is string length w/ NUL that's ≤ edx
/ @return rdi is rdi+edx
.text.startup
__getntsyspath:
push %rbp
mov %rsp,%rbp
push %rdx
movpp %rdi,%rcx # call f=%rax(p1=%rcx,p2=%rdx)
sub $40,%rsp
call *%rax
xor %edx,%edx
mov -8(%rbp),%ecx # restore %edx param as %ecx
cmp %eax,%ecx # use current dir on overflow
cmovbe %edx,%eax
cmp $1,%eax # leave empty strings empty
jbe 1f
cmpb $'\\,-1(%rdi,%rax) # guarantee trailing slash
je 1f
movw $'\\,(%rdi,%rax)
inc %eax
1: inc %rdi # change backslash to slash
cmpb $'\\,-1(%rdi)
jne 2f
movb $'/,-1(%rdi)
2: loop 1b
leave
ret
.endfn __getntsyspath,globl,hidden

54
libc/calls/getpid.c Normal file
View file

@ -0,0 +1,54 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/nt/process.h"
#include "libc/runtime/missioncritical.h"
#include "libc/runtime/runtime.h"
static int g_pid;
static void __updatepid(void) {
atfork(__updatepid, NULL);
g_pid = __getpid();
}
int __getpid(void) {
if (!IsWindows()) {
return GETPID();
} else {
return NtGetPid();
}
}
/**
* Returns process id.
* @asyncsignalsafe
*/
int getpid(void) {
static bool once;
if (!once) {
once = true;
__updatepid();
}
return g_pid;
}

53
libc/calls/getppid.c Normal file
View 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 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/nt/nt/process.h"
#include "libc/nt/ntdll.h"
#include "libc/nt/process.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/processbasicinformation.h"
static textwindows noinline int32_t getppid$nt(void) {
struct NtProcessBasicInformation ProcessInformation;
uint32_t gotsize = 0;
if (!NtError(
NtQueryInformationProcess(GetCurrentProcess(), 0, &ProcessInformation,
sizeof(ProcessInformation), &gotsize)) &&
gotsize >= sizeof(ProcessInformation) &&
ProcessInformation.InheritedFromUniqueProcessId) {
/* TODO(jart): Fix type mismatch and do we need to close this? */
return ProcessInformation.InheritedFromUniqueProcessId;
}
return GetCurrentProcessId();
}
/**
* Returns parent process id.
* @asyncsignalsafe
*/
int32_t getppid(void) {
if (!IsWindows()) {
return getppid$sysv();
} else {
return getppid$nt();
}
}

View file

@ -0,0 +1,50 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/kntprioritycombos.h"
#include "libc/conv/conv.h"
#include "libc/nt/enum/processcreationflags.h"
#include "libc/nt/enum/threadpriority.h"
#include "libc/nt/process.h"
#include "libc/nt/runtime.h"
#include "libc/nt/thread.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/prio.h"
#include "libc/sysv/errfuns.h"
textwindows int getpriority$nt(int ignored) {
size_t i;
uint32_t tier, lg2tier, wut;
if ((tier = GetPriorityClass(GetCurrentProcess())) != 0 &&
(wut = GetThreadPriority(GetCurrentThread())) != -1u) {
lg2tier = ffs(tier);
for (i = 0; i < kNtPriorityCombosLen; ++i) {
if (kNtPriorityCombos[i].lg2tier == lg2tier &&
kNtPriorityCombos[i].wut == wut) {
return kNtPriorityCombos[i].nice;
}
}
abort();
} else {
return winerr();
}
}

37
libc/calls/getpriority.c Normal file
View file

@ -0,0 +1,37 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
/**
* Returns nice value of thing.
*
* @param which can be PRIO_PROCESS, PRIO_PGRP, PRIO_USER
* @param who is the pid, pgid, or uid (0 means current)
* @return value [-NZERO,NZERO) or -1 w/ errno
* @see setpriority(), nice()
*/
int getpriority(int which, unsigned who) {
if (!IsWindows()) {
return getpriority$sysv(which, who) - 20;
} else {
return getsetpriority$nt(which, who, 0, getpriority$nt);
}
}

View file

@ -0,0 +1,28 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/nt/dll.h"
#include "libc/calls/calls.h"
/**
* Returns address of function in a DLL that's already loaded.
*/
textwindows void *getprocaddressmodule(const char *module, const char *symbol) {
return GetProcAddress(GetModuleHandle(module), symbol);
}

37
libc/calls/getrlimit.c Normal file
View file

@ -0,0 +1,37 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/sysv/errfuns.h"
/**
* Gets resource limit for current process.
*
* @param resource can be RLIMIT_{CPU,FSIZE,DATA,STACK,CORE,RSS,etc.}
* @param rlim receives result, modified only on success
* @return 0 on success or -1 w/ errno
* @see libc/sysv/consts.sh
*/
int getrlimit(int resource, struct rlimit *rlim) {
/* TODO(jart): Windows */
if (resource == -1) return einval();
return getrlimit$sysv(resource, rlim);
}

65
libc/calls/getrusage.c Normal file
View file

@ -0,0 +1,65 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/rusage.h"
#include "libc/conv/conv.h"
#include "libc/dce.h"
#include "libc/nt/accounting.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/filetime.h"
#include "libc/nt/thread.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/rusage.h"
#include "libc/sysv/errfuns.h"
static textwindows noinline int getrusage$nt(int who, struct rusage *usage) {
struct NtFileTime CreationFileTime;
struct NtFileTime ExitFileTime;
struct NtFileTime KernelFileTime;
struct NtFileTime UserFileTime;
memset(usage, 0, sizeof(*usage));
if ((who == RUSAGE_SELF ? GetProcessTimes : GetThreadTimes)(
(who == RUSAGE_SELF ? GetCurrentProcess : GetCurrentThread)(),
&CreationFileTime, &ExitFileTime, &KernelFileTime, &UserFileTime)) {
filetimetotimeval(&usage->ru_utime, UserFileTime);
filetimetotimeval(&usage->ru_stime, KernelFileTime);
return 0;
} else {
return winerr();
}
}
/**
* Returns resource usage statistics.
*
* @param who can be RUSAGE_{SELF,CHILDREN,THREAD}
* @return 0 on success, or -1 w/ errno
*/
int getrusage(int who, struct rusage *usage) {
if (who == 99) return enosys(); /* @see libc/sysv/consts.sh */
if (!usage) return efault();
if (!IsWindows()) {
return getrusage$sysv(who, usage);
} else {
return getrusage$nt(who, usage);
}
}

View file

@ -0,0 +1,30 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/conv/conv.h"
#include "libc/sysv/consts/prio.h"
#include "libc/sysv/errfuns.h"
textwindows int getsetpriority$nt(int which, unsigned who, int value,
int (*impl)(int)) {
if (which != PRIO_PROCESS && which != PRIO_PGRP) return einval();
if (who && abs(who) != getpid() && abs(who) != gettid()) return eopnotsupp();
return impl(value);
}

40
libc/calls/gettid.c Normal file
View file

@ -0,0 +1,40 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/nt/thread.h"
/**
* Returns current thread id.
* @asyncsignalsafe
*/
uint32_t gettid(void) {
if (!IsWindows()) {
uint32_t res;
res = gettid$sysv();
if (res <= 0) {
res = getpid();
}
return res;
} else {
return GetCurrentThreadId();
}
}

73
libc/calls/getuid.c Normal file
View file

@ -0,0 +1,73 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/macros.h"
#include "libc/nt/accounting.h"
#include "libc/runtime/runtime.h"
#include "libc/str/knuthmultiplicativehash.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/auxv.h"
static textwindows noinline uint32_t GetUserNameHash(void) {
char16_t buf[257];
uint32_t size = ARRAYLEN(buf);
GetUserName(&buf, &size);
return KnuthMultiplicativeHash32(buf, size >> 1);
}
static uint32_t getuidgid(int at, uint32_t impl(void)) {
if (!IsWindows()) {
if (at != -1) {
return getauxval(at);
} else {
return impl();
}
} else {
return GetUserNameHash();
}
}
/**
* Returns real user id of process.
*
* This never fails. On Windows, which doesn't really have this concept,
* we return a deterministic value that's likely to work. On Linux, this
* is fast.
*
* @asyncsignalsafe
*/
uint32_t getuid(void) {
return getuidgid(AT_UID, getuid$sysv);
}
/**
* Returns real group id of process.
*
* This never fails. On Windows, which doesn't really have this concept,
* we return a deterministic value that's likely to work. On Linux, this
* is fast.
*
* @asyncsignalsafe
*/
uint32_t getgid(void) {
return getuidgid(AT_GID, getgid$sysv);
}

22
libc/calls/grantpt.c Normal file
View file

@ -0,0 +1,22 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
int grantpt(int fd) { return 0; }

44
libc/calls/growfds.c Normal file
View file

@ -0,0 +1,44 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/assert.h"
#include "libc/bits/bits.h"
#include "libc/calls/internal.h"
#include "libc/mem/mem.h"
#include "libc/sysv/errfuns.h"
int growfds(void) {
size_t i, n;
struct Fd *p;
if (weaken(realloc)) {
if ((p = weaken(realloc)(g_fds.p != g_fds.__init_p ? g_fds.p : NULL,
(n = ((i = g_fds.n) * 2)) * sizeof(*p)))) {
do {
p[i++].kind = kFdEmpty;
} while (i < n);
g_fds.p = p;
g_fds.n = n;
return 0;
} else {
return enomem();
}
} else {
return emfile();
}
}

41
libc/calls/hefty/access.c Normal file
View file

@ -0,0 +1,41 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/dce.h"
#include "libc/calls/internal.h"
#include "libc/calls/calls.h"
#include "libc/sysv/consts/at.h"
/**
* Checks if effective user can access path in particular ways.
*
* @param path is a filename or directory
* @param mode can be R_OK, W_OK, X_OK, F_OK
* @return 0 if ok, or -1 and sets errno
* @asyncsignalsafe
*/
int access(const char *path, int mode) {
if (!IsWindows()) {
return faccessat$sysv(AT_FDCWD, path, mode, 0);
} else {
char16_t path16[PATH_MAX];
if (mkntpath(path, path16) == -1) return -1;
return ntaccesscheck(path16, mode);
}
}

170
libc/calls/hefty/commandv.c Normal file
View file

@ -0,0 +1,170 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/alg/alg.h"
#include "libc/bits/progn.h"
#include "libc/bits/safemacros.h"
#include "libc/calls/calls.h"
#include "libc/conv/conv.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/mem/mem.h"
#include "libc/nt/ntdll.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/ok.h"
#include "libc/sysv/errfuns.h"
static struct critbit0 g_commandv;
textstartup static void g_commandv_init(void) {
__cxa_atexit(critbit0_clear, &g_commandv, NULL);
}
const void *const g_commandv_ctor[] initarray = {g_commandv_init};
static int accessexe(char pathname[hasatleast PATH_MAX], size_t len,
const char *ext) {
len = stpcpy(&pathname[len], ext) - &pathname[0];
if (access(pathname, X_OK) != -1) {
return len;
} else {
return -1;
}
}
static int accesscmd(char pathname[hasatleast PATH_MAX], const char *path,
const char *name, size_t namelen) { /* cf. %PATHEXT% */
int rc;
char *p;
bool hasdot;
size_t pathlen, len;
pathlen = strlen(path);
if (pathlen + 1 + namelen + 1 + 4 + 1 > PATH_MAX) return -1;
p = mempcpy(pathname, path, pathlen);
if (pathlen) *p++ = '/';
p = mempcpy(p, name, namelen);
len = p - &pathname[0];
hasdot = !!memchr(basename(name), '.', namelen);
if ((hasdot && (rc = accessexe(pathname, len, "")) != -1) ||
(!hasdot &&
((rc = accessexe(pathname, len, ".com")) != -1 ||
(IsWindows() && (rc = accessexe(pathname, len, ".exe")) != -1) ||
(!IsWindows() && (rc = accessexe(pathname, len, "")) != -1)))) {
return rc;
} else {
return -1;
}
}
static int searchcmdpath(char pathname[hasatleast PATH_MAX], const char *name,
size_t namelen) {
int rc;
char *ep, *path, *pathtok;
struct critbit0 deduplicate;
rc = -1;
pathtok = ep =
strdup(firstnonnull(getenv("PATH"), "/bin:/usr/local/bin:/usr/bin"));
memset(&deduplicate, 0, sizeof(deduplicate));
while ((path = strsep(&pathtok, IsWindows() ? ";" : ":"))) {
if (strchr(path, '=')) continue;
if (!critbit0_insert(&deduplicate, path)) continue;
if ((rc = accesscmd(pathname, path, name, namelen)) != -1) {
break;
}
}
critbit0_clear(&deduplicate);
free(ep);
return rc;
}
static char *mkcmdquery(const char *name, size_t namelen,
char scratch[hasatleast PATH_MAX]) {
char *p;
if (namelen + 1 + 1 > PATH_MAX) return NULL;
p = mempcpy(scratch, name, namelen);
*p++ = '=';
*p++ = '\0';
if (IsWindows() || IsXnu()) strntolower(scratch, namelen);
return &scratch[0];
}
static const char *cachecmd(const char *name, size_t namelen,
const char *pathname, size_t pathnamelen) {
size_t entrylen;
char *res, *entry;
if ((entry = malloc((entrylen = namelen + 1 + pathnamelen) + 1))) {
mkcmdquery(name, namelen, entry);
res = memcpy(&entry[namelen + 1], pathname, pathnamelen + 1);
critbit0_emplace(&g_commandv, entry, entrylen);
} else {
res = NULL;
}
return res;
}
static const char *getcmdcache(const char *name, size_t namelen,
char scratch[hasatleast PATH_MAX]) {
const char *entry;
if ((entry = critbit0_get(&g_commandv, mkcmdquery(name, namelen, scratch)))) {
return &entry[namelen + 1];
}
return NULL;
}
noinline static const char *findcmdpath(const char *name,
char pathname[hasatleast PATH_MAX]) {
char *p;
int rc, olderr;
size_t len;
olderr = errno;
if (!(len = strlen(name))) return PROGN(enoent(), NULL);
if (memchr(name, '=', len)) return PROGN(einval(), NULL);
if ((p = getcmdcache(name, len, pathname)) ||
(((IsWindows() &&
((rc = accesscmd(pathname, kNtSystemDirectory, name, len)) != -1 ||
(rc = accesscmd(pathname, kNtWindowsDirectory, name, len)) != -1)) ||
(rc = accesscmd(pathname, "", name, len)) != -1 ||
(!strpbrk(name, "/\\") &&
(rc = searchcmdpath(pathname, name, len)) != -1)) &&
(p = cachecmd(name, len, pathname, rc)))) {
errno = olderr;
return p;
} else {
return NULL;
}
}
/**
* Resolves pathname of executable.
*
* This does the same thing as `command -v` in bourne shell. Path
* lookups are cached for the lifetime of the process. Paths with
* multiple components will skip the resolution process. Undotted
* basenames get automatic .com and .exe suffix resolution on all
* platforms. Windows' system directories will always trump PATH.
*
* @return execve()'able path, or NULL w/ errno
* @errno ENOENT, EACCES, ENOMEM
* @see free(), execvpe()
*/
const char *commandv(const char *name) {
char pathname[PATH_MAX];
return findcmdpath(name, pathname);
}

View file

@ -0,0 +1,190 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/bits/progn.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/dirent.h"
#include "libc/dce.h"
#include "libc/mem/mem.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/win32finddata.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/dt.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h"
struct dirstream {
int64_t tell;
int64_t fd;
union {
struct {
unsigned buf_pos;
unsigned buf_end;
char buf[BUFSIZ];
};
struct {
struct dirent winent;
char __d_name[PATH_MAX];
bool isdone;
struct NtWin32FindData windata;
};
};
};
static textwindows noinline DIR *opendir$nt(const char *name) {
int len;
DIR *res;
char16_t name16[PATH_MAX];
if ((len = mkntpath(name, name16)) == -1) return NULL;
if (len + 2 + 1 > PATH_MAX) return PROGN(enametoolong(), NULL);
if (name16[len - 1] == u'/' || name16[len - 1] == u'\\') {
name16[--len] = u'\0';
}
name16[len++] = u'/';
name16[len++] = u'*';
name16[len] = u'\0';
if (!(res = calloc(1, sizeof(DIR)))) return NULL;
if ((res->fd = FindFirstFile(name16, &res->windata)) != -1) {
return res;
} else {
winerr();
free(res);
return NULL;
}
}
/**
* Opens directory so readdir() and closedir() may be called.
*
* @returns newly allocated DIR object, or NULL w/ errno
* @errors ENOENT, ENOTDIR, EACCES, EMFILE, ENFILE, ENOMEM
*/
DIR *opendir(const char *name) {
if (!IsWindows() && !IsXnu()) {
int fd;
DIR *res = NULL;
if ((fd = open(name, O_RDONLY | O_DIRECTORY | O_CLOEXEC, 0)) != -1) {
if (!(res = fdopendir(fd))) close(fd);
}
return res;
} else if (IsWindows()) {
return opendir$nt(name);
} else {
enosys(); /* TODO(jart): Implement me! */
return NULL;
}
}
/**
* Creates directory object for file descriptor.
*
* @param fd gets owned by this function, if it succeeds
* @return new directory object, which must be freed by closedir(),
* or NULL w/ errno
* @errors ENOMEM and fd is closed
*/
DIR *fdopendir(int fd) {
if (!IsWindows() && !IsXnu()) {
DIR *dir;
if ((dir = calloc(1, sizeof(*dir)))) {
dir->fd = fd;
return dir;
}
} else {
enosys(); /* TODO(jart): Implement me! */
}
return NULL;
}
/**
* Reads next entry from DIR.
*
* This API doesn't define any particular ordering.
*
* @param dir is the object opendir() or fdopendir() returned
* @return next entry or NULL on end or error, which can be
* differentiated by setting errno to 0 beforehand
*/
struct dirent *readdir(DIR *dir) {
if (!IsWindows()) {
if (dir->buf_pos >= dir->buf_end) {
int rc;
if (!(rc = getdents(dir->fd, dir->buf, BUFSIZ)) || rc == -1) {
return NULL;
}
dir->buf_pos = 0;
dir->buf_end = rc;
}
/* TODO(jart): Check FreeBSD and OpenBSD again regarding this */
char *record = dir->buf + dir->buf_pos;
char *name = record + 8 + 8 + 2;
size_t namelen = strlen(name);
unsigned char dtype = name[namelen + 1];
memmove(name + 1, name, namelen + 1); /* shove forward one byte */
*name = dtype; /* is dirent d_type field */
struct dirent *ent = (void *)record;
dir->buf_pos += ent->d_reclen;
dir->tell = ent->d_off;
return ent;
} else {
if (dir->isdone) return NULL;
struct dirent *ent = &dir->winent;
memset(ent, 0, sizeof(*ent));
ent->d_reclen =
sizeof(*ent) +
tprecode16to8(ent->d_name, PATH_MAX, dir->windata.cFileName) + 1;
dir->isdone = FindNextFile(dir->fd, &dir->windata);
return ent;
}
}
/**
* Closes directory object returned by opendir().
* @return 0 on success or -1 w/ errno
*/
int closedir(DIR *dir) {
int rc;
if (dir) {
if (!IsWindows()) {
rc = close(dir->fd);
} else {
rc = FindClose(dir->fd) ? 0 : winerr();
}
free(dir);
} else {
rc = 0;
}
return rc;
}
/**
* Returns current byte offset into directory data.
*/
long telldir(DIR *dir) {
return dir->tell;
}
/**
* Returns file descriptor associated with DIR object.
*/
int dirfd(DIR *dir) {
return dir->fd;
}

47
libc/calls/hefty/execl.c Normal file
View file

@ -0,0 +1,47 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/calls/hefty/mkvarargv.h"
#include "libc/calls/calls.h"
/**
* Executes program, with current environment.
*
* The current process is replaced with the executed one.
*
* @param prog will not be PATH searched, see execlp()
* @param arg[0] is the name of the program to run
* @param arg[1,n-2] optionally specify program arguments
* @param arg[n-1] is NULL
* @return doesn't return on success, otherwise -1 w/ errno
* @notasyncsignalsafe (TODO)
*/
int execl(const char *exe, const char *arg, ... /*, NULL*/) {
va_list va;
void *argv;
va_start(va, arg);
if ((argv = mkvarargv(arg, va))) {
execve(exe, argv, environ);
free(argv);
}
va_end(va);
return -1;
}

48
libc/calls/hefty/execle.c Normal file
View file

@ -0,0 +1,48 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/mem/mem.h"
#include "libc/calls/hefty/mkvarargv.h"
#include "libc/calls/calls.h"
/**
* Executes program, with custom environment.
*
* The current process is replaced with the executed one.
*
* @param prog will not be PATH searched, see commandv()
* @param arg[0] is the name of the program to run
* @param arg[1,n-3] optionally specify program arguments
* @param arg[n-2] is NULL
* @param arg[n-1] is a pointer to a ["key=val",...,NULL] array
* @return doesn't return on success, otherwise -1 w/ errno
* @notasyncsignalsafe (TODO)
*/
int execle(const char *exe, const char *arg,
... /*, NULL, char *const envp[] */) {
va_list va;
void *argv;
va_start(va, arg);
if ((argv = mkvarargv(arg, va))) {
execve(exe, argv, va_arg(va, char *const *));
free(argv);
}
va_end(va);
return -1;
}

50
libc/calls/hefty/execlp.c Normal file
View file

@ -0,0 +1,50 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/calls/hefty/mkvarargv.h"
#include "libc/calls/calls.h"
/**
* Executes program, with PATH search and current environment.
*
* The current process is replaced with the executed one.
*
* @param prog is program to launch (may be PATH searched)
* @param arg[0] is the name of the program to run
* @param arg[1,n-2] optionally specify program arguments
* @param arg[n-1] is NULL
* @return doesn't return on success, otherwise -1 w/ errno
* @notasyncsignalsafe
*/
int execlp(const char *prog, const char *arg, ... /*, NULL*/) {
char *exe;
if ((exe = commandv(prog))) {
va_list va;
void *argv;
va_start(va, arg);
if ((argv = mkvarargv(arg, va))) {
execve(exe, argv, environ);
free(argv);
}
va_end(va);
}
return -1;
}

29
libc/calls/hefty/execv.c Normal file
View file

@ -0,0 +1,29 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/runtime/runtime.h"
#include "libc/calls/calls.h"
/**
* Replaces process with specific program, using default environment.
* @asyncsignalsafe
*/
int execv(const char *exe, char *const argv[]) {
return execve(exe, argv, environ);
}

View file

@ -0,0 +1,55 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/hefty/internal.h"
#include "libc/calls/hefty/ntspawn.h"
#include "libc/calls/internal.h"
#include "libc/nt/enum/startf.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/startupinfo.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/fileno.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/sock.h"
static textwindows int64_t passstdhand$nt(int fd) {
if (g_fds.p[fd].kind != kFdEmpty &&
!(g_fds.p[fd].flags &
(g_fds.p[fd].kind == kFdSocket ? SOCK_CLOEXEC : O_CLOEXEC))) {
return g_fds.p[fd].handle;
} else {
return -1;
}
}
textwindows int execve$nt(const char *program, char *const argv[],
char *const envp[]) {
struct NtStartupInfo startinfo;
memset(&startinfo, 0, sizeof(startinfo));
startinfo.cb = sizeof(struct NtStartupInfo);
startinfo.dwFlags = kNtStartfUsestdhandles;
startinfo.hStdInput = passstdhand$nt(STDIN_FILENO);
startinfo.hStdOutput = passstdhand$nt(STDOUT_FILENO);
startinfo.hStdError = passstdhand$nt(STDERR_FILENO);
if (ntspawn(program, argv, envp, NULL, NULL, true, 0, NULL, &startinfo,
NULL) != -1) {
for (;;) TerminateProcess(GetCurrentProcess(), 0);
}
return -1;
}

43
libc/calls/hefty/execve.c Normal file
View file

@ -0,0 +1,43 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/hefty/internal.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
/**
* Replaces current process with program.
*
* @param program will not be PATH searched, see commandv()
* @param argv[0] is the name of the program to run
* @param argv[1,n-2] optionally specify program arguments
* @param argv[n-1] is NULL
* @param envp[0,n-2] specifies "foo=bar" environment variables
* @param envp[n-1] is NULL
* @return doesn't return, or -1 w/ errno
* @asyncsignalsafe
*/
int execve(const char *program, char *const argv[], char *const envp[]) {
if (!IsWindows()) {
return execve$sysv(program, argv, envp);
} else {
return execve$nt(program, argv, envp);
}
}

29
libc/calls/hefty/execvp.c Normal file
View file

@ -0,0 +1,29 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/runtime/runtime.h"
#include "libc/calls/calls.h"
/**
* Replaces process, with path search, using default environment.
* @notasyncsignalsafe
*/
int execvp(const char *file, char *const argv[]) {
return execvpe(file, argv, environ);
}

View file

@ -0,0 +1,40 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/mem/mem.h"
#include "libc/calls/calls.h"
/**
* Executes program, with path environment search.
*
* The current process is replaced with the executed one.
*
* @param prog is the program to launch
* @param argv is [file,argv..argvₙ,NULL]
* @param envp is ["key=val",...,NULL]
* @return doesn't return on success, otherwise -1 w/ errno
* @notasyncsignalsafe
*/
int execvpe(const char *prog, char *const argv[], char *const *envp) {
char *exe;
if ((exe = commandv(prog))) {
execve(exe, argv, envp);
}
return -1;
}

View file

@ -0,0 +1,44 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/errfuns.h"
/**
* Checks if effective user can access path in particular ways.
*
* @param dirfd is usually AT_FDCWD
* @param path is a filename or directory
* @param flags can be R_OK, W_OK, X_OK, F_OK
* @return 0 if ok, or -1 and sets errno
* @asyncsignalsafe
*/
int faccessat(int dirfd, const char *path, int mode, uint32_t flags) {
if (!IsWindows()) {
return faccessat$sysv(dirfd, path, mode, flags);
} else {
char16_t path16[PATH_MAX];
if (dirfd != AT_FDCWD || flags) return einval();
if (mkntpath(path, path16) == -1) return -1;
return ntaccesscheck(path16, mode);
}
}

View file

@ -0,0 +1,78 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/alg/alg.h"
#include "libc/bits/safemacros.h"
#include "libc/calls/calls.h"
#include "libc/errno.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/madv.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
static void *filecmp$mmap(int fd, size_t size) {
return size ? mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0) : NULL;
}
/**
* Compares contents of files with memcmp().
*
* @return 0, 0, or 0 based on comparison; or 0 on error, in which
* case we make our best effort to sift failing filenames rightward,
* and errno can be set to 0 beforehand to differentiate errors
*/
int filecmp(const char *pathname1, const char *pathname2) {
int res, olderr;
int fd1 = -1;
int fd2 = -1;
char *addr1 = MAP_FAILED;
char *addr2 = MAP_FAILED;
size_t size1 = 0;
size_t size2 = 0;
if ((fd1 = open(pathname1, O_RDONLY)) != -1 &&
(fd2 = open(pathname2, O_RDONLY)) != -1 &&
(size1 = getfiledescriptorsize(fd1)) != -1 &&
(size2 = getfiledescriptorsize(fd2)) != -1 &&
(addr1 = filecmp$mmap(fd1, size1)) != MAP_FAILED &&
(addr2 = filecmp$mmap(fd2, size2)) != MAP_FAILED) {
olderr = errno;
madvise(addr1, size1, MADV_WILLNEED | MADV_SEQUENTIAL);
madvise(addr2, size2, MADV_WILLNEED | MADV_SEQUENTIAL);
errno = olderr;
res = memcmp(addr1, addr2, min(size1, size2));
if (!res && size1 != size2) {
char kNul = '\0';
if (size1 > size2) {
res = cmpub(addr1 + size2, &kNul);
} else {
res = cmpub(addr2 + size1, &kNul);
}
}
} else {
res = cmpuq(&fd1, &fd2) | 1;
}
olderr = errno;
munmap(addr1, size1);
munmap(addr2, size2);
close(fd1);
close(fd2);
errno = olderr;
return res;
}

View file

@ -0,0 +1,40 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/safemacros.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/calls/calls.h"
#include "libc/sysv/errfuns.h"
/**
* Returns current working directory.
*
* If the PWD environment variable is set, that'll be returned (since
* it's faster than issuing a system call).
*
* @return pointer that must be free()'d, or NULL w/ errno
*/
nodiscard char *get_current_dir_name(void) {
char *buf, *res;
if ((res = getenv("PWD"))) return strdup(res);
if (!(buf = malloc(PATH_MAX))) return NULL;
if (!(res = (getcwd)(buf, PATH_MAX))) free(buf);
return res;
}

73
libc/calls/hefty/hefty.mk Normal file
View file

@ -0,0 +1,73 @@
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
#
# SYNOPSIS
#
# Cosmopolitan System Call Compatibility Layer
#
# DESCRIPTION
#
# This subpackage exports functions traditionally understood as system
# calls that Cosmopolitan needs to wrap in a nontrivial way, requiring
# things like dynamic memory allocation.
PKGS += LIBC_CALLS_HEFTY
LIBC_CALLS_HEFTY_ARTIFACTS += LIBC_CALLS_HEFTY_A
LIBC_CALLS_HEFTY = $(LIBC_CALLS_HEFTY_A_DEPS) $(LIBC_CALLS_HEFTY_A)
LIBC_CALLS_HEFTY_A = o/$(MODE)/libc/calls/hefty/hefty.a
LIBC_CALLS_HEFTY_A_FILES := $(wildcard libc/calls/hefty/*)
LIBC_CALLS_HEFTY_A_HDRS = $(filter %.h,$(LIBC_CALLS_HEFTY_A_FILES))
LIBC_CALLS_HEFTY_A_SRCS_S = $(filter %.S,$(LIBC_CALLS_HEFTY_A_FILES))
LIBC_CALLS_HEFTY_A_SRCS_C = $(filter %.c,$(LIBC_CALLS_HEFTY_A_FILES))
LIBC_CALLS_HEFTY_A_SRCS = \
$(LIBC_CALLS_HEFTY_A_SRCS_S) \
$(LIBC_CALLS_HEFTY_A_SRCS_C)
LIBC_CALLS_HEFTY_A_OBJS = \
$(LIBC_CALLS_HEFTY_A_SRCS:%=o/$(MODE)/%.zip.o) \
$(LIBC_CALLS_HEFTY_A_SRCS_S:%.S=o/$(MODE)/%.o) \
$(LIBC_CALLS_HEFTY_A_SRCS_C:%.c=o/$(MODE)/%.o)
LIBC_CALLS_HEFTY_A_CHECKS = \
$(LIBC_CALLS_HEFTY_A).pkg \
$(LIBC_CALLS_HEFTY_A_HDRS:%=o/$(MODE)/%.ok)
LIBC_CALLS_HEFTY_A_DIRECTDEPS = \
LIBC_ALG \
LIBC_CONV \
LIBC_FMT \
LIBC_MEM \
LIBC_STR \
LIBC_NEXGEN32E \
LIBC_RUNTIME \
LIBC_CALLS \
LIBC_STUBS \
LIBC_NT_KERNELBASE \
LIBC_SYSV_CALLS \
LIBC_SYSV
LIBC_CALLS_HEFTY_A_DEPS := \
$(call uniq,$(foreach x,$(LIBC_CALLS_HEFTY_A_DIRECTDEPS),$($(x))))
$(LIBC_CALLS_HEFTY_A): \
libc/calls/hefty/ \
$(LIBC_CALLS_HEFTY_A).pkg \
$(LIBC_CALLS_HEFTY_A_OBJS)
$(LIBC_CALLS_HEFTY_A).pkg: \
$(LIBC_CALLS_HEFTY_A_OBJS) \
$(foreach x,$(LIBC_CALLS_HEFTY_A_DIRECTDEPS),$($(x)_A).pkg)
LIBC_CALLS_HEFTY_LIBS = $(foreach x,$(LIBC_CALLS_HEFTY_ARTIFACTS),$($(x)))
LIBC_CALLS_HEFTY_SRCS = $(foreach x,$(LIBC_CALLS_HEFTY_ARTIFACTS),$($(x)_SRCS))
LIBC_CALLS_HEFTY_HDRS = $(foreach x,$(LIBC_CALLS_HEFTY_ARTIFACTS),$($(x)_HDRS))
LIBC_CALLS_HEFTY_BINS = $(foreach x,$(LIBC_CALLS_HEFTY_ARTIFACTS),$($(x)_BINS))
LIBC_CALLS_HEFTY_CHECKS = $(foreach x,$(LIBC_CALLS_HEFTY_ARTIFACTS),$($(x)_CHECKS))
LIBC_CALLS_HEFTY_OBJS = $(foreach x,$(LIBC_CALLS_HEFTY_ARTIFACTS),$($(x)_OBJS))
LIBC_CALLS_HEFTY_TESTS = $(foreach x,$(LIBC_CALLS_HEFTY_ARTIFACTS),$($(x)_TESTS))
$(LIBC_CALLS_HEFTY_OBJS): $(BUILD_FILES) libc/calls/hefty/hefty.mk
.PHONY: o/$(MODE)/libc/calls/hefty
o/$(MODE)/libc/calls/hefty: $(LIBC_CALLS_HEFTY_CHECKS)

View file

@ -0,0 +1,14 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_HEFTY_INTERNAL_H_
#define COSMOPOLITAN_LIBC_CALLS_HEFTY_INTERNAL_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
int execve$nt(const char *, char *const[], char *const[]) hidden;
int spawnve$nt(unsigned, int[3], const char *, char *const[],
char *const[]) hidden;
int spawnve$sysv(unsigned, int[3], const char *, char *const[],
char *const[]) hidden;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_HEFTY_INTERNAL_H_ */

View file

@ -0,0 +1,98 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/alg/arraylist2.h"
#include "libc/calls/calls.h"
#include "libc/calls/hefty/ntspawn.h"
#include "libc/conv/conv.h"
#include "libc/macros.h"
#include "libc/mem/mem.h"
#include "libc/nexgen32e/hascharacter.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/fileno.h"
#include "libc/sysv/errfuns.h"
#define APPENDCHAR(C) \
do { \
if (mkntcmdline_append(&cmdline_p, &cmdline_i, &cmdline_n, C) == -1) { \
goto error; \
} \
} while (0)
static int mkntcmdline_append(char16_t **p, size_t *i, size_t *n, char16_t c) {
return APPEND(p, i, n, &c);
}
/**
* Converts System V argv to Windows-style command line.
*
* Escaping is performed and it's designed to round-trip with
* getdosargv() or getdosargv(). This function does NOT escape
* command interpreter syntax, e.g. $VAR (sh), %VAR% (cmd).
*
* @param argv is an a NULL-terminated array of UTF-8 strings
* @return freshly allocated lpCommandLine or NULL w/ errno
* @kudos Daniel Colascione for teaching how to quote
* @see libc/runtime/dosargv.c
*/
hidden textwindows nodiscard char16_t *mkntcmdline(char *const argv[]) {
wint_t wc;
size_t i, j;
char16_t cbuf[2];
char16_t *cmdline_p = NULL;
size_t cmdline_i = 0;
size_t cmdline_n = 0;
if (argv[0]) {
for (i = 0; argv[i]; ++i) {
if (i) APPENDCHAR(u' ');
bool needsquote = !argv[i] || !!argv[i][strcspn(argv[i], " \t\n\v\"")];
if (needsquote) APPENDCHAR(u'"');
for (j = 0;;) {
if (needsquote) {
int slashes = 0;
while (argv[i][j] && argv[i][j] == u'\\') slashes++, j++;
slashes <<= 1;
if (argv[i][j] == u'"') slashes++;
while (slashes--) APPENDCHAR(u'\\');
}
if (!argv[i][j]) break;
j += abs(tpdecode(&argv[i][j], &wc));
if (CONCAT(&cmdline_p, &cmdline_i, &cmdline_n, cbuf,
abs(pututf16(cbuf, ARRAYLEN(cbuf), wc, false))) == -1) {
goto error;
}
}
if (needsquote) APPENDCHAR(u'"');
}
APPENDCHAR(u'\0');
if (cmdline_i > CMD_MAX) {
e2big();
goto error;
}
} else {
einval();
}
return cmdline_p;
error:
free(cmdline_p);
return NULL;
}
#undef APPENDCHAR

View file

@ -0,0 +1,69 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/alg/arraylist2.h"
#include "libc/calls/hefty/ntspawn.h"
#include "libc/conv/conv.h"
#include "libc/macros.h"
#include "libc/mem/mem.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
/**
* Copies sorted environment variable block for Windows.
*
* This is designed to meet the requirements of CreateProcess().
*
* @param envp is an a NULL-terminated array of UTF-8 strings
* @return freshly allocated lpEnvironment or NULL w/ errno
*/
textwindows char16_t *mkntenvblock(char *const envp[]) {
size_t block_i = 0;
size_t block_n = 0;
char16_t *block_p = NULL;
size_t i, j;
if (!(envp = sortenvp(envp))) goto error;
const char16_t kNul = u'\0';
for (i = 0; envp[i]; ++i) {
unsigned consumed;
for (j = 0;; j += consumed) {
wint_t wc;
char16_t cbuf[2];
consumed = abs(tpdecode(&envp[i][j], &wc));
if (CONCAT(&block_p, &block_i, &block_n, cbuf,
abs(pututf16(cbuf, ARRAYLEN(cbuf), wc, false))) == -1) {
goto error;
}
if (!wc) break;
}
}
if (APPEND(&block_p, &block_i, &block_n, &kNul) == -1) {
goto error;
}
if (block_i > ENV_MAX) {
e2big();
goto error;
}
free(envp);
return block_p;
error:
free(envp);
free(block_p);
return NULL;
}

View file

@ -0,0 +1,32 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_HEFTY_MKVARARGV_H_
#define COSMOPOLITAN_LIBC_CALLS_HEFTY_MKVARARGV_H_
#include "libc/alg/arraylist2.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
/**
* Turns variadic program arguments into array.
*
* This is a support function for execl(), execlp(), spawnl(), etc.
*
* @note type signatures are fubar for these functions
*/
forceinline void *mkvarargv(const char *arg1, va_list va) {
size_t i, n;
const char **p, *arg;
i = 0;
n = 0;
p = NULL;
arg = arg1;
do {
if (APPEND(&p, &i, &n, &arg) == -1) {
free(p);
return NULL;
}
} while ((arg = va_arg(va, const char *)));
return p;
}
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_HEFTY_MKVARARGV_H_ */

View file

@ -0,0 +1,87 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/mem/mem.h"
#include "libc/nt/enum/accessmask.h"
#include "libc/nt/enum/securityinformation.h"
#include "libc/nt/errors.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/genericmapping.h"
#include "libc/nt/struct/privilegeset.h"
#include "libc/nt/struct/securitydescriptor.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/calls/internal.h"
#include "libc/calls/calls.h"
#include "libc/sysv/consts/ok.h"
/**
* Checks if current process has access to folder or file.
*
* @param flags can have R_OK, W_OK, X_OK, etc.
* @return 0 if authorized, or -1 w/ errno
* @kudos Aaron Ballman for teaching how to do this
* @see libc/sysv/consts.sh
*/
textwindows int ntaccesscheck(const char16_t *pathname, uint32_t flags) {
int rc;
bool32 result;
int64_t hToken, hImpersonatedToken;
uint32_t secsize, granted, privsize;
struct NtPrivilegeSet privileges;
struct NtGenericMapping mapping;
struct NtSecurityDescriptor security;
struct NtSecurityDescriptor *psecurity;
const uint32_t request = kNtOwnerSecurityInformation |
kNtGroupSecurityInformation |
kNtDaclSecurityInformation;
granted = 0;
result = false;
psecurity = &security;
secsize = sizeof(security);
privsize = sizeof(privileges);
memset(&privileges, 0, sizeof(privileges));
mapping.GenericRead = kNtFileGenericRead;
mapping.GenericWrite = kNtFileGenericWrite;
mapping.GenericExecute = kNtFileGenericExecute;
mapping.GenericAll = kNtFileAllAccess;
MapGenericMask(&flags, &mapping);
hImpersonatedToken = hToken = -1;
if ((GetFileSecurity(pathname, request, psecurity, 0, &secsize) ||
(GetLastError() == kNtErrorInsufficientBuffer &&
(psecurity = malloc(secsize)) &&
GetFileSecurity(pathname, request, psecurity, secsize, &secsize))) &&
OpenProcessToken(GetCurrentProcess(),
kNtTokenImpersonate | kNtTokenQuery | kNtTokenDuplicate |
kNtStandardRightsRead,
&hToken) &&
DuplicateToken(hToken, kNtSecurityImpersonation, &hImpersonatedToken) &&
AccessCheck(psecurity, hImpersonatedToken, flags, &mapping, &privileges,
&privsize, &granted, &result) &&
(result || flags == F_OK)) {
rc = 0;
} else {
rc = winerr();
}
free_s(&psecurity);
close(hImpersonatedToken);
close(hToken);
return rc;
}

View file

@ -0,0 +1,88 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/alg/alg.h"
#include "libc/alg/arraylist.h"
#include "libc/bits/bits.h"
#include "libc/bits/safemacros.h"
#include "libc/calls/calls.h"
#include "libc/calls/hefty/ntspawn.h"
#include "libc/calls/internal.h"
#include "libc/conv/conv.h"
#include "libc/nt/process.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/fileno.h"
#include "libc/sysv/errfuns.h"
/**
* Spawns process on Windows NT.
*
* This function delegates to CreateProcess() with UTF-8 UTF-16
* translation and argv escaping. Please note this will NOT escape
* command interpreter syntax.
*
* @param program will not be PATH searched, see commandv()
* @param argv[0] is the name of the program to run
* @param argv[1,n-2] optionally specifies program arguments
* @param argv[n-1] is NULL
* @param envp[𝟶,m-2] specifies "foo=bar" environment variables, which
* don't need to be passed in sorted order; however, this function
* goes faster the closer they are to sorted
* @param envp[m-1] is NULL
* @param bInheritHandles means handles already marked inheritable will
* be inherited; which, assuming the System V wrapper functions are
* being used, should mean (1) all files and sockets that weren't
* opened with O_CLOEXEC; and (2) all memory mappings
* @param opt_out_lpProcessInformation can be used to return process and
* thread IDs to parent, as well as open handles that need close()
* @return 0 on success, or -1 w/ errno
* @see spawnve() which abstracts this function
*/
textwindows int ntspawn(
const char *program, char *const argv[], char *const envp[],
struct NtSecurityAttributes *opt_lpProcessAttributes,
struct NtSecurityAttributes *opt_lpThreadAttributes, bool32 bInheritHandles,
uint32_t dwCreationFlags, const char16_t *opt_lpCurrentDirectory,
/*nodiscard*/ const struct NtStartupInfo *lpStartupInfo,
struct NtProcessInformation *opt_out_lpProcessInformation) {
int rc;
char16_t program16[PATH_MAX], *lpCommandLine, *lpEnvironment;
lpCommandLine = NULL;
lpEnvironment = NULL;
if (mkntpath(program, program16) != -1 &&
(lpCommandLine = mkntcmdline(argv)) &&
(lpEnvironment = mkntenvblock(envp))) {
if (CreateProcess(program16, lpCommandLine, opt_lpProcessAttributes,
opt_lpThreadAttributes, bInheritHandles,
dwCreationFlags | kNtCreateUnicodeEnvironment,
lpEnvironment, opt_lpCurrentDirectory, lpStartupInfo,
opt_out_lpProcessInformation)) {
rc = 0;
} else {
rc = winerr();
}
} else {
rc = -1;
}
free(lpCommandLine);
free(lpEnvironment);
return rc;
}

View file

@ -0,0 +1,20 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_HEFTY_NTSPAWN_H_
#define COSMOPOLITAN_LIBC_CALLS_HEFTY_NTSPAWN_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct NtProcessInformation;
struct NtSecurityAttributes;
struct NtStartupInfo;
char **sortenvp(char *const[]) hidden nodiscard paramsnonnull();
char16_t *mkntcmdline(char *const[]) hidden nodiscard paramsnonnull();
char16_t *mkntenvblock(char *const[]) hidden nodiscard paramsnonnull();
int ntspawn(const char *, char *const[], char *const[],
struct NtSecurityAttributes *, struct NtSecurityAttributes *,
bool32, uint32_t, const char16_t *, const struct NtStartupInfo *,
struct NtProcessInformation *) paramsnonnull((1, 2, 3, 9)) hidden;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_HEFTY_NTSPAWN_H_ */

View 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 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/safemacros.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/calls/calls.h"
/**
* Replaces tilde in path w/ user home folder.
*
* @param path is NULL propagating
* @return must be free()'d
*/
char *replaceuser(const char *path) {
char *res, *p;
const char *home;
size_t pathlen, homelen;
res = NULL;
if (path && *path++ == '~' && !isempty((home = getenv("HOME")))) {
while (*path == '/') path++;
pathlen = strlen(path);
homelen = strlen(home);
while (homelen && home[homelen - 1] == '/') homelen--;
if ((p = res = malloc(pathlen + 1 + homelen + 1))) {
p = mempcpy(p, home, homelen);
*p++ = '/';
memcpy(p, path, pathlen + 1);
}
}
return res;
}

89
libc/calls/hefty/slurp.c Normal file
View file

@ -0,0 +1,89 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/alg/arraylist2.h"
#include "libc/bits/safemacros.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h"
#include "libc/errno.h"
#include "libc/mem/mem.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/madv.h"
#include "libc/sysv/consts/o.h"
static size_t getfilesize(int fd) {
struct stat st;
st.st_size = 0;
fstat(fd, &st);
return st.st_size;
}
static size_t smudgefilesize(size_t size) {
return roundup(size, PAGESIZE) + PAGESIZE;
}
/**
* Reads entire file into memory.
*
* This function is fantastic for being lazy. It may waste space if the
* file is large, but it's implemented in a conscientious way that won't
* bomb the systemwide page cache. It means performance too, naturally.
*
* @return contents which must be free()'d or NULL w/ errno
*/
char *slurp(const char *path, size_t *opt_out_readlength) {
int fd;
ssize_t rc;
char *res, *p;
size_t i, n, got, want;
res = NULL;
if ((fd = open(path, O_RDONLY)) == -1) goto Failure;
n = getfilesize(fd);
/* TODO(jart): Fix this, it's totally broken */
if (!(res = valloc(smudgefilesize(n)))) goto Failure;
if (n > FRAMESIZE) fadvise(fd, 0, n, MADV_SEQUENTIAL);
i = 0;
for (;;) {
want = smudgefilesize(n - i);
TryAgain:
if ((rc = read(fd, &res[i], want)) == -1) {
if (errno == EINTR) goto TryAgain;
goto Failure;
}
got = (size_t)rc;
if (i + 1 >= n) {
if ((p = realloc(res, smudgefilesize((n += n >> 1))))) {
res = p;
} else {
goto Failure;
}
}
i += got;
if (got == 0) break;
if (got > want) abort();
}
if (opt_out_readlength) *opt_out_readlength = i;
res[i] = '\0';
close(fd);
return res;
Failure:
free(res);
close(fd);
return NULL;
}

View file

@ -0,0 +1,68 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/alg/alg.h"
#include "libc/alg/arraylist.h"
#include "libc/calls/hefty/ntspawn.h"
#include "libc/dce.h"
#include "libc/nexgen32e/tinystrcmp.h"
#include "libc/str/str.h"
static int sortenvpcb(const char **a, const char **b) { return strcmp(*a, *b); }
static void slowsort(char **a, int n) {
size_t i, j;
const char *t;
for (i = 1; i < n; ++i) {
j = i;
t = a[i];
while (j > 0 && tinystrcmp(t, a[j - 1]) < 0) {
a[j] = a[j - 1];
--j;
}
a[j] = t;
}
}
/**
* Copies environment variable pointers and sorts them.
*
* This is useful for (a) binary searching; and (b) keeping the NT
* Executive happy, which wants strings to be ordered by UNICODE
* codepoint identifiers. That's basically what uint8_t comparisons on
* UTF8-encoded data gives us.
*
* @param envp is a NULL-terminated string array
* @return newly allocated sorted copy of envp pointer array
*/
hidden textwindows nodiscard char **sortenvp(char *const envp[]) {
size_t count = 0;
while (envp[count]) count++;
size_t bytesize = (count + 1) * sizeof(char *);
char **copy = malloc(bytesize);
if (copy) {
memcpy(copy, envp, bytesize);
if (IsTiny()) {
slowsort(copy, count);
} else {
qsort(copy, count, sizeof(char *), (void *)sortenvpcb);
}
}
return copy;
}

26
libc/calls/hefty/spawn.h Normal file
View file

@ -0,0 +1,26 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_HEFTY_SPAWN_H_
#define COSMOPOLITAN_LIBC_CALLS_HEFTY_SPAWN_H_
#define SPAWN_DETACH 1
#define SPAWN_TABULARASA 2
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
int spawnve(unsigned, int[3], const char *, char *const[], char *const[])
paramsnonnull((3, 4, 5));
int spawnl(unsigned, int[3], const char *, const char *, ...) nullterminated()
paramsnonnull((3, 4));
int spawnlp(unsigned, int[3], const char *, const char *, ...) nullterminated()
paramsnonnull((3, 4));
int spawnle(unsigned, int[3], const char *, const char *, ...)
nullterminated((1)) paramsnonnull((3, 4));
int spawnv(unsigned, int[3], const char *, char *const[]) paramsnonnull((3, 4));
int spawnvp(unsigned, int[3], const char *, char *const[])
paramsnonnull((3, 4));
int spawnvpe(unsigned, int[3], const char *, char *const[], char *const[])
paramsnonnull((3, 4, 5));
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_HEFTY_SPAWN_H_ */

49
libc/calls/hefty/spawnl.c Normal file
View 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 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/hefty/mkvarargv.h"
#include "libc/calls/hefty/spawn.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
/**
* Launches program, with current environment.
*
* @param stdiofds may optionally be passed to customize standard i/o
* @param stdiofds[𝑖] may be -1 to receive a pipe() fd
* @param prog is program to launch (may be PATH searched)
* @param arg[0] is the name of the program to run
* @param arg[1,n-2] optionally specify program arguments
* @param arg[n-1] is NULL
* @return pid of child, or -1 w/ errno
*/
int spawnl(unsigned flags, int stdiofds[3], const char *exe, const char *arg,
... /*, NULL*/) {
int rc;
va_list va;
void *argv;
rc = -1;
va_start(va, arg);
if ((argv = mkvarargv(arg, va))) {
rc = spawnve(flags, stdiofds, exe, argv, environ);
free(argv);
}
va_end(va);
return rc;
}

View 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 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/hefty/mkvarargv.h"
#include "libc/calls/hefty/spawn.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
/**
* Launches program, with PATH search and current environment.
*
* @param stdiofds may optionally be passed to customize standard i/o
* @param stdiofds[𝑖] may be -1 to receive a pipe() fd
* @param prog is program to launch (may be PATH searched)
* @param arg[0] is the name of the program to run
* @param arg[1,n-2] optionally specify program arguments
* @param arg[n-1] is NULL
* @return pid of child, or -1 w/ errno
*/
nodiscard int spawnlp(unsigned flags, int stdiofds[3], const char *prog,
const char *arg, ... /*, NULL*/) {
int pid;
char *exe;
va_list va;
void *argv;
pid = -1;
if ((exe = commandv(prog))) {
va_start(va, arg);
if ((argv = mkvarargv(arg, va))) {
pid = spawnve(flags, stdiofds, exe, argv, environ);
free(argv);
}
va_end(va);
}
return pid;
}

View file

@ -0,0 +1,98 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/xchg.h"
#include "libc/calls/calls.h"
#include "libc/calls/hefty/internal.h"
#include "libc/calls/hefty/ntspawn.h"
#include "libc/calls/hefty/spawn.h"
#include "libc/calls/internal.h"
#include "libc/nt/enum/startf.h"
#include "libc/nt/files.h"
#include "libc/nt/ipc.h"
#include "libc/nt/process.h"
#include "libc/nt/runtime.h"
#include "libc/nt/startupinfo.h"
#include "libc/nt/struct/processinformation.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/fileno.h"
#include "libc/sysv/consts/o.h"
textwindows int spawnve$nt(unsigned flags, int stdiofds[3], const char *program,
char *const argv[], char *const envp[]) {
int pid;
size_t i;
int tubes[3];
int64_t handle, h, *x, *y;
struct NtStartupInfo sti;
struct NtProcessInformation procinfo;
handle = 0;
memset(&sti, 0, sizeof(sti));
sti.cb = sizeof(sti);
sti.dwFlags = kNtStartfUsestdhandles;
if ((pid = createfd()) == -1) return -1;
for (i = 0; i < 3; ++i) {
if (stdiofds[i] == -1) {
x = &h;
y = &sti.stdiofds[i];
if (kIoMotion[i]) xchg(&x, &y);
if ((tubes[i] = createfd()) != -1 &&
CreatePipe(x, y, &kNtIsInheritable, 0)) {
g_fds.p[tubes[i]].handle = h;
} else {
handle = -1;
}
} else {
sti.stdiofds[i] = g_fds.p[stdiofds[i]].handle;
}
}
if (handle != -1 &&
ntspawn(program, argv, envp, NULL, NULL,
(flags & SPAWN_TABULARASA) ? false : true,
(flags & SPAWN_DETACH)
? (kNtCreateNewProcessGroup | kNtDetachedProcess |
kNtCreateBreakawayFromJob)
: 0,
NULL, &sti, &procinfo) != -1) {
CloseHandle(procinfo.hThread);
handle = procinfo.hProcess;
}
for (i = 0; i < 3; ++i) {
if (stdiofds[i] == -1) {
if (handle != -1) {
stdiofds[i] = tubes[i];
g_fds.p[tubes[i]].kind = kFdFile;
g_fds.p[tubes[i]].flags = O_CLOEXEC;
CloseHandle(sti.stdiofds[i]);
} else {
CloseHandle(tubes[i]);
}
}
}
g_fds.p[pid].kind = kFdProcess;
g_fds.p[pid].handle = handle;
g_fds.p[pid].flags = flags;
return pid;
}

View file

@ -0,0 +1,121 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/hefty/internal.h"
#include "libc/calls/hefty/spawn.h"
#include "libc/calls/internal.h"
#include "libc/conv/conv.h"
#include "libc/dce.h"
#include "libc/mem/mem.h"
#include "libc/paths.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/consts/fileno.h"
#include "libc/sysv/consts/o.h"
int spawnve$sysv(unsigned flags, int stdiofds[3], const char *program,
char *const argv[], char *const envp[]) {
int rc, pid, fd;
size_t i, j, len;
int32_t tubes[3][2];
char **argv2, MZqFpD[8];
void *argv3;
pid = 0;
argv2 = NULL;
argv3 = argv;
/*
* αcτµαlly pδrταblε εxεcµταblε w/ thompson shell script
* morphology needs to be launched via command interpreter.
*/
if (endswith(program, ".com") || endswith(program, ".exe")) {
memset(MZqFpD, 0, sizeof(MZqFpD));
fd = openat$sysv(AT_FDCWD, program, O_RDONLY, 0);
read$sysv(fd, MZqFpD, sizeof(MZqFpD));
close$sysv(fd);
if (memcmp(MZqFpD, "MZqFpD", 6) == 0) {
/*
* If we got this:
*
* spawn(/bin/echo, [echo, hi, there])
*
* It will become this:
*
* spawn(/bin/sh, [sh, /bin/echo, hi, there])
*/
len = 1;
while (argv[len]) len++;
if ((argv2 = malloc((2 + len + 1) * sizeof(char *)))) {
i = 0, j = 1;
argv2[i++] = "sh";
argv2[i++] = program;
while (j < len) argv2[i++] = argv[j++];
argv2[i] = NULL;
argv3 = argv2;
program = "/bin/sh";
}
}
}
for (i = 0; i < 3; ++i) {
if (stdiofds[i] == -1) {
pid |= pipe$sysv(tubes[i]);
}
}
if (pid != -1) {
if ((pid = fork$sysv()) == 0) {
if (flags & SPAWN_DETACH) {
if (setsid() == -1) abort();
if ((rc = fork$sysv()) == -1) abort();
if (rc > 0) _exit(0);
}
for (i = 0; i < 3; ++i) {
if (stdiofds[i] == -1) {
close$sysv(tubes[i][kIoMotion[i]]);
fd = tubes[i][!kIoMotion[i]];
} else {
fd = stdiofds[i];
}
dup2$sysv(fd, i);
}
execve$sysv(program, argv3, envp);
abort();
}
}
for (i = 0; i < 3; ++i) {
if (stdiofds[i] == -1) {
close$sysv(tubes[i][!kIoMotion[i]]);
fd = tubes[i][kIoMotion[i]];
if (pid != -1) {
stdiofds[i] = fd;
} else {
close$sysv(fd);
}
}
}
if (argv2) free(argv2);
return pid;
}

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