Home | History | Annotate | Line # | Download | only in filecorefs
      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
    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
    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
    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
    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
    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
    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