From b6cf9ca456a60870373c9afc848b9bb9b22c431c Mon Sep 17 00:00:00 2001 From: Leo C. Date: Mon, 22 Jul 2024 14:09:10 +0200 Subject: add fat command cp --- avr/cmd_fat.c | 190 ++++++++++++++++++++++++++++++++++++++++++++------------- avr/strerror.c | 3 +- 2 files changed, 150 insertions(+), 43 deletions(-) (limited to 'avr') diff --git a/avr/cmd_fat.c b/avr/cmd_fat.c index c4d17b3..c97fd79 100644 --- a/avr/cmd_fat.c +++ b/avr/cmd_fat.c @@ -24,8 +24,9 @@ uint32_t fat_time(const struct tm * timeptr); #include "getopt-min.h" #define DEBUG_FA 0 /* set to 1 to debug */ -#define DEBUG_LS 1 /* set to 1 to debug */ +#define DEBUG_LS 0 /* set to 1 to debug */ #define DEBUG_RM 0 /* set to 1 to debug */ +#define DEBUG_CP 0 /* set to 1 to debug */ #define debug_fa(fmt, args...) \ debug_cond(DEBUG_FA, fmt, ##args) @@ -33,12 +34,15 @@ uint32_t fat_time(const struct tm * timeptr); debug_cond(DEBUG_LS, fmt, ##args) #define debug_rm(fmt, args...) \ debug_cond(DEBUG_RM, fmt, ##args) +#define debug_cp(fmt, args...) \ + debug_cond(DEBUG_CP, fmt, ##args) /* TODO: use memory size test function (z80_memsize_detect() ) */ -#define MAX_MEMORY CONFIG_SYS_RAMSIZE_MAX -#define BUFFER_SIZE FF_MAX_SS -#define PATH_MAX CONFIG_SYS_MAX_PATHLEN +#define MAX_MEMORY CONFIG_SYS_RAMSIZE_MAX +#define BUFFER_SIZE FF_MAX_SS +#define CPY_BUF_SIZE (2*FF_MAX_SS) +#define PATH_MAX CONFIG_SYS_MAX_PATHLEN /* @@ -293,8 +297,10 @@ command_ret_t do_ls(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc, return CMD_RET_SUCCESS; } -typedef FRESULT (*fatfunc_t)(const TCHAR* path_old, const TCHAR* path_new); +typedef void (*fatfunc_t)(const TCHAR* path_old, const TCHAR* path_new); + +command_ret_t exit_val; uint8_t cmd_flags; #define I_FLAG (1<<1) // prompt before overwrite (overrides a previous -n option) #define N_FLAG (1<<2) // do not overwrite an existing file (overrides a previous -i option) @@ -316,7 +322,57 @@ char* splitpath(const char* path) return NULL; } -FRESULT ff_remove(const TCHAR *file, const TCHAR *dest UNUSED) +/* + * Copy File +*/ +FRESULT copy_file(const TCHAR* src, const TCHAR* dst) +{ + FIL fsrc, fdst; + FRESULT res; + + /* File copy buffer */ + uint8_t *buffer = (uint8_t *) malloc(CPY_BUF_SIZE); + if (buffer == NULL) { + res = (FRESULT) ENOMEM; + } else { + + /* Open source file */ + res = f_open(&fsrc, src, FA_READ); + if (res == FR_OK) { + + /* Create destination file */ + res = f_open(&fdst, dst, FA_WRITE | FA_CREATE_NEW); + if (res == FR_OK) { + UINT br, bw; /* File read/write count */ + + /* Copy source to destination */ + for (;;) { + res = f_read(&fsrc, buffer, CPY_BUF_SIZE, &br); /* Read a chunk of source file */ + if (res || br == 0) + break; /* error or eof */ + res = f_write(&fdst, buffer, br, &bw); /* Write it to the destination file */ + if (res != FR_OK) + break; + if (bw < br) { + res = (FRESULT) EFULL; /* disk full */ + break; + } + } + +debug_cp("==== copy() res: %d, br: %d, bw: %d\n", res, br, bw); + f_close(&fdst); + if (res != FR_OK) + f_unlink(dst); + } + f_close(&fsrc); + } + free(buffer); + } + + return res; +} + +void ff_remove(const TCHAR *file, const TCHAR *dest UNUSED) { FRESULT res = FR_OK; @@ -325,15 +381,31 @@ FRESULT ff_remove(const TCHAR *file, const TCHAR *dest UNUSED) if (!(cmd_flags & N_FLAG)) { if ((res = f_unlink(file)) == FR_OK) { if (cmd_flags & V_FLAG) - printf_P(PSTR("removed '%s'\n"), file); + printf_P(PSTR("removed: '%s'\n"), file); } else { cmd_error(0, res, PSTR("cannot remove '%s'"), file); } } else { - printf_P(PSTR("not removed '%s'\n"), file); + printf_P(PSTR("not removed: '%s'\n"), file); } - return res; + exit_val = (res != FR_OK); + return; +} + +void ff_copy(const TCHAR* path_old, const TCHAR* path_new) +{ + FRESULT res; + + debug_cp("==== ff_copy: '%s' --> '%s'\n", path_old, path_new); + + if (cmd_flags & V_FLAG) + printf_P(PSTR("'%s' -> '%s'\n"), path_old, path_new); + if ((res = copy_file(path_old, path_new)) != FR_OK) + cmd_error(0, res, PSTR("error copying '%s' to '%s'"), path_old, path_new); + + exit_val = (res != FR_OK); + return; } void ff_iterate(fatfunc_t fatfunc, int count, char* const file[], char* dest) @@ -353,9 +425,6 @@ void ff_iterate(fatfunc_t fatfunc, int count, char* const file[], char* dest) pattern = (char *) malloc(strlen(p1)+1); strcpy(pattern, p1); } - - debug_rm("### iter1 srcpath, pattern: '%s', '%s'\n", srcpath, pattern ? pattern : ""); - if (pattern != NULL) { res = f_findfirst(&dir, &finfo, srcpath, pattern); p1 = srcpath+strlen(srcpath)-1; @@ -365,39 +434,36 @@ void ff_iterate(fatfunc_t fatfunc, int count, char* const file[], char* dest) res = f_findfirst(&dir, &finfo, ".", file[i]); p1 = srcpath; } - if (finfo.fname[0] == 0) - cmd_error(0, res, PSTR("cannot remove '%s': no such file or directory"), file[i]); - - - while (res == FR_OK && finfo.fname[0] != 0) { - strcpy(p1, finfo.fname); - - debug_rm("### iter3 srcpath: '%s'\n", srcpath); - - if (dest != NULL) { - strcpy(destpath, dest); - if (dest_is_dir) { - strcat_P(destpath, PSTR("/")); - strcat(destpath, finfo.fname); - } - } - fatfunc(srcpath, destpath); - res = f_findnext(&dir, &finfo); - debug_rm("### iter4 res, .fname: %d, '%s'\n", res, finfo.fname); + if ((res != FR_OK) || (finfo.fname[0] == 0)) { + cmd_error(0, res, PSTR("'%s': no such file or directory"), file[i]); + exit_val = CMD_RET_FAILURE; + } else { - } - res = f_closedir(&dir); + while (res == FR_OK && finfo.fname[0] != 0) { + strcpy(p1, finfo.fname); + if (dest != NULL) { + strcpy(destpath, dest); + if (dest_is_dir) { + strcat_P(destpath, PSTR("/")); + strcat(destpath, finfo.fname); + } + } + fatfunc(srcpath, destpath); + res = f_findnext(&dir, &finfo); + } + if (res != FR_OK) + cmd_error(CMD_RET_FAILURE, res, PSTR("error enumerating files")); + } + f_closedir(&dir); free(pattern); } - if (res != FR_OK) - cmd_error(CMD_RET_FAILURE, res, PSTR("error enumerating files")); - //printf_P(PSTR("error enumerating files: %S\n"), ffw_error(res)); } command_ret_t do_rm(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc, char * const argv[]) { - + exit_val = CMD_RET_SUCCESS; cmd_flags = 0; + int opt; while ((opt = getopt(argc, argv, PSTR("nv"))) != -1) { switch (opt) { @@ -422,7 +488,36 @@ command_ret_t do_rm(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc, ff_iterate(ff_remove, argc, argv, NULL); - return CMD_RET_SUCCESS; + return exit_val; +} + +command_ret_t do_cp(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc, char * const argv[]) +{ + exit_val = CMD_RET_SUCCESS; + cmd_flags = 0; + + int opt; + while ((opt = getopt(argc, argv, PSTR("v"))) != -1) { + switch (opt) { + case 'v': + cmd_flags |= V_FLAG; + break; + default: + return CMD_RET_USAGE; + break; + } + } + argc -= optind; + argv += optind; + + debug_cp("==== do_rm: argc, argv[0]: %d, '%s'\n", argc, argv[0]); + + if (argc < 2) + return CMD_RET_USAGE; + + ff_iterate(ff_copy, argc - 1, argv, argv[argc - 1]); + + return exit_val; } /* @@ -749,13 +844,24 @@ CMD_TBL_ITEM( ), CMD_TBL_ITEM( rm, CONFIG_SYS_MAXARGS, 0, do_rm, - "Remove FILE(s)", + "Remove FILE(s) or empty DIRECTORY(ies)", "[OPTION]... [FILE]...\n" //" -i prompt before removal\n" - " -v explain what is being done\n" - "\n" - "rm removes directories, if they are empty." + " -n do not remove\n" + " -v explain what is being done" +), +CMD_TBL_ITEM( + cp, CONFIG_SYS_MAXARGS, 0, do_cp, + "Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.", + "[OPTION]... SOURCE... DEST\n" +// " -f overwrite existing file ignoring write protection\n" +// " this option is ignored when the -n option is also used\n" +// " -i prompt before overwrite (overrides a previous -n option)\n" +// " -n do not overwrite an existing file (overrides a previous -i option)\n" +// " -p preserve attributes and timestamps\n" + " -v explain what is being done" ), + CMD_TBL_ITEM( load, 5, 0, do_rw, "load binary file from a dos filesystem", diff --git a/avr/strerror.c b/avr/strerror.c index 199504a..f5850f7 100644 --- a/avr/strerror.c +++ b/avr/strerror.c @@ -10,7 +10,7 @@ static const FLASH char * const FLASH error_strings[] = { FSTR("Unknown error"), - FSTR("Not enough memory"), /* 101 */ + FSTR("Not enough memory"), /* 101 */ FSTR("Interrupt"), /* 102 */ FSTR("Bus timeout"), /* 103 */ FSTR("Unexpected argument"), /* 104 */ @@ -22,6 +22,7 @@ static const FLASH char * const FLASH error_strings[] = { FSTR("CPU is running"), /* 110 */ FSTR("Invalid argument"), /* 111 */ FSTR("Unexpected EOF"), /* 112 */ + FSTR("Disk full"), /* 113 */ }; -- cgit v1.2.3