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