From bdce9ef7c50e203ce5fd99868ea4951c656d2ec1 Mon Sep 17 00:00:00 2001 From: kamkow1 Date: Sun, 12 Apr 2026 21:27:06 +0200 Subject: [PATCH] CE Add copy command --- ce/interp.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++-- ce/strbuf.c | 5 +++ ce/strbuf.h | 2 ++ 3 files changed, 104 insertions(+), 3 deletions(-) diff --git a/ce/interp.c b/ce/interp.c index c1603e9..abc70b4 100644 --- a/ce/interp.c +++ b/ce/interp.c @@ -203,6 +203,94 @@ static void cat (struct context* context, char** file_paths, size_t files_count) } } +static void copy (struct context* context, const char* path_a, const char* path_b) { + char volume[VOLUME_MAX]; + const char* path; + int ret; + struct strbuf strbuf; + memset (&strbuf, 0, sizeof (strbuf)); + + if (!path_parse (path_a, volume, &path)) { + cprintf (context, "ERROR bad path '%s'\n", path_a); + return; + } + + struct filereader fr; + if ((ret = filereader_init (&fr, volume, path)) < 0) { + cprintf (context, "ERROR could not initialize filereader for '%s:%s'\n", volume, path); + return; + } + + size_t chunk_size = 1024; + char* buffer = arena_malloc (&arena, chunk_size); + + size_t chunks = fr.file_size / chunk_size; + size_t rem = fr.file_size % chunk_size; + + for (size_t chunk = 0; chunk < chunks; chunk++) { + if ((ret = filereader_read (&fr, (uint8_t*)buffer, chunk_size)) < 0) { + filereader_fini (&fr); + cprintf (context, "ERROR filereader failed to read from '%s:%s'\n", volume, path); + return; + } + + strbuf_append_n (&strbuf, buffer, chunk_size); + } + + if (rem > 0) { + if ((ret = filereader_read (&fr, (uint8_t*)buffer, rem)) < 0) { + filereader_fini (&fr); + cprintf (context, "ERROR filereader failed to read from '%s:%s'\n", volume, path); + return; + } + + strbuf_append_n (&strbuf, buffer, rem); + } + + filereader_fini (&fr); + + if (!(path_parse (path_b, volume, &path))) { + cprintf (context, "ERROR bad path '%s'\n", path_b); + return; + } + + uint32_t fw_flags = FW_CREATE_FILE | FW_TRUNCATE; + + struct filewriter fw; + if ((ret = filewriter_init (&fw, volume, path, fw_flags)) < 0) { + cprintf (context, "ERROR could not initialize filewriter for '%s:%s'\n", volume, path); + return; + } + + if (strbuf.count == 0) { + filewriter_fini (&fw); + return; + } + + chunk_size = 1024; + chunks = (strbuf.count - 1) / chunk_size; + rem = (strbuf.count - 1) % chunk_size; + + for (size_t chunk = 0; chunk < chunks; chunk++) { + if ((ret = filewriter_write (&fw, (uint8_t*)&strbuf.items[chunk * chunk_size], chunk_size)) < + 0) { + filewriter_fini (&fw); + cprintf (context, "ERROR filewriter failed to write to '%s:%s'\n", volume, path); + return; + } + } + + if (rem > 0) { + if ((ret = filewriter_write (&fw, (uint8_t*)&strbuf.items[chunks * chunk_size], rem)) < 0) { + filewriter_fini (&fw); + cprintf (context, "ERROR filewriter failed to write to '%s:%s'\n", volume, path); + return; + } + } + + filewriter_fini (&fw); +} + static void ls (struct context* context, const char* path_string) { struct desc desc; char volume[VOLUME_MAX]; @@ -344,6 +432,7 @@ static void help (struct context* context) { cprintf (context, "procinfo\n"); cprintf (context, "quit\n"); cprintf (context, "stall \n"); + cprintf (context, "copy \n"); } struct cmd_write_proc_ctx { @@ -390,7 +479,7 @@ static void execute_cmd (struct ast_cmd* cmd, struct context* context, bool run_ } else if (strcmp (cmd->name, "cat") == 0) { cat (context, cmd->args, cmd->arg_count); } else if (strcmp (cmd->name, "ls") == 0) { - if (cmd->args[0] != NULL) + if (cmd->arg_count == 1) ls (context, cmd->args[0]); else cprintf (context, "ERROR No directory path provided\n"); @@ -403,7 +492,7 @@ static void execute_cmd (struct ast_cmd* cmd, struct context* context, bool run_ } else if (strcmp (cmd->name, "rm") == 0) { rm (context, cmd->args, cmd->arg_count); } else if (strcmp (cmd->name, "edit") == 0) { - if (cmd->args[0] != NULL) + if (cmd->arg_count == 1) edit (context, cmd->args[0]); else cprintf (context, "ERROR No file path provided\n"); @@ -412,7 +501,7 @@ static void execute_cmd (struct ast_cmd* cmd, struct context* context, bool run_ } else if (strcmp (cmd->name, "cls") == 0) { cls (context); } else if (strcmp (cmd->name, "mkvol") == 0) { - if ((cmd->args[0] != NULL) && (cmd->args[1] != NULL) && (cmd->args[2] != NULL)) + if (cmd->arg_count == 3) mkvol (context, cmd->args[0], cmd->args[1], cmd->args[2]); else cprintf (context, "ERROR No volume key, filesystem type or device key provided\n"); @@ -425,6 +514,11 @@ static void execute_cmd (struct ast_cmd* cmd, struct context* context, bool run_ } else { cprintf (context, "ERROR stall requires a timeout argument\n"); } + } else if (strcmp (cmd->name, "copy") == 0) { + if (cmd->arg_count == 2) + copy (context, cmd->args[0], cmd->args[1]); + else + cprintf (context, "ERROR copy requires source and destination\n"); } else { char volume[VOLUME_MAX]; const char* path; diff --git a/ce/strbuf.c b/ce/strbuf.c index 3e22c1d..ce39448 100644 --- a/ce/strbuf.c +++ b/ce/strbuf.c @@ -22,3 +22,8 @@ void strbuf_append_str (struct strbuf* strbuf, const char* s) { while (*s) strbuf_append (strbuf, *s++); } + +void strbuf_append_n (struct strbuf* strbuf, const char* s, size_t n) { + for (size_t i = 0; i < n; i++) + strbuf_append (strbuf, s[i]); +} diff --git a/ce/strbuf.h b/ce/strbuf.h index 672026c..62df7a2 100644 --- a/ce/strbuf.h +++ b/ce/strbuf.h @@ -12,4 +12,6 @@ void strbuf_append (struct strbuf* strbuf, char c); void strbuf_append_str (struct strbuf* strbuf, const char* s); +void strbuf_append_n (struct strbuf* strbuf, const char* s, size_t n); + #endif // _STRBUF_H