00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 #include "FSCopyObject.h"
00049 #include "GenLinkedList.h"
00050 #if !TARGET_API_MAC_OSX
00051 #include <UnicodeConverter.h>
00052 #endif
00053 #include <stddef.h>
00054 #include <string.h>
00055 
00056 #pragma mark ----- Tunable Parameters -----
00057 
00058 
00059 
00060 enum {          
00061                  
00062         kDefaultCopyBufferSize  = 256L * 1024,                                  
00063         kMaximumCopyBufferSize  =   2L * 1024 * 1024,
00064         kMinimumCopyBufferSize  = 1024
00065 };
00066 
00067 enum {          
00068         errFSDestInsideSource   = -1234
00069 };
00070 
00071 enum {          
00072                         
00073         kPrivilegesMask                 = kioACAccessUserWriteMask | kioACAccessUserReadMask | kioACAccessUserSearchMask,
00074 
00075                         
00076                         
00077                         
00078                         
00079                         
00080                         
00081         kRWXUserAccessMask              = 0x01C0,
00082         kReadAccessUser                 = 0x0100,
00083         kWriteAccessUser                = 0x0080,
00084         kExecuteAccessUser              = 0x0040,
00085 
00086         kRWXGroupAccessMask             = 0x0038,
00087         kReadAccessGroup                = 0x0020,
00088         kWriteAccessGroup               = 0x0010,
00089         kExecuteAccessGroup             = 0x0008,
00090 
00091         kRWXOtherAccessMask             = 0x0007,
00092         kReadAccessOther                = 0x0004,
00093         kWriteAccessOther               = 0x0002,
00094         kExecuteAccessOther             = 0x0001,
00095 
00096         kDropFolderValue                = kWriteAccessOther | kExecuteAccessOther
00097 };
00098 
00099 #define kNumObjects                     80
00100 
00101 #define VolHasCopyFile(volParms)        (((volParms)->vMAttrib & (1L << bHasCopyFile)) != 0)
00102 
00103 #pragma mark ----- Struct Definitions -----
00104 
00105         
00106         
00107         
00108 struct CopyParams {
00109         void                               *copyBuffer;
00110         ByteCount                               copyBufferSize;
00111         Boolean                         copyingToDropFolder;
00112         Boolean                                 copyingToLocalVolume;
00113         Boolean                                 volHasCopyFile;
00114         DupeAction                              dupeAction;
00115 };
00116 typedef struct CopyParams CopyParams;
00117 
00118         
00119         
00120         
00121 struct FilterParams {
00122         FSCatalogInfoBitmap             whichInfo;
00123         CopyObjectFilterProcPtr filterProcPtr;
00124         Boolean                                 containerChanged;
00125         Boolean                                 wantSpec;
00126         Boolean                                 wantName;
00127         void                               *yourDataPtr;
00128 };
00129 typedef struct FilterParams FilterParams;
00130 
00131         
00132         
00133         
00134         
00135         
00136         
00137 struct ForkTracker {
00138         HFSUniStr255                    forkName;
00139         SInt64                                  forkSize;
00140         SInt16                          forkDestRefNum;
00141 };
00142 typedef struct ForkTracker ForkTracker;
00143 typedef ForkTracker *ForkTrackerPtr;
00144 
00145         
00146         
00147          
00148 struct FolderListData
00149 {
00150         FSRef                                   sourceDirRef;
00151         FSRef                                   destDirRef;
00152         UInt32                                  level;
00153 };
00154 typedef struct FolderListData FolderListData;
00155 
00156         
00157         
00158 struct FSCopyFolderGlobals
00159 {
00160         FSRef                              *sourceDirRef;
00161         FSRef                              *destDirRef;
00162 
00163         FSCatalogInfo              *catInfoList;
00164         FSRef                              *srcRefList;
00165         HFSUniStr255               *nameList;
00166         
00167         GenLinkedList                   folderList;
00168         GenIteratorPtr                  folderListIter;
00169         
00170         CopyParams                         *copyParams;
00171         FilterParams               *filterParams;
00172         Boolean                                 containerChanged;
00173         
00174         ItemCount                               maxLevels;
00175         ItemCount                               currentLevel;
00176 };
00177 typedef struct FSCopyFolderGlobals FSCopyFolderGlobals;
00178 
00179         
00180         
00181 struct FSDeleteObjectGlobals
00182 {
00183         FSCatalogInfo                   catalogInfo;            
00184         ItemCount                               actualObjects;          
00185         OSErr                                   result;                         
00186 };
00187 typedef struct FSDeleteObjectGlobals FSDeleteObjectGlobals;
00188 
00189 #pragma mark ----- Local Prototypes -----
00190 
00191 static OSErr    FSCopyObjectPreflight ( const FSRef                     *source,
00192                                                                                 const FSRef                     *destDir,
00193                                                                                 const DupeAction         dupeAction,
00194                                                                                 FSCatalogInfo           *sourceCatInfo,
00195                                                                                 CopyParams                      *copyParams,            
00196                                                                                 HFSUniStr255            *newObjectName,
00197                                                                                 FSRef                           *deleteMeRef,
00198                                                                                 Boolean                         *isReplacing,
00199                                                                                 Boolean                         *isDirectory );
00200 
00201 static OSErr    FSCopyFile                        (     const FSRef                     *source,
00202                                                                                 const FSRef                     *destDir,
00203                                                                                 const FSCatalogInfo     *sourceCatInfo,
00204                                                                                 const HFSUniStr255      *newFileName,
00205                                                                                 CopyParams                      *copyParams,
00206                                                                                 FilterParams            *filterParams,
00207                                                                                 FSRef                           *newFileRef,            
00208                                                                                 FSSpec                          *newFileSpec );         
00209                                                                 
00210 static OSErr    CopyFile                          (     const FSRef                     *source,
00211                                                                                 FSCatalogInfo           *sourceCatInfo,
00212                                                                                 const FSRef                     *destDir,
00213                                                                                 const HFSUniStr255      *destName,                      
00214                                                                                 CopyParams                      *copyParams,
00215                                                                                 FSRef                           *newRef,                        
00216                                                                                 FSSpec                          *newSpec );                     
00217                                                                 
00218 static  OSErr   FSUsePBHCopyFile          (     const FSRef                     *srcFileRef,
00219                                                                                 const FSRef             *dstDirectoryRef,
00220                                                                                 const HFSUniStr255      *destName,                      
00221                                                                                 TextEncoding            textEncodingHint,
00222                                                                                 FSRef                           *newRef,                        
00223                                                                                 FSSpec                          *newSpec );                     
00224                                                                                         
00225 static OSErr    DoCopyFile                        (     const FSRef             *source,
00226                                                                                 FSCatalogInfo           *sourceCatInfo,
00227                                                                                 const FSRef                     *destDir,
00228                                                                                 const HFSUniStr255      *destName,
00229                                                                                 CopyParams                      *params, 
00230                                                                                 FSRef                           *newRef,                        
00231                                                                                 FSSpec                          *newSpec );                     
00232 
00233 static OSErr    FSCopyFolder              (     const FSRef                     *source,
00234                                                                                 const FSRef                     *destDir,
00235                                                                                 const FSCatalogInfo     *sourceCatInfo,
00236                                                                                 const HFSUniStr255      *newFoldName,
00237                                                                                 CopyParams                      *copyParams,
00238                                                                                 FilterParams            *filterParams,
00239                                                                                 ItemCount                        maxLevels,
00240                                                                                 FSRef                           *outDirRef,                     
00241                                                                                 FSSpec                          *outDirSpec );          
00242 
00243 static OSErr    ProcessFolderList         (     FSCopyFolderGlobals *folderGlobals );
00244 
00245 static OSErr    CopyFolder                        (     FSCopyFolderGlobals     *folderGlobals );
00246 
00247 static OSErr    CheckForDestInsideSrc ( const FSRef                     *source,
00248                                                                                 const FSRef                     *destDir );
00249 
00250 static OSErr    CopyForks                         (     const FSRef                     *source,
00251                                                                                 const FSRef                     *dest,
00252                                                                                 CopyParams                      *params );
00253 
00254 static OSErr    CopyForksToDisk           (     const FSRef                     *source,
00255                                                                                 const FSRef                     *dest,
00256                                                                                 CopyParams                      *params );
00257                                                                                 
00258 static OSErr    CopyForksToDropBox        (     const FSRef                     *source,
00259                                                                                 const FSRef                     *dest,
00260                                                                                 CopyParams                      *params );
00261 
00262 static OSErr    OpenAllForks              (     const FSRef                     *dest,
00263                                                                                 GenLinkedList           *forkList );
00264 
00265 static OSErr    WriteFork                         (     const SInt16            srcRefNum,
00266                                                                                 const SInt16            destRefNum,
00267                                                                                 const CopyParams        *params,
00268                                                                                 const SInt64            forkSize );
00269 
00270 static UInt32   CalcBufferSizeForVol  ( const GetVolParmsInfoBuffer *volParms,
00271                                                                                 UInt32                          volParmsSize );
00272 
00273 static UInt32   BufferSizeForVolSpeed ( UInt32                          volumeBytesPerSecond );
00274 
00275 static OSErr    FSDeleteFolder            (     const FSRef                     *container );
00276 
00277 static void             FSDeleteFolderLevel       (     const FSRef                     *container,
00278                                                                                 FSDeleteObjectGlobals *theGlobals );
00279 
00280 static OSErr    IsDropBox                         (     const FSRef                     *source,
00281                                                                                 Boolean                         *isDropBox );
00282 
00283 static OSErr    GetMagicBusyCreateDate( UTCDateTime                     *date );
00284 
00285 static OSErr    FSGetVRefNum              (     const FSRef                     *ref,
00286                                                                                 FSVolumeRefNum          *vRefNum );
00287 
00288 static OSErr    FSGetVolParms             (     FSVolumeRefNum            volRefNum,
00289                                                                                 UInt32                            bufferSize,
00290                                                                                 GetVolParmsInfoBuffer*volParmsInfo,
00291                                                                                 UInt32                           *actualInfoSize );     
00292 
00293 static OSErr    UniStrToPStr              (     const HFSUniStr255      *uniStr,
00294                                                                                 TextEncoding             textEncodingHint,
00295                                                                                 Boolean                          isVolumeName,
00296                                                                                 Str255                           pStr );
00297 
00298 static OSErr    FSMakeFSRef                       (     FSVolumeRefNum           volRefNum,
00299                                                                                 SInt32                           dirID,
00300                                                                                 ConstStr255Param         name,
00301                                                                                 FSRef                           *ref );
00302                                                 
00303 static OSErr    SetupDestination          (     const FSRef                     *destDir,
00304                                                                                 const DupeAction         dupeAction,
00305                                                                                 HFSUniStr255            *sourceName,
00306                                                                                 FSRef                           *deleteMeRef,
00307                                                                                 Boolean                         *isReplacing);
00308 
00309 static OSErr    GetUniqueName             (     const FSRef                     *destDir,
00310                                                                                 HFSUniStr255            *sourceName );
00311 
00312 static OSErr    GetObjectName             (     const FSRef                     *sourceRef,
00313                                                                                 HFSUniStr255            *sourceName,
00314                                                                                 TextEncoding            *sourceEncoding );
00315                                                                         
00316 static OSErr    CreateFolder              (     const FSRef                     *sourceRef,
00317                                                                                 const FSRef                     *destDirRef,
00318                                                                                 const FSCatalogInfo     *catalogInfo,
00319                                                                                 const HFSUniStr255      *folderName,
00320                                                                                 CopyParams                      *params,
00321                                                                                 FSRef                           *newFSRefPtr,
00322                                                                                 FSSpec                          *newFSSpecPtr );
00323 
00324 static OSErr    DoCreateFolder            (     const FSRef                     *sourceRef,
00325                                                                                 const FSRef                     *destDirRef,
00326                                                                                 const FSCatalogInfo     *catalogInfo,
00327                                                                                 const HFSUniStr255      *folderName,
00328                                                                                 CopyParams                      *params,
00329                                                                                 FSRef                           *newFSRefPtr,
00330                                                                                 FSSpec                          *newFSSpecPtr);
00331 
00332 static pascal void MyDisposeDataProc  ( void                            *pData );
00333 
00334 static pascal void MyCloseForkProc        (     void                            *pData );
00335 
00336 
00337 
00338 
00339 
00340 #pragma mark ----- Copy Objects -----
00341 
00342          
00343 OSErr FSCopyObject(     const FSRef                             *source,
00344                                         const FSRef                             *destDir,
00345                                         ItemCount                               maxLevels,
00346                                         FSCatalogInfoBitmap             whichInfo,
00347                                         DupeAction                              dupeAction,
00348                                         const HFSUniStr255              *newObjectName, 
00349                                         Boolean                                 wantFSSpec,
00350                                         Boolean                                 wantName,
00351                                         CopyObjectFilterProcPtr filterProcPtr,  
00352                                         void                                    *yourDataPtr,   
00353                                         FSRef                                   *newObjectRef,  
00354                                         FSSpec                                  *newObjectSpec) 
00355 {
00356         CopyParams      copyParams;
00357         FilterParams    filterParams;
00358         FSCatalogInfo   sourceCatInfo;
00359         HFSUniStr255    sourceName,
00360                                         tmpObjectName;
00361         FSRef                   tmpObjectRef,
00362                                         deleteMeRef;
00363         Boolean                 isDirectory = false,
00364                                         isReplacing = false;
00365         OSErr                   err = ( source != NULL && destDir != NULL ) ? noErr : paramErr;
00366 
00367                 
00368                 
00369         BlockZero( &deleteMeRef,        sizeof( FSRef ) );
00370         BlockZero( &tmpObjectRef,       sizeof( FSRef ) );
00371 
00372                 
00373         filterParams.whichInfo          = whichInfo;
00374         filterParams.filterProcPtr      = filterProcPtr;
00375         filterParams.wantSpec           = ( filterProcPtr && wantFSSpec );      
00376         filterParams.wantName           = ( filterProcPtr && wantName );        
00377         filterParams.yourDataPtr        = yourDataPtr;
00378         
00379                 
00380                 
00381         if( err == noErr )
00382                 err = GetObjectName( source, &sourceName, NULL );
00383         if( err == noErr )
00384                 tmpObjectName = (newObjectName != NULL) ? *newObjectName : sourceName;
00385 
00386         if( err == noErr )              
00387                 err = FSCopyObjectPreflight( source, destDir, dupeAction, &sourceCatInfo, ©Params, &tmpObjectName, &deleteMeRef, &isReplacing, &isDirectory );
00388                 
00389                                                         
00390         if( err == noErr )
00391         {
00392                 dwarning(( "%s -- err: %d, maxLevels: %u, whichInfo: %08x,\n", __FUNCTION__, err, (unsigned int)maxLevels, (int)whichInfo ));
00393                 dwarning(( "\t\t\t\tdupeAction: %s, wantSpec: %s, wantName: %s,\n", ((dupeAction == kDupeActionReplace) ? "replace" : ((dupeAction == kDupeActionRename) ? "rename" : "standard")), (filterParams.wantSpec)?"yes":"no", (filterParams.wantName)?"yes":"no" ));
00394                 dwarning(( "\t\t\t\tfilterProcPtr: 0x%08x, yourDataPtr: 0x%08x,\n", (unsigned int)filterProcPtr, (unsigned int)yourDataPtr ));
00395                 dwarning(( "\t\t\t\tnewObjectRef: 0x%08x, newObjectSpec: 0x%08x,\n", (unsigned int)newObjectRef, (unsigned int)newObjectSpec ));
00396                 dwarning(( "\t\t\t\tcopyBufferSize: %dkB, isDirectory: %s, isLocal: %s,\n", (int)copyParams.copyBufferSize/1024, (isDirectory)?"yes":"no", (copyParams.copyingToLocalVolume)?"yes":"no" ));
00397                 dwarning(( "\t\t\t\tisDropBox: %s, PBHCopyFileSync supported: %s\n\n", (copyParams.copyingToDropFolder)?"yes":"no", (copyParams.volHasCopyFile)?"yes":"no" ));
00398         }
00399                 
00400         if( err == noErr )              
00401         {               
00402                 if ( isDirectory )
00403                 {               
00404                         err = CheckForDestInsideSrc(source, destDir);                   
00405                         if( err == noErr )
00406                                 err = FSCopyFolder( source, destDir, &sourceCatInfo, &tmpObjectName, ©Params, &filterParams, maxLevels, &tmpObjectRef, newObjectSpec );
00407                 }
00408                 else    
00409                         err = FSCopyFile(source, destDir, &sourceCatInfo, &tmpObjectName, ©Params, &filterParams, &tmpObjectRef, newObjectSpec);
00410         }
00411         
00412                 
00413                 
00414                 
00415                 
00416                 
00417                 
00418                 
00419                 
00420                 
00421         if( copyParams.dupeAction == kDupeActionReplace && isReplacing == true )
00422         {
00423                 dwarning(("%s -- Cleaning up, this might take a moment.  err : %d\n", __FUNCTION__, err));
00424         
00425                 if( err == noErr )
00426                         err = FSDeleteObjects( &deleteMeRef );
00427                 else    
00428                 {               
00429                                 
00430                                 
00431                                 
00432                                 
00433                                 
00434                         myverify_noerr( FSDeleteObjects( &tmpObjectRef ) );
00435                         myverify_noerr( FSRenameUnicode( &deleteMeRef, sourceName.length, sourceName.unicode, sourceCatInfo.textEncodingHint, NULL ) );
00436                 }
00437         }
00438         
00439         if( err == noErr && newObjectRef != NULL )
00440                 *newObjectRef = tmpObjectRef;
00441 
00442                 
00443         if( copyParams.copyBuffer != NULL )
00444                 DisposePtr((char*)copyParams.copyBuffer);
00445                 
00446         mycheck_noerr( err );   
00447         
00448         return err;
00449 }                                
00450 
00451 
00452 
00453         
00454         
00455 static OSErr FSCopyObjectPreflight(     const FSRef                     *source,
00456                                                                         const FSRef                     *destDir,
00457                                                                         const DupeAction        dupeAction,
00458                                                                         FSCatalogInfo           *sourceCatInfo,
00459                                                                         CopyParams              *copyParams,
00460                                                                         HFSUniStr255            *newObjectName,
00461                                                                         FSRef                           *deleteMeRef,
00462                                                                         Boolean                         *isReplacing,
00463                                                                         Boolean                         *isDirectory)
00464 {
00465         GetVolParmsInfoBuffer   srcVolParms,
00466                                                         destVolParms;
00467         UInt32                                  srcVolParmsSize = 0,
00468                                                         destVolParmsSize = 0;
00469         FSVolumeRefNum                  srcVRefNum = 0,
00470                                                         destVRefNum = 0;
00471         OSErr                                   err = ( source            != NULL && destDir     != NULL &&
00472                                                                         sourceCatInfo != NULL && copyParams      != NULL &&
00473                                                                         newObjectName != NULL && deleteMeRef != NULL &&
00474                                                                         isDirectory       != NULL ) ? noErr : paramErr;
00475 
00476         BlockZero( copyParams, sizeof( CopyParams ) );
00477 
00478         copyParams->dupeAction = dupeAction;
00479 
00480         if( err == noErr )              
00481                 err = FSGetCatalogInfo( source, kFSCatInfoSettableInfo, sourceCatInfo, NULL, NULL, NULL );              
00482         if( err == noErr )              
00483                 err = FSGetVRefNum( source, &srcVRefNum );
00484         if( err == noErr )              
00485                 err = FSGetVolParms( srcVRefNum,  sizeof(GetVolParmsInfoBuffer), &srcVolParms, &srcVolParmsSize );                      
00486         if( err == noErr )              
00487                 err = FSGetVRefNum( destDir, &destVRefNum );
00488         if( err == noErr )
00489         {
00490                                                         
00491                 copyParams->copyBufferSize = CalcBufferSizeForVol( &srcVolParms, srcVolParmsSize );
00492         
00493                                                         
00494                                                         
00495                                                         
00496                 if( srcVRefNum != destVRefNum )
00497                 {
00498                         err = FSGetVolParms( destVRefNum, sizeof(GetVolParmsInfoBuffer), &destVolParms, &destVolParmsSize );
00499                         if( err == noErr )
00500                         {
00501                                 ByteCount tmpBufferSize = CalcBufferSizeForVol( &destVolParms, destVolParmsSize );
00502                                 if( tmpBufferSize < copyParams->copyBufferSize )
00503                                         copyParams->copyBufferSize = tmpBufferSize;                             
00504                         }
00505                 }
00506                 else 
00507                         destVolParms = srcVolParms;
00508         }
00509         if( err == noErr )
00510                 err = ((copyParams->copyBuffer = NewPtr( copyParams->copyBufferSize )) != NULL ) ? noErr : MemError();
00511 
00512                 
00513                 
00514                 
00515                 
00516                 
00517         if( err == noErr )              
00518                 err = IsDropBox( destDir, ©Params->copyingToDropFolder );
00519         if( err == noErr )
00520         {
00521                         
00522                 *isDirectory = ((sourceCatInfo->nodeFlags & kFSNodeIsDirectoryMask) != 0);
00523                         
00524                 copyParams->copyingToLocalVolume = (destVolParms.vMServerAdr == 0);
00525                 if( !copyParams->copyingToLocalVolume )
00526                 {
00527                                 
00528                                 
00529                                 
00530 
00531                                 
00532                         copyParams->volHasCopyFile = ( err == noErr && destVolParms.vMServerAdr == srcVolParms.vMServerAdr ) ?
00533                                                                                    VolHasCopyFile(&srcVolParms) : false;
00534                 }       
00535         }
00536         
00537         if( err == noErr )
00538                 err = SetupDestination( destDir, copyParams->dupeAction, newObjectName, deleteMeRef, isReplacing );
00539                 
00540         return err;
00541 }
00542 
00543 #pragma mark ----- Copy Files -----
00544 
00545 
00546 
00547 static OSErr FSCopyFile(        const FSRef                     *source,
00548                                                         const FSRef                     *destDir,
00549                                                         const FSCatalogInfo     *sourceCatInfo,
00550                                                         const HFSUniStr255      *newFileName,
00551                                                         CopyParams                      *copyParams,
00552                                                         FilterParams            *filterParams,
00553                                                         FSRef                           *outFileRef,
00554                                                         FSSpec                          *outFileSpec )
00555 {
00556         FSCatalogInfo   catInfo = *sourceCatInfo;
00557         FSRef                   newFileRef;
00558         FSSpec                  newFileSpec;
00559         OSErr                   err = ( source != NULL && destDir != NULL &&
00560                                                         copyParams != NULL && filterParams != NULL ) ? noErr : paramErr;
00561         
00562                                                         
00563                                                         
00564         
00565         if( err == noErr )              
00566                 err = CopyFile( source, &catInfo, destDir, newFileName, copyParams, &newFileRef, (filterParams->wantSpec || outFileSpec) ? &newFileSpec : NULL );
00567 
00568                 
00569                 
00570         if( filterParams->filterProcPtr != NULL )
00571         {
00572                         
00573                 if( err == noErr && (filterParams->whichInfo & ~kFSCatInfoSettableInfo) != kFSCatInfoNone )
00574                         err = FSGetCatalogInfo( &newFileRef, filterParams->whichInfo & ~kFSCatInfoSettableInfo, &catInfo, NULL, NULL, NULL );   
00575 
00576                 err = CallCopyObjectFilterProc( filterParams->filterProcPtr, false, 0, err, &catInfo, &newFileRef, 
00577                                                                                 (filterParams->wantSpec) ? &newFileSpec : NULL,
00578                                                                                 (filterParams->wantName) ? newFileName : NULL,
00579                                                                                 filterParams->yourDataPtr);
00580         }
00581         
00582         if( err == noErr )
00583         {       
00584                 if( outFileRef != NULL )
00585                         *outFileRef             = newFileRef;
00586                 if( outFileSpec != NULL )
00587                         *outFileSpec    = newFileSpec;
00588         }
00589                 
00590         mycheck_noerr(err);
00591 
00592         return err;
00593 }
00594 
00595 
00596 
00597 static OSErr CopyFile(  const FSRef                     *source,
00598                                                 FSCatalogInfo           *sourceCatInfo,
00599                                                 const FSRef                     *destDir,
00600                                                 const HFSUniStr255      *destName,              
00601                                                 CopyParams                      *params,
00602                                                 FSRef                           *newFile,               
00603                                                 FSSpec                          *newSpec )              
00604 {
00605         OSErr           err = paramErr;
00606         
00607                 
00608         ((FInfo *)(sourceCatInfo->finderInfo))->fdFlags &= ~kHasBeenInited;
00609 
00610                 
00611         if( params->volHasCopyFile == true )
00612                 err = FSUsePBHCopyFile( source, destDir, destName, kTextEncodingUnknown, newFile, newSpec );
00613                         
00614                                                         
00615         if( err != noErr )              
00616                 err = DoCopyFile( source, sourceCatInfo, destDir, destName, params, newFile, newSpec );         
00617 
00618         mycheck_noerr(err);
00619 
00620         return err;
00621 }
00622 
00623 
00624 
00625         
00626 static OSErr FSUsePBHCopyFile(  const FSRef                     *srcFileRef,
00627                                                                 const FSRef                     *dstDirectoryRef,
00628                                                                 const HFSUniStr255      *destName,                      
00629                                                                 TextEncoding            textEncodingHint,
00630                                                                 FSRef                           *newRef,                        
00631                                                                 FSSpec                          *newSpec)                       
00632 {
00633         FSSpec                                  srcFileSpec;
00634         FSCatalogInfo                   catalogInfo;
00635         HParamBlockRec                  pb;
00636         Str255                                  hfsName;
00637         OSErr                                   err = ( srcFileRef != NULL && dstDirectoryRef != NULL ) ? noErr : paramErr;
00638         
00639         if( err == noErr )              
00640                 err = FSGetCatalogInfo(srcFileRef, kFSCatInfoNone, NULL, NULL, &srcFileSpec, NULL);
00641         if( err == noErr )              
00642                 err = FSGetCatalogInfo(dstDirectoryRef, kFSCatInfoVolume | kFSCatInfoNodeID, &catalogInfo, NULL, NULL, NULL);
00643         if( err == noErr )              
00644         {
00645                 pb.copyParam.ioVRefNum          = srcFileSpec.vRefNum;
00646                 pb.copyParam.ioDirID            = srcFileSpec.parID;
00647                 pb.copyParam.ioNamePtr          = (StringPtr)srcFileSpec.name;
00648                 pb.copyParam.ioDstVRefNum       = catalogInfo.volume;
00649                 pb.copyParam.ioNewDirID         = (long)catalogInfo.nodeID;
00650                 pb.copyParam.ioNewName          = NULL;
00651                 if( destName != NULL )
00652                         err = UniStrToPStr( destName, textEncodingHint, false, hfsName );
00653                 pb.copyParam.ioCopyName         = ( destName != NULL && err == noErr ) ? hfsName : NULL;
00654         }
00655         if( err == noErr )                      
00656                 err = PBHCopyFileSync(&pb);
00657         
00658         if( err == noErr )
00659         {
00660                 if( newSpec != NULL )                   
00661                         myverify_noerr(FSMakeFSSpec( pb.copyParam.ioDstVRefNum, pb.copyParam.ioNewDirID, pb.copyParam.ioCopyName, newSpec));
00662                 if( newRef != NULL )    
00663                         myverify_noerr(FSMakeFSRef( pb.copyParam.ioDstVRefNum, pb.copyParam.ioNewDirID, pb.copyParam.ioCopyName, newRef));
00664         }
00665         
00666         if( err != paramErr )           
00667                 mycheck_noerr(err);
00668 
00669         return err;
00670 }
00671 
00672 
00673 
00674         
00675         
00676         
00677         
00678         
00679         
00680         
00681 static OSErr DoCopyFile(const FSRef                     *source,
00682                                                 FSCatalogInfo           *sourceCatInfo,
00683                                                 const FSRef                     *destDir,
00684                                                 const HFSUniStr255      *destName,
00685                                                 CopyParams                      *params,
00686                                                 FSRef                           *newRef,
00687                                                 FSSpec                          *newSpec )
00688 {
00689         FSRef                           dest;
00690         FSSpec                          tmpSpec;
00691         FSPermissionInfo        originalPermissions;
00692         OSType                          originalFileType = 'xxxx';
00693         UInt16                          originalNodeFlags = kFSCatInfoNone;
00694         Boolean                         getSpec;
00695         OSErr                           err = noErr;
00696 
00697                 
00698                 
00699                 
00700                 
00701         if (!params->copyingToDropFolder)
00702         {
00703                         
00704                         
00705                 originalFileType = ((FInfo *) &sourceCatInfo->finderInfo)->fdType;
00706                 ((FInfo *) &sourceCatInfo->finderInfo)->fdType = kFirstMagicBusyFiletype;
00707 
00708                         
00709                         
00710                 originalNodeFlags = sourceCatInfo->nodeFlags;
00711         }
00712         sourceCatInfo->nodeFlags &= ~kFSNodeLockedMask;
00713         
00714                 
00715                 
00716         getSpec = ( ( newSpec != NULL ) || ( !params->copyingToDropFolder && originalFileType == 'slnk' && ((FInfo *) &sourceCatInfo->finderInfo)->fdCreator == 'rhap' ) );
00717         
00718                 
00719                 
00720                 
00721                 
00722         originalPermissions = *((FSPermissionInfo*)sourceCatInfo->permissions);
00723         ((FSPermissionInfo*)sourceCatInfo->permissions)->mode |= kRWXUserAccessMask;
00724         
00725                 
00726                 
00727         if( err == noErr )
00728                 err = FSCreateFileUnicode(destDir, destName->length, destName->unicode, kFSCatInfoSettableInfo, sourceCatInfo, &dest, ( getSpec ) ? &tmpSpec : NULL );
00729         if( err == noErr )      
00730                 err = CopyForks(source, &dest, params);
00731 
00732                 
00733                 
00734                 
00735                 
00736                 
00737         if (err == noErr && !params->copyingToDropFolder)
00738         {
00739                 ((FInfo *) &sourceCatInfo->finderInfo)->fdType = originalFileType;
00740                 sourceCatInfo->nodeFlags  = originalNodeFlags;
00741                 *((FSPermissionInfo*)sourceCatInfo->permissions) = originalPermissions;
00742 
00743                         
00744                         
00745                         
00746                         
00747                         
00748                         
00749                         
00750                         
00751                         
00752                         
00753                         
00754                 if ((originalFileType == 'slnk') && (((FInfo *) &sourceCatInfo->finderInfo)->fdCreator == 'rhap'))
00755                 {                                                               
00756                                                                                 
00757                         err = FSSetCatalogInfo(&dest, kFSCatInfoNodeFlags | kFSCatInfoPermissions, sourceCatInfo);
00758                         if ( err == noErr )                     
00759                                 err = FSpSetFInfo( &tmpSpec, ((FInfo *) &sourceCatInfo->finderInfo) );
00760                 }
00761                 else                                                    
00762                         err = FSSetCatalogInfo(&dest, kFSCatInfoNodeFlags | kFSCatInfoFinderInfo | kFSCatInfoPermissions, sourceCatInfo);
00763         }
00764         
00765                 
00766                 
00767                 
00768                 
00769                 
00770                 
00771         if( err == noErr || err == dupFNErr )
00772         {                       
00773                 if( newRef != NULL )
00774                         *newRef = dest;
00775                 if( newSpec != NULL )
00776                         *newSpec = tmpSpec;
00777         }
00778         else    
00779                 myverify_noerr( FSDeleteObjects(&dest) );
00780 
00781         mycheck_noerr(err);
00782 
00783         return err;
00784 }
00785 
00786 
00787 
00788 #pragma mark ----- Copy Folders -----
00789 
00790 static OSErr FSCopyFolder(      const FSRef                     *source,
00791                                                         const FSRef                     *destDir,
00792                                                         const FSCatalogInfo     *sourceCatInfo,
00793                                                         const HFSUniStr255      *newObjectName,
00794                                                         CopyParams                      *copyParams, 
00795                                                         FilterParams            *filterParams,
00796                                                         ItemCount                       maxLevels,
00797                                                         FSRef                           *outDirRef,
00798                                                         FSSpec                          *outDirSpec )
00799 {
00800         FSCopyFolderGlobals     folderGlobals;
00801         FolderListData          *tmpListData            = NULL;
00802         FSCatalogInfo           catInfo = *sourceCatInfo;
00803         FSRef                           newDirRef;
00804         FSSpec                          newDirSpec;
00805         OSErr                           err;
00806 
00807                                                         
00808         folderGlobals.catInfoList               = (FSCatalogInfo*)      NewPtr( sizeof( FSCatalogInfo ) * kNumObjects );
00809         folderGlobals.srcRefList                = (FSRef*)                      NewPtr( sizeof( FSRef )                 * kNumObjects );
00810         folderGlobals.nameList                  = (HFSUniStr255*)       NewPtr( sizeof( HFSUniStr255 )  * kNumObjects );
00811         folderGlobals.folderListIter    = NULL;
00812         folderGlobals.copyParams                = copyParams;
00813         folderGlobals.filterParams              = filterParams;
00814         folderGlobals.maxLevels                 = maxLevels;
00815         folderGlobals.currentLevel              = 0;
00816 
00817                                                         
00818         err                                                             = ( folderGlobals.catInfoList   != NULL &&
00819                                                                                 folderGlobals.srcRefList        != NULL &&
00820                                                                                 folderGlobals.nameList          != NULL ) ? noErr : memFullErr;
00821 
00822                                                         
00823         InitLinkedList( &folderGlobals.folderList, MyDisposeDataProc );
00824 
00825         if( err == noErr && !copyParams->copyingToDropFolder )
00826                 err = GetMagicBusyCreateDate( &catInfo.createDate );
00827         if( err == noErr )              
00828                 err = DoCreateFolder( source, destDir, &catInfo, newObjectName, folderGlobals.copyParams, &newDirRef, (filterParams->wantSpec || outDirSpec ) ? &newDirSpec : NULL );
00829         
00830                 
00831         if( filterParams->filterProcPtr != NULL )
00832         {
00833                         
00834                 if( err == noErr && (filterParams->whichInfo & ~kFSCatInfoSettableInfo) != kFSCatInfoNone )
00835                         err = FSGetCatalogInfo(&newDirRef, filterParams->whichInfo & ~kFSCatInfoSettableInfo, &catInfo, NULL, NULL, NULL);
00836 
00837                 err = CallCopyObjectFilterProc(filterParams->filterProcPtr, false, folderGlobals.currentLevel,
00838                                                                            err, &catInfo, &newDirRef,
00839                                                                            ( filterParams->wantSpec ) ? &newDirSpec : NULL,
00840                                                                            ( filterParams->wantName ) ? newObjectName : NULL,
00841                                                                              filterParams->yourDataPtr);
00842         }
00843         if( err == noErr )              
00844                 err = ( ( tmpListData = (FolderListData*) NewPtr( sizeof( FolderListData ) ) ) != NULL ) ? noErr : MemError();
00845         if( err == noErr )
00846         {               
00847                 tmpListData->sourceDirRef       = *source;
00848                 tmpListData->destDirRef         = newDirRef;
00849                 tmpListData->level                      = folderGlobals.currentLevel;
00850                         
00851                 err = AddToTail( &folderGlobals.folderList, tmpListData );
00852                 if( err == noErr )                      
00853                         err = ProcessFolderList( &folderGlobals );
00854                 else                                            
00855                         DisposePtr( (char*) tmpListData );
00856         }
00857         
00858         dwarning(("\n%s -- %u folders were found\n", __FUNCTION__, (unsigned int)GetNumberOfItems( &folderGlobals.folderList ) ));
00859         
00860                 
00861         DestroyList( &folderGlobals.folderList );
00862 
00863                 
00864                 
00865                 
00866                 
00867         if( err == noErr && !folderGlobals.copyParams->copyingToDropFolder )
00868                 err = FSSetCatalogInfo( &newDirRef, kFSCatInfoCreateDate | kFSCatInfoPermissions, sourceCatInfo );
00869                                         
00870                                
00871         if( err == noErr )
00872         {
00873                 if( outDirRef != NULL)
00874                         *outDirRef = newDirRef;
00875                 if( outDirSpec != NULL )
00876                         *outDirSpec = newDirSpec;
00877         }
00878 
00879                 
00880         if( folderGlobals.catInfoList )
00881                 DisposePtr( (char*) folderGlobals.catInfoList );
00882         if( folderGlobals.srcRefList )
00883                 DisposePtr( (char*) folderGlobals.srcRefList );
00884         if( folderGlobals.nameList )
00885                 DisposePtr( (char*) folderGlobals.nameList );
00886 
00887         mycheck_noerr(err);     
00888 
00889         return ( err );
00890 }
00891 
00892 
00893 
00894         
00895         
00896         
00897         
00898         
00899         
00900         
00901         
00902 static OSErr ProcessFolderList( FSCopyFolderGlobals *folderGlobals )
00903 {
00904         FolderListData          *folderListData;
00905         OSErr                           err = noErr;
00906         
00907                 
00908         for( InitIterator( &folderGlobals->folderList, &folderGlobals->folderListIter ); folderGlobals->folderListIter != NULL && err == noErr; Next( &folderGlobals->folderListIter ) )
00909         {
00910                         
00911                 folderListData = (FolderListData*) GetData( folderGlobals->folderListIter );
00912                 if( folderListData != NULL )
00913                 {
00914                         #if DEBUG && !TARGET_API_MAC_OS8
00915                         {
00916                                 char    path[1024];             
00917                                 myverify_noerr(FSRefMakePath( &(folderListData->sourceDirRef),  (unsigned char*)path, 1024 ));
00918                                 dwarning(("\n\n%s -- Copying contents of\n\t%s\n", __FUNCTION__, path));
00919                                 myverify_noerr(FSRefMakePath( &(folderListData->destDirRef),    (unsigned char*)path, 1024 ));
00920                                 dwarning(("\t\tto\n\t%s\n", path));
00921                         }       
00922                         #endif
00923                         
00924                                 
00925                         folderGlobals->sourceDirRef     = &(folderListData->sourceDirRef);
00926                         folderGlobals->destDirRef       = &(folderListData->destDirRef);
00927                         folderGlobals->currentLevel = folderListData->level;
00928                         
00929                                 
00930                                 
00931                         err = CopyFolder( folderGlobals );
00932                 }
00933         }
00934         
00935         return err;
00936 }
00937 
00938 
00939 
00940         
00941         
00942         
00943         
00944         
00945 static OSErr CopyFolder( FSCopyFolderGlobals *folderGlobals )
00946 {
00947         GenLinkedList   tmpList;
00948         FolderListData  *tmpListData = NULL;
00949         FilterParams    *filterPtr = folderGlobals->filterParams;
00950         FSIterator              iterator;
00951         FSRef                   newRef;
00952         FSSpec                  newSpec;
00953         UInt32                  actualObjects;
00954         OSErr                   err,
00955                                         junkErr;
00956         int                             i;
00957 
00958                 
00959         InitLinkedList( &tmpList, MyDisposeDataProc);
00960 
00961         err = FSOpenIterator( folderGlobals->sourceDirRef, kFSIterateFlat, &iterator );
00962         if( err == noErr )
00963         {
00964                 do
00965                 {
00966                                 
00967                         err = FSGetCatalogInfoBulk( iterator, kNumObjects, &actualObjects, &filterPtr->containerChanged,
00968                                                                                 kFSCatInfoSettableInfo, folderGlobals->catInfoList, folderGlobals->srcRefList,
00969                                                                                 NULL, folderGlobals->nameList );
00970                         if( ( err == noErr || err == errFSNoMoreItems ) &&
00971                                 ( actualObjects != 0 ) )
00972                         {                       
00973                                 dwarning(("%s -- actualObjects retrieved from FSGetCatalogInfoBulk: %u\n",__FUNCTION__, (unsigned int)actualObjects ));
00974                         
00975                                         
00976                                 for( i = 0; i < actualObjects; i++ )
00977                                 {
00978                                                 
00979                                                 
00980 
00981                                                 
00982                                                 
00983 
00984                                                                               
00985                                         if( ( folderGlobals->catInfoList[i].nodeFlags & kFSNodeIsDirectoryMask ) != 0 )
00986                                         {               
00987                                                 junkErr = CreateFolder( &folderGlobals->srcRefList[i], folderGlobals->destDirRef,
00988                                                                                                 &folderGlobals->catInfoList[i], &folderGlobals->nameList[i],
00989                                                                                                 folderGlobals->copyParams, &newRef, (filterPtr->wantSpec) ? &newSpec : NULL );
00990                                                         
00991                                                         
00992                                                 if( folderGlobals->maxLevels == 0 || (folderGlobals->currentLevel + 1) < folderGlobals->maxLevels )
00993                                                 {
00994                                                         if( junkErr == noErr )          
00995                                                                 junkErr = ( ( tmpListData = (FolderListData*) NewPtr( sizeof( FolderListData ) ) ) != NULL ) ? noErr : MemError();
00996                                                         if( junkErr == noErr )
00997                                                         {                                                       
00998                                                                 tmpListData->sourceDirRef       = folderGlobals->srcRefList[i];
00999                                                                 tmpListData->destDirRef         = newRef;
01000                                                                 tmpListData->level                      = folderGlobals->currentLevel + 1;
01001                                                                 
01002                                                                                                                 
01003                                                                 junkErr = AddToTail( &tmpList, tmpListData );
01004                                                         }
01005                                                                 
01006                                                                 
01007                                                         if( junkErr != noErr && tmpListData != NULL )
01008                                                                 DisposePtr( (char*) tmpListData );
01009                                                 }
01010                                         }
01011                                         else
01012                                         {               
01013                                                 junkErr = CopyFile(     &folderGlobals->srcRefList[i], &folderGlobals->catInfoList[i], 
01014                                                                                         folderGlobals->destDirRef, &folderGlobals->nameList[i], 
01015                                                                                         folderGlobals->copyParams, &newRef, ( filterPtr->wantSpec ) ? &newSpec : NULL );
01016                                         }
01017                                         
01018                                                 
01019                                         if( filterPtr->filterProcPtr != NULL )
01020                                         {
01021                                                 if( junkErr == noErr && (filterPtr->whichInfo & ~kFSCatInfoSettableInfo) != kFSCatInfoNone )    
01022                                                         junkErr = FSGetCatalogInfo( &newRef, filterPtr->whichInfo & ~kFSCatInfoSettableInfo, &folderGlobals->catInfoList[i], NULL, NULL, NULL );
01023 
01024                                                 err = CallCopyObjectFilterProc( filterPtr->filterProcPtr, filterPtr->containerChanged,
01025                                                                                                                 folderGlobals->currentLevel, junkErr,
01026                                                                                                                 &folderGlobals->catInfoList[i], &newRef,
01027                                                                                                                 ( filterPtr->wantSpec ) ? &newSpec : NULL,
01028                                                                                                                 ( filterPtr->wantName ) ? &folderGlobals->nameList[i] : NULL,
01029                                                                                                                 filterPtr->yourDataPtr);
01030                                         }
01031                                 }
01032                         }
01033                 }while( err == noErr );
01034         
01035                         
01036                         
01037                 if( err == errFSNoMoreItems || err == afpAccessDenied )
01038                         err = noErr;
01039 
01040                         
01041                         
01042                         
01043                         
01044                         
01045                 InsertList( &folderGlobals->folderList, &tmpList, folderGlobals->folderListIter );      
01046                         
01047                         
01048                 (void) FSCloseIterator(iterator);
01049         }
01050 
01051         mycheck_noerr( err );   
01052         
01053         return err;
01054 }
01055 
01056 
01057 
01058         
01059         
01060         
01061         
01062         
01063 static OSErr CheckForDestInsideSrc(     const FSRef     *source,
01064                                                                         const FSRef     *destDir)
01065 {
01066         FSRef                   thisDir = *destDir;
01067         FSCatalogInfo   thisDirInfo;
01068         Boolean                 done = false;
01069         OSErr                   err;
01070         
01071         do
01072         {
01073                 err = FSCompareFSRefs(source, &thisDir);
01074                 if (err == noErr)
01075                         err = errFSDestInsideSource;
01076                 else if (err == diffVolErr)
01077                 {
01078                         err = noErr;
01079                         done = true;
01080                 } 
01081                 else if (err == errFSRefsDifferent)
01082                 {
01083                         
01084                         
01085                         
01086                         
01087                         
01088                         
01089                         
01090                         
01091                         
01092                         err = FSGetCatalogInfo(&thisDir, kFSCatInfoParentDirID, &thisDirInfo, NULL, NULL, &thisDir);
01093                         if( ( err == noErr ) && ( thisDirInfo.parentDirID == fsRtParID ) )
01094                                 done = true;
01095                 }
01096         } while ( err == noErr && ! done );
01097         
01098         mycheck_noerr( err );   
01099 
01100         return err;
01101 }
01102 
01103 
01104 
01105 #pragma mark ----- Copy Forks -----
01106 
01107         
01108         
01109         
01110         
01111 static OSErr CopyForks( const FSRef             *source,
01112                                                 const FSRef             *dest,
01113                                                 CopyParams              *params)
01114 {
01115         OSErr                   err;
01116 
01117         err = ( !params->copyingToDropFolder ) ?        CopyForksToDisk         ( source, dest, params ) :
01118                                                                                                 CopyForksToDropBox      ( source, dest, params );
01119 
01120         mycheck_noerr( err );   
01121 
01122         return err;
01123 }
01124 
01125         
01126 static OSErr CopyForksToDisk(   const FSRef     *source,
01127                                                                 const FSRef     *dest,
01128                                                                 CopyParams      *params )
01129 {
01130         HFSUniStr255    forkName;
01131         CatPositionRec  iterator;
01132         SInt64                  forkSize;
01133         SInt16                  srcRefNum,
01134                                         destRefNum;
01135         OSErr                   err;
01136         
01137                 
01138         iterator.initialize = 0;
01139         
01140         do
01141         {
01142                 err = FSIterateForks( source, &iterator, &forkName, &forkSize, NULL );
01143 
01144                         
01145                         
01146                         
01147                         
01148                 if( err == noErr )
01149                         err = FSCreateFork( dest, forkName.length, forkName.unicode );
01150 
01151                         
01152                         
01153                         
01154                         
01155                 if( err == errFSForkExists && !params->copyingToLocalVolume )
01156                         err = noErr;
01157 
01158                         
01159                         
01160 
01161                 if( err == noErr && forkSize > 0 )
01162                 {
01163                         destRefNum = srcRefNum = 0;
01164                         
01165                                                                         
01166                         err = FSOpenFork(dest, forkName.length, forkName.unicode, fsWrPerm, &destRefNum);
01167                         if( err == noErr )              
01168                                 err = FSOpenFork(source, forkName.length, forkName.unicode, fsRdPerm, &srcRefNum);
01169                         if( err == noErr )              
01170                                 err = WriteFork( srcRefNum, destRefNum, params, forkSize );
01171 
01172                         if( destRefNum  != 0 )  
01173                                 myverify_noerr( FSCloseFork( destRefNum ) );
01174                         if( srcRefNum   != 0 )  
01175                                 myverify_noerr( FSCloseFork( srcRefNum ) );
01176                 }                                       
01177         }
01178         while( err == noErr );
01179         
01180         if( err == errFSNoMoreItems )
01181                 err = noErr;
01182 
01183         mycheck_noerr( err );
01184                 
01185         return err;
01186 }
01187 
01188         
01189         
01190 static OSErr CopyForksToDropBox(        const FSRef             *source,
01191                                                                         const FSRef             *dest,
01192                                                                         CopyParams              *params )
01193 {
01194         GenLinkedList   forkList;
01195         GenIteratorPtr  pIter;
01196         ForkTrackerPtr  forkPtr;
01197         SInt16                  srcRefNum;
01198         OSErr                   err;
01199 
01200         InitLinkedList( &forkList, MyCloseForkProc );
01201         
01202                 
01203                 
01204                 
01205         err = OpenAllForks( dest, &forkList );
01206                 
01207                 
01208         for( InitIterator( &forkList, &pIter ); pIter != NULL && err == noErr; Next( &pIter ) )
01209         {
01210                 srcRefNum       = 0;
01211                 forkPtr         = GetData( pIter );
01212                                                                 
01213                 err = FSOpenFork(source, forkPtr->forkName.length, forkPtr->forkName.unicode, fsRdPerm, &srcRefNum);
01214                 if( err == noErr )              
01215                         err = WriteFork( srcRefNum, forkPtr->forkDestRefNum, params, forkPtr->forkSize );
01216 
01217                 if( srcRefNum   != 0 )  
01218                         myverify_noerr( FSCloseFork( srcRefNum ) );
01219         }
01220                 
01221                 
01222         DestroyList( &forkList );
01223 
01224         mycheck_noerr( err );
01225 
01226         return err;
01227 }
01228 
01229 
01230 
01231         
01232         
01233         
01234         
01235         
01236         
01237         
01238 static OSErr OpenAllForks(      const FSRef             *dest,
01239                                                         GenLinkedList   *forkList )
01240 {
01241         ForkTrackerPtr  forkPtr;
01242         HFSUniStr255    forkName;
01243         CatPositionRec  iterator;
01244         SInt64                  forkSize;
01245         OSErr                   err = ( dest != NULL && forkList != NULL ) ? noErr : paramErr;
01246         
01247                 
01248         iterator.initialize = 0;
01249         
01250                 
01251         while( err == noErr )
01252         {
01253                 forkPtr = NULL; 
01254                 
01255                 err = FSIterateForks( dest, &iterator, &forkName, &forkSize, NULL );
01256                 if( err == noErr )
01257                         err = ( forkPtr = (ForkTrackerPtr) NewPtr( sizeof( ForkTracker ) ) ) != NULL ? noErr : MemError();
01258                 if( err == noErr )
01259                 {
01260                         forkPtr->forkName               = forkName;
01261                         forkPtr->forkSize               = forkSize;
01262                         forkPtr->forkDestRefNum = 0;
01263 
01264                                 
01265                                 
01266                                 
01267                                 
01268                         err = FSCreateFork( dest, forkName.length, forkName.unicode );
01269 
01270                                 
01271                                 
01272                                 
01273                                 
01274                                 
01275                                 
01276                                 
01277                                 
01278                                 
01279                         if( err == afpAccessDenied )
01280                                 err = noErr;
01281                                 
01282                                 
01283                         if( err == noErr && forkPtr->forkSize > 0 )
01284                                 err = FSOpenFork( dest, forkPtr->forkName.length, forkPtr->forkName.unicode, fsWrPerm, &forkPtr->forkDestRefNum );
01285 
01286                                 
01287                         if( err == noErr )
01288                                 err = AddToTail( forkList, forkPtr );
01289                 }
01290  
01291                 if( err != noErr && forkPtr != NULL )
01292                         DisposePtr( (char*) forkPtr );
01293         }
01294 
01295         if( err == errFSNoMoreItems )
01296                 err = noErr;
01297 
01298         mycheck_noerr( err );   
01299 
01300         return err;
01301 }
01302 
01303 
01304 
01305         
01306         
01307 static OSErr WriteFork( const SInt16            srcRefNum,
01308                                                 const SInt16            destRefNum,
01309                                                 const CopyParams        *params,
01310                                                 const SInt64            forkSize )
01311 {
01312         UInt64                  bytesRemaining;
01313         UInt64                  bytesToReadThisTime;
01314         UInt64                  bytesToWriteThisTime;
01315         OSErr                   err;
01316         
01317 
01318                       
01319                 
01320                 
01321                 
01322                 
01323                 
01324                 
01325                 
01326         err = FSAllocateFork(destRefNum, kFSAllocNoRoundUpMask, fsFromStart, 0, forkSize, NULL);
01327 
01328                 
01329                 
01330                 
01331                 
01332                 
01333                 
01334                 
01335                 
01336                 
01337                 
01338                 
01339                 
01340                 
01341                 
01342                 
01343                 
01344                 
01345                 
01346                 
01347         bytesRemaining = forkSize;
01348         while( err == noErr && bytesRemaining != 0 )
01349         {
01350                 if( bytesRemaining > params->copyBufferSize )
01351                 {
01352                         bytesToReadThisTime  =  params->copyBufferSize;
01353                         bytesToWriteThisTime =  bytesToReadThisTime;
01354                 }
01355                 else 
01356                 {
01357                         bytesToReadThisTime  =  bytesRemaining;
01358                         bytesToWriteThisTime =  ( params->copyingToLocalVolume )                  ?
01359                                                                         ( (bytesRemaining + 0x01FF ) & ~0x01FF ) : bytesRemaining;
01360                 }
01361                 
01362                 err = FSReadFork( srcRefNum, fsAtMark + noCacheMask, 0, bytesToReadThisTime, params->copyBuffer, NULL );
01363                 if( err == noErr )
01364                         err = FSWriteFork( destRefNum, fsAtMark + noCacheMask, 0, bytesToWriteThisTime, params->copyBuffer, NULL );
01365                 if( err == noErr )
01366                         bytesRemaining -= bytesToReadThisTime;
01367         }
01368         
01369         if (err == noErr && params->copyingToLocalVolume && ( forkSize & 0x01FF ) != 0 )
01370                 err = FSSetForkSize( destRefNum, fsFromStart, forkSize );
01371 
01372         return err;
01373 }
01374 
01375 
01376 
01377 #pragma mark ----- Calculate Buffer Size -----
01378 
01379         
01380         
01381         
01382 static UInt32 CalcBufferSizeForVol(const GetVolParmsInfoBuffer *volParms, UInt32 volParmsSize)
01383 {
01384         UInt32  volumeBytesPerSecond = 0;
01385 
01386         
01387         
01388         
01389         
01390         
01391         mycheck(volParmsSize >= offsetof(GetVolParmsInfoBuffer, vMVolumeGrade));
01392 
01393         
01394         
01395         
01396         
01397         if( ( volParmsSize >= offsetof(GetVolParmsInfoBuffer, vMForeignPrivID) ) &&
01398                 ( volParms->vMVolumeGrade <= 0 ) ) 
01399         {
01400                 volumeBytesPerSecond = -volParms->vMVolumeGrade;
01401         }
01402 
01403         return BufferSizeForVolSpeed(volumeBytesPerSecond);
01404 }
01405 
01406 
01407 
01408         
01409         
01410         
01411         
01412         
01413         
01414         
01415         
01416         
01417         
01418 static UInt32 BufferSizeForVolSpeed(UInt32 volumeBytesPerSecond)
01419 {
01420         ByteCount bufferSize;
01421         
01422         if (volumeBytesPerSecond == 0)
01423                 bufferSize = kDefaultCopyBufferSize;
01424         else
01425         {       
01426                 
01427                 bufferSize = volumeBytesPerSecond / 4;
01428         }
01429         
01430                 
01431         bufferSize &= ~0x01FF;
01432         
01433                 
01434         if (bufferSize < kMinimumCopyBufferSize)
01435                 bufferSize = kMinimumCopyBufferSize;
01436         else if (bufferSize > kMaximumCopyBufferSize)
01437                 bufferSize = kMaximumCopyBufferSize;
01438                 
01439         return bufferSize;
01440 }
01441 
01442 
01443 
01444 #pragma mark ----- Delete Objects -----
01445 
01446 OSErr FSDeleteObjects( const FSRef *source )
01447 {
01448         FSCatalogInfo   catalogInfo;
01449         OSErr                   err = ( source != NULL ) ? noErr : paramErr;
01450         
01451         #if DEBUG && !TARGET_API_MAC_OS8
01452         if( err == noErr )
01453         {
01454                 char    path[1024];             
01455                 myverify_noerr(FSRefMakePath( source,   (unsigned char*)path, 1024 ));
01456                 dwarning(("\n%s -- Deleting %s\n", __FUNCTION__, path));
01457         }       
01458         #endif
01459 
01460                 
01461         if( err == noErr )
01462                 err = FSGetCatalogInfo(source, kFSCatInfoNodeFlags, &catalogInfo, NULL, NULL,NULL);
01463         if( err == noErr && (catalogInfo.nodeFlags & kFSNodeIsDirectoryMask) != 0 )
01464         {               
01465                 err = FSDeleteFolder(source);
01466         }
01467         if( err == noErr && (catalogInfo.nodeFlags & kFSNodeLockedMask) != 0 )  
01468         {               
01469                 catalogInfo.nodeFlags &= ~kFSNodeLockedMask;
01470                 (void) FSSetCatalogInfo(source, kFSCatInfoNodeFlags, &catalogInfo);
01471         }               
01472         if( err == noErr )      
01473                 err = FSDeleteObject(source);
01474 
01475         mycheck_noerr( err );
01476         
01477         return ( err );
01478 }
01479 
01480 
01481 
01482 #pragma mark ----- Delete Folders -----
01483 
01484 static OSErr FSDeleteFolder( const FSRef *container )
01485 {
01486         FSDeleteObjectGlobals   theGlobals;
01487         
01488         theGlobals.result = ( container != NULL ) ? noErr : paramErr;
01489         
01490                 
01491         if( theGlobals.result == noErr )
01492                 FSDeleteFolderLevel(container, &theGlobals);
01493         
01494         mycheck_noerr( theGlobals.result );
01495         
01496         return ( theGlobals.result );
01497 }
01498 
01499 
01500 
01501 static void FSDeleteFolderLevel(const FSRef                             *container,
01502                                                                 FSDeleteObjectGlobals   *theGlobals )
01503 {
01504         FSIterator                                      iterator;
01505         FSRef                                           itemToDelete;
01506         UInt16                                          nodeFlags;
01507 
01508                 
01509         theGlobals->result = FSOpenIterator(container, kFSIterateFlat + kFSIterateDelete, &iterator);
01510         if ( theGlobals->result == noErr )
01511         {
01512                 do      
01513                 {
01514                                 
01515                         theGlobals->result = FSGetCatalogInfoBulk(      iterator, 1, &theGlobals->actualObjects,
01516                                                                                                                 NULL, kFSCatInfoNodeFlags, &theGlobals->catalogInfo,
01517                                                                                                                 &itemToDelete, NULL, NULL);
01518                         if ( (theGlobals->result == noErr) && (theGlobals->actualObjects == 1) )
01519                         {
01520                                         
01521                                 nodeFlags = theGlobals->catalogInfo.nodeFlags;
01522                                 
01523                                         
01524                                 if ( (nodeFlags & kFSNodeIsDirectoryMask) != 0 )
01525                                 {        
01526                                         FSDeleteFolderLevel(&itemToDelete, theGlobals);
01527                                 }
01528                                 if ( theGlobals->result == noErr)                       
01529                                 {       
01530                                         if ( (nodeFlags & kFSNodeLockedMask) != 0 )     
01531                                         {               
01532                                                 theGlobals->catalogInfo.nodeFlags = nodeFlags & ~kFSNodeLockedMask;
01533                                                 (void) FSSetCatalogInfo(&itemToDelete, kFSCatInfoNodeFlags, &theGlobals->catalogInfo);
01534                                         }
01535                                                 
01536                                         theGlobals->result = FSDeleteObject(&itemToDelete);
01537                                 }
01538                         }
01539                 } while ( theGlobals->result == noErr );
01540                         
01541                         
01542                 if ( theGlobals->result == errFSNoMoreItems )
01543                         theGlobals->result = noErr;
01544                         
01545                         
01546                 myverify_noerr(FSCloseIterator(iterator));
01547         }
01548 
01549         mycheck_noerr( theGlobals->result );
01550         
01551         return;
01552 }
01553 
01554 
01555 
01556 #pragma mark ----- Utilities -----
01557 
01558         
01559         
01560 static OSErr IsDropBox( const FSRef* source,
01561                                                 Boolean *isDropBox )
01562 {
01563         FSCatalogInfo                   tmpCatInfo;
01564         FSSpec                                  sourceSpec;
01565         Boolean                                 isDrop = false;
01566         OSErr                                   err;
01567         
01568                 
01569         err = FSGetCatalogInfo(source, kFSCatInfoNodeFlags | kFSCatInfoPermissions, &tmpCatInfo, NULL, &sourceSpec, NULL);
01570         if( err == noErr )      
01571                 err = ((tmpCatInfo.nodeFlags & kFSNodeIsDirectoryMask) != 0) ? noErr : errFSNotAFolder;
01572         if( err == noErr )
01573         {
01574                 HParamBlockRec  hPB;
01575 
01576                 BlockZero( &hPB, sizeof( HParamBlockRec ) );
01577 
01578                 hPB.accessParam.ioNamePtr               = sourceSpec.name;
01579                 hPB.accessParam.ioVRefNum               = sourceSpec.vRefNum;
01580                 hPB.accessParam.ioDirID                 = sourceSpec.parID;
01581                 
01582                         
01583                         
01584                 err = PBHGetDirAccessSync(&hPB);
01585                 if( err == noErr )      
01586                         isDrop = (hPB.accessParam.ioACAccess & kPrivilegesMask) == kioACAccessUserWriteMask;
01587                 else if ( err == paramErr )
01588                 {
01589                         
01590                         
01591                         
01592                         
01593                         
01594                         
01595                         FSPermissionInfo *tmpPerm = (FSPermissionInfo *)tmpCatInfo.permissions;
01596                         isDrop = ((tmpPerm->mode & kRWXOtherAccessMask) == kDropFolderValue);
01597                         err = noErr;
01598                 }
01599         }
01600 
01601         *isDropBox = isDrop;
01602 
01603         mycheck_noerr( err );
01604         
01605         return err;
01606 }
01607 
01608 
01609 
01610         
01611         
01612         
01613         
01614         
01615         
01616         
01617         
01618         
01619         
01620         
01621 static OSErr GetMagicBusyCreateDate( UTCDateTime *date )
01622 {
01623         static  UTCDateTime     magicDate       = { 0, 0xDEADBEEF, 0 };
01624                         OSErr           err             = ( date != NULL ) ? noErr : paramErr;
01625         
01626         if( err == noErr && magicDate.lowSeconds == 0xDEADBEEF )
01627                 err = ConvertLocalTimeToUTC( kMagicBusyCreationDate, &magicDate.lowSeconds );
01628         if( err == noErr )
01629                 *date = magicDate;
01630                 
01631         mycheck_noerr( err );   
01632 
01633         return err;             
01634 }
01635 
01636 
01637 
01638 static OSErr FSGetVRefNum(      const FSRef             *ref,
01639                                                         FSVolumeRefNum  *vRefNum)
01640 {
01641         FSCatalogInfo   catalogInfo;
01642         OSErr                   err = ( ref != NULL && vRefNum != NULL ) ? noErr : paramErr;
01643 
01644         if( err == noErr )      
01645                 err = FSGetCatalogInfo(ref, kFSCatInfoVolume, &catalogInfo, NULL, NULL, NULL);
01646         if( err == noErr )
01647                 *vRefNum = catalogInfo.volume;
01648                 
01649         mycheck_noerr( err );
01650 
01651         return err;
01652 }
01653 
01654  
01655 
01656 static OSErr FSGetVolParms(     FSVolumeRefNum                  volRefNum,
01657                                                         UInt32                                  bufferSize,
01658                                                         GetVolParmsInfoBuffer   *volParmsInfo,
01659                                                         UInt32                                  *actualInfoSize)                
01660 {
01661         HParamBlockRec  pb;
01662         OSErr                   err = ( volParmsInfo != NULL ) ? noErr : paramErr;
01663                 
01664         if( err == noErr )
01665         {
01666                 pb.ioParam.ioNamePtr = NULL;
01667                 pb.ioParam.ioVRefNum = volRefNum;
01668                 pb.ioParam.ioBuffer = (Ptr)volParmsInfo;
01669                 pb.ioParam.ioReqCount = (SInt32)bufferSize;
01670                 err = PBHGetVolParmsSync(&pb);
01671         }
01672                 
01673         if( err == noErr && actualInfoSize != NULL)
01674                 *actualInfoSize = (UInt32)pb.ioParam.ioActCount;
01675 
01676         mycheck_noerr( err );   
01677 
01678         return ( err );
01679 }
01680 
01681 
01682 
01683 
01684 
01685 
01686 
01687 static OSErr UniStrToPStr(      const HFSUniStr255      *uniStr,
01688                                                         TextEncoding             textEncodingHint,
01689                                                         Boolean                          isVolumeName,
01690                                                         Str255                           pStr )
01691 {
01692         UnicodeMapping          uMapping;
01693         UnicodeToTextInfo       utInfo;
01694         ByteCount                       unicodeByteLength = 0;
01695         ByteCount                       unicodeBytesConverted;
01696         ByteCount                       actualPascalBytes;
01697         OSErr                           err = (uniStr != NULL && pStr != NULL) ? noErr : paramErr;
01698 
01699                 
01700         pStr[0] = 0;
01701 
01702         if( err == noErr )
01703                 unicodeByteLength = uniStr->length * sizeof(UniChar); 
01704         if( err == noErr && unicodeByteLength != 0 )
01705         {
01706                         
01707                 if ( kTextEncodingUnknown == textEncodingHint )
01708                 {
01709                         ScriptCode                      script;
01710                         RegionCode                      region;
01711                         
01712                         script = (ScriptCode)GetScriptManagerVariable(smSysScript);
01713                         region = (RegionCode)GetScriptManagerVariable(smRegionCode);
01714                         err = UpgradeScriptInfoToTextEncoding(script, kTextLanguageDontCare, 
01715                                                                                                         region, NULL, &textEncodingHint );
01716                         if ( err == paramErr )
01717                         {               
01718                                 err = UpgradeScriptInfoToTextEncoding(script, kTextLanguageDontCare,
01719                                                                                                                 kTextRegionDontCare, NULL, 
01720                                                                                                                 &textEncodingHint );
01721                         }
01722                         if ( err != noErr )                     
01723                                 textEncodingHint = kTextEncodingMacRoman;               
01724                 }
01725                 
01726                 uMapping.unicodeEncoding        = CreateTextEncoding(   kTextEncodingUnicodeV2_0,
01727                                                                                                                         kUnicodeCanonicalDecompVariant, 
01728                                                                                                                         kUnicode16BitFormat);
01729                 uMapping.otherEncoding          = GetTextEncodingBase(textEncodingHint);
01730                 uMapping.mappingVersion         = kUnicodeUseHFSPlusMapping;
01731         
01732                 err = CreateUnicodeToTextInfo(&uMapping, &utInfo);
01733                 if( err == noErr )
01734                 {
01735                         err = ConvertFromUnicodeToText( utInfo, unicodeByteLength, uniStr->unicode, kUnicodeLooseMappingsMask,
01736                                                                                                 0, NULL, 0, NULL,       
01737                                                                                                 isVolumeName ? kHFSMaxVolumeNameChars : kHFSPlusMaxFileNameChars,
01738                                                                                                 &unicodeBytesConverted, &actualPascalBytes, &pStr[1]);
01739                 }
01740                 if( err == noErr )
01741                         pStr[0] = actualPascalBytes;
01742                 
01743                         
01744                 myverify_noerr(DisposeUnicodeToTextInfo(&utInfo));                              
01745         }
01746         
01747         mycheck_noerr( err );
01748         
01749         return ( err ); 
01750 }
01751 
01752 
01753 
01754         
01755         
01756         
01757 static OSErr FSMakeFSRef(       FSVolumeRefNum          volRefNum,
01758                                                         SInt32                          dirID,
01759                                                         ConstStr255Param        name,
01760                                                         FSRef                           *ref )
01761 {
01762         FSRefParam      pb;
01763         OSErr           err = ( ref != NULL ) ? noErr : paramErr;
01764         
01765         if( err == noErr )
01766         {
01767                 pb.ioVRefNum = volRefNum;
01768                 pb.ioDirID = dirID;
01769                 pb.ioNamePtr = (StringPtr)name;
01770                 pb.newRef = ref;
01771                 err = PBMakeFSRefSync(&pb);
01772         }
01773         
01774         mycheck_noerr( err );   
01775                 
01776         return ( err );
01777 }
01778 
01779 
01780 
01781         
01782         
01783         
01784         
01785         
01786         
01787         
01788         
01789         
01790         
01791         
01792         
01793         
01794 static OSErr SetupDestination(  const FSRef                     *destDir,
01795                                                                 const DupeAction        dupeAction,
01796                                                                 HFSUniStr255            *sourceName,
01797                                                                 FSRef                           *deleteMeRef,
01798                                                                 Boolean                         *isReplacing )
01799 {
01800         FSRef   tmpRef;
01801         OSErr   err;
01802 
01803                 
01804         err = FSMakeFSRefUnicode( destDir, sourceName->length, sourceName->unicode, kTextEncodingUnknown, &tmpRef );
01805         if( err == noErr )
01806         {                                                                                                       
01807                                                                                                                 
01808                 if( dupeAction == kDupeActionReplace )                  
01809                 {
01810                         err = FSRenameUnicode( &tmpRef, 9, (UniChar*)"\0.\0D\0e\0l\0e\0t\0e\0M\0e", kTextEncodingMacRoman, deleteMeRef );
01811                         *isReplacing = ( err == noErr ) ? true : false;
01812                 }
01813                 else if( dupeAction == kDupeActionRename )              
01814                         err = GetUniqueName( destDir, sourceName );     
01815         }
01816         else if ( err == fnfErr )                                                       
01817                 err = noErr;                                                                    
01818         
01819         return err;
01820 }
01821 
01822 
01823 
01824         
01825         
01826         
01827         
01828         
01829         
01830         
01831         
01832 static OSErr GetUniqueName(     const FSRef             *destDir,
01833                                                         HFSUniStr255    *sourceName )
01834 {
01835         HFSUniStr255    tmpName = *sourceName;
01836         FSRef                   tmpRef;
01837         unsigned char   hexStr[17] = "123456789";                               
01838         long                    count = 0;
01839         int                             index;
01840         OSErr                   err;    
01841 
01842                 
01843         for( index = tmpName.length; index >= 0 && tmpName.unicode[index] != (UniChar) '.'; index-- ) {  }              
01844         
01845         if( index <= 0) 
01846                 index = tmpName.length;
01847         else                    
01848                 BlockMoveData( tmpName.unicode + index, tmpName.unicode + index + 2, (tmpName.length - index) * 2 );
01849                 
01850                 
01851         tmpName.unicode[ index ] = (UniChar)' ';
01852                 
01853         tmpName.length += 2;
01854 
01855         do {    
01856                 tmpName.unicode[ index + 1 ] = hexStr[count];
01857                         
01858                 err = FSMakeFSRefUnicode( destDir, tmpName.length, tmpName.unicode, kTextEncodingUnknown, &tmpRef );
01859                 count++;
01860         } while( err == noErr && count < 10 );
01861 
01862         if( err == fnfErr )
01863         {
01864                 err = noErr;
01865                 *sourceName = tmpName;
01866         }
01867         
01868         return err;
01869 }
01870 
01871 
01872 
01873 static OSErr GetObjectName( const FSRef                 *sourceRef,
01874                                                         HFSUniStr255            *sourceName,            
01875                                                         TextEncoding            *sourceEncoding )       
01876 {
01877         FSCatalogInfo           catInfo;
01878         FSCatalogInfoBitmap     whichInfo = (sourceEncoding != NULL) ? kFSCatInfoTextEncoding : kFSCatInfoNone;
01879         OSErr                           err;
01880         
01881         err = FSGetCatalogInfo( sourceRef, whichInfo, &catInfo, sourceName, NULL, NULL );
01882         if( err == noErr && sourceEncoding != NULL )
01883                 *sourceEncoding = catInfo.textEncodingHint;
01884         
01885         return err;
01886 }
01887 
01888 
01889 
01890 static OSErr CreateFolder(      const FSRef                     *sourceRef,
01891                                                         const FSRef                     *destDirRef,
01892                                                         const FSCatalogInfo     *catalogInfo,
01893                                                         const HFSUniStr255      *folderName,
01894                                                         CopyParams                      *params,
01895                                                         FSRef                           *newFSRefPtr,
01896                                                         FSSpec                          *newFSSpecPtr )
01897 {
01898         FSCatalogInfo           tmpCatInfo;
01899         FSPermissionInfo        origPermissions;
01900         OSErr                           err = ( sourceRef != NULL && destDirRef != NULL && catalogInfo != NULL &&
01901                                                                 folderName != NULL && newFSRefPtr != NULL ) ? noErr : paramErr;
01902 
01903         if( err == noErr )
01904         {               
01905                 tmpCatInfo = *catalogInfo;
01906                 origPermissions = *((FSPermissionInfo*)catalogInfo->permissions);
01907         }
01908         if( err == noErr )                      
01909                 err = DoCreateFolder( sourceRef, destDirRef, &tmpCatInfo, folderName, params, newFSRefPtr, newFSSpecPtr ); 
01910         if( err == noErr && !params->copyingToDropFolder )
01911         {                       
01912                 *((FSPermissionInfo*)tmpCatInfo.permissions)    = origPermissions;
01913                 err = FSSetCatalogInfo( newFSRefPtr, kFSCatInfoPermissions, &tmpCatInfo );
01914         }
01915         
01916         mycheck_noerr( err );
01917         
01918         return err;
01919 }
01920 
01921 
01922 
01923 static OSErr DoCreateFolder(const FSRef                 *sourceRef,
01924                                                         const FSRef                     *destDirRef,
01925                                                         const FSCatalogInfo     *catalogInfo,
01926                                                         const HFSUniStr255      *folderName,
01927                                                         CopyParams                      *params,
01928                                                         FSRef                           *newFSRefPtr,
01929                                                         FSSpec                          *newFSSpecPtr)
01930 {
01931         FSCatalogInfo   catInfo = *catalogInfo;
01932         OSErr                   err;
01933         
01934                 
01935         ((FInfo *)(catInfo.finderInfo))->fdFlags &= ~kHasBeenInited;
01936                 
01937                 
01938                 
01939                 
01940         ((FSPermissionInfo*) catInfo.permissions)->mode |= kRWXUserAccessMask;
01941         
01942         err = FSCreateDirectoryUnicode( destDirRef, folderName->length,
01943                                                                         folderName->unicode, kFSCatInfoSettableInfo,
01944                                                                         &catInfo, newFSRefPtr,
01945                                                                         newFSSpecPtr, NULL);
01946                                                                         
01947                 
01948                 
01949                 
01950                 
01951                 
01952         if( err == noErr )
01953                 err = CopyForks( sourceRef, newFSRefPtr, params );
01954         
01955         mycheck_noerr( err );
01956 
01957         return err;
01958 }
01959 
01960 
01961 
01962         
01963         
01964 static pascal void MyDisposeDataProc( void *pData )
01965 {
01966         if( pData != NULL )
01967                 DisposePtr( (char*) pData );
01968 }
01969 
01970 
01971 
01972         
01973         
01974 static pascal void MyCloseForkProc( void *pData )
01975 {
01976         SInt16          refNum;
01977 
01978         if( pData == NULL )
01979                 return;
01980                 
01981         refNum = ((ForkTrackerPtr)pData)->forkDestRefNum;
01982         if( refNum != 0 )
01983                 myverify_noerr( FSCloseFork( refNum ) );        
01984         
01985         DisposePtr( (char*) pData );    
01986 }