|
|
1.1 ! root 1: /* ! 2: * libhfs - library for reading and writing Macintosh HFS volumes ! 3: * Copyright (C) 1996-1998 Robert Leslie ! 4: * ! 5: * This program is free software; you can redistribute it and/or modify ! 6: * it under the terms of the GNU General Public License as published by ! 7: * the Free Software Foundation; either version 2 of the License, or ! 8: * (at your option) any later version. ! 9: * ! 10: * This program is distributed in the hope that it will be useful, ! 11: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 12: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 13: * GNU General Public License for more details. ! 14: * ! 15: * You should have received a copy of the GNU General Public License ! 16: * along with this program; if not, write to the Free Software ! 17: * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, ! 18: * MA 02110-1301, USA. ! 19: * ! 20: * $Id: btree.c,v 1.10 1998/11/02 22:08:54 rob Exp $ ! 21: */ ! 22: ! 23: #include "config.h" ! 24: ! 25: #include "libhfs.h" ! 26: #include "btree.h" ! 27: #include "data.h" ! 28: #include "file.h" ! 29: #include "block.h" ! 30: #include "node.h" ! 31: ! 32: /* ! 33: * NAME: btree->getnode() ! 34: * DESCRIPTION: retrieve a numbered node from a B*-tree file ! 35: */ ! 36: int bt_getnode(node *np, btree *bt, unsigned long nnum) ! 37: { ! 38: block *bp = &np->data; ! 39: const byte *ptr; ! 40: int i; ! 41: ! 42: np->bt = bt; ! 43: np->nnum = nnum; ! 44: ! 45: # if 0 ! 46: fprintf(stderr, "BTREE: GET vol \"%s\" btree \"%s\" node %lu\n", ! 47: bt->f.vol->mdb.drVN, bt->f.name, np->nnum); ! 48: # endif ! 49: ! 50: /* verify the node exists and is marked as in-use */ ! 51: ! 52: if (nnum > 0 && nnum >= bt->hdr.bthNNodes) ! 53: ERROR(EIO, "read nonexistent b*-tree node"); ! 54: else if (bt->map && ! BMTST(bt->map, nnum)) ! 55: ERROR(EIO, "read unallocated b*-tree node"); ! 56: ! 57: if (f_getblock(&bt->f, nnum, bp) == -1) ! 58: goto fail; ! 59: ! 60: ptr = *bp; ! 61: ! 62: d_fetchul(&ptr, &np->nd.ndFLink); ! 63: d_fetchul(&ptr, &np->nd.ndBLink); ! 64: d_fetchsb(&ptr, &np->nd.ndType); ! 65: d_fetchsb(&ptr, &np->nd.ndNHeight); ! 66: d_fetchuw(&ptr, &np->nd.ndNRecs); ! 67: d_fetchsw(&ptr, &np->nd.ndResv2); ! 68: ! 69: if (np->nd.ndNRecs > HFS_MAX_NRECS) ! 70: ERROR(EIO, "too many b*-tree node records"); ! 71: ! 72: i = np->nd.ndNRecs + 1; ! 73: ! 74: ptr = *bp + HFS_BLOCKSZ - (2 * i); ! 75: ! 76: while (i--) ! 77: d_fetchuw(&ptr, &np->roff[i]); ! 78: ! 79: return 0; ! 80: ! 81: fail: ! 82: return -1; ! 83: } ! 84: ! 85: ! 86: /* ! 87: * NAME: btree->readhdr() ! 88: * DESCRIPTION: read the header node of a B*-tree ! 89: */ ! 90: int bt_readhdr(btree *bt) ! 91: { ! 92: const byte *ptr; ! 93: byte *map = NULL; ! 94: int i; ! 95: unsigned long nnum; ! 96: ! 97: if (bt_getnode(&bt->hdrnd, bt, 0) == -1) ! 98: goto fail; ! 99: ! 100: if (bt->hdrnd.nd.ndType != ndHdrNode || ! 101: bt->hdrnd.nd.ndNRecs != 3 || ! 102: bt->hdrnd.roff[0] != 0x00e || ! 103: bt->hdrnd.roff[1] != 0x078 || ! 104: bt->hdrnd.roff[2] != 0x0f8 || ! 105: bt->hdrnd.roff[3] != 0x1f8) ! 106: ERROR(EIO, "malformed b*-tree header node"); ! 107: ! 108: /* read header record */ ! 109: ! 110: ptr = HFS_NODEREC(bt->hdrnd, 0); ! 111: ! 112: d_fetchuw(&ptr, &bt->hdr.bthDepth); ! 113: d_fetchul(&ptr, &bt->hdr.bthRoot); ! 114: d_fetchul(&ptr, &bt->hdr.bthNRecs); ! 115: d_fetchul(&ptr, &bt->hdr.bthFNode); ! 116: d_fetchul(&ptr, &bt->hdr.bthLNode); ! 117: d_fetchuw(&ptr, &bt->hdr.bthNodeSize); ! 118: d_fetchuw(&ptr, &bt->hdr.bthKeyLen); ! 119: d_fetchul(&ptr, &bt->hdr.bthNNodes); ! 120: d_fetchul(&ptr, &bt->hdr.bthFree); ! 121: ! 122: for (i = 0; i < 76; ++i) ! 123: d_fetchsb(&ptr, &bt->hdr.bthResv[i]); ! 124: ! 125: if (bt->hdr.bthNodeSize != HFS_BLOCKSZ) ! 126: ERROR(EINVAL, "unsupported b*-tree node size"); ! 127: ! 128: /* read map record; construct btree bitmap */ ! 129: /* don't set bt->map until we're done, since getnode() checks it */ ! 130: ! 131: map = ALLOC(byte, HFS_MAP1SZ); ! 132: if (map == NULL) ! 133: ERROR(ENOMEM, NULL); ! 134: ! 135: memcpy(map, HFS_NODEREC(bt->hdrnd, 2), HFS_MAP1SZ); ! 136: bt->mapsz = HFS_MAP1SZ; ! 137: ! 138: /* read continuation map records, if any */ ! 139: ! 140: nnum = bt->hdrnd.nd.ndFLink; ! 141: ! 142: while (nnum) ! 143: { ! 144: node n; ! 145: byte *newmap; ! 146: ! 147: if (bt_getnode(&n, bt, nnum) == -1) ! 148: goto fail; ! 149: ! 150: if (n.nd.ndType != ndMapNode || ! 151: n.nd.ndNRecs != 1 || ! 152: n.roff[0] != 0x00e || ! 153: n.roff[1] != 0x1fa) ! 154: ERROR(EIO, "malformed b*-tree map node"); ! 155: ! 156: newmap = REALLOC(map, byte, bt->mapsz + HFS_MAPXSZ); ! 157: if (newmap == NULL) ! 158: ERROR(ENOMEM, NULL); ! 159: ! 160: map = newmap; ! 161: ! 162: memcpy(map + bt->mapsz, HFS_NODEREC(n, 0), HFS_MAPXSZ); ! 163: bt->mapsz += HFS_MAPXSZ; ! 164: ! 165: nnum = n.nd.ndFLink; ! 166: } ! 167: ! 168: bt->map = map; ! 169: ! 170: return 0; ! 171: ! 172: fail: ! 173: FREE(map); ! 174: return -1; ! 175: } ! 176: ! 177: ! 178: /* ! 179: * NAME: btree->search() ! 180: * DESCRIPTION: locate a data record given a search key ! 181: */ ! 182: int bt_search(btree *bt, const byte *key, node *np) ! 183: { ! 184: int found = 0; ! 185: unsigned long nnum; ! 186: ! 187: nnum = bt->hdr.bthRoot; ! 188: ! 189: if (nnum == 0) ! 190: ERROR(ENOENT, NULL); ! 191: ! 192: while (1) ! 193: { ! 194: const byte *rec; ! 195: ! 196: if (bt_getnode(np, bt, nnum) == -1) ! 197: { ! 198: found = -1; ! 199: goto fail; ! 200: } ! 201: ! 202: found = n_search(np, key); ! 203: ! 204: switch (np->nd.ndType) ! 205: { ! 206: case ndIndxNode: ! 207: if (np->rnum == -1) ! 208: ERROR(ENOENT, NULL); ! 209: ! 210: rec = HFS_NODEREC(*np, np->rnum); ! 211: nnum = d_getul(HFS_RECDATA(rec)); ! 212: ! 213: break; ! 214: ! 215: case ndLeafNode: ! 216: if (! found) ! 217: ERROR(ENOENT, NULL); ! 218: ! 219: goto done; ! 220: ! 221: default: ! 222: found = -1; ! 223: ERROR(EIO, "unexpected b*-tree node"); ! 224: } ! 225: } ! 226: ! 227: done: ! 228: fail: ! 229: return found; ! 230: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.