[comp.sources.mac] Constructing full paths

cute@sphinx.uchicago.edu (John Cavallino) (07/16/87)

[Constructing full paths]

Here is some pascal code which performs said useful function.  If you like it,
use it. It was developed in Lightspeed Pascal, and is known to work correctly
on a 512kE, MacPlus and Mac SE.

---
{ some helpful HFS procedures and functions }
{ by John Cavallino }
{ last edit: 5-25-87 }

FUNCTION HFS : boolean;
{ returns TRUE if we are running under HFS }
CONST
	FSFCBLen = $3F6;		{ see Inside Mac., IV-309 }
VAR
	FCBLen : ^integer;
BEGIN
	FCBLen := pointer(FSFCBLen);
	HFS := (FCBLen^ > 0);
END; { function HFS }


FUNCTION BigDisk (vRefNum : integer) : boolean;
{ the function assumes it is running under HFS, }
{ else why would we want to check? }
CONST
	BigDiskSig = $4244;	{ see Inside Mac., IV-166 }
VAR
	vInfo : HParamBlockRec;
	err : integer;
BEGIN
	WITH vInfo DO BEGIN
	ioCompletion := NIL;
	ioNamePtr := NIL;	{ we're not interested in the name }
	ioVRefNum := vRefNum;	{ this volume, please }
	ioVolIndex := 0;	{ look up using ioVRefNum only }
	END;
	err := PBHGetVInfo(@vInfo, false);
	IF (err = noErr) THEN
          BigDisk := (vInfo.ioVSigWord = BigDiskSig)
	ELSE
          BigDisk := false;
END; { function BigDisk }
	

FUNCTION BuildPath (VAR vRefNum : integer;
			fileName : Str31;
			DirID : longint;
			wdProc : longint;
			VAR path : Str255) : OSErr;
{ constructs the full path for the file, directory and volume specified }
{ If the path runs over 255 characters, it is truncated to a partial path and }
{ a WD reference (built with wdProc) to the root of the path is returned }
{ in vRefNum. If the path is complete, the original vRefNum value is returned }
CONST
	rootID=2;
VAR
	pInfo : CInfoPBRec;
	vInfo : ParamBlockRec;
	wdInfo : WDPBRec;
	dirName : Str255;
	theDir : longint;
	wdRef : integer;
	err : integer;
	MFS : boolean;
	done : boolean;
	tooLong : boolean;
BEGIN
	IF HFS THEN
	   MFS := NOT BigDisk(vRefNum)
	ELSE
	   MFS := true;
	IF MFS THEN BEGIN  { is MFS volume }
	   dirName := '';	{ initialize the name }
	   WITH vInfo DO BEGIN
	      ioCompletion := NIL;
	      ioNamePtr := @dirName;	{ volume name is returned here }
	      ioVRefNum := vRefNum;	{ this volume, please }
	      ioVolIndex := 0;	        { use ioVRefNum only }
	   END;
	   err := PBGetVInfo(@vInfo, false);
	   IF (err = noErr) THEN
	      path := concat(dirName, ':', fileName)
	   ELSE
	      path := '';
	   END  { is MFS volume }
	ELSE BEGIN  { is HFS volume }
	   path := fileName;
	   done := false;
	   tooLong := false;
	   theDir := DirID;
	   err := noErr;
	   WHILE NOT done AND NOT tooLong AND (err = noErr) DO BEGIN
	      dirName := '';	{ initialize the name }
	      WITH pInfo DO BEGIN
	         ioCompletion := NIL;
	         ioNamePtr := @dirName;  { dir. name returned here }
	         ioVRefNum := vRefNum;   { this volume, please }
	         ioFDirIndex := -1;      { look at theDir only }
	         ioDirID := theDir;      { this directory please }
	      END;
	      err := PBGetCatInfo(@pInfo, false);
	      IF (err = noErr) THEN
	         IF (2 + length(dirName) + length(path)) > 255 THEN
		 { the 2 is to allow for colons }
	            tooLong := true
	         ELSE BEGIN
	            path := concat(dirName, ':', path);
	            done := (pInfo.ioDirID = rootID);  { are we at the root? }
	            IF NOT done THEN
	               theDir := pInfo.ioFlParID;  { climb the tree }
	         END;
	   END;  { while not done and not tooLong and (err = noErr) do }
	   IF tooLong THEN BEGIN
	      path := concat(':', path);  { return partial path }
	      WITH wdInfo DO BEGIN
	         ioCompletion := NIL;
	         ioNamePtr := NIL;      { just initialize field }
	         ioVRefNum := vRefNum;  { on this volume, please }
	         ioWDProcID := wdProc;  { give it this procID }
	         ioWDDirID := theDir;	{ it's this directory }
	      END;
	      err := PBOpenWD(@wdInfo, false);  { build WD for root of path }
	      IF (err = noErr) THEN
	         vRefNum := wdInfo.ioVRefNum { WDRefNum returned in this field }
	      ELSE BEGIN { no more working directories available }
	         vRefNum := 0;
	         path := '';
	      END;
	   END;  { if tooLong }
	END;  { is HFS volume }
	BuildPath := err;	{ return the error code }
END;  { function BuildPath }

---