/* * NAME: vol->readmdb() * DESCRIPTION: load Master Directory Block into memory */ int v_readmdb(hfsvol *vol) { if (l_getmdb(vol, &vol->mdb, 0) == -1) goto fail; if (vol->mdb.drSigWord != HFS_SIGWORD) { if (vol->mdb.drSigWord == HFS_SIGWORD_MFS) ERROR(EINVAL, "MFS volume format not supported"); else ERROR(EINVAL, "not a Macintosh HFS volume"); } if (vol->mdb.drAlBlkSiz % HFS_BLOCKSZ != 0) ERROR(EINVAL, "bad volume allocation block size"); vol->lpa = vol->mdb.drAlBlkSiz >> HFS_BLOCKSZ_BITS; /* extents pseudo-file structs */ vol->ext.f.cat.u.fil.filStBlk = vol->mdb.drXTExtRec[0].xdrStABN; vol->ext.f.cat.u.fil.filLgLen = vol->mdb.drXTFlSize; vol->ext.f.cat.u.fil.filPyLen = vol->mdb.drXTFlSize; vol->ext.f.cat.u.fil.filCrDat = vol->mdb.drCrDate; vol->ext.f.cat.u.fil.filMdDat = vol->mdb.drLsMod; vol->ext.f.cat.u.fil.filClpSize = vol->mdb.drXTClpSiz; memcpy(&vol->ext.f.cat.u.fil.filExtRec, &vol->mdb.drXTExtRec, sizeof(ExtDataRec)); f_selectfork(&vol->ext.f, fkData); /* catalog pseudo-file structs */ vol->cat.f.cat.u.fil.filStBlk = vol->mdb.drCTExtRec[0].xdrStABN; vol->cat.f.cat.u.fil.filLgLen = vol->mdb.drCTFlSize; vol->cat.f.cat.u.fil.filPyLen = vol->mdb.drCTFlSize; vol->cat.f.cat.u.fil.filCrDat = vol->mdb.drCrDate; vol->cat.f.cat.u.fil.filMdDat = vol->mdb.drLsMod; vol->cat.f.cat.u.fil.filClpSize = vol->mdb.drCTClpSiz; memcpy(&vol->cat.f.cat.u.fil.filExtRec, &vol->mdb.drCTExtRec, sizeof(ExtDataRec)); f_selectfork(&vol->cat.f, fkData); return 0; fail: return -1; }
/* * NAME: file->init() * DESCRIPTION: initialize file structure */ void f_init(hfsfile *file, hfsvol *vol, long cnid, const char *name) { int i; file->vol = vol; file->parid = 0; strcpy(file->name, name); file->cat.cdrType = cdrFilRec; file->cat.cdrResrv2 = 0; file->cat.u.fil.filFlags = 0; file->cat.u.fil.filTyp = 0; file->cat.u.fil.filUsrWds.fdType = 0; file->cat.u.fil.filUsrWds.fdCreator = 0; file->cat.u.fil.filUsrWds.fdFlags = 0; file->cat.u.fil.filUsrWds.fdLocation.v = 0; file->cat.u.fil.filUsrWds.fdLocation.h = 0; file->cat.u.fil.filUsrWds.fdFldr = 0; file->cat.u.fil.filFlNum = cnid; file->cat.u.fil.filStBlk = 0; file->cat.u.fil.filLgLen = 0; file->cat.u.fil.filPyLen = 0; file->cat.u.fil.filRStBlk = 0; file->cat.u.fil.filRLgLen = 0; file->cat.u.fil.filRPyLen = 0; file->cat.u.fil.filCrDat = 0; file->cat.u.fil.filMdDat = 0; file->cat.u.fil.filBkDat = 0; file->cat.u.fil.filFndrInfo.fdIconID = 0; for (i = 0; i < 4; ++i) file->cat.u.fil.filFndrInfo.fdUnused[i] = 0; file->cat.u.fil.filFndrInfo.fdComment = 0; file->cat.u.fil.filFndrInfo.fdPutAway = 0; file->cat.u.fil.filClpSize = 0; for (i = 0; i < 3; ++i) { file->cat.u.fil.filExtRec[i].xdrStABN = 0; file->cat.u.fil.filExtRec[i].xdrNumABlks = 0; file->cat.u.fil.filRExtRec[i].xdrStABN = 0; file->cat.u.fil.filRExtRec[i].xdrNumABlks = 0; } file->cat.u.fil.filResrv = 0; f_selectfork(file, fkData); file->flags = 0; file->prev = 0; file->next = 0; }
/* * NAME: hfs->setfork() * DESCRIPTION: select file fork for I/O operations */ int hfs_setfork(hfsfile *file, int fork) { int result = 0; f_selectfork(file, fork ? fkRsrc : fkData); return result; }
/* * NAME: hfs->setfork() * DESCRIPTION: select file fork for I/O operations */ int hfs_setfork(hfsfile *file, int fork) { int result = 0; if (f_trunc(file) == -1) result = -1; f_selectfork(file, fork ? fkRsrc : fkData); return result; }
/* * NAME: hfs->setfork() * DESCRIPTION: select file fork for I/O operations */ int hfs_setfork(hfsfile *file, int fork) { int result = 0; if (! (file->vol->flags & HFS_READONLY) && f_trunc(file) < 0) result = -1; f_selectfork(file, fork); return result; }
/* * NAME: hfs->open() * DESCRIPTION: prepare a file for I/O */ hfsfile *hfs_open(hfsvol *vol, const char *path) { hfsfile *file = 0; hfsfile *f = 0; if (getvol(&vol) == -1) ERROR(ENODEV, 0); file = ALLOC(hfsfile, 1); if (file == 0) ERROR(ENOMEM, 0); if (v_resolve(&vol, path, &file->cat, &file->parid, file->name, 0) <= 0) ERROR(ENOENT, 0); if (file->cat.cdrType != cdrFilRec) ERROR(EISDIR, 0); // see if it's already open for(f = vol->files; f; f = f->next) { if (f->cat.u.fil.filFlNum == file->cat.u.fil.filFlNum) { // already open, increment refcount and return FREE(file); file = f; file->refs++; printf("REOPEN: file %s now has %d refs\n", path, file->refs); return file; } } /* package file handle for user */ file->refs = 1; file->vol = vol; file->flags = 0; f_selectfork(file, fkData); file->prev = 0; file->next = vol->files; if (vol->files) vol->files->prev = file; vol->files = file; return file; fail: FREE(file); return 0; }
/* * NAME: hfs->open() * DESCRIPTION: prepare a file for I/O */ hfsfile *hfs_open(hfsvol *vol, char *path) { hfsfile *file; if (v_getvol(&vol) < 0) return 0; file = ALLOC(hfsfile, 1); if (file == 0) { ERROR(ENOMEM, 0); return 0; } if (v_resolve(&vol, path, &file->cat, &file->parid, file->name, 0) <= 0) { FREE(file); return 0; } if (file->cat.cdrType != cdrFilRec) { FREE(file); ERROR(EISDIR, 0); return 0; } file->vol = vol; file->clump = file->cat.u.fil.filClpSize; file->flags = 0; f_selectfork(file, 0); file->prev = 0; file->next = vol->files; if (vol->files) vol->files->prev = file; vol->files = file; return file; }
/* * NAME: hfs->open() * DESCRIPTION: prepare a file for I/O */ hfsfile *hfs_open(hfsvol *vol, const char *path) { hfsfile *file = NULL; if (getvol(&vol) == -1) goto fail; file = ALLOC(hfsfile, 1); if (file == NULL) ERROR(ENOMEM, NULL); if (v_resolve(&vol, path, &file->cat, &file->parid, file->name, NULL) <= 0) goto fail; if (file->cat.cdrType != cdrFilRec) ERROR(EISDIR, NULL); /* package file handle for user */ file->vol = vol; file->flags = 0; f_selectfork(file, fkData); file->prev = NULL; file->next = vol->files; if (vol->files) vol->files->prev = file; vol->files = file; return file; fail: FREE(file); return NULL; }
/* * 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: hfs->delete() * DESCRIPTION: remove both forks of a file */ int hfs_delete(hfsvol *vol, const char *path) { hfsfile file; CatKeyRec key; byte pkey[HFS_CATKEYLEN]; int found; if (getvol(&vol) == -1 || v_resolve(&vol, path, &file.cat, &file.parid, file.name, 0) <= 0) goto fail; if (file.cat.cdrType != cdrFilRec) ERROR(EISDIR, 0); if (file.parid == HFS_CNID_ROOTPAR) ERROR(EINVAL, 0); if (vol->flags & HFS_VOL_READONLY) ERROR(EROFS, 0); /* free allocation blocks */ file.vol = vol; file.flags = 0; file.cat.u.fil.filLgLen = 0; file.cat.u.fil.filRLgLen = 0; f_selectfork(&file, fkData); if (f_trunc(&file) == -1) goto fail; f_selectfork(&file, fkRsrc); if (f_trunc(&file) == -1) goto fail; /* delete file record */ r_makecatkey(&key, file.parid, file.name); r_packcatkey(&key, pkey, 0); if (bt_delete(&vol->cat, pkey) == -1 || v_adjvalence(vol, file.parid, 0, -1) == -1) goto fail; /* delete file thread, if any */ found = v_getfthread(vol, file.cat.u.fil.filFlNum, 0, 0); if (found == -1) goto fail; if (found) { r_makecatkey(&key, file.cat.u.fil.filFlNum, ""); r_packcatkey(&key, pkey, 0); if (bt_delete(&vol->cat, pkey) == -1) goto fail; } 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; }
/* * NAME: hfs->delete() * DESCRIPTION: remove both forks of a file */ int hfs_delete(hfsvol *vol, char *path) { hfsfile file; CatKeyRec key; unsigned char pkey[HFS_CATKEYLEN]; int found; if (v_getvol(&vol) < 0 || v_resolve(&vol, path, &file.cat, &file.parid, file.name, 0) <= 0) return -1; if (file.cat.cdrType != cdrFilRec) { ERROR(EISDIR, 0); return -1; } if (file.parid == HFS_CNID_ROOTPAR) { ERROR(EINVAL, 0); return -1; } if (vol->flags & HFS_READONLY) { ERROR(EROFS, 0); return -1; } /* free disk blocks */ file.vol = vol; file.flags = 0; file.cat.u.fil.filLgLen = 0; file.cat.u.fil.filRLgLen = 0; f_selectfork(&file, 0); if (f_trunc(&file) < 0) return -1; f_selectfork(&file, 1); if (f_trunc(&file) < 0) return -1; /* delete file record */ r_makecatkey(&key, file.parid, file.name); r_packcatkey(&key, pkey, 0); if (bt_delete(&vol->cat, pkey) < 0 || v_adjvalence(vol, file.parid, 0, -1) < 0) return -1; /* delete file thread, if any */ found = v_getfthread(vol, file.cat.u.fil.filFlNum, 0, 0); if (found < 0) return -1; if (found) { r_makecatkey(&key, file.cat.u.fil.filFlNum, (char *)""); r_packcatkey(&key, pkey, 0); if (bt_delete(&vol->cat, pkey) < 0) return -1; } return 0; }