• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/ap/gpl/amule/wxWidgets-2.8.12/src/mac/classic/morefile/
1/*
2	File:		DirectoryCopy.c
3
4	Contains:	A robust, general purpose directory copy routine.
5
6	Version:	MoreFiles
7
8	Copyright:	� 1992-2001 by Apple Computer, Inc., all rights reserved.
9
10	You may incorporate this sample code into your applications without
11	restriction, though the sample code has been provided "AS IS" and the
12	responsibility for its operation is 100% yours.  However, what you are
13	not permitted to do is to redistribute the source as "DSC Sample Code"
14	after having made changes. If you're going to re-distribute the source,
15	we require that you make it clear in the source that the code was
16	descended from Apple Sample Code, but that you've made changes.
17
18	File Ownership:
19
20		DRI:				Apple Macintosh Developer Technical Support
21
22		Other Contact:		Apple Macintosh Developer Technical Support
23							<http://developer.apple.com/bugreporter/>
24
25		Technology:			DTS Sample Code
26
27	Writers:
28
29		(JL)	Jim Luther
30
31	Change History (most recent first):
32
33		 <2>	  2/7/01	JL		Added standard header. Updated names of includes.
34		<1>		12/06/99	JL		MoreFiles 1.5.
35*/
36
37#include <MacTypes.h>
38#include <MacErrors.h>
39#include <MacMemory.h>
40#include <Files.h>
41#include <Script.h>
42#include <Math64.h>
43
44#define	__COMPILINGMOREFILES
45
46#include "MoreFiles.h"
47#include "MoreFilesExtras.h"
48#include "MoreDesktopMgr.h"
49#include "FileCopy.h"
50#include "DirectoryCopy.h"
51
52/*****************************************************************************/
53
54/* local constants */
55
56enum
57{
58	dirCopyBigCopyBuffSize  = 0x00004000,
59	dirCopyMinCopyBuffSize  = 0x00000200
60};
61
62
63/*****************************************************************************/
64
65/* local data structures */
66
67/* The EnumerateGlobals structure is used to minimize the amount of
68** stack space used when recursively calling CopyLevel and to hold
69** global information that might be needed at any time. */
70
71#if PRAGMA_STRUCT_ALIGN
72#pragma options align=mac68k
73#endif
74struct EnumerateGlobals
75{
76	Ptr			copyBuffer;			/* pointer to buffer used for file copy operations */
77	long		bufferSize;			/* the size of the copy buffer */
78	CopyErrProcPtr errorHandler;	/* pointer to error handling function */
79	CopyFilterProcPtr copyFilterProc; /* pointer to filter function */
80	OSErr		error;				/* temporary holder of results - saves 2 bytes of stack each level */
81	Boolean		bailout;			/* set to true to by error handling function if fatal error */
82	short		destinationVRefNum;	/* the destination vRefNum */
83	Str63		itemName;			/* the name of the current item */
84	CInfoPBRec	myCPB;				/* the parameter block used for PBGetCatInfo calls */
85};
86#if PRAGMA_STRUCT_ALIGN
87#pragma options align=reset
88#endif
89
90typedef struct EnumerateGlobals EnumerateGlobals;
91typedef EnumerateGlobals *EnumerateGlobalsPtr;
92
93
94/* The PreflightGlobals structure is used to minimize the amount of
95** stack space used when recursively calling GetLevelSize and to hold
96** global information that might be needed at any time. */
97
98#if PRAGMA_STRUCT_ALIGN
99#pragma options align=mac68k
100#endif
101struct PreflightGlobals
102{
103	OSErr			result;				/* temporary holder of results - saves 2 bytes of stack each level */
104	Str63			itemName;			/* the name of the current item */
105	CInfoPBRec		myCPB;				/* the parameter block used for PBGetCatInfo calls */
106
107	unsigned long	dstBlksPerAllocBlk;	/* the number of 512 byte blocks per allocation block on destination */
108
109	unsigned long	allocBlksNeeded;	/* the total number of allocation blocks needed  */
110
111	unsigned long	tempBlocks;			/* temporary storage for calculations (save some stack space)  */
112	CopyFilterProcPtr copyFilterProc;	/* pointer to filter function */
113};
114#if PRAGMA_STRUCT_ALIGN
115#pragma options align=reset
116#endif
117
118typedef struct PreflightGlobals PreflightGlobals;
119typedef PreflightGlobals *PreflightGlobalsPtr;
120
121/*****************************************************************************/
122
123/* static prototypes */
124
125static	void	GetLevelSize(long currentDirID,
126							 PreflightGlobals *theGlobals);
127
128static	OSErr	PreflightDirectoryCopySpace(short srcVRefNum,
129											long srcDirID,
130											short dstVRefNum,
131											CopyFilterProcPtr copyFilterProc,
132											Boolean *spaceOK);
133
134static	void	CopyLevel(long sourceDirID,
135						  long dstDirID,
136						  EnumerateGlobals *theGlobals);
137
138/*****************************************************************************/
139
140static	void	GetLevelSize(long currentDirID,
141							 PreflightGlobals *theGlobals)
142{
143	short	index = 1;
144
145	do
146	{
147		theGlobals->myCPB.dirInfo.ioFDirIndex = index;
148		theGlobals->myCPB.dirInfo.ioDrDirID = currentDirID;	/* we need to do this every time */
149															/* through, since GetCatInfo  */
150															/* returns ioFlNum in this field */
151		theGlobals->result = PBGetCatInfoSync(&theGlobals->myCPB);
152		if ( theGlobals->result == noErr )
153		{
154			if ( (theGlobals->copyFilterProc == NULL) ||
155				 CallCopyFilterProc(theGlobals->copyFilterProc, &theGlobals->myCPB) ) /* filter if filter proc was supplied */
156			{
157				/* Either there's no filter proc OR the filter proc says to use this item */
158				if ( (theGlobals->myCPB.dirInfo.ioFlAttrib & kioFlAttribDirMask) != 0 )
159				{
160					/* we have a directory */
161
162					GetLevelSize(theGlobals->myCPB.dirInfo.ioDrDirID, theGlobals); /* recurse */
163					theGlobals->result = noErr; /* clear error return on way back */
164				}
165				else
166				{
167					/* We have a file - add its allocation blocks to allocBlksNeeded. */
168					/* Since space on Mac OS disks is always allocated in allocation blocks, */
169					/* this takes into account rounding up to the end of an allocation block. */
170
171					/* get number of 512-byte blocks needed for data fork */
172					if ( ((unsigned long)theGlobals->myCPB.hFileInfo.ioFlLgLen & 0x000001ff) != 0 )
173					{
174						theGlobals->tempBlocks = ((unsigned long)theGlobals->myCPB.hFileInfo.ioFlLgLen >> 9) + 1;
175					}
176					else
177					{
178						theGlobals->tempBlocks = (unsigned long)theGlobals->myCPB.hFileInfo.ioFlLgLen >> 9;
179					}
180					/* now, calculate number of new allocation blocks needed for the data fork and add it to the total */
181					if ( theGlobals->tempBlocks % theGlobals->dstBlksPerAllocBlk )
182					{
183						theGlobals->allocBlksNeeded += (theGlobals->tempBlocks / theGlobals->dstBlksPerAllocBlk) + 1;
184					}
185					else
186					{
187						theGlobals->allocBlksNeeded += theGlobals->tempBlocks / theGlobals->dstBlksPerAllocBlk;
188					}
189
190					/* get number of 512-byte blocks needed for resource fork */
191					if ( ((unsigned long)theGlobals->myCPB.hFileInfo.ioFlRLgLen & 0x000001ff) != 0 )
192					{
193						theGlobals->tempBlocks = ((unsigned long)theGlobals->myCPB.hFileInfo.ioFlRLgLen >> 9) + 1;
194					}
195					else
196					{
197						theGlobals->tempBlocks = (unsigned long)theGlobals->myCPB.hFileInfo.ioFlRLgLen >> 9;
198					}
199					/* now, calculate number of new allocation blocks needed for the resource  fork and add it to the total */
200					if ( theGlobals->tempBlocks % theGlobals->dstBlksPerAllocBlk )
201					{
202						theGlobals->allocBlksNeeded += (theGlobals->tempBlocks / theGlobals->dstBlksPerAllocBlk) + 1;
203					}
204					else
205					{
206						theGlobals->allocBlksNeeded += theGlobals->tempBlocks / theGlobals->dstBlksPerAllocBlk;
207					}
208				}
209			}
210		}
211		++index;
212	} while ( theGlobals->result == noErr );
213}
214
215/*****************************************************************************/
216
217static	OSErr	PreflightDirectoryCopySpace(short srcVRefNum,
218											long srcDirID,
219											short dstVRefNum,
220											CopyFilterProcPtr copyFilterProc,
221											Boolean *spaceOK)
222{
223	XVolumeParam pb;
224	OSErr error;
225	unsigned long dstFreeBlocks;
226	PreflightGlobals theGlobals;
227
228	error = XGetVolumeInfoNoName(NULL, dstVRefNum, &pb);
229	if ( error == noErr )
230	{
231		/* Convert freeBytes to free disk blocks (512-byte blocks) */
232		dstFreeBlocks = U32SetU(U64ShiftRight(pb.ioVFreeBytes, 9));
233
234		/* get allocation block size (always multiple of 512) and divide by 512
235		  to get number of 512-byte blocks per allocation block */
236		theGlobals.dstBlksPerAllocBlk = ((unsigned long)pb.ioVAlBlkSiz >> 9);
237
238		theGlobals.allocBlksNeeded = 0;
239
240		theGlobals.myCPB.dirInfo.ioNamePtr = theGlobals.itemName;
241		theGlobals.myCPB.dirInfo.ioVRefNum = srcVRefNum;
242
243		theGlobals.copyFilterProc = copyFilterProc;
244
245		GetLevelSize(srcDirID, &theGlobals);
246
247		/* Is there enough room on the destination volume for the source file?					*/
248		/* Note:	This will work because the largest number of disk blocks supported			*/
249		/*			on a 2TB volume is 0xffffffff and (allocBlksNeeded * dstBlksPerAllocBlk)	*/
250		/*			will always be less than 0xffffffff.										*/
251		*spaceOK = ((theGlobals.allocBlksNeeded * theGlobals.dstBlksPerAllocBlk) <= dstFreeBlocks);
252	}
253
254	return ( error );
255}
256
257/*****************************************************************************/
258
259static	void	CopyLevel(long sourceDirID,
260						  long dstDirID,
261						  EnumerateGlobals *theGlobals)
262{
263	long currentSrcDirID = 0 ;
264	long newDirID;
265	short index = 1;
266
267	do
268	{
269		/* Get next source item at the current directory level */
270
271		theGlobals->myCPB.dirInfo.ioFDirIndex = index;
272		theGlobals->myCPB.dirInfo.ioDrDirID = sourceDirID;
273		theGlobals->error = PBGetCatInfoSync(&theGlobals->myCPB);
274
275		if ( theGlobals->error == noErr )
276		{
277			if ( (theGlobals->copyFilterProc == NULL) ||
278				 CallCopyFilterProc(theGlobals->copyFilterProc, &theGlobals->myCPB) ) /* filter if filter proc was supplied */
279			{
280				/* Either there's no filter proc OR the filter proc says to use this item */
281
282				/* We have an item.  Is it a file or directory? */
283				if ( (theGlobals->myCPB.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 )
284				{
285					/* We have a directory */
286
287					/* Create a new directory at the destination. No errors allowed! */
288					theGlobals->error = DirCreate(theGlobals->destinationVRefNum, dstDirID, theGlobals->itemName, &newDirID);
289					if ( theGlobals->error == noErr )
290					{
291						/* Save the current source directory ID where we can get it when we come back
292						** from recursion land. */
293						currentSrcDirID = theGlobals->myCPB.dirInfo.ioDrDirID;
294
295						/* Dive again (copy the directory level we just found below this one) */
296						CopyLevel(theGlobals->myCPB.dirInfo.ioDrDirID, newDirID, theGlobals);
297
298						if ( !theGlobals->bailout )
299						{
300							/* Copy comment from old to new directory. */
301							/* Ignore the result because we really don't care if it worked or not. */
302							(void) DTCopyComment(theGlobals->myCPB.dirInfo.ioVRefNum, currentSrcDirID, NULL, theGlobals->destinationVRefNum, newDirID, NULL);
303
304							/* Copy directory attributes (dates, etc.) to newDirID. */
305							/* No errors allowed */
306							theGlobals->error = CopyFileMgrAttributes(theGlobals->myCPB.dirInfo.ioVRefNum, currentSrcDirID, NULL, theGlobals->destinationVRefNum, newDirID, NULL, true);
307
308							/* handle any errors from CopyFileMgrAttributes */
309							if ( theGlobals->error != noErr )
310							{
311								if ( theGlobals->errorHandler != NULL )
312								{
313									theGlobals->bailout =  CallCopyErrProc(theGlobals->errorHandler, theGlobals->error, copyDirFMAttributesOp,
314															theGlobals->myCPB.dirInfo.ioVRefNum, currentSrcDirID, NULL,
315															theGlobals->destinationVRefNum, newDirID, NULL);
316								}
317								else
318								{
319									/* If you don't handle the errors with an error handler, */
320									/* then the copy stops here. */
321									theGlobals->bailout = true;
322								}
323							}
324						}
325					}
326					else	/* error handling for DirCreate */
327					{
328 						/* note that currentSrcDirID has not been initialised when entering this execution path */
329						if ( theGlobals->errorHandler != NULL )
330						{
331							theGlobals->bailout = CallCopyErrProc(theGlobals->errorHandler, theGlobals->error, dirCreateOp,
332														theGlobals->myCPB.dirInfo.ioVRefNum, currentSrcDirID, NULL,
333														theGlobals->destinationVRefNum, dstDirID, theGlobals->itemName);
334						}
335						else
336						{
337							/* If you don't handle the errors with an error handler, */
338							/* then the copy stops here. */
339							theGlobals->bailout = true;
340						}
341					}
342
343					if ( !theGlobals->bailout )
344					{
345						/* clear error return on way back if we aren't bailing out */
346						theGlobals->error = noErr;
347					}
348				}
349				else
350				{
351					/* We have a file, so copy it */
352
353					theGlobals->error = FileCopy(theGlobals->myCPB.hFileInfo.ioVRefNum,
354												 theGlobals->myCPB.hFileInfo.ioFlParID,
355												 theGlobals->itemName,
356												 theGlobals->destinationVRefNum,
357												 dstDirID,
358												 NULL,
359												 NULL,
360												 theGlobals->copyBuffer,
361												 theGlobals->bufferSize,
362												 false);
363
364					/* handle any errors from FileCopy */
365					if ( theGlobals->error != noErr )
366					{
367						if ( theGlobals->errorHandler != NULL )
368						{
369							theGlobals->bailout = CallCopyErrProc(theGlobals->errorHandler, theGlobals->error, fileCopyOp,
370													theGlobals->myCPB.hFileInfo.ioVRefNum, theGlobals->myCPB.hFileInfo.ioFlParID, theGlobals->itemName,
371													theGlobals->destinationVRefNum, dstDirID, NULL);
372							if ( !theGlobals->bailout )
373							{
374								/* If the CopyErrProc handled the problem, clear the error here */
375								theGlobals->error = noErr;
376							}
377						}
378						else
379						{
380							/* If you don't handle the errors with an error handler, */
381							/* then the copy stops here. */
382							theGlobals->bailout = true;
383						}
384					}
385				}
386			}
387		}
388		else
389		{	/* error handling for PBGetCatInfo */
390			/* it's normal to get a fnfErr when indexing; that only means you've hit the end of the directory */
391			if ( theGlobals->error != fnfErr )
392			{
393				if ( theGlobals->errorHandler != NULL )
394				{
395					theGlobals->bailout = CallCopyErrProc(theGlobals->errorHandler, theGlobals->error, getNextItemOp,
396											theGlobals->myCPB.dirInfo.ioVRefNum, sourceDirID, NULL, 0, 0, NULL);
397					if ( !theGlobals->bailout )
398					{
399						/* If the CopyErrProc handled the problem, clear the error here */
400						theGlobals->error = noErr;
401					}
402				}
403				else
404				{
405					/* If you don't handle the errors with an error handler, */
406					/* then the copy stops here. */
407					theGlobals->bailout = true;
408				}
409			}
410		}
411		++index; /* prepare to get next item */
412	} while ( (theGlobals->error == noErr) && (!theGlobals->bailout) ); /* time to fall back a level? */
413}
414
415/*****************************************************************************/
416
417pascal	OSErr	FilteredDirectoryCopy(short srcVRefNum,
418									  long srcDirID,
419									  ConstStr255Param srcName,
420									  short dstVRefNum,
421									  long dstDirID,
422									  ConstStr255Param dstName,
423									  ConstStr255Param copyName,
424									  void *copyBufferPtr,
425									  long copyBufferSize,
426									  Boolean preflight,
427									  CopyErrProcPtr copyErrHandler,
428									  CopyFilterProcPtr copyFilterProc)
429{
430	EnumerateGlobals theGlobals;
431	Boolean	isDirectory;
432	OSErr	error;
433	Boolean ourCopyBuffer = false;
434	Str63	srcDirName, oldDiskName;
435	Boolean spaceOK;
436
437	/* Make sure a copy buffer is allocated. */
438	if ( copyBufferPtr == NULL )
439	{
440		/* The caller didn't supply a copy buffer so grab one from the application heap.
441		** Try to get a big copy buffer, if we can't, try for a 512-byte buffer.
442		** If 512 bytes aren't available, we're in trouble. */
443		copyBufferSize = dirCopyBigCopyBuffSize;
444		copyBufferPtr = NewPtr(copyBufferSize);
445		if ( copyBufferPtr == NULL )
446		{
447			copyBufferSize = dirCopyMinCopyBuffSize;
448			copyBufferPtr = NewPtr(copyBufferSize);
449			if ( copyBufferPtr == NULL )
450			{
451				return ( memFullErr );
452			}
453		}
454		ourCopyBuffer = true;
455	}
456
457	/* Get the real dirID where we're copying from and make sure it is a directory. */
458	error = GetDirectoryID(srcVRefNum, srcDirID, srcName, &srcDirID, &isDirectory);
459	if ( error != noErr )
460	{
461		goto ErrorExit;
462	}
463	if ( !isDirectory )
464	{
465		error = dirNFErr;
466		goto ErrorExit;
467	}
468
469	/* Special case destination if it is the root parent directory. */
470	/* Since you can't create the root directory, this is needed if */
471	/* you want to copy a directory's content to a disk's root directory. */
472	if ( (dstDirID == fsRtParID) && (dstName == NULL) )
473	{
474		dstDirID = fsRtParID;
475		isDirectory = true;
476		error = noErr;
477	}
478	else
479	{
480		/*  Get the real dirID where we're going to put the copy and make sure it is a directory. */
481		error = GetDirectoryID(dstVRefNum, dstDirID, dstName, &dstDirID, &isDirectory);
482		if ( error != noErr )
483		{
484			goto ErrorExit;
485		}
486		if ( !isDirectory )
487		{
488			error =  dirNFErr;
489			goto ErrorExit;
490		}
491	}
492
493	/* Get the real vRefNum of both the source and destination */
494	error = DetermineVRefNum(srcName, srcVRefNum, &srcVRefNum);
495	if ( error != noErr )
496	{
497		goto ErrorExit;
498	}
499	error = DetermineVRefNum(dstName, dstVRefNum, &dstVRefNum);
500	if ( error != noErr )
501	{
502		goto ErrorExit;
503	}
504
505	if ( preflight )
506	{
507		error = PreflightDirectoryCopySpace(srcVRefNum, srcDirID, dstVRefNum, copyFilterProc, &spaceOK);
508		if ( error != noErr )
509		{
510			goto ErrorExit;
511		}
512		if ( !spaceOK )
513		{
514			error = dskFulErr; /* not enough room on destination */
515			goto ErrorExit;
516		}
517	}
518
519	/* Create the new directory in the destination directory with the */
520	/* same name as the source directory. */
521	error = GetDirName(srcVRefNum, srcDirID, srcDirName);
522	if ( error != noErr )
523	{
524		goto ErrorExit;
525	}
526
527	/* Again, special case destination if the destination is the */
528	/* root parent directory. This time, we'll rename the disk to */
529	/* the source directory name. */
530	if ( dstDirID == fsRtParID )
531	{
532		/* Get the current name of the destination disk */
533		error = GetDirName(dstVRefNum, fsRtDirID, oldDiskName);
534		if ( error == noErr )
535		{
536			/* use the copyName as srcDirName if supplied */
537			if ( copyName != NULL )
538			{
539				/* make a copy since copyName is a const input */
540				BlockMoveData(copyName, srcDirName, sizeof(Str31));
541			}
542			/* Shorten the name if it's too long to be the volume name */
543			TruncPString(srcDirName, srcDirName, 27);
544
545			/* Rename the disk */
546			error = HRename(dstVRefNum, fsRtParID, oldDiskName, srcDirName);
547
548			/* and copy to the root directory */
549			dstDirID = fsRtDirID;
550		}
551	}
552	else
553	{
554		/* use the copyName as srcDirName if supplied */
555		error = DirCreate(dstVRefNum, dstDirID, ((copyName != NULL) ? copyName : srcDirName), &dstDirID);
556	}
557	if ( error != noErr )
558	{
559		/* handle any errors from DirCreate */
560		if ( copyErrHandler != NULL )
561		{
562			if ( CallCopyErrProc(copyErrHandler, error, dirCreateOp,
563													srcVRefNum, srcDirID, NULL,
564													dstVRefNum, dstDirID, srcDirName) )
565			{
566				goto ErrorExit;
567			}
568			else
569			{
570				/* If the CopyErrProc handled the problem, clear the error here */
571				/* and continue */
572				error = noErr;
573			}
574		}
575		else
576		{
577			/* If you don't handle the errors with an error handler, */
578			/* then the copy stops here. */
579			goto ErrorExit;
580		}
581	}
582
583	/* dstDirID is now the newly created directory! */
584
585	/* Set up the globals we need to access from the recursive routine. */
586	theGlobals.copyBuffer = (Ptr)copyBufferPtr;
587	theGlobals.bufferSize = copyBufferSize;
588	theGlobals.destinationVRefNum = dstVRefNum; /* so we can get to it always */
589	theGlobals.myCPB.hFileInfo.ioNamePtr = (StringPtr)&theGlobals.itemName;
590	theGlobals.myCPB.hFileInfo.ioVRefNum = srcVRefNum;
591	theGlobals.errorHandler = copyErrHandler;
592	theGlobals.bailout = false;
593	theGlobals.copyFilterProc =  copyFilterProc;
594
595	/* Here we go into recursion land... */
596	CopyLevel(srcDirID, dstDirID, &theGlobals);
597	error = theGlobals.error;	/* get the result */
598
599	if ( !theGlobals.bailout )
600	{
601		/* Copy comment from source to destination directory. */
602		/* Ignore the result because we really don't care if it worked or not. */
603		(void) DTCopyComment(srcVRefNum, srcDirID, NULL, dstVRefNum, dstDirID, NULL);
604
605		/* Copy the File Manager attributes */
606		error = CopyFileMgrAttributes(srcVRefNum, srcDirID, NULL,
607					dstVRefNum, dstDirID, NULL, true);
608
609		/* handle any errors from CopyFileMgrAttributes */
610		if ( (error != noErr) && (copyErrHandler != NULL) )
611		{
612			theGlobals.bailout = CallCopyErrProc(copyErrHandler, error, copyDirFMAttributesOp,
613												srcVRefNum, srcDirID, NULL,
614												dstVRefNum, dstDirID, NULL);
615		}
616	}
617
618ErrorExit:
619	/* Get rid of the copy buffer if we allocated it. */
620	if ( ourCopyBuffer )
621	{
622		DisposePtr((Ptr)copyBufferPtr);
623	}
624
625	return ( error );
626}
627
628/*****************************************************************************/
629
630pascal	OSErr	DirectoryCopy(short srcVRefNum,
631							  long srcDirID,
632							  ConstStr255Param srcName,
633							  short dstVRefNum,
634							  long dstDirID,
635							  ConstStr255Param dstName,
636							  ConstStr255Param copyName,
637							  void *copyBufferPtr,
638							  long copyBufferSize,
639							  Boolean preflight,
640							  CopyErrProcPtr copyErrHandler)
641{
642	return ( FilteredDirectoryCopy(srcVRefNum, srcDirID, srcName,
643								   dstVRefNum, dstDirID, dstName,
644								   copyName,
645								   copyBufferPtr, copyBufferSize, preflight,
646								   copyErrHandler, NULL) );
647}
648
649/*****************************************************************************/
650
651pascal	OSErr	FSpFilteredDirectoryCopy(const FSSpec *srcSpec,
652										 const FSSpec *dstSpec,
653										 ConstStr255Param copyName,
654										 void *copyBufferPtr,
655										 long copyBufferSize,
656										 Boolean preflight,
657										 CopyErrProcPtr copyErrHandler,
658										 CopyFilterProcPtr copyFilterProc)
659{
660	return ( FilteredDirectoryCopy(srcSpec->vRefNum, srcSpec->parID, srcSpec->name,
661								   dstSpec->vRefNum, dstSpec->parID, dstSpec->name,
662								   copyName,
663								   copyBufferPtr, copyBufferSize, preflight,
664								   copyErrHandler, copyFilterProc) );
665}
666
667/*****************************************************************************/
668
669pascal	OSErr	FSpDirectoryCopy(const FSSpec *srcSpec,
670								 const FSSpec *dstSpec,
671								 ConstStr255Param copyName,
672								 void *copyBufferPtr,
673								 long copyBufferSize,
674								 Boolean preflight,
675								 CopyErrProcPtr copyErrHandler)
676{
677	return ( FilteredDirectoryCopy(srcSpec->vRefNum, srcSpec->parID, srcSpec->name,
678								   dstSpec->vRefNum, dstSpec->parID, dstSpec->name,
679								   copyName,
680								   copyBufferPtr, copyBufferSize, preflight,
681								   copyErrHandler, NULL) );
682}
683
684/*****************************************************************************/
685
686