From cd2bf21f9ab36bac6c0c4004f016cd639b17f0a3 Mon Sep 17 00:00:00 2001 From: Jon Simons Date: Sat, 12 Nov 2022 17:06:31 -0500 Subject: [PATCH] tests/pkd: support -L, --temp-dir= Teach `pkd` a new flag `-L, --temp-dir=` to enable behavior whereby `pkd` creates a new temporary directory and uses it for a workspace while running. The original design of `pkd` assumed that it could freely use the current working directory from wherever it happened to be invoked. But, this could pose a problem when multiple `pkd` instances are run in parallel from the same working directory, due to the usage of various temporary files within that directory. To avoid the problem of multiple `pkd` instances interfering with each other, expose a `-L` flag for optionally specifying a `mkdtemp` template string such that a temporary scratch space is used instead. Testing notes: - I ran handfuls of iterations locally using the new flag and observed `pkd` is indeed using scratch space as desired. Resolves https://gitlab.com/libssh/libssh-mirror/-/issues/143. Signed-off-by: Jon Simons Reviewed-by: Jakub Jelen (cherry picked from commit b610757e6366c3093879f1ac5ddb7520169b0869) --- tests/pkd/pkd_daemon.h | 6 +++ tests/pkd/pkd_hello.c | 99 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 101 insertions(+), 4 deletions(-) diff --git a/tests/pkd/pkd_daemon.h b/tests/pkd/pkd_daemon.h index 493326c1..81273912 100644 --- a/tests/pkd/pkd_daemon.h +++ b/tests/pkd/pkd_daemon.h @@ -30,6 +30,8 @@ struct pkd_daemon_args { uint64_t rekey_data_limit; + int original_dir_fd; + struct { int list; @@ -44,6 +46,10 @@ struct pkd_daemon_args { struct { char *mkdtemp_str; } socket_wrapper; + + struct { + char *mkdtemp_str; + } temp_dir; } opts; }; diff --git a/tests/pkd/pkd_hello.c b/tests/pkd/pkd_hello.c index 18ac97b4..657ce8cc 100644 --- a/tests/pkd/pkd_hello.c +++ b/tests/pkd/pkd_hello.c @@ -1,15 +1,16 @@ /* * pkd_hello.c -- * - * (c) 2014, 2017-2018 Jon Simons + * (c) 2014, 2017-2018, 2022 Jon Simons */ #include "config.h" +#include #include // for cmocka #include // for cmocka #include #include -#include // for cmocka +#include #include #include "libssh/priv.h" @@ -33,7 +34,7 @@ static size_t default_payload_len = sizeof(default_payload_buf); #include #define PROGNAME "pkd_hello" #define ARGP_PROGNAME "libssh " PROGNAME -const char *argp_program_version = ARGP_PROGNAME " 2017-07-12"; +const char *argp_program_version = ARGP_PROGNAME " 2022-11-12"; const char *argp_program_bug_address = "Jon Simons "; static char doc[] = \ @@ -61,6 +62,8 @@ static struct argp_option options[] = { "Run each test for the given number of iterations (default is 10)", 0 }, { "match", 'm', "testmatch", 0, "Run all tests with the given string", 0 }, + { "temp-dir", 'L', "", 0, + "Run in a temporary directory using the given mkdtemp template", 0 }, { "socket-wrapper-dir", 'w', "", 0, "Run in socket-wrapper mode using the given mkdtemp directory template", 0 }, { "stdout", 'o', NULL, 0, @@ -90,6 +93,9 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) { case 'l': pkd_dargs.opts.list = 1; break; + case 'L': + pkd_dargs.opts.temp_dir.mkdtemp_str = arg; + break; case 'i': pkd_dargs.opts.iterations = atoi(arg); break; @@ -950,6 +956,52 @@ static int pkd_run_tests(void) { return rc; } +static int pkd_init_temp_dir(void) { + int rc = 0; + char *mkdtemp_str = NULL; + pkd_dargs.original_dir_fd = -1; + + if (pkd_dargs.opts.temp_dir.mkdtemp_str == NULL) { + return 0; + } + + pkd_dargs.original_dir_fd = open(".", O_RDONLY); + if (pkd_dargs.original_dir_fd < 0) { + fprintf(stderr, "pkd_init_temp_dir open failed\n"); + return -1; + } + + mkdtemp_str = strdup(pkd_dargs.opts.temp_dir.mkdtemp_str); + if (mkdtemp_str == NULL) { + fprintf(stderr, "pkd_init_temp_dir strdup failed\n"); + goto errstrdup; + } + pkd_dargs.opts.temp_dir.mkdtemp_str = mkdtemp_str; + + if (mkdtemp(mkdtemp_str) == NULL) { + fprintf(stderr, "pkd_init_temp_dir mkdtemp '%s' failed\n", mkdtemp_str); + goto errmkdtemp; + } + + rc = chdir(mkdtemp_str); + if (rc != 0) { + fprintf(stderr, "pkd_init_temp_dir chdir '%s' failed\n", mkdtemp_str); + goto errchdir; + } + + return 0; + +errchdir: + rmdir(mkdtemp_str); +errmkdtemp: + free(mkdtemp_str); +errstrdup: + close(pkd_dargs.original_dir_fd); + pkd_dargs.original_dir_fd = -1; + rc = -1; + return rc; +} + static int pkd_init_socket_wrapper(void) { int rc = 0; char *mkdtemp_str = NULL; @@ -991,6 +1043,33 @@ static int pkd_rmfiles(const char *path) { return system_checked(bin); } +static int pkd_cleanup_temp_dir(void) { + int rc = 0; + + if (pkd_dargs.opts.temp_dir.mkdtemp_str == NULL) { + return 0; + } + + if (fchdir(pkd_dargs.original_dir_fd) != 0) { + fprintf(stderr, "pkd_cleanup_temp_dir failed fchdir\n"); + rc = -1; + goto out; + } + + if (rmdir(pkd_dargs.opts.temp_dir.mkdtemp_str) != 0) { + fprintf(stderr, "pkd_cleanup_temp_dir rmdir '%s' failed\n", + pkd_dargs.opts.temp_dir.mkdtemp_str); + rc = -1; + goto out; + } + +out: + close(pkd_dargs.original_dir_fd); + pkd_dargs.original_dir_fd = -1; + free(pkd_dargs.opts.temp_dir.mkdtemp_str); + return rc; +} + static int pkd_cleanup_socket_wrapper(void) { int rc = 0; @@ -1042,10 +1121,16 @@ int main(int argc, char **argv) { (void) argc; (void) argv; #endif /* HAVE_ARGP_H */ + rc = pkd_init_temp_dir(); + if (rc != 0) { + fprintf(stderr, "pkd_init_temp_dir failed: %d\n", rc); + goto out_finalize; + } + rc = pkd_init_socket_wrapper(); if (rc != 0) { fprintf(stderr, "pkd_init_socket_wrapper failed: %d\n", rc); - goto out_finalize; + goto out_tempdir; } if (pkd_dargs.opts.list != 0) { @@ -1064,6 +1149,12 @@ int main(int argc, char **argv) { fprintf(stderr, "pkd_cleanup_socket_wrapper failed: %d\n", rc); } +out_tempdir: + rc = pkd_cleanup_temp_dir(); + if (rc != 0) { + fprintf(stderr, "pkd_cleanup_temp_dir failed: %d\n", rc); + } + out_finalize: rc = ssh_finalize(); if (rc != 0) {