dfs_file.c 20 KB

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