[comp.sys.mac.programmer] file system questions

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