diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2023-04-18 23:47:28 +0200 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2023-04-18 23:47:28 +0200 |
commit | 7e03fc35f528c7776dac0b4dc0b6814ca012986b (patch) | |
tree | c7585083c8d34559b8f8fb5ec8125afa06d6a996 /newlib/libc | |
parent | d30a5917a9c40aec18c2243dfc2848c616dca77a (diff) | |
download | newlib-7e03fc35f528c7776dac0b4dc0b6814ca012986b.zip newlib-7e03fc35f528c7776dac0b4dc0b6814ca012986b.tar.gz newlib-7e03fc35f528c7776dac0b4dc0b6814ca012986b.tar.bz2 |
Add posix_spawn_file_actions_add{f}chdir_np
These are defined as _np functions and available in glibc, musl, macOS,
FreeBSD, Solaris ≥ 11.3
They are likely to be standardized without the _np suffix as a result of
Austin Group issue 1208. if so, both names will be kept as aliases.
Introduce HAVE_CHDIR and HAVE_FCHDIR to allow building on systems not
providing these calls.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Diffstat (limited to 'newlib/libc')
-rw-r--r-- | newlib/libc/include/spawn.h | 7 | ||||
-rw-r--r-- | newlib/libc/posix/posix_spawn.c | 89 |
2 files changed, 94 insertions, 2 deletions
diff --git a/newlib/libc/include/spawn.h b/newlib/libc/include/spawn.h index d172177..d6ae992 100644 --- a/newlib/libc/include/spawn.h +++ b/newlib/libc/include/spawn.h @@ -70,6 +70,13 @@ int posix_spawn_file_actions_addopen (posix_spawn_file_actions_t * __restrict, int, const char * __restrict, int, mode_t); int posix_spawn_file_actions_adddup2 (posix_spawn_file_actions_t *, int, int); int posix_spawn_file_actions_addclose (posix_spawn_file_actions_t *, int); +#if __MISC_VISIBLE || __GNU_VISIBLE +int posix_spawn_file_actions_addchdir_np (posix_spawn_file_actions_t *__restrict +, + const char *__restrict); +int posix_spawn_file_actions_addfchdir_np (posix_spawn_file_actions_t *__restrict, + int); +#endif /* * Spawn attributes diff --git a/newlib/libc/posix/posix_spawn.c b/newlib/libc/posix/posix_spawn.c index 85bfa64..3506b0f 100644 --- a/newlib/libc/posix/posix_spawn.c +++ b/newlib/libc/posix/posix_spawn.c @@ -123,7 +123,13 @@ struct __posix_spawn_file_actions { typedef struct __posix_spawn_file_actions_entry { STAILQ_ENTRY(__posix_spawn_file_actions_entry) fae_list; - enum { FAE_OPEN, FAE_DUP2, FAE_CLOSE } fae_action; + enum { + FAE_OPEN, + FAE_DUP2, + FAE_CLOSE, + FAE_CHDIR, + FAE_FCHDIR + } fae_action; int fae_fildes; union { @@ -139,6 +145,10 @@ typedef struct __posix_spawn_file_actions_entry { int newfildes; #define fae_newfildes fae_data.dup2.newfildes } dup2; + char *dir; +#define fae_dir fae_data.dir + int dirfd; +#define fae_dirfd fae_data.dirfd } fae_data; } posix_spawn_file_actions_entry_t; @@ -235,7 +245,21 @@ process_file_actions_entry(posix_spawn_file_actions_entry_t *fae) /* Perform a close(), do not fail if already closed */ (void)_close(fae->fae_fildes); break; +#ifdef HAVE_CHDIR + case FAE_CHDIR: + /* Perform a chdir. */ + if (chdir (fae->fae_dir) == -1) + return (errno); + break; +#endif +#ifdef HAVE_FCHDIR + case FAE_FCHDIR: + /* Perform a chdir. */ + if (fchdir (fae->fae_dirfd) == -1) + return (errno); + break; } +#endif return (0); } @@ -407,8 +431,18 @@ posix_spawn_file_actions_destroy (posix_spawn_file_actions_t *fa) STAILQ_REMOVE_HEAD(&(*fa)->fa_list, fae_list); /* Deallocate file action entry */ - if (fae->fae_action == FAE_OPEN) + switch (fae->fae_action) { + case FAE_OPEN: free(fae->fae_path); + break; +#ifdef HAVE_CHDIR + case FAE_CHDIR: + free(fae->fae_dir); + break; +#endif + default: + break; + } free(fae); } @@ -496,6 +530,57 @@ posix_spawn_file_actions_addclose (posix_spawn_file_actions_t *fa, return (0); } +#ifdef HAVE_CHDIR +int +posix_spawn_file_actions_addchdir_np ( + posix_spawn_file_actions_t * __restrict fa, + const char * __restrict path) +{ + posix_spawn_file_actions_entry_t *fae; + int error; + + /* Allocate object */ + fae = malloc(sizeof(posix_spawn_file_actions_entry_t)); + if (fae == NULL) + return (errno); + + /* Set values and store in queue */ + fae->fae_action = FAE_CHDIR; + fae->fae_dir = strdup(path); + if (fae->fae_dir == NULL) { + error = errno; + free(fae); + return (error); + } + + STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list); + return (0); +} +#endif + +#ifdef HAVE_FCHDIR +int +posix_spawn_file_actions_addfchdir_np ( + posix_spawn_file_actions_t * __restrict fa, + int fd) +{ + posix_spawn_file_actions_entry_t *fae; + int error; + + /* Allocate object */ + fae = malloc(sizeof(posix_spawn_file_actions_entry_t)); + if (fae == NULL) + return (errno); + + /* Set values and store in queue */ + fae->fae_action = FAE_FCHDIR; + fae->fae_dirfd = fd; + + STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list); + return (0); +} +#endif + /* * Spawn attributes */ |