]> cloudbase.mooo.com Git - z180-stamp.git/blobdiff - avr/cmd_fat.c
add fat command cp
[z180-stamp.git] / avr / cmd_fat.c
index c4d17b3661159ec83696f451fc8673c210ed7645..c97fd79cdb51b5ba271cc5a159da06d4fab6fad3 100644 (file)
@@ -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 : "<NULL>");
-
         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",