latest CW additions
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@1561 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
291a8f20b3
commit
2276c29594
Binary file not shown.
653
src/mac/morefile/Director.cpp
Normal file
653
src/mac/morefile/Director.cpp
Normal file
@ -0,0 +1,653 @@
|
||||
/*
|
||||
** Apple Macintosh Developer Technical Support
|
||||
**
|
||||
** DirectoryCopy: A robust, general purpose directory copy routine.
|
||||
**
|
||||
** by Jim Luther, Apple Developer Technical Support Emeritus
|
||||
**
|
||||
** File: DirectoryCopy.c
|
||||
**
|
||||
** Copyright © 1992-1998 Apple Computer, Inc.
|
||||
** All rights reserved.
|
||||
**
|
||||
** You may incorporate this sample code into your applications without
|
||||
** restriction, though the sample code has been provided "AS IS" and the
|
||||
** responsibility for its operation is 100% yours. However, what you are
|
||||
** not permitted to do is to redistribute the source as "DSC Sample Code"
|
||||
** after having made changes. If you're going to re-distribute the source,
|
||||
** we require that you make it clear in the source that the code was
|
||||
** descended from Apple Sample Code, but that you've made changes.
|
||||
*/
|
||||
|
||||
#include <Types.h>
|
||||
#include <Errors.h>
|
||||
#include <Memory.h>
|
||||
#include <Files.h>
|
||||
#include <Script.h>
|
||||
|
||||
#define __COMPILINGMOREFILES
|
||||
|
||||
#include "MoreFile.h"
|
||||
#include "MoreExtr.h"
|
||||
#include "MoreDesk.h"
|
||||
#include "FileCopy.h"
|
||||
#include "Director.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* local constants */
|
||||
|
||||
enum
|
||||
{
|
||||
dirCopyBigCopyBuffSize = 0x00004000,
|
||||
dirCopyMinCopyBuffSize = 0x00000200
|
||||
};
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* local data structures */
|
||||
|
||||
/* The EnumerateGlobals structure is used to minimize the amount of
|
||||
** stack space used when recursively calling CopyLevel and to hold
|
||||
** global information that might be needed at any time. */
|
||||
|
||||
#if PRAGMA_ALIGN_SUPPORTED
|
||||
#pragma options align=mac68k
|
||||
#endif
|
||||
struct EnumerateGlobals
|
||||
{
|
||||
Ptr copyBuffer; /* pointer to buffer used for file copy operations */
|
||||
long bufferSize; /* the size of the copy buffer */
|
||||
CopyErrProcPtr errorHandler; /* pointer to error handling function */
|
||||
CopyFilterProcPtr copyFilterProc; /* pointer to filter function */
|
||||
OSErr error; /* temporary holder of results - saves 2 bytes of stack each level */
|
||||
Boolean bailout; /* set to true to by error handling function if fatal error */
|
||||
short destinationVRefNum; /* the destination vRefNum */
|
||||
Str63 itemName; /* the name of the current item */
|
||||
CInfoPBRec myCPB; /* the parameter block used for PBGetCatInfo calls */
|
||||
};
|
||||
#if PRAGMA_ALIGN_SUPPORTED
|
||||
#pragma options align=reset
|
||||
#endif
|
||||
|
||||
typedef struct EnumerateGlobals EnumerateGlobals;
|
||||
typedef EnumerateGlobals *EnumerateGlobalsPtr;
|
||||
|
||||
|
||||
/* The PreflightGlobals structure is used to minimize the amount of
|
||||
** stack space used when recursively calling GetLevelSize and to hold
|
||||
** global information that might be needed at any time. */
|
||||
|
||||
#if PRAGMA_ALIGN_SUPPORTED
|
||||
#pragma options align=mac68k
|
||||
#endif
|
||||
struct PreflightGlobals
|
||||
{
|
||||
OSErr result; /* temporary holder of results - saves 2 bytes of stack each level */
|
||||
Str63 itemName; /* the name of the current item */
|
||||
CInfoPBRec myCPB; /* the parameter block used for PBGetCatInfo calls */
|
||||
|
||||
unsigned long dstBlksPerAllocBlk; /* the number of 512 byte blocks per allocation block on destination */
|
||||
|
||||
unsigned long allocBlksNeeded; /* the total number of allocation blocks needed */
|
||||
|
||||
unsigned long tempBlocks; /* temporary storage for calculations (save some stack space) */
|
||||
CopyFilterProcPtr copyFilterProc; /* pointer to filter function */
|
||||
};
|
||||
#if PRAGMA_ALIGN_SUPPORTED
|
||||
#pragma options align=reset
|
||||
#endif
|
||||
|
||||
typedef struct PreflightGlobals PreflightGlobals;
|
||||
typedef PreflightGlobals *PreflightGlobalsPtr;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* static prototypes */
|
||||
|
||||
static void GetLevelSize(long currentDirID,
|
||||
PreflightGlobals *theGlobals);
|
||||
|
||||
static OSErr PreflightDirectoryCopySpace(short srcVRefNum,
|
||||
long srcDirID,
|
||||
short dstVRefNum,
|
||||
CopyFilterProcPtr copyFilterProc,
|
||||
Boolean *spaceOK);
|
||||
|
||||
static void CopyLevel(long sourceDirID,
|
||||
long dstDirID,
|
||||
EnumerateGlobals *theGlobals);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void GetLevelSize(long currentDirID,
|
||||
PreflightGlobals *theGlobals)
|
||||
{
|
||||
short index = 1;
|
||||
|
||||
do
|
||||
{
|
||||
theGlobals->myCPB.dirInfo.ioFDirIndex = index;
|
||||
theGlobals->myCPB.dirInfo.ioDrDirID = currentDirID; /* we need to do this every time */
|
||||
/* through, since GetCatInfo */
|
||||
/* returns ioFlNum in this field */
|
||||
theGlobals->result = PBGetCatInfoSync(&theGlobals->myCPB);
|
||||
if ( theGlobals->result == noErr )
|
||||
{
|
||||
if ( (theGlobals->copyFilterProc == NULL) ||
|
||||
CallCopyFilterProc(theGlobals->copyFilterProc, &theGlobals->myCPB) ) /* filter if filter proc was supplied */
|
||||
{
|
||||
/* Either there's no filter proc OR the filter proc says to use this item */
|
||||
if ( (theGlobals->myCPB.dirInfo.ioFlAttrib & ioDirMask) != 0 )
|
||||
{
|
||||
/* we have a directory */
|
||||
|
||||
GetLevelSize(theGlobals->myCPB.dirInfo.ioDrDirID, theGlobals); /* recurse */
|
||||
theGlobals->result = noErr; /* clear error return on way back */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We have a file - add its allocation blocks to allocBlksNeeded. */
|
||||
/* Since space on Mac OS disks is always allocated in allocation blocks, */
|
||||
/* this takes into account rounding up to the end of an allocation block. */
|
||||
|
||||
/* get number of 512-byte blocks needed for data fork */
|
||||
if ( ((unsigned long)theGlobals->myCPB.hFileInfo.ioFlLgLen & 0x000001ff) != 0 )
|
||||
{
|
||||
theGlobals->tempBlocks = ((unsigned long)theGlobals->myCPB.hFileInfo.ioFlLgLen >> 9) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
theGlobals->tempBlocks = (unsigned long)theGlobals->myCPB.hFileInfo.ioFlLgLen >> 9;
|
||||
}
|
||||
/* now, calculate number of new allocation blocks needed for the data fork and add it to the total */
|
||||
if ( theGlobals->tempBlocks % theGlobals->dstBlksPerAllocBlk )
|
||||
{
|
||||
theGlobals->allocBlksNeeded += (theGlobals->tempBlocks / theGlobals->dstBlksPerAllocBlk) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
theGlobals->allocBlksNeeded += theGlobals->tempBlocks / theGlobals->dstBlksPerAllocBlk;
|
||||
}
|
||||
|
||||
/* get number of 512-byte blocks needed for resource fork */
|
||||
if ( ((unsigned long)theGlobals->myCPB.hFileInfo.ioFlRLgLen & 0x000001ff) != 0 )
|
||||
{
|
||||
theGlobals->tempBlocks = ((unsigned long)theGlobals->myCPB.hFileInfo.ioFlRLgLen >> 9) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
theGlobals->tempBlocks = (unsigned long)theGlobals->myCPB.hFileInfo.ioFlRLgLen >> 9;
|
||||
}
|
||||
/* now, calculate number of new allocation blocks needed for the resource fork and add it to the total */
|
||||
if ( theGlobals->tempBlocks % theGlobals->dstBlksPerAllocBlk )
|
||||
{
|
||||
theGlobals->allocBlksNeeded += (theGlobals->tempBlocks / theGlobals->dstBlksPerAllocBlk) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
theGlobals->allocBlksNeeded += theGlobals->tempBlocks / theGlobals->dstBlksPerAllocBlk;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
++index;
|
||||
} while ( theGlobals->result == noErr );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static OSErr PreflightDirectoryCopySpace(short srcVRefNum,
|
||||
long srcDirID,
|
||||
short dstVRefNum,
|
||||
CopyFilterProcPtr copyFilterProc,
|
||||
Boolean *spaceOK)
|
||||
{
|
||||
XVolumeParam pb;
|
||||
OSErr error;
|
||||
unsigned long dstFreeBlocks;
|
||||
PreflightGlobals theGlobals;
|
||||
|
||||
error = XGetVolumeInfoNoName(NULL, dstVRefNum, &pb);
|
||||
if ( error == noErr )
|
||||
{
|
||||
/* Convert freeBytes to free disk blocks (512-byte blocks) */
|
||||
dstFreeBlocks = (pb.ioVFreeBytes.hi << 23) + (pb.ioVFreeBytes.lo >> 9);
|
||||
|
||||
/* get allocation block size (always multiple of 512) and divide by 512
|
||||
to get number of 512-byte blocks per allocation block */
|
||||
theGlobals.dstBlksPerAllocBlk = ((unsigned long)pb.ioVAlBlkSiz >> 9);
|
||||
|
||||
theGlobals.allocBlksNeeded = 0;
|
||||
|
||||
theGlobals.myCPB.dirInfo.ioNamePtr = theGlobals.itemName;
|
||||
theGlobals.myCPB.dirInfo.ioVRefNum = srcVRefNum;
|
||||
|
||||
theGlobals.copyFilterProc = copyFilterProc;
|
||||
|
||||
GetLevelSize(srcDirID, &theGlobals);
|
||||
|
||||
/* Is there enough room on the destination volume for the source file? */
|
||||
/* Note: This will work because the largest number of disk blocks supported */
|
||||
/* on a 2TB volume is 0xffffffff and (allocBlksNeeded * dstBlksPerAllocBlk) */
|
||||
/* will always be less than 0xffffffff. */
|
||||
*spaceOK = ((theGlobals.allocBlksNeeded * theGlobals.dstBlksPerAllocBlk) <= dstFreeBlocks);
|
||||
}
|
||||
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void CopyLevel(long sourceDirID,
|
||||
long dstDirID,
|
||||
EnumerateGlobals *theGlobals)
|
||||
{
|
||||
long currentSrcDirID;
|
||||
long newDirID;
|
||||
short index = 1;
|
||||
|
||||
do
|
||||
{
|
||||
/* Get next source item at the current directory level */
|
||||
|
||||
theGlobals->myCPB.dirInfo.ioFDirIndex = index;
|
||||
theGlobals->myCPB.dirInfo.ioDrDirID = sourceDirID;
|
||||
theGlobals->error = PBGetCatInfoSync(&theGlobals->myCPB);
|
||||
|
||||
if ( theGlobals->error == noErr )
|
||||
{
|
||||
if ( (theGlobals->copyFilterProc == NULL) ||
|
||||
CallCopyFilterProc(theGlobals->copyFilterProc, &theGlobals->myCPB) ) /* filter if filter proc was supplied */
|
||||
{
|
||||
/* Either there's no filter proc OR the filter proc says to use this item */
|
||||
|
||||
/* We have an item. Is it a file or directory? */
|
||||
if ( (theGlobals->myCPB.hFileInfo.ioFlAttrib & ioDirMask) != 0 )
|
||||
{
|
||||
/* We have a directory */
|
||||
|
||||
/* Create a new directory at the destination. No errors allowed! */
|
||||
theGlobals->error = DirCreate(theGlobals->destinationVRefNum, dstDirID, theGlobals->itemName, &newDirID);
|
||||
if ( theGlobals->error == noErr )
|
||||
{
|
||||
/* Save the current source directory ID where we can get it when we come back
|
||||
** from recursion land. */
|
||||
currentSrcDirID = theGlobals->myCPB.dirInfo.ioDrDirID;
|
||||
|
||||
/* Dive again (copy the directory level we just found below this one) */
|
||||
CopyLevel(theGlobals->myCPB.dirInfo.ioDrDirID, newDirID, theGlobals);
|
||||
|
||||
if ( !theGlobals->bailout )
|
||||
{
|
||||
/* Copy comment from old to new directory. */
|
||||
/* Ignore the result because we really don't care if it worked or not. */
|
||||
(void) DTCopyComment(theGlobals->myCPB.dirInfo.ioVRefNum, currentSrcDirID, NULL, theGlobals->destinationVRefNum, newDirID, NULL);
|
||||
|
||||
/* Copy directory attributes (dates, etc.) to newDirID. */
|
||||
/* No errors allowed */
|
||||
theGlobals->error = CopyFileMgrAttributes(theGlobals->myCPB.dirInfo.ioVRefNum, currentSrcDirID, NULL, theGlobals->destinationVRefNum, newDirID, NULL, true);
|
||||
|
||||
/* handle any errors from CopyFileMgrAttributes */
|
||||
if ( theGlobals->error != noErr )
|
||||
{
|
||||
if ( theGlobals->errorHandler != NULL )
|
||||
{
|
||||
theGlobals->bailout = CallCopyErrProc(theGlobals->errorHandler, theGlobals->error, copyDirFMAttributesOp,
|
||||
theGlobals->myCPB.dirInfo.ioVRefNum, currentSrcDirID, NULL,
|
||||
theGlobals->destinationVRefNum, newDirID, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If you don't handle the errors with an error handler, */
|
||||
/* then the copy stops here. */
|
||||
theGlobals->bailout = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* error handling for DirCreate */
|
||||
{
|
||||
if ( theGlobals->errorHandler != NULL )
|
||||
{
|
||||
theGlobals->bailout = CallCopyErrProc(theGlobals->errorHandler, theGlobals->error, dirCreateOp,
|
||||
theGlobals->myCPB.dirInfo.ioVRefNum, currentSrcDirID, NULL,
|
||||
theGlobals->destinationVRefNum, dstDirID, theGlobals->itemName);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If you don't handle the errors with an error handler, */
|
||||
/* then the copy stops here. */
|
||||
theGlobals->bailout = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !theGlobals->bailout )
|
||||
{
|
||||
/* clear error return on way back if we aren't bailing out */
|
||||
theGlobals->error = noErr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We have a file, so copy it */
|
||||
|
||||
theGlobals->error = FileCopy(theGlobals->myCPB.hFileInfo.ioVRefNum,
|
||||
theGlobals->myCPB.hFileInfo.ioFlParID,
|
||||
theGlobals->itemName,
|
||||
theGlobals->destinationVRefNum,
|
||||
dstDirID,
|
||||
NULL,
|
||||
NULL,
|
||||
theGlobals->copyBuffer,
|
||||
theGlobals->bufferSize,
|
||||
false);
|
||||
|
||||
/* handle any errors from FileCopy */
|
||||
if ( theGlobals->error != noErr )
|
||||
{
|
||||
if ( theGlobals->errorHandler != NULL )
|
||||
{
|
||||
theGlobals->bailout = CallCopyErrProc(theGlobals->errorHandler, theGlobals->error, fileCopyOp,
|
||||
theGlobals->myCPB.hFileInfo.ioVRefNum, theGlobals->myCPB.hFileInfo.ioFlParID, theGlobals->itemName,
|
||||
theGlobals->destinationVRefNum, dstDirID, NULL);
|
||||
if ( !theGlobals->bailout )
|
||||
{
|
||||
/* If the CopyErrProc handled the problem, clear the error here */
|
||||
theGlobals->error = noErr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If you don't handle the errors with an error handler, */
|
||||
/* then the copy stops here. */
|
||||
theGlobals->bailout = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* error handling for PBGetCatInfo */
|
||||
/* it's normal to get a fnfErr when indexing; that only means you've hit the end of the directory */
|
||||
if ( theGlobals->error != fnfErr )
|
||||
{
|
||||
if ( theGlobals->errorHandler != NULL )
|
||||
{
|
||||
theGlobals->bailout = CallCopyErrProc(theGlobals->errorHandler, theGlobals->error, getNextItemOp,
|
||||
theGlobals->myCPB.dirInfo.ioVRefNum, sourceDirID, NULL, 0, 0, NULL);
|
||||
if ( !theGlobals->bailout )
|
||||
{
|
||||
/* If the CopyErrProc handled the problem, clear the error here */
|
||||
theGlobals->error = noErr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If you don't handle the errors with an error handler, */
|
||||
/* then the copy stops here. */
|
||||
theGlobals->bailout = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
++index; /* prepare to get next item */
|
||||
} while ( (theGlobals->error == noErr) && (!theGlobals->bailout) ); /* time to fall back a level? */
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FilteredDirectoryCopy(short srcVRefNum,
|
||||
long srcDirID,
|
||||
ConstStr255Param srcName,
|
||||
short dstVRefNum,
|
||||
long dstDirID,
|
||||
ConstStr255Param dstName,
|
||||
void *copyBufferPtr,
|
||||
long copyBufferSize,
|
||||
Boolean preflight,
|
||||
CopyErrProcPtr copyErrHandler,
|
||||
CopyFilterProcPtr copyFilterProc)
|
||||
{
|
||||
EnumerateGlobals theGlobals;
|
||||
Boolean isDirectory;
|
||||
OSErr error;
|
||||
Boolean ourCopyBuffer = false;
|
||||
Str63 srcDirName, oldDiskName;
|
||||
Boolean spaceOK;
|
||||
|
||||
/* Make sure a copy buffer is allocated. */
|
||||
if ( copyBufferPtr == NULL )
|
||||
{
|
||||
/* The caller didn't supply a copy buffer so grab one from the application heap.
|
||||
** Try to get a big copy buffer, if we can't, try for a 512-byte buffer.
|
||||
** If 512 bytes aren't available, we're in trouble. */
|
||||
copyBufferSize = dirCopyBigCopyBuffSize;
|
||||
copyBufferPtr = NewPtr(copyBufferSize);
|
||||
if ( copyBufferPtr == NULL )
|
||||
{
|
||||
copyBufferSize = dirCopyMinCopyBuffSize;
|
||||
copyBufferPtr = NewPtr(copyBufferSize);
|
||||
if ( copyBufferPtr == NULL )
|
||||
{
|
||||
return ( memFullErr );
|
||||
}
|
||||
}
|
||||
ourCopyBuffer = true;
|
||||
}
|
||||
|
||||
/* Get the real dirID where we're copying from and make sure it is a directory. */
|
||||
error = GetDirectoryID(srcVRefNum, srcDirID, srcName, &srcDirID, &isDirectory);
|
||||
if ( error != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
if ( !isDirectory )
|
||||
{
|
||||
error = dirNFErr;
|
||||
goto ErrorExit;
|
||||
}
|
||||
|
||||
/* Special case destination if it is the root parent directory. */
|
||||
/* Since you can't create the root directory, this is needed if */
|
||||
/* you want to copy a directory's content to a disk's root directory. */
|
||||
if ( (dstDirID == fsRtParID) && (dstName == NULL) )
|
||||
{
|
||||
dstDirID = fsRtParID;
|
||||
isDirectory = true;
|
||||
error = noErr;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get the real dirID where we're going to put the copy and make sure it is a directory. */
|
||||
error = GetDirectoryID(dstVRefNum, dstDirID, dstName, &dstDirID, &isDirectory);
|
||||
if ( error != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
if ( !isDirectory )
|
||||
{
|
||||
error = dirNFErr;
|
||||
goto ErrorExit;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the real vRefNum of both the source and destination */
|
||||
error = DetermineVRefNum(srcName, srcVRefNum, &srcVRefNum);
|
||||
if ( error != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
error = DetermineVRefNum(dstName, dstVRefNum, &dstVRefNum);
|
||||
if ( error != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
|
||||
if ( preflight )
|
||||
{
|
||||
error = PreflightDirectoryCopySpace(srcVRefNum, srcDirID, dstVRefNum, copyFilterProc, &spaceOK);
|
||||
if ( error != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
if ( !spaceOK )
|
||||
{
|
||||
error = dskFulErr; /* not enough room on destination */
|
||||
goto ErrorExit;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create the new directory in the destination directory with the */
|
||||
/* same name as the source directory. */
|
||||
error = GetDirName(srcVRefNum, srcDirID, srcDirName);
|
||||
if ( error != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
|
||||
/* Again, special case destination if the destination is the */
|
||||
/* root parent directory. This time, we'll rename the disk to */
|
||||
/* the source directory name. */
|
||||
if ( dstDirID == fsRtParID )
|
||||
{
|
||||
/* Get the current name of the destination disk */
|
||||
error = GetDirName(dstVRefNum, fsRtDirID, oldDiskName);
|
||||
if ( error == noErr )
|
||||
{
|
||||
/* Shorten the name if it's too long to be the volume name */
|
||||
TruncPString(srcDirName, srcDirName, 27);
|
||||
|
||||
/* Rename the disk */
|
||||
error = HRename(dstVRefNum, fsRtParID, oldDiskName, srcDirName);
|
||||
/* and copy to the root directory */
|
||||
dstDirID = fsRtDirID;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error = DirCreate(dstVRefNum, dstDirID, srcDirName, &dstDirID);
|
||||
}
|
||||
if ( error != noErr )
|
||||
{
|
||||
/* handle any errors from DirCreate */
|
||||
if ( copyErrHandler != NULL )
|
||||
{
|
||||
if ( CallCopyErrProc(copyErrHandler, error, dirCreateOp,
|
||||
srcVRefNum, srcDirID, NULL,
|
||||
dstVRefNum, dstDirID, srcDirName) )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the CopyErrProc handled the problem, clear the error here */
|
||||
/* and continue */
|
||||
error = noErr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If you don't handle the errors with an error handler, */
|
||||
/* then the copy stops here. */
|
||||
goto ErrorExit;
|
||||
}
|
||||
}
|
||||
|
||||
/* dstDirID is now the newly created directory! */
|
||||
|
||||
/* Set up the globals we need to access from the recursive routine. */
|
||||
theGlobals.copyBuffer = (Ptr)copyBufferPtr;
|
||||
theGlobals.bufferSize = copyBufferSize;
|
||||
theGlobals.destinationVRefNum = dstVRefNum; /* so we can get to it always */
|
||||
theGlobals.myCPB.hFileInfo.ioNamePtr = (StringPtr)&theGlobals.itemName;
|
||||
theGlobals.myCPB.hFileInfo.ioVRefNum = srcVRefNum;
|
||||
theGlobals.errorHandler = copyErrHandler;
|
||||
theGlobals.bailout = false;
|
||||
theGlobals.copyFilterProc = copyFilterProc;
|
||||
|
||||
/* Here we go into recursion land... */
|
||||
CopyLevel(srcDirID, dstDirID, &theGlobals);
|
||||
error = theGlobals.error; /* get the result */
|
||||
|
||||
if ( !theGlobals.bailout )
|
||||
{
|
||||
/* Copy comment from source to destination directory. */
|
||||
/* Ignore the result because we really don't care if it worked or not. */
|
||||
(void) DTCopyComment(srcVRefNum, srcDirID, NULL, dstVRefNum, dstDirID, NULL);
|
||||
|
||||
/* Copy the File Manager attributes */
|
||||
error = CopyFileMgrAttributes(srcVRefNum, srcDirID, NULL,
|
||||
dstVRefNum, dstDirID, NULL, true);
|
||||
|
||||
/* handle any errors from CopyFileMgrAttributes */
|
||||
if ( (error != noErr) && (copyErrHandler != NULL) )
|
||||
{
|
||||
theGlobals.bailout = CallCopyErrProc(copyErrHandler, error, copyDirFMAttributesOp,
|
||||
srcVRefNum, srcDirID, NULL,
|
||||
dstVRefNum, dstDirID, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
ErrorExit:
|
||||
/* Get rid of the copy buffer if we allocated it. */
|
||||
if ( ourCopyBuffer )
|
||||
{
|
||||
DisposePtr((Ptr)copyBufferPtr);
|
||||
}
|
||||
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr DirectoryCopy(short srcVRefNum,
|
||||
long srcDirID,
|
||||
ConstStr255Param srcName,
|
||||
short dstVRefNum,
|
||||
long dstDirID,
|
||||
ConstStr255Param dstName,
|
||||
void *copyBufferPtr,
|
||||
long copyBufferSize,
|
||||
Boolean preflight,
|
||||
CopyErrProcPtr copyErrHandler)
|
||||
{
|
||||
return ( FilteredDirectoryCopy(srcVRefNum, srcDirID, srcName,
|
||||
dstVRefNum, dstDirID, dstName,
|
||||
copyBufferPtr, copyBufferSize, preflight,
|
||||
copyErrHandler, NULL) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpFilteredDirectoryCopy(const FSSpec *srcSpec,
|
||||
const FSSpec *dstSpec,
|
||||
void *copyBufferPtr,
|
||||
long copyBufferSize,
|
||||
Boolean preflight,
|
||||
CopyErrProcPtr copyErrHandler,
|
||||
CopyFilterProcPtr copyFilterProc)
|
||||
{
|
||||
return ( FilteredDirectoryCopy(srcSpec->vRefNum, srcSpec->parID, srcSpec->name,
|
||||
dstSpec->vRefNum, dstSpec->parID, dstSpec->name,
|
||||
copyBufferPtr, copyBufferSize, preflight,
|
||||
copyErrHandler, copyFilterProc) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpDirectoryCopy(const FSSpec *srcSpec,
|
||||
const FSSpec *dstSpec,
|
||||
void *copyBufferPtr,
|
||||
long copyBufferSize,
|
||||
Boolean preflight,
|
||||
CopyErrProcPtr copyErrHandler)
|
||||
{
|
||||
return ( FilteredDirectoryCopy(srcSpec->vRefNum, srcSpec->parID, srcSpec->name,
|
||||
dstSpec->vRefNum, dstSpec->parID, dstSpec->name,
|
||||
copyBufferPtr, copyBufferSize, preflight,
|
||||
copyErrHandler, NULL) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
493
src/mac/morefile/Director.h
Normal file
493
src/mac/morefile/Director.h
Normal file
@ -0,0 +1,493 @@
|
||||
/*
|
||||
** Apple Macintosh Developer Technical Support
|
||||
**
|
||||
** DirectoryCopy: A robust, general purpose directory copy routine.
|
||||
**
|
||||
** by Jim Luther, Apple Developer Technical Support Emeritus
|
||||
**
|
||||
** File: DirectoryCopy.h
|
||||
**
|
||||
** Copyright © 1992-1998 Apple Computer, Inc.
|
||||
** All rights reserved.
|
||||
**
|
||||
** You may incorporate this sample code into your applications without
|
||||
** restriction, though the sample code has been provided "AS IS" and the
|
||||
** responsibility for its operation is 100% yours. However, what you are
|
||||
** not permitted to do is to redistribute the source as "DSC Sample Code"
|
||||
** after having made changes. If you're going to re-distribute the source,
|
||||
** we require that you make it clear in the source that the code was
|
||||
** descended from Apple Sample Code, but that you've made changes.
|
||||
*/
|
||||
|
||||
#ifndef __DIRECTORYCOPY__
|
||||
#define __DIRECTORYCOPY__
|
||||
|
||||
#include <Types.h>
|
||||
#include <Files.h>
|
||||
|
||||
#include "Optim.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
enum
|
||||
{
|
||||
getNextItemOp = 1, /* couldn't access items in this directory - no access privileges */
|
||||
copyDirCommentOp = 2, /* couldn't copy directory's Finder comment */
|
||||
copyDirAccessPrivsOp = 3, /* couldn't copy directory's AFP access privileges */
|
||||
copyDirFMAttributesOp = 4, /* couldn't copy directory's File Manager attributes */
|
||||
dirCreateOp = 5, /* couldn't create destination directory */
|
||||
fileCopyOp = 6 /* couldn't copy file */
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef pascal Boolean (*CopyErrProcPtr) (OSErr error,
|
||||
short failedOperation,
|
||||
short srcVRefNum,
|
||||
long srcDirID,
|
||||
ConstStr255Param srcName,
|
||||
short dstVRefNum,
|
||||
long dstDirID,
|
||||
ConstStr255Param dstName);
|
||||
/* ¦ Prototype for the CopyErrProc function DirectoryCopy calls.
|
||||
This is the prototype for the CopyErrProc function DirectoryCopy
|
||||
calls if an error condition is detected sometime during the copy. If
|
||||
CopyErrProc returns false, then DirectoryCopy attempts to continue with
|
||||
the directory copy operation. If CopyErrProc returns true, then
|
||||
DirectoryCopy stops the directory copy operation.
|
||||
|
||||
error input: The error result code that caused CopyErrProc to
|
||||
be called.
|
||||
failedOperation input: The operation that returned an error to
|
||||
DirectoryCopy.
|
||||
srcVRefNum input: Source volume specification.
|
||||
srcDirID input: Source directory ID.
|
||||
srcName input: Source file or directory name, or nil if
|
||||
srcDirID specifies the directory.
|
||||
dstVRefNum input: Destination volume specification.
|
||||
dstDirID input: Destination directory ID.
|
||||
dstName input: Destination file or directory name, or nil if
|
||||
dstDirID specifies the directory.
|
||||
|
||||
__________
|
||||
|
||||
Also see: FilteredDirectoryCopy, FSpFilteredDirectoryCopy, DirectoryCopy, FSpDirectoryCopy
|
||||
*/
|
||||
|
||||
#define CallCopyErrProc(userRoutine, error, failedOperation, srcVRefNum, srcDirID, srcName, dstVRefNum, dstDirID, dstName) \
|
||||
(*(userRoutine))((error), (failedOperation), (srcVRefNum), (srcDirID), (srcName), (dstVRefNum), (dstDirID), (dstName))
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef pascal Boolean (*CopyFilterProcPtr) (const CInfoPBRec * const cpbPtr);
|
||||
|
||||
/* ¦ Prototype for the CopyFilterProc function.
|
||||
This is the prototype for the CopyFilterProc function called by
|
||||
FilteredDirectoryCopy and GetLevelSize. If true is returned,
|
||||
the file/folder is included in the copy, otherwise it is excluded.
|
||||
|
||||
pb input: Points to the CInfoPBRec for the item under consideration.
|
||||
|
||||
__________
|
||||
|
||||
Also see: FilteredDirectoryCopy, FSpFilteredDirectoryCopy
|
||||
*/
|
||||
|
||||
#define CallCopyFilterProc(userRoutine, cpbPtr) (*(userRoutine))((cpbPtr))
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FilteredDirectoryCopy(short srcVRefNum,
|
||||
long srcDirID,
|
||||
ConstStr255Param srcName,
|
||||
short dstVRefNum,
|
||||
long dstDirID,
|
||||
ConstStr255Param dstName,
|
||||
void *copyBufferPtr,
|
||||
long copyBufferSize,
|
||||
Boolean preflight,
|
||||
CopyErrProcPtr copyErrHandler,
|
||||
CopyFilterProcPtr copyFilterProc);
|
||||
/* ¦ Make a copy of a directory structure in a new location with item filtering.
|
||||
The FilteredDirectoryCopy function makes a copy of a directory
|
||||
structure in a new location. If copyBufferPtr <> NIL, it points to
|
||||
a buffer of copyBufferSize that is used to copy files data. The
|
||||
larger the supplied buffer, the faster the copy. If
|
||||
copyBufferPtr = NIL, then this routine allocates a buffer in the
|
||||
application heap. If you pass a copy buffer to this routine, make
|
||||
its size a multiple of 512 ($200) bytes for optimum performance.
|
||||
|
||||
The optional copyFilterProc parameter lets a routine you define
|
||||
decide what files or directories are copied to the destination.
|
||||
|
||||
FilteredDirectoryCopy normally creates a new directory *in* the
|
||||
specified destination directory and copies the source directory's
|
||||
content into the new directory. However, if root parent directory
|
||||
(fsRtParID) is passed as the dstDirID parameter and NULL is
|
||||
passed as the dstName parameter, DirectoryCopy renames the
|
||||
destination volume to the source directory's name (truncating
|
||||
if the name is longer than 27 characters) and copies the source
|
||||
directory's content into the destination volume's root directory.
|
||||
This special case is supported by FilteredDirectoryCopy, but
|
||||
not by FSpFilteredDirectoryCopy since with FSpFilteredDirectoryCopy,
|
||||
the dstName parameter can not be NULL.
|
||||
|
||||
srcVRefNum input: Source volume specification.
|
||||
srcDirID input: Source directory ID.
|
||||
srcName input: Source directory name, or nil if
|
||||
srcDirID specifies the directory.
|
||||
dstVRefNum input: Destination volume specification.
|
||||
dstDirID input: Destination directory ID.
|
||||
dstName input: Destination directory name, or nil if
|
||||
dstDirID specifies the directory.
|
||||
copyBufferPtr input: Points to a buffer of copyBufferSize that
|
||||
is used the i/o buffer for the copy or
|
||||
nil if you want DirectoryCopy to allocate its
|
||||
own buffer in the application heap.
|
||||
copyBufferSize input: The size of the buffer pointed to
|
||||
by copyBufferPtr.
|
||||
preflight input: If true, DirectoryCopy makes sure there are
|
||||
enough allocation blocks on the destination
|
||||
volume to hold the directory's files before
|
||||
starting the copy.
|
||||
copyErrHandler input: A pointer to the routine you want called if an
|
||||
error condition is detected during the copy, or
|
||||
nil if you don't want to handle error conditions.
|
||||
If you don't handle error conditions, the first
|
||||
error will cause the copy to quit and
|
||||
DirectoryCopy will return the error.
|
||||
Error handling is recommended...
|
||||
copyFilterProc input: A pointer to the filter routine you want called
|
||||
for each item in the source directory, or NULL
|
||||
if you don't want to filter.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
readErr Ð19 Driver does not respond to read requests
|
||||
writErr Ð20 Driver does not respond to write requests
|
||||
badUnitErr Ð21 Driver reference number does not
|
||||
match unit table
|
||||
unitEmptyErr Ð22 Driver reference number specifies a
|
||||
nil handle in unit table
|
||||
abortErr Ð27 Request aborted by KillIO
|
||||
notOpenErr Ð28 Driver not open
|
||||
dskFulErr -34 Destination volume is full
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
tmfoErr -42 Too many files open
|
||||
fnfErr -43 Source file not found, or destination
|
||||
directory does not exist
|
||||
wPrErr -44 Volume locked by hardware
|
||||
fLckdErr -45 File is locked
|
||||
vLckdErr -46 Destination volume is read-only
|
||||
fBsyErr -47 The source or destination file could
|
||||
not be opened with the correct access
|
||||
modes
|
||||
dupFNErr -48 Destination file already exists
|
||||
opWrErr -49 File already open for writing
|
||||
paramErr -50 No default volume or function not
|
||||
supported by volume
|
||||
permErr -54 File is already open and cannot be opened using specified deny modes
|
||||
memFullErr -108 Copy buffer could not be allocated
|
||||
dirNFErr -120 Directory not found or incomplete pathname
|
||||
wrgVolTypErr -123 Function not supported by volume
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
afpDenyConflict -5006 The source or destination file could
|
||||
not be opened with the correct access
|
||||
modes
|
||||
afpObjectTypeErr -5025 Source is a directory, directory not found
|
||||
or incomplete pathname
|
||||
|
||||
__________
|
||||
|
||||
Also see: CopyErrProcPtr, CopyFilterProcPtr, FSpFilteredDirectoryCopy,
|
||||
DirectoryCopy, FSpDirectoryCopy, FileCopy, FSpFileCopy
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpFilteredDirectoryCopy(const FSSpec *srcSpec,
|
||||
const FSSpec *dstSpec,
|
||||
void *copyBufferPtr,
|
||||
long copyBufferSize,
|
||||
Boolean preflight,
|
||||
CopyErrProcPtr copyErrHandler,
|
||||
CopyFilterProcPtr copyFilterProc);
|
||||
/* ¦ Make a copy of a directory structure in a new location with item filtering.
|
||||
The FSpFilteredDirectoryCopy function makes a copy of a directory
|
||||
structure in a new location. If copyBufferPtr <> NIL, it points to
|
||||
a buffer of copyBufferSize that is used to copy files data. The
|
||||
larger the supplied buffer, the faster the copy. If
|
||||
copyBufferPtr = NIL, then this routine allocates a buffer in the
|
||||
application heap. If you pass a copy buffer to this routine, make
|
||||
its size a multiple of 512 ($200) bytes for optimum performance.
|
||||
|
||||
The optional copyFilterProc parameter lets a routine you define
|
||||
decide what files or directories are copied to the destination.
|
||||
|
||||
srcSpec input: An FSSpec record specifying the directory to copy.
|
||||
dstSpec input: An FSSpec record specifying destination directory
|
||||
of the copy.
|
||||
copyBufferPtr input: Points to a buffer of copyBufferSize that
|
||||
is used the i/o buffer for the copy or
|
||||
nil if you want DirectoryCopy to allocate its
|
||||
own buffer in the application heap.
|
||||
copyBufferSize input: The size of the buffer pointed to
|
||||
by copyBufferPtr.
|
||||
preflight input: If true, FSpDirectoryCopy makes sure there are
|
||||
enough allocation blocks on the destination
|
||||
volume to hold the directory's files before
|
||||
starting the copy.
|
||||
copyErrHandler input: A pointer to the routine you want called if an
|
||||
error condition is detected during the copy, or
|
||||
nil if you don't want to handle error conditions.
|
||||
If you don't handle error conditions, the first
|
||||
error will cause the copy to quit and
|
||||
DirectoryCopy will return the error.
|
||||
Error handling is recommended...
|
||||
copyFilterProc input: A pointer to the filter routine you want called
|
||||
for each item in the source directory, or NULL
|
||||
if you don't want to filter.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
readErr Ð19 Driver does not respond to read requests
|
||||
writErr Ð20 Driver does not respond to write requests
|
||||
badUnitErr Ð21 Driver reference number does not
|
||||
match unit table
|
||||
unitEmptyErr Ð22 Driver reference number specifies a
|
||||
nil handle in unit table
|
||||
abortErr Ð27 Request aborted by KillIO
|
||||
notOpenErr Ð28 Driver not open
|
||||
dskFulErr -34 Destination volume is full
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
tmfoErr -42 Too many files open
|
||||
fnfErr -43 Source file not found, or destination
|
||||
directory does not exist
|
||||
wPrErr -44 Volume locked by hardware
|
||||
fLckdErr -45 File is locked
|
||||
vLckdErr -46 Destination volume is read-only
|
||||
fBsyErr -47 The source or destination file could
|
||||
not be opened with the correct access
|
||||
modes
|
||||
dupFNErr -48 Destination file already exists
|
||||
opWrErr -49 File already open for writing
|
||||
paramErr -50 No default volume or function not
|
||||
supported by volume
|
||||
permErr -54 File is already open and cannot be opened using specified deny modes
|
||||
memFullErr -108 Copy buffer could not be allocated
|
||||
dirNFErr -120 Directory not found or incomplete pathname
|
||||
wrgVolTypErr -123 Function not supported by volume
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
afpDenyConflict -5006 The source or destination file could
|
||||
not be opened with the correct access
|
||||
modes
|
||||
afpObjectTypeErr -5025 Source is a directory, directory not found
|
||||
or incomplete pathname
|
||||
|
||||
__________
|
||||
|
||||
Also see: CopyErrProcPtr, CopyFilterProcPtr, FilteredDirectoryCopy,
|
||||
DirectoryCopy, FSpDirectoryCopy, FileCopy, FSpFileCopy
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr DirectoryCopy(short srcVRefNum,
|
||||
long srcDirID,
|
||||
ConstStr255Param srcName,
|
||||
short dstVRefNum,
|
||||
long dstDirID,
|
||||
ConstStr255Param dstName,
|
||||
void *copyBufferPtr,
|
||||
long copyBufferSize,
|
||||
Boolean preflight,
|
||||
CopyErrProcPtr copyErrHandler);
|
||||
/* ¦ Make a copy of a directory structure in a new location.
|
||||
The DirectoryCopy function makes a copy of a directory structure in a
|
||||
new location. If copyBufferPtr <> NIL, it points to a buffer of
|
||||
copyBufferSize that is used to copy files data. The larger the
|
||||
supplied buffer, the faster the copy. If copyBufferPtr = NIL, then this
|
||||
routine allocates a buffer in the application heap. If you pass a
|
||||
copy buffer to this routine, make its size a multiple of 512
|
||||
($200) bytes for optimum performance.
|
||||
|
||||
DirectoryCopy normally creates a new directory *in* the specified
|
||||
destination directory and copies the source directory's content into
|
||||
the new directory. However, if root parent directory (fsRtParID)
|
||||
is passed as the dstDirID parameter and NULL is passed as the
|
||||
dstName parameter, DirectoryCopy renames the destination volume to
|
||||
the source directory's name (truncating if the name is longer than
|
||||
27 characters) and copies the source directory's content into the
|
||||
destination volume's root directory. This special case is supported
|
||||
by DirectoryCopy, but not by FSpDirectoryCopy since with
|
||||
FSpDirectoryCopy, the dstName parameter can not be NULL.
|
||||
|
||||
srcVRefNum input: Source volume specification.
|
||||
srcDirID input: Source directory ID.
|
||||
srcName input: Source directory name, or nil if
|
||||
srcDirID specifies the directory.
|
||||
dstVRefNum input: Destination volume specification.
|
||||
dstDirID input: Destination directory ID.
|
||||
dstName input: Destination directory name, or nil if
|
||||
dstDirID specifies the directory.
|
||||
copyBufferPtr input: Points to a buffer of copyBufferSize that
|
||||
is used the i/o buffer for the copy or
|
||||
nil if you want DirectoryCopy to allocate its
|
||||
own buffer in the application heap.
|
||||
copyBufferSize input: The size of the buffer pointed to
|
||||
by copyBufferPtr.
|
||||
preflight input: If true, DirectoryCopy makes sure there are
|
||||
enough allocation blocks on the destination
|
||||
volume to hold the directory's files before
|
||||
starting the copy.
|
||||
copyErrHandler input: A pointer to the routine you want called if an
|
||||
error condition is detected during the copy, or
|
||||
nil if you don't want to handle error conditions.
|
||||
If you don't handle error conditions, the first
|
||||
error will cause the copy to quit and
|
||||
DirectoryCopy will return the error.
|
||||
Error handling is recommended...
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
readErr Ð19 Driver does not respond to read requests
|
||||
writErr Ð20 Driver does not respond to write requests
|
||||
badUnitErr Ð21 Driver reference number does not
|
||||
match unit table
|
||||
unitEmptyErr Ð22 Driver reference number specifies a
|
||||
nil handle in unit table
|
||||
abortErr Ð27 Request aborted by KillIO
|
||||
notOpenErr Ð28 Driver not open
|
||||
dskFulErr -34 Destination volume is full
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
tmfoErr -42 Too many files open
|
||||
fnfErr -43 Source file not found, or destination
|
||||
directory does not exist
|
||||
wPrErr -44 Volume locked by hardware
|
||||
fLckdErr -45 File is locked
|
||||
vLckdErr -46 Destination volume is read-only
|
||||
fBsyErr -47 The source or destination file could
|
||||
not be opened with the correct access
|
||||
modes
|
||||
dupFNErr -48 Destination file already exists
|
||||
opWrErr -49 File already open for writing
|
||||
paramErr -50 No default volume or function not
|
||||
supported by volume
|
||||
permErr -54 File is already open and cannot be opened using specified deny modes
|
||||
memFullErr -108 Copy buffer could not be allocated
|
||||
dirNFErr -120 Directory not found or incomplete pathname
|
||||
wrgVolTypErr -123 Function not supported by volume
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
afpDenyConflict -5006 The source or destination file could
|
||||
not be opened with the correct access
|
||||
modes
|
||||
afpObjectTypeErr -5025 Source is a directory, directory not found
|
||||
or incomplete pathname
|
||||
|
||||
__________
|
||||
|
||||
Also see: CopyErrProcPtr, FSpDirectoryCopy, FilteredDirectoryCopy,
|
||||
FSpFilteredDirectoryCopy, FileCopy, FSpFileCopy
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpDirectoryCopy(const FSSpec *srcSpec,
|
||||
const FSSpec *dstSpec,
|
||||
void *copyBufferPtr,
|
||||
long copyBufferSize,
|
||||
Boolean preflight,
|
||||
CopyErrProcPtr copyErrHandler);
|
||||
/* ¦ Make a copy of a directory structure in a new location.
|
||||
The FSpDirectoryCopy function makes a copy of a directory structure in a
|
||||
new location. If copyBufferPtr <> NIL, it points to a buffer of
|
||||
copyBufferSize that is used to copy files data. The larger the
|
||||
supplied buffer, the faster the copy. If copyBufferPtr = NIL, then this
|
||||
routine allocates a buffer in the application heap. If you pass a
|
||||
copy buffer to this routine, make its size a multiple of 512
|
||||
($200) bytes for optimum performance.
|
||||
|
||||
srcSpec input: An FSSpec record specifying the directory to copy.
|
||||
dstSpec input: An FSSpec record specifying destination directory
|
||||
of the copy.
|
||||
copyBufferPtr input: Points to a buffer of copyBufferSize that
|
||||
is used the i/o buffer for the copy or
|
||||
nil if you want DirectoryCopy to allocate its
|
||||
own buffer in the application heap.
|
||||
copyBufferSize input: The size of the buffer pointed to
|
||||
by copyBufferPtr.
|
||||
preflight input: If true, FSpDirectoryCopy makes sure there are
|
||||
enough allocation blocks on the destination
|
||||
volume to hold the directory's files before
|
||||
starting the copy.
|
||||
copyErrHandler input: A pointer to the routine you want called if an
|
||||
error condition is detected during the copy, or
|
||||
nil if you don't want to handle error conditions.
|
||||
If you don't handle error conditions, the first
|
||||
error will cause the copy to quit and
|
||||
DirectoryCopy will return the error.
|
||||
Error handling is recommended...
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
readErr Ð19 Driver does not respond to read requests
|
||||
writErr Ð20 Driver does not respond to write requests
|
||||
badUnitErr Ð21 Driver reference number does not
|
||||
match unit table
|
||||
unitEmptyErr Ð22 Driver reference number specifies a
|
||||
nil handle in unit table
|
||||
abortErr Ð27 Request aborted by KillIO
|
||||
notOpenErr Ð28 Driver not open
|
||||
dskFulErr -34 Destination volume is full
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
tmfoErr -42 Too many files open
|
||||
fnfErr -43 Source file not found, or destination
|
||||
directory does not exist
|
||||
wPrErr -44 Volume locked by hardware
|
||||
fLckdErr -45 File is locked
|
||||
vLckdErr -46 Destination volume is read-only
|
||||
fBsyErr -47 The source or destination file could
|
||||
not be opened with the correct access
|
||||
modes
|
||||
dupFNErr -48 Destination file already exists
|
||||
opWrErr -49 File already open for writing
|
||||
paramErr -50 No default volume or function not
|
||||
supported by volume
|
||||
permErr -54 File is already open and cannot be opened using specified deny modes
|
||||
memFullErr -108 Copy buffer could not be allocated
|
||||
dirNFErr -120 Directory not found or incomplete pathname
|
||||
wrgVolTypErr -123 Function not supported by volume
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
afpDenyConflict -5006 The source or destination file could
|
||||
not be opened with the correct access
|
||||
modes
|
||||
afpObjectTypeErr -5025 Source is a directory, directory not found
|
||||
or incomplete pathname
|
||||
|
||||
__________
|
||||
|
||||
Also see: CopyErrProcPtr, DirectoryCopy, FilteredDirectoryCopy,
|
||||
FSpFilteredDirectoryCopy, FileCopy, FSpFileCopy
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "OptimEnd.h"
|
||||
|
||||
#endif /* __DIRECTORYCOPY__ */
|
928
src/mac/morefile/FSpCompa.cpp
Normal file
928
src/mac/morefile/FSpCompa.cpp
Normal file
@ -0,0 +1,928 @@
|
||||
/*
|
||||
** Apple Macintosh Developer Technical Support
|
||||
**
|
||||
** FSSpec compatibility functions.
|
||||
**
|
||||
** by Jim Luther, Apple Developer Technical Support Emeritus
|
||||
**
|
||||
** File: FSpCompat.c
|
||||
**
|
||||
** Copyright © 1992-1998 Apple Computer, Inc.
|
||||
** All rights reserved.
|
||||
**
|
||||
** You may incorporate this sample code into your applications without
|
||||
** restriction, though the sample code has been provided "AS IS" and the
|
||||
** responsibility for its operation is 100% yours. However, what you are
|
||||
** not permitted to do is to redistribute the source as "DSC Sample Code"
|
||||
** after having made changes. If you're going to re-distribute the source,
|
||||
** we require that you make it clear in the source that the code was
|
||||
** descended from Apple Sample Code, but that you've made changes.
|
||||
*/
|
||||
|
||||
/*
|
||||
** If building application 68K code, set GENERATENODATA to 0 for faster code.
|
||||
** If building stand-alone 68K code, set GENERATENODATA to 1 so globals
|
||||
** (static variables) are not used.
|
||||
*/
|
||||
#ifndef GENERATENODATA
|
||||
#define GENERATENODATA 0
|
||||
#endif
|
||||
|
||||
#include <Types.h>
|
||||
#include <Errors.h>
|
||||
#include <LowMem.h>
|
||||
#include <Gestalt.h>
|
||||
#include <Resources.h>
|
||||
#include <Script.h>
|
||||
|
||||
#define __COMPILINGMOREFILES
|
||||
|
||||
#include "MoreExtr.h"
|
||||
#include "FSpCompa.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* local constants */
|
||||
|
||||
enum {
|
||||
gestaltBugFixAttrsTwo = 'bugy',
|
||||
gestaltFSpExchangeFilesCompatibilityFix = 26,
|
||||
gestaltBugFixAttrsThree = 'bugx',
|
||||
gestaltFSpCreateScriptSupportFix = 1
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* static prototypes */
|
||||
|
||||
|
||||
#if !__MACOSSEVENORLATER
|
||||
static Boolean FSHasFSSpecCalls(void);
|
||||
|
||||
static Boolean QTHasFSSpecCalls(void);
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
|
||||
#if !__MACOSSEVENFIVEORLATER
|
||||
static Boolean HasFSpExchangeFilesCompatibilityFix(void);
|
||||
|
||||
static OSErr GenerateUniqueName(short volume,
|
||||
long *startSeed,
|
||||
long dir1,
|
||||
long dir2,
|
||||
StringPtr uniqueName);
|
||||
#endif /* !__MACOSSEVENFIVEORLATER */
|
||||
|
||||
#if !__MACOSSEVENFIVEONEORLATER
|
||||
static Boolean HasFSpCreateScriptSupportFix(void);
|
||||
#endif /* !__MACOSSEVENFIVEONEORLATER */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* FSHasFSSpecCalls returns true if the file system provides FSSpec calls. */
|
||||
|
||||
#if !__MACOSSEVENORLATER
|
||||
static Boolean FSHasFSSpecCalls(void)
|
||||
{
|
||||
long response;
|
||||
#if !GENERATENODATA
|
||||
static Boolean tested = false;
|
||||
static Boolean result = false;
|
||||
#else
|
||||
Boolean result = false;
|
||||
#endif
|
||||
|
||||
#if !GENERATENODATA
|
||||
if ( !tested )
|
||||
{
|
||||
tested = true;
|
||||
#endif
|
||||
if ( Gestalt(gestaltFSAttr, &response) == noErr )
|
||||
{
|
||||
result = ((response & (1L << gestaltHasFSSpecCalls)) != 0);
|
||||
}
|
||||
#if !GENERATENODATA
|
||||
}
|
||||
#endif
|
||||
return ( result );
|
||||
}
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* QTHasFSSpecCalls returns true if QuickTime provides FSSpec calls */
|
||||
/* except for FSpExchangeFiles. */
|
||||
|
||||
#if !__MACOSSEVENORLATER
|
||||
static Boolean QTHasFSSpecCalls(void)
|
||||
{
|
||||
long response;
|
||||
#if !GENERATENODATA
|
||||
static Boolean tested = false;
|
||||
static Boolean result = false;
|
||||
#else
|
||||
Boolean result = false;
|
||||
#endif
|
||||
|
||||
#if !GENERATENODATA
|
||||
if ( !tested )
|
||||
{
|
||||
tested = true;
|
||||
#endif
|
||||
result = (Gestalt(gestaltQuickTimeVersion, &response) == noErr);
|
||||
#if !GENERATENODATA
|
||||
}
|
||||
#endif
|
||||
return ( result );
|
||||
}
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* HasFSpExchangeFilesCompatibilityFix returns true if FSpExchangeFiles */
|
||||
/* compatibility code has been fixed in system software. */
|
||||
/* This was fixed by System Update 3.0, so if SystemSevenFiveOrLater */
|
||||
/* is true, then we know the fix is in. */
|
||||
|
||||
#if !__MACOSSEVENFIVEORLATER
|
||||
static Boolean HasFSpExchangeFilesCompatibilityFix(void)
|
||||
{
|
||||
long response;
|
||||
#if !GENERATENODATA
|
||||
static Boolean tested = false;
|
||||
static Boolean result = false;
|
||||
#else /* !GENERATENODATA */
|
||||
Boolean result = false;
|
||||
#endif /* !GENERATENODATA */
|
||||
|
||||
#if !GENERATENODATA
|
||||
if ( !tested )
|
||||
{
|
||||
tested = true;
|
||||
#endif /* !GENERATENODATA */
|
||||
if ( Gestalt(gestaltBugFixAttrsTwo, &response) == noErr )
|
||||
{
|
||||
result = ((response & (1L << gestaltFSpExchangeFilesCompatibilityFix)) != 0);
|
||||
}
|
||||
#if !GENERATENODATA
|
||||
}
|
||||
#endif /* !GENERATENODATA */
|
||||
return ( result );
|
||||
}
|
||||
#endif /* !__MACOSSEVENFIVEORLATER */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* HasFSpCreateScriptSupportFix returns true if FSpCreate and */
|
||||
/* FSpCreateResFile have been fixed in system software to correctly set */
|
||||
/* the scriptCode in the volume's catalog. */
|
||||
/* This was fixed by System 7.5 Update 1.0 */
|
||||
|
||||
#if !__MACOSSEVENFIVEONEORLATER
|
||||
static Boolean HasFSpCreateScriptSupportFix(void)
|
||||
{
|
||||
long response;
|
||||
#if !GENERATENODATA
|
||||
static Boolean tested = false;
|
||||
static Boolean result = false;
|
||||
#else
|
||||
Boolean result = false;
|
||||
#endif /* !GENERATENODATA */
|
||||
|
||||
#if !GENERATENODATA
|
||||
if ( !tested )
|
||||
{
|
||||
tested = true;
|
||||
#endif /* !GENERATENODATA */
|
||||
if ( Gestalt(gestaltBugFixAttrsThree, &response) == noErr )
|
||||
{
|
||||
result = ((response & (1L << gestaltFSpCreateScriptSupportFix)) != 0);
|
||||
}
|
||||
#if !GENERATENODATA
|
||||
}
|
||||
#endif /* !GENERATENODATA */
|
||||
return ( result );
|
||||
}
|
||||
#endif /* !__MACOSSEVENFIVEONEORLATER */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/*
|
||||
** File Manager FSp calls
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSMakeFSSpecCompat(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param fileName,
|
||||
FSSpec *spec)
|
||||
{
|
||||
OSErr result;
|
||||
|
||||
#if !__MACOSSEVENORLATER
|
||||
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
|
||||
{
|
||||
Boolean isDirectory;
|
||||
|
||||
result = GetObjectLocation(vRefNum, dirID, fileName,
|
||||
&(spec->vRefNum), &(spec->parID), spec->name,
|
||||
&isDirectory);
|
||||
}
|
||||
else
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
{
|
||||
/* Let the file system create the FSSpec if it can since it does the job */
|
||||
/* much more efficiently than I can. */
|
||||
result = FSMakeFSSpec(vRefNum, dirID, fileName, spec);
|
||||
|
||||
/* Fix a bug in Macintosh PC Exchange's MakeFSSpec code where 0 is */
|
||||
/* returned in the parID field when making an FSSpec to the volume's */
|
||||
/* root directory by passing a full pathname in MakeFSSpec's */
|
||||
/* fileName parameter. Fixed in Mac OS 8.1 */
|
||||
if ( (result == noErr) && (spec->parID == 0) )
|
||||
spec->parID = fsRtParID;
|
||||
}
|
||||
return ( result );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpOpenDFCompat(const FSSpec *spec,
|
||||
char permission,
|
||||
short *refNum)
|
||||
{
|
||||
#if !__MACOSSEVENORLATER
|
||||
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
|
||||
{
|
||||
OSErr result;
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.ioParam.ioVRefNum = spec->vRefNum;
|
||||
pb.fileParam.ioDirID = spec->parID;
|
||||
pb.ioParam.ioNamePtr = (StringPtr) &(spec->name);
|
||||
pb.ioParam.ioVersNum = 0;
|
||||
pb.ioParam.ioPermssn = permission;
|
||||
pb.ioParam.ioMisc = NULL;
|
||||
result = PBHOpenSync(&pb); /* OpenDF not supported by System 6, so use Open */
|
||||
*refNum = pb.ioParam.ioRefNum;
|
||||
return ( result );
|
||||
}
|
||||
else
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
{
|
||||
return ( FSpOpenDF(spec, permission, refNum) );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpOpenRFCompat(const FSSpec *spec,
|
||||
char permission,
|
||||
short *refNum)
|
||||
{
|
||||
#if !__MACOSSEVENORLATER
|
||||
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
|
||||
{
|
||||
OSErr result;
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.ioParam.ioVRefNum = spec->vRefNum;
|
||||
pb.fileParam.ioDirID = spec->parID;
|
||||
pb.ioParam.ioNamePtr = (StringPtr) &(spec->name);
|
||||
pb.ioParam.ioVersNum = 0;
|
||||
pb.ioParam.ioPermssn = permission;
|
||||
pb.ioParam.ioMisc = NULL;
|
||||
result = PBHOpenRFSync(&pb);
|
||||
*refNum = pb.ioParam.ioRefNum;
|
||||
return ( result );
|
||||
}
|
||||
else
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
{
|
||||
return ( FSpOpenRF(spec, permission, refNum) );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpCreateCompat(const FSSpec *spec,
|
||||
OSType creator,
|
||||
OSType fileType,
|
||||
ScriptCode scriptTag)
|
||||
{
|
||||
#if !__MACOSSEVENFIVEONEORLATER
|
||||
OSErr result;
|
||||
UniversalFMPB pb;
|
||||
|
||||
|
||||
if (
|
||||
#if !__MACOSSEVENORLATER
|
||||
(!FSHasFSSpecCalls() && !QTHasFSSpecCalls()) ||
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
!HasFSpCreateScriptSupportFix() )
|
||||
{
|
||||
/* If FSpCreate isn't called, this code will be executed */
|
||||
pb.hPB.fileParam.ioVRefNum = spec->vRefNum;
|
||||
pb.hPB.fileParam.ioDirID = spec->parID;
|
||||
pb.hPB.fileParam.ioNamePtr = (StringPtr) &(spec->name);
|
||||
pb.hPB.fileParam.ioFVersNum = 0;
|
||||
result = PBHCreateSync(&(pb.hPB));
|
||||
if ( result == noErr )
|
||||
{
|
||||
/* get info on created item */
|
||||
pb.ciPB.hFileInfo.ioFDirIndex = 0;
|
||||
result = PBGetCatInfoSync(&(pb.ciPB));
|
||||
if ( result == noErr )
|
||||
{
|
||||
/* Set fdScript in FXInfo */
|
||||
/* The negative script constants (smSystemScript, smCurrentScript, and smAllScripts) */
|
||||
/* don't make sense on disk, so only use scriptTag if scriptTag >= smRoman */
|
||||
/* (smRoman is 0). fdScript is valid if high bit is set (see IM-6, page 9-38) */
|
||||
pb.ciPB.hFileInfo.ioFlXFndrInfo.fdScript = (scriptTag >= smRoman) ?
|
||||
((char)scriptTag | (char)0x80) :
|
||||
(smRoman);
|
||||
/* Set creator/fileType */
|
||||
pb.ciPB.hFileInfo.ioFlFndrInfo.fdCreator = creator;
|
||||
pb.ciPB.hFileInfo.ioFlFndrInfo.fdType = fileType;
|
||||
/* Restore ioDirID field in pb which was changed by PBGetCatInfo */
|
||||
pb.ciPB.hFileInfo.ioDirID = spec->parID;
|
||||
result = PBSetCatInfoSync(&(pb.ciPB));
|
||||
}
|
||||
}
|
||||
return ( result );
|
||||
}
|
||||
else
|
||||
#endif /* !__MACOSSEVENFIVEONEORLATER */
|
||||
{
|
||||
return ( FSpCreate(spec, creator, fileType, scriptTag) );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpDirCreateCompat(const FSSpec *spec,
|
||||
ScriptCode scriptTag,
|
||||
long *createdDirID)
|
||||
{
|
||||
#if !__MACOSSEVENORLATER
|
||||
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
|
||||
{
|
||||
OSErr result;
|
||||
UniversalFMPB pb;
|
||||
|
||||
pb.hPB.fileParam.ioVRefNum = spec->vRefNum;
|
||||
pb.hPB.fileParam.ioDirID = spec->parID;
|
||||
pb.hPB.fileParam.ioNamePtr = (StringPtr) &(spec->name);
|
||||
result = PBDirCreateSync(&(pb.hPB));
|
||||
*createdDirID = pb.hPB.fileParam.ioDirID;
|
||||
if ( result == noErr )
|
||||
{
|
||||
/* get info on created item */
|
||||
pb.ciPB.dirInfo.ioFDirIndex = 0;
|
||||
pb.ciPB.dirInfo.ioDrDirID = spec->parID;
|
||||
result = PBGetCatInfoSync(&(pb.ciPB));
|
||||
if ( result == noErr )
|
||||
{
|
||||
/* Set frScript in DXInfo */
|
||||
/* The negative script constants (smSystemScript, smCurrentScript, and smAllScripts) */
|
||||
/* don't make sense on disk, so only use scriptTag if scriptTag >= smRoman */
|
||||
/* (smRoman is 0). frScript is valid if high bit is set (see IM-6, page 9-38) */
|
||||
pb.ciPB.dirInfo.ioDrFndrInfo.frScript = (scriptTag >= smRoman) ?
|
||||
((char)scriptTag | (char)0x80) :
|
||||
(smRoman);
|
||||
/* Restore ioDirID field in pb which was changed by PBGetCatInfo */
|
||||
pb.ciPB.dirInfo.ioDrDirID = spec->parID;
|
||||
result = PBSetCatInfoSync(&(pb.ciPB));
|
||||
}
|
||||
}
|
||||
return ( result );
|
||||
}
|
||||
else
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
{
|
||||
return ( FSpDirCreate(spec, scriptTag, createdDirID) );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpDeleteCompat(const FSSpec *spec)
|
||||
{
|
||||
#if !__MACOSSEVENORLATER
|
||||
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.ioParam.ioVRefNum = spec->vRefNum;
|
||||
pb.fileParam.ioDirID = spec->parID;
|
||||
pb.ioParam.ioNamePtr = (StringPtr) &(spec->name);
|
||||
pb.ioParam.ioVersNum = 0;
|
||||
return ( PBHDeleteSync(&pb) );
|
||||
}
|
||||
else
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
{
|
||||
return ( FSpDelete(spec) );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpGetFInfoCompat(const FSSpec *spec,
|
||||
FInfo *fndrInfo)
|
||||
{
|
||||
#if !__MACOSSEVENORLATER
|
||||
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
|
||||
{
|
||||
OSErr result;
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.fileParam.ioVRefNum = spec->vRefNum;
|
||||
pb.fileParam.ioDirID = spec->parID;
|
||||
pb.fileParam.ioNamePtr = (StringPtr) &(spec->name);
|
||||
pb.fileParam.ioFVersNum = 0;
|
||||
pb.fileParam.ioFDirIndex = 0;
|
||||
result = PBHGetFInfoSync(&pb);
|
||||
*fndrInfo = pb.fileParam.ioFlFndrInfo;
|
||||
return ( result );
|
||||
}
|
||||
else
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
{
|
||||
return ( FSpGetFInfo(spec, fndrInfo) );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpSetFInfoCompat(const FSSpec *spec,
|
||||
const FInfo *fndrInfo)
|
||||
{
|
||||
#if !__MACOSSEVENORLATER
|
||||
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
|
||||
{
|
||||
OSErr result;
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.fileParam.ioVRefNum = spec->vRefNum;
|
||||
pb.fileParam.ioDirID = spec->parID;
|
||||
pb.fileParam.ioNamePtr = (StringPtr) &(spec->name);
|
||||
pb.fileParam.ioFVersNum = 0;
|
||||
pb.fileParam.ioFDirIndex = 0;
|
||||
result = PBHGetFInfoSync(&pb);
|
||||
if ( result == noErr )
|
||||
{
|
||||
pb.fileParam.ioFlFndrInfo = *fndrInfo;
|
||||
pb.fileParam.ioDirID = spec->parID;
|
||||
result = PBHSetFInfoSync(&pb);
|
||||
}
|
||||
return ( result );
|
||||
}
|
||||
else
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
{
|
||||
return ( FSpSetFInfo(spec, fndrInfo) );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpSetFLockCompat(const FSSpec *spec)
|
||||
{
|
||||
#if !__MACOSSEVENORLATER
|
||||
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.fileParam.ioVRefNum = spec->vRefNum;
|
||||
pb.fileParam.ioDirID = spec->parID;
|
||||
pb.fileParam.ioNamePtr = (StringPtr) &(spec->name);
|
||||
pb.fileParam.ioFVersNum = 0;
|
||||
return ( PBHSetFLockSync(&pb) );
|
||||
}
|
||||
else
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
{
|
||||
return ( FSpSetFLock(spec) );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpRstFLockCompat(const FSSpec *spec)
|
||||
{
|
||||
#if !__MACOSSEVENORLATER
|
||||
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.fileParam.ioVRefNum = spec->vRefNum;
|
||||
pb.fileParam.ioDirID = spec->parID;
|
||||
pb.fileParam.ioNamePtr = (StringPtr) &(spec->name);
|
||||
pb.fileParam.ioFVersNum = 0;
|
||||
return ( PBHRstFLockSync(&pb) );
|
||||
}
|
||||
else
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
{
|
||||
return ( FSpRstFLock(spec) );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpRenameCompat(const FSSpec *spec,
|
||||
ConstStr255Param newName)
|
||||
{
|
||||
#if !__MACOSSEVENORLATER
|
||||
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.ioParam.ioVRefNum = spec->vRefNum;
|
||||
pb.fileParam.ioDirID = spec->parID;
|
||||
pb.ioParam.ioNamePtr = (StringPtr) &(spec->name);
|
||||
pb.ioParam.ioVersNum = 0;
|
||||
pb.ioParam.ioMisc = (Ptr) newName;
|
||||
return ( PBHRenameSync(&pb) );
|
||||
}
|
||||
else
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
{
|
||||
return ( FSpRename(spec, newName) );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpCatMoveCompat(const FSSpec *source,
|
||||
const FSSpec *dest)
|
||||
{
|
||||
#if !__MACOSSEVENORLATER
|
||||
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
|
||||
{
|
||||
CMovePBRec pb;
|
||||
|
||||
/* source and destination volume must be the same */
|
||||
if ( source->vRefNum != dest->vRefNum )
|
||||
return ( paramErr );
|
||||
|
||||
pb.ioNamePtr = (StringPtr) &(source->name);
|
||||
pb.ioVRefNum = source->vRefNum;
|
||||
pb.ioDirID = source->parID;
|
||||
pb.ioNewDirID = dest->parID;
|
||||
pb.ioNewName = (StringPtr) &(dest->name);
|
||||
return ( PBCatMoveSync(&pb) );
|
||||
}
|
||||
else
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
{
|
||||
return ( FSpCatMove(source, dest) );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* GenerateUniqueName generates a name that is unique in both dir1 and dir2 */
|
||||
/* on the specified volume. Ripped off from Feldman's code. */
|
||||
|
||||
#if !__MACOSSEVENFIVEORLATER
|
||||
static OSErr GenerateUniqueName(short volume,
|
||||
long *startSeed,
|
||||
long dir1,
|
||||
long dir2,
|
||||
StringPtr uniqueName)
|
||||
{
|
||||
OSErr error = noErr;
|
||||
long i;
|
||||
CInfoPBRec cinfo;
|
||||
unsigned char hexStr[16];
|
||||
|
||||
for ( i = 0; i < 16; ++i )
|
||||
{
|
||||
if ( i < 10 )
|
||||
{
|
||||
hexStr[i] = 0x30 + i;
|
||||
}
|
||||
else
|
||||
{
|
||||
hexStr[i] = 0x37 + i;
|
||||
}
|
||||
}
|
||||
|
||||
cinfo.hFileInfo.ioVRefNum = volume;
|
||||
cinfo.hFileInfo.ioFDirIndex = 0;
|
||||
cinfo.hFileInfo.ioNamePtr = uniqueName;
|
||||
|
||||
while ( error != fnfErr )
|
||||
{
|
||||
(*startSeed)++;
|
||||
cinfo.hFileInfo.ioNamePtr[0] = 8;
|
||||
for ( i = 1; i <= 8; i++ )
|
||||
{
|
||||
cinfo.hFileInfo.ioNamePtr[i] = hexStr[((*startSeed >> ((8-i)*4)) & 0xf)];
|
||||
}
|
||||
cinfo.hFileInfo.ioDirID = dir1;
|
||||
error = fnfErr;
|
||||
for ( i = 1; i <= 2; i++ )
|
||||
{
|
||||
error = error & PBGetCatInfoSync(&cinfo);
|
||||
cinfo.hFileInfo.ioDirID = dir2;
|
||||
if ( (error != fnfErr) && (error != noErr) )
|
||||
{
|
||||
return ( error );
|
||||
}
|
||||
}
|
||||
}
|
||||
return ( noErr );
|
||||
}
|
||||
#endif /* !__MACOSSEVENFIVEORLATER */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpExchangeFilesCompat(const FSSpec *source,
|
||||
const FSSpec *dest)
|
||||
{
|
||||
#if !__MACOSSEVENFIVEORLATER
|
||||
if (
|
||||
#if !__MACOSSEVENORLATER
|
||||
!FSHasFSSpecCalls() ||
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
!HasFSpExchangeFilesCompatibilityFix() )
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
CInfoPBRec catInfoSource, catInfoDest;
|
||||
OSErr result, result2;
|
||||
Str31 unique1, unique2;
|
||||
StringPtr unique1Ptr, unique2Ptr, swapola;
|
||||
GetVolParmsInfoBuffer volInfo;
|
||||
long theSeed, temp;
|
||||
|
||||
/* Make sure the source and destination are on the same volume */
|
||||
if ( source->vRefNum != dest->vRefNum )
|
||||
{
|
||||
result = diffVolErr;
|
||||
goto errorExit3;
|
||||
}
|
||||
|
||||
/* Try PBExchangeFiles first since it preserves the file ID reference */
|
||||
pb.fidParam.ioNamePtr = (StringPtr) &(source->name);
|
||||
pb.fidParam.ioVRefNum = source->vRefNum;
|
||||
pb.fidParam.ioDestNamePtr = (StringPtr) &(dest->name);
|
||||
pb.fidParam.ioDestDirID = dest->parID;
|
||||
pb.fidParam.ioSrcDirID = source->parID;
|
||||
|
||||
result = PBExchangeFilesSync(&pb);
|
||||
|
||||
/* Note: The compatibility case won't work for files with *Btree control blocks. */
|
||||
/* Right now the only *Btree files are created by the system. */
|
||||
if ( result != noErr )
|
||||
{
|
||||
pb.ioParam.ioNamePtr = NULL;
|
||||
pb.ioParam.ioBuffer = (Ptr) &volInfo;
|
||||
pb.ioParam.ioReqCount = sizeof(volInfo);
|
||||
result2 = PBHGetVolParmsSync(&pb);
|
||||
|
||||
/* continue if volume has no fileID support (or no GetVolParms support) */
|
||||
if ( (result2 == noErr) && hasFileIDs(volInfo) )
|
||||
{
|
||||
goto errorExit3;
|
||||
}
|
||||
|
||||
/* Get the catalog information for each file */
|
||||
/* and make sure both files are *really* files */
|
||||
catInfoSource.hFileInfo.ioVRefNum = source->vRefNum;
|
||||
catInfoSource.hFileInfo.ioFDirIndex = 0;
|
||||
catInfoSource.hFileInfo.ioNamePtr = (StringPtr) &(source->name);
|
||||
catInfoSource.hFileInfo.ioDirID = source->parID;
|
||||
catInfoSource.hFileInfo.ioACUser = 0; /* ioACUser used to be filler2 */
|
||||
result = PBGetCatInfoSync(&catInfoSource);
|
||||
if ( result != noErr )
|
||||
{
|
||||
goto errorExit3;
|
||||
}
|
||||
if ( (catInfoSource.hFileInfo.ioFlAttrib & ioDirMask) != 0 )
|
||||
{
|
||||
result = notAFileErr;
|
||||
goto errorExit3;
|
||||
}
|
||||
|
||||
catInfoDest.hFileInfo.ioVRefNum = dest->vRefNum;
|
||||
catInfoDest.hFileInfo.ioFDirIndex = 0;
|
||||
catInfoDest.hFileInfo.ioNamePtr = (StringPtr) &(dest->name);
|
||||
catInfoDest.hFileInfo.ioDirID = dest->parID;
|
||||
catInfoDest.hFileInfo.ioACUser = 0; /* ioACUser used to be filler2 */
|
||||
result = PBGetCatInfoSync(&catInfoDest);
|
||||
if ( result != noErr )
|
||||
{
|
||||
goto errorExit3;
|
||||
}
|
||||
if ( (catInfoDest.hFileInfo.ioFlAttrib & ioDirMask) != 0 )
|
||||
{
|
||||
result = notAFileErr;
|
||||
goto errorExit3;
|
||||
}
|
||||
|
||||
/* generate 2 filenames that are unique in both directories */
|
||||
theSeed = 0x64666A6C; /* a fine unlikely filename */
|
||||
unique1Ptr = (StringPtr)&unique1;
|
||||
unique2Ptr = (StringPtr)&unique2;
|
||||
|
||||
result = GenerateUniqueName(source->vRefNum, &theSeed, source->parID, dest->parID, unique1Ptr);
|
||||
if ( result != noErr )
|
||||
{
|
||||
goto errorExit3;
|
||||
}
|
||||
|
||||
GenerateUniqueName(source->vRefNum, &theSeed, source->parID, dest->parID, unique2Ptr);
|
||||
if ( result != noErr )
|
||||
{
|
||||
goto errorExit3;
|
||||
}
|
||||
|
||||
/* rename source to unique1 */
|
||||
pb.fileParam.ioNamePtr = (StringPtr) &(source->name);
|
||||
pb.ioParam.ioMisc = (Ptr) unique1Ptr;
|
||||
pb.ioParam.ioVersNum = 0;
|
||||
result = PBHRenameSync(&pb);
|
||||
if ( result != noErr )
|
||||
{
|
||||
goto errorExit3;
|
||||
}
|
||||
|
||||
/* rename dest to unique2 */
|
||||
pb.ioParam.ioMisc = (Ptr) unique2Ptr;
|
||||
pb.ioParam.ioVersNum = 0;
|
||||
pb.fileParam.ioNamePtr = (StringPtr) &(dest->name);
|
||||
pb.fileParam.ioDirID = dest->parID;
|
||||
result = PBHRenameSync(&pb);
|
||||
if ( result != noErr )
|
||||
{
|
||||
goto errorExit2; /* back out gracefully by renaming unique1 back to source */
|
||||
}
|
||||
|
||||
/* If files are not in same directory, swap their locations */
|
||||
if ( source->parID != dest->parID )
|
||||
{
|
||||
/* move source file to dest directory */
|
||||
pb.copyParam.ioNamePtr = unique1Ptr;
|
||||
pb.copyParam.ioNewName = NULL;
|
||||
pb.copyParam.ioNewDirID = dest->parID;
|
||||
pb.copyParam.ioDirID = source->parID;
|
||||
result = PBCatMoveSync((CMovePBPtr) &pb);
|
||||
if ( result != noErr )
|
||||
{
|
||||
goto errorExit1; /* back out gracefully by renaming both files to original names */
|
||||
}
|
||||
|
||||
/* move dest file to source directory */
|
||||
pb.copyParam.ioNamePtr = unique2Ptr;
|
||||
pb.copyParam.ioNewDirID = source->parID;
|
||||
pb.copyParam.ioDirID = dest->parID;
|
||||
result = PBCatMoveSync((CMovePBPtr) &pb);
|
||||
if ( result != noErr)
|
||||
{
|
||||
/* life is very bad. We'll at least try to move source back */
|
||||
pb.copyParam.ioNamePtr = unique1Ptr;
|
||||
pb.copyParam.ioNewName = NULL;
|
||||
pb.copyParam.ioNewDirID = source->parID;
|
||||
pb.copyParam.ioDirID = dest->parID;
|
||||
(void) PBCatMoveSync((CMovePBPtr) &pb); /* ignore errors */
|
||||
goto errorExit1; /* back out gracefully by renaming both files to original names */
|
||||
}
|
||||
}
|
||||
|
||||
/* Make unique1Ptr point to file in source->parID */
|
||||
/* and unique2Ptr point to file in dest->parID */
|
||||
/* This lets us fall through to the rename code below */
|
||||
swapola = unique1Ptr;
|
||||
unique1Ptr = unique2Ptr;
|
||||
unique2Ptr = swapola;
|
||||
|
||||
/* At this point, the files are in their new locations (if they were moved) */
|
||||
/* Source is named Unique1 (name pointed to by unique2Ptr) and is in dest->parID */
|
||||
/* Dest is named Unique2 (name pointed to by unique1Ptr) and is in source->parID */
|
||||
/* Need to swap attributes except mod date and swap names */
|
||||
|
||||
/* swap the catalog info by re-aiming the CInfoPB's */
|
||||
catInfoSource.hFileInfo.ioNamePtr = unique1Ptr;
|
||||
catInfoDest.hFileInfo.ioNamePtr = unique2Ptr;
|
||||
|
||||
catInfoSource.hFileInfo.ioDirID = source->parID;
|
||||
catInfoDest.hFileInfo.ioDirID = dest->parID;
|
||||
|
||||
/* Swap the original mod dates with each file */
|
||||
temp = catInfoSource.hFileInfo.ioFlMdDat;
|
||||
catInfoSource.hFileInfo.ioFlMdDat = catInfoDest.hFileInfo.ioFlMdDat;
|
||||
catInfoDest.hFileInfo.ioFlMdDat = temp;
|
||||
|
||||
/* Here's the swap (ignore errors) */
|
||||
(void) PBSetCatInfoSync(&catInfoSource);
|
||||
(void) PBSetCatInfoSync(&catInfoDest);
|
||||
|
||||
/* rename unique2 back to dest */
|
||||
errorExit1:
|
||||
pb.ioParam.ioMisc = (Ptr) &(dest->name);
|
||||
pb.ioParam.ioVersNum = 0;
|
||||
pb.fileParam.ioNamePtr = unique2Ptr;
|
||||
pb.fileParam.ioDirID = dest->parID;
|
||||
(void) PBHRenameSync(&pb); /* ignore errors */
|
||||
|
||||
/* rename unique1 back to source */
|
||||
errorExit2:
|
||||
pb.ioParam.ioMisc = (Ptr) &(source->name);
|
||||
pb.ioParam.ioVersNum = 0;
|
||||
pb.fileParam.ioNamePtr = unique1Ptr;
|
||||
pb.fileParam.ioDirID = source->parID;
|
||||
(void) PBHRenameSync(&pb); /* ignore errors */
|
||||
}
|
||||
errorExit3: { /* null statement */ }
|
||||
return ( result );
|
||||
}
|
||||
else
|
||||
#endif /* !__MACOSSEVENFIVEORLATER */
|
||||
{
|
||||
return ( FSpExchangeFiles(source, dest) );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/*
|
||||
** Resource Manager FSp calls
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal short FSpOpenResFileCompat(const FSSpec *spec,
|
||||
SignedByte permission)
|
||||
{
|
||||
#if !__MACOSSEVENORLATER
|
||||
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
|
||||
{
|
||||
return ( HOpenResFile(spec->vRefNum, spec->parID, spec->name, permission) );
|
||||
}
|
||||
else
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
{
|
||||
return ( FSpOpenResFile(spec, permission) );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal void FSpCreateResFileCompat(const FSSpec *spec,
|
||||
OSType creator,
|
||||
OSType fileType,
|
||||
ScriptCode scriptTag)
|
||||
{
|
||||
#if !__MACOSSEVENFIVEONEORLATER
|
||||
if (
|
||||
#if !__MACOSSEVENORLATER
|
||||
(!FSHasFSSpecCalls() && !QTHasFSSpecCalls()) ||
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
!HasFSpCreateScriptSupportFix() )
|
||||
{
|
||||
OSErr result;
|
||||
CInfoPBRec pb;
|
||||
|
||||
HCreateResFile(spec->vRefNum, spec->parID, spec->name);
|
||||
if ( ResError() == noErr )
|
||||
{
|
||||
/* get info on created item */
|
||||
pb.hFileInfo.ioVRefNum = spec->vRefNum;
|
||||
pb.hFileInfo.ioDirID = spec->parID;
|
||||
pb.hFileInfo.ioNamePtr = (StringPtr) &(spec->name);
|
||||
pb.hFileInfo.ioFDirIndex = 0;
|
||||
result = PBGetCatInfoSync(&pb);
|
||||
if ( result == noErr )
|
||||
{
|
||||
/* Set fdScript in FXInfo */
|
||||
/* The negative script constants (smSystemScript, smCurrentScript, and smAllScripts) */
|
||||
/* don't make sense on disk, so only use scriptTag if scriptTag >= smRoman */
|
||||
/* (smRoman is 0). fdScript is valid if high bit is set (see IM-6, page 9-38) */
|
||||
pb.hFileInfo.ioFlXFndrInfo.fdScript = (scriptTag >= smRoman) ?
|
||||
((char)scriptTag | (char)0x80) :
|
||||
(smRoman);
|
||||
/* Set creator/fileType */
|
||||
pb.hFileInfo.ioFlFndrInfo.fdCreator = creator;
|
||||
pb.hFileInfo.ioFlFndrInfo.fdType = fileType;
|
||||
|
||||
/* Restore ioDirID field in pb which was changed by PBGetCatInfo */
|
||||
pb.hFileInfo.ioDirID = spec->parID;
|
||||
result = PBSetCatInfoSync(&pb);
|
||||
}
|
||||
/* Set ResErr low memory global to result */
|
||||
LMSetResErr(result);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
#endif /* !__MACOSSEVENFIVEONEORLATER */
|
||||
{
|
||||
FSpCreateResFile(spec, creator, fileType, scriptTag);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
488
src/mac/morefile/FSpCompa.h
Normal file
488
src/mac/morefile/FSpCompa.h
Normal file
@ -0,0 +1,488 @@
|
||||
/*
|
||||
** Apple Macintosh Developer Technical Support
|
||||
**
|
||||
** FSSpec compatibility functions.
|
||||
**
|
||||
** by Jim Luther, Apple Developer Technical Support Emeritus
|
||||
**
|
||||
** File: FSpCompat.h
|
||||
**
|
||||
** Copyright © 1992-1998 Apple Computer, Inc.
|
||||
** All rights reserved.
|
||||
**
|
||||
** You may incorporate this sample code into your applications without
|
||||
** restriction, though the sample code has been provided "AS IS" and the
|
||||
** responsibility for its operation is 100% yours. However, what you are
|
||||
** not permitted to do is to redistribute the source as "DSC Sample Code"
|
||||
** after having made changes. If you're going to re-distribute the source,
|
||||
** we require that you make it clear in the source that the code was
|
||||
** descended from Apple Sample Code, but that you've made changes.
|
||||
*/
|
||||
|
||||
#ifndef __FSPCOMPAT__
|
||||
#define __FSPCOMPAT__
|
||||
|
||||
#include <Types.h>
|
||||
#include <Files.h>
|
||||
|
||||
#include "Optim.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSMakeFSSpecCompat(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param fileName,
|
||||
FSSpec *spec);
|
||||
/* ¦ Initialize a FSSpec record.
|
||||
The FSMakeFSSpecCompat function fills in the fields of an FSSpec record.
|
||||
If the file system can't create the FSSpec, then the compatibility code
|
||||
creates a FSSpec that is exactly like an FSSpec except that spec.name
|
||||
for a file may not have the same capitalization as the file's catalog
|
||||
entry on the disk volume. That is because fileName is parsed to get the
|
||||
name instead of getting the name back from the file system. This works
|
||||
fine with System 6 where FSMakeSpec isn't available.
|
||||
|
||||
vRefNum input: Volume specification.
|
||||
dirID input: Directory ID.
|
||||
fileName input: Pointer to object name, or nil when dirID specifies
|
||||
a directory that's the object.
|
||||
spec output: A file system specification to be filled in by
|
||||
FSMakeFSSpecCompat.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume doesnÕt exist
|
||||
fnfErr -43 File or directory does not exist
|
||||
(FSSpec is still valid)
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpOpenDFCompat(const FSSpec *spec,
|
||||
char permission,
|
||||
short *refNum);
|
||||
/* ¦ Open a file's data fork.
|
||||
The FSpOpenDFCompat function opens the data fork of the file specified
|
||||
by spec.
|
||||
Differences from FSpOpenDF: If FSpOpenDF isn't available,
|
||||
FSpOpenDFCompat uses PHBOpen because System 6 doesn't support PBHOpenDF.
|
||||
This means FSpOpenDFCompat could accidentally open a driver if the
|
||||
spec->name begins with a period.
|
||||
|
||||
spec input: An FSSpec record specifying the file whose data
|
||||
fork is to be opened.
|
||||
permission input: A constant indicating the desired file access
|
||||
permissions.
|
||||
refNum output: A reference number of an access path to the file's
|
||||
data fork.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
tmfoErr -42 Too many files open
|
||||
fnfErr -43 File not found
|
||||
opWrErr -49 File already open for writing
|
||||
permErr -54 Attempt to open locked file for writing
|
||||
dirNFErr -120 Directory not found or incomplete pathname
|
||||
afpAccessDenied -5000 User does not have the correct access to
|
||||
the file
|
||||
|
||||
__________
|
||||
|
||||
See also: FSpOpenAware
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpOpenRFCompat(const FSSpec *spec,
|
||||
char permission,
|
||||
short *refNum);
|
||||
/* ¦ Open a file's resource fork.
|
||||
The FSpOpenRFCompat function opens the resource fork of the file
|
||||
specified by spec.
|
||||
|
||||
spec input: An FSSpec record specifying the file whose resource
|
||||
fork is to be opened.
|
||||
permission input: A constant indicating the desired file access
|
||||
permissions.
|
||||
refNum output: A reference number of an access path to the file's
|
||||
resource fork.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
tmfoErr -42 Too many files open
|
||||
fnfErr -43 File not found
|
||||
opWrErr -49 File already open for writing
|
||||
permErr -54 Attempt to open locked file for writing
|
||||
dirNFErr -120 Directory not found or incomplete pathname
|
||||
afpAccessDenied -5000 User does not have the correct access to
|
||||
the file
|
||||
|
||||
__________
|
||||
|
||||
See also: FSpOpenRFAware
|
||||
*/
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpCreateCompat(const FSSpec *spec,
|
||||
OSType creator,
|
||||
OSType fileType,
|
||||
ScriptCode scriptTag);
|
||||
/* ¦ Create a new file.
|
||||
The FSpCreateCompat function creates a new file with the specified
|
||||
type, creator, and script code.
|
||||
Differences from FSpCreate: FSpCreateCompat correctly sets the
|
||||
fdScript in the file's FXInfo record to scriptTag if the problem
|
||||
isn't fixed in the File Manager code.
|
||||
|
||||
spec input: An FSSpec record specifying the file to create.
|
||||
creator input: The creator of the new file.
|
||||
fileType input The file type of the new file.
|
||||
scriptCode input: The code of the script system in which the file
|
||||
name is to be displayed.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
dirFulErr -33 File directory full
|
||||
dskFulErr -34 Disk is full
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
fnfErr -43 Directory not found or incomplete pathname
|
||||
wPrErr -44 Hardware volume lock
|
||||
vLckdErr -46 Software volume lock
|
||||
dupFNErr -48 Duplicate filename and version
|
||||
dirNFErrdirNFErr -120 Directory not found or incomplete pathname
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
afpObjectTypeErr -5025 A directory exists with that name
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpDirCreateCompat(const FSSpec *spec,
|
||||
ScriptCode scriptTag,
|
||||
long *createdDirID);
|
||||
/* ¦ Create a new directory.
|
||||
The FSpDirCreateCompat function creates a new directory and returns the
|
||||
directory ID of the newDirectory.
|
||||
|
||||
spec input: An FSSpec record specifying the directory to
|
||||
create.
|
||||
scriptCode input: The code of the script system in which the
|
||||
directory name is to be displayed.
|
||||
createdDirID output: The directory ID of the directory that was
|
||||
created.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
dirFulErr -33 File directory full
|
||||
dskFulErr -34 Disk is full
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
fnfErr -43 Directory not found or incomplete pathname
|
||||
wPrErr -44 Hardware volume lock
|
||||
vLckdErr -46 Software volume lock
|
||||
dupFNErr -48 Duplicate filename and version
|
||||
dirNFErrdirNFErr -120 Directory not found or incomplete pathname
|
||||
wrgVolTypErr -123 Not an HFS volume
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpDeleteCompat(const FSSpec *spec);
|
||||
/* ¦ Delete a file or directory.
|
||||
The FSpDeleteCompat function deletes a file or directory.
|
||||
|
||||
spec input: An FSSpec record specifying the file or
|
||||
directory to delete.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
fnfErr -43 File not found
|
||||
wPrErr -44 Hardware volume lock
|
||||
fLckdErr -45 File is locked
|
||||
vLckdErr -46 Software volume lock
|
||||
fBsyErr -47 File busy, directory not empty, or
|
||||
working directory control block open
|
||||
dirNFErrdirNFErr -120 Directory not found or incomplete pathname
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpGetFInfoCompat(const FSSpec *spec,
|
||||
FInfo *fndrInfo);
|
||||
/* ¦ Get the finder information for a file.
|
||||
The FSpGetFInfoCompat function gets the finder information for a file.
|
||||
|
||||
spec input: An FSSpec record specifying the file.
|
||||
fndrInfo output: If the object is a file, then its FInfo.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
fnfErr -43 File not found
|
||||
paramErr -50 No default volume
|
||||
dirNFErrdirNFErr -120 Directory not found or incomplete pathname
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
afpObjectTypeErr -5025 Directory not found or incomplete pathname
|
||||
|
||||
__________
|
||||
|
||||
Also see: FSpGetDInfo
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpSetFInfoCompat(const FSSpec *spec,
|
||||
const FInfo *fndrInfo);
|
||||
/* ¦ Set the finder information for a file.
|
||||
The FSpSetFInfoCompat function sets the finder information for a file.
|
||||
|
||||
spec input: An FSSpec record specifying the file.
|
||||
fndrInfo input: The FInfo.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
fnfErr -43 File not found
|
||||
wPrErr -44 Hardware volume lock
|
||||
fLckdErr -45 File is locked
|
||||
vLckdErr -46 Software volume lock
|
||||
dirNFErrdirNFErr -120 Directory not found or incomplete pathname
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
afpObjectTypeErr -5025 Object was a directory
|
||||
|
||||
__________
|
||||
|
||||
Also see: FSpSetDInfo
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpSetFLockCompat(const FSSpec *spec);
|
||||
/* ¦ Lock a file.
|
||||
The FSpSetFLockCompat function locks a file.
|
||||
|
||||
spec input: An FSSpec record specifying the file.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
fnfErr -43 File not found
|
||||
wPrErr -44 Hardware volume lock
|
||||
vLckdErr -46 Software volume lock
|
||||
dirNFErrdirNFErr -120 Directory not found or incomplete pathname
|
||||
afpAccessDenied -5000 User does not have the correct access to
|
||||
the file
|
||||
afpObjectTypeErr -5025 Folder locking not supported by volume
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpRstFLockCompat(const FSSpec *spec);
|
||||
/* ¦ Unlock a file.
|
||||
The FSpRstFLockCompat function unlocks a file.
|
||||
|
||||
spec input: An FSSpec record specifying the file.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
fnfErr -43 File not found
|
||||
wPrErr -44 Hardware volume lock
|
||||
vLckdErr -46 Software volume lock
|
||||
dirNFErrdirNFErr -120 Directory not found or incomplete pathname
|
||||
afpAccessDenied -5000 User does not have the correct access to
|
||||
the file
|
||||
afpObjectTypeErr -5025 Folder locking not supported by volume
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpRenameCompat(const FSSpec *spec,
|
||||
ConstStr255Param newName);
|
||||
/* ¦ Rename a file or directory.
|
||||
The FSpRenameCompat function renames a file or directory.
|
||||
|
||||
spec input: An FSSpec record specifying the file.
|
||||
newName input: The new name of the file or directory.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
dirFulErr -33 File directory full
|
||||
dskFulErr -34 Volume is full
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
fnfErr -43 File not found
|
||||
wPrErr -44 Hardware volume lock
|
||||
fLckdErr -45 File is locked
|
||||
vLckdErr -46 Software volume lock
|
||||
dupFNErr -48 Duplicate filename and version
|
||||
paramErr -50 No default volume
|
||||
fsRnErr -59 Problem during rename
|
||||
dirNFErrdirNFErr -120 Directory not found or incomplete pathname
|
||||
afpAccessDenied -5000 User does not have the correct access to
|
||||
the file
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpCatMoveCompat(const FSSpec *source,
|
||||
const FSSpec *dest);
|
||||
/* ¦ Move a file or directory to a different location on on the same volume.
|
||||
The FSpCatMoveCompat function moves a file or directory to a different
|
||||
location on on the same volume.
|
||||
|
||||
source input: An FSSpec record specifying the file or directory.
|
||||
dest input: An FSSpec record specifying the name and location
|
||||
of the directory into which the source file or
|
||||
directory is to be moved.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename or attempt to move into
|
||||
a file
|
||||
fnfErr -43 File not found
|
||||
wPrErr -44 Hardware volume lock
|
||||
fLckdErr -45 Target directory is locked
|
||||
vLckdErr -46 Software volume lock
|
||||
dupFNErr -48 Duplicate filename and version
|
||||
paramErr -50 No default volume
|
||||
badMovErr -122 Attempt to move into offspring
|
||||
wrgVolTypErr -123 Not an HFS volume
|
||||
afpAccessDenied -5000 User does not have the correct access to
|
||||
the file
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpExchangeFilesCompat(const FSSpec *source,
|
||||
const FSSpec *dest);
|
||||
/* ¦ Exchange the data stored in two files on the same volume.
|
||||
The FSpExchangeFilesCompat function swaps the data in two files by
|
||||
changing the information in the volume's catalog and, if the files
|
||||
are open, in the file control blocks.
|
||||
Differences from FSpExchangeFiles: Correctly exchanges files on volumes
|
||||
that don't support PBExchangeFiles. FSpExchangeFiles attempts to support
|
||||
volumes that don't support PBExchangeFiles, but in System 7, 7.0.1, 7.1,
|
||||
and 7 Pro, the compatibility code just doesn't work on volumes that
|
||||
don't support PBExchangeFiles (even though you may get a noErr result).
|
||||
System Update 3.0 and System 7.5 and later have the problems in
|
||||
FSpExchangeFiles corrected.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
fnfErr -43 File not found
|
||||
fLckdErr -45 File is locked
|
||||
vLckdErr -46 Volume is locked or read-only
|
||||
paramErr -50 Function not supported by volume
|
||||
volOfflinErr -53 Volume is offline
|
||||
wrgVolTypErr -123 Not an HFS volume
|
||||
diffVolErr -1303 Files on different volumes
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
afpObjectTypeErr -5025 Object is a directory, not a file
|
||||
afpSameObjectErr -5038 Source and destination files are the same
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal short FSpOpenResFileCompat(const FSSpec *spec,
|
||||
SignedByte permission);
|
||||
/* ¦ Open a file's resource file.
|
||||
The FSpOpenResFileCompat function opens the resource file specified
|
||||
by spec.
|
||||
|
||||
spec input: An FSSpec record specifying the file whose
|
||||
resource file is to be opened.
|
||||
permission input: A constant indicating the desired file access
|
||||
permissions.
|
||||
function result output: A resource file reference number, or if there's
|
||||
an error -1.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr Ð35 No such volume
|
||||
ioErr Ð36 I/O error
|
||||
bdNamErr Ð37 Bad filename or volume name (perhaps zero
|
||||
length)
|
||||
eofErr Ð39 End of file
|
||||
tmfoErr Ð42 Too many files open
|
||||
fnfErr Ð43 File not found
|
||||
opWrErr Ð49 File already open with write permission
|
||||
permErr Ð54 Permissions error (on file open)
|
||||
extFSErr Ð58 Volume belongs to an external file system
|
||||
memFullErr Ð108 Not enough room in heap zone
|
||||
dirNFErr Ð120 Directory not found
|
||||
mapReadErr Ð199 Map inconsistent with operation
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal void FSpCreateResFileCompat(const FSSpec *spec,
|
||||
OSType creator,
|
||||
OSType fileType,
|
||||
ScriptCode scriptTag);
|
||||
/* ¦ Create a resource file.
|
||||
The FSpCreateResFileCompat function creates a new resource file with
|
||||
the specified type, creator, and script code.
|
||||
Differences from FSpCreateResFile: FSpCreateResFileCompat correctly
|
||||
sets the fdScript in the file's FXInfo record to scriptTag if the
|
||||
problem isn't fixed in the File Manager code.
|
||||
|
||||
spec input: An FSSpec record specifying the resource file to create.
|
||||
creator input: The creator of the new file.
|
||||
fileType input The file type of the new file.
|
||||
scriptCode input: The code of the script system in which the file
|
||||
name is to be displayed.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
dirFulErr Ð33 Directory full
|
||||
dskFulErr Ð34 Disk full
|
||||
nsvErr Ð35 No such volume
|
||||
ioErr Ð36 I/O error
|
||||
bdNamErr Ð37 Bad filename or volume name (perhaps zero
|
||||
length)
|
||||
tmfoErr Ð42 Too many files open
|
||||
wPrErrw Ð44 Disk is write-protected
|
||||
fLckdErr Ð45 File is locked
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "OptimEnd.h"
|
||||
|
||||
#endif /* __FSPCOMPAT__ */
|
||||
|
593
src/mac/morefile/FileCopy.cpp
Normal file
593
src/mac/morefile/FileCopy.cpp
Normal file
@ -0,0 +1,593 @@
|
||||
/*
|
||||
** Apple Macintosh Developer Technical Support
|
||||
**
|
||||
** FileCopy: A robust, general purpose file copy routine.
|
||||
**
|
||||
** by Jim Luther, Apple Developer Technical Support Emeritus
|
||||
**
|
||||
** File: FileCopy.c
|
||||
**
|
||||
** Copyright © 1992-1998 Apple Computer, Inc.
|
||||
** All rights reserved.
|
||||
**
|
||||
** You may incorporate this sample code into your applications without
|
||||
** restriction, though the sample code has been provided "AS IS" and the
|
||||
** responsibility for its operation is 100% yours. However, what you are
|
||||
** not permitted to do is to redistribute the source as "DSC Sample Code"
|
||||
** after having made changes. If you're going to re-distribute the source,
|
||||
** we require that you make it clear in the source that the code was
|
||||
** descended from Apple Sample Code, but that you've made changes.
|
||||
*/
|
||||
|
||||
#include <Types.h>
|
||||
#include <Errors.h>
|
||||
#include <Memory.h>
|
||||
#include <Files.h>
|
||||
|
||||
#define __COMPILINGMOREFILES
|
||||
|
||||
#include "MoreFile.h"
|
||||
#include "MoreExtr.h"
|
||||
#include "MoreDesk.h"
|
||||
#include "FileCopy.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* local constants */
|
||||
|
||||
/* The deny-mode privileges to use when opening the source and destination files. */
|
||||
|
||||
enum
|
||||
{
|
||||
srcCopyMode = dmRdDenyWr,
|
||||
dstCopyMode = dmWrDenyRdWr
|
||||
};
|
||||
|
||||
/* The largest (16K) and smallest (.5K) copy buffer to use if the caller doesn't supply
|
||||
** their own copy buffer. */
|
||||
|
||||
enum
|
||||
{
|
||||
bigCopyBuffSize = 0x00004000,
|
||||
minCopyBuffSize = 0x00000200
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* static prototypes */
|
||||
|
||||
static OSErr GetDestinationDirInfo(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name,
|
||||
long *theDirID,
|
||||
Boolean *isDirectory,
|
||||
Boolean *isDropBox);
|
||||
/* GetDestinationDirInfo tells us if the destination is a directory, it's
|
||||
directory ID, and if it's an AppleShare drop box (write privileges only --
|
||||
no read or search privileges).
|
||||
vRefNum input: Volume specification.
|
||||
dirID input: Directory ID.
|
||||
name input: Pointer to object name, or nil when dirID
|
||||
specifies a directory that's the object.
|
||||
theDirID output: If the object is a file, then its parent directory
|
||||
ID. If the object is a directory, then its ID.
|
||||
isDirectory output: True if object is a directory; false if
|
||||
object is a file.
|
||||
isDropBox output: True if directory is an AppleShare drop box.
|
||||
*/
|
||||
|
||||
static OSErr CheckForForks(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name,
|
||||
Boolean *hasDataFork,
|
||||
Boolean *hasResourceFork);
|
||||
/* CheckForForks tells us if there is a data or resource fork to copy.
|
||||
vRefNum input: Volume specification of the file's current
|
||||
location.
|
||||
dirID input: Directory ID of the file's current location.
|
||||
name input: The name of the file.
|
||||
*/
|
||||
|
||||
static OSErr PreflightFileCopySpace(short srcVRefNum,
|
||||
long srcDirID,
|
||||
ConstStr255Param srcName,
|
||||
ConstStr255Param dstVolName,
|
||||
short dstVRefNum,
|
||||
Boolean *spaceOK);
|
||||
/* PreflightFileCopySpace determines if there's enough space on a
|
||||
volume to copy the specified file to that volume.
|
||||
Note: The results of this routine are not perfect. For example if the
|
||||
volume's catalog or extents overflow file grows when the new file is
|
||||
created, more allocation blocks may be needed beyond those needed for
|
||||
the file's data and resource forks.
|
||||
|
||||
srcVRefNum input: Volume specification of the file's current
|
||||
location.
|
||||
srcDirID input: Directory ID of the file's current location.
|
||||
srcName input: The name of the file.
|
||||
dstVolName input: A pointer to the name of the volume where
|
||||
the file will be copied or NULL.
|
||||
dstVRefNum input: Volume specification indicating the volume
|
||||
where the file will be copied.
|
||||
spaceOK output: true if there's enough space on the volume for
|
||||
the file's data and resource forks.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static OSErr GetDestinationDirInfo(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name,
|
||||
long *theDirID,
|
||||
Boolean *isDirectory,
|
||||
Boolean *isDropBox)
|
||||
{
|
||||
CInfoPBRec pb;
|
||||
OSErr error;
|
||||
|
||||
pb.dirInfo.ioACUser = 0; /* ioACUser used to be filler2, clear it before calling GetCatInfo */
|
||||
error = GetCatInfoNoName(vRefNum, dirID, name, &pb);
|
||||
*theDirID = pb.dirInfo.ioDrDirID;
|
||||
*isDirectory = (pb.dirInfo.ioFlAttrib & ioDirMask) != 0;
|
||||
/* see if access priviledges are make changes, not see folder, and not see files (drop box) */
|
||||
*isDropBox = ((pb.dirInfo.ioACUser & 0x07) == 0x03);
|
||||
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static OSErr CheckForForks(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name,
|
||||
Boolean *hasDataFork,
|
||||
Boolean *hasResourceFork)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
OSErr error;
|
||||
|
||||
pb.fileParam.ioNamePtr = (StringPtr)name;
|
||||
pb.fileParam.ioVRefNum = vRefNum;
|
||||
pb.fileParam.ioFVersNum = 0;
|
||||
pb.fileParam.ioDirID = dirID;
|
||||
pb.fileParam.ioFDirIndex = 0;
|
||||
error = PBHGetFInfoSync(&pb);
|
||||
*hasDataFork = (pb.fileParam.ioFlLgLen != 0);
|
||||
*hasResourceFork = (pb.fileParam.ioFlRLgLen != 0);
|
||||
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static OSErr PreflightFileCopySpace(short srcVRefNum,
|
||||
long srcDirID,
|
||||
ConstStr255Param srcName,
|
||||
ConstStr255Param dstVolName,
|
||||
short dstVRefNum,
|
||||
Boolean *spaceOK)
|
||||
{
|
||||
UniversalFMPB pb;
|
||||
OSErr error;
|
||||
unsigned long dstFreeBlocks;
|
||||
unsigned long dstBlksPerAllocBlk;
|
||||
unsigned long srcDataBlks;
|
||||
unsigned long srcResourceBlks;
|
||||
|
||||
error = XGetVolumeInfoNoName(dstVolName, dstVRefNum, &pb.xPB);
|
||||
if ( error == noErr )
|
||||
{
|
||||
/* get allocation block size (always multiple of 512) and divide by 512
|
||||
to get number of 512-byte blocks per allocation block */
|
||||
dstBlksPerAllocBlk = ((unsigned long)pb.xPB.ioVAlBlkSiz >> 9);
|
||||
|
||||
/* Convert freeBytes to free disk blocks (512-byte blocks) */
|
||||
dstFreeBlocks = (pb.xPB.ioVFreeBytes.hi << 23) + (pb.xPB.ioVFreeBytes.lo >> 9);
|
||||
|
||||
/* Now, get the size of the file's data resource forks */
|
||||
pb.hPB.fileParam.ioNamePtr = (StringPtr)srcName;
|
||||
pb.hPB.fileParam.ioVRefNum = srcVRefNum;
|
||||
pb.hPB.fileParam.ioFVersNum = 0;
|
||||
pb.hPB.fileParam.ioDirID = srcDirID;
|
||||
pb.hPB.fileParam.ioFDirIndex = 0;
|
||||
error = PBHGetFInfoSync(&pb.hPB);
|
||||
if ( error == noErr )
|
||||
{
|
||||
/* Since space on Mac OS disks is always allocated in allocation blocks, */
|
||||
/* this code takes into account rounding up to the end of an allocation block. */
|
||||
|
||||
/* get number of 512-byte blocks needed for data fork */
|
||||
if ( ((unsigned long)pb.hPB.fileParam.ioFlLgLen & 0x000001ff) != 0 )
|
||||
{
|
||||
srcDataBlks = ((unsigned long)pb.hPB.fileParam.ioFlLgLen >> 9) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
srcDataBlks = (unsigned long)pb.hPB.fileParam.ioFlLgLen >> 9;
|
||||
}
|
||||
|
||||
/* now, calculate number of new allocation blocks needed */
|
||||
if ( srcDataBlks % dstBlksPerAllocBlk )
|
||||
{
|
||||
srcDataBlks = (srcDataBlks / dstBlksPerAllocBlk) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
srcDataBlks /= dstBlksPerAllocBlk;
|
||||
}
|
||||
|
||||
/* get number of 512-byte blocks needed for resource fork */
|
||||
if ( ((unsigned long)pb.hPB.fileParam.ioFlRLgLen & 0x000001ff) != 0 )
|
||||
{
|
||||
srcResourceBlks = ((unsigned long)pb.hPB.fileParam.ioFlRLgLen >> 9) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
srcResourceBlks = (unsigned long)pb.hPB.fileParam.ioFlRLgLen >> 9;
|
||||
}
|
||||
|
||||
/* now, calculate number of new allocation blocks needed */
|
||||
if ( srcResourceBlks % dstBlksPerAllocBlk )
|
||||
{
|
||||
srcResourceBlks = (srcResourceBlks / dstBlksPerAllocBlk) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
srcResourceBlks /= dstBlksPerAllocBlk;
|
||||
}
|
||||
|
||||
/* Is there enough room on the destination volume for the source file? */
|
||||
*spaceOK = ( ((srcDataBlks + srcResourceBlks) * dstBlksPerAllocBlk) <= dstFreeBlocks );
|
||||
}
|
||||
}
|
||||
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FileCopy(short srcVRefNum,
|
||||
long srcDirID,
|
||||
ConstStr255Param srcName,
|
||||
short dstVRefNum,
|
||||
long dstDirID,
|
||||
ConstStr255Param dstPathname,
|
||||
ConstStr255Param copyName,
|
||||
void *copyBufferPtr,
|
||||
long copyBufferSize,
|
||||
Boolean preflight)
|
||||
{
|
||||
OSErr err;
|
||||
|
||||
short srcRefNum = 0, /* 0 when source data and resource fork are closed */
|
||||
dstDataRefNum = 0, /* 0 when destination data fork is closed */
|
||||
dstRsrcRefNum = 0; /* 0 when destination resource fork is closed */
|
||||
|
||||
Str63 dstName; /* The filename of the destination. It might be the
|
||||
** source filename, it might be a new name... */
|
||||
|
||||
GetVolParmsInfoBuffer infoBuffer; /* Where PBGetVolParms dumps its info */
|
||||
long srcServerAdr; /* AppleTalk server address of source (if any) */
|
||||
|
||||
Boolean dstCreated = false, /* true when destination file has been created */
|
||||
ourCopyBuffer = false, /* true if we had to allocate the copy buffer */
|
||||
isDirectory, /* true if destination is really a directory */
|
||||
isDropBox; /* true if destination is an AppleShare drop box */
|
||||
|
||||
long tempLong;
|
||||
short tempInt;
|
||||
|
||||
Boolean spaceOK; /* true if there's enough room to copy the file to the destination volume */
|
||||
|
||||
Boolean hasDataFork;
|
||||
Boolean hasResourceFork;
|
||||
|
||||
/* Preflight for size */
|
||||
if ( preflight )
|
||||
{
|
||||
err = PreflightFileCopySpace(srcVRefNum, srcDirID, srcName,
|
||||
dstPathname, dstVRefNum, &spaceOK);
|
||||
if ( err != noErr )
|
||||
{
|
||||
return ( err );
|
||||
}
|
||||
|
||||
if ( !spaceOK )
|
||||
{
|
||||
return ( dskFulErr );
|
||||
}
|
||||
}
|
||||
|
||||
/* get the destination's real dirID and make sure it really is a directory */
|
||||
err = GetDestinationDirInfo(dstVRefNum, dstDirID, dstPathname,
|
||||
&dstDirID, &isDirectory, &isDropBox);
|
||||
if ( err != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
|
||||
if ( !isDirectory )
|
||||
{
|
||||
return ( dirNFErr );
|
||||
}
|
||||
|
||||
/* get the destination's real vRefNum */
|
||||
err = DetermineVRefNum(dstPathname, dstVRefNum, &dstVRefNum);
|
||||
if ( err != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
|
||||
/* See if PBHCopyFile can be used. Using PBHCopyFile saves time by letting the file server
|
||||
** copy the file if the source and destination locations are on the same file server. */
|
||||
tempLong = sizeof(infoBuffer);
|
||||
err = HGetVolParms(srcName, srcVRefNum, &infoBuffer, &tempLong);
|
||||
if ( (err != noErr) && (err != paramErr) )
|
||||
{
|
||||
return ( err );
|
||||
}
|
||||
|
||||
if ( (err != paramErr) && hasCopyFile(infoBuffer) )
|
||||
{
|
||||
/* The source volume supports PBHCopyFile. */
|
||||
srcServerAdr = infoBuffer.vMServerAdr;
|
||||
|
||||
/* Now, see if the destination volume is on the same file server. */
|
||||
tempLong = sizeof(infoBuffer);
|
||||
err = HGetVolParms(NULL, dstVRefNum, &infoBuffer, &tempLong);
|
||||
if ( (err != noErr) && (err != paramErr) )
|
||||
{
|
||||
return ( err );
|
||||
}
|
||||
if ( (err != paramErr) && (srcServerAdr == infoBuffer.vMServerAdr) )
|
||||
{
|
||||
/* Source and Dest are on same server and PBHCopyFile is supported. Copy with CopyFile. */
|
||||
err = HCopyFile(srcVRefNum, srcDirID, srcName, dstVRefNum, dstDirID, NULL, copyName);
|
||||
if ( err != noErr )
|
||||
{
|
||||
return ( err );
|
||||
}
|
||||
|
||||
/* AppleShare's CopyFile clears the isAlias bit, so I still need to attempt to copy
|
||||
the File's attributes to attempt to get things right. */
|
||||
if ( copyName != NULL ) /* Did caller supply copy file name? */
|
||||
{
|
||||
/* Yes, use the caller supplied copy file name. */
|
||||
(void) CopyFileMgrAttributes(srcVRefNum, srcDirID, srcName,
|
||||
dstVRefNum, dstDirID, copyName, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* They didn't, so get the source file name and use it. */
|
||||
if ( GetFilenameFromPathname(srcName, dstName) == noErr )
|
||||
{
|
||||
/* */
|
||||
(void) CopyFileMgrAttributes(srcVRefNum, srcDirID, srcName,
|
||||
dstVRefNum, dstDirID, dstName, true);
|
||||
}
|
||||
}
|
||||
return ( err );
|
||||
}
|
||||
}
|
||||
|
||||
/* If we're here, then PBHCopyFile couldn't be used so we have to copy the file by hand. */
|
||||
|
||||
/* Make sure a copy buffer is allocated. */
|
||||
if ( copyBufferPtr == NULL )
|
||||
{
|
||||
/* The caller didn't supply a copy buffer so grab one from the application heap.
|
||||
** Try to get a big copy buffer, if we can't, try for a 512-byte buffer.
|
||||
** If 512 bytes aren't available, we're in trouble. */
|
||||
copyBufferSize = bigCopyBuffSize;
|
||||
copyBufferPtr = NewPtr(copyBufferSize);
|
||||
if ( copyBufferPtr == NULL )
|
||||
{
|
||||
copyBufferSize = minCopyBuffSize;
|
||||
copyBufferPtr = NewPtr(copyBufferSize);
|
||||
if ( copyBufferPtr == NULL )
|
||||
{
|
||||
return ( memFullErr );
|
||||
}
|
||||
}
|
||||
ourCopyBuffer = true;
|
||||
}
|
||||
|
||||
/* Open the source data fork. */
|
||||
err = HOpenAware(srcVRefNum, srcDirID, srcName, srcCopyMode, &srcRefNum);
|
||||
if ( err != noErr )
|
||||
return ( err );
|
||||
|
||||
/* Once a file is opened, we have to exit via ErrorExit to make sure things are cleaned up */
|
||||
|
||||
/* See if the copy will be renamed. */
|
||||
if ( copyName != NULL ) /* Did caller supply copy file name? */
|
||||
BlockMoveData(copyName, dstName, copyName[0] + 1); /* Yes, use the caller supplied copy file name. */
|
||||
else
|
||||
{ /* They didn't, so get the source file name and use it. */
|
||||
err = GetFileLocation(srcRefNum, &tempInt, &tempLong, dstName);
|
||||
if ( err != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create the destination file. */
|
||||
err = HCreateMinimum(dstVRefNum, dstDirID, dstName);
|
||||
if ( err != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
dstCreated = true; /* After creating the destination file, any
|
||||
** error conditions should delete the destination file */
|
||||
|
||||
/* An AppleShare dropbox folder is a folder for which the user has the Make Changes
|
||||
** privilege (write access), but not See Files (read access) and See Folders (search access).
|
||||
** Copying a file into an AppleShare dropbox presents some special problems. Here are the
|
||||
** rules we have to follow to copy a file into a dropbox:
|
||||
** ¥ File attributes can be changed only when both forks of a file are empty.
|
||||
** ¥ DeskTop Manager comments can be added to a file only when both forks of a file
|
||||
** are empty.
|
||||
** ¥ A fork can be opened for write access only when both forks of a file are empty.
|
||||
** So, with those rules to live with, we'll do those operations now while both forks
|
||||
** are empty. */
|
||||
|
||||
if ( isDropBox )
|
||||
{
|
||||
/* We only set the file attributes now if the file is being copied into a
|
||||
** drop box. In all other cases, it is better to set the attributes last
|
||||
** so that if FileCopy is modified to give up time to other processes
|
||||
** periodicly, the Finder won't try to read any bundle information (because
|
||||
** the bundle-bit will still be clear) from a partially copied file. If the
|
||||
** copy is into a drop box, we have to set the attributes now, but since the
|
||||
** destination forks are opened with write/deny-read/deny-write permissions,
|
||||
** any Finder that might see the file in the drop box won't be able to open
|
||||
** its resource fork until the resource fork is closed.
|
||||
**
|
||||
** Note: if you do modify FileCopy to give up time to other processes, don't
|
||||
** give up time between the time the destination file is created (above) and
|
||||
** the time both forks are opened (below). That way, you stand the best chance
|
||||
** of making sure the Finder doesn't read a partially copied resource fork.
|
||||
*/
|
||||
/* Copy attributes but don't lock the destination. */
|
||||
err = CopyFileMgrAttributes(srcVRefNum, srcDirID, srcName,
|
||||
dstVRefNum, dstDirID, dstName, false);
|
||||
if ( err != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
}
|
||||
|
||||
/* Attempt to copy the comments while both forks are empty.
|
||||
** Ignore the result because we really don't care if it worked or not. */
|
||||
(void) DTCopyComment(srcVRefNum, srcDirID, srcName, dstVRefNum, dstDirID, dstName);
|
||||
|
||||
/* See which forks we need to copy. By doing this, we won't create a data or resource fork
|
||||
** for the destination unless it's really needed (some foreign file systems such as
|
||||
** the ProDOS File System and Macintosh PC Exchange have to create additional disk
|
||||
** structures to support resource forks). */
|
||||
err = CheckForForks(srcVRefNum, srcDirID, srcName, &hasDataFork, &hasResourceFork);
|
||||
if ( err != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
|
||||
if ( hasDataFork )
|
||||
{
|
||||
/* Open the destination data fork. */
|
||||
err = HOpenAware(dstVRefNum, dstDirID, dstName, dstCopyMode, &dstDataRefNum);
|
||||
if ( err != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
}
|
||||
|
||||
if ( hasResourceFork )
|
||||
{
|
||||
/* Open the destination resource fork. */
|
||||
err = HOpenRFAware(dstVRefNum, dstDirID, dstName, dstCopyMode, &dstRsrcRefNum);
|
||||
if ( err != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
}
|
||||
|
||||
if ( hasDataFork )
|
||||
{
|
||||
/* Copy the data fork. */
|
||||
err = CopyFork(srcRefNum, dstDataRefNum, copyBufferPtr, copyBufferSize);
|
||||
if ( err != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
|
||||
/* Close both data forks and clear reference numbers. */
|
||||
(void) FSClose(srcRefNum);
|
||||
(void) FSClose(dstDataRefNum);
|
||||
srcRefNum = dstDataRefNum = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Close the source data fork since it was opened earlier */
|
||||
(void) FSClose(srcRefNum);
|
||||
srcRefNum = 0;
|
||||
}
|
||||
|
||||
if ( hasResourceFork )
|
||||
{
|
||||
/* Open the source resource fork. */
|
||||
err = HOpenRFAware(srcVRefNum, srcDirID, srcName, srcCopyMode, &srcRefNum);
|
||||
if ( err != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
|
||||
/* Copy the resource fork. */
|
||||
err = CopyFork(srcRefNum, dstRsrcRefNum, copyBufferPtr, copyBufferSize);
|
||||
if ( err != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
|
||||
/* Close both resource forks and clear reference numbers. */
|
||||
(void) FSClose(srcRefNum);
|
||||
(void) FSClose(dstRsrcRefNum);
|
||||
srcRefNum = dstRsrcRefNum = 0;
|
||||
}
|
||||
|
||||
/* Get rid of the copy buffer if we allocated it. */
|
||||
if ( ourCopyBuffer )
|
||||
{
|
||||
DisposePtr((Ptr)copyBufferPtr);
|
||||
}
|
||||
|
||||
/* Attempt to copy attributes again to set mod date. Copy lock condition this time
|
||||
** since we're done with the copy operation. This operation will fail if we're copying
|
||||
** into an AppleShare dropbox, so we don't check for error conditions. */
|
||||
CopyFileMgrAttributes(srcVRefNum, srcDirID, srcName,
|
||||
dstVRefNum, dstDirID, dstName, true);
|
||||
|
||||
/* Hey, we did it! */
|
||||
return ( noErr );
|
||||
|
||||
ErrorExit:
|
||||
if ( srcRefNum != 0 )
|
||||
{
|
||||
(void) FSClose(srcRefNum); /* Close the source file */
|
||||
}
|
||||
if ( dstDataRefNum != 0 )
|
||||
{
|
||||
(void) FSClose(dstDataRefNum); /* Close the destination file data fork */
|
||||
}
|
||||
if ( dstRsrcRefNum != 0 )
|
||||
{
|
||||
(void) FSClose(dstRsrcRefNum); /* Close the destination file resource fork */
|
||||
}
|
||||
if ( dstCreated )
|
||||
{
|
||||
(void) HDelete(dstVRefNum, dstDirID, dstName); /* Delete dest file. This may fail if the file
|
||||
is in a "drop folder" */
|
||||
}
|
||||
if ( ourCopyBuffer ) /* dispose of any memory we allocated */
|
||||
{
|
||||
DisposePtr((Ptr)copyBufferPtr);
|
||||
}
|
||||
|
||||
return ( err );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpFileCopy(const FSSpec *srcSpec,
|
||||
const FSSpec *dstSpec,
|
||||
ConstStr255Param copyName,
|
||||
void *copyBufferPtr,
|
||||
long copyBufferSize,
|
||||
Boolean preflight)
|
||||
{
|
||||
return ( FileCopy(srcSpec->vRefNum, srcSpec->parID, srcSpec->name,
|
||||
dstSpec->vRefNum, dstSpec->parID, dstSpec->name,
|
||||
copyName, copyBufferPtr, copyBufferSize, preflight) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
220
src/mac/morefile/FileCopy.h
Normal file
220
src/mac/morefile/FileCopy.h
Normal file
@ -0,0 +1,220 @@
|
||||
/*
|
||||
** Apple Macintosh Developer Technical Support
|
||||
**
|
||||
** FileCopy: A robust, general purpose file copy routine.
|
||||
**
|
||||
** by Jim Luther, Apple Developer Technical Support Emeritus
|
||||
**
|
||||
** File: FileCopy.h
|
||||
**
|
||||
** Copyright © 1992-1998 Apple Computer, Inc.
|
||||
** All rights reserved.
|
||||
**
|
||||
** You may incorporate this sample code into your applications without
|
||||
** restriction, though the sample code has been provided "AS IS" and the
|
||||
** responsibility for its operation is 100% yours. However, what you are
|
||||
** not permitted to do is to redistribute the source as "DSC Sample Code"
|
||||
** after having made changes. If you're going to re-distribute the source,
|
||||
** we require that you make it clear in the source that the code was
|
||||
** descended from Apple Sample Code, but that you've made changes.
|
||||
*/
|
||||
|
||||
#ifndef __FILECOPY__
|
||||
#define __FILECOPY__
|
||||
|
||||
#include <Types.h>
|
||||
#include <Files.h>
|
||||
|
||||
#include "Optim.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FileCopy(short srcVRefNum,
|
||||
long srcDirID,
|
||||
ConstStr255Param srcName,
|
||||
short dstVRefNum,
|
||||
long dstDirID,
|
||||
ConstStr255Param dstPathname,
|
||||
ConstStr255Param copyName,
|
||||
void *copyBufferPtr,
|
||||
long copyBufferSize,
|
||||
Boolean preflight);
|
||||
/* ¦ Duplicate a file and optionally rename it.
|
||||
The FileCopy function duplicates a file and optionally renames it.
|
||||
Since the PBHCopyFile routine is only available on some
|
||||
AFP server volumes under specific conditions, this routine
|
||||
either uses PBHCopyFile, or does all of the work PBHCopyFile
|
||||
does. The srcVRefNum, srcDirID and srcName are used to
|
||||
determine the location of the file to copy. The dstVRefNum
|
||||
dstDirID and dstPathname are used to determine the location of
|
||||
the destination directory. If copyName <> NIL, then it points
|
||||
to the name of the new file. If copyBufferPtr <> NIL, it
|
||||
points to a buffer of copyBufferSize that is used to copy
|
||||
the file's data. The larger the supplied buffer, the
|
||||
faster the copy. If copyBufferPtr = NIL, then this routine
|
||||
allocates a buffer in the application heap. If you pass a
|
||||
copy buffer to this routine, make its size a multiple of 512
|
||||
($200) bytes for optimum performance.
|
||||
|
||||
srcVRefNum input: Source volume specification.
|
||||
srcDirID input: Source directory ID.
|
||||
srcName input: Source file name.
|
||||
dstVRefNum input: Destination volume specification.
|
||||
dstDirID input: Destination directory ID.
|
||||
dstPathname input: Pointer to destination directory name, or
|
||||
nil when dstDirID specifies a directory.
|
||||
copyName input: Points to the new file name if the file is
|
||||
to be renamed or nil if the file isn't to
|
||||
be renamed.
|
||||
copyBufferPtr input: Points to a buffer of copyBufferSize that
|
||||
is used the i/o buffer for the copy or
|
||||
nil if you want FileCopy to allocate its
|
||||
own buffer in the application heap.
|
||||
copyBufferSize input: The size of the buffer pointed to
|
||||
by copyBufferPtr.
|
||||
preflight input: If true, FileCopy makes sure there are enough
|
||||
allocation blocks on the destination volume to
|
||||
hold both the data and resource forks before
|
||||
starting the copy.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
readErr Ð19 Driver does not respond to read requests
|
||||
writErr Ð20 Driver does not respond to write requests
|
||||
badUnitErr Ð21 Driver reference number does not
|
||||
match unit table
|
||||
unitEmptyErr Ð22 Driver reference number specifies a
|
||||
nil handle in unit table
|
||||
abortErr Ð27 Request aborted by KillIO
|
||||
notOpenErr Ð28 Driver not open
|
||||
dskFulErr -34 Destination volume is full
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
tmfoErr -42 Too many files open
|
||||
fnfErr -43 Source file not found, or destination
|
||||
directory does not exist
|
||||
wPrErr -44 Volume locked by hardware
|
||||
fLckdErr -45 File is locked
|
||||
vLckdErr -46 Destination volume is read-only
|
||||
fBsyErr -47 The source or destination file could
|
||||
not be opened with the correct access
|
||||
modes
|
||||
dupFNErr -48 Destination file already exists
|
||||
opWrErr -49 File already open for writing
|
||||
paramErr -50 No default volume or function not
|
||||
supported by volume
|
||||
permErr -54 File is already open and cannot be opened using specified deny modes
|
||||
memFullErr -108 Copy buffer could not be allocated
|
||||
dirNFErr -120 Directory not found or incomplete pathname
|
||||
wrgVolTypErr -123 Function not supported by volume
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
afpDenyConflict -5006 The source or destination file could
|
||||
not be opened with the correct access
|
||||
modes
|
||||
afpObjectTypeErr -5025 Source is a directory, directory not found
|
||||
or incomplete pathname
|
||||
|
||||
__________
|
||||
|
||||
Also see: FSpFileCopy, DirectoryCopy, FSpDirectoryCopy
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpFileCopy(const FSSpec *srcSpec,
|
||||
const FSSpec *dstSpec,
|
||||
ConstStr255Param copyName,
|
||||
void *copyBufferPtr,
|
||||
long copyBufferSize,
|
||||
Boolean preflight);
|
||||
/* ¦ Duplicate a file and optionally rename it.
|
||||
The FSpFileCopy function duplicates a file and optionally renames it.
|
||||
Since the PBHCopyFile routine is only available on some
|
||||
AFP server volumes under specific conditions, this routine
|
||||
either uses PBHCopyFile, or does all of the work PBHCopyFile
|
||||
does. The srcSpec is used to
|
||||
determine the location of the file to copy. The dstSpec is
|
||||
used to determine the location of the
|
||||
destination directory. If copyName <> NIL, then it points
|
||||
to the name of the new file. If copyBufferPtr <> NIL, it
|
||||
points to a buffer of copyBufferSize that is used to copy
|
||||
the file's data. The larger the supplied buffer, the
|
||||
faster the copy. If copyBufferPtr = NIL, then this routine
|
||||
allocates a buffer in the application heap. If you pass a
|
||||
copy buffer to this routine, make its size a multiple of 512
|
||||
($200) bytes for optimum performance.
|
||||
|
||||
srcSpec input: An FSSpec record specifying the source file.
|
||||
dstSpec input: An FSSpec record specifying the destination
|
||||
directory.
|
||||
copyName input: Points to the new file name if the file is
|
||||
to be renamed or nil if the file isn't to
|
||||
be renamed.
|
||||
copyBufferPtr input: Points to a buffer of copyBufferSize that
|
||||
is used the i/o buffer for the copy or
|
||||
nil if you want FileCopy to allocate its
|
||||
own buffer in the application heap.
|
||||
copyBufferSize input: The size of the buffer pointed to
|
||||
by copyBufferPtr.
|
||||
preflight input: If true, FSpFileCopy makes sure there are
|
||||
enough allocation blocks on the destination
|
||||
volume to hold both the data and resource forks
|
||||
before starting the copy.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
readErr Ð19 Driver does not respond to read requests
|
||||
writErr Ð20 Driver does not respond to write requests
|
||||
badUnitErr Ð21 Driver reference number does not
|
||||
match unit table
|
||||
unitEmptyErr Ð22 Driver reference number specifies a
|
||||
nil handle in unit table
|
||||
abortErr Ð27 Request aborted by KillIO
|
||||
notOpenErr Ð28 Driver not open
|
||||
dskFulErr -34 Destination volume is full
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
tmfoErr -42 Too many files open
|
||||
fnfErr -43 Source file not found, or destination
|
||||
directory does not exist
|
||||
wPrErr -44 Volume locked by hardware
|
||||
fLckdErr -45 File is locked
|
||||
vLckdErr -46 Destination volume is read-only
|
||||
fBsyErr -47 The source or destination file could
|
||||
not be opened with the correct access
|
||||
modes
|
||||
dupFNErr -48 Destination file already exists
|
||||
opWrErr -49 File already open for writing
|
||||
paramErr -50 No default volume or function not
|
||||
supported by volume
|
||||
permErr -54 File is already open and cannot be opened using specified deny modes
|
||||
memFullErr -108 Copy buffer could not be allocated
|
||||
dirNFErr -120 Directory not found or incomplete pathname
|
||||
wrgVolTypErr -123 Function not supported by volume
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
afpDenyConflict -5006 The source or destination file could
|
||||
not be opened with the correct access
|
||||
modes
|
||||
afpObjectTypeErr -5025 Source is a directory, directory not found
|
||||
or incomplete pathname
|
||||
|
||||
__________
|
||||
|
||||
Also see: FileCopy, DirectoryCopy, FSpDirectoryCopy
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "OptimEnd.h"
|
||||
|
||||
#endif /* __FILECOPY__ */
|
246
src/mac/morefile/FullPath.cpp
Normal file
246
src/mac/morefile/FullPath.cpp
Normal file
@ -0,0 +1,246 @@
|
||||
/*
|
||||
** Apple Macintosh Developer Technical Support
|
||||
**
|
||||
** Routines for dealing with full pathnames... if you really must.
|
||||
**
|
||||
** by Jim Luther, Apple Developer Technical Support Emeritus
|
||||
**
|
||||
** File: FullPath.c
|
||||
**
|
||||
** Copyright © 1995-1998 Apple Computer, Inc.
|
||||
** All rights reserved.
|
||||
**
|
||||
** You may incorporate this sample code into your applications without
|
||||
** restriction, though the sample code has been provided "AS IS" and the
|
||||
** responsibility for its operation is 100% yours. However, what you are
|
||||
** not permitted to do is to redistribute the source as "DSC Sample Code"
|
||||
** after having made changes. If you're going to re-distribute the source,
|
||||
** we require that you make it clear in the source that the code was
|
||||
** descended from Apple Sample Code, but that you've made changes.
|
||||
*/
|
||||
|
||||
#include <Types.h>
|
||||
#include <Errors.h>
|
||||
#include <Memory.h>
|
||||
#include <Files.h>
|
||||
#include <TextUtils.h>
|
||||
#include <Aliases.h>
|
||||
|
||||
#define __COMPILINGMOREFILES
|
||||
|
||||
#include "FSpCompa.h"
|
||||
#include "FullPath.h"
|
||||
|
||||
/*
|
||||
IMPORTANT NOTE:
|
||||
|
||||
The use of full pathnames is strongly discouraged. Full pathnames are
|
||||
particularly unreliable as a means of identifying files, directories
|
||||
or volumes within your application, for two primary reasons:
|
||||
|
||||
¥ The user can change the name of any element in the path at virtually
|
||||
any time.
|
||||
¥ Volume names on the Macintosh are *not* unique. Multiple
|
||||
mounted volumes can have the same name. For this reason, the use of
|
||||
a full pathname to identify a specific volume may not produce the
|
||||
results you expect. If more than one volume has the same name and
|
||||
a full pathname is used, the File Manager currently uses the first
|
||||
mounted volume it finds with a matching name in the volume queue.
|
||||
|
||||
In general, you should use a fileÕs name, parent directory ID, and
|
||||
volume reference number to identify a file you want to open, delete,
|
||||
or otherwise manipulate.
|
||||
|
||||
If you need to remember the location of a particular file across
|
||||
subsequent system boots, use the Alias Manager to create an alias record
|
||||
describing the file. If the Alias Manager is not available, you can save
|
||||
the fileÕs name, its parent directory ID, and the name of the volume on
|
||||
which itÕs located. Although none of these methods is foolproof, they are
|
||||
much more reliable than using full pathnames to identify files.
|
||||
|
||||
Nonetheless, it is sometimes useful to display a fileÕs full pathname to
|
||||
the user. For example, a backup utility might display a list of full
|
||||
pathnames of files as it copies them onto the backup medium. Or, a
|
||||
utility might want to display a dialog box showing the full pathname of
|
||||
a file when it needs the userÕs confirmation to delete the file. No
|
||||
matter how unreliable full pathnames may be from a file-specification
|
||||
viewpoint, users understand them more readily than volume reference
|
||||
numbers or directory IDs. (Hint: Use the TruncString function from
|
||||
TextUtils.h with truncMiddle as the truncWhere argument to shorten
|
||||
full pathnames to a displayable length.)
|
||||
|
||||
The following technique for constructing the full pathname of a file is
|
||||
intended for display purposes only. Applications that depend on any
|
||||
particular structure of a full pathname are likely to fail on alternate
|
||||
foreign file systems or under future system software versions.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr GetFullPath(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name,
|
||||
short *fullPathLength,
|
||||
Handle *fullPath)
|
||||
{
|
||||
OSErr result;
|
||||
FSSpec spec;
|
||||
|
||||
*fullPathLength = 0;
|
||||
*fullPath = NULL;
|
||||
|
||||
result = FSMakeFSSpecCompat(vRefNum, dirID, name, &spec);
|
||||
if ( (result == noErr) || (result == fnfErr) )
|
||||
{
|
||||
result = FSpGetFullPath(&spec, fullPathLength, fullPath);
|
||||
}
|
||||
|
||||
return ( result );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpGetFullPath(const FSSpec *spec,
|
||||
short *fullPathLength,
|
||||
Handle *fullPath)
|
||||
{
|
||||
OSErr result;
|
||||
OSErr realResult;
|
||||
FSSpec tempSpec;
|
||||
CInfoPBRec pb;
|
||||
|
||||
*fullPathLength = 0;
|
||||
*fullPath = NULL;
|
||||
|
||||
// Default to noErr
|
||||
realResult = noErr;
|
||||
|
||||
/* Make a copy of the input FSSpec that can be modified */
|
||||
BlockMoveData(spec, &tempSpec, sizeof(FSSpec));
|
||||
|
||||
if ( tempSpec.parID == fsRtParID )
|
||||
{
|
||||
/* The object is a volume */
|
||||
|
||||
/* Add a colon to make it a full pathname */
|
||||
++tempSpec.name[0];
|
||||
tempSpec.name[tempSpec.name[0]] = ':';
|
||||
|
||||
/* We're done */
|
||||
result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The object isn't a volume */
|
||||
|
||||
/* Is the object a file or a directory? */
|
||||
pb.dirInfo.ioNamePtr = tempSpec.name;
|
||||
pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
|
||||
pb.dirInfo.ioDrDirID = tempSpec.parID;
|
||||
pb.dirInfo.ioFDirIndex = 0;
|
||||
result = PBGetCatInfoSync(&pb);
|
||||
// Allow file/directory name at end of path to not exist.
|
||||
realResult = result;
|
||||
if ( (result == noErr) || (result == fnfErr) )
|
||||
{
|
||||
/* if the object is a directory, append a colon so full pathname ends with colon */
|
||||
if ( (result == noErr) && (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0 )
|
||||
{
|
||||
++tempSpec.name[0];
|
||||
tempSpec.name[tempSpec.name[0]] = ':';
|
||||
}
|
||||
|
||||
/* Put the object name in first */
|
||||
result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
|
||||
if ( result == noErr )
|
||||
{
|
||||
/* Get the ancestor directory names */
|
||||
pb.dirInfo.ioNamePtr = tempSpec.name;
|
||||
pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
|
||||
pb.dirInfo.ioDrParID = tempSpec.parID;
|
||||
do /* loop until we have an error or find the root directory */
|
||||
{
|
||||
pb.dirInfo.ioFDirIndex = -1;
|
||||
pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
|
||||
result = PBGetCatInfoSync(&pb);
|
||||
if ( result == noErr )
|
||||
{
|
||||
/* Append colon to directory name */
|
||||
++tempSpec.name[0];
|
||||
tempSpec.name[tempSpec.name[0]] = ':';
|
||||
|
||||
/* Add directory name to beginning of fullPath */
|
||||
(void) Munger(*fullPath, 0, NULL, 0, &tempSpec.name[1], tempSpec.name[0]);
|
||||
result = MemError();
|
||||
}
|
||||
} while ( (result == noErr) && (pb.dirInfo.ioDrDirID != fsRtDirID) );
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( result == noErr )
|
||||
{
|
||||
/* Return the length */
|
||||
*fullPathLength = InlineGetHandleSize(*fullPath);
|
||||
result = realResult; // return realResult in case it was fnfErr
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Dispose of the handle and return NULL and zero length */
|
||||
if ( *fullPath != NULL )
|
||||
{
|
||||
DisposeHandle(*fullPath);
|
||||
}
|
||||
*fullPath = NULL;
|
||||
*fullPathLength = 0;
|
||||
}
|
||||
|
||||
return ( result );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpLocationFromFullPath(short fullPathLength,
|
||||
const void *fullPath,
|
||||
FSSpec *spec)
|
||||
{
|
||||
AliasHandle alias;
|
||||
OSErr result;
|
||||
Boolean wasChanged;
|
||||
Str32 nullString;
|
||||
|
||||
/* Create a minimal alias from the full pathname */
|
||||
nullString[0] = 0; /* null string to indicate no zone or server name */
|
||||
result = NewAliasMinimalFromFullPath(fullPathLength, fullPath, nullString, nullString, &alias);
|
||||
if ( result == noErr )
|
||||
{
|
||||
/* Let the Alias Manager resolve the alias. */
|
||||
result = ResolveAlias(NULL, alias, spec, &wasChanged);
|
||||
|
||||
DisposeHandle((Handle)alias); /* Free up memory used */
|
||||
}
|
||||
return ( result );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr LocationFromFullPath(short fullPathLength,
|
||||
const void *fullPath,
|
||||
short *vRefNum,
|
||||
long *parID,
|
||||
Str31 name)
|
||||
{
|
||||
OSErr result;
|
||||
FSSpec spec;
|
||||
|
||||
result = FSpLocationFromFullPath(fullPathLength, fullPath, &spec);
|
||||
if ( result == noErr )
|
||||
{
|
||||
*vRefNum = spec.vRefNum;
|
||||
*parID = spec.parID;
|
||||
BlockMoveData(&spec.name[0], &name[0], spec.name[0] + 1);
|
||||
}
|
||||
return ( result );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
243
src/mac/morefile/FullPath.h
Normal file
243
src/mac/morefile/FullPath.h
Normal file
@ -0,0 +1,243 @@
|
||||
/*
|
||||
** Apple Macintosh Developer Technical Support
|
||||
**
|
||||
** Routines for dealing with full pathnames... if you really must.
|
||||
**
|
||||
** by Jim Luther, Apple Developer Technical Support Emeritus
|
||||
**
|
||||
** File: FullPath.h
|
||||
**
|
||||
** Copyright © 1995-1998 Apple Computer, Inc.
|
||||
** All rights reserved.
|
||||
**
|
||||
** You may incorporate this sample code into your applications without
|
||||
** restriction, though the sample code has been provided "AS IS" and the
|
||||
** responsibility for its operation is 100% yours. However, what you are
|
||||
** not permitted to do is to redistribute the source as "DSC Sample Code"
|
||||
** after having made changes. If you're going to re-distribute the source,
|
||||
** we require that you make it clear in the source that the code was
|
||||
** descended from Apple Sample Code, but that you've made changes.
|
||||
*/
|
||||
|
||||
#ifndef __FULLPATH__
|
||||
#define __FULLPATH__
|
||||
|
||||
#include <Types.h>
|
||||
#include <Files.h>
|
||||
|
||||
#include "Optim.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
IMPORTANT NOTE:
|
||||
|
||||
The use of full pathnames is strongly discouraged. Full pathnames are
|
||||
particularly unreliable as a means of identifying files, directories
|
||||
or volumes within your application, for two primary reasons:
|
||||
|
||||
¥ The user can change the name of any element in the path at
|
||||
virtually any time.
|
||||
¥ Volume names on the Macintosh are *not* unique. Multiple
|
||||
mounted volumes can have the same name. For this reason, the use of
|
||||
a full pathname to identify a specific volume may not produce the
|
||||
results you expect. If more than one volume has the same name and
|
||||
a full pathname is used, the File Manager currently uses the first
|
||||
mounted volume it finds with a matching name in the volume queue.
|
||||
|
||||
In general, you should use a fileÕs name, parent directory ID, and
|
||||
volume reference number to identify a file you want to open, delete,
|
||||
or otherwise manipulate.
|
||||
|
||||
If you need to remember the location of a particular file across
|
||||
subsequent system boots, use the Alias Manager to create an alias
|
||||
record describing the file. If the Alias Manager is not available, you
|
||||
can save the fileÕs name, its parent directory ID, and the name of the
|
||||
volume on which itÕs located. Although none of these methods is
|
||||
foolproof, they are much more reliable than using full pathnames to
|
||||
identify files.
|
||||
|
||||
Nonetheless, it is sometimes useful to display a fileÕs full pathname
|
||||
to the user. For example, a backup utility might display a list of full
|
||||
pathnames of files as it copies them onto the backup medium. Or, a
|
||||
utility might want to display a dialog box showing the full pathname of
|
||||
a file when it needs the userÕs confirmation to delete the file. No
|
||||
matter how unreliable full pathnames may be from a file-specification
|
||||
viewpoint, users understand them more readily than volume reference
|
||||
numbers or directory IDs. (Hint: Use the TruncString function from
|
||||
TextUtils.h with truncMiddle as the truncWhere argument to shorten
|
||||
full pathnames to a displayable length.)
|
||||
|
||||
The following technique for constructing the full pathname of a file is
|
||||
intended for display purposes only. Applications that depend on any
|
||||
particular structure of a full pathname are likely to fail on alternate
|
||||
foreign file systems or under future system software versions.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr GetFullPath(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name,
|
||||
short *fullPathLength,
|
||||
Handle *fullPath);
|
||||
/* ¦ Get a full pathname to a volume, directory or file.
|
||||
The GetFullPath function builds a full pathname to the specified
|
||||
object. The full pathname is returned in the newly created handle
|
||||
fullPath and the length of the full pathname is returned in
|
||||
fullPathLength. Your program is responsible for disposing of the
|
||||
fullPath handle.
|
||||
|
||||
Note that a full pathname can be made to a file/directory that does not
|
||||
yet exist if all directories up to that file/directory exist. In this case,
|
||||
GetFullPath will return a fnfErr.
|
||||
|
||||
vRefNum input: Volume specification.
|
||||
dirID input: Directory ID.
|
||||
name input: Pointer to object name, or nil when dirID
|
||||
specifies a directory that's the object.
|
||||
fullPathLength output: The number of characters in the full pathname.
|
||||
If the function fails to create a full
|
||||
pathname, it sets fullPathLength to 0.
|
||||
fullPath output: A handle to the newly created full pathname
|
||||
buffer. If the function fails to create a
|
||||
full pathname, it sets fullPath to NULL.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
fnfErr -43 File or directory does not exist (fullPath
|
||||
and fullPathLength are still valid)
|
||||
paramErr -50 No default volume
|
||||
memFullErr -108 Not enough memory
|
||||
dirNFErr -120 Directory not found or incomplete pathname
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
afpObjectTypeErr -5025 Directory not found or incomplete pathname
|
||||
|
||||
__________
|
||||
|
||||
See also: FSpGetFullPath
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpGetFullPath(const FSSpec *spec,
|
||||
short *fullPathLength,
|
||||
Handle *fullPath);
|
||||
/* ¦ Get a full pathname to a volume, directory or file.
|
||||
The GetFullPath function builds a full pathname to the specified
|
||||
object. The full pathname is returned in the newly created handle
|
||||
fullPath and the length of the full pathname is returned in
|
||||
fullPathLength. Your program is responsible for disposing of the
|
||||
fullPath handle.
|
||||
|
||||
Note that a full pathname can be made to a file/directory that does not
|
||||
yet exist if all directories up to that file/directory exist. In this case,
|
||||
FSpGetFullPath will return a fnfErr.
|
||||
|
||||
spec input: An FSSpec record specifying the object.
|
||||
fullPathLength output: The number of characters in the full pathname.
|
||||
If the function fails to create a full pathname,
|
||||
it sets fullPathLength to 0.
|
||||
fullPath output: A handle to the newly created full pathname
|
||||
buffer. If the function fails to create a
|
||||
full pathname, it sets fullPath to NULL.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
fnfErr -43 File or directory does not exist (fullPath
|
||||
and fullPathLength are still valid)
|
||||
paramErr -50 No default volume
|
||||
memFullErr -108 Not enough memory
|
||||
dirNFErr -120 Directory not found or incomplete pathname
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
afpObjectTypeErr -5025 Directory not found or incomplete pathname
|
||||
|
||||
__________
|
||||
|
||||
See also: GetFullPath
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpLocationFromFullPath(short fullPathLength,
|
||||
const void *fullPath,
|
||||
FSSpec *spec);
|
||||
/* ¦ Get a FSSpec from a full pathname.
|
||||
The FSpLocationFromFullPath function returns a FSSpec to the object
|
||||
specified by full pathname. This function requires the Alias Manager.
|
||||
|
||||
fullPathLength input: The number of characters in the full pathname
|
||||
of the target.
|
||||
fullPath input: A pointer to a buffer that contains the full
|
||||
pathname of the target. The full pathname
|
||||
starts with the name of the volume, includes
|
||||
all of the directory names in the path to the
|
||||
target, and ends with the target name.
|
||||
spec output: An FSSpec record specifying the object.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 The volume is not mounted
|
||||
fnfErr -43 Target not found, but volume and parent
|
||||
directory found
|
||||
paramErr -50 Parameter error
|
||||
usrCanceledErr -128 The user canceled the operation
|
||||
|
||||
__________
|
||||
|
||||
See also: LocationFromFullPath
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr LocationFromFullPath(short fullPathLength,
|
||||
const void *fullPath,
|
||||
short *vRefNum,
|
||||
long *parID,
|
||||
Str31 name);
|
||||
/* ¦ Get an object's location from a full pathname.
|
||||
The LocationFromFullPath function returns the volume reference number,
|
||||
parent directory ID and name of the object specified by full pathname.
|
||||
This function requires the Alias Manager.
|
||||
|
||||
fullPathLength input: The number of characters in the full pathname
|
||||
of the target.
|
||||
fullPath input: A pointer to a buffer that contains the full
|
||||
pathname of the target. The full pathname starts
|
||||
with the name of the volume, includes all of
|
||||
the directory names in the path to the target,
|
||||
and ends with the target name.
|
||||
vRefNum output: The volume reference number.
|
||||
parID output: The parent directory ID of the specified object.
|
||||
name output: The name of the specified object.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 The volume is not mounted
|
||||
fnfErr -43 Target not found, but volume and parent
|
||||
directory found
|
||||
paramErr -50 Parameter error
|
||||
usrCanceledErr -128 The user canceled the operation
|
||||
|
||||
__________
|
||||
|
||||
See also: FSpLocationFromFullPath
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "OptimEnd.h"
|
||||
|
||||
#endif /* __FULLPATH__ */
|
189
src/mac/morefile/IterateD.cpp
Normal file
189
src/mac/morefile/IterateD.cpp
Normal file
@ -0,0 +1,189 @@
|
||||
/*
|
||||
** IterateDirectory: File Manager directory iterator routines.
|
||||
**
|
||||
** by Jim Luther
|
||||
**
|
||||
** File: IterateDirectory.c
|
||||
**
|
||||
** Copyright © 1995-1998 Jim Luther and Apple Computer, Inc.
|
||||
** All rights reserved.
|
||||
**
|
||||
** You may incorporate this sample code into your applications without
|
||||
** restriction, though the sample code has been provided "AS IS" and the
|
||||
** responsibility for its operation is 100% yours.
|
||||
**
|
||||
** IterateDirectory is designed to drop into the MoreFiles sample code
|
||||
** library I wrote while in Apple Developer Technical Support
|
||||
*/
|
||||
|
||||
#include <Types.h>
|
||||
#include <Errors.h>
|
||||
#include <Files.h>
|
||||
|
||||
#define __COMPILINGMOREFILES
|
||||
|
||||
#include "MoreExtr.h"
|
||||
#include "IterateD.h"
|
||||
|
||||
/*
|
||||
** Type definitions
|
||||
*/
|
||||
|
||||
/* The IterateGlobals structure is used to minimize the amount of
|
||||
** stack space used when recursively calling IterateDirectoryLevel
|
||||
** and to hold global information that might be needed at any time.
|
||||
*/
|
||||
#if PRAGMA_ALIGN_SUPPORTED
|
||||
#pragma options align=mac68k
|
||||
#endif
|
||||
struct IterateGlobals
|
||||
{
|
||||
IterateFilterProcPtr iterateFilter; /* pointer to IterateFilterProc */
|
||||
CInfoPBRec cPB; /* the parameter block used for PBGetCatInfo calls */
|
||||
Str63 itemName; /* the name of the current item */
|
||||
OSErr result; /* temporary holder of results - saves 2 bytes of stack each level */
|
||||
Boolean quitFlag; /* set to true if filter wants to kill interation */
|
||||
unsigned short maxLevels; /* Maximum levels to iterate through */
|
||||
unsigned short currentLevel; /* The current level IterateLevel is on */
|
||||
void *yourDataPtr; /* A pointer to caller data the filter may need to access */
|
||||
};
|
||||
#if PRAGMA_ALIGN_SUPPORTED
|
||||
#pragma options align=reset
|
||||
#endif
|
||||
|
||||
typedef struct IterateGlobals IterateGlobals;
|
||||
typedef IterateGlobals *IterateGlobalsPtr;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Static Prototype */
|
||||
|
||||
static void IterateDirectoryLevel(long dirID,
|
||||
IterateGlobals *theGlobals);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/*
|
||||
** Functions
|
||||
*/
|
||||
|
||||
static void IterateDirectoryLevel(long dirID,
|
||||
IterateGlobals *theGlobals)
|
||||
{
|
||||
if ( (theGlobals->maxLevels == 0) || /* if maxLevels is zero, we aren't checking levels */
|
||||
(theGlobals->currentLevel < theGlobals->maxLevels) ) /* if currentLevel < maxLevels, look at this level */
|
||||
{
|
||||
short index = 1;
|
||||
|
||||
++theGlobals->currentLevel; /* go to next level */
|
||||
|
||||
do
|
||||
{ /* Isn't C great... What I'd give for a "WITH theGlobals DO" about now... */
|
||||
|
||||
/* Get next source item at the current directory level */
|
||||
|
||||
theGlobals->cPB.dirInfo.ioFDirIndex = index;
|
||||
theGlobals->cPB.dirInfo.ioDrDirID = dirID;
|
||||
theGlobals->result = PBGetCatInfoSync((CInfoPBPtr)&theGlobals->cPB);
|
||||
|
||||
if ( theGlobals->result == noErr )
|
||||
{
|
||||
/* Call the IterateFilterProc */
|
||||
CallIterateFilterProc(theGlobals->iterateFilter, &theGlobals->cPB, &theGlobals->quitFlag, theGlobals->yourDataPtr);
|
||||
|
||||
/* Is it a directory? */
|
||||
if ( (theGlobals->cPB.hFileInfo.ioFlAttrib & ioDirMask) != 0 )
|
||||
{
|
||||
/* We have a directory */
|
||||
if ( !theGlobals->quitFlag )
|
||||
{
|
||||
/* Dive again if the IterateFilterProc didn't say "quit" */
|
||||
IterateDirectoryLevel(theGlobals->cPB.dirInfo.ioDrDirID, theGlobals);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
++index; /* prepare to get next item */
|
||||
} while ( (theGlobals->result == noErr) && (!theGlobals->quitFlag) ); /* time to fall back a level? */
|
||||
|
||||
if ( (theGlobals->result == fnfErr) || /* fnfErr is OK - it only means we hit the end of this level */
|
||||
(theGlobals->result == afpAccessDenied) ) /* afpAccessDenied is OK, too - it only means we cannot see inside a directory */
|
||||
{
|
||||
theGlobals->result = noErr;
|
||||
}
|
||||
|
||||
--theGlobals->currentLevel; /* return to previous level as we leave */
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr IterateDirectory(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name,
|
||||
unsigned short maxLevels,
|
||||
IterateFilterProcPtr iterateFilter,
|
||||
void *yourDataPtr)
|
||||
{
|
||||
IterateGlobals theGlobals;
|
||||
OSErr result;
|
||||
long theDirID;
|
||||
short theVRefNum;
|
||||
Boolean isDirectory;
|
||||
|
||||
/* Make sure there is a IterateFilter */
|
||||
if ( iterateFilter != NULL )
|
||||
{
|
||||
/* Get the real directory ID and make sure it is a directory */
|
||||
result = GetDirectoryID(vRefNum, dirID, name, &theDirID, &isDirectory);
|
||||
if ( result == noErr )
|
||||
{
|
||||
if ( isDirectory == true )
|
||||
{
|
||||
/* Get the real vRefNum */
|
||||
result = DetermineVRefNum(name, vRefNum, &theVRefNum);
|
||||
if ( result == noErr )
|
||||
{
|
||||
/* Set up the globals we need to access from the recursive routine. */
|
||||
theGlobals.iterateFilter = iterateFilter;
|
||||
theGlobals.cPB.hFileInfo.ioNamePtr = (StringPtr)&theGlobals.itemName;
|
||||
theGlobals.cPB.hFileInfo.ioVRefNum = theVRefNum;
|
||||
theGlobals.itemName[0] = 0;
|
||||
theGlobals.result = noErr;
|
||||
theGlobals.quitFlag = false;
|
||||
theGlobals.maxLevels = maxLevels;
|
||||
theGlobals.currentLevel = 0; /* start at level 0 */
|
||||
theGlobals.yourDataPtr = yourDataPtr;
|
||||
|
||||
/* Here we go into recursion land... */
|
||||
IterateDirectoryLevel(theDirID, &theGlobals);
|
||||
|
||||
result = theGlobals.result; /* set the result */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = dirNFErr; /* a file was passed instead of a directory */
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = paramErr; /* iterateFilter was NULL */
|
||||
}
|
||||
|
||||
return ( result );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpIterateDirectory(const FSSpec *spec,
|
||||
unsigned short maxLevels,
|
||||
IterateFilterProcPtr iterateFilter,
|
||||
void *yourDataPtr)
|
||||
{
|
||||
return ( IterateDirectory(spec->vRefNum, spec->parID, spec->name,
|
||||
maxLevels, iterateFilter, yourDataPtr) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
171
src/mac/morefile/IterateD.h
Normal file
171
src/mac/morefile/IterateD.h
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
** IterateDirectory: File Manager directory iterator routines.
|
||||
**
|
||||
** by Jim Luther
|
||||
**
|
||||
** File: IterateDirectory.h
|
||||
**
|
||||
** Copyright © 1995-1998 Jim Luther and Apple Computer, Inc.
|
||||
** All rights reserved.
|
||||
**
|
||||
** You may incorporate this sample code into your applications without
|
||||
** restriction, though the sample code has been provided "AS IS" and the
|
||||
** responsibility for its operation is 100% yours.
|
||||
**
|
||||
** IterateDirectory is designed to drop into the MoreFiles sample code
|
||||
** library I wrote while in Apple Developer Technical Support
|
||||
*/
|
||||
|
||||
#ifndef __ITERATEDIRECTORY__
|
||||
#define __ITERATEDIRECTORY__
|
||||
|
||||
#include <Types.h>
|
||||
#include <Files.h>
|
||||
|
||||
#include "Optim.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef pascal void (*IterateFilterProcPtr) (const CInfoPBRec * const cpbPtr,
|
||||
Boolean *quitFlag,
|
||||
void *yourDataPtr);
|
||||
/* ¦ Prototype for the IterateFilterProc function IterateDirectory calls.
|
||||
This is the prototype for the IterateFilterProc function which is
|
||||
called once for each file and directory found by IterateDirectory. The
|
||||
IterateFilterProc gets a pointer to the CInfoPBRec that IterateDirectory
|
||||
used to call PBGetCatInfo. The IterateFilterProc can use the read-only
|
||||
data in the CInfoPBRec for whatever it wants.
|
||||
|
||||
If the IterateFilterProc wants to stop IterateDirectory, it can set
|
||||
quitFlag to true (quitFlag will be passed to the IterateFilterProc
|
||||
false).
|
||||
|
||||
The yourDataPtr parameter can point to whatever data structure you might
|
||||
want to access from within the IterateFilterProc.
|
||||
|
||||
cpbPtr input: A pointer to the CInfoPBRec that IterateDirectory
|
||||
used to call PBGetCatInfo. The CInfoPBRec and the
|
||||
data it points to must not be changed by your
|
||||
IterateFilterProc.
|
||||
quitFlag output: Your IterateFilterProc can set quitFlag to true
|
||||
if it wants to stop IterateDirectory.
|
||||
yourDataPtr input: A pointer to whatever data structure you might
|
||||
want to access from within the IterateFilterProc.
|
||||
|
||||
__________
|
||||
|
||||
Also see: IterateDirectory, FSpIterateDirectory
|
||||
*/
|
||||
|
||||
#define CallIterateFilterProc(userRoutine, cpbPtr, quitFlag, yourDataPtr) \
|
||||
(*(userRoutine))((cpbPtr), (quitFlag), (yourDataPtr))
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr IterateDirectory(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name,
|
||||
unsigned short maxLevels,
|
||||
IterateFilterProcPtr iterateFilter,
|
||||
void *yourDataPtr);
|
||||
/* ¦ Iterate (scan) through a directory's content.
|
||||
The IterateDirectory function performs a recursive iteration (scan) of
|
||||
the specified directory and calls your IterateFilterProc function once
|
||||
for each file and directory found.
|
||||
|
||||
The maxLevels parameter lets you control how deep the recursion goes.
|
||||
If maxLevels is 1, IterateDirectory only scans the specified directory;
|
||||
if maxLevels is 2, IterateDirectory scans the specified directory and
|
||||
one subdirectory below the specified directory; etc. Set maxLevels to
|
||||
zero to scan all levels.
|
||||
|
||||
The yourDataPtr parameter can point to whatever data structure you might
|
||||
want to access from within the IterateFilterProc.
|
||||
|
||||
vRefNum input: Volume specification.
|
||||
dirID input: Directory ID.
|
||||
name input: Pointer to object name, or nil when dirID
|
||||
specifies a directory that's the object.
|
||||
maxLevels input: Maximum number of directory levels to scan or
|
||||
zero to scan all directory levels.
|
||||
iterateFilter input: A pointer to the routine you want called once
|
||||
for each file and directory found by
|
||||
IterateDirectory.
|
||||
yourDataPtr input: A pointer to whatever data structure you might
|
||||
want to access from within the IterateFilterProc.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
fnfErr -43 File not found
|
||||
paramErr -50 No default volume or iterateFilter was NULL
|
||||
dirNFErr -120 Directory not found or incomplete pathname
|
||||
or a file was passed instead of a directory
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
afpObjectTypeErr -5025 Directory not found or incomplete pathname
|
||||
|
||||
__________
|
||||
|
||||
See also: IterateFilterProcPtr, FSpIterateDirectory
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpIterateDirectory(const FSSpec *spec,
|
||||
unsigned short maxLevels,
|
||||
IterateFilterProcPtr iterateFilter,
|
||||
void *yourDataPtr);
|
||||
/* ¦ Iterate (scan) through a directory's content.
|
||||
The FSpIterateDirectory function performs a recursive iteration (scan)
|
||||
of the specified directory and calls your IterateFilterProc function once
|
||||
for each file and directory found.
|
||||
|
||||
The maxLevels parameter lets you control how deep the recursion goes.
|
||||
If maxLevels is 1, FSpIterateDirectory only scans the specified directory;
|
||||
if maxLevels is 2, FSpIterateDirectory scans the specified directory and
|
||||
one subdirectory below the specified directory; etc. Set maxLevels to
|
||||
zero to scan all levels.
|
||||
|
||||
The yourDataPtr parameter can point to whatever data structure you might
|
||||
want to access from within the IterateFilterProc.
|
||||
|
||||
spec input: An FSSpec record specifying the directory to scan.
|
||||
maxLevels input: Maximum number of directory levels to scan or
|
||||
zero to scan all directory levels.
|
||||
iterateFilter input: A pointer to the routine you want called once
|
||||
for each file and directory found by
|
||||
FSpIterateDirectory.
|
||||
yourDataPtr input: A pointer to whatever data structure you might
|
||||
want to access from within the IterateFilterProc.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
fnfErr -43 File not found
|
||||
paramErr -50 No default volume or iterateFilter was NULL
|
||||
dirNFErr -120 Directory not found or incomplete pathname
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
afpObjectTypeErr -5025 Directory not found or incomplete pathname
|
||||
|
||||
__________
|
||||
|
||||
See also: IterateFilterProcPtr, IterateDirectory
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "OptimEnd.h"
|
||||
|
||||
#endif /* __ITERATEDIRECTORY__ */
|
1254
src/mac/morefile/MoreDesk.cpp
Normal file
1254
src/mac/morefile/MoreDesk.cpp
Normal file
File diff suppressed because it is too large
Load Diff
541
src/mac/morefile/MoreDesk.h
Normal file
541
src/mac/morefile/MoreDesk.h
Normal file
@ -0,0 +1,541 @@
|
||||
/*
|
||||
** Apple Macintosh Developer Technical Support
|
||||
**
|
||||
** A collection of useful high-level Desktop Manager routines.
|
||||
** If the Desktop Manager isn't available, use the Desktop file
|
||||
** for 'read' operations.
|
||||
**
|
||||
** We do more because we can...
|
||||
**
|
||||
** by Jim Luther and Nitin Ganatra, Apple Developer Technical Support Emeriti
|
||||
**
|
||||
** File: MoreDesktopMgr.h
|
||||
**
|
||||
** Copyright © 1992-1998 Apple Computer, Inc.
|
||||
** All rights reserved.
|
||||
**
|
||||
** You may incorporate this sample code into your applications without
|
||||
** restriction, though the sample code has been provided "AS IS" and the
|
||||
** responsibility for its operation is 100% yours. However, what you are
|
||||
** not permitted to do is to redistribute the source as "DSC Sample Code"
|
||||
** after having made changes. If you're going to re-distribute the source,
|
||||
** we require that you make it clear in the source that the code was
|
||||
** descended from Apple Sample Code, but that you've made changes.
|
||||
*/
|
||||
|
||||
#ifndef __MOREDESKTOPMGR__
|
||||
#define __MOREDESKTOPMGR__
|
||||
|
||||
#include <Types.h>
|
||||
#include <Files.h>
|
||||
|
||||
#include "Optim.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr DTOpen(ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
short *dtRefNum,
|
||||
Boolean *newDTDatabase);
|
||||
/* ¦ Open a volume's desktop database and return the desktop database refNum.
|
||||
The DTOpen function opens a volume's desktop database. It returns
|
||||
the reference number of the desktop database and indicates if the
|
||||
desktop database was created as a result of this call (if it was created,
|
||||
then it is empty).
|
||||
|
||||
volName input: A pointer to the name of a mounted volume
|
||||
or nil.
|
||||
vRefNum input: Volume specification.
|
||||
dtRefNum output: The reference number of Desktop Manager's
|
||||
desktop database on the specified volume.
|
||||
newDTDatabase output: true if the desktop database was created as a
|
||||
result of this call and thus empty.
|
||||
false if the desktop database was already created,
|
||||
or if it could not be determined if it was already
|
||||
created.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
paramErr -50 Volume doesn't support this function
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call.
|
||||
desktopDamagedErr -1305 The desktop database has become corrupted -
|
||||
the Finder will fix this, but if your
|
||||
application is not running with the
|
||||
Finder, use PBDTReset or PBDTDelete
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr DTXGetAPPL(ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
OSType creator,
|
||||
Boolean searchCatalog,
|
||||
short *applVRefNum,
|
||||
long *applParID,
|
||||
Str255 applName);
|
||||
/* ¦ Find an application on a volume that can open a file with a given creator.
|
||||
The DTXGetAPPL function finds an application (file type 'APPL') with
|
||||
the specified creator on the specified volume. It first tries to get
|
||||
the application mapping from the desktop database. If that fails,
|
||||
then it tries to find an application in the Desktop file. If that
|
||||
fails and searchCatalog is true, then it tries to find an application
|
||||
with the specified creator using the File Manager's CatSearch routine.
|
||||
|
||||
volName input: A pointer to the name of a mounted volume
|
||||
or nil.
|
||||
vRefNum input: Volume specification.
|
||||
creator input: The file's creator type.
|
||||
searchCatalog input: If true, search the catalog for the application
|
||||
if it isn't found in the desktop database.
|
||||
applVRefNum output: The volume reference number of the volume the
|
||||
application is on.
|
||||
applParID output: The parent directory ID of the application.
|
||||
applName output: The name of the application.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
paramErr -50 No default volume
|
||||
rfNumErr -51 Reference number invalid
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call
|
||||
desktopDamagedErr -1305 The desktop database has become corrupted -
|
||||
the Finder will fix this, but if your
|
||||
application is not running with the
|
||||
Finder, use PBDTReset or PBDTDelete
|
||||
afpItemNotFound -5012 Information not found
|
||||
|
||||
__________
|
||||
|
||||
Also see: FSpDTGetAPPL
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpDTXGetAPPL(ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
OSType creator,
|
||||
Boolean searchCatalog,
|
||||
FSSpec *spec);
|
||||
/* ¦ Find an application on a volume that can open a file with a given creator.
|
||||
The FSpDTXGetAPPL function finds an application (file type 'APPL') with
|
||||
the specified creator on the specified volume. It first tries to get
|
||||
the application mapping from the desktop database. If that fails,
|
||||
then it tries to find an application in the Desktop file. If that
|
||||
fails and searchCatalog is true, then it tries to find an application
|
||||
with the specified creator using the File Manager's CatSearch routine.
|
||||
|
||||
volName input: A pointer to the name of a mounted volume
|
||||
or nil.
|
||||
vRefNum input: Volume specification.
|
||||
creator input: The file's creator type.
|
||||
searchCatalog input: If true, search the catalog for the application
|
||||
if it isn't found in the desktop database.
|
||||
spec output: FSSpec record containing the application name and
|
||||
location.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
paramErr -50 No default volume
|
||||
rfNumErr -51 Reference number invalid
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call
|
||||
desktopDamagedErr -1305 The desktop database has become corrupted -
|
||||
the Finder will fix this, but if your
|
||||
application is not running with the
|
||||
Finder, use PBDTReset or PBDTDelete
|
||||
afpItemNotFound -5012 Information not found
|
||||
|
||||
__________
|
||||
|
||||
Also see: FSpDTGetAPPL
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr DTGetAPPL(ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
OSType creator,
|
||||
short *applVRefNum,
|
||||
long *applParID,
|
||||
Str255 applName);
|
||||
/* ¦ Find an application on a volume that can open a file with a given creator.
|
||||
The DTGetAPPL function finds an application (file type 'APPL') with
|
||||
the specified creator on the specified volume. It first tries to get
|
||||
the application mapping from the desktop database. If that fails,
|
||||
then it tries to find an application in the Desktop file. If that
|
||||
fails, then it tries to find an application with the specified creator
|
||||
using the File Manager's CatSearch routine.
|
||||
|
||||
volName input: A pointer to the name of a mounted volume
|
||||
or nil.
|
||||
vRefNum input: Volume specification.
|
||||
creator input: The file's creator type.
|
||||
applVRefNum output: The volume reference number of the volume the
|
||||
application is on.
|
||||
applParID output: The parent directory ID of the application.
|
||||
applName output: The name of the application.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
paramErr -50 No default volume
|
||||
rfNumErr -51 Reference number invalid
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call
|
||||
desktopDamagedErr -1305 The desktop database has become corrupted -
|
||||
the Finder will fix this, but if your
|
||||
application is not running with the
|
||||
Finder, use PBDTReset or PBDTDelete
|
||||
afpItemNotFound -5012 Information not found
|
||||
|
||||
__________
|
||||
|
||||
Also see: FSpDTGetAPPL
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpDTGetAPPL(ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
OSType creator,
|
||||
FSSpec *spec);
|
||||
/* ¦ Find an application on a volume that can open a file with a given creator.
|
||||
The FSpDTGetAPPL function finds an application (file type 'APPL') with
|
||||
the specified creator on the specified volume. It first tries to get
|
||||
the application mapping from the desktop database. If that fails,
|
||||
then it tries to find an application in the Desktop file. If that
|
||||
fails, then it tries to find an application with the specified creator
|
||||
using the File Manager's CatSearch routine.
|
||||
|
||||
volName input: A pointer to the name of a mounted volume
|
||||
or nil.
|
||||
vRefNum input: Volume specification.
|
||||
creator input: The file's creator type.
|
||||
spec output: FSSpec record containing the application name and
|
||||
location.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
paramErr -50 No default volume
|
||||
rfNumErr -51 Reference number invalid
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call
|
||||
desktopDamagedErr -1305 The desktop database has become corrupted -
|
||||
the Finder will fix this, but if your
|
||||
application is not running with the
|
||||
Finder, use PBDTReset or PBDTDelete
|
||||
afpItemNotFound -5012 Information not found
|
||||
|
||||
__________
|
||||
|
||||
Also see: DTGetAPPL
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr DTGetIcon(ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
short iconType,
|
||||
OSType fileCreator,
|
||||
OSType fileType,
|
||||
Handle *iconHandle);
|
||||
/* ¦ Get an icon from the desktop database or Desktop file.
|
||||
The DTGetIcon function retrieves the specified icon and returns it in
|
||||
a newly created handle. The icon is retrieves from the Desktop Manager
|
||||
or if the Desktop Manager is not available, from the Finder's Desktop
|
||||
file. Your program is responsible for disposing of the handle when it is
|
||||
done using the icon.
|
||||
|
||||
volName input: A pointer to the name of a mounted volume
|
||||
or nil.
|
||||
vRefNum input: Volume specification.
|
||||
iconType input: The icon type as defined in Files.h. Valid values are:
|
||||
kLargeIcon
|
||||
kLarge4BitIcon
|
||||
kLarge8BitIcon
|
||||
kSmallIcon
|
||||
kSmall4BitIcon
|
||||
kSmall8BitIcon
|
||||
fileCreator input: The icon's creator type.
|
||||
fileType input: The icon's file type.
|
||||
iconHandle output: A Handle containing the newly created icon.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
paramErr -50 Volume doesn't support this function
|
||||
rfNumErr -51 Reference number invalid
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call
|
||||
memFullErr -108 iconHandle could not be allocated
|
||||
desktopDamagedErr -1305 The desktop database has become corrupted -
|
||||
the Finder will fix this, but if your
|
||||
application is not running with the
|
||||
Finder, use PBDTReset or PBDTDelete
|
||||
afpItemNotFound -5012 Information not found
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr DTSetComment(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name,
|
||||
ConstStr255Param comment);
|
||||
/* ¦ Set a file or directory's Finder comment field.
|
||||
The DTSetComment function sets a file or directory's Finder comment
|
||||
field. The volume must support the Desktop Manager because you only
|
||||
have read access to the Desktop file.
|
||||
|
||||
vRefNum input: Volume specification.
|
||||
dirID input: Directory ID.
|
||||
name input: Pointer to object name, or nil when dirID
|
||||
specifies a directory that's the object.
|
||||
comment input: The comment to add. Comments are limited to 200 characters;
|
||||
longer comments are truncated.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
fnfErr Ð43 File or directory doesnÕt exist
|
||||
paramErr -50 Volume doesn't support this function
|
||||
wPrErr Ð44 Volume is locked through hardware
|
||||
vLckdErr Ð46 Volume is locked through software
|
||||
rfNumErr Ð51 Reference number invalid
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call.
|
||||
desktopDamagedErr -1305 The desktop database has become corrupted -
|
||||
the Finder will fix this, but if your
|
||||
application is not running with the
|
||||
Finder, use PBDTReset or PBDTDelete
|
||||
|
||||
__________
|
||||
|
||||
Also see: DTCopyComment, FSpDTCopyComment, FSpDTSetComment, DTGetComment,
|
||||
FSpDTGetComment
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpDTSetComment(const FSSpec *spec,
|
||||
ConstStr255Param comment);
|
||||
/* ¦ Set a file or directory's Finder comment field.
|
||||
The FSpDTSetComment function sets a file or directory's Finder comment
|
||||
field. The volume must support the Desktop Manager because you only
|
||||
have read access to the Desktop file.
|
||||
|
||||
spec input: An FSSpec record specifying the file or directory.
|
||||
comment input: The comment to add. Comments are limited to 200 characters;
|
||||
longer comments are truncated.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
fnfErr Ð43 File or directory doesnÕt exist
|
||||
wPrErr Ð44 Volume is locked through hardware
|
||||
vLckdErr Ð46 Volume is locked through software
|
||||
rfNumErr Ð51 Reference number invalid
|
||||
paramErr -50 Volume doesn't support this function
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call.
|
||||
desktopDamagedErr -1305 The desktop database has become corrupted -
|
||||
the Finder will fix this, but if your
|
||||
application is not running with the
|
||||
Finder, use PBDTReset or PBDTDelete
|
||||
|
||||
__________
|
||||
|
||||
Also see: DTCopyComment, FSpDTCopyComment, DTSetComment, DTGetComment,
|
||||
FSpDTGetComment
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr DTGetComment(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name,
|
||||
Str255 comment);
|
||||
/* ¦ Get a file or directory's Finder comment field (if any).
|
||||
The DTGetComment function gets a file or directory's Finder comment
|
||||
field (if any) from the Desktop Manager or if the Desktop Manager is
|
||||
not available, from the Finder's Desktop file.
|
||||
|
||||
IMPORTANT NOTE: Inside Macintosh says that comments are up to
|
||||
200 characters. While that may be correct for the HFS file system's
|
||||
Desktop Manager, other file systems (such as Apple Photo Access) return
|
||||
up to 255 characters. Make sure the comment buffer is a Str255 or you'll
|
||||
regret it.
|
||||
|
||||
vRefNum input: Volume specification.
|
||||
dirID input: Directory ID.
|
||||
name input: Pointer to object name, or nil when dirID
|
||||
specifies a directory that's the object.
|
||||
comment output: A Str255 where the comment is to be returned.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
fnfErr -43 File not found
|
||||
paramErr -50 Volume doesn't support this function
|
||||
rfNumErr Ð51 Reference number invalid
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call.
|
||||
desktopDamagedErr -1305 The desktop database has become corrupted -
|
||||
the Finder will fix this, but if your
|
||||
application is not running with the
|
||||
Finder, use PBDTReset or PBDTDelete
|
||||
afpItemNotFound -5012 Information not found
|
||||
|
||||
__________
|
||||
|
||||
Also see: DTCopyComment, FSpDTCopyComment, DTSetComment, FSpDTSetComment,
|
||||
FSpDTGetComment
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpDTGetComment(const FSSpec *spec,
|
||||
Str255 comment);
|
||||
/* ¦ Get a file or directory's Finder comment field (if any).
|
||||
The FSpDTGetComment function gets a file or directory's Finder comment
|
||||
field (if any) from the Desktop Manager or if the Desktop Manager is
|
||||
not available, from the Finder's Desktop file.
|
||||
|
||||
IMPORTANT NOTE: Inside Macintosh says that comments are up to
|
||||
200 characters. While that may be correct for the HFS file system's
|
||||
Desktop Manager, other file systems (such as Apple Photo Access) return
|
||||
up to 255 characters. Make sure the comment buffer is a Str255 or you'll
|
||||
regret it.
|
||||
|
||||
spec input: An FSSpec record specifying the file or directory.
|
||||
comment output: A Str255 where the comment is to be returned.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
fnfErr -43 File not found
|
||||
paramErr -50 Volume doesn't support this function
|
||||
rfNumErr Ð51 Reference number invalid
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call.
|
||||
desktopDamagedErr -1305 The desktop database has become corrupted -
|
||||
the Finder will fix this, but if your
|
||||
application is not running with the
|
||||
Finder, use PBDTReset or PBDTDelete
|
||||
afpItemNotFound -5012 Information not found
|
||||
|
||||
__________
|
||||
|
||||
Also see: DTCopyComment, FSpDTCopyComment, DTSetComment, FSpDTSetComment,
|
||||
DTGetComment
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr DTCopyComment(short srcVRefNum,
|
||||
long srcDirID,
|
||||
ConstStr255Param srcName,
|
||||
short dstVRefNum,
|
||||
long dstDirID,
|
||||
ConstStr255Param dstName);
|
||||
/* ¦ Copy the file or folder comment from the source to the destination object.
|
||||
The DTCopyComment function copies the file or folder comment from the
|
||||
source to the destination object. The destination volume must support
|
||||
the Desktop Manager because you only have read access to the Desktop file.
|
||||
|
||||
srcVRefNum input: Source volume specification.
|
||||
srcDirID input: Source directory ID.
|
||||
srcName input: Pointer to source object name, or nil when srcDirID
|
||||
specifies a directory that's the object.
|
||||
dstVRefNum input: Destination volume specification.
|
||||
dstDirID input: Destination directory ID.
|
||||
dstName input: Pointer to destination object name, or nil when
|
||||
dstDirID specifies a directory that's the object.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
fnfErr Ð43 File or directory doesnÕt exist
|
||||
wPrErr Ð44 Volume is locked through hardware
|
||||
vLckdErr Ð46 Volume is locked through software
|
||||
paramErr -50 Volume doesn't support this function
|
||||
rfNumErr Ð51 Reference number invalid
|
||||
paramErr -50 Volume doesn't support this function
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call.
|
||||
desktopDamagedErr -1305 The desktop database has become corrupted -
|
||||
the Finder will fix this, but if your
|
||||
application is not running with the
|
||||
Finder, use PBDTReset or PBDTDelete
|
||||
afpItemNotFound -5012 Information not found
|
||||
|
||||
__________
|
||||
|
||||
Also see: FSpDTCopyComment, DTSetComment, FSpDTSetComment, DTGetComment,
|
||||
FSpDTGetComment
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpDTCopyComment(const FSSpec *srcSpec,
|
||||
const FSSpec *dstSpec);
|
||||
/* ¦ Copy the desktop database comment from the source to the destination object.
|
||||
The FSpDTCopyComment function copies the desktop database comment from
|
||||
the source to the destination object. Both the source and the
|
||||
destination volumes must support the Desktop Manager.
|
||||
|
||||
srcSpec input: An FSSpec record specifying the source object.
|
||||
dstSpec input: An FSSpec record specifying the destination object.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
fnfErr Ð43 File or directory doesnÕt exist
|
||||
wPrErr Ð44 Volume is locked through hardware
|
||||
vLckdErr Ð46 Volume is locked through software
|
||||
paramErr -50 Volume doesn't support this function
|
||||
rfNumErr Ð51 Reference number invalid
|
||||
paramErr -50 Volume doesn't support this function
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call.
|
||||
desktopDamagedErr -1305 The desktop database has become corrupted -
|
||||
the Finder will fix this, but if your
|
||||
application is not running with the
|
||||
Finder, use PBDTReset or PBDTDelete
|
||||
afpItemNotFound -5012 Information not found
|
||||
|
||||
__________
|
||||
|
||||
Also see: DTCopyComment, DTSetComment, FSpDTSetComment, DTGetComment,
|
||||
FSpDTGetComment
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "OptimEnd.h"
|
||||
|
||||
#endif /* __MOREDESKTOPMGR__ */
|
3228
src/mac/morefile/MoreExtr.cpp
Normal file
3228
src/mac/morefile/MoreExtr.cpp
Normal file
File diff suppressed because it is too large
Load Diff
3141
src/mac/morefile/MoreExtr.h
Normal file
3141
src/mac/morefile/MoreExtr.h
Normal file
File diff suppressed because it is too large
Load Diff
628
src/mac/morefile/MoreFile.cpp
Normal file
628
src/mac/morefile/MoreFile.cpp
Normal file
@ -0,0 +1,628 @@
|
||||
/*
|
||||
** Apple Macintosh Developer Technical Support
|
||||
**
|
||||
** The long lost high-level and FSSpec File Manager functions.
|
||||
**
|
||||
** by Jim Luther, Apple Developer Technical Support Emeritus
|
||||
**
|
||||
** File: MoreFiles.c
|
||||
**
|
||||
** Copyright © 1992-1998 Apple Computer, Inc.
|
||||
** All rights reserved.
|
||||
**
|
||||
** You may incorporate this sample code into your applications without
|
||||
** restriction, though the sample code has been provided "AS IS" and the
|
||||
** responsibility for its operation is 100% yours. However, what you are
|
||||
** not permitted to do is to redistribute the source as "DSC Sample Code"
|
||||
** after having made changes. If you're going to re-distribute the source,
|
||||
** we require that you make it clear in the source that the code was
|
||||
** descended from Apple Sample Code, but that you've made changes.
|
||||
*/
|
||||
|
||||
#include <Types.h>
|
||||
#include <Errors.h>
|
||||
#include <Files.h>
|
||||
|
||||
#define __COMPILINGMOREFILES
|
||||
|
||||
#include "MoreFile.h"
|
||||
#include "MoreExtr.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr HGetVolParms(ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
GetVolParmsInfoBuffer *volParmsInfo,
|
||||
long *infoSize)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
OSErr error;
|
||||
|
||||
pb.ioParam.ioNamePtr = (StringPtr)volName;
|
||||
pb.ioParam.ioVRefNum = vRefNum;
|
||||
pb.ioParam.ioBuffer = (Ptr)volParmsInfo;
|
||||
pb.ioParam.ioReqCount = *infoSize;
|
||||
error = PBHGetVolParmsSync(&pb);
|
||||
if ( error == noErr )
|
||||
{
|
||||
*infoSize = pb.ioParam.ioActCount;
|
||||
}
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr HCreateMinimum(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param fileName)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.fileParam.ioNamePtr = (StringPtr)fileName;
|
||||
pb.fileParam.ioVRefNum = vRefNum;
|
||||
pb.ioParam.ioVersNum = 0;
|
||||
pb.fileParam.ioDirID = dirID;
|
||||
return ( PBHCreateSync(&pb) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpCreateMinimum(const FSSpec *spec)
|
||||
{
|
||||
return ( HCreateMinimum(spec->vRefNum, spec->parID, spec->name) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr ExchangeFiles(short vRefNum,
|
||||
long srcDirID,
|
||||
ConstStr255Param srcName,
|
||||
long dstDirID,
|
||||
ConstStr255Param dstName)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.fidParam.ioVRefNum = vRefNum;
|
||||
pb.fidParam.ioSrcDirID = srcDirID;
|
||||
pb.fidParam.ioNamePtr = (StringPtr)srcName;
|
||||
pb.fidParam.ioDestDirID = dstDirID;
|
||||
pb.fidParam.ioDestNamePtr = (StringPtr)dstName;
|
||||
return ( PBExchangeFilesSync(&pb) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr ResolveFileIDRef(ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
long fileID,
|
||||
long *parID,
|
||||
StringPtr fileName)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
OSErr error;
|
||||
Str255 tempStr;
|
||||
|
||||
tempStr[0] = 0;
|
||||
if ( volName != NULL )
|
||||
{
|
||||
BlockMoveData(volName, tempStr, volName[0] + 1);
|
||||
}
|
||||
pb.fidParam.ioNamePtr = (StringPtr)tempStr;
|
||||
pb.fidParam.ioVRefNum = vRefNum;
|
||||
pb.fidParam.ioFileID = fileID;
|
||||
error = PBResolveFileIDRefSync(&pb);
|
||||
if ( error == noErr )
|
||||
{
|
||||
*parID = pb.fidParam.ioSrcDirID;
|
||||
if ( fileName != NULL )
|
||||
{
|
||||
BlockMoveData(tempStr, fileName, tempStr[0] + 1);
|
||||
}
|
||||
}
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpResolveFileIDRef(ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
long fileID,
|
||||
FSSpec *spec)
|
||||
{
|
||||
OSErr error;
|
||||
|
||||
error = DetermineVRefNum(volName, vRefNum, &(spec->vRefNum));
|
||||
if ( error == noErr )
|
||||
{
|
||||
error = ResolveFileIDRef(volName, vRefNum, fileID, &(spec->parID), spec->name);
|
||||
}
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr CreateFileIDRef(short vRefNum,
|
||||
long parID,
|
||||
ConstStr255Param fileName,
|
||||
long *fileID)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
OSErr error;
|
||||
|
||||
pb.fidParam.ioNamePtr = (StringPtr)fileName;
|
||||
pb.fidParam.ioVRefNum = vRefNum;
|
||||
pb.fidParam.ioSrcDirID = parID;
|
||||
error = PBCreateFileIDRefSync(&pb);
|
||||
if ( error == noErr )
|
||||
{
|
||||
*fileID = pb.fidParam.ioFileID;
|
||||
}
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpCreateFileIDRef(const FSSpec *spec,
|
||||
long *fileID)
|
||||
{
|
||||
return ( CreateFileIDRef(spec->vRefNum, spec->parID, spec->name, fileID) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr DeleteFileIDRef(ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
long fileID)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.fidParam.ioNamePtr = (StringPtr)volName;
|
||||
pb.fidParam.ioVRefNum = vRefNum;
|
||||
pb.fidParam.ioFileID = fileID;
|
||||
return ( PBDeleteFileIDRefSync(&pb) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FlushFile(short refNum)
|
||||
{
|
||||
ParamBlockRec pb;
|
||||
|
||||
pb.ioParam.ioRefNum = refNum;
|
||||
return ( PBFlushFileSync(&pb) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr LockRange(short refNum,
|
||||
long rangeLength,
|
||||
long rangeStart)
|
||||
{
|
||||
ParamBlockRec pb;
|
||||
|
||||
pb.ioParam.ioRefNum = refNum;
|
||||
pb.ioParam.ioReqCount = rangeLength;
|
||||
pb.ioParam.ioPosMode = fsFromStart;
|
||||
pb.ioParam.ioPosOffset = rangeStart;
|
||||
return ( PBLockRangeSync(&pb) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr UnlockRange(short refNum,
|
||||
long rangeLength,
|
||||
long rangeStart)
|
||||
{
|
||||
ParamBlockRec pb;
|
||||
|
||||
pb.ioParam.ioRefNum = refNum;
|
||||
pb.ioParam.ioReqCount = rangeLength;
|
||||
pb.ioParam.ioPosMode = fsFromStart;
|
||||
pb.ioParam.ioPosOffset = rangeStart;
|
||||
return ( PBUnlockRangeSync(&pb) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr GetForeignPrivs(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name,
|
||||
void *foreignPrivBuffer,
|
||||
long *foreignPrivSize,
|
||||
long *foreignPrivInfo1,
|
||||
long *foreignPrivInfo2,
|
||||
long *foreignPrivInfo3,
|
||||
long *foreignPrivInfo4)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
OSErr error;
|
||||
|
||||
pb.foreignPrivParam.ioNamePtr = (StringPtr)name;
|
||||
pb.foreignPrivParam.ioVRefNum = vRefNum;
|
||||
pb.foreignPrivParam.ioForeignPrivDirID = dirID;
|
||||
pb.foreignPrivParam.ioForeignPrivBuffer = (Ptr)foreignPrivBuffer;
|
||||
pb.foreignPrivParam.ioForeignPrivReqCount = *foreignPrivSize;
|
||||
error = PBGetForeignPrivsSync(&pb);
|
||||
*foreignPrivSize = pb.foreignPrivParam.ioForeignPrivActCount;
|
||||
*foreignPrivInfo1 = pb.foreignPrivParam.ioForeignPrivInfo1;
|
||||
*foreignPrivInfo2 = pb.foreignPrivParam.ioForeignPrivInfo2;
|
||||
*foreignPrivInfo3 = pb.foreignPrivParam.ioForeignPrivInfo3;
|
||||
*foreignPrivInfo4 = pb.foreignPrivParam.ioForeignPrivInfo4;
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpGetForeignPrivs(const FSSpec *spec,
|
||||
void *foreignPrivBuffer,
|
||||
long *foreignPrivSize,
|
||||
long *foreignPrivInfo1,
|
||||
long *foreignPrivInfo2,
|
||||
long *foreignPrivInfo3,
|
||||
long *foreignPrivInfo4)
|
||||
{
|
||||
return ( GetForeignPrivs(spec->vRefNum, spec->parID, spec->name,
|
||||
foreignPrivBuffer, foreignPrivSize,
|
||||
foreignPrivInfo1, foreignPrivInfo2,
|
||||
foreignPrivInfo3, foreignPrivInfo4) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr SetForeignPrivs(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name,
|
||||
const void *foreignPrivBuffer,
|
||||
long *foreignPrivSize,
|
||||
long foreignPrivInfo1,
|
||||
long foreignPrivInfo2,
|
||||
long foreignPrivInfo3,
|
||||
long foreignPrivInfo4)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
OSErr error;
|
||||
|
||||
pb.foreignPrivParam.ioNamePtr = (StringPtr)name;
|
||||
pb.foreignPrivParam.ioVRefNum = vRefNum;
|
||||
pb.foreignPrivParam.ioForeignPrivDirID = dirID;
|
||||
pb.foreignPrivParam.ioForeignPrivBuffer = (Ptr)foreignPrivBuffer;
|
||||
pb.foreignPrivParam.ioForeignPrivReqCount = *foreignPrivSize;
|
||||
pb.foreignPrivParam.ioForeignPrivInfo1 = foreignPrivInfo1;
|
||||
pb.foreignPrivParam.ioForeignPrivInfo2 = foreignPrivInfo2;
|
||||
pb.foreignPrivParam.ioForeignPrivInfo3 = foreignPrivInfo3;
|
||||
pb.foreignPrivParam.ioForeignPrivInfo4 = foreignPrivInfo4;
|
||||
error = PBSetForeignPrivsSync(&pb);
|
||||
if ( error == noErr )
|
||||
{
|
||||
*foreignPrivSize = pb.foreignPrivParam.ioForeignPrivActCount;
|
||||
}
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpSetForeignPrivs(const FSSpec *spec,
|
||||
const void *foreignPrivBuffer,
|
||||
long *foreignPrivSize,
|
||||
long foreignPrivInfo1,
|
||||
long foreignPrivInfo2,
|
||||
long foreignPrivInfo3,
|
||||
long foreignPrivInfo4)
|
||||
{
|
||||
return ( SetForeignPrivs(spec->vRefNum, spec->parID, spec->name,
|
||||
foreignPrivBuffer, foreignPrivSize,
|
||||
foreignPrivInfo1, foreignPrivInfo2,
|
||||
foreignPrivInfo3, foreignPrivInfo4) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr HGetLogInInfo(ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
short *loginMethod,
|
||||
StringPtr userName)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
OSErr error;
|
||||
|
||||
pb.objParam.ioNamePtr = (StringPtr)volName;
|
||||
pb.objParam.ioVRefNum = vRefNum;
|
||||
pb.objParam.ioObjNamePtr = userName;
|
||||
error = PBHGetLogInInfoSync(&pb);
|
||||
if ( error == noErr )
|
||||
{
|
||||
*loginMethod = pb.objParam.ioObjType;
|
||||
}
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr HGetDirAccess(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name,
|
||||
long *ownerID,
|
||||
long *groupID,
|
||||
long *accessRights)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
OSErr error;
|
||||
|
||||
pb.accessParam.ioNamePtr = (StringPtr)name;
|
||||
pb.accessParam.ioVRefNum = vRefNum;
|
||||
pb.fileParam.ioDirID = dirID;
|
||||
error = PBHGetDirAccessSync(&pb);
|
||||
if ( error == noErr )
|
||||
{
|
||||
*ownerID = pb.accessParam.ioACOwnerID;
|
||||
*groupID = pb.accessParam.ioACGroupID;
|
||||
*accessRights = pb.accessParam.ioACAccess;
|
||||
}
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpGetDirAccess(const FSSpec *spec,
|
||||
long *ownerID,
|
||||
long *groupID,
|
||||
long *accessRights)
|
||||
{
|
||||
return ( HGetDirAccess(spec->vRefNum, spec->parID, spec->name,
|
||||
ownerID, groupID, accessRights) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr HSetDirAccess(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name,
|
||||
long ownerID,
|
||||
long groupID,
|
||||
long accessRights)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.accessParam.ioNamePtr = (StringPtr)name;
|
||||
pb.accessParam.ioVRefNum = vRefNum;
|
||||
pb.fileParam.ioDirID = dirID;
|
||||
pb.accessParam.ioACOwnerID = ownerID;
|
||||
pb.accessParam.ioACGroupID = groupID;
|
||||
pb.accessParam.ioACAccess = accessRights;
|
||||
return ( PBHSetDirAccessSync(&pb) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpSetDirAccess(const FSSpec *spec,
|
||||
long ownerID,
|
||||
long groupID,
|
||||
long accessRights)
|
||||
{
|
||||
return ( HSetDirAccess(spec->vRefNum, spec->parID, spec->name,
|
||||
ownerID, groupID, accessRights) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr HMapID(ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
long ugID,
|
||||
short objType,
|
||||
StringPtr name)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.objParam.ioNamePtr = (StringPtr)volName;
|
||||
pb.objParam.ioVRefNum = vRefNum;
|
||||
pb.objParam.ioObjType = objType;
|
||||
pb.objParam.ioObjNamePtr = name;
|
||||
pb.objParam.ioObjID = ugID;
|
||||
return ( PBHMapIDSync(&pb) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr HMapName(ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
ConstStr255Param name,
|
||||
short objType,
|
||||
long *ugID)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
OSErr error;
|
||||
|
||||
pb.objParam.ioNamePtr = (StringPtr)volName;
|
||||
pb.objParam.ioVRefNum = vRefNum;
|
||||
pb.objParam.ioObjType = objType;
|
||||
pb.objParam.ioObjNamePtr = (StringPtr)name;
|
||||
error = PBHMapNameSync(&pb);
|
||||
if ( error == noErr )
|
||||
{
|
||||
*ugID = pb.objParam.ioObjID;
|
||||
}
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr HCopyFile(short srcVRefNum,
|
||||
long srcDirID,
|
||||
ConstStr255Param srcName,
|
||||
short dstVRefNum,
|
||||
long dstDirID,
|
||||
ConstStr255Param dstPathname,
|
||||
ConstStr255Param copyName)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.copyParam.ioVRefNum = srcVRefNum;
|
||||
pb.copyParam.ioDirID = srcDirID;
|
||||
pb.copyParam.ioNamePtr = (StringPtr)srcName;
|
||||
pb.copyParam.ioDstVRefNum = dstVRefNum;
|
||||
pb.copyParam.ioNewDirID = dstDirID;
|
||||
pb.copyParam.ioNewName = (StringPtr)dstPathname;
|
||||
pb.copyParam.ioCopyName = (StringPtr)copyName;
|
||||
return ( PBHCopyFileSync(&pb) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpCopyFile(const FSSpec *srcSpec,
|
||||
const FSSpec *dstSpec,
|
||||
ConstStr255Param copyName)
|
||||
{
|
||||
return ( HCopyFile(srcSpec->vRefNum, srcSpec->parID, srcSpec->name,
|
||||
dstSpec->vRefNum, dstSpec->parID,
|
||||
dstSpec->name, copyName) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr HMoveRename(short vRefNum,
|
||||
long srcDirID,
|
||||
ConstStr255Param srcName,
|
||||
long dstDirID,
|
||||
ConstStr255Param dstpathName,
|
||||
ConstStr255Param copyName)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.copyParam.ioVRefNum = vRefNum;
|
||||
pb.copyParam.ioDirID = srcDirID;
|
||||
pb.copyParam.ioNamePtr = (StringPtr)srcName;
|
||||
pb.copyParam.ioNewDirID = dstDirID;
|
||||
pb.copyParam.ioNewName = (StringPtr)dstpathName;
|
||||
pb.copyParam.ioCopyName = (StringPtr)copyName;
|
||||
return ( PBHMoveRenameSync(&pb) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpMoveRename(const FSSpec *srcSpec,
|
||||
const FSSpec *dstSpec,
|
||||
ConstStr255Param copyName)
|
||||
{
|
||||
OSErr error;
|
||||
|
||||
/* make sure the FSSpecs refer to the same volume */
|
||||
if ( srcSpec->vRefNum != dstSpec->vRefNum )
|
||||
{
|
||||
error = diffVolErr;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = HMoveRename(srcSpec->vRefNum, srcSpec->parID, srcSpec->name,
|
||||
dstSpec->parID, dstSpec->name, copyName);
|
||||
}
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr GetVolMountInfoSize(ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
short *size)
|
||||
{
|
||||
ParamBlockRec pb;
|
||||
|
||||
pb.ioParam.ioNamePtr = (StringPtr)volName;
|
||||
pb.ioParam.ioVRefNum = vRefNum;
|
||||
pb.ioParam.ioBuffer = (Ptr)size;
|
||||
return ( PBGetVolMountInfoSize(&pb) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr GetVolMountInfo(ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
void *volMountInfo)
|
||||
{
|
||||
ParamBlockRec pb;
|
||||
|
||||
pb.ioParam.ioNamePtr = (StringPtr)volName;
|
||||
pb.ioParam.ioVRefNum = vRefNum;
|
||||
pb.ioParam.ioBuffer = (Ptr)volMountInfo;
|
||||
return ( PBGetVolMountInfo(&pb) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr VolumeMount(const void *volMountInfo,
|
||||
short *vRefNum)
|
||||
{
|
||||
ParamBlockRec pb;
|
||||
OSErr error;
|
||||
|
||||
pb.ioParam.ioBuffer = (Ptr)volMountInfo;
|
||||
error = PBVolumeMount(&pb);
|
||||
if ( error == noErr )
|
||||
{
|
||||
*vRefNum = pb.ioParam.ioVRefNum;
|
||||
}
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr Share(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.fileParam.ioNamePtr = (StringPtr)name;
|
||||
pb.fileParam.ioVRefNum = vRefNum;
|
||||
pb.fileParam.ioDirID = dirID;
|
||||
return ( PBShareSync(&pb) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpShare(const FSSpec *spec)
|
||||
{
|
||||
return ( Share(spec->vRefNum, spec->parID, spec->name) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr Unshare(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.fileParam.ioNamePtr = (StringPtr)name;
|
||||
pb.fileParam.ioVRefNum = vRefNum;
|
||||
pb.fileParam.ioDirID = dirID;
|
||||
return ( PBUnshareSync(&pb) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpUnshare(const FSSpec *spec)
|
||||
{
|
||||
return ( Unshare(spec->vRefNum, spec->parID, spec->name) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr GetUGEntry(short objType,
|
||||
StringPtr objName,
|
||||
long *objID)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
OSErr error;
|
||||
|
||||
pb.objParam.ioObjType = objType;
|
||||
pb.objParam.ioObjNamePtr = objName;
|
||||
pb.objParam.ioObjID = *objID;
|
||||
error = PBGetUGEntrySync(&pb);
|
||||
if ( error == noErr )
|
||||
{
|
||||
*objID = pb.objParam.ioObjID;
|
||||
}
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
1244
src/mac/morefile/MoreFile.h
Normal file
1244
src/mac/morefile/MoreFile.h
Normal file
File diff suppressed because it is too large
Load Diff
91
src/mac/morefile/Optim.h
Normal file
91
src/mac/morefile/Optim.h
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
** Apple Macintosh Developer Technical Support
|
||||
**
|
||||
** DirectoryCopy: #defines that let you make MoreFiles code more efficient.
|
||||
**
|
||||
** by Jim Luther, Apple Developer Technical Support Emeritus
|
||||
**
|
||||
** File: Optimization.h
|
||||
**
|
||||
** Copyright © 1992-1998 Apple Computer, Inc.
|
||||
** All rights reserved.
|
||||
**
|
||||
** You may incorporate this sample code into your applications without
|
||||
** restriction, though the sample code has been provided "AS IS" and the
|
||||
** responsibility for its operation is 100% yours. However, what you are
|
||||
** not permitted to do is to redistribute the source as "DSC Sample Code"
|
||||
** after having made changes. If you're going to re-distribute the source,
|
||||
** we require that you make it clear in the source that the code was
|
||||
** descended from Apple Sample Code, but that you've made changes.
|
||||
**
|
||||
** The Optimization changes to MoreFiles source and header files, along with
|
||||
** this file and OptimizationEnd.h, let you optimize the code produced
|
||||
** by MoreFiles in several ways.
|
||||
**
|
||||
** 1 -- MoreFiles contains extra code so that many routines can run under
|
||||
** Mac OS systems back to System 6. If your program requires a specific
|
||||
** version of Mac OS and your program checks for that version before
|
||||
** calling MoreFiles routines, then you can remove a lot of compatibility
|
||||
** code by defining one of the following to 1:
|
||||
**
|
||||
** __MACOSSEVENFIVEONEORLATER // assume Mac OS 7.5.1 or later
|
||||
** __MACOSSEVENFIVEORLATER // assume Mac OS 7.5 or later
|
||||
** __MACOSSEVENORLATER // assume Mac OS 7.0 or later
|
||||
**
|
||||
** By default, all compatibility code is ON.
|
||||
**
|
||||
** 2 -- You may disable Pascal calling conventions in all MoreFiles routines
|
||||
** except for system callbacks that require Pascal calling conventions.
|
||||
** This will make C programs both smaller and faster.
|
||||
** Just define __WANTPASCALELIMINATION to be 1 to turn this optimization on
|
||||
** when building MoreFiles for use from C programs (you'll need to keep
|
||||
** Pascal calling conventions when linking MoreFiles routines with Pascal
|
||||
** programs).
|
||||
**
|
||||
** 3 -- If Metrowerks compiler is used, "#pragma internal on" may help produce
|
||||
** better code. However, this option can also cause problems if you're
|
||||
** trying to build MoreFiles as a shared library, so it is by default not used.
|
||||
** Just define __USEPRAGMAINTERNAL to be 1 to turn this optimization on.
|
||||
**
|
||||
** Original changes supplied by Fabrizio Oddone
|
||||
**
|
||||
** File: Optimization.h
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __MACOSSEVENFIVEONEORLATER
|
||||
#define __MACOSSEVENFIVEONEORLATER 0
|
||||
#endif
|
||||
|
||||
#ifndef __MACOSSEVENFIVEORLATER
|
||||
#define __MACOSSEVENFIVEORLATER __MACOSSEVENFIVEONEORLATER
|
||||
#endif
|
||||
|
||||
#ifndef __MACOSSEVENORLATER
|
||||
#if GENERATINGCFM
|
||||
#define __MACOSSEVENORLATER 1
|
||||
#else
|
||||
#define __MACOSSEVENORLATER __MACOSSEVENFIVEORLATER
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __WANTPASCALELIMINATION
|
||||
#define __WANTPASCALELIMINATION 0
|
||||
#endif
|
||||
|
||||
#if __WANTPASCALELIMINATION
|
||||
#define pascal
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __USEPRAGMAINTERNAL
|
||||
#define __USEPRAGMAINTERNAL 0
|
||||
#endif
|
||||
|
||||
#if __USEPRAGMAINTERNAL
|
||||
#if defined(__MWERKS__)
|
||||
#pragma internal on
|
||||
#endif
|
||||
#endif
|
||||
|
40
src/mac/morefile/OptimEnd.h
Normal file
40
src/mac/morefile/OptimEnd.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
** Apple Macintosh Developer Technical Support
|
||||
**
|
||||
** DirectoryCopy: #defines that let you make MoreFiles code more efficient.
|
||||
**
|
||||
** by Jim Luther, Apple Developer Technical Support Emeritus
|
||||
**
|
||||
** File: OptimizationEnd.h
|
||||
**
|
||||
** Copyright © 1992-1998 Apple Computer, Inc.
|
||||
** All rights reserved.
|
||||
**
|
||||
** You may incorporate this sample code into your applications without
|
||||
** restriction, though the sample code has been provided "AS IS" and the
|
||||
** responsibility for its operation is 100% yours. However, what you are
|
||||
** not permitted to do is to redistribute the source as "DSC Sample Code"
|
||||
** after having made changes. If you're going to re-distribute the source,
|
||||
** we require that you make it clear in the source that the code was
|
||||
** descended from Apple Sample Code, but that you've made changes.
|
||||
**
|
||||
** The Optimization changes to MoreFiles source and header files, along with
|
||||
** this file and Optimization.h, let you optimize the code produced by MoreFiles
|
||||
** in several ways.
|
||||
**
|
||||
** Original changes supplied by Fabrizio Oddone
|
||||
*/
|
||||
|
||||
|
||||
#if __USEPRAGMAINTERNAL
|
||||
#if defined(__MWERKS__)
|
||||
#pragma internal reset
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#if __WANTPASCALELIMINATION
|
||||
#ifndef __COMPILINGMOREFILES
|
||||
#undef pascal
|
||||
#endif
|
||||
#endif
|
1275
src/mac/morefile/Search.cpp
Normal file
1275
src/mac/morefile/Search.cpp
Normal file
File diff suppressed because it is too large
Load Diff
246
src/mac/morefile/Search.h
Normal file
246
src/mac/morefile/Search.h
Normal file
@ -0,0 +1,246 @@
|
||||
/*
|
||||
** Apple Macintosh Developer Technical Support
|
||||
**
|
||||
** IndexedSearch and the PBCatSearch compatibility function.
|
||||
**
|
||||
** by Jim Luther, Apple Developer Technical Support Emeritus
|
||||
**
|
||||
** File: Search.h
|
||||
**
|
||||
** Copyright © 1992-1998 Apple Computer, Inc.
|
||||
** All rights reserved.
|
||||
**
|
||||
** You may incorporate this sample code into your applications without
|
||||
** restriction, though the sample code has been provided "AS IS" and the
|
||||
** responsibility for its operation is 100% yours. However, what you are
|
||||
** not permitted to do is to redistribute the source as "DSC Sample Code"
|
||||
** after having made changes. If you're going to re-distribute the source,
|
||||
** we require that you make it clear in the source that the code was
|
||||
** descended from Apple Sample Code, but that you've made changes.
|
||||
*/
|
||||
|
||||
#ifndef __SEARCH__
|
||||
#define __SEARCH__
|
||||
|
||||
#include <Types.h>
|
||||
#include <Files.h>
|
||||
|
||||
#include "Optim.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr IndexedSearch(CSParamPtr pb,
|
||||
long dirID);
|
||||
/* ¦ Search in and below a directory.
|
||||
The IndexedSearch function performs an indexed search in and below the
|
||||
specified directory using the same parameters (in pb) as is passed to
|
||||
PBCatSearch. See Inside Macintosh: Files for a description of the
|
||||
parameter block.
|
||||
|
||||
pb input: A CSParamPtr record specifying the volume to search
|
||||
and the search criteria.
|
||||
output: Fields in the parameter block are returned indicating
|
||||
the number of matches found, the matches, and if the
|
||||
search ended with noErr, the CatPosition record that
|
||||
lets you resume a search where the last search left
|
||||
off.
|
||||
dirID input: The directory to search. If fsRtDirID is passed,
|
||||
the entire volume is searched.
|
||||
|
||||
Note: If you use a high-level debugger and use ioSearchTime to limit
|
||||
the length of time to run the search, you'll want to step over
|
||||
calls to IndexedSearch because it installs a Time Manager task.
|
||||
Most high-level debuggers don't deal gracefully with interrupt
|
||||
driven code.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
eofErr -39 End of catalog found (this is normal!)
|
||||
paramErr -50 Parameter block has invalid parameters
|
||||
(see source for VerifyUserPB) or
|
||||
invalid catPosition record was passed
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call.
|
||||
memFullErr -108 Memory could not be allocated in heap
|
||||
catChangedErr -1304 Catalog has changed and catalog position
|
||||
record may be invalid
|
||||
|
||||
__________
|
||||
|
||||
See also: PBCatSearch, PBCatSearchSyncCompat
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr PBCatSearchSyncCompat(CSParamPtr paramBlock);
|
||||
/* ¦ Search a volume using PBCatSearch or IndexedSearch.
|
||||
The PBCatSearchSyncCompat function uses PBCatSearch (if available) or
|
||||
IndexedSearch (if PBCatSearch is not available) to search a volume
|
||||
using a set of search criteria that you specify. It builds a list of all
|
||||
files or directories that meet your specifications.
|
||||
|
||||
pb input: A CSParamPtr record specifying the volume to search
|
||||
and the search criteria.
|
||||
output: Fields in the parameter block are returned indicating
|
||||
the number of matches found, the matches, and if the
|
||||
search ended with noErr, the CatPosition record that
|
||||
lets you resume a search where the last search left
|
||||
off.
|
||||
|
||||
Note: If you use a high-level debugger and use ioSearchTime to limit
|
||||
the length of time to run the search, you'll want to step over
|
||||
calls to PBCatSearchSyncCompat because it calls IndexedSearch
|
||||
which installs a Time Manager task. Most high-level debuggers
|
||||
don't deal gracefully with interrupt driven code.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
eofErr -39 End of catalog found (this is normal!)
|
||||
paramErr -50 Parameter block has invalid parameters
|
||||
(see source for VerifyUserPB) or
|
||||
invalid catPosition record was passed
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call.
|
||||
memFullErr -108 Memory could not be allocated in heap
|
||||
catChangedErr -1304 Catalog has changed and catalog position
|
||||
record may be invalid
|
||||
afpCatalogChanged -5037 Catalog has changed and search cannot
|
||||
be resumed
|
||||
|
||||
__________
|
||||
|
||||
See also: PBCatSearch, IndexedSearch
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr NameFileSearch(ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
ConstStr255Param fileName,
|
||||
FSSpecPtr matches,
|
||||
long reqMatchCount,
|
||||
long *actMatchCount,
|
||||
Boolean newSearch,
|
||||
Boolean partial);
|
||||
/* ¦ Search for files by file name with PBCatSearch.
|
||||
The NameFileSearch function searches for files with a specific file
|
||||
name on a volume that supports PBCatSearch.
|
||||
Note: A result of catChangedErr means the catalog has changed between
|
||||
searches, but the search can be continued with the possiblity that you
|
||||
may miss some matches or get duplicate matches. For all other results
|
||||
(except for noErr), the search cannot be continued.
|
||||
|
||||
volName input: A pointer to the name of a mounted volume
|
||||
or nil.
|
||||
vRefNum input: Volume specification.
|
||||
fileName input: The name of the file to search for.
|
||||
matches input: Pointer to array of FSSpec where the match list is
|
||||
returned.
|
||||
reqMatchCount input: Maximum number of matches to return (the number of
|
||||
elements in the matches array).
|
||||
actMatchCount output: The number of matches actually returned.
|
||||
newSearch input: If true, start a new search. If false and if
|
||||
vRefNum is the same as the last call to
|
||||
NameFileSearch, then start searching at the
|
||||
position where the last search left off.
|
||||
partial input: If the partial parameter is false, then only files
|
||||
that exactly match fileName will be found. If the
|
||||
partial parameter is true, then all file names that
|
||||
contain fileName will be found.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
eofErr -39 End of catalog found (this is normal!)
|
||||
paramErr -50 Parameter block has invalid parameters
|
||||
(see source for VerifyUserPB) or
|
||||
invalid catPosition record was passed
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call.
|
||||
memFullErr -108 Memory could not be allocated in heap
|
||||
catChangedErr -1304 Catalog has changed and catalog position
|
||||
record may be invalid
|
||||
afpCatalogChanged -5037 Catalog has changed and search cannot
|
||||
be resumed
|
||||
|
||||
__________
|
||||
|
||||
Also see: CreatorTypeFileSearch
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr CreatorTypeFileSearch(ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
OSType creator,
|
||||
OSType fileType,
|
||||
FSSpecPtr matches,
|
||||
long reqMatchCount,
|
||||
long *actMatchCount,
|
||||
Boolean newSearch);
|
||||
/* ¦ Search for files by creator/fileType with PBCatSearch.
|
||||
The CreatorTypeFileSearch function searches for files with a specific
|
||||
creator or fileType on a volume that supports PBCatSearch.
|
||||
Note: A result of catChangedErr means the catalog has changed between
|
||||
searches, but the search can be continued with the possiblity that you
|
||||
may miss some matches or get duplicate matches. For all other results
|
||||
(except for noErr), the search cannot be continued.
|
||||
|
||||
volName input: A pointer to the name of a mounted volume
|
||||
or nil.
|
||||
vRefNum input: Volume specification.
|
||||
creator input: The creator type of the file to search for.
|
||||
To ignore the creator type, pass 0x00000000 in
|
||||
this field.
|
||||
fileType input: The file type of the file to search for.
|
||||
To ignore the file type, pass 0x00000000 in
|
||||
this field.
|
||||
matches input: Pointer to array of FSSpec where the match list is
|
||||
returned.
|
||||
reqMatchCount input: Maximum number of matches to return (the number of
|
||||
elements in the matches array).
|
||||
actMatchCount output: The number of matches actually returned.
|
||||
newSearch input: If true, start a new search. If false and if
|
||||
vRefNum is the same as the last call to
|
||||
CreatorTypeFileSearch, then start searching at the
|
||||
position where the last search left off.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
eofErr -39 End of catalog found (this is normal!)
|
||||
paramErr -50 Parameter block has invalid parameters
|
||||
(see source for VerifyUserPB) or
|
||||
invalid catPosition record was passed
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call.
|
||||
memFullErr -108 Memory could not be allocated in heap
|
||||
catChangedErr -1304 Catalog has changed and catalog position
|
||||
record may be invalid
|
||||
afpCatalogChanged -5037 Catalog has changed and search cannot
|
||||
be resumed
|
||||
|
||||
__________
|
||||
|
||||
Also see: NameFileSearch
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "OptimEnd.h"
|
||||
|
||||
#endif /* __SEARCH__ */
|
BIN
src/make_cw.mcp
BIN
src/make_cw.mcp
Binary file not shown.
Loading…
Reference in New Issue
Block a user