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