sys7.1-doc-wip/OS/HFS/TFSDIR3.a
2019-07-27 22:37:48 +08:00

878 lines
38 KiB
Plaintext

;
; File: TFSDIR3.a
;
; Contains: This file contains routines using file names to specify file.
;
; Copyright: © 1982-1993 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <SM3> 8/27/93 BH Removed <SM2>. The flushing stuff is now in CmdDone.
; <SM2> 8/3/93 BH Flushing critical volume info when changed for a volume in a
; manual-eject drive.
; <SM1> 4/1/92 kc Roll in SetFileLock patch from FileMgrPatches.a.
; • Pre-SuperMario comments follow •
; <2> 9/12/91 JSM Add a header.
; <1.2> 3/2/89 DNF removed references to forROM; HFS now builds identically for ram
; or rom
; <1.1> 11/10/88 CCH Fixed Header.
; <1.0> 11/9/88 CCH Adding to EASE.
; <1.0> 2/11/88 BBM Adding file for the first time into EASE…
; 1/14/87 BB Fixed GetFileInfo to return bad name error (BdNamErr) for a zero
; length name parameter (Bug #3819). NOTE: this is not patched for
; the Mac+ or MAUI.
; 9/24/86 BB Updated to use new MPW equates.
; 11/6/85 PWD Changed bits used for fork busy flags to 2 (resource fork) and 3
; (data fork)
; 10/29/85 LAK Vectored FndFilName.
; 10/27/85 PWD Changed _GetFileInfo to return separate busy bits for different
; forks of a file.
; 10/8/85 PWD Fixed to call correct MFS entry point (SetMFlType)
; 10/1/85 LAK Removed convert of internal errors to TFDSIntErr.
; 9/25/85 PWD Changed to skip PMSP if filename contains directory spec. in
; FndFilName.
; 9/25/85 PWD Fixed FndFilName to check for root directory before moving up in
; directory hierarchy, changed GetCatInfo to do complete DirID
; determination before checking for volume-type (to allow MFS
; VRefNum used as sole argument to return directory info)
; 9/24/85 PWD Removed code to set clump size in SetCatInfo
; 9/8/85 LAK Modified CkFilMod so it doesn't use FSTemp4.
; 9/6/85 LAK Clear IORefNum before calling CkFileBusy for GetFile/Cat/Info.
; For MFS volumes, SetCatInfo is now the same as SetFileInfo.
; 8/28/85 LAK Cleaned up FndFilName a bit (short branches added).
; 8/22/85 PWD Changed GetFileInfo/GetCatInfo to skip PMSP when using FileIndex
; 6/20/85 PWD Changed to use new system CNode equates
; 6/19/85 PWD Changed internal errors to FSDSIntErr instead of IOErr.
; 5/9/85 PWD Changed GetCatInfo to return fake information for root directory
; on MFS volumes to simplify enumeration
; 5/9/85 PWD Changed to check TFS dir. entry type before acting
; 5/1/85 PWD Added GetCatInfo and SetCatInfo; changed GetFileInfo to clear
; ioDirFlg bit in ioFlAttrb.
; 4/26/85 PWD Changed to use expanded Finder info field
; 4/25/85 PWD Changed to convert all internal errors to IOErr.
; 4/22/85 PWD Fixed GetFileName enumeration to use VCBDirIndex field.
; 4/14/85 LAK Added RAM patch for GetCatInfo/GetFileInfo (VCBDirIndex field is
; invalid after an indexed GetCatInfo call). Removed clear of this
; field for GetCatInfo by name. This all should really be handled
; by the Catalog manager: it should have a separate call which
; gets indexed cnode skipping directories).
; 3/10/85 PWD Changed to use TFS catalog structure for TFS volumes
; 2/28/85 PWD Moved MFS-specific code into MFSDir3. Changed FndFilName to
; parse TFS filenames for TFS volumes.
; 7/9/84 GSS Patched SetFileInfo to write out creation and modification date
; info.
; 9/1/83 LAK Changed BPL to BCC in file name transfer to support file names >
; 127 chars in GetFileInfo.
; 8/31/83 LAK Changed GetFileInfo to return current file info for opened files
; (from FCB information).
; 6/6/83 LAK Added changes to support ext fs, offline volumes.
; 6/6/83 LAK Changed to use CkFilMod subroutine.
; 5/25/83 LAK Adapted FndFilName to new CmpString interface.
; 1/16/83 LAK Final pass changes . . . added SetFilLock,RstFilLock,SetFilType.
; 1/16/83 LAK New today.
; 12/14/82 LAK Undelete removal changes
; 12/13/82 LAK Reworked all files for new file system data structures.
; 1/12/82 LAK Made string compare proc an OS call; code is in IOCore.
;
;_______________________________________________________________________
;
; External Routines: GetFileInfo,SetFileInfo, Get/SetCatInfo
;
; Internal Routines: CkFilMod,FndFilName,GetCurB1,ExtOffLinCk
;
;_______________________________________________________________________
;_______________________________________________________________________
;
; Routine: SetFilType
;
; (c) 1983 Apple Computer, Inc.
;
; Arguments: A0.L (input) -- pointer to I/O parameter block, uses
; IOFileName,IODrvNum,IOFileType,IONewType
; D0.W (output) -- 0 if file was found and set correctly.
; Calls: FndFilName
; Function: Set the directory type field for a file. The directory is first
; searched for a file with the same name and new type fields to
; avoid naming conflicts.
;
; Modification History:
; 16 Jan 83 LAK New today.
; 06 Jun 83 LAK Changed to use CkFilMod subroutine.
; 10 Mar 85 PWD Changed to use TFS catalog structure for TFS volumes
; 9 May 85 PWD Changed to check TFS dir. entry type before acting
; 8 Oct 85 PWD Fixed to call correct MFS entry point (SetMFlType)
;_______________________________________________________________________
SetFilType:
BLANKS ON
STRING ASIS
BSR FSQueue ; wait our turn
MOVE.B IOFileType(A0),D1 ; save original type
MOVE.B IONewType(A0),IOFileType(A0) ; set for destination type
BSR FndFilName ; does it exist already?
MOVE.B D1,IOFileType(A0) ; (restore original state)
TST.W D0 ; Re-check condition codes from FndFilName
BNE.S @1 ; br on error (incl not fnd)
BSR TFSVCBTst ; Are we dealing with a TFS volume? <01Oct85>
BEQ.S @2 ; If so, let it slide until CkFilMod <18Oct85>
MOVEQ #DupFNErr,D0 ; duplicate file name if found
@1 CMP.W #FNFErr,D0 ; file should not have been found
BNE.S SRFLXit3 ; br if not ok (also ext fs, offline errs)
BSR CkFilMod ; look for file and see if we can mod it
; (doesn't return on errors)
BSR TFSVCBTst ; Are we dealing with a TFS volume? <01Oct85>
BNE SetMFlType ; No - handle MFS dir. entry <PWD 08Oct85>
@2 MOVEQ #ParamErr,D0 ; If we didn't find it yet, there's no hope
BRA.S SRFLXit3 ; Exit
;_______________________________________________________________________
;
; Routine: SetFilLock, RstFilLock
;
; (c) 1983 Apple Computer, Inc.
;
; Arguments: A0.L (input) -- pointer to I/O parameter block, uses
; IOFileName,IOFileType,IODrvNum
; D0.W (output) -- 0 if file was found and set correctly.
; Calls: FndFilName
; Function: Set or reset the file lock bit.
;
; Modification History:
; 16 Jan 83 LAK New today.
; 06 Jun 83 LAK Broke out CkFilMod as a subroutine.
; 10 Mar 85 PWD Modified for use with TFS catalog entries
;
; Note: if the file is locked after it has already been opened with write
; permission, the lock will not affect that opened file. If the lock bit
; is not changed by this command, the directory buffer is not marked dirty
; (allows quick lock/unlocking of a group of file, regardless of their current
; status).
;_______________________________________________________________________
SetFilLock:
BSR FSQueue ; wait our turn
ST FLckUnlck ; want to lock it
BRA.S SRFLck
RstFilLock:
BSR FSQueue
CLR.B FLckUnlck
SRFLck BSR CkFilMod ; look for file and see if we can mod it
; (doesn't return on errors)
BSR TFSVCBTst ; Are we dealing with a TFS volume? <01Oct85>
BNE ChgMFlLock ; Nope - do it the old fashioned way
MOVEQ #FNFErr,D0 ; Expect the worst
CMP.B #cdrFilRec,cdrType(A5) ; Is this a file entry?
BNE.S SRFLXit3 ; No - don't touch it
TST.B FLckUnlck ; Yes! Now, what was it we wanted?
BEQ.S @1 ; br if we want to unlock it
BSET #FilWrtFlag,FilFlags(A5) ; lock it
BNE.S SRFLXit2 ; br if already locked
ori.b #xFFFilAttrLockMask, filFndrInfo+fdXFlags(a5) ; set bits in fdXFlags <28Jun90> <SM1>
BRA.S SRFLXit1 ; otherwise, it's been modified
@1 BCLR #FilWrtFlag,FilFlags(A5) ; unlock it
BEQ.S SRFLXit2 ; br if already unlocked
andi.b #~xFFFilAttrLockMask, filFndrInfo+fdXFlags(a5) ; clear bits in fdXFlags <28Jun90> <SM1>
; Mark the buffer holding the catalog entry dirty:
SRFLXit1 MOVE.L D7,D2 ; Get a hold of the catalog hint
JSR CMUpdateCN ; Update the Catalog buffer
BRA.S SRFLXit3 ; If EQ, we're all set.
SRFLXit2 MOVEQ #0,D0
SRFLXit3 BRA CmdDone
;_______________________________________________________________________
;
; Routine: SetFileInfo
;
; (c) 1983 Apple Computer, Inc.
;
; Arguments: A0.L (input) -- pointer to File Info I/O parameter block, uses
; IOFileName,IOFlAttrib,IOFlUsrWds
; D0.W (output) -- 0 if entry was found, error code otherwise
; File's entry is modified to reflect changes
; Calls: FndFilName
; Function: Sets the user-definable fields in a file's directory entry.
; The caller specifies the filename and type, and the eight
; user-defined words. The file lock bit does not inhibit this
; command.
;
; Modification History:
; 13 Dec 82 LAK Modified for new file system data structures.
; 17 Jan 83 LAK Latest changes: no longer used to change lock, type fields;
; there are now 16 user-defined bytes.
; 06 Jun 83 LAK Adapted to new offline, ext fs problems. Uses CkFilMod
; and SRFLXit1 to save code.
; 09 Jul 84 GSS Patched to write out creation and modification date info
; 13 Mar 85 PWD Separated out MFS code; added TFS support
; 26-Apr-85 PWD Changed to use expanded Finder info field
;_______________________________________________________________________
SetFileInfo:
BSR FSQueue ; wait our turn
BSR CkFilMod ; look for modifiable file
; (doesn't return on errors)
BSR TFSVCBTst ; Are we dealing with a TFS volume? <01Oct85>
BNE SetMFlInfo ; If not, leave it to the MFS code
MOVEQ #FNFErr,D0 ; Expect the worst
CMP.B #cdrFilRec,cdrType(A5) ; Is this a file entry?
BNE.S SRFLXit3 ; No - don't touch it
MOVEM.L IOFlUsrWds(A0),D1-D4 ; get 16 bytes of Finder Info
MOVEM.L D1-D4,FilUsrWds(A5) ; transfer 16 finder bytes
MOVEM.L IOFlCrDat(A0),D1-D2 ; get IOFlCrDat, IOFlMdDat
MOVEM.L D1-D2,FilCrDat(A5) ; and store in FilCrDat, FilMdDat
BRA.S SRFLXit1 ; exit ok, marking buffer modified
;_______________________________________________________________________
;
; Routine: SetCatInfo
;
; (c) 1983 Apple Computer, Inc.
;
; Arguments: A0.L (input) -- pointer to File Info I/O parameter block, uses
; IOFileName,IOFlAttrib,IOFlUsrWds,IOFlFndrInfo
; D0.W (output) -- 0 if entry was found, error code otherwise
; File's entry is modified to reflect changes
; Calls: FndFilName
; Function: Sets the user-definable fields in a file's catalog entry.
; The caller specifies the filename and type, the sixteen
; user-defined bytes, and the 32 bytes of Finder Info.
; The file lock bit does not inhibit this command.
;
; Modification History:
; 1-May-85 PWD New today.
; 9-Aug-85 PWD Added code to support file Clump Size attributes.
; <06Sep85> LAK For MFS volumes, it's now the same as SetFileInfo.
; 24-Sep-85 PWD Removed code to set clump size
;_______________________________________________________________________
SetCatInfo:
BSR FSQueue ; Wait our turn
BSR.S CkFilMod ; look for modifiable file
; (doesn't return on errors)
BSR TFSVCBTst ; Are we dealing with a TFS volume? <01Oct85>
BNE SetMFlInfo ; If not,same as SetFileInfo for MFS. <06Sep85>
CMP.B #cdrFilRec,cdrType(A5) ; Is this a file we're dealing with?
BNE.S @10 ; Nope - check for directory
; MOVE.L ioFlClpSiz(A0),D0 ; Pick up new clump size in bytes <24Sep85>
; DIVU VCBAlBlkSiz+2(A2),D1 ; Pick up allocation block size <24Sep85>
; BSR DivUp ; Divide, rounding up <24Sep85>
; MOVE.W D0,FilClpSize(A5) ; Set new clump size in al. blks. <24Sep85>
MOVEM.L IOFlUsrWds(A0),D0-D3 ; get 16 bytes of user info
MOVEM.L D0-D3,FilUsrWds(A5) ; transfer 16 user info bytes
MOVEM.L ioFlxFndrInfo(A0),D0-D3 ; Get 16 bytes of additional finder info <24Sep86>
MOVEM.L D0-D3,FilFndrInfo(A5) ; and copy them into the catalog entry
MOVEM.L IOFlCrDat(A0),D0-D1 ; Pick up creation & modification times
MOVEM.L D0-D1,FilCrDat(A5) ; Set new for entry
MOVE.L IOFlBkDat(A0),FilBkDat(A5) ; New backup date
BRA.S @90
@10 MOVEQ #BdNamErr,D0 ; Expect the worst
CMP.B #cdrDirRec,cdrType(A5) ; Is it a directory?
BNE.S SetCatIExit ; Nope - give up.
MOVEM.L IOFlUsrWds(A0),D1-D4 ; get 16 bytes of user info
MOVEM.L D1-D4,DirUsrInfo(A5) ; transfer 16 user info bytes
MOVEM.L ioFlxFndrInfo(A0),D0-D3 ; Get 16 bytes of finder info <24Sep86>
MOVEM.L D0-D3,DirFndrInfo(A5) ; and copy them into the catalog entry
MOVEM.L IODrCrDat(A0),D0-D2 ; Pick up create, mod, backup times
MOVEM.L D0-D2,DirCrDat(A5) ; Set new information for entry
@90 MOVEQ #0,D0 ; Indicate a successful completion
SetCatIExit BRA SRFLXit1 ; exit ok, marking buffer modified
; short code-saving routine called by Delete, SetFilType, SRFLck, SetFileInfo
CkFilMod:
MOVE.L (SP)+,-(A6) ; Save return address (FndFilName is async) <08Sep85>
BSR.S FndFilName ; find the file in the directory
BNE.S @1 ; exit if error (also ext fs, offline vols) <08Sep85>
BSR CVFlgs ; see if we can change it
BNE.S @1 ; exit if locked or write-protected <08Sep85>
MOVE.L (A6)+,-(SP) ; restore return address <08Sep85>
RTS ; and go there . . . <08Sep85>
@1 ADDQ #4,A6 ; don't return to caller <08Sep85>
BRA CmdDone ; <08Sep85>
;_______________________________________________________________________
;
; Routine: FndFilName,FndFN2
;
; (c) 1983 Apple Computer, Inc.
;
; Arguments: A0.L (input) -- pointer to I/O parameter block, uses:
; IOFileName,IOFileType,IODrvNum
; D0.W (output) -- 0 if file was found, error code otherwise.
; D2.L (output) -- name length excluding any volume prefix
; A1.L (output) -- points to volume buffer (if name found)
; A2.L (output) -- pointer to appropriate VCB
; A3.L (output) -- pointer to WDCB, or nil if none specified
; A4.L (output) -- pointer to input file name.
; A5.L (output) -- pointer to file directory entry in buffer.
;
; TFS volumes only:
; D6.L (in/out) -- DirID of directory containing file
; D7.L (in/out) -- Catalog hint
;
; Preserves: D1,D5,A0
; Clobbers: all other registers (D3,D4,D6,D7,A3,A6)
; Note that the routine will return to one level above
; caller during the asynchronous reads.
; FndFN2 entry point for Rename (alternate volume may be used)
; Calls: DtrmVol,MyReadDB(via Rd1stDB and RdNxtDB)
; Called By: Create,Delete,FileOpen,Rename,GetFileInfo,SetFileInfo
; Function: Locate a filename within the directory on a diskette
; Search algorithm: if dir blk there, search it first;
; if not found, start from beginning, skipping searched blk.
;
; Modification History:
; 08 Dec 82 LAK Added FndFilName entry point.
; 13 Dec 82 LAK Rewrote. Removed index search mode.
; 14 Dec 82 LAK Removed check for delete file.
; 17 Jan 83 LAK Changes for last data structure mods: now checks for both
; filename and filetype match.
; 05 Jun 83 LAK Added checks for offline volume, external file system vols
; 28 Sep 84 GSS Inserted patch for setting ReqstVol in ExtOffLinCk
; (from CDHook in MSFileFix)
; 28-Feb-85 PWD Changed to parse TFS pathnames and return directory info
; in D6-D7.
; 14-Mar-85 PWD Changed to allow lookup of Directory CNodes (caller must
; check cdrType(A5) on return).
; 9-May-85 PWD Changed to interpret '::' in filename specs. Zero-length
; filename specs are OK on TFS volumes now (refers to Dir entry)
; Changed to ignore ioDirID when full pathname is specified (by
; semi-ultra-grosso kludge)
; 25-Sep-85 PWD Fixed to check for root directory before moving up to parent dir
; 25-Sep-85 PWD Changed to skip PMSP if filename contains directory spec.
;_______________________________________________________________________
FndFilName:
MOVE.L jFndFilName,-(SP) ; jumptable entry for vFndFilName <29Oct85>
RTS ; go there <29Oct85>
vFndFilName ; 'vectored' FndFilName routine <29Oct85>
BSR DtrmV3 ; determine the volume to be used
BEQ.S FndWDChk ; Check for WDCBs if vol. is determined
FndFNRTS RTS ; exit on vol errs
FndWDChk MOVEQ #FSRtDirID,D6 ; Default to root.
MOVE.L A3,D7 ; Get WDCB pointer, if any
BEQ.S @2 ; If it's zero, we're all set <28Aug85>
;
; The user specified a WDCB:
;
MOVE.L WDDirID(A3),D6 ; Retrieve Directory ID in WDCB
MOVE.L WDCatHint(A3),D7 ; Catalog node hint.
;
; Compute the length of the volume name removed from the head of the original
; file name: if non-zero, ignore the DirID specified, and use the root DirID.
;
@2 MOVE.L A4,D0 ; Examine new name pointer
BEQ.S @3 ; If nil, none was specified <28Aug85>
SUB.L IOFileName(A0),D0 ; Subtract original pointer
SUBQ.L #2,D0 ; Subtract out length byte & colon
BGT.S FndFN2 ; If resulting length >0, volname was found <28Aug85>
@3 BTST #HFSBit,IOTrap(A0) ; Are TFS arguments specified?
BEQ.S FndFN2 ; If not, this is it. <28Aug85>
MOVE.L IODirID(A0),D0 ; Otherwise, this might be the DirID
BEQ.S FndFN2 ; But it'd better be non-zero <28Aug85>
MOVE.L D0,D6 ; This one's for real, though
MOVEQ #0,D7 ; no B*-Tree hint known
;
; The FndFN2 entry point requires the caller to've set up:
; A0.L - I/O Parameter block
; A2.L - VCB pointer
; D2,A4 - File name string
; D6,D7 - DirID and catalog hint (TFS Volumes only)
;
FndFN2 BSR ExtOffLinCk ; make sure it's online, internal fs
BNE.S FndFNRTS ; Give up now if it isn't
BSR TFSVCBTst ; Are we dealing with a TFS volume? <01Oct85>
BNE FndMFSFile ; If not, leave it to the MFS code
;
; If we've come this far, we're dealing with a TFS volume, requiring delicate
; pathname parsing and working-directory consideration.
;
MOVE.L (SP)+,-(A6) ; Save return address on TFS stack
MOVEM.L D1/A0-A1,-(A6) ; Save registers
;;; MOVEQ #BdNamErr,D0 ; Assume bad file name
MOVE.L D2,D1 ; Set up copy for restoration on errors
;;; BEQ FndFNExit ; Skip out on zero length files
MOVE.L D2,D4 ; Save name length (not incl. vol. name)
;
; Scan the name string for the first element in the pathname:
;
@1 MOVEQ #DirNFErr,D0 ; Assume we're looking for a directory
MOVEQ #0,D1 ; Start at start
@2 MOVEQ #0,D3 ; Clear 'empty-PN-elmt' flag
CMP.W D4,D1 ; Check against available length
BGE.S @5 ; If exceeded, that's full name scanned <28Aug85>
CMP.B #':',0(A4,D1) ; Hit a separator?
BEQ.S @3 ; If so, it's the end of a pathname elmt. <28Aug85>
CMP.W #31,D1 ; Already collected 31 characters (max)?
BLT.S @25 ; If not, continue
MOVEQ #BdNamErr,D0 ; Otherwise, we're up the creek
BRA FndFNErr ; So Punt.
;
@25 ADDQ.W #1,D1 ; Adavance the string pointer
BRA.S @2 ; And check the next character <28Aug85>
@3 BSET #SkipPMSP,HFSFlags ; If there's a colon in the file name <25Sep85>
; that wasn't part of the vol spec, skip <25Sep85>
; any PMSP trouble. <25Sep85>
TST.W D1 ; Check: just scan an empty PN elmt?
SEQ D3 ; Set flag to indicate parent req.
SWAP D3 ; Hide flag for a sec
MOVE.W D4,D3 ; Copy for a quick check
SUB.W D1,D3 ; Subtract out length so far
SUBQ.W #1,D3 ; Including colon
BGT.S @6 ; If something left, we're OK
@5 MOVEQ #FNFErr,D0 ; Last PN elmt: no need to try again
@6 SWAP D3 ; Restore empty PN elmt flag
MOVEM.L D6-D7,-(A6) ; Copy DirID and Catalog hint onto stack
MOVEM.L D0/A1,-(SP) ; Save 'em through this little manouver
MOVEA.L D1,A0 ; Save string length
ADDQ.W #1,D1 ; Prepare to round length up: add one
LSR.W #1,D1 ; Divide by two
LSL.W #1,D1 ; And multiply back to rounded value
SUBA.L D1,A6 ; Allocate room for string on stack
MOVE.L D1,-(SP) ; Stash 'fixed' length on stack
MOVE.L A0,D1 ; Restore original length
;
; Copy the name string:
;
MOVEA.L A4,A0 ; Point to source string start
MOVEA.L A6,A1 ; Point to target string start
MOVE.L D1,D0 ; String length for _BlockMove
_BlockMove
MOVE.W D1,-(A6) ; Push length in front of new string
MOVE.L (SP)+,D1 ; Set D1 to 'fixed' length
MOVEA.L A6,A0 ; Point to element name
ADDQ.L #1,A0 ; Length actually starts in low byte
MOVEM.L (SP)+,D0/A1 ; Restore scratch registers
EXG D6,D0 ; Put DirID in D0, err. code in D6
MOVE.L D7,D2 ; Catalog hint
JSR CMGetCN ; Try to retrieve the CNode.
;
; Now to remove this junk from the A6 stack again:
;
MOVE.W (A6)+,-(SP) ; Stash real length word
ADDA.L D1,A6 ; Adjust for string contents+length word
MOVEQ #0,D1 ; Clear top half of D1
MOVE.W (SP)+,D1 ; Retrieve the true string length
TST.W D0 ; Now then, any errors?
BNE.S @20 ; Examine errors carefully <28Aug85>
TST.B D3 ; Time to move up in the world?
BEQ.S @8 ; Nope - just keep on truckin' <28Aug85>
;
; We're parsing an empty pathname element: the previous search for <dir>'' must
; have led us to the directory descriptor for <dir> in its parent: to continue
; the search in the parent directory, we must recover the directory entry for the
; parent directory ITSELF, which can be found from the parent ID and a null CName
; (a NIL pointer will do, courtecy CMSvcs):
;
MOVEQ #DirNFErr,D0 ; Start out pessimistically <25Sep85>
CMP.L #FSRtParID,CKRParID(A0) ; Are we already looking at the root? <25Sep85>
BEQ.S @20 ; If so, our worst fears were just realized <25Sep85>
MOVE.L CKRParID(A0),D0 ; Otherwise, go look up the parent directory<25Sep85>
MOVEQ #0,D2 ; No hint.
SUBA.L A0,A0 ; No CName
JSR CMGetCN ; Find the parent directory entry back
BNE.S @20 ; Examine errors carefully <28Aug85>
MOVE.L CKRParID(A0),D0 ; Set up D0 as parent directory
MOVEQ #0,D2 ; No known hint.
@8 CMP.W #FNFErr,D6 ; Were we looking for a file?
BEQ.S @10 ; If so, we've just found our man! <28Aug85>
;
; Retrieve the directory information from the directory CNode:
;
MOVEM.L (A6)+,D6-D7 ; Discard the old DirID and Cat. hint
MOVE.L DIRDirID(A1),D6 ; This directory's directory ID
MOVE.L D2,D7 ; Catalog hint
;
; Continue the pathname scan with the next pathname element:
;
ADDQ.W #1,D1 ; Advance beyond separator
ADDA.L D1,A4 ; Advance string pointer to next element
SUB.W D1,D4 ; Reduce length by length of first elmt.
BRA @1 ; Continue the scan
;
; The last element on the path was successfully found:
;
@10 MOVEQ #0,D0 ; All is well.
MOVEA.L A1,A5 ; Point to catalog record
MOVE.L D2,4(A6) ; Update catalog hint still on A6 stack
BRA.S @40
@20 CMP.W #CMNotFound,D0 ; Did we miss a CNode?
BNE.S @40 ; Nope - something else went wrong <28Aug85>
MOVE.L D6,D0 ; Fill in appropriate message
@40 MOVEM.L (A6)+,D6-D7 ; Restore last DirID and Catalog hint
FNDFNExit MOVE.L D1,D2 ; Restore file name length
FNDFNErr MOVEM.L (A6)+,D1/A0-A1 ;
MOVE.L (A6)+,-(SP) ; Restore return address
TST.W D0 ; Set condition codes
RTS
; short routine to save code (used by GetFilInfo, FndFilName)
ExtOffLinCk BSR CkExtFS ; is this VCB for us?
BNE.S @1 ; br if not
TST.W VCBDrvNum(A2) ; volume offline?
BNE.S @1 ; br if not
MOVEQ #VolOffLinErr,D0 ; otherwise, note the error
@1 MOVE.L A2, ReqstVol
TST.W D0
RTS
;_______________________________________________________________________
;
; Routine: GetFileInfo
;
; (c) 1983 Apple Computer, Inc.
;
; Arguments: A0.L (input) -- pointer to File Info I/O parameter block, uses
; all fields?
; D0.W (output) -- 0 if info was found, error code otherwise
; Calls: FndFilName(if searching by name)
; Function: Get information about a specific file from the file directory.
; User can specify search by either filename or by index,
; where the index specifies the file's offset from the beginning
; of the directory.
;
; An index of zero means search by filename and type.
;
; Modification History:
; 10 Dec 82 LAK Modified for new file system data structures.
; 13 Dec 82 LAK Removed delete file support.
; 17 Jan 83 LAK Another passover.
; 06 Jun 83 LAK Added changes to detect offline volumes, ext fs calls.
; 01 Sep 83 LAK Changed BPL to BCC in file name transfer to support file
; names > 127 chars.
; 10 Mar 85 PWD Changed to search catalog for TFS volumes
; 22 Apr 85 PWD Changed to shortcut enumeration by looking at VCBDirIndex and
; catalog manager's VCBDirIDM and VCBOffsM.
; 9 May 85 PWD Changed GetCatInfo to construct fake root directory for MFS volumes
; 22-Aug-85 PWD Changed to not use PMSP when searching by index.
; 21-Sep-85 PWD Changed to allow general 'volume name:' spec. by constructing a
; fake root entry for MFS volumes.
; <27Oct85> PWD Changed to return separate busy bits for different forks of a file.
; <06Nov85> PWD Changed bits used for flags above to 2 (resource fork) and 3 (data fork)
;_______________________________________________________________________
GetCatInfo:
BSR FSQueue ; Wait our turn
BSET #HFSReq,HFSFlags ; Request full catalog information
TST.W IOFDirIndex(A0) ; Check the index:
BMI.S GetDirInfo ; If <0, look up directory information
BRA.S FndCatEntry ; Go look up the requested entry
GetFileInfo:
BSR FSQueue ; Wait our turn
BCLR #HFSReq,HFSFlags ; don't return full catalog info
FndCatEntry MOVE.W IOFDirIndex(A0),D1 ; get file index, if there is one
BGT.S GFIByIndx ; If >0, look by index
BSR FndFilName ; search by name for file or dir.
BEQ.S @1 ; Continue if all was well <21Sep85>
CMP.W #BdNamErr,D0 ; Bad file name returned? <21Sep85>
BNE GFIExit ; exit if not found, offline, ext fs <21Sep85>
TST.B D2 ; Zero-length name? <21Sep85>
BNE GFIExit ; Nope - error's for real <21Sep85>
BTST #HFSReq,HFSFlags ; GetCatInfo call? <14Jan87>
BNE.S fakeRoot ; Yes - contruct a fake root entry <14Jan87>
BRA GFIExit ; No - return bad name error <14Jan87>
@1 BSR TFSVCBTst ; Are we dealing with a TFS volume? <01Oct85>
BNE GetMFlInfo ; If not, leave it to the old code
MOVE.L D6,D1 ; Save parent's directory ID
BRA XferFInfo ; br if not searching by index
GetDirInfo MOVEQ #0,D1 ; Indicate directory itself is wanted
GFIByIndx BSET #SkipPMSP,HFSFlags ; Don't try any search path stuff here <22Aug85>
BSR DtrmV1 ; figure volume from drvnum/vrefnum
BNE GFIExit ; Punt on errors
BSR.S ExtOffLinCk ; make sure it's on-line, internal fs
BNE GFIExit
; Determine the directory of choice: <25Sep85>
; .
dtrmDir MOVEQ #FSRtDirID,D6 ; Default is root DirID .
MOVE.L A3,D7 ; WDCB specified? (may clear hint) .
BEQ.S @3 ; If none specified, we're all set.
MOVE.L WDDirID(A3),D6 ; Pick up the directory from the WDCB
MOVE.L WDCatHint(A3),D7 ; And use the catalog hint supplied there
@3 BTST #HFSBit,ioTrap(A0) ; TFS bit set on trap word?
BEQ.S @10 ; Nope - good thing we've got defaults
TST.L ioDirID(A0) ; User specified directory
BEQ.S @10 ; If not, we're set
@5 MOVE.L ioDirID(A0),D6 ; Set DirID of choice
MOVEQ #0,D7 ; No hint known for this DirID .
; .
@10 BSR TFSVCBTst ; Are we dealing with a TFS volume? <01Oct85>
BEQ.S retDirInfo ; Yes: there's a real catalog: go for it<25Sep85>
; We were asked for information on an MFS volume:
rootCheck MOVEQ #DirNFErr,D0 ; Prepare for the worst <25Sep85>
CMP.L #FSRtDirID,D6 ; Can we fake it? <25Sep85>
BNE GFIExit ; No - fail miserably <25Sep85>
TST.W D1 ; Check the directory index <25Sep85>
BGT GtMFlIBI ; If >0, MFS code will find the file <25Sep85>
; Zero the return information area, mostly to zero some non-existant fields
; (i.e. ioDrUsrInfo, ioDrFndrInfo, ioDrBkDat):
fakeRoot LEA ioFlAttrib(A0),A1 ; Clear the return information
MOVEQ #(ioHFQElSiz-ioFlAttrib)/2-1,D0 ; Number of words to clear <24Sep86>
@0 CLR.W (A1)+ ; Clear a word in the return info
DBRA D0,@0 ; until all's clear
BSET #ioDirFlg,ioFlAttrib(A0) ; Set directory bit in attributes
MOVE.L #FSRtDirID,ioDrDirID(A0) ; Fake directory ID
MOVE.L #FSRtParID,ioDrParID(A0) ; Fake parent ID
;
; Pick up some of the information from the VCB:
;
MOVE.W VCBNmFls(A2),ioDrNmFls(A0) ; Number of directory entries
MOVE.L VCBCrDate(A2),ioDrCrDat(A0) ; Creation date
MOVE.L VCBLsMod(A2),ioDrMdDat(A0) ; Modification date
MOVE.L ioFileName(A0),D0 ; File name specified?
BEQ.S GFIOK ; If not, we're done
TST.W ioFDirIndex(A0) ; Asking for directory info by DirID? <25Sep85>
BEQ.S GFIOK ; If not, we're all set. <25Sep85>
MOVEA.L D0,A1 ; Make it the dest. of _BlockMove
LEA VCBVN(A2),A0 ; Source name is in VCB
MOVEQ #1,D0 ; Clear top 3 bytes, add one for length byte <29Aug85>
ADD.B (A0),D0 ; Pick up length to copy
_BlockMove ; Copy volume name
GFIOK MOVEQ #0,D0 ; Indicate complete success
BRA.S GFIExit ; All done!
; we are searching by index here: it's a bit tricky since the directory may
; contain directory nodes, which should be ignored on non-catalog calls, and we'd
; like to continue the search from the last one if at all possible:
retDirInfo
MOVEQ #FSRtParID,D0 ; Asking about the root parent? <01Oct85>
CMP.L D0,D6 ; <01Oct85>
BEQ.S GFInfErr ; If so, fail miserably
TST.W D1 ; Looking for directory itself?
BNE.S @13 ; Nope - go look by index
MOVEM.L A0-A1,-(A6) ; Store CMGetCN's output registers
MOVE.L D6,D0 ; DirID of choice
MOVE.L D7,D2 ; Directory hint
SUBA.L A0,A0 ; Clear CName
JSR CMGetCN ; Look up the directory information
BNE.S LookupErr ; Punt on errors
MOVE.L D2,D7 ; Save the hint
BRA.S GotIndFile ; Go return the directory information
@13 BTST #HFSReq,HFSFlags ; Requesting normal catalog treatment?
BNE.S GetCatOff ; If so, go read it directly
MOVE.W D1,D5 ; Stash directory index for later reference
MOVE.W VCBOffsM(A2),D1 ; Get last search's catalog offset
CMP.L VCBDirIDM(A2),D6 ; Same directory as last search?
BNE.S @15 ; If not, start afresh
CMP.W VCBDirIndex(A2),D5 ; Are we looking for file beyond this one?
BCS.S @15 ; If we're backing up, start afresh
MOVE.W VCBDirIndex(A2),D0 ; Otherwise, hold last DirIndex for later offset
MOVE.W D5,VCBDirIndex(A2) ; Set this up for future reference
SUB.W D0,D5 ; Skip to where we last left off
BRA.S @19 ; And start search at last offset
@15 MOVEQ #1,D1 ; Start with the first catalog offset
MOVE.W D5,VCBDirIndex(A2) ; Set up current file index for later
SUBQ #1,D5 ; #files to skip = index - 1
@19 MOVEM.L A0-A1,-(A6) ; Save CMGetOff's output registers
@20 MOVE.L D6,D0 ; Set up DirID for lookup
MOVE.L D7,D2 ; Accompanying catalog hint
SUBA.L A0,A0 ; No CNode specified
JSR CMGetOff ; Look up the indicated CNode
BNE.S LookupErr ; Fail miserably
MOVE.L D2,D7 ; Save catalog hint
ADDQ.W #1,D1 ; Look for next dir. entry
CMP.B #CDRFilRec,CDRType(A1) ; Did we find a file?
BNE.S @20 ; If not, just keep looking
DBRA D5,@20 ; Count down: 1 file skipped
BRA.S GotIndFile ; And show some results for our efforts
LookupErr MOVEM.L (A6)+,A0-A1 ; Restore originals
CMP.W #CMNotFound,D0 ; Did we just miss it?
BNE.S GFIExit ; Br if not. Otherwise, it's an FNFErr.
GFINFErr MOVEQ #FNFErr,D0 ; file not found . . . hmmmm
GFIExit BRA CmdDone
;
; We're handling a GetCatInfo request by index: D1 is already set up with
; the requested file index:
;
GetCatOff MOVEM.L A0/A1,-(A6) ; Save CMGetOff's output registers
; (1) CMGetOff is called from exactly two places: both in GetCatInfo.
; (2) CMGetOff is the only place where VCBDirIDM is validated.
; (3) The first GetCatInfo call to CMGetOff is for an indexed GetFileInfo call
; in which only files are wanted. VCBDirIndex is used here to keep
; a separate index marker for files. If VCBDirIDM is validated
; in this path, it is cool.
; (4) This second GetCatInfo call to CMGetOff is for a real indexed GetCatInfo
; call. If VCBDirIDM is validated in this path, VCBDirIndex should
; be invalidated.
; (5) VCBDirIndex can not be invalidated by setting it to zero: this makes
; it look valid always. By setting it to $FFFF, it will appear that
; any other indexed call is looking for a file before it and will
; thus be invalidated.
MOVE.W #-1,VCBDirIndex(A2) ; DirIndex will now be invalid <14Apr85>
MOVE.L D6,D0 ; DirID of choice
MOVE.L D7,D2 ; Accompanying catalog hint
SUBA.L A0,A0 ; No CName specified
JSR CMGetOff ; Look up the requested entry
BNE.S LookupErr
GotIndFile
; searched by index, so return the name . . .
LEA CKRCName(A0),A3 ; file entry name ptr
MOVE.L CKRParID(A0),D1 ; Save parent directory ID
MOVEA.L A1,A5 ; Point to catalog entry
MOVEM.L (A6)+,A0-A1 ; Restore the originals
MOVE.L IOFileName(A0),D0 ; parameter block filename ptr
BEQ.S XferFInfo ; skip it if it's zero
MOVE.L D0,A4
MOVE.B (A3),D0 ; name length
@1 MOVE.B (A3)+,(A4)+ ; name length, then name, byte by byte
SUBQ.B #1,D0
BCC.S @1
XferFInfo
BTST #HFSReq,HFSFlags ; Requesting full catalog information?
BNE.S XferCInfo ; If so, transfer it all
CMP.B #CDRFilRec,CDRType(A5) ; Otherwise, is this a file node?
BNE.S GFInfErr ; If not, that's trouble
LEA IOFlAttrib(A0),A4 ; info destination
MOVEQ #(IOFlMdDat+4-IOFlAttrib)/2-1,D0 ; number of words to copy - 1
LEA FilFlags(A5),A3 ; start of regular info to transfer
@1 MOVE.W (A3)+,(A4)+ ; move word by word
DBRA D0,@1
;
; Clear the directory flag for file information:
;
BCLR #ioDirFlg,ioFlAttrib(A0) ; 0 = file info returned
;
; Code shared by MFS entries (GetMFlInfo, GtMFlIBI):
;
CkFilStatus ANDI.B #$73,ioFlAttrib(A0) ;Clear out busy, DFBusy, and RFBusy flags <06Nov85>
CLR.W IORefnum(A0) ; Clear refnum in case file isn't open <27Oct85>
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
BNE.S @10 ; If there's no match, we're set. <27Oct85>
@1 BTST #FCBRscBit,FCBMdRByt(A1,D1) ; Is this a resource file? <27Oct85>
BEQ.S @3 ; If not, set different flag <27Oct85>
BSET #2,ioFlAttrib(A0) ; Mark resource fork busy <27Oct85>
BRA.S @5 ; <27Oct85>
@3 BSET #3,ioFlAttrib(A0) ; Mark data fork busy <27Oct85>
@5 BSET #7,ioFlAttrib(A0) ; Mark file busy <27Oct85>
BNE.S @7 ; If already set, don't overwrite refNum <27Oct85>
MOVE.W D1,IORefnum(A0) ; note the refnum of fcb entry
; the file is opened, so we update the return information appropriately in case
; the file has been modified . . .
@7 LEA IOFlStBlk(A0),A3 ; info destination, regular fork
BSR UpDatFlNtry ; update info (shared with close)
BSR GtNxtMatch ; Look for next matching FCB <27Oct85>
BEQ.S @1 ; Continue if another FCB is found <27Oct85>
@10 MOVEQ #0,D0 ; no errors
BRA GFIExit
; Transfer all catalog information:
XferCInfo LEA IOFlAttrib(A0),A4 ; info destination
CMP.B #CDRFilRec,CDRType(A5) ; Is this a file node?
BNE.S @50 ; If not, it's probably a directory
MOVEQ #(ioFlxFndrInfo+16-IOFlAttrib)/2-1,D0 ; number of words to copy - 1 <24Sep86>
LEA FilFlags(A5),A3 ; start of regular info to transfer
@1 MOVE.W (A3)+,(A4)+ ; move word by word
DBRA D0,@1
MOVEQ #0,D0 ; Clear top word
MOVE.W FilClpSize(A5),D0 ; Pick up clump size in allocation blocks
MULU VCBAlBlkSiz+2(A2),D0; Convert to bytes
MOVE.L D0,ioFlClpSiz(A0) ; Return it to the user
MOVE.L D1,IOFlParID(A0) ; Return parent information
;
; Clear the directory flag for file information:
;
BCLR #ioDirFlg,ioFlAttrib(A0) ; 0 = file info returned
BRA CkFilStatus
@50 CMP.B #CDRDirRec,CDRType(A5) ; Is this a directory node?
BNE GFInfErr ; If not, there went our last chance
MOVE.W DirFlags(A5),IOFlAttrib(A0) ; Copy attribute bytes
MOVE.W DirVal(A5),IODrNmFls(A0) ; Copy dir. entry count
MOVE.L DirDirID(A5),IODrDirID(A0) ; Copy Directory ID
MOVE.L D1,IODrParID(A0) ; Return parent dir ID
MOVEM.L DirCrDat(A5),D0-D2 ; Pick up DTC, DTM, and DTB
MOVEM.L D0-D2,IODrCrDat(A0) ; And copy them into the user IOPB
MOVEM.L DirUsrInfo(A5),D0-D3 ; Pick up 16 bytes of user info
MOVEM.L D0-D3,IODrUsrWds(A0); Copy them into the parameter block
MOVEM.L DirFndrInfo(A5),D0-D3 ; Pick up 16 bytes of Finder info
MOVEM.L D0-D3,IODrFndrInfo(A0); Copy them into the parameter block
BCLR #7,IOFlAttrib(A0) ; Directories are never too busy for ya
; Set the directory flag for directory information:
BSET #ioDirFlg,ioFlAttrib(A0) ; 1 = directory info returned
@90 MOVEQ #0,D0 ; Indicate success
BRA GFIExit ; And leave.