mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-30 08:18:30 +00:00
Introduce posix_spawn_file_actions_addchdir_np()
This commit is contained in:
parent
f92ad74e6b
commit
3a1f887928
25 changed files with 446 additions and 748 deletions
|
@ -54,6 +54,35 @@ textwindows static const char *FixNtMagicPath(const char *path,
|
|||
return path;
|
||||
}
|
||||
|
||||
textwindows size_t __normntpath(char16_t *p, size_t n) {
|
||||
size_t i, j;
|
||||
for (j = i = 0; i < n; ++i) {
|
||||
int c = p[i];
|
||||
if (c == '/') {
|
||||
c = '\\';
|
||||
}
|
||||
if (j > 1 && c == '\\' && p[j - 1] == '\\') {
|
||||
// matched "^/" or "//" but not "^//"
|
||||
} else if ((j && p[j - 1] == '\\') && //
|
||||
c == '.' && //
|
||||
(i + 1 == n || IsSlash(p[i + 1]))) {
|
||||
// matched "/./" or "/.$"
|
||||
i += !(i + 1 == n);
|
||||
} else if ((j && p[j - 1] == '\\') && //
|
||||
c == '.' && //
|
||||
(i + 1 < n && p[i + 1] == '.') && //
|
||||
(i + 2 == n || IsSlash(p[i + 2]))) {
|
||||
// matched "/../" or "/..$"
|
||||
while (j && p[j - 1] == '\\') --j;
|
||||
while (j && p[j - 1] != '\\') --j;
|
||||
} else {
|
||||
p[j++] = c;
|
||||
}
|
||||
}
|
||||
p[j] = 0;
|
||||
return j;
|
||||
}
|
||||
|
||||
textwindows int __mkntpath(const char *path,
|
||||
char16_t path16[hasatleast PATH_MAX]) {
|
||||
return __mkntpath2(path, path16, -1);
|
||||
|
@ -78,7 +107,6 @@ textwindows int __mkntpath(const char *path,
|
|||
*/
|
||||
textwindows int __mkntpath2(const char *path,
|
||||
char16_t path16[hasatleast PATH_MAX], int flags) {
|
||||
|
||||
// 1. Need +1 for NUL-terminator
|
||||
// 2. Need +1 for UTF-16 overflow
|
||||
// 3. Need ≥2 for SetCurrentDirectory trailing slash requirement
|
||||
|
@ -165,32 +193,7 @@ textwindows int __mkntpath2(const char *path,
|
|||
// normalize path
|
||||
// we need it because \\?\... paths have to be normalized
|
||||
// we don't remove the trailing slash since it is special
|
||||
size_t i, j;
|
||||
for (j = i = 0; i < n; ++i) {
|
||||
int c = p[i];
|
||||
if (c == '/') {
|
||||
c = '\\';
|
||||
}
|
||||
if (j > 1 && c == '\\' && p[j - 1] == '\\') {
|
||||
// matched "^/" or "//" but not "^//"
|
||||
} else if ((j && p[j - 1] == '\\') && //
|
||||
c == '.' && //
|
||||
(i + 1 == n || IsSlash(p[i + 1]))) {
|
||||
// matched "/./" or "/.$"
|
||||
i += !(i + 1 == n);
|
||||
} else if ((j && p[j - 1] == '\\') && //
|
||||
c == '.' && //
|
||||
(i + 1 < n && p[i + 1] == '.') && //
|
||||
(i + 2 == n || IsSlash(p[i + 2]))) {
|
||||
// matched "/../" or "/..$"
|
||||
while (j && p[j - 1] == '\\') --j;
|
||||
while (j && p[j - 1] != '\\') --j;
|
||||
} else {
|
||||
p[j++] = c;
|
||||
}
|
||||
}
|
||||
p[j] = 0;
|
||||
n = j;
|
||||
n = __normntpath(p, n);
|
||||
|
||||
// our path is now stored at `path16` with length `n`
|
||||
n = x + m + n;
|
||||
|
|
|
@ -27,37 +27,35 @@
|
|||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static int __mkntpathat_impl(int dirfd, const char *path, int flags,
|
||||
char16_t file[hasatleast PATH_MAX]) {
|
||||
static textwindows int __mkntpathath_impl(int64_t dirhand, const char *path,
|
||||
int flags,
|
||||
char16_t file[hasatleast PATH_MAX]) {
|
||||
size_t n;
|
||||
char16_t dir[PATH_MAX];
|
||||
uint32_t dirlen, filelen;
|
||||
if (!isutf8(path, -1)) return eilseq(); // thwart overlong nul in conversion
|
||||
if ((filelen = __mkntpath2(path, file, flags)) == -1) return -1;
|
||||
if (!filelen) return enoent();
|
||||
if (file[0] != u'\\' && dirfd != AT_FDCWD) { // ProTip: \\?\C:\foo
|
||||
if (!__isfdkind(dirfd, kFdFile)) return ebadf();
|
||||
dirlen = GetFinalPathNameByHandle(g_fds.p[dirfd].handle, dir, ARRAYLEN(dir),
|
||||
if (file[0] != u'\\' && dirhand != AT_FDCWD) { // ProTip: \\?\C:\foo
|
||||
dirlen = GetFinalPathNameByHandle(dirhand, dir, ARRAYLEN(dir),
|
||||
kNtFileNameNormalized | kNtVolumeNameDos);
|
||||
if (!dirlen) return __winerr();
|
||||
if (dirlen + 1 + filelen + 1 > ARRAYLEN(dir)) {
|
||||
STRACE("path too long: %#.*hs\\%#.*hs", dirlen, dir, filelen, file);
|
||||
return enametoolong();
|
||||
}
|
||||
if (dirlen + 1 + filelen + 1 > ARRAYLEN(dir)) return enametoolong();
|
||||
dir[dirlen] = u'\\';
|
||||
memcpy(dir + dirlen + 1, file, (filelen + 1) * sizeof(char16_t));
|
||||
memcpy(file, dir, (dirlen + 1 + filelen + 1) * sizeof(char16_t));
|
||||
return dirlen + 1 + filelen;
|
||||
memcpy(file, dir, ((n = dirlen + 1 + filelen) + 1) * sizeof(char16_t));
|
||||
return __normntpath(file, n);
|
||||
} else {
|
||||
return filelen;
|
||||
}
|
||||
}
|
||||
|
||||
int __mkntpathat(int dirfd, const char *path, int flags,
|
||||
char16_t file[hasatleast PATH_MAX]) {
|
||||
textwindows int __mkntpathath(int64_t dirhand, const char *path, int flags,
|
||||
char16_t file[hasatleast PATH_MAX]) {
|
||||
|
||||
// convert the path.
|
||||
int len;
|
||||
if ((len = __mkntpathat_impl(dirfd, path, flags, file)) == -1) {
|
||||
if ((len = __mkntpathath_impl(dirhand, path, flags, file)) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -78,3 +76,16 @@ int __mkntpathat(int dirfd, const char *path, int flags,
|
|||
|
||||
return len;
|
||||
}
|
||||
|
||||
textwindows int __mkntpathat(int dirfd, const char *path, int flags,
|
||||
char16_t file[hasatleast PATH_MAX]) {
|
||||
int64_t dirhand;
|
||||
if (dirfd == AT_FDCWD) {
|
||||
dirhand = AT_FDCWD;
|
||||
} else if (__isfdkind(dirfd, kFdFile)) {
|
||||
dirhand = g_fds.p[dirfd].handle;
|
||||
} else {
|
||||
return ebadf();
|
||||
}
|
||||
return __mkntpathath(dirhand, path, flags, file);
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ static void ntspawn_free(void *ptr) {
|
|||
* @asyncsignalsafe
|
||||
*/
|
||||
textwindows int ntspawn(
|
||||
const char *prog, char *const argv[], char *const envp[],
|
||||
int64_t dirhand, const char *prog, char *const argv[], char *const envp[],
|
||||
char *const extravars[], uint32_t dwCreationFlags,
|
||||
const char16_t *opt_lpCurrentDirectory, int64_t opt_hParentProcess,
|
||||
int64_t *opt_lpExplicitHandleList, uint32_t dwExplicitHandleCount,
|
||||
|
@ -82,7 +82,8 @@ textwindows int ntspawn(
|
|||
int rc = -1;
|
||||
struct SpawnBlock *sb;
|
||||
BLOCK_SIGNALS;
|
||||
if ((sb = ntspawn_malloc(sizeof(*sb))) && __mkntpath(prog, sb->path) != -1) {
|
||||
if ((sb = ntspawn_malloc(sizeof(*sb))) &&
|
||||
__mkntpathath(dirhand, prog, 0, sb->path) != -1) {
|
||||
if (!mkntcmdline(sb->cmdline, argv) &&
|
||||
!mkntenvblock(sb->envblock, envp, extravars, sb->envbuf)) {
|
||||
bool32 ok;
|
||||
|
@ -133,6 +134,8 @@ textwindows int ntspawn(
|
|||
STRACE("CreateProcess() failed w/ %d", GetLastError());
|
||||
if (GetLastError() == kNtErrorSharingViolation) {
|
||||
etxtbsy();
|
||||
} else if (GetLastError() == kNtErrorInvalidName) {
|
||||
enoent();
|
||||
}
|
||||
}
|
||||
rc = __fix_enotdir(rc, sb->path);
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/promises.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/nexgen32e/vendor.internal.h"
|
||||
|
@ -267,11 +268,13 @@ int pledge(const char *promises, const char *execpromises) {
|
|||
// if bits are missing in execpromises that exist in promises
|
||||
// then execpromises wouldn't be a monotonic access reduction
|
||||
// this check only matters when exec / execnative are allowed
|
||||
if ((ipromises & ~iexecpromises) &&
|
||||
(~ipromises & (1ul << PROMISE_EXEC))) {
|
||||
bool notsubset = ((ipromises & ~iexecpromises) &&
|
||||
(~ipromises & (1ul << PROMISE_EXEC)));
|
||||
if (notsubset && execpromises) {
|
||||
STRACE("execpromises must be a subset of promises");
|
||||
rc = einval();
|
||||
} else {
|
||||
if (notsubset) iexecpromises = ipromises;
|
||||
rc = sys_pledge_linux(ipromises, __pledge_mode);
|
||||
if (rc > -4096u) errno = -rc, rc = -1;
|
||||
}
|
||||
|
|
|
@ -10,9 +10,11 @@ bool isregularfile_nt(const char *);
|
|||
bool issymlink_nt(const char *);
|
||||
bool32 ntsetprivilege(int64_t, const char16_t *, uint32_t);
|
||||
char16_t *__create_pipe_name(char16_t *);
|
||||
size_t __normntpath(char16_t *, size_t);
|
||||
int __mkntpath(const char *, char16_t[hasatleast PATH_MAX]);
|
||||
int __mkntpath2(const char *, char16_t[hasatleast PATH_MAX], int);
|
||||
int __mkntpathat(int, const char *, int, char16_t[hasatleast PATH_MAX]);
|
||||
int __mkntpathath(int64_t, const char *, int, char16_t[hasatleast PATH_MAX]);
|
||||
int ntaccesscheck(const char16_t *, uint32_t) paramsnonnull();
|
||||
int sys_pause_nt(void);
|
||||
int64_t __fix_enotdir(int64_t, char16_t *);
|
||||
|
|
|
@ -45,7 +45,7 @@ CreateProcess(const char16_t *opt_lpApplicationName, char16_t *lpCommandLine,
|
|||
opt_lpCurrentDirectory, lpStartupInfo,
|
||||
opt_out_lpProcessInformation);
|
||||
if (!ok) __winerr();
|
||||
NTTRACE("CreateProcess(%#hs, %#!hs, %s, %s, %hhhd, %u, %p, %#hs, %p, %p) → "
|
||||
NTTRACE("CreateProcess(%#!hs, %#!hs, %s, %s, %hhhd, %u, %p, %#!hs, %p, %p) → "
|
||||
"%hhhd% m",
|
||||
opt_lpApplicationName, lpCommandLine,
|
||||
DescribeNtSecurityAttributes(opt_lpProcessAttributes),
|
||||
|
|
|
@ -39,8 +39,8 @@ int ulock_wait(uint32_t operation, void *addr, uint64_t value,
|
|||
LOCKTRACE("ulock_wait(%#x, %p, %lx, %u) → ...", operation, addr, value,
|
||||
timeout_micros);
|
||||
rc = sys_ulock_wait(operation, addr, value, timeout_micros);
|
||||
STRACE("ulock_wait(%#x, %p, %lx, %u) → %d% m", operation, addr, value,
|
||||
timeout_micros, rc);
|
||||
LOCKTRACE("ulock_wait(%#x, %p, %lx, %u) → %d% m", operation, addr, value,
|
||||
timeout_micros, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ int ulock_wait(uint32_t operation, void *addr, uint64_t value,
|
|||
int ulock_wake(uint32_t operation, void *addr, uint64_t wake_value) {
|
||||
int rc;
|
||||
rc = __syscall3i(operation, (long)addr, wake_value, 0x2000000 | 516);
|
||||
STRACE("ulock_wake(%#x, %p, %lx) → %s", operation, addr, wake_value,
|
||||
DescribeErrno(rc));
|
||||
LOCKTRACE("ulock_wake(%#x, %p, %lx) → %s", operation, addr, wake_value,
|
||||
DescribeErrno(rc));
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
*/
|
||||
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/pledge.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/cosmo.h"
|
||||
|
@ -59,6 +60,7 @@
|
|||
#include "libc/str/unicode.h"
|
||||
#include "libc/str/utf16.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "net/http/http.h"
|
||||
|
||||
#ifdef COSMO_ALREADY_DEFINED
|
||||
#undef COSMO_ALREADY_DEFINED
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "libc/proc/describefds.internal.h"
|
||||
#include "libc/proc/ntspawn.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/thread/posixthread.internal.h"
|
||||
|
@ -85,9 +86,9 @@ textwindows int sys_execve_nt(const char *program, char *const argv[],
|
|||
|
||||
// launch the process
|
||||
struct NtProcessInformation pi;
|
||||
int rc =
|
||||
ntspawn(program, argv, envp, (char *[]){fdspec, 0}, 0, 0, hParentProcess,
|
||||
lpExplicitHandles, dwExplicitHandleCount, &si, &pi);
|
||||
int rc = ntspawn(AT_FDCWD, program, argv, envp, (char *[]){fdspec, 0}, 0, 0,
|
||||
hParentProcess, lpExplicitHandles, dwExplicitHandleCount,
|
||||
&si, &pi);
|
||||
__undescribe_fds(hParentProcess, lpExplicitHandles, dwExplicitHandleCount);
|
||||
if (rc == -1) {
|
||||
free(fdspec);
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/runtime/symbols.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/limits.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
@ -345,7 +346,7 @@ textwindows int sys_fork_nt(uint32_t dwCreationFlags) {
|
|||
}
|
||||
#endif
|
||||
NTTRACE("STARTING SPAWN");
|
||||
int spawnrc = ntspawn(GetProgramExecutableName(), args, environ,
|
||||
int spawnrc = ntspawn(AT_FDCWD, GetProgramExecutableName(), args, environ,
|
||||
(char *[]){forkvar, 0}, dwCreationFlags, 0, 0, 0, 0,
|
||||
&startinfo, &procinfo);
|
||||
if (spawnrc != -1) {
|
||||
|
|
|
@ -7,8 +7,8 @@ COSMOPOLITAN_C_START_
|
|||
|
||||
int mkntcmdline(char16_t[32767], char *const[]);
|
||||
int mkntenvblock(char16_t[32767], char *const[], char *const[], char[32767]);
|
||||
int ntspawn(const char *, char *const[], char *const[], char *const[], uint32_t,
|
||||
const char16_t *, int64_t, int64_t *, uint32_t,
|
||||
int ntspawn(int64_t, const char *, char *const[], char *const[], char *const[],
|
||||
uint32_t, const char16_t *, int64_t, int64_t *, uint32_t,
|
||||
const struct NtStartupInfo *, struct NtProcessInformation *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
|
|
|
@ -44,6 +44,10 @@
|
|||
#include "libc/mem/alloca.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nt/createfile.h"
|
||||
#include "libc/nt/enum/accessmask.h"
|
||||
#include "libc/nt/enum/creationdisposition.h"
|
||||
#include "libc/nt/enum/fileflagandattributes.h"
|
||||
#include "libc/nt/enum/filesharemode.h"
|
||||
#include "libc/nt/enum/processcreationflags.h"
|
||||
#include "libc/nt/enum/startf.h"
|
||||
#include "libc/nt/files.h"
|
||||
|
@ -176,15 +180,15 @@ static textwindows errno_t spawnfds_dup2(struct SpawnFds *fds, int fildes,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static textwindows errno_t spawnfds_open(struct SpawnFds *fds, int fildes,
|
||||
const char *path, int oflag,
|
||||
int mode) {
|
||||
static textwindows errno_t spawnfds_open(struct SpawnFds *fds, int64_t dirhand,
|
||||
int fildes, const char *path,
|
||||
int oflag, int mode) {
|
||||
int64_t h;
|
||||
errno_t err;
|
||||
char16_t path16[PATH_MAX];
|
||||
uint32_t perm, share, disp, attr;
|
||||
if ((err = spawnfds_ensure(fds, fildes))) return err;
|
||||
if (__mkntpathat(AT_FDCWD, path, 0, path16) != -1 &&
|
||||
if (__mkntpathath(dirhand, path, 0, path16) != -1 &&
|
||||
GetNtOpenFlags(oflag, mode, &perm, &share, &disp, &attr) != -1 &&
|
||||
(h = CreateFile(path16, perm, share, &kNtIsInheritable, disp, attr, 0))) {
|
||||
spawnfds_closelater(fds, h);
|
||||
|
@ -198,6 +202,39 @@ static textwindows errno_t spawnfds_open(struct SpawnFds *fds, int fildes,
|
|||
}
|
||||
}
|
||||
|
||||
static textwindows errno_t spawnfds_chdir(struct SpawnFds *fds, int64_t dirhand,
|
||||
const char *path,
|
||||
int64_t *out_dirhand) {
|
||||
int64_t h;
|
||||
char16_t path16[PATH_MAX];
|
||||
if (__mkntpathath(dirhand, path, 0, path16) != -1 &&
|
||||
(h = CreateFile(path16, kNtFileGenericRead,
|
||||
kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete,
|
||||
0, kNtOpenExisting,
|
||||
kNtFileAttributeNormal | kNtFileFlagBackupSemantics,
|
||||
0))) {
|
||||
spawnfds_closelater(fds, h);
|
||||
*out_dirhand = h;
|
||||
return 0;
|
||||
} else {
|
||||
return errno;
|
||||
}
|
||||
}
|
||||
|
||||
static textwindows errno_t spawnfds_fchdir(struct SpawnFds *fds, int fildes,
|
||||
int64_t *out_dirhand) {
|
||||
int64_t h;
|
||||
if (spawnfds_exists(fds, fildes)) {
|
||||
h = fds->p[fildes].handle;
|
||||
} else if (__isfdopen(fildes)) {
|
||||
h = g_fds.p[fildes].handle;
|
||||
} else {
|
||||
return EBADF;
|
||||
}
|
||||
*out_dirhand = h;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static textwindows errno_t posix_spawn_nt_impl(
|
||||
int *pid, const char *path, const posix_spawn_file_actions_t *file_actions,
|
||||
const posix_spawnattr_t *attrp, char *const argv[], char *const envp[]) {
|
||||
|
@ -207,6 +244,7 @@ static textwindows errno_t posix_spawn_nt_impl(
|
|||
errno_t e = errno;
|
||||
struct Proc *proc = 0;
|
||||
struct SpawnFds fds = {0};
|
||||
int64_t dirhand = AT_FDCWD;
|
||||
int64_t *lpExplicitHandles = 0;
|
||||
uint32_t dwExplicitHandleCount = 0;
|
||||
int64_t hCreatorProcess = GetCurrentProcess();
|
||||
|
@ -257,12 +295,27 @@ static textwindows errno_t posix_spawn_nt_impl(
|
|||
}
|
||||
break;
|
||||
case _POSIX_SPAWN_OPEN:
|
||||
err = spawnfds_open(&fds, a->fildes, a->path, a->oflag, a->mode);
|
||||
err = spawnfds_open(&fds, dirhand, a->fildes, a->path, a->oflag,
|
||||
a->mode);
|
||||
if (err) {
|
||||
STRACE("spawnfds_open(%d, %#s) failed", a->fildes, a->path);
|
||||
goto ReturnErr;
|
||||
}
|
||||
break;
|
||||
case _POSIX_SPAWN_CHDIR:
|
||||
err = spawnfds_chdir(&fds, dirhand, a->path, &dirhand);
|
||||
if (err) {
|
||||
STRACE("spawnfds_chdir(%#s) failed", a->path);
|
||||
goto ReturnErr;
|
||||
}
|
||||
break;
|
||||
case _POSIX_SPAWN_FCHDIR:
|
||||
err = spawnfds_fchdir(&fds, a->fildes, &dirhand);
|
||||
if (err) {
|
||||
STRACE("spawnfds_fchdir(%d) failed", a->fildes);
|
||||
goto ReturnErr;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
@ -289,15 +342,26 @@ static textwindows errno_t posix_spawn_nt_impl(
|
|||
.hStdError = spawnfds_handle(&fds, 2),
|
||||
};
|
||||
|
||||
// determine spawn directory
|
||||
char16_t *lpCurrentDirectory = 0;
|
||||
if (dirhand != AT_FDCWD) {
|
||||
lpCurrentDirectory = alloca(PATH_MAX * sizeof(char16_t));
|
||||
if (!GetFinalPathNameByHandle(dirhand, lpCurrentDirectory, PATH_MAX,
|
||||
kNtFileNameNormalized | kNtVolumeNameDos)) {
|
||||
err = GetLastError();
|
||||
goto ReturnErr;
|
||||
}
|
||||
}
|
||||
|
||||
// launch process
|
||||
int rc = -1;
|
||||
struct NtProcessInformation procinfo;
|
||||
if (!envp) envp = environ;
|
||||
if ((fdspec = __describe_fds(fds.p, fds.n, &startinfo, hCreatorProcess,
|
||||
&lpExplicitHandles, &dwExplicitHandleCount))) {
|
||||
rc = ntspawn(path, argv, envp, (char *[]){fdspec, 0}, dwCreationFlags, 0, 0,
|
||||
lpExplicitHandles, dwExplicitHandleCount, &startinfo,
|
||||
&procinfo);
|
||||
rc = ntspawn(dirhand, path, argv, envp, (char *[]){fdspec, 0},
|
||||
dwCreationFlags, lpCurrentDirectory, 0, lpExplicitHandles,
|
||||
dwExplicitHandleCount, &startinfo, &procinfo);
|
||||
}
|
||||
if (rc == -1) {
|
||||
err = errno;
|
||||
|
@ -479,6 +543,16 @@ errno_t posix_spawn(int *pid, const char *path,
|
|||
}
|
||||
break;
|
||||
}
|
||||
case _POSIX_SPAWN_CHDIR:
|
||||
if (chdir(a->path) == -1) {
|
||||
goto ChildFailed;
|
||||
}
|
||||
break;
|
||||
case _POSIX_SPAWN_FCHDIR:
|
||||
if (fchdir(a->fildes) == -1) {
|
||||
goto ChildFailed;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
|
|
@ -31,6 +31,9 @@ int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *, int);
|
|||
int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *, int, int);
|
||||
int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t *, int,
|
||||
const char *, int, unsigned);
|
||||
int posix_spawn_file_actions_addchdir_np(posix_spawn_file_actions_t *,
|
||||
const char *);
|
||||
int posix_spawn_file_actions_addfchdir_np(posix_spawn_file_actions_t *, int);
|
||||
|
||||
int posix_spawnattr_init(posix_spawnattr_t *);
|
||||
int posix_spawnattr_destroy(posix_spawnattr_t *);
|
||||
|
|
|
@ -5,9 +5,11 @@
|
|||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/proc/posix_spawn.h"
|
||||
|
||||
#define _POSIX_SPAWN_CLOSE 1
|
||||
#define _POSIX_SPAWN_DUP2 2
|
||||
#define _POSIX_SPAWN_OPEN 3
|
||||
#define _POSIX_SPAWN_CLOSE 1
|
||||
#define _POSIX_SPAWN_DUP2 2
|
||||
#define _POSIX_SPAWN_OPEN 3
|
||||
#define _POSIX_SPAWN_CHDIR 4
|
||||
#define _POSIX_SPAWN_FCHDIR 5
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
|
41
libc/proc/posix_spawn_file_actions_addchdir_np.c
Normal file
41
libc/proc/posix_spawn_file_actions_addchdir_np.c
Normal 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 2023 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/errno.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/proc/posix_spawn.h"
|
||||
#include "libc/proc/posix_spawn.internal.h"
|
||||
|
||||
/**
|
||||
* Add chdir() action to spawn.
|
||||
*
|
||||
* @param file_actions was initialized by posix_spawn_file_actions_init()
|
||||
* @param path will be safely copied
|
||||
* @return 0 on success, or errno on error
|
||||
* @raise ENOMEM if insufficient memory was available
|
||||
*/
|
||||
int posix_spawn_file_actions_addchdir_np(
|
||||
posix_spawn_file_actions_t *file_actions, const char *path) {
|
||||
char *path2;
|
||||
if (!(path2 = strdup(path))) return ENOMEM;
|
||||
return __posix_spawn_add_file_action(file_actions,
|
||||
(struct _posix_faction){
|
||||
.action = _POSIX_SPAWN_CHDIR,
|
||||
.path = path2,
|
||||
});
|
||||
}
|
39
libc/proc/posix_spawn_file_actions_addfchdir_np.c
Normal file
39
libc/proc/posix_spawn_file_actions_addfchdir_np.c
Normal 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 2023 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/errno.h"
|
||||
#include "libc/proc/posix_spawn.h"
|
||||
#include "libc/proc/posix_spawn.internal.h"
|
||||
|
||||
/**
|
||||
* Add fchdir() action to spawn.
|
||||
*
|
||||
* @param path will be safely copied
|
||||
* @return 0 on success, or errno on error
|
||||
* @raise ENOMEM if insufficient memory was available
|
||||
* @raise EBADF if `fildes` is negative
|
||||
*/
|
||||
int posix_spawn_file_actions_addfchdir_np(
|
||||
posix_spawn_file_actions_t *file_actions, int fildes) {
|
||||
if (fildes < 0) return EBADF;
|
||||
return __posix_spawn_add_file_action(file_actions,
|
||||
(struct _posix_faction){
|
||||
.action = _POSIX_SPAWN_FCHDIR,
|
||||
.fildes = fildes,
|
||||
});
|
||||
}
|
|
@ -29,16 +29,14 @@
|
|||
* @param fildes is what open() result gets duplicated to
|
||||
* @param path will be safely copied
|
||||
* @return 0 on success, or errno on error
|
||||
* @raise ENOMEM if we require more vespene gas
|
||||
* @raise ENOMEM if insufficient memory was available
|
||||
* @raise EBADF if `fildes` is negative
|
||||
* @raise ENOTSUP if `fildes` isn't 0, 1, or 2 on Windows
|
||||
*/
|
||||
int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t *file_actions,
|
||||
int fildes, const char *path, int oflag,
|
||||
unsigned mode) {
|
||||
char *path2;
|
||||
if (fildes < 0) return EBADF;
|
||||
if (IsWindows() && fildes > 2) return ENOTSUP;
|
||||
if (!(path2 = strdup(path))) return ENOMEM;
|
||||
return __posix_spawn_add_file_action(file_actions,
|
||||
(struct _posix_faction){
|
||||
|
|
|
@ -133,7 +133,7 @@ errno_t pthread_setname_np(pthread_t thread, const char *name) {
|
|||
BLOCK_CANCELATION;
|
||||
err = pthread_setname_impl(pt, name);
|
||||
ALLOW_CANCELATION;
|
||||
STRACE("pthread_setname_np(%d, %s) → %s", _pthread_tid(pt), name,
|
||||
STRACE("pthread_setname_np(%d, %#s) → %s", _pthread_tid(pt), name,
|
||||
DescribeErrno(err));
|
||||
return err;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue