• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/ap/gpl/amule/wxWidgets-2.8.12/src/mac/classic/morefile/
1/*
2	File:		FullPath.c
3
4	Contains:	Routines for dealing with full pathnames... if you really must.
5
6	Version:	MoreFiles
7
8	Copyright:	� 1995-2001 by Apple Computer, Inc., all rights reserved.
9
10	You may incorporate this sample code into your applications without
11	restriction, though the sample code has been provided "AS IS" and the
12	responsibility for its operation is 100% yours.  However, what you are
13	not permitted to do is to redistribute the source as "DSC Sample Code"
14	after having made changes. If you're going to re-distribute the source,
15	we require that you make it clear in the source that the code was
16	descended from Apple Sample Code, but that you've made changes.
17
18	File Ownership:
19
20		DRI:				Apple Macintosh Developer Technical Support
21
22		Other Contact:		Apple Macintosh Developer Technical Support
23							<http://developer.apple.com/bugreporter/>
24
25		Technology:			DTS Sample Code
26
27	Writers:
28
29		(JL)	Jim Luther
30
31	Change History (most recent first):
32
33		 <2>	  2/7/01	JL		Added standard header. Updated names of includes.
34		<1>		12/06/99	JL		MoreFiles 1.5.
35*/
36
37#include <MacTypes.h>
38#include <MacErrors.h>
39#include <MacMemory.h>
40#include <Files.h>
41#include <TextUtils.h>
42#include <Aliases.h>
43
44#define	__COMPILINGMOREFILES
45
46#include "FSpCompat.h"
47#include "FullPath.h"
48
49/*
50	IMPORTANT NOTE:
51
52	The use of full pathnames is strongly discouraged. Full pathnames are
53	particularly unreliable as a means of identifying files, directories
54	or volumes within your application, for two primary reasons:
55
56	� 	The user can change the name of any element in the path at virtually
57		any time.
58	�	Volume names on the Macintosh are *not* unique. Multiple
59		mounted volumes can have the same name. For this reason, the use of
60		a full pathname to identify a specific volume may not produce the
61		results you expect. If more than one volume has the same name and
62		a full pathname is used, the File Manager currently uses the first
63		mounted volume it finds with a matching name in the volume queue.
64
65	In general, you should use a file�s name, parent directory ID, and
66	volume reference number to identify a file you want to open, delete,
67	or otherwise manipulate.
68
69	If you need to remember the location of a particular file across
70	subsequent system boots, use the Alias Manager to create an alias record
71	describing the file. If the Alias Manager is not available, you can save
72	the file�s name, its parent directory ID, and the name of the volume on
73	which it�s located. Although none of these methods is foolproof, they are
74	much more reliable than using full pathnames to identify files.
75
76	Nonetheless, it is sometimes useful to display a file�s full pathname to
77	the user. For example, a backup utility might display a list of full
78	pathnames of files as it copies them onto the backup medium. Or, a
79	utility might want to display a dialog box showing the full pathname of
80	a file when it needs the user�s confirmation to delete the file. No
81	matter how unreliable full pathnames may be from a file-specification
82	viewpoint, users understand them more readily than volume reference
83	numbers or directory IDs. (Hint: Use the TruncString function from
84	TextUtils.h with truncMiddle as the truncWhere argument to shorten
85	full pathnames to a displayable length.)
86
87	The following technique for constructing the full pathname of a file is
88	intended for display purposes only. Applications that depend on any
89	particular structure of a full pathname are likely to fail on alternate
90	foreign file systems or under future system software versions.
91*/
92
93/*****************************************************************************/
94
95pascal	OSErr	GetFullPath(short vRefNum,
96							long dirID,
97							ConstStr255Param name,
98							short *fullPathLength,
99							Handle *fullPath)
100{
101	OSErr		result;
102	FSSpec		spec;
103
104	*fullPathLength = 0;
105	*fullPath = NULL;
106
107	result = FSMakeFSSpecCompat(vRefNum, dirID, name, &spec);
108	if ( (result == noErr) || (result == fnfErr) )
109	{
110		result = FSpGetFullPath(&spec, fullPathLength, fullPath);
111	}
112
113	return ( result );
114}
115
116/*****************************************************************************/
117
118pascal	OSErr	FSpGetFullPath(const FSSpec *spec,
119							   short *fullPathLength,
120							   Handle *fullPath)
121{
122	OSErr		result;
123	OSErr		realResult;
124	FSSpec		tempSpec;
125	CInfoPBRec	pb;
126
127	*fullPathLength = 0;
128	*fullPath = NULL;
129
130
131	/* Default to noErr */
132	realResult = result = noErr;
133
134	/* work around Nav Services "bug" (it returns invalid FSSpecs with empty names) */
135	if ( spec->name[0] == 0 )
136	{
137		result = FSMakeFSSpecCompat(spec->vRefNum, spec->parID, spec->name, &tempSpec);
138	}
139	else
140	{
141		/* Make a copy of the input FSSpec that can be modified */
142		BlockMoveData(spec, &tempSpec, sizeof(FSSpec));
143	}
144
145	if ( result == noErr )
146	{
147		if ( tempSpec.parID == fsRtParID )
148		{
149			/* The object is a volume */
150
151			/* Add a colon to make it a full pathname */
152			++tempSpec.name[0];
153			tempSpec.name[tempSpec.name[0]] = ':';
154
155			/* We're done */
156			result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
157		}
158		else
159		{
160			/* The object isn't a volume */
161
162			/* Is the object a file or a directory? */
163			pb.dirInfo.ioNamePtr = tempSpec.name;
164			pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
165			pb.dirInfo.ioDrDirID = tempSpec.parID;
166			pb.dirInfo.ioFDirIndex = 0;
167			result = PBGetCatInfoSync(&pb);
168			// Allow file/directory name at end of path to not exist.
169			realResult = result;
170			if ( (result == noErr) || (result == fnfErr) )
171			{
172				/* if the object is a directory, append a colon so full pathname ends with colon */
173				if ( (result == noErr) && (pb.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 )
174				{
175					++tempSpec.name[0];
176					tempSpec.name[tempSpec.name[0]] = ':';
177				}
178
179				/* Put the object name in first */
180				result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
181				if ( result == noErr )
182				{
183					/* Get the ancestor directory names */
184					pb.dirInfo.ioNamePtr = tempSpec.name;
185					pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
186					pb.dirInfo.ioDrParID = tempSpec.parID;
187					do	/* loop until we have an error or find the root directory */
188					{
189						pb.dirInfo.ioFDirIndex = -1;
190						pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
191						result = PBGetCatInfoSync(&pb);
192						if ( result == noErr )
193						{
194							/* Append colon to directory name */
195							++tempSpec.name[0];
196							tempSpec.name[tempSpec.name[0]] = ':';
197
198							/* Add directory name to beginning of fullPath */
199							(void) Munger(*fullPath, 0, NULL, 0, &tempSpec.name[1], tempSpec.name[0]);
200							result = MemError();
201						}
202					} while ( (result == noErr) && (pb.dirInfo.ioDrDirID != fsRtDirID) );
203				}
204			}
205		}
206	}
207
208	if ( result == noErr )
209	{
210		/* Return the length */
211		*fullPathLength = GetHandleSize(*fullPath);
212		result = realResult;	// return realResult in case it was fnfErr
213	}
214	else
215	{
216		/* Dispose of the handle and return NULL and zero length */
217		if ( *fullPath != NULL )
218		{
219			DisposeHandle(*fullPath);
220		}
221		*fullPath = NULL;
222		*fullPathLength = 0;
223	}
224
225	return ( result );
226}
227
228/*****************************************************************************/
229
230pascal OSErr FSpLocationFromFullPath(short fullPathLength,
231									 const void *fullPath,
232									 FSSpec *spec)
233{
234	AliasHandle	alias;
235	OSErr		result;
236	Boolean		wasChanged;
237	Str32		nullString;
238
239	/* Create a minimal alias from the full pathname */
240	nullString[0] = 0;	/* null string to indicate no zone or server name */
241	result = NewAliasMinimalFromFullPath(fullPathLength, fullPath, nullString, nullString, &alias);
242	if ( result == noErr )
243	{
244		/* Let the Alias Manager resolve the alias. */
245		result = ResolveAlias(NULL, alias, spec, &wasChanged);
246
247		/* work around Alias Mgr sloppy volume matching bug */
248		if ( spec->vRefNum == 0 )
249		{
250			/* invalidate wrong FSSpec */
251			spec->parID = 0;
252			spec->name[0] =  0;
253			result = nsvErr;
254		}
255		DisposeHandle((Handle)alias);	/* Free up memory used */
256	}
257	return ( result );
258}
259
260/*****************************************************************************/
261
262pascal OSErr LocationFromFullPath(short fullPathLength,
263								  const void *fullPath,
264								  short *vRefNum,
265								  long *parID,
266								  Str31 name)
267{
268	OSErr	result;
269	FSSpec	spec;
270
271	result = FSpLocationFromFullPath(fullPathLength, fullPath, &spec);
272	if ( result == noErr )
273	{
274		*vRefNum = spec.vRefNum;
275		*parID = spec.parID;
276		BlockMoveData(&spec.name[0], &name[0], spec.name[0] + 1);
277	}
278	return ( result );
279}
280
281/*****************************************************************************/
282
283