TweetFollow Us on Twitter

File Path
Volume Number:7
Issue Number:9
Column Tag:TechNotes

Related Info: File Manager File Mgr (PBxxx) Standard FIle

File Path Revisited

By Alexander Colwell, Redondo Beach, CA

Note: Source code files accompanying article are located on MacTech CD-ROM or source code disks.

File Path Revisited

Some of the MacTutor readers probably noticed. “Hey! Somebody has already written this article before! So, why is it here again?” Well the answer is yes, it has, but only half the story. The previous MacTutor articles in January 1986 “Programming for HFS Compatibility” by Mike Schuster and in July 1986 “Make a Path Name for HFS” by Tom Taylor discuss when given the volume reference number (vRefNum) obtained by the standard SFGetFile dialog then the file’s full file path can be derived.1 But what about when given a full file path and deriving the file’s vRefNum that would be identical number returned by the SFGetFile dialog?

There are cases when applications, DA’s, or other resource codes may want to know where the file is located between invocations. In April 1990, The Apple Technical Journal’s “d e v e l o p e “ in Macintosh Q&A section recommends saving the “DirID” number that references the directory.2 This scheme is desirable because it’s simple and easy to retrieve the file’s vRefNum by calling the PBOpenWD ROM routine that can be used either by the FSOpen or PBOpen ROM routines. Another advantage is that the user can change the directory name and the directory ID number will remain the same. There are cases when this scheme fails if the directory is backed up, deleted, and restored, then the directory ID number is likely to be changed. Therefore, the application must ask you for the location of the desired file by popping up the SFGetFile dialog again.

OK. So you bother the user again by reasking the location of the file. No big deal. But what about an application managing distributed databases of files where each user has mirror copy of the files and folders relationship on its hard disk? This could be a real pain to ask the user to find hundreds of files when they periodically receive database updates, and the directories are constantly changing. This was exactly the situation I encountered a few years ago during a Macintosh application development at my place of employment.

During the development cycle of that application, I poured over the MacTutor articles and Macintosh Technical Notes on how to do this seemingly simple procedure. To my disappointment, I could not find a method that somebody else might have hacked out! After a few weeks of off and on hacking, I finally figured out how to obtain the vRefNum based on the file path that is equivalent to the same vRefNum returned by the SFGetFile dialog.

The results are two procedures rewritten from Pascal to THINK C from my old Mac programming projects. The first procedure is “GetFilePath” (rehash from previous articles) to obtain the file path given by the vRefNum. The other inverse procedure is the “GetVolRefNbr” to obtain the vRefNum given by the file path.3

The key in the “GetVolRefNbr” procedure is the use of system working directory proc ID : ‘ERIK’. This small tidbit of information can be found in Macintosh Technical Note #77. In my case, I had to figure-out the hard way how this magic working directory proc ID ‘ERIK’ was used in the SFGetFile dialog. At the time, the technical note reference about ‘ERIK’ did not exist.

The conclusion is for those who need to save the file path and then later reconstruct the vRefNum for the FSOpen or PBOpen ROM routines other than using the “DirID” method, then these procedures are for you.

Bibliography

1 You can find additional references in Macintosh Technical Note #238.

2 Finder’s Desktop directory/folder hierarchy. Directories and folders are analogous.

3 I use these routines in the not quite popular shareware NotePad++ desk accessory to remember the last opened “NotePad++ File”.

