1 /* $NetBSD: filecore_utils.c,v 1.10 2009/03/14 15:36:21 dsl 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.10 2009/03/14 15:36:21 dsl 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(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 brelse(pbp, 0); 265 return error; 266 } 267 paddr = fcdirtail(pbp->b_data)->parent1 268 | fcdirtail(pbp->b_data)->parent2 << 16; 269 #ifdef FILECORE_DEBUG_BR 270 printf("brelse(%p) ut1\n", pbp); 271 #endif 272 brelse(pbp, 0); 273 274 /* If parent's parent is the parent then parent is root dir */ 275 if (paddr == addr) { 276 ip->i_parent = FILECORE_ROOTINO; 277 return FILECORE_ROOTINO; 278 } 279 280 #ifdef FILECORE_DEBUG 281 printf("filecore_getparent() read grand-parent dir contents\n"); 282 #endif 283 error = filecore_bread(ip->i_mnt, paddr, FILECORE_DIR_SIZE, 284 NOCRED, &pbp); 285 if (error) { 286 brelse(pbp, 0); 287 return error; 288 } 289 while (fcdirentry(pbp->b_data,i)->addr != addr) { 290 if (fcdirentry(pbp->b_data, i++)->name[0] == 0) { 291 #ifdef FILECORE_DEBUG_BR 292 printf("brelse(%p) ut2\n", pbp); 293 #endif 294 brelse(pbp, 0); 295 return FILECORE_ROOTINO; 296 } 297 } 298 #ifdef FILECORE_DEBUG_BR 299 printf("brelse(%p) ut3\n", pbp); 300 #endif 301 brelse(pbp, 0); 302 ip->i_parent = paddr + (i << FILECORE_INO_INDEX); 303 return (paddr + (i << FILECORE_INO_INDEX)); 304 } 305 306 int 307 filecore_fn2unix(char *fcfn, char *ufn, u_int16_t *len) 308 { 309 int i = 0; 310 311 if (*fcfn == 0) 312 return (-1); 313 while (i++ < 10 && *fcfn >= ' ') { 314 if (*fcfn == '/') 315 *ufn++ = '.'; 316 else 317 *ufn++ = *fcfn; 318 fcfn++; 319 } 320 #ifdef notdef 321 if (ip->i_mnt->fc_mntflags & FILECOREMNT_FILETYPE) { 322 *ufn++ = ','; 323 *ufn++ = hexdigits[(ip->i_dirent.load >> 10) & 15]; 324 *ufn++ = hexdigits[(ip->i_dirent.load >> 9) & 15]; 325 *ufn++ = hexdigits[(ip->i_dirent.load >> 8) & 15]; 326 } 327 #endif 328 *ufn = 0; 329 *len = i - 1; 330 return 0; 331 } 332 333 int 334 filecore_fncmp(const char *fcfn, const char *ufn, u_short len) 335 { 336 char f, u; 337 int i = 0; 338 339 if (*fcfn == 0 || len > 10) 340 return -1; 341 while (i++ < len) { 342 if (*fcfn < ' ') 343 return 1; 344 f = *fcfn++; 345 u = *ufn++; 346 if (u == '.') 347 u = '/'; 348 if (u >= 'a' && u <= 'z') u -= 'a' - 'A'; 349 if (f >= 'a' && f <= 'z') f -= 'a' - 'A'; 350 if (f < u) 351 return 1; 352 else if (f > u) 353 return -1; 354 } 355 if (len == 10 || *fcfn < ' ') 356 return 0; 357 return -1; 358 } 359