4      Contains:   A robust, general purpose directory copy routine. 
   6      Version:    Technology: MoreFiles 
   9      Copyright:  © 1992-2001 by Apple Computer, Inc., all rights reserved. 
  11      Bugs?:      For bug reports, consult the following page on 
  14                      http://developer.apple.com/bugreporter/ 
  19     You may incorporate this sample code into your applications without 
  20     restriction, though the sample code has been provided "AS IS" and the 
  21     responsibility for its operation is 100% yours.  However, what you are 
  22     not permitted to do is to redistribute the source as "DSC Sample Code" 
  23     after having made changes. If you're going to re-distribute the source, 
  24     we require that you make it clear in the source that the code was 
  25     descended from Apple Sample Code, but that you've made changes. 
  28 #ifndef __DIRECTORYCOPY__ 
  29 #define __DIRECTORYCOPY__ 
  39 #include "Optimization.h" 
  54 #if PRAGMA_STRUCT_ALIGN 
  55     #pragma options align=mac68k 
  56 #elif PRAGMA_STRUCT_PACKPUSH 
  58 #elif PRAGMA_STRUCT_PACK 
  62 /*****************************************************************************/ 
  65   getNextItemOp                 
= 1,    /* couldn't access items in this directory - no access privileges */ 
  66   copyDirCommentOp              
= 2,    /* couldn't copy directory's Finder comment */ 
  67   copyDirAccessPrivsOp          
= 3,    /* couldn't copy directory's AFP access privileges */ 
  68   copyDirFMAttributesOp         
= 4,    /* couldn't copy directory's File Manager attributes */ 
  69   dirCreateOp                   
= 5,    /* couldn't create destination directory */ 
  70   fileCopyOp                    
