4 Contains: FSSpec compatibility functions.
8 Copyright: © 1992-2001 by Apple Computer, Inc., all rights reserved.
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.
20 DRI: Apple Macintosh Developer Technical Support
22 Other Contact: Apple Macintosh Developer Technical Support
23 <http://developer.apple.com/bugreporter/>
25 Technology: DTS Sample Code
31 Change History (most recent first):
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.
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.
44 #ifndef GENERATENODATA
45 #define GENERATENODATA 0
49 #include <MacErrors.h>
53 #include <Resources.h>
56 #define __COMPILINGMOREFILES
58 #include "MoreFilesExtras.h"
59 #include "FSpCompat.h"
61 /*****************************************************************************/
66 gestaltBugFixAttrsTwo
= 'bugy',
67 gestaltFSpExchangeFilesCompatibilityFix
= 26,
68 gestaltBugFixAttrsThree
= 'bugx',
69 gestaltFSpCreateScriptSupportFix
= 1
72 /*****************************************************************************/
74 /* static prototypes */
77 #if !__MACOSSEVENORLATER
78 static Boolean
FSHasFSSpecCalls(void);
80 static Boolean
QTHasFSSpecCalls(void);
81 #endif /* !__MACOSSEVENORLATER */
83 #if !__MACOSSEVENFIVEORLATER
84 static Boolean
HasFSpExchangeFilesCompatibilityFix(void);
86 static OSErr
GenerateUniqueName(short volume
,
90 StringPtr uniqueName
);
91 #endif /* !__MACOSSEVENFIVEORLATER */
93 #if !__MACOSSEVENFIVEONEORLATER
94 static Boolean
HasFSpCreateScriptSupportFix(void);
95 #endif /* !__MACOSSEVENFIVEONEORLATER */
97 /*****************************************************************************/
99 /* FSHasFSSpecCalls returns true if the file system provides FSSpec calls. */
101 #if !__MACOSSEVENORLATER
102 static Boolean
FSHasFSSpecCalls(void)
106 static Boolean tested
= false;
107 static Boolean result
= false;
109 Boolean result
= false;
117 if ( Gestalt(gestaltFSAttr
, &response
) == noErr
)
119 result
= ((response
& (1L << gestaltHasFSSpecCalls
)) != 0);
126 #endif /* !__MACOSSEVENORLATER */
128 /*****************************************************************************/
130 /* QTHasFSSpecCalls returns true if QuickTime provides FSSpec calls */
131 /* except for FSpExchangeFiles. */
133 #if !__MACOSSEVENORLATER
134 static Boolean
QTHasFSSpecCalls(void)
138 static Boolean tested
= false;
139 static Boolean result
= false;
141 Boolean result
= false;
149 result
= (Gestalt(gestaltQuickTimeVersion
, &response
) == noErr
);
155 #endif /* !__MACOSSEVENORLATER */
157 /*****************************************************************************/
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. */
164 #if !__MACOSSEVENFIVEORLATER
165 static Boolean
HasFSpExchangeFilesCompatibilityFix(void)
169 static Boolean tested
= false;
170 static Boolean result
= false;
171 #else /* !GENERATENODATA */
172 Boolean result
= false;
173 #endif /* !GENERATENODATA */
179 #endif /* !GENERATENODATA */
180 if ( Gestalt(gestaltBugFixAttrsTwo
, &response
) == noErr
)
182 result
= ((response
& (1L << gestaltFSpExchangeFilesCompatibilityFix
)) != 0);
186 #endif /* !GENERATENODATA */
189 #endif /* !__MACOSSEVENFIVEORLATER */
191 /*****************************************************************************/
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 */
198 #if !__MACOSSEVENFIVEONEORLATER
199 static Boolean
HasFSpCreateScriptSupportFix(void)
203 static Boolean tested
= false;
204 static Boolean result
= false;
206 Boolean result
= false;
207 #endif /* !GENERATENODATA */
213 #endif /* !GENERATENODATA */
214 if ( Gestalt(gestaltBugFixAttrsThree
, &response
) == noErr
)
216 result
= ((response
& (1L << gestaltFSpCreateScriptSupportFix
)) != 0);
220 #endif /* !GENERATENODATA */
223 #endif /* !__MACOSSEVENFIVEONEORLATER */
225 /*****************************************************************************/
228 ** File Manager FSp calls
231 /*****************************************************************************/
233 pascal OSErr
FSMakeFSSpecCompat(short vRefNum
,
235 ConstStr255Param fileName
,
240 #if !__MACOSSEVENORLATER
241 if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
245 result
= GetObjectLocation(vRefNum
, dirID
, fileName
,
246 &(spec
->vRefNum
), &(spec
->parID
), spec
->name
,
250 #endif /* !__MACOSSEVENORLATER */
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
);
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
;
266 /*****************************************************************************/
268 pascal OSErr
FSpOpenDFCompat(const FSSpec
*spec
,
272 #if !__MACOSSEVENORLATER
273 if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
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
;
289 #endif /* !__MACOSSEVENORLATER */
291 return ( FSpOpenDF(spec
, permission
, refNum
) );
295 /*****************************************************************************/
297 pascal OSErr
FSpOpenRFCompat(const FSSpec
*spec
,
301 #if !__MACOSSEVENORLATER
302 if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
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
;
318 #endif /* !__MACOSSEVENORLATER */
320 return ( FSpOpenRF(spec
, permission
, refNum
) );
324 /*****************************************************************************/
326 pascal OSErr
FSpCreateCompat(const FSSpec
*spec
,
329 ScriptCode scriptTag
)
331 #if !__MACOSSEVENFIVEONEORLATER
337 #if !__MACOSSEVENORLATER
338 (!FSHasFSSpecCalls() && !QTHasFSSpecCalls()) ||
339 #endif /* !__MACOSSEVENORLATER */
340 !HasFSpCreateScriptSupportFix() )
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
)
350 /* get info on created item */
351 pb
.ciPB
.hFileInfo
.ioFDirIndex
= 0;
352 result
= PBGetCatInfoSync(&(pb
.ciPB
));
353 if ( result
== noErr
)
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) :
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
));
373 #endif /* !__MACOSSEVENFIVEONEORLATER */
375 return ( FSpCreate(spec
, creator
, fileType
, scriptTag
) );
379 /*****************************************************************************/
381 pascal OSErr
FSpDirCreateCompat(const FSSpec
*spec
,
382 ScriptCode scriptTag
,
385 #if !__MACOSSEVENORLATER
386 if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
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
)
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
)
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) :
411 /* Restore ioDirID field in pb which was changed by PBGetCatInfo */
412 pb
.ciPB
.dirInfo
.ioDrDirID
= spec
->parID
;
413 result
= PBSetCatInfoSync(&(pb
.ciPB
));
419 #endif /* !__MACOSSEVENORLATER */
421 return ( FSpDirCreate(spec
, scriptTag
, createdDirID
) );
425 /*****************************************************************************/
427 pascal OSErr
FSpDeleteCompat(const FSSpec
*spec
)
429 #if !__MACOSSEVENORLATER
430 if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
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
) );
441 #endif /* !__MACOSSEVENORLATER */
443 return ( FSpDelete(spec
) );
447 /*****************************************************************************/
449 pascal OSErr
FSpGetFInfoCompat(const FSSpec
*spec
,
452 #if !__MACOSSEVENORLATER
453 if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
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
;
468 #endif /* !__MACOSSEVENORLATER */
470 return ( FSpGetFInfo(spec
, fndrInfo
) );
474 /*****************************************************************************/
476 pascal OSErr
FSpSetFInfoCompat(const FSSpec
*spec
,
477 const FInfo
*fndrInfo
)
479 #if !__MACOSSEVENORLATER
480 if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
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
)
493 pb
.fileParam
.ioFlFndrInfo
= *fndrInfo
;
494 pb
.fileParam
.ioDirID
= spec
->parID
;
495 result
= PBHSetFInfoSync(&pb
);
500 #endif /* !__MACOSSEVENORLATER */
502 return ( FSpSetFInfo(spec
, fndrInfo
) );
506 /*****************************************************************************/
508 pascal OSErr
FSpSetFLockCompat(const FSSpec
*spec
)
510 #if !__MACOSSEVENORLATER
511 if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
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
) );
522 #endif /* !__MACOSSEVENORLATER */
524 return ( FSpSetFLock(spec
) );
528 /*****************************************************************************/
530 pascal OSErr
FSpRstFLockCompat(const FSSpec
*spec
)
532 #if !__MACOSSEVENORLATER
533 if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
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
) );
544 #endif /* !__MACOSSEVENORLATER */
546 return ( FSpRstFLock(spec
) );
550 /*****************************************************************************/
552 pascal OSErr
FSpRenameCompat(const FSSpec
*spec
,
553 ConstStr255Param newName
)
555 #if !__MACOSSEVENORLATER
556 if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
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
) );
568 #endif /* !__MACOSSEVENORLATER */
570 return ( FSpRename(spec
, newName
) );
574 /*****************************************************************************/
576 pascal OSErr
FSpCatMoveCompat(const FSSpec
*source
,
579 #if !__MACOSSEVENORLATER
580 if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
584 /* source and destination volume must be the same */
585 if ( source
->vRefNum
!= dest
->vRefNum
)
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
) );
596 #endif /* !__MACOSSEVENORLATER */
598 return ( FSpCatMove(source
, dest
) );
602 /*****************************************************************************/
604 /* GenerateUniqueName generates a name that is unique in both dir1 and dir2 */
605 /* on the specified volume. Ripped off from Feldman's code. */
607 #if !__MACOSSEVENFIVEORLATER
608 static OSErr
GenerateUniqueName(short volume
,
612 StringPtr uniqueName
)
617 unsigned char hexStr
[16];
619 for ( i
= 0; i
< 16; ++i
)
623 hexStr
[i
] = 0x30 + i
;
627 hexStr
[i
] = 0x37 + i
;
631 cinfo
.hFileInfo
.ioVRefNum
= volume
;
632 cinfo
.hFileInfo
.ioFDirIndex
= 0;
633 cinfo
.hFileInfo
.ioNamePtr
= uniqueName
;
635 while ( error
!= fnfErr
)
638 cinfo
.hFileInfo
.ioNamePtr
[0] = 8;
639 for ( i
= 1; i
<= 8; i
++ )
641 cinfo
.hFileInfo
.ioNamePtr
[i
] = hexStr
[((*startSeed
>> ((8-i
)*4)) & 0xf)];
643 cinfo
.hFileInfo
.ioDirID
= dir1
;
645 for ( i
= 1; i
<= 2; i
++ )
647 error
= error
& PBGetCatInfoSync(&cinfo
);
648 cinfo
.hFileInfo
.ioDirID
= dir2
;
649 if ( (error
!= fnfErr
) && (error
!= noErr
) )
657 #endif /* !__MACOSSEVENFIVEORLATER */
659 /*****************************************************************************/
661 pascal OSErr
FSpExchangeFilesCompat(const FSSpec
*source
,
664 #if !__MACOSSEVENFIVEORLATER
666 #if !__MACOSSEVENORLATER
667 !FSHasFSSpecCalls() ||
668 #endif /* !__MACOSSEVENORLATER */
669 !HasFSpExchangeFilesCompatibilityFix() )
672 CInfoPBRec catInfoSource
, catInfoDest
;
673 OSErr result
, result2
;
674 Str31 unique1
, unique2
;
675 StringPtr unique1Ptr
, unique2Ptr
, swapola
;
676 GetVolParmsInfoBuffer volInfo
;
679 /* Make sure the source and destination are on the same volume */
680 if ( source
->vRefNum
!= dest
->vRefNum
)
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
;
693 result
= PBExchangeFilesSync(&pb
);
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
)
699 pb
.ioParam
.ioNamePtr
= NULL
;
700 pb
.ioParam
.ioBuffer
= (Ptr
) &volInfo
;
701 pb
.ioParam
.ioReqCount
= sizeof(volInfo
);
702 result2
= PBHGetVolParmsSync(&pb
);
704 /* continue if volume has no fileID support (or no GetVolParms support) */
705 if ( (result2
== noErr
) && hasFileIDs(&volInfo
) )
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
)
722 if ( (catInfoSource
.hFileInfo
.ioFlAttrib
& kioFlAttribDirMask
) != 0 )
724 result
= notAFileErr
;
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
)
738 if ( (catInfoDest
.hFileInfo
.ioFlAttrib
& kioFlAttribDirMask
) != 0 )
740 result
= notAFileErr
;
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
;
749 result
= GenerateUniqueName(source
->vRefNum
, &theSeed
, source
->parID
, dest
->parID
, unique1Ptr
);
750 if ( result
!= noErr
)
755 GenerateUniqueName(source
->vRefNum
, &theSeed
, source
->parID
, dest
->parID
, unique2Ptr
);
756 if ( result
!= noErr
)
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
)
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
)
779 goto errorExit2
; /* back out gracefully by renaming unique1 back to source */
782 /* If files are not in same directory, swap their locations */
783 if ( source
->parID
!= dest
->parID
)
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
)
793 goto errorExit1
; /* back out gracefully by renaming both files to original names */
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
)
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 */
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
;
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 */
825 /* swap the catalog info by re-aiming the CInfoPB's */
826 catInfoSource
.hFileInfo
.ioNamePtr
= unique1Ptr
;
827 catInfoDest
.hFileInfo
.ioNamePtr
= unique2Ptr
;
829 catInfoSource
.hFileInfo
.ioDirID
= source
->parID
;
830 catInfoDest
.hFileInfo
.ioDirID
= dest
->parID
;
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
;
837 /* Here's the swap (ignore errors) */
838 (void) PBSetCatInfoSync(&catInfoSource
);
839 (void) PBSetCatInfoSync(&catInfoDest
);
841 /* rename unique2 back to dest */
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 */
849 /* rename unique1 back to source */
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 */
857 errorExit3
: { /* null statement */ }
861 #endif /* !__MACOSSEVENFIVEORLATER */
863 return ( FSpExchangeFiles(source
, dest
) );
867 /*****************************************************************************/
870 ** Resource Manager FSp calls
873 /*****************************************************************************/
875 pascal short FSpOpenResFileCompat(const FSSpec
*spec
,
876 SignedByte permission
)
878 #if !__MACOSSEVENORLATER
879 if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
881 return ( HOpenResFile(spec
->vRefNum
, spec
->parID
, spec
->name
, permission
) );
884 #endif /* !__MACOSSEVENORLATER */
886 return ( FSpOpenResFile(spec
, permission
) );
890 /*****************************************************************************/
892 pascal void FSpCreateResFileCompat(const FSSpec
*spec
,
895 ScriptCode scriptTag
)
897 #if !__MACOSSEVENFIVEONEORLATER
899 #if !__MACOSSEVENORLATER
900 (!FSHasFSSpecCalls() && !QTHasFSSpecCalls()) ||
901 #endif /* !__MACOSSEVENORLATER */
902 !HasFSpCreateScriptSupportFix() )
907 HCreateResFile(spec
->vRefNum
, spec
->parID
, spec
->name
);
908 if ( ResError() == noErr
)
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
)
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) :
925 /* Set creator/fileType */
926 pb
.hFileInfo
.ioFlFndrInfo
.fdCreator
= creator
;
927 pb
.hFileInfo
.ioFlFndrInfo
.fdType
= fileType
;
929 /* Restore ioDirID field in pb which was changed by PBGetCatInfo */
930 pb
.hFileInfo
.ioDirID
= spec
->parID
;
931 result
= PBSetCatInfoSync(&pb
);
933 /* Set ResErr low memory global to result */
939 #endif /* !__MACOSSEVENFIVEONEORLATER */
941 FSpCreateResFile(spec
, creator
, fileType
, scriptTag
);
946 /*****************************************************************************/