dfs_file.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808
  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. if (fs->ops->lseek == RT_NULL)
  286. return -DFS_STATUS_ENOSYS;
  287. result = fs->ops->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(RT_NULL, path);
  307. if (fullpath == RT_NULL)
  308. {
  309. return -1;
  310. }
  311. if ((fs = dfs_filesystem_lookup(fullpath)) == RT_NULL)
  312. {
  313. dfs_log(DFS_DEBUG_ERROR,
  314. ("can't find mounted filesystem on this path:%s", fullpath));
  315. rt_free(fullpath);
  316. return -DFS_STATUS_ENOENT;
  317. }
  318. if ((fullpath[0] == '/' && fullpath[1] == '\0') ||
  319. (dfs_subdir(fs->path, fullpath) == RT_NULL))
  320. {
  321. /* it's the root directory */
  322. buf->st_dev = 0;
  323. buf->st_mode = DFS_S_IRUSR | DFS_S_IRGRP | DFS_S_IROTH |
  324. DFS_S_IWUSR | DFS_S_IWGRP | DFS_S_IWOTH;
  325. buf->st_mode |= DFS_S_IFDIR | DFS_S_IXUSR | DFS_S_IXGRP | DFS_S_IXOTH;
  326. buf->st_size = 0;
  327. buf->st_mtime = 0;
  328. buf->st_blksize = 512;
  329. /* release full path */
  330. rt_free(fullpath);
  331. return DFS_STATUS_OK;
  332. }
  333. else
  334. {
  335. if (fs->ops->stat == RT_NULL)
  336. {
  337. rt_free(fullpath);
  338. dfs_log(DFS_DEBUG_ERROR,
  339. ("the filesystem didn't implement this function"));
  340. return -DFS_STATUS_ENOSYS;
  341. }
  342. /* get the real file path and get file stat */
  343. if (fs->ops->flags & DFS_FS_FLAG_FULLPATH)
  344. result = fs->ops->stat(fs, fullpath, buf);
  345. else
  346. result = fs->ops->stat(fs, dfs_subdir(fs->path, fullpath), buf);
  347. }
  348. rt_free(fullpath);
  349. return result;
  350. }
  351. /**
  352. * this function will rename an old path name to a new path name.
  353. *
  354. * @param oldpath the old path name.
  355. * @param newpath the new path name.
  356. *
  357. * @return 0 on successful, -1 on failed.
  358. */
  359. int dfs_file_rename(const char *oldpath, const char *newpath)
  360. {
  361. int result;
  362. struct dfs_filesystem *oldfs, *newfs;
  363. char *oldfullpath, *newfullpath;
  364. result = DFS_STATUS_OK;
  365. newfullpath = RT_NULL;
  366. oldfullpath = RT_NULL;
  367. oldfullpath = dfs_normalize_path(RT_NULL, oldpath);
  368. if (oldfullpath == RT_NULL)
  369. {
  370. result = -DFS_STATUS_ENOENT;
  371. goto __exit;
  372. }
  373. newfullpath = dfs_normalize_path(RT_NULL, newpath);
  374. if (newfullpath == RT_NULL)
  375. {
  376. result = -DFS_STATUS_ENOENT;
  377. goto __exit;
  378. }
  379. oldfs = dfs_filesystem_lookup(oldfullpath);
  380. newfs = dfs_filesystem_lookup(newfullpath);
  381. if (oldfs == newfs)
  382. {
  383. if (oldfs->ops->rename == RT_NULL)
  384. {
  385. result = -DFS_STATUS_ENOSYS;
  386. }
  387. else
  388. {
  389. if (oldfs->ops->flags & DFS_FS_FLAG_FULLPATH)
  390. result = oldfs->ops->rename(oldfs, oldfullpath, newfullpath);
  391. else
  392. /* use sub directory to rename in file system */
  393. result = oldfs->ops->rename(oldfs,
  394. dfs_subdir(oldfs->path, oldfullpath),
  395. dfs_subdir(newfs->path, newfullpath));
  396. }
  397. }
  398. else
  399. {
  400. result = -DFS_STATUS_EXDEV;
  401. }
  402. __exit:
  403. rt_free(oldfullpath);
  404. rt_free(newfullpath);
  405. /* not at same file system, return EXDEV */
  406. return result;
  407. }
  408. #ifdef RT_USING_FINSH
  409. #include <finsh.h>
  410. static struct dfs_fd fd;
  411. static struct dirent dirent;
  412. void ls(const char *pathname)
  413. {
  414. struct stat stat;
  415. int length;
  416. char *fullpath, *path;
  417. fullpath = RT_NULL;
  418. if (pathname == RT_NULL)
  419. {
  420. #ifdef DFS_USING_WORKDIR
  421. /* open current working directory */
  422. path = rt_strdup(working_directory);
  423. #else
  424. path = rt_strdup("/");
  425. #endif
  426. if (path == RT_NULL)
  427. return ; /* out of memory */
  428. }
  429. else
  430. {
  431. path = (char *)pathname;
  432. }
  433. /* list directory */
  434. if (dfs_file_open(&fd, path, DFS_O_DIRECTORY) == 0)
  435. {
  436. rt_kprintf("Directory %s:\n", path);
  437. do
  438. {
  439. rt_memset(&dirent, 0, sizeof(struct dirent));
  440. length = dfs_file_getdents(&fd, &dirent, sizeof(struct dirent));
  441. if (length > 0)
  442. {
  443. rt_memset(&stat, 0, sizeof(struct stat));
  444. /* build full path for each file */
  445. fullpath = dfs_normalize_path(path, dirent.d_name);
  446. if (fullpath == RT_NULL)
  447. break;
  448. if (dfs_file_stat(fullpath, &stat) == 0)
  449. {
  450. rt_kprintf("%-20s", dirent.d_name);
  451. if ( DFS_S_ISDIR(stat.st_mode))
  452. {
  453. rt_kprintf("%-25s\n", "<DIR>");
  454. }
  455. else
  456. {
  457. rt_kprintf("%-25lu\n", stat.st_size);
  458. }
  459. }
  460. else
  461. rt_kprintf("BAD file: %s\n", dirent.d_name);
  462. rt_free(fullpath);
  463. }
  464. }while(length > 0);
  465. dfs_file_close(&fd);
  466. }
  467. else
  468. {
  469. rt_kprintf("No such directory\n");
  470. }
  471. if (pathname == RT_NULL)
  472. rt_free(path);
  473. }
  474. FINSH_FUNCTION_EXPORT(ls, list directory contents)
  475. void rm(const char *filename)
  476. {
  477. if (dfs_file_unlink(filename) < 0)
  478. {
  479. rt_kprintf("Delete %s failed\n", filename);
  480. }
  481. }
  482. FINSH_FUNCTION_EXPORT(rm, remove files or directories)
  483. void cat(const char* filename)
  484. {
  485. rt_uint32_t length;
  486. char buffer[81];
  487. if (dfs_file_open(&fd, filename, DFS_O_RDONLY) < 0)
  488. {
  489. rt_kprintf("Open %s failed\n", filename);
  490. return;
  491. }
  492. do
  493. {
  494. rt_memset(buffer, 0, sizeof(buffer));
  495. length = dfs_file_read(&fd, buffer, sizeof(buffer)-1 );
  496. if (length > 0)
  497. {
  498. rt_kprintf("%s", buffer);
  499. }
  500. }while (length > 0);
  501. dfs_file_close(&fd);
  502. }
  503. FINSH_FUNCTION_EXPORT(cat, print file)
  504. #define BUF_SZ 4096
  505. static void copyfile(const char *src, const char *dst)
  506. {
  507. struct dfs_fd src_fd;
  508. rt_uint8_t *block_ptr;
  509. rt_int32_t read_bytes;
  510. block_ptr = rt_malloc(BUF_SZ);
  511. if (block_ptr == RT_NULL)
  512. {
  513. rt_kprintf("out of memory\n");
  514. return;
  515. }
  516. if (dfs_file_open(&src_fd, src, DFS_O_RDONLY) < 0)
  517. {
  518. rt_free(block_ptr);
  519. rt_kprintf("Read %s failed\n", src);
  520. return;
  521. }
  522. if (dfs_file_open(&fd, dst, DFS_O_WRONLY | DFS_O_CREAT) < 0)
  523. {
  524. rt_free(block_ptr);
  525. dfs_file_close(&src_fd);
  526. rt_kprintf("Write %s failed\n", dst);
  527. return;
  528. }
  529. do
  530. {
  531. read_bytes = dfs_file_read(&src_fd, block_ptr, BUF_SZ);
  532. if (read_bytes > 0)
  533. {
  534. dfs_file_write(&fd, block_ptr, read_bytes);
  535. }
  536. } while (read_bytes > 0);
  537. dfs_file_close(&src_fd);
  538. dfs_file_close(&fd);
  539. rt_free(block_ptr);
  540. }
  541. extern int mkdir(const char *path, mode_t mode);
  542. static void copydir(const char * src, const char * dst)
  543. {
  544. struct dfs_fd fd;
  545. struct dirent dirent;
  546. struct stat stat;
  547. int length;
  548. if (dfs_file_open(&fd, src, DFS_O_DIRECTORY) < 0)
  549. {
  550. rt_kprintf("open %s failed\n", src);
  551. return ;
  552. }
  553. do
  554. {
  555. rt_memset(&dirent, 0, sizeof(struct dirent));
  556. length = dfs_file_getdents(&fd, &dirent, sizeof(struct dirent));
  557. if (length > 0)
  558. {
  559. char * src_entry_full = RT_NULL;
  560. char * dst_entry_full = RT_NULL;
  561. if (strcmp(dirent.d_name, "..") == 0 || strcmp(dirent.d_name, ".") == 0)
  562. continue;
  563. /* build full path for each file */
  564. if ((src_entry_full = dfs_normalize_path(src, dirent.d_name)) == RT_NULL)
  565. {
  566. rt_kprintf("out of memory!\n");
  567. break;
  568. }
  569. if ((dst_entry_full = dfs_normalize_path(dst, dirent.d_name)) == RT_NULL)
  570. {
  571. rt_kprintf("out of memory!\n");
  572. rt_free(src_entry_full);
  573. break;
  574. }
  575. rt_memset(&stat, 0, sizeof(struct stat));
  576. if (dfs_file_stat(src_entry_full, &stat) != 0)
  577. {
  578. rt_kprintf("open file: %s failed\n", dirent.d_name);
  579. continue;
  580. }
  581. if (DFS_S_ISDIR(stat.st_mode))
  582. {
  583. mkdir(dst_entry_full, 0);
  584. copydir(src_entry_full, dst_entry_full);
  585. }
  586. else
  587. {
  588. copyfile(src_entry_full, dst_entry_full);
  589. }
  590. rt_free(src_entry_full);
  591. rt_free(dst_entry_full);
  592. }
  593. }while(length > 0);
  594. dfs_file_close(&fd);
  595. }
  596. static const char *_get_path_lastname(const char *path)
  597. {
  598. char * ptr;
  599. if ((ptr = strrchr(path, '/')) == RT_NULL)
  600. return path;
  601. /* skip the '/' then return */
  602. return ++ptr;
  603. }
  604. void copy(const char *src, const char *dst)
  605. {
  606. #define FLAG_SRC_TYPE 0x03
  607. #define FLAG_SRC_IS_DIR 0x01
  608. #define FLAG_SRC_IS_FILE 0x02
  609. #define FLAG_SRC_NON_EXSIT 0x00
  610. #define FLAG_DST_TYPE 0x0C
  611. #define FLAG_DST_IS_DIR 0x04
  612. #define FLAG_DST_IS_FILE 0x08
  613. #define FLAG_DST_NON_EXSIT 0x00
  614. struct stat stat;
  615. rt_uint32_t flag = 0;
  616. /* check the staus of src and dst */
  617. if (dfs_file_stat(src, &stat) < 0)
  618. {
  619. rt_kprintf("copy failed, bad %s\n", src);
  620. return;
  621. }
  622. if (DFS_S_ISDIR(stat.st_mode))
  623. flag |= FLAG_SRC_IS_DIR;
  624. else
  625. flag |= FLAG_SRC_IS_FILE;
  626. if (dfs_file_stat(dst, &stat) < 0)
  627. {
  628. flag |= FLAG_DST_NON_EXSIT;
  629. }
  630. else
  631. {
  632. if (DFS_S_ISDIR(stat.st_mode))
  633. flag |= FLAG_DST_IS_DIR;
  634. else
  635. flag |= FLAG_DST_IS_FILE;
  636. }
  637. //2. check status
  638. if ((flag & FLAG_SRC_IS_DIR) && (flag & FLAG_DST_IS_FILE))
  639. {
  640. rt_kprintf("cp faild, cp dir to file is not permitted!\n");
  641. return ;
  642. }
  643. //3. do copy
  644. if (flag & FLAG_SRC_IS_FILE)
  645. {
  646. if (flag & FLAG_DST_IS_DIR)
  647. {
  648. char * fdst;
  649. fdst = dfs_normalize_path(dst, _get_path_lastname(src));
  650. if (fdst == NULL)
  651. {
  652. rt_kprintf("out of memory\n");
  653. return;
  654. }
  655. copyfile(src, fdst);
  656. rt_free(fdst);
  657. }
  658. else
  659. {
  660. copyfile(src, dst);
  661. }
  662. }
  663. else //flag & FLAG_SRC_IS_DIR
  664. {
  665. if (flag & FLAG_DST_IS_DIR)
  666. {
  667. char * fdst;
  668. fdst = dfs_normalize_path(dst, _get_path_lastname(src));
  669. if (fdst == NULL)
  670. {
  671. rt_kprintf("out of memory\n");
  672. return;
  673. }
  674. mkdir(fdst, 0);
  675. copydir(src, fdst);
  676. rt_free(fdst);
  677. }
  678. else if ((flag & FLAG_DST_TYPE) == FLAG_DST_NON_EXSIT)
  679. {
  680. mkdir(dst, 0);
  681. copydir(src, dst);
  682. }
  683. else
  684. {
  685. copydir(src, dst);
  686. }
  687. }
  688. }
  689. FINSH_FUNCTION_EXPORT(copy, copy file or dir)
  690. #endif
  691. /* @} */