/* Copyright 1992-1996 by Abacus Research and * Development, Inc. All rights reserved. */ #if !defined (OMIT_RCSID_STRINGS) char ROMlib_rcsid_hfsHier[] = "$Id: hfsHier.c 63 2004-12-24 18:19:43Z ctm $"; #endif #include "rsys/common.h" #include "OSUtil.h" #include "FileMgr.h" #include "MemoryMgr.h" #include "rsys/hfs.h" #include "rsys/file.h" typedef enum { catGet, catSet } catop; PRIVATE OSErr cathelper(CInfoPBPtr pb, BOOLEAN async, catop op) { filekind kind; filerec *frp; void *voidp; directoryrec *drp; HFileInfo *pbf; DirInfo *pbd; OSErr err, err1; btparam btparamrec; HVCB *vcbp; catkey *catkeyp; BOOLEAN ignorename; vcbp = 0; if (CW(pb->hFileInfo.ioFDirIndex) > 0 && op == catGet) { err = ROMlib_btpbindex((ioParam *) pb, CL(pb->hFileInfo.ioDirID), &vcbp, &frp, &catkeyp, FALSE); if (err != noErr) goto done; voidp = DATAPFROMKEY(catkeyp); switch (((filerec *)voidp)->cdrType) { case FILETYPE: kind = regular; break; case DIRTYPE: kind = directory; break; default: warning_unexpected ("unknown cdrtype in cathelper"); err = fsDSIntErr; goto done; break; } } else { if (CW(pb->hFileInfo.ioFDirIndex) < 0) { kind = directory; ignorename = TRUE; } else { kind = regular | directory; ignorename = FALSE; } err = ROMlib_findvcbandfile((ioParam *) pb, CL(pb->hFileInfo.ioDirID), &btparamrec, &kind, ignorename); if (err != noErr) goto done; vcbp = btparamrec.vcbp; if (op == catSet) { err = ROMlib_writevcbp (vcbp); if (err != noErr) goto done; } voidp = DATAPFROMKEY(btparamrec.foundp); catkeyp = (catkey *) btparamrec.foundp; } switch (kind) { case regular: frp = voidp; pbf = (HFileInfo *) pb; if (op == catGet) { if (UPDATE_IONAMEPTR_P(*pbf)) str255assign(MR(pbf->ioNamePtr), catkeyp->ckrCName); pbf->ioACUser = 0; pbf->ioFlAttrib = CB (open_attrib_bits (CL (frp->filFlNum), vcbp, &pbf->ioFRefNum)); pbf->ioFlAttrib |= frp->filFlags & CB (INHERITED_FLAG_BITS); memmove(&pbf->ioFlFndrInfo, &frp->filUsrWds, (LONGINT) sizeof(pbf->ioFlFndrInfo)); pbf->ioDirID = frp->filFlNum; pbf->ioFlStBlk = frp->filStBlk; pbf->ioFlLgLen = frp->filLgLen; pbf->ioFlPyLen = frp->filPyLen; pbf->ioFlRStBlk = frp->filRStBlk; pbf->ioFlRLgLen = frp->filRLgLen; pbf->ioFlRPyLen = frp->filRPyLen; pbf->ioFlCrDat = frp->filCrDat; pbf->ioFlMdDat = frp->filMdDat; pbf->ioFlBkDat = frp->filBkDat; memmove(&pbf->ioFlXFndrInfo, frp->filFndrInfo, (LONGINT) sizeof(pbf->ioFlXFndrInfo)); pbf->ioFlParID = catkeyp->ckrParID; pbf->ioFlClpSiz = frp->filClpSize; } else { frp->filFlags &= ~FILEFLAGSUSERSETTABLEMASK; frp->filFlags |= FILEFLAGSUSERSETTABLEMASK &pbf->ioFlAttrib; memmove(&frp->filUsrWds, &pbf->ioFlFndrInfo, (LONGINT) sizeof(frp->filUsrWds)); frp->filCrDat = pbf->ioFlCrDat; frp->filMdDat = pbf->ioFlMdDat; frp->filBkDat = pbf->ioFlBkDat; memmove(&frp->filFndrInfo, &pbf->ioFlXFndrInfo, (LONGINT) sizeof(frp->filFndrInfo)); frp->filClpSize = pbf->ioFlClpSiz; ROMlib_dirtyleaf(frp, vcbp); err = ROMlib_flushvcbp (vcbp); } break; case directory: drp = voidp; pbd = (DirInfo *) pb; if (op == catGet) { if (UPDATE_IONAMEPTR_P(*pbd)) str255assign(MR(pbd->ioNamePtr), catkeyp->ckrCName); pbd->ioACUser = 0; /* NOTE: IMIV-155 claims that pbd->ioFRefNum is updated, but the Mac+ doesn't do the updating */ pbd->ioFlAttrib = drp->dirFlags >> 8; pbd->ioFlAttrib |= ATTRIB_ISADIR; memmove(&pbd->ioDrUsrWds, drp->dirUsrInfo, (LONGINT) sizeof(pbd->ioDrUsrWds)); pbd->ioDrDirID = drp->dirDirID; pbd->ioDrNmFls = drp->dirVal; pbd->ioDrCrDat = drp->dirCrDat; pbd->ioDrMdDat = drp->dirMdDat; pbd->ioDrBkDat = drp->dirBkDat; memmove(&pbd->ioDrFndrInfo, drp->dirFndrInfo, (LONGINT) sizeof(pbd->ioDrFndrInfo)); pbd->ioDrParID = catkeyp->ckrParID; } else { #if 0 /* I don't think you can change any directory flags */ drp->dirFlags = pbd->ioFlAttrib; #endif memmove(&drp->dirUsrInfo, &pbd->ioDrUsrWds, (LONGINT) sizeof(drp->dirUsrInfo)); drp->dirCrDat = pbd->ioDrCrDat; drp->dirMdDat = pbd->ioDrMdDat; drp->dirBkDat = pbd->ioDrBkDat; memmove(&drp->dirFndrInfo, &pbd->ioDrCrDat, (LONGINT) sizeof(drp->dirFndrInfo)); ROMlib_dirtyleaf(drp, vcbp); err = ROMlib_flushvcbp (vcbp); } break; default: warning_unexpected ("unknown kind in cathelper"); err = fsDSIntErr; goto done; break; } done: err1 = vcbp ? ROMlib_cleancache(vcbp) : noErr; if (err == noErr) err = err1; fs_err_hook (err); PBRETURN((ioParam *) pb, err); } PUBLIC OSErr hfsPBGetCatInfo(CInfoPBPtr pb, BOOLEAN async) { OSErr err; err = cathelper(pb, async, catGet); fs_err_hook (err); return err; } PUBLIC OSErr hfsPBSetCatInfo(CInfoPBPtr pb, BOOLEAN async) { OSErr err; err = cathelper(pb, async, catSet); fs_err_hook (err); return err; } PRIVATE OSErr parentchild(HVCB *vcbp, catkey *parentcatp, directoryrec *parentdirp, catkey *childcatp, directoryrec *childdirp) { OSErr err; LONGINT parid, newid; INTEGER ctref; btparam btparamrec; err = noErr; parid = CL(parentdirp->dirDirID); if (parid == CL(childdirp->dirDirID)) err = badMovErr; /* can't move into oneself */ else if (parentdirp->dirVal != 0) { /* no need to check if no children */ if (parid <= 2) /* automatic disqualification; can't move */ err = badMovErr; /* root directory */ else { newid = CL(childcatp->ckrParID); err = ROMlib_makecatparam(&btparamrec, vcbp, (LONGINT) 0, 0, (Ptr) 0); ctref = CW(vcbp->vcbCTRef); while (err == noErr && newid > 2 && newid != parid) { btparamrec.tofind.catk.ckrParID = CL(newid); err = ROMlib_keyfind(&btparamrec); if (err == noErr && !btparamrec.success) { err = fsDSIntErr; warning_unexpected ("no success in parentchild"); } newid = CL( ((threadrec *)DATAPFROMKEY(btparamrec.foundp))->thdParID); } if (err == noErr) err = newid <= 2 ? noErr : badMovErr; } } fs_err_hook (err); return err; } PUBLIC OSErr hfsPBCatMove(CMovePBPtr pb, BOOLEAN async) { OSErr err, err1; filekind srccurkind, dstcurkind; ioParam iop; btparam srcbtparam, dstdirbtparam, dstbtparam; directoryrec *dstdirdrp; directoryrec srcdrec; filerec srcfrec; BOOLEAN ignorename; srccurkind = regular | directory; err = ROMlib_findvcbandfile((ioParam *) pb, CL(pb->ioDirID), &srcbtparam, &srccurkind, FALSE); if (err == noErr) { err = ROMlib_writevcbp(srcbtparam.vcbp); iop = *(ioParam *)pb; iop.ioNamePtr = pb->ioNewName; dstcurkind = directory; ignorename = iop.ioNamePtr == 0; err = ROMlib_findvcbandfile(&iop, CL(pb->ioNewDirID), &dstdirbtparam, &dstcurkind, ignorename); if (err == noErr) { if (srcbtparam.vcbp != dstdirbtparam.vcbp) err = badMovErr; else { dstdirdrp = (directoryrec *) DATAPFROMKEY(dstdirbtparam.foundp); dstbtparam = dstdirbtparam; err = ROMlib_makecatkey((catkey *) &dstbtparam.tofind, CL(dstdirdrp->dirDirID), srcbtparam.foundp->catk.ckrCName[0], (Ptr) srcbtparam.foundp->catk.ckrCName+1); dstbtparam.leafindex = -1; err = ROMlib_keyfind (&dstbtparam); if (err != noErr) ; else if (dstbtparam.success) err = dupFNErr; else { dstbtparam.leafindex = -1; if (srccurkind == directory) { srcdrec = *(directoryrec *) DATAPFROMKEY(srcbtparam.foundp); if (err == noErr) err = parentchild(srcbtparam.vcbp, (catkey *) srcbtparam.foundp, &srcdrec, (catkey *) dstdirbtparam.foundp, dstdirdrp); /* * NOTE: Even though it is less safe to delete and then create (an * untimely power hit loses the file), we need to do it in this * order or greatly rework things. The problem is that if we * do a create followed by a delete, we wind up putting in another * thread record WITH A DUPLICATE KEY, which means that the dirdelete * may will the wrong thread record when moving directories up. */ if (err == noErr) err = ROMlib_dirdelete(&srcbtparam); if (err == noErr) err = ROMlib_dircreate(&dstbtparam, &srcdrec); } else { srcfrec = *(filerec *) DATAPFROMKEY(srcbtparam.foundp); if (err == noErr) err = ROMlib_filecreate(&dstbtparam, &srcfrec, regular); if (err == noErr) { srcbtparam.leafindex = -1; err = ROMlib_filedelete(&srcbtparam, regular); } } } } } } err1 = ROMlib_cleancache(srcbtparam.vcbp); if (err1 == noErr) err1 = ROMlib_flushvcbp(srcbtparam.vcbp); if (err == noErr) err = err1; fs_err_hook (err); PBRETURN(pb, err); }