/* * 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: 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; }