; ; File: TFSDIR2.a ; ; Contains: This file contains file-level routines which use filenames. ; ; Copyright: © 1983-1993 by Apple Computer, Inc., all rights reserved. ; ; Change History (most recent first): ; ; 8/27/93 BH Removed . The flushing stuff is now in CmdDone. ; 8/3/93 BH Flushing critical volume info when changed for a volume in a ; manual-eject drive. ; 5/21/92 kc Append "Trap" to the name of ReName to avoid name conflict with ; the glue. ; 4/1/92 kc Roll in FixVolumeRenames patch from FileMgrPatches.a. ; Rolled in the Disappearing Folder patch. ; Rolled in RenameCheckVolNameLength in FileMgrPatches.a. ; ¥ Pre-SuperMario comments follow ¥ ; <2> 9/12/91 JSM Add a header. ; <1.1> 11/10/88 CCH Fixed Header. ; <1.0> 11/9/88 CCH Adding to EASE. ; <1.0> 2/11/88 BBM Adding file for the first time into EASEÉ ; 1/14/87 BB Fixed FileDelete to return "paramErr" error rather than the file ; system internal error "FSDSIntErr" if attempting to delete the ; root directory. NOTE: this is not patched for the Mac+ or MAUI. ; 4/15/86 PWD Fix rename bug when renameing an external volume. ; 1/13/86 LAK After Renaming MFS volume with SetVolName, take the exit which ; sets D0=0. This incorporates the patch in ROM75Fix. ; 10/6/85 PWD Changed to use new SetVolName routine throughout (move to ; TFSVol). ; 10/1/85 LAK Don't worry about adjusting internal errors - done by CmdDone. ; 9/21/85 LAK Fixed bug in above. ; 9/20/85 PWD Changed Rename to allow source vol. spec by VRefNum only. ; 9/20/85 LAK Call TrashFBlocks when deleting a file. ; 9/5/85 LAK Don't allow rename for locked files. ; 8/28/85 LAK New today. ; 8/28/85 LAK Added CkDirBusy, Gt1stWDCB, GtNxtWDCB, Gt1stWDVMatch, ; GtNxtWDVMatch subroutines. Refuse to delete a directory which ; has an open WDCB. ; 6/20/85 PWD Changed to use new system CNode equates ; 6/19/85 PWD Changed internal errors to FSDSIntErr instead of IOErr. ; 4/25/85 PWD Changed to convert internal error codes to IOErr. ; 3/10/85 PWD Split off MFS-specific code into MFSDir2. Added code to deal ; specifically with TFS volumes. ; 8/29/83 LAK Changed ReName to update affected FCBs FCBFlPos (rename may ; cause a directory entry to migrate). ; 4/20/83 LAK Minor change to CkFileBusy. ; 2/8/83 LAK Fixed rename bug (A5 trash) ; 1/16/83 LAK Added latest changes; cosmetic and documentation updates. ; ;_______________________________________________________________________ ; ; External Routines: FileDelete,ReName,TFMove ; ; Internal Routines: CkFileBusy, CkDirBusy, Gt1stWDCB, GtNxtWDCB, ; Gt1stWDVMatch, GtNxtWDVMatch ; ;_______________________________________________________________________ ;_______________________________________________________________________ ; ; Routine: Gt1stWDCB,GtNxtWDCB ; ; Arguments: A1.L (input) -- FCB start pointer (GtNxtFCB) ; D1.W (input) -- offset to current FCB (GtNxtFCB) ; A1.L (output) -- unchanged ; D1.W (output) -- offset to next WDCB ; CCR set so that BCS will not br when past last WDCB ; Called By: Gt1stWDMatch,GtNxtWDMatch ; Function: Scan through the WDCBs. ; ; Routine: Gt1stWDVMatch,GtNxtWDVMatch ; ; Arguments: A1.L (input) -- WDCB start pointer (GtNxtWDMatch) ; D1.W (input) -- offset to current FCB (GtNxtWDMatch) ; A2.L (input) -- VCB pointer to match against ; A1.L (output) -- WDCB start pointer ; D1.W (output) -- offset to next WDCB on same volume ; CCR set so that BNE will not br when past last WDCB ; Called By: CkDirBusy ; Function: Scan through the WDCBs which match a certain volume. ; ; Modification History: ; <28Aug85> LAK New today. ;_______________________________________________________________________ BLANKS ON STRING ASIS Gt1stWDCB MOVE.L WDCBSPtr,A1 ; get WDCB ptr <28Aug85> MOVEQ #2,D1 ; index to first FCB <28Aug85> RTS ; <28Aug85> GtNxtWDCB ADD.W #WDCBLen,D1 ; go to next FCB <28Aug85> CMP.W (A1),D1 ; reached the end yet? <28Aug85> RTS ; let the caller test (BCS if not) <28Aug85> Gt1stWDVMatch BSR.S Gt1stWDCB ; <28Aug85> gt1stLoop CMP.L WDVCBPtr(A1,D1),A2 ; on the same volume? <28Aug85> BEQ.S gtNxtRTS ; <28Aug85> GtNxtWDVMatch BSR.S GtNxtWDCB ; <28Aug85> BCS.S gt1stLoop ; loop thru them all <28Aug85> MOVE #0,CCR ; clear Z bit <28Aug85> gtNxtRTS RTS ; BEQ for match, BNE at end . . . <28Aug85> ;_______________________________________________________________________ ; ; Routine: CkDirBusy ; Arguments: A0.L (input) -- IO parameter block ptr ; A2.L (input) -- VCB pointer ; A5.L (input) -- file directory entry pointer ; D0.W (output) -- result code (0 if file not open) ; D1.W (output) -- WDCB index if directory busy ; All other registers are preserved. ; Calls: Gt1stWDCB,GtNxtWDCB ; Called by: FileDelete ; Function: Searches WDCB buffer to see if the directory is ; currently open. ; ; Modification History: ; <28Aug85> LAK New today. ;_______________________________________________________________________ CkDirBusy MOVEM.L D2/A1,-(SP) ; Preserve A1/D2 <28Aug85> MOVE.L dirDirID(A5),D2 ; Get dir number from TFS cat. entry <28Aug85> ; scan through the WDCBs and look for a match of directory number and same volume BSR.S Gt1stWDVMatch ; get first WDCB for this volume <28Aug85> @0 BNE.S @1 ; br if no match <28Aug85> CMP.L WDDirID(A1,D1),D2 ; for the same directory? <28Aug85> BEQ.S @3 ; br if so - error <28Aug85> BSR.S GtNxtWDVMatch ; try the next <28Aug85> BRA.S @0 ; and loop <28Aug85> @1 MOVEQ #0,D0 ; not busy . . . <28Aug85> @2 MOVEM.L (SP)+,D2/A1 ; restore A1/D2 <28Aug85> RTS ; <28Aug85> @3 MOVE.W D1,IORefnum(A0) ; note the refnum of WDCB entry <28Aug85> MOVEQ #FBsyErr,D0 ; directory is busy <28Aug85> BRA.S @2 ; <28Aug85> ;_______________________________________________________________________ ; ; Routine: CkFileBusy ; Arguments: A0.L (input) -- IO parameter block ptr ; A2.L (input) -- VCB pointer ; A5.L (input) -- file directory entry pointer ; D0.W (output) -- result code (0 if file not open) ; D1.W (output) -- FCB index if file busy ; D2.L (output) -- FilFLNum(A5) ; All other registers are preserved. ; Calls: Gt1stFCB,GtNxtFCB ; Called by: FileDelete,MFSDelete,GetFileInfo,GetMFlInfo ; Function: Searches FCB buffer to see if the file directory entry ; pointed to by A5 is already open. ; ; Modification History: ; 10 Dec 82 LAK New today. ; 16 Jan 83 LAK Now calls procs to search thru FCBs. ; 20 Apr 83 LAK Changed to return refnum of entry found when file is ; found to be busy already. ; 29 Aug 83 LAK Changed to use Gt1stMatch instead of Gt1stFCB, GtNxtFCB. ; Now returns file number in D2 (no one uses it tho). ; 10 Mar 85 PWD Changed to check volume sigword and handle (possibly) different ; file descriptor data structures to find file number. ;_______________________________________________________________________ CkFileBusy MOVE.L A1,-(SP) ; Preserve A1 MOVE.L FilFLNum(A5),D2 ; Get file number from TFS cat. entry BSR TFSVCBTst ; Are we dealing with a TFS volume? <01Oct85> BEQ.S @0 ; If TFS, handle TFS catalog entries MOVE.L FlFlNum(A5),D2 ; get the file number from MFS dir. entry ; scan through the FCBs and look for a match of file number and same volume @0 BSR Gt1stMatch BEQ.S @2 ; fail if any match MOVEQ #0,D0 @1 MOVE.L (SP)+,A1 ; restore A1 RTS @2 MOVE.W D1,IORefnum(A0) ; note the refnum of fcb entry MOVEQ #FBsyErr,D0 ; file is busy BRA.S @1 ;_______________________________________________________________________ ; ; Routine: FileDelete ; ; (c) 1983 Apple Computer, Inc. ; ; Arguments: A0.L (input) -- pointer to I/O parameter block; uses: ; IOFileName,IOFileType ; D0.W (output) -- error code ; This call may be executed asynchronously. ; Calls: FSQueue,DtrmVol,CVFlgs,FndFilName,CkFileBusy,DAlBlks,RemovEntry, ; CmdDone ; Function: Delete a file. The file is removed from ; the directory and its blocks are freed up (both resource and ; normal fork blocks are deallocated). The entry is zeroed and ; any following entries are moved down. All blocks associated ; with the file are marked free in the block map and the VCB ; info is marked dirty. ; ; Modification History: ; 09 Dec 82 LAK Redid for new file data structures. ; 10 Dec 82 LAK Broke out routine to search FCBs by filenum (share it ; with GetFileInfo). ; 14 Dec 82 LAK Removed undelete scheme. ; 16 Jan 83 LAK Modified RemovEntry for new directory format (no entry ; length); updated documentation. ; 04 Jun 83 LAK No longer calls DtrmVol (this is done by FndFilName) since ; case of write-protected diskette is a low-percentage hit. ; Uses CkFilMod subroutine to save code. ; 9 May 85 PWD CkFlMod no longer checks for file entry, so directories can ; be deleted at last. Directories with files still in them ; cause a FBsyErr. ; 9-Aug-85 PWD Changed to leave VCB file/directory count up to CMDeleteCN ; <28Aug85> LAK Don't delete a directory if there's a WDCB open for it. ; <14Jan87> BB Fixed FileDelete to return "paramErr" error rather than the file ; system internal error "FSDSIntErr" if attempting to delete ; the root directory. NOTE: this is not patched for the Mac+ ; or MAUI. ;_______________________________________________________________________ FileDelete: BSR FSQueue ; queue it up BSR CkFilMod ; find File and check if we can mod vol. ; ; If we've made it this far without being derailed into CmdDone, the volume is ; writable and we know the file exists: now see if file is locked or is busy. ; BSR TFSVCBTst ; Are we dealing with a TFS volume? <01Oct85> BNE MFSDelete ; If not, leave it to the MFS code. MOVEQ #FLckdErr,D0 ; assume locked BTST #FilWrtFlag,FilFlags(A5) ; well, is it? BNE.S FDelExit ; br if so BCLR #DirCN,HFSFlags ; Assume it's not a directory CMP.B #CMDirCN,cdrType(A5); Is the CNode a directory? BNE.S @1 ; Nope. BSET #DirCN,HFSFlags ; Otherwise, set a flag for future reference BSR.S CkDirBusy ; Is the directory busy? BRA.S @2 ; br to check @1 CMP.B #cdrFilRec,cdrType(A5) ; Is this a file? BNE.S DeleteIt ; If not, it won't be open MOVE.L D2,-(A6) ; Save D2 across CkFileBusy call BSR.S CkFileBusy ; Check if the file is busy? MOVE.L (A6)+,D2 ; restore D2 TST.W D0 ; busy? @2 BNE.S FDelExit ; exit if busy . . . ; Free up the space previously occupied by the file's contents: DeleteIt BSR PushCName ; Create a copy of the string on the stack: MOVE.L D2,-(A6) ; Save D2 for use as 'scratch' MOVE.L D7,D2 ; Catalog hint CMP.B #CMFilCN,cdrType(A5); Is this a file? BNE.S @0 ; If not, it doesn't occupy any real space MOVE.L FilFLNum(A5),D0 ; Get file number from TFS cat. entry <20Sep85> JSR TrashFBlocks ; Trash all file blocks (pass A2,D0) <20Sep85> MOVE.L D6,D0 ; DirID from FindFilName <21Sep85> JSR DeallocFile ; Free disk space occupied by file BNE.S FDelExit ; Punt on errors ; Restore parent ID and remove the file from the catalog: @0 MOVE.L D6,D0 ; Parent directory ID JSR CMDeleteCN ; Delete the catalog node MOVE.L (A6)+,D2 ; Restore rounded string length again BSR PopCName ; Remove CName from A6 stack again CMP.W #CMNotEmpty,D0 ; Was the directory non-empty? BNE.S @1 ; No - something else went wrong <14Jan87> MOVEQ #FBsyErr,D0 ; Recycle a nice error code BRA.S FDelExit ; exit FileDelete <14Jan87> @1 CMP.W #CMRootCN,D0 ; attempt to delete the root directory? <14Jan87> BNE.S FDelExit ; no, exit FileDelete <14Jan87> MOVEQ #paramErr,D0 ; yes, return illegal param error code <14Jan87> FDelExit BRA CmdDone ;_______________________________________________________________________ ; ; Routine: ReName ; Arguments: A0 (input) -- pointer to parameter block: ; D0 (output) -- error code ; Calls: FSQueue,DtrmVol,FndFilName,CVFlgs,RemovEntry,FndFilSpc, ; GtEntryLen,CmdDone ; Function: Rename a file or a volume. For files, the directory is ; first searched for the target name (to make sure we don't ; get two files with the same name). If not found, the directory ; is then searched for the real file (using the source name); ; the entry is copied onto the stack and removed from the directory ; block. FndFilSpc is used to find space for the changed entry. ; ; ; Modification History: ; 09 Dec 82 LAK Changed to use a new rename algorithm; updated for new ; file system data structures. ; 16 Jan 83 LAK Updated for final data structures. ; 05 Jun 83 LAK Added change to allow rename of a file to itself (for case ; changes). ; 29 Aug 83 LAK Fixed bug: rename now updates FCBs for the renamed file (opened ; files may be renamed) to point to correct directory block. ; 19 Jun 85 PWD Added quick fix for renaming files with same name on TFS ; volumes: changed to NOP instead of calling CMRenameCN ; 9-Aug-85 PWD Reverted to calling CMRenameCN for case changes. ; ; Test: no more room in directory case . . . ; renaming a volume ; renaming both file and volume with 0-length name. ;_______________________________________________________________________ ReNameTrap: BSR FSQueue ; what a queue command! MOVE.L IONewName(A0),D2 ; check out the new name BSR DtrmV2 ; find what volume the new name is on BNE RNmVol ; br if error (may want to rename vol) TST.W D2 ; check name length BEQ RNmVol1 ; if zero, may be volume-conflict rename MOVE.L A2,A1 ; save volume for the destination name MOVE.W D3,D7 ; save vol specified indication MOVEM.L D2/A4,FSTemp8 ; save dest name ptr and length BSR DtrmV3 ; det vol source name is on BNE.S RNmExit ; exit if we can't determine volume CMPA.L A1,A2 ; are the names on the same volume? BEQ.S NmOK ; if so, life may be beautiful TST.W D7 ; otherwise, if dest didn't specify volume, BEQ.S NmOK ; it's ok (just use source's volume) BadNewNam MOVEQ #BdNamErr,D0 ; names are on different vols RNmExit CMP.W #BTExists,D0 ; B*-Tree error? BNE.S @5 ; MOVEQ #dupFNErr,D0 ; If entry exists, give better error code @5 BRA CmdDone ; that's all folks. NmOK BSR CVFlgs ; is the volume locked/write protected? BNE.S RNmExit ; exit if so BSR TFSVCBTst ; Are we dealing with a TFS volume? <01Oct85> BNE MFSRename ; If not, different rules apply BSR FndFilName ; search directory for the source file BNE.S RNmExit ; if not around, bummers MOVEQ #FLckdErr,D0 ; assume locked <05Sep85> BTST #FilWrtFlag,FilFlags(A5) ; well, is it? <05Sep85> BNE.S RNmExit ; br if so <05Sep85> MOVE.L D6,D4 ; Save source DirID MOVE.L D7,D5 ; and corresponding catalog hint MOVEM.L D2/D4-D5/A4,-(A6) ; Save source file name and length MOVE.L IOFileName(A0),-(A6); Save source file spec. MOVE.L IONewName(A0),D2 ; Get full new name MOVE.L D2,IOFileName(A0) ; Try it out for a name BSR FndFilName ; Look for the new file MOVEM.L D2/A4,FSTemp8 ; save dest name ptr and length MOVE.L (A6)+,IOFileName(A0); Restore original file name MOVEM.L (A6)+,D2/D4-D5/A4 ; Restore source name and length TST.W D0 ; Re-check result from FndFilName BNE.S @10 ; Error is expected ; ; The destination exists: before giving up completely, though, check if perhaps ; the new file name is the same as the old (though perhaps with slighly more ; pleasing case, for instance): ; MOVE.L A0,-(SP) ; preserve parameter block pointer MOVEM.L D2/A4,-(A6) ; MOVE.W D2,D0 ; source name length MOVE.L A4,A0 ; source name ptr SWAP D0 MOVEM.L FSTemp8,D2/A4 ; Retrieve dest. name and length MOVE.W D2,D0 ; new name length MOVE.L A4,A1 ; new name ptr _CmpString ; see if it's a case of the same name MOVEM.L (A6)+,D2/A4 ; Recover source name, length MOVEA.L (SP)+,A0 BNE.S @5 ; br if not CMP.L D4,D6 ; Source and dest. DirID identical? BEQ.S @30 ; If they are, this is a duplicate ; ; We weren't changing the case of an existing filename: ; @5 MOVEQ #DupFNErr,D0 ; duplicate file name if found @10 CMP.W #FNFErr,D0 ; file should not have been found BNE.S RNmExit ; else exit for ext fs, vol offline errs ; ; A final check: did the attempt to find the destination file end in the ; same directory? ; @20 CMP.L D4,D6 ; Compare source and dest. dirs, resp. BNE BadNewNam ; If they differ, we'd be in trouble ; (leave data on A6 stack) ; ; OK, all seems well so far, rename the CNode as requested: ; @30 BSR PushCName ; Set up source name string on A6 stack MOVE.L D2,-(SP) ; Save rounded source name length MOVEA.L A0,A1 ; Stash it for now MOVEM.L FSTemp8,D2/A4 ; Retrieve dest. name and length BSR PushCName ; set up source name on A6 stack MOVE.L (SP)+,-(A6) ; Save rounded source length more permanently MOVE.L D2,-(A6) ; Save rounded dest. length, too EXG A0,A1 ; Put them in their proper order MOVE.L D4,D0 ; Source DirID MOVE.L D5,D2 ; Source Catalog hint ; ( From RenameCheckVolNameLength ) CMP.L #FSRtParID,d0 ; Renamed an entry in root's parent [root]? BEQ.S @checkName ; If so, go update vol. name CMP.L #FSRtDirID,d0 ; Finally, check for rear entries BNE.S @noProblem ; If it's not this, we're all set. MOVE.L a0, -4(sp) ; test by storing onto live stack BNE.S @noProblem ; non-zero entries here are not for us ; @checkName CMP.B #VCBMaxNam,(a1) ; max volume name is 27 characters BLS.S @noProblem ; ; @badName MOVEQ.L #bdNamErr,d0 ; Don't change vol. name if new Bra.S @70 ; name is longer than 27 characters ; @noProblem JSR CMRenameCN ; Update the catalog MOVE.L D2,D7 ; New catalog hint TST.W D0 ; Error on Rename? BNE.S @70 ; Don't change vol. name on errors CMP.L #FSRtParID,D4 ; Renamed an entry in root's parent [root]? BEQ.S @50 ; If so, go update vol. name CMP.L #FSRtDirID,D4 ; Finally, check for rear entries BNE.S @70 ; If it's not this, we're all set. TST.L 4(A6) ; Check rounded source length BGT.S @70 ; Non-null source name length: no dice. @50 BSR SetVolName ; Update the volume name MOVEQ #0,D0 ; If we're here, all is well MOVEQ #FSRtParID,D6 ; Make this case easier to spot... @70 MOVE.L (A6)+,D2 ; Restore the rounded dest. string length MOVE.L (A6)+,-(SP) ; Relocate the rounded source length BSR PopCName ; Remove dest. name string MOVE.L (SP)+,D2 ; Recover rounded source length BSR PopCName ; Remove source string from A6 stack TST.W D0 ; Did an error occur on the rename? BNE RNmExit ; If so, punt. CMPI.L #FSRtParID,D6 ; Working with the root directory? BEQ RNmExit ; Yes - we're all set. ; ; Finally, update any FCBs for the file if it's currently open: ; MOVEM.L FSTemp8,D2/A4 ; Retrieve dest. name and length BSR PushCName ; set up source name on A6 stack MOVE.L D2,-(A6) ; Save rounded dest. length, too MOVE.L D6,D0 ; Set up DirID MOVE.L D7,D2 ; Recover catalog hint JSR CMGetCN ; Look up the Catalog entry MOVE.L (A6)+,D2 ; Recover rounded string length BSR PopCName ; Remove name from A6 stack TST.W D0 ; So how DID the lookup go? BNE RNmExit ; Punt on errors CMPI.B #cdrDirRec,cdrType(A1) ; Is it a directory? BEQ RNmExit ; Hey! we shouldn't even be here... MOVE.B D2,D3 ; Save dest. name length MOVEA.L A1,A5 ; Stash the catalog entry pointer MOVEA.L A4,A0 ; Point to source CName MOVE.L FilFlNum(A5),D2 ; Pick out the file number BSR Gt1stMatch ; Find the first file with a matching FlNum BNE RNmExit ; If there are none, we're all set @100 MOVE.L D7,FCBCatPos(A1,D1) ; Set new catalog hint (may have changed) LEA FCBCName(A1,D1),A1 ; Point to CName to be filled in MOVE.B D3,(A1)+ ; Store CName length MOVEQ #0,D0 ; make sure high word is clear <29Aug85> MOVE.B D3,D0 ; Set up for block move _BlockMove ; Copy in the name MOVEA.L FCBsPtr,A1 ; Restore A1 to its former glory BSR GtNxtMatch ; And look for the next FCB BEQ.S @100 ; If found, do it all again RNmExOK MOVEQ #0,D0 ; no errors RNmEx1 BRA RNmExit ; User is trying to rename a volume. Give it a try . . . RNmVol CMP.W #NSVErr,D0 ; make sure it's no-such-vol error BNE.S RNmEx1 TST.W D2 ; name length should be zero BNE BadNewNam RNmVol1 CMP.W #VCBMaxNam,d3 ; is the proposed name too long? BHI.S BadNewNam ; > 27 is too long (FixVolumeRenames case 1) TST.W D3 ; volume name should be non-zero BEQ.S RNmEx1 ; br if nil BSR DtrmV3 ; check source volume <20Sep85> BNE.S RNmEx1 ; exit if no such volume BSR CVFlgs ; see if can do. BNE.S RNmEx1 ; br if no modification allowed ; TST.W VCBDrvNum(A2) ; make sure it's on-line, too ; BEQ.S RNmEx1 ; exit if not . . . CMPI.W #$4244,VCBSigWord(A2); HFS volume? <15APR86> PWD BEQ.S @50 ; Yes - make sure it's not ext. FS <15APR86> PWD TST.W VCBDrvNum(A2) ; Volume on-line? <15APR86> PWD BEQ.S RNmEx1 ; No - just forget it <15APR86> PWD BRA.S @70 ; Yes - go and rename it <15APR86> PWD @50 BSR ExtOffLinCk ; Our file system, on-line volume? <15APR86> PWD BNE.S RNmEx1 ; If not, get out now <15APR86> PWD @70 ; <15APR86> PWD MOVE.L IONewName(A0),A1 ; get new name pointer BSR SetVolName ; Change the volume name (blows D0) <13Jan86> BSR TFSVCBTst ; Are we dealing with a TFS volume? <01Oct85> BNE.S RNmExOK ; If not, we're all set (exit D0=0) <13Jan86> ; ; For Turbo volumes, the name of the root is maintained with the volume name: ; MOVEQ #0,D2 ; No catalog hint for rename MOVEQ #FSRtDirID,D0 ; Root directory MOVEA.L D2,A0 ; Nil CName pointer LEA VCBVN(A2),A1 ; Point at new name JSR CMRenameCN ; Rename the catalog root directory BRA RNmExit ; we're done (and hopefully OK) ;_______________________________________________________________________ ; ; Routine: TFMove ; Arguments: A0 (input) -- pointer to parameter block: ; D0 (output) -- error code ; Calls: FSQueue,DtrmVol,FndFilName,CVFlgs,RemovEntry,FndFilSpc, ; GtEntryLen,CmdDone ; Function: Move a Cnode into a different directory ; ; Modification History: ; 13 Mar 85 PWD New today ; 6-Aug-85 PWD Fixed to call external file system for ext. fs volumes. ; 7-Aug-85 PWD Fixed to handle CMExists errors (generate DupFNErr) ; 9-Aug-85 PWD Changed to let CMMoveCN take care of updating VCB ; file/directory count fields. ; 22-Aug-85 PWD Fixed bug in dest. vol. determination by saving old FileName Ptr ;_______________________________________________________________________ TFMove: BSR FSQueue ; Wait our turn MOVE.L ioFileName(A0),-(A6); Save filename pointer <22Aug85> MOVE.L IONewName(A0),ioFileName(A0) ; Use new file name <22Aug85> BSR DtrmV3 ; To check dest. volume MOVE.L (A6)+,ioFileName(A0); Restore original file name <22Aug85> MOVE.L A2,A1 ; Save destination volume MOVE.W D3,D7 ; Save volume spec'd indication BSR DtrmV3 ; det vol source name is on BNE.S MvExit ; exit if we can't determine volume CMP.L A1,A2 ; are the names on the same volume? BEQ.S MvNmOK ; if so, things are still OK TST.W D7 ; otherwise, if dest didn't specify a volume, BEQ.S MvNmOK ; it's ok: use source vol. as real default BadMvName MOVEQ #BdNamErr,D0 ; Return bad name error MvExit BRA CmdDone ; And terminate this I/O operation. MvNmOK BSR CVFlgs ; is the volume locked/write protected? BNE.S MvExit ; exit if so BSR ExtOffLinCk ; Check if vol is on-line, and ours BNE.S MvExit ; Punt if it's not MOVEQ #ParamErr,D0 ; Assume all won't be well BSR TFSVCBTst ; Are we dealing with a TFS volume? <01Oct85> BNE.S MvExit ; If not, none of this makes sense BSR FndFilName ; search directory for the source CNode BNE.S MvExit ; if not around, bummers MOVEQ #0,D3 ; Assume it's not a file for now CMP.B #CDRFilRec,CDRType(A5) ; Is CNode a file? BNE.S @0 ; If not, there's no file number to use later MOVE.L filFlNum(A5),D3 ; Save file number @0 MOVE.L D6,D4 ; Save source DirID MOVE.L D7,D5 ; and corresponding catalog hint MOVEM.L D2/A4,FSTemp8 ; Save source file name and length MOVE.L IOFileName(A0),-(A6); Save source file spec. MOVE.L IODirID(A0),-(A6) ; Save source DirID MOVE.L IONewName(A0),IOFileName(A0) ; Get full new name MOVE.L IONewDirID(A0),IODirID(A0) ; And new DirID spec MOVEM.L D3-D5,-(A6) ; Save shelter registers across FndFilName BSR FndFilName ; Look for the new file MOVEM.L (A6)+,D3-D5 ; Restore copies of source DirID and hint MOVE.L (A6)+,IODirID(A0) ; Restore original DirID MOVE.L (A6)+,IOFileName(A0); Restore original file name TST.W D0 ; Re-check result from FndFilName BEQ.S @1 ; No error: check if CNode = directory ; ; There is one error expected from FndFilName: BdNamErr, which is returned for ; zero-length file names. Normally, this is uncool, but here we may be able ; to make do with just the DirID: ; CMP.W #BdNamErr,D0 ; Was error as expected? BNE.S MvExit ; Nope - pass it unchanged TST.W D2 ; Check name length BNE.S BadMvName ; If non-zero, it really IS bad news BRA.S @2 @1 CMP.B #CDRDirRec,CDRType(A5) ; Was CNode found a directory? BNE.S BadMvName ; If not, that's trouble MOVE.L DIRDirID(A5),D6 ; Get this directory's ID MOVEQ #0,D7 ; Hint is lost in the shuffle @2 MOVEM.L FSTemp8,D2/A4 ; Retrieve source name and length CMP.L D4,D6 ; Source and dest. DirID identical? BEQ.S MvExOK ; If so, we're all set now ; OK, all seems well so far, move the CNode as requested: BSR PushCName ; Set up dest. name string on A6 stack MOVE.L D2,-(A6) ; Push rounded D2 MOVE.L D3,-(A6) ; Save file number MOVE.L D4,D0 ; Source DirID MOVE.L D5,D2 ; Source Catalog hint MOVE.L D6,D1 ; Destination DirID MOVE.L D7,D3 ; Destination catalog hint SUBA.L A1,A1 ; Dest. is fully specified by dirID JSR CMMoveCN ; Update the catalog MOVE.L D2,D7 ; Stash the new catalog hint MOVE.L (A6)+,D3 ; Restore file number MOVE.L (A6)+,D2 ; Restore the rounded dest. string length BSR PopCName ; Remove source name string TST.W D0 ; So how DID the move go? BEQ.S @10 ; If EQ, fine. CMP.W #CMExists,D0 ; Just a duplication of effort here? BNE.S @3 ; If not, that's REAL BAD news. MOVEQ #DupFNErr,D0 ; Say it in words intelligble to the user @3 BRA MvExit ; And PUNT. ; Finally, update any FCBs for the file if it's currently open: @10 MOVE.L D3,D2 ; Set the file number to search for BEQ.S MvExOK ; If it wasn't a file, don't bother looking BSR Gt1stMatch ; Find the first file with a matching FlNum BNE.S MvExOK ; If there are none, we're all set @20 MOVE.L D7,FCBCatPos(A1,D1) ; Update catalog hint MOVE.L D6,FCBDirID(A1,D1) ; Set up the new DirID BSR GtNxtMatch ; And look for the next FCB BEQ.S @20 MvExOK MOVEQ #0,D0 ; no errors MvEx1 BRA MvExit