diff options
Diffstat (limited to 'src/cli/export.c')
| -rw-r--r-- | src/cli/export.c | 48 |
1 files changed, 45 insertions, 3 deletions
diff --git a/src/cli/export.c b/src/cli/export.c index 4288ba4..d7397c4 100644 --- a/src/cli/export.c +++ b/src/cli/export.c @@ -3,17 +3,42 @@ #include "mcp/tools/common/common.h" #include "storage/codec.h" #include "storage/store.h" +#include "sys/system.h" #include <stdio.h> #include <stdlib.h> #include <string.h> +static bool +export_finish(FILE *output, const char *temporary_path, const char *destination) +{ + bool ok = fflush(output) == 0; + if (output == stdout) + { + return ok; + } + if (fclose(output) != 0) + { + ok = false; + } + if (ok && !tiny_sys_path_replace(temporary_path, destination)) + { + ok = false; + } + if (!ok) + { + (void)tiny_sys_file_remove(temporary_path); + } + return ok; +} + int tiny_cli_export(tiny_store_t *store, const tiny_cli_options_t *options) { size_t index; size_t emitted = 0; FILE *output = NULL; + char *temporary_path = NULL; tiny_json_buffer_t item; if (!options || !options->export_path) @@ -28,9 +53,19 @@ tiny_cli_export(tiny_store_t *store, const tiny_cli_options_t *options) } else { - if (fopen_s(&output, options->export_path, "wb") != 0 || !output) + size_t path_length = strlen(options->export_path); + temporary_path = malloc(path_length + sizeof(".tmp")); + if (!temporary_path) + { + fprintf(stderr, "export: out of memory\n"); + return 1; + } + memcpy(temporary_path, options->export_path, path_length); + memcpy(temporary_path + path_length, ".tmp", sizeof(".tmp")); + if (fopen_s(&output, temporary_path, "wb") != 0 || !output) { fprintf(stderr, "export: unable to open '%s'\n", options->export_path); + free(temporary_path); return 1; } } @@ -41,7 +76,9 @@ tiny_cli_export(tiny_store_t *store, const tiny_cli_options_t *options) if (output != stdout) { fclose(output); + (void)tiny_sys_file_remove(temporary_path); } + free(temporary_path); return 1; } @@ -83,16 +120,21 @@ tiny_cli_export(tiny_store_t *store, const tiny_cli_options_t *options) if (output != stdout) { fclose(output); + (void)tiny_sys_file_remove(temporary_path); } + free(temporary_path); return 1; } emitted++; } - if (output != stdout) + if (!export_finish(output, temporary_path, options->export_path)) { - fclose(output); + fprintf(stderr, "export: unable to complete '%s'\n", options->export_path); + free(temporary_path); + return 1; } + free(temporary_path); (void)emitted; return 0; } |
