]>
git.saurik.com Git - wxWidgets.git/blob - src/mac/morefile/FullPath.cpp
   2 **      Apple Macintosh Developer Technical Support 
   4 **      Routines for dealing with full pathnames... if you really must. 
   6 **      by Jim Luther, Apple Developer Technical Support Emeritus 
  10 **      Copyright © 1995-1998 Apple Computer, Inc. 
  11 **      All rights reserved. 
  13 **      You may incorporate this sample code into your applications without 
  14 **      restriction, though the sample code has been provided "AS IS" and the 
  15 **      responsibility for its operation is 100% yours.  However, what you are 
  16 **      not permitted to do is to redistribute the source as "DSC Sample Code" 
  17 **      after having made changes. If you're going to re-distribute the source, 
  18 **      we require that you make it clear in the source that the code was 
  19 **      descended from Apple Sample Code, but that you've made changes. 
  26 #include <TextUtils.h> 
  29 #define __COMPILINGMOREFILES 
  37         The use of full pathnames is strongly discouraged. Full pathnames are 
  38         particularly unreliable as a means of identifying files, directories 
  39         or volumes within your application, for two primary reasons: 
  41         ¥      The user can change the name of any element in the path at virtually 
  43         ¥      Volume names on the Macintosh are *not* unique. Multiple 
  44                 mounted volumes can have the same name. For this reason, the use of 
  45                 a full pathname to identify a specific volume may not produce the 
  46                 results you expect. If more than one volume has the same name and 
  47                 a full pathname is used, the File Manager currently uses the first 
  48                 mounted volume it finds with a matching name in the volume queue. 
  50         In general, you should use a fileÕs name, parent directory ID, and 
  51         volume reference number to identify a file you want to open, delete, 
  52         or otherwise manipulate. 
  54         If you need to remember the location of a particular file across 
  55         subsequent system boots, use the Alias Manager to create an alias record 
  56         describing the file. If the Alias Manager is not available, you can save 
  57         the fileÕs name, its parent directory ID, and the name of the volume on 
  58         which itÕs located. Although none of these methods is foolproof, they are 
  59         much more reliable than using full pathnames to identify files. 
  61         Nonetheless, it is sometimes useful to display a fileÕs full pathname to 
  62         the user. For example, a backup utility might display a list of full 
  63         pathnames of files as it copies them onto the backup medium. Or, a 
  64         utility might want to display a dialog box showing the full pathname of 
  65         a file when it needs the userÕs confirmation to delete the file. No 
  66         matter how unreliable full pathnames may be from a file-specification 
  67         viewpoint, users understand them more readily than volume reference 
  68         numbers or directory IDs. (Hint: Use the TruncString function from 
  69         TextUtils.h with truncMiddle as the truncWhere argument to shorten 
  70         full pathnames to a displayable length.) 
  72         The following technique for constructing the full pathname of a file is 
  73         intended for display purposes only. Applications that depend on any 
  74         particular structure of a full pathname are likely to fail on alternate 
  75         foreign file systems or under future system software versions. 
  78 /*****************************************************************************/ 
  80 pascal  OSErr   
GetFullPath(short vRefNum
, 
  82                                                         ConstStr255Param name
, 
  83                                                         short *fullPathLength
, 
  92         result 
= FSMakeFSSpecCompat(vRefNum
, dirID
, name
, &spec
); 
  93         if ( (result 
== noErr
) || (result 
== fnfErr
) ) 
  95                 result 
= FSpGetFullPath(&spec
, fullPathLength
, fullPath
); 
 101 /*****************************************************************************/ 
 103 pascal  OSErr   
FSpGetFullPath(const FSSpec 
*spec
, 
 104                                                            short *fullPathLength
, 
 118         /* Make a copy of the input FSSpec that can be modified */ 
 119         BlockMoveData(spec
, &tempSpec
, sizeof(FSSpec
)); 
 121         if ( tempSpec
.parID 
== fsRtParID 
) 
 123                 /* The object is a volume */ 
 125                 /* Add a colon to make it a full pathname */ 
 127                 tempSpec
.name
[tempSpec
.name
[0]] = ':'; 
 130                 result 
= PtrToHand(&tempSpec
.name
[1], fullPath
, tempSpec
.name
[0]); 
 134                 /* The object isn't a volume */ 
 136                 /* Is the object a file or a directory? */ 
 137                 pb
.dirInfo
.ioNamePtr 
= tempSpec
.name
; 
 138                 pb
.dirInfo
.ioVRefNum 
= tempSpec
.vRefNum
; 
 139                 pb
.dirInfo
.ioDrDirID 
= tempSpec
.parID
; 
 140                 pb
.dirInfo
.ioFDirIndex 
= 0; 
 141                 result 
= PBGetCatInfoSync(&pb
); 
 142                 // Allow file/directory name at end of path to not exist. 
 144                 if ( (result 
== noErr
) || (result 
== fnfErr
) ) 
 146                         /* if the object is a directory, append a colon so full pathname ends with colon */ 
 147                         if ( (result 
== noErr
) && (pb
.hFileInfo
.ioFlAttrib 
& ioDirMask
) != 0 ) 
 150                                 tempSpec
.name
[tempSpec
.name
[0]] = ':'; 
 153                         /* Put the object name in first */ 
 154                         result 
= PtrToHand(&tempSpec
.name
[1], fullPath
, tempSpec
.name
[0]); 
 155                         if ( result 
== noErr 
) 
 157                                 /* Get the ancestor directory names */ 
 158                                 pb
.dirInfo
.ioNamePtr 
= tempSpec
.name
; 
 159                                 pb
.dirInfo
.ioVRefNum 
= tempSpec
.vRefNum
; 
 160                                 pb
.dirInfo
.ioDrParID 
= tempSpec
.parID
; 
 161                                 do      /* loop until we have an error or find the root directory */ 
 163                                         pb
.dirInfo
.ioFDirIndex 
= -1; 
 164                                         pb
.dirInfo
.ioDrDirID 
= pb
.dirInfo
.ioDrParID
; 
 165                                         result 
= PBGetCatInfoSync(&pb
); 
 166                                         if ( result 
== noErr 
) 
 168                                                 /* Append colon to directory name */ 
 170                                                 tempSpec
.name
[tempSpec
.name
[0]] = ':'; 
 172                                                 /* Add directory name to beginning of fullPath */ 
 173                                                 (void) Munger(*fullPath
, 0, NULL
, 0, &tempSpec
.name
[1], tempSpec
.name
[0]); 
 176                                 } while ( (result 
== noErr
) && (pb
.dirInfo
.ioDrDirID 
!= fsRtDirID
) ); 
 180         if ( result 
== noErr 
) 
 182                 /* Return the length */ 
 183                 *fullPathLength 
= InlineGetHandleSize(*fullPath
); 
 184                 result 
= realResult
;    // return realResult in case it was fnfErr 
 188                 /* Dispose of the handle and return NULL and zero length */ 
 189                 if ( *fullPath 
!= NULL 
) 
 191                         DisposeHandle(*fullPath
); 
 200 /*****************************************************************************/ 
 202 pascal OSErr 
FSpLocationFromFullPath(short fullPathLength
, 
 203                                                                          const void *fullPath
, 
 211         /* Create a minimal alias from the full pathname */ 
 212         nullString
[0] = 0;      /* null string to indicate no zone or server name */ 
 213         result 
= NewAliasMinimalFromFullPath(fullPathLength
, fullPath
, nullString
, nullString
, &alias
); 
 214         if ( result 
== noErr 
) 
 216                 /* Let the Alias Manager resolve the alias. */ 
 217                 result 
= ResolveAlias(NULL
, alias
, spec
, &wasChanged
); 
 219                 DisposeHandle((Handle
)alias
);   /* Free up memory used */ 
 224 /*****************************************************************************/ 
 226 pascal OSErr 
LocationFromFullPath(short fullPathLength
, 
 227                                                                   const void *fullPath
, 
 235         result 
= FSpLocationFromFullPath(fullPathLength
, fullPath
, &spec
); 
 236         if ( result 
== noErr 
) 
 238                 *vRefNum 
= spec
.vRefNum
; 
 240                 BlockMoveData(&spec
.name
[0], &name
[0], spec
.name
[0] + 1); 
 245 /*****************************************************************************/