= 6     /* couldn't copy file */ 
  74 /*****************************************************************************/ 
  76 typedef CALLBACK_API( Boolean 
, CopyErrProcPtr 
)(OSErr error
, short failedOperation
, short srcVRefNum
, long srcDirID
, ConstStr255Param srcName
, short dstVRefNum
, long dstDirID
, ConstStr255Param dstName
); 
  78     This is the prototype for the CopyErrProc function DirectoryCopy 
  79     calls if an error condition is detected sometime during the copy.  If 
  80     CopyErrProc returns false, then DirectoryCopy attempts to continue with 
  81     the directory copy operation.  If CopyErrProc returns true, then 
  82     DirectoryCopy stops the directory copy operation. 
  84     error           input:  The error result code that caused CopyErrProc to 
  86     failedOperation input:  The operation that returned an error to 
  88     srcVRefNum      input:  Source volume specification. 
  89     srcDirID        input:  Source directory ID. 
  90     srcName         input:  Source file or directory name, or nil if 
  91                             srcDirID specifies the directory. 
  92     dstVRefNum      input:  Destination volume specification. 
  93     dstDirID        input:  Destination directory ID. 
  94     dstName         input:  Destination file or directory name, or nil if 
  95                             dstDirID specifies the directory. 
  99     Also see:   FilteredDirectoryCopy, FSpFilteredDirectoryCopy, DirectoryCopy, FSpDirectoryCopy 
 101 #define CallCopyErrProc(userRoutine, error, failedOperation, srcVRefNum, srcDirID, srcName, dstVRefNum, dstDirID, dstName) \ 
 102     (*(userRoutine))((error), (failedOperation), (srcVRefNum), (srcDirID), (srcName), (dstVRefNum), (dstDirID), (dstName)) 
 104 /*****************************************************************************/ 
 106 typedef CALLBACK_API( Boolean 
, CopyFilterProcPtr 
)(const CInfoPBRec 
* cpbPtr
); 
 108     This is the prototype for the CopyFilterProc function called by 
 109     FilteredDirectoryCopy and GetLevelSize. If true is returned, 
 110     the file/folder is included in the copy, otherwise it is excluded. 
 112     pb  input:  Points to the CInfoPBRec for the item under consideration. 
 116     Also see:   FilteredDirectoryCopy, FSpFilteredDirectoryCopy 
 118 #define CallCopyFilterProc(userRoutine, cpbPtr) \ 
 119     (*(userRoutine))((cpbPtr)) 
 121 /*****************************************************************************/ 
 124 FilteredDirectoryCopy( 
 127   ConstStr255Param    srcName
, 
 130   ConstStr255Param    dstName
, 
 131   ConstStr255Param    copyName
, 
 132   void *              copyBufferPtr
, 
 135   CopyErrProcPtr      copyErrHandler
, 
 136   CopyFilterProcPtr   copyFilterProc
); 
 140     The FilteredDirectoryCopy function makes a copy of a directory 
 141     structure in a new location. If copyBufferPtr <> NIL, it points to 
 142     a buffer of copyBufferSize that is used to copy files data. The 
 143     larger the supplied buffer, the faster the copy. If 
 144     copyBufferPtr = NIL, then this routine allocates a buffer in the 
 145     application heap. If you pass a copy buffer to this routine, make 
 146     its size a multiple of 512 ($200) bytes for optimum performance. 
 148     The optional copyFilterProc parameter lets a routine you define 
 149     decide what files or directories are copied to the destination. 
 151     FilteredDirectoryCopy normally creates a new directory *in* the 
 152     specified destination directory and copies the source directory's 
 153     content into the new directory. However, if root parent directory 
 154     (fsRtParID) is passed as the dstDirID parameter and NULL is 
 155     passed as the dstName parameter, DirectoryCopy renames the 
 156     destination volume to the source directory's name (truncating 
 157     if the name is longer than 27 characters) and copies the source 
 158     directory's content into the destination volume's root directory. 
 159     This special case is supported by FilteredDirectoryCopy, but 
 160     not by FSpFilteredDirectoryCopy since with FSpFilteredDirectoryCopy, 
 161     the dstName parameter can not be NULL. 
 163     srcVRefNum      input:  Source volume specification. 
 164     srcDirID        input:  Source directory ID. 
 165     srcName         input:  Source directory name, or nil if 
 166                             srcDirID specifies the directory. 
 167     dstVRefNum      input:  Destination volume specification. 
 168     dstDirID        input:  Destination directory ID. 
 169     dstName         input:  Destination directory name, or nil if 
 170                             dstDirID specifies the directory. 
 171     copyName        input:  Points to the new directory name if the directory 
 172                             is to be renamed or nil if the directory isn't to 
 174     copyBufferPtr   input:  Points to a buffer of copyBufferSize that 
 175                             is used the i/o buffer for the copy or 
 176                             nil if you want DirectoryCopy to allocate its 
 177                             own buffer in the application heap. 
 178     copyBufferSize  input:  The size of the buffer pointed to 
 180     preflight       input:  If true, DirectoryCopy makes sure there are 
 181                             enough allocation blocks on the destination 
 182                             volume to hold the directory's files before 
 184     copyErrHandler  input:  A pointer to the routine you want called if an 
 185                             error condition is detected during the copy, or 
 186                             nil if you don't want to handle error conditions. 
 187                             If you don't handle error conditions, the first 
 188                             error will cause the copy to quit and 
 189                             DirectoryCopy will return the error. 
 190                             Error handling is recommended... 
 191     copyFilterProc  input:  A pointer to the filter routine you want called 
 192                             for each item in the source directory, or NULL 
 193                             if you don't want to filter. 
 197         readErr             Ð19     Driver does not respond to read requests 
 198         writErr             Ð20     Driver does not respond to write requests 
 199         badUnitErr          Ð21     Driver reference number does not 
 201         unitEmptyErr        Ð22     Driver reference number specifies a 
 202                                     nil handle in unit table 
 203         abortErr            Ð27     Request aborted by KillIO 
 204         notOpenErr          Ð28     Driver not open 
 205         dskFulErr           -34     Destination volume is full 
 206         nsvErr              -35     No such volume 
 208         bdNamErr            -37     Bad filename 
 209         tmfoErr             -42     Too many files open 
 210         fnfErr              -43     Source file not found, or destination 
 211                                     directory does not exist 
 212         wPrErr              -44     Volume locked by hardware 
 213         fLckdErr            -45     File is locked 
 214         vLckdErr            -46     Destination volume is read-only 
 215         fBsyErr             -47     The source or destination file could 
 216                                     not be opened with the correct access 
 218         dupFNErr            -48     Destination file already exists 
 219         opWrErr             -49     File already open for writing 
 220         paramErr            -50     No default volume or function not 
 222         permErr             -54     File is already open and cannot be opened using specified deny modes 
 223         memFullErr          -108    Copy buffer could not be allocated 
 224         dirNFErr            -120    Directory not found or incomplete pathname 
 225         wrgVolTypErr        -123    Function not supported by volume 
 226         afpAccessDenied     -5000   User does not have the correct access 
 227         afpDenyConflict     -5006   The source or destination file could 
 228                                     not be opened with the correct access 
 230         afpObjectTypeErr    -5025   Source is a directory, directory not found 
 231                                     or incomplete pathname 
 235     Also see:   CopyErrProcPtr, CopyFilterProcPtr, FSpFilteredDirectoryCopy, 
 236                 DirectoryCopy, FSpDirectoryCopy, FileCopy, FSpFileCopy 
 239 /*****************************************************************************/ 
 242 FSpFilteredDirectoryCopy( 
 243   const FSSpec 
*      srcSpec
, 
 244   const FSSpec 
*      dstSpec
, 
 245   ConstStr255Param    copyName
, 
 246   void *              copyBufferPtr
, 
 249   CopyErrProcPtr      copyErrHandler
, 
 250   CopyFilterProcPtr   copyFilterProc
); 
 254     The FSpFilteredDirectoryCopy function makes a copy of a directory 
 255     structure in a new location. If copyBufferPtr <> NIL, it points to 
 256     a buffer of copyBufferSize that is used to copy files data. The 
 257     larger the supplied buffer, the faster the copy. If 
 258     copyBufferPtr = NIL, then this routine allocates a buffer in the 
 259     application heap. If you pass a copy buffer to this routine, make 
 260     its size a multiple of 512 ($200) bytes for optimum performance. 
 262     The optional copyFilterProc parameter lets a routine you define 
 263     decide what files or directories are copied to the destination. 
 265     srcSpec         input:  An FSSpec record specifying the directory to copy. 
 266     dstSpec         input:  An FSSpec record specifying destination directory 
 268     copyName        input:  Points to the new directory name if the directory 
 269                             is to be renamed or nil if the directory isn't to 
 271     copyBufferPtr   input:  Points to a buffer of copyBufferSize that 
 272                             is used the i/o buffer for the copy or 
 273                             nil if you want DirectoryCopy to allocate its 
 274                             own buffer in the application heap. 
 275     copyBufferSize  input:  The size of the buffer pointed to 
 277     preflight       input:  If true, FSpDirectoryCopy makes sure there are 
 278                             enough allocation blocks on the destination 
 279                             volume to hold the directory's files before 
 281     copyErrHandler  input:  A pointer to the routine you want called if an 
 282                             error condition is detected during the copy, or 
 283                             nil if you don't want to handle error conditions. 
 284                             If you don't handle error conditions, the first 
 285                             error will cause the copy to quit and 
 286                             DirectoryCopy will return the error. 
 287                             Error handling is recommended... 
 288     copyFilterProc  input:  A pointer to the filter routine you want called 
 289                             for each item in the source directory, or NULL 
 290                             if you don't want to filter. 
 294         readErr             Ð19     Driver does not respond to read requests 
 295         writErr             Ð20     Driver does not respond to write requests 
 296         badUnitErr          Ð21     Driver reference number does not 
 298         unitEmptyErr        Ð22     Driver reference number specifies a 
 299                                     nil handle in unit table 
 300         abortErr            Ð27     Request aborted by KillIO 
 301         notOpenErr          Ð28     Driver not open 
 302         dskFulErr           -34     Destination volume is full 
 303         nsvErr              -35     No such volume 
 305         bdNamErr            -37     Bad filename 
 306         tmfoErr             -42     Too many files open 
 307         fnfErr              -43     Source file not found, or destination 
 308                                     directory does not exist 
 309         wPrErr              -44     Volume locked by hardware 
 310         fLckdErr            -45     File is locked 
 311         vLckdErr            -46     Destination volume is read-only 
 312         fBsyErr             -47     The source or destination file could 
 313                                     not be opened with the correct access 
 315         dupFNErr            -48     Destination file already exists 
 316         opWrErr             -49     File already open for writing 
 317         paramErr            -50     No default volume or function not 
 319         permErr             -54     File is already open and cannot be opened using specified deny modes 
 320         memFullErr          -108    Copy buffer could not be allocated 
 321         dirNFErr            -120    Directory not found or incomplete pathname 
 322         wrgVolTypErr        -123    Function not supported by volume 
 323         afpAccessDenied     -5000   User does not have the correct access 
 324         afpDenyConflict     -5006   The source or destination file could 
 325                                     not be opened with the correct access 
 327         afpObjectTypeErr    -5025   Source is a directory, directory not found 
 328                                     or incomplete pathname 
 332     Also see:   CopyErrProcPtr, CopyFilterProcPtr, FilteredDirectoryCopy, 
 333                 DirectoryCopy, FSpDirectoryCopy, FileCopy, FSpFileCopy 
 336 /*****************************************************************************/ 
 342   ConstStr255Param   srcName
