xref: /netbsd-src/sys/fs/filecorefs/filecore_utils.c (revision bfb6cb13d599546df69c7e4d20d70e22e15a549d)
1 /*	$NetBSD: filecore_utils.c,v 1.7 2006/05/15 01:29:02 christos 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.7 2006/05/15 01:29:02 christos 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 occurence
150  * (probably impossible, actually) for a valid filecore boot block,
151  * so we treat such blocks as invalid.
152  */
153 int
154 filecore_bbchecksum(bb)
155 	void *bb;
156 {
157 	u_char *bootblock = bb;
158 	u_char byte0, accum_diff;
159 	u_int sum;
160 	int i;
161 
162 	sum = 0;
163 	accum_diff = 0;
164 	byte0 = bootblock[0];
165 
166 	/*
167 	 * Sum the contents of the block, keeping track of whether
168 	 * or not all bytes are the same.  If 'accum_diff' ends up
169 	 * being zero, all of the bytes are, in fact, the same.
170 	 */
171 	for (i = 0; i < 511; ++i) {
172 		sum += bootblock[i];
173 		accum_diff |= bootblock[i] ^ byte0;
174 	}
175 
176 	/*
177 	 * Check to see if the checksum byte is the same as the
178 	 * rest of the bytes, too.  (Note that if all of the bytes
179 	 * are the same except the checksum, a checksum compare
180 	 * won't succeed, but that's not our problem.)
181 	 */
182 	accum_diff |= bootblock[i] ^ byte0;
183 	sum = (sum - ((sum - 1) / 255) * 255);
184 
185 	/*
186 	 * If all bytes in block are the same
187 	 * or the checksum does not match ; call it invalid.
188 	 */
189 	if (accum_diff == 0 || sum != bootblock[511])
190 		return -1;
191 	return 0;
192 }
193 
194 mode_t
195 filecore_mode(ip)
196 	struct filecore_node *ip;
197 {
198 	mode_t m = 0;
199 	int rf = 0;
200 
201 	if ((ip->i_dirent.attr & FILECORE_ATTR_READ) ||
202 	    (ip->i_mnt->fc_mntflags & FILECOREMNT_OWNREAD) ||
203 	    (ip->i_dirent.attr & FILECORE_ATTR_DIR))
204 		rf = 1;
205 	if (ip->i_mnt->fc_mntflags & FILECOREMNT_ALLACCESS) {
206 		m |= S_IRUSR | S_IXUSR;
207 		if (rf || (ip->i_dirent.attr & FILECORE_ATTR_OREAD))
208 			m |= S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
209 	} else if (ip->i_mnt->fc_mntflags & FILECOREMNT_OWNACCESS) {
210 		if (rf) m |= S_IRUSR | S_IXUSR;
211 		if (ip->i_dirent.attr & FILECORE_ATTR_OREAD)
212 			m |= S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
213 	} else {
214 		m |= S_IRUSR | S_IXUSR;
215 		if (rf) m |= S_IRGRP | S_IXGRP;
216 		if (ip->i_dirent.attr & FILECORE_ATTR_OREAD)
217 			m |= S_IROTH | S_IXOTH;
218 	}
219 	if (ip->i_dirent.attr & FILECORE_ATTR_DIR) {
220 		m |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
221 	} else
222 		m |= S_IFREG;
223 	return m;
224 }
225 
226 struct timespec
227 filecore_time(ip)
228 	struct filecore_node *ip;
229 {
230 	struct timespec ts;
231 	u_int64_t cs;
232 
233 	cs = (((u_int64_t)(ip->i_dirent.load & 0xFF)) << 32)
234 	    + ip->i_dirent.exec - ((u_int64_t)1725772500 << 7);
235 	ts.tv_sec = cs / 100;
236 	ts.tv_nsec = (cs % 100) * 10000000;
237 	return ts;
238 }
239 
240 ino_t
241 filecore_getparent(ip)
242 	struct filecore_node *ip;
243 {
244 	struct buf *pbp;
245 	u_int32_t addr;
246 	u_int32_t paddr;
247 	int error = 0;
248 	int i = 0;
249 
250 #ifdef FILECORE_DEBUG
251 	printf("filecore_getparent(ino=%x)\n", ip->i_number);
252 #endif
253 	if (ip->i_parent != -2) {
254 		return ip->i_parent;
255 	}
256 	if (ip->i_number == FILECORE_ROOTINO) {
257 		ip->i_parent = ip->i_number;
258 		return ip->i_number;
259 	}
260 	addr = ip->i_number & FILECORE_INO_MASK;
261 	/* Read directory data for parent dir to find its parent */
262 #ifdef FILECORE_DEBUG
263 	printf("filecore_getparent() read parent dir contents\n");
264 #endif
265 	error = filecore_bread(ip->i_mnt, addr, FILECORE_DIR_SIZE,
266 	    NOCRED, &pbp);
267 	if (error) {
268 		brelse(pbp);
269 		return error;
270 	}
271 	paddr = fcdirtail(pbp->b_data)->parent1
272 	    | fcdirtail(pbp->b_data)->parent2 << 16;
273 #ifdef FILECORE_DEBUG_BR
274 	printf("brelse(%p) ut1\n", pbp);
275 #endif
276 	brelse(pbp);
277 
278 	/* If parent's parent is the parent then parent is root dir */
279 	if (paddr == addr) {
280 		ip->i_parent = FILECORE_ROOTINO;
281 		return FILECORE_ROOTINO;
282 	}
283 
284 #ifdef FILECORE_DEBUG
285 	printf("filecore_getparent() read grand-parent dir contents\n");
286 #endif
287 	error = filecore_bread(ip->i_mnt, paddr, FILECORE_DIR_SIZE,
288 	    NOCRED, &pbp);
289 	if (error) {
290 		brelse(pbp);
291 		return error;
292 	}
293 	while (fcdirentry(pbp->b_data,i)->addr != addr) {
294 		if (fcdirentry(pbp->b_data, i++)->name[0] == 0) {
295 #ifdef FILECORE_DEBUG_BR
296 			printf("brelse(%p) ut2\n", pbp);
297 #endif
298 			brelse(pbp);
299 			return FILECORE_ROOTINO;
300 		}
301 	}
302 #ifdef FILECORE_DEBUG_BR
303 	printf("brelse(%p) ut3\n", pbp);
304 #endif
305 	brelse(pbp);
306 	ip->i_parent = paddr + (i << FILECORE_INO_INDEX);
307 	return (paddr + (i << FILECORE_INO_INDEX));
308 }
309 
310 int
311 filecore_fn2unix(fcfn, ufn, len)
312 	char *fcfn;
313 	char *ufn;
314 	u_int16_t *len;
315 {
316 	int i = 0;
317 
318 	if (*fcfn == 0)
319 		return (-1);
320 	while (i++ < 10 && *fcfn >= ' ') {
321 		if (*fcfn == '/')
322 			*ufn++ = '.';
323 		else
324 			*ufn++ = *fcfn;
325 		fcfn++;
326 	}
327 #ifdef notdef
328 	if (ip->i_mnt->fc_mntflags & FILECOREMNT_FILETYPE) {
329 		*ufn++ = ',';
330 		*ufn++ = hexdigits[(ip->i_dirent.load >> 10) & 15];
331 		*ufn++ = hexdigits[(ip->i_dirent.load >> 9) & 15];
332 		*ufn++ = hexdigits[(ip->i_dirent.load >> 8) & 15];
333 	}
334 #endif
335 	*ufn = 0;
336 	*len = i - 1;
337 	return 0;
338 }
339 
340 int
341 filecore_fncmp(fcfn, ufn, len)
342 	const char *fcfn;
343 	const char *ufn;
344 	u_short len;
345 {
346 	char f, u;
347 	int i = 0;
348 
349 	if (*fcfn == 0 || len > 10)
350 		return -1;
351 	while (i++ < len) {
352 		if (*fcfn < ' ')
353 			return 1;
354 		f = *fcfn++;
355 		u = *ufn++;
356 		if (u == '.')
357 			u = '/';
358 		if (u >= 'a' && u <= 'z') u -= 'a' - 'A';
359 		if (f >= 'a' && f <= 'z') f -= 'a' - 'A';
360 		if (f < u)
361 			return 1;
362 		else if (f > u)
363 			return -1;
364 	}
365 	if (len == 10 || *fcfn < ' ')
366 		return 0;
367 	return -1;
368 }
369