X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/52479aefae169d5c85cd0e07d159db0b8dd0a965..f973828cd9b31d3b80386fab5e6f7c4a106d97fc:/src/mac/classic/morefile/FSpCompat.c?ds=inline diff --git a/src/mac/classic/morefile/FSpCompat.c b/src/mac/classic/morefile/FSpCompat.c new file mode 100644 index 0000000000..17577684f6 --- /dev/null +++ b/src/mac/classic/morefile/FSpCompat.c @@ -0,0 +1,946 @@ +/* + File: FSpCompat.c + + Contains: FSSpec compatibility functions. + + Version: MoreFiles + + Copyright: © 1992-2001 by Apple Computer, Inc., all rights reserved. + + You may incorporate this sample code into your applications without + restriction, though the sample code has been provided "AS IS" and the + responsibility for its operation is 100% yours. However, what you are + not permitted to do is to redistribute the source as "DSC Sample Code" + after having made changes. If you're going to re-distribute the source, + we require that you make it clear in the source that the code was + descended from Apple Sample Code, but that you've made changes. + + File Ownership: + + DRI: Apple Macintosh Developer Technical Support + + Other Contact: Apple Macintosh Developer Technical Support + + + Technology: DTS Sample Code + + Writers: + + (JL) Jim Luther + + Change History (most recent first): + + <2> 2/7/01 JL Added standard header. Updated names of includes. Updated + various routines to use new calling convention of the + MoreFilesExtras accessor functions. + <1> 12/06/99 JL MoreFiles 1.5. +*/ + +/* +** If building application 68K code, set GENERATENODATA to 0 for faster code. +** If building stand-alone 68K code, set GENERATENODATA to 1 so globals +** (static variables) are not used. +*/ +#ifndef GENERATENODATA +#define GENERATENODATA 0 +#endif + +#include +#include +#include +#include +#include +#include +#include + +#define __COMPILINGMOREFILES + +#include "MoreFilesExtras.h" +#include "FSpCompat.h" + +/*****************************************************************************/ + +/* local constants */ + +enum { + gestaltBugFixAttrsTwo = 'bugy', + gestaltFSpExchangeFilesCompatibilityFix = 26, + gestaltBugFixAttrsThree = 'bugx', + gestaltFSpCreateScriptSupportFix = 1 +}; + +/*****************************************************************************/ + +/* static prototypes */ + + +#if !__MACOSSEVENORLATER +static Boolean FSHasFSSpecCalls(void); + +static Boolean QTHasFSSpecCalls(void); +#endif /* !__MACOSSEVENORLATER */ + +#if !__MACOSSEVENFIVEORLATER +static Boolean HasFSpExchangeFilesCompatibilityFix(void); + +static OSErr GenerateUniqueName(short volume, + long *startSeed, + long dir1, + long dir2, + StringPtr uniqueName); +#endif /* !__MACOSSEVENFIVEORLATER */ + +#if !__MACOSSEVENFIVEONEORLATER +static Boolean HasFSpCreateScriptSupportFix(void); +#endif /* !__MACOSSEVENFIVEONEORLATER */ + +/*****************************************************************************/ + +/* FSHasFSSpecCalls returns true if the file system provides FSSpec calls. */ + +#if !__MACOSSEVENORLATER +static Boolean FSHasFSSpecCalls(void) +{ + long response; +#if !GENERATENODATA + static Boolean tested = false; + static Boolean result = false; +#else + Boolean result = false; +#endif + +#if !GENERATENODATA + if ( !tested ) + { + tested = true; +#endif + if ( Gestalt(gestaltFSAttr, &response) == noErr ) + { + result = ((response & (1L << gestaltHasFSSpecCalls)) != 0); + } +#if !GENERATENODATA + } +#endif + return ( result ); +} +#endif /* !__MACOSSEVENORLATER */ + +/*****************************************************************************/ + +/* QTHasFSSpecCalls returns true if QuickTime provides FSSpec calls */ +/* except for FSpExchangeFiles. */ + +#if !__MACOSSEVENORLATER +static Boolean QTHasFSSpecCalls(void) +{ + long response; +#if !GENERATENODATA + static Boolean tested = false; + static Boolean result = false; +#else + Boolean result = false; +#endif + +#if !GENERATENODATA + if ( !tested ) + { + tested = true; +#endif + result = (Gestalt(gestaltQuickTimeVersion, &response) == noErr); +#if !GENERATENODATA + } +#endif + return ( result ); +} +#endif /* !__MACOSSEVENORLATER */ + +/*****************************************************************************/ + +/* HasFSpExchangeFilesCompatibilityFix returns true if FSpExchangeFiles */ +/* compatibility code has been fixed in system software. */ +/* This was fixed by System Update 3.0, so if SystemSevenFiveOrLater */ +/* is true, then we know the fix is in. */ + +#if !__MACOSSEVENFIVEORLATER +static Boolean HasFSpExchangeFilesCompatibilityFix(void) +{ + long response; +#if !GENERATENODATA + static Boolean tested = false; + static Boolean result = false; +#else /* !GENERATENODATA */ + Boolean result = false; +#endif /* !GENERATENODATA */ + +#if !GENERATENODATA + if ( !tested ) + { + tested = true; +#endif /* !GENERATENODATA */ + if ( Gestalt(gestaltBugFixAttrsTwo, &response) == noErr ) + { + result = ((response & (1L << gestaltFSpExchangeFilesCompatibilityFix)) != 0); + } +#if !GENERATENODATA + } +#endif /* !GENERATENODATA */ + return ( result ); +} +#endif /* !__MACOSSEVENFIVEORLATER */ + +/*****************************************************************************/ + +/* HasFSpCreateScriptSupportFix returns true if FSpCreate and */ +/* FSpCreateResFile have been fixed in system software to correctly set */ +/* the scriptCode in the volume's catalog. */ +/* This was fixed by System 7.5 Update 1.0 */ + +#if !__MACOSSEVENFIVEONEORLATER +static Boolean HasFSpCreateScriptSupportFix(void) +{ + long response; +#if !GENERATENODATA + static Boolean tested = false; + static Boolean result = false; +#else + Boolean result = false; +#endif /* !GENERATENODATA */ + +#if !GENERATENODATA + if ( !tested ) + { + tested = true; +#endif /* !GENERATENODATA */ + if ( Gestalt(gestaltBugFixAttrsThree, &response) == noErr ) + { + result = ((response & (1L << gestaltFSpCreateScriptSupportFix)) != 0); + } +#if !GENERATENODATA + } +#endif /* !GENERATENODATA */ + return ( result ); +} +#endif /* !__MACOSSEVENFIVEONEORLATER */ + +/*****************************************************************************/ + +/* +** File Manager FSp calls +*/ + +/*****************************************************************************/ + +pascal OSErr FSMakeFSSpecCompat(short vRefNum, + long dirID, + ConstStr255Param fileName, + FSSpec *spec) +{ + OSErr result; + +#if !__MACOSSEVENORLATER + if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() ) + { + Boolean isDirectory; + + result = GetObjectLocation(vRefNum, dirID, fileName, + &(spec->vRefNum), &(spec->parID), spec->name, + &isDirectory); + } + else +#endif /* !__MACOSSEVENORLATER */ + { + /* Let the file system create the FSSpec if it can since it does the job */ + /* much more efficiently than I can. */ + result = FSMakeFSSpec(vRefNum, dirID, fileName, spec); + + /* Fix a bug in Macintosh PC Exchange's MakeFSSpec code where 0 is */ + /* returned in the parID field when making an FSSpec to the volume's */ + /* root directory by passing a full pathname in MakeFSSpec's */ + /* fileName parameter. Fixed in Mac OS 8.1 */ + if ( (result == noErr) && (spec->parID == 0) ) + spec->parID = fsRtParID; + } + return ( result ); +} + +/*****************************************************************************/ + +pascal OSErr FSpOpenDFCompat(const FSSpec *spec, + char permission, + short *refNum) +{ +#if !__MACOSSEVENORLATER + if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() ) + { + OSErr result; + HParamBlockRec pb; + + pb.ioParam.ioVRefNum = spec->vRefNum; + pb.fileParam.ioDirID = spec->parID; + pb.ioParam.ioNamePtr = (StringPtr) &(spec->name); + pb.ioParam.ioVersNum = 0; + pb.ioParam.ioPermssn = permission; + pb.ioParam.ioMisc = NULL; + result = PBHOpenSync(&pb); /* OpenDF not supported by System 6, so use Open */ + *refNum = pb.ioParam.ioRefNum; + return ( result ); + } + else +#endif /* !__MACOSSEVENORLATER */ + { + return ( FSpOpenDF(spec, permission, refNum) ); + } +} + +/*****************************************************************************/ + +pascal OSErr FSpOpenRFCompat(const FSSpec *spec, + char permission, + short *refNum) +{ +#if !__MACOSSEVENORLATER + if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() ) + { + OSErr result; + HParamBlockRec pb; + + pb.ioParam.ioVRefNum = spec->vRefNum; + pb.fileParam.ioDirID = spec->parID; + pb.ioParam.ioNamePtr = (StringPtr) &(spec->name); + pb.ioParam.ioVersNum = 0; + pb.ioParam.ioPermssn = permission; + pb.ioParam.ioMisc = NULL; + result = PBHOpenRFSync(&pb); + *refNum = pb.ioParam.ioRefNum; + return ( result ); + } + else +#endif /* !__MACOSSEVENORLATER */ + { + return ( FSpOpenRF(spec, permission, refNum) ); + } +} + +/*****************************************************************************/ + +pascal OSErr FSpCreateCompat(const FSSpec *spec, + OSType creator, + OSType fileType, + ScriptCode scriptTag) +{ +#if !__MACOSSEVENFIVEONEORLATER + OSErr result; + UniversalFMPB pb; + + + if ( +#if !__MACOSSEVENORLATER + (!FSHasFSSpecCalls() && !QTHasFSSpecCalls()) || +#endif /* !__MACOSSEVENORLATER */ + !HasFSpCreateScriptSupportFix() ) + { + /* If FSpCreate isn't called, this code will be executed */ + pb.hPB.fileParam.ioVRefNum = spec->vRefNum; + pb.hPB.fileParam.ioDirID = spec->parID; + pb.hPB.fileParam.ioNamePtr = (StringPtr) &(spec->name); + pb.hPB.fileParam.ioFVersNum = 0; + result = PBHCreateSync(&(pb.hPB)); + if ( result == noErr ) + { + /* get info on created item */ + pb.ciPB.hFileInfo.ioFDirIndex = 0; + result = PBGetCatInfoSync(&(pb.ciPB)); + if ( result == noErr ) + { + /* Set fdScript in FXInfo */ + /* The negative script constants (smSystemScript, smCurrentScript, and smAllScripts) */ + /* don't make sense on disk, so only use scriptTag if scriptTag >= smRoman */ + /* (smRoman is 0). fdScript is valid if high bit is set (see IM-6, page 9-38) */ + pb.ciPB.hFileInfo.ioFlXFndrInfo.fdScript = (scriptTag >= smRoman) ? + ((char)scriptTag | (char)0x80) : + (smRoman); + /* Set creator/fileType */ + pb.ciPB.hFileInfo.ioFlFndrInfo.fdCreator = creator; + pb.ciPB.hFileInfo.ioFlFndrInfo.fdType = fileType; + /* Restore ioDirID field in pb which was changed by PBGetCatInfo */ + pb.ciPB.hFileInfo.ioDirID = spec->parID; + result = PBSetCatInfoSync(&(pb.ciPB)); + } + } + return ( result ); + } + else +#endif /* !__MACOSSEVENFIVEONEORLATER */ + { + return ( FSpCreate(spec, creator, fileType, scriptTag) ); + } +} + +/*****************************************************************************/ + +pascal OSErr FSpDirCreateCompat(const FSSpec *spec, + ScriptCode scriptTag, + long *createdDirID) +{ +#if !__MACOSSEVENORLATER + if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() ) + { + OSErr result; + UniversalFMPB pb; + + pb.hPB.fileParam.ioVRefNum = spec->vRefNum; + pb.hPB.fileParam.ioDirID = spec->parID; + pb.hPB.fileParam.ioNamePtr = (StringPtr) &(spec->name); + result = PBDirCreateSync(&(pb.hPB)); + *createdDirID = pb.hPB.fileParam.ioDirID; + if ( result == noErr ) + { + /* get info on created item */ + pb.ciPB.dirInfo.ioFDirIndex = 0; + pb.ciPB.dirInfo.ioDrDirID = spec->parID; + result = PBGetCatInfoSync(&(pb.ciPB)); + if ( result == noErr ) + { + /* Set frScript in DXInfo */ + /* The negative script constants (smSystemScript, smCurrentScript, and smAllScripts) */ + /* don't make sense on disk, so only use scriptTag if scriptTag >= smRoman */ + /* (smRoman is 0). frScript is valid if high bit is set (see IM-6, page 9-38) */ + pb.ciPB.dirInfo.ioDrFndrInfo.frScript = (scriptTag >= smRoman) ? + ((char)scriptTag | (char)0x80) : + (smRoman); + /* Restore ioDirID field in pb which was changed by PBGetCatInfo */ + pb.ciPB.dirInfo.ioDrDirID = spec->parID; + result = PBSetCatInfoSync(&(pb.ciPB)); + } + } + return ( result ); + } + else +#endif /* !__MACOSSEVENORLATER */ + { + return ( FSpDirCreate(spec, scriptTag, createdDirID) ); + } +} + +/*****************************************************************************/ + +pascal OSErr FSpDeleteCompat(const FSSpec *spec) +{ +#if !__MACOSSEVENORLATER + if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() ) + { + HParamBlockRec pb; + + pb.ioParam.ioVRefNum = spec->vRefNum; + pb.fileParam.ioDirID = spec->parID; + pb.ioParam.ioNamePtr = (StringPtr) &(spec->name); + pb.ioParam.ioVersNum = 0; + return ( PBHDeleteSync(&pb) ); + } + else +#endif /* !__MACOSSEVENORLATER */ + { + return ( FSpDelete(spec) ); + } +} + +/*****************************************************************************/ + +pascal OSErr FSpGetFInfoCompat(const FSSpec *spec, + FInfo *fndrInfo) +{ +#if !__MACOSSEVENORLATER + if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() ) + { + OSErr result; + HParamBlockRec pb; + + pb.fileParam.ioVRefNum = spec->vRefNum; + pb.fileParam.ioDirID = spec->parID; + pb.fileParam.ioNamePtr = (StringPtr) &(spec->name); + pb.fileParam.ioFVersNum = 0; + pb.fileParam.ioFDirIndex = 0; + result = PBHGetFInfoSync(&pb); + *fndrInfo = pb.fileParam.ioFlFndrInfo; + return ( result ); + } + else +#endif /* !__MACOSSEVENORLATER */ + { + return ( FSpGetFInfo(spec, fndrInfo) ); + } +} + +/*****************************************************************************/ + +pascal OSErr FSpSetFInfoCompat(const FSSpec *spec, + const FInfo *fndrInfo) +{ +#if !__MACOSSEVENORLATER + if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() ) + { + OSErr result; + HParamBlockRec pb; + + pb.fileParam.ioVRefNum = spec->vRefNum; + pb.fileParam.ioDirID = spec->parID; + pb.fileParam.ioNamePtr = (StringPtr) &(spec->name); + pb.fileParam.ioFVersNum = 0; + pb.fileParam.ioFDirIndex = 0; + result = PBHGetFInfoSync(&pb); + if ( result == noErr ) + { + pb.fileParam.ioFlFndrInfo = *fndrInfo; + pb.fileParam.ioDirID = spec->parID; + result = PBHSetFInfoSync(&pb); + } + return ( result ); + } + else +#endif /* !__MACOSSEVENORLATER */ + { + return ( FSpSetFInfo(spec, fndrInfo) ); + } +} + +/*****************************************************************************/ + +pascal OSErr FSpSetFLockCompat(const FSSpec *spec) +{ +#if !__MACOSSEVENORLATER + if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() ) + { + HParamBlockRec pb; + + pb.fileParam.ioVRefNum = spec->vRefNum; + pb.fileParam.ioDirID = spec->parID; + pb.fileParam.ioNamePtr = (StringPtr) &(spec->name); + pb.fileParam.ioFVersNum = 0; + return ( PBHSetFLockSync(&pb) ); + } + else +#endif /* !__MACOSSEVENORLATER */ + { + return ( FSpSetFLock(spec) ); + } +} + +/*****************************************************************************/ + +pascal OSErr FSpRstFLockCompat(const FSSpec *spec) +{ +#if !__MACOSSEVENORLATER + if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() ) + { + HParamBlockRec pb; + + pb.fileParam.ioVRefNum = spec->vRefNum; + pb.fileParam.ioDirID = spec->parID; + pb.fileParam.ioNamePtr = (StringPtr) &(spec->name); + pb.fileParam.ioFVersNum = 0; + return ( PBHRstFLockSync(&pb) ); + } + else +#endif /* !__MACOSSEVENORLATER */ + { + return ( FSpRstFLock(spec) ); + } +} + +/*****************************************************************************/ + +pascal OSErr FSpRenameCompat(const FSSpec *spec, + ConstStr255Param newName) +{ +#if !__MACOSSEVENORLATER + if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() ) + { + HParamBlockRec pb; + + pb.ioParam.ioVRefNum = spec->vRefNum; + pb.fileParam.ioDirID = spec->parID; + pb.ioParam.ioNamePtr = (StringPtr) &(spec->name); + pb.ioParam.ioVersNum = 0; + pb.ioParam.ioMisc = (Ptr) newName; + return ( PBHRenameSync(&pb) ); + } + else +#endif /* !__MACOSSEVENORLATER */ + { + return ( FSpRename(spec, newName) ); + } +} + +/*****************************************************************************/ + +pascal OSErr FSpCatMoveCompat(const FSSpec *source, + const FSSpec *dest) +{ +#if !__MACOSSEVENORLATER + if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() ) + { + CMovePBRec pb; + + /* source and destination volume must be the same */ + if ( source->vRefNum != dest->vRefNum ) + return ( paramErr ); + + pb.ioNamePtr = (StringPtr) &(source->name); + pb.ioVRefNum = source->vRefNum; + pb.ioDirID = source->parID; + pb.ioNewDirID = dest->parID; + pb.ioNewName = (StringPtr) &(dest->name); + return ( PBCatMoveSync(&pb) ); + } + else +#endif /* !__MACOSSEVENORLATER */ + { + return ( FSpCatMove(source, dest) ); + } +} + +/*****************************************************************************/ + +/* GenerateUniqueName generates a name that is unique in both dir1 and dir2 */ +/* on the specified volume. Ripped off from Feldman's code. */ + +#if !__MACOSSEVENFIVEORLATER +static OSErr GenerateUniqueName(short volume, + long *startSeed, + long dir1, + long dir2, + StringPtr uniqueName) +{ + OSErr error = noErr; + long i; + CInfoPBRec cinfo; + unsigned char hexStr[16]; + + for ( i = 0; i < 16; ++i ) + { + if ( i < 10 ) + { + hexStr[i] = 0x30 + i; + } + else + { + hexStr[i] = 0x37 + i; + } + } + + cinfo.hFileInfo.ioVRefNum = volume; + cinfo.hFileInfo.ioFDirIndex = 0; + cinfo.hFileInfo.ioNamePtr = uniqueName; + + while ( error != fnfErr ) + { + (*startSeed)++; + cinfo.hFileInfo.ioNamePtr[0] = 8; + for ( i = 1; i <= 8; i++ ) + { + cinfo.hFileInfo.ioNamePtr[i] = hexStr[((*startSeed >> ((8-i)*4)) & 0xf)]; + } + cinfo.hFileInfo.ioDirID = dir1; + error = fnfErr; + for ( i = 1; i <= 2; i++ ) + { + error = error & PBGetCatInfoSync(&cinfo); + cinfo.hFileInfo.ioDirID = dir2; + if ( (error != fnfErr) && (error != noErr) ) + { + return ( error ); + } + } + } + return ( noErr ); +} +#endif /* !__MACOSSEVENFIVEORLATER */ + +/*****************************************************************************/ + +pascal OSErr FSpExchangeFilesCompat(const FSSpec *source, + const FSSpec *dest) +{ +#if !__MACOSSEVENFIVEORLATER + if ( +#if !__MACOSSEVENORLATER + !FSHasFSSpecCalls() || +#endif /* !__MACOSSEVENORLATER */ + !HasFSpExchangeFilesCompatibilityFix() ) + { + HParamBlockRec pb; + CInfoPBRec catInfoSource, catInfoDest; + OSErr result, result2; + Str31 unique1, unique2; + StringPtr unique1Ptr, unique2Ptr, swapola; + GetVolParmsInfoBuffer volInfo; + long theSeed, temp; + + /* Make sure the source and destination are on the same volume */ + if ( source->vRefNum != dest->vRefNum ) + { + result = diffVolErr; + goto errorExit3; + } + + /* Try PBExchangeFiles first since it preserves the file ID reference */ + pb.fidParam.ioNamePtr = (StringPtr) &(source->name); + pb.fidParam.ioVRefNum = source->vRefNum; + pb.fidParam.ioDestNamePtr = (StringPtr) &(dest->name); + pb.fidParam.ioDestDirID = dest->parID; + pb.fidParam.ioSrcDirID = source->parID; + + result = PBExchangeFilesSync(&pb); + + /* Note: The compatibility case won't work for files with *Btree control blocks. */ + /* Right now the only *Btree files are created by the system. */ + if ( result != noErr ) + { + pb.ioParam.ioNamePtr = NULL; + pb.ioParam.ioBuffer = (Ptr) &volInfo; + pb.ioParam.ioReqCount = sizeof(volInfo); + result2 = PBHGetVolParmsSync(&pb); + + /* continue if volume has no fileID support (or no GetVolParms support) */ + if ( (result2 == noErr) && hasFileIDs(&volInfo) ) + { + goto errorExit3; + } + + /* Get the catalog information for each file */ + /* and make sure both files are *really* files */ + catInfoSource.hFileInfo.ioVRefNum = source->vRefNum; + catInfoSource.hFileInfo.ioFDirIndex = 0; + catInfoSource.hFileInfo.ioNamePtr = (StringPtr) &(source->name); + catInfoSource.hFileInfo.ioDirID = source->parID; + catInfoSource.hFileInfo.ioACUser = 0; /* ioACUser used to be filler2 */ + result = PBGetCatInfoSync(&catInfoSource); + if ( result != noErr ) + { + goto errorExit3; + } + if ( (catInfoSource.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 ) + { + result = notAFileErr; + goto errorExit3; + } + + catInfoDest.hFileInfo.ioVRefNum = dest->vRefNum; + catInfoDest.hFileInfo.ioFDirIndex = 0; + catInfoDest.hFileInfo.ioNamePtr = (StringPtr) &(dest->name); + catInfoDest.hFileInfo.ioDirID = dest->parID; + catInfoDest.hFileInfo.ioACUser = 0; /* ioACUser used to be filler2 */ + result = PBGetCatInfoSync(&catInfoDest); + if ( result != noErr ) + { + goto errorExit3; + } + if ( (catInfoDest.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 ) + { + result = notAFileErr; + goto errorExit3; + } + + /* generate 2 filenames that are unique in both directories */ + theSeed = 0x64666A6C; /* a fine unlikely filename */ + unique1Ptr = (StringPtr)&unique1; + unique2Ptr = (StringPtr)&unique2; + + result = GenerateUniqueName(source->vRefNum, &theSeed, source->parID, dest->parID, unique1Ptr); + if ( result != noErr ) + { + goto errorExit3; + } + + GenerateUniqueName(source->vRefNum, &theSeed, source->parID, dest->parID, unique2Ptr); + if ( result != noErr ) + { + goto errorExit3; + } + + /* rename source to unique1 */ + pb.fileParam.ioNamePtr = (StringPtr) &(source->name); + pb.ioParam.ioMisc = (Ptr) unique1Ptr; + pb.ioParam.ioVersNum = 0; + result = PBHRenameSync(&pb); + if ( result != noErr ) + { + goto errorExit3; + } + + /* rename dest to unique2 */ + pb.ioParam.ioMisc = (Ptr) unique2Ptr; + pb.ioParam.ioVersNum = 0; + pb.fileParam.ioNamePtr = (StringPtr) &(dest->name); + pb.fileParam.ioDirID = dest->parID; + result = PBHRenameSync(&pb); + if ( result != noErr ) + { + goto errorExit2; /* back out gracefully by renaming unique1 back to source */ + } + + /* If files are not in same directory, swap their locations */ + if ( source->parID != dest->parID ) + { + /* move source file to dest directory */ + pb.copyParam.ioNamePtr = unique1Ptr; + pb.copyParam.ioNewName = NULL; + pb.copyParam.ioNewDirID = dest->parID; + pb.copyParam.ioDirID = source->parID; + result = PBCatMoveSync((CMovePBPtr) &pb); + if ( result != noErr ) + { + goto errorExit1; /* back out gracefully by renaming both files to original names */ + } + + /* move dest file to source directory */ + pb.copyParam.ioNamePtr = unique2Ptr; + pb.copyParam.ioNewDirID = source->parID; + pb.copyParam.ioDirID = dest->parID; + result = PBCatMoveSync((CMovePBPtr) &pb); + if ( result != noErr) + { + /* life is very bad. We'll at least try to move source back */ + pb.copyParam.ioNamePtr = unique1Ptr; + pb.copyParam.ioNewName = NULL; + pb.copyParam.ioNewDirID = source->parID; + pb.copyParam.ioDirID = dest->parID; + (void) PBCatMoveSync((CMovePBPtr) &pb); /* ignore errors */ + goto errorExit1; /* back out gracefully by renaming both files to original names */ + } + } + + /* Make unique1Ptr point to file in source->parID */ + /* and unique2Ptr point to file in dest->parID */ + /* This lets us fall through to the rename code below */ + swapola = unique1Ptr; + unique1Ptr = unique2Ptr; + unique2Ptr = swapola; + + /* At this point, the files are in their new locations (if they were moved) */ + /* Source is named Unique1 (name pointed to by unique2Ptr) and is in dest->parID */ + /* Dest is named Unique2 (name pointed to by unique1Ptr) and is in source->parID */ + /* Need to swap attributes except mod date and swap names */ + + /* swap the catalog info by re-aiming the CInfoPB's */ + catInfoSource.hFileInfo.ioNamePtr = unique1Ptr; + catInfoDest.hFileInfo.ioNamePtr = unique2Ptr; + + catInfoSource.hFileInfo.ioDirID = source->parID; + catInfoDest.hFileInfo.ioDirID = dest->parID; + + /* Swap the original mod dates with each file */ + temp = catInfoSource.hFileInfo.ioFlMdDat; + catInfoSource.hFileInfo.ioFlMdDat = catInfoDest.hFileInfo.ioFlMdDat; + catInfoDest.hFileInfo.ioFlMdDat = temp; + + /* Here's the swap (ignore errors) */ + (void) PBSetCatInfoSync(&catInfoSource); + (void) PBSetCatInfoSync(&catInfoDest); + + /* rename unique2 back to dest */ +errorExit1: + pb.ioParam.ioMisc = (Ptr) &(dest->name); + pb.ioParam.ioVersNum = 0; + pb.fileParam.ioNamePtr = unique2Ptr; + pb.fileParam.ioDirID = dest->parID; + (void) PBHRenameSync(&pb); /* ignore errors */ + + /* rename unique1 back to source */ +errorExit2: + pb.ioParam.ioMisc = (Ptr) &(source->name); + pb.ioParam.ioVersNum = 0; + pb.fileParam.ioNamePtr = unique1Ptr; + pb.fileParam.ioDirID = source->parID; + (void) PBHRenameSync(&pb); /* ignore errors */ + } +errorExit3: { /* null statement */ } + return ( result ); + } + else +#endif /* !__MACOSSEVENFIVEORLATER */ + { + return ( FSpExchangeFiles(source, dest) ); + } +} + +/*****************************************************************************/ + +/* +** Resource Manager FSp calls +*/ + +/*****************************************************************************/ + +pascal short FSpOpenResFileCompat(const FSSpec *spec, + SignedByte permission) +{ +#if !__MACOSSEVENORLATER + if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() ) + { + return ( HOpenResFile(spec->vRefNum, spec->parID, spec->name, permission) ); + } + else +#endif /* !__MACOSSEVENORLATER */ + { + return ( FSpOpenResFile(spec, permission) ); + } +} + +/*****************************************************************************/ + +pascal void FSpCreateResFileCompat(const FSSpec *spec, + OSType creator, + OSType fileType, + ScriptCode scriptTag) +{ +#if !__MACOSSEVENFIVEONEORLATER + if ( +#if !__MACOSSEVENORLATER + (!FSHasFSSpecCalls() && !QTHasFSSpecCalls()) || +#endif /* !__MACOSSEVENORLATER */ + !HasFSpCreateScriptSupportFix() ) + { + OSErr result; + CInfoPBRec pb; + + HCreateResFile(spec->vRefNum, spec->parID, spec->name); + if ( ResError() == noErr ) + { + /* get info on created item */ + pb.hFileInfo.ioVRefNum = spec->vRefNum; + pb.hFileInfo.ioDirID = spec->parID; + pb.hFileInfo.ioNamePtr = (StringPtr) &(spec->name); + pb.hFileInfo.ioFDirIndex = 0; + result = PBGetCatInfoSync(&pb); + if ( result == noErr ) + { + /* Set fdScript in FXInfo */ + /* The negative script constants (smSystemScript, smCurrentScript, and smAllScripts) */ + /* don't make sense on disk, so only use scriptTag if scriptTag >= smRoman */ + /* (smRoman is 0). fdScript is valid if high bit is set (see IM-6, page 9-38) */ + pb.hFileInfo.ioFlXFndrInfo.fdScript = (scriptTag >= smRoman) ? + ((char)scriptTag | (char)0x80) : + (smRoman); + /* Set creator/fileType */ + pb.hFileInfo.ioFlFndrInfo.fdCreator = creator; + pb.hFileInfo.ioFlFndrInfo.fdType = fileType; + + /* Restore ioDirID field in pb which was changed by PBGetCatInfo */ + pb.hFileInfo.ioDirID = spec->parID; + result = PBSetCatInfoSync(&pb); + } + /* Set ResErr low memory global to result */ + LMSetResErr(result); + } + return; + } + else +#endif /* !__MACOSSEVENFIVEONEORLATER */ + { + FSpCreateResFile(spec, creator, fileType, scriptTag); + return; + } +} + +/*****************************************************************************/