1 /* $NetBSD: filecore_utils.c,v 1.12 2020/09/29 02:58:52 msaitoh Exp $ */
2
3 /*-
4 * Copyright (c) 1994 The Regents of the University of California.
5 * All rights reserved.
6 *
7 * This code includes code derived from software contributed to the
8 * NetBSD project by Mark Brinicombe.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * filecore_utils.c 1.1 1998/6/26
35 */
36
37 /*-
38 * Copyright (c) 1998 Andrew McMurry
39 *
40 * This code includes code derived from software contributed to the
41 * NetBSD project by Mark Brinicombe.
42 *
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
45 * are met:
46 * 1. Redistributions of source code must retain the above copyright
47 * notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in the
50 * documentation and/or other materials provided with the distribution.
51 * 3. All advertising materials mentioning features or use of this software
52 * must display the following acknowledgement:
53 * This product includes software developed by the University of
54 * California, Berkeley and its contributors.
55 * 4. Neither the name of the University nor the names of its contributors
56 * may be used to endorse or promote products derived from this software
57 * without specific prior written permission.
58 *
59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69 * SUCH DAMAGE.
70 *
71 * filecore_utils.c 1.1 1998/6/26
72 */
73
74 /*
75 * Copyright (c) 1998 Christopher G. Demetriou. All rights reserved.
76 *
77 * Redistribution and use in source and binary forms, with or without
78 * modification, are permitted provided that the following conditions
79 * are met:
80 * 1. Redistributions of source code must retain the above copyright
81 * notice, this list of conditions and the following disclaimer.
82 * 2. Redistributions in binary form must reproduce the above copyright
83 * notice, this list of conditions and the following disclaimer in the
84 * documentation and/or other materials provided with the distribution.
85 * 3. All advertising materials mentioning features or use of this software
86 * must display the following acknowledgement:
87 * This product includes software developed by Christopher G. Demetriou
88 * for the NetBSD Project.
89 * 4. The name of the author may not be used to endorse or promote products
90 * derived from this software without specific prior written permission
91 *
92 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
93 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
94 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
95 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
96 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
97 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
98 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
99 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
100 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
101 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
102 */
103
104 #include <sys/cdefs.h>
105 __KERNEL_RCSID(0, "$NetBSD: filecore_utils.c,v 1.12 2020/09/29 02:58:52 msaitoh Exp $");
106
107 #include <sys/param.h>
108 #include <sys/systm.h>
109 #include <sys/stat.h>
110 #include <sys/buf.h>
111 #include <sys/mount.h>
112 #include <sys/vnode.h>
113 #include <sys/dirent.h>
114 #include <sys/kauth.h>
115
116 #include <fs/filecorefs/filecore.h>
117 #include <fs/filecorefs/filecore_extern.h>
118 #include <fs/filecorefs/filecore_node.h>
119 #include <fs/filecorefs/filecore_mount.h>
120
121 /*
122 * int filecore_bbchecksum(u_char *bootblock)
123 *
124 * Calculates the filecore boot block checksum. This is used to validate
125 * a filecore boot block on the disk. If a boot block is validated then
126 * it is used to locate the partition table. If the boot block is not
127 * validated, it is assumed that the whole disk is NetBSD.
128 *
129 * The basic algorithm is:
130 *
131 * for (each byte in block, excluding checksum) {
132 * sum += byte;
133 * if (sum > 255)
134 * sum -= 255;
135 * }
136 *
137 * That's equivalent to summing all of the bytes in the block
138 * (excluding the checksum byte, of course), then calculating the
139 * checksum as "cksum = sum - ((sum - 1) / 255) * 255)". That
140 * expression may or may not yield a faster checksum function,
141 * but it's easier to reason about.
142 *
143 * Note that if you have a block filled with bytes of a single
144 * value "X" (regardless of that value!) and calculate the cksum
145 * of the block (excluding the checksum byte), you will _always_
146 * end up with a checksum of X. (Do the math; that can be derived
147 * from the checksum calculation function!) That means that
148 * blocks which contain bytes which all have the same value will
149 * always checksum properly. That's a _very_ unlikely occurrence
150 * (probably impossible, actually) for a valid filecore boot block,
151 * so we treat such blocks as invalid.
152 */
153 int
filecore_bbchecksum(void * bb)154 filecore_bbchecksum(void *bb)
155 {
156 u_char *bootblock = bb;
157 u_char byte0, accum_diff;
158 u_int sum;
159 int i;
160
161 sum = 0;
162 accum_diff = 0;
163 byte0 = bootblock[0];
164
165 /*
166 * Sum the contents of the block, keeping track of whether
167 * or not all bytes are the same. If 'accum_diff' ends up
168 * being zero, all of the bytes are, in fact, the same.
169 */
170 for (i = 0; i < 511; ++i) {
171 sum += bootblock[i];
172 accum_diff |= bootblock[i] ^ byte0;
173 }
174
175 /*
176 * Check to see if the checksum byte is the same as the
177 * rest of the bytes, too. (Note that if all of the bytes
178 * are the same except the checksum, a checksum compare
179 * won't succeed, but that's not our problem.)
180 */
181 accum_diff |= bootblock[i] ^ byte0;
182 sum = (sum - ((sum - 1) / 255) * 255);
183
184 /*
185 * If all bytes in block are the same
186 * or the checksum does not match ; call it invalid.
187 */
188 if (accum_diff == 0 || sum != bootblock[511])
189 return -1;
190 return 0;
191 }
192
193 mode_t
filecore_mode(struct filecore_node * ip)194 filecore_mode(struct filecore_node *ip)
195 {
196 mode_t m = 0;
197 int rf = 0;
198
199 if ((ip->i_dirent.attr & FILECORE_ATTR_READ) ||
200 (ip->i_mnt->fc_mntflags & FILECOREMNT_OWNREAD) ||
201 (ip->i_dirent.attr & FILECORE_ATTR_DIR))
202 rf = 1;
203 if (ip->i_mnt->fc_mntflags & FILECOREMNT_ALLACCESS) {
204 m |= S_IRUSR | S_IXUSR;
205 if (rf || (ip->i_dirent.attr & FILECORE_ATTR_OREAD))
206 m |= S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
207 } else if (ip->i_mnt->fc_mntflags & FILECOREMNT_OWNACCESS) {
208 if (rf) m |= S_IRUSR | S_IXUSR;
209 if (ip->i_dirent.attr & FILECORE_ATTR_OREAD)
210 m |= S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
211 } else {
212 m |= S_IRUSR | S_IXUSR;
213 if (rf) m |= S_IRGRP | S_IXGRP;
214 if (ip->i_dirent.attr & FILECORE_ATTR_OREAD)
215 m |= S_IROTH | S_IXOTH;
216 }
217 if (ip->i_dirent.attr & FILECORE_ATTR_DIR) {
218 m |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
219 } else
220 m |= S_IFREG;
221 return m;
222 }
223
224 struct timespec
filecore_time(struct filecore_node * ip)225 filecore_time(struct filecore_node *ip)
226 {
227 struct timespec ts;
228 u_int64_t cs;
229
230 cs = (((u_int64_t)(ip->i_dirent.load & 0xFF)) << 32)
231 + ip->i_dirent.exec - ((u_int64_t)1725772500 << 7);
232 ts.tv_sec = cs / 100;
233 ts.tv_nsec = (cs % 100) * 10000000;
234 return ts;
235 }
236
237 ino_t
filecore_getparent(struct filecore_node * ip)238 filecore_getparent(struct filecore_node *ip)
239 {
240 struct buf *pbp;
241 u_int32_t addr;
242 u_int32_t paddr;
243 int error = 0;
244 int i = 0;
245
246 #ifdef FILECORE_DEBUG
247 printf("filecore_getparent(ino=%llx)\n", (long long)ip->i_number);
248 #endif
249 if (ip->i_parent != -2) {
250 return ip->i_parent;
251 }
252 if (ip->i_number == FILECORE_ROOTINO) {
253 ip->i_parent = ip->i_number;
254 return ip->i_number;
255 }
256 addr = ip->i_number & FILECORE_INO_MASK;
257 /* Read directory data for parent dir to find its parent */
258 #ifdef FILECORE_DEBUG
259 printf("filecore_getparent() read parent dir contents\n");
260 #endif
261 error = filecore_bread(ip->i_mnt, addr, FILECORE_DIR_SIZE,
262 NOCRED, &pbp);
263 if (error) {
264 return error;
265 }
266 paddr = fcdirtail(pbp->b_data)->parent1
267 | fcdirtail(pbp->b_data)->parent2 << 16;
268 #ifdef FILECORE_DEBUG_BR
269 printf("brelse(%p) ut1\n", pbp);
270 #endif
271 brelse(pbp, 0);
272
273 /* If parent's parent is the parent then parent is root dir */
274 if (paddr == addr) {
275 ip->i_parent = FILECORE_ROOTINO;
276 return FILECORE_ROOTINO;
277 }
278
279 #ifdef FILECORE_DEBUG
280 printf("filecore_getparent() read grand-parent dir contents\n");
281 #endif
282 error = filecore_bread(ip->i_mnt, paddr, FILECORE_DIR_SIZE,
283 NOCRED, &pbp);
284 if (error) {
285 return error;
286 }
287 while (fcdirentry(pbp->b_data,i)->addr != addr) {
288 if (fcdirentry(pbp->b_data, i++)->name[0] == 0) {
289 #ifdef FILECORE_DEBUG_BR
290 printf("brelse(%p) ut2\n", pbp);
291 #endif
292 brelse(pbp, 0);
293 return FILECORE_ROOTINO;
294 }
295 }
296 #ifdef FILECORE_DEBUG_BR
297 printf("brelse(%p) ut3\n", pbp);
298 #endif
299 brelse(pbp, 0);
300 ip->i_parent = paddr + (i << FILECORE_INO_INDEX);
301 return (paddr + (i << FILECORE_INO_INDEX));
302 }
303
304 int
filecore_fn2unix(char * fcfn,char * ufn,u_int16_t * len)305 filecore_fn2unix(char *fcfn, char *ufn, u_int16_t *len)
306 {
307 int i = 0;
308
309 if (*fcfn == 0)
310 return (-1);
311 while (i++ < 10 && *fcfn >= ' ') {
312 if (*fcfn == '/')
313 *ufn++ = '.';
314 else
315 *ufn++ = *fcfn;
316 fcfn++;
317 }
318 #ifdef notdef
319 if (ip->i_mnt->fc_mntflags & FILECOREMNT_FILETYPE) {
320 *ufn++ = ',';
321 *ufn++ = hexdigits[(ip->i_dirent.load >> 10) & 15];
322 *ufn++ = hexdigits[(ip->i_dirent.load >> 9) & 15];
323 *ufn++ = hexdigits[(ip->i_dirent.load >> 8) & 15];
324 }
325 #endif
326 *ufn = 0;
327 *len = i - 1;
328 return 0;
329 }
330
331 int
filecore_fncmp(const char * fcfn,const char * ufn,u_short len)332 filecore_fncmp(const char *fcfn, const char *ufn, u_short len)
333 {
334 char f, u;
335 int i = 0;
336
337 if (*fcfn == 0 || len > 10)
338 return -1;
339 while (i++ < len) {
340 if (*fcfn < ' ')
341 return 1;
342 f = *fcfn++;
343 u = *ufn++;
344 if (u == '.')
345 u = '/';
346 if (u >= 'a' && u <= 'z') u -= 'a' - 'A';
347 if (f >= 'a' && f <= 'z') f -= 'a' - 'A';
348 if (f < u)
349 return 1;
350 else if (f > u)
351 return -1;
352 }
353 if (len == 10 || *fcfn < ' ')
354 return 0;
355 return -1;
356 }
357