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 /*****************************************************************************/