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>
This commit is contained in:
Corinna Vinschen 2023-04-18 23:47:28 +02:00
parent d30a5917a9
commit 7e03fc35f5
3 changed files with 95 additions and 3 deletions

View File

@ -587,7 +587,7 @@ case "${host}" in
default_newlib_io_long_double="yes" default_newlib_io_long_double="yes"
default_newlib_io_pos_args="yes" default_newlib_io_pos_args="yes"
CC="${CC} -I${cygwin_srcdir}/include" CC="${CC} -I${cygwin_srcdir}/include"
newlib_cflags="${newlib_cflags} -DHAVE_OPENDIR -DHAVE_RENAME -DGETREENT_PROVIDED -DSIGNAL_PROVIDED -DHAVE_BLKSIZE -DHAVE_FCNTL -DMALLOC_PROVIDED" newlib_cflags="${newlib_cflags} -DHAVE_OPENDIR -DHAVE_RENAME -DGETREENT_PROVIDED -DSIGNAL_PROVIDED -DHAVE_BLKSIZE -DHAVE_FCNTL -DMALLOC_PROVIDED -DHAVE_CHDIR -DHAVE_FCHDIR"
syscall_dir=syscalls syscall_dir=syscalls
;; ;;
# RTEMS supplies its own versions of some routines: # RTEMS supplies its own versions of some routines:

View File

@ -70,6 +70,13 @@ int posix_spawn_file_actions_addopen (posix_spawn_file_actions_t * __restrict,
int, const char * __restrict, int, mode_t); 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_adddup2 (posix_spawn_file_actions_t *, int, int);
int posix_spawn_file_actions_addclose (posix_spawn_file_actions_t *, 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 * Spawn attributes

View File

@ -123,7 +123,13 @@ struct __posix_spawn_file_actions {
typedef struct __posix_spawn_file_actions_entry { typedef struct __posix_spawn_file_actions_entry {
STAILQ_ENTRY(__posix_spawn_file_actions_entry) fae_list; 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; int fae_fildes;
union { union {
@ -139,6 +145,10 @@ typedef struct __posix_spawn_file_actions_entry {
int newfildes; int newfildes;
#define fae_newfildes fae_data.dup2.newfildes #define fae_newfildes fae_data.dup2.newfildes
} dup2; } dup2;
char *dir;
#define fae_dir fae_data.dir
int dirfd;
#define fae_dirfd fae_data.dirfd
} fae_data; } fae_data;
} posix_spawn_file_actions_entry_t; } 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 */ /* Perform a close(), do not fail if already closed */
(void)_close(fae->fae_fildes); (void)_close(fae->fae_fildes);
break; 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); 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); STAILQ_REMOVE_HEAD(&(*fa)->fa_list, fae_list);
/* Deallocate file action entry */ /* Deallocate file action entry */
if (fae->fae_action == FAE_OPEN) switch (fae->fae_action) {
case FAE_OPEN:
free(fae->fae_path); free(fae->fae_path);
break;
#ifdef HAVE_CHDIR
case FAE_CHDIR:
free(fae->fae_dir);
break;
#endif
default:
break;
}
free(fae); free(fae);
} }
@ -496,6 +530,57 @@ posix_spawn_file_actions_addclose (posix_spawn_file_actions_t *fa,
return (0); 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 * Spawn attributes
*/ */