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