Browse Source

dfs: support copy directory

prife 11 years ago
parent
commit
f015f36d05
1 changed files with 166 additions and 2 deletions
  1. 166 2
      components/dfs/src/dfs_file.c

+ 166 - 2
components/dfs/src/dfs_file.c

@@ -593,7 +593,7 @@ void cat(const char* filename)
 FINSH_FUNCTION_EXPORT(cat, print file)
 FINSH_FUNCTION_EXPORT(cat, print file)
 
 
 #define BUF_SZ  4096
 #define BUF_SZ  4096
-void copy(const char *src, const char *dst)
+static void copyfile(const char *src, const char *dst)
 {
 {
     struct dfs_fd src_fd;
     struct dfs_fd src_fd;
     rt_uint8_t *block_ptr;
     rt_uint8_t *block_ptr;
@@ -637,7 +637,171 @@ void copy(const char *src, const char *dst)
     dfs_file_close(&fd);
     dfs_file_close(&fd);
     rt_free(block_ptr);
     rt_free(block_ptr);
 }
 }
-FINSH_FUNCTION_EXPORT(copy, copy source file to destination file)
+
+extern int mkdir(const char *path, mode_t mode);
+static void copydir(const char * src, const char * dst)
+{
+    struct dfs_fd fd;
+    struct dirent dirent;
+    struct stat stat;
+    int length;
+
+    if (dfs_file_open(&fd, src, DFS_O_DIRECTORY) < 0)
+    {
+        rt_kprintf("open %s failed\n", src);
+        return ;
+    }
+
+    do
+    {
+        rt_memset(&dirent, 0, sizeof(struct dirent));
+        length = dfs_file_getdents(&fd, &dirent, sizeof(struct dirent));
+        if (length > 0)
+        {
+            char * src_entry_full = RT_NULL;
+            char * dst_entry_full = RT_NULL;
+
+            if (strcmp(dirent.d_name, "..") == 0 || strcmp(dirent.d_name, ".") == 0)
+                continue;
+
+            /* build full path for each file */
+            if ((src_entry_full = dfs_normalize_path(src, dirent.d_name)) == RT_NULL)
+            {
+                rt_kprintf("out of memory!\n");
+                break;
+            }
+            if ((dst_entry_full = dfs_normalize_path(dst, dirent.d_name)) == RT_NULL)
+            {
+                rt_kprintf("out of memory!\n");
+                rt_free(src_entry_full);
+                break;
+            }
+
+            rt_memset(&stat, 0, sizeof(struct stat));
+            if (dfs_file_stat(src_entry_full, &stat) != 0)
+            {
+                rt_kprintf("open file: %s failed\n", dirent.d_name);
+                continue;
+            }
+
+            if (DFS_S_ISDIR(stat.st_mode))
+            {
+                mkdir(dst_entry_full, 0);
+                copydir(src_entry_full, dst_entry_full);
+            }
+            else
+            {
+                copyfile(src_entry_full, dst_entry_full);
+            }
+            rt_free(src_entry_full);
+            rt_free(dst_entry_full);
+        }
+    }while(length > 0);
+
+    dfs_file_close(&fd);
+}
+
+static const char *_get_path_lastname(const char *path)
+{
+    char * ptr;
+    if ((ptr = strrchr(path, '/')) == RT_NULL)
+        return path;
+
+    /* skip the '/' then return */
+    return ++ptr;
+}
+void copy(const char *src, const char *dst)
+{
+#define FLAG_SRC_TYPE      0x03
+#define FLAG_SRC_IS_DIR    0x01
+#define FLAG_SRC_IS_FILE   0x02
+#define FLAG_SRC_NON_EXSIT 0x00
+
+#define FLAG_DST_TYPE      0x0C
+#define FLAG_DST_IS_DIR    0x04
+#define FLAG_DST_IS_FILE   0x08
+#define FLAG_DST_NON_EXSIT 0x00
+
+    struct stat stat;
+    rt_uint32_t flag = 0;
+
+    /* check the staus of src and dst */
+    if (dfs_file_stat(src, &stat) < 0)
+    {
+        rt_kprintf("copy failed, bad %s\n", src);
+        return;
+    }
+    if (DFS_S_ISDIR(stat.st_mode))
+        flag |= FLAG_SRC_IS_DIR;
+    else
+        flag |= FLAG_SRC_IS_FILE;
+
+    if (dfs_file_stat(dst, &stat) < 0)
+    {
+        flag |= FLAG_DST_NON_EXSIT;
+    }
+    else
+    {
+        if (DFS_S_ISDIR(stat.st_mode))
+            flag |= FLAG_DST_IS_DIR;
+        else
+            flag |= FLAG_DST_IS_FILE;
+    }
+
+    //2. check status
+    if ((flag & FLAG_SRC_IS_DIR) && (flag & FLAG_DST_IS_FILE))
+    {
+        rt_kprintf("cp faild, cp dir to file is not permitted!\n");
+        return ;
+    }
+
+    //3. do copy
+    if (flag & FLAG_SRC_IS_FILE)
+    {
+        if (flag & FLAG_DST_IS_DIR)
+        {
+            char * fdst;
+            fdst = dfs_normalize_path(dst, _get_path_lastname(src));
+            if (fdst == NULL)
+            {
+                rt_kprintf("out of memory\n");
+                return;
+            }
+            copyfile(src, fdst);
+            rt_free(fdst);
+        }
+        else
+        {
+            copyfile(src, dst);
+        }
+    }
+    else //flag & FLAG_SRC_IS_DIR
+    {
+        if (flag & FLAG_DST_IS_DIR)
+        {
+            char * fdst;
+            fdst = dfs_normalize_path(dst, _get_path_lastname(src));
+            if (fdst == NULL)
+            {
+                rt_kprintf("out of memory\n");
+                return;
+            }
+            mkdir(fdst, 0);
+            copydir(src, fdst);
+            rt_free(fdst);
+        }
+        else if ((flag & FLAG_DST_TYPE) == FLAG_DST_NON_EXSIT)
+        {
+            mkdir(dst, 0);
+            copydir(src, dst);
+        }
+        else
+        {
+            copydir(src, dst);
+        }
+    }
+}
+FINSH_FUNCTION_EXPORT(copy, copy file or dir)
 
 
 #endif
 #endif
 /* @} */
 /* @} */