• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 National Institute of Advanced Industrial Science
3  *                    and Technology (AIST)
4  *
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * Redistributions of source code must retain the above copyright notice, this
11  * list of conditions and the following disclaimer.
12  *
13  * Redistributions in binary form must reproduce the above copyright notice,
14  * this list of conditions and the following disclaimer in the documentation
15  * and/or other materials provided with the distribution.
16  *
17  * Neither the name of AIST nor the names of its contributors may be used
18  * to endorse or promote products derived from this software without specific
19  * prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include <libwebsockets.h>
35 #include <string.h>
36 #include <stdint.h>
37 #include <stdio.h>
38 #include "romfs.h"
39 #if defined(LWS_WITH_ESP32)
40 #include "esp_spi_flash.h"
41 #endif
42 
43 #define RFS_STRING_MAX 96
44 
45 static u32_be_t cache[(RFS_STRING_MAX + 32) / 4];
46 static romfs_inode_t ci = (romfs_inode_t)cache;
47 static romfs_t cr = (romfs_t)cache;
48 
49 static void
set_cache(romfs_inode_t inode,size_t len)50 set_cache(romfs_inode_t inode, size_t len)
51 {
52 #if defined(LWS_WITH_ESP32)
53 	spi_flash_read((uint32_t)inode, cache, len);
54 #endif
55 }
56 
57 static uint32_t
untohl(const u32_be_t be)58 untohl(const u32_be_t be)
59 {
60 	return ((be >> 24) & 0xff) |
61 	       ((be >> 16) & 0xff) << 8 |
62 	       ((be >> 8) & 0xff) << 16 |
63 	       (be & 0xff) << 24;
64 }
65 static romfs_inode_t
66 romfs_lookup(romfs_t romfs, romfs_inode_t start, const char *path);
67 
68 static int
plus_padding(const uint8_t * s)69 plus_padding(const uint8_t *s)
70 {
71 	int n;
72 
73 	set_cache((romfs_inode_t)s, RFS_STRING_MAX);
74 	n = strlen((const char *)cache);
75 
76 	if (!(n & 15))
77 		n += 0x10;
78 
79 	return (n + 15) & ~15;
80 }
81 
82 static romfs_inode_t
skip_and_pad(romfs_inode_t ri)83 skip_and_pad(romfs_inode_t ri)
84 {
85 	const uint8_t *p = ((const uint8_t *)ri) + sizeof(*ri);
86 
87 	return (romfs_inode_t)(p + plus_padding(p));
88 }
89 
90 size_t
romfs_mount_check(romfs_t romfs)91 romfs_mount_check(romfs_t romfs)
92 {
93 	set_cache((romfs_inode_t)romfs, sizeof(*romfs));
94 
95 	if (cr->magic1 != 0x6d6f722d ||
96 	    cr->magic2 != 0x2d736631)
97 		return 0;
98 
99 	return untohl(cr->size);
100 }
101 
102 static romfs_inode_t
romfs_symlink(romfs_t romfs,romfs_inode_t level,romfs_inode_t i)103 romfs_symlink(romfs_t romfs, romfs_inode_t level, romfs_inode_t i)
104 {
105 	const char *p = (const char *)skip_and_pad(i);
106 
107 	if (*p == '/') {
108 		level = skip_and_pad((romfs_inode_t)romfs);
109 		p++;
110 	}
111 
112 	return romfs_lookup(romfs, level, p);
113 }
114 
115 static romfs_inode_t
dir_link(romfs_t romfs,romfs_inode_t i)116 dir_link(romfs_t romfs, romfs_inode_t i)
117 {
118 	set_cache(i, sizeof(*i));
119 	return (romfs_inode_t)((const uint8_t *)romfs +
120 						untohl(ci->dir_start));
121 }
122 
123 static romfs_inode_t
romfs_lookup(romfs_t romfs,romfs_inode_t start,const char * path)124 romfs_lookup(romfs_t romfs, romfs_inode_t start, const char *path)
125 {
126 	romfs_inode_t level, i = start, i_in;
127 	const char *p, *cp;
128 	uint32_t next_be;
129 
130 	if (start == (romfs_inode_t)romfs)
131 		i = skip_and_pad((romfs_inode_t)romfs);
132 	level = i;
133 	while (i != (romfs_inode_t)romfs) {
134 		const char *n = ((const char *)i) + sizeof(*i);
135 
136 		p = path;
137 		i_in = i;
138 
139 		set_cache(i, sizeof(*i));
140 		next_be = ci->next;
141 
142 		cp = (const char *)cache;
143 		set_cache((romfs_inode_t)n, RFS_STRING_MAX);
144 
145 		while (*p && *p != '/' && *cp && *p == *cp &&
146 		       (p - path) < RFS_STRING_MAX) {
147 			p++;
148 			n++;
149 			cp++;
150 		}
151 
152 		while (*p == '/' && p[1] == '/')
153 			p++;
154 
155 		if (!*cp && (!*p || *p == '/') &&
156 		    (untohl(next_be) & 7) == RFST_HARDLINK) {
157 			set_cache(i, sizeof(*i));
158 			return (romfs_inode_t)
159 			       ((const uint8_t *)romfs +
160 			        (untohl(ci->dir_start) & ~15));
161 		}
162 
163 		if (!*p && !*cp) {
164 			set_cache(i, sizeof(*i));
165 			if ((untohl(ci->next) & 7) == RFST_SYMLINK) {
166 				i = romfs_symlink(romfs, level, i);
167 				continue;
168 			}
169 			return i;
170 		}
171 
172 		if (!*p && *cp == '/')
173 			return NULL;
174 
175 		while (*p == '/' && p[1] == '/')
176 			p++;
177 
178 		if (*p == '/' && !*cp) {
179 			set_cache(i, sizeof(*i));
180 			switch (untohl(ci->next) & 7) {
181 			case RFST_SYMLINK:
182 				i = romfs_symlink(romfs, level, i);
183 				if (!i)
184 					return NULL;
185 				i = dir_link(romfs, i);
186 				while (*path != '/' && *path)
187 					path++;
188 				if (!*path)
189 					return NULL;
190 				path++;
191 				continue;
192 			case RFST_DIR:
193 				path = p + 1;
194 				i = dir_link(romfs, i);
195 				break;
196 			default:
197 				path = p + 1;
198 				i = skip_and_pad(i);
199 				break;
200 			}
201 			level = i;
202 			continue;
203 		}
204 
205 		set_cache(i, sizeof(*i));
206 		if (!(untohl(ci->next) & ~15))
207 			return NULL;
208 
209 		i = (romfs_inode_t)((const uint8_t *)romfs +
210 				    (untohl(ci->next) & ~15));
211 		if (i == i_in)
212 			return NULL;
213 	}
214 
215 	return NULL;
216 }
217 
218 const void *
romfs_get_info(romfs_t romfs,const char * path,size_t * len,size_t * csum)219 romfs_get_info(romfs_t romfs, const char *path, size_t *len, size_t *csum)
220 {
221 	romfs_inode_t i;
222 
223 	if (*path == '/')
224 		path++;
225 
226 	i = romfs_lookup(romfs, (romfs_inode_t)romfs, path);
227 
228 	if (!i)
229 		return NULL;
230 
231 	set_cache(i, sizeof(*i));
232 	*len = untohl(ci->size);
233 	if (csum)
234 		*csum = untohl(ci->checksum);
235 
236 	return (void *)skip_and_pad(i);
237 }
238