/* * NAME: vol->readvbm() * DESCRIPTION: read volume bitmap into memory */ int v_readvbm(hfsvol *vol) { int vbmst = vol->mdb.drVBMSt; int vbmsz = (vol->mdb.drNmAlBlks + 4095) / 4096; block *bp; # ifdef DEBUG if (vol->vbm) abort(); # endif if (vol->mdb.drAlBlSt - vbmst < vbmsz) ERROR(EIO, "volume bitmap collides with volume data"); vol->vbm = ALLOC(block, vbmsz); if (vol->vbm == 0) ERROR(ENOMEM, 0); for (bp = vol->vbm; vbmsz--; ++bp) { if (b_readlb(vol, vbmst++, bp) == -1) goto fail; } return 0; fail: FREE(vol->vbm); vol->vbm = 0; return -1; }
/* * NAME: low->readvbm() * DESCRIPTION: read the volume bit map into memory */ int l_readvbm(hfsvol *vol) { int vbmst = vol->mdb.drVBMSt; int vbmsz = (vol->mdb.drNmAlBlks + 4095) / 4096; block *bp; if (vol->mdb.drAlBlSt - vbmst < vbmsz) { ERROR(EIO, "volume bitmap collides with volume data"); return -1; } bp = ALLOC(block, vbmsz); if (bp == 0) { ERROR(ENOMEM, 0); return -1; } vol->vbm = bp; while (vbmsz--) { if (b_readlb(vol, vbmst++, bp++) < 0) { FREE(vol->vbm); vol->vbm = 0; return -1; } } return 0; }
/* * NAME: low->getbb() * DESCRIPTION: read a volume's boot blocks */ int l_getbb(hfsvol *vol, BootBlkHdr *bb, byte *bootcode) { block b; const byte *ptr = b; if (b_readlb(vol, 0, &b) == -1) goto fail; d_fetchsw(&ptr, &bb->bbID); d_fetchsl(&ptr, &bb->bbEntry); d_fetchsw(&ptr, &bb->bbVersion); d_fetchsw(&ptr, &bb->bbPageFlags); d_fetchstr(&ptr, bb->bbSysName, sizeof(bb->bbSysName)); d_fetchstr(&ptr, bb->bbShellName, sizeof(bb->bbShellName)); d_fetchstr(&ptr, bb->bbDbg1Name, sizeof(bb->bbDbg1Name)); d_fetchstr(&ptr, bb->bbDbg2Name, sizeof(bb->bbDbg2Name)); d_fetchstr(&ptr, bb->bbScreenName, sizeof(bb->bbScreenName)); d_fetchstr(&ptr, bb->bbHelloName, sizeof(bb->bbHelloName)); d_fetchstr(&ptr, bb->bbScrapName, sizeof(bb->bbScrapName)); d_fetchsw(&ptr, &bb->bbCntFCBs); d_fetchsw(&ptr, &bb->bbCntEvts); d_fetchsl(&ptr, &bb->bb128KSHeap); d_fetchsl(&ptr, &bb->bb256KSHeap); d_fetchsl(&ptr, &bb->bbSysHeapSize); d_fetchsw(&ptr, &bb->filler); d_fetchsl(&ptr, &bb->bbSysHeapExtra); d_fetchsl(&ptr, &bb->bbSysHeapFract); ASSERT(ptr - b == 148); if (bootcode) { memcpy(bootcode, ptr, HFS_BOOTCODE1LEN); if (b_readlb(vol, 1, &b) == -1) goto fail; memcpy(bootcode + HFS_BOOTCODE1LEN, b, HFS_BOOTCODE2LEN); } return 0; fail: return -1; }
/* * NAME: low->readblock0() * DESCRIPTION: read the first sector and get bearings */ int l_readblock0(hfsvol *vol) { block b; unsigned char *ptr = b; Block0 rec; if (b_readlb(vol, 0, &b) < 0) return -1; d_fetchw(&ptr, &rec.sbSig); d_fetchw(&ptr, &rec.sbBlkSize); d_fetchl(&ptr, &rec.sbBlkCount); d_fetchw(&ptr, &rec.sbDevType); d_fetchw(&ptr, &rec.sbDevId); d_fetchl(&ptr, &rec.sbData); d_fetchw(&ptr, &rec.sbDrvrCount); d_fetchl(&ptr, &rec.ddBlock); d_fetchw(&ptr, &rec.ddSize); d_fetchw(&ptr, &rec.ddType); switch (rec.sbSig) { case 0x4552: /* block device with a partition table */ { if (rec.sbBlkSize != HFS_BLOCKSZ) { ERROR(EINVAL, "unsupported block size"); return -1; } vol->vlen = rec.sbBlkCount; if (l_readpm(vol) < 0) return -1; } break; case 0x4c4b: /* bootable floppy */ vol->pnum = 0; break; default: /* non-bootable floppy or something else */ /* some miscreant media may also be partitioned; we attempt to read a partition map, but ignore any failure */ if (l_readpm(vol) < 0) vol->pnum = 0; } return 0; }
/* * NAME: low->readmdb() * DESCRIPTION: read the master directory block into memory */ int l_readmdb(hfsvol *vol) { block b; unsigned char *ptr = b; MDB *mdb = &vol->mdb; hfsfile *ext = &vol->ext.f; hfsfile *cat = &vol->cat.f; int i; if (b_readlb(vol, 2, &b) < 0) return -1; d_fetchw(&ptr, &mdb->drSigWord); d_fetchl(&ptr, &mdb->drCrDate); d_fetchl(&ptr, &mdb->drLsMod); d_fetchw(&ptr, &mdb->drAtrb); d_fetchw(&ptr, (short *) &mdb->drNmFls); d_fetchw(&ptr, (short *) &mdb->drVBMSt); d_fetchw(&ptr, (short *) &mdb->drAllocPtr); d_fetchw(&ptr, (short *) &mdb->drNmAlBlks); d_fetchl(&ptr, (long *) &mdb->drAlBlkSiz); d_fetchl(&ptr, (long *) &mdb->drClpSiz); d_fetchw(&ptr, (short *) &mdb->drAlBlSt); d_fetchl(&ptr, &mdb->drNxtCNID); d_fetchw(&ptr, (short *) &mdb->drFreeBks); d_fetchs(&ptr, mdb->drVN, sizeof(mdb->drVN)); if (ptr - b != 64) abort(); d_fetchl(&ptr, &mdb->drVolBkUp); d_fetchw(&ptr, &mdb->drVSeqNum); d_fetchl(&ptr, (long *) &mdb->drWrCnt); d_fetchl(&ptr, (long *) &mdb->drXTClpSiz); d_fetchl(&ptr, (long *) &mdb->drCTClpSiz); d_fetchw(&ptr, (short *) &mdb->drNmRtDirs); d_fetchl(&ptr, (long *) &mdb->drFilCnt); d_fetchl(&ptr, (long *) &mdb->drDirCnt); for (i = 0; i < 8; ++i) d_fetchl(&ptr, &mdb->drFndrInfo[i]); if (ptr - b != 124) abort(); d_fetchw(&ptr, (short *) &mdb->drVCSize); d_fetchw(&ptr, (short *) &mdb->drVBMCSize); d_fetchw(&ptr, (short *) &mdb->drCtlCSize); d_fetchl(&ptr, (long *) &mdb->drXTFlSize); for (i = 0; i < 3; ++i) { d_fetchw(&ptr, (short *) &mdb->drXTExtRec[i].xdrStABN); d_fetchw(&ptr, (short *) &mdb->drXTExtRec[i].xdrNumABlks); } if (ptr - b != 146) abort(); d_fetchl(&ptr, (long *) &mdb->drCTFlSize); for (i = 0; i < 3; ++i) { d_fetchw(&ptr, (short *) &mdb->drCTExtRec[i].xdrStABN); d_fetchw(&ptr, (short *) &mdb->drCTExtRec[i].xdrNumABlks); } if (ptr - b != 162) abort(); vol->lpa = mdb->drAlBlkSiz / HFS_BLOCKSZ; /* extents pseudo-file structs */ ext->vol = vol; ext->parid = 0; strcpy(ext->name, "extents overflow"); ext->cat.cdrType = cdrFilRec; /* ext->cat.cdrResrv2 */ ext->cat.u.fil.filFlags = 0; ext->cat.u.fil.filTyp = 0; /* ext->cat.u.fil.filUsrWds */ ext->cat.u.fil.filFlNum = HFS_CNID_EXT; ext->cat.u.fil.filStBlk = mdb->drXTExtRec[0].xdrStABN; ext->cat.u.fil.filLgLen = mdb->drXTFlSize; ext->cat.u.fil.filPyLen = mdb->drXTFlSize; ext->cat.u.fil.filRStBlk = 0; ext->cat.u.fil.filRLgLen = 0; ext->cat.u.fil.filRPyLen = 0; ext->cat.u.fil.filCrDat = mdb->drCrDate; ext->cat.u.fil.filMdDat = mdb->drLsMod; ext->cat.u.fil.filBkDat = 0; /* ext->cat.u.fil.filFndrInfo */ ext->cat.u.fil.filClpSize = 0; memcpy(ext->cat.u.fil.filExtRec, mdb->drXTExtRec, sizeof(ExtDataRec)); for (i = 0; i < 3; ++i) { ext->cat.u.fil.filRExtRec[i].xdrStABN = 0; ext->cat.u.fil.filRExtRec[i].xdrNumABlks = 0; } f_selectfork(ext, 0); ext->clump = mdb->drXTClpSiz; ext->flags = 0; ext->prev = ext->next = 0; /* catalog pseudo-file structs */ cat->vol = vol; cat->parid = 0; strcpy(cat->name, "catalog"); cat->cat.cdrType = cdrFilRec; /* cat->cat.cdrResrv2 */ cat->cat.u.fil.filFlags = 0; cat->cat.u.fil.filTyp = 0; /* cat->cat.u.fil.filUsrWds */ cat->cat.u.fil.filFlNum = HFS_CNID_CAT; cat->cat.u.fil.filStBlk = mdb->drCTExtRec[0].xdrStABN; cat->cat.u.fil.filLgLen = mdb->drCTFlSize; cat->cat.u.fil.filPyLen = mdb->drCTFlSize; cat->cat.u.fil.filRStBlk = 0; cat->cat.u.fil.filRLgLen = 0; cat->cat.u.fil.filRPyLen = 0; cat->cat.u.fil.filCrDat = mdb->drCrDate; cat->cat.u.fil.filMdDat = mdb->drLsMod; cat->cat.u.fil.filBkDat = 0; /* cat->cat.u.fil.filFndrInfo */ cat->cat.u.fil.filClpSize = 0; memcpy(cat->cat.u.fil.filExtRec, mdb->drCTExtRec, sizeof(ExtDataRec)); for (i = 0; i < 3; ++i) { cat->cat.u.fil.filRExtRec[i].xdrStABN = 0; cat->cat.u.fil.filRExtRec[i].xdrNumABlks = 0; } f_selectfork(cat, 0); cat->clump = mdb->drCTClpSiz; cat->flags = 0; cat->prev = cat->next = 0; return 0; }
/* * NAME: low->readpm() * DESCRIPTION: read the partition map and locate an HFS volume */ int l_readpm(hfsvol *vol) { block b; unsigned char *ptr; Partition map; unsigned long bnum; int pnum; bnum = 1; pnum = vol->pnum; while (1) { if (b_readlb(vol, bnum, &b) < 0) return -1; ptr = b; d_fetchw(&ptr, &map.pmSig); d_fetchw(&ptr, &map.pmSigPad); d_fetchl(&ptr, &map.pmMapBlkCnt); d_fetchl(&ptr, &map.pmPyPartStart); d_fetchl(&ptr, &map.pmPartBlkCnt); memcpy(map.pmPartName, ptr, 32); map.pmPartName[32] = 0; ptr += 32; memcpy(map.pmParType, ptr, 32); map.pmParType[32] = 0; ptr += 32; d_fetchl(&ptr, &map.pmLgDataStart); d_fetchl(&ptr, &map.pmDataCnt); d_fetchl(&ptr, &map.pmPartStatus); d_fetchl(&ptr, &map.pmLgBootStart); d_fetchl(&ptr, &map.pmBootSize); d_fetchl(&ptr, &map.pmBootAddr); d_fetchl(&ptr, &map.pmBootAddr2); d_fetchl(&ptr, &map.pmBootEntry); d_fetchl(&ptr, &map.pmBootEntry2); d_fetchl(&ptr, &map.pmBootCksum); memcpy(map.pmProcessor, ptr, 16); map.pmProcessor[16] = 0; ptr += 16; if (map.pmSig == 0x5453) { /* old partition map sig */ ERROR(EINVAL, "unsupported partition map signature"); return -1; } if (map.pmSig != 0x504d) { ERROR(EINVAL, "bad partition map"); return -1; } if (strcmp((char *) map.pmParType, "Apple_HFS") == 0 && --pnum == 0) { if (map.pmLgDataStart != 0) { ERROR(EINVAL, "unsupported start of partition logical data"); return -1; } vol->vstart = map.pmPyPartStart; vol->vlen = map.pmPartBlkCnt; return 0; } if (bnum >= map.pmMapBlkCnt) { ERROR(EINVAL, "can't find HFS partition"); return -1; } ++bnum; } }
/* * NAME: low->getmdb() * DESCRIPTION: read a master directory block */ int l_getmdb(hfsvol *vol, MDB *mdb, int backup) { block b; const byte *ptr = b; int i; if (b_readlb(vol, backup ? vol->vlen - 2 : 2, &b) == -1) goto fail; d_fetchsw(&ptr, &mdb->drSigWord); d_fetchsl(&ptr, &mdb->drCrDate); d_fetchsl(&ptr, &mdb->drLsMod); d_fetchsw(&ptr, &mdb->drAtrb); d_fetchuw(&ptr, &mdb->drNmFls); d_fetchuw(&ptr, &mdb->drVBMSt); d_fetchuw(&ptr, &mdb->drAllocPtr); d_fetchuw(&ptr, &mdb->drNmAlBlks); d_fetchul(&ptr, &mdb->drAlBlkSiz); d_fetchul(&ptr, &mdb->drClpSiz); d_fetchuw(&ptr, &mdb->drAlBlSt); d_fetchsl(&ptr, &mdb->drNxtCNID); d_fetchuw(&ptr, &mdb->drFreeBks); d_fetchstr(&ptr, mdb->drVN, sizeof(mdb->drVN)); ASSERT(ptr - b == 64); d_fetchsl(&ptr, &mdb->drVolBkUp); d_fetchsw(&ptr, &mdb->drVSeqNum); d_fetchul(&ptr, &mdb->drWrCnt); d_fetchul(&ptr, &mdb->drXTClpSiz); d_fetchul(&ptr, &mdb->drCTClpSiz); d_fetchuw(&ptr, &mdb->drNmRtDirs); d_fetchul(&ptr, &mdb->drFilCnt); d_fetchul(&ptr, &mdb->drDirCnt); for (i = 0; i < 8; ++i) d_fetchsl(&ptr, &mdb->drFndrInfo[i]); ASSERT(ptr - b == 124); d_fetchuw(&ptr, &mdb->drEmbedSigWord); d_fetchuw(&ptr, &mdb->drEmbedExtent.xdrStABN); d_fetchuw(&ptr, &mdb->drEmbedExtent.xdrNumABlks); d_fetchul(&ptr, &mdb->drXTFlSize); for (i = 0; i < 3; ++i) { d_fetchuw(&ptr, &mdb->drXTExtRec[i].xdrStABN); d_fetchuw(&ptr, &mdb->drXTExtRec[i].xdrNumABlks); } ASSERT(ptr - b == 146); d_fetchul(&ptr, &mdb->drCTFlSize); for (i = 0; i < 3; ++i) { d_fetchuw(&ptr, &mdb->drCTExtRec[i].xdrStABN); d_fetchuw(&ptr, &mdb->drCTExtRec[i].xdrNumABlks); } ASSERT(ptr - b == 162); return 0; fail: return -1; }
/* * NAME: hfs->format() * DESCRIPTION: write a new filesystem */ int hfs_format(char *path, int pnum, char *vname) { hfsvol vol; btree *ext = &vol.ext; btree *cat = &vol.cat; unsigned int vbmsz; int i, result = 0; block vbm[16]; char *map; if (mystrchr(vname, ':')) { ERROR(EINVAL, "volume name may not contain colons"); return -1; } i = strlen(vname); if (i < 1 || i > HFS_MAX_VLEN) { ERROR(EINVAL, "volume name must be 1-27 chars"); return -1; } vol.flags = 0; vol.pnum = pnum; vol.vstart = 0; vol.vlen = 0; vol.lpa = 0; vol.vbm = vbm; vol.cwd = HFS_CNID_ROOTDIR; vol.refs = 0; vol.files = 0; vol.dirs = 0; vol.prev = 0; vol.next = 0; #if 0 vol.fd = open(path, O_RDWR); if (vol.fd < 0) { ERROR(errno, "error opening device for writing"); return -1; } #endif if (l_lockvol(&vol) < 0) { #if 0 close(vol.fd); #endif return -1; } if (pnum > 0) { if (l_readpm(&vol) < 0) { #if 0 close(vol.fd); #endif return -1; } } else /* determine size of entire device */ { unsigned long low, high, mid; block b; for (low = 0, high = 2879; b_readlb(&vol, high, &b) >= 0; high *= 2) low = high; while (low < high - 1) { mid = (low + high) / 2; if (b_readlb(&vol, mid, &b) < 0) high = mid; else low = mid; } vol.vlen = low + 1; } if (vol.vlen < 800 * 1024 / HFS_BLOCKSZ) { #if 0 close(vol.fd); #endif ERROR(EINVAL, "volume size must be >= 800K"); return -1; } /* initialize volume geometry */ vol.lpa = 1 + vol.vlen / 65536; vbmsz = (vol.vlen / vol.lpa + 4095) / 4096; vol.mdb.drSigWord = 0x4244; vol.mdb.drCrDate = d_tomtime(/*time*/(0)); vol.mdb.drLsMod = vol.mdb.drCrDate; vol.mdb.drAtrb = 0; vol.mdb.drNmFls = 0; vol.mdb.drVBMSt = 3; vol.mdb.drAllocPtr = 0; vol.mdb.drNmAlBlks = (vol.vlen - 5 - vbmsz) / vol.lpa; vol.mdb.drAlBlkSiz = vol.lpa * HFS_BLOCKSZ; vol.mdb.drClpSiz = vol.mdb.drAlBlkSiz * 4; vol.mdb.drAlBlSt = 3 + vbmsz; vol.mdb.drNxtCNID = HFS_CNID_ROOTDIR; /* modified later */ vol.mdb.drFreeBks = vol.mdb.drNmAlBlks; strcpy(vol.mdb.drVN, vname); vol.mdb.drVolBkUp = 0; vol.mdb.drVSeqNum = 0; vol.mdb.drWrCnt = 0; vol.mdb.drXTClpSiz = vol.mdb.drNmAlBlks / 128 * vol.mdb.drAlBlkSiz; vol.mdb.drCTClpSiz = vol.mdb.drXTClpSiz; vol.mdb.drNmRtDirs = 0; vol.mdb.drFilCnt = 0; vol.mdb.drDirCnt = -1; /* incremented when root folder is created */ for (i = 0; i < 8; ++i) vol.mdb.drFndrInfo[i] = 0; vol.mdb.drVCSize = 0; vol.mdb.drVBMCSize = 0; vol.mdb.drCtlCSize = 0; vol.mdb.drXTFlSize = 0; vol.mdb.drCTFlSize = 0; for (i = 0; i < 3; ++i) { vol.mdb.drXTExtRec[i].xdrStABN = 0; vol.mdb.drXTExtRec[i].xdrNumABlks = 0; vol.mdb.drCTExtRec[i].xdrStABN = 0; vol.mdb.drCTExtRec[i].xdrNumABlks = 0; } /* initialize volume bitmap */ memset(vol.vbm, 0, sizeof(vbm)); /* create extents overflow file */ ext->f.vol = &vol; ext->f.parid = 0; strcpy(ext->f.name, "extents overflow"); ext->f.cat.cdrType = cdrFilRec; /* ext->f.cat.cdrResrv2 */ ext->f.cat.u.fil.filFlags = 0; ext->f.cat.u.fil.filTyp = 0; /* ext->f.cat.u.fil.filUsrWds */ ext->f.cat.u.fil.filFlNum = HFS_CNID_EXT; ext->f.cat.u.fil.filStBlk = 0; ext->f.cat.u.fil.filLgLen = 0; ext->f.cat.u.fil.filPyLen = 0; ext->f.cat.u.fil.filRStBlk = 0; ext->f.cat.u.fil.filRLgLen = 0; ext->f.cat.u.fil.filRPyLen = 0; ext->f.cat.u.fil.filCrDat = vol.mdb.drCrDate; ext->f.cat.u.fil.filMdDat = vol.mdb.drLsMod; ext->f.cat.u.fil.filBkDat = 0; /* ext->f.cat.u.fil.filFndrInfo */ ext->f.cat.u.fil.filClpSize = 0; for (i = 0; i < 3; ++i) { ext->f.cat.u.fil.filExtRec[i].xdrStABN = 0; ext->f.cat.u.fil.filExtRec[i].xdrNumABlks = 0; ext->f.cat.u.fil.filRExtRec[i].xdrStABN = 0; ext->f.cat.u.fil.filRExtRec[i].xdrNumABlks = 0; } /* ext->f.cat.u.fil.filResrv */ f_selectfork(&ext->f, 0); ext->f.clump = vol.mdb.drXTClpSiz; ext->f.flags = 0; ext->f.prev = ext->f.next = 0; n_init(&ext->hdrnd, ext, ndHdrNode, 0); ext->hdrnd.nnum = 0; ext->hdrnd.nd.ndNRecs = 3; ext->hdrnd.roff[1] = 0x078; ext->hdrnd.roff[2] = 0x0f8; ext->hdrnd.roff[3] = 0x1f8; memset(HFS_NODEREC(ext->hdrnd, 1), 0, 128); ext->hdr.bthDepth = 0; ext->hdr.bthRoot = 0; ext->hdr.bthNRecs = 0; ext->hdr.bthFNode = 0; ext->hdr.bthLNode = 0; ext->hdr.bthNodeSize = HFS_BLOCKSZ; ext->hdr.bthKeyLen = 0x07; ext->hdr.bthNNodes = 0; ext->hdr.bthFree = 0; for (i = 0; i < 76; ++i) ext->hdr.bthResv[i] = 0; map = ALLOC(char, HFS_MAP1SZ); if (map == 0) { if (result == 0) { ERROR(ENOMEM, 0); result = -1; } } else { memset(map, 0, HFS_MAP1SZ); BMSET(map, 0); } ext->map = map; ext->mapsz = HFS_MAP1SZ; ext->flags = HFS_UPDATE_BTHDR; ext->compare = r_compareextkeys; if (result == 0 && bt_space(ext, 1) < 0) result = -1; --ext->hdr.bthFree; /* create catalog file */ cat->f.vol = &vol; cat->f.parid = 0; strcpy(cat->f.name, "catalog"); cat->f.cat.cdrType = cdrFilRec; /* cat->f.cat.cdrResrv2 */ cat->f.cat.u.fil.filFlags = 0; cat->f.cat.u.fil.filTyp = 0; /* cat->f.cat.u.fil.filUsrWds */ cat->f.cat.u.fil.filFlNum = HFS_CNID_CAT; cat->f.cat.u.fil.filStBlk = 0; cat->f.cat.u.fil.filLgLen = 0; cat->f.cat.u.fil.filPyLen = 0; cat->f.cat.u.fil.filRStBlk = 0; cat->f.cat.u.fil.filRLgLen = 0; cat->f.cat.u.fil.filRPyLen = 0; cat->f.cat.u.fil.filCrDat = vol.mdb.drCrDate; cat->f.cat.u.fil.filMdDat = vol.mdb.drLsMod; cat->f.cat.u.fil.filBkDat = 0; /* cat->f.cat.u.fil.filFndrInfo */ cat->f.cat.u.fil.filClpSize = 0; for (i = 0; i < 3; ++i) { cat->f.cat.u.fil.filExtRec[i].xdrStABN = 0; cat->f.cat.u.fil.filExtRec[i].xdrNumABlks = 0; cat->f.cat.u.fil.filRExtRec[i].xdrStABN = 0; cat->f.cat.u.fil.filRExtRec[i].xdrNumABlks = 0; } /* cat->f.cat.u.fil.filResrv */ f_selectfork(&cat->f, 0); cat->f.clump = vol.mdb.drCTClpSiz; cat->f.flags = 0; cat->f.prev = cat->f.next = 0; n_init(&cat->hdrnd, cat, ndHdrNode, 0); cat->hdrnd.nnum = 0; cat->hdrnd.nd.ndNRecs = 3; cat->hdrnd.roff[1] = 0x078; cat->hdrnd.roff[2] = 0x0f8; cat->hdrnd.roff[3] = 0x1f8; memset(HFS_NODEREC(cat->hdrnd, 1), 0, 128); cat->hdr.bthDepth = 0; cat->hdr.bthRoot = 0; cat->hdr.bthNRecs = 0; cat->hdr.bthFNode = 0; cat->hdr.bthLNode = 0; cat->hdr.bthNodeSize = HFS_BLOCKSZ; cat->hdr.bthKeyLen = 0x25; cat->hdr.bthNNodes = 0; cat->hdr.bthFree = 0; for (i = 0; i < 76; ++i) cat->hdr.bthResv[i] = 0; map = ALLOC(char, HFS_MAP1SZ); if (map == 0) { if (result == 0) { ERROR(ENOMEM, 0); result = -1; } } else { memset(map, 0, HFS_MAP1SZ); BMSET(map, 0); } cat->map = map; cat->mapsz = HFS_MAP1SZ; cat->flags = HFS_UPDATE_BTHDR; cat->compare = r_comparecatkeys; if (result == 0 && bt_space(cat, 1) < 0) result = -1; --cat->hdr.bthFree; /* create root folder */ if (result == 0 && v_newfolder(&vol, HFS_CNID_ROOTPAR, vname) < 0) result = -1; vol.mdb.drNxtCNID = 16; /* finish up */ if (result == 0) { block b; /* write boot blocks */ memset(&b, 0, sizeof(b)); b_writelb(&vol, 0, &b); b_writelb(&vol, 1, &b); /* flush other disk state */ vol.flags |= HFS_UPDATE_MDB | HFS_UPDATE_ALTMDB | HFS_UPDATE_VBM; if (v_flush(&vol, 1) < 0) result = -1; } if ( #if 0 close(vol.fd) < 0 && #endif result == 0) { ERROR(errno, "error closing device"); result = -1; } FREE(vol.ext.map); FREE(vol.cat.map); return result; }