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