Logo Search packages:      
Sourcecode: xaos version File versions  Download package

FSpCompa.cpp

/*
**    Apple Macintosh Developer Technical Support
**
**    FSSpec compatibility functions.
**
**    by Jim Luther, Apple Developer Technical Support Emeritus
**
**    File:       FSpCompat.c
**
**    Copyright  1992-1998 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.
*/

/*
**    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 <Types.h>
#include <Errors.h>
#include <LowMem.h>
#include <Gestalt.h>
#include <Resources.h>
#include <Script.h>

#define     __COMPILINGMOREFILES

#include "moreextr.h"
#include "fspcompa.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 & ioDirMask) != 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 & ioDirMask) != 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;
      }
}

/*****************************************************************************/

Generated by  Doxygen 1.6.0   Back to index