dfs_raw.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681
  1. /*
  2. +------------------------------------------------------------------------------
  3. | Project : Device Filesystem
  4. +------------------------------------------------------------------------------
  5. | Copyright 2004, 2005 www.fayfayspace.org.
  6. | All rights reserved.
  7. |------------------------------------------------------------------------------
  8. | File : dfs_raw.c, the raw APIs of Device FileSystem
  9. |------------------------------------------------------------------------------
  10. | Chang Logs:
  11. | Date Author Notes
  12. | 2005-02-22 ffxz The first version.
  13. +------------------------------------------------------------------------------
  14. */
  15. #include <dfs_raw.h>
  16. #include <dfs_util.h>
  17. #include <string.h>
  18. extern struct dfs_fd fd_table[];
  19. /*
  20. +------------------------------------------------------------------------------
  21. | Function : fd_new
  22. +------------------------------------------------------------------------------
  23. | Description :
  24. |
  25. | Parameters :
  26. | Returns :
  27. |
  28. +------------------------------------------------------------------------------
  29. */
  30. int fd_new(void)
  31. {
  32. struct dfs_fd* d;
  33. int idx;
  34. /* lock filesystem */
  35. dfs_lock();
  36. /* find an empty fd entry */
  37. #ifdef DFS_USING_STDIO
  38. for (idx = 3; idx < DFS_FD_MAX + 3 && fd_table[idx].ref_count > 0; idx++);
  39. #else
  40. for (idx = 0; idx < DFS_FD_MAX && fd_table[idx].ref_count > 0; idx++);
  41. #endif
  42. /* can't find an empty fd entry */
  43. #ifdef DFS_USING_STDIO
  44. if (idx == DFS_FD_MAX + 3)
  45. #else
  46. if (idx == DFS_FD_MAX)
  47. #endif
  48. {
  49. idx = -1;
  50. goto __result;
  51. }
  52. d = &(fd_table[idx]);
  53. d->ref_count = 1;
  54. __result:
  55. dfs_unlock();
  56. return idx;
  57. }
  58. /*
  59. +------------------------------------------------------------------------------
  60. | Function : fd_get
  61. +------------------------------------------------------------------------------
  62. | Description :
  63. |
  64. | Parameters :
  65. | Returns :
  66. |
  67. +------------------------------------------------------------------------------
  68. */
  69. struct dfs_fd* fd_get(int fd)
  70. {
  71. struct dfs_fd* d;
  72. #ifdef DFS_USING_STDIO
  73. if ( fd < 3 || fd > DFS_FD_MAX + 3) return RT_NULL;
  74. #else
  75. if ( fd < 0 || fd > DFS_FD_MAX ) return RT_NULL;
  76. #endif
  77. d = &fd_table[fd];
  78. dfs_lock();
  79. d->ref_count ++;
  80. dfs_unlock();
  81. return d;
  82. }
  83. /*
  84. +------------------------------------------------------------------------------
  85. | Function : fd_put
  86. +------------------------------------------------------------------------------
  87. | Description :
  88. |
  89. | Parameters :
  90. | Returns :
  91. |
  92. +------------------------------------------------------------------------------
  93. */
  94. void fd_put(struct dfs_fd* fd)
  95. {
  96. dfs_lock();
  97. fd->ref_count --;
  98. /* clear this fd entry */
  99. if ( fd->ref_count == 0 )
  100. {
  101. rt_memset(fd, 0, sizeof(struct dfs_fd));
  102. }
  103. dfs_unlock();
  104. };
  105. /*
  106. +------------------------------------------------------------------------------
  107. | Function : dfile_raw_open
  108. +------------------------------------------------------------------------------
  109. | Description :
  110. |
  111. | Parameters :
  112. | Returns :
  113. |
  114. +------------------------------------------------------------------------------
  115. */
  116. int dfile_raw_open(struct dfs_fd* fd, const char *path, int flags)
  117. {
  118. struct dfs_filesystem* fs;
  119. char *fullpath;
  120. #ifdef DFS_USING_WORKDIR
  121. char full_path[DFS_PATH_MAX + 1];
  122. #endif
  123. int fspathlen, result;
  124. /* parameter check */
  125. if ( fd == RT_NULL ) return -DFS_STATUS_EINVAL;
  126. /* make sure we have an absolute path */
  127. fullpath = (char*)path;
  128. if ( fullpath[0] != '/')
  129. {
  130. #ifdef DFS_USING_WORKDIR
  131. /* build full path */
  132. fullpath = &full_path[0];
  133. dfs_lock();
  134. build_fullpath(working_directory, path, fullpath);
  135. dfs_unlock();
  136. #else
  137. #ifdef RT_USING_FINSH
  138. rt_kprintf("bad filename");
  139. #endif
  140. return -1;
  141. #endif
  142. }
  143. dfs_log(DFS_DEBUG_INFO, ("open file:%s", fullpath));
  144. /* find filesystem */
  145. fs = dfs_filesystem_lookup(fullpath);
  146. if ( fs == RT_NULL ) return -DFS_STATUS_ENOENT;
  147. dfs_log(DFS_DEBUG_INFO, ("open in filesystem:%s", fs->ops->name));
  148. fd->fs = fs;
  149. /* initilize the fd item */
  150. fd->type = FT_REGULAR;
  151. //fd->ref_count = 1;
  152. fd->flags = flags;
  153. fd->size = 0;
  154. fd->pos = 0;
  155. fspathlen = strlen(fs->path);
  156. rt_memset(fd->path, 0, DFS_PATH_MAX + 1);
  157. if (*(fullpath + fspathlen) != '/') strcpy(fd->path, "/");
  158. strcat(fd->path, fullpath + fspathlen);
  159. /* specific file system open routine */
  160. if (fs->ops->open == RT_NULL)
  161. {
  162. /* clear fd */
  163. rt_memset(fd->path, 0, DFS_PATH_MAX + 1);
  164. fd->type = FT_REGULAR;
  165. fd->ref_count = 0;
  166. fd->fs = RT_NULL;
  167. fd->flags = 0;
  168. fd->size = 0;
  169. fd->pos = 0;
  170. fd->data = RT_NULL;
  171. return -DFS_STATUS_ENOSYS;
  172. }
  173. if ((result = fs->ops->open(fd)) < 0)
  174. {
  175. /* clear fd */
  176. fd->fs = RT_NULL;
  177. fd->flags = 0;
  178. fd->data = RT_NULL;
  179. dfs_log(DFS_DEBUG_INFO, ("open failed"));
  180. return result;
  181. }
  182. fd->flags |= DFS_F_OPEN;
  183. if ( flags & DFS_O_DIRECTORY )
  184. {
  185. fd->type = FT_DIRECTORY;
  186. fd->flags |= DFS_F_DIRECTORY;
  187. }
  188. dfs_log(DFS_DEBUG_INFO, ("open successful"));
  189. return 0;
  190. }
  191. /*
  192. +------------------------------------------------------------------------------
  193. | Function : dfile_raw_close
  194. +------------------------------------------------------------------------------
  195. | Description :
  196. |
  197. | Parameters :
  198. | Returns :
  199. |
  200. +------------------------------------------------------------------------------
  201. */
  202. int dfile_raw_close(struct dfs_fd* fd)
  203. {
  204. int result = 0;
  205. if (fd != RT_NULL && fd->fs->ops->close != RT_NULL) result = fd->fs->ops->close(fd);
  206. /* close fd error, return */
  207. if ( result < 0 ) return result;
  208. fd->flags &= ~DFS_F_OPEN;
  209. return result;
  210. }
  211. /*
  212. +------------------------------------------------------------------------------
  213. | Function : dfile_raw_ioctl
  214. +------------------------------------------------------------------------------
  215. | Description :
  216. |
  217. | Parameters :
  218. | Returns :
  219. |
  220. +------------------------------------------------------------------------------
  221. */
  222. int dfile_raw_ioctl(struct dfs_fd* fd, int cmd, void *args)
  223. {
  224. struct dfs_filesystem* fs;
  225. if (fd == RT_NULL || fd->type != FT_REGULAR) return -DFS_STATUS_EINVAL;
  226. fs = fd->fs;
  227. #if 0 /* not support right now */
  228. if (cmd == FILEGETSIZE)
  229. {
  230. if (args == RT_NULL) return -DFS_STATUS_EINVAL;
  231. *((rt_uint32_t *) args) = fd->size;
  232. return 0;
  233. }
  234. else if (cmd == FILEGETPOS)
  235. {
  236. if (args == RT_NULL) return -DFS_STATUS_EINVAL;
  237. *((rt_uint32_t *) args) = fd->pos;
  238. return 0;
  239. }
  240. #endif
  241. if (fs->ops->ioctl != RT_NULL) return fs->ops->ioctl(fd, cmd, args);
  242. return -DFS_STATUS_ENOSYS;
  243. }
  244. /*
  245. +------------------------------------------------------------------------------
  246. | Function : dfile_raw_read
  247. +------------------------------------------------------------------------------
  248. | Description :
  249. |
  250. | Parameters :
  251. | Returns :
  252. |
  253. +------------------------------------------------------------------------------
  254. */
  255. int dfile_raw_read(struct dfs_fd* fd, void *buf, rt_size_t len)
  256. {
  257. struct dfs_filesystem* fs;
  258. int result = 0;
  259. if (fd == RT_NULL) return -DFS_STATUS_EINVAL;
  260. fs = (struct dfs_filesystem*) fd->fs;
  261. if (fs->ops->read == RT_NULL) return -DFS_STATUS_ENOSYS;
  262. if ( (result = fs->ops->read(fd, buf, len)) < 0 ) fd->flags |= DFS_F_EOF;
  263. return result;
  264. }
  265. /*
  266. +------------------------------------------------------------------------------
  267. | Function : dfile_raw_getdents
  268. +------------------------------------------------------------------------------
  269. | Description :
  270. |
  271. | Parameters :
  272. | Returns :
  273. |
  274. +------------------------------------------------------------------------------
  275. */
  276. int dfile_raw_getdents(struct dfs_fd* fd, struct dfs_dirent* dirp, rt_size_t nbytes)
  277. {
  278. struct dfs_filesystem* fs;
  279. /* parameter check */
  280. if (fd == RT_NULL || fd->type != FT_DIRECTORY) return -DFS_STATUS_EINVAL;
  281. fs = (struct dfs_filesystem*) fd->fs;
  282. if (fs->ops->getdents != RT_NULL) return fs->ops->getdents(fd, dirp, nbytes);
  283. return -DFS_STATUS_ENOSYS;
  284. }
  285. /*
  286. +------------------------------------------------------------------------------
  287. | Function : dfile_raw_unlink
  288. +------------------------------------------------------------------------------
  289. | Description :
  290. |
  291. | Parameters :
  292. | Returns :
  293. |
  294. +------------------------------------------------------------------------------
  295. */
  296. int dfile_raw_unlink(const char *path)
  297. {
  298. struct dfs_filesystem* fs;
  299. char *fullpath, *real_path, search_path[DFS_PATH_MAX + 1];
  300. #ifdef DFS_USING_WORKDIR
  301. char full_path[DFS_PATH_MAX+1];
  302. #endif
  303. struct dfs_fd* fd;
  304. int index, fspathlen;
  305. /* Make sure we have an absolute path */
  306. fullpath = (char*)path;
  307. if ( fullpath[0] != '/')
  308. {
  309. #ifdef DFS_USING_WORKDIR
  310. /* build full path */
  311. fullpath = full_path;
  312. dfs_lock();
  313. build_fullpath(working_directory, path, fullpath);
  314. dfs_unlock();
  315. #else
  316. #ifdef RT_USING_FINSH
  317. rt_kprintf("bad filename");
  318. #endif
  319. return -1;
  320. #endif
  321. }
  322. if ( (fs = dfs_filesystem_lookup(fullpath)) == RT_NULL) return -DFS_STATUS_ENOENT;
  323. /* Check whether file is already open */
  324. dfs_lock();
  325. for (index = 0; index < DFS_FD_MAX; index++)
  326. {
  327. fd = &(fd_table[index]);
  328. if (fd->fs == RT_NULL) continue;
  329. build_fullpath(fd->fs->path, fd->path, search_path);
  330. if (strcmp(fullpath, search_path) == 0)
  331. {
  332. dfs_unlock();
  333. return -DFS_STATUS_EEXIST;
  334. }
  335. }
  336. dfs_unlock();
  337. fspathlen = strlen(fs->path);
  338. real_path = search_path;
  339. rt_memset( real_path, 0, sizeof( real_path ) );
  340. if (*(fullpath + fspathlen) != '/') strcpy(real_path, "/");
  341. strcat(real_path, fullpath + fspathlen);
  342. if (fs->ops->unlink != RT_NULL) return fs->ops->unlink(fs, real_path);
  343. return -DFS_STATUS_ENOSYS;
  344. }
  345. /*
  346. +------------------------------------------------------------------------------
  347. | Function : dfile_raw_write
  348. +------------------------------------------------------------------------------
  349. | Description :
  350. |
  351. | Parameters :
  352. | Returns :
  353. |
  354. +------------------------------------------------------------------------------
  355. */
  356. int dfile_raw_write(struct dfs_fd* fd, const void *buf, rt_size_t len)
  357. {
  358. struct dfs_filesystem* fs = fd->fs;
  359. if (fd == RT_NULL) return -DFS_STATUS_EINVAL;
  360. if (fs->ops->write == RT_NULL) return -DFS_STATUS_ENOSYS;
  361. return fs->ops->write(fd, buf, len);
  362. }
  363. /*
  364. +------------------------------------------------------------------------------
  365. | Function : dfile_raw_lseek
  366. +------------------------------------------------------------------------------
  367. | Description :
  368. |
  369. | Parameters :
  370. | Returns :
  371. |
  372. +------------------------------------------------------------------------------
  373. */
  374. int dfile_raw_lseek(struct dfs_fd* fd, rt_off_t offset)
  375. {
  376. struct dfs_filesystem* fs = fd->fs;
  377. if (fd == RT_NULL) return -DFS_STATUS_EINVAL;
  378. if (fs->ops->lseek == RT_NULL) return -DFS_STATUS_ENOSYS;
  379. return fs->ops->lseek(fd, offset);
  380. }
  381. /*
  382. +------------------------------------------------------------------------------
  383. | Function : dfile_raw_stat
  384. +------------------------------------------------------------------------------
  385. | Description : get the file or directory stat description
  386. |
  387. | Parameters : path, the file or directory path
  388. | buf, the stat description will be saved in it
  389. | Returns :
  390. |
  391. +------------------------------------------------------------------------------
  392. */
  393. int dfile_raw_stat(const char *path, struct dfs_stat *buf)
  394. {
  395. struct dfs_filesystem* fs;
  396. char* fullpath, real_path[DFS_PATH_MAX + 1];
  397. #ifdef DFS_USING_WORKDIR
  398. char full_path[DFS_PATH_MAX + 1];
  399. #endif
  400. int fspathlen;
  401. fullpath = (char*)path;
  402. if ( fullpath[0] != '/' )
  403. {
  404. #ifdef DFS_USING_WORKDIR
  405. /* build full path */
  406. fullpath = full_path;
  407. dfs_lock();
  408. build_fullpath(working_directory, path, fullpath);
  409. dfs_unlock();
  410. #else
  411. #ifdef RT_USING_FINSH
  412. rt_kprintf("not support working directory, bad filename\n");
  413. #endif
  414. return -1;
  415. #endif
  416. }
  417. if ( (fs = dfs_filesystem_lookup(fullpath)) == RT_NULL )
  418. {
  419. dfs_log(DFS_DEBUG_ERROR, ("can't find mounted filesystem on this path:%s", fullpath));
  420. return -DFS_STATUS_ENOENT;
  421. }
  422. fspathlen = strlen(fs->path);
  423. rt_memset(real_path, 0, sizeof(real_path));
  424. if (*(fullpath + fspathlen) != '/') strcpy(real_path, "/");
  425. strcat(real_path, fullpath + fspathlen);
  426. if (fs->ops->stat == RT_NULL)
  427. {
  428. dfs_log(DFS_DEBUG_ERROR, ("the filesystem didn't implement this function"));
  429. return -DFS_STATUS_ENOSYS;
  430. }
  431. return fs->ops->stat(fs, real_path, buf);
  432. }
  433. /*
  434. +------------------------------------------------------------------------------
  435. | Function : dfile_raw_rename
  436. +------------------------------------------------------------------------------
  437. | Description :
  438. |
  439. | Parameters :
  440. | Returns :
  441. |
  442. +------------------------------------------------------------------------------
  443. */
  444. int dfile_raw_rename(const char* oldpath, const char* newpath)
  445. {
  446. struct dfs_filesystem *oldfs, *newfs;
  447. char *oldfullpath, *newfullpath;
  448. #ifdef DFS_USING_WORKDIR
  449. /* Change DFS_PATH_MAX to DFS_PATH_MAX + 1, yi.qiu@2008.09.23*/
  450. char old_realpath[DFS_PATH_MAX + 1], new_realpath[DFS_PATH_MAX + 1];
  451. #endif
  452. oldfullpath = (char*)oldpath;
  453. newfullpath = (char*)newpath;
  454. if ( oldfullpath[0] != '/' )
  455. {
  456. #ifdef DFS_USING_WORKDIR
  457. /* build full path */
  458. oldfullpath = old_realpath;
  459. dfs_lock();
  460. build_fullpath(working_directory, oldpath, oldfullpath);
  461. dfs_unlock();
  462. #else
  463. rt_kprintf("bad filename\n");
  464. return -1;
  465. #endif
  466. }
  467. if ( newfullpath[0] != '/' )
  468. {
  469. #ifdef DFS_USING_WORKDIR
  470. /* build full path */
  471. newfullpath = new_realpath;
  472. dfs_lock();
  473. build_fullpath(working_directory, newpath, newfullpath);
  474. dfs_unlock();
  475. #else
  476. rt_kprintf("bad filename");
  477. return -1;
  478. #endif
  479. }
  480. if ( (oldfs = dfs_filesystem_lookup(oldfullpath)) == RT_NULL )
  481. {
  482. return -DFS_STATUS_ENOENT;
  483. }
  484. if ( (newfs = dfs_filesystem_lookup(newfullpath)) == RT_NULL )
  485. {
  486. return -DFS_STATUS_ENOENT;
  487. }
  488. if ( oldfs == newfs )
  489. {
  490. if ( oldfs->ops->rename == RT_NULL ) return -DFS_STATUS_ENOSYS;
  491. return oldfs->ops->rename(oldfs, oldfullpath, newfullpath);
  492. }
  493. /* not at same file system, return EXDEV */
  494. return -DFS_STATUS_EXDEV;
  495. }
  496. #ifdef RT_USING_FINSH
  497. #include <finsh.h>
  498. static char fullpath[256 + 1];
  499. static struct dfs_fd fd;
  500. static struct dfs_dirent dirent;
  501. void __ls(const char* pathname)
  502. {
  503. struct dfs_stat stat;
  504. int length;
  505. /* list directory */
  506. if ( dfile_raw_open(&fd, pathname, DFS_O_DIRECTORY) == 0 )
  507. {
  508. rt_kprintf("Directory %s:\n", pathname);
  509. do
  510. {
  511. rt_memset(&dirent, 0, sizeof(struct dfs_dirent));
  512. length = dfile_raw_getdents(&fd, &dirent, sizeof(struct dfs_dirent));
  513. if ( length > 0 )
  514. {
  515. rt_memset(&stat, 0, sizeof(struct dfs_stat));
  516. /* build full path for each file */
  517. strncpy(fullpath, pathname, 256);
  518. strcat(fullpath, "/");
  519. strcat(fullpath, dirent.d_name);
  520. dfile_raw_stat(fullpath, &stat);
  521. if ( stat.st_mode & DFS_S_IFDIR )
  522. {
  523. rt_kprintf("%s\t\t<DIR>\n", dirent.d_name);
  524. }
  525. else
  526. {
  527. rt_kprintf("%s\t\t%lu\n", dirent.d_name, stat.st_size);
  528. }
  529. }
  530. }while(length > 0);
  531. dfile_raw_close(&fd);
  532. }
  533. else
  534. {
  535. rt_kprintf("No such directory\n");
  536. }
  537. }
  538. FINSH_FUNCTION_EXPORT(__ls, list directory contents)
  539. void __mkdir(const char* pathname)
  540. {
  541. /* make a new directory */
  542. if (dfile_raw_open(&fd, pathname, DFS_O_DIRECTORY | DFS_O_CREAT) == 0)
  543. {
  544. dfile_raw_close(&fd);
  545. }
  546. else rt_kprintf("Can't mkdir %s\n", pathname);
  547. }
  548. FINSH_FUNCTION_EXPORT(__mkdir, make a directory)
  549. void __rm(const char* filename)
  550. {
  551. if (dfile_raw_unlink(filename) < 0)
  552. {
  553. rt_kprintf("Delete %s failed\n", filename);
  554. }
  555. }
  556. FINSH_FUNCTION_EXPORT(__rm, remove files or directories)
  557. void __cat(const char* filename)
  558. {
  559. rt_uint32_t length;
  560. char buffer[81];
  561. if (dfile_raw_open(&fd, filename, DFS_O_RDONLY) < 0)
  562. {
  563. rt_kprintf("Open %s failed\n", filename);
  564. return;
  565. }
  566. do
  567. {
  568. rt_memset(buffer, 0, sizeof(buffer));
  569. length = dfile_raw_read(&fd, buffer, 81);
  570. if (length > 0)
  571. {
  572. rt_kprintf("%s", buffer);
  573. }
  574. }while (length > 0);
  575. dfile_raw_close(&fd);
  576. }
  577. FINSH_FUNCTION_EXPORT(__cat, print file)
  578. #ifndef FINSH_USING_SYMTAB
  579. void dfs_export_finsh(void)
  580. {
  581. finsh_syscall_append("ls", (syscall_func)__ls);
  582. finsh_syscall_append("mkdir", (syscall_func)__mkdir);
  583. finsh_syscall_append("rm", (syscall_func)__rm);
  584. finsh_syscall_append("cat", (syscall_func)__cat);
  585. }
  586. #endif
  587. #endif