2 ** Apple Macintosh Developer Technical Support
4 ** FSSpec compatibility functions.
6 ** by Jim Luther, Apple Developer Technical Support Emeritus
10 ** Copyright © 1992-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.
23 ** If building application 68K code, set GENERATENODATA to 0 for faster code.
24 ** If building stand-alone 68K code, set GENERATENODATA to 1 so globals
25 ** (static variables) are not used.
27 #ifndef GENERATENODATA
28 #define GENERATENODATA 0
35 #include <Resources.h>
38 #define __COMPILINGMOREFILES
43 /*****************************************************************************/
48 gestaltBugFixAttrsTwo
= 'bugy',
49 gestaltFSpExchangeFilesCompatibilityFix
= 26,
50 gestaltBugFixAttrsThree
= 'bugx',
51 gestaltFSpCreateScriptSupportFix
= 1
54 /*****************************************************************************/
56 /* static prototypes */
59 #if !__MACOSSEVENORLATER
60 static Boolean
FSHasFSSpecCalls(void);
62 static Boolean
QTHasFSSpecCalls(void);
63 #endif /* !__MACOSSEVENORLATER */
65 #if !__MACOSSEVENFIVEORLATER
66 static Boolean
HasFSpExchangeFilesCompatibilityFix(void);
68 static OSErr
GenerateUniqueName(short volume
,
72 StringPtr uniqueName
);
73 #endif /* !__MACOSSEVENFIVEORLATER */
75 #if !__MACOSSEVENFIVEONEORLATER
76 static Boolean
HasFSpCreateScriptSupportFix(void);
77 #endif /* !__MACOSSEVENFIVEONEORLATER */
79 /*****************************************************************************/
81 /* FSHasFSSpecCalls returns true if the file system provides FSSpec calls. */
83 #if !__MACOSSEVENORLATER
84 static Boolean
FSHasFSSpecCalls(void)
88 static Boolean tested
= false;
89 static Boolean result
= false;
91 Boolean result
= false;
99 if ( Gestalt(gestaltFSAttr
, &response
) == noErr
)
101 result
= ((response
& (1L << gestaltHasFSSpecCalls
)) != 0);
108 #endif /* !__MACOSSEVENORLATER */
110 /*****************************************************************************/
112 /* QTHasFSSpecCalls returns true if QuickTime provides FSSpec calls */
113 /* except for FSpExchangeFiles. */
115 #if !__MACOSSEVENORLATER
116 static Boolean
QTHasFSSpecCalls(void)
120 static Boolean tested
= false;
121 static Boolean result
= false;
123 Boolean result
= false;
131 result
= (Gestalt(gestaltQuickTimeVersion
, &response
) == noErr
);
137 #endif /* !__MACOSSEVENORLATER */
139 /*****************************************************************************/
141 /* HasFSpExchangeFilesCompatibilityFix returns true if FSpExchangeFiles */
142 /* compatibility code has been fixed in system software. */
143 /* This was fixed by System Update 3.0, so if SystemSevenFiveOrLater */
144 /* is true, then we know the fix is in. */
146 #if !__MACOSSEVENFIVEORLATER
147 static Boolean
HasFSpExchangeFilesCompatibilityFix(void)
151 static Boolean tested
= false;
152 static Boolean result
= false;
153 #else /* !GENERATENODATA */
154 Boolean result
= false;
155 #endif /* !GENERATENODATA */
161 #endif /* !GENERATENODATA */
162 if ( Gestalt(gestaltBugFixAttrsTwo
, &response
) == noErr
)
164 result
= ((response
& (1L << gestaltFSpExchangeFilesCompatibilityFix
)) != 0);
168 #endif /* !GENERATENODATA */
171 #endif /* !__MACOSSEVENFIVEORLATER */
173 /*****************************************************************************/
175 /* HasFSpCreateScriptSupportFix returns true if FSpCreate and */
176 /* FSpCreateResFile have been fixed in system software to correctly set */
177 /* the scriptCode in the volume's catalog. */
178 /* This was fixed by System 7.5 Update 1.0 */
180 #if !__MACOSSEVENFIVEONEORLATER
181 static Boolean
HasFSpCreateScriptSupportFix(void)
185 static Boolean tested
= false;
186 static Boolean result
= false;
188 Boolean result
= false;
189 #endif /* !GENERATENODATA */
195 #endif /* !GENERATENODATA */
196 if ( Gestalt(gestaltBugFixAttrsThree
, &response
) == noErr
)
198 result
= ((response
& (1L << gestaltFSpCreateScriptSupportFix
)) != 0);
202 #endif /* !GENERATENODATA */
205 #endif /* !__MACOSSEVENFIVEONEORLATER */
207 /*****************************************************************************/
210 ** File Manager FSp calls
213 /*****************************************************************************/
215 pascal OSErr
FSMakeFSSpecCompat(short vRefNum
,
217 ConstStr255Param fileName
,
222 #if !__MACOSSEVENORLATER
223 if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
227 result
= GetObjectLocation(vRefNum
, dirID
, fileName
,
228 &(spec
->vRefNum
), &(spec
->parID
), spec
->name
,
232 #endif /* !__MACOSSEVENORLATER */
234 /* Let the file system create the FSSpec if it can since it does the job */
235 /* much more efficiently than I can. */
236 result
= FSMakeFSSpec(vRefNum
, dirID
, fileName
, spec
);
238 /* Fix a bug in Macintosh PC Exchange's MakeFSSpec code where 0 is */
239 /* returned in the parID field when making an FSSpec to the volume's */
240 /* root directory by passing a full pathname in MakeFSSpec's */
241 /* fileName parameter. Fixed in Mac OS 8.1 */
242 if ( (result
== noErr
) && (spec
->parID
== 0) )
243 spec
->parID
= fsRtParID
;
248 /*****************************************************************************/
250 pascal OSErr
FSpOpenDFCompat(const FSSpec
*spec
,
254 #if !__MACOSSEVENORLATER
255 if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
260 pb
.ioParam
.ioVRefNum
= spec
->vRefNum
;
261 pb
.fileParam
.ioDirID
= spec
->parID
;
262 pb
.ioParam
.ioNamePtr
= (StringPtr
) &(spec
->name
);
263 pb
.ioParam
.ioVersNum
= 0;
264 pb
.ioParam
.ioPermssn
= permission
;
265 pb
.ioParam
.ioMisc
= NULL
;
266 result
= PBHOpenSync(&pb
); /* OpenDF not supported by System 6, so use Open */
267 *refNum
= pb
.ioParam
.ioRefNum
;
271 #endif /* !__MACOSSEVENORLATER */
273 return ( FSpOpenDF(spec
, permission
, refNum
) );
277 /*****************************************************************************/
279 pascal OSErr
FSpOpenRFCompat(const FSSpec
*spec
,
283 #if !__MACOSSEVENORLATER
284 if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
289 pb
.ioParam
.ioVRefNum
= spec
->vRefNum
;
290 pb
.fileParam
.ioDirID
= spec
->parID
;
291 pb
.ioParam
.ioNamePtr
= (StringPtr
) &(spec
->name
);
292 pb
.ioParam
.ioVersNum
= 0;
293 pb
.ioParam
.ioPermssn
= permission
;
294 pb
.ioParam
.ioMisc
= NULL
;
295 result
= PBHOpenRFSync(&pb
);
296 *refNum
= pb
.ioParam
.ioRefNum
;
300 #endif /* !__MACOSSEVENORLATER */
302 return ( FSpOpenRF(spec
, permission
, refNum
) );
306 /*****************************************************************************/
308 pascal OSErr
FSpCreateCompat(const FSSpec
*spec
,
311 ScriptCode scriptTag
)
313 #if !__MACOSSEVENFIVEONEORLATER
319 #if !__MACOSSEVENORLATER
320 (!FSHasFSSpecCalls() && !QTHasFSSpecCalls()) ||
321 #endif /* !__MACOSSEVENORLATER */
322 !HasFSpCreateScriptSupportFix() )
324 /* If FSpCreate isn't called, this code will be executed */
325 pb
.hPB
.fileParam
.ioVRefNum
= spec
->vRefNum
;
326 pb
.hPB
.fileParam
.ioDirID
= spec
->parID
;
327 pb
.hPB
.fileParam
.ioNamePtr
= (StringPtr
) &(spec
->name
);
328 pb
.hPB
.fileParam
.ioFVersNum
= 0;
329 result
= PBHCreateSync(&(pb
.hPB
));
330 if ( result
== noErr
)
332 /* get info on created item */
333 pb
.ciPB
.hFileInfo
.ioFDirIndex
= 0;
334 result
= PBGetCatInfoSync(&(pb
.ciPB
));
335 if ( result
== noErr
)
337 /* Set fdScript in FXInfo */
338 /* The negative script constants (smSystemScript, smCurrentScript, and smAllScripts) */
339 /* don't make sense on disk, so only use scriptTag if scriptTag >= smRoman */
340 /* (smRoman is 0). fdScript is valid if high bit is set (see IM-6, page 9-38) */
341 pb
.ciPB
.hFileInfo
.ioFlXFndrInfo
.fdScript
= (scriptTag
>= smRoman
) ?
342 ((char)scriptTag
| (char)0x80) :
344 /* Set creator/fileType */
345 pb
.ciPB
.hFileInfo
.ioFlFndrInfo
.fdCreator
= creator
;
346 pb
.ciPB
.hFileInfo
.ioFlFndrInfo
.fdType
= fileType
;
347 /* Restore ioDirID field in pb which was changed by PBGetCatInfo */
348 pb
.ciPB
.hFileInfo
.ioDirID
= spec
->parID
;
349 result
= PBSetCatInfoSync(&(pb
.ciPB
));
355 #endif /* !__MACOSSEVENFIVEONEORLATER */
357 return ( FSpCreate(spec
, creator
, fileType
, scriptTag
) );
361 /*****************************************************************************/
363 pascal OSErr
FSpDirCreateCompat(const FSSpec
*spec
,
364 ScriptCode scriptTag
,
367 #if !__MACOSSEVENORLATER
368 if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
373 pb
.hPB
.fileParam
.ioVRefNum
= spec
->vRefNum
;
374 pb
.hPB
.fileParam
.ioDirID
= spec
->parID
;
375 pb
.hPB
.fileParam
.ioNamePtr
= (StringPtr
) &(spec
->name
);
376 result
= PBDirCreateSync(&(pb
.hPB
));
377 *createdDirID
= pb
.hPB
.fileParam
.ioDirID
;
378 if ( result
== noErr
)
380 /* get info on created item */
381 pb
.ciPB
.dirInfo
.ioFDirIndex
= 0;
382 pb
.ciPB
.dirInfo
.ioDrDirID
= spec
->parID
;
383 result
= PBGetCatInfoSync(&(pb
.ciPB
));
384 if ( result
== noErr
)
386 /* Set frScript in DXInfo */
387 /* The negative script constants (smSystemScript, smCurrentScript, and smAllScripts) */
388 /* don't make sense on disk, so only use scriptTag if scriptTag >= smRoman */
389 /* (smRoman is 0). frScript is valid if high bit is set (see IM-6, page 9-38) */
390 pb
.ciPB
.dirInfo
.ioDrFndrInfo
.frScript
= (scriptTag
>= smRoman
) ?
391 ((char)scriptTag
| (char)0x80) :
393 /* Restore ioDirID field in pb which was changed by PBGetCatInfo */
394 pb
.ciPB
.dirInfo
.ioDrDirID
= spec
->parID
;
395 result
= PBSetCatInfoSync(&(pb
.ciPB
));
401 #endif /* !__MACOSSEVENORLATER */
403 return ( FSpDirCreate(spec
, scriptTag
, createdDirID
) );
407 /*****************************************************************************/
409 pascal OSErr
FSpDeleteCompat(const FSSpec
*spec
)
411 #if !__MACOSSEVENORLATER
412 if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
416 pb
.ioParam
.ioVRefNum
= spec
->vRefNum
;
417 pb
.fileParam
.ioDirID
= spec
->parID
;
418 pb
.ioParam
.ioNamePtr
= (StringPtr
) &(spec
->name
);
419 pb
.ioParam
.ioVersNum
= 0;
420 return ( PBHDeleteSync(&pb
) );
423 #endif /* !__MACOSSEVENORLATER */
425 return ( FSpDelete(spec
) );
429 /*****************************************************************************/
431 pascal OSErr
FSpGetFInfoCompat(const FSSpec
*spec
,
434 #if !__MACOSSEVENORLATER
435 if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
440 pb
.fileParam
.ioVRefNum
= spec
->vRefNum
;
441 pb
.fileParam
.ioDirID
= spec
->parID
;
442 pb
.fileParam
.ioNamePtr
= (StringPtr
) &(spec
->name
);
443 pb
.fileParam
.ioFVersNum
= 0;
444 pb
.fileParam
.ioFDirIndex
= 0;
445 result
= PBHGetFInfoSync(&pb
);
446 *fndrInfo
= pb
.fileParam
.ioFlFndrInfo
;
450 #endif /* !__MACOSSEVENORLATER */
452 return ( FSpGetFInfo(spec
, fndrInfo
) );
456 /*****************************************************************************/
458 pascal OSErr
FSpSetFInfoCompat(const FSSpec
*spec
,
459 const FInfo
*fndrInfo
)
461 #if !__MACOSSEVENORLATER
462 if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
467 pb
.fileParam
.ioVRefNum
= spec
->vRefNum
;
468 pb
.fileParam
.ioDirID
= spec
->parID
;
469 pb
.fileParam
.ioNamePtr
= (StringPtr
) &(spec
->name
);
470 pb
.fileParam
.ioFVersNum
= 0;
471 pb
.fileParam
.ioFDirIndex
= 0;
472 result
= PBHGetFInfoSync(&pb
);
473 if ( result
== noErr
)
475 pb
.fileParam
.ioFlFndrInfo
= *fndrInfo
;
476 pb
.fileParam
.ioDirID
= spec
->parID
;
477 result
= PBHSetFInfoSync(&pb
);
482 #endif /* !__MACOSSEVENORLATER */
484 return ( FSpSetFInfo(spec
, fndrInfo
) );
488 /*****************************************************************************/
490 pascal OSErr
FSpSetFLockCompat(const FSSpec
*spec
)
492 #if !__MACOSSEVENORLATER
493 if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
497 pb
.fileParam
.ioVRefNum
= spec
->vRefNum
;
498 pb
.fileParam
.ioDirID
= spec
->parID
;
499 pb
.fileParam
.ioNamePtr
= (StringPtr
) &(spec
->name
);
500 pb
.fileParam
.ioFVersNum
= 0;
501 return ( PBHSetFLockSync(&pb
) );
504 #endif /* !__MACOSSEVENORLATER */
506 return ( FSpSetFLock(spec
) );
510 /*****************************************************************************/
512 pascal OSErr
FSpRstFLockCompat(const FSSpec
*spec
)
514 #if !__MACOSSEVENORLATER
515 if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
519 pb
.fileParam
.ioVRefNum
= spec
->vRefNum
;
520 pb
.fileParam
.ioDirID
= spec
->parID
;
521 pb
.fileParam
.ioNamePtr
= (StringPtr
) &(spec
->name
);
522 pb
.fileParam
.ioFVersNum
= 0;
523 return ( PBHRstFLockSync(&pb
) );
526 #endif /* !__MACOSSEVENORLATER */
528 return ( FSpRstFLock(spec
) );
532 /*****************************************************************************/
534 pascal OSErr
FSpRenameCompat(const FSSpec
*spec
,
535 ConstStr255Param newName
)
537 #if !__MACOSSEVENORLATER
538 if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
542 pb
.ioParam
.ioVRefNum
= spec
->vRefNum
;
543 pb
.fileParam
.ioDirID
= spec
->parID
;
544 pb
.ioParam
.ioNamePtr
= (StringPtr
) &(spec
->name
);
545 pb
.ioParam
.ioVersNum
= 0;
546 pb
.ioParam
.ioMisc
= (Ptr
) newName
;
547 return ( PBHRenameSync(&pb
) );
550 #endif /* !__MACOSSEVENORLATER */
552 return ( FSpRename(spec
, newName
) );
556 /*****************************************************************************/
558 pascal OSErr
FSpCatMoveCompat(const FSSpec
*source
,
561 #if !__MACOSSEVENORLATER
562 if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
566 /* source and destination volume must be the same */
567 if ( source
->vRefNum
!= dest
->vRefNum
)
570 pb
.ioNamePtr
= (StringPtr
) &(source
->name
);
571 pb
.ioVRefNum
= source
->vRefNum
;
572 pb
.ioDirID
= source
->parID
;
573 pb
.ioNewDirID
= dest
->parID
;
574 pb
.ioNewName
= (StringPtr
) &(dest
->name
);
575 return ( PBCatMoveSync(&pb
) );
578 #endif /* !__MACOSSEVENORLATER */
580 return ( FSpCatMove(source
, dest
) );
584 /*****************************************************************************/
586 /* GenerateUniqueName generates a name that is unique in both dir1 and dir2 */
587 /* on the specified volume. Ripped off from Feldman's code. */
589 #if !__MACOSSEVENFIVEORLATER
590 static OSErr
GenerateUniqueName(short volume
,
594 StringPtr uniqueName
)
599 unsigned char hexStr
[16];
601 for ( i
= 0; i
< 16; ++i
)
605 hexStr
[i
] = 0x30 + i
;
609 hexStr
[i
] = 0x37 + i
;
613 cinfo
.hFileInfo
.ioVRefNum
= volume
;
614 cinfo
.hFileInfo
.ioFDirIndex
= 0;
615 cinfo
.hFileInfo
.ioNamePtr
= uniqueName
;
617 while ( error
!= fnfErr
)
620 cinfo
.hFileInfo
.ioNamePtr
[0] = 8;
621 for ( i
= 1; i
<= 8; i
++ )
623 cinfo
.hFileInfo
.ioNamePtr
[i
] = hexStr
[((*startSeed
>> ((8-i
)*4)) & 0xf)];
625 cinfo
.hFileInfo
.ioDirID
= dir1
;
627 for ( i
= 1; i
<= 2; i
++ )
629 error
= error
& PBGetCatInfoSync(&cinfo
);
630 cinfo
.hFileInfo
.ioDirID
= dir2
;
631 if ( (error
!= fnfErr
) && (error
!= noErr
) )
639 #endif /* !__MACOSSEVENFIVEORLATER */
641 /*****************************************************************************/
643 pascal OSErr
FSpExchangeFilesCompat(const FSSpec
*source
,
646 #if !__MACOSSEVENFIVEORLATER
648 #if !__MACOSSEVENORLATER
649 !FSHasFSSpecCalls() ||
650 #endif /* !__MACOSSEVENORLATER */
651 !HasFSpExchangeFilesCompatibilityFix() )
654 CInfoPBRec catInfoSource
, catInfoDest
;
655 OSErr result
, result2
;
656 Str31 unique1
, unique2
;
657 StringPtr unique1Ptr
, unique2Ptr
, swapola
;
658 GetVolParmsInfoBuffer volInfo
;
661 /* Make sure the source and destination are on the same volume */
662 if ( source
->vRefNum
!= dest
->vRefNum
)
668 /* Try PBExchangeFiles first since it preserves the file ID reference */
669 pb
.fidParam
.ioNamePtr
= (StringPtr
) &(source
->name
);
670 pb
.fidParam
.ioVRefNum
= source
->vRefNum
;
671 pb
.fidParam
.ioDestNamePtr
= (StringPtr
) &(dest
->name
);
672 pb
.fidParam
.ioDestDirID
= dest
->parID
;
673 pb
.fidParam
.ioSrcDirID
= source
->parID
;
675 result
= PBExchangeFilesSync(&pb
);
677 /* Note: The compatibility case won't work for files with *Btree control blocks. */
678 /* Right now the only *Btree files are created by the system. */
679 if ( result
!= noErr
)
681 pb
.ioParam
.ioNamePtr
= NULL
;
682 pb
.ioParam
.ioBuffer
= (Ptr
) &volInfo
;
683 pb
.ioParam
.ioReqCount
= sizeof(volInfo
);
684 result2
= PBHGetVolParmsSync(&pb
);
686 /* continue if volume has no fileID support (or no GetVolParms support) */
687 if ( (result2
== noErr
) && hasFileIDs(volInfo
) )
692 /* Get the catalog information for each file */
693 /* and make sure both files are *really* files */
694 catInfoSource
.hFileInfo
.ioVRefNum
= source
->vRefNum
;
695 catInfoSource
.hFileInfo
.ioFDirIndex
= 0;
696 catInfoSource
.hFileInfo
.ioNamePtr
= (StringPtr
) &(source
->name
);
697 catInfoSource
.hFileInfo
.ioDirID
= source
->parID
;
698 catInfoSource
.hFileInfo
.ioACUser
= 0; /* ioACUser used to be filler2 */
699 result
= PBGetCatInfoSync(&catInfoSource
);
700 if ( result
!= noErr
)
704 if ( (catInfoSource
.hFileInfo
.ioFlAttrib
& ioDirMask
) != 0 )
706 result
= notAFileErr
;
710 catInfoDest
.hFileInfo
.ioVRefNum
= dest
->vRefNum
;
711 catInfoDest
.hFileInfo
.ioFDirIndex
= 0;
712 catInfoDest
.hFileInfo
.ioNamePtr
= (StringPtr
) &(dest
->name
);
713 catInfoDest
.hFileInfo
.ioDirID
= dest
->parID
;
714 catInfoDest
.hFileInfo
.ioACUser
= 0; /* ioACUser used to be filler2 */
715 result
= PBGetCatInfoSync(&catInfoDest
);
716 if ( result
!= noErr
)
720 if ( (catInfoDest
.hFileInfo
.ioFlAttrib
& ioDirMask
) != 0 )
722 result
= notAFileErr
;
726 /* generate 2 filenames that are unique in both directories */
727 theSeed
= 0x64666A6C; /* a fine unlikely filename */
728 unique1Ptr
= (StringPtr
)&unique1
;
729 unique2Ptr
= (StringPtr
)&unique2
;
731 result
= GenerateUniqueName(source
->vRefNum
, &theSeed
, source
->parID
, dest
->parID
, unique1Ptr
);
732 if ( result
!= noErr
)
737 GenerateUniqueName(source
->vRefNum
, &theSeed
, source
->parID
, dest
->parID
, unique2Ptr
);
738 if ( result
!= noErr
)
743 /* rename source to unique1 */
744 pb
.fileParam
.ioNamePtr
= (StringPtr
) &(source
->name
);
745 pb
.ioParam
.ioMisc
= (Ptr
) unique1Ptr
;
746 pb
.ioParam
.ioVersNum
= 0;
747 result
= PBHRenameSync(&pb
);
748 if ( result
!= noErr
)
753 /* rename dest to unique2 */
754 pb
.ioParam
.ioMisc
= (Ptr
) unique2Ptr
;
755 pb
.ioParam
.ioVersNum
= 0;
756 pb
.fileParam
.ioNamePtr
= (StringPtr
) &(dest
->name
);
757 pb
.fileParam
.ioDirID
= dest
->parID
;
758 result
= PBHRenameSync(&pb
);
759 if ( result
!= noErr
)
761 goto errorExit2
; /* back out gracefully by renaming unique1 back to source */
764 /* If files are not in same directory, swap their locations */
765 if ( source
->parID
!= dest
->parID
)
767 /* move source file to dest directory */
768 pb
.copyParam
.ioNamePtr
= unique1Ptr
;
769 pb
.copyParam
.ioNewName
= NULL
;
770 pb
.copyParam
.ioNewDirID
= dest
->parID
;
771 pb
.copyParam
.ioDirID
= source
->parID
;
772 result
= PBCatMoveSync((CMovePBPtr
) &pb
);
773 if ( result
!= noErr
)
775 goto errorExit1
; /* back out gracefully by renaming both files to original names */
778 /* move dest file to source directory */
779 pb
.copyParam
.ioNamePtr
= unique2Ptr
;
780 pb
.copyParam
.ioNewDirID
= source
->parID
;
781 pb
.copyParam
.ioDirID
= dest
->parID
;
782 result
= PBCatMoveSync((CMovePBPtr
) &pb
);
783 if ( result
!= noErr
)
785 /* life is very bad. We'll at least try to move source back */
786 pb
.copyParam
.ioNamePtr
= unique1Ptr
;
787 pb
.copyParam
.ioNewName
= NULL
;
788 pb
.copyParam
.ioNewDirID
= source
->parID
;
789 pb
.copyParam
.ioDirID
= dest
->parID
;
790 (void) PBCatMoveSync((CMovePBPtr
) &pb
); /* ignore errors */
791 goto errorExit1
; /* back out gracefully by renaming both files to original names */
795 /* Make unique1Ptr point to file in source->parID */
796 /* and unique2Ptr point to file in dest->parID */
797 /* This lets us fall through to the rename code below */
798 swapola
= unique1Ptr
;
799 unique1Ptr
= unique2Ptr
;
800 unique2Ptr
= swapola
;
802 /* At this point, the files are in their new locations (if they were moved) */
803 /* Source is named Unique1 (name pointed to by unique2Ptr) and is in dest->parID */
804 /* Dest is named Unique2 (name pointed to by unique1Ptr) and is in source->parID */
805 /* Need to swap attributes except mod date and swap names */
807 /* swap the catalog info by re-aiming the CInfoPB's */
808 catInfoSource
.hFileInfo
.ioNamePtr
= unique1Ptr
;
809 catInfoDest
.hFileInfo
.ioNamePtr
= unique2Ptr
;
811 catInfoSource
.hFileInfo
.ioDirID
= source
->parID
;
812 catInfoDest
.hFileInfo
.ioDirID
= dest
->parID
;
814 /* Swap the original mod dates with each file */
815 temp
= catInfoSource
.hFileInfo
.ioFlMdDat
;
816 catInfoSource
.hFileInfo
.ioFlMdDat
= catInfoDest
.hFileInfo
.ioFlMdDat
;
817 catInfoDest
.hFileInfo
.ioFlMdDat
= temp
;
819 /* Here's the swap (ignore errors) */
820 (void) PBSetCatInfoSync(&catInfoSource
);
821 (void) PBSetCatInfoSync(&catInfoDest
);
823 /* rename unique2 back to dest */
825 pb
.ioParam
.ioMisc
= (Ptr
) &(dest
->name
);
826 pb
.ioParam
.ioVersNum
= 0;
827 pb
.fileParam
.ioNamePtr
= unique2Ptr
;
828 pb
.fileParam
.ioDirID
= dest
->parID
;
829 (void) PBHRenameSync(&pb
); /* ignore errors */
831 /* rename unique1 back to source */
833 pb
.ioParam
.ioMisc
= (Ptr
) &(source
->name
);
834 pb
.ioParam
.ioVersNum
= 0;
835 pb
.fileParam
.ioNamePtr
= unique1Ptr
;
836 pb
.fileParam
.ioDirID
= source
->parID
;
837 (void) PBHRenameSync(&pb
); /* ignore errors */
839 errorExit3
: { /* null statement */ }
843 #endif /* !__MACOSSEVENFIVEORLATER */
845 return ( FSpExchangeFiles(source
, dest
) );
849 /*****************************************************************************/
852 ** Resource Manager FSp calls
855 /*****************************************************************************/
857 pascal short FSpOpenResFileCompat(const FSSpec
*spec
,
858 SignedByte permission
)
860 #if !__MACOSSEVENORLATER
861 if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
863 return ( HOpenResFile(spec
->vRefNum
, spec
->parID
, spec
->name
, permission
) );
866 #endif /* !__MACOSSEVENORLATER */
868 return ( FSpOpenResFile(spec
, permission
) );
872 /*****************************************************************************/
874 pascal void FSpCreateResFileCompat(const FSSpec
*spec
,
877 ScriptCode scriptTag
)
879 #if !__MACOSSEVENFIVEONEORLATER
881 #if !__MACOSSEVENORLATER
882 (!FSHasFSSpecCalls() && !QTHasFSSpecCalls()) ||
883 #endif /* !__MACOSSEVENORLATER */
884 !HasFSpCreateScriptSupportFix() )
889 HCreateResFile(spec
->vRefNum
, spec
->parID
, spec
->name
);
890 if ( ResError() == noErr
)
892 /* get info on created item */
893 pb
.hFileInfo
.ioVRefNum
= spec
->vRefNum
;
894 pb
.hFileInfo
.ioDirID
= spec
->parID
;
895 pb
.hFileInfo
.ioNamePtr
= (StringPtr
) &(spec
->name
);
896 pb
.hFileInfo
.ioFDirIndex
= 0;
897 result
= PBGetCatInfoSync(&pb
);
898 if ( result
== noErr
)
900 /* Set fdScript in FXInfo */
901 /* The negative script constants (smSystemScript, smCurrentScript, and smAllScripts) */
902 /* don't make sense on disk, so only use scriptTag if scriptTag >= smRoman */
903 /* (smRoman is 0). fdScript is valid if high bit is set (see IM-6, page 9-38) */
904 pb
.hFileInfo
.ioFlXFndrInfo
.fdScript
= (scriptTag
>= smRoman
) ?
905 ((char)scriptTag
| (char)0x80) :
907 /* Set creator/fileType */
908 pb
.hFileInfo
.ioFlFndrInfo
.fdCreator
= creator
;
909 pb
.hFileInfo
.ioFlFndrInfo
.fdType
= fileType
;
911 /* Restore ioDirID field in pb which was changed by PBGetCatInfo */
912 pb
.hFileInfo
.ioDirID
= spec
->parID
;
913 result
= PBSetCatInfoSync(&pb
);
915 /* Set ResErr low memory global to result */
921 #endif /* !__MACOSSEVENFIVEONEORLATER */
923 FSpCreateResFile(spec
, creator
, fileType
, scriptTag
);
928 /*****************************************************************************/