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:
Stefan Csomor 1999-02-01 15:43:00 +00:00
parent 291a8f20b3
commit 2276c29594
22 changed files with 15912 additions and 0 deletions

Binary file not shown.

View 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
View 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__ */

View 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
View 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__ */

View 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
View 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__ */

View 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
View 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__ */

View 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
View 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__ */

File diff suppressed because it is too large Load Diff

541
src/mac/morefile/MoreDesk.h Normal file
View 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__ */

File diff suppressed because it is too large Load Diff

3141
src/mac/morefile/MoreExtr.h Normal file

File diff suppressed because it is too large Load Diff

View 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

File diff suppressed because it is too large Load Diff

91
src/mac/morefile/Optim.h Normal file
View 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

View 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

File diff suppressed because it is too large Load Diff

246
src/mac/morefile/Search.h Normal file
View 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__ */

Binary file not shown.