xref: /nrf52832-nimble/rt-thread/components/dfs/filesystems/romfs/dfs_romfs.c (revision 104654410c56c573564690304ae786df310c91fc)
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  */
9*10465441SEvalZero 
10*10465441SEvalZero #include <rtthread.h>
11*10465441SEvalZero #include <dfs.h>
12*10465441SEvalZero #include <dfs_fs.h>
13*10465441SEvalZero #include <dfs_file.h>
14*10465441SEvalZero 
15*10465441SEvalZero #include "dfs_romfs.h"
16*10465441SEvalZero 
dfs_romfs_mount(struct dfs_filesystem * fs,unsigned long rwflag,const void * data)17*10465441SEvalZero int dfs_romfs_mount(struct dfs_filesystem *fs, unsigned long rwflag, const void *data)
18*10465441SEvalZero {
19*10465441SEvalZero     struct romfs_dirent *root_dirent;
20*10465441SEvalZero 
21*10465441SEvalZero     if (data == NULL)
22*10465441SEvalZero         return -EIO;
23*10465441SEvalZero 
24*10465441SEvalZero     root_dirent = (struct romfs_dirent *)data;
25*10465441SEvalZero     fs->data = root_dirent;
26*10465441SEvalZero 
27*10465441SEvalZero     return RT_EOK;
28*10465441SEvalZero }
29*10465441SEvalZero 
dfs_romfs_unmount(struct dfs_filesystem * fs)30*10465441SEvalZero int dfs_romfs_unmount(struct dfs_filesystem *fs)
31*10465441SEvalZero {
32*10465441SEvalZero     return RT_EOK;
33*10465441SEvalZero }
34*10465441SEvalZero 
dfs_romfs_ioctl(struct dfs_fd * file,int cmd,void * args)35*10465441SEvalZero int dfs_romfs_ioctl(struct dfs_fd *file, int cmd, void *args)
36*10465441SEvalZero {
37*10465441SEvalZero     return -EIO;
38*10465441SEvalZero }
39*10465441SEvalZero 
check_dirent(struct romfs_dirent * dirent)40*10465441SEvalZero rt_inline int check_dirent(struct romfs_dirent *dirent)
41*10465441SEvalZero {
42*10465441SEvalZero     if ((dirent->type != ROMFS_DIRENT_FILE && dirent->type != ROMFS_DIRENT_DIR)
43*10465441SEvalZero         || dirent->size == ~0)
44*10465441SEvalZero         return -1;
45*10465441SEvalZero     return 0;
46*10465441SEvalZero }
47*10465441SEvalZero 
dfs_romfs_lookup(struct romfs_dirent * root_dirent,const char * path,rt_size_t * size)48*10465441SEvalZero struct romfs_dirent *dfs_romfs_lookup(struct romfs_dirent *root_dirent, const char *path, rt_size_t *size)
49*10465441SEvalZero {
50*10465441SEvalZero     rt_size_t index, found;
51*10465441SEvalZero     const char *subpath, *subpath_end;
52*10465441SEvalZero     struct romfs_dirent *dirent;
53*10465441SEvalZero     rt_size_t dirent_size;
54*10465441SEvalZero 
55*10465441SEvalZero     /* Check the root_dirent. */
56*10465441SEvalZero     if (check_dirent(root_dirent) != 0)
57*10465441SEvalZero         return NULL;
58*10465441SEvalZero 
59*10465441SEvalZero     if (path[0] == '/' && path[1] == '\0')
60*10465441SEvalZero     {
61*10465441SEvalZero         *size = root_dirent->size;
62*10465441SEvalZero         return root_dirent;
63*10465441SEvalZero     }
64*10465441SEvalZero 
65*10465441SEvalZero     /* goto root directy entries */
66*10465441SEvalZero     dirent = (struct romfs_dirent *)root_dirent->data;
67*10465441SEvalZero     dirent_size = root_dirent->size;
68*10465441SEvalZero 
69*10465441SEvalZero     /* get the end position of this subpath */
70*10465441SEvalZero     subpath_end = path;
71*10465441SEvalZero     /* skip /// */
72*10465441SEvalZero     while (*subpath_end && *subpath_end == '/')
73*10465441SEvalZero         subpath_end ++;
74*10465441SEvalZero     subpath = subpath_end;
75*10465441SEvalZero     while ((*subpath_end != '/') && *subpath_end)
76*10465441SEvalZero         subpath_end ++;
77*10465441SEvalZero 
78*10465441SEvalZero     while (dirent != NULL)
79*10465441SEvalZero     {
80*10465441SEvalZero         found = 0;
81*10465441SEvalZero 
82*10465441SEvalZero         /* search in folder */
83*10465441SEvalZero         for (index = 0; index < dirent_size; index ++)
84*10465441SEvalZero         {
85*10465441SEvalZero             if (check_dirent(&dirent[index]) != 0)
86*10465441SEvalZero                 return NULL;
87*10465441SEvalZero             if (rt_strlen(dirent[index].name) == (subpath_end - subpath) &&
88*10465441SEvalZero                     rt_strncmp(dirent[index].name, subpath, (subpath_end - subpath)) == 0)
89*10465441SEvalZero             {
90*10465441SEvalZero                 dirent_size = dirent[index].size;
91*10465441SEvalZero 
92*10465441SEvalZero                 /* skip /// */
93*10465441SEvalZero                 while (*subpath_end && *subpath_end == '/')
94*10465441SEvalZero                     subpath_end ++;
95*10465441SEvalZero                 subpath = subpath_end;
96*10465441SEvalZero                 while ((*subpath_end != '/') && *subpath_end)
97*10465441SEvalZero                     subpath_end ++;
98*10465441SEvalZero 
99*10465441SEvalZero                 if (!(*subpath))
100*10465441SEvalZero                 {
101*10465441SEvalZero                     *size = dirent_size;
102*10465441SEvalZero                     return &dirent[index];
103*10465441SEvalZero                 }
104*10465441SEvalZero 
105*10465441SEvalZero                 if (dirent[index].type == ROMFS_DIRENT_DIR)
106*10465441SEvalZero                 {
107*10465441SEvalZero                     /* enter directory */
108*10465441SEvalZero                     dirent = (struct romfs_dirent*)dirent[index].data;
109*10465441SEvalZero                     found = 1;
110*10465441SEvalZero                     break;
111*10465441SEvalZero                 }
112*10465441SEvalZero                 else
113*10465441SEvalZero                 {
114*10465441SEvalZero                     /* return file dirent */
115*10465441SEvalZero                     if (subpath != NULL)
116*10465441SEvalZero                         break; /* not the end of path */
117*10465441SEvalZero 
118*10465441SEvalZero                     return &dirent[index];
119*10465441SEvalZero                 }
120*10465441SEvalZero             }
121*10465441SEvalZero         }
122*10465441SEvalZero 
123*10465441SEvalZero         if (!found)
124*10465441SEvalZero             break; /* not found */
125*10465441SEvalZero     }
126*10465441SEvalZero 
127*10465441SEvalZero     /* not found */
128*10465441SEvalZero     return NULL;
129*10465441SEvalZero }
130*10465441SEvalZero 
dfs_romfs_read(struct dfs_fd * file,void * buf,size_t count)131*10465441SEvalZero int dfs_romfs_read(struct dfs_fd *file, void *buf, size_t count)
132*10465441SEvalZero {
133*10465441SEvalZero     rt_size_t length;
134*10465441SEvalZero     struct romfs_dirent *dirent;
135*10465441SEvalZero 
136*10465441SEvalZero     dirent = (struct romfs_dirent *)file->data;
137*10465441SEvalZero     RT_ASSERT(dirent != NULL);
138*10465441SEvalZero 
139*10465441SEvalZero     if (check_dirent(dirent) != 0)
140*10465441SEvalZero     {
141*10465441SEvalZero         return -EIO;
142*10465441SEvalZero     }
143*10465441SEvalZero 
144*10465441SEvalZero     if (count < file->size - file->pos)
145*10465441SEvalZero         length = count;
146*10465441SEvalZero     else
147*10465441SEvalZero         length = file->size - file->pos;
148*10465441SEvalZero 
149*10465441SEvalZero     if (length > 0)
150*10465441SEvalZero         memcpy(buf, &(dirent->data[file->pos]), length);
151*10465441SEvalZero 
152*10465441SEvalZero     /* update file current position */
153*10465441SEvalZero     file->pos += length;
154*10465441SEvalZero 
155*10465441SEvalZero     return length;
156*10465441SEvalZero }
157*10465441SEvalZero 
dfs_romfs_lseek(struct dfs_fd * file,off_t offset)158*10465441SEvalZero int dfs_romfs_lseek(struct dfs_fd *file, off_t offset)
159*10465441SEvalZero {
160*10465441SEvalZero     if (offset <= file->size)
161*10465441SEvalZero     {
162*10465441SEvalZero         file->pos = offset;
163*10465441SEvalZero         return file->pos;
164*10465441SEvalZero     }
165*10465441SEvalZero 
166*10465441SEvalZero     return -EIO;
167*10465441SEvalZero }
168*10465441SEvalZero 
dfs_romfs_close(struct dfs_fd * file)169*10465441SEvalZero int dfs_romfs_close(struct dfs_fd *file)
170*10465441SEvalZero {
171*10465441SEvalZero     file->data = NULL;
172*10465441SEvalZero     return RT_EOK;
173*10465441SEvalZero }
174*10465441SEvalZero 
dfs_romfs_open(struct dfs_fd * file)175*10465441SEvalZero int dfs_romfs_open(struct dfs_fd *file)
176*10465441SEvalZero {
177*10465441SEvalZero     rt_size_t size;
178*10465441SEvalZero     struct romfs_dirent *dirent;
179*10465441SEvalZero     struct romfs_dirent *root_dirent;
180*10465441SEvalZero     struct dfs_filesystem *fs;
181*10465441SEvalZero 
182*10465441SEvalZero     fs = (struct dfs_filesystem *)file->data;
183*10465441SEvalZero     root_dirent = (struct romfs_dirent *)fs->data;
184*10465441SEvalZero 
185*10465441SEvalZero     if (check_dirent(root_dirent) != 0)
186*10465441SEvalZero         return -EIO;
187*10465441SEvalZero 
188*10465441SEvalZero     if (file->flags & (O_CREAT | O_WRONLY | O_APPEND | O_TRUNC | O_RDWR))
189*10465441SEvalZero         return -EINVAL;
190*10465441SEvalZero 
191*10465441SEvalZero     dirent = dfs_romfs_lookup(root_dirent, file->path, &size);
192*10465441SEvalZero     if (dirent == NULL)
193*10465441SEvalZero         return -ENOENT;
194*10465441SEvalZero 
195*10465441SEvalZero     /* entry is a directory file type */
196*10465441SEvalZero     if (dirent->type == ROMFS_DIRENT_DIR)
197*10465441SEvalZero     {
198*10465441SEvalZero         if (!(file->flags & O_DIRECTORY))
199*10465441SEvalZero             return -ENOENT;
200*10465441SEvalZero     }
201*10465441SEvalZero     else
202*10465441SEvalZero     {
203*10465441SEvalZero         /* entry is a file, but open it as a directory */
204*10465441SEvalZero         if (file->flags & O_DIRECTORY)
205*10465441SEvalZero             return -ENOENT;
206*10465441SEvalZero     }
207*10465441SEvalZero 
208*10465441SEvalZero     file->data = dirent;
209*10465441SEvalZero     file->size = size;
210*10465441SEvalZero     file->pos = 0;
211*10465441SEvalZero 
212*10465441SEvalZero     return RT_EOK;
213*10465441SEvalZero }
214*10465441SEvalZero 
dfs_romfs_stat(struct dfs_filesystem * fs,const char * path,struct stat * st)215*10465441SEvalZero int dfs_romfs_stat(struct dfs_filesystem *fs, const char *path, struct stat *st)
216*10465441SEvalZero {
217*10465441SEvalZero     rt_size_t size;
218*10465441SEvalZero     struct romfs_dirent *dirent;
219*10465441SEvalZero     struct romfs_dirent *root_dirent;
220*10465441SEvalZero 
221*10465441SEvalZero     root_dirent = (struct romfs_dirent *)fs->data;
222*10465441SEvalZero     dirent = dfs_romfs_lookup(root_dirent, path, &size);
223*10465441SEvalZero 
224*10465441SEvalZero     if (dirent == NULL)
225*10465441SEvalZero         return -ENOENT;
226*10465441SEvalZero 
227*10465441SEvalZero     st->st_dev = 0;
228*10465441SEvalZero     st->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH |
229*10465441SEvalZero     S_IWUSR | S_IWGRP | S_IWOTH;
230*10465441SEvalZero 
231*10465441SEvalZero     if (dirent->type == ROMFS_DIRENT_DIR)
232*10465441SEvalZero     {
233*10465441SEvalZero         st->st_mode &= ~S_IFREG;
234*10465441SEvalZero         st->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
235*10465441SEvalZero     }
236*10465441SEvalZero 
237*10465441SEvalZero     st->st_size = dirent->size;
238*10465441SEvalZero     st->st_mtime = 0;
239*10465441SEvalZero 
240*10465441SEvalZero     return RT_EOK;
241*10465441SEvalZero }
242*10465441SEvalZero 
dfs_romfs_getdents(struct dfs_fd * file,struct dirent * dirp,uint32_t count)243*10465441SEvalZero int dfs_romfs_getdents(struct dfs_fd *file, struct dirent *dirp, uint32_t count)
244*10465441SEvalZero {
245*10465441SEvalZero     rt_size_t index;
246*10465441SEvalZero     const char *name;
247*10465441SEvalZero     struct dirent *d;
248*10465441SEvalZero     struct romfs_dirent *dirent, *sub_dirent;
249*10465441SEvalZero 
250*10465441SEvalZero     dirent = (struct romfs_dirent *)file->data;
251*10465441SEvalZero     if (check_dirent(dirent) != 0)
252*10465441SEvalZero         return -EIO;
253*10465441SEvalZero     RT_ASSERT(dirent->type == ROMFS_DIRENT_DIR);
254*10465441SEvalZero 
255*10465441SEvalZero     /* enter directory */
256*10465441SEvalZero     dirent = (struct romfs_dirent *)dirent->data;
257*10465441SEvalZero 
258*10465441SEvalZero     /* make integer count */
259*10465441SEvalZero     count = (count / sizeof(struct dirent));
260*10465441SEvalZero     if (count == 0)
261*10465441SEvalZero         return -EINVAL;
262*10465441SEvalZero 
263*10465441SEvalZero     index = 0;
264*10465441SEvalZero     for (index = 0; index < count && file->pos < file->size; index ++)
265*10465441SEvalZero     {
266*10465441SEvalZero         d = dirp + index;
267*10465441SEvalZero 
268*10465441SEvalZero         sub_dirent = &dirent[file->pos];
269*10465441SEvalZero         name = sub_dirent->name;
270*10465441SEvalZero 
271*10465441SEvalZero         /* fill dirent */
272*10465441SEvalZero         if (sub_dirent->type == ROMFS_DIRENT_DIR)
273*10465441SEvalZero             d->d_type = DT_DIR;
274*10465441SEvalZero         else
275*10465441SEvalZero             d->d_type = DT_REG;
276*10465441SEvalZero 
277*10465441SEvalZero         d->d_namlen = rt_strlen(name);
278*10465441SEvalZero         d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
279*10465441SEvalZero         rt_strncpy(d->d_name, name, rt_strlen(name) + 1);
280*10465441SEvalZero 
281*10465441SEvalZero         /* move to next position */
282*10465441SEvalZero         ++ file->pos;
283*10465441SEvalZero     }
284*10465441SEvalZero 
285*10465441SEvalZero     return index * sizeof(struct dirent);
286*10465441SEvalZero }
287*10465441SEvalZero 
288*10465441SEvalZero static const struct dfs_file_ops _rom_fops =
289*10465441SEvalZero {
290*10465441SEvalZero     dfs_romfs_open,
291*10465441SEvalZero     dfs_romfs_close,
292*10465441SEvalZero     dfs_romfs_ioctl,
293*10465441SEvalZero     dfs_romfs_read,
294*10465441SEvalZero     NULL,
295*10465441SEvalZero     NULL,
296*10465441SEvalZero     dfs_romfs_lseek,
297*10465441SEvalZero     dfs_romfs_getdents,
298*10465441SEvalZero };
299*10465441SEvalZero static const struct dfs_filesystem_ops _romfs =
300*10465441SEvalZero {
301*10465441SEvalZero     "rom",
302*10465441SEvalZero     DFS_FS_FLAG_DEFAULT,
303*10465441SEvalZero     &_rom_fops,
304*10465441SEvalZero 
305*10465441SEvalZero     dfs_romfs_mount,
306*10465441SEvalZero     dfs_romfs_unmount,
307*10465441SEvalZero     NULL,
308*10465441SEvalZero     NULL,
309*10465441SEvalZero 
310*10465441SEvalZero     NULL,
311*10465441SEvalZero     dfs_romfs_stat,
312*10465441SEvalZero     NULL,
313*10465441SEvalZero };
314*10465441SEvalZero 
dfs_romfs_init(void)315*10465441SEvalZero int dfs_romfs_init(void)
316*10465441SEvalZero {
317*10465441SEvalZero     /* register rom file system */
318*10465441SEvalZero     dfs_register(&_romfs);
319*10465441SEvalZero     return 0;
320*10465441SEvalZero }
321*10465441SEvalZero INIT_COMPONENT_EXPORT(dfs_romfs_init);
322*10465441SEvalZero 
323