diff --git a/src/archiver.c b/src/archiver.c index 6a3a1c7..3be56b5 100644 --- a/src/archiver.c +++ b/src/archiver.c @@ -873,11 +873,31 @@ int write_files_fn(void *data, void *ud) { void cleanup_nop_fn(__attribute__((unused)) void *unused) {} void cleanup_free_fn(void *data) { free(data); } +void simple_archiver_internal_chdir_back2(char **original) { + if (original && *original) { +#if SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX || \ + SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \ + SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_COSMOPOLITAN + chdir(*original); +#endif + free(*original); + *original = NULL; + } +} + int filenames_to_abs_map_fn(void *data, void *ud) { SDArchiverFileInfo *file_info = data; void **ptr_array = ud; SDArchiverHashMap **abs_filenames = ptr_array[0]; const char *user_cwd = ptr_array[1]; + __attribute__(( + cleanup(simple_archiver_internal_chdir_back2))) char *original_cwd = NULL; + if (user_cwd) { + original_cwd = realpath(".", NULL); + if (chdir(user_cwd)) { + return 1; + } + } // Get combined full path to file. char *fullpath = filename_to_absolute_path(file_info->filename); @@ -894,11 +914,7 @@ int filenames_to_abs_map_fn(void *data, void *ud) { #if SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_COSMOPOLITAN || \ SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \ SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX - if (user_cwd) { - cwd_dirname = realpath(user_cwd, NULL); - } else { - cwd_dirname = realpath(".", NULL); - } + cwd_dirname = realpath(".", NULL); #endif if (!cwd_dirname) { return 1; @@ -1081,6 +1097,14 @@ int simple_archiver_write_all(FILE *out_f, SDArchiverState *state, state->out_f = out_f; state->map = abs_filenames; fprintf(stderr, "Begin archiving...\n"); + __attribute__(( + cleanup(simple_archiver_internal_chdir_back2))) char *original_cwd = NULL; + if (state->parsed->user_cwd) { + original_cwd = realpath(".", NULL); + if (chdir(state->parsed->user_cwd)) { + return 1; + } + } fprintf(stderr, "[%10u/%10u]\n", state->count, state->max); if (simple_archiver_list_get(filenames, write_files_fn, state)) { // Error occurred. diff --git a/src/main.c b/src/main.c index 40eef65..52d985f 100644 --- a/src/main.c +++ b/src/main.c @@ -70,6 +70,11 @@ int main(int argc, const char **argv) { __attribute__((cleanup(simple_archiver_list_free))) SDArchiverLinkedList *filenames = simple_archiver_parsed_to_filenames(&parsed); + if (!filenames) { + fprintf(stderr, + "ERROR: Failed to resolve filenames from positional arguments!\n"); + return 8; + } if (filenames->count > 0) { fprintf(stderr, "Filenames:\n"); diff --git a/src/parser.c b/src/parser.c index be1a1e3..81f6d7d 100644 --- a/src/parser.c +++ b/src/parser.c @@ -103,6 +103,18 @@ void simple_archiver_parser_internal_remove_end_slash(char *filename) { } } +void simple_archiver_internal_chdir_back(char **original) { + if (original && *original) { +#if SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX || \ + SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \ + SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_COSMOPOLITAN + chdir(*original); +#endif + free(*original); + *original = NULL; + } +} + void simple_archiver_internal_free_file_info_fn(void *data) { SDArchiverFileInfo *file_info = data; if (file_info) { @@ -305,26 +317,6 @@ int simple_archiver_parse_args(int argc, const char **argv, out->working_files[0] = malloc(arg_length); strncpy(out->working_files[0], argv[0] + arg_idx, arg_length); simple_archiver_parser_internal_remove_end_slash(out->working_files[0]); - if (out->user_cwd) { - if (out->user_cwd[strlen(out->user_cwd) - 1] != '/') { - char *temp = malloc(strlen(out->user_cwd) + 1 + - strlen(out->working_files[0]) + 1); - strncpy(temp, out->user_cwd, strlen(out->user_cwd) + 1); - temp[strlen(out->user_cwd)] = '/'; - strncpy(temp + strlen(out->user_cwd) + 1, out->working_files[0], - strlen(out->working_files[0]) + 1); - free(out->working_files[0]); - out->working_files[0] = temp; - } else { - char *temp = malloc(strlen(out->user_cwd) + - strlen(out->working_files[0]) + 1); - strncpy(temp, out->user_cwd, strlen(out->user_cwd) + 1); - strncpy(temp + strlen(out->user_cwd), out->working_files[0], - strlen(out->working_files[0]) + 1); - free(out->working_files[0]); - out->working_files[0] = temp; - } - } out->working_files[1] = NULL; } else { int working_size = 1; @@ -348,30 +340,6 @@ int simple_archiver_parse_args(int argc, const char **argv, strncpy(out->working_files[working_size - 1], argv[0] + arg_idx, size); simple_archiver_parser_internal_remove_end_slash( out->working_files[working_size - 1]); - if (out->user_cwd) { - if (out->user_cwd[strlen(out->user_cwd) - 1] != '/') { - char *temp = - malloc(strlen(out->user_cwd) + 1 + - strlen(out->working_files[working_size - 1]) + 1); - strncpy(temp, out->user_cwd, strlen(out->user_cwd) + 1); - temp[strlen(out->user_cwd)] = '/'; - strncpy(temp + strlen(out->user_cwd) + 1, - out->working_files[working_size - 1], - strlen(out->working_files[working_size - 1]) + 1); - free(out->working_files[working_size - 1]); - out->working_files[working_size - 1] = temp; - } else { - char *temp = - malloc(strlen(out->user_cwd) + - strlen(out->working_files[working_size - 1]) + 1); - strncpy(temp, out->user_cwd, strlen(out->user_cwd) + 1); - strncpy(temp + strlen(out->user_cwd), - out->working_files[working_size - 1], - strlen(out->working_files[working_size - 1]) + 1); - free(out->working_files[working_size - 1]); - out->working_files[working_size - 1] = temp; - } - } } } @@ -421,6 +389,16 @@ SDArchiverLinkedList *simple_archiver_parsed_to_filenames( #if SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_COSMOPOLITAN || \ SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \ SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX + __attribute__(( + cleanup(simple_archiver_internal_chdir_back))) char *original_cwd = NULL; + if (parsed->user_cwd) { + original_cwd = realpath(".", NULL); + if (chdir(parsed->user_cwd)) { + simple_archiver_list_free(&files_list); + return NULL; + } + } + for (char **iter = parsed->working_files; iter && *iter; ++iter) { struct stat st; memset(&st, 0, sizeof(struct stat));