zben@umd5.umd.edu (Ben Cranston) (06/20/89)
A recent question in comp.sys.mac.digest piqued my own curiousity. A reader
asks how to find the Directory ID of the directory containing the currently
executing application. The routine GetVRefNum, which takes a path reference
number and returns a volume reference number, came up in this discussion.
Could anybody set me straight on the following topics?
1. As far as I could determine, GetVRefNum is the ONLY File Manager routine
that accepts a path reference number as an argument. I had always naively
thought that the high-level routines were crutches for weenies who were
afraid of IOPBs, but in this case there is no low-level equivalent.
(Please find appended a disassembled listing of GetVRefNum.)
2. On page II-80 it is stated "Initially, the volume used to start up the
application is the default volume, but an application can designate...".
This would lead one to believe that a GetVol before ever doing a SetVol
would reliably return the volume containing the current application.
However, I have been running benchmarks on the NFS package, building the
benchmark program as a MPW tool and using the following sequence to run
the benchmark against a specific NFS-mounted volume:
directory tmp@camelot:
harddisk:projects:bmark:bmark
The first line sets the default volume to the NFS mounted volume on host
camelot, the second line execute the benchmark program from the local
Macintosh hard disk. The "bmark" program opens a file in the current
directory (it just calls the MPW C "open" routine). Yet this sequence
causes the benchmark to run against the NFS mounted volume.
Ergo, this is one case in which the "default volume" is NOT the one
containing the application (granted MPW is a nonstandard environment).
Is there a better way to determine the directory ID of the directory
containing the currently executing application?
3. There appear to be at least two variables which could be termed the
"current directory". One is the "current volume" which can be set to
a WDRefNum by the SetVol call. I assume this is kept in the File Manager
somewhere. The other variable is the "CurDirStore" used by the Standard
File package. This variable determines which directory is initially
visible when SFGetFile/SFPutFile get called.
As a nicety to the user many routines that do a SetVol call will also
change CurDirStore, as a user-friendlyness touch. This sometimes leads
to confused users who think there is only one current directory variable.
Is this mental model correct, or are there MORE machinations to learn?
*
* Given a path reference number, return reference number to volume on
* which the file resides.
*
* This code KNOWS that the path reference number is really an offset into a
* system heap block containing the File Control Blocks. It performs a few
* sanity checks (detailed below).
*
* Examines incore FCB (II-127) and VCB (II-125).
*
GetVRefNum Entry ;
Move.L (A7)+,A1 ; Pop return address
*
* Two sanity checks are performed on the PathRefNum. One, the modulo residue
* should be 2 (because of the length word at the beginning). Two, the RefNum
* should be less than the length of the FCB buffer.
*
Move.L #0,D1 ; Clear slack bits
Move.W 4(A7),D1 ; Get pathRefNum argument
Move.L FCBSPtr,A0 ; Get pointer to FCB block
Move.W FSFCBLen,D0 ; HFS flag/length of entry
BMi.S @010 ; If MFS go use constant
DivU.W D0,D1 ; Compute mod of pointer
Bra.S @020 ; Go check remainder
@010 ;
DivU.W #94,D1 ; MFS constant FCB size
@020 ;
Swap D1 ; Get remainder of division
Sub.W #2,D1 ; Allow for length word
BNE.S @030 ; If not zero then error
*
Move.W 4(A7),D0 ; Get pathRefNum argument
Cmp.W (A0),D0 ; Within size of buffer?
BHS.S @030 ; If not then error
*
* Sanity check passed, link to volume to get reference number.
*
Move.L fcbVPtr(A0,D0.W),A0 ; Link to volume control block
Move.W vcbVRefNum(A0),D0 ; Get Volume RefNum
Move.L #0,D1 ; Clear error code
Bra.S @040 ; Return to caller
*
* Error in pathRefNum
*
@030 ;
Move.L #0,D0 ; Return zero to caller
Move.W #$FFCD,D1 ; Get error code
*
@040 ;
Move.L (A7),A0 ; Get address of vRefNum argument
Move.W D0,(A0) ; Set vRefNum argument
Add.W #6,A7 ; Pop arguments
Move.W D1,(A7) ; Set function result computed above
Jmp (A1) ; Return to caller
--
Ben Cranston <zben@umd2.UMD.EDU> (Kingdom of Merryland UniSys 1100/92)
Copyright 1989 (you may redistribute ONLY if your recipients can).