char *GetFilePathName(vRefNum)
 short vRefNum;              /* File's vol/dir ref    */
 {
  WDParam      wDir;         /* Working directory     */
  HVolumeParam wVol;         /* Working HFS param blk */
  DirInfo      wCInfo;       /* Working cat info blk  */
  long         wDirID;       /* Working dir number    */
  Str255       wName;        /* Working directory name*/
  char         *wPtr;        /* Working string pointer*/
  long         wLength;      /* Working string length */
  char         *pathFileName;/* Working file path name*/

  wDir.ioNamePtr = 0L;       /* Init working directory*/
  wDir.ioVRefNum = vRefNum;
  wDir.ioWDIndex = 0;
  wDir.ioWDProcID = 0;
  wDir.ioWDVRefNum = vRefNum;

  PBGetWDInfo(&wDir,FALSE);  /* Get the directory ref */
  
  vRefNum = wDir.ioWDVRefNum;/* Save working vol ref #*/
  wDirID = wDir.ioWDDirID;   /* Save working dir ref #*/

  wVol.ioNamePtr = (StringPtr)&wName;/* Init vol block*/
  wVol.ioVRefNum = vRefNum;
  wVol.ioVolIndex = 0;
    
  wLength = 0L;              /* Set path length to zip*/
  pathFileName = NewPtr(0L); /* Set null file's path  */
  
  if (!PBHGetVInfo(&wVol,FALSE) &&/* Got vol info?    */
   pathFileName) {           /* Got file path pointer?*/
   if (wVol.ioVSigWord == 0x4244) {/* Check if it HFS */
    wCInfo.ioNamePtr = (StringPtr)&wName;/* Init it   */
    wCInfo.ioVRefNum = vRefNum;
    wCInfo.ioFDirIndex = -1;
    wCInfo.ioDrParID = wDirID;
    wCInfo.ioDrDirID = wDirID;

    while (wCInfo.ioDrParID != 1){/* Do full path     */
     wCInfo.ioDrDirID = wCInfo.ioDrParID;/*Move up dir*/

     if (PBGetCatInfo(&wCInfo,FALSE))/* Get dir info  */
      break;                 /* Break-out if failed!! */

     wLength += wName[0] + 1L;/* Set string length    */
     wPtr = NewPtr(wLength + 1L);/* Alloc new str     */

     if (!wPtr) {            /* Didn't get str ptr?   */
      if (pathFileName)      /* Check if got memory   */
       DisposPtr(pathFileName);/* Release it          */
      pathFileName = 0L;     /* Invalidate str pointer*/
      break;                 /* Break-out if failed!! */
     }
                             /* Shuffle file path down*/
     BlockMove(pathFileName,wPtr + wName[0] + 1,
               wLength - (long)(wName[0]));
     DisposPtr(pathFileName);/* Release old one       */
     *(wPtr + wName[0]) = ':';/* Add dir delimeter    */
     BlockMove(&wName[1],pathFileName = wPtr, (long)(wName[0]));
    }
   }
   else {                    /* Oops, get vol info    */
    wLength = wName[0] + 1L; /* Set string length     */
    wPtr = NewPtr(wLength + 1L);/* Alloc new string   */

    if (wPtr) {              /* Got string pointer?   */
     *(wPtr + wName[0]) = ':';/* Tack on dir delimeter*/
     BlockMove(&wName[1],pathFileName = wPtr,
               (long)(wName[0]));
    }

   }
   if (pathFileName)         /* Check if got da string*/
    pathFileName[wLength] = 0;/* Set end-of-string    */
  }
  return(pathFileName);      /* Return file path name */
 }
 
short GetFilePathVolRef(pathFileName)
 char *pathFileName;         /* File's path string    */
 {
  short        i;            /* Working index         */
  char         c;            /* Working input char    */
  short        vRefNum;      /* Working vol/dir ref   */
  WDParam      wDir;         /* Working directory     */
  HVolumeParam wVol;         /* Working HFS param blk */
  DirInfo      wCInfo;       /* Working cat info block*/
  long         wDirID;       /* Working directory ID  */
  Str255       wVolName;     /* Working volume name   */
  Str255       wName;        /* Working string name   */
  char         *wPtr;        /* Working string pointer*/
  short        wLength;      /* Working string length */
  
  vRefNum = 0;               /* Invalid vol/dir ref # */
  
  wVol.ioVRefNum = 0;        /* Init working vol ID # */
  wCInfo.ioDrDirID = 2;      /* Init top-most dir     */
  
  i = 0;                     /* Init working index    */
  wLength = 0;               /* Init string length    */
  
  c = pathFileName[i];       /* Set 1st input char    */
  
  while(c) {                 /* Do til get vol/dir ref*/
   if (c == ':') {           /* Check if got dir specs*/
    wName[0] = wLength - 1;  /* Set "Pascal" str len  */
    wLength = 0;             /* Reset string length   */

    if (!wVol.ioVRefNum) {   /* Check if need vol ref */
     wVol.ioNamePtr = (StringPtr)(&wVolName);

     for(wVol.ioVolIndex = 1; !PBHGetVInfo(&wVol,FALSE);
      wVol.ioVolIndex++) {
      if (EqualString(wName,wVolName,FALSE,FALSE))
       break;
      }

     vRefNum = wVol.ioVRefNum;/* Save vol ID          */
     if (wVol.ioVSigWord != 0x4244)/* MFS ?           */
      return(vRefNum);       /* Let's get out early!  */
    }
    else {                   /* Nope, get dir ref     */
     wCInfo.ioNamePtr = (StringPtr)(&wName);
     wCInfo.ioVRefNum = wVol.ioVRefNum;
     wCInfo.ioFDirIndex = 0;
     wCInfo.ioDrParID = wCInfo.ioDrDirID;

     if (PBGetCatInfo(&wCInfo,FALSE))/* Check dir ?   */
      return(0);             /* Nope, break-out!!!    */
    }
   }                         /* Add to directory specs*/
   c = wName[++wLength] = pathFileName[i++];
  }
  wDir.ioNamePtr = 0L;       /* Init dir data block   */
  wDir.ioVRefNum = wVol.ioVRefNum;
  wDir.ioWDProcID = 'ERIK';  /* Magic 'SFGetFile' ID #*/
  wDir.ioWDDirID = wCInfo.ioDrDirID;
  
  if (!PBOpenWD(&wDir,FALSE))/* Check if opened dir   */
   vRefNum = wDir.ioVRefNum; /* Return vol/dir ref #  */

  return(vRefNum);           /* Return vol/dir ref #  */
 }
 

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Latest Forum Discussions

See All

