summaryrefslogtreecommitdiff
path: root/src/cli/export.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cli/export.c')
-rw-r--r--src/cli/export.c48
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;
}