dfs_file.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819
  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. */
  25. #include <dfs.h>
  26. #include <dfs_file.h>
  27. /**
  28. * @addtogroup FileApi
  29. */
  30. /*@{*/
  31. /**
  32. * this function will open a file which specified by path with specified flags.
  33. *
  34. * @param fd the file descriptor pointer to return the corresponding result.
  35. * @param path the specified file path.
  36. * @param flags the flags for open operator.
  37. *
  38. * @return 0 on successful, -1 on failed.
  39. */
  40. int dfs_file_open(struct dfs_fd *fd, const char *path, int flags)
  41. {
  42. struct dfs_filesystem *fs;
  43. char *fullpath;
  44. int result;
  45. /* parameter check */
  46. if (fd == RT_NULL)
  47. return -DFS_STATUS_EINVAL;
  48. /* make sure we have an absolute path */
  49. fullpath = dfs_normalize_path(RT_NULL, path);
  50. if (fullpath == RT_NULL)
  51. {
  52. return -1;
  53. }
  54. dfs_log(DFS_DEBUG_INFO, ("open file:%s", fullpath));
  55. /* find filesystem */
  56. fs = dfs_filesystem_lookup(fullpath);
  57. if (fs == RT_NULL)
  58. {
  59. rt_free(fullpath); /* release path */
  60. return -DFS_STATUS_ENOENT;
  61. }
  62. dfs_log(DFS_DEBUG_INFO, ("open in filesystem:%s", fs->ops->name));
  63. fd->fs = fs;
  64. /* initialize the fd item */
  65. fd->type = FT_REGULAR;
  66. fd->flags = flags;
  67. fd->size = 0;
  68. fd->pos = 0;
  69. if (!(fs->ops->flags & DFS_FS_FLAG_FULLPATH))
  70. {
  71. if (dfs_subdir(fs->path, fullpath) == RT_NULL)
  72. fd->path = rt_strdup("/");
  73. else
  74. fd->path = rt_strdup(dfs_subdir(fs->path, fullpath));
  75. rt_free(fullpath);
  76. dfs_log(DFS_DEBUG_INFO, ("Actual file path: %s\n", fd->path));
  77. }
  78. else
  79. {
  80. fd->path = fullpath;
  81. }
  82. /* specific file system open routine */
  83. if (fs->ops->open == RT_NULL)
  84. {
  85. /* clear fd */
  86. rt_free(fd->path);
  87. rt_memset(fd, 0, sizeof(*fd));
  88. return -DFS_STATUS_ENOSYS;
  89. }
  90. if ((result = fs->ops->open(fd)) < 0)
  91. {
  92. /* clear fd */
  93. rt_free(fd->path);
  94. rt_memset(fd, 0, sizeof(*fd));
  95. dfs_log(DFS_DEBUG_INFO, ("open failed"));
  96. return result;
  97. }
  98. fd->flags |= DFS_F_OPEN;
  99. if (flags & DFS_O_DIRECTORY)
  100. {
  101. fd->type = FT_DIRECTORY;
  102. fd->flags |= DFS_F_DIRECTORY;
  103. }
  104. dfs_log(DFS_DEBUG_INFO, ("open successful"));
  105. return 0;
  106. }
  107. /**
  108. * this function will close a file descriptor.
  109. *
  110. * @param fd the file descriptor to be closed.
  111. *
  112. * @return 0 on successful, -1 on failed.
  113. */
  114. int dfs_file_close(struct dfs_fd *fd)
  115. {
  116. int result = 0;
  117. if (fd != RT_NULL && fd->fs->ops->close != RT_NULL)
  118. result = fd->fs->ops->close(fd);
  119. /* close fd error, return */
  120. if (result < 0)
  121. return result;
  122. rt_free(fd->path);
  123. rt_memset(fd, 0, sizeof(struct dfs_fd));
  124. return result;
  125. }
  126. /**
  127. * this function will perform a io control on a file descriptor.
  128. *
  129. * @param fd the file descriptor.
  130. * @param cmd the command to send to file descriptor.
  131. * @param args the argument to send to file descriptor.
  132. *
  133. * @return 0 on successful, -1 on failed.
  134. */
  135. int dfs_file_ioctl(struct dfs_fd *fd, int cmd, void *args)
  136. {
  137. struct dfs_filesystem *fs;
  138. if (fd == RT_NULL || fd->type != FT_REGULAR)
  139. return -DFS_STATUS_EINVAL;
  140. fs = fd->fs;
  141. if (fs->ops->ioctl != RT_NULL)
  142. return fs->ops->ioctl(fd, cmd, args);
  143. return -DFS_STATUS_ENOSYS;
  144. }
  145. /**
  146. * this function will read specified length data from a file descriptor to a
  147. * buffer.
  148. *
  149. * @param fd the file descriptor.
  150. * @param buf the buffer to save the read data.
  151. * @param len the length of data buffer to be read.
  152. *
  153. * @return the actual read data bytes or 0 on end of file or failed.
  154. */
  155. int dfs_file_read(struct dfs_fd *fd, void *buf, rt_size_t len)
  156. {
  157. struct dfs_filesystem *fs;
  158. int result = 0;
  159. if (fd == RT_NULL)
  160. return -DFS_STATUS_EINVAL;
  161. fs = (struct dfs_filesystem *)fd->fs;
  162. if (fs->ops->read == RT_NULL)
  163. return -DFS_STATUS_ENOSYS;
  164. if ((result = fs->ops->read(fd, buf, len)) < 0)
  165. fd->flags |= DFS_F_EOF;
  166. return result;
  167. }
  168. /**
  169. * this function will fetch directory entries from a directory descriptor.
  170. *
  171. * @param fd the directory descriptor.
  172. * @param dirp the dirent buffer to save result.
  173. * @param nbytes the available room in the buffer.
  174. *
  175. * @return the read dirent, others on failed.
  176. */
  177. int dfs_file_getdents(struct dfs_fd *fd, struct dirent *dirp, rt_size_t nbytes)
  178. {
  179. struct dfs_filesystem *fs;
  180. /* parameter check */
  181. if (fd == RT_NULL || fd->type != FT_DIRECTORY)
  182. return -DFS_STATUS_EINVAL;
  183. fs = (struct dfs_filesystem *)fd->fs;
  184. if (fs->ops->getdents != RT_NULL)
  185. return fs->ops->getdents(fd, dirp, nbytes);
  186. return -DFS_STATUS_ENOSYS;
  187. }
  188. /**
  189. * this function will unlink (remove) a specified path file from file system.
  190. *
  191. * @param path the specified path file to be unlinked.
  192. *
  193. * @return 0 on successful, -1 on failed.
  194. */
  195. int dfs_file_unlink(const char *path)
  196. {
  197. int result;
  198. char *fullpath;
  199. struct dfs_filesystem *fs;
  200. /* Make sure we have an absolute path */
  201. fullpath = dfs_normalize_path(RT_NULL, path);
  202. if (fullpath == RT_NULL)
  203. {
  204. return -DFS_STATUS_EINVAL;
  205. }
  206. /* get filesystem */
  207. if ((fs = dfs_filesystem_lookup(fullpath)) == RT_NULL)
  208. {
  209. result = -DFS_STATUS_ENOENT;
  210. goto __exit;
  211. }
  212. /* Check whether file is already open */
  213. if (fd_is_open(fullpath) == 0)
  214. {
  215. result = -DFS_STATUS_EBUSY;
  216. goto __exit;
  217. }
  218. if (fs->ops->unlink != RT_NULL)
  219. {
  220. if (!(fs->ops->flags & DFS_FS_FLAG_FULLPATH))
  221. {
  222. if (dfs_subdir(fs->path, fullpath) == RT_NULL)
  223. result = fs->ops->unlink(fs, "/");
  224. else
  225. result = fs->ops->unlink(fs, dfs_subdir(fs->path, fullpath));
  226. }
  227. else
  228. result = fs->ops->unlink(fs, fullpath);
  229. }
  230. else result = -DFS_STATUS_ENOSYS;
  231. __exit:
  232. rt_free(fullpath);
  233. return result;
  234. }
  235. /**
  236. * this function will write some specified length data to file system.
  237. *
  238. * @param fd the file descriptor.
  239. * @param buf the data buffer to be written.
  240. * @param len the data buffer length
  241. *
  242. * @return the actual written data length.
  243. */
  244. int dfs_file_write(struct dfs_fd *fd, const void *buf, rt_size_t len)
  245. {
  246. struct dfs_filesystem *fs;
  247. if (fd == RT_NULL)
  248. return -DFS_STATUS_EINVAL;
  249. fs = fd->fs;
  250. if (fs->ops->write == RT_NULL)
  251. return -DFS_STATUS_ENOSYS;
  252. return fs->ops->write(fd, buf, len);
  253. }
  254. /**
  255. * this function will flush buffer on a file descriptor.
  256. *
  257. * @param fd the file descriptor.
  258. *
  259. * @return 0 on successful, -1 on failed.
  260. */
  261. int dfs_file_flush(struct dfs_fd *fd)
  262. {
  263. struct dfs_filesystem *fs;
  264. if (fd == RT_NULL)
  265. return -DFS_STATUS_EINVAL;
  266. fs = fd->fs;
  267. if (fs->ops->flush == RT_NULL)
  268. return -DFS_STATUS_ENOSYS;
  269. return fs->ops->flush(fd);
  270. }
  271. /**
  272. * this function will seek the offset for specified file descriptor.
  273. *
  274. * @param fd the file descriptor.
  275. * @param offset the offset to be sought.
  276. *
  277. * @return the current position after seek.
  278. */
  279. int dfs_file_lseek(struct dfs_fd *fd, rt_off_t offset)
  280. {
  281. int result;
  282. struct dfs_filesystem *fs = fd->fs;
  283. if (fd == RT_NULL)
  284. return -DFS_STATUS_EINVAL;
  285. fs = fd->fs;
  286. if (fs == RT_NULL)
  287. return -DFS_STATUS_EINVAL;
  288. if (fs->ops->lseek == RT_NULL)
  289. return -DFS_STATUS_ENOSYS;
  290. result = fs->ops->lseek(fd, offset);
  291. /* update current position */
  292. if (result >= 0)
  293. fd->pos = result;
  294. return result;
  295. }
  296. /**
  297. * this function will get file information.
  298. *
  299. * @param path the file path.
  300. * @param buf the data buffer to save stat description.
  301. *
  302. * @return 0 on successful, -1 on failed.
  303. */
  304. int dfs_file_stat(const char *path, struct stat *buf)
  305. {
  306. int result;
  307. char *fullpath;
  308. struct dfs_filesystem *fs;
  309. fullpath = dfs_normalize_path(RT_NULL, path);
  310. if (fullpath == RT_NULL)
  311. {
  312. return -1;
  313. }
  314. if ((fs = dfs_filesystem_lookup(fullpath)) == RT_NULL)
  315. {
  316. dfs_log(DFS_DEBUG_ERROR,
  317. ("can't find mounted filesystem on this path:%s", fullpath));
  318. rt_free(fullpath);
  319. return -DFS_STATUS_ENOENT;
  320. }
  321. if ((fullpath[0] == '/' && fullpath[1] == '\0') ||
  322. (dfs_subdir(fs->path, fullpath) == RT_NULL))
  323. {
  324. /* it's the root directory */
  325. buf->st_dev = 0;
  326. buf->st_mode = DFS_S_IRUSR | DFS_S_IRGRP | DFS_S_IROTH |
  327. DFS_S_IWUSR | DFS_S_IWGRP | DFS_S_IWOTH;
  328. buf->st_mode |= DFS_S_IFDIR | DFS_S_IXUSR | DFS_S_IXGRP | DFS_S_IXOTH;
  329. buf->st_size = 0;
  330. buf->st_mtime = 0;
  331. buf->st_blksize = 512;
  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 dfs_fd fd;
  555. struct dirent dirent;
  556. struct stat stat;
  557. int length;
  558. if (dfs_file_open(&fd, src, DFS_O_DIRECTORY) < 0)
  559. {
  560. rt_kprintf("open %s failed\n", src);
  561. return ;
  562. }
  563. do
  564. {
  565. rt_memset(&dirent, 0, sizeof(struct dirent));
  566. length = dfs_file_getdents(&fd, &dirent, sizeof(struct dirent));
  567. if (length > 0)
  568. {
  569. char * src_entry_full = RT_NULL;
  570. char * dst_entry_full = RT_NULL;
  571. if (strcmp(dirent.d_name, "..") == 0 || strcmp(dirent.d_name, ".") == 0)
  572. continue;
  573. /* build full path for each file */
  574. if ((src_entry_full = dfs_normalize_path(src, dirent.d_name)) == RT_NULL)
  575. {
  576. rt_kprintf("out of memory!\n");
  577. break;
  578. }
  579. if ((dst_entry_full = dfs_normalize_path(dst, dirent.d_name)) == RT_NULL)
  580. {
  581. rt_kprintf("out of memory!\n");
  582. rt_free(src_entry_full);
  583. break;
  584. }
  585. rt_memset(&stat, 0, sizeof(struct stat));
  586. if (dfs_file_stat(src_entry_full, &stat) != 0)
  587. {
  588. rt_kprintf("open file: %s failed\n", dirent.d_name);
  589. continue;
  590. }
  591. if (DFS_S_ISDIR(stat.st_mode))
  592. {
  593. mkdir(dst_entry_full, 0);
  594. copydir(src_entry_full, dst_entry_full);
  595. }
  596. else
  597. {
  598. copyfile(src_entry_full, dst_entry_full);
  599. }
  600. rt_free(src_entry_full);
  601. rt_free(dst_entry_full);
  602. }
  603. }while(length > 0);
  604. dfs_file_close(&fd);
  605. }
  606. static const char *_get_path_lastname(const char *path)
  607. {
  608. char * ptr;
  609. if ((ptr = strrchr(path, '/')) == RT_NULL)
  610. return path;
  611. /* skip the '/' then return */
  612. return ++ptr;
  613. }
  614. void copy(const char *src, const char *dst)
  615. {
  616. #define FLAG_SRC_TYPE 0x03
  617. #define FLAG_SRC_IS_DIR 0x01
  618. #define FLAG_SRC_IS_FILE 0x02
  619. #define FLAG_SRC_NON_EXSIT 0x00
  620. #define FLAG_DST_TYPE 0x0C
  621. #define FLAG_DST_IS_DIR 0x04
  622. #define FLAG_DST_IS_FILE 0x08
  623. #define FLAG_DST_NON_EXSIT 0x00
  624. struct stat stat;
  625. rt_uint32_t flag = 0;
  626. /* check the staus of src and dst */
  627. if (dfs_file_stat(src, &stat) < 0)
  628. {
  629. rt_kprintf("copy failed, bad %s\n", src);
  630. return;
  631. }
  632. if (DFS_S_ISDIR(stat.st_mode))
  633. flag |= FLAG_SRC_IS_DIR;
  634. else
  635. flag |= FLAG_SRC_IS_FILE;
  636. if (dfs_file_stat(dst, &stat) < 0)
  637. {
  638. flag |= FLAG_DST_NON_EXSIT;
  639. }
  640. else
  641. {
  642. if (DFS_S_ISDIR(stat.st_mode))
  643. flag |= FLAG_DST_IS_DIR;
  644. else
  645. flag |= FLAG_DST_IS_FILE;
  646. }
  647. //2. check status
  648. if ((flag & FLAG_SRC_IS_DIR) && (flag & FLAG_DST_IS_FILE))
  649. {
  650. rt_kprintf("cp faild, cp dir to file is not permitted!\n");
  651. return ;
  652. }
  653. //3. do copy
  654. if (flag & FLAG_SRC_IS_FILE)
  655. {
  656. if (flag & FLAG_DST_IS_DIR)
  657. {
  658. char * fdst;
  659. fdst = dfs_normalize_path(dst, _get_path_lastname(src));
  660. if (fdst == NULL)
  661. {
  662. rt_kprintf("out of memory\n");
  663. return;
  664. }
  665. copyfile(src, fdst);
  666. rt_free(fdst);
  667. }
  668. else
  669. {
  670. copyfile(src, dst);
  671. }
  672. }
  673. else //flag & FLAG_SRC_IS_DIR
  674. {
  675. if (flag & FLAG_DST_IS_DIR)
  676. {
  677. char * fdst;
  678. fdst = dfs_normalize_path(dst, _get_path_lastname(src));
  679. if (fdst == NULL)
  680. {
  681. rt_kprintf("out of memory\n");
  682. return;
  683. }
  684. mkdir(fdst, 0);
  685. copydir(src, fdst);
  686. rt_free(fdst);
  687. }
  688. else if ((flag & FLAG_DST_TYPE) == FLAG_DST_NON_EXSIT)
  689. {
  690. mkdir(dst, 0);
  691. copydir(src, dst);
  692. }
  693. else
  694. {
  695. copydir(src, dst);
  696. }
  697. }
  698. }
  699. FINSH_FUNCTION_EXPORT(copy, copy file or dir)
  700. #endif
  701. /* @} */