; ; File: CMSvcsExtras.a ; ; Copyright: © 1989-1991 by Apple Computer, Inc., all rights reserved. ; ; Change History (most recent first): ; ; <7> 9/13/91 JSM Cleanup header. ; <6> 1/14/91 KST With dnf and BB: Changed MarkVCBTime to MarkVCB so the VCB will ; be marked dirty. Added a patch to fix the same problem for ; CMCreateCN and CMUpdateCN. ; <5> 12/18/90 dnf (dba) Move the come-from patches out of here and into ; FileMgrPatches.a. ; <4> 7/30/90 dnf Change myCMSetUp into a patch proc. Rename rom references and ; use jsrROM macros. ; <3> 3/6/90 KST CMDeleteCN patch branched to a wrong lable that it clears D0 and ; wipe out the error code. ; <2> 2/4/90 DNF Remove include of HFS70Equ.a ; <1.5> 12/8/89 dnf Change order of includes to accomodate changes in HFS70Equ.a ; <1.4> 9/29/89 EKN Document bit 9 in Delete for File threads usage. ; 9/11/89 EKN Document bit 9's usage in Delete for file threads ; <1.3> 5/31/89 EKN use +2s for CmpBind stuff for CmRename, CMDelete, CMMove ; <1.1> 5/31/89 EKN Made sure my CMRename, CMDelete, CMMove are called.SubmitF -p ; <1.2> 5/31/89 EKN Get the stupid EASE comments out of here! ; <1.0> 5/30/89 dnf Integrate CatSearch, FileID's and Desktop Database Mgr into one ; ptch ; 5/30/89 EKN Patching out existing Delete, Rename, and Move. ; ;_________________________________________________________________________________ ; ; External ; Routines: CMDeleteCN - Deletes an existing directory or file CNode. ; CMMoveCN - Moves an existing directory or file CNode to ; another directory CNode. ; CMRenameCN - Renames an existing directory or file CNode; ; ;_________________________________________________________________________________ LOAD 'StandardEqu.d' include 'LinkedPatchMacros.a' ;_________________________________________________________________________________ ; ; Routine: CMDeleteCN (Delete CNode) ; ; Function: Deletes an existing directory or file CNode. The catalog ; BTree is first searched the designated CNode record. ; If not found, an error is returned. If found, the record for ; that CNode is deleted from the catalog. The thread record ; is also deleted for directories. And the file thread record ; for files, if one exists. Note that the valence for ; a directory must be zero before it can be deleted. ; ; Input: A2.L - VCB pointer ; D0.L - DirID or parent DirID ; A0.L - CName pointer ; ; Output: D0.W - result code ; 0 = ok ; CMnotfound = CNode not found ; CMnotempty = directory not empty ; CMRootCN = root CNode was referenced ; -n = IO error ;_________________________________________________________________________________ CMDeleteCNAfterSetup proc export unusedBit EQU 9 ; pick unused bit in a register (D4 only uses abyte) ; MOVE.L (SP)+,-(A6) ; save return address on A6 stack ; MOVEM.L D1-D6/A0-A1/A3-A4,-(A6) ; save regs ; ; set up some common stuff ; ; BSR CMSetUp ; common set up routine <25Oct85> ; ROM code to here ;_________________________________________________________________________ CLR.L VCBDirIDM(A2) ; invalidate current DirID marker MOVE.L D0,D3 ; D3 = parID MOVEA.L A0,A3 ; A3 = CName pointer ; ; locate subject CNode ; MOVEQ #0,D2 ; no hint jsrROM romLocCNode ; locate the CNode BNE DCExit1 ; didn't find it, exit -> MOVE.B cdrType(A1),D4 ; D4 = CNode record type BCLR #unusedBit, D4 ; for determining when to process file thds diffently MOVE.L ckrParID(A0),D6 ; D6 = CNode ParID ; ; if directory CNode, make sure it is not the root and that it is empty ; DCCkDir CMPI.B #cdrDirRec,D4 ; directory record? BNE.S DCFDelete ; no, must be a file -> MOVE.L dirDirID(A1),D5 ; save DirID CMPI.L #FSRtDirID,D5 ; root directory? BNE.S @1 ; no -> MOVEQ #CMRootCN,D0 ; yes, set error code <16Oct85> bra DCExit1 ; exit -> @1 TST.W dirVal(A1) ; directory empty? BEQ.S DCDelete ; yes -> MOVEQ #CMnotempty,D0 ; set error code <16Oct85> bra DCExit1 ; exit -> <06Mar90> ; ; delete catalog records for CNode and file threads if they exist ; DCFDelete MOVE.L filFlNum(A1), D5 ; save file ID BTST #fThreadFlag, filFlags(A1) ; is there a file thread BEQ.S DCDelete BSET #unusedBit, D4 ; mark an unused bit implying file thread handling DCDelete LEA ckrOff(A4),A0 ; addr(key record) MOVE.W VCBCtRef(A2),D0 ; catalog file refnum jsrROM romBTDelete ; delete directory/file record BNE.S DCExit1 ; error, exit-> CMPI.B #cdrDirRec,D4 ; directory being deleted? BEQ.S DCDelThd ; yep -> BTST #unusedBit, D4 ; was the bit set implying file thread handling BEQ.S DCUpdPar ; no file thread, -> DCDelThd MOVE.L D5,D0 ; parID = directory DirID or file ID SUBA.L A0,A0 ; no CName LEA ckrOff(A4),A1 ; addr(key record buffer) jsrROM romBuildKey ; build thread key record LEA ckrOff(A4),A0 ; addr(key record) MOVE.W VCBCtRef(A2),D0 ; catalog file refnum jsrROM romBTDelete ; delete thread record BEQ.S DCUpdPar BTST #unusedBit, D4 ; if it was a file thd, just ignore the error BEQ.S DCExit1 ; ; update parent directory ; DCUpdPar MOVE.L D6,D0 ; ParID SUBA.L A0,A0 ; no Cname MOVEQ #0,D2 ; no hint jsrROM romlocCNode ; locate parent directory record BNE.S DCExit1 ; error -> SUBQ.W #1,dirVal(A1) ; decrement valence MOVE.L Time,dirMdDat(A1) ; set date/time last modified MOVE.W VCBCtRef(A2),D0 ; catalog refnum jsrROM romBTUpdate ; update the BTree record BNE.S DCExit1 ; error -> ; ; update VCB directory and file counts ; MOVE.B D4,D0 ; CNode type MOVE.L D6,D1 ; ParID MOVEQ #-1,D2 ; increment value jsrROM romUpdVCnts ; update the counts ; ; clean up and exit ; DCExit CLR.W D0 ; result = 'ok' jsrROM romMarkVCB ; Mark the VCB changed <10Jan91 #6> jsrROM romCMFlush ; flush the catalog DCExit1 ADD #lenCMVars,A6 ; de-allocate memory for CM vars MOVEM.L (A6)+,D1-D6/A0-A1/A3-A4 ; restore regs MOVE.L (A6)+,-(SP) ; put return address back on stack TST.W D0 ; set condition codes RTS ; exit CMDeleteCN endproc ;_________________________________________________________________________________ ; ; Routine: CMMoveCN (Move CNode) ; ; Function: Moves an existing directory or file CNode to another directory ; CNode. Note that for a directory, all decendants (its offspring, ; their offspring, etc.) are also moved. ; ; Input: A2.L - VCB pointer ; D0.L - source DirID or parent DirID ; A0.L - source CName pointer ; D1.L - destination DirID or parent DirID ; A1.L - destination CName pointer ; ; Output: D0.W - result code ; 0 = ok ; CMexists = A CNode already exists in destination ; directory with same CName ; -n = IO error ; D2.L - catalog hint for moved CNode ;_________________________________________________________________________________ CMMoveCNAfterSetup: Proc Export ; MOVE.L (SP)+,-(A6) ; save return address on A6 stack ; MOVEM.L D1/D3-D7/A0-A1/A3-A4,-(A6) ; save regs ; ; set up some common stuff ; ; BSR CMSetUp ; common set up routine <25Oct85> ; ROM code to here ;_________________________________________________________________________ CLR.L VCBDirIDM(A2) ; invalidate current DirID marker MOVE.L D1,D5 ; D5 = dest DirID/ParID MOVE.L A1,D6 ; D6 = dest CName ptr MOVE.L D0,D3 ; D3 = source DirID/ParID MOVEA.L A0,A3 ; A3 = source CName pointer ; ; make sure source CNode exists ; MCChkSrc MOVEQ #0,D2 ; no hint jsrROM romLocCNode ; locate the record BNE MCExit1 ; didn't find source -> MOVEQ #0,D4 ; assume source is not a directory CMPI.B #cdrDirRec,cdrType(A1) ; directory record? BNE.S MCChkDest ; no -> MOVE.L dirDirID(A1),D4 ; D4 = source DirID ; ; make sure destination directory exists ; MCChkDest MOVE.L D5,D0 ; dest DirID/ParID MOVE.L D6,A0 ; dest CName pointer MOVEQ #0,D2 ; no hint jsrROM romLocCNode ; locate the record BNE MCExit1 ; didn't find dest -> CMPI.B #cdrDirRec,cdrType(A1) ; directory record? BEQ.S @1 ; yes -> MOVE.W #BadMovErr,D0 ; set error code BRA MCExit1 ; exit -> @1 MOVE.L dirDirID(A1),D7 ; D7 = dest DirID ; ; make sure its a proper move ; MCChkMove TST.L D4 ; is source a directory? BEQ.S MCGetSrc ; no, nothing to check -> CMPI.L #FSRtDirID,D4 ; source = root? BEQ.S @3 ; yes, error -> CMP.L D4,D7 ; source = dest? BEQ.S @3 ; yes, error -> @1 MOVE.L ckrParID(A0),D0 ; source = dest ancestor? CMP.L D4,D0 ; BEQ.S @3 ; yes, error -> CMPI.L #FSRtDirID,D0 ; up to root directory? BLE.S MCGetSrc ; yes, done checking -> @2 SUBA.L A0,A0 ; locate next directory up the tree MOVEQ #0,D2 ; jsrROM romLocCNode ; BNE MCExit1 ; didn't find it -> BRA.S @1 ; continue checking -> @3 MOVE.W #BadMovErr,D0 ; result = 'bad move' BRA MCExit1 ; exit -> ; ; locate the source CNode and copy the key and data record ; MCGetSrc MOVE.L D3,D0 ; source DirID/ParID MOVEA.L A3,A0 ; source CName pointer MOVEQ #0,D2 ; no hint jsrROM romLocCNode ; locate the record BNE MCExit1 ; didn't find it -> CMP.L ckrParID(A0),D7 ; source ParID = dest DirID? BNE.S @2 ; no -> MOVE.L D2,D7 ; D7 = new hint BRA MCExit ; all done -> @2 MOVE.L A1,-(SP) ; save ptr(data record) LEA ckrOff(A4),A1 ; dest = key record in CM vars MOVEQ #1,D0 ; get key length (include length byte) ADD.B (A0),D0 ; _BlockMove ; copy the key MOVEA.L (SP)+,A0 ; A0 = ptr(data record) LEA cdrOff(A4),A1 ; dest = data record in CM vars MOVE.W D1,D0 ; length = len(data record) EXT.L D0 ; _BlockMove ; copy the data record ; ; insert new source CNode record in BTree with new key ; MCInsert LEA ckrOff(A4),A0 ; addr(key record) MOVE.L ckrParID(A0),D4 ; D4 = source ParID MOVE.L D7,ckrParID(A0) ; set ParID to new one LEA cdrOff(A4),A1 ; addr(source data record) MOVEQ #lenfil,D1 ; assume its a file record CMPI.B #cdrFilRec,cdrType(A1) ; file record? BEQ.S @1 ; yes -> MOVEQ #lendir,D1 ; use length of a directory record MOVE.L Time,dirMdDat(A1) ; set date/time last modified @1 MOVE.W VCBCtRef(A2),D0 ; catalog file refnum jsrROM romBTInsert ; insert the new record BEQ.S @2 ; ok -> CMPI.W #BTexists,D0 ; record already exist? BNE MCExit1 ; no, some other error -> MOVEQ #CMExists,D0 ; result = 'CNode already exists' <16Oct85> BNE MCExit1 ; exit -> @2 MOVE.L D2,D7 ; D7 = new hint MOVE.L ckrParID(A0),D0 ; D0 = dest DirID ; ; update destination directory record ; MCUpdDest EXG D5,D0 ; D0 = dest DirID/ParID, D5 = dest DirID MOVE.L D6,A0 ; dest CName pointer MOVEQ #0,D2 ; no hint jsrROM romLocCNode ; locate the record BNE MCExit1 ; didn't find it -> ADDQ.W #1,dirVal(A1) ; bump its valence MOVE.L Time,dirMdDat(A1) ; set date/time last modified MOVE.W VCBCtRef(A2),D0 ; catalog file refnum jsrROM romBTUpdate ; update the BTree record BNE MCExit1 ; error -> ; ; update root directory counts ; LEA cdrOff(A4),A1 ; ptr(source data record) MOVE.B cdrType(A1),D0 ; Cnode Type MOVE.L D5,D1 ; dest DirID MOVEQ #1,D2 ; increment jsrROM romUpdRtCnts ; update the counts ; ; delete old source CNode record ; MCDelSrc MOVE.L D3,D0 ; source DirID/ParID MOVEA.L A3,A0 ; source CName pointer MOVEQ #0,D2 ; no hint jsrROM romLocCNode ; locate the record BNE MCExit1 ; didn't find it -> LEA ckrOff(A4),A0 ; addr(key record) MOVE.W VCBCtRef(A2),D0 ; catalog file refnum jsrROM romBTDelete ; delete directory/file record BNE.S MCExit1 ; error -> ; ; update source thread record if a directory was moved ; MCUpdThd LEA cdrOff(A4),A1 ; ptr(source data record) CMPI.B #cdrDirRec,cdrType(A1) ; source = directory? BEQ.S MCUpdDThd BTST #fThreadFlag, filFlags(A1) BEQ.S MCUpdPar ; no file thread -> MOVE.L filFlNum(A1), D0 BRA.S MCUpdThd1 MCUpdDThd MOVE.L dirDirID(A1),D0 ; source DirID MCUpdThd1 SUBA.L A0,A0 ; no Cname MOVEQ #0,D2 ; no hint jsrROM romLocCRec ; locate thread record BNE.S MCExit1 ; didn't find it -> MOVE.L D5,thdParID(A1) ; new ParID = dest DirID MOVE.W VCBCtRef(A2),D0 ; catalog file refnum jsrROM romBTUpdate ; update BTree record BNE.S MCExit1 ; error -> ; ; update source parent directory ; MCUpdPar MOVE.L D4,D0 ; source ParID SUBA.L A0,A0 ; no Cname MOVEQ #0,D2 ; no hint jsrROM romlocCNode ; locate parent directory record BNE.S MCExit1 ; didn't find it -> SUBQ.W #1,dirVal(A1) ; decrement valence MOVE.L Time,dirMdDat(A1) ; set date/time last modified MOVE.W VCBCtRef(A2),D0 ; catalog file refnum jsrROM romBTUpdate ; update the BTree record BNE.S MCExit1 ; error -> ; ; update root directory counts ; LEA cdrOff(A4),A1 ; ptr(source data record) MOVE.B cdrType(A1),D0 ; Cnode Type MOVE.L D4,D1 ; source ParID MOVEQ #-1,D2 ; increment jsrROM romUpdRtCnts ; update the counts ; ; clean up and exit ; MCExit CLR.W D0 ; result = 'ok' MOVE.L D7,D2 ; return new hint in D2 jsrROM romMarkVCB ; Mark the VCB changed <10Jan91 #6> jsrROM romCMFlush ; flush the catalog MCExit1 ADD #lenCMVars,A6 ; de-allocate memory for CM vars MOVEM.L (A6)+,D1/D3-D7/A0-A1/A3-A4 ; restore regs MOVE.L (A6)+,-(SP) ; put return address back on stack TST.W D0 ; set condition codes RTS ; exit CMMoveCN EndProc ;_________________________________________________________________________________ ; ; Routine: CMRenameCN (Rename CNode) ; ; Function: Renames an existing directory or file CNode. ; ; Input: A2.L - VCB pointer ; D0.L - DirID or parent DirID ; A0.L - CName pointer ; A1.L - CName pointer (new CName) ; D2.L - catalog hint ; ; Output: D0.W - result code ; 0 = ok ; CMnotfound = CNode not found ; CMexists = CNode already exists for new CName ; -n = IO error ; D2.L - new catalog hint ;_________________________________________________________________________________ CMRenameCNAfterSetup Proc Export Export CMRenameCNExit1 ; used for patch ; MOVE.L (SP)+,-(A6) ; save return address on A6 stack ; MOVEM.L D1/D3-D7/A0-A1/A3-A4,-(A6) ; save regs ; ; set up some common stuff ; ; BSR CMSetUp ; common set up routine <25Oct85> ; ROM code to here ;_________________________________________________________________________ CLR.L VCBDirIDM(A2) ; invalidate current DirID marker MOVE.L D0,D3 ; D3 = parID MOVEA.L A0,A3 ; A3 = ptr(old CName) MOVE.L A1,D5 ; D5 = ptr(new CName) ; ; locate subject CNode ; jsrROM romLocCNode ; locate the CNode BNE RCExit1 ; didn't find it, exit -> MOVE.L D2,D4 ; D4 = hint for old CNode record MOVE.W D1,D6 ; D6 = len(CNode data record) ; ; save copy of data record ; MOVEA.L A1,A0 ; source ptr = cdr LEA cdrOff(A4),A1 ; dest ptr = CM vars MOVE.W D6,D0 ; length = len(data record) EXT.L D0 ; _BlockMove ; copy the record ; ; insert old CNode record in BTree with new key ; RCInsert LEA ckrOff(A4),A1 ; addr(key record buffer) MOVE.L ckrParID(A1),D0 ; ParID = same as before MOVEA.L D5,A0 ; new CName ptr jsrROM romBuildKey ; build new key MOVEA.L A1,A0 ; addr(key record) LEA cdrOff(A4),A1 ; addr(data record) ;MOVE.L Time,D0 ; get date/time <31Oct85> ;CMPI.B #cdrDirRec,cdrType(A1) ; directory CNode? <31Oct85> ;BNE.S @1 ; no -> <31Oct85> ;MOVE.L D0,dirMdDat(A1) ; set date/time last modified <31Oct85> ;BRA.S @2 ; -> <31Oct85> ;@1 MOVE.L D0,filMdDat(A1) ; set date/time last modified <31Oct85> @2 MOVE.W D6,D1 ; record size MOVE.W VCBCtRef(A2),D0 ; catalog file refnum jsrROM romBTInsert ; insert the new record BEQ.S RCDelOld ; ok -> <09Sep85> CMP.W #BTExists,D0 ; CNode already exist? <09Sep85> BNE RCExit1 ; no, some other error -> <09Sep85> ; ; new CNode already exists, locate the existing one ; LEA ckrOff(A4),A1 ; ptr(key record buffer) <09Sep85> MOVE.L ckrParID(A1),D0 ; ParID = same as before <09Sep85> MOVEA.L D5,A0 ; new CName ptr <09Sep85> MOVEQ #0,D2 ; no hint <09Sep85> jsrROM romLocCNode ; locate the CNode <09Sep85> BNE RCExit1 ; error -> <09Sep85> MOVE.L D2,D7 ; save new hint ; ; check if same CNode ; RCChkSame MOVE.L A0,D6 ; save ptr to ckr in BTree node <09Sep85> LEA cdrOff(A4),A0 ; p0int to old data record MOVE.B cdrType(A0),D0 ; same CNode type? CMP.B cdrType(A1),D0 ; BNE.S @2 ; no, error -> CMPI.B #cdrDirRec,D0 ; directory CNode? BNE.S @1 ; no -> MOVE.L dirDirID(A1),D1 ; same DirID? CMP.L dirDirID(A0),D1 ; BEQ.S RCReplace ; yes, replace the name -> <09Sep85> BRA.S @2 ; no, error -> @1 MOVE.L filFlNum(A1),D1 ; same file number? CMP.L filFlNum(A0),D1 ; BEQ.S RCReplace ; yes, replace the name -> <09Sep85> @2 MOVEQ #CMExists,D0 ; result = 'CNode already exists' <16Oct85> BRA RCExit1 ; exit -> ; ; replace the name in the existing CNode key ; RCReplace MOVEA.L D6,A1 ; restore ptr to ckr buffer <09Sep85> LEA ckrCName(A1),A1 ; dest = CName in ckr <09Sep85> MOVEA.L D5,A0 ; source = new CName <09Sep85> jsrROM romUpdCName ; replace the name <09Sep85> MOVE.W VCBCtRef(A2),D0 ; catalog file refnum <09Sep85> jsrROM romBTUpdate ; update BTree record <09Sep85> BRA.S RCUpdThd ; update thread -> <09Sep85> ; ; delete old CNode record ; RCDelOld MOVE.L D2,D7 ; save hint for new record MOVE.L D3,D0 ; DirID/ParID MOVEA.L A3,A0 ; CName pointer MOVE.L D4,D2 ; hint jsrROM romLocCNode ; locate the record BNE.S RCExit1 ; didn't find it -> LEA ckrOff(A4),A0 ; addr(key record) MOVE.W VCBCtRef(A2),D0 ; catalog file refnum MOVEQ #0,D2 ; no hint jsrROM romBTDelete ; delete directory/file record BNE.S RCExit1 ; error, exit-> ; ; update thread record if a directory was renamed ; RCUpdThd LEA cdrOff(A4),A1 ; ptr to cdr in CM buffer <09Sep85> CMPI.B #cdrDirRec,cdrType(A1) ; directory CNode? BEQ.S RCUpdDThd BTST #fThreadFlag, filFlags(A1) BEQ.S RCExit ; no file thread, all done -> MOVE.L filFlNum(A1), D0 BRA.S RCUpdThd1 RCUpdDThd MOVE.L dirDirID(A1),D0 ; source DirID RCUpdThd1 SUBA.L A0,A0 ; no Cname CLR.L D2 ; no hint jsrROM romLocCRec ; locate thread record BNE.S RCExit1 ; didn't find it -> MOVEA.L D5,A0 ; ptr to new CName LEA thdCName(A1),A1 ; ptr to CName in thread record jsrROM romUpdCName ; update the CName <09Sep85> MOVE.W VCBCtRef(A2),D0 ; catalog file refnum jsrROM romBTUpdate ; update BTree record ; ; clean up and exit ; RCExit CLR.W D0 ; result = 'ok' MOVE.L D7,D2 ; return new hint in D2 jsrROM romMarkVCB ; Mark the VCB changed <10Jan91 #6> jsrROM romCMFlush ; flush the catalog RCExit1 CMRenameCNExit1: ADD #lenCMVars,A6 ; de-allocate memory for CM vars MOVEM.L (A6)+,D1/D3-D7/A0-A1/A3-A4 ; restore regs MOVE.L (A6)+,-(SP) ; put return address back on stack TST.W D0 ; set condition codes RTS ; exit CMRenameCN EndProc ; ______________________________________________________________________________ ; 10Jan91 KST CMCreateCN only MarkVCBTime, doesn't mark it dirty. This patch, ; with the patch to CMSetUP in FileMgrPatch.a will mark VCB dirty ; if the VCB Mod time has been changed. ; ______________________________________________________________________________ CMCreateUpdateCNPatch Proc Export MOVE.W D0,-(SP) ; save error code <10Jan91 #6> MOVE.L (A6)+,D0 ; get old mod time <10Jan91 #6> CMP.L VCBLsMod(A2),D0 ; mod time changed by ROM code? <10Jan91 #6> BEQ.S @2 ; no <10Jan91 #6> ST VCBFlags(A2) ; otherwise, mark the VCB dirty <10Jan91 #6> @2 MOVE.W (SP)+,D0 ; restore error code <10Jan91 #6> MOVE.L (A6)+,-(SP) ; put return address back on stack <10Jan91 #6> TST.W D0 ; set condition codes <10Jan91 #6> RTS ; exit CMCreateCN <10Jan91 #6> END