; ; File: CMSVCS.a ; ; Contains: These routines provide service functions used to access ; and maintain the file catalog. ; ; Written by: Bill Bruffey ; ; Copyright: © 1984-1992 by Apple Computer, Inc., all rights reserved. ; ; Change History (most recent first): ; ; 4/1/92 kc Roll in CMCreateUpdateCNPatch, CMRenameCNAfterSetup, ; CMMoveCNAfterSetup, CMDeleteCNAfterSetup, ; and CMCreateUpdateCNPatch from FileMgrPatches.a. ; ¥ Pre-SuperMario comments follow ¥ ; <2> 9/10/91 JSM Add a header. ; <1.2> 3/2/89 DNF removed references to forROM; HFS now builds identically for ram ; or rom ; <1.1> 11/10/88 CCH Fixed Header. ; <1.0> 11/9/88 CCH Adding to EASE. ; <¥1.1> 9/23/88 CCH Got rid of inc.sum.d and empty nFiles ; <1.0> 2/11/88 BBM Adding file for the first time into EASEÉ ; 9/25/86 BB Updated to use new MPW equate files. ; 12/15/85 BB 1st version. ; 10/31/85 BB CMRenameCN no longer updates the file or directory mod date. ; 10/25/85 BB Added a common CMSetUp subroutine. Added vector for ROM ; versions. ; 10/16/85 BB Modified all routines to use new new MOVEQ error code equates. ; 9/9/85 BB Fixed CMCreateCN and CMRenameCN to handled partial catalog ; updates. ; 9/8/85 LAK Call MarkVCBTime instead of MarkVCB since consistency check will ; be used to determine file and directory counts if VCB info is ; not flushed . . . ; 8/9/85 BB Fixed bug in CMRenameCN which was trashing Finder info. ; 8/5/85 BB Fixed bug in CMGetOff, was not converting error codes upon ; return from BTGetRecord. ; 7/26/85 BB Added calls to MarkVCB to set the VCB dirty. Also added code to ; set the modification date for updated directories. ; 7/25/85 BB Modified CMCreateCN and CMRenameCN to truncate CName's in thread ; records to max length. ; 7/10/85 BB Added calls to CMFlush. ; 7/2/85 BB Modified CMRenameCN to rename an existing CNode. Modified ; CMMoveCN to handle a null move, i.e., a move to the same parent ; directory. ; 6/27/85 BB Changed internal error code 'CMbadmove' to TFS global error code ; 'BadMovErr'. ; 6/20/85 PWD Changed to use system CNode equates Changed to use VCBNxtCNID ; for file numbers and DirIDs. ; 6/12/85 BB Added check for invalid move operation to CMMoveCN. ; 5/30/85 BB Fixed CMGetOff to invalidate directory and offspring markers ; when an error condition is detected. ; 5/16/85 BB Cleaned the code up some. ; 4/21/85 BB Added use of directory and offspring markers for catalog ; enumeration. ; 3/30/85 BB Replaced use of memory manager for CM vars allocation with A6 ; stack based allocation. ; 3/15/85 BB Modified to use A6 stack. ; 3/14/85 BB Change names of CM service routines. ; 3/7/85 BB Modified to support the existence of a root directory record. ; 2/12/85 BB Added save/restore for scratch registers ; 12/11/84 BB Birth. ; ; ;_________________________________________________________________________________ ; ; External ; Routines: CMCreateCN - Creates a new directory or file CNode. ; CMDeleteCN - Deletes an existing directory or file CNode. ; CMGetCN - Locates an existing directory or file CNode. ; CMGetOff - Gets an offspring record from a directory. ; CMMoveCN - Moves an existing directory or file CNode to ; another directory CNode. ; CMRenameCN - Renames an existing directory or file CNode. ; CMUpdateCN - Marks a Catalog BTree node as 'dirty'. ; ;_________________________________________________________________________________ BLANKS ON STRING ASIS PRINT OFF LOAD 'StandardEqu.d' PRINT ON PRINT NOGEN CMSvcs PROC EXPORT EXPORT CMCreateCN,CMDeleteCN,CMGetOff EXPORT CMGetCN,CMMoveCN,CMRenameCN,CMUpdateCN EXPORT vCMSetUp,CMSetUp IMPORT BTGetRecord,BTDelete,BTInsert,BtSearch,BTUpdate IMPORT BuildKey,CMFlush,LocCNode,LocCRec,UpdCName IMPORT MarkVCB ;_________________________________________________________________________________ ; ; Routine: CMCreateCN (Create CNode) ; ; Function: Creates a new directory or file CNode. A new directory or file ; record is added to the catalog BTree. If a directory CNode is ; being created, a new thread record is also added. ; ; Input: A2.L - VCB pointer ; D0.L - parent DirID ; A0.L - CName pointer ; D1.L - new CNode type (low byte in lower half) ; CMDirCN - directory ; CMFilCN - file ; file type (low byte of upper half) ; ; Output: D0.W - result code ; 0 = ok ; CMexists = CNode already exists ; CMnotfound = parent directory not found ; -n = IO error ; D1.L - DirID of new directory CNode ; D2.L - new catalog hint ;_________________________________________________________________________________ CMCreateCN MOVE.L (SP)+,-(A6) ; save return address on A6 stack MOVEM.L D3-D7/A0-A4,-(A6) ; save regs ; ; set up some initial stuff ; BSR CMSetUp ; common set up routine <25Oct85> CLR.L VCBDirIDM(A2) ; invalidate current DirID marker MOVE.L D1,D5 ; D5 = CNode type / file type MOVE.L D0,D3 ; D3 = parID MOVEA.L A0,A3 ; A3 = CName pointer ; ; make sure parent exists ; SUBA.L A0,A0 ; no Cname MOVEQ #0,D2 ; no hint JSR locCRec ; locate the parent's thread record BNE CCExit1 ; error -> ; ; build key for new CNode ; MOVE.L D3,D0 ; parID MOVEA.L A3,A0 ; CName pointer LEA ckrOff(A4),A1 ; addr(key record buffer) JSR BuildKey ; build the key record ; ; initialize catalog data record (cdr) for directory or file ; LEA cdrOff(A4),A1 ; addr(data record buffer) MOVEA.L A1,A0 ; clear MOVE.W #(lencdr/2)-1,D0 ; @2 CLR.W (A0)+ ; DBRA D0,@2 ; ...the record first MOVE.B D5,cdrType(A1) ; set record type MOVE.L Time,D2 ; D2 = current date/time CMPI.B #CMDirCN,D5 ; creating a directory? BNE.S @3 ; no -> MOVE.L VCBNxtCNID(A2),D6 ; assign it a DirID MOVE.L D6,dirDirID(A1) ; ADDQ.L #1,vcbNxtCNID(A2) ; bump next available CNode ID MOVE.L D2,dirCrDat(A1) ; set creation date/time MOVE.L D2,dirMdDat(A1) ; set date/time of last modified MOVEQ #lendir,D1 ; D1 = size of directory data record BRA.S CCAddRec ; add new record -> @3 MOVE.L D2,filCrDat(A1) ; set creation date/time MOVE.L D2,filMdDat(A1) ; set date/time of last modified MOVE.L VCBNxtCNID(A2),filFlNum(A1) ; assign it the next file number ADDQ.L #1,VCBNxtCNID(A2) ; SWAP D5 ; set file type MOVE.B D5,filTyp(A1) ; SWAP D5 ; MOVEQ #lenfil,D1 ; D1 = size of file data record ; ; add new directory/file record to catalog BTree ; CCAddRec MOVE.W VCBCtRef(A2),D0 ; refnum of catalog file LEA ckrOff(A4),A0 ; addr(key record buffer) JSR BTInsert ; insert the record BEQ.S @1 ; ok -> CMP.W #BTexists,D0 ; does CNode already exist? BNE CCExit1 ; no, some other error -> MOVEQ #CMexists,D0 ; set CM result code <16Oct85> BRA CCExit1 ; exit -> @1 MOVE.L D2,D7 ; D7 = new hint ; ; build thread record for new directory CNode ; CCBldThd CMPI.B #CMDirCN,D5 ; creating a directory? BNE.S CCUpdPar ; no -> MOVE.L D6,D0 ; parID = new directory ID SUBA.L A0,A0 ; no CName LEA ckrOff(A4),A1 ; addr(key record buffer) JSR BuildKey ; build the key record LEA cdrOff(A4),A1 ; clear MOVE.W #(lenthd/2)-1,D0 ; @1 CLR.W (A1)+ ; DBRA D0,@1 ; ...the record first LEA cdrOff(A4),A1 ; addr(thread record) MOVE.B #cdrThdRec,cdrType(A1) ; set record type MOVE.L D3,thdParID(A1) ; set parent ID MOVEA.L A3,A0 ; source = input CName LEA thdCName(A1),A1 ; dest = thread record CName JSR UpdCName ; move in the CName <09Sep85> ; ; add thread record to catalog BTree ; MOVE.W VCBCtRef(A2),D0 ; refnum of catalog file MOVE.W #lenthd,D1 ; length of thread record LEA ckrOff(A4),A0 ; addr(key record) LEA cdrOff(A4),A1 ; addr(thread record) JSR BTInsert ; insert the record BEQ.S CCUpdPar ; ok -> ; ; couldn't add thread record, delete newly created directory record and exit ; MOVE.L D0,-(A6) ; save result code <09Sep85> MOVE.L D3,D0 ; parID <09Sep85> MOVEA.L A3,A0 ; CName pointer <09Sep85> LEA ckrOff(A4),A1 ; ptr(key record buffer) <09Sep85> JSR BuildKey ; build the key record <09Sep85> MOVEA.L A1,A0 ; ptr to key <09Sep85> MOVE.W VCBCtRef(A2),D0 ; refnum of catalog file <09Sep85> JSR BTDelete ; delete the directory record <09Sep85> MOVE.L (A6)+,D0 ; restore original result code <09Sep85> CMP.W #BTexists,D0 ; did thread record already exist? BNE.S CCExit1 ; no, some other error -> MOVEQ #CMexists,D0 ; set CM result code <16Oct85> BRA.S CCExit1 ; exit -> ; ; update parent directory ; CCUpdPar MOVE.L D3,D0 ; ParID SUBA.L A0,A0 ; no Cname MOVEQ #0,D2 ; no hint JSR locCNode ; locate the directory record BNE.S CCExit1 ; error -> ADDQ.W #1,dirVal(A1) ; bump valence MOVE.L Time,dirMdDat(A1) ; set date/time last modified MOVE.W VCBCtRef(A2),D0 ; catalog refnum JSR BTUpdate ; update the BTree record BNE.S CCExit1 ; error -> ; ; update VCB directory and file counts ; MOVE.B D5,D0 ; CNode type MOVE.L D3,D1 ; ParID MOVEQ #1,D2 ; increment value BSR UpdVCnts ; update the counts ; ; clean up and exit ; CCExit CLR.W D0 ; result = 'ok' MOVE.L D6,D1 ; return DirID in D1 MOVE.L D7,D2 ; return hint in D2 JSR MarkVCB ; Mark the VCB dirty (From CMCreateUpdateCNPatch) JSR CMFlush ; flush the catalog CCExit1 ADD #lenCMVars,A6 ; de-allocate memory for CM vars MOVEM.L (A6)+,D3-D7/A0-A4 ; restore regs MOVE.L (A6)+,-(SP) ; put return address back on stack TST.W D0 ; set condition codes RTS ; exit CMCreateCN ;_________________________________________________________________________________ ; ; 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. 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 ;_________________________________________________________________________________ ; from CMDeleteCNAfterSetup patch unusedBit EQU 9 ; pick unused bit in a register (D4 only uses abyte) CMDeleteCN 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> 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 JSR LocCNode ; 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.S DCExit1 ; exit -> ; ; delete catalog records for CNode and file threads if they exist .start ; 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 .end DCDelete LEA ckrOff(A4),A0 ; addr(key record) MOVE.W VCBCtRef(A2),D0 ; catalog file refnum JSR BTDelete ; delete directory/file record BNE.S DCExit1 ; error, exit-> CMPI.B #cdrDirRec,D4 ; directory being deleted? .start 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 .end LEA ckrOff(A4),A1 ; addr(key record buffer) JSR BuildKey ; build thread key record LEA ckrOff(A4),A0 ; addr(key record) MOVE.W VCBCtRef(A2),D0 ; catalog file refnum JSR BTDelete ; delete thread record BEQ.S DCUpdPar ; .start BTST #unusedBit, D4 ; if it was a file thd, just ignore the error BEQ.S DCExit1 ; .end ; ; update parent directory ; DCUpdPar MOVE.L D6,D0 ; ParID SUBA.L A0,A0 ; no Cname MOVEQ #0,D2 ; no hint JSR locCNode ; 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 JSR BTUpdate ; 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 BSR UpdVCnts ; update the counts ; ; clean up and exit ; DCExit CLR.W D0 ; result = 'ok' JSR MarkVCB ; Mark the VCB changed JSR CMFlush ; 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 ;_________________________________________________________________________________ ; ; Routine: CMGetCN (Get CNode) ; ; Function: Locates an existing directory or file CNode and returns a pointer ; to the CNode key and data records. ; ; Input: A2.L - VCB pointer ; D0.L - DirID or parent DirID ; A0.L - CName pointer ; D2.L - catalog hint ; ; Output: D0.W - result code ; 0 = ok ; CMnotfound = CNode not found ; -n = IO error ; A0.L - pointer to catalog key record (ckr) ; A1.L - pointer to catalog data record (cdr) ; D2.L - catalog hint ;_________________________________________________________________________________ CMGetCN MOVE.L (SP)+,-(A6) ; save return address on A6 stack MOVEM.L D1/D3/A3-A4,-(A6) ; save regs ; ; set up some common stuff ; BSR CMSetUp ; common set up routine <25Oct85> CLR.L VCBDirIDM(A2) ; invalidate current DirID marker ; ; Locate directory/file BTree record for the CNode ; JSR LocCNode ; locate the record ; ; clean up and exit ; GCExit ADD #lenCMVars,A6 ; de-allocate memory for CM vars MOVEM.L (A6)+,D1/D3/A3-A4 ; restore regs MOVE.L (A6)+,-(SP) ; put return address back on stack TST.W D0 ; set condition codes RTS ; exit CMGetCN ;_________________________________________________________________________________ ; ; Routine: CMGetOff (Get Offspring) ; ; Function: Gets an offspring record from a specified directory. The directory ; is identified by it's DirID. The desired offspring CNode is ; indicated by the value of the offspring index (1 = 1st offspring ; CNode, 2 = 2nd offspring CNode, etc.). ; ; Input: A2.L - VCB pointer ; D0.L - DirID ; D1.W - offspring index ; ; Output: D0.W - result code ; 0 = ok ; CMnotfound = offspring not found (no more ; offspring for this directory) ; -n = IO error ; A0.L - ptr(catalog key record) ; A1.L - ptr(catalog data record) ; D2.L - catalog hint ;_________________________________________________________________________________ CMGetOff MOVE.L (SP)+,-(A6) ; save return address on A6 stack MOVEM.L D1/D3-D4/A4,-(A6) ; save regs ; ; set up some common stuff ; BSR CMSetUp ; common set up routine <25Oct85> MOVE.L D0,D3 ; D3 = DirID MOVE.W D1,D4 ; D4 = offspring index ; ; locate thread record for the specified DirID ; MOVE.L VCBDirIDM(A2),D1 ; have a current DirID marker? BEQ.S @1 ; no, search for thread record -> CMP.L D3,D1 ; same DirID? BEQ.S GOGetOff ; yes, skip search for thread record -> @1 CLR.L VCBDirIDM(A2) ; invalidate current DirID marker MOVE.L D3,D0 ; DirID SUBA.L A0,A0 ; no CName JSR LocCRec ; locate the thread record BNE.S GOExit ; didn't find it, exit -> MOVE.L D3,VCBDirIDM(A2) ; update current DirID CLR.W VCBOffsM(A2) ; ...and offspring index markers ; ; get offspring record ; GOGetOff MOVE.W VCBCtRef(A2),D0 ; catalog file refnum MOVE.W D4,D1 ; selection index = offspring index SUB.W VCBOffsM(A2),D1 ; - current offspring index marker JSR BTGetRecord ; get the record BEQ.S @3 ; ok -> CMP.W #BTnotfound,D0 ; result = 'not found'? BNE.S @2 ; no, some other error -> @1 MOVEQ #CMnotfound,D0 ; set error code <16Oct85> @2 CLR.L VCBDirIDM(A2) ; invalidate current DirID marker BRA.S GOExit ; exit -> @3 CMP.L ckrParID(A0),D3 ; same parent? BNE.S @1 ; no -> MOVE.W D4,VCBOffsM(A2) ; update offspring index marker ; ; clean up and exit ; GOExit ADD #lenCMVars,A6 ; de-allocate memory for CM vars MOVEM.L (A6)+,D1/D3-D4/A4 ; restore regs MOVE.L (A6)+,-(SP) ; put return address back on stack TST.W D0 ; set condition codes RTS ; exit CMGetOff ;_________________________________________________________________________________ ; ; 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 ;_________________________________________________________________________________ CMMoveCN 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> 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 JSR LocCNode ; 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 JSR LocCNode ; 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 ; JSR LocCNode ; 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 JSR LocCNode ; 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 JSR BTInsert ; 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 JSR LocCNode ; 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 JSR BTUpdate ; 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 BSR UpdRtCnts ; 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 JSR LocCNode ; locate the record BNE.S MCExit1 ; didn't find it -> LEA ckrOff(A4),A0 ; addr(key record) MOVE.W VCBCtRef(A2),D0 ; catalog file refnum JSR BTDelete ; 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 ; (from CMMoveCNAfterSetup) .start 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 .end MOVEQ #0,D2 ; no hint JSR LocCRec ; 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 JSR BTUpdate ; 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 JSR locCNode ; 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 JSR BTUpdate ; 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 BSR UpdRtCnts ; update the counts ; ; clean up and exit ; MCExit CLR.W D0 ; result = 'ok' MOVE.L D7,D2 ; return new hint in D2 JSR MarkVCB ; Mark the VCB changed JSR CMFlush ; 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 ;_________________________________________________________________________________ ; ; 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 ;_________________________________________________________________________________ CMRenameCN 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> 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 ; JSR LocCNode ; 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 JSR BuildKey ; build new key MOVEA.L A1,A0 ; addr(key record) LEA cdrOff(A4),A1 ; addr(data record) @2 MOVE.W D6,D1 ; record size MOVE.W VCBCtRef(A2),D0 ; catalog file refnum JSR BTInsert ; 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> JSR LocCNode ; 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.S 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> JSR UpdCName ; replace the name <09Sep85> MOVE.W VCBCtRef(A2),D0 ; catalog file refnum <09Sep85> JSR BTUpdate ; 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 JSR LocCNode ; 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 JSR BTDelete ; 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 ; (from CMRenameCNAfterSetup) .start 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 .end CLR.L D2 ; no hint JSR LocCRec ; 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 JSR UpdCName ; update the CName <09Sep85> MOVE.W VCBCtRef(A2),D0 ; catalog file refnum JSR BTUpdate ; update BTree record ; ; clean up and exit ; RCExit CLR.W D0 ; result = 'ok' MOVE.L D7,D2 ; return new hint in D2 JSR MarkVCB ; Mark the VCB changed JSR CMFlush ; flush the catalog RCExit1 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 ;_________________________________________________________________________________ ; ; Routine: CMUpdateCN (Update CNode) ; ; Function: Marks the Catalog BTree node identified by the given catalog hint ; as 'dirty'. ; ; Input: A2.L - VCB pointer ; D2.L - catalog hint ; ; Output: D0.W - result code ; 0 = ok ; CMnotfound = CNode not found ; -n = IO error ;_________________________________________________________________________________ CMUpdateCN MOVE.L (SP)+,-(A6) ; save return address on A6 stack MOVEM.L D1-D2/A0-A1,-(A6) ; save regs BSR.S CMSetUp ; common set up routine <25Oct85> MOVE.W VCBCtRef(A2),D0 ; catalog file refnum JSR BTUpdate ; mark the node 'dirty' BEQ.S UCExit ; ok, all done -> CMPI.W #BTnotfound,D0 ; node not found? BNE.S UCExit1 ; no, some other error -> MOVEQ #CMnotfound,D0 ; result = 'not found' <16Oct85> BRA.S UCExit1 ; exit -> UCExit JSR MarkVCB ; Mark the VCB dirty (From CMCreateUpdateCNPatch) JSR CMFlush ; flush the catalog UCExit1 ADD #lenCMVars,A6 ; de-allocate memory for CM vars <25Oct85> MOVEM.L (A6)+,D1-D2/A0-A1 ; restore regs MOVE.L (A6)+,-(SP) ; put return address back on stack TST.W D0 ; set condition codes RTS ; exit CMUpdateCN ;__________________________________________________________________________________ ; ; Internal Subroutines ;__________________________________________________________________________________ ;__________________________________________________________________________________ ; ; Subroutine: CMSetUp (CM Set Up) ; ; Function: Sets up for all CM service calls. Space for the CM variable storage area ; (CMVars) is allocated on the A6 stack. ; ; Input: none ; ; Output: A4.L - pointer to CMVars ;__________________________________________________________________________________ CMSetUp MOVE.L jCMSetUp,-(SP) ; jumptable entry for vCMSetUp <25Oct85> RTS ; go there <25Oct85> vCMSetUp ; 'vectored' CMSetUp routine <25Oct85> SUB #lenCMVars,A6 ; allocate memory for CM vars <25Oct85> MOVEA.L A6,A4 ; A4 = pointer to CM vars <25Oct85> RTS ; exit CMSetUp <25Oct85> ;__________________________________________________________________________________ ; ; Subroutine: UpdVCnts (Update Volume Counts) ; UpdRtCnts (Update Root Counts) ; ; Function: Updates Volume directory and file counts. ; ; Input: A2.L - pointer to VCB ; D0.B - CNode type ; D1.L - ParID ; D2.L - increment value (+1 or -1) ; ; Output: none ;__________________________________________________________________________________ UpdVCnts CMPI.B #CMDirCN,D0 ; add/delete a directory? BNE.S @1 ; no -> ADD.L D2,VCBDirCnt(A2) ; adjust volume directory count BRA.S UpdRtCnts ; -> @1 ADD.L D2,VCBFilCnt(A2) ; adjust volume file count UpdRtCnts CMPI.L #FSRtDirID,D1 ; add/delete to root? BNE.S @2 ; no, all done -> CMPI.B #CMDirCN,D0 ; adding/deleting a directory? BNE.S @1 ; no -> ADD.W D2,VCBNmRtDirs(A2) ; adjust root directory count BRA.S @2 @1 ADD.W D2,VCBNmFls(A2) ; adjust root file count @2 RTS ; exit UpdVCnts/UpdRtCnts END