dfs_file.c 20 KB

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