From f33f4868feabef0fbd3b5aaff459e23eedfb7b5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Tue, 5 Feb 2019 20:54:45 +0100 Subject: [PATCH] posix_spawn: add posix_spawn_file_actions_add[f]chdir_np. see http://austingroupbugs.net/view.php?id=1208 and https://sourceware.org/bugzilla/show_bug.cgi?id=17405 * also free paths in posix_spawn_file_actions_destroy(). Change-Id: I8bed848154025bd5a25322bdc4c25aa417f86ec6 Reviewed-on: https://review.haiku-os.org/c/1010 Reviewed-by: Rene Gollent --- headers/compatibility/gnu/spawn.h | 33 +++++++++++++ src/system/libroot/posix/spawn.cpp | 76 +++++++++++++++++++++++++++++- 2 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 headers/compatibility/gnu/spawn.h diff --git a/headers/compatibility/gnu/spawn.h b/headers/compatibility/gnu/spawn.h new file mode 100644 index 0000000000..6c5745f687 --- /dev/null +++ b/headers/compatibility/gnu/spawn.h @@ -0,0 +1,33 @@ +/* + * Copyright 2019 Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the Haiku License. + */ +#ifndef _GNU_SPAWN_H_ +#define _GNU_SPAWN_H_ + + +#include_next + + +#ifdef _GNU_SOURCE + + +#ifdef __cplusplus +extern "C" { +#endif + +extern int posix_spawn_file_actions_addchdir_np( + posix_spawn_file_actions_t *file_actions, const char *path); +extern int posix_spawn_file_actions_addfchdir_np( + posix_spawn_file_actions_t *file_actions, int fildes); + +#ifdef __cplusplus +} +#endif + + +#endif + + +#endif /* _GNU_SPAWN_H_ */ + diff --git a/src/system/libroot/posix/spawn.cpp b/src/system/libroot/posix/spawn.cpp index 473a3b067d..bb5ddfaefc 100644 --- a/src/system/libroot/posix/spawn.cpp +++ b/src/system/libroot/posix/spawn.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2017, Jérôme Duval, jerome.Duval@gmail.com + * Copyright 2017-2019, Jérôme Duval, jerome.Duval@gmail.com * Distributed under the terms of the MIT license. */ @@ -20,7 +20,9 @@ enum action_type { file_action_open, file_action_close, - file_action_dup2 + file_action_dup2, + file_action_chdir, + file_action_fchdir }; struct _file_action { @@ -35,6 +37,9 @@ struct _file_action { struct { int srcfd; } dup2_action; + struct { + char* path; + } chdir_action; } action; }; @@ -90,6 +95,15 @@ posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *_actions) if (actions == NULL) return EINVAL; + for (int i = 0; i < actions->count; i++) { + struct _file_action *action = &actions->actions[i]; + + if (action->type == file_action_open) + free(action->action.open_action.path); + else if (action->type == file_action_chdir) + free(action->action.chdir_action.path); + } + free(actions); return 0; @@ -179,6 +193,58 @@ posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *_actions, } +int +posix_spawn_file_actions_addchdir_np(posix_spawn_file_actions_t *_actions, + const char *path) +{ + struct _posix_spawn_file_actions* actions = _actions != NULL ? *_actions : NULL; + + if (actions == NULL) + return EINVAL; + + char* npath = strdup(path); + if (npath == NULL) + return ENOMEM; + if (actions->count == actions->size + && posix_spawn_file_actions_extend(actions) != 0) { + free(npath); + return ENOMEM; + } + + struct _file_action *action = &actions->actions[actions->count]; + action->type = file_action_chdir; + action->fd = -1; + action->action.chdir_action.path = npath; + actions->count++; + return 0; +} + + +int +posix_spawn_file_actions_addfchdir_np(posix_spawn_file_actions_t *_actions, + int fildes) +{ + struct _posix_spawn_file_actions* actions = _actions != NULL ? *_actions : NULL; + + if (actions == NULL) + return EINVAL; + + if (fildes < 0 || fildes >= sysconf(_SC_OPEN_MAX)) + return EBADF; + + if (actions->count == actions->size + && posix_spawn_file_actions_extend(actions) != 0) { + return ENOMEM; + } + + struct _file_action *action = &actions->actions[actions->count]; + action->type = file_action_fchdir; + action->fd = fildes; + actions->count++; + return 0; +} + + int posix_spawnattr_init(posix_spawnattr_t *_attr) { @@ -415,6 +481,12 @@ process_file_actions(const posix_spawn_file_actions_t *_actions, int *errfd) } else if (action->type == file_action_dup2) { if (dup2(action->action.dup2_action.srcfd, action->fd) == -1) return errno; + } else if (action->type == file_action_chdir) { + if (chdir(action->action.chdir_action.path) == -1) + return errno; + } else if (action->type == file_action_fchdir) { + if (fchdir(action->fd) == -1) + return errno; } }