Blame | Last modification | View Log | Download | RSS feed
/*** Apple Macintosh Developer Technical Support**** Routines for dealing with full pathnames... if you really must.**** by Jim Luther, Apple Developer Technical Support Emeritus**** File: FullPath.c**** Copyright © 1995-1996 Apple Computer, Inc.** All rights reserved.**** You may incorporate this sample code into your applications without** restriction, though the sample code has been provided "AS IS" and the** responsibility for its operation is 100% yours. However, what you are** not permitted to do is to redistribute the source as "DSC Sample Code"** after having made changes. If you're going to re-distribute the source,** we require that you make it clear in the source that the code was** descended from Apple Sample Code, but that you've made changes.*/#include <Types.h>#include <Errors.h>#include <Memory.h>#include <Files.h>#include <TextUtils.h>#include <Aliases.h>#define __COMPILINGMOREFILES#include "FullPath.h"/*IMPORTANT NOTE:The use of full pathnames is strongly discouraged. Full pathnames areparticularly unreliable as a means of identifying files, directoriesor volumes within your application, for two primary reasons:¥ The user can change the name of any element in the path at virtuallyany time.¥ Volume names on the Macintosh are *not* unique. Multiplemounted volumes can have the same name. For this reason, the use ofa full pathname to identify a specific volume may not produce theresults you expect. If more than one volume has the same name anda full pathname is used, the File Manager currently uses the firstmounted volume it finds with a matching name in the volume queue.In general, you should use a fileÕs name, parent directory ID, andvolume reference number to identify a file you want to open, delete,or otherwise manipulate.If you need to remember the location of a particular file acrosssubsequent system boots, use the Alias Manager to create an alias recorddescribing the file. If the Alias Manager is not available, you can savethe fileÕs name, its parent directory ID, and the name of the volume onwhich itÕs located. Although none of these methods is foolproof, they aremuch more reliable than using full pathnames to identify files.Nonetheless, it is sometimes useful to display a fileÕs full pathname tothe user. For example, a backup utility might display a list of fullpathnames of files as it copies them onto the backup medium. Or, autility might want to display a dialog box showing the full pathname ofa file when it needs the userÕs confirmation to delete the file. Nomatter how unreliable full pathnames may be from a file-specificationviewpoint, users understand them more readily than volume referencenumbers or directory IDs. (Hint: Use the TruncString function fromTextUtils.h with truncMiddle as the truncWhere argument to shortenfull pathnames to a displayable length.)The following technique for constructing the full pathname of a file isintended for display purposes only. Applications that depend on anyparticular structure of a full pathname are likely to fail on alternateforeign file systems or under future system software versions.*//*****************************************************************************/pascal OSErr FSpGetFullPath(const FSSpec *spec,short *fullPathLength,Handle *fullPath){OSErr result;FSSpec tempSpec;CInfoPBRec pb;*fullPathLength = 0;*fullPath = NULL;/* Make a copy of the input FSSpec that can be modified */BlockMoveData(spec, &tempSpec, sizeof(FSSpec));if ( tempSpec.parID == fsRtParID ){/* The object is a volume *//* Add a colon to make it a full pathname */++tempSpec.name[0];tempSpec.name[tempSpec.name[0]] = ':';/* We're done */result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);}else{/* The object isn't a volume *//* Is the object a file or a directory? */pb.dirInfo.ioNamePtr = tempSpec.name;pb.dirInfo.ioVRefNum = tempSpec.vRefNum;pb.dirInfo.ioDrDirID = tempSpec.parID;pb.dirInfo.ioFDirIndex = 0;result = PBGetCatInfoSync(&pb);if ( result == noErr ){/* if the object is a directory, append a colon so full pathname ends with colon */if ( (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0 ){++tempSpec.name[0];tempSpec.name[tempSpec.name[0]] = ':';}/* Put the object name in first */result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);if ( result == noErr ){/* Get the ancestor directory names */pb.dirInfo.ioNamePtr = tempSpec.name;pb.dirInfo.ioVRefNum = tempSpec.vRefNum;pb.dirInfo.ioDrParID = tempSpec.parID;do /* loop until we have an error or find the root directory */{pb.dirInfo.ioFDirIndex = -1;pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;result = PBGetCatInfoSync(&pb);if ( result == noErr ){/* Append colon to directory name */++tempSpec.name[0];tempSpec.name[tempSpec.name[0]] = ':';/* Add directory name to beginning of fullPath */(void) Munger(*fullPath, 0, NULL, 0, &tempSpec.name[1], tempSpec.name[0]);result = MemError();}} while ( (result == noErr) && (pb.dirInfo.ioDrDirID != fsRtDirID) );}}}if ( result == noErr ){/* Return the length */*fullPathLength = GetHandleSize(*fullPath);}else{/* Dispose of the handle and return NULL and zero length */if ( *fullPath != NULL ){DisposeHandle(*fullPath);}*fullPath = NULL;*fullPathLength = 0;}return ( result );}/*****************************************************************************/