boot3/OS/HFS/FXM.a

1117 lines
38 KiB
Plaintext
Raw Permalink Normal View History

;
; File: FXM.a
;
; Contains: These routines provide functions used to access and maintain
; file extents.
;
; Written by: Bill Bruffey
;
; Copyright: <09> 1985-1992 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <SM1> 4/1/92 kc Export XFFlush.
; <09> Pre-SuperMario comments follow <20>
; <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.
; <<3C>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<53>
; 3/24/87 BB Fixed bug in MapFBlock which was incorrectly calculating the
; starting logical block number (a word value was being added
; rather than a long word value). This fix rolls in patches S118
; in ROMAllFix and PM119 in ROM75Fix.
; 10/27/86 BB Vectored MapFBlock and XFSearch routines.
; 9/25/86 BB Updated to use new MPW equate files.
; 1/9/86 BB Added use of an option flags byte to TruncateFile. An option
; flag was defined to indicate 'truncate to end of extent'
; replacing the current use of the FlushOnly flag for that
; purpose.
; 1/8/86 BB Added use of an option flags byte to ExtendFile. Two flags were
; defined indicating 'all or nothing' and 'contiguous' allocation
; requests. The ROM75 SetEOF patch supporting the 'all or nothing'
; allocation was integrated into the code.
; 10/28/85 BB TruncateFile now truncates based on the current state of the
; "FlushOnly" flag. If FlushOnly is set, the file is truncated at
; the end of the extent containing the new PEOF. If FlushOnly is
; not set, the file is truncated to the new PEOF rounded to the
; next allocation block. Truncate File now sets the PEOF in the
; FCB once new PEOF has been successfully mapped.
; 10/25/85 BB Added common FX set up routine. Added vectors for ROM versions.
; 10/22/85 PWD Fixed TruncateFile bug when starting deallocation in FCB ext.
; rec.
; 10/17/85 BB Replaced extent record BlockMoves with MOVE.L loops. XRUpdate
; now returns updated hints. ExtendFile no longer requires a
; re-map of the PEOF in order to add more than one extent.
; 10/16/85 BB Cleaned up some.
; 10/2/85 LAK Code-saving pass.
; 10/1/85 LAK MapFBlock now returns D0 as result code rather than end block+1.
; 9/26/85 PWD Fixed bug in MapFBlock w. >512 byte allocation blocks
; 9/23/85 BB Modified MapFBlock to save low level error code before calling
; SysError.
; 9/19/85 BB Fixed another bug in TruncateFile, D3 was not being set up
; following a truncation of the last extent in the FCB.
; 9/17/85 BB Fixed bug in TruncateFile, was not saving BTree hints.
; 8/27/85 BB Added support for contiguous allocation.
; 7/10/85 BB Added XFFlush subroutine and the necessary calls to it.
; 6/27/85 BB Reworked MapFBlock. Added check in DeAllocFile to verify the
; CNode type.
; 6/22/85 PWD Fixed MapFBlock bug in computation of available bytes
; 5/30/85 BB Modified TruncateFile to handle a new PEOF = 0.
; 5/20/85 BB Fixed bug in XFSearch, it wasn't checking for 'not found' result
; code from BTGetRecord.
; 5/15/85 BB Fixed bug in ExtendFile, return code was getting trashed.
; 5/13/85 BB Fixed PEOF stuff.
; 4/29/85 BB Rewrote from Gary's initial version and added support for FCB
; resident extents.
;
;_________________________________________________________________________________
;
; External
; Routines: DeAllocFile - Deallocates all disk space for a given file.
; ExtendFile - Extends the disk space allocated to a file.
; FXMKeyCmp - Compares two extent file keys.
; MapFBlock - Maps a file position into a physical disk
; address.
; TruncateFile - Truncates the disk space allocated to a file.
;
; Internal
; Subroutines: XFFlush - Flushes the extent BTree file.
; XFSearch - Searches extent file (including the FCB resident
; extent record) for a given file position.
; XRSearch - Searches an extent record for a given file
; allocation block number (FABN).
; XRUpdate - Updates an extent record.
;
;_________________________________________________________________________________
BLANKS ON
STRING ASIS
PRINT OFF
LOAD 'StandardEqu.d'
PRINT ON
PRINT NOGEN
FXM PROC EXPORT
EXPORT DeAllocFile,Extendfile,FXMKeyCmp,MapFBlock,TruncateFile,XFFlush
EXPORT vDeallocFile,vExtendFile,vMapFBlock,vTruncateFile,vXFSearch ;<27Oct86>
IMPORT BTGetRecord,BTDelete,BTFlush,BTInsert,BtSearch,BTUpdate
IMPORT BlkAlloc,BlkDealloc
IMPORT CMGetCN
IMPORT MarkVCB,FlushMDB
;_________________________________________________________________________________
;
; Routine: DeallocFile (Deallocate File)
;
; Function: De-allocates all disk space allocated to a specified file.
; The space occupied by both forks is deallocated.
;
; Input: A2.L - VCB pointer
; D0.W - ParID
; A0.L - CName pointer
;
; Output: D0.W - result code
; 0 = ok
; other = error
;
; Called by: DeleteFile
;
; Note: The extent records resident in catalog are not updated by DeallocFile.
; DeleteFile deletes the catalog record for the file after calling
; DeallocFile.
;_________________________________________________________________________________
DeallocFile
MOVE.L jDeallocFile,-(SP) ; jump table entry for vDeallocFile <25Oct85>
RTS ; go there <25Oct85>
vDeallocFile ; 'vectored' DeallocFile routine <25Oct85>
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
MOVEM.L D1-D7/A0-A1/A3-A4,-(A6) ; save registers
BSR FXSetUp ; set up common stuff <25Oct85>
MOVEA.L A0,A3 ; A3 = ptr to Cname
MOVE.L D0,D7 ; D7 = ParID
CLR.B D6 ; D6 = initial fork type (0 = data fork)
; Locate catalog record for file
DFFkLoop
CLR.W D4 ; initial FABN
MOVEA.L A3,A0 ; ptr to Cname
MOVE.L D7,D0 ; ParID
CLR.L D2 ; no hint
JSR CMGetCN ; locate catalog record
BNE DFExit1 ; didn't get it ->
CMPI.B #CMFilCN,cdrType(A1) ; file CNode?
BEQ.S @1 ; yes ->
MOVEQ #CMnotfound,D0 ; result = 'not found' <02Oct85>
BNE DFExit1 ; exit ->
@1 MOVE.L filFlNum(A1),D5 ; D5 = file number
LEA FXVxkrOff(A4),A0 ; ptr to FXM key buffer
CLR.W xkrFABN(A0) ; indicate catalog resident extent record
TST.B D6 ; deleting the data fork?
BNE.S @2 ; no ->
LEA filExtRec(A1),A1 ; position to data fork extent record
BRA.S DFCopyRec ; copy extent record ->
@2 LEA filRExtRec(A1),A1 ; position to resource fork extent record
BRA.S DFCopyRec ; copy extent record ->
;
; set up key for next extent file record
;
DFRecLoop
LEA FXVxkrOff(A4),A0 ; A0 points to FXM key buffer
MOVE.B #lenxkr-1,xkrKeyLen(A0) ; key length
MOVE.B D6,xkrFkType(A0) ; fork type
MOVE.L D5,xkrFNum(A0) ; file number
MOVE.W D4,xkrFABN(A0) ; file alloc block number
;
; get the next extent record
;
MOVE.W VCBXTRef(A2),D0 ; extents file refnum
CLR.L D2 ; no hint
JSR BTSearch ; find the record
BEQ.S DFCopyRec ; found it ->
CMPI.W #BTnotfound,D0 ; record not found?
BEQ.S DFNxtFork ; yes, done with this fork ->
BRA.S DFExit1 ; error ->
;
; copy extent data to FXM buffer
;
DFCopyRec
LEA FXVxdrOff(A4),A0 ; dest = xdr buffer in fxm vars <17Oct85>
MOVEQ #(lenxdr/4)-1,D0 ; loop index in long words <17Oct85>
@1 MOVE.L (A1)+,(A0)+ ; Copy the record <17Oct85>
DBRA D0,@1 ; <17Oct85>
;
; release extents for this record
;
LEA FXVxdrOff(A4),A1 ; A1 = ptr to extent record <17Oct85>
CLR.W D1 ; offset to 1st extent
DFRelExt
MOVE.W xdrStABN(A1,D1.W),D2 ; starting alloc blk number
MOVE.W xdrNumABlks(A1,D1.W),D3 ; number of alloc blks
BEQ.S DFDelRec ; extent not used, delete the record ->
JSR BlkDealloc ; deallocate the space
BNE.S DFExit1 ; error ->
ADD.W D3,D4 ; bump FABN to beg of next extent
ADDQ.W #lenExt,D1 ; bump to next extent
CMPI.W #maxExtOff,D1 ; past last extent?
BLE.S DFRelExt ; no, release next one ->
;
; delete extent record
;
DFDelRec
LEA FXVxkrOff(A4),A0 ; A0 points to search key
TST.W xkrFABN(A0) ; catalog resident record?
BEQ.S @1 ; yes, nothing to delete ->
MOVE.W VCBXTRef(A2),D0 ; extents file refnum
JSR BTDelete ; delete the record
BNE.S DFExit1 ; error ->
@1 TST.W D3 ; end with null extent entry?
BNE.S DFRecLoop ; no, get next record for same fork ->
;
; finished with current fork, check for another one
;
DFNxtFork
NOT.B D6 ; just finished resource fork ($FF -> $00)? <02Oct85>
BNE DFFkLoop ; $00 -> $FF: release space for resource fork <02Oct85>
;
; clean up and exit
;
DFExit
CLR.W D0 ; result = ok
BSR XFFlush ; flush the extent file
DFExit1
ADD #lenFXVars,A6 ; de-allocate memory for FXM vars <02Oct85>
MOVEM.L (A6)+,D1-D7/A0-A1/A3-A4 ; restore regs
MOVE.L (A6)+,-(SP) ; put return address back on stack
TST.W D0 ; set up condition codes
RTS ; exit DeallocFile
;_________________________________________________________________________________
;
; Routine: Extendfile
;
; Function: Extends the disk space allocated to a file.
;
; Input: A2.L - VCB pointer
; A1.L - pointer to FCB array
; D1.W - file refnum
; D3.B - option flags
; EFContig - force contiguous allocation
; EFAll - allocate all requested bytes or none
; D4.L - number of additional bytes to allocate
;
; Output: D0.W - result code
; 0 = ok
; -n = IO error
; D6.L - number of bytes allocated
;
; Called by: FileAloc,FileWrite,SetEof
;
; Note: ExtendFile updates the PEOF in the FCB.
;_________________________________________________________________________________
ExtendFile
MOVE.L jExtendFile,-(SP) ; jump table entry for vExtendFile <25Oct85>
RTS ; go there <25Oct85>
vExtendFile ; 'vectored' ExtendFile routine <25Oct85>
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
MOVEM.L D1-D5/D7/A0-A4,-(A6) ; save regs
BSR FXSetUp ; set up common stuff <25Oct85>
LEA 0(A1,D1.W),A3 ; A3 = FCB pointer
MOVE.L FCBPLen(A3),-(A6) ; save previous PEOF
;
; Set up for type of allocation requested.
;
BTST #EFAll,D3 ; all or nothing requested? <08Jan86>
BEQ.S @1 ; no -> <08Jan86>
MOVE.W VCBFreeBks(A2),D0 ; Compute free space in bytes <08Jan86>
MULU VCBAlBlkSiz+2(A2),D0 ; <08Jan86>
CMP.L D4,D0 ; Compare against requested space <08Jan86>
BHS.S @1 ; If enough space free, go on -> <08Jan86>
MOVEQ #DskFulErr,D0 ; result = 'disk full' <08Jan86>
BRA EFExit1 ; exit ExtendFile -> <08Jan86>
@1 BSET #FXVTContig,FXVFlags(A4) ; 1st try contig allocation <27Aug85>
BTST #EFContig,D3 ; forced contiguous requested? <08Jan86>
BEQ.S @2 ; no -> <02Sep85>
BSET #FXVFContig,FXVFlags(A4) ; yes, set flag <27Aug85>
@2 MOVE.L VCBAlBlkSiz(A2),D0 ; round the # of bytes requested
ADD.L D0,D4 ;
SUBQ.L #1,D4 ;
DIVU D0,D4 ;
MULU D0,D4 ; ...up to next alloc blk
;
; locate the extent mapping the new PEOF - 1 (last byte in file)
;
EFLocExt
MOVE.L FCBPLen(A3),D0 ; current PEOF
ADD.L D4,D0 ; + # of bytes requested = new PEOF
SUBQ.L #1,D0 ; new PEOF - 1 = last byte in file
BSR XFSearch ; locate the extent
BNE.S @1 ; didn't find it ->
ADD.L D4,FCBPLen(A3) ; update PEOF
BSET #FCBModBit,FCBMdRByt(A3) ; mark FCB dirty
BRA EFExit ; all done ->
@1 CMPI.W #FXRangeErr,D0 ; out of range?
BNE EFExit1 ; no, some error ->
MOVE.L D2,D7 ; D7 = BTree hint
MOVE.W D3,D6 ; D6 = ending FABN +1
;
; adjust PEOF to end of extent
;
MOVE.W D6,D0 ; (ending FABN + 1)
MULU VCBAlBlkSiz+2(A2),D0 ; in bytes = max PEOF for extent
SUB.L FCBPlen(A3),D0 ; PEOF already at end of extent?
BEQ.S EFAddSpace ; yes ->
ADD.L D0,FCBPlen(A3) ; no, adjust PEOF to end of extent
BSET #FCBModBit,FCBMdRByt(A3) ; mark FCB dirty
SUB.L D0,D4 ; adjust remaining count
;
; allocate additional disk space
;
EFAddSpace
MOVE.W xdrStABN(A1,D1.W),D5 ; starting alloc blk number
ADD.W xdrNumABlks(A1,D1.W),D5 ; + # of blks = last blk +1
@1 MOVE.W D5,D2 ; preferred starting blk = last blk + 1
BTST #FXVTContig,FXVFlags(A4) ; are we trying for contig <27Aug85>
SNE D3 ; yes, set flag for BlkAlloc <27Aug85>
JSR BlkAlloc ; allocate the disk space <27Aug85>
BEQ.S EFExtExt ; got it -> <27Aug85>
CMPI.W #DskFulErr,D0 ; disk full error? <27Aug85>
BNE EFExit1 ; no, some other error -> <27Aug85>
BCLR #FXVTContig,FXVFlags(A4) ; did we just try for contig? <27Aug85>
BEQ EFExit1 ; no, must be out of space -> <27Aug85>
BTST #FXVFContig,FXVFlags(A4) ; forced contig requested? <27Aug85>
BNE EFExit1 ; yes, could't get it -> <27Aug85>
BRA.S @1 ; try non-contig -> <27Aug85>
;
; got some space, see if current extent can be extended
;
EFExtExt
CMP.W D2,D5 ; get preferred space?
BNE.S EFAddExt ; no, must add an extent ->
ADD.W D3,xdrNumABlks(A1,D1.W) ; add new blks to current extent
BRA.S EFUpdExt ; use common code -> <17Oct85>
;
; add a new extent entry
;
EFAddExt
TST.W xdrNumABlks(A1,D1.W) ; current extent null?
BEQ.S @1 ; yes, use it ->
ADDQ.W #lenExt,D1 ; bump to next extent
CMPI.W #maxExtOff,D1 ; past last extent?
BGT.S EFNewRec ; yes, must add new record? ->
@1 MOVE.W D2,xdrStABN(A1,D1.W) ; set starting alloc blk #
MOVE.W D3,xdrNumABlks(A1,D1.W) ; ...and # of blks
;
; update the extent record
;
EFUpdExt
MOVE.L D7,D2 ; BTree hint
BSR XRUpdate ; update the extent record
BNE EFExit1 ; error ->
MOVE.L D2,D7 ; D7 = new hint <17Oct85>
BRA.S EFUpdFCB ; go update FCB ->
;
; add a new extent record
;
EFNewRec
MOVE.L FCBFlNm(A3),D5 ; D5 = file number
CMPI.L #FSXtCNID,D5 ; mapping the extents file?
BNE.S @1 ; no ->
MOVEQ #FXOvFlErr,D0 ; result = 'extent file overflow' <16Oct85>
BRA.S EFExit1 ; exit ->
@1 LEA FXVxkrOff(A4),A0 ; point to FXM buffer
LEA FXVxdrOff(A4),A1 ;
MOVE.B #lenxkr-1,xkrKeyLen(A0) ; key length
CLR.B xkrFkType(A0) ;assume data fork
BTST #FCBRscBit,FCBMdRByt(A3) ; mapping resource fork?
SNE xkrFkType(A0) ; yes, set resource fork flag
MOVE.L D5,xkrFNum(A0) ; file number
MOVE.W D6,xkrFABN(A0) ; starting file allocation blk #
MOVE.W #(lenxdr/2)-1,D0 ; clear new extent record
@2 CLR.W (A1)+ ;
DBRA D0,@2 ;
LEA FXVxdrOff(A4),A1 ; restore ptr to xdr
CLR.W D1 ; offset to 1st extent in record
MOVE.W D2,xdrStABN(A1,D1.W) ; set starting alloc blk #
MOVE.W D3,xdrNumABlks(A1,D1.W) ; ...and # of blks
MOVE.L D1,-(A6) ; save D1 <17Oct85>
MOVE.W #lenxdr,D1 ; record length
MOVE.W VCBXTRef(A2),D0 ; extents file refnum
JSR BTInsert ; insert the new record
MOVE.L (A6)+,D1 ; restore D1 <17Oct85>
TST.W D0 ; restore BTInsert result <17Oct85>
BNE.S EFExit1 ; error ->
MOVE.L D2,D7 ; D7 = new hint <17Oct85>
;
; finished with this extension, update FCB and see if more space is needed
;
EFUpdFCB
ADD.W D3,D6 ; update ending FABN + 1 <17Oct85>
MULU VCBAlBlkSiz+2(A2),D3 ; convert # of blks allocated to bytes
ADD.L D3,FCBPlen(A3) ; adjust PEOF to include new space
BSET #FCBModBit,FCBMdRByt(A3) ; mark FCB dirty
SUB.L D3,D4 ; allocated enough space?
BGT EFAddSpace ; no, do it again -> <17Oct85>
ADD.L D4,FCBPLen(A3) ; adjust PEOF to alloc blk boundry
;
; clean up and exit
;
EFExit
CLR.W D0 ; result = ok
BSR XFFlush ; flush the extent file
EFExit1
MOVE.L FCBPLen(A3),D6 ; new PEOF
MOVE.L (A6)+,D1 ; - previous PEOF
SUB.L D1,D6 ; = # of bytes allocated
ADD #lenFXVars,A6 ; de-allocate memory for FXM vars <02Oct85>
MOVEM.L (A6)+,D1-D5/D7/A0-A4 ; restore regs
MOVE.L (A6)+,-(SP) ; put return address back on stack
TST.W D0 ; set condition codes
RTS ; exit ExtendFile
;_________________________________________________________________________________
;
; Routine: FXMKeyCmp (FXM Key Compare)
;
; Function: Compares two extent file keys (a search key and a trial key).
;
; Input: A0.L - search key pointer
; A1.L - trial key pointer
;
; Output: D0.W - result code
; +n search key > trial key
; 0 search key = trial key
; -n search key < trial key
;_________________________________________________________________________________
FXMKeyCmp
MOVEM.L A0-A1,-(SP) ; save registers
MOVE.L 2(A0),D0 ; compare file ID's
CMP.L 2(A1),D0 ;
BHI.S KCIsGT ; search fileNum > trial fileNum ->
BCS.S KCIsLT ; search fileNum < trial fileNum -> <02Oct85>
;
; file ID's are equal, compare fork types
;
MOVE.B 1(A0),D0 ; Get search key fork type
CMP.B 1(A1),D0 ; Compare against trial fork type
BHI.S KCIsGT ; search key fork type > trial key fork type
BCS.S KCIsLT ; search key fork type < trial key fork type <02Oct85>
;
; fork types are equal; compare the starting block numbers
;
MOVE.W 6(A0),D0 ; compare block numbers
CMP.W 6(A1),D0 ;
BHI.S KCIsGT ; search block # > trial block # ->
BCS.S KCIsLT ; search block # < trial block # -> <02Oct85>
KCIsEQ
CLR.W D0 ; result = "equal"
BRA.S KCExit
KCIsLT
MOVE.W #-1,D0 ; result = "less than"
BRA.S KCExit
KCIsGT
MOVE.W #+1,D0 ; result = "greater than"
KCExit
MOVEM.L (sp)+,A0-A1 ; restore registers
TST.W D0 ; set up condition codes
RTS ; exit FXMKeyCmp
;_________________________________________________________________________________
;
; Routine: MapFBlock
;
; Function: Maps a file position into a physical disk address.
;
; Input: A2.L - VCB pointer
; (A1,D1.W) - FCB pointer
; D4.L - number of bytes desired
; D5.L - file position (byte address)
;
; Output: D3.L - physical start block
; D6.L - number of contiguous bytes available (up to D4 bytes)
; D0.L - result code <01Oct85>
; 0 = ok
; FXRangeErr = file position beyond mapped range <17Oct85>
; FXOvFlErr = extents file overflow <17Oct85>
; other = error <17Oct85>
;
; Called By: Log2Phys (read/write in place), Cache (map a file block).
;_________________________________________________________________________________
MapFBlock
MOVE.L jMapFBlock,-(SP) ; jump table entry for vMapFBlock <27Oct86>
RTS ; go there <27Oct86>
vMapFBlock ; 'vectored' MapFBlock routine <27Oct86>
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
MOVEM.L D1-D2/D4-D5/D7/A0-A1/A3-A4,-(A6) ; save registers
BSR FXSetUp ; set up common stuff <25Oct85>
LEA 0(A1,D1.W),A3 ; A3 = FCB pointer
;
; locate the extent mapping the desired file position
;
MOVE.L D5,D0 ; file position
BSR XFSearch ; locate the extent
BNE.S MFExit ; exit on errors
LEA 0(A1,D1.W),A1 ; A1 = ptr to extent entry
MOVE.W D3,D1 ; D1 = beg FABN for extent
SUB.W xdrNumABlks(A1),D1 ;
MOVE.W D3,D2 ; D2 = end FABN in extent + 1
;
; determine end of available space (PEOF or end of extent)
;
MULU VCBAlBlkSiz+2(A2),D2 ; convert end FABN + 1 to file pos
MOVE.L FCBPLen(A3),D0 ; get PEOF
CMP.L D0,D2 ; end of extent > PEOF?
BLE.S @1 ; no, use end of extent ->
MOVE.L D0,D2 ; yes, use PEOF
@1 DIVU VCBAlBlkSiz+2(A2),D2 ; D2 = end of avail space ( end FABN + 1)
;
; set up some constants
;
MOVE.L VCBAlBlkSiz(A2),D6 ; D6 = # blks per alloc blk
DIVU #512,D6 ;
MOVEQ #0,D7 ; D7 = start blk # for alloc blks
MOVE.W VCBAlBlSt(A2),D7 ;
;
; calculate physical start block
;
MOVE.L D5,D3 ; file position / alloc blk size
DIVU VCBAlBlkSiz+2(A2),D3 ; = FABN mapping file position
SWAP D3 ; Get remainder in low word <PWD 26Sep85>
MOVEQ #0,D0 ; Clear top word to get remainder as long <PWD 26Sep85>
MOVE.W D3,D0 ; Compute block offset within alloc block <PWD 26Sep85>
LSR.L #8,D0 ; 'divide' by 256 <PWD 26Sep85>
LSR.L #1,D0 ; and again by 2 to get size in phys. blocks <PWD 26Sep85>
SWAP D3 ; Restore D3 for use <PWD 26Sep85>
SUB.W D1,D3 ; - beg FABN = alloc blk delta
ADD.W xdrStABN(A1),D3 ; + starting ABN = ABN mapping file pos
MULU D6,D3 ; convert to physical block #
ADD.L D0,D3 ; Offset in physical blocks within alloc. blk <24Mar87>
ADD.L D7,D3 ;
;
; calculate number of available bytes
;
MOVE.W D2,D6 ; end FABN + 1 * alloc blk size
MULU VCBAlBlkSiz+2(A2),D6 ; = ending file pos + 1
SUB.L D5,D6 ; - file position = size avail
CMP.L D4,D6 ; compare with desired number
BCS.S mFBlockOK ; < D4 bytes, leave it alone <02Oct85>
MOVE.L D4,D6 ; > D4 bytes, set to D4 bytes
mFBlockOK MOVEQ #0,D0 ; we're ok <01Oct85>
;
; clean up and exit
;
MFExit
ADD #lenFXVars,A6 ; de-allocate memory for FXM vars <02Oct85>
MOVEM.L (A6)+,D1-D2/D4-D5/D7/A0-A1/A3-A4 ; restore registers
MOVE.L (A6)+,-(SP) ; put return address back on stack
TST.W D0 ; set CCR for result <01Oct85>
RTS ; exit MapFBlock
;_________________________________________________________________________________
;
; Routine: TruncateFile
;
; Function: Truncates the disk space allocated to a file. The file space is
; truncated a specified new PEOF rounded up to the next allocation block
; boundry. If the 'TFTrunExt' option is specified, the file is truncated
; to the end of the extent containing the new PEOF.
;
; Input: A2.L - VCB pointer
; A1.L - pointer to FCB array
; D1.W - file refnum
; D2.B - option flags
; TFTrunExt - truncate to the extent containing new PEOF
; D3.L - new PEOF
;
; Output: D0.W - result code
; 0 = ok
; -n = IO error
;
; Note: TruncateFile updates the PEOF in the FCB.
;_________________________________________________________________________________
TruncateFile
MOVE.L jTruncateFile,-(SP) ; jump table entry for vTruncateFile <25Oct85>
RTS ; go there <25Oct85>
vTruncateFile ; 'vectored' TruncateFile routine <25Oct85>
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
MOVEM.L D1-D7/A0-A4,-(A6) ; save registers
BSR FXSetUp ; set up common stuff <25Oct85>
LEA 0(A1,D1.W),A3 ; A3 = FCB pointer
MOVE.B D2,D6 ; D6 = option flags <09Jan86>
;
; locate the extent mapping the last byte of the truncated file
;
TFLocExt
MOVE.L D3,D5 ; D5 = new PEOF
MOVE.L VCBAlBlkSiz(A2),D0 ; round the new PEOF
ADD.L D0,D5 ;
SUBQ.L #1,D5 ;
DIVU D0,D5 ;
MULU D0,D5 ; ...up to next alloc blk
MOVE.L D5,D0 ; new PEOF - 1 = last byte in file
SUBQ.L #1,D0 ;
BGE.S @1 ; new PEOF > 0 ->
MOVE.L D5,FCBPlen(A3) ; update PEOF in FCB <28Oct85>
BSET #FCBModBit,FCBMdRByt(A3) ; mark FCB dirty <28Oct85>
SUBA.L A0,A0 ; indicate FCB resident record
MOVEQ #0,D7 ; no hint
LEA FCBExtRec(A3),A1 ; point to FCB extent record
CLR.W D4 ; last FABN in extent + 1
BRA TFRelExt ; release all extents -> <28Oct85>
@1 BSR XFSearch ; locate the extent
BNE TFExit1 ; error ->
MOVE.L D2,D7 ; D7 = BTree hint
MOVE.W D3,D4 ; D4 = last FABN in extent + 1
MOVE.L D5,FCBPlen(A3) ; update PEOF in FCB <28Oct85>
BSET #FCBModBit,FCBMdRByt(A3) ; mark FCB dirty <28Oct85>
BTST #TFTrunExt,D6 ; truncate to end of extent? <09Jan86>
BEQ.S TFTrunPEOF ; no, truncate to new PEOF -> <09Jan86>
MOVE.W xdrNumABlks(A1,D1.W),D3 ; D3 = # of blks in extent <28Oct85>
BRA TFRelRExt ; release remaining extents in record -> <28Oct85>
;
; truncate extent containing new PEOF
;
TFTrunPEOF
MOVE.L D5,D0 ; new PEOF - 1 (last byte in file)
SUBQ.L #1,D0 ;
DIVU VCBAlBlkSiz+2(A2),D0 ; / alloc blk size = last FABN in file
SUB.W D0,D3 ; (last extent FABN +1) - (last file FABN)
SUBQ.W #1,D3 ; - 1 = # to deallocate
BEQ.S @1 ; nothing to deallocate ->
MOVE.W xdrStABN(A1,D1.W),D2 ; starting ABN
ADD.W xdrNumABlks(A1,D1.W),D2 ; + # alloc blks in extent
SUB.W D3,D2 ; - # to dealloc = starting ABN
JSR BlkDealloc ; deallocate the space
BNE TFExit1 ; error ->
@1 MOVE.W D3,D0 ; D0 = # of blks deallocated <19Sep85>
MOVE.W xdrNumABlks(A1,D1.W),D3 ; D3 = orig # of blks <19Sep85>
SUB.W D0,xdrNumABlks(A1,D1.W) ; update # of blks in extent <19Sep85>
BNE.S TFRelRExt ; extent not empty ->
CLR.W xdrStABN(A1,D1.W) ; set extent null
BRA.S TFRelRExt ; release remaining extents in record ->
;
; get the next extent record in BTree
;
TFLoop
LEA FXVxkrOff(A4),A0 ; A0 points to search key buffer
MOVE.B #lenxkr-1,xkrKeyLen(A0) ; key length
BTST #FCBRscBit,FCBMdRByt(A3) ; mapping resource fork? <09Jan86>
SNE xkrFkType(A0) ; yes, indicate resource fork <09Jan86>
MOVE.L FCBFlNm(A3),xkrFNum(A0) ; file number
MOVE.W D4,xkrFABN(A0) ; file alloc block number
MOVE.W VCBXTRef(A2),D0 ; extents file refnum
CLR.L D2 ; no hint
JSR BTSearch ; find the record
BEQ.S @1 ; found it ->
CMPI.W #BTnotfound,D0 ; record not found?
BEQ.S TFExit ; yes, all done -> <28Oct85>
BRA.S TFExit1 ; error ->
@1 MOVE.L D2,D7 ; save hint in D7 <17Sep85>
LEA FXVxdrOff(A4),A0 ; dest = xdr buffer in fxm vars <17Oct85>
MOVEQ #(lenxdr/4)-1,D0 ; loop index in long words <17Oct85>
@2 MOVE.L (A1)+,(A0)+ ; Copy the record into FXM buffer <17Oct85>
DBRA D0,@2 ; <17Oct85>
LEA FXVxkrOff(A4),A0 ; A0 = ptr to search key <28Oct85>
LEA FXVxdrOff(A4),A1 ; A1 = ptr to extent record <28Oct85>
;
; release extents for this record
;
TFRelExt
CLR.W D1 ; offset to 1st extent <22Oct85>
TFRelNxt
MOVE.W xdrStABN(A1,D1.W),D2 ; starting alloc blk number
MOVE.W xdrNumABlks(A1,D1.W),D3 ; number of alloc blks
BEQ.S TFUpdRec ; extent not used, update the record ->
JSR BlkDealloc ; deallocate the space
BNE.S TFExit1 ; error ->
CLR.L xdrStABN(A1,D1.W) ; set the extent null
ADD.W D3,D4 ; bump FABN to beg of next extent
TFRelRExt
ADDQ.W #lenExt,D1 ; bump to next extent
CMPI.W #maxExtOff,D1 ; past last extent?
BLE.S TFRelNxt ; no, release next one ->
;
; update extent record
;
TFUpdRec
TST.W xdrNumABlks(A1) ; 1st extent null?
BEQ.S @1 ; yes, delete record ->
MOVE.L D7,D2 ; BTree hint
BSR XRUpdate ; update the record
BRA.S @2 ;
@1 MOVE.L A0,D0 ; FCB resident record?
BEQ.S @2 ; yes, nothing to delete ->
MOVE.W VCBXTRef(A2),D0 ; extents file refnum
JSR BTDelete ; delete the record
BNE.S TFExit1 ; error ->
@2 TST.W D3 ; end with null extent entry?
BNE TFLoop ; no, continue with next record ->
;
; clean up and exit
;
TFExit
CLR.W D0 ; result = ok
BSR.S XFFlush ; flush the extent file <02Oct85>
TFExit1
ADD #lenFXVars,A6 ; de-allocate memory for FXM vars <02Oct85>
MOVEM.L (A6)+,D1-D7/A0-A4 ; restore registers
MOVE.L (A6)+,-(SP) ; put return address back on stack
TST.W D0 ; set condition codes
RTS ; exit TruncateFile
;_________________________________________________________________________________
;
; Internal Subroutines
;_________________________________________________________________________________
;__________________________________________________________________________________
;
; Subroutine: FXSetUp (FXM Set Up)
;
; Function: Sets up for all FXM calls. Space for the FXM variable storage area
; (FXVars) is allocated on the A6 stack. The status flags in FXVars
; are also cleared.
;
; Input: none
;
; Output: A4.L - pointer to FXVars
;__________________________________________________________________________________
FXSetUp
SUB #lenFXVars,A6 ; allocate memory for FXM vars <25Oct85>
MOVEA.L A6,A4 ; A4 = pointer to FXM vars <25Oct85>
CLR.B FXVFlags(A4) ; clear all flags <25Oct85>
RTS ; exit FXSetUp <25Oct85>
;_________________________________________________________________________________
;
; Subroutine: XFFlush (Extent File Flush)
;
; Function: Flushes the extent file for a specified volume.
;
;
; Input: A2.L - VCB pointer
;
; Output: D0.W - result code
; 0 = ok
; other = error
;_________________________________________________________________________________
XFFlush
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
MOVEM.L D1/A1,-(A6) ; save registers
MOVE.W VCBXTRef(A2),D1 ; D1 = refnum of extent file
MOVE.W D1,D0 ; flush the extent BTree
JSR BTFlush ;
BNE.S FFExit1 ; error ->
MOVEA.L FCBSPtr,A1 ; FCB dirty?
BTST #FCBModBit,FCBMdRByt(A1,D1.W) ;
BEQ.S FFExit ; no, all done ->
JSR MarkVCB ; Mark the VCB dirty
JSR FlushMDB ; flush the MDB
BNE.S FFExit1 ; error ->
FFExit
CLR.W D0 ; result ='ok'
FFExit1
MOVEM.L (A6)+,D1/A1 ; restore registers
MOVE.L (A6)+,-(SP) ; put return address back on stack
TST.W D0 ; set condition codes
RTS ; exit XFFlush
;_________________________________________________________________________________
;
; Subroutine: XFSearch (Extent File Search)
;
; Function: Searches extent file (including the FCB resident extent record)
; for the extent mapping a given file position.
;
; Input: A2.L - VCB pointer
; A3.L - FCB pointer
; A4.L - pointer to FXM vars
; D0.L - file position (byte address)
;
; Output: D0.W - result code
; 0 = ok
; FXRangeErr = file position beyond mapped range
; other = error
; A0.L - pointer to extent key record (xkr)
; 0 = FCB resident extent record
; A1.L - pointer to extent data record(xdr)
; D1.L - offset to extent entry in xdr
; result = 0, offset to extent mapping desired FABN
; result = FXRangeErr, offset to last extent in record
; D2.L - BTree hint for extent record
; D3.W - ending FABN +1
;_________________________________________________________________________________
XFSearch
MOVE.L jXFSearch,-(SP) ; jump table entry for vXFSearch <27Oct86>
RTS ; go there <27Oct86>
vXFSearch ; 'vectored' XFSearch routine <27Oct86>
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
MOVEM.L D4-D6,-(A6) ; save regs
MOVE.L D0,D4 ; D4 = file position to be mapped
DIVU VCBAlBlkSiz+2(A2),D4 ; convert to FABN
MOVE.L FCBFlNm(A3),D5 ; D5 = file number
;
; search FCB extent record first
;
FSSchFCB
SUBA.L A0,A0 ; indicate FCB resident record
MOVEQ #0,D2 ; no hint
LEA FCBExtRec(A3),A1 ; point to extent record
MOVE.W D4,D0 ; desired FABN
CLR.W D3 ; starting FABN
BSR XRSearch ; search record for extent entry
BEQ FSExit ; found it ->
CMP.W #maxExtOff,D1 ; end before last extent entry?
BLT FSExit1 ; yes, no more extents ->
TST.W xdrNumABlks(A1,D1.W) ; end with a null extent?
BEQ FSExit1 ; yes, no more extents ->
CMPI.L #FSXtCNID,D5 ; mapping the extents file?
BEQ FSExit1 ; yes, no more extents ->
;
; locate desired record in extents file
;
FSSchFile
LEA FXVxkrOff(A4),A0 ; A0 = ptr to key buffer
MOVE.B #lenxkr-1,xkrKeyLen(A0) ; key length
BTST #FCBRscBit,FCBMdRByt(A3) ; mapping resource fork?
SNE D6 ; yes, set resource fork flag <02Oct85>
MOVE.B D6,xkrFkType(A0) ; D6 = fork flag <02Oct85>
MOVE.L D5,xkrFNum(A0) ; file number
MOVE.W D4,xkrFABN(A0) ; desired file allocation blk #
MOVE.W VCBXTRef(A2),D0 ; extents file refnum
CLR.L D2 ; no hint
JSR BTSearch ; search BTree for extent record
BEQ.S FSCopyRec ; a direct hit ->
CMPI.W #BTnotfound,D0 ; result = 'not found'?
BNE.S FSExit1 ; no, error ->
MOVE.W VCBXTRef(A2),D0 ; extents file refnum
MOVEQ #-1,D1 ; indicate previous record
JSR BTGetrecord ; get previous extent record
BEQ.S @1 ; got it ->
CMPI.W #BTnotfound,D0 ; result = 'not found'?
BEQ.S FSMissed ; yes, no extent record ->
BRA.S FSExit1 ; error ->
@1 CMP.L xkrFNum(A0),D5 ; same file?
BNE.S FSMissed ; no ->
CMP.B xkrFkType(A0),D6 ; same fork?
BEQ.S FSCopyRec ; yes, we got it ->
;
; didn't find extent record in BTree, return pointing to last extent in FCB
;
FSMissed
SUBA.L A0,A0 ; indicate FCB resident record
MOVEQ #0,D2 ; no hint
LEA FCBExtRec(A3),A1 ; point to FCB extent record
MOVE.W #maxExtOff,D1 ; the last extent
MOVEQ #FXRangeErr,D0 ; result = 'range error' <02Oct85>
BRA.S FSExit1 ; exit ->
;
;found extent record, copy the key and data records into FXM vars
;
FSCopyRec
MOVE.L A1,-(SP) ; save ptr(xdr) in cache buffer
LEA FXVxkrOff(A4),A1 ; dest = key buffer in FXM vars <17Oct85>
MOVEQ #(lenxkr/4)-1,D0 ; loop index in long words <17Oct85>
@1 MOVE.L (A0)+,(A1)+ ; Copy the key record <17Oct85>
DBRA D0,@1 ; <17Oct85>
MOVEA.L (SP)+,A0 ; source = xdr in cache buffer
LEA FXVxdrOff(A4),A1 ; dest = xdr in FXM vars
MOVEQ #(lenxdr/4)-1,D0 ; loop index in long words <17Oct85>
@2 MOVE.L (A0)+,(A1)+ ; Copy the data record <17Oct85>
DBRA D0,@2 ; <17Oct85>
LEA FXVxkrOff(A4),A0 ; A0 = ptr to xkr in FXM vars <17Oct85>
LEA FXVxdrOff(A4),A1 ; A1 = ptr to xdr in FXM vars <17Oct85>
MOVE.W xkrFABN(A0),D3 ; D3 = beg FABN for extent record
; search record for desired extent entry
FSSchRec
MOVE.W D4,D0 ; desired FABN
BSR.S XRSearch ; search record for desired FABN <17Oct85>
BNE.S FSExit1 ; didn't find it ->
; clean up and exit
FSExit
CLR.W D0 ; result = ok
FSExit1
MOVEM.L (A6)+,D4-D6 ; restore regs
MOVE.L (A6)+,-(SP) ; put return address back on stack
TST.W D0 ; set condition codes
RTS ; exit XFSearch
;_________________________________________________________________________________
;
; Subroutine: XRSearch (Extent Record Search)
;
; Function: Searches extent record for the extent mapping a given file
; allocation block number (FABN).
;
; Input: D0.W - desired FABN
; A1.L - pointer to extent data record (xdr)
; D3.W - beginning FABN for extent record
;
; Output: D0.W - result code
; 0 = ok
; FXRangeErr = desired FABN > last mapped FABN in record
; D1.L - offset to extent entry within xdr
; result = 0, offset to extent mapping desired FABN
; result = FXRangeErr, offset to last extent in record
; D3.W - ending FABN +1
;_________________________________________________________________________________
XRSearch
MOVE.L D2,-(SP) ; save regs
MOVE.W D0,D2 ; D2 = desired FABN
CLR.W D1 ; D1 = initial offset
@1 MOVE.W xdrNumABlks(A1,D1.W),D0 ; number of alloc blks in extent
BEQ.S @2 ; null extent ->
ADD.W D0,D3 ; ending FABN + 1
CMP.W D2,D3 ; desired FAB within this extent?
BHI.S RSExit ; yes, all done ->
ADDQ.W #lenExt,D1 ; bump to next extent
CMPI.W #maxExtOff,D1 ; past last extent?
BLE.S @1 ; no, continue search ->
@2 SUBQ.W #lenExt,D1 ; back up to previous extent
BGE.S @3 ; still within the record ->
CLR.W D1 ; reset to 1st extent
@3 MOVEQ #FXRangeErr,D0 ; result = 'range error' <02Oct85>
BRA.S RSExit1 ; exit ->
RSExit
CLR.W D0 ; result = ok
RSExit1
MOVE.L (SP)+,D2 ; restore regs
TST.W D0 ; set condition codes
RTS ; exit XRSearch
;_________________________________________________________________________________
;
; Subroutine: XRUpdate (Extent Record Update)
;
; Function: Updates the current extent record. For the FCB resident record,
; the FCB is marked 'dirty'. For an extents file record, the
; corresponding BTree record is re-located and updated.
;
; Input: A2.L - VCB pointer
; A3.L - FCB pointer
; A4.L - pointer to FXM vars
; A0.L - pointer to extent key record (xkr)
; 0 = FCB resident extent record
; A1.L - pointer to extent data record(xdr)
; D2.L - BTree hint for extent record
;
; Output: D0.W - result code
; 0 = ok
; other = error
; D2.L - updated BTree hint for extent record <17Oct85>
;_________________________________________________________________________________
XRUpdate
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
MOVEM.L D1/A0-A1,-(A6) ; save registers <17Oct85>
MOVE.L A0,D0 ; FCB resident record?
BNE.S RUUpdFile ; no, must update extents file ->
BSET #FCBModBit,FCBMdRByt(A3) ; mark FCB dirty
BRA.S RUExit ; all done, exit ->
RUUpdFile
MOVE.W VCBXTRef(A2),D0 ; extents file refnum
JSR BTSearch ; re-locate the extent file record
BNE.S RUExit1 ; error ->
LEA FXVxdrOff(A4),A0 ; source = xdr in FXM vars
MOVEQ #(lenxdr/4)-1,D0 ; loop index in long words <17Oct85>
@2 MOVE.L (A0)+,(A1)+ ; update the xdr in cache buffer <17Oct85>
DBRA D0,@2 ; <17Oct85>
MOVE.W VCBXTRef(A2),D0 ; extents file refnum
JSR BTUpdate ; update BTree record
BNE.S RUExit1 ; error ->
RUExit
CLR.W D0 ; result = 'ok'
RUExit1
MOVEM.L (A6)+,D1/A0-A1 ; restore registers <17Oct85>
MOVE.L (A6)+,-(SP) ; put return address back on stack
TST.W D0 ; set condition codes
RTS ; exit XRUpdate
END