mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2025-01-21 03:31:39 +00:00
1091 lines
39 KiB
Plaintext
1091 lines
39 KiB
Plaintext
|
;
|
|||
|
; File: FileIDsSvcs.a
|
|||
|
;
|
|||
|
; Contains: This file implements the low level File IDs facility by making a new
|
|||
|
; type of CNode record called file threads. FThreads are similar to threads
|
|||
|
; in record structure (key record = [ID, null]; data record = [parID, CName]
|
|||
|
; and in functionality. (fThread data record locates the CNode record of file,
|
|||
|
; while thread data record locates the CNode record of a directory).
|
|||
|
; Note: File threads are keyed off the file number.
|
|||
|
; For more details, see the documentation preceeding each call.
|
|||
|
;
|
|||
|
; Written by: Earsh Nandkeshwar
|
|||
|
;
|
|||
|
; Copyright: <09> 1989-1992 by Apple Computer, Inc., all rights reserved.
|
|||
|
;
|
|||
|
; Change History (most recent first):
|
|||
|
;
|
|||
|
; <SM1> 4/15/92 kc Removed the "ROM" prefix from the RomBind routines.
|
|||
|
; <09> Pre-SuperMario comments follow <20>
|
|||
|
; <13> 9/13/91 JSM Cleanup header.
|
|||
|
; <12> 3/30/91 KST bb, #83912: Fixing a bug in ExchangeFile which uses a signed
|
|||
|
; branch on an unsigned comparison (in CheckExtents).
|
|||
|
; <11> 1/14/91 KST With BB: Documentation change.
|
|||
|
; <10> 1/14/91 KST With BB: "FIDCreateID" should handle the situation when a file is
|
|||
|
; MOVED or RENAMED on 6.0 system which doesn't update file thread.
|
|||
|
; <9> 9/21/90 KST Check the file number in FidResolveID. Also, we don't delete the
|
|||
|
; fileID if the file is not found. We just return an error.
|
|||
|
; <8> 8/24/90 KST Delete the thread record only if the volume is writable (Re:
|
|||
|
; <7>).
|
|||
|
; <7> 8/23/90 KST Fixing a bug in ResolveID which didn't check for left-over
|
|||
|
; FileID. (BRC#70809, #71502)
|
|||
|
; <6> 8/9/90 KST Fixing a bug in FIDExchangeFiles (DeleteExts) that uses an
|
|||
|
; invalid HINT which could cause the system to crash.
|
|||
|
; <5> 7/30/90 dnf Rename rom references and use jsrROM macro.
|
|||
|
;
|
|||
|
; <4> 5/23/90 dnf Change tests for catalog record type to explicitly look for type
|
|||
|
; "file" instead avoiding type "dir thread"
|
|||
|
; <3> 3/16/90 dnf Clear VCBDirIDM on all routines that make BTree calls (moving
|
|||
|
; the hint) so as to not break indexed GetCatInfo calls
|
|||
|
; <2> 2/4/90 DNF Get rid of include of HFS70Equ.a
|
|||
|
; <1.9> 11/15/89 EKN Tweeks from 2nd code review.
|
|||
|
; 11/9/89 EKN Tweeks from 2nd code review.
|
|||
|
; <1.8> 10/13/89 EKN Cleanup UpdateLastID. Added FIDGetID.
|
|||
|
; 10/12/89 EKN Cleanup UpdateLastID some.
|
|||
|
; <1.7> 9/29/89 EKN REWORK ExchangeFiles AND Some minor twiddles in styleish stuff
|
|||
|
; from code review.
|
|||
|
; 9/28/89 EKN Minor twiddles on stylish stuff from code review. MAIN Thing:
|
|||
|
; Quit on ioErrors. Only Back out of DskFulErr. AND BIGGIE:
|
|||
|
; Redesign ExchangeFiles and MoveExtents to make it simpler.
|
|||
|
; BugFix: ResolveID and DeleteID should CMPI.B for cdrType tests.
|
|||
|
; <1.6> 8/29/89 EKN FIDDeleteID and FIDResolveID doing CMPI.W instead of CMPI.B
|
|||
|
; #cdrThdRec.
|
|||
|
; <1.5> 7/24/89 EKN ExchangeFiles: Fix & cleanup backing out of errors A LOT.
|
|||
|
; Cathints as parameters. Give bogusID back. Exch mod dates.
|
|||
|
; 7/24/89 EKN Give nextID back after Exchange. Pretty up: Capitalize all
|
|||
|
; "bsr"s; Change all JSRs to BSRs; Fix comments; Change labels.
|
|||
|
; Cleaned up "backing out of errors" in ExchangeFiles A LOT! Add
|
|||
|
; exchanging of mod dates (in CopyCNodeInfo). Have ExchangeFiles
|
|||
|
; take cat hints as parameters.
|
|||
|
; <1.4> 5/30/89 dnf Getting more kinks out
|
|||
|
; <1.3> 5/30/89 dnf Change MOVEQ to MOVE.W for errors which changed to < -127
|
|||
|
; <1.2> 5/30/89 dnf Changes to support HFS7.0 Enhancements ptch
|
|||
|
; 5/29/89 EKN Created file.
|
|||
|
; <1.1> 5/24/89 rwh include inc.sum.a to fix build problems
|
|||
|
; <1.0> 5/15/89 EKN New for FileIDs facility.
|
|||
|
;
|
|||
|
; To Do:
|
|||
|
;
|
|||
|
;-- THINGS TO DO (FUTURE ENHANCEMENTS):
|
|||
|
;-- 1) Make common setup routine for 4 external calls, if we decide not to vector all 4.
|
|||
|
;
|
|||
|
|
|||
|
;_________________________________________________________________________________
|
|||
|
;
|
|||
|
; External
|
|||
|
; Routines: FIDCreateID - Creates a file thread to an HFS existing file.
|
|||
|
; FIDDeleteID - Destroys the file thread to the HFS File.
|
|||
|
; FIDGetID - Returns the value of the file ID if it exists.
|
|||
|
; FIDResolveID - Given a fileID, returns the parID and cname of the file.
|
|||
|
; FIDExchangeFiles - Swaps the data of the files. For doing "save as".
|
|||
|
;
|
|||
|
; Note about VCBDirIDM: dnf <2>
|
|||
|
; The indexed GetCatInfo call (and CMGetOff below it) depend on the fact
|
|||
|
; that if VCBDirIDM is non-zero then the current btree hint is at VCBOffsM
|
|||
|
; in directory VCBDirIDM. Thus, on an indexed call CMGetOff can do a
|
|||
|
; quick BTGetRec instead of a search.
|
|||
|
;
|
|||
|
; All of the catalog manager routines which can change the hint clear
|
|||
|
; VCBDirIDM. However, the FileIDsSvcs routines in this file don't use
|
|||
|
; any of the CMxxx routines, so VCBDirIDM needs to be cleared manually in
|
|||
|
; here.
|
|||
|
;
|
|||
|
;_________________________________________________________________________________
|
|||
|
|
|||
|
|
|||
|
BLANKS ON ; need semicolons to separate comments now
|
|||
|
STRING ASIS ; strings are the way they look
|
|||
|
PRINT PUSH
|
|||
|
PRINT OFF ; don't send lines to assembly listing file
|
|||
|
LOAD 'StandardEqu.d'
|
|||
|
include 'LinkedPatchMacros.a'
|
|||
|
PRINT POP ; okay, send the lines for the listing
|
|||
|
PRINT NOGEN ; don't show the macro expansions
|
|||
|
|
|||
|
FileIDsSvcs PROC EXPORT
|
|||
|
|
|||
|
EXPORT FIDCreateID, FIDDeleteID, FIDGetID, FIDResolveID, FIDExchangeFiles
|
|||
|
|
|||
|
;_________________________________________________________________________________
|
|||
|
;
|
|||
|
; Routine: FIDCreateID (Create a file thread)
|
|||
|
;
|
|||
|
; Function: FIDCreateID creates a file thread to an HFS file. The file thread
|
|||
|
; is similar to a directory thread, with it's key being a
|
|||
|
; [fileCNodeID, NULL], instead of a [dirID, NULL]. If the file thread
|
|||
|
; exists, fidExists is returned in D0, and the ID in D1 anyway.
|
|||
|
;
|
|||
|
; Input: A2.L - VCB pointer
|
|||
|
; D0.L - DirID
|
|||
|
; A0.L - CName pointer
|
|||
|
;
|
|||
|
; Output: D0.W - result code
|
|||
|
; 0 = ok
|
|||
|
; CMnotfound = CNode not found
|
|||
|
; CMExists = CNode for file thread exists
|
|||
|
; cmFThdDirErr = file is a directory, not a file
|
|||
|
; -n = IO Error
|
|||
|
; D1.L - file thread
|
|||
|
; Modification History:
|
|||
|
; <11Jan91> KSCT File with a thread could be moved on the 6.0 system without updating the
|
|||
|
; thread record. FIDCreateID should check and do the update if necessary.
|
|||
|
;_______________________________________________________________________________________________
|
|||
|
|
|||
|
FIDCrRegs reg D2-D6/A1/A3-A4
|
|||
|
FIDCreateID:
|
|||
|
|
|||
|
;
|
|||
|
; do some initial stuff
|
|||
|
;
|
|||
|
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
|
|||
|
MOVEM.L FIDCrRegs, -(A6) ; save registers
|
|||
|
MOVE.L D0,D6 ; save the par ID
|
|||
|
MOVEA.L A0,A3 ; save the cname ptr
|
|||
|
jsrROM CMSETUP ; set up key storage pointed to by A4
|
|||
|
MOVEQ #0,D5 ; clear fileID, in case we return early due to errors
|
|||
|
CLR.L VCBDirIDM(A2) ; invalidate current DirID marker
|
|||
|
;
|
|||
|
; locate the file record
|
|||
|
;
|
|||
|
MOVEQ #0,D2 ; no catalog hint
|
|||
|
jsrROM LOCCREC
|
|||
|
BNE @CrExit ; it's not there, just exit with what's in D0
|
|||
|
CMPI.B #cdrFilRec, cdrType(A1); better be a file (type=2)
|
|||
|
BNE.S @CrNotAFileErr
|
|||
|
MOVE.L D2,D4 ; save cat hint for later
|
|||
|
MOVE.B FilFlags(A1),D3 ; save the flag byte <11Jan91 #10>
|
|||
|
;
|
|||
|
; build the key for the file thread
|
|||
|
;
|
|||
|
MOVE.L filFlNum(A1), D0 ; get file's CNode id for fthread key
|
|||
|
MOVE.L D0,D5 ; keep fileID for later
|
|||
|
SUBA.L A0,A0 ; use NULL for fthread key name
|
|||
|
LEA ckrOff(A4), A1 ; use this storage for the fthread key
|
|||
|
jsrROM BUILDKEY ; fill in the key
|
|||
|
;
|
|||
|
; and do the data of the file thread
|
|||
|
;
|
|||
|
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
|
|||
|
MOVE.B #cdrfThdRec, cdrType(A1)
|
|||
|
MOVE.L D6, thdParID(A1) ; the saved parID
|
|||
|
|
|||
|
MOVEA.L A3, A0 ; the cname ptr
|
|||
|
LEA thdCName(A1), A1
|
|||
|
jsrROM UPDCNAME
|
|||
|
;
|
|||
|
; Insert the file thread in the catalog btree
|
|||
|
;
|
|||
|
MOVE.W VCBCtRef(A2), D0 ; refnum of catalog file
|
|||
|
MOVE.W #lenthd, D1
|
|||
|
LEA cdrOff(A4), A1
|
|||
|
LEA ckrOff(A4), A0
|
|||
|
jsrROM BTINSERT
|
|||
|
BNE.S @CrBTErr ; could be disk full, so stop
|
|||
|
;
|
|||
|
; finally, turn on thread flag in file CNode. Too bad, gotta find it again
|
|||
|
;
|
|||
|
MOVE.L D4, D2 ; use saved cat hint
|
|||
|
MOVE.L D6, D0 ; dirID or parent dirID
|
|||
|
MOVEA.L A3, A0 ; CName pointer
|
|||
|
jsrROM LOCCREC ; we know it's there
|
|||
|
BSET #fThreadFlag,FilFlags(A1); set the flag
|
|||
|
|
|||
|
MOVE.W VCBCtRef(A2),D0 ; refnum of catalog file
|
|||
|
jsrROM BTUPDATE
|
|||
|
BNE.S @CRExit ; if there was an error, catalog could be shot!
|
|||
|
;
|
|||
|
; get it out to disk
|
|||
|
;
|
|||
|
jsrROm CMFLUSH ; flush the catalog
|
|||
|
BRA.S @CrExit
|
|||
|
;
|
|||
|
; handle errors
|
|||
|
;
|
|||
|
@CrNotAFileErr
|
|||
|
MOVE.W #cmFThdDirErr,D0 ; Error "cmFThdDirErr = it is a directory"
|
|||
|
BRA.S @CrExit
|
|||
|
@CrBTErr CMP.W #BTExists,D0
|
|||
|
BNE.S @CrExit ; It maybe out of space. Let it pass through.
|
|||
|
|
|||
|
;; Thread already exists, check if the thread info is consistent. <11Jan91 #10>
|
|||
|
;; Fixing a bug if the file has been MOVED or RENAMED on a 6.0 system which doesn't update FID info!
|
|||
|
MOVE.L D5,D0 ; file number <11Jan91 #10>
|
|||
|
SUBA.L A0,A0 ; no Cname <11Jan91 #10>
|
|||
|
MOVEQ #0,D2 ; no hint <11Jan91 #10>
|
|||
|
jsrROM LOCCREC ; locate thread record <11Jan91 #10>
|
|||
|
BNE.S @7 ; bad time for error <11Jan91 #10>
|
|||
|
|
|||
|
CMP.B #cdrfThdRec,cdrType(A1) ; file thread type? <11Jan91 #10>
|
|||
|
BNE.S @7 ; serious problem <11Jan91 #10>
|
|||
|
BTST #fThreadFlag,D3 ; flag should be set <11Jan91 #10>
|
|||
|
BEQ.S @7 ; serious problem <11Jan91 #10>
|
|||
|
CMP.L thdParID(A1),D6 ; has the file been moved? <14Jan91 #11>
|
|||
|
BEQ.S @4 ; NO, (this is the common case) <11Jan91 #10>
|
|||
|
MOVE.L D6,thdParID(A1) ; otherwise, update it <11Jan91 #10>
|
|||
|
MOVEQ #0,D3 ; D3 = 0 means we changed the file <11Jan91 #10>
|
|||
|
@4
|
|||
|
LEA thdCName(A1),A1 ; the dest cname ptr <11Jan91 #10>
|
|||
|
MOVEA.L A3,A0 ; the source cname ptr <11Jan91 #10>
|
|||
|
MOVEM.L A0/A1,-(SP) ; save two names <11Jan91 #10>
|
|||
|
MOVEQ #0,D0 ; clear D0 <11Jan91 #10>
|
|||
|
MOVE.B (A0)+,D0 ; D0(high order word) = length of A0 <11Jan91 #10>
|
|||
|
SWAP D0 ; swap it <11Jan91 #10>
|
|||
|
MOVE.B (A1)+,D0 ; D0( low order word) = length of A1 <11Jan91 #10>
|
|||
|
_RelString ; has the file been renamed? <14Jan91 #11>
|
|||
|
MOVEM.L (SP)+,A0/A1 ; restore the names <11Jan91 #10>
|
|||
|
BEQ.S @5 ; NO, (this is the common case) <11Jan91 #10>
|
|||
|
; A0/A1 preserved across the call <11Jan91 #10>
|
|||
|
MOVEQ #1,D0 ; include length byte <11Jan91 #10>
|
|||
|
ADD.B (A0),D0 ; D0.L = length of source <11Jan91 #10>
|
|||
|
_BlockMove ; A0 -> A1 <11Jan91 #10>
|
|||
|
BRA.S @6 ; always updateBT <11Jan91 #10>
|
|||
|
@5 TST.W D3 ; have we changed the file? <11Jan91 #10>
|
|||
|
BNE.S @7 ; no <11Jan91 #10>
|
|||
|
@6 MOVE.W VCBCtRef(A2),D0 ; refnum of catalog file (input = D0/D2) <11Jan91 #10>
|
|||
|
jsrROM BTUPDATE ; mark the node (D2) dirty <11Jan91 #10>
|
|||
|
BNE.S @CrExit ; bad time for error <11Jan91 #10>
|
|||
|
jsrROm CMFLUSH ; flush the catalog (input = A2) <11Jan91 #10>
|
|||
|
BNE.S @CrExit ; bad time for error <11Jan91 #10>
|
|||
|
|
|||
|
@7 MOVE.W #CMExists,D0 ; Translate error "CMExists = cnode already there"
|
|||
|
;
|
|||
|
; cleanup and return
|
|||
|
;
|
|||
|
@CrExit MOVE.L D5,D1 ; return the file id
|
|||
|
ADD #lenCMVars,A6 ; de-allocate memory for CM vars
|
|||
|
MOVEM.L (A6)+, FIDCrRegs ; restore regs
|
|||
|
|
|||
|
MOVE.L (A6)+,-(SP) ; put return address back on stack
|
|||
|
TST.W D0 ; set condition codes
|
|||
|
RTS ; exit FIDCreateID
|
|||
|
|
|||
|
|
|||
|
; sameNameP
|
|||
|
; Input: A1 = cat. file name
|
|||
|
; A3 = user's file name
|
|||
|
; Output: BEQ if 2 names are the same
|
|||
|
LEA thdCName(A1), A1
|
|||
|
jsrROM UPDCNAME
|
|||
|
|
|||
|
|
|||
|
;_________________________________________________________________________________
|
|||
|
;
|
|||
|
; Routine: FIDDeleteID (Delete a file thread)
|
|||
|
;
|
|||
|
; Function: FIDDeleteID invalidates a file id, by removing the thread from the
|
|||
|
; from the cat file and by turning off the file CNode link flag.
|
|||
|
;
|
|||
|
; Input: A2.L - VCB pointer
|
|||
|
; D0.L - file thread
|
|||
|
;
|
|||
|
; Output: D0.W - result code
|
|||
|
; 0 = ok
|
|||
|
; CMnotfound = CNode not found
|
|||
|
; cmFThdGone = File thread not found
|
|||
|
; cmFThdDirErr = file is a directory, not a file
|
|||
|
; -n = IO error
|
|||
|
;_________________________________________________________________________________
|
|||
|
|
|||
|
FIDDelRegs reg D1-D7/A1/A3-A4
|
|||
|
FIDDeleteID:
|
|||
|
|
|||
|
;
|
|||
|
; do some initial stuff
|
|||
|
;
|
|||
|
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
|
|||
|
MOVEM.L FIDDelRegs,-(A6) ; save registers
|
|||
|
jsrROM CMSETUP ; set up key storage pointed to by A4
|
|||
|
MOVE.L D0, D5 ; save fileID
|
|||
|
MOVEQ #0, D7 ; save error in here, if CNode for file is missing
|
|||
|
CLR.L VCBDirIDM(A2) ; invalidate current DirID marker
|
|||
|
;
|
|||
|
; locate the file thread
|
|||
|
;
|
|||
|
MOVEQ #0, D2 ; no catalog hint
|
|||
|
SUBA.L A0, A0 ; use NULL for fthread key.
|
|||
|
jsrROM LOCCREC
|
|||
|
BNE.S @DlNoThdErr ; it's not there
|
|||
|
CMPI.B #cdrFThdRec, cdrType(A1); better be a file
|
|||
|
BNE.S @DlNotAFileErr
|
|||
|
;
|
|||
|
; and then find the file
|
|||
|
;
|
|||
|
MOVEQ #0, D2 ; no catalog hint
|
|||
|
MOVE.L thdParID(A1), D0 ; get file's dir id from fthread data
|
|||
|
LEA thdCName(A1), A0 ; and it's name
|
|||
|
jsrROM LOCCREC
|
|||
|
BEQ.S @DlUnsetFlg
|
|||
|
MOVE.W D0, D7 ; need to return the error later
|
|||
|
BNE.S @DlDelThd ; whoops, it's not there...well, delete the thread
|
|||
|
;
|
|||
|
; ** NOTE: If LocCNode were modified for fthreads, the two LocCRecs above could be avoided
|
|||
|
;
|
|||
|
; turn off thread flag in file CNode
|
|||
|
;
|
|||
|
@DlUnsetFlg BCLR #fThreadFlag,FilFlags(A1)
|
|||
|
MOVE.W VCBCtRef(A2), D0 ; refnum of catalog file
|
|||
|
jsrROM BTUPDATE ; tell the btree
|
|||
|
BNE.S @DlExit ; if there's an error, the catalog could be shot!
|
|||
|
;
|
|||
|
; Delete the file thread in the catalog btree
|
|||
|
;
|
|||
|
@DlDelThd MOVE.L D5, D0 ; file id
|
|||
|
SUBA.L A0,A0 ; use NULL for fthread key
|
|||
|
LEA ckrOff(A4), A1 ; use this storage for fthread key
|
|||
|
jsrROM BUILDKEY ; fill in the key
|
|||
|
|
|||
|
LEA ckrOff(A4), A0 ; get the storage again
|
|||
|
MOVE.W VCBCtRef(A2), D0 ; refnum of catalog file
|
|||
|
jsrROM BTDELETE ; delete file thread
|
|||
|
BNE.S @DlExit ; we know it exists, so must be IOError...
|
|||
|
; ...Oh well, leave the cnode's fthread flag off.
|
|||
|
;
|
|||
|
; get it out to disk.
|
|||
|
;
|
|||
|
jsrROM CMFLUSH ; flush the catalog
|
|||
|
MOVE.W D7, D0 ; should be clear, unless file CNode was missing
|
|||
|
BRA.S @DlExit
|
|||
|
;
|
|||
|
; handle errors
|
|||
|
;
|
|||
|
@DlNoThdErr CMP.W #CMNotFound, D0 ; translate the error so callee knows it wasn't a fnfErr
|
|||
|
BNE.S @DlExit
|
|||
|
MOVE.W #cmFThdGone, D0
|
|||
|
BRA.S @DlExit
|
|||
|
@DlNotAFileErr
|
|||
|
MOVE.W #cmFThdDirErr, D0 ; Error "cmFThdDirErr = it's a directory"
|
|||
|
;
|
|||
|
; cleanup and return
|
|||
|
;
|
|||
|
@DlExit ADD #lenCMVars,A6 ; de-allocate memory for CM vars
|
|||
|
MOVEM.L (A6)+, FIDDelRegs ; restore regs
|
|||
|
|
|||
|
MOVE.L (A6)+,-(SP) ; put return address back on stack
|
|||
|
TST.W D0 ; set condition codes
|
|||
|
RTS ; exit FIDDeleteID
|
|||
|
|
|||
|
|
|||
|
;_________________________________________________________________________________
|
|||
|
;
|
|||
|
; Routine: FIDGetID (Get a file thread)
|
|||
|
;
|
|||
|
; Function: FIDGetID returns a file thread to an HFS file if it exists.
|
|||
|
;
|
|||
|
; Input: A2.L - VCB pointer
|
|||
|
; D0.L - DirID
|
|||
|
; A0.L - CName pointer
|
|||
|
;
|
|||
|
; Output: D0.W - result code
|
|||
|
; 0 = ok
|
|||
|
; CMnotfound = CNode not found
|
|||
|
; cmFThdGone = File thread not found
|
|||
|
; cmFThdDirErr = file is a directory, not a file
|
|||
|
; -n = IO Error
|
|||
|
; D1.L - file thread
|
|||
|
;_________________________________________________________________________________
|
|||
|
|
|||
|
FIDGtRegs reg A1/A4/D2
|
|||
|
FIDGetID:
|
|||
|
|
|||
|
;
|
|||
|
; do some initial stuff
|
|||
|
;
|
|||
|
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
|
|||
|
MOVEM.L FIDGtRegs, -(A6) ; save registers
|
|||
|
jsrROM CMSETUP ; set up key storage pointed to by A4
|
|||
|
MOVEQ #0, D5 ; clear fileID, in case we return early due to errors
|
|||
|
CLR.L VCBDirIDM(A2) ; invalidate current DirID marker
|
|||
|
;
|
|||
|
; locate the file record
|
|||
|
;
|
|||
|
MOVEQ #0, D2 ; no catalog hint
|
|||
|
jsrROM LOCCREC
|
|||
|
BNE @GtExit ; it's not there, just exit with what's in D0
|
|||
|
CMPI.B #cdrFilRec, cdrType(A1); better be a file
|
|||
|
BNE.S @GtNotAFileErr
|
|||
|
;
|
|||
|
; finally, if the file thread flag is set, grab the fileID and set D0
|
|||
|
;
|
|||
|
BTST #fThreadFlag,FilFlags(A1); tst the flag
|
|||
|
BEQ.S @GtNoThdErr
|
|||
|
MOVE.L filFlNum(A1),D1 ; save file number
|
|||
|
BRA.S @GtExit1
|
|||
|
;
|
|||
|
; handle errors
|
|||
|
;
|
|||
|
@GtNotAFileErr
|
|||
|
MOVE.W #cmFThdDirErr, D0 ; Error "cmFThdDirErr = it is a directory"
|
|||
|
BRA.S @GtExit
|
|||
|
@GtNoThdErr MOVE.W #cmFThdGone, D0 ; Error "cmFThdGone = file ID doesn't exist"
|
|||
|
;
|
|||
|
; cleanup and return
|
|||
|
;
|
|||
|
@GtExit MOVE.L D5, D1 ; return the file id
|
|||
|
@GtExit1 ADD #lenCMVars,A6 ; de-allocate memory for CM vars
|
|||
|
MOVEM.L (A6)+, FIDGtRegs ; restore regs
|
|||
|
|
|||
|
MOVE.L (A6)+,-(SP) ; put return address back on stack
|
|||
|
TST.W D0 ; set condition codes
|
|||
|
RTS ; exit FIDGetID
|
|||
|
|
|||
|
;_________________________________________________________________________________
|
|||
|
;
|
|||
|
; Routine: FIDResolveID (Resolves a file thread)
|
|||
|
;
|
|||
|
; Function: FIDResolveID finds the dirID and CName for a file, given it's thread.
|
|||
|
;
|
|||
|
; Input: A2.L - VCB pointer
|
|||
|
; D0.L - file thread
|
|||
|
; A0.L - CName pointer (empty storage)
|
|||
|
;
|
|||
|
; Output: D0.W - result code
|
|||
|
; 0 = ok
|
|||
|
; cmFThdDirErr = file is a directory, not a file
|
|||
|
; CMNotFound = Cnode not found (where cnode is file thread)
|
|||
|
; -n = IO Error
|
|||
|
; A0.L - CName pointer (filled in storage)
|
|||
|
; D1.L - dirID
|
|||
|
; 23Aug90 KST Checking for possible dangling fileID and delete the thread record if it is.
|
|||
|
;_________________________________________________________________________________
|
|||
|
|
|||
|
FIDResRegs reg D2-D6/A1/A3-A5 ; <why saving all those regs?? 23Aug90>
|
|||
|
FIDResolveID:
|
|||
|
|
|||
|
;
|
|||
|
; do some initial stuff
|
|||
|
;
|
|||
|
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
|
|||
|
MOVEM.L FIDResRegs,-(A6) ; save registers
|
|||
|
MOVE.L D0,D3 ; save fileID
|
|||
|
jsrROM CMSETUP ; set up key record and data storage
|
|||
|
MOVEA.L A0, A3 ; save cName ptr
|
|||
|
CLR.L VCBDirIDM(A2) ; invalidate current DirID marker
|
|||
|
;
|
|||
|
; locate the file thread
|
|||
|
;
|
|||
|
;; MOVEQ #0, D2 ; no catalog hint <23Aug90>
|
|||
|
SUBA.L A0, A0 ; use NULL for file name.
|
|||
|
jsrROM LOCCREC
|
|||
|
BNE.S @RsExit ; it's not there, pass error on up
|
|||
|
CMPI.B #cdrFThdRec, cdrType(A1); better be a file
|
|||
|
BNE.S @RsNotAFileErr
|
|||
|
;
|
|||
|
; extract the info
|
|||
|
MOVE.L thdParID(A1), D0 ; get file's dir id from fthread data
|
|||
|
LEA thdCName(A1), A0 ; and it's name
|
|||
|
MOVEM.L D0/D2/A0,-(A6) ; save dirID/hint/name <23Aug90>
|
|||
|
MOVEQ #0, D2 ; no catalog hint <23Aug90>
|
|||
|
jsrROM LOCCREC ; does the file exist? <23Aug90>
|
|||
|
MOVEM.L (A6)+,D1/D2/A0 ; restore dirID/hint/name <23Aug90>
|
|||
|
BNE.S @dangling ; it's not there <23Aug90>
|
|||
|
|
|||
|
;; we found the file, but is this the file we really want? <21Sep90>
|
|||
|
CMP.L filFlNum(A1),D3 ; file number match? <21Sep90>
|
|||
|
BNE.S @dangling ; it's not <21Sep90>
|
|||
|
|
|||
|
MOVEA.L A3, A1 ; the cname ptr
|
|||
|
jsrROM UPDCNAME
|
|||
|
MOVEQ #0, D0 ; to be safe
|
|||
|
;
|
|||
|
; cleanup and exit
|
|||
|
;
|
|||
|
@RsExit ADD #lenCMVars,A6 ; de-allocate memory for CM vars
|
|||
|
MOVEM.L (A6)+, FIDResRegs ; restore regs
|
|||
|
|
|||
|
MOVE.L (A6)+,-(SP) ; put return address back on stack
|
|||
|
TST.W D0 ; set condition codes
|
|||
|
RTS ; exit FIDResolveID
|
|||
|
;
|
|||
|
; handle errors
|
|||
|
;
|
|||
|
@RsNotAFileErr
|
|||
|
MOVE.W #cmFThdDirErr, D0 ; Error "cmFThdDirErr = it's a directory"
|
|||
|
BRA.S @RsExit
|
|||
|
@dangling
|
|||
|
;; This is a dangling fID, if the volume is writable, <24Aug90>
|
|||
|
;; then delete the thread record in the catalog btree. <23Aug90>
|
|||
|
; jsrROM CVFLGS ; is VOL writable? (IN: A2=vcb) <24Aug90>
|
|||
|
; BNE.S @2 ; no, don't bother with delete <24Aug90>
|
|||
|
|
|||
|
; MOVE.L D3,D0 ; file id <23Aug90>
|
|||
|
; SUBA.L A0,A0 ; use NULL for fthread key <23Aug90>
|
|||
|
; LEA ckrOff(A4), A1 ; use this storage for fthread key <23Aug90>
|
|||
|
; jsrROM BUILDKEY ; fill in the key <23Aug90>
|
|||
|
|
|||
|
; LEA ckrOff(A4),A0 ; get the storage again <23Aug90>
|
|||
|
; MOVE.W VCBCtRef(A2),D0 ; refnum of catalog file <23Aug90>
|
|||
|
; jsrROM BTDELETE ; delete file thread <23Aug90>
|
|||
|
; BNE.S @2 ; this must be IOError or VolLocked <23Aug90>
|
|||
|
; jsrROM CMFLUSH ; flush the catalog <23Aug90>
|
|||
|
|
|||
|
;; Now we just return an error, we don't delete the Fid. <21Sep90>
|
|||
|
@2 MOVE.W #badFidErr,D0 ; treat it as fidNotFound error <21Sep90>
|
|||
|
BRA.S @RsExit ; and return <23Aug90>
|
|||
|
|
|||
|
;_________________________________________________________________________________
|
|||
|
;
|
|||
|
; Routine: FIDExchangeFiles
|
|||
|
;
|
|||
|
; Function: FIDExchangeFiles exchanges the data of the source and dest files. It has to
|
|||
|
; locate the CNodes, check for extents in extents file, exchange them,
|
|||
|
; and then exchange the CNode file record info pertaining to data
|
|||
|
; (lengths, extents, and mod dates).
|
|||
|
; All other CNode info remains unchanged (finder info, create/backup dates).
|
|||
|
; FIDExchangeFiles gives apps the functionality of a "safe save".
|
|||
|
;
|
|||
|
; Input: A2.L - VCB pointer
|
|||
|
; D1.L - destination directory id
|
|||
|
; D0.L - source directory id
|
|||
|
; A1.L - destination name
|
|||
|
; A0.L - source name
|
|||
|
; D2.L - src cat hint to CNode rec
|
|||
|
; D3.L - dest cat hint to Cnode rec
|
|||
|
;
|
|||
|
; Output: D0.W - result code
|
|||
|
; 0 = ok
|
|||
|
; cmFThdDirErr = file is a directory, not a file
|
|||
|
; CMNotFound = Cnode for source or dest not found
|
|||
|
; -n = IO error
|
|||
|
;_________________________________________________________________________________
|
|||
|
|
|||
|
FIDExchRegs reg D1-D7/A0-A1/A3-A5
|
|||
|
FIDExchangeFiles:
|
|||
|
|
|||
|
;
|
|||
|
; STEP 0: DO SOME INITIAL STUFF
|
|||
|
;
|
|||
|
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
|
|||
|
MOVEM.L FIDExchRegs, -(A6) ; save registers
|
|||
|
SUB #lenFIDSwapVars, A6 ; grab some storage
|
|||
|
MOVEA.L A6, A4 ; set storage to A4
|
|||
|
MOVEA.L A1, A3 ; save dest Cname for later
|
|||
|
MOVEA.L A0, A5 ; save src CName for later
|
|||
|
MOVE.L D1, destDIDOff(A4)
|
|||
|
MOVE.L D0, srcDIDOff(A4)
|
|||
|
MOVE.L D3, D7 ; save dest catHint for later
|
|||
|
MOVE.L D2, D6 ; save src catHint for later
|
|||
|
CLR.L VCBDirIDM(A2) ; invalidate current DirID marker
|
|||
|
|
|||
|
;
|
|||
|
; STEP 1: GRAB THE CNODE RECORDS AND CHECK FOR EXTENTS IN EXTENT FILE
|
|||
|
;
|
|||
|
; locate the source file, test for extents in extent file, and copy the cat record for later
|
|||
|
;
|
|||
|
CLR.W extFlgsOff(A4) ; assume no extents in extents file
|
|||
|
jsrROM LOCCREC ; A0, D0, D2 already set up from input
|
|||
|
BNE @ExExit ; either CNode not there or io error
|
|||
|
CMPI.B #cdrFilRec, cdrType(A1); better be a file
|
|||
|
BNE @ExNotAFileErr
|
|||
|
MOVE.L D2, D6 ; save the catHint in case it changed
|
|||
|
|
|||
|
LEA filExtRec(A1), A0 ; are there extents in source data fork
|
|||
|
MOVE.L filPyLen(A1), D0
|
|||
|
BSR CheckExtents
|
|||
|
TST.W D0
|
|||
|
BEQ.S @ExNxt
|
|||
|
BSET #srcExt, extFlgsOff(A4)
|
|||
|
BRA.S @ExNxt1 ; no need to check resource fork now
|
|||
|
|
|||
|
@ExNxt LEA filRExtRec(A1), A0 ; are there extents in source resource fork
|
|||
|
MOVE.L filRPyLen(A1), D0
|
|||
|
BSR CheckExtents
|
|||
|
TST.W D0
|
|||
|
BEQ.S @ExNxt1
|
|||
|
BSET #srcExt, extFlgsOff(A4)
|
|||
|
|
|||
|
@ExNxt1 MOVEA.L A1, A0 ; source - the cnode in memory
|
|||
|
LEA srcCNode(A4), A1 ; dest - the cnode on the stack
|
|||
|
MOVEQ #lencdr, D0 ; length of file record
|
|||
|
_BlockMove
|
|||
|
;
|
|||
|
; locate the dest file, test for extents in extent file, and copy the cat record for later
|
|||
|
;
|
|||
|
MOVE.L D7, D2 ; catalog hint
|
|||
|
MOVE.L destDIDOff(A4), D0 ; it's dir id
|
|||
|
MOVEA.L A3, A0 ; it's name
|
|||
|
jsrROM LOCCREC ; keep the cat hint in D2 for the BTUpdate later
|
|||
|
BNE @ExExit ; either CNode not there or io error (callee knows it's there!)
|
|||
|
CMPI.B #cdrFilRec, cdrType(A1); better be a file
|
|||
|
BNE @ExNotAFileErr
|
|||
|
MOVE.L D2, D7 ; save the catHint in case it changed
|
|||
|
|
|||
|
LEA filExtRec(A1), A0 ; are there extents in dests data fork
|
|||
|
MOVE.L filPyLen(A1), D0
|
|||
|
BSR CheckExtents
|
|||
|
TST.W D0
|
|||
|
BEQ.S @ExNxt2
|
|||
|
BSET #destExt, extFlgsOff(A4)
|
|||
|
BRA.S @ExNxt3 ; no need to check resource fork now
|
|||
|
|
|||
|
@ExNxt2 LEA filRExtRec(A1), A0 ; are there extents in dests resource fork
|
|||
|
MOVE.L filRPyLen(A1), D0
|
|||
|
BSR CheckExtents
|
|||
|
TST.W D0
|
|||
|
BEQ.S @ExNxt3
|
|||
|
BSET #destExt, extFlgsOff(A4)
|
|||
|
|
|||
|
@ExNxt3 MOVEA.L A1, A0 ; source - the cnode in memory
|
|||
|
LEA destCNode(A4), A1 ; dest - the cnode on the stack
|
|||
|
MOVEQ #lencdr, D0 ; length of file record
|
|||
|
_BlockMove
|
|||
|
|
|||
|
;
|
|||
|
; STEP 2: EXCHANGE THE EXTENTS KEY IN THE EXTENT FILE (IF ANY)
|
|||
|
; NOTE: We could avoid some backing out of errors on DskFullErr if we checked free space first, right?
|
|||
|
;
|
|||
|
MOVEQ #fidBogusExtID, D0 ; first delete any existing extents of this value (resulting from a crash)
|
|||
|
BSR DeleteExts
|
|||
|
BNE @ExExit ; best to stop
|
|||
|
|
|||
|
LEA srcCNode(A4), A0 ; get the source cnode record
|
|||
|
LEA destCNode(A4), A1 ; get the dest cnode record
|
|||
|
|
|||
|
BTST #srcExt, extFlgsOff(A4) ; does the source file have extents?
|
|||
|
BNE.S @ExYesSrc ; yep, =>
|
|||
|
BTST #destExt, extFlgsOff(A4) ; nope, so test dest
|
|||
|
BNE.S @ExNoSrcExt ; yep, no source extents, but some dest extents
|
|||
|
BRA.S @ExGetOut ; YIPPIE!!! No extents in extents files!
|
|||
|
|
|||
|
@ExYesSrc BTST #destExt, extFlgsOff(A4) ; src has extents, what about dest?
|
|||
|
BEQ.S @ExNoDestExt ; no dest extents, so =>
|
|||
|
;
|
|||
|
; GROSS! Extents in both files. Now we got grab a new ID to move one set of extents into
|
|||
|
;
|
|||
|
MOVEQ #fidBogusExtID, D5 ; get the ID reserved for exchanging extents
|
|||
|
MOVE.L filFlNum(A0), D1 ; move this ID to ...
|
|||
|
MOVE.L D5, D2 ; ...this one
|
|||
|
BSR MoveExtents ; change source extents to bogus id extents
|
|||
|
BNE @ExUndo1
|
|||
|
MOVE.L filFlNum(A1), D1 ; move this ID to ...
|
|||
|
MOVE.L filFlNum(A0), D2 ; ... this one
|
|||
|
BSR MoveExtents ; change dest extents to source extents
|
|||
|
BNE @ExUndo2
|
|||
|
MOVE.L D5, D1 ; move this ID to ...
|
|||
|
MOVE.L filFlNum(A1), D2 ; ... this one
|
|||
|
BSR MoveExtents ; change bogus id extents to dest extents
|
|||
|
BNE.S @ExUndo3
|
|||
|
BRA.S @ExGetOut
|
|||
|
|
|||
|
@ExNoSrcExt MOVE.L filFlNum(A1), D1 ; move this ID to...
|
|||
|
MOVE.L filFlNum(A0), D2 ; ... this one
|
|||
|
BSR MoveExtents
|
|||
|
BNE @ExUndo0
|
|||
|
BRA.S @ExGetOut
|
|||
|
|
|||
|
@ExNoDestExt MOVE.L filFlNum(A0), D1 ; move this ID to ...
|
|||
|
MOVE.L filFlNum(A1), D2 ; ... this one
|
|||
|
BSR MoveExtents
|
|||
|
BNE @ExUndo0
|
|||
|
;
|
|||
|
; STEP 3: CHANGE THE DATA IN THE CNODES
|
|||
|
;
|
|||
|
; find the source cnode and put dest info in it
|
|||
|
;
|
|||
|
@ExGetOut MOVE.L D6, D2 ; catalog hint
|
|||
|
MOVEA.L A5,A0 ; it's name
|
|||
|
MOVE.L srcDIDOff(A4), D0 ; it's dir id
|
|||
|
jsrROM LOCCREC
|
|||
|
BNE @ExBusted
|
|||
|
|
|||
|
LEA destCNode(A4), A0 ; from saved dest (A0) to memory src (A1)
|
|||
|
BSR CopyCNodeInfo
|
|||
|
|
|||
|
MOVE.W VCBCtRef(A2), D0
|
|||
|
jsrROM BTUPDATE ; tell the btree
|
|||
|
BNE @ExExit ; if there's an error, the catalog could be shot!
|
|||
|
|
|||
|
;
|
|||
|
; find the destination cnode and put source info in it
|
|||
|
;
|
|||
|
MOVE.L D7, D2 ; catalog hint
|
|||
|
MOVEA.L A3, A0 ; it's name
|
|||
|
MOVE.L destDIDOff(A4), D0 ; it's dir id
|
|||
|
jsrROM LOCCREC ; keep cat hint in D2 for the BTUpdate later
|
|||
|
BNE @ExBusted
|
|||
|
|
|||
|
LEA srcCNode(A4), A0 ; from saved src (A0) to memory dest (A1)
|
|||
|
BSR CopyCNodeInfo
|
|||
|
|
|||
|
MOVE.W VCBCtRef(A2), D0
|
|||
|
jsrROM BTUPDATE ; tell the btree
|
|||
|
BNE @ExExit ; if there's an error, the catalog could be shot!
|
|||
|
BRA.S @ExFinishUp
|
|||
|
|
|||
|
;
|
|||
|
; STEP 4: ERROR HANDLING SECTION (just deal with DiskFulErr. With the others, stop and don't flush!)
|
|||
|
;
|
|||
|
@ExUndo3 CMP.W #dskFulErr, D0
|
|||
|
BNE @ExExit ; don't flush a thing on other errors!
|
|||
|
MOVE.L filFlNum(A1), D0 ; delete dest extents
|
|||
|
BSR DeleteExts
|
|||
|
BNE.S @ExExit ; we are doomed. Just QUIT!
|
|||
|
MOVE.L filFlNum(A1), D2
|
|||
|
MOVE.L filFlNum(A0), D1
|
|||
|
BSR MoveExtents ; move source extents back into dest extents
|
|||
|
BNE.S @ExExit ; we are doomed. Just QUIT!
|
|||
|
BRA.S @ExUndo2a
|
|||
|
|
|||
|
@ExUndo2 CMP.W #dskFulErr, D0
|
|||
|
BNE.S @ExExit ; don't flush a thing on other errors!
|
|||
|
@ExUndo2a MOVE.L filFlNum(A0), D0 ; delete src extents
|
|||
|
BSR DeleteExts
|
|||
|
BNE.S @ExExit ; we are doomed. Just QUIT!
|
|||
|
MOVE.L filFlNum(A0), D2
|
|||
|
MOVE.L D5, D1
|
|||
|
BSR MoveExtents ; move nextID extents back into source extents
|
|||
|
BNE.S @ExExit ; we are doomed. Just QUIT!
|
|||
|
BRA.S @ExUndo1a
|
|||
|
|
|||
|
@ExUndo1 CMP.W #dskFulErr, D0
|
|||
|
BNE.S @ExExit ; don't flush a thing on other errors!
|
|||
|
@ExUndo1a MOVE.L D5, D0 ; delete nextID extents
|
|||
|
BSR DeleteExts
|
|||
|
BNE.S @ExExit ; we are doomed. Just QUIT!
|
|||
|
BRA.S @ExFinishErr
|
|||
|
|
|||
|
@ExUndo0 CMP.W #dskFulErr, D0
|
|||
|
BNE.S @ExExit ; don't flush a thing on other errors!
|
|||
|
MOVE.L D2, D0
|
|||
|
BSR DeleteExts ; delete src or dest
|
|||
|
BNE.S @ExExit ; we are doomed. Just QUIT!
|
|||
|
;
|
|||
|
; STEP 5: ALL DONE....ALMOST...
|
|||
|
;
|
|||
|
@ExFinishErr
|
|||
|
jsrROM CMFLUSH ; flush the catalog
|
|||
|
jsrROM XFFLUSH ; flush the extent file (unneeded for common case, but it's cheap)
|
|||
|
MOVE.W #dskFulErr, D0 ; well, report the original error even if the flushes croaked.
|
|||
|
BRA.S @ExExit
|
|||
|
@ExNotAFileErr
|
|||
|
MOVE.W #cmFThdDirErr, D0 ; Error "cmFThdDirErr = it's a directory"
|
|||
|
BRA.S @ExExit
|
|||
|
@ExBusted MOVE.W #cmBadNews, D0 ; the cnode record got lost after we looked it up
|
|||
|
BRA.S @ExExit
|
|||
|
;
|
|||
|
; cleanup and return
|
|||
|
;
|
|||
|
@ExFinishUp
|
|||
|
MOVEQ #0, D0 ; no errors....yet...
|
|||
|
jsrROM CMFLUSH ; flush the catalog
|
|||
|
jsrROM XFFLUSH ; flush the extent file (unneeded for common case, but it's cheap)
|
|||
|
@ExExit ADD #lenFIDSwapVars,A6 ; de-allocate memory for CM vars
|
|||
|
MOVEM.L (A6)+, FIDExchRegs ; restore regs
|
|||
|
|
|||
|
MOVE.L (A6)+,-(SP) ; put return address back on stack
|
|||
|
TST.W D0 ; set condition codes
|
|||
|
RTS ; exit FIDExchangeFiles
|
|||
|
|
|||
|
|
|||
|
;__________________________________________________________________________________
|
|||
|
; INTERNAL ROUTINES
|
|||
|
;__________________________________________________________________________________
|
|||
|
|
|||
|
;__________________________________________________________________________________
|
|||
|
; Routine: CheckExtents
|
|||
|
;
|
|||
|
; Function: Checks the extents in CNode to see if there are any more in the
|
|||
|
; extent file.
|
|||
|
;
|
|||
|
; Input: A0.L - addr(extent in CNODE of data or resource fork)
|
|||
|
; D0.L - peof of file
|
|||
|
; A2.L - vcb pointer
|
|||
|
;
|
|||
|
; Output: D0.W - first FABN in extent file (or zero if none in extent file)
|
|||
|
; A0.L - unchanged from input
|
|||
|
;
|
|||
|
; <30Mar91> KSCT Fixing a bug in ExchangeFile which uses a signed
|
|||
|
; branch on an unsigned comparison.
|
|||
|
;__________________________________________________________________________________
|
|||
|
|
|||
|
CheckExtents:
|
|||
|
|
|||
|
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
|
|||
|
MOVEM.L D1-D4, -(A6) ; save registers
|
|||
|
|
|||
|
MOVE.L D0, D3 ; extract peof (it's in bytes and a long word)
|
|||
|
TST.L D3 ; convert it to blocks
|
|||
|
BEQ.S @ChNoneThere ; zero length file
|
|||
|
SUBQ.L #1, D3
|
|||
|
DIVU.W vcbAlBlkSiz+2(A2), D3 ; the high word could have trash in it, but we don't care
|
|||
|
ADDQ.W #1, D3 ; now the peof is in blocks and only a word size
|
|||
|
|
|||
|
@1 CLR.W D1 ; extent offset in extent record
|
|||
|
MOVEQ #0, D0 ; sum of extents allocation blocks
|
|||
|
MOVEQ #numExts-1, D2 ; loop through extents checking for last FABN
|
|||
|
@2 MOVE.W xdrNumABlks(A0, D1.W), D4 ; make sure we only pick up a word!
|
|||
|
ADD.W D4, D0
|
|||
|
CMP.W D3, D0 ; check for eof
|
|||
|
BHS.S @ChNoneThere ; greater than or equal (extents can add past eof if 'Close" crashes w/o truncating new clump)
|
|||
|
; changed from BGE to BHS <30Mar91 #12>
|
|||
|
ADDQ.W #lenExt, D1 ; bump to next extent
|
|||
|
DBRA D2, @2
|
|||
|
BRA.S @ChExit
|
|||
|
|
|||
|
@ChNoneThere MOVEQ #0, D0
|
|||
|
@ChExit MOVEM.L (A6)+, D1-D4 ; restore regs
|
|||
|
MOVE.L (A6)+,-(SP) ; put return address back on stack
|
|||
|
RTS
|
|||
|
|
|||
|
;_________________________________________________________________________________
|
|||
|
; CopyCNodeInfo
|
|||
|
;
|
|||
|
; Routine: CopyCNodeInfo
|
|||
|
;
|
|||
|
; Function: Copies the info in the file cnode record relating to data exchanges.
|
|||
|
;
|
|||
|
; NOTE: If the layout in the catalog file record changes between bytes 24-98,
|
|||
|
; this WILL BREAK!
|
|||
|
;
|
|||
|
; Input: A0.L - from
|
|||
|
; A1.L - to
|
|||
|
;_________________________________________________________________________________
|
|||
|
|
|||
|
CopyCNodeInfo:
|
|||
|
|
|||
|
MOVE.L (SP)+, -(A6)
|
|||
|
MOVEM.L D0/A0-A1, -(A6)
|
|||
|
|
|||
|
ADDA.W #filStBlk, A1 ; set up to copy filStBlk, filLgLen, filPyLen, ...
|
|||
|
ADDA.W #filStBlk, A0 ; ...filRStBlk, filRLgLen, filRPyLen
|
|||
|
MOVE.W #((filCrDat-filStBlk)/2)-1, D0
|
|||
|
@1 MOVE.W (A0)+, (A1)+
|
|||
|
DBRA D0, @1
|
|||
|
|
|||
|
ADDA.W #4, A0 ; skip past the filCrDat
|
|||
|
ADDA.W #4, A1 ; skip past the filCrDat
|
|||
|
MOVE.L (A0)+, (A1)+ ; copy the filMdDat
|
|||
|
|
|||
|
ADDA.W #(filExtRec-filBkDat), A1 ; set up to copy filExtRec and filRExtRec
|
|||
|
ADDA.W #(filExtRec-filBkDat), A0
|
|||
|
MOVE.W #((filResrv-filExtRec)/2)-1, D0
|
|||
|
@2 MOVE.W (A0)+, (A1)+
|
|||
|
DBRA D0, @2
|
|||
|
|
|||
|
MOVEM.L (A6)+, D0/A0-A1
|
|||
|
MOVE.L (A6)+, -(SP)
|
|||
|
RTS
|
|||
|
|
|||
|
;__________________________________________________________________________________
|
|||
|
; Routine: CopyExtentInfo
|
|||
|
;
|
|||
|
; Function: Copy the key and data extents to a storage.
|
|||
|
;
|
|||
|
; Input: A0.L - addr(key)
|
|||
|
; A1.L - addr(data)
|
|||
|
; A3.L - addr(extent storage)
|
|||
|
;
|
|||
|
; Output: A3.L - addr(end of extent storage, all filled in)
|
|||
|
;__________________________________________________________________________________
|
|||
|
|
|||
|
CopyExtentInfo:
|
|||
|
|
|||
|
MOVE.L (SP)+, -(A6) ; save return address on A6 stack
|
|||
|
MOVEM.L D0/A0-A1, -(A6)
|
|||
|
|
|||
|
MOVEQ #(lenxkr/2)-1, D0 ; copy the key
|
|||
|
@1 MOVE.W (A0)+, (A3)+
|
|||
|
DBRA D0, @1
|
|||
|
MOVEQ #(lenxdr/2)-1, D0 ; copy the data
|
|||
|
@2 MOVE.W (A1)+, (A3)+ ; A3 should be right place at start
|
|||
|
DBRA D0, @2
|
|||
|
|
|||
|
MOVEM.L (A6)+, D0/A0-A1
|
|||
|
MOVE.L (A6)+, -(SP) ; put return address back on stack
|
|||
|
RTS
|
|||
|
|
|||
|
;__________________________________________________________________________________
|
|||
|
; Routine: DeleteExts
|
|||
|
;
|
|||
|
; Function: Delete all extents in extent file that have the ID given.
|
|||
|
;
|
|||
|
; Input: A4.L - fidSwapVars pointer (pointer to variable storage)
|
|||
|
; A2.L - vcb pointer
|
|||
|
; D0.L - ID of file with extents to delete
|
|||
|
;
|
|||
|
; Output: D0.W - errors
|
|||
|
;__________________________________________________________________________________
|
|||
|
|
|||
|
DXRegs reg D1-D3/D6/A0-A1
|
|||
|
DeleteExts:
|
|||
|
;
|
|||
|
; set up some initial stuff
|
|||
|
;
|
|||
|
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
|
|||
|
MOVEM.L DXRegs, -(A6) ; save registers
|
|||
|
MOVE.L D0, D6 ; save it for later
|
|||
|
;
|
|||
|
; set up key to delete
|
|||
|
;
|
|||
|
LEA tempKeyOff(A4), A0 ; get the blank key we started out with
|
|||
|
MOVE.B #lenxkr-1, xkrKeyLen(A0)
|
|||
|
CLR.B xkrFkType(A0) ; clear the fork
|
|||
|
MOVE.L D0, xkrFNum(A0) ; set the key's ID
|
|||
|
CLR.W xkrFABN(A0) ; clear the FABN
|
|||
|
;
|
|||
|
; start grabbing extents from extent file and delete them
|
|||
|
;
|
|||
|
@DXNxtDelete
|
|||
|
MOVEQ #0, D2 ; no hint (after BTDelete) <09Aug90>
|
|||
|
MOVE.W VCBXTRef(A2), D0 ; extents file refnum
|
|||
|
jsrROM BTSEARCH ; search BTree for extent record
|
|||
|
CMP.W #BTNotFound, D0
|
|||
|
BNE.S @DXExit ; has to be an ioerror!
|
|||
|
MOVEQ #0, D1 ; get what it's pointing at
|
|||
|
MOVE.W VCBXTRef(A2), D0 ; extents file refnum
|
|||
|
jsrROM BTGETRECORD ; this is the first record we want for this file
|
|||
|
BNE.S @DXBtErr
|
|||
|
CMP.L xkrFNum(A0), D6
|
|||
|
BNE.S @DXExit ; Yippie!!! We're done!
|
|||
|
|
|||
|
MOVE.W VCBXTRef(A2), D0 ; extent file's refnum
|
|||
|
jsrROM BTDELETE ; and delete from btree (AO has key)
|
|||
|
BNE.S @DXExit
|
|||
|
|
|||
|
LEA tempKeyOff(A4), A0 ; look again
|
|||
|
BRA.S @DXNxtDelete
|
|||
|
;
|
|||
|
; handle errors
|
|||
|
;
|
|||
|
@DXBTErr CMP.W #BTNotFound, D0
|
|||
|
BNE.S @DXExit ; let the other errors go on up
|
|||
|
CLR.W D0
|
|||
|
;
|
|||
|
; cleanup and return
|
|||
|
;
|
|||
|
@DXExit MOVEM.L (A6)+, DXRegs ; restore regs
|
|||
|
MOVE.L (A6)+,-(SP) ; put return address back on stack
|
|||
|
TST.W D0 ; set condition codes
|
|||
|
RTS
|
|||
|
|
|||
|
;_________________________________________________________________________________
|
|||
|
; MoveExtents
|
|||
|
;
|
|||
|
; Routine: MoveExtents
|
|||
|
;
|
|||
|
; Function: Reads in up to four extent records at a time, change the ID in the keys,
|
|||
|
; and inserts them back in the extent btree.
|
|||
|
; Then searches again one-by-one for the original extents and deletes them.
|
|||
|
;
|
|||
|
; NOTE: Picking four extent records up is just a guess. Perhaps more is
|
|||
|
; necessary. But since we're getting the storage for them off the A6
|
|||
|
; stack, best not take too much. However, the fewer we pick up the more
|
|||
|
; disk arm movement will occur during the "search, edit, insert"
|
|||
|
; per extent record cycle
|
|||
|
;
|
|||
|
; Input: D1.L - source key ID
|
|||
|
; D2.L - dest key ID
|
|||
|
; A2.L - vcb pointer
|
|||
|
; A4.L - fidSwapVars pointer (pointer to variable storage)
|
|||
|
;
|
|||
|
; Output: D0 - errors
|
|||
|
; All others - unchanged
|
|||
|
;_________________________________________________________________________________
|
|||
|
|
|||
|
MvRegs reg D1-D7/A0-A1/A3-A4
|
|||
|
MoveExtents:
|
|||
|
|
|||
|
extSize EQU lenxkr+lenxdr
|
|||
|
|
|||
|
;
|
|||
|
; do some initial stuff
|
|||
|
;
|
|||
|
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
|
|||
|
MOVEM.L MvRegs, -(A6); save registers
|
|||
|
|
|||
|
MOVE.L D1, D6 ; save src ID for later
|
|||
|
MOVE.L D2, D7 ; save dest ID for later
|
|||
|
;
|
|||
|
; collect the extent records
|
|||
|
;
|
|||
|
LEA tempKeyOff(A4), A0 ; get some key storage
|
|||
|
MOVE.B #lenxkr-1, xkrKeyLen(A0)
|
|||
|
CLR.B xkrFkType(A0) ; clear the fork
|
|||
|
MOVE.L D6, xkrFNum(A0) ; set the key's ID
|
|||
|
CLR.W xkrFABN(A0) ; clear the FABN
|
|||
|
|
|||
|
@MvNextBatch MOVE.W VCBXTRef(A2), D0 ; extents file refnum
|
|||
|
MOVEQ #0, D2 ; no hint
|
|||
|
jsrROM BTSEARCH ; search BTree for extent record.
|
|||
|
CMP.W #BtNotFound, D0 ; it won't exist the first time thru the loop
|
|||
|
BEQ.S @MvGoOn
|
|||
|
TST.W D0
|
|||
|
BNE @MvExit ; must be ioError
|
|||
|
MOVEQ #1, D1 ; second or later batch has to skip over last key searched
|
|||
|
BRA.S @MvGoOn1
|
|||
|
@MvGoOn MOVEQ #0, D1 ; get what it's pointing at
|
|||
|
@MvGoOn1 MOVEQ #numExtToCache-1, D3 ; set up counter
|
|||
|
LEA extOff(A4), A3 ; extent ptr
|
|||
|
|
|||
|
@MvNextRec MOVE.W VCBXTRef(A2), D0 ; extents file refnum
|
|||
|
jsrROM BTGETRECORD ; this is the first record we want for this file
|
|||
|
CMP.W #BtNotFound, D0 ; if xkrFNum(A0) is cleared on this error, then this test is bogus!
|
|||
|
BEQ.S @MvNoMoreExts
|
|||
|
TST.W D0
|
|||
|
BNE.S @MvExit ; must be ioError
|
|||
|
CMP.L xkrFNum(A0), D6
|
|||
|
BNE.S @MvNoMoreExts ; whoops, no more of this file's extents
|
|||
|
BSR CopyExtentInfo ; copy the key and data to storage
|
|||
|
MOVEQ #1, D1 ; tell it you want the next record
|
|||
|
DBRA D3, @MvNextRec
|
|||
|
;
|
|||
|
; edit each extent key, and reinsert each extent record in the extent file
|
|||
|
;
|
|||
|
@MvNoMoreExts
|
|||
|
CMP.W #numExtToCache-1, D3 ; did we do anything?
|
|||
|
BEQ.S @MvGoDelete ; nope, we're done collecting and inserting
|
|||
|
MOVEQ #numExtToCache-2, D0 ; -1 for loop counting, -1 cause counter had a DBRA
|
|||
|
SUB.W D3, D0 ; number of valid extents (-1) for looping
|
|||
|
MOVE.W D0, D3
|
|||
|
SWAP D3 ; save for later
|
|||
|
MOVE.W D0, D3
|
|||
|
|
|||
|
LEA extOff(A4), A0 ; pointer to key
|
|||
|
MOVEA.L A0, A1
|
|||
|
ADDQ #lenxkr, A1 ; pointer to data
|
|||
|
MOVEQ #lenxdr, D1 ; data length
|
|||
|
@2 MOVE.L D7, xkrFNum(A0) ; change only the id in the key to dest ID
|
|||
|
MOVE.W VCBXTRef(A2), D0 ; extent file's refnum
|
|||
|
jsrROM BTINSERT ; insert in btree
|
|||
|
BNE.S @MvBTInsertErr
|
|||
|
ADDA.W #extSize, A0
|
|||
|
ADDA.W #extSize, A1
|
|||
|
DBRA D3, @2
|
|||
|
;
|
|||
|
; okay, done with this batch, go get the next set of extent records
|
|||
|
;
|
|||
|
SWAP D3 ; check how many were cached
|
|||
|
CMP.W #numExtToCache-1, D3
|
|||
|
BNE.S @MvGoDelete ; since it stopped early, must not be anymore
|
|||
|
SUBA #extSize, A0 ; get the last key cached ...
|
|||
|
MOVE.L D6, xkrFNum(A0) ; change it back to what it was before the insert code...
|
|||
|
BRA.S @MvNextBatch ; ... and go search again
|
|||
|
;
|
|||
|
; we are done with all the inserts. Now go and delete the old entries.
|
|||
|
;
|
|||
|
@MvGoDelete MOVE.L D6, D0 ; srcID
|
|||
|
BSR DeleteExts
|
|||
|
BRA.S @MvExit
|
|||
|
;
|
|||
|
; handle errors
|
|||
|
;
|
|||
|
@MvBTInsertErr
|
|||
|
CMP.W #BTExists, D0 ; BUG!
|
|||
|
BNE.S @MvExit ; let the other errors go on up
|
|||
|
MOVE.W #cmbadnews, D0
|
|||
|
;
|
|||
|
; cleanup and return
|
|||
|
;
|
|||
|
@MvExit MOVEM.L (A6)+, MvRegs ; restore regs
|
|||
|
MOVE.L (A6)+,-(SP) ; put return address back on stack
|
|||
|
TST.W D0 ; set condition codes
|
|||
|
RTS
|
|||
|
|
|||
|
|
|||
|
ENDP
|
|||
|
END
|