Combo Quest (Games)
Combo Quest 1.0 Device: iOS Universal Category: Games Price: $.99, Version: 1.0 (iTunes) Description: Combo Quest is an epic, time tap role-playing adventure. In this unique masterpiece, you are a knight on a heroic quest to retrieve... | Read more »
Hero Emblems (Games)
Hero Emblems 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: ** 25% OFF for a limited time to celebrate the release ** ** Note for iPhone 6 user: If it doesn't run fullscreen on your device... | Read more »
Puzzle Blitz (Games)
Puzzle Blitz 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: Puzzle Blitz is a frantic puzzle solving race against the clock! Solve as many puzzles as you can, before time runs out! You have... | Read more »
Sky Patrol (Games)
Sky Patrol 1.0.1 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0.1 (iTunes) Description: 'Strategic Twist On The Classic Shooter Genre' - Indie Game Mag... | Read more »
The Princess Bride - The Official Game...
The Princess Bride - The Official Game 1.1 Device: iOS Universal Category: Games Price: $3.99, Version: 1.1 (iTunes) Description: An epic game based on the beloved classic movie? Inconceivable! Play the world of The Princess Bride... | Read more »
Frozen Synapse (Games)
Frozen Synapse 1.0 Device: iOS iPhone Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: Frozen Synapse is a multi-award-winning tactical game. (Full cross-play with desktop and tablet versions) 9/10 Edge 9/10 Eurogamer... | Read more »
Space Marshals (Games)
Space Marshals 1.0.1 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0.1 (iTunes) Description: ### IMPORTANT ### Please note that iPhone 4 is not supported. Space Marshals is a Sci-fi Wild West adventure taking place... | Read more »
Battle Slimes (Games)
Battle Slimes 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: BATTLE SLIMES is a fun local multiplayer game. Control speedy & bouncy slime blobs as you compete with friends and family.... | Read more »
Spectrum - 3D Avenue (Games)
Spectrum - 3D Avenue 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: "Spectrum is a pretty cool take on twitchy/reaction-based gameplay with enough complexity and style to stand out from the... | Read more »
Drop Wizard (Games)
Drop Wizard 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: Bring back the joy of arcade games! Drop Wizard is an action arcade game where you play as Teo, a wizard on a quest to save his... | Read more »

Price Scanner via MacPrices.net

Our MacBook Price Trackers will show you the...
Our Apple award-winning MacBook Price Trackers are continually updated with the latest information on prices, bundles, and availability for 16″ and 14″ MacBook Pros along with 13″ and 15″ MacBook... Read more
Amazon is offering a 10% discount on Apple’s...
Don’t pay full price! Amazon has 16-inch M4 Pro MacBook Pros (Silver and Black colors) on sale today for 10% off Apple’s MSRP. Shipping is free. These are the lowest prices currently available for 16... Read more
13-inch M4 MacBook Airs on sale for $150 off...
Amazon has new 13″ M4 MacBook Airs on sale for $150 off MSRP right now, starting at $849. Sale prices apply to most colors and configurations. Be sure to select Amazon as the seller, rather than a... Read more
15-inch M4 MacBook Airs on sale for $150 off...
Amazon has new 15″ M4 MacBook Airs on sale for $150 off Apple’s MSRP, starting at $1049. Be sure to select Amazon as the seller, rather than a third-party: – 15″ M4 MacBook Air (16GB/256GB): $1049, $... Read more
Amazon is offering a $50 discount on Apple’s...
Amazon has Apple’s 11th-generation A16 iPads in stock on sale for $50 (or a little more) off MSRP this week. Shipping is free: – 11″ 11th-generation 128GB WiFi iPads: $299 $50 off MSRP – 11″ 11th-... Read more
Clearance 13-inch M1 MacBook Airs available f...
Walmart has clearance, but new, Apple 13″ M1 MacBook Airs (8GB RAM, 256GB SSD) available online for $649, $360 off original MSRP, in Space Gray, Silver, and Gold colors. These are new MacBooks for... Read more
iPad minis on sale for $100 off Apple’s MSRP...
Amazon is offering $100 discounts (up to 20% off) on Apple’s newest 2024 WiFi iPad minis, each with free shipping. These are the lowest prices available for new minis among the Apple retailers we... Read more
AirPods Max headphones on sale for $479, $70...
Amazon has AirPods Max with USB-C on sale for $479.99 in all colors. Shipping is free. Their price is $70 off Apple’s MSRP, and it’s the lowest price available today for AirPods Max. Keep an eye on... Read more
14-inch M4 Pro/M4 Max MacBook Pros on sale th...
Don’t pay full price! Get a new 14″ MacBook Pro with an M4 Pro or M4 Max CPU for up to $320 off Apple’s MSRP this weekend at these retailers…they are the lowest prices available for these MacBook... Read more
Get a 15-inch M4 MacBook Air for $150 off App...
A couple of Apple retailers are offering $150 discounts on new 15″ M4 MacBook Airs this weekend. Prices at these retailers start at $1049: (1): Amazon has new 15″ M4 MacBook Airs on sale for $150 off... Read more

Jobs Board

All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.