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 <[email protected]>
This commit is contained in:
Jérôme Duval
2019-02-06 16:39:33 +00:00
committed by Rene Gollent
parent e4803b2c61
commit f33f4868fe
2 changed files with 107 additions and 2 deletions
+33
View File
@@ -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 <spawn.h>
#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_ */
+74 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2017, Jérôme Duval, [email protected]
* Copyright 2017-2019, Jérôme Duval, [email protected]
* 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;
}
}