mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2025-01-23 01:30:17 +00:00
4325cdcc78
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included. The Tools directory, containing mostly junk, is also excluded.
329 lines
11 KiB
Plaintext
329 lines
11 KiB
Plaintext
;
|
|
; File: MakeFSSpec.a
|
|
;
|
|
; Contains: The call MakeFSSpec
|
|
;
|
|
; Written by: Dave Feldman
|
|
;
|
|
; Copyright: © 1990,1992 by Apple Computer, Inc., all rights reserved.
|
|
;
|
|
; Change History (most recent first):
|
|
;
|
|
; <SM2> 11/7/93 pdw ConsultCatalog was assuming totally synchronous behavior (i.e.
|
|
; it was using the A7 stack instead of A6). Changed register
|
|
; saving and return address handling to use HFS stack.
|
|
; <SM1> 4/15/92 kc Removed the "ROM" prefix from the RomBind routines.
|
|
; ¥ Pre-SuperMario comments follow ¥
|
|
; <12> 1/6/91 dnf (fjs) Add code to check for terminating ::'s on pathname
|
|
; parsing.
|
|
; <11> 9/22/90 dnf Add ExtOffLinCheck
|
|
; <10> 8/29/90 dnf Make sure TFSVCBTst happens after FndFilName.
|
|
; <9> 8/28/90 dnf Don't clobber a3 (WDCB pointer after FndFilName) so external
|
|
; file systems can use it.
|
|
; <8> 8/6/90 dnf Rename __MakeFSSpec to MakeFSSpec
|
|
; <7> 7/30/90 dnf Change all bsr and jsr instructions that point at Rom bind
|
|
; symbols into jsrRom macros.
|
|
; <6> 7/2/90 dnf Use TFSVCBTst
|
|
; <5> 7/2/90 dnf Check for volume-only input and convert to root directory.
|
|
; Handle fnfErr, dirNFErr, volume info only, and multiply
|
|
; simultaneous error cases.
|
|
; <4> 6/2/90 dnf Handle fnfErr case
|
|
; <3> 5/4/90 dnf Eliminate hardcoded include pathnames
|
|
; <2> 5/4/90 dnf version for a10
|
|
; <1> 5/4/90 dnf first checked in
|
|
;
|
|
; To Do:
|
|
; add proper cname capitalization
|
|
|
|
print push
|
|
print off
|
|
LOAD 'StandardEqu.d'
|
|
include 'FileMgrPrivate.a'
|
|
include 'LinkedPatchMacros.a'
|
|
print pop
|
|
|
|
MACHINE MC68020
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: CopyCName
|
|
;
|
|
; Registers In:
|
|
; a1 - target buffer
|
|
; a4 - pointer to CName (no length byte)
|
|
; d2.b - length of CName
|
|
;
|
|
; All registers preserved
|
|
;
|
|
; Prepends length byte to CName in buffer
|
|
;_______________________________________________________________________
|
|
CopyCNameRegs reg a1/a4/d2
|
|
CopyCName: proc
|
|
movem.l CopyCNameRegs, -(sp)
|
|
andi.w #$00ff, d2 ; kill high byte of low word
|
|
move.b d2, (a1)+ ; set name length into string
|
|
beq.s @done ; catch zero length strings
|
|
subq.b #1, d2 ; -1 for dbra
|
|
@loop:
|
|
move.b (a4)+, (a1)+ ; copy the cname
|
|
dbra d2, @loop
|
|
|
|
@done:
|
|
movem.l (sp)+, CopyCNameRegs
|
|
rts
|
|
endproc
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: ConsultCatalog
|
|
;
|
|
; Registers In:
|
|
; a2 - VCB of volume to look on
|
|
; a3 - pointer to FSSpec to look up
|
|
; d7 - catalog hint or zero if none
|
|
;
|
|
; Registers Out:
|
|
; a2 - VCB of volume to look on
|
|
; a3 - pointer to FSSpec to look up
|
|
; d7 - new catalog hint or zero if none
|
|
;
|
|
; All other registers preserved
|
|
;
|
|
; FSSpec on a3:
|
|
; vRefNum - not used. Use vcb on a2 instead
|
|
; parID - input/output
|
|
; CName - input/output
|
|
;
|
|
; Function:
|
|
; Look up the parID/CName combo in the catalog. Return the spelling of
|
|
; the CName as it is in the catalog. If the CName is zero-length,
|
|
; treat the parID as a dirID and return its parID/CName.
|
|
;
|
|
; The FSSpec passed in here doesn't have to be a true FSSpec. It just needs
|
|
; to have a parID and a CName.
|
|
;
|
|
;_______________________________________________________________________
|
|
ConsultCatalog: proc
|
|
ConsultCatalogRegs reg d2/a0/a1/a4
|
|
|
|
move.l (SP)+,-(A6) ; save return address on A6 stack <SM2> pdw
|
|
movem.l ConsultCatalogRegs,-(A6) ; <SM2> pdw
|
|
lea.l FSSpec.name(a3), a0 ; a0 = ptr(CName)
|
|
tst.b (a0) ; zero length name?
|
|
bne.s @NotZeroLength
|
|
suba.l a0,a0 ; pass null to CMGetCN
|
|
|
|
@NotZeroLength:
|
|
move.l FSSpec.parID(a3), d0 ; move parID to input reg for GetCN
|
|
move.l d7, d2 ; move catalog hint to input reg for CMGetCN
|
|
jsrROM CMGETCN ; go consult with the expert
|
|
bne.s @Exit ; errors are good cause to leave
|
|
|
|
move.l ckrParID(a0), FSSpec.parID(a3) ; set parID for directory name case
|
|
|
|
lea.l FSSpec.name(a3), a1 ; a1 = ptr(name buffer in FSSpec)
|
|
lea.l ckrCName(a0), a4 ; a4 = correctly capitalized cname pstring
|
|
move.b (a4)+, d2 ; d2 = length of cname
|
|
bsr CopyCName ; copy correctly capitalized name into FSSpec
|
|
|
|
@Exit:
|
|
move.l d2, d7 ; restore catalog hint
|
|
movem.l (A6)+, ConsultCatalogRegs ; <SM2> pdw
|
|
move.l (A6)+,-(SP) ; Restore the return address <SM2> pdw
|
|
tst.w d0 ; set condition codes
|
|
rts
|
|
endproc
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: MakeFSSpec
|
|
;
|
|
; Registers In:
|
|
; a0 - user param block
|
|
; ioNamePtr - any pathname
|
|
; ioVRefNum - any legal vol/wd spec
|
|
; ioDirID - (optional) dirID
|
|
; ioMisc - pointer to an FSSpec
|
|
;
|
|
; Function: Munges the three input parameters into a friendly FSSpec for
|
|
; caller consumption. Tries to be as much like HFS parsing as
|
|
; possible.
|
|
;
|
|
; Extensions to the "standard" HFS parsing rules:
|
|
;
|
|
; When the leaf requested by the caller doesn't exist, return
|
|
; an FSSpec for that (nonexistent) leaf and return an fnfErr
|
|
; to indicate this condition.
|
|
;
|
|
; When there is no name (null or zero-length), return the name
|
|
; of the directory whose ID came in dirID. If there is no
|
|
; dirID, use the dirID from a wdRef in ioVRefNum or use fsRtDirID.
|
|
;
|
|
; Return the spelling of the leaf name directly from the catalog
|
|
;
|
|
; Special cases:
|
|
;
|
|
; When FndFilName returns an fnfErr it certainly means that
|
|
; the leaf doesn't exist. However, if the cName is a single
|
|
; segment (no colons) and the directory id is to a non-existent
|
|
; directory, FndFilName still returns an fnfErr instead of a
|
|
; dirNFErr. We need to check for the existence of the directory
|
|
; to distinguish the cases.
|
|
;
|
|
; When FndFilName is given a zero-length name it returns a
|
|
; bdNamErr. We need to make sure that the bad name was caused
|
|
; by a zero-length input (as opposed to the other bad name cases)
|
|
; and return an FSSpec on the volume/directory (i.e. vRef or wdRef)
|
|
;
|
|
; When FndFilName is given a pathname ending in a directory leaf name
|
|
; and a double colon (i.e "vol:dir1:dir2::") it returns a string length
|
|
; of zero, leaves d6 with the dirID of dir2 and a5 pointing to the
|
|
; directory record of dir1. To get around this, whenever we see
|
|
; directory records returned from FndFilName, we'll check the path
|
|
; name to see if it ends in '::'. If so, we'll substitute
|
|
; the catalog record's dir ID (dirDirID(a5)) for the dirID in d6.
|
|
; Note that if FndFilName is fixed a5 will still point to the
|
|
; same record, so we'll still work.
|
|
;
|
|
; When FndFilName is given a nil name it returns just a volume
|
|
; spec. We need to converted this into an FSSpec on the
|
|
; volume/directory (i.e. vRef or wdRef).
|
|
;
|
|
; Let the compatibility layer handle MFS volumes.
|
|
;_______________________________________________________________________
|
|
MakeFSSpec: proc export
|
|
|
|
jsrROM FSQUEUE
|
|
|
|
jsrROM DTRMV3 ; get at least the volume
|
|
bne @Exit
|
|
|
|
moveq.l #wrgVolTypErr, d0 ; assume the worst
|
|
jsrROM TFSVCBTST ; split HFS/MFS volumes
|
|
bne @Exit ; go handle MFS in the compatibility layer
|
|
|
|
moveq.l #0, d6 ; no input dirID
|
|
move.l d6, d7 ; no catalog hint
|
|
|
|
bset.b #SkipPMSP,HFSFlags ; Don't bother with PMSP for this operation
|
|
jsrROM FNDFILNAME ; parse things up
|
|
|
|
; After FndFilName, registers are:
|
|
; a2 - vcb ptr
|
|
; a4 - file name ptr
|
|
; a5 - catalog data record
|
|
; d2 - name length
|
|
; d6 - parent ID
|
|
; d7 - catalog hint
|
|
|
|
move.w d0, d5 ; save the FndFilName error for later
|
|
beq.s @NoFndFilNameErr ; keep going if there wasn't any
|
|
|
|
; Check out the error that we got
|
|
cmp.w #fnfErr, d5 ; file not found?
|
|
beq.s @FileNotFoundErr ; check this one more closely
|
|
cmp.w #bdNamErr, d5 ; bad name error?
|
|
beq.s @BadNameErr ; check this one more closely
|
|
bra @Exit ; pass other errors right on back
|
|
|
|
; Separate the bad name cases. The only one we rescue when the input name
|
|
; is null but a valid volume is determined from the vRefNum. Since we got
|
|
; a bad name we have no idea whether the dirID is valid, so fall through
|
|
; to the FileNotFoundErr case.
|
|
@BadNameErr:
|
|
move.l a4, d1 ; get name pointer
|
|
beq @AdjustErrExit ; null names have non-zero pointers
|
|
tst.b (a4) ; zero-length name?
|
|
bne.s @AdjustErrExit ; if not, must truly be a bad name
|
|
move.l a2, d1 ; do we have a good volume spec?
|
|
beq.s @AdjustErrExit ; if not, leave
|
|
moveq.l #noErr, d5 ; cancel the bdNamErr; just a zero-length name
|
|
move.l d5, d2 ; set the name length to zero
|
|
suba.l a4, a4 ; clear the name pointer
|
|
|
|
; Distinguish the real fnfErr cases from the dirNFErr cases.
|
|
@FileNotFoundErr:
|
|
move.l ioFSSpecPtr(a0), a3 ; a3 = ptr(FSSpec)
|
|
move.l d6, FSSpec.parID(a3) ; fill in the parent ID
|
|
clr.b FSSpec.name(a3) ; set name length to zero
|
|
bsr ConsultCatalog ; look up the name of the directory
|
|
cmp.w #cmnotfound, d0 ; directory not found?
|
|
beq.s @DirNFErrExit ; go tell the caller
|
|
tst.w d0 ; some other catalog manager error?
|
|
beq.s @PrepareFSSpec ; no? keep on trucking
|
|
bra.s @Exit ; if so, that's real trouble
|
|
|
|
@NoFndFilNameErr:
|
|
cmpi.b #cdrDirRec, cdrType(a5) ; a directory record?
|
|
bne.s @PrepareFSSpec ; only directories have trouble with colons
|
|
|
|
move.l ioNamePtr(a0), d0 ; grab caller's pathname
|
|
beq.s @PrepareFSSpec ; no colon problems on nil string ptrs
|
|
movea.l d0, a1
|
|
moveq.l #0, d0 ; clear high bytes
|
|
move.b (a1), d0 ; get length byte
|
|
beq.s @PrepareFSSpec ; no colon problems in null strings
|
|
lea.l 1(a1, d0.w), a1 ; make a1 point after last character
|
|
cmp.b #':', -(a1) ; did we end with a ':'?
|
|
bne.s @PrepareFSSpec ; if not, we can't have colon trouble
|
|
cmp.b #':', -(a1) ; did we end with a '::'?
|
|
bne.s @PrepareFSSpec ; no? we're all set
|
|
|
|
; Bummer. We have a leaf name that ended in '::'. FndFileName
|
|
; has unfortunately left d6 aimed at the offspring of the directory
|
|
; in a5. We can fix this by pulling the dirID out of the directory
|
|
; record, and falling through to our regular case. This will look
|
|
; like a straight dirID-only lookup, since d2 is always zero from
|
|
; FndFilName when there's a terminal ::.
|
|
move.l dirDirID(a5), d6 ; be a thread case
|
|
|
|
;
|
|
; Registers:
|
|
; d2 - length of leafname
|
|
; d5 - saved error code
|
|
; a0 - iopb
|
|
; a2 - vcb
|
|
; a4 - leafname ptr if d2 > 0
|
|
|
|
@PrepareFSSpec:
|
|
; Check for the cases where we have a dirID instead of a parID + cName
|
|
move.l ioFSSpecPtr(a0), a3 ; a3 = ptr (FSSpec)
|
|
move.w vcbVRefNum(a2), FSSpec.vRefNum(a3) ; fill in the volume refnum
|
|
move.l d6, FSSpec.parID(a3) ; fill in the dir ID
|
|
tst.w d2 ; zero-length name?
|
|
beq.s @FollowThread ; yup. Don't try to copy the leaf name
|
|
|
|
; Move the leaf name into the FSSpec
|
|
lea.l FSSpec.name(a3), a1 ; a1 = ptr(name buffer in FSSpec)
|
|
bsr CopyCName ; copy name from a4/d2 to Pstring in a1
|
|
bra.s @CorrectLeaf
|
|
|
|
@FollowThread:
|
|
clr.b FSSpec.name(a3) ; set the spec's name length to 0
|
|
|
|
@CorrectLeaf:
|
|
tst.w d5 ; did we get an fnfErr from FndFilName?
|
|
bne.s @AdjustErrExit ; if so, we can leave now
|
|
bsr ConsultCatalog ; look up the name of the leaf
|
|
bra.s @Exit ; pass errors straight back
|
|
|
|
@DirNFErrExit:
|
|
move.w #dirNFErr, d5
|
|
|
|
@AdjustErrExit:
|
|
move.w d5, d0 ; set the correct error code
|
|
|
|
@Exit:
|
|
tst.w d0 ; do we have any errors?
|
|
beq.s @1 ; if not, we're done
|
|
cmp.w #fnfErr, d0 ; did we get an fnfErr?
|
|
beq.s @1 ; then don't clear the FSSpec
|
|
move.l ioFSSpecPtr(a0), a1 ; a1 = ptr (FSSpec)
|
|
clr.l (a1)+ ; clear the volume & high word of directory
|
|
clr.l (a1)+ ; clear the directory & length byte of string
|
|
@1:
|
|
jmpROM CMDDONE
|
|
|
|
endproc
|
|
end
|