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

The beginner's guide to Warbits
Warbits is a turn-based strategy that's clearly inspired by Nintendo's Advance Wars series. Since turn-based strategy games can be kind of tricky to dive into, see below for a few tips to help you in the beginning. Positioning is crucial [Read... | Read more »
How to upgrade your character in Spellsp...
So you’ve mastered the basics of Spellspire. By which I mean you’ve realised it’s all about spelling things in a spire. What next? Well you’re going to need to figure out how to toughen up your character. It’s all well and good being able to spell... | Read more »
5 slither.io mash-ups we'd love to...
If there's one thing that slither.io has proved, it's that the addictive gameplay of Agar.io can be transplanted onto basically anything and it will still be good fun. It wouldn't be surprising if we saw other developers jumping on the bandwagon,... | Read more »
How to navigate the terrain in Sky Charm...
Sky Charms is a whimsical match-'em up adventure that uses creative level design to really ramp up the difficulty. [Read more] | Read more »
Victorious Knight (Games)
Victorious Knight 1.3 Device: iOS Universal Category: Games Price: $1.99, Version: 1.3 (iTunes) Description: New challenges awaits you! Experience fresh RPG experience with a unique combat mechanic, packed with high quality 3D... | Read more »
Agent Gumball - Roguelike Spy Game (Gam...
Agent Gumball - Roguelike Spy Game 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: Someone’s been spying on Gumball. What the what?! Two can play at that game! GO UNDERCOVERSneak past enemy... | Read more »
Runaway Toad (Games)
Runaway Toad 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: It ain’t easy bein’ green! Tap, hold, and swipe to help Toad hop to safety in this gorgeous new action game from the creators of... | Read more »
PsyCard (Games)
PsyCard 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: From the makers och Card City Nights, Progress To 100 and Ittle Dew PSYCARD is a minesweeper-like game set in a cozy cyberpunk... | Read more »
Sago Mini Robot Party (Education)
Sago Mini Robot Party 1.0 Device: iOS Universal Category: Education Price: $2.99, Version: 1.0 (iTunes) Description: -- Children's Technology Review Editor's Choice -- | Read more »
Egz – The Origin of the Universe (Games...
Egz – The Origin of the Universe 1.0.2 Device: iOS Universal Category: Games Price: $3.99, Version: 1.0.2 (iTunes) Description: ►►► Special offer until 2nd may : get the game at 2.99€ instead of 3.99€ ! ◄◄◄ Egz is a mesmerizing mix... | Read more »

Price Scanner via MacPrices.net

Price drops on clearance 12-inch Retina MacBo...
B&H Photo has dropped prices on leftover 2015 12″ Retina MacBooks with models now available starting at $999. Shipping is free, and B&H charges NY tax only: - 12″ 1.1GHz Gray Retina MacBook... Read more
15-inch Retina MacBook Pros available for $20...
B&H Photo has 15″ Retina MacBook Pros on sale for up to $210 off MSRP. Shipping is free, and B&H charges NY tax only: - 15″ 2.2GHz Retina MacBook Pro: $1799 $200 off MSRP - 15″ 2.5GHz Retina... Read more
Target offers Apple Watch Sport for $50 off M...
Target has Apple Watch Sports on sale for $50 off MSRP for a limited time. Choose free shipping or free local store pickup (if available). Sale prices for online orders only, in-store prices may vary... Read more
Apple restocks Certified Refurbished Mac mini...
Apple has restocked Certified Refurbished 2014 Mac minis, with models available starting at $419. Apple’s one-year warranty is included with each mini, and shipping is free: - 1.4GHz Mac mini: $419 $... Read more
15-inch 2.2GHz Retina MacBook Pro on sale for...
Amazon.com has the 15″ 2.2GHz Retina MacBook Pro on sale for $1699.99 including free shipping. Their price is $300 off MSRP, and it’s the lowest price available for this model from any reseller (and... Read more
Apple Beats Microsoft at Own Game; Amazon Pri...
First quarter seasonality combined with an overall disinterested customer base led to an annual decline of 14.7% in worldwide tablet shipments during the first quarter of 2016 (1Q16). Worldwide... Read more
Tablets Had Worst Quarter Since 2012, says St...
The global tablet market began 2016 just as 2015 left off, down. Tablet shipments fell 10% to 46.5 million units during the Q1 2016, according to the new “Preliminary Global Tablet Shipments and... Read more
Clearance 13-inch MacBook Airs, Apple refurbi...
Apple recently dropped prices on certified refurbished 2015 13″ MacBook Airs with 4GB of RAM with models now available starting at $759. An Apple one-year warranty is included with each MacBook, and... Read more
Clearance 12-inch Retina MacBooks, Apple refu...
Apple has dropped prices on Certified Refurbished 2015 12″ Retina MacBooks with models now available starting at $929. Apple will include a standard one-year warranty with each MacBook, and shipping... Read more
Aleratec Releases Mac Software Upgrade for 1...
California based Aleratec Inc., designer, developer and manufacturer of Portable Device Management (PDM) charge/sync products for mobile devices and professional-grade duplicators for hard disk... Read more

Jobs Board

Restaurant Manager (Neighborhood Captain) - A...
…in every aspect of daily operation. WHY YOU'LL LIKE IT: You'll be the Big Apple . You'll solve problems. You'll get to show your ability to handle the stress and Read more
Simply Mac *Apple* Specialist- Service Repa...
Simply Mac is the largest premier retailer of Apple products in the nation. In order to support our growing customer base, we are currently looking for a driven Read more
*Apple* Retail - Multiple Positions - Apple,...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
Restaurant Manager (Neighborhood Captain) - A...
…in every aspect of daily operation. WHY YOU'LL LIKE IT: You'll be the Big Apple . You'll solve problems. You'll get to show your ability to handle the stress and Read more
Automotive Sales Consultant - Apple Ford Linc...
…you. The best candidates are smart, technologically savvy and are customer focused. Apple Ford Lincoln Apple Valley is different, because: $30,000 annual salary Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.