, 
 345   ConstStr255Param   dstName
, 
 346   ConstStr255Param   copyName
, 
 347   void *             copyBufferPtr
, 
 350   CopyErrProcPtr     copyErrHandler
); 
 354     The DirectoryCopy function makes a copy of a directory structure in a 
 355     new location. If copyBufferPtr <> NIL, it points to a buffer of 
 356     copyBufferSize that is used to copy files data.  The larger the 
 357     supplied buffer, the faster the copy.  If copyBufferPtr = NIL, then this 
 358     routine allocates a buffer in the application heap. If you pass a 
 359     copy buffer to this routine, make its size a multiple of 512 
 360     ($200) bytes for optimum performance. 
 362     DirectoryCopy normally creates a new directory *in* the specified 
 363     destination directory and copies the source directory's content into 
 364     the new directory. However, if root parent directory (fsRtParID) 
 365     is passed as the dstDirID parameter and NULL is passed as the 
 366     dstName parameter, DirectoryCopy renames the destination volume to 
 367     the source directory's name (truncating if the name is longer than 
 368     27 characters) and copies the source directory's content into the 
 369     destination volume's root directory. This special case is supported 
 370     by DirectoryCopy, but not by FSpDirectoryCopy since with 
 371     FSpDirectoryCopy, the dstName parameter can not be NULL. 
 373     srcVRefNum      input:  Source volume specification. 
 374     srcDirID        input:  Source directory ID. 
 375     srcName         input:  Source directory name, or nil if 
 376                             srcDirID specifies the directory. 
 377     dstVRefNum      input:  Destination volume specification. 
 378     dstDirID        input:  Destination directory ID. 
 379     dstName         input:  Destination directory name, or nil if 
 380                             dstDirID specifies the directory. 
 381     copyName        input:  Points to the new directory name if the directory 
 382                             is to be renamed or nil if the directory isn't to 
 384     copyBufferPtr   input:  Points to a buffer of copyBufferSize that 
 385                             is used the i/o buffer for the copy or 
 386                             nil if you want DirectoryCopy to allocate its 
 387                             own buffer in the application heap. 
 388     copyBufferSize  input:  The size of the buffer pointed to 
 390     preflight       input:  If true, DirectoryCopy makes sure there are 
 391                             enough allocation blocks on the destination 
 392                             volume to hold the directory's files before 
 394     copyErrHandler  input:  A pointer to the routine you want called if an 
 395                             error condition is detected during the copy, or 
 396                             nil if you don't want to handle error conditions. 
 397                             If you don't handle error conditions, the first 
 398                             error will cause the copy to quit and 
 399                             DirectoryCopy will return the error. 
 400                             Error handling is recommended... 
 404         readErr             Ð19     Driver does not respond to read requests 
 405         writErr             Ð20     Driver does not respond to write requests 
 406         badUnitErr          Ð21     Driver reference number does not 
 408         unitEmptyErr        Ð22     Driver reference number specifies a 
 409                                     nil handle in unit table 
 410         abortErr            Ð27     Request aborted by KillIO 
 411         notOpenErr          Ð28     Driver not open 
 412         dskFulErr           -34     Destination volume is full 
 413         nsvErr              -35     No such volume 
 415         bdNamErr            -37     Bad filename 
 416         tmfoErr             -42     Too many files open 
 417         fnfErr              -43     Source file not found, or destination 
 418                                     directory does not exist 
 419         wPrErr              -44     Volume locked by hardware 
 420         fLckdErr            -45     File is locked 
 421         vLckdErr            -46     Destination volume is read-only 
 422         fBsyErr             -47     The source or destination file could 
 423                                     not be opened with the correct access 
 425         dupFNErr            -48     Destination file already exists 
 426         opWrErr             -49     File already open for writing 
 427         paramErr            -50     No default volume or function not 
 429         permErr             -54     File is already open and cannot be opened using specified deny modes 
 430         memFullErr          -108    Copy buffer could not be allocated 
 431         dirNFErr            -120    Directory not found or incomplete pathname 
 432         wrgVolTypErr        -123    Function not supported by volume 
 433         afpAccessDenied     -5000   User does not have the correct access 
 434         afpDenyConflict     -5006   The source or destination file could 
 435                                     not be opened with the correct access 
 437         afpObjectTypeErr    -5025   Source is a directory, directory not found 
 438                                     or incomplete pathname 
 442     Also see:   CopyErrProcPtr, FSpDirectoryCopy, FilteredDirectoryCopy, 
 443                 FSpFilteredDirectoryCopy, FileCopy, FSpFileCopy 
 446 /*****************************************************************************/ 
 450   const FSSpec 
*     srcSpec
, 
 451   const FSSpec 
*     dstSpec
, 
 452   ConstStr255Param   copyName
, 
 453   void *             copyBufferPtr
, 
 456   CopyErrProcPtr     copyErrHandler
); 
 460     The FSpDirectoryCopy function makes a copy of a directory structure in a 
 461     new location. If copyBufferPtr <> NIL, it points to a buffer of 
 462     copyBufferSize that is used to copy files data.  The larger the 
 463     supplied buffer, the faster the copy.  If copyBufferPtr = NIL, then this 
 464     routine allocates a buffer in the application heap. If you pass a 
 465     copy buffer to this routine, make its size a multiple of 512 
 466     ($200) bytes for optimum performance. 
 468     srcSpec         input:  An FSSpec record specifying the directory to copy. 
 469     dstSpec         input:  An FSSpec record specifying destination directory 
 471     copyName        input:  Points to the new directory name if the directory 
 472                             is to be renamed or nil if the directory isn't to 
 474     copyBufferPtr   input:  Points to a buffer of copyBufferSize that 
 475                             is used the i/o buffer for the copy or 
 476                             nil if you want DirectoryCopy to allocate its 
 477                             own buffer in the application heap. 
 478     copyBufferSize  input:  The size of the buffer pointed to 
 480     preflight       input:  If true, FSpDirectoryCopy makes sure there are 
 481                             enough allocation blocks on the destination 
 482                             volume to hold the directory's files before 
 484     copyErrHandler  input:  A pointer to the routine you want called if an 
 485                             error condition is detected during the copy, or 
 486                             nil if you don't want to handle error conditions. 
 487                             If you don't handle error conditions, the first 
 488                             error will cause the copy to quit and 
 489                             DirectoryCopy will return the error. 
 490                             Error handling is recommended... 
 494         readErr             Ð19     Driver does not respond to read requests 
 495         writErr             Ð20     Driver does not respond to write requests 
 496         badUnitErr          Ð21     Driver reference number does not 
 498         unitEmptyErr        Ð22     Driver reference number specifies a 
 499                                     nil handle in unit table 
 500         abortErr            Ð27     Request aborted by KillIO 
 501         notOpenErr          Ð28     Driver not open 
 502         dskFulErr           -34     Destination volume is full 
 503         nsvErr              -35     No such volume 
 505         bdNamErr            -37     Bad filename 
 506         tmfoErr             -42     Too many files open 
 507         fnfErr              -43     Source file not found, or destination 
 508                                     directory does not exist 
 509         wPrErr              -44     Volume locked by hardware 
 510         fLckdErr            -45     File is locked 
 511         vLckdErr            -46     Destination volume is read-only 
 512         fBsyErr             -47     The source or destination file could 
 513                                     not be opened with the correct access 
 515         dupFNErr            -48     Destination file already exists 
 516         opWrErr             -49     File already open for writing 
 517         paramErr            -50     No default volume or function not 
 519         permErr             -54     File is already open and cannot be opened using specified deny modes 
 520         memFullErr          -108    Copy buffer could not be allocated 
 521         dirNFErr            -120    Directory not found or incomplete pathname 
 522         wrgVolTypErr        -123    Function not supported by volume 
 523         afpAccessDenied     -5000   User does not have the correct access 
 524         afpDenyConflict     -5006   The source or destination file could 
 525                                     not be opened with the correct access 
 527         afpObjectTypeErr    -5025   Source is a directory, directory not found 
 528                                     or incomplete pathname 
 532     Also see:   CopyErrProcPtr, DirectoryCopy, FilteredDirectoryCopy, 
 533                 FSpFilteredDirectoryCopy, FileCopy, FSpFileCopy 
 536 /*****************************************************************************/ 
 538 #include "OptimizationEnd.h" 
 540 #if PRAGMA_STRUCT_ALIGN 
 541     #pragma options align=reset 
 542 #elif PRAGMA_STRUCT_PACKPUSH 
 544 #elif PRAGMA_STRUCT_PACK 
 548 #ifdef PRAGMA_IMPORT_OFF 
 558 #endif /* __DIRECTORYCOPY__ */