diff --git a/components/dfs/src/dfs_file.c b/components/dfs/src/dfs_file.c index 3ec9b5b5b08276715c4c326409e51d0738fed2e3..32198371d7dd1e0fcaf925ac3d2df70d2c0ca61e 100644 --- a/components/dfs/src/dfs_file.c +++ b/components/dfs/src/dfs_file.c @@ -593,7 +593,7 @@ void cat(const char* filename) FINSH_FUNCTION_EXPORT(cat, print file) #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; rt_uint8_t *block_ptr; @@ -637,7 +637,171 @@ void copy(const char *src, const char *dst) dfs_file_close(&fd); 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 /* @} */