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).