mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-06 19:28:29 +00:00
Delete LIBC_CALLS_HEFTY
- fork() no longer requires malloc() - readdir() moved to LIBC_STDIO - Custom APIs moved to LIBC_X
This commit is contained in:
parent
c843243322
commit
23a14b537c
44 changed files with 95 additions and 168 deletions
|
@ -94,6 +94,4 @@ 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)
|
||||
o/$(MODE)/libc/calls: $(LIBC_CALLS_CHECKS)
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/hefty/copyfile.h"
|
||||
#include "libc/calls/copyfile.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/dce.h"
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_HEFTY_COPYFILE_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_HEFTY_COPYFILE_H_
|
||||
#ifndef COSMOPOLITAN_LIBC_CALLS_COPYFILE_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_COPYFILE_H_
|
||||
|
||||
#define COPYFILE_NOCLOBBER 1
|
||||
#define COPYFILE_PRESERVE_OWNER 2
|
||||
|
@ -12,4 +12,4 @@ int copyfile(const char *, const char *, int) paramsnonnull();
|
|||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_HEFTY_COPYFILE_H_ */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_COPYFILE_H_ */
|
|
@ -47,7 +47,7 @@ textwindows int execve$nt(const char *program, char *const argv[],
|
|||
close(i);
|
||||
}
|
||||
}
|
||||
rc = ntspawn(program, argv, envp, NULL, NULL, true, 0, NULL, &startinfo,
|
||||
rc = ntspawn(program, argv, envp, NULL, NULL, NULL, true, 0, NULL, &startinfo,
|
||||
&procinfo);
|
||||
if (rc == -1) return -1;
|
||||
CloseHandle(procinfo.hThread);
|
||||
|
|
|
@ -16,10 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#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.
|
||||
|
|
|
@ -1,277 +0,0 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/progn.internal.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/dirent.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nt/enum/fileflagandattributes.h"
|
||||
#include "libc/nt/enum/filetype.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"
|
||||
|
||||
/**
|
||||
* @fileoverview Directory Streams for Linux+Mac+Windows+FreeBSD+OpenBSD.
|
||||
*
|
||||
* System interfaces for listing the contents of file system directories
|
||||
* are famously incompatible across platforms. Most native projects that
|
||||
* have been around a long time implement wrappers for this. Normally it
|
||||
* will only be for DOS or Windows support. So this is the first time it
|
||||
* has been done for five platforms, having a remarkably tiny footprint.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Directory stream object.
|
||||
*/
|
||||
struct dirstream {
|
||||
int64_t tell;
|
||||
int64_t fd;
|
||||
struct dirent ent;
|
||||
union {
|
||||
struct {
|
||||
unsigned buf_pos;
|
||||
unsigned buf_end;
|
||||
char buf[BUFSIZ];
|
||||
};
|
||||
struct {
|
||||
bool isdone;
|
||||
struct NtWin32FindData windata;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* FreeBSD getdents() and XNU getdirentries() ABI.
|
||||
*/
|
||||
struct dirent$bsd {
|
||||
uint32_t d_fileno;
|
||||
uint16_t d_reclen;
|
||||
uint8_t d_type;
|
||||
uint8_t d_namlen;
|
||||
char d_name[256];
|
||||
};
|
||||
|
||||
/**
|
||||
* OpenBSD getdents() ABI.
|
||||
*/
|
||||
struct dirent$openbsd {
|
||||
uint64_t d_fileno;
|
||||
int64_t d_off;
|
||||
uint16_t d_reclen;
|
||||
uint8_t d_type;
|
||||
uint8_t d_namlen;
|
||||
uint8_t __zomg[4];
|
||||
char d_name[256];
|
||||
};
|
||||
|
||||
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);
|
||||
while (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;
|
||||
}
|
||||
}
|
||||
|
||||
static textwindows noinline struct dirent *readdir$nt(DIR *dir) {
|
||||
if (!dir->isdone) {
|
||||
memset(&dir->ent, 0, sizeof(dir->ent));
|
||||
dir->ent.d_ino = 0;
|
||||
dir->ent.d_off = dir->tell++;
|
||||
dir->ent.d_reclen = sizeof(dir->ent) +
|
||||
tprecode16to8(dir->ent.d_name, sizeof(dir->ent.d_name),
|
||||
dir->windata.cFileName)
|
||||
.ax +
|
||||
1;
|
||||
switch (dir->windata.dwFileType) {
|
||||
case kNtFileTypeDisk:
|
||||
dir->ent.d_type = DT_BLK;
|
||||
break;
|
||||
case kNtFileTypeChar:
|
||||
dir->ent.d_type = DT_CHR;
|
||||
break;
|
||||
case kNtFileTypePipe:
|
||||
dir->ent.d_type = DT_FIFO;
|
||||
break;
|
||||
default:
|
||||
if (dir->windata.dwFileAttributes & kNtFileAttributeDirectory) {
|
||||
dir->ent.d_type = DT_DIR;
|
||||
} else {
|
||||
dir->ent.d_type = DT_REG;
|
||||
}
|
||||
break;
|
||||
}
|
||||
dir->isdone = !FindNextFile(dir->fd, &dir->windata);
|
||||
return &dir->ent;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens directory, e.g.
|
||||
*
|
||||
* DIR *d;
|
||||
* struct dirent *e;
|
||||
* CHECK((d = opendir(path)));
|
||||
* while ((e = readdir(d))) {
|
||||
* printf("%s/%s\n", path, e->d_name);
|
||||
* }
|
||||
* LOGIFNEG1(closedir(d));
|
||||
*
|
||||
* @returns newly allocated DIR object, or NULL w/ errno
|
||||
* @errors ENOENT, ENOTDIR, EACCES, EMFILE, ENFILE, ENOMEM
|
||||
* @see glob()
|
||||
*/
|
||||
DIR *opendir(const char *name) {
|
||||
int fd;
|
||||
DIR *res;
|
||||
if (!IsWindows()) {
|
||||
res = NULL;
|
||||
if ((fd = open(name, O_RDONLY | O_DIRECTORY | O_CLOEXEC)) != -1) {
|
||||
if (!(res = fdopendir(fd))) close(fd);
|
||||
}
|
||||
return res;
|
||||
} else {
|
||||
return opendir$nt(name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
DIR *dir;
|
||||
if (!IsWindows()) {
|
||||
if ((dir = calloc(1, sizeof(*dir)))) {
|
||||
dir->fd = fd;
|
||||
return dir;
|
||||
}
|
||||
} else {
|
||||
enosys(); /* TODO(jart): Implement me! */
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads next entry from directory stream.
|
||||
*
|
||||
* 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) {
|
||||
int rc;
|
||||
long basep;
|
||||
struct dirent *ent;
|
||||
struct dirent$bsd *bsd;
|
||||
struct dirent$openbsd *obsd;
|
||||
if (!IsWindows()) {
|
||||
if (dir->buf_pos >= dir->buf_end) {
|
||||
basep = dir->tell; /* <- what does xnu do */
|
||||
rc = getdents(dir->fd, dir->buf, sizeof(dir->buf) - 256, &basep);
|
||||
if (!rc || rc == -1) return NULL;
|
||||
dir->buf_pos = 0;
|
||||
dir->buf_end = rc;
|
||||
}
|
||||
if (IsLinux()) {
|
||||
ent = (struct dirent *)(dir->buf + dir->buf_pos);
|
||||
dir->buf_pos += ent->d_reclen;
|
||||
dir->tell = ent->d_off;
|
||||
} else if (IsOpenbsd()) {
|
||||
obsd = (struct dirent$openbsd *)(dir->buf + dir->buf_pos);
|
||||
dir->buf_pos += obsd->d_reclen;
|
||||
ent = &dir->ent;
|
||||
ent->d_ino = obsd->d_fileno;
|
||||
ent->d_off = obsd->d_off;
|
||||
ent->d_reclen = obsd->d_reclen;
|
||||
ent->d_type = obsd->d_type;
|
||||
memcpy(ent->d_name, obsd->d_name, obsd->d_namlen + 1);
|
||||
} else {
|
||||
bsd = (struct dirent$bsd *)(dir->buf + dir->buf_pos);
|
||||
dir->buf_pos += bsd->d_reclen;
|
||||
ent = &dir->ent;
|
||||
ent->d_ino = bsd->d_fileno;
|
||||
ent->d_off = IsXnu() ? (dir->tell = basep) : dir->tell++;
|
||||
ent->d_reclen = bsd->d_reclen;
|
||||
ent->d_type = bsd->d_type;
|
||||
memcpy(ent->d_name, bsd->d_name, bsd->d_namlen + 1);
|
||||
}
|
||||
return ent;
|
||||
} else {
|
||||
return readdir$nt(dir);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 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;
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/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;
|
||||
}
|
|
@ -1,179 +0,0 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ntspawn.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/nexgen32e/nt2sysv.h"
|
||||
#include "libc/nt/dll.h"
|
||||
#include "libc/nt/enum/filemapflags.h"
|
||||
#include "libc/nt/enum/pageflags.h"
|
||||
#include "libc/nt/enum/startf.h"
|
||||
#include "libc/nt/enum/wt.h"
|
||||
#include "libc/nt/ipc.h"
|
||||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/signals.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/nt/thread.h"
|
||||
#include "libc/runtime/directmap.h"
|
||||
#include "libc/runtime/memtrack.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static textwindows int64_t ParseInt(char16_t **p) {
|
||||
uint64_t x = 0;
|
||||
while ('0' <= **p && **p <= '9') {
|
||||
x *= 10;
|
||||
x += *(*p)++ - '0';
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
static noinline textwindows void ForkIo(int64_t h, void *buf, size_t n,
|
||||
bool32 (*f)()) {
|
||||
char *p;
|
||||
size_t i;
|
||||
uint32_t x;
|
||||
for (p = buf, i = 0; i < n; i += x) {
|
||||
f(h, p + i, n - i, &x, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static noinline textwindows void WriteAll(int64_t h, void *buf, size_t n) {
|
||||
ForkIo(h, buf, n, WriteFile);
|
||||
}
|
||||
|
||||
static noinline textwindows void ReadAll(int64_t h, void *buf, size_t n) {
|
||||
ForkIo(h, buf, n, ReadFile);
|
||||
}
|
||||
|
||||
textwindows void WinMainForked(void) {
|
||||
int64_t h;
|
||||
void *addr;
|
||||
jmp_buf jb;
|
||||
char16_t *p;
|
||||
uint64_t size;
|
||||
uint32_t i, varlen;
|
||||
struct DirectMap dm;
|
||||
char16_t var[21 + 1 + 21 + 1];
|
||||
varlen = GetEnvironmentVariable(u"_FORK", var, ARRAYLEN(var));
|
||||
SetEnvironmentVariable(u"_FORK", NULL);
|
||||
if (!varlen || varlen >= ARRAYLEN(var)) return;
|
||||
p = var;
|
||||
h = ParseInt(&p);
|
||||
if (*p++ == ' ') CloseHandle(ParseInt(&p));
|
||||
ReadAll(h, jb, sizeof(jb));
|
||||
ReadAll(h, &_mmi.i, sizeof(_mmi.i));
|
||||
for (i = 0; i < _mmi.i; ++i) {
|
||||
ReadAll(h, &_mmi.p[i], sizeof(_mmi.p[i]));
|
||||
addr = (void *)((uint64_t)_mmi.p[i].x << 16);
|
||||
size = ((uint64_t)(_mmi.p[i].y - _mmi.p[i].x) << 16) + FRAMESIZE;
|
||||
if (_mmi.p[i].flags & MAP_PRIVATE) {
|
||||
CloseHandle(_mmi.p[i].h);
|
||||
_mmi.p[i].h =
|
||||
__mmap$nt(addr, size, PROT_READ | PROT_WRITE | PROT_EXEC, -1, 0)
|
||||
.maphandle;
|
||||
ReadAll(h, addr, size);
|
||||
} else {
|
||||
MapViewOfFileExNuma(
|
||||
_mmi.p[i].h,
|
||||
(_mmi.p[i].prot & PROT_WRITE)
|
||||
? kNtFileMapWrite | kNtFileMapExecute | kNtFileMapRead
|
||||
: kNtFileMapExecute | kNtFileMapRead,
|
||||
0, 0, size, addr, kNtNumaNoPreferredNode);
|
||||
}
|
||||
}
|
||||
ReadAll(h, _edata, _end - _edata);
|
||||
CloseHandle(h);
|
||||
unsetenv("_FORK");
|
||||
if (weaken(__wincrash$nt)) {
|
||||
AddVectoredExceptionHandler(1, (void *)weaken(__wincrash$nt));
|
||||
}
|
||||
longjmp(jb, 1);
|
||||
}
|
||||
|
||||
textwindows int fork$nt(void) {
|
||||
jmp_buf jb;
|
||||
int i, rc, pid;
|
||||
char exe[PATH_MAX];
|
||||
int64_t reader, writer;
|
||||
char *p, buf[21 + 1 + 21 + 1];
|
||||
struct NtStartupInfo startinfo;
|
||||
struct NtProcessInformation procinfo;
|
||||
if ((pid = __getemptyfd()) == -1) return -1;
|
||||
if (!setjmp(jb)) {
|
||||
if (CreatePipe(&reader, &writer, &kNtIsInheritable, 0)) {
|
||||
p = buf;
|
||||
p += uint64toarray_radix10(reader, p);
|
||||
*p++ = ' ';
|
||||
p += uint64toarray_radix10(writer, p);
|
||||
setenv("_FORK", buf, true);
|
||||
memset(&startinfo, 0, sizeof(startinfo));
|
||||
startinfo.cb = sizeof(struct NtStartupInfo);
|
||||
startinfo.dwFlags = kNtStartfUsestdhandles;
|
||||
startinfo.hStdInput = g_fds.p[0].handle;
|
||||
startinfo.hStdOutput = g_fds.p[1].handle;
|
||||
startinfo.hStdError = g_fds.p[2].handle;
|
||||
GetModuleFileNameA(0, exe, ARRAYLEN(exe));
|
||||
if (ntspawn(exe, g_argv, environ, &kNtIsInheritable, NULL, true, 0, NULL,
|
||||
&startinfo, &procinfo) != -1) {
|
||||
CloseHandle(reader);
|
||||
CloseHandle(procinfo.hThread);
|
||||
if (weaken(__sighandrvas) &&
|
||||
weaken(__sighandrvas)[SIGCHLD] == SIG_IGN) {
|
||||
CloseHandle(procinfo.hProcess);
|
||||
} else {
|
||||
g_fds.p[pid].kind = kFdProcess;
|
||||
g_fds.p[pid].handle = procinfo.hProcess;
|
||||
g_fds.p[pid].flags = O_CLOEXEC;
|
||||
}
|
||||
WriteAll(writer, jb, sizeof(jb));
|
||||
WriteAll(writer, &_mmi.i, sizeof(_mmi.i));
|
||||
for (i = 0; i < _mmi.i; ++i) {
|
||||
WriteAll(writer, &_mmi.p[i], sizeof(_mmi.p[i]));
|
||||
if (_mmi.p[i].flags & MAP_PRIVATE) {
|
||||
WriteAll(writer, (void *)((uint64_t)_mmi.p[i].x << 16),
|
||||
((uint64_t)(_mmi.p[i].y - _mmi.p[i].x) << 16) + FRAMESIZE);
|
||||
}
|
||||
}
|
||||
WriteAll(writer, _edata, _end - _edata);
|
||||
CloseHandle(writer);
|
||||
} else {
|
||||
rc = -1;
|
||||
}
|
||||
unsetenv("_FORK");
|
||||
rc = pid;
|
||||
} else {
|
||||
rc = __winerr();
|
||||
}
|
||||
} else {
|
||||
rc = 0;
|
||||
}
|
||||
return rc;
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
|
||||
/**
|
||||
* Creates new process zygote style.
|
||||
*
|
||||
* @return 0 to child, child pid to parent, or -1 on error
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int fork(void) {
|
||||
int rc;
|
||||
if (!IsWindows()) {
|
||||
rc = fork$sysv();
|
||||
} else {
|
||||
rc = fork$nt();
|
||||
}
|
||||
if (rc == 0) {
|
||||
__onfork();
|
||||
}
|
||||
return rc;
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.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 (!(buf = malloc(PATH_MAX))) return NULL;
|
||||
if (!(res = (getcwd)(buf, PATH_MAX))) free(buf);
|
||||
return res;
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
#-*-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_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_CALLS \
|
||||
LIBC_FMT \
|
||||
LIBC_INTRIN \
|
||||
LIBC_MEM \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_NT_KERNEL32 \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_STR \
|
||||
LIBC_STUBS \
|
||||
LIBC_SYSV \
|
||||
LIBC_SYSV_CALLS
|
||||
|
||||
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)
|
|
@ -1,48 +0,0 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.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;
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
/*-*- mode:unix-assembly; 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 │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/macros.h"
|
||||
.text.syscall
|
||||
|
||||
/ Forks process without copying page tables.
|
||||
/
|
||||
/ This is the same as fork() except it's optimized for the case
|
||||
/ where the caller invokes execve() immediately afterwards. You
|
||||
/ can also call functions like close(), dup2(), etc. You cannot
|
||||
/ call read() safely but you can call pread(). Call _exit() but
|
||||
/ don't call exit(). Look for the vforksafe function annotation
|
||||
/
|
||||
/ Do not make the assumption that the parent is suspended until
|
||||
/ the child terminates since this impl calls fork() on Windows.
|
||||
/
|
||||
/ @return pid of child process or 0 if forked process
|
||||
/ @returnstwice
|
||||
/ @vforksafe
|
||||
vfork:
|
||||
#if SupportsWindows()
|
||||
testb IsWindows()
|
||||
jnz fork$nt
|
||||
#endif
|
||||
mov __NR_vfork(%rip),%eax
|
||||
pop %rsi # saves return address in a register
|
||||
#if SupportsBsd()
|
||||
testb IsBsd()
|
||||
jnz vfork.bsd
|
||||
#endif
|
||||
syscall
|
||||
push %rsi # note it happens twice in same page
|
||||
cmp $-4095,%eax
|
||||
jae systemfive.error
|
||||
0: ezlea __vforked,di
|
||||
test %eax,%eax
|
||||
jz 1f
|
||||
decl (%rdi)
|
||||
jns 2f # openbsd doesn't actually share mem
|
||||
1: incl (%rdi)
|
||||
2: ret
|
||||
.endfn vfork,globl
|
||||
|
||||
#if SupportsBsd()
|
||||
vfork.bsd:
|
||||
syscall
|
||||
push %rsi
|
||||
jc systemfive.errno
|
||||
#if SupportsXnu()
|
||||
testb IsXnu()
|
||||
jz 0b
|
||||
neg %edx # edx is 0 for parent and 1 for child
|
||||
not %edx # eax always returned with childs pid
|
||||
and %edx,%eax
|
||||
#endif /* XNU */
|
||||
jmp 0b
|
||||
.endfn vfork.bsd
|
||||
#endif /* BSD */
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
/**
|
||||
* Controls settings on device.
|
||||
* @vforksafe
|
||||
*/
|
||||
int(ioctl)(int fd, uint64_t request, void *memory) {
|
||||
__IOCTL_DISPATCH(EQUAL, fd, request, memory);
|
||||
|
|
|
@ -51,18 +51,23 @@ static void SortStrings(char **a, size_t n) {
|
|||
*
|
||||
* This is designed to meet the requirements of CreateProcess().
|
||||
*
|
||||
* @param envvars receives sorted double-NUL terminated string list
|
||||
* @param envp is an a NULL-terminated array of UTF-8 strings
|
||||
* @return freshly allocated lpEnvironment or NULL w/ errno
|
||||
* @param extravar is a VAR=val string we consider part of envp or NULL
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @error E2BIG if total number of shorts exceeded ARG_MAX (0x8000)
|
||||
*/
|
||||
textwindows int mkntenvblock(char16_t envvars[ARG_MAX], char *const envp[]) {
|
||||
textwindows int mkntenvblock(char16_t envvars[ARG_MAX], char *const envp[],
|
||||
const char *extravar) {
|
||||
axdx_t rc;
|
||||
uint64_t w;
|
||||
char **vars;
|
||||
wint_t x, y;
|
||||
size_t i, j, k, n, m;
|
||||
for (n = 0; envp[n];) n++;
|
||||
vars = alloca(n * sizeof(char *));
|
||||
vars = alloca((n + 1) * sizeof(char *));
|
||||
memcpy(vars, envp, n * sizeof(char *));
|
||||
if (extravar) vars[n++] = extravar;
|
||||
SortStrings(vars, n);
|
||||
for (k = i = 0; i < n; ++i) {
|
||||
j = 0;
|
||||
|
|
|
@ -48,6 +48,7 @@ struct SpawnBlock {
|
|||
* 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 extravar is added to envp to avoid setenv() in caller
|
||||
* @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
|
||||
|
@ -59,7 +60,7 @@ struct SpawnBlock {
|
|||
*/
|
||||
textwindows int ntspawn(
|
||||
const char *prog, char *const argv[], char *const envp[],
|
||||
struct NtSecurityAttributes *opt_lpProcessAttributes,
|
||||
const char *extravar, struct NtSecurityAttributes *opt_lpProcessAttributes,
|
||||
struct NtSecurityAttributes *opt_lpThreadAttributes, bool32 bInheritHandles,
|
||||
uint32_t dwCreationFlags, const char16_t *opt_lpCurrentDirectory,
|
||||
const struct NtStartupInfo *lpStartupInfo,
|
||||
|
@ -81,7 +82,7 @@ textwindows int ntspawn(
|
|||
MapViewOfFileExNuma(handle, kNtFileMapRead | kNtFileMapWrite, 0, 0,
|
||||
blocksize, NULL, kNtNumaNoPreferredNode))) {
|
||||
if (mkntcmdline(block->cmdline, prog, argv) != -1 &&
|
||||
mkntenvblock(block->envvars, envp) != -1) {
|
||||
mkntenvblock(block->envvars, envp, extravar) != -1) {
|
||||
if (CreateProcess(NULL, block->cmdline, opt_lpProcessAttributes,
|
||||
opt_lpThreadAttributes, bInheritHandles,
|
||||
dwCreationFlags | kNtCreateUnicodeEnvironment,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_HEFTY_NTSPAWN_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_HEFTY_NTSPAWN_H_
|
||||
#ifndef COSMOPOLITAN_LIBC_CALLS_NTSPAWN_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_NTSPAWN_H_
|
||||
#include "libc/nt/struct/processinformation.h"
|
||||
#include "libc/nt/struct/securityattributes.h"
|
||||
#include "libc/nt/struct/startupinfo.h"
|
||||
|
@ -7,12 +7,12 @@
|
|||
COSMOPOLITAN_C_START_
|
||||
|
||||
int mkntcmdline(char16_t[ARG_MAX], const char *, char *const[]) hidden;
|
||||
int mkntenvblock(char16_t[ARG_MAX], char *const[]) hidden;
|
||||
int ntspawn(const char *, char *const[], char *const[],
|
||||
int mkntenvblock(char16_t[ARG_MAX], char *const[], const char *) hidden;
|
||||
int ntspawn(const char *, char *const[], char *const[], const char *,
|
||||
struct NtSecurityAttributes *, struct NtSecurityAttributes *,
|
||||
bool32, uint32_t, const char16_t *, const struct NtStartupInfo *,
|
||||
struct NtProcessInformation *) hidden;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_HEFTY_NTSPAWN_H_ */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_NTSPAWN_H_ */
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
* ignored if O_CREAT or O_TMPFILE weren't passed
|
||||
* @return number needing close(), or -1 w/ errno
|
||||
* @asyncsignalsafe
|
||||
* @vforksafe
|
||||
*/
|
||||
nodiscard int openat(int dirfd, const char *file, int flags, ...) {
|
||||
va_list va;
|
||||
|
@ -47,11 +48,9 @@ nodiscard int openat(int dirfd, const char *file, int flags, ...) {
|
|||
va_end(va);
|
||||
if (!file) return efault();
|
||||
if (weaken(__zipos_open) && weaken(__zipos_parseuri)(file, &zipname) != -1) {
|
||||
if (dirfd == AT_FDCWD) {
|
||||
return weaken(__zipos_open)(&zipname, flags, mode);
|
||||
} else {
|
||||
return eopnotsupp(); /* TODO */
|
||||
}
|
||||
if (__vforked) return einval();
|
||||
if (dirfd != AT_FDCWD) return einval();
|
||||
return weaken(__zipos_open)(&zipname, flags, mode);
|
||||
} else if (!IsWindows()) {
|
||||
return openat$sysv(dirfd, file, flags, mode);
|
||||
} else {
|
||||
|
|
|
@ -118,6 +118,7 @@ static void sigaction$native2cosmo(union metasigaction *sa) {
|
|||
*
|
||||
* @see xsigaction() for a much better api
|
||||
* @asyncsignalsafe
|
||||
* @vforksafe
|
||||
*/
|
||||
int(sigaction)(int sig, const struct sigaction *act, struct sigaction *oldact) {
|
||||
_Static_assert(sizeof(struct sigaction) > sizeof(struct sigaction$linux) &&
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue