1*10465441SEvalZero /*
2*10465441SEvalZero * Copyright (c) 2006-2018, RT-Thread Development Team
3*10465441SEvalZero *
4*10465441SEvalZero * SPDX-License-Identifier: Apache-2.0
5*10465441SEvalZero *
6*10465441SEvalZero * Change Logs:
7*10465441SEvalZero * Date Author Notes
8*10465441SEvalZero * 2013-04-15 Bernard the first version
9*10465441SEvalZero * 2013-05-05 Bernard remove CRC for ramfs persistence
10*10465441SEvalZero * 2013-05-22 Bernard fix the no entry issue.
11*10465441SEvalZero */
12*10465441SEvalZero
13*10465441SEvalZero #include <rtthread.h>
14*10465441SEvalZero #include <dfs.h>
15*10465441SEvalZero #include <dfs_fs.h>
16*10465441SEvalZero #include <dfs_file.h>
17*10465441SEvalZero
18*10465441SEvalZero #include "dfs_ramfs.h"
19*10465441SEvalZero
dfs_ramfs_mount(struct dfs_filesystem * fs,unsigned long rwflag,const void * data)20*10465441SEvalZero int dfs_ramfs_mount(struct dfs_filesystem *fs,
21*10465441SEvalZero unsigned long rwflag,
22*10465441SEvalZero const void *data)
23*10465441SEvalZero {
24*10465441SEvalZero struct dfs_ramfs* ramfs;
25*10465441SEvalZero
26*10465441SEvalZero if (data == NULL)
27*10465441SEvalZero return -EIO;
28*10465441SEvalZero
29*10465441SEvalZero ramfs = (struct dfs_ramfs *)data;
30*10465441SEvalZero fs->data = ramfs;
31*10465441SEvalZero
32*10465441SEvalZero return RT_EOK;
33*10465441SEvalZero }
34*10465441SEvalZero
dfs_ramfs_unmount(struct dfs_filesystem * fs)35*10465441SEvalZero int dfs_ramfs_unmount(struct dfs_filesystem *fs)
36*10465441SEvalZero {
37*10465441SEvalZero fs->data = NULL;
38*10465441SEvalZero
39*10465441SEvalZero return RT_EOK;
40*10465441SEvalZero }
41*10465441SEvalZero
dfs_ramfs_statfs(struct dfs_filesystem * fs,struct statfs * buf)42*10465441SEvalZero int dfs_ramfs_statfs(struct dfs_filesystem *fs, struct statfs *buf)
43*10465441SEvalZero {
44*10465441SEvalZero struct dfs_ramfs *ramfs;
45*10465441SEvalZero
46*10465441SEvalZero ramfs = (struct dfs_ramfs *)fs->data;
47*10465441SEvalZero RT_ASSERT(ramfs != NULL);
48*10465441SEvalZero RT_ASSERT(buf != NULL);
49*10465441SEvalZero
50*10465441SEvalZero buf->f_bsize = 512;
51*10465441SEvalZero buf->f_blocks = ramfs->memheap.pool_size/512;
52*10465441SEvalZero buf->f_bfree = ramfs->memheap.available_size/512;
53*10465441SEvalZero
54*10465441SEvalZero return RT_EOK;
55*10465441SEvalZero }
56*10465441SEvalZero
dfs_ramfs_ioctl(struct dfs_fd * file,int cmd,void * args)57*10465441SEvalZero int dfs_ramfs_ioctl(struct dfs_fd *file, int cmd, void *args)
58*10465441SEvalZero {
59*10465441SEvalZero return -EIO;
60*10465441SEvalZero }
61*10465441SEvalZero
dfs_ramfs_lookup(struct dfs_ramfs * ramfs,const char * path,rt_size_t * size)62*10465441SEvalZero struct ramfs_dirent *dfs_ramfs_lookup(struct dfs_ramfs *ramfs,
63*10465441SEvalZero const char *path,
64*10465441SEvalZero rt_size_t *size)
65*10465441SEvalZero {
66*10465441SEvalZero const char *subpath;
67*10465441SEvalZero struct ramfs_dirent *dirent;
68*10465441SEvalZero
69*10465441SEvalZero subpath = path;
70*10465441SEvalZero while (*subpath == '/' && *subpath)
71*10465441SEvalZero subpath ++;
72*10465441SEvalZero if (! *subpath) /* is root directory */
73*10465441SEvalZero {
74*10465441SEvalZero *size = 0;
75*10465441SEvalZero
76*10465441SEvalZero return &(ramfs->root);
77*10465441SEvalZero }
78*10465441SEvalZero
79*10465441SEvalZero for (dirent = rt_list_entry(ramfs->root.list.next, struct ramfs_dirent, list);
80*10465441SEvalZero dirent != &(ramfs->root);
81*10465441SEvalZero dirent = rt_list_entry(dirent->list.next, struct ramfs_dirent, list))
82*10465441SEvalZero {
83*10465441SEvalZero if (rt_strcmp(dirent->name, subpath) == 0)
84*10465441SEvalZero {
85*10465441SEvalZero *size = dirent->size;
86*10465441SEvalZero
87*10465441SEvalZero return dirent;
88*10465441SEvalZero }
89*10465441SEvalZero }
90*10465441SEvalZero
91*10465441SEvalZero /* not found */
92*10465441SEvalZero return NULL;
93*10465441SEvalZero }
94*10465441SEvalZero
dfs_ramfs_read(struct dfs_fd * file,void * buf,size_t count)95*10465441SEvalZero int dfs_ramfs_read(struct dfs_fd *file, void *buf, size_t count)
96*10465441SEvalZero {
97*10465441SEvalZero rt_size_t length;
98*10465441SEvalZero struct ramfs_dirent *dirent;
99*10465441SEvalZero
100*10465441SEvalZero dirent = (struct ramfs_dirent *)file->data;
101*10465441SEvalZero RT_ASSERT(dirent != NULL);
102*10465441SEvalZero
103*10465441SEvalZero if (count < file->size - file->pos)
104*10465441SEvalZero length = count;
105*10465441SEvalZero else
106*10465441SEvalZero length = file->size - file->pos;
107*10465441SEvalZero
108*10465441SEvalZero if (length > 0)
109*10465441SEvalZero memcpy(buf, &(dirent->data[file->pos]), length);
110*10465441SEvalZero
111*10465441SEvalZero /* update file current position */
112*10465441SEvalZero file->pos += length;
113*10465441SEvalZero
114*10465441SEvalZero return length;
115*10465441SEvalZero }
116*10465441SEvalZero
dfs_ramfs_write(struct dfs_fd * fd,const void * buf,size_t count)117*10465441SEvalZero int dfs_ramfs_write(struct dfs_fd *fd, const void *buf, size_t count)
118*10465441SEvalZero {
119*10465441SEvalZero struct ramfs_dirent *dirent;
120*10465441SEvalZero struct dfs_ramfs *ramfs;
121*10465441SEvalZero
122*10465441SEvalZero dirent = (struct ramfs_dirent*)fd->data;
123*10465441SEvalZero RT_ASSERT(dirent != NULL);
124*10465441SEvalZero
125*10465441SEvalZero ramfs = dirent->fs;
126*10465441SEvalZero RT_ASSERT(ramfs != NULL);
127*10465441SEvalZero
128*10465441SEvalZero if (count + fd->pos > fd->size)
129*10465441SEvalZero {
130*10465441SEvalZero rt_uint8_t *ptr;
131*10465441SEvalZero ptr = rt_memheap_realloc(&(ramfs->memheap), dirent->data, fd->pos + count);
132*10465441SEvalZero if (ptr == NULL)
133*10465441SEvalZero {
134*10465441SEvalZero rt_set_errno(-ENOMEM);
135*10465441SEvalZero
136*10465441SEvalZero return 0;
137*10465441SEvalZero }
138*10465441SEvalZero
139*10465441SEvalZero /* update dirent and file size */
140*10465441SEvalZero dirent->data = ptr;
141*10465441SEvalZero dirent->size = fd->pos + count;
142*10465441SEvalZero fd->size = dirent->size;
143*10465441SEvalZero }
144*10465441SEvalZero
145*10465441SEvalZero if (count > 0)
146*10465441SEvalZero memcpy(dirent->data + fd->pos, buf, count);
147*10465441SEvalZero
148*10465441SEvalZero /* update file current position */
149*10465441SEvalZero fd->pos += count;
150*10465441SEvalZero
151*10465441SEvalZero return count;
152*10465441SEvalZero }
153*10465441SEvalZero
dfs_ramfs_lseek(struct dfs_fd * file,off_t offset)154*10465441SEvalZero int dfs_ramfs_lseek(struct dfs_fd *file, off_t offset)
155*10465441SEvalZero {
156*10465441SEvalZero if (offset <= (off_t)file->size)
157*10465441SEvalZero {
158*10465441SEvalZero file->pos = offset;
159*10465441SEvalZero
160*10465441SEvalZero return file->pos;
161*10465441SEvalZero }
162*10465441SEvalZero
163*10465441SEvalZero return -EIO;
164*10465441SEvalZero }
165*10465441SEvalZero
dfs_ramfs_close(struct dfs_fd * file)166*10465441SEvalZero int dfs_ramfs_close(struct dfs_fd *file)
167*10465441SEvalZero {
168*10465441SEvalZero file->data = NULL;
169*10465441SEvalZero
170*10465441SEvalZero return RT_EOK;
171*10465441SEvalZero }
172*10465441SEvalZero
dfs_ramfs_open(struct dfs_fd * file)173*10465441SEvalZero int dfs_ramfs_open(struct dfs_fd *file)
174*10465441SEvalZero {
175*10465441SEvalZero rt_size_t size;
176*10465441SEvalZero struct dfs_ramfs *ramfs;
177*10465441SEvalZero struct ramfs_dirent *dirent;
178*10465441SEvalZero struct dfs_filesystem *fs;
179*10465441SEvalZero
180*10465441SEvalZero fs = (struct dfs_filesystem *)file->data;
181*10465441SEvalZero
182*10465441SEvalZero ramfs = (struct dfs_ramfs *)fs->data;
183*10465441SEvalZero RT_ASSERT(ramfs != NULL);
184*10465441SEvalZero
185*10465441SEvalZero if (file->flags & O_DIRECTORY)
186*10465441SEvalZero {
187*10465441SEvalZero if (file->flags & O_CREAT)
188*10465441SEvalZero {
189*10465441SEvalZero return -ENOSPC;
190*10465441SEvalZero }
191*10465441SEvalZero
192*10465441SEvalZero /* open directory */
193*10465441SEvalZero dirent = dfs_ramfs_lookup(ramfs, file->path, &size);
194*10465441SEvalZero if (dirent == NULL)
195*10465441SEvalZero return -ENOENT;
196*10465441SEvalZero if (dirent == &(ramfs->root)) /* it's root directory */
197*10465441SEvalZero {
198*10465441SEvalZero if (!(file->flags & O_DIRECTORY))
199*10465441SEvalZero {
200*10465441SEvalZero return -ENOENT;
201*10465441SEvalZero }
202*10465441SEvalZero }
203*10465441SEvalZero }
204*10465441SEvalZero else
205*10465441SEvalZero {
206*10465441SEvalZero dirent = dfs_ramfs_lookup(ramfs, file->path, &size);
207*10465441SEvalZero if (dirent == &(ramfs->root)) /* it's root directory */
208*10465441SEvalZero {
209*10465441SEvalZero return -ENOENT;
210*10465441SEvalZero }
211*10465441SEvalZero
212*10465441SEvalZero if (dirent == NULL)
213*10465441SEvalZero {
214*10465441SEvalZero if (file->flags & O_CREAT || file->flags & O_WRONLY)
215*10465441SEvalZero {
216*10465441SEvalZero char *name_ptr;
217*10465441SEvalZero
218*10465441SEvalZero /* create a file entry */
219*10465441SEvalZero dirent = (struct ramfs_dirent *)
220*10465441SEvalZero rt_memheap_alloc(&(ramfs->memheap),
221*10465441SEvalZero sizeof(struct ramfs_dirent));
222*10465441SEvalZero if (dirent == NULL)
223*10465441SEvalZero {
224*10465441SEvalZero return -ENOMEM;
225*10465441SEvalZero }
226*10465441SEvalZero
227*10465441SEvalZero /* remove '/' separator */
228*10465441SEvalZero name_ptr = file->path;
229*10465441SEvalZero while (*name_ptr == '/' && *name_ptr)
230*10465441SEvalZero name_ptr ++;
231*10465441SEvalZero strncpy(dirent->name, name_ptr, RAMFS_NAME_MAX);
232*10465441SEvalZero
233*10465441SEvalZero rt_list_init(&(dirent->list));
234*10465441SEvalZero dirent->data = NULL;
235*10465441SEvalZero dirent->size = 0;
236*10465441SEvalZero dirent->fs = ramfs;
237*10465441SEvalZero
238*10465441SEvalZero /* add to the root directory */
239*10465441SEvalZero rt_list_insert_after(&(ramfs->root.list), &(dirent->list));
240*10465441SEvalZero }
241*10465441SEvalZero else
242*10465441SEvalZero return -ENOENT;
243*10465441SEvalZero }
244*10465441SEvalZero
245*10465441SEvalZero /* Creates a new file.
246*10465441SEvalZero * If the file is existing, it is truncated and overwritten.
247*10465441SEvalZero */
248*10465441SEvalZero if (file->flags & O_TRUNC)
249*10465441SEvalZero {
250*10465441SEvalZero dirent->size = 0;
251*10465441SEvalZero if (dirent->data != NULL)
252*10465441SEvalZero {
253*10465441SEvalZero rt_memheap_free(dirent->data);
254*10465441SEvalZero dirent->data = NULL;
255*10465441SEvalZero }
256*10465441SEvalZero }
257*10465441SEvalZero }
258*10465441SEvalZero
259*10465441SEvalZero file->data = dirent;
260*10465441SEvalZero file->size = dirent->size;
261*10465441SEvalZero if (file->flags & O_APPEND)
262*10465441SEvalZero file->pos = file->size;
263*10465441SEvalZero else
264*10465441SEvalZero file->pos = 0;
265*10465441SEvalZero
266*10465441SEvalZero return 0;
267*10465441SEvalZero }
268*10465441SEvalZero
dfs_ramfs_stat(struct dfs_filesystem * fs,const char * path,struct stat * st)269*10465441SEvalZero int dfs_ramfs_stat(struct dfs_filesystem *fs,
270*10465441SEvalZero const char *path,
271*10465441SEvalZero struct stat *st)
272*10465441SEvalZero {
273*10465441SEvalZero rt_size_t size;
274*10465441SEvalZero struct ramfs_dirent *dirent;
275*10465441SEvalZero struct dfs_ramfs *ramfs;
276*10465441SEvalZero
277*10465441SEvalZero ramfs = (struct dfs_ramfs *)fs->data;
278*10465441SEvalZero dirent = dfs_ramfs_lookup(ramfs, path, &size);
279*10465441SEvalZero
280*10465441SEvalZero if (dirent == NULL)
281*10465441SEvalZero return -ENOENT;
282*10465441SEvalZero
283*10465441SEvalZero st->st_dev = 0;
284*10465441SEvalZero st->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH |
285*10465441SEvalZero S_IWUSR | S_IWGRP | S_IWOTH;
286*10465441SEvalZero
287*10465441SEvalZero st->st_size = dirent->size;
288*10465441SEvalZero st->st_mtime = 0;
289*10465441SEvalZero
290*10465441SEvalZero return RT_EOK;
291*10465441SEvalZero }
292*10465441SEvalZero
dfs_ramfs_getdents(struct dfs_fd * file,struct dirent * dirp,uint32_t count)293*10465441SEvalZero int dfs_ramfs_getdents(struct dfs_fd *file,
294*10465441SEvalZero struct dirent *dirp,
295*10465441SEvalZero uint32_t count)
296*10465441SEvalZero {
297*10465441SEvalZero rt_size_t index, end;
298*10465441SEvalZero struct dirent *d;
299*10465441SEvalZero struct ramfs_dirent *dirent;
300*10465441SEvalZero struct dfs_ramfs *ramfs;
301*10465441SEvalZero
302*10465441SEvalZero dirent = (struct ramfs_dirent *)file->data;
303*10465441SEvalZero
304*10465441SEvalZero ramfs = dirent->fs;
305*10465441SEvalZero RT_ASSERT(ramfs != RT_NULL);
306*10465441SEvalZero
307*10465441SEvalZero if (dirent != &(ramfs->root))
308*10465441SEvalZero return -EINVAL;
309*10465441SEvalZero
310*10465441SEvalZero /* make integer count */
311*10465441SEvalZero count = (count / sizeof(struct dirent));
312*10465441SEvalZero if (count == 0)
313*10465441SEvalZero return -EINVAL;
314*10465441SEvalZero
315*10465441SEvalZero end = file->pos + count;
316*10465441SEvalZero index = 0;
317*10465441SEvalZero count = 0;
318*10465441SEvalZero for (dirent = rt_list_entry(dirent->list.next, struct ramfs_dirent, list);
319*10465441SEvalZero dirent != &(ramfs->root) && index < end;
320*10465441SEvalZero dirent = rt_list_entry(dirent->list.next, struct ramfs_dirent, list))
321*10465441SEvalZero {
322*10465441SEvalZero if (index >= (rt_size_t)file->pos)
323*10465441SEvalZero {
324*10465441SEvalZero d = dirp + count;
325*10465441SEvalZero d->d_type = DT_REG;
326*10465441SEvalZero d->d_namlen = RT_NAME_MAX;
327*10465441SEvalZero d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
328*10465441SEvalZero rt_strncpy(d->d_name, dirent->name, RAMFS_NAME_MAX);
329*10465441SEvalZero
330*10465441SEvalZero count += 1;
331*10465441SEvalZero file->pos += 1;
332*10465441SEvalZero }
333*10465441SEvalZero index += 1;
334*10465441SEvalZero }
335*10465441SEvalZero
336*10465441SEvalZero return count * sizeof(struct dirent);
337*10465441SEvalZero }
338*10465441SEvalZero
dfs_ramfs_unlink(struct dfs_filesystem * fs,const char * path)339*10465441SEvalZero int dfs_ramfs_unlink(struct dfs_filesystem *fs, const char *path)
340*10465441SEvalZero {
341*10465441SEvalZero rt_size_t size;
342*10465441SEvalZero struct dfs_ramfs *ramfs;
343*10465441SEvalZero struct ramfs_dirent *dirent;
344*10465441SEvalZero
345*10465441SEvalZero ramfs = (struct dfs_ramfs *)fs->data;
346*10465441SEvalZero RT_ASSERT(ramfs != NULL);
347*10465441SEvalZero
348*10465441SEvalZero dirent = dfs_ramfs_lookup(ramfs, path, &size);
349*10465441SEvalZero if (dirent == NULL)
350*10465441SEvalZero return -ENOENT;
351*10465441SEvalZero
352*10465441SEvalZero rt_list_remove(&(dirent->list));
353*10465441SEvalZero if (dirent->data != NULL)
354*10465441SEvalZero rt_memheap_free(dirent->data);
355*10465441SEvalZero rt_memheap_free(dirent);
356*10465441SEvalZero
357*10465441SEvalZero return RT_EOK;
358*10465441SEvalZero }
359*10465441SEvalZero
dfs_ramfs_rename(struct dfs_filesystem * fs,const char * oldpath,const char * newpath)360*10465441SEvalZero int dfs_ramfs_rename(struct dfs_filesystem *fs,
361*10465441SEvalZero const char *oldpath,
362*10465441SEvalZero const char *newpath)
363*10465441SEvalZero {
364*10465441SEvalZero struct ramfs_dirent *dirent;
365*10465441SEvalZero struct dfs_ramfs *ramfs;
366*10465441SEvalZero rt_size_t size;
367*10465441SEvalZero
368*10465441SEvalZero ramfs = (struct dfs_ramfs *)fs->data;
369*10465441SEvalZero RT_ASSERT(ramfs != NULL);
370*10465441SEvalZero
371*10465441SEvalZero dirent = dfs_ramfs_lookup(ramfs, newpath, &size);
372*10465441SEvalZero if (dirent != NULL)
373*10465441SEvalZero return -EEXIST;
374*10465441SEvalZero
375*10465441SEvalZero dirent = dfs_ramfs_lookup(ramfs, oldpath, &size);
376*10465441SEvalZero if (dirent == NULL)
377*10465441SEvalZero return -ENOENT;
378*10465441SEvalZero
379*10465441SEvalZero strncpy(dirent->name, newpath, RAMFS_NAME_MAX);
380*10465441SEvalZero
381*10465441SEvalZero return RT_EOK;
382*10465441SEvalZero }
383*10465441SEvalZero
384*10465441SEvalZero static const struct dfs_file_ops _ram_fops =
385*10465441SEvalZero {
386*10465441SEvalZero dfs_ramfs_open,
387*10465441SEvalZero dfs_ramfs_close,
388*10465441SEvalZero dfs_ramfs_ioctl,
389*10465441SEvalZero dfs_ramfs_read,
390*10465441SEvalZero dfs_ramfs_write,
391*10465441SEvalZero NULL, /* flush */
392*10465441SEvalZero dfs_ramfs_lseek,
393*10465441SEvalZero dfs_ramfs_getdents,
394*10465441SEvalZero };
395*10465441SEvalZero
396*10465441SEvalZero static const struct dfs_filesystem_ops _ramfs =
397*10465441SEvalZero {
398*10465441SEvalZero "ram",
399*10465441SEvalZero DFS_FS_FLAG_DEFAULT,
400*10465441SEvalZero &_ram_fops,
401*10465441SEvalZero
402*10465441SEvalZero dfs_ramfs_mount,
403*10465441SEvalZero dfs_ramfs_unmount,
404*10465441SEvalZero NULL, /* mkfs */
405*10465441SEvalZero dfs_ramfs_statfs,
406*10465441SEvalZero
407*10465441SEvalZero dfs_ramfs_unlink,
408*10465441SEvalZero dfs_ramfs_stat,
409*10465441SEvalZero dfs_ramfs_rename,
410*10465441SEvalZero };
411*10465441SEvalZero
dfs_ramfs_init(void)412*10465441SEvalZero int dfs_ramfs_init(void)
413*10465441SEvalZero {
414*10465441SEvalZero /* register ram file system */
415*10465441SEvalZero dfs_register(&_ramfs);
416*10465441SEvalZero
417*10465441SEvalZero return 0;
418*10465441SEvalZero }
419*10465441SEvalZero INIT_COMPONENT_EXPORT(dfs_ramfs_init);
420*10465441SEvalZero
dfs_ramfs_create(rt_uint8_t * pool,rt_size_t size)421*10465441SEvalZero struct dfs_ramfs* dfs_ramfs_create(rt_uint8_t *pool, rt_size_t size)
422*10465441SEvalZero {
423*10465441SEvalZero struct dfs_ramfs *ramfs;
424*10465441SEvalZero rt_uint8_t *data_ptr;
425*10465441SEvalZero rt_err_t result;
426*10465441SEvalZero
427*10465441SEvalZero size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE);
428*10465441SEvalZero ramfs = (struct dfs_ramfs *)pool;
429*10465441SEvalZero
430*10465441SEvalZero data_ptr = (rt_uint8_t *)(ramfs + 1);
431*10465441SEvalZero size = size - sizeof(struct dfs_ramfs);
432*10465441SEvalZero size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE);
433*10465441SEvalZero
434*10465441SEvalZero result = rt_memheap_init(&ramfs->memheap, "ramfs", data_ptr, size);
435*10465441SEvalZero if (result != RT_EOK)
436*10465441SEvalZero return NULL;
437*10465441SEvalZero /* detach this memheap object from the system */
438*10465441SEvalZero rt_object_detach((rt_object_t)&(ramfs->memheap));
439*10465441SEvalZero
440*10465441SEvalZero /* initialize ramfs object */
441*10465441SEvalZero ramfs->magic = RAMFS_MAGIC;
442*10465441SEvalZero ramfs->memheap.parent.type = RT_Object_Class_MemHeap | RT_Object_Class_Static;
443*10465441SEvalZero
444*10465441SEvalZero /* initialize root directory */
445*10465441SEvalZero memset(&(ramfs->root), 0x00, sizeof(ramfs->root));
446*10465441SEvalZero rt_list_init(&(ramfs->root.list));
447*10465441SEvalZero ramfs->root.size = 0;
448*10465441SEvalZero strcpy(ramfs->root.name, ".");
449*10465441SEvalZero ramfs->root.fs = ramfs;
450*10465441SEvalZero
451*10465441SEvalZero return ramfs;
452*10465441SEvalZero }
453*10465441SEvalZero
454