]> cloudbase.mooo.com Git - z180-stamp.git/blobdiff - avr/cmd_fat.c
fat ls: works again
[z180-stamp.git] / avr / cmd_fat.c
index f6e1bcceb1183661ce8035a48a39fbce563154c0..0fcc72c51e9ed4bed7325587c381c172a2080799 100644 (file)
@@ -23,8 +23,8 @@
 #include "getopt-min.h"
 
 
-#define DEBUG_CP               0       /* set to 1 to debug */
-#define DEBUG_LS               0       /* set to 1 to debug */
+#define DEBUG_CP               1       /* set to 1 to debug */
+#define DEBUG_LS               1       /* set to 1 to debug */
 
 #define debug_cp(fmt, args...)                                                        \
        debug_cond(DEBUG_CP, fmt, ##args)
@@ -162,6 +162,124 @@ void err(const char *fmt, ...)
        command_ret = CMD_RET_FAILURE;
 }
 
+/******************************************************************************/
+
+/*
+ * These functions manipulate paths in PATH_T structures.
+ *
+ * They eliminate multiple slashes in paths when they notice them,
+ * and keep the path non-slash terminated.
+ *
+ * Both path_set() and path_append() return 0 if the requested name
+ * would be too long.
+ */
+
+
+static void path_init(void)
+{
+       from.p_end = from.p_path; from.p_path[0] = '\0';
+       to.p_end = to.p_path; to.p_path[0] = '\0';
+}
+
+static void strip_trailing_slash(PATH_T *p)
+{
+       char *beg = p->p_path;
+       char *end = p->p_end;
+       if ((beg + 2) < end && (*beg & 0x38) == '0' &&  *(beg+1) == ':')
+               beg += 2;
+       if (beg < end && *beg == '/')
+               ++beg;
+       while (end > beg && end[-1] == '/')
+               *--end = '\0';
+
+       p->p_end =end;
+}
+
+/*
+ * Move specified string into path.  Convert "" to "." to handle BSD
+ * semantics for a null path.  Strip trailing slashes.
+ */
+int
+path_set(PATH_T *p, char *string)
+{
+       if (strlen(string) > MAX_PATHLEN) {
+               err(PSTR("set: '%s': name too long"), string);
+               return 0;
+       }
+
+       (void)strcpy(p->p_path, string);
+       p->p_end = p->p_path + strlen(p->p_path);
+
+       if (p->p_path == p->p_end) {
+               *p->p_end++ = '.';
+               *p->p_end = 0;
+       }
+
+       strip_trailing_slash(p);
+       return 1;
+}
+
+/*
+ * Append specified string to path, inserting '/' if necessary.  Return a
+ * pointer to the old end of path for restoration.
+ */
+char *
+path_append(PATH_T *p, char *name)
+{
+       char *old = p->p_end;
+       int len = strlen(name);
+
+       /* The "+ 1" accounts for the '/' between old path and name. */
+       if ((len + p->p_end - p->p_path + 1) > MAX_PATHLEN) {
+               err(PSTR("append: '%s/%s': name too long"), p->p_path, name);
+               return(0);
+       }
+
+       /*
+        * This code should always be executed, since paths shouldn't
+        * end in '/'.
+        */
+       if (p->p_end[-1] != '/') {
+               *p->p_end++ = '/';
+               *p->p_end = '\0';
+       }
+
+       (void)strncat(p->p_end, name, len);
+       p->p_end += len;
+       *p->p_end = '\0';
+
+       strip_trailing_slash(p);
+       return old;
+}
+
+/*
+ * Restore path to previous value.  (As returned by path_append.)
+ */
+void
+path_restore(PATH_T *p, char *old)
+{
+       p->p_end = old;
+       *p->p_end = '\0';
+}
+
+/*
+ * Return basename of path.
+ */
+char *path_basename(PATH_T *p)
+{
+       char *basename = strrchr(p->p_path, '/');
+
+       if (basename) {
+               ++basename;
+       } else {
+               basename = p->p_path;
+               if ((basename[0] & 0x38) == '0' &&  basename[1] == ':')
+                       basename += 2;
+       }
+
+       return basename;
+}
+
 
 
 static void swirl(void)
@@ -243,7 +361,7 @@ command_ret_t do_cd(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc,
        return CMD_RET_SUCCESS;
 }
 
-
+#if 0
 /*
  * Remove trailing slashes,
  * but keep a leading slash (absolute path)
@@ -263,6 +381,7 @@ void strip_trailing_slash_relpath(char *p)
        while (n-- != 0  && p[n] == '/')
                        p[n] = '\0';
 }
+#endif
 
 int print_dirent(FILINFO *f)
 {
@@ -290,34 +409,27 @@ command_ret_t do_ls(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc,
        unsigned int s1, s2;
        FRESULT res;
 
-       char *path = "";
-       if (argc > 1)
-               path = argv[1];
-       strip_trailing_slash_relpath(path);
 
-       char *p = strrchr(path, '/');
-       if (p)
-               p++;
-       else {
-               p = path;
-               char *q = p;
-               if ((*q++ & 0x38) == '0' &&  *q++ == ':')
-                       p = q;
-       }
+       path_init();
+       if (argc > 1)
+               if (!path_set(&from, argv[1])) {
+                       /* TODO: error out*/
+               }
 
-       char *pattern;
+       char *p = path_basename(&from);
        if (strpbrk_P(p, PSTR("*?")) ||
-                       (f_stat(path, &Finfo) == FR_OK && !(Finfo.fattrib & AM_DIR))) {
-               pattern = strdup(p);
+                       (f_stat(from.p_path, &Finfo) == FR_OK && !(Finfo.fattrib & AM_DIR))) {
+               path_set(&to, p);
                *p = '\0';
-       } else
-               pattern = strdup("*");
-       strip_trailing_slash_relpath(path);
+       } else {
+               to.p_path[0] = '*';
+               to.p_path[1] = '\0';
+       }
 
-debug_ls("==== path: '%s', pattern: '%s'\n", path ? path : "<NULL>", pattern ? pattern : "<NULL>");
+debug_ls("==== path: '%s', pattern: '%s'\n", from.p_path ? from.p_path : "<NULL>", to.p_path ? to.p_path : "<NULL>");
 
        p1 = s1 = s2 = 0;
-       res = f_findfirst(&Dir, &Finfo, path, pattern);  /* Start to search for files */
+       res = f_findfirst(&Dir, &Finfo, from.p_path, to.p_path);  /* Start to search for files */
        while (res == FR_OK && Finfo.fname[0]) {
                if (Finfo.fattrib & AM_DIR) {
                        s2++;
@@ -330,11 +442,10 @@ debug_ls("==== path: '%s', pattern: '%s'\n", path ? path : "<NULL>", pattern ? p
                res = f_findnext(&Dir, &Finfo);
        }
        f_closedir(&Dir);
-       free(pattern);
 
        if (res == FR_OK) {
                printf_P(PSTR("%4u File(s),%10lu bytes total\n%4u Dir(s)"), s1, p1, s2);
-               if (f_getfree(path, (DWORD*)&p1, &fs) == FR_OK)
+               if (f_getfree(from.p_path, (DWORD*)&p1, &fs) == FR_OK)
                        printf_P(PSTR(", %10luK bytes free\n"), p1 * fs->csize / 2);
        }
 
@@ -405,144 +516,8 @@ command_ret_t do_tst(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc
        return CMD_RET_SUCCESS;
 }
 
-#if 0
-static
-FRESULT mkpath(TCHAR *path)
-{
-       /* TODO: */
-       (void) path;
-       FILINFO fd
-       TCHAR *p, *q;
-       FRESULT ret;
-
-       res = f_stat (path, &fd)
-
-       p = strchr(path, ':');
-       if (p == NULL || *++p == '\0' || *p++ != '/')
-               return FR_OK;
-
-       while ((q = strchr(p, '/')) != NULL) {
-               *q = '\0';
-               ret = f_mkdir(path);
-               *q = '/';
-                       if (ret != FR_OK && ret != FR_EXIST)
-                               return ret;
-               p = q + 1;
-       }
-
-       return FR_OK;
-}
-#endif
-
 /******************************************************************************/
 
-/*
- * These functions manipulate paths in PATH_T structures.
- *
- * They eliminate multiple slashes in paths when they notice them,
- * and keep the path non-slash terminated.
- *
- * Both path_set() and path_append() return 0 if the requested name
- * would be too long.
- */
-
-
-static void strip_trailing_slash(PATH_T *p)
-{
-       char *beg = p->p_path;
-       char *end = p->p_end;
-       if ((beg + 2) < end && (*beg & 0x38) == '0' &&  *(beg+1) == ':')
-               beg += 2;
-       if (beg < end && *beg == '/')
-               ++beg;
-       while (end > beg && end[-1] == '/')
-               *--end = '\0';
-
-       p->p_end =end;
-}
-
-/*
- * Move specified string into path.  Convert "" to "." to handle BSD
- * semantics for a null path.  Strip trailing slashes.
- */
-int
-path_set(PATH_T *p, char *string)
-{
-       if (strlen(string) > MAX_PATHLEN) {
-               err(PSTR("set: '%s': name too long"), string);
-               return 0;
-       }
-
-       (void)strcpy(p->p_path, string);
-       p->p_end = p->p_path + strlen(p->p_path);
-
-       if (p->p_path == p->p_end) {
-               *p->p_end++ = '.';
-               *p->p_end = 0;
-       }
-
-       strip_trailing_slash(p);
-       return 1;
-}
-
-/*
- * Append specified string to path, inserting '/' if necessary.  Return a
- * pointer to the old end of path for restoration.
- */
-char *
-path_append(PATH_T *p, char *name, int len)
-{
-       char *old;
-
-       old = p->p_end;
-       if (len == -1)
-               len = strlen(name);
-
-       /* The "+ 1" accounts for the '/' between old path and name. */
-       if ((len + p->p_end - p->p_path + 1) > MAX_PATHLEN) {
-               err(PSTR("append: '%s/%s': name too long"), p->p_path, name);
-               return(0);
-       }
-
-       /*
-        * This code should always be executed, since paths shouldn't
-        * end in '/'.
-        */
-       if (p->p_end[-1] != '/') {
-               *p->p_end++ = '/';
-               *p->p_end = '\0';
-       }
-
-       (void)strncat(p->p_end, name, len);
-       p->p_end += len;
-       *p->p_end = '\0';
-
-       strip_trailing_slash(p);
-       return old;
-}
-
-/*
- * Restore path to previous value.  (As returned by path_append.)
- */
-void
-path_restore(PATH_T *p, char *old)
-{
-       p->p_end = old;
-       *p->p_end = '\0';
-}
-
-/*
- * Return basename of path.
- */
-char *path_basename(PATH_T *p)
-{
-       char *basename;
-
-       basename = strrchr(p->p_path, '/');
-       return(basename ? basename + 1 : p->p_path);
-}
-
-
 static uint8_t flags;
 #define F_FLAG (1<<3)  // overwrite existing file ignoring write protection
 #define I_FLAG (1<<1)  // prompt before overwrite (overrides a previous -n option)
@@ -676,8 +651,8 @@ debug_cp("     from:'%s'  to:'%s'\n", from.p_path, to.p_path);
                 res = f_findfirst(&Dir, &Finfo, from.p_path, pattern)) {
 
                if (!(Finfo.fattrib & AM_DIR) &&
-                               (old_from = path_append(&from, Finfo.fname, 0))) {
-                       if ((old_to = path_append(&to, Finfo.fname, 0))) {
+                               (old_from = path_append(&from, Finfo.fname))) {
+                       if ((old_to = path_append(&to, Finfo.fname))) {
                                copy();
                                path_restore(&to, old_to);
                        }
@@ -690,8 +665,8 @@ debug_cp("     from:'%s'  to:'%s'\n", from.p_path, to.p_path);
                 res = f_findnext(&Dir, &Finfo)) {
 
                if ((Finfo.fattrib & AM_DIR) &&
-                               (old_from = path_append(&from, Finfo.fname, 0))) {
-                       if ((old_to = path_append(&to, Finfo.fname, 0))) {
+                               (old_from = path_append(&from, Finfo.fname))) {
+                       if ((old_to = path_append(&to, Finfo.fname))) {
                                copy();
                                path_restore(&to, old_to);
                        }
@@ -892,17 +867,7 @@ command_ret_t do_cp(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc,
        if (argc < 2)
                return CMD_RET_USAGE;
 
-#if 0
-       from = (PATH_T *) malloc(sizeof(PATH_T));
-       to   = (PATH_T *) malloc(sizeof(PATH_T));
-       if (from == NULL || to == NULL) {
-               printf_P(PSTR("cp: Out of Memory!\n"));
-               command_ret = CMD_RET_FAILURE;
-               goto cleanup;
-       }
-#endif
-       from.p_end = from.p_path; from.p_path[0] = '\0';
-       to.p_end = to.p_path; to.p_path[0] = '\0';
+       path_init();
 
        /* last argument is destination */
        if (!path_set(&to, argv[--argc]))
@@ -954,7 +919,7 @@ debug_cp("     from:'%s'  to:'%s'\n", from.p_path, to.p_path);
                for (;; ++argv) {
                        if (!path_set(&from, *argv))
                                continue;
-                       if (!(old_to = path_append(&to, path_basename(&from), -1)))
+                       if (!(old_to = path_append(&to, path_basename(&from))))
                                continue;
                        copy();
                        if (!--argc)