dfs_ramfs.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. /*
  2. * File : dfs_ramfs.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2011, Shanghai Real-Thread Technology Co., Ltd
  5. *
  6. * All rights reserved.
  7. *
  8. * Change Logs:
  9. * Date Author Notes
  10. * 2013-04-15 Bernard the first version
  11. * 2013-05-05 Bernard remove CRC for ramfs persistence
  12. */
  13. #include <rtthread.h>
  14. #include <dfs.h>
  15. #include <dfs_fs.h>
  16. #include "dfs_ramfs.h"
  17. int dfs_ramfs_mount(struct dfs_filesystem *fs, unsigned long rwflag, const void *data)
  18. {
  19. struct dfs_ramfs* ramfs;
  20. if (data == RT_NULL) return -DFS_STATUS_EIO;
  21. ramfs = (struct dfs_ramfs*) data;
  22. fs->data = ramfs;
  23. return DFS_STATUS_OK;
  24. }
  25. int dfs_ramfs_unmount(struct dfs_filesystem *fs)
  26. {
  27. fs->data = RT_NULL;
  28. return DFS_STATUS_OK;
  29. }
  30. int dfs_ramfs_statfs(struct dfs_filesystem *fs, struct statfs *buf)
  31. {
  32. struct dfs_ramfs *ramfs;
  33. ramfs = (struct dfs_ramfs *)fs->data;
  34. RT_ASSERT(ramfs != RT_NULL);
  35. RT_ASSERT(buf != RT_NULL);
  36. buf->f_bsize = 512;
  37. buf->f_blocks = ramfs->memheap.pool_size/512;
  38. buf->f_bfree = ramfs->memheap.available_size/512;
  39. return DFS_STATUS_OK;
  40. }
  41. int dfs_ramfs_ioctl(struct dfs_fd *file, int cmd, void *args)
  42. {
  43. return -DFS_STATUS_EIO;
  44. }
  45. struct ramfs_dirent *dfs_ramfs_lookup(struct dfs_ramfs* ramfs, const char *path, rt_size_t *size)
  46. {
  47. const char *subpath;
  48. struct ramfs_dirent *dirent;
  49. subpath = path;
  50. while (*subpath == '/' && *subpath) subpath ++;
  51. if (! *subpath) /* is root directory */
  52. {
  53. *size = 0;
  54. return &(ramfs->root);
  55. }
  56. for (dirent = rt_list_entry(ramfs->root.list.next, struct ramfs_dirent, list);
  57. dirent != &(ramfs->root);
  58. dirent = rt_list_entry(dirent->list.next, struct ramfs_dirent, list))
  59. {
  60. if (rt_strcmp(dirent->name, subpath) == 0)
  61. {
  62. *size = dirent->size;
  63. return dirent;
  64. }
  65. }
  66. /* not found */
  67. return RT_NULL;
  68. }
  69. int dfs_ramfs_read(struct dfs_fd *file, void *buf, rt_size_t count)
  70. {
  71. rt_size_t length;
  72. struct ramfs_dirent *dirent;
  73. dirent = (struct ramfs_dirent *)file->data;
  74. RT_ASSERT(dirent != RT_NULL);
  75. if (count < file->size - file->pos)
  76. length = count;
  77. else
  78. length = file->size - file->pos;
  79. if (length > 0)
  80. memcpy(buf, &(dirent->data[file->pos]), length);
  81. /* update file current position */
  82. file->pos += length;
  83. return length;
  84. }
  85. int dfs_ramfs_write(struct dfs_fd *fd, const void *buf, rt_size_t count)
  86. {
  87. struct ramfs_dirent *dirent;
  88. struct dfs_ramfs *ramfs;
  89. ramfs = (struct dfs_ramfs*)fd->fs->data;
  90. RT_ASSERT(ramfs != RT_NULL);
  91. dirent = (struct ramfs_dirent*)fd->data;
  92. RT_ASSERT(dirent != RT_NULL);
  93. if (count + fd->pos > fd->size)
  94. {
  95. rt_uint8_t *ptr;
  96. ptr = rt_memheap_realloc(&(ramfs->memheap), dirent->data, fd->pos + count);
  97. if (ptr == RT_NULL)
  98. {
  99. rt_set_errno(-RT_ENOMEM);
  100. return 0;
  101. }
  102. /* update dirent and file size */
  103. dirent->data = ptr;
  104. dirent->size = fd->pos + count;
  105. fd->size = dirent->size;
  106. }
  107. if (count > 0)
  108. memcpy(dirent->data + fd->pos, buf, count);
  109. /* update file current position */
  110. fd->pos += count;
  111. return count;
  112. }
  113. int dfs_ramfs_lseek(struct dfs_fd *file, rt_off_t offset)
  114. {
  115. if (offset <= (rt_off_t)file->size)
  116. {
  117. file->pos = offset;
  118. return file->pos;
  119. }
  120. return -DFS_STATUS_EIO;
  121. }
  122. int dfs_ramfs_close(struct dfs_fd *file)
  123. {
  124. file->data = RT_NULL;
  125. return DFS_STATUS_OK;
  126. }
  127. int dfs_ramfs_open(struct dfs_fd *file)
  128. {
  129. rt_size_t size;
  130. struct dfs_ramfs *ramfs;
  131. struct ramfs_dirent *dirent;
  132. ramfs = (struct dfs_ramfs *)file->fs->data;
  133. RT_ASSERT(ramfs != RT_NULL);
  134. if (file->flags & DFS_O_DIRECTORY)
  135. {
  136. if (file->flags & DFS_O_CREAT)
  137. {
  138. return -DFS_STATUS_ENOSPC;
  139. }
  140. /* open directory */
  141. dirent = dfs_ramfs_lookup(ramfs, file->path, &size);
  142. if (dirent == RT_NULL)
  143. return -DFS_STATUS_ENOENT;
  144. if (dirent == &(ramfs->root)) /* it's root directory */
  145. {
  146. if (!(file->flags & DFS_O_DIRECTORY))
  147. {
  148. return -DFS_STATUS_ENOENT;
  149. }
  150. }
  151. }
  152. else
  153. {
  154. dirent = dfs_ramfs_lookup(ramfs, file->path, &size);
  155. if (dirent == &(ramfs->root)) /* it's root directory */
  156. {
  157. return -DFS_STATUS_ENOENT;
  158. }
  159. if (dirent == RT_NULL)
  160. {
  161. if (file->flags & DFS_O_CREAT ||
  162. file->flags & DFS_O_WRONLY)
  163. {
  164. char *name_ptr;
  165. /* create a file entry */
  166. dirent = (struct ramfs_dirent*)rt_memheap_alloc(&(ramfs->memheap), sizeof(struct ramfs_dirent));
  167. if (dirent == RT_NULL)
  168. {
  169. return -DFS_STATUS_ENOMEM;
  170. }
  171. /* remove '/' separator */
  172. name_ptr = file->path;
  173. while (*name_ptr == '/' && *name_ptr) name_ptr ++;
  174. strncpy(dirent->name, name_ptr, RAMFS_NAME_MAX);
  175. rt_list_init(&(dirent->list));
  176. dirent->data = RT_NULL;
  177. dirent->size = 0;
  178. /* add to the root directory */
  179. rt_list_insert_after(&(ramfs->root.list), &(dirent->list));
  180. }
  181. }
  182. /* Creates a new file. If the file is existing, it is truncated and overwritten. */
  183. if (file->flags & DFS_O_TRUNC)
  184. {
  185. dirent->size = 0;
  186. if (dirent->data != RT_NULL)
  187. {
  188. rt_memheap_free(dirent->data);
  189. dirent->data = RT_NULL;
  190. }
  191. }
  192. }
  193. file->data = dirent;
  194. file->size = dirent->size;
  195. file->pos = 0;
  196. return DFS_STATUS_OK;
  197. }
  198. int dfs_ramfs_stat(struct dfs_filesystem *fs, const char *path, struct stat *st)
  199. {
  200. rt_size_t size;
  201. struct ramfs_dirent *dirent;
  202. struct dfs_ramfs *ramfs;
  203. ramfs = (struct dfs_ramfs *)fs->data;
  204. dirent = dfs_ramfs_lookup(ramfs, path, &size);
  205. if (dirent == RT_NULL)
  206. return -DFS_STATUS_ENOENT;
  207. st->st_dev = 0;
  208. st->st_mode = DFS_S_IFREG | DFS_S_IRUSR | DFS_S_IRGRP | DFS_S_IROTH |
  209. DFS_S_IWUSR | DFS_S_IWGRP | DFS_S_IWOTH;
  210. st->st_size = dirent->size;
  211. st->st_mtime = 0;
  212. st->st_blksize = 512;
  213. return DFS_STATUS_OK;
  214. }
  215. int dfs_ramfs_getdents(struct dfs_fd *file, struct dirent *dirp, rt_uint32_t count)
  216. {
  217. rt_size_t index, end;
  218. struct dirent *d;
  219. struct ramfs_dirent *dirent;
  220. struct dfs_ramfs* ramfs;
  221. ramfs = (struct dfs_ramfs*)file->fs->data;
  222. dirent = (struct ramfs_dirent *)file->data;
  223. if (dirent != &(ramfs->root)) return -DFS_STATUS_EINVAL;
  224. /* make integer count */
  225. count = (count / sizeof(struct dirent));
  226. if (count == 0) return -DFS_STATUS_EINVAL;
  227. end = file->pos + count;
  228. index = 0;
  229. count = 0;
  230. for (dirent = rt_list_entry(dirent->list.next, struct ramfs_dirent, list);
  231. dirent != &(ramfs->root) && index < end;
  232. dirent = rt_list_entry(dirent->list.next, struct ramfs_dirent, list))
  233. {
  234. if (index >= (rt_size_t)file->pos)
  235. {
  236. d = dirp + count;
  237. d->d_type = DFS_DT_REG;
  238. d->d_namlen = RT_NAME_MAX;
  239. d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
  240. rt_strncpy(d->d_name, dirent->name, RAMFS_NAME_MAX);
  241. count += 1;
  242. file->pos += 1;
  243. }
  244. index += 1;
  245. }
  246. return count * sizeof(struct dirent);
  247. }
  248. int dfs_ramfs_unlink(struct dfs_filesystem *fs, const char *path)
  249. {
  250. rt_size_t size;
  251. struct dfs_ramfs *ramfs;
  252. struct ramfs_dirent *dirent;
  253. ramfs = (struct dfs_ramfs *)fs->data;
  254. RT_ASSERT(ramfs != RT_NULL);
  255. dirent = dfs_ramfs_lookup(ramfs, path, &size);
  256. if (dirent == RT_NULL) return -DFS_STATUS_ENOENT;
  257. rt_list_remove(&(dirent->list));
  258. if (dirent->data != RT_NULL)
  259. rt_memheap_free(dirent->data);
  260. rt_memheap_free(dirent);
  261. return DFS_STATUS_OK;
  262. }
  263. int dfs_ramfs_rename(struct dfs_filesystem *fs, const char *oldpath, const char *newpath)
  264. {
  265. struct ramfs_dirent *dirent;
  266. struct dfs_ramfs *ramfs;
  267. rt_size_t size;
  268. ramfs = (struct dfs_ramfs *)fs->data;
  269. RT_ASSERT(ramfs != RT_NULL);
  270. dirent = dfs_ramfs_lookup(ramfs, newpath, &size);
  271. if (dirent != RT_NULL) return -DFS_STATUS_EEXIST;
  272. dirent = dfs_ramfs_lookup(ramfs, oldpath, &size);
  273. if (dirent == RT_NULL) return -DFS_STATUS_ENOENT;
  274. strncpy(dirent->name, newpath, RAMFS_NAME_MAX);
  275. return DFS_STATUS_OK;
  276. }
  277. static const struct dfs_filesystem_operation _ramfs =
  278. {
  279. "ram",
  280. DFS_FS_FLAG_DEFAULT,
  281. dfs_ramfs_mount,
  282. dfs_ramfs_unmount,
  283. RT_NULL, /* mkfs */
  284. dfs_ramfs_statfs,
  285. dfs_ramfs_open,
  286. dfs_ramfs_close,
  287. dfs_ramfs_ioctl,
  288. dfs_ramfs_read,
  289. dfs_ramfs_write,
  290. RT_NULL, /* flush */
  291. dfs_ramfs_lseek,
  292. dfs_ramfs_getdents,
  293. dfs_ramfs_unlink,
  294. dfs_ramfs_stat,
  295. dfs_ramfs_rename,
  296. };
  297. int dfs_ramfs_init(void)
  298. {
  299. /* register ram file system */
  300. dfs_register(&_ramfs);
  301. return 0;
  302. }
  303. struct dfs_ramfs* dfs_ramfs_create(rt_uint8_t* pool, rt_size_t size)
  304. {
  305. struct dfs_ramfs *ramfs;
  306. rt_uint8_t *data_ptr;
  307. rt_err_t result;
  308. size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE);
  309. ramfs = (struct dfs_ramfs*) pool;
  310. data_ptr = (rt_uint8_t *)(ramfs + 1);
  311. size = size - sizeof(struct dfs_ramfs);
  312. size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE);
  313. result = rt_memheap_init(&ramfs->memheap, "ramfs", data_ptr, size);
  314. if (result != RT_EOK) return RT_NULL;
  315. /* detach this memheap object from the system */
  316. rt_object_detach((rt_object_t)&(ramfs->memheap));
  317. /* initialize ramfs object */
  318. ramfs->magic = RAMFS_MAGIC;
  319. /* initialize root directory */
  320. memset(&(ramfs->root), 0x00, sizeof(ramfs->root));
  321. rt_list_init(&(ramfs->root.list));
  322. ramfs->root.size = 0;
  323. strcpy(ramfs->root.name, ".");
  324. return ramfs;
  325. }