1*57920690Smsaitoh /* $NetBSD: filecore_utils.c,v 1.12 2020/09/29 02:58:52 msaitoh Exp $ */
2aad01611Sagc
3aad01611Sagc /*-
4aad01611Sagc * Copyright (c) 1994 The Regents of the University of California.
5aad01611Sagc * All rights reserved.
6aad01611Sagc *
7aad01611Sagc * This code includes code derived from software contributed to the
8aad01611Sagc * NetBSD project by Mark Brinicombe.
9aad01611Sagc *
10aad01611Sagc * Redistribution and use in source and binary forms, with or without
11aad01611Sagc * modification, are permitted provided that the following conditions
12aad01611Sagc * are met:
13aad01611Sagc * 1. Redistributions of source code must retain the above copyright
14aad01611Sagc * notice, this list of conditions and the following disclaimer.
15aad01611Sagc * 2. Redistributions in binary form must reproduce the above copyright
16aad01611Sagc * notice, this list of conditions and the following disclaimer in the
17aad01611Sagc * documentation and/or other materials provided with the distribution.
18aad01611Sagc * 3. Neither the name of the University nor the names of its contributors
19aad01611Sagc * may be used to endorse or promote products derived from this software
20aad01611Sagc * without specific prior written permission.
21aad01611Sagc *
22aad01611Sagc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23aad01611Sagc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24aad01611Sagc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25aad01611Sagc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26aad01611Sagc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27aad01611Sagc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28aad01611Sagc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29aad01611Sagc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30aad01611Sagc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31aad01611Sagc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32aad01611Sagc * SUCH DAMAGE.
33aad01611Sagc *
34aad01611Sagc * filecore_utils.c 1.1 1998/6/26
35aad01611Sagc */
365356de15Sjdolecek
375356de15Sjdolecek /*-
385356de15Sjdolecek * Copyright (c) 1998 Andrew McMurry
395356de15Sjdolecek *
405356de15Sjdolecek * This code includes code derived from software contributed to the
415356de15Sjdolecek * NetBSD project by Mark Brinicombe.
425356de15Sjdolecek *
435356de15Sjdolecek * Redistribution and use in source and binary forms, with or without
445356de15Sjdolecek * modification, are permitted provided that the following conditions
455356de15Sjdolecek * are met:
465356de15Sjdolecek * 1. Redistributions of source code must retain the above copyright
475356de15Sjdolecek * notice, this list of conditions and the following disclaimer.
485356de15Sjdolecek * 2. Redistributions in binary form must reproduce the above copyright
495356de15Sjdolecek * notice, this list of conditions and the following disclaimer in the
505356de15Sjdolecek * documentation and/or other materials provided with the distribution.
515356de15Sjdolecek * 3. All advertising materials mentioning features or use of this software
525356de15Sjdolecek * must display the following acknowledgement:
535356de15Sjdolecek * This product includes software developed by the University of
545356de15Sjdolecek * California, Berkeley and its contributors.
555356de15Sjdolecek * 4. Neither the name of the University nor the names of its contributors
565356de15Sjdolecek * may be used to endorse or promote products derived from this software
575356de15Sjdolecek * without specific prior written permission.
585356de15Sjdolecek *
595356de15Sjdolecek * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
605356de15Sjdolecek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
615356de15Sjdolecek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
625356de15Sjdolecek * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
635356de15Sjdolecek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
645356de15Sjdolecek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
655356de15Sjdolecek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
665356de15Sjdolecek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
675356de15Sjdolecek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
685356de15Sjdolecek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
695356de15Sjdolecek * SUCH DAMAGE.
705356de15Sjdolecek *
715356de15Sjdolecek * filecore_utils.c 1.1 1998/6/26
725356de15Sjdolecek */
735356de15Sjdolecek
745356de15Sjdolecek /*
755356de15Sjdolecek * Copyright (c) 1998 Christopher G. Demetriou. All rights reserved.
765356de15Sjdolecek *
775356de15Sjdolecek * Redistribution and use in source and binary forms, with or without
785356de15Sjdolecek * modification, are permitted provided that the following conditions
795356de15Sjdolecek * are met:
805356de15Sjdolecek * 1. Redistributions of source code must retain the above copyright
815356de15Sjdolecek * notice, this list of conditions and the following disclaimer.
825356de15Sjdolecek * 2. Redistributions in binary form must reproduce the above copyright
835356de15Sjdolecek * notice, this list of conditions and the following disclaimer in the
845356de15Sjdolecek * documentation and/or other materials provided with the distribution.
855356de15Sjdolecek * 3. All advertising materials mentioning features or use of this software
865356de15Sjdolecek * must display the following acknowledgement:
875356de15Sjdolecek * This product includes software developed by Christopher G. Demetriou
885356de15Sjdolecek * for the NetBSD Project.
895356de15Sjdolecek * 4. The name of the author may not be used to endorse or promote products
905356de15Sjdolecek * derived from this software without specific prior written permission
915356de15Sjdolecek *
925356de15Sjdolecek * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
935356de15Sjdolecek * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
945356de15Sjdolecek * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
955356de15Sjdolecek * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
965356de15Sjdolecek * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
975356de15Sjdolecek * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
985356de15Sjdolecek * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
995356de15Sjdolecek * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1005356de15Sjdolecek * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
1015356de15Sjdolecek * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1025356de15Sjdolecek */
1035356de15Sjdolecek
1045356de15Sjdolecek #include <sys/cdefs.h>
105*57920690Smsaitoh __KERNEL_RCSID(0, "$NetBSD: filecore_utils.c,v 1.12 2020/09/29 02:58:52 msaitoh Exp $");
1065356de15Sjdolecek
1075356de15Sjdolecek #include <sys/param.h>
1085356de15Sjdolecek #include <sys/systm.h>
1095356de15Sjdolecek #include <sys/stat.h>
1105356de15Sjdolecek #include <sys/buf.h>
1115356de15Sjdolecek #include <sys/mount.h>
1125356de15Sjdolecek #include <sys/vnode.h>
1135356de15Sjdolecek #include <sys/dirent.h>
114641b7ad8Schristos #include <sys/kauth.h>
1155356de15Sjdolecek
1165356de15Sjdolecek #include <fs/filecorefs/filecore.h>
1175356de15Sjdolecek #include <fs/filecorefs/filecore_extern.h>
1185356de15Sjdolecek #include <fs/filecorefs/filecore_node.h>
1195356de15Sjdolecek #include <fs/filecorefs/filecore_mount.h>
1205356de15Sjdolecek
1215356de15Sjdolecek /*
1225356de15Sjdolecek * int filecore_bbchecksum(u_char *bootblock)
1235356de15Sjdolecek *
1245356de15Sjdolecek * Calculates the filecore boot block checksum. This is used to validate
1255356de15Sjdolecek * a filecore boot block on the disk. If a boot block is validated then
1265356de15Sjdolecek * it is used to locate the partition table. If the boot block is not
1275356de15Sjdolecek * validated, it is assumed that the whole disk is NetBSD.
1285356de15Sjdolecek *
1295356de15Sjdolecek * The basic algorithm is:
1305356de15Sjdolecek *
1315356de15Sjdolecek * for (each byte in block, excluding checksum) {
1325356de15Sjdolecek * sum += byte;
1335356de15Sjdolecek * if (sum > 255)
1345356de15Sjdolecek * sum -= 255;
1355356de15Sjdolecek * }
1365356de15Sjdolecek *
1375356de15Sjdolecek * That's equivalent to summing all of the bytes in the block
1385356de15Sjdolecek * (excluding the checksum byte, of course), then calculating the
1395356de15Sjdolecek * checksum as "cksum = sum - ((sum - 1) / 255) * 255)". That
1405356de15Sjdolecek * expression may or may not yield a faster checksum function,
1415356de15Sjdolecek * but it's easier to reason about.
1425356de15Sjdolecek *
1435356de15Sjdolecek * Note that if you have a block filled with bytes of a single
1445356de15Sjdolecek * value "X" (regardless of that value!) and calculate the cksum
1455356de15Sjdolecek * of the block (excluding the checksum byte), you will _always_
1465356de15Sjdolecek * end up with a checksum of X. (Do the math; that can be derived
1475356de15Sjdolecek * from the checksum calculation function!) That means that
1485356de15Sjdolecek * blocks which contain bytes which all have the same value will
149*57920690Smsaitoh * always checksum properly. That's a _very_ unlikely occurrence
1505356de15Sjdolecek * (probably impossible, actually) for a valid filecore boot block,
1515356de15Sjdolecek * so we treat such blocks as invalid.
1525356de15Sjdolecek */
1535356de15Sjdolecek int
filecore_bbchecksum(void * bb)154454af1c0Sdsl filecore_bbchecksum(void *bb)
1555356de15Sjdolecek {
1565356de15Sjdolecek u_char *bootblock = bb;
1575356de15Sjdolecek u_char byte0, accum_diff;
1585356de15Sjdolecek u_int sum;
1595356de15Sjdolecek int i;
1605356de15Sjdolecek
1615356de15Sjdolecek sum = 0;
1625356de15Sjdolecek accum_diff = 0;
1635356de15Sjdolecek byte0 = bootblock[0];
1645356de15Sjdolecek
1655356de15Sjdolecek /*
1665356de15Sjdolecek * Sum the contents of the block, keeping track of whether
1675356de15Sjdolecek * or not all bytes are the same. If 'accum_diff' ends up
1685356de15Sjdolecek * being zero, all of the bytes are, in fact, the same.
1695356de15Sjdolecek */
1705356de15Sjdolecek for (i = 0; i < 511; ++i) {
1715356de15Sjdolecek sum += bootblock[i];
1725356de15Sjdolecek accum_diff |= bootblock[i] ^ byte0;
1735356de15Sjdolecek }
1745356de15Sjdolecek
1755356de15Sjdolecek /*
1765356de15Sjdolecek * Check to see if the checksum byte is the same as the
1775356de15Sjdolecek * rest of the bytes, too. (Note that if all of the bytes
1785356de15Sjdolecek * are the same except the checksum, a checksum compare
1795356de15Sjdolecek * won't succeed, but that's not our problem.)
1805356de15Sjdolecek */
1815356de15Sjdolecek accum_diff |= bootblock[i] ^ byte0;
1825356de15Sjdolecek sum = (sum - ((sum - 1) / 255) * 255);
1835356de15Sjdolecek
1845356de15Sjdolecek /*
1855356de15Sjdolecek * If all bytes in block are the same
1865356de15Sjdolecek * or the checksum does not match ; call it invalid.
1875356de15Sjdolecek */
1885356de15Sjdolecek if (accum_diff == 0 || sum != bootblock[511])
1895356de15Sjdolecek return -1;
1905356de15Sjdolecek return 0;
1915356de15Sjdolecek }
1925356de15Sjdolecek
1935356de15Sjdolecek mode_t
filecore_mode(struct filecore_node * ip)194454af1c0Sdsl filecore_mode(struct filecore_node *ip)
1955356de15Sjdolecek {
1965356de15Sjdolecek mode_t m = 0;
1975356de15Sjdolecek int rf = 0;
1985356de15Sjdolecek
1995356de15Sjdolecek if ((ip->i_dirent.attr & FILECORE_ATTR_READ) ||
2005356de15Sjdolecek (ip->i_mnt->fc_mntflags & FILECOREMNT_OWNREAD) ||
2015356de15Sjdolecek (ip->i_dirent.attr & FILECORE_ATTR_DIR))
2025356de15Sjdolecek rf = 1;
2035356de15Sjdolecek if (ip->i_mnt->fc_mntflags & FILECOREMNT_ALLACCESS) {
2045356de15Sjdolecek m |= S_IRUSR | S_IXUSR;
2055356de15Sjdolecek if (rf || (ip->i_dirent.attr & FILECORE_ATTR_OREAD))
2065356de15Sjdolecek m |= S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
2075356de15Sjdolecek } else if (ip->i_mnt->fc_mntflags & FILECOREMNT_OWNACCESS) {
2085356de15Sjdolecek if (rf) m |= S_IRUSR | S_IXUSR;
2095356de15Sjdolecek if (ip->i_dirent.attr & FILECORE_ATTR_OREAD)
2105356de15Sjdolecek m |= S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
2115356de15Sjdolecek } else {
2125356de15Sjdolecek m |= S_IRUSR | S_IXUSR;
2135356de15Sjdolecek if (rf) m |= S_IRGRP | S_IXGRP;
2145356de15Sjdolecek if (ip->i_dirent.attr & FILECORE_ATTR_OREAD)
2155356de15Sjdolecek m |= S_IROTH | S_IXOTH;
2165356de15Sjdolecek }
2175356de15Sjdolecek if (ip->i_dirent.attr & FILECORE_ATTR_DIR) {
2185356de15Sjdolecek m |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
2195356de15Sjdolecek } else
2205356de15Sjdolecek m |= S_IFREG;
2215356de15Sjdolecek return m;
2225356de15Sjdolecek }
2235356de15Sjdolecek
2245356de15Sjdolecek struct timespec
filecore_time(struct filecore_node * ip)225454af1c0Sdsl filecore_time(struct filecore_node *ip)
2265356de15Sjdolecek {
2275356de15Sjdolecek struct timespec ts;
2285356de15Sjdolecek u_int64_t cs;
2295356de15Sjdolecek
2305356de15Sjdolecek cs = (((u_int64_t)(ip->i_dirent.load & 0xFF)) << 32)
2315356de15Sjdolecek + ip->i_dirent.exec - ((u_int64_t)1725772500 << 7);
2325356de15Sjdolecek ts.tv_sec = cs / 100;
2335356de15Sjdolecek ts.tv_nsec = (cs % 100) * 10000000;
2345356de15Sjdolecek return ts;
2355356de15Sjdolecek }
2365356de15Sjdolecek
2375356de15Sjdolecek ino_t
filecore_getparent(struct filecore_node * ip)238454af1c0Sdsl filecore_getparent(struct filecore_node *ip)
2395356de15Sjdolecek {
2405356de15Sjdolecek struct buf *pbp;
2415356de15Sjdolecek u_int32_t addr;
2425356de15Sjdolecek u_int32_t paddr;
2435356de15Sjdolecek int error = 0;
2445356de15Sjdolecek int i = 0;
2455356de15Sjdolecek
2465356de15Sjdolecek #ifdef FILECORE_DEBUG
2471498ad22Sad printf("filecore_getparent(ino=%llx)\n", (long long)ip->i_number);
2485356de15Sjdolecek #endif
2495356de15Sjdolecek if (ip->i_parent != -2) {
2505356de15Sjdolecek return ip->i_parent;
2515356de15Sjdolecek }
2525356de15Sjdolecek if (ip->i_number == FILECORE_ROOTINO) {
2535356de15Sjdolecek ip->i_parent = ip->i_number;
2545356de15Sjdolecek return ip->i_number;
2555356de15Sjdolecek }
2565356de15Sjdolecek addr = ip->i_number & FILECORE_INO_MASK;
2575356de15Sjdolecek /* Read directory data for parent dir to find its parent */
2585356de15Sjdolecek #ifdef FILECORE_DEBUG
2595356de15Sjdolecek printf("filecore_getparent() read parent dir contents\n");
2605356de15Sjdolecek #endif
2615356de15Sjdolecek error = filecore_bread(ip->i_mnt, addr, FILECORE_DIR_SIZE,
2625356de15Sjdolecek NOCRED, &pbp);
2635356de15Sjdolecek if (error) {
2645356de15Sjdolecek return error;
2655356de15Sjdolecek }
2665356de15Sjdolecek paddr = fcdirtail(pbp->b_data)->parent1
2675356de15Sjdolecek | fcdirtail(pbp->b_data)->parent2 << 16;
2685356de15Sjdolecek #ifdef FILECORE_DEBUG_BR
2695356de15Sjdolecek printf("brelse(%p) ut1\n", pbp);
2705356de15Sjdolecek #endif
2719f56dfa5Sad brelse(pbp, 0);
2725356de15Sjdolecek
2735356de15Sjdolecek /* If parent's parent is the parent then parent is root dir */
2745356de15Sjdolecek if (paddr == addr) {
2755356de15Sjdolecek ip->i_parent = FILECORE_ROOTINO;
2765356de15Sjdolecek return FILECORE_ROOTINO;
2775356de15Sjdolecek }
2785356de15Sjdolecek
2795356de15Sjdolecek #ifdef FILECORE_DEBUG
2805356de15Sjdolecek printf("filecore_getparent() read grand-parent dir contents\n");
2815356de15Sjdolecek #endif
2825356de15Sjdolecek error = filecore_bread(ip->i_mnt, paddr, FILECORE_DIR_SIZE,
2835356de15Sjdolecek NOCRED, &pbp);
2845356de15Sjdolecek if (error) {
2855356de15Sjdolecek return error;
2865356de15Sjdolecek }
2875356de15Sjdolecek while (fcdirentry(pbp->b_data,i)->addr != addr) {
2885356de15Sjdolecek if (fcdirentry(pbp->b_data, i++)->name[0] == 0) {
2895356de15Sjdolecek #ifdef FILECORE_DEBUG_BR
2905356de15Sjdolecek printf("brelse(%p) ut2\n", pbp);
2915356de15Sjdolecek #endif
2929f56dfa5Sad brelse(pbp, 0);
2935356de15Sjdolecek return FILECORE_ROOTINO;
2945356de15Sjdolecek }
2955356de15Sjdolecek }
2965356de15Sjdolecek #ifdef FILECORE_DEBUG_BR
2975356de15Sjdolecek printf("brelse(%p) ut3\n", pbp);
2985356de15Sjdolecek #endif
2999f56dfa5Sad brelse(pbp, 0);
3005356de15Sjdolecek ip->i_parent = paddr + (i << FILECORE_INO_INDEX);
3015356de15Sjdolecek return (paddr + (i << FILECORE_INO_INDEX));
3025356de15Sjdolecek }
3035356de15Sjdolecek
3045356de15Sjdolecek int
filecore_fn2unix(char * fcfn,char * ufn,u_int16_t * len)305454af1c0Sdsl filecore_fn2unix(char *fcfn, char *ufn, u_int16_t *len)
3065356de15Sjdolecek {
3075356de15Sjdolecek int i = 0;
3085356de15Sjdolecek
3095356de15Sjdolecek if (*fcfn == 0)
3105356de15Sjdolecek return (-1);
3115356de15Sjdolecek while (i++ < 10 && *fcfn >= ' ') {
3125356de15Sjdolecek if (*fcfn == '/')
3135356de15Sjdolecek *ufn++ = '.';
3145356de15Sjdolecek else
3155356de15Sjdolecek *ufn++ = *fcfn;
3165356de15Sjdolecek fcfn++;
3175356de15Sjdolecek }
318362a4a0bSchristos #ifdef notdef
319362a4a0bSchristos if (ip->i_mnt->fc_mntflags & FILECOREMNT_FILETYPE) {
3205356de15Sjdolecek *ufn++ = ',';
321362a4a0bSchristos *ufn++ = hexdigits[(ip->i_dirent.load >> 10) & 15];
322362a4a0bSchristos *ufn++ = hexdigits[(ip->i_dirent.load >> 9) & 15];
323362a4a0bSchristos *ufn++ = hexdigits[(ip->i_dirent.load >> 8) & 15];
324362a4a0bSchristos }
325362a4a0bSchristos #endif
3265356de15Sjdolecek *ufn = 0;
3275356de15Sjdolecek *len = i - 1;
3285356de15Sjdolecek return 0;
3295356de15Sjdolecek }
3305356de15Sjdolecek
3315356de15Sjdolecek int
filecore_fncmp(const char * fcfn,const char * ufn,u_short len)332454af1c0Sdsl filecore_fncmp(const char *fcfn, const char *ufn, u_short len)
3335356de15Sjdolecek {
3345356de15Sjdolecek char f, u;
3355356de15Sjdolecek int i = 0;
3365356de15Sjdolecek
3375356de15Sjdolecek if (*fcfn == 0 || len > 10)
3385356de15Sjdolecek return -1;
3395356de15Sjdolecek while (i++ < len) {
3405356de15Sjdolecek if (*fcfn < ' ')
3415356de15Sjdolecek return 1;
3425356de15Sjdolecek f = *fcfn++;
3435356de15Sjdolecek u = *ufn++;
3445356de15Sjdolecek if (u == '.')
3455356de15Sjdolecek u = '/';
3465356de15Sjdolecek if (u >= 'a' && u <= 'z') u -= 'a' - 'A';
3475356de15Sjdolecek if (f >= 'a' && f <= 'z') f -= 'a' - 'A';
3485356de15Sjdolecek if (f < u)
3495356de15Sjdolecek return 1;
3505356de15Sjdolecek else if (f > u)
3515356de15Sjdolecek return -1;
3525356de15Sjdolecek }
3535356de15Sjdolecek if (len == 10 || *fcfn < ' ')
3545356de15Sjdolecek return 0;
3555356de15Sjdolecek return -1;
3565356de15Sjdolecek }
357