dfs_file.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846
  1. /*
  2. * Copyright (c) 2006-2018, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2005-02-22 Bernard The first version.
  9. * 2011-12-08 Bernard Merges rename patch from iamcacy.
  10. * 2015-05-27 Bernard Fix the fd clear issue.
  11. * 2019-01-24 Bernard Remove file repeatedly open check.
  12. */
  13. #include <dfs.h>
  14. #include <dfs_file.h>
  15. #include <dfs_private.h>
  16. /**
  17. * @addtogroup FileApi
  18. */
  19. /*@{*/
  20. /**
  21. * this function will open a file which specified by path with specified flags.
  22. *
  23. * @param fd the file descriptor pointer to return the corresponding result.
  24. * @param path the specified file path.
  25. * @param flags the flags for open operator.
  26. *
  27. * @return 0 on successful, -1 on failed.
  28. */
  29. int dfs_file_open(struct dfs_fd *fd, const char *path, int flags)
  30. {
  31. struct dfs_filesystem *fs;
  32. char *fullpath;
  33. int result;
  34. /* parameter check */
  35. if (fd == NULL)
  36. return -EINVAL;
  37. /* make sure we have an absolute path */
  38. fullpath = dfs_normalize_path(NULL, path);
  39. if (fullpath == NULL)
  40. {
  41. return -ENOMEM;
  42. }
  43. LOG_D("open file:%s", fullpath);
  44. /* find filesystem */
  45. fs = dfs_filesystem_lookup(fullpath);
  46. if (fs == NULL)
  47. {
  48. rt_free(fullpath); /* release path */
  49. return -ENOENT;
  50. }
  51. LOG_D("open in filesystem:%s", fs->ops->name);
  52. fd->fs = fs; /* set file system */
  53. fd->fops = fs->ops->fops; /* set file ops */
  54. /* initialize the fd item */
  55. fd->type = FT_REGULAR;
  56. fd->flags = flags;
  57. fd->size = 0;
  58. fd->pos = 0;
  59. fd->data = fs;
  60. if (!(fs->ops->flags & DFS_FS_FLAG_FULLPATH))
  61. {
  62. if (dfs_subdir(fs->path, fullpath) == NULL)
  63. fd->path = rt_strdup("/");
  64. else
  65. fd->path = rt_strdup(dfs_subdir(fs->path, fullpath));
  66. rt_free(fullpath);
  67. LOG_D("Actual file path: %s", fd->path);
  68. }
  69. else
  70. {
  71. fd->path = fullpath;
  72. }
  73. /* specific file system open routine */
  74. if (fd->fops->open == NULL)
  75. {
  76. /* clear fd */
  77. rt_free(fd->path);
  78. fd->path = NULL;
  79. return -ENOSYS;
  80. }
  81. if ((result = fd->fops->open(fd)) < 0)
  82. {
  83. /* clear fd */
  84. rt_free(fd->path);
  85. fd->path = NULL;
  86. LOG_D("%s open failed", fullpath);
  87. return result;
  88. }
  89. fd->flags |= DFS_F_OPEN;
  90. if (flags & O_DIRECTORY)
  91. {
  92. fd->type = FT_DIRECTORY;
  93. fd->flags |= DFS_F_DIRECTORY;
  94. }
  95. LOG_D("open successful");
  96. return 0;
  97. }
  98. /**
  99. * this function will close a file descriptor.
  100. *
  101. * @param fd the file descriptor to be closed.
  102. *
  103. * @return 0 on successful, -1 on failed.
  104. */
  105. int dfs_file_close(struct dfs_fd *fd)
  106. {
  107. int result = 0;
  108. if (fd == NULL)
  109. return -ENXIO;
  110. if (fd->fops->close != NULL)
  111. result = fd->fops->close(fd);
  112. /* close fd error, return */
  113. if (result < 0)
  114. return result;
  115. rt_free(fd->path);
  116. fd->path = NULL;
  117. return result;
  118. }
  119. /**
  120. * this function will perform a io control on a file descriptor.
  121. *
  122. * @param fd the file descriptor.
  123. * @param cmd the command to send to file descriptor.
  124. * @param args the argument to send to file descriptor.
  125. *
  126. * @return 0 on successful, -1 on failed.
  127. */
  128. int dfs_file_ioctl(struct dfs_fd *fd, int cmd, void *args)
  129. {
  130. if (fd == NULL)
  131. return -EINVAL;
  132. /* regular file system fd */
  133. if (fd->type == FT_REGULAR || fd->type == FT_DEVICE)
  134. {
  135. switch (cmd)
  136. {
  137. case F_GETFL:
  138. return fd->flags; /* return flags */
  139. case F_SETFL:
  140. {
  141. int flags = (int)(rt_base_t)args;
  142. int mask = O_NONBLOCK | O_APPEND;
  143. flags &= mask;
  144. fd->flags &= ~mask;
  145. fd->flags |= flags;
  146. }
  147. return 0;
  148. }
  149. }
  150. if (fd->fops->ioctl != NULL)
  151. return fd->fops->ioctl(fd, cmd, args);
  152. return -ENOSYS;
  153. }
  154. /**
  155. * this function will read specified length data from a file descriptor to a
  156. * buffer.
  157. *
  158. * @param fd the file descriptor.
  159. * @param buf the buffer to save the read data.
  160. * @param len the length of data buffer to be read.
  161. *
  162. * @return the actual read data bytes or 0 on end of file or failed.
  163. */
  164. int dfs_file_read(struct dfs_fd *fd, void *buf, size_t len)
  165. {
  166. int result = 0;
  167. if (fd == NULL)
  168. return -EINVAL;
  169. if (fd->fops->read == NULL)
  170. return -ENOSYS;
  171. if ((result = fd->fops->read(fd, buf, len)) < 0)
  172. fd->flags |= DFS_F_EOF;
  173. return result;
  174. }
  175. /**
  176. * this function will fetch directory entries from a directory descriptor.
  177. *
  178. * @param fd the directory descriptor.
  179. * @param dirp the dirent buffer to save result.
  180. * @param nbytes the available room in the buffer.
  181. *
  182. * @return the read dirent, others on failed.
  183. */
  184. int dfs_file_getdents(struct dfs_fd *fd, struct dirent *dirp, size_t nbytes)
  185. {
  186. /* parameter check */
  187. if (fd == NULL || fd->type != FT_DIRECTORY)
  188. return -EINVAL;
  189. if (fd->fops->getdents != NULL)
  190. return fd->fops->getdents(fd, dirp, nbytes);
  191. return -ENOSYS;
  192. }
  193. /**
  194. * this function will unlink (remove) a specified path file from file system.
  195. *
  196. * @param path the specified path file to be unlinked.
  197. *
  198. * @return 0 on successful, -1 on failed.
  199. */
  200. int dfs_file_unlink(const char *path)
  201. {
  202. int result;
  203. char *fullpath;
  204. struct dfs_filesystem *fs;
  205. /* Make sure we have an absolute path */
  206. fullpath = dfs_normalize_path(NULL, path);
  207. if (fullpath == NULL)
  208. {
  209. return -EINVAL;
  210. }
  211. /* get filesystem */
  212. if ((fs = dfs_filesystem_lookup(fullpath)) == NULL)
  213. {
  214. result = -ENOENT;
  215. goto __exit;
  216. }
  217. /* Check whether file is already open */
  218. if (fd_is_open(fullpath) == 0)
  219. {
  220. result = -EBUSY;
  221. goto __exit;
  222. }
  223. if (fs->ops->unlink != NULL)
  224. {
  225. if (!(fs->ops->flags & DFS_FS_FLAG_FULLPATH))
  226. {
  227. if (dfs_subdir(fs->path, fullpath) == NULL)
  228. result = fs->ops->unlink(fs, "/");
  229. else
  230. result = fs->ops->unlink(fs, dfs_subdir(fs->path, fullpath));
  231. }
  232. else
  233. result = fs->ops->unlink(fs, fullpath);
  234. }
  235. else result = -ENOSYS;
  236. __exit:
  237. rt_free(fullpath);
  238. return result;
  239. }
  240. /**
  241. * this function will write some specified length data to file system.
  242. *
  243. * @param fd the file descriptor.
  244. * @param buf the data buffer to be written.
  245. * @param len the data buffer length
  246. *
  247. * @return the actual written data length.
  248. */
  249. int dfs_file_write(struct dfs_fd *fd, const void *buf, size_t len)
  250. {
  251. if (fd == NULL)
  252. return -EINVAL;
  253. if (fd->fops->write == NULL)
  254. return -ENOSYS;
  255. return fd->fops->write(fd, buf, len);
  256. }
  257. /**
  258. * this function will flush buffer on a file descriptor.
  259. *
  260. * @param fd the file descriptor.
  261. *
  262. * @return 0 on successful, -1 on failed.
  263. */
  264. int dfs_file_flush(struct dfs_fd *fd)
  265. {
  266. if (fd == NULL)
  267. return -EINVAL;
  268. if (fd->fops->flush == NULL)
  269. return -ENOSYS;
  270. return fd->fops->flush(fd);
  271. }
  272. /**
  273. * this function will seek the offset for specified file descriptor.
  274. *
  275. * @param fd the file descriptor.
  276. * @param offset the offset to be sought.
  277. *
  278. * @return the current position after seek.
  279. */
  280. int dfs_file_lseek(struct dfs_fd *fd, off_t offset)
  281. {
  282. int result;
  283. if (fd == NULL)
  284. return -EINVAL;
  285. if (fd->fops->lseek == NULL)
  286. return -ENOSYS;
  287. result = fd->fops->lseek(fd, offset);
  288. /* update current position */
  289. if (result >= 0)
  290. fd->pos = result;
  291. return result;
  292. }
  293. /**
  294. * this function will get file information.
  295. *
  296. * @param path the file path.
  297. * @param buf the data buffer to save stat description.
  298. *
  299. * @return 0 on successful, -1 on failed.
  300. */
  301. int dfs_file_stat(const char *path, struct stat *buf)
  302. {
  303. int result;
  304. char *fullpath;
  305. struct dfs_filesystem *fs;
  306. fullpath = dfs_normalize_path(NULL, path);
  307. if (fullpath == NULL)
  308. {
  309. return -1;
  310. }
  311. if ((fs = dfs_filesystem_lookup(fullpath)) == NULL)
  312. {
  313. LOG_E("can't find mounted filesystem on this path:%s", fullpath);
  314. rt_free(fullpath);
  315. return -ENOENT;
  316. }
  317. if ((fullpath[0] == '/' && fullpath[1] == '\0') ||
  318. (dfs_subdir(fs->path, fullpath) == NULL))
  319. {
  320. /* it's the root directory */
  321. buf->st_dev = 0;
  322. buf->st_mode = S_IRUSR | S_IRGRP | S_IROTH |
  323. S_IWUSR | S_IWGRP | S_IWOTH;
  324. buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
  325. buf->st_size = 0;
  326. buf->st_mtime = 0;
  327. /* release full path */
  328. rt_free(fullpath);
  329. return RT_EOK;
  330. }
  331. else
  332. {
  333. if (fs->ops->stat == NULL)
  334. {
  335. rt_free(fullpath);
  336. LOG_E("the filesystem didn't implement this function");
  337. return -ENOSYS;
  338. }
  339. /* get the real file path and get file stat */
  340. if (fs->ops->flags & DFS_FS_FLAG_FULLPATH)
  341. result = fs->ops->stat(fs, fullpath, buf);
  342. else
  343. result = fs->ops->stat(fs, dfs_subdir(fs->path, fullpath), buf);
  344. }
  345. rt_free(fullpath);
  346. return result;
  347. }
  348. /**
  349. * this function will rename an old path name to a new path name.
  350. *
  351. * @param oldpath the old path name.
  352. * @param newpath the new path name.
  353. *
  354. * @return 0 on successful, -1 on failed.
  355. */
  356. int dfs_file_rename(const char *oldpath, const char *newpath)
  357. {
  358. int result;
  359. struct dfs_filesystem *oldfs, *newfs;
  360. char *oldfullpath, *newfullpath;
  361. result = RT_EOK;
  362. newfullpath = NULL;
  363. oldfullpath = NULL;
  364. oldfullpath = dfs_normalize_path(NULL, oldpath);
  365. if (oldfullpath == NULL)
  366. {
  367. result = -ENOENT;
  368. goto __exit;
  369. }
  370. newfullpath = dfs_normalize_path(NULL, newpath);
  371. if (newfullpath == NULL)
  372. {
  373. result = -ENOENT;
  374. goto __exit;
  375. }
  376. oldfs = dfs_filesystem_lookup(oldfullpath);
  377. newfs = dfs_filesystem_lookup(newfullpath);
  378. if (oldfs == newfs)
  379. {
  380. if (oldfs->ops->rename == NULL)
  381. {
  382. result = -ENOSYS;
  383. }
  384. else
  385. {
  386. if (oldfs->ops->flags & DFS_FS_FLAG_FULLPATH)
  387. result = oldfs->ops->rename(oldfs, oldfullpath, newfullpath);
  388. else
  389. /* use sub directory to rename in file system */
  390. result = oldfs->ops->rename(oldfs,
  391. dfs_subdir(oldfs->path, oldfullpath),
  392. dfs_subdir(newfs->path, newfullpath));
  393. }
  394. }
  395. else
  396. {
  397. result = -EXDEV;
  398. }
  399. __exit:
  400. rt_free(oldfullpath);
  401. rt_free(newfullpath);
  402. /* not at same file system, return EXDEV */
  403. return result;
  404. }
  405. /**
  406. * this function is will cause the regular file referenced by fd
  407. * to be truncated to a size of precisely length bytes.
  408. *
  409. * @param fd the file descriptor.
  410. * @param length the length to be truncated.
  411. *
  412. * @return the status of truncated.
  413. */
  414. int dfs_file_ftruncate(struct dfs_fd *fd, off_t length)
  415. {
  416. int result;
  417. /* fd is null or not a regular file system fd, or length is invalid */
  418. if (fd == NULL || fd->type != FT_REGULAR || length < 0)
  419. return -EINVAL;
  420. if (fd->fops->ioctl == NULL)
  421. return -ENOSYS;
  422. result = fd->fops->ioctl(fd, RT_FIOFTRUNCATE, (void*)&length);
  423. /* update current size */
  424. if (result == 0)
  425. fd->size = length;
  426. return result;
  427. }
  428. #ifdef RT_USING_FINSH
  429. #include <finsh.h>
  430. static struct dfs_fd fd;
  431. static struct dirent dirent;
  432. void ls(const char *pathname)
  433. {
  434. struct stat stat;
  435. int length;
  436. char *fullpath, *path;
  437. fullpath = NULL;
  438. if (pathname == NULL)
  439. {
  440. #ifdef DFS_USING_WORKDIR
  441. /* open current working directory */
  442. path = rt_strdup(working_directory);
  443. #else
  444. path = rt_strdup("/");
  445. #endif
  446. if (path == NULL)
  447. return ; /* out of memory */
  448. }
  449. else
  450. {
  451. path = (char *)pathname;
  452. }
  453. /* list directory */
  454. if (dfs_file_open(&fd, path, O_DIRECTORY) == 0)
  455. {
  456. rt_kprintf("Directory %s:\n", path);
  457. do
  458. {
  459. memset(&dirent, 0, sizeof(struct dirent));
  460. length = dfs_file_getdents(&fd, &dirent, sizeof(struct dirent));
  461. if (length > 0)
  462. {
  463. memset(&stat, 0, sizeof(struct stat));
  464. /* build full path for each file */
  465. fullpath = dfs_normalize_path(path, dirent.d_name);
  466. if (fullpath == NULL)
  467. break;
  468. if (dfs_file_stat(fullpath, &stat) == 0)
  469. {
  470. rt_kprintf("%-20s", dirent.d_name);
  471. if (S_ISDIR(stat.st_mode))
  472. {
  473. rt_kprintf("%-25s\n", "<DIR>");
  474. }
  475. else
  476. {
  477. rt_kprintf("%-25lu\n", (unsigned long)stat.st_size);
  478. }
  479. }
  480. else
  481. rt_kprintf("BAD file: %s\n", dirent.d_name);
  482. rt_free(fullpath);
  483. }
  484. }
  485. while (length > 0);
  486. dfs_file_close(&fd);
  487. }
  488. else
  489. {
  490. rt_kprintf("No such directory\n");
  491. }
  492. if (pathname == NULL)
  493. rt_free(path);
  494. }
  495. FINSH_FUNCTION_EXPORT(ls, list directory contents);
  496. void rm(const char *filename)
  497. {
  498. if (dfs_file_unlink(filename) < 0)
  499. {
  500. rt_kprintf("Delete %s failed\n", filename);
  501. }
  502. }
  503. FINSH_FUNCTION_EXPORT(rm, remove files or directories);
  504. void cat(const char *filename)
  505. {
  506. uint32_t length;
  507. char buffer[81];
  508. if (dfs_file_open(&fd, filename, O_RDONLY) < 0)
  509. {
  510. rt_kprintf("Open %s failed\n", filename);
  511. return;
  512. }
  513. do
  514. {
  515. memset(buffer, 0, sizeof(buffer));
  516. length = dfs_file_read(&fd, buffer, sizeof(buffer) - 1);
  517. if (length > 0)
  518. {
  519. rt_kprintf("%s", buffer);
  520. }
  521. }
  522. while (length > 0);
  523. dfs_file_close(&fd);
  524. }
  525. FINSH_FUNCTION_EXPORT(cat, print file);
  526. #define BUF_SZ 4096
  527. static void copyfile(const char *src, const char *dst)
  528. {
  529. struct dfs_fd src_fd;
  530. rt_uint8_t *block_ptr;
  531. rt_int32_t read_bytes;
  532. block_ptr = (rt_uint8_t *)rt_malloc(BUF_SZ);
  533. if (block_ptr == NULL)
  534. {
  535. rt_kprintf("out of memory\n");
  536. return;
  537. }
  538. if (dfs_file_open(&src_fd, src, O_RDONLY) < 0)
  539. {
  540. rt_free(block_ptr);
  541. rt_kprintf("Read %s failed\n", src);
  542. return;
  543. }
  544. if (dfs_file_open(&fd, dst, O_WRONLY | O_CREAT) < 0)
  545. {
  546. rt_free(block_ptr);
  547. dfs_file_close(&src_fd);
  548. rt_kprintf("Write %s failed\n", dst);
  549. return;
  550. }
  551. do
  552. {
  553. read_bytes = dfs_file_read(&src_fd, block_ptr, BUF_SZ);
  554. if (read_bytes > 0)
  555. {
  556. int length;
  557. length = dfs_file_write(&fd, block_ptr, read_bytes);
  558. if (length != read_bytes)
  559. {
  560. /* write failed. */
  561. rt_kprintf("Write file data failed, errno=%d\n", length);
  562. break;
  563. }
  564. }
  565. }
  566. while (read_bytes > 0);
  567. dfs_file_close(&src_fd);
  568. dfs_file_close(&fd);
  569. rt_free(block_ptr);
  570. }
  571. extern int mkdir(const char *path, mode_t mode);
  572. static void copydir(const char *src, const char *dst)
  573. {
  574. struct dirent dirent;
  575. struct stat stat;
  576. int length;
  577. struct dfs_fd cpfd;
  578. if (dfs_file_open(&cpfd, src, O_DIRECTORY) < 0)
  579. {
  580. rt_kprintf("open %s failed\n", src);
  581. return ;
  582. }
  583. do
  584. {
  585. memset(&dirent, 0, sizeof(struct dirent));
  586. length = dfs_file_getdents(&cpfd, &dirent, sizeof(struct dirent));
  587. if (length > 0)
  588. {
  589. char *src_entry_full = NULL;
  590. char *dst_entry_full = NULL;
  591. if (strcmp(dirent.d_name, "..") == 0 || strcmp(dirent.d_name, ".") == 0)
  592. continue;
  593. /* build full path for each file */
  594. if ((src_entry_full = dfs_normalize_path(src, dirent.d_name)) == NULL)
  595. {
  596. rt_kprintf("out of memory!\n");
  597. break;
  598. }
  599. if ((dst_entry_full = dfs_normalize_path(dst, dirent.d_name)) == NULL)
  600. {
  601. rt_kprintf("out of memory!\n");
  602. rt_free(src_entry_full);
  603. break;
  604. }
  605. memset(&stat, 0, sizeof(struct stat));
  606. if (dfs_file_stat(src_entry_full, &stat) != 0)
  607. {
  608. rt_kprintf("open file: %s failed\n", dirent.d_name);
  609. continue;
  610. }
  611. if (S_ISDIR(stat.st_mode))
  612. {
  613. mkdir(dst_entry_full, 0);
  614. copydir(src_entry_full, dst_entry_full);
  615. }
  616. else
  617. {
  618. copyfile(src_entry_full, dst_entry_full);
  619. }
  620. rt_free(src_entry_full);
  621. rt_free(dst_entry_full);
  622. }
  623. }
  624. while (length > 0);
  625. dfs_file_close(&cpfd);
  626. }
  627. static const char *_get_path_lastname(const char *path)
  628. {
  629. char *ptr;
  630. if ((ptr = (char *)strrchr(path, '/')) == NULL)
  631. return path;
  632. /* skip the '/' then return */
  633. return ++ptr;
  634. }
  635. void copy(const char *src, const char *dst)
  636. {
  637. #define FLAG_SRC_TYPE 0x03
  638. #define FLAG_SRC_IS_DIR 0x01
  639. #define FLAG_SRC_IS_FILE 0x02
  640. #define FLAG_SRC_NON_EXSIT 0x00
  641. #define FLAG_DST_TYPE 0x0C
  642. #define FLAG_DST_IS_DIR 0x04
  643. #define FLAG_DST_IS_FILE 0x08
  644. #define FLAG_DST_NON_EXSIT 0x00
  645. struct stat stat;
  646. uint32_t flag = 0;
  647. /* check the staus of src and dst */
  648. if (dfs_file_stat(src, &stat) < 0)
  649. {
  650. rt_kprintf("copy failed, bad %s\n", src);
  651. return;
  652. }
  653. if (S_ISDIR(stat.st_mode))
  654. flag |= FLAG_SRC_IS_DIR;
  655. else
  656. flag |= FLAG_SRC_IS_FILE;
  657. if (dfs_file_stat(dst, &stat) < 0)
  658. {
  659. flag |= FLAG_DST_NON_EXSIT;
  660. }
  661. else
  662. {
  663. if (S_ISDIR(stat.st_mode))
  664. flag |= FLAG_DST_IS_DIR;
  665. else
  666. flag |= FLAG_DST_IS_FILE;
  667. }
  668. //2. check status
  669. if ((flag & FLAG_SRC_IS_DIR) && (flag & FLAG_DST_IS_FILE))
  670. {
  671. rt_kprintf("cp faild, cp dir to file is not permitted!\n");
  672. return ;
  673. }
  674. //3. do copy
  675. if (flag & FLAG_SRC_IS_FILE)
  676. {
  677. if (flag & FLAG_DST_IS_DIR)
  678. {
  679. char *fdst;
  680. fdst = dfs_normalize_path(dst, _get_path_lastname(src));
  681. if (fdst == NULL)
  682. {
  683. rt_kprintf("out of memory\n");
  684. return;
  685. }
  686. copyfile(src, fdst);
  687. rt_free(fdst);
  688. }
  689. else
  690. {
  691. copyfile(src, dst);
  692. }
  693. }
  694. else //flag & FLAG_SRC_IS_DIR
  695. {
  696. if (flag & FLAG_DST_IS_DIR)
  697. {
  698. char *fdst;
  699. fdst = dfs_normalize_path(dst, _get_path_lastname(src));
  700. if (fdst == NULL)
  701. {
  702. rt_kprintf("out of memory\n");
  703. return;
  704. }
  705. mkdir(fdst, 0);
  706. copydir(src, fdst);
  707. rt_free(fdst);
  708. }
  709. else if ((flag & FLAG_DST_TYPE) == FLAG_DST_NON_EXSIT)
  710. {
  711. mkdir(dst, 0);
  712. copydir(src, dst);
  713. }
  714. else
  715. {
  716. copydir(src, dst);
  717. }
  718. }
  719. }
  720. FINSH_FUNCTION_EXPORT(copy, copy file or dir)
  721. #endif
  722. /* @} */