• 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:		FSpCompat.c
3
4	Contains:	FSSpec compatibility functions.
5
6	Version:	MoreFiles
7
8	Copyright:	� 1992-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. Updated
34									various routines to use new calling convention of the
35									MoreFilesExtras accessor functions.
36		<1>		12/06/99	JL		MoreFiles 1.5.
37*/
38
39/*
40**	If building application 68K code, set GENERATENODATA to 0 for faster code.
41**	If building stand-alone 68K code, set GENERATENODATA to 1 so globals
42**		(static variables) are not used.
43*/
44#ifndef GENERATENODATA
45#define GENERATENODATA 0
46#endif
47
48#include <MacTypes.h>
49#include <MacErrors.h>
50#include <Files.h>
51#include <LowMem.h>
52#include <Gestalt.h>
53#include <Resources.h>
54#include <Script.h>
55
56#define	__COMPILINGMOREFILES
57
58#include "MoreFilesExtras.h"
59#include "FSpCompat.h"
60
61/*****************************************************************************/
62
63/* local constants */
64
65enum {
66	gestaltBugFixAttrsTwo					= 'bugy',
67	gestaltFSpExchangeFilesCompatibilityFix	= 26,
68	gestaltBugFixAttrsThree					= 'bugx',
69	gestaltFSpCreateScriptSupportFix		= 1
70};
71
72/*****************************************************************************/
73
74/* static prototypes */
75
76
77#if !__MACOSSEVENORLATER
78static	Boolean	FSHasFSSpecCalls(void);
79
80static	Boolean	QTHasFSSpecCalls(void);
81#endif	/* !__MACOSSEVENORLATER */
82
83#if !__MACOSSEVENFIVEORLATER
84static	Boolean	HasFSpExchangeFilesCompatibilityFix(void);
85
86static	OSErr	GenerateUniqueName(short volume,
87								   long *startSeed,
88								   long dir1,
89								   long dir2,
90								   StringPtr uniqueName);
91#endif	/* !__MACOSSEVENFIVEORLATER */
92
93#if !__MACOSSEVENFIVEONEORLATER
94static	Boolean	HasFSpCreateScriptSupportFix(void);
95#endif	/* !__MACOSSEVENFIVEONEORLATER */
96
97/*****************************************************************************/
98
99/* FSHasFSSpecCalls returns true if the file system provides FSSpec calls. */
100
101#if !__MACOSSEVENORLATER
102static	Boolean	FSHasFSSpecCalls(void)
103{
104	long			response;
105#if !GENERATENODATA
106	static Boolean	tested = false;
107	static Boolean	result = false;
108#else
109	Boolean	result = false;
110#endif
111
112#if !GENERATENODATA
113	if ( !tested )
114	{
115		tested = true;
116#endif
117		if ( Gestalt(gestaltFSAttr, &response) == noErr )
118		{
119			result = ((response & (1L << gestaltHasFSSpecCalls)) != 0);
120		}
121#if !GENERATENODATA
122	}
123#endif
124	return ( result );
125}
126#endif	/* !__MACOSSEVENORLATER */
127
128/*****************************************************************************/
129
130/* QTHasFSSpecCalls returns true if QuickTime provides FSSpec calls */
131/* except for FSpExchangeFiles. */
132
133#if !__MACOSSEVENORLATER
134static	Boolean	QTHasFSSpecCalls(void)
135{
136	long			response;
137#if !GENERATENODATA
138	static Boolean	tested = false;
139	static Boolean	result = false;
140#else
141	Boolean	result = false;
142#endif
143
144#if !GENERATENODATA
145	if ( !tested )
146	{
147		tested = true;
148#endif
149		result = (Gestalt(gestaltQuickTimeVersion, &response) == noErr);
150#if !GENERATENODATA
151	}
152#endif
153	return ( result );
154}
155#endif	/* !__MACOSSEVENORLATER */
156
157/*****************************************************************************/
158
159/* HasFSpExchangeFilesCompatibilityFix returns true if FSpExchangeFiles */
160/* compatibility code has been fixed in system software. */
161/* This was fixed by System Update 3.0, so if SystemSevenFiveOrLater */
162/* is true, then we know the fix is in. */
163
164#if !__MACOSSEVENFIVEORLATER
165static	Boolean	HasFSpExchangeFilesCompatibilityFix(void)
166{
167	long			response;
168#if !GENERATENODATA
169	static Boolean	tested = false;
170	static Boolean	result = false;
171#else	/* !GENERATENODATA */
172	Boolean	result = false;
173#endif	/* !GENERATENODATA */
174
175#if !GENERATENODATA
176	if ( !tested )
177	{
178		tested = true;
179#endif	/* !GENERATENODATA */
180		if ( Gestalt(gestaltBugFixAttrsTwo, &response) == noErr )
181		{
182			result = ((response & (1L << gestaltFSpExchangeFilesCompatibilityFix)) != 0);
183		}
184#if !GENERATENODATA
185	}
186#endif	/* !GENERATENODATA */
187	return ( result );
188}
189#endif	/* !__MACOSSEVENFIVEORLATER */
190
191/*****************************************************************************/
192
193/* HasFSpCreateScriptSupportFix returns true if FSpCreate and */
194/* FSpCreateResFile have been fixed in system software to correctly set */
195/* the scriptCode in the volume's catalog. */
196/* This was fixed by System 7.5 Update 1.0 */
197
198#if !__MACOSSEVENFIVEONEORLATER
199static	Boolean	HasFSpCreateScriptSupportFix(void)
200{
201	long			response;
202#if !GENERATENODATA
203	static Boolean	tested = false;
204	static Boolean	result = false;
205#else
206	Boolean	result = false;
207#endif	/* !GENERATENODATA */
208
209#if !GENERATENODATA
210	if ( !tested )
211	{
212		tested = true;
213#endif	/* !GENERATENODATA */
214		if ( Gestalt(gestaltBugFixAttrsThree, &response) == noErr )
215		{
216			result = ((response & (1L << gestaltFSpCreateScriptSupportFix)) != 0);
217		}
218#if !GENERATENODATA
219	}
220#endif	/* !GENERATENODATA */
221	return ( result );
222}
223#endif	/* !__MACOSSEVENFIVEONEORLATER */
224
225/*****************************************************************************/
226
227/*
228**	File Manager FSp calls
229*/
230
231/*****************************************************************************/
232
233pascal	OSErr	FSMakeFSSpecCompat(short vRefNum,
234								   long dirID,
235								   ConstStr255Param fileName,
236								   FSSpec *spec)
237{
238	OSErr	result;
239
240#if !__MACOSSEVENORLATER
241	if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
242	{
243		Boolean	isDirectory;
244
245		result = GetObjectLocation(vRefNum, dirID, fileName,
246									&(spec->vRefNum), &(spec->parID), spec->name,
247									&isDirectory);
248	}
249	else
250#endif	/* !__MACOSSEVENORLATER */
251	{
252		/* Let the file system create the FSSpec if it can since it does the job */
253		/* much more efficiently than I can. */
254		result = FSMakeFSSpec(vRefNum, dirID, fileName, spec);
255
256		/* Fix a bug in Macintosh PC Exchange's MakeFSSpec code where 0 is */
257		/* returned in the parID field when making an FSSpec to the volume's */
258		/* root directory by passing a full pathname in MakeFSSpec's */
259		/* fileName parameter. Fixed in Mac OS 8.1 */
260		if ( (result == noErr) && (spec->parID == 0) )
261			spec->parID = fsRtParID;
262	}
263	return ( result );
264}
265
266/*****************************************************************************/
267
268pascal	OSErr	FSpOpenDFCompat(const FSSpec *spec,
269								char permission,
270								short *refNum)
271{
272#if !__MACOSSEVENORLATER
273	if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
274	{
275		OSErr			result;
276		HParamBlockRec	pb;
277
278		pb.ioParam.ioVRefNum = spec->vRefNum;
279		pb.fileParam.ioDirID = spec->parID;
280		pb.ioParam.ioNamePtr = (StringPtr) &(spec->name);
281		pb.ioParam.ioVersNum = 0;
282		pb.ioParam.ioPermssn = permission;
283		pb.ioParam.ioMisc = NULL;
284		result = PBHOpenSync(&pb);	/* OpenDF not supported by System 6, so use Open */
285		*refNum = pb.ioParam.ioRefNum;
286		return ( result );
287	}
288	else
289#endif	/* !__MACOSSEVENORLATER */
290	{
291		return ( FSpOpenDF(spec, permission, refNum) );
292	}
293}
294
295/*****************************************************************************/
296
297pascal	OSErr	FSpOpenRFCompat(const FSSpec *spec,
298								char permission,
299								short *refNum)
300{
301#if !__MACOSSEVENORLATER
302	if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
303	{
304		OSErr			result;
305		HParamBlockRec	pb;
306
307		pb.ioParam.ioVRefNum = spec->vRefNum;
308		pb.fileParam.ioDirID = spec->parID;
309		pb.ioParam.ioNamePtr = (StringPtr) &(spec->name);
310		pb.ioParam.ioVersNum = 0;
311		pb.ioParam.ioPermssn = permission;
312		pb.ioParam.ioMisc = NULL;
313		result = PBHOpenRFSync(&pb);
314		*refNum = pb.ioParam.ioRefNum;
315		return ( result );
316	}
317	else
318#endif	/* !__MACOSSEVENORLATER */
319	{
320		return ( FSpOpenRF(spec, permission, refNum) );
321	}
322}
323
324/*****************************************************************************/
325
326pascal	OSErr	FSpCreateCompat(const FSSpec *spec,
327								OSType creator,
328								OSType fileType,
329								ScriptCode scriptTag)
330{
331#if !__MACOSSEVENFIVEONEORLATER
332	OSErr			result;
333	UniversalFMPB	pb;
334
335
336	if (
337#if !__MACOSSEVENORLATER
338		 (!FSHasFSSpecCalls() && !QTHasFSSpecCalls()) ||
339#endif	/* !__MACOSSEVENORLATER */
340		 !HasFSpCreateScriptSupportFix() )
341	{
342		/*	If FSpCreate isn't called, this code will be executed */
343		pb.hPB.fileParam.ioVRefNum = spec->vRefNum;
344		pb.hPB.fileParam.ioDirID = spec->parID;
345		pb.hPB.fileParam.ioNamePtr = (StringPtr) &(spec->name);
346		pb.hPB.fileParam.ioFVersNum = 0;
347		result = PBHCreateSync(&(pb.hPB));
348		if ( result == noErr )
349		{
350			/* get info on created item */
351			pb.ciPB.hFileInfo.ioFDirIndex = 0;
352			result = PBGetCatInfoSync(&(pb.ciPB));
353			if ( result == noErr )
354			{
355				/* Set fdScript in FXInfo */
356				/* The negative script constants (smSystemScript, smCurrentScript, and smAllScripts) */
357				/* don't make sense on disk, so only use scriptTag if scriptTag >= smRoman */
358				/* (smRoman is 0). fdScript is valid if high bit is set (see IM-6, page 9-38) */
359				pb.ciPB.hFileInfo.ioFlXFndrInfo.fdScript = (scriptTag >= smRoman) ?
360															((char)scriptTag | (char)0x80) :
361															(smRoman);
362				/* Set creator/fileType */
363				pb.ciPB.hFileInfo.ioFlFndrInfo.fdCreator = creator;
364				pb.ciPB.hFileInfo.ioFlFndrInfo.fdType = fileType;
365				/* Restore ioDirID field in pb which was changed by PBGetCatInfo */
366				pb.ciPB.hFileInfo.ioDirID = spec->parID;
367				result = PBSetCatInfoSync(&(pb.ciPB));
368			}
369		}
370		return ( result );
371	}
372	else
373#endif	/* !__MACOSSEVENFIVEONEORLATER */
374	{
375		return ( FSpCreate(spec, creator, fileType, scriptTag) );
376	}
377}
378
379/*****************************************************************************/
380
381pascal	OSErr	FSpDirCreateCompat(const FSSpec *spec,
382								   ScriptCode scriptTag,
383								   long *createdDirID)
384{
385#if !__MACOSSEVENORLATER
386	if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
387	{
388		OSErr			result;
389		UniversalFMPB	pb;
390
391		pb.hPB.fileParam.ioVRefNum = spec->vRefNum;
392		pb.hPB.fileParam.ioDirID = spec->parID;
393		pb.hPB.fileParam.ioNamePtr = (StringPtr) &(spec->name);
394		result = PBDirCreateSync(&(pb.hPB));
395		*createdDirID = pb.hPB.fileParam.ioDirID;
396		if ( result == noErr )
397		{
398			/* get info on created item */
399			pb.ciPB.dirInfo.ioFDirIndex = 0;
400			pb.ciPB.dirInfo.ioDrDirID = spec->parID;
401			result = PBGetCatInfoSync(&(pb.ciPB));
402			if ( result == noErr )
403			{
404				/* Set frScript in DXInfo */
405				/* The negative script constants (smSystemScript, smCurrentScript, and smAllScripts) */
406				/* don't make sense on disk, so only use scriptTag if scriptTag >= smRoman */
407				/* (smRoman is 0). frScript is valid if high bit is set (see IM-6, page 9-38) */
408				pb.ciPB.dirInfo.ioDrFndrInfo.frScript = (scriptTag >= smRoman) ?
409															((char)scriptTag | (char)0x80) :
410															(smRoman);
411				/* Restore ioDirID field in pb which was changed by PBGetCatInfo */
412				pb.ciPB.dirInfo.ioDrDirID = spec->parID;
413				result = PBSetCatInfoSync(&(pb.ciPB));
414			}
415		}
416		return ( result );
417	}
418	else
419#endif	/* !__MACOSSEVENORLATER */
420	{
421		return ( FSpDirCreate(spec, scriptTag, createdDirID) );
422	}
423}
424
425/*****************************************************************************/
426
427pascal	OSErr	FSpDeleteCompat(const FSSpec *spec)
428{
429#if !__MACOSSEVENORLATER
430	if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
431	{
432		HParamBlockRec	pb;
433
434		pb.ioParam.ioVRefNum = spec->vRefNum;
435		pb.fileParam.ioDirID = spec->parID;
436		pb.ioParam.ioNamePtr = (StringPtr) &(spec->name);
437		pb.ioParam.ioVersNum = 0;
438		return ( PBHDeleteSync(&pb) );
439	}
440	else
441#endif	/* !__MACOSSEVENORLATER */
442	{
443		return ( FSpDelete(spec) );
444	}
445}
446
447/*****************************************************************************/
448
449pascal	OSErr	FSpGetFInfoCompat(const FSSpec *spec,
450								  FInfo *fndrInfo)
451{
452#if !__MACOSSEVENORLATER
453	if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
454	{
455		OSErr			result;
456		HParamBlockRec	pb;
457
458		pb.fileParam.ioVRefNum = spec->vRefNum;
459		pb.fileParam.ioDirID = spec->parID;
460		pb.fileParam.ioNamePtr = (StringPtr) &(spec->name);
461		pb.fileParam.ioFVersNum = 0;
462		pb.fileParam.ioFDirIndex = 0;
463		result = PBHGetFInfoSync(&pb);
464		*fndrInfo = pb.fileParam.ioFlFndrInfo;
465		return ( result );
466	}
467	else
468#endif	/* !__MACOSSEVENORLATER */
469	{
470		return ( FSpGetFInfo(spec, fndrInfo) );
471	}
472}
473
474/*****************************************************************************/
475
476pascal	OSErr	FSpSetFInfoCompat(const FSSpec *spec,
477								  const FInfo *fndrInfo)
478{
479#if !__MACOSSEVENORLATER
480	if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
481	{
482		OSErr			result;
483		HParamBlockRec	pb;
484
485		pb.fileParam.ioVRefNum = spec->vRefNum;
486		pb.fileParam.ioDirID = spec->parID;
487		pb.fileParam.ioNamePtr = (StringPtr) &(spec->name);
488		pb.fileParam.ioFVersNum = 0;
489		pb.fileParam.ioFDirIndex = 0;
490		result = PBHGetFInfoSync(&pb);
491		if ( result == noErr )
492		{
493			pb.fileParam.ioFlFndrInfo = *fndrInfo;
494			pb.fileParam.ioDirID = spec->parID;
495			result = PBHSetFInfoSync(&pb);
496		}
497		return ( result );
498	}
499	else
500#endif	/* !__MACOSSEVENORLATER */
501	{
502		return ( FSpSetFInfo(spec, fndrInfo) );
503	}
504}
505
506/*****************************************************************************/
507
508pascal	OSErr	FSpSetFLockCompat(const FSSpec *spec)
509{
510#if !__MACOSSEVENORLATER
511	if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
512	{
513		HParamBlockRec	pb;
514
515		pb.fileParam.ioVRefNum = spec->vRefNum;
516		pb.fileParam.ioDirID = spec->parID;
517		pb.fileParam.ioNamePtr = (StringPtr) &(spec->name);
518		pb.fileParam.ioFVersNum = 0;
519		return ( PBHSetFLockSync(&pb) );
520	}
521	else
522#endif	/* !__MACOSSEVENORLATER */
523	{
524		return ( FSpSetFLock(spec) );
525	}
526}
527
528/*****************************************************************************/
529
530pascal	OSErr	FSpRstFLockCompat(const FSSpec *spec)
531{
532#if !__MACOSSEVENORLATER
533	if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
534	{
535		HParamBlockRec	pb;
536
537		pb.fileParam.ioVRefNum = spec->vRefNum;
538		pb.fileParam.ioDirID = spec->parID;
539		pb.fileParam.ioNamePtr = (StringPtr) &(spec->name);
540		pb.fileParam.ioFVersNum = 0;
541		return ( PBHRstFLockSync(&pb) );
542	}
543	else
544#endif	/* !__MACOSSEVENORLATER */
545	{
546		return ( FSpRstFLock(spec) );
547	}
548}
549
550/*****************************************************************************/
551
552pascal	OSErr	FSpRenameCompat(const FSSpec *spec,
553								ConstStr255Param newName)
554{
555#if !__MACOSSEVENORLATER
556	if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
557	{
558		HParamBlockRec	pb;
559
560		pb.ioParam.ioVRefNum = spec->vRefNum;
561		pb.fileParam.ioDirID = spec->parID;
562		pb.ioParam.ioNamePtr = (StringPtr) &(spec->name);
563		pb.ioParam.ioVersNum = 0;
564		pb.ioParam.ioMisc = (Ptr) newName;
565		return ( PBHRenameSync(&pb) );
566	}
567	else
568#endif	/* !__MACOSSEVENORLATER */
569	{
570		return ( FSpRename(spec, newName) );
571	}
572}
573
574/*****************************************************************************/
575
576pascal	OSErr	FSpCatMoveCompat(const FSSpec *source,
577								 const FSSpec *dest)
578{
579#if !__MACOSSEVENORLATER
580	if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
581	{
582		CMovePBRec	pb;
583
584		/* source and destination volume must be the same */
585		if ( source->vRefNum != dest->vRefNum )
586			return ( paramErr );
587
588		pb.ioNamePtr = (StringPtr) &(source->name);
589		pb.ioVRefNum = source->vRefNum;
590		pb.ioDirID = source->parID;
591		pb.ioNewDirID = dest->parID;
592		pb.ioNewName = (StringPtr) &(dest->name);
593		return ( PBCatMoveSync(&pb) );
594	}
595	else
596#endif	/* !__MACOSSEVENORLATER */
597	{
598		return ( FSpCatMove(source, dest) );
599	}
600}
601
602/*****************************************************************************/
603
604/* GenerateUniqueName generates a name that is unique in both dir1 and dir2 */
605/* on the specified volume. Ripped off from Feldman's code. */
606
607#if !__MACOSSEVENFIVEORLATER
608static	OSErr	GenerateUniqueName(short volume,
609								   long *startSeed,
610								   long dir1,
611								   long dir2,
612								   StringPtr uniqueName)
613{
614	OSErr			error = noErr;
615	long			i;
616	CInfoPBRec		cinfo;
617	unsigned char	hexStr[16];
618
619	for ( i = 0; i < 16; ++i )
620	{
621		if ( i < 10 )
622		{
623			hexStr[i] = 0x30 + i;
624		}
625		else
626		{
627			hexStr[i] = 0x37 + i;
628		}
629	}
630
631	cinfo.hFileInfo.ioVRefNum = volume;
632	cinfo.hFileInfo.ioFDirIndex = 0;
633	cinfo.hFileInfo.ioNamePtr = uniqueName;
634
635	while ( error != fnfErr )
636	{
637		(*startSeed)++;
638		cinfo.hFileInfo.ioNamePtr[0] = 8;
639		for ( i = 1; i <= 8; i++ )
640		{
641			cinfo.hFileInfo.ioNamePtr[i] = hexStr[((*startSeed >> ((8-i)*4)) & 0xf)];
642		}
643		cinfo.hFileInfo.ioDirID = dir1;
644		error = fnfErr;
645		for ( i = 1; i <= 2; i++ )
646		{
647			error = error & PBGetCatInfoSync(&cinfo);
648			cinfo.hFileInfo.ioDirID = dir2;
649			if ( (error != fnfErr) && (error != noErr) )
650			{
651				return ( error );
652			}
653		}
654	}
655	return ( noErr );
656}
657#endif	/* !__MACOSSEVENFIVEORLATER */
658
659/*****************************************************************************/
660
661pascal	OSErr	FSpExchangeFilesCompat(const FSSpec *source,
662									   const FSSpec *dest)
663{
664#if !__MACOSSEVENFIVEORLATER
665	if (
666#if !__MACOSSEVENORLATER
667		 !FSHasFSSpecCalls() ||
668#endif	/* !__MACOSSEVENORLATER */
669		 !HasFSpExchangeFilesCompatibilityFix() )
670	{
671		HParamBlockRec			pb;
672		CInfoPBRec				catInfoSource, catInfoDest;
673		OSErr					result, result2;
674		Str31					unique1, unique2;
675		StringPtr				unique1Ptr, unique2Ptr, swapola;
676		GetVolParmsInfoBuffer	volInfo;
677		long					theSeed, temp;
678
679		/* Make sure the source and destination are on the same volume */
680		if ( source->vRefNum != dest->vRefNum )
681		{
682			result = diffVolErr;
683			goto errorExit3;
684		}
685
686		/* Try PBExchangeFiles first since it preserves the file ID reference */
687		pb.fidParam.ioNamePtr = (StringPtr) &(source->name);
688		pb.fidParam.ioVRefNum = source->vRefNum;
689		pb.fidParam.ioDestNamePtr = (StringPtr) &(dest->name);
690		pb.fidParam.ioDestDirID = dest->parID;
691		pb.fidParam.ioSrcDirID = source->parID;
692
693		result = PBExchangeFilesSync(&pb);
694
695		/* Note: The compatibility case won't work for files with *Btree control blocks. */
696		/* Right now the only *Btree files are created by the system. */
697		if ( result != noErr )
698		{
699			pb.ioParam.ioNamePtr = NULL;
700			pb.ioParam.ioBuffer = (Ptr) &volInfo;
701			pb.ioParam.ioReqCount = sizeof(volInfo);
702			result2 = PBHGetVolParmsSync(&pb);
703
704			/* continue if volume has no fileID support (or no GetVolParms support) */
705			if ( (result2 == noErr) && hasFileIDs(&volInfo) )
706			{
707				goto errorExit3;
708			}
709
710			/* Get the catalog information for each file */
711			/* and make sure both files are *really* files */
712			catInfoSource.hFileInfo.ioVRefNum = source->vRefNum;
713			catInfoSource.hFileInfo.ioFDirIndex = 0;
714			catInfoSource.hFileInfo.ioNamePtr = (StringPtr) &(source->name);
715			catInfoSource.hFileInfo.ioDirID = source->parID;
716			catInfoSource.hFileInfo.ioACUser = 0; /* ioACUser used to be filler2 */
717			result = PBGetCatInfoSync(&catInfoSource);
718			if ( result != noErr )
719			{
720				goto errorExit3;
721			}
722			if ( (catInfoSource.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 )
723			{
724				result = notAFileErr;
725				goto errorExit3;
726			}
727
728			catInfoDest.hFileInfo.ioVRefNum = dest->vRefNum;
729			catInfoDest.hFileInfo.ioFDirIndex = 0;
730			catInfoDest.hFileInfo.ioNamePtr = (StringPtr) &(dest->name);
731			catInfoDest.hFileInfo.ioDirID = dest->parID;
732			catInfoDest.hFileInfo.ioACUser = 0; /* ioACUser used to be filler2 */
733			result = PBGetCatInfoSync(&catInfoDest);
734			if ( result != noErr )
735			{
736				goto errorExit3;
737			}
738			if ( (catInfoDest.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 )
739			{
740				result = notAFileErr;
741				goto errorExit3;
742			}
743
744			/* generate 2 filenames that are unique in both directories */
745			theSeed = 0x64666A6C;	/* a fine unlikely filename */
746			unique1Ptr = (StringPtr)&unique1;
747			unique2Ptr = (StringPtr)&unique2;
748
749			result = GenerateUniqueName(source->vRefNum, &theSeed, source->parID, dest->parID, unique1Ptr);
750			if ( result != noErr )
751			{
752				goto errorExit3;
753			}
754
755			GenerateUniqueName(source->vRefNum, &theSeed, source->parID, dest->parID, unique2Ptr);
756			if ( result != noErr )
757			{
758				goto errorExit3;
759			}
760
761			/* rename source to unique1 */
762			pb.fileParam.ioNamePtr = (StringPtr) &(source->name);
763			pb.ioParam.ioMisc = (Ptr) unique1Ptr;
764			pb.ioParam.ioVersNum = 0;
765			result = PBHRenameSync(&pb);
766			if ( result != noErr )
767			{
768				goto errorExit3;
769			}
770
771			/* rename dest to unique2 */
772			pb.ioParam.ioMisc = (Ptr) unique2Ptr;
773			pb.ioParam.ioVersNum = 0;
774			pb.fileParam.ioNamePtr = (StringPtr) &(dest->name);
775			pb.fileParam.ioDirID = dest->parID;
776			result = PBHRenameSync(&pb);
777			if ( result != noErr )
778			{
779				goto errorExit2;	/* back out gracefully by renaming unique1 back to source */
780			}
781
782			/* If files are not in same directory, swap their locations */
783			if ( source->parID != dest->parID )
784			{
785				/* move source file to dest directory */
786				pb.copyParam.ioNamePtr = unique1Ptr;
787				pb.copyParam.ioNewName = NULL;
788				pb.copyParam.ioNewDirID = dest->parID;
789				pb.copyParam.ioDirID = source->parID;
790				result = PBCatMoveSync((CMovePBPtr) &pb);
791				if ( result != noErr )
792				{
793					goto errorExit1;	/* back out gracefully by renaming both files to original names */
794				}
795
796				/* move dest file to source directory */
797				pb.copyParam.ioNamePtr = unique2Ptr;
798				pb.copyParam.ioNewDirID = source->parID;
799				pb.copyParam.ioDirID = dest->parID;
800				result = PBCatMoveSync((CMovePBPtr) &pb);
801				if ( result != noErr)
802				{
803					/* life is very bad.  We'll at least try to move source back */
804					pb.copyParam.ioNamePtr = unique1Ptr;
805					pb.copyParam.ioNewName = NULL;
806					pb.copyParam.ioNewDirID = source->parID;
807					pb.copyParam.ioDirID = dest->parID;
808					(void) PBCatMoveSync((CMovePBPtr) &pb);	/* ignore errors */
809					goto errorExit1;	/* back out gracefully by renaming both files to original names */
810				}
811			}
812
813			/* Make unique1Ptr point to file in source->parID */
814			/* and unique2Ptr point to file in dest->parID */
815			/* This lets us fall through to the rename code below */
816			swapola = unique1Ptr;
817			unique1Ptr = unique2Ptr;
818			unique2Ptr = swapola;
819
820			/* At this point, the files are in their new locations (if they were moved) */
821			/* Source is named Unique1 (name pointed to by unique2Ptr) and is in dest->parID */
822			/* Dest is named Unique2 (name pointed to by unique1Ptr) and is in source->parID */
823			/* Need to swap attributes except mod date and swap names */
824
825			/* swap the catalog info by re-aiming the CInfoPB's */
826			catInfoSource.hFileInfo.ioNamePtr = unique1Ptr;
827			catInfoDest.hFileInfo.ioNamePtr = unique2Ptr;
828
829			catInfoSource.hFileInfo.ioDirID = source->parID;
830			catInfoDest.hFileInfo.ioDirID = dest->parID;
831
832			/* Swap the original mod dates with each file */
833			temp = catInfoSource.hFileInfo.ioFlMdDat;
834			catInfoSource.hFileInfo.ioFlMdDat = catInfoDest.hFileInfo.ioFlMdDat;
835			catInfoDest.hFileInfo.ioFlMdDat = temp;
836
837			/* Here's the swap (ignore errors) */
838			(void) PBSetCatInfoSync(&catInfoSource);
839			(void) PBSetCatInfoSync(&catInfoDest);
840
841			/* rename unique2 back to dest */
842errorExit1:
843			pb.ioParam.ioMisc = (Ptr) &(dest->name);
844			pb.ioParam.ioVersNum = 0;
845			pb.fileParam.ioNamePtr = unique2Ptr;
846			pb.fileParam.ioDirID = dest->parID;
847			(void) PBHRenameSync(&pb);	/* ignore errors */
848
849			/* rename unique1 back to source */
850errorExit2:
851			pb.ioParam.ioMisc = (Ptr) &(source->name);
852			pb.ioParam.ioVersNum = 0;
853			pb.fileParam.ioNamePtr = unique1Ptr;
854			pb.fileParam.ioDirID = source->parID;
855			(void) PBHRenameSync(&pb); /* ignore errors */
856		}
857errorExit3: { /* null statement */ }
858		return ( result );
859	}
860	else
861#endif	/* !__MACOSSEVENFIVEORLATER */
862	{
863		return ( FSpExchangeFiles(source, dest) );
864	}
865}
866
867/*****************************************************************************/
868
869/*
870**	Resource Manager FSp calls
871*/
872
873/*****************************************************************************/
874
875pascal	short	FSpOpenResFileCompat(const FSSpec *spec,
876									 SignedByte permission)
877{
878#if !__MACOSSEVENORLATER
879	if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
880	{
881		return ( HOpenResFile(spec->vRefNum, spec->parID, spec->name, permission) );
882	}
883	else
884#endif	/* !__MACOSSEVENORLATER */
885	{
886		return ( FSpOpenResFile(spec, permission) );
887	}
888}
889
890/*****************************************************************************/
891
892pascal	void	FSpCreateResFileCompat(const FSSpec *spec,
893									   OSType creator,
894									   OSType fileType,
895									   ScriptCode scriptTag)
896{
897#if !__MACOSSEVENFIVEONEORLATER
898	if (
899#if !__MACOSSEVENORLATER
900		 (!FSHasFSSpecCalls() && !QTHasFSSpecCalls()) ||
901#endif	/* !__MACOSSEVENORLATER */
902		 !HasFSpCreateScriptSupportFix() )
903	{
904		OSErr			result;
905		CInfoPBRec		pb;
906
907		HCreateResFile(spec->vRefNum, spec->parID, spec->name);
908		if ( ResError() == noErr )
909		{
910			/* get info on created item */
911			pb.hFileInfo.ioVRefNum = spec->vRefNum;
912			pb.hFileInfo.ioDirID = spec->parID;
913			pb.hFileInfo.ioNamePtr = (StringPtr) &(spec->name);
914			pb.hFileInfo.ioFDirIndex = 0;
915			result = PBGetCatInfoSync(&pb);
916			if ( result == noErr )
917			{
918				/* Set fdScript in FXInfo */
919				/* The negative script constants (smSystemScript, smCurrentScript, and smAllScripts) */
920				/* don't make sense on disk, so only use scriptTag if scriptTag >= smRoman */
921				/* (smRoman is 0). fdScript is valid if high bit is set (see IM-6, page 9-38) */
922				pb.hFileInfo.ioFlXFndrInfo.fdScript = (scriptTag >= smRoman) ?
923														((char)scriptTag | (char)0x80) :
924														(smRoman);
925				/* Set creator/fileType */
926				pb.hFileInfo.ioFlFndrInfo.fdCreator = creator;
927				pb.hFileInfo.ioFlFndrInfo.fdType = fileType;
928
929				/* Restore ioDirID field in pb which was changed by PBGetCatInfo */
930				pb.hFileInfo.ioDirID = spec->parID;
931				result = PBSetCatInfoSync(&pb);
932			}
933			/* Set ResErr low memory global to result */
934			LMSetResErr(result);
935		}
936		return;
937	}
938	else
939#endif	/* !__MACOSSEVENFIVEONEORLATER */
940	{
941		FSpCreateResFile(spec, creator, fileType, scriptTag);
942		return;
943	}
944}
945
946/*****************************************************************************/
947