dfs_file.c 19 KB

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