From: Stefan Csomor Date: Wed, 10 Oct 2001 22:57:33 +0000 (+0000) Subject: new version 1.5.2 for morefiles X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/92622ef4c2162596f543d304059375552db5c313 new version 1.5.2 for morefiles git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@11937 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/src/mac/carbon/dirmac.cpp b/src/mac/carbon/dirmac.cpp index 36835cd68c..5f06ceab58 100644 --- a/src/mac/carbon/dirmac.cpp +++ b/src/mac/carbon/dirmac.cpp @@ -41,10 +41,8 @@ #endif #ifndef __DARWIN__ - #include "morefile.h" - #include "moreextr.h" - #include "fullpath.h" - #include "fspcompa.h" + #include "MoreFiles.h" + #include "MoreFilesExtras.h" #endif // ---------------------------------------------------------------------------- diff --git a/src/mac/carbon/filedlg.cpp b/src/mac/carbon/filedlg.cpp index 1d6fd58d44..504b2af6da 100644 --- a/src/mac/carbon/filedlg.cpp +++ b/src/mac/carbon/filedlg.cpp @@ -35,11 +35,8 @@ IMPLEMENT_CLASS(wxFileDialog, wxDialog) #endif #ifndef __DARWIN__ - #include "morefile.h" - #include "moreextr.h" - #include "fullpath.h" - #include "fspcompa.h" - #include "PLStringFuncs.h" + #include "MoreFiles.h" + #include "MoreFilesExtras.h" #endif extern bool gUseNavServices ; diff --git a/src/mac/carbon/utils.cpp b/src/mac/carbon/utils.cpp index f234da7456..e490ce4583 100644 --- a/src/mac/carbon/utils.cpp +++ b/src/mac/carbon/utils.cpp @@ -28,8 +28,8 @@ #include #ifndef __DARWIN__ -# include "morefile.h" -# include "moreextr.h" + #include "MoreFiles.h" + #include "MoreFilesExtras.h" #endif #ifndef __DARWIN__ diff --git a/src/mac/dirmac.cpp b/src/mac/dirmac.cpp index 36835cd68c..5f06ceab58 100644 --- a/src/mac/dirmac.cpp +++ b/src/mac/dirmac.cpp @@ -41,10 +41,8 @@ #endif #ifndef __DARWIN__ - #include "morefile.h" - #include "moreextr.h" - #include "fullpath.h" - #include "fspcompa.h" + #include "MoreFiles.h" + #include "MoreFilesExtras.h" #endif // ---------------------------------------------------------------------------- diff --git a/src/mac/filedlg.cpp b/src/mac/filedlg.cpp index 1d6fd58d44..504b2af6da 100644 --- a/src/mac/filedlg.cpp +++ b/src/mac/filedlg.cpp @@ -35,11 +35,8 @@ IMPLEMENT_CLASS(wxFileDialog, wxDialog) #endif #ifndef __DARWIN__ - #include "morefile.h" - #include "moreextr.h" - #include "fullpath.h" - #include "fspcompa.h" - #include "PLStringFuncs.h" + #include "MoreFiles.h" + #include "MoreFilesExtras.h" #endif extern bool gUseNavServices ; diff --git a/src/mac/morefile/Director.cpp b/src/mac/morefile/Director.cpp deleted file mode 100644 index 635877693f..0000000000 --- a/src/mac/morefile/Director.cpp +++ /dev/null @@ -1,675 +0,0 @@ -/* -** 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 -#include -#include -#include -#include - -#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_STRUCT_ALIGN - #pragma options align=mac68k -#elif PRAGMA_STRUCT_PACKPUSH - #pragma pack(push, 2) -#elif PRAGMA_STRUCT_PACK - #pragma pack(2) -#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_STRUCT_ALIGN - #pragma options align=reset -#elif PRAGMA_STRUCT_PACKPUSH - #pragma pack(pop) -#elif PRAGMA_STRUCT_PACK - #pragma pack() -#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_STRUCT_ALIGN - #pragma options align=mac68k -#elif PRAGMA_STRUCT_PACKPUSH - #pragma pack(push, 2) -#elif PRAGMA_STRUCT_PACK - #pragma pack(2) -#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_STRUCT_ALIGN - #pragma options align=reset -#elif PRAGMA_STRUCT_PACKPUSH - #pragma pack(pop) -#elif PRAGMA_STRUCT_PACK - #pragma pack() -#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 ); -} - - -#if !TARGET_CARBON - -/*****************************************************************************/ - -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); - dstFreeBlocks = pb.ioVFreeBytes >> 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 ); -} -#endif -/*****************************************************************************/ - -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) ); -} - -/*****************************************************************************/ - diff --git a/src/mac/morefile/Director.h b/src/mac/morefile/Director.h deleted file mode 100644 index a05335a63b..0000000000 --- a/src/mac/morefile/Director.h +++ /dev/null @@ -1,493 +0,0 @@ -/* -** 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 -#include - -#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__ */ diff --git a/src/mac/morefile/DirectoryCopy.c b/src/mac/morefile/DirectoryCopy.c new file mode 100644 index 0000000000..ed9c834718 --- /dev/null +++ b/src/mac/morefile/DirectoryCopy.c @@ -0,0 +1,684 @@ +/* + File: DirectoryCopy.c + + Contains: A robust, general purpose directory copy routine. + + Version: MoreFiles + + Copyright: © 1992-2001 by 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. + + File Ownership: + + DRI: Apple Macintosh Developer Technical Support + + Other Contact: Apple Macintosh Developer Technical Support + + + Technology: DTS Sample Code + + Writers: + + (JL) Jim Luther + + Change History (most recent first): + + <2> 2/7/01 JL Added standard header. Updated names of includes. + <1> 12/06/99 JL MoreFiles 1.5. +*/ + +#include +#include +#include +#include +#include +#include + +#define __COMPILINGMOREFILES + +#include "MoreFiles.h" +#include "MoreFilesExtras.h" +#include "MoreDesktopMgr.h" +#include "FileCopy.h" +#include "DirectoryCopy.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_STRUCT_ALIGN +#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_STRUCT_ALIGN +#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_STRUCT_ALIGN +#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_STRUCT_ALIGN +#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 & kioFlAttribDirMask) != 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 = U32SetU(U64ShiftRight(pb.ioVFreeBytes, 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 & kioFlAttribDirMask) != 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, + ConstStr255Param copyName, + 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 ) + { + /* use the copyName as srcDirName if supplied */ + if ( copyName != NULL ) + { + /* make a copy since copyName is a const input */ + BlockMoveData(copyName, srcDirName, sizeof(Str31)); + } + /* 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 + { + /* use the copyName as srcDirName if supplied */ + error = DirCreate(dstVRefNum, dstDirID, ((copyName != NULL) ? copyName : 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, + ConstStr255Param copyName, + void *copyBufferPtr, + long copyBufferSize, + Boolean preflight, + CopyErrProcPtr copyErrHandler) +{ + return ( FilteredDirectoryCopy(srcVRefNum, srcDirID, srcName, + dstVRefNum, dstDirID, dstName, + copyName, + copyBufferPtr, copyBufferSize, preflight, + copyErrHandler, NULL) ); +} + +/*****************************************************************************/ + +pascal OSErr FSpFilteredDirectoryCopy(const FSSpec *srcSpec, + const FSSpec *dstSpec, + ConstStr255Param copyName, + void *copyBufferPtr, + long copyBufferSize, + Boolean preflight, + CopyErrProcPtr copyErrHandler, + CopyFilterProcPtr copyFilterProc) +{ + return ( FilteredDirectoryCopy(srcSpec->vRefNum, srcSpec->parID, srcSpec->name, + dstSpec->vRefNum, dstSpec->parID, dstSpec->name, + copyName, + copyBufferPtr, copyBufferSize, preflight, + copyErrHandler, copyFilterProc) ); +} + +/*****************************************************************************/ + +pascal OSErr FSpDirectoryCopy(const FSSpec *srcSpec, + const FSSpec *dstSpec, + ConstStr255Param copyName, + void *copyBufferPtr, + long copyBufferSize, + Boolean preflight, + CopyErrProcPtr copyErrHandler) +{ + return ( FilteredDirectoryCopy(srcSpec->vRefNum, srcSpec->parID, srcSpec->name, + dstSpec->vRefNum, dstSpec->parID, dstSpec->name, + copyName, + copyBufferPtr, copyBufferSize, preflight, + copyErrHandler, NULL) ); +} + +/*****************************************************************************/ + diff --git a/src/mac/morefile/DirectoryCopy.h b/src/mac/morefile/DirectoryCopy.h new file mode 100644 index 0000000000..14637e31aa --- /dev/null +++ b/src/mac/morefile/DirectoryCopy.h @@ -0,0 +1,559 @@ +/* + File: DirectoryCopy.h + + Contains: A robust, general purpose directory copy routine. + + Version: Technology: MoreFiles + Release: 1.5.2 + + Copyright: © 1992-2001 by Apple Computer, Inc., all rights reserved. + + Bugs?: For bug reports, consult the following page on + the World Wide Web: + + http://developer.apple.com/bugreporter/ + +*/ + +/* + 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__ + +#ifndef __MACTYPES__ +#include +#endif + +#ifndef __FILES__ +#include +#endif + +#include "Optimization.h" + + +#if PRAGMA_ONCE +#pragma once +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if PRAGMA_IMPORT +#pragma import on +#endif + +#if PRAGMA_STRUCT_ALIGN + #pragma options align=mac68k +#elif PRAGMA_STRUCT_PACKPUSH + #pragma pack(push, 2) +#elif PRAGMA_STRUCT_PACK + #pragma pack(2) +#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 CALLBACK_API( Boolean , CopyErrProcPtr )(OSErr error, short failedOperation, short srcVRefNum, long srcDirID, ConstStr255Param srcName, short dstVRefNum, long dstDirID, ConstStr255Param dstName); +/* + 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 CALLBACK_API( Boolean , CopyFilterProcPtr )(const CInfoPBRec * cpbPtr); +/* + 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)) + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FilteredDirectoryCopy( + short srcVRefNum, + long srcDirID, + ConstStr255Param srcName, + short dstVRefNum, + long dstDirID, + ConstStr255Param dstName, + ConstStr255Param copyName, + void * copyBufferPtr, + long copyBufferSize, + Boolean preflight, + CopyErrProcPtr copyErrHandler, + CopyFilterProcPtr copyFilterProc); + + +/* + 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. + copyName input: Points to the new directory name if the directory + is to be renamed or nil if the directory 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 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpFilteredDirectoryCopy( + const FSSpec * srcSpec, + const FSSpec * dstSpec, + ConstStr255Param copyName, + void * copyBufferPtr, + long copyBufferSize, + Boolean preflight, + CopyErrProcPtr copyErrHandler, + CopyFilterProcPtr copyFilterProc); + + +/* + 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. + copyName input: Points to the new directory name if the directory + is to be renamed or nil if the directory 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 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +DirectoryCopy( + short srcVRefNum, + long srcDirID, + ConstStr255Param srcName, + short dstVRefNum, + long dstDirID, + ConstStr255Param dstName, + ConstStr255Param copyName, + void * copyBufferPtr, + long copyBufferSize, + Boolean preflight, + CopyErrProcPtr copyErrHandler); + + +/* + 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. + copyName input: Points to the new directory name if the directory + is to be renamed or nil if the directory 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 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpDirectoryCopy( + const FSSpec * srcSpec, + const FSSpec * dstSpec, + ConstStr255Param copyName, + void * copyBufferPtr, + long copyBufferSize, + Boolean preflight, + CopyErrProcPtr copyErrHandler); + + +/* + 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. + copyName input: Points to the new directory name if the directory + is to be renamed or nil if the directory 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 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 +*/ + +/*****************************************************************************/ + +#include "OptimizationEnd.h" + +#if PRAGMA_STRUCT_ALIGN + #pragma options align=reset +#elif PRAGMA_STRUCT_PACKPUSH + #pragma pack(pop) +#elif PRAGMA_STRUCT_PACK + #pragma pack() +#endif + +#ifdef PRAGMA_IMPORT_OFF +#pragma import off +#elif PRAGMA_IMPORT +#pragma import reset +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __DIRECTORYCOPY__ */ + diff --git a/src/mac/morefile/FSpCompa.cpp b/src/mac/morefile/FSpCompa.cpp deleted file mode 100644 index b6a538acb5..0000000000 --- a/src/mac/morefile/FSpCompa.cpp +++ /dev/null @@ -1,928 +0,0 @@ -/* -** 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 -#include -#include -#include -#include -#include - -#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; - } -} - -/*****************************************************************************/ diff --git a/src/mac/morefile/FSpCompa.h b/src/mac/morefile/FSpCompa.h deleted file mode 100644 index d808ad8b93..0000000000 --- a/src/mac/morefile/FSpCompa.h +++ /dev/null @@ -1,488 +0,0 @@ -/* -** 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 -#include - -#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__ */ - diff --git a/src/mac/morefile/FSpCompat.c b/src/mac/morefile/FSpCompat.c new file mode 100644 index 0000000000..17577684f6 --- /dev/null +++ b/src/mac/morefile/FSpCompat.c @@ -0,0 +1,946 @@ +/* + File: FSpCompat.c + + Contains: FSSpec compatibility functions. + + Version: MoreFiles + + Copyright: © 1992-2001 by 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. + + File Ownership: + + DRI: Apple Macintosh Developer Technical Support + + Other Contact: Apple Macintosh Developer Technical Support + + + Technology: DTS Sample Code + + Writers: + + (JL) Jim Luther + + Change History (most recent first): + + <2> 2/7/01 JL Added standard header. Updated names of includes. Updated + various routines to use new calling convention of the + MoreFilesExtras accessor functions. + <1> 12/06/99 JL MoreFiles 1.5. +*/ + +/* +** 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 +#include +#include +#include +#include +#include +#include + +#define __COMPILINGMOREFILES + +#include "MoreFilesExtras.h" +#include "FSpCompat.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 & kioFlAttribDirMask) != 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 & kioFlAttribDirMask) != 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; + } +} + +/*****************************************************************************/ diff --git a/src/mac/morefile/FSpCompat.h b/src/mac/morefile/FSpCompat.h new file mode 100644 index 0000000000..1014cb8e58 --- /dev/null +++ b/src/mac/morefile/FSpCompat.h @@ -0,0 +1,586 @@ +/* + File: FSpCompat.h + + Contains: FSSpec compatibility functions. + + Version: Technology: MoreFiles + Release: 1.5.2 + + Copyright: © 1992-2001 by Apple Computer, Inc., all rights reserved. + + Bugs?: For bug reports, consult the following page on + the World Wide Web: + + http://developer.apple.com/bugreporter/ + +*/ + +/* + 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__ + +#ifndef __MACTYPES__ +#include +#endif + +#ifndef __FILES__ +#include +#endif + +#include "Optimization.h" + + +#if PRAGMA_ONCE +#pragma once +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if PRAGMA_IMPORT +#pragma import on +#endif + +#if PRAGMA_STRUCT_ALIGN + #pragma options align=mac68k +#elif PRAGMA_STRUCT_PACKPUSH + #pragma pack(push, 2) +#elif PRAGMA_STRUCT_PACK + #pragma pack(2) +#endif + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSMakeFSSpecCompat( + short vRefNum, + long dirID, + ConstStr255Param fileName, + FSSpec * spec); + + +/* + 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) +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpOpenDFCompat( + const FSSpec * spec, + char permission, + short * refNum); + + +/* + 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpOpenRFCompat( + const FSSpec * spec, + char permission, + short * refNum); + + +/* + 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpCreateCompat( + const FSSpec * spec, + OSType creator, + OSType fileType, + ScriptCode scriptTag); + + +/* + 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpDirCreateCompat( + const FSSpec * spec, + ScriptCode scriptTag, + long * createdDirID); + + +/* + 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpDeleteCompat(const FSSpec * spec); + + +/* + 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpGetFInfoCompat( + const FSSpec * spec, + FInfo * fndrInfo); + + +/* + 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpSetFInfoCompat( + const FSSpec * spec, + const FInfo * fndrInfo); + + +/* + 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpSetFLockCompat(const FSSpec * spec); + + +/* + 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpRstFLockCompat(const FSSpec * spec); + + +/* + 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpRenameCompat( + const FSSpec * spec, + ConstStr255Param newName); + + +/* + 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpCatMoveCompat( + const FSSpec * source, + const FSSpec * dest); + + +/* + 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpExchangeFilesCompat( + const FSSpec * source, + const FSSpec * dest); + + +/* + 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( short ) +FSpOpenResFileCompat( + const FSSpec * spec, + SignedByte permission); + + +/* + 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( void ) +FSpCreateResFileCompat( + const FSSpec * spec, + OSType creator, + OSType fileType, + ScriptCode scriptTag); + + +/* + 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 +*/ + +/*****************************************************************************/ + +#include "OptimizationEnd.h" + +#if PRAGMA_STRUCT_ALIGN + #pragma options align=reset +#elif PRAGMA_STRUCT_PACKPUSH + #pragma pack(pop) +#elif PRAGMA_STRUCT_PACK + #pragma pack() +#endif + +#ifdef PRAGMA_IMPORT_OFF +#pragma import off +#elif PRAGMA_IMPORT +#pragma import reset +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __FSPCOMPAT__ */ + diff --git a/src/mac/morefile/FileCopy.c b/src/mac/morefile/FileCopy.c new file mode 100644 index 0000000000..4848613b51 --- /dev/null +++ b/src/mac/morefile/FileCopy.c @@ -0,0 +1,611 @@ +/* + File: FileCopy.c + + Contains: A robust, general purpose file copy routine. + + Version: MoreFiles + + Copyright: © 1992-2001 by 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. + + File Ownership: + + DRI: Apple Macintosh Developer Technical Support + + Other Contact: Apple Macintosh Developer Technical Support + + + Technology: DTS Sample Code + + Writers: + + (JL) Jim Luther + + Change History (most recent first): + + <2> 2/7/01 JL Added standard header. Updated names of includes. Updated + various routines to use new calling convention of the + MoreFilesExtras accessor functions. + <1> 12/06/99 JL MoreFiles 1.5. +*/ + +#include +#include +#include +#include +#include + +#define __COMPILINGMOREFILES + +#include "MoreFiles.h" +#include "MoreFilesExtras.h" +#include "MoreDesktopMgr.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 & kioFlAttribDirMask) != 0; + /* see if access priviledges are make changes, not see folder, and not see files (drop box) */ + *isDropBox = userHasDropBoxAccess(pb.dirInfo.ioACUser); + + 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 = U32SetU(U64ShiftRight(pb.xPB.ioVFreeBytes, 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) ); +} + +/*****************************************************************************/ + diff --git a/src/mac/morefile/FileCopy.cpp b/src/mac/morefile/FileCopy.cpp deleted file mode 100644 index acb9c92d11..0000000000 --- a/src/mac/morefile/FileCopy.cpp +++ /dev/null @@ -1,597 +0,0 @@ -/* -** 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 -#include -#include -#include -#include - -#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 ); -} - -/*****************************************************************************/ - -#if !TARGET_CARBON - -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); - dstFreeBlocks = pb.xPB.ioVFreeBytes >> 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 ); -} -#endif -/*****************************************************************************/ - -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) ); -} - -/*****************************************************************************/ - diff --git a/src/mac/morefile/FileCopy.h b/src/mac/morefile/FileCopy.h index 257a73315c..a855f1f96f 100644 --- a/src/mac/morefile/FileCopy.h +++ b/src/mac/morefile/FileCopy.h @@ -1,220 +1,271 @@ /* -** 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. + File: FileCopy.h + + Contains: A robust, general purpose file copy routine. + + Version: Technology: MoreFiles + Release: 1.5.2 + + Copyright: © 1992-2001 by Apple Computer, Inc., all rights reserved. + + Bugs?: For bug reports, consult the following page on + the World Wide Web: + + http://developer.apple.com/bugreporter/ + +*/ + +/* + 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 +#ifndef __MACTYPES__ +#include +#endif + +#ifndef __FILES__ #include +#endif -#include "optim.h" +#include "Optimization.h" + + +#if PRAGMA_ONCE +#pragma once +#endif #ifdef __cplusplus extern "C" { #endif +#if PRAGMA_IMPORT +#pragma import on +#endif + +#if PRAGMA_STRUCT_ALIGN + #pragma options align=mac68k +#elif PRAGMA_STRUCT_PACKPUSH + #pragma pack(push, 2) +#elif PRAGMA_STRUCT_PACK + #pragma pack(2) +#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 +EXTERN_API( OSErr ) +FileCopy( + short srcVRefNum, + long srcDirID, + ConstStr255Param srcName, + short dstVRefNum, + long dstDirID, + ConstStr255Param dstPathname, + ConstStr255Param copyName, + void * copyBufferPtr, + long copyBufferSize, + Boolean preflight); + + +/* + 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 +EXTERN_API( OSErr ) +FSpFileCopy( + const FSSpec * srcSpec, + const FSSpec * dstSpec, + ConstStr255Param copyName, + void * copyBufferPtr, + long copyBufferSize, + Boolean preflight); + + +/* + 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 */ /*****************************************************************************/ +#include "OptimizationEnd.h" + +#if PRAGMA_STRUCT_ALIGN + #pragma options align=reset +#elif PRAGMA_STRUCT_PACKPUSH + #pragma pack(pop) +#elif PRAGMA_STRUCT_PACK + #pragma pack() +#endif + +#ifdef PRAGMA_IMPORT_OFF +#pragma import off +#elif PRAGMA_IMPORT +#pragma import reset +#endif + #ifdef __cplusplus } #endif -#include "optimend.h" +#endif /* __FILECOPY__ */ -#endif /* __FILECOPY__ */ diff --git a/src/mac/morefile/FullPath.c b/src/mac/morefile/FullPath.c new file mode 100644 index 0000000000..32ccb9977b --- /dev/null +++ b/src/mac/morefile/FullPath.c @@ -0,0 +1,282 @@ +/* + File: FullPath.c + + Contains: Routines for dealing with full pathnames... if you really must. + + Version: MoreFiles + + Copyright: © 1995-2001 by 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. + + File Ownership: + + DRI: Apple Macintosh Developer Technical Support + + Other Contact: Apple Macintosh Developer Technical Support + + + Technology: DTS Sample Code + + Writers: + + (JL) Jim Luther + + Change History (most recent first): + + <2> 2/7/01 JL Added standard header. Updated names of includes. + <1> 12/06/99 JL MoreFiles 1.5. +*/ + +#include +#include +#include +#include +#include +#include + +#define __COMPILINGMOREFILES + +#include "FSpCompat.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 = result = noErr; + + /* work around Nav Services "bug" (it returns invalid FSSpecs with empty names) */ + if ( spec->name[0] == 0 ) + { + result = FSMakeFSSpecCompat(spec->vRefNum, spec->parID, spec->name, &tempSpec); + } + else + { + /* Make a copy of the input FSSpec that can be modified */ + BlockMoveData(spec, &tempSpec, sizeof(FSSpec)); + } + + if ( result == noErr ) + { + 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 & kioFlAttribDirMask) != 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 = GetHandleSize(*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); + + /* work around Alias Mgr sloppy volume matching bug */ + if ( spec->vRefNum == 0 ) + { + /* invalidate wrong FSSpec */ + spec->parID = 0; + spec->name[0] = 0; + result = nsvErr; + } + 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 ); +} + +/*****************************************************************************/ + diff --git a/src/mac/morefile/FullPath.cpp b/src/mac/morefile/FullPath.cpp deleted file mode 100644 index 7e54d6c5fa..0000000000 --- a/src/mac/morefile/FullPath.cpp +++ /dev/null @@ -1,250 +0,0 @@ -/* -** 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 -#include -#include -#include -#include -#include - -#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 */ -#if TARGET_CARBON - *fullPathLength = GetHandleSize(*fullPath); -#else - *fullPathLength = InlineGetHandleSize(*fullPath); -#endif - 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 ); -} - -/*****************************************************************************/ - diff --git a/src/mac/morefile/FullPath.h b/src/mac/morefile/FullPath.h index cf18a9741c..e1710c12bc 100644 --- a/src/mac/morefile/FullPath.h +++ b/src/mac/morefile/FullPath.h @@ -1,243 +1,311 @@ /* -** 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. + File: FullPath.h + + Contains: Routines for dealing with full pathnames... if you really must. + + Version: Technology: MoreFiles + Release: 1.5.2 + + Copyright: © 1995-2001 by Apple Computer, Inc., all rights reserved. + + Bugs?: For bug reports, consult the following page on + the World Wide Web: + + http://developer.apple.com/bugreporter/ + +*/ + +/* + 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. +*/ + +/* + 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. */ #ifndef __FULLPATH__ #define __FULLPATH__ -#include +#ifndef __MACTYPES__ +#include +#endif + +#ifndef __FILES__ #include +#endif -#include "optim.h" +#include "Optimization.h" + + +#if PRAGMA_ONCE +#pragma once +#endif #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. -*/ +#if PRAGMA_IMPORT +#pragma import on +#endif + +#if PRAGMA_STRUCT_ALIGN + #pragma options align=mac68k +#elif PRAGMA_STRUCT_PACKPUSH + #pragma pack(push, 2) +#elif PRAGMA_STRUCT_PACK + #pragma pack(2) +#endif /*****************************************************************************/ -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 +EXTERN_API( OSErr ) +GetFullPath( + short vRefNum, + long dirID, + ConstStr255Param name, + short * fullPathLength, + Handle * fullPath); + + +/* + 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 +EXTERN_API( OSErr ) +FSpGetFullPath( + const FSSpec * spec, + short * fullPathLength, + Handle * fullPath); + + +/* + 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. + + IMPORTANT: The definition of a FSSpec is a volume reference number (not a + drive number, working directory number, or 0), a parent directory ID (not 0), + and the name of a file or folder (not an empty name, a full pathname, or + a partial pathname containing one or more colon (:) characters). + FSpGetFullPath assumes it is getting a FSSpec that matches the rules. + If you have an FSSpec record that wasn't created by FSMakeFSSpec (or + FSMakeFSSpecCompat from FSpCompat in MoreFiles which correctly builds + FSSpecs), you should call GetFullPath instead of FSpGetFullPath. + + 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 +EXTERN_API( OSErr ) +FSpLocationFromFullPath( + short fullPathLength, + const void * fullPath, + FSSpec * spec); + + +/* + 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 +EXTERN_API( OSErr ) +LocationFromFullPath( + short fullPathLength, + const void * fullPath, + short * vRefNum, + long * parID, + Str31 name); + + +/* + 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 */ /*****************************************************************************/ +#include "OptimizationEnd.h" + +#if PRAGMA_STRUCT_ALIGN + #pragma options align=reset +#elif PRAGMA_STRUCT_PACKPUSH + #pragma pack(pop) +#elif PRAGMA_STRUCT_PACK + #pragma pack() +#endif + +#ifdef PRAGMA_IMPORT_OFF +#pragma import off +#elif PRAGMA_IMPORT +#pragma import reset +#endif + #ifdef __cplusplus } #endif -#include "optimend.h" +#endif /* __FULLPATH__ */ -#endif /* __FULLPATH__ */ \ No newline at end of file diff --git a/src/mac/morefile/IterateD.cpp b/src/mac/morefile/IterateD.cpp deleted file mode 100644 index 4786b80c01..0000000000 --- a/src/mac/morefile/IterateD.cpp +++ /dev/null @@ -1,199 +0,0 @@ -/* -** 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 -#include -#include - -#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_STRUCT_ALIGN - #pragma options align=mac68k -#elif PRAGMA_STRUCT_PACKPUSH - #pragma pack(push, 2) -#elif PRAGMA_STRUCT_PACK - #pragma pack(2) -#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_STRUCT_ALIGN - #pragma options align=reset -#elif PRAGMA_STRUCT_PACKPUSH - #pragma pack(pop) -#elif PRAGMA_STRUCT_PACK - #pragma pack() -#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) ); -} - -/*****************************************************************************/ diff --git a/src/mac/morefile/IterateD.h b/src/mac/morefile/IterateD.h deleted file mode 100644 index 46fafb9fe1..0000000000 --- a/src/mac/morefile/IterateD.h +++ /dev/null @@ -1,171 +0,0 @@ -/* -** 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 -#include - -#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__ */ diff --git a/src/mac/morefile/IterateDirectory.c b/src/mac/morefile/IterateDirectory.c new file mode 100644 index 0000000000..e748829ff5 --- /dev/null +++ b/src/mac/morefile/IterateDirectory.c @@ -0,0 +1,207 @@ +/* + File: IterateDirectory.c + + Contains: File Manager directory iterator routines. + + Version: MoreFiles + + Copyright: © 1995-2001 by 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. 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. + + File Ownership: + + DRI: Apple Macintosh Developer Technical Support + + Other Contact: Apple Macintosh Developer Technical Support + + + Technology: DTS Sample Code + + Writers: + + (JL) Jim Luther + + Change History (most recent first): + + <2> 2/7/01 JL Added standard header. Updated names of includes. + <1> 12/06/99 JL MoreFiles 1.5. +*/ + +#include +#include +#include + +#define __COMPILINGMOREFILES + +#include "MoreFilesExtras.h" +#include "IterateDirectory.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_STRUCT_ALIGN +#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_STRUCT_ALIGN +#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 & kioFlAttribDirMask) != 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) ); +} + +/*****************************************************************************/ diff --git a/src/mac/morefile/IterateDirectory.h b/src/mac/morefile/IterateDirectory.h new file mode 100644 index 0000000000..ef6b113eea --- /dev/null +++ b/src/mac/morefile/IterateDirectory.h @@ -0,0 +1,222 @@ +/* + File: IterateDirectory.h + + Contains: File Manager directory iterator routines. + + Version: Technology: MoreFiles + Release: 1.5.2 + + Copyright: © 1995-2001 by Jim Luther and Apple Computer, Inc., all rights reserved. + + Bugs?: For bug reports, consult the following page on + the World Wide Web: + + http://developer.apple.com/bugreporter/ + +*/ + +/* + 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 __ITERATEDIRECTORY__ +#define __ITERATEDIRECTORY__ + +#ifndef __MACTYPES__ +#include +#endif + +#ifndef __FILES__ +#include +#endif + +#include "Optimization.h" + + +#if PRAGMA_ONCE +#pragma once +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if PRAGMA_IMPORT +#pragma import on +#endif + +#if PRAGMA_STRUCT_ALIGN + #pragma options align=mac68k +#elif PRAGMA_STRUCT_PACKPUSH + #pragma pack(push, 2) +#elif PRAGMA_STRUCT_PACK + #pragma pack(2) +#endif + +/*****************************************************************************/ + +typedef CALLBACK_API( void , IterateFilterProcPtr )(const CInfoPBRec *cpbPtr, Boolean *quitFlag, void *yourDataPtr); +/* + 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)) + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +IterateDirectory( + short vRefNum, + long dirID, + ConstStr255Param name, + unsigned short maxLevels, + IterateFilterProcPtr iterateFilter, + void * yourDataPtr); + + +/* + 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpIterateDirectory( + const FSSpec * spec, + unsigned short maxLevels, + IterateFilterProcPtr iterateFilter, + void * yourDataPtr); + + +/* + 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 +*/ + +/*****************************************************************************/ + +#include "OptimizationEnd.h" + +#if PRAGMA_STRUCT_ALIGN + #pragma options align=reset +#elif PRAGMA_STRUCT_PACKPUSH + #pragma pack(pop) +#elif PRAGMA_STRUCT_PACK + #pragma pack() +#endif + +#ifdef PRAGMA_IMPORT_OFF +#pragma import off +#elif PRAGMA_IMPORT +#pragma import reset +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __ITERATEDIRECTORY__ */ + diff --git a/src/mac/morefile/MoreDesk.cpp b/src/mac/morefile/MoreDesk.cpp deleted file mode 100644 index 5c74005ffd..0000000000 --- a/src/mac/morefile/MoreDesk.cpp +++ /dev/null @@ -1,1270 +0,0 @@ -/* -** 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.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 -#include -#include -#include -#include -#include - -#define __COMPILINGMOREFILES - -#include "morefile.h" -#include "moreextr.h" -#include "mfsearch.h" -#include "moredesk.h" - -/*****************************************************************************/ - -/* Desktop file notes: -** -** ¥ The Desktop file is owned by the Finder and is normally open by the -** Finder. That means that we only have read-only access to the Desktop -** file. -** ¥ Since the Resource Manager doesn't support shared access to resource -** files and we're using read-only access, we don't ever leave the -** Desktop file open. We open a path to it, get the data we want out -** of it, and then close the open path. This is the only safe way to -** open a resource file with read-only access since some other program -** could have it open with write access. -** ¥ The bundle related resources in the Desktop file are normally -** purgable, so when we're looking through them, we don't bother to -** release resources we're done looking at - closing the resource file -** (which we always do) will release them. -** ¥ Since we can't assume the Desktop file is named "Desktop" -** (it probably is everywhere but France), we get the Desktop -** file's name by searching the volume's root directory for a file -** with fileType == 'FNDR' and creator == 'ERIK'. The only problem with -** this scheme is that someone could create another file with that type -** and creator in the root directory and we'd find the wrong file. -** The chances of this are very slim. -*/ - -/*****************************************************************************/ - -/* local defines */ - -enum -{ - kBNDLResType = 'BNDL', - kFREFResType = 'FREF', - kIconFamResType = 'ICN#', - kFCMTResType = 'FCMT', - kAPPLResType = 'APPL' -}; - -/*****************************************************************************/ - -/* local data structures */ - -#if PRAGMA_STRUCT_ALIGN - #pragma options align=mac68k -#elif PRAGMA_STRUCT_PACKPUSH - #pragma pack(push, 2) -#elif PRAGMA_STRUCT_PACK - #pragma pack(2) -#endif - -struct IDRec -{ - short localID; - short rsrcID; -}; -typedef struct IDRec IDRec; -typedef IDRec *IDRecPtr; - -struct BundleType -{ - OSType type; /* 'ICN#' or 'FREF' */ - short count; /* number of IDRecs - 1 */ - IDRec idArray[1]; -}; -typedef struct BundleType BundleType; -typedef BundleType *BundleTypePtr; - -struct BNDLRec -{ - OSType signature; /* creator type signature */ - short versionID; /* version - should always be 0 */ - short numTypes; /* number of elements in typeArray - 1 */ - BundleType typeArray[1]; -}; -typedef struct BNDLRec BNDLRec; -typedef BNDLRec **BNDLRecHandle; - -struct FREFRec -{ - OSType fileType; /* file type */ - short iconID; /* icon local ID */ - Str255 fileName; /* file name */ -}; -typedef struct FREFRec FREFRec; -typedef FREFRec **FREFRecHandle; - -struct APPLRec -{ - OSType creator; /* creator type signature */ - long parID; /* parent directory ID */ - Str255 applName; /* application name */ -}; -typedef struct APPLRec APPLRec; -typedef APPLRec *APPLRecPtr; - -#if PRAGMA_STRUCT_ALIGN - #pragma options align=reset -#elif PRAGMA_STRUCT_PACKPUSH - #pragma pack(pop) -#elif PRAGMA_STRUCT_PACK - #pragma pack() -#endif - -/*****************************************************************************/ - -/* static prototypes */ - -static OSErr GetDesktopFileName(short vRefNum, - Str255 desktopName); - -static OSErr GetAPPLFromDesktopFile(ConstStr255Param volName, - short vRefNum, - OSType creator, - short *applVRefNum, - long *applParID, - Str255 applName); - -static OSErr FindBundleGivenCreator(OSType creator, - BNDLRecHandle *returnBndl); - -static OSErr FindTypeInBundle(OSType typeToFind, - BNDLRecHandle theBndl, - BundleTypePtr *returnBundleType); - -static OSErr GetLocalIDFromFREF(BundleTypePtr theBundleType, - OSType fileType, - short *iconLocalID); - -static OSErr GetIconRsrcIDFromLocalID(BundleTypePtr theBundleType, - short iconLocalID, - short *iconRsrcID); - -static OSType DTIconToResIcon(short iconType); - -static OSErr GetIconFromDesktopFile(ConstStr255Param volName, - short vRefNum, - short iconType, - OSType fileCreator, - OSType fileType, - Handle *iconHandle); - -static OSErr GetCommentID(short vRefNum, - long dirID, - ConstStr255Param name, - short *commentID); - -static OSErr GetCommentFromDesktopFile(short vRefNum, - long dirID, - ConstStr255Param name, - Str255 comment); - -/*****************************************************************************/ - -/* -** GetDesktopFileName -** -** Get the name of the Desktop file. -*/ -static OSErr GetDesktopFileName(short vRefNum, - Str255 desktopName) -{ - OSErr error; - HParamBlockRec pb; - short index; - Boolean found; - - pb.fileParam.ioNamePtr = desktopName; - pb.fileParam.ioVRefNum = vRefNum; - pb.fileParam.ioFVersNum = 0; - index = 1; - found = false; - do - { - pb.fileParam.ioDirID = fsRtDirID; - pb.fileParam.ioFDirIndex = index; - error = PBHGetFInfoSync(&pb); - if ( error == noErr ) - { - if ( (pb.fileParam.ioFlFndrInfo.fdType == 'FNDR') && - (pb.fileParam.ioFlFndrInfo.fdCreator == 'ERIK') ) - { - found = true; - } - } - ++index; - } while ( (error == noErr) && !found ); - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr DTOpen(ConstStr255Param volName, - short vRefNum, - short *dtRefNum, - Boolean *newDTDatabase) -{ - OSErr error; - GetVolParmsInfoBuffer volParmsInfo; - long infoSize; - DTPBRec pb; - - /* Check for volume Desktop Manager support before calling */ - infoSize = sizeof(GetVolParmsInfoBuffer); - error = HGetVolParms(volName, vRefNum, &volParmsInfo, &infoSize); - if ( error == noErr ) - { - if ( hasDesktopMgr(volParmsInfo) ) - { - pb.ioNamePtr = (StringPtr)volName; - pb.ioVRefNum = vRefNum; - error = PBDTOpenInform(&pb); - /* PBDTOpenInform informs us if the desktop was just created */ - /* by leaving the low bit of ioTagInfo clear (0) */ - *newDTDatabase = ((pb.ioTagInfo & 1L) == 0); - if ( error == paramErr ) - { - error = PBDTGetPath(&pb); - /* PBDTGetPath doesn't tell us if the database is new */ - /* so assume it is not new */ - *newDTDatabase = false; - } - *dtRefNum = pb.ioDTRefNum; - } - else - { - error = paramErr; - } - } - return ( error ); -} - -/*****************************************************************************/ - -/* -** GetAPPLFromDesktopFile -** -** Get a application's location from the -** Desktop file's 'APPL' resources. -*/ -static OSErr GetAPPLFromDesktopFile(ConstStr255Param volName, - short vRefNum, - OSType creator, - short *applVRefNum, - long *applParID, - Str255 applName) -{ - OSErr error; - short realVRefNum; - Str255 desktopName; - short savedResFile; - short dfRefNum; - Handle applResHandle; - Boolean foundCreator; - Ptr applPtr; - long applSize; - - error = DetermineVRefNum(volName, vRefNum, &realVRefNum); - if ( error == noErr ) - { - error = GetDesktopFileName(realVRefNum, desktopName); - if ( error == noErr ) - { - savedResFile = CurResFile(); - /* - ** Open the 'Desktop' file in the root directory. (because - ** opening the resource file could preload unwanted resources, - ** bracket the call with SetResLoad(s)) - */ - SetResLoad(false); - dfRefNum = HOpenResFile(realVRefNum, fsRtDirID, desktopName, fsRdPerm); - SetResLoad(true); - - if ( dfRefNum != -1) - { - /* Get 'APPL' resource ID 0 */ - applResHandle = Get1Resource(kAPPLResType, 0); - if ( applResHandle != NULL ) - { -#if !TARGET_CARBON - applSize = InlineGetHandleSize((Handle)applResHandle); -#else - applSize = GetHandleSize((Handle)applResHandle); -#endif - if ( applSize != 0 ) /* make sure the APPL resource isn't empty */ - { - foundCreator = false; - applPtr = *applResHandle; - - /* APPL's don't have a count so I have to use the size as the bounds */ - while ( (foundCreator == false) && - (applPtr < (*applResHandle + applSize)) ) - { - if ( ((APPLRecPtr)applPtr)->creator == creator ) - { - foundCreator = true; - } - else - { - /* fun with pointer math... */ - applPtr += sizeof(OSType) + - sizeof(long) + - ((APPLRecPtr)applPtr)->applName[0] + 1; - /* application mappings are word aligned within the resource */ - if ( ((unsigned long)applPtr % 2) != 0 ) - { - applPtr += 1; - } - } - } - if ( foundCreator == true ) - { - *applVRefNum = realVRefNum; - *applParID = ((APPLRecPtr)applPtr)->parID; - BlockMoveData(((APPLRecPtr)applPtr)->applName, - applName, - ((APPLRecPtr)applPtr)->applName[0] + 1); - /* error is already noErr */ - } - else - { - error = afpItemNotFound; /* didn't find a creator match */ - } - } - else - { - error = afpItemNotFound; /* no APPL mapping available */ - } - } - else - { - error = afpItemNotFound; /* no APPL mapping available */ - } - - /* restore the resource chain and close the Desktop file */ - UseResFile(savedResFile); - CloseResFile(dfRefNum); - } - else - { - error = afpItemNotFound; - } - } - } - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr DTXGetAPPL(ConstStr255Param volName, - short vRefNum, - OSType creator, - Boolean searchCatalog, - short *applVRefNum, - long *applParID, - Str255 applName) -{ - OSErr error; - UniversalFMPB pb; - short dtRefNum; - Boolean newDTDatabase; - short realVRefNum; - short index; - Boolean applFound; - FSSpec spec; - long actMatchCount; - - /* get the real vRefNum */ - error = DetermineVRefNum(volName, vRefNum, &realVRefNum); - if ( error == noErr ) - { - error = DTOpen(volName, vRefNum, &dtRefNum, &newDTDatabase); - if ( error == noErr ) - { - if ( !newDTDatabase ) - { - index = 0; - applFound = false; - do - { - pb.dtPB.ioNamePtr = applName; - pb.dtPB.ioDTRefNum = dtRefNum; - pb.dtPB.ioIndex = index; - pb.dtPB.ioFileCreator = creator; - error = PBDTGetAPPLSync(&pb.dtPB); - if ( error == noErr ) - { - /* got a match - see if it is valid */ - - *applVRefNum = realVRefNum; /* get the vRefNum now */ - *applParID = pb.dtPB.ioAPPLParID; /* get the parent ID now */ - - /* pb.hPB.fileParam.ioNamePtr is already set */ - pb.hPB.fileParam.ioVRefNum = realVRefNum; - pb.hPB.fileParam.ioFVersNum = 0; - pb.hPB.fileParam.ioDirID = *applParID; - pb.hPB.fileParam.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ - if ( PBHGetFInfoSync(&pb.hPB) == noErr ) - { - if ( (pb.hPB.fileParam.ioFlFndrInfo.fdCreator == creator) && - (pb.hPB.fileParam.ioFlFndrInfo.fdType == 'APPL') ) - { - applFound = true; - } - } - } - ++index; - } while ( (error == noErr) && !applFound ); - if ( error != noErr ) - { - error = afpItemNotFound; - } - } - else - { - /* Desktop database is empty (new), set error to try CatSearch */ - error = afpItemNotFound; - } - } - /* acceptable errors from Desktop Manager to continue are paramErr or afpItemNotFound */ - if ( error == paramErr ) - { - /* if paramErr, the volume didn't support the Desktop Manager */ - /* try the Desktop file */ - - error = GetAPPLFromDesktopFile(volName, vRefNum, creator, - applVRefNum, applParID, applName); - if ( error == noErr ) - { - /* got a match - see if it is valid */ - - pb.hPB.fileParam.ioNamePtr = applName; - pb.hPB.fileParam.ioVRefNum = *applVRefNum; - pb.hPB.fileParam.ioFVersNum = 0; - pb.hPB.fileParam.ioDirID = *applParID; - pb.hPB.fileParam.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ - if ( PBHGetFInfoSync(&pb.hPB) == noErr ) - { - if ( (pb.hPB.fileParam.ioFlFndrInfo.fdCreator != creator) || - (pb.hPB.fileParam.ioFlFndrInfo.fdType != 'APPL') ) - { - error = afpItemNotFound; - } - } - else if ( error == fnfErr ) - { - error = afpItemNotFound; - } - } - } - /* acceptable error from DesktopFile code to continue is afpItemNotFound */ - if ( (error == afpItemNotFound) && searchCatalog) - { - /* Couldn't be found in the Desktop file either, */ - /* try searching with CatSearch if requested */ - - error = CreatorTypeFileSearch(NULL, realVRefNum, creator, kAPPLResType, &spec, 1, - &actMatchCount, true); - if ( (error == noErr) || (error == eofErr) ) - { - if ( actMatchCount > 0 ) - { - *applVRefNum = spec.vRefNum; - *applParID = spec.parID; - BlockMoveData(spec.name, applName, spec.name[0] + 1); - } - else - { - error = afpItemNotFound; - } - } - } - } - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr FSpDTXGetAPPL(ConstStr255Param volName, - short vRefNum, - OSType creator, - Boolean searchCatalog, - FSSpec *spec) -{ - return ( DTXGetAPPL(volName, vRefNum, creator, searchCatalog, - &(spec->vRefNum), &(spec->parID), spec->name) ); -} - -/*****************************************************************************/ - -pascal OSErr DTGetAPPL(ConstStr255Param volName, - short vRefNum, - OSType creator, - short *applVRefNum, - long *applParID, - Str255 applName) -{ - /* Call DTXGetAPPL with the "searchCatalog" parameter true */ - return ( DTXGetAPPL(volName, vRefNum, creator, true, - applVRefNum, applParID, applName) ); -} - -/*****************************************************************************/ - -pascal OSErr FSpDTGetAPPL(ConstStr255Param volName, - short vRefNum, - OSType creator, - FSSpec *spec) -{ - /* Call DTXGetAPPL with the "searchCatalog" parameter true */ - return ( DTXGetAPPL(volName, vRefNum, creator, true, - &(spec->vRefNum), &(spec->parID), spec->name) ); -} - -/*****************************************************************************/ - -/* -** FindBundleGivenCreator -** -** Search the current resource file for the 'BNDL' resource with the given -** creator and return a handle to it. -*/ -static OSErr FindBundleGivenCreator(OSType creator, - BNDLRecHandle *returnBndl) -{ - OSErr error; - short numOfBundles; - short index; - BNDLRecHandle theBndl; - - error = afpItemNotFound; /* default to not found */ - - /* Search each BNDL resource until we find the one with a matching creator. */ - - numOfBundles = Count1Resources(kBNDLResType); - index = 1; - *returnBndl = NULL; - - while ( (index <= numOfBundles) && (*returnBndl == NULL) ) - { - theBndl = (BNDLRecHandle)Get1IndResource(kBNDLResType, index); - - if ( theBndl != NULL ) - { - if ( (*theBndl)->signature == creator ) - { - /* numTypes and typeArray->count will always be the actual count minus 1, */ - /* so 0 in both fields is valid. */ - if ( ((*theBndl)->numTypes >= 0) && ((*theBndl)->typeArray->count >= 0) ) - { - /* got it */ - *returnBndl = theBndl; - error = noErr; - } - } - } - - index ++; - } - - return ( error ); -} - -/*****************************************************************************/ - -/* -** FindTypeInBundle -** -** Given a Handle to a BNDL return a pointer to the desired type -** in it. If the type is not found, or if the type's count < 0, -** return afpItemNotFound. -*/ -static OSErr FindTypeInBundle(OSType typeToFind, - BNDLRecHandle theBndl, - BundleTypePtr *returnBundleType) -{ - OSErr error; - short index; - Ptr ptrIterator; /* use a Ptr so we can do ugly pointer math */ - - error = afpItemNotFound; /* default to not found */ - - ptrIterator = (Ptr)((*theBndl)->typeArray); - index = 0; - *returnBundleType = NULL; - - while ( (index < ((*theBndl)->numTypes + 1)) && - (*returnBundleType == NULL) ) - { - if ( (((BundleTypePtr)ptrIterator)->type == typeToFind) && - (((BundleTypePtr)ptrIterator)->count >= 0) ) - { - *returnBundleType = (BundleTypePtr)ptrIterator; - error = noErr; - } - else - { - ptrIterator += ( sizeof(OSType) + - sizeof(short) + - ( sizeof(IDRec) * (((BundleTypePtr)ptrIterator)->count + 1) ) ); - ++index; - } - } - - return ( error ); -} - -/*****************************************************************************/ - -/* -** GetLocalIDFromFREF -** -** Given a pointer to a 'FREF' BundleType record, load each 'FREF' resource -** looking for a matching fileType. If a matching fileType is found, return -** its icon local ID. If no match is found, return afpItemNotFound as the -** function result. -*/ -static OSErr GetLocalIDFromFREF(BundleTypePtr theBundleType, - OSType fileType, - short *iconLocalID) -{ - OSErr error; - short index; - IDRecPtr idIterator; - FREFRecHandle theFref; - - error = afpItemNotFound; /* default to not found */ - - /* For each localID in this type, get the FREF resource looking for fileType */ - index = 0; - idIterator = &theBundleType->idArray[0]; - *iconLocalID = 0; - - while ( (index <= theBundleType->count) && (*iconLocalID == 0) ) - { - theFref = (FREFRecHandle)Get1Resource(kFREFResType, idIterator->rsrcID); - if ( theFref != NULL ) - { - if ( (*theFref)->fileType == fileType ) - { - *iconLocalID = (*theFref)->iconID; - error = noErr; - } - } - - ++idIterator; - ++index; - } - - return ( error ); -} - -/*****************************************************************************/ - -/* -** GetIconRsrcIDFromLocalID -** -** Given a pointer to a 'ICN#' BundleType record, look for the IDRec with -** the localID that matches iconLocalID. If a matching IDRec is found, -** return the IDRec's rsrcID field value. If no match is found, return -** afpItemNotFound as the function result. -*/ -static OSErr GetIconRsrcIDFromLocalID(BundleTypePtr theBundleType, - short iconLocalID, - short *iconRsrcID) -{ - OSErr error; - short index; - IDRecPtr idIterator; - - error = afpItemNotFound; /* default to not found */ - - /* Find the rsrcID of the icon family type, given the localID */ - index = 0; - idIterator = &theBundleType->idArray[0]; - *iconRsrcID = 0; - - while ( (index <= theBundleType->count) && (*iconRsrcID == 0) ) - { - if ( idIterator->localID == iconLocalID ) - { - *iconRsrcID = idIterator->rsrcID; - error = noErr; - } - - idIterator ++; - index ++; - } - - return ( error ); -} - -/*****************************************************************************/ - -/* -** DTIconToResIcon -** -** Map a Desktop Manager icon type to the corresponding resource type. -** Return (OSType)0 if there is no corresponding resource type. -*/ -static OSType DTIconToResIcon(short iconType) -{ - OSType resType; - - switch ( iconType ) - { - case kLargeIcon: - resType = large1BitMask; - break; - case kLarge4BitIcon: - resType = large4BitData; - break; - case kLarge8BitIcon: - resType = large8BitData; - break; - case kSmallIcon: - resType = small1BitMask; - break; - case kSmall4BitIcon: - resType = small4BitData; - break; - case kSmall8BitIcon: - resType = small8BitData; - break; - default: - resType = (OSType)0; - break; - } - - return ( resType ); -} - -/*****************************************************************************/ - -/* -** GetIconFromDesktopFile -** -** INPUT a pointer to a non-existent Handle, because we'll allocate one -** -** search each BNDL resource for the right fileCreator and once we get it -** find the 'FREF' type in BNDL -** for each localID in the type, open the FREF resource -** if the FREF is the desired fileType -** get its icon localID -** get the ICN# type in BNDL -** get the icon resource number from the icon localID -** get the icon resource type from the desktop mgr's iconType -** get the icon of that type and number -*/ -static OSErr GetIconFromDesktopFile(ConstStr255Param volName, - short vRefNum, - short iconType, - OSType fileCreator, - OSType fileType, - Handle *iconHandle) -{ - OSErr error; - short realVRefNum; - Str255 desktopName; - short savedResFile; - short dfRefNum; - BNDLRecHandle theBndl = NULL; - BundleTypePtr theBundleType; - short iconLocalID; - short iconRsrcID; - OSType iconRsrcType; - Handle returnIconHandle; - char bndlState; - - *iconHandle = NULL; - - error = DetermineVRefNum(volName, vRefNum, &realVRefNum); - if ( error == noErr ) - { - error = GetDesktopFileName(realVRefNum, desktopName); - if ( error == noErr ) - { - savedResFile = CurResFile(); - - /* - ** Open the 'Desktop' file in the root directory. (because - ** opening the resource file could preload unwanted resources, - ** bracket the call with SetResLoad(s)) - */ - SetResLoad(false); - dfRefNum = HOpenResFile(realVRefNum, fsRtDirID, desktopName, fsRdPerm); - SetResLoad(true); - - if ( dfRefNum != -1 ) - { - /* - ** Find the BNDL resource with the specified creator. - */ - error = FindBundleGivenCreator(fileCreator, &theBndl); - if ( error == noErr ) - { - /* Lock the BNDL resource so it won't be purged when other resources are loaded */ - bndlState = HGetState((Handle)theBndl); - HLock((Handle)theBndl); - - /* Find the 'FREF' BundleType record in the BNDL resource. */ - error = FindTypeInBundle(kFREFResType, theBndl, &theBundleType); - if ( error == noErr ) - { - /* Find the local ID in the 'FREF' resource with the specified fileType */ - error = GetLocalIDFromFREF(theBundleType, fileType, &iconLocalID); - if ( error == noErr ) - { - /* Find the 'ICN#' BundleType record in the BNDL resource. */ - error = FindTypeInBundle(kIconFamResType, theBndl, &theBundleType); - if ( error == noErr ) - { - /* Find the icon's resource ID in the 'ICN#' BundleType record */ - error = GetIconRsrcIDFromLocalID(theBundleType, iconLocalID, &iconRsrcID); - if ( error == noErr ) - { - /* Map Desktop Manager icon type to resource type */ - iconRsrcType = DTIconToResIcon(iconType); - - if ( iconRsrcType != (OSType)0 ) - { - /* Load the icon */ - returnIconHandle = Get1Resource(iconRsrcType, iconRsrcID); - if ( returnIconHandle != NULL ) - { - /* Copy the resource handle, and return the copy */ - HandToHand(&returnIconHandle); - if ( MemError() == noErr ) - { - *iconHandle = returnIconHandle; - } - else - { - error = afpItemNotFound; - } - } - else - { - error = afpItemNotFound; - } - } - } - } - } - } - /* Restore the state of the BNDL resource */ - HSetState((Handle)theBndl, bndlState); - } - /* Restore the resource chain and close the Desktop file */ - UseResFile(savedResFile); - CloseResFile(dfRefNum); - } - else - { - error = ResError(); /* could not open Desktop file */ - } - } - if ( (error != noErr) && (error != memFullErr) ) - { - error = afpItemNotFound; /* force an error we should return */ - } - } - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr DTGetIcon(ConstStr255Param volName, - short vRefNum, - short iconType, - OSType fileCreator, - OSType fileType, - Handle *iconHandle) -{ - OSErr error; - DTPBRec pb; - short dtRefNum; - Boolean newDTDatabase; - Size bufferSize; - - *iconHandle = NULL; - error = DTOpen(volName, vRefNum, &dtRefNum, &newDTDatabase); - if ( error == noErr ) - { - /* there was a desktop database and it's now open */ - - if ( !newDTDatabase ) /* don't bother to look in a new (empty) database */ - { - /* get the buffer size for the requested icon type */ - switch ( iconType ) - { - case kLargeIcon: - bufferSize = kLargeIconSize; - break; - case kLarge4BitIcon: - bufferSize = kLarge4BitIconSize; - break; - case kLarge8BitIcon: - bufferSize = kLarge8BitIconSize; - break; - case kSmallIcon: - bufferSize = kSmallIconSize; - break; - case kSmall4BitIcon: - bufferSize = kSmall4BitIconSize; - break; - case kSmall8BitIcon: - bufferSize = kSmall8BitIconSize; - break; - default: - iconType = 0; - bufferSize = 0; - break; - } - if ( bufferSize != 0 ) - { - *iconHandle = NewHandle(bufferSize); - if ( *iconHandle != NULL ) - { - HLock(*iconHandle); - - pb.ioDTRefNum = dtRefNum; - pb.ioTagInfo = 0; - pb.ioDTBuffer = **iconHandle; - pb.ioDTReqCount = bufferSize; - pb.ioIconType = iconType; - pb.ioFileCreator = fileCreator; - pb.ioFileType = fileType; - error = PBDTGetIconSync(&pb); - - HUnlock(*iconHandle); - - if ( error != noErr ) - { - DisposeHandle(*iconHandle); /* dispose of the allocated memory */ - *iconHandle = NULL; - } - } - else - { - error = memFullErr; /* handle could not be allocated */ - } - } - else - { - error = paramErr; /* unknown icon type requested */ - } - } - else - { - error = afpItemNotFound; /* the desktop database was empty - nothing to return */ - } - } - else - { - /* There is no desktop database - try the Desktop file */ - - error = GetIconFromDesktopFile(volName, vRefNum, iconType, - fileCreator, fileType, iconHandle); - } - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr DTSetComment(short vRefNum, - long dirID, - ConstStr255Param name, - ConstStr255Param comment) -{ - DTPBRec pb; - OSErr error; - short dtRefNum; - Boolean newDTDatabase; - - error = DTOpen(name, vRefNum, &dtRefNum, &newDTDatabase); - if ( error == noErr ) - { - pb.ioDTRefNum = dtRefNum; - pb.ioNamePtr = (StringPtr)name; - pb.ioDirID = dirID; - pb.ioDTBuffer = (Ptr)&comment[1]; - /* Truncate the comment to 200 characters just in case */ - /* some file system doesn't range check */ - if ( comment[0] <= 200 ) - { - pb.ioDTReqCount = comment[0]; - } - else - { - pb.ioDTReqCount = 200; - } - error = PBDTSetCommentSync(&pb); - } - return (error); -} - -/*****************************************************************************/ - -pascal OSErr FSpDTSetComment(const FSSpec *spec, - ConstStr255Param comment) -{ - return (DTSetComment(spec->vRefNum, spec->parID, spec->name, comment)); -} - -/*****************************************************************************/ - -/* -** GetCommentID -** -** Get the comment ID number for the Desktop file's 'FCMT' resource ID from -** the file or folders fdComment (frComment) field. -*/ -static OSErr GetCommentID(short vRefNum, - long dirID, - ConstStr255Param name, - short *commentID) -{ - CInfoPBRec pb; - OSErr error; - - error = GetCatInfoNoName(vRefNum, dirID, name, &pb); - *commentID = pb.hFileInfo.ioFlXFndrInfo.fdComment; - return ( error ); -} - -/*****************************************************************************/ - -/* -** GetCommentFromDesktopFile -** -** Get a file or directory's Finder comment field (if any) from the -** Desktop file's 'FCMT' resources. -*/ -static OSErr GetCommentFromDesktopFile(short vRefNum, - long dirID, - ConstStr255Param name, - Str255 comment) -{ - OSErr error; - short commentID; - short realVRefNum; - Str255 desktopName; - short savedResFile; - short dfRefNum; - StringHandle commentHandle; - - /* Get the comment ID number */ - error = GetCommentID(vRefNum, dirID, name, &commentID); - if ( error == noErr ) - { - if ( commentID != 0 ) /* commentID == 0 means there's no comment */ - { - error = DetermineVRefNum(name, vRefNum, &realVRefNum); - if ( error == noErr ) - { - error = GetDesktopFileName(realVRefNum, desktopName); - if ( error == noErr ) - { - savedResFile = CurResFile(); - /* - ** Open the 'Desktop' file in the root directory. (because - ** opening the resource file could preload unwanted resources, - ** bracket the call with SetResLoad(s)) - */ - SetResLoad(false); - dfRefNum = HOpenResFile(realVRefNum, fsRtDirID, desktopName, fsRdPerm); - SetResLoad(true); - - if ( dfRefNum != -1) - { - /* Get the comment resource */ - commentHandle = (StringHandle)Get1Resource(kFCMTResType,commentID); - if ( commentHandle != NULL ) - { -#if !TARGET_CARBON - if ( InlineGetHandleSize((Handle)commentHandle) > 0 ) -#else - if ( GetHandleSize((Handle)commentHandle) > 0 ) -#endif - { - BlockMoveData(*commentHandle, comment, *commentHandle[0] + 1); - } - else - { - error = afpItemNotFound; /* no comment available */ - } - } - else - { - error = afpItemNotFound; /* no comment available */ - } - - /* restore the resource chain and close the Desktop file */ - UseResFile(savedResFile); - CloseResFile(dfRefNum); - } - else - { - error = afpItemNotFound; - } - } - else - { - error = afpItemNotFound; - } - } - } - else - { - error = afpItemNotFound; /* no comment available */ - } - } - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr DTGetComment(short vRefNum, - long dirID, - ConstStr255Param name, - Str255 comment) -{ - DTPBRec pb; - OSErr error; - short dtRefNum; - Boolean newDTDatabase; - - if (comment != NULL) - { - comment[0] = 0; /* return nothing by default */ - - /* attempt to open the desktop database */ - error = DTOpen(name, vRefNum, &dtRefNum, &newDTDatabase); - if ( error == noErr ) - { - /* There was a desktop database and it's now open */ - - if ( !newDTDatabase ) - { - pb.ioDTRefNum = dtRefNum; - pb.ioNamePtr = (StringPtr)name; - pb.ioDirID = dirID; - pb.ioDTBuffer = (Ptr)&comment[1]; - /* - ** IMPORTANT NOTE #1: 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. - ** - ** IMPORTANT NOTE #2: Although Inside Macintosh doesn't - ** mention it, ioDTReqCount is a input field to - ** PBDTGetCommentSync. Some file systems (like HFS) ignore - ** ioDTReqCount and always return the full comment -- - ** others (like AppleShare) respect ioDTReqCount and only - ** return up to ioDTReqCount characters of the comment. - */ - pb.ioDTReqCount = sizeof(Str255) - 1; - error = PBDTGetCommentSync(&pb); - if (error == noErr) - { - comment[0] = (unsigned char)pb.ioDTActCount; - } - } - } - else - { - /* There is no desktop database - try the Desktop file */ - error = GetCommentFromDesktopFile(vRefNum, dirID, name, comment); - if ( error != noErr ) - { - error = afpItemNotFound; /* return an expected error */ - } - } - } - else - { - error = paramErr; - } - - return (error); -} - -/*****************************************************************************/ - -pascal OSErr FSpDTGetComment(const FSSpec *spec, - Str255 comment) -{ - return (DTGetComment(spec->vRefNum, spec->parID, spec->name, comment)); -} - -/*****************************************************************************/ - -pascal OSErr DTCopyComment(short srcVRefNum, - long srcDirID, - ConstStr255Param srcName, - short dstVRefNum, - long dstDirID, - ConstStr255Param dstName) -/* The destination volume must support the Desktop Manager for this to work */ -{ - OSErr error; - Str255 comment; - - error = DTGetComment(srcVRefNum, srcDirID, srcName, comment); - if ( (error == noErr) && (comment[0] > 0) ) - { - error = DTSetComment(dstVRefNum, dstDirID, dstName, comment); - } - return (error); -} - -/*****************************************************************************/ - -pascal OSErr FSpDTCopyComment(const FSSpec *srcSpec, - const FSSpec *dstSpec) -/* The destination volume must support the Desktop Manager for this to work */ -{ - return (DTCopyComment(srcSpec->vRefNum, srcSpec->parID, srcSpec->name, - dstSpec->vRefNum, dstSpec->parID, dstSpec->name)); -} - -/*****************************************************************************/ diff --git a/src/mac/morefile/MoreDesk.h b/src/mac/morefile/MoreDesk.h deleted file mode 100644 index ee8dbb4f80..0000000000 --- a/src/mac/morefile/MoreDesk.h +++ /dev/null @@ -1,541 +0,0 @@ -/* -** 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 -#include - -#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__ */ diff --git a/src/mac/morefile/MoreDesktopMgr.c b/src/mac/morefile/MoreDesktopMgr.c new file mode 100644 index 0000000000..880ed263f0 --- /dev/null +++ b/src/mac/morefile/MoreDesktopMgr.c @@ -0,0 +1,1270 @@ +/* + File: MoreDesktopMgr.c + + Contains: A collection of useful high-level Desktop Manager routines. + If the Desktop Manager is not available, use the Desktop file + for 'read' operations. + + Version: MoreFiles + + Copyright: © 1992-2001 by 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. + + File Ownership: + + DRI: Apple Macintosh Developer Technical Support + + Other Contact: Apple Macintosh Developer Technical Support + + + Technology: DTS Sample Code + + Writers: + + (JL) Jim Luther + (NG) Nitin Ganatra + + Change History (most recent first): + + <2> 2/7/01 JL Added standard header. Updated names of includes. Updated + various routines to use new calling convention of the + MoreFilesExtras accessor functions. + <1> 12/06/99 JL MoreFiles 1.5. +*/ + +#include +#include +#include +#include +#include +#include + +#define __COMPILINGMOREFILES + +#include "MoreFiles.h" +#include "MoreFilesExtras.h" +#include "Search.h" +#include "MoreDesktopMgr.h" + +/*****************************************************************************/ + +/* Desktop file notes: +** +** ¥ The Desktop file is owned by the Finder and is normally open by the +** Finder. That means that we only have read-only access to the Desktop +** file. +** ¥ Since the Resource Manager doesn't support shared access to resource +** files and we're using read-only access, we don't ever leave the +** Desktop file open. We open a path to it, get the data we want out +** of it, and then close the open path. This is the only safe way to +** open a resource file with read-only access since some other program +** could have it open with write access. +** ¥ The bundle related resources in the Desktop file are normally +** purgable, so when we're looking through them, we don't bother to +** release resources we're done looking at - closing the resource file +** (which we always do) will release them. +** ¥ Since we can't assume the Desktop file is named "Desktop" +** (it probably is everywhere but France), we get the Desktop +** file's name by searching the volume's root directory for a file +** with fileType == 'FNDR' and creator == 'ERIK'. The only problem with +** this scheme is that someone could create another file with that type +** and creator in the root directory and we'd find the wrong file. +** The chances of this are very slim. +*/ + +/*****************************************************************************/ + +/* local defines */ + +enum +{ + kBNDLResType = 'BNDL', + kFREFResType = 'FREF', + kIconFamResType = 'ICN#', + kFCMTResType = 'FCMT', + kAPPLResType = 'APPL' +}; + +/*****************************************************************************/ + +/* local data structures */ + +#if PRAGMA_STRUCT_ALIGN +#pragma options align=mac68k +#endif + +struct IDRec +{ + short localID; + short rsrcID; +}; +typedef struct IDRec IDRec; +typedef IDRec *IDRecPtr; + +struct BundleType +{ + OSType type; /* 'ICN#' or 'FREF' */ + short count; /* number of IDRecs - 1 */ + IDRec idArray[1]; +}; +typedef struct BundleType BundleType; +typedef BundleType *BundleTypePtr; + +struct BNDLRec +{ + OSType signature; /* creator type signature */ + short versionID; /* version - should always be 0 */ + short numTypes; /* number of elements in typeArray - 1 */ + BundleType typeArray[1]; +}; +typedef struct BNDLRec BNDLRec; +typedef BNDLRec **BNDLRecHandle; + +struct FREFRec +{ + OSType fileType; /* file type */ + short iconID; /* icon local ID */ + Str255 fileName; /* file name */ +}; +typedef struct FREFRec FREFRec; +typedef FREFRec **FREFRecHandle; + +struct APPLRec +{ + OSType creator; /* creator type signature */ + long parID; /* parent directory ID */ + Str255 applName; /* application name */ +}; +typedef struct APPLRec APPLRec; +typedef APPLRec *APPLRecPtr; + +#if PRAGMA_STRUCT_ALIGN +#pragma options align=reset +#endif + +/*****************************************************************************/ + +/* static prototypes */ + +static OSErr GetDesktopFileName(short vRefNum, + Str255 desktopName); + +static OSErr GetAPPLFromDesktopFile(ConstStr255Param volName, + short vRefNum, + OSType creator, + short *applVRefNum, + long *applParID, + Str255 applName); + +static OSErr FindBundleGivenCreator(OSType creator, + BNDLRecHandle *returnBndl); + +static OSErr FindTypeInBundle(OSType typeToFind, + BNDLRecHandle theBndl, + BundleTypePtr *returnBundleType); + +static OSErr GetLocalIDFromFREF(BundleTypePtr theBundleType, + OSType fileType, + short *iconLocalID); + +static OSErr GetIconRsrcIDFromLocalID(BundleTypePtr theBundleType, + short iconLocalID, + short *iconRsrcID); + +static OSType DTIconToResIcon(short iconType); + +static OSErr GetIconFromDesktopFile(ConstStr255Param volName, + short vRefNum, + short iconType, + OSType fileCreator, + OSType fileType, + Handle *iconHandle); + +static OSErr GetCommentID(short vRefNum, + long dirID, + ConstStr255Param name, + short *commentID); + +static OSErr GetCommentFromDesktopFile(short vRefNum, + long dirID, + ConstStr255Param name, + Str255 comment); + +/*****************************************************************************/ + +/* +** GetDesktopFileName +** +** Get the name of the Desktop file. +*/ +static OSErr GetDesktopFileName(short vRefNum, + Str255 desktopName) +{ + OSErr error; + HParamBlockRec pb; + short index; + Boolean found; + + pb.fileParam.ioNamePtr = desktopName; + pb.fileParam.ioVRefNum = vRefNum; + pb.fileParam.ioFVersNum = 0; + index = 1; + found = false; + do + { + pb.fileParam.ioDirID = fsRtDirID; + pb.fileParam.ioFDirIndex = index; + error = PBHGetFInfoSync(&pb); + if ( error == noErr ) + { + if ( (pb.fileParam.ioFlFndrInfo.fdType == 'FNDR') && + (pb.fileParam.ioFlFndrInfo.fdCreator == 'ERIK') ) + { + found = true; + } + } + ++index; + } while ( (error == noErr) && !found ); + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr DTOpen(ConstStr255Param volName, + short vRefNum, + short *dtRefNum, + Boolean *newDTDatabase) +{ + OSErr error; + GetVolParmsInfoBuffer volParmsInfo; + long infoSize; + DTPBRec pb; + + /* Check for volume Desktop Manager support before calling */ + infoSize = sizeof(GetVolParmsInfoBuffer); + error = HGetVolParms(volName, vRefNum, &volParmsInfo, &infoSize); + if ( error == noErr ) + { + if ( hasDesktopMgr(&volParmsInfo) ) + { + pb.ioNamePtr = (StringPtr)volName; + pb.ioVRefNum = vRefNum; + error = PBDTOpenInform(&pb); + /* PBDTOpenInform informs us if the desktop was just created */ + /* by leaving the low bit of ioTagInfo clear (0) */ + *newDTDatabase = ((pb.ioTagInfo & 1L) == 0); + if ( error == paramErr ) + { + error = PBDTGetPath(&pb); + /* PBDTGetPath doesn't tell us if the database is new */ + /* so assume it is not new */ + *newDTDatabase = false; + } + *dtRefNum = pb.ioDTRefNum; + } + else + { + error = paramErr; + } + } + return ( error ); +} + +/*****************************************************************************/ + +/* +** GetAPPLFromDesktopFile +** +** Get a application's location from the +** Desktop file's 'APPL' resources. +*/ +static OSErr GetAPPLFromDesktopFile(ConstStr255Param volName, + short vRefNum, + OSType creator, + short *applVRefNum, + long *applParID, + Str255 applName) +{ + OSErr error; + short realVRefNum; + Str255 desktopName; + short savedResFile; + short dfRefNum; + Handle applResHandle; + Boolean foundCreator; + Ptr applPtr; + long applSize; + + error = DetermineVRefNum(volName, vRefNum, &realVRefNum); + if ( error == noErr ) + { + error = GetDesktopFileName(realVRefNum, desktopName); + if ( error == noErr ) + { + savedResFile = CurResFile(); + /* + ** Open the 'Desktop' file in the root directory. (because + ** opening the resource file could preload unwanted resources, + ** bracket the call with SetResLoad(s)) + */ + SetResLoad(false); + dfRefNum = HOpenResFile(realVRefNum, fsRtDirID, desktopName, fsRdPerm); + SetResLoad(true); + + if ( dfRefNum != -1) + { + /* Get 'APPL' resource ID 0 */ + applResHandle = Get1Resource(kAPPLResType, 0); + if ( applResHandle != NULL ) + { + applSize = GetHandleSize((Handle)applResHandle); + if ( applSize != 0 ) /* make sure the APPL resource isn't empty */ + { + foundCreator = false; + applPtr = *applResHandle; + + /* APPL's don't have a count so I have to use the size as the bounds */ + while ( (foundCreator == false) && + (applPtr < (*applResHandle + applSize)) ) + { + if ( ((APPLRecPtr)applPtr)->creator == creator ) + { + foundCreator = true; + } + else + { + /* fun with pointer math... */ + applPtr += sizeof(OSType) + + sizeof(long) + + ((APPLRecPtr)applPtr)->applName[0] + 1; + /* application mappings are word aligned within the resource */ + if ( ((unsigned long)applPtr % 2) != 0 ) + { + applPtr += 1; + } + } + } + if ( foundCreator == true ) + { + *applVRefNum = realVRefNum; + *applParID = ((APPLRecPtr)applPtr)->parID; + BlockMoveData(((APPLRecPtr)applPtr)->applName, + applName, + ((APPLRecPtr)applPtr)->applName[0] + 1); + /* error is already noErr */ + } + else + { + error = afpItemNotFound; /* didn't find a creator match */ + } + } + else + { + error = afpItemNotFound; /* no APPL mapping available */ + } + } + else + { + error = afpItemNotFound; /* no APPL mapping available */ + } + + /* restore the resource chain and close the Desktop file */ + UseResFile(savedResFile); + CloseResFile(dfRefNum); + } + else + { + error = afpItemNotFound; + } + } + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr DTXGetAPPL(ConstStr255Param volName, + short vRefNum, + OSType creator, + Boolean searchCatalog, + short *applVRefNum, + long *applParID, + Str255 applName) +{ + OSErr error; + UniversalFMPB pb; + short dtRefNum; + Boolean newDTDatabase; + short realVRefNum; + short index; + Boolean applFound; + FSSpec spec; + long actMatchCount; + + /* get the real vRefNum */ + error = DetermineVRefNum(volName, vRefNum, &realVRefNum); + if ( error == noErr ) + { + error = DTOpen(volName, vRefNum, &dtRefNum, &newDTDatabase); + if ( error == noErr ) + { + if ( !newDTDatabase ) + { + index = 0; + applFound = false; + do + { + pb.dtPB.ioNamePtr = applName; + pb.dtPB.ioDTRefNum = dtRefNum; + pb.dtPB.ioIndex = index; + pb.dtPB.ioFileCreator = creator; + error = PBDTGetAPPLSync(&pb.dtPB); + if ( error == noErr ) + { + /* got a match - see if it is valid */ + + *applVRefNum = realVRefNum; /* get the vRefNum now */ + *applParID = pb.dtPB.ioAPPLParID; /* get the parent ID now */ + + /* pb.hPB.fileParam.ioNamePtr is already set */ + pb.hPB.fileParam.ioVRefNum = realVRefNum; + pb.hPB.fileParam.ioFVersNum = 0; + pb.hPB.fileParam.ioDirID = *applParID; + pb.hPB.fileParam.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ + if ( PBHGetFInfoSync(&pb.hPB) == noErr ) + { + if ( (pb.hPB.fileParam.ioFlFndrInfo.fdCreator == creator) && + (pb.hPB.fileParam.ioFlFndrInfo.fdType == 'APPL') ) + { + applFound = true; + } + } + } + ++index; + } while ( (error == noErr) && !applFound ); + if ( error != noErr ) + { + error = afpItemNotFound; + } + } + else + { + /* Desktop database is empty (new), set error to try CatSearch */ + error = afpItemNotFound; + } + } + /* acceptable errors from Desktop Manager to continue are paramErr or afpItemNotFound */ + if ( error == paramErr ) + { + /* if paramErr, the volume didn't support the Desktop Manager */ + /* try the Desktop file */ + + error = GetAPPLFromDesktopFile(volName, vRefNum, creator, + applVRefNum, applParID, applName); + if ( error == noErr ) + { + /* got a match - see if it is valid */ + + pb.hPB.fileParam.ioNamePtr = applName; + pb.hPB.fileParam.ioVRefNum = *applVRefNum; + pb.hPB.fileParam.ioFVersNum = 0; + pb.hPB.fileParam.ioDirID = *applParID; + pb.hPB.fileParam.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ + if ( PBHGetFInfoSync(&pb.hPB) == noErr ) + { + if ( (pb.hPB.fileParam.ioFlFndrInfo.fdCreator != creator) || + (pb.hPB.fileParam.ioFlFndrInfo.fdType != 'APPL') ) + { + error = afpItemNotFound; + } + } + else if ( error == fnfErr ) + { + error = afpItemNotFound; + } + } + } + /* acceptable error from DesktopFile code to continue is afpItemNotFound */ + if ( (error == afpItemNotFound) && searchCatalog) + { + /* Couldn't be found in the Desktop file either, */ + /* try searching with CatSearch if requested */ + + error = CreatorTypeFileSearch(NULL, realVRefNum, creator, kAPPLResType, &spec, 1, + &actMatchCount, true); + if ( (error == noErr) || (error == eofErr) ) + { + if ( actMatchCount > 0 ) + { + *applVRefNum = spec.vRefNum; + *applParID = spec.parID; + BlockMoveData(spec.name, applName, spec.name[0] + 1); + } + else + { + error = afpItemNotFound; + } + } + } + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr FSpDTXGetAPPL(ConstStr255Param volName, + short vRefNum, + OSType creator, + Boolean searchCatalog, + FSSpec *spec) +{ + return ( DTXGetAPPL(volName, vRefNum, creator, searchCatalog, + &(spec->vRefNum), &(spec->parID), spec->name) ); +} + +/*****************************************************************************/ + +pascal OSErr DTGetAPPL(ConstStr255Param volName, + short vRefNum, + OSType creator, + short *applVRefNum, + long *applParID, + Str255 applName) +{ + /* Call DTXGetAPPL with the "searchCatalog" parameter true */ + return ( DTXGetAPPL(volName, vRefNum, creator, true, + applVRefNum, applParID, applName) ); +} + +/*****************************************************************************/ + +pascal OSErr FSpDTGetAPPL(ConstStr255Param volName, + short vRefNum, + OSType creator, + FSSpec *spec) +{ + /* Call DTXGetAPPL with the "searchCatalog" parameter true */ + return ( DTXGetAPPL(volName, vRefNum, creator, true, + &(spec->vRefNum), &(spec->parID), spec->name) ); +} + +/*****************************************************************************/ + +/* +** FindBundleGivenCreator +** +** Search the current resource file for the 'BNDL' resource with the given +** creator and return a handle to it. +*/ +static OSErr FindBundleGivenCreator(OSType creator, + BNDLRecHandle *returnBndl) +{ + OSErr error; + short numOfBundles; + short index; + BNDLRecHandle theBndl; + + error = afpItemNotFound; /* default to not found */ + + /* Search each BNDL resource until we find the one with a matching creator. */ + + numOfBundles = Count1Resources(kBNDLResType); + index = 1; + *returnBndl = NULL; + + while ( (index <= numOfBundles) && (*returnBndl == NULL) ) + { + theBndl = (BNDLRecHandle)Get1IndResource(kBNDLResType, index); + + if ( theBndl != NULL ) + { + if ( (*theBndl)->signature == creator ) + { + /* numTypes and typeArray->count will always be the actual count minus 1, */ + /* so 0 in both fields is valid. */ + if ( ((*theBndl)->numTypes >= 0) && ((*theBndl)->typeArray->count >= 0) ) + { + /* got it */ + *returnBndl = theBndl; + error = noErr; + } + } + } + + index ++; + } + + return ( error ); +} + +/*****************************************************************************/ + +/* +** FindTypeInBundle +** +** Given a Handle to a BNDL return a pointer to the desired type +** in it. If the type is not found, or if the type's count < 0, +** return afpItemNotFound. +*/ +static OSErr FindTypeInBundle(OSType typeToFind, + BNDLRecHandle theBndl, + BundleTypePtr *returnBundleType) +{ + OSErr error; + short index; + Ptr ptrIterator; /* use a Ptr so we can do ugly pointer math */ + + error = afpItemNotFound; /* default to not found */ + + ptrIterator = (Ptr)((*theBndl)->typeArray); + index = 0; + *returnBundleType = NULL; + + while ( (index < ((*theBndl)->numTypes + 1)) && + (*returnBundleType == NULL) ) + { + if ( (((BundleTypePtr)ptrIterator)->type == typeToFind) && + (((BundleTypePtr)ptrIterator)->count >= 0) ) + { + *returnBundleType = (BundleTypePtr)ptrIterator; + error = noErr; + } + else + { + ptrIterator += ( sizeof(OSType) + + sizeof(short) + + ( sizeof(IDRec) * (((BundleTypePtr)ptrIterator)->count + 1) ) ); + ++index; + } + } + + return ( error ); +} + +/*****************************************************************************/ + +/* +** GetLocalIDFromFREF +** +** Given a pointer to a 'FREF' BundleType record, load each 'FREF' resource +** looking for a matching fileType. If a matching fileType is found, return +** its icon local ID. If no match is found, return afpItemNotFound as the +** function result. +*/ +static OSErr GetLocalIDFromFREF(BundleTypePtr theBundleType, + OSType fileType, + short *iconLocalID) +{ + OSErr error; + short index; + IDRecPtr idIterator; + FREFRecHandle theFref; + + error = afpItemNotFound; /* default to not found */ + + /* For each localID in this type, get the FREF resource looking for fileType */ + index = 0; + idIterator = &theBundleType->idArray[0]; + *iconLocalID = 0; + + while ( (index <= theBundleType->count) && (*iconLocalID == 0) ) + { + theFref = (FREFRecHandle)Get1Resource(kFREFResType, idIterator->rsrcID); + if ( theFref != NULL ) + { + if ( (*theFref)->fileType == fileType ) + { + *iconLocalID = (*theFref)->iconID; + error = noErr; + } + } + + ++idIterator; + ++index; + } + + return ( error ); +} + +/*****************************************************************************/ + +/* +** GetIconRsrcIDFromLocalID +** +** Given a pointer to a 'ICN#' BundleType record, look for the IDRec with +** the localID that matches iconLocalID. If a matching IDRec is found, +** return the IDRec's rsrcID field value. If no match is found, return +** afpItemNotFound as the function result. +*/ +static OSErr GetIconRsrcIDFromLocalID(BundleTypePtr theBundleType, + short iconLocalID, + short *iconRsrcID) +{ + OSErr error; + short index; + IDRecPtr idIterator; + + error = afpItemNotFound; /* default to not found */ + + /* Find the rsrcID of the icon family type, given the localID */ + index = 0; + idIterator = &theBundleType->idArray[0]; + *iconRsrcID = 0; + + while ( (index <= theBundleType->count) && (*iconRsrcID == 0) ) + { + if ( idIterator->localID == iconLocalID ) + { + *iconRsrcID = idIterator->rsrcID; + error = noErr; + } + + idIterator ++; + index ++; + } + + return ( error ); +} + +/*****************************************************************************/ + +/* +** DTIconToResIcon +** +** Map a Desktop Manager icon type to the corresponding resource type. +** Return (OSType)0 if there is no corresponding resource type. +*/ +static OSType DTIconToResIcon(short iconType) +{ + OSType resType; + + switch ( iconType ) + { + case kLargeIcon: + resType = large1BitMask; + break; + case kLarge4BitIcon: + resType = large4BitData; + break; + case kLarge8BitIcon: + resType = large8BitData; + break; + case kSmallIcon: + resType = small1BitMask; + break; + case kSmall4BitIcon: + resType = small4BitData; + break; + case kSmall8BitIcon: + resType = small8BitData; + break; + default: + resType = (OSType)0; + break; + } + + return ( resType ); +} + +/*****************************************************************************/ + +/* +** GetIconFromDesktopFile +** +** INPUT a pointer to a non-existent Handle, because we'll allocate one +** +** search each BNDL resource for the right fileCreator and once we get it +** find the 'FREF' type in BNDL +** for each localID in the type, open the FREF resource +** if the FREF is the desired fileType +** get its icon localID +** get the ICN# type in BNDL +** get the icon resource number from the icon localID +** get the icon resource type from the desktop mgr's iconType +** get the icon of that type and number +*/ +static OSErr GetIconFromDesktopFile(ConstStr255Param volName, + short vRefNum, + short iconType, + OSType fileCreator, + OSType fileType, + Handle *iconHandle) +{ + OSErr error; + short realVRefNum; + Str255 desktopName; + short savedResFile; + short dfRefNum; + BNDLRecHandle theBndl = NULL; + BundleTypePtr theBundleType; + short iconLocalID; + short iconRsrcID; + OSType iconRsrcType; + Handle returnIconHandle; + char bndlState; + + *iconHandle = NULL; + + error = DetermineVRefNum(volName, vRefNum, &realVRefNum); + if ( error == noErr ) + { + error = GetDesktopFileName(realVRefNum, desktopName); + if ( error == noErr ) + { + savedResFile = CurResFile(); + + /* + ** Open the 'Desktop' file in the root directory. (because + ** opening the resource file could preload unwanted resources, + ** bracket the call with SetResLoad(s)) + */ + SetResLoad(false); + dfRefNum = HOpenResFile(realVRefNum, fsRtDirID, desktopName, fsRdPerm); + SetResLoad(true); + + if ( dfRefNum != -1 ) + { + /* + ** Find the BNDL resource with the specified creator. + */ + error = FindBundleGivenCreator(fileCreator, &theBndl); + if ( error == noErr ) + { + /* Lock the BNDL resource so it won't be purged when other resources are loaded */ + bndlState = HGetState((Handle)theBndl); + HLock((Handle)theBndl); + + /* Find the 'FREF' BundleType record in the BNDL resource. */ + error = FindTypeInBundle(kFREFResType, theBndl, &theBundleType); + if ( error == noErr ) + { + /* Find the local ID in the 'FREF' resource with the specified fileType */ + error = GetLocalIDFromFREF(theBundleType, fileType, &iconLocalID); + if ( error == noErr ) + { + /* Find the 'ICN#' BundleType record in the BNDL resource. */ + error = FindTypeInBundle(kIconFamResType, theBndl, &theBundleType); + if ( error == noErr ) + { + /* Find the icon's resource ID in the 'ICN#' BundleType record */ + error = GetIconRsrcIDFromLocalID(theBundleType, iconLocalID, &iconRsrcID); + if ( error == noErr ) + { + /* Map Desktop Manager icon type to resource type */ + iconRsrcType = DTIconToResIcon(iconType); + + if ( iconRsrcType != (OSType)0 ) + { + /* Load the icon */ + returnIconHandle = Get1Resource(iconRsrcType, iconRsrcID); + if ( returnIconHandle != NULL ) + { + /* Copy the resource handle, and return the copy */ + HandToHand(&returnIconHandle); + if ( MemError() == noErr ) + { + *iconHandle = returnIconHandle; + } + else + { + error = afpItemNotFound; + } + } + else + { + error = afpItemNotFound; + } + } + } + } + } + } + /* Restore the state of the BNDL resource */ + HSetState((Handle)theBndl, bndlState); + } + /* Restore the resource chain and close the Desktop file */ + UseResFile(savedResFile); + CloseResFile(dfRefNum); + } + else + { + error = ResError(); /* could not open Desktop file */ + } + } + if ( (error != noErr) && (error != memFullErr) ) + { + error = afpItemNotFound; /* force an error we should return */ + } + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr DTGetIcon(ConstStr255Param volName, + short vRefNum, + short iconType, + OSType fileCreator, + OSType fileType, + Handle *iconHandle) +{ + OSErr error; + DTPBRec pb; + short dtRefNum; + Boolean newDTDatabase; + Size bufferSize; + + *iconHandle = NULL; + error = DTOpen(volName, vRefNum, &dtRefNum, &newDTDatabase); + if ( error == noErr ) + { + /* there was a desktop database and it's now open */ + + if ( !newDTDatabase ) /* don't bother to look in a new (empty) database */ + { + /* get the buffer size for the requested icon type */ + switch ( iconType ) + { + case kLargeIcon: + bufferSize = kLargeIconSize; + break; + case kLarge4BitIcon: + bufferSize = kLarge4BitIconSize; + break; + case kLarge8BitIcon: + bufferSize = kLarge8BitIconSize; + break; + case kSmallIcon: + bufferSize = kSmallIconSize; + break; + case kSmall4BitIcon: + bufferSize = kSmall4BitIconSize; + break; + case kSmall8BitIcon: + bufferSize = kSmall8BitIconSize; + break; + default: + iconType = 0; + bufferSize = 0; + break; + } + if ( bufferSize != 0 ) + { + *iconHandle = NewHandle(bufferSize); + if ( *iconHandle != NULL ) + { + HLock(*iconHandle); + + pb.ioDTRefNum = dtRefNum; + pb.ioTagInfo = 0; + pb.ioDTBuffer = **iconHandle; + pb.ioDTReqCount = bufferSize; + pb.ioIconType = iconType; + pb.ioFileCreator = fileCreator; + pb.ioFileType = fileType; + error = PBDTGetIconSync(&pb); + + HUnlock(*iconHandle); + + if ( error != noErr ) + { + DisposeHandle(*iconHandle); /* dispose of the allocated memory */ + *iconHandle = NULL; + } + } + else + { + error = memFullErr; /* handle could not be allocated */ + } + } + else + { + error = paramErr; /* unknown icon type requested */ + } + } + else + { + error = afpItemNotFound; /* the desktop database was empty - nothing to return */ + } + } + else + { + /* There is no desktop database - try the Desktop file */ + + error = GetIconFromDesktopFile(volName, vRefNum, iconType, + fileCreator, fileType, iconHandle); + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr DTSetComment(short vRefNum, + long dirID, + ConstStr255Param name, + ConstStr255Param comment) +{ + DTPBRec pb; + OSErr error; + short dtRefNum; + Boolean newDTDatabase; + + error = DTOpen(name, vRefNum, &dtRefNum, &newDTDatabase); + if ( error == noErr ) + { + pb.ioDTRefNum = dtRefNum; + pb.ioNamePtr = (StringPtr)name; + pb.ioDirID = dirID; + pb.ioDTBuffer = (Ptr)&comment[1]; + /* Truncate the comment to 200 characters just in case */ + /* some file system doesn't range check */ + if ( comment[0] <= 200 ) + { + pb.ioDTReqCount = comment[0]; + } + else + { + pb.ioDTReqCount = 200; + } + error = PBDTSetCommentSync(&pb); + } + return (error); +} + +/*****************************************************************************/ + +pascal OSErr FSpDTSetComment(const FSSpec *spec, + ConstStr255Param comment) +{ + return (DTSetComment(spec->vRefNum, spec->parID, spec->name, comment)); +} + +/*****************************************************************************/ + +/* +** GetCommentID +** +** Get the comment ID number for the Desktop file's 'FCMT' resource ID from +** the file or folders fdComment (frComment) field. +*/ +static OSErr GetCommentID(short vRefNum, + long dirID, + ConstStr255Param name, + short *commentID) +{ + CInfoPBRec pb; + OSErr error; + + error = GetCatInfoNoName(vRefNum, dirID, name, &pb); + *commentID = pb.hFileInfo.ioFlXFndrInfo.fdComment; + return ( error ); +} + +/*****************************************************************************/ + +/* +** GetCommentFromDesktopFile +** +** Get a file or directory's Finder comment field (if any) from the +** Desktop file's 'FCMT' resources. +*/ +static OSErr GetCommentFromDesktopFile(short vRefNum, + long dirID, + ConstStr255Param name, + Str255 comment) +{ + OSErr error; + short commentID; + short realVRefNum; + Str255 desktopName; + short savedResFile; + short dfRefNum; + StringHandle commentHandle; + + /* Get the comment ID number */ + error = GetCommentID(vRefNum, dirID, name, &commentID); + if ( error == noErr ) + { + if ( commentID != 0 ) /* commentID == 0 means there's no comment */ + { + error = DetermineVRefNum(name, vRefNum, &realVRefNum); + if ( error == noErr ) + { + error = GetDesktopFileName(realVRefNum, desktopName); + if ( error == noErr ) + { + savedResFile = CurResFile(); + /* + ** Open the 'Desktop' file in the root directory. (because + ** opening the resource file could preload unwanted resources, + ** bracket the call with SetResLoad(s)) + */ + SetResLoad(false); + dfRefNum = HOpenResFile(realVRefNum, fsRtDirID, desktopName, fsRdPerm); + SetResLoad(true); + + if ( dfRefNum != -1) + { + /* Get the comment resource */ + commentHandle = (StringHandle)Get1Resource(kFCMTResType,commentID); + if ( commentHandle != NULL ) + { + if ( GetHandleSize((Handle)commentHandle) > 0 ) + { + BlockMoveData(*commentHandle, comment, *commentHandle[0] + 1); + } + else + { + error = afpItemNotFound; /* no comment available */ + } + } + else + { + error = afpItemNotFound; /* no comment available */ + } + + /* restore the resource chain and close the Desktop file */ + UseResFile(savedResFile); + CloseResFile(dfRefNum); + } + else + { + error = afpItemNotFound; + } + } + else + { + error = afpItemNotFound; + } + } + } + else + { + error = afpItemNotFound; /* no comment available */ + } + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr DTGetComment(short vRefNum, + long dirID, + ConstStr255Param name, + Str255 comment) +{ + DTPBRec pb; + OSErr error; + short dtRefNum; + Boolean newDTDatabase; + + if (comment != NULL) + { + comment[0] = 0; /* return nothing by default */ + + /* attempt to open the desktop database */ + error = DTOpen(name, vRefNum, &dtRefNum, &newDTDatabase); + if ( error == noErr ) + { + /* There was a desktop database and it's now open */ + + if ( !newDTDatabase ) + { + pb.ioDTRefNum = dtRefNum; + pb.ioNamePtr = (StringPtr)name; + pb.ioDirID = dirID; + pb.ioDTBuffer = (Ptr)&comment[1]; + /* + ** IMPORTANT NOTE #1: 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. + ** + ** IMPORTANT NOTE #2: Although Inside Macintosh doesn't + ** mention it, ioDTReqCount is a input field to + ** PBDTGetCommentSync. Some file systems (like HFS) ignore + ** ioDTReqCount and always return the full comment -- + ** others (like AppleShare) respect ioDTReqCount and only + ** return up to ioDTReqCount characters of the comment. + */ + pb.ioDTReqCount = sizeof(Str255) - 1; + error = PBDTGetCommentSync(&pb); + if (error == noErr) + { + comment[0] = (unsigned char)pb.ioDTActCount; + } + } + } + else + { + /* There is no desktop database - try the Desktop file */ + error = GetCommentFromDesktopFile(vRefNum, dirID, name, comment); + if ( error != noErr ) + { + error = afpItemNotFound; /* return an expected error */ + } + } + } + else + { + error = paramErr; + } + + return (error); +} + +/*****************************************************************************/ + +pascal OSErr FSpDTGetComment(const FSSpec *spec, + Str255 comment) +{ + return (DTGetComment(spec->vRefNum, spec->parID, spec->name, comment)); +} + +/*****************************************************************************/ + +pascal OSErr DTCopyComment(short srcVRefNum, + long srcDirID, + ConstStr255Param srcName, + short dstVRefNum, + long dstDirID, + ConstStr255Param dstName) +/* The destination volume must support the Desktop Manager for this to work */ +{ + OSErr error; + Str255 comment; + + error = DTGetComment(srcVRefNum, srcDirID, srcName, comment); + if ( (error == noErr) && (comment[0] > 0) ) + { + error = DTSetComment(dstVRefNum, dstDirID, dstName, comment); + } + return (error); +} + +/*****************************************************************************/ + +pascal OSErr FSpDTCopyComment(const FSSpec *srcSpec, + const FSSpec *dstSpec) +/* The destination volume must support the Desktop Manager for this to work */ +{ + return (DTCopyComment(srcSpec->vRefNum, srcSpec->parID, srcSpec->name, + dstSpec->vRefNum, dstSpec->parID, dstSpec->name)); +} + +/*****************************************************************************/ diff --git a/src/mac/morefile/MoreDesktopMgr.h b/src/mac/morefile/MoreDesktopMgr.h new file mode 100644 index 0000000000..110c673403 --- /dev/null +++ b/src/mac/morefile/MoreDesktopMgr.h @@ -0,0 +1,628 @@ +/* + File: MoreDesktopMgr.h + + Contains: A collection of useful high-level Desktop Manager routines. If the Desktop Manager is not available, use the Desktop file for 'read' operations. + + Version: Technology: MoreFiles + Release: 1.5.2 + + Copyright: © 1992-2001 by Apple Computer, Inc., all rights reserved. + + Bugs?: For bug reports, consult the following page on + the World Wide Web: + + http://developer.apple.com/bugreporter/ + +*/ + +/* + 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__ + +#ifndef __MACTYPES__ +#include +#endif + +#ifndef __FILES__ +#include +#endif + +#include "Optimization.h" + + +#if PRAGMA_ONCE +#pragma once +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if PRAGMA_IMPORT +#pragma import on +#endif + +#if PRAGMA_STRUCT_ALIGN + #pragma options align=mac68k +#elif PRAGMA_STRUCT_PACKPUSH + #pragma pack(push, 2) +#elif PRAGMA_STRUCT_PACK + #pragma pack(2) +#endif + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +DTOpen( + ConstStr255Param volName, + short vRefNum, + short * dtRefNum, + Boolean * newDTDatabase); + + +/* + 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +DTXGetAPPL( + ConstStr255Param volName, + short vRefNum, + OSType creator, + Boolean searchCatalog, + short * applVRefNum, + long * applParID, + Str255 applName); + + +/* + 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpDTXGetAPPL( + ConstStr255Param volName, + short vRefNum, + OSType creator, + Boolean searchCatalog, + FSSpec * spec); + + +/* + 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +DTGetAPPL( + ConstStr255Param volName, + short vRefNum, + OSType creator, + short * applVRefNum, + long * applParID, + Str255 applName); + + +/* + 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpDTGetAPPL( + ConstStr255Param volName, + short vRefNum, + OSType creator, + FSSpec * spec); + + +/* + 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +DTGetIcon( + ConstStr255Param volName, + short vRefNum, + short iconType, + OSType fileCreator, + OSType fileType, + Handle * iconHandle); + + +/* + 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +DTSetComment( + short vRefNum, + long dirID, + ConstStr255Param name, + ConstStr255Param comment); + + +/* + 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpDTSetComment( + const FSSpec * spec, + ConstStr255Param comment); + + +/* + 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +DTGetComment( + short vRefNum, + long dirID, + ConstStr255Param name, + Str255 comment); + + +/* + 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpDTGetComment( + const FSSpec * spec, + Str255 comment); + + +/* + 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +DTCopyComment( + short srcVRefNum, + long srcDirID, + ConstStr255Param srcName, + short dstVRefNum, + long dstDirID, + ConstStr255Param dstName); + + +/* + 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpDTCopyComment( + const FSSpec * srcSpec, + const FSSpec * dstSpec); + + +/* + 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 +*/ + +/*****************************************************************************/ + +#include "OptimizationEnd.h" + +#if PRAGMA_STRUCT_ALIGN + #pragma options align=reset +#elif PRAGMA_STRUCT_PACKPUSH + #pragma pack(pop) +#elif PRAGMA_STRUCT_PACK + #pragma pack() +#endif + +#ifdef PRAGMA_IMPORT_OFF +#pragma import off +#elif PRAGMA_IMPORT +#pragma import reset +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __MOREDESKTOPMGR__ */ + diff --git a/src/mac/morefile/MoreExtr.cpp b/src/mac/morefile/MoreExtr.cpp deleted file mode 100644 index d24c3c996b..0000000000 --- a/src/mac/morefile/MoreExtr.cpp +++ /dev/null @@ -1,3270 +0,0 @@ -/* -** Apple Macintosh Developer Technical Support -** -** A collection of useful high-level File Manager routines. -** -** by Jim Luther, Apple Developer Technical Support Emeritus -** -** File: MoreFilesExtras.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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define __COMPILINGMOREFILES - -#include "morefile.h" -#include "moreextr.h" -#include "moredesk.h" -#include "fspcompa.h" - -/*****************************************************************************/ - -/* local data structures */ - -/* The DeleteEnumGlobals structure is used to minimize the amount of -** stack space used when recursively calling DeleteLevel and to hold -** global information that might be needed at any time. */ - -#if PRAGMA_STRUCT_ALIGN - #pragma options align=mac68k -#elif PRAGMA_STRUCT_PACKPUSH - #pragma pack(push, 2) -#elif PRAGMA_STRUCT_PACK - #pragma pack(2) -#endif -struct DeleteEnumGlobals -{ - OSErr error; /* temporary holder of results - saves 2 bytes of stack each level */ - Str63 itemName; /* the name of the current item */ - UniversalFMPB myPB; /* the parameter block used for PBGetCatInfo calls */ -}; -#if PRAGMA_STRUCT_ALIGN - #pragma options align=reset -#elif PRAGMA_STRUCT_PACKPUSH - #pragma pack(pop) -#elif PRAGMA_STRUCT_PACK - #pragma pack() -#endif - -typedef struct DeleteEnumGlobals DeleteEnumGlobals; -typedef DeleteEnumGlobals *DeleteEnumGlobalsPtr; - -/*****************************************************************************/ - -pascal void TruncPString(StringPtr destination, - ConstStr255Param source, - short maxLength) -{ - short charType; - - if ( source != NULL && destination != NULL ) /* don't do anything stupid */ - { - if ( source[0] > maxLength ) - { - /* Make sure the string isn't truncated in the middle of */ - /* a multi-byte character. */ - while (maxLength != 0) - { -#if TARGET_CARBON - charType = CharacterByteType((Ptr)&source[1], maxLength,smAllScripts); -#else - charType = CharByte((Ptr)&source[1], maxLength); -#endif - if ( (charType == smSingleByte) || (charType == smLastByte) ) - break; /* source[maxLength] is now a valid last character */ - --maxLength; - } - } - else - { - maxLength = source[0]; - } - /* Set the destination string length */ - destination[0] = maxLength; - /* and copy maxLength characters (if needed) */ - if ( source != destination ) - { - while ( maxLength != 0 ) - { - destination[maxLength] = source[maxLength]; - --maxLength; - } - } - } -} - -/*****************************************************************************/ - -pascal Ptr GetTempBuffer(long buffReqSize, - long *buffActSize) -{ - enum - { - kSlopMemory = 0x00008000 /* 32K - Amount of free memory to leave when allocating buffers */ - }; - Ptr tempPtr; - - /* Make request a multiple of 1024 bytes */ - buffReqSize = buffReqSize & 0xfffffc00; - - if ( buffReqSize < 0x00000400 ) - { - /* Request was smaller than 1024 bytes - make it 1024 */ - buffReqSize = 0x00000400; - } - - /* Attempt to allocate the memory */ - tempPtr = NewPtr(buffReqSize); - - /* If request failed, go to backup plan */ - if ( (tempPtr == NULL) && (buffReqSize > 0x00000400) ) - { - /* - ** Try to get largest 1024-byte block available - ** leaving some slop for the toolbox if possible - */ - long freeMemory = (FreeMem() - kSlopMemory) & 0xfffffc00; - - buffReqSize = MaxBlock() & 0xfffffc00; - - if ( buffReqSize > freeMemory ) - { - buffReqSize = freeMemory; - } - - if ( buffReqSize == 0 ) - { - buffReqSize = 0x00000400; - } - - tempPtr = NewPtr(buffReqSize); - } - - /* Return bytes allocated */ - if ( tempPtr != NULL ) - { - *buffActSize = buffReqSize; - } - else - { - *buffActSize = 0; - } - - return ( tempPtr ); -} - -/*****************************************************************************/ - -/* -** GetVolumeInfoNoName uses pathname and vRefNum to call PBHGetVInfoSync -** in cases where the returned volume name is not needed by the caller. -** The pathname and vRefNum parameters are not touched, and the pb -** parameter is initialized by PBHGetVInfoSync except that ioNamePtr in -** the parameter block is always returned as NULL (since it might point -** to the local tempPathname). -** -** I noticed using this code in several places, so here it is once. -** This reduces the code size of MoreFiles. -*/ -pascal OSErr GetVolumeInfoNoName(ConstStr255Param pathname, - short vRefNum, - HParmBlkPtr pb) -{ - Str255 tempPathname; - OSErr error; - - /* Make sure pb parameter is not NULL */ - if ( pb != NULL ) - { - pb->volumeParam.ioVRefNum = vRefNum; - if ( pathname == NULL ) - { - pb->volumeParam.ioNamePtr = NULL; - pb->volumeParam.ioVolIndex = 0; /* use ioVRefNum only */ - } - else - { - BlockMoveData(pathname, tempPathname, pathname[0] + 1); /* make a copy of the string and */ - pb->volumeParam.ioNamePtr = (StringPtr)tempPathname; /* use the copy so original isn't trashed */ - pb->volumeParam.ioVolIndex = -1; /* use ioNamePtr/ioVRefNum combination */ - } - error = PBHGetVInfoSync(pb); - pb->volumeParam.ioNamePtr = NULL; /* ioNamePtr may point to local tempPathname, so don't return it */ - } - else - { - error = paramErr; - } - return ( error ); -} - -/*****************************************************************************/ - -/* -** XGetVolumeInfoNoName uses pathname and vRefNum to call PBXGetVolInfoSync -** in cases where the returned volume name is not needed by the caller. -** The pathname and vRefNum parameters are not touched, and the pb -** parameter is initialized by PBXGetVolInfoSync except that ioNamePtr in -** the parameter block is always returned as NULL (since it might point -** to the local tempPathname). -*/ - -// #if TARGET_CARBON - -pascal OSErr XGetVolumeInfoNoName(ConstStr255Param pathname, - short vRefNum, - XVolumeParamPtr pb) -{ - Str255 tempPathname; - long response; - OSErr error; - - /* Make sure pb parameter is not NULL */ - if ( pb != NULL ) - { - pb->ioVRefNum = vRefNum; - pb->ioXVersion = 0; /* this XVolumeParam version (0) */ - if ( pathname == NULL ) - { - pb->ioNamePtr = NULL; - pb->ioVolIndex = 0; /* use ioVRefNum only */ - } - else - { - BlockMoveData(pathname, tempPathname, pathname[0] + 1); /* make a copy of the string and */ - pb->ioNamePtr = (StringPtr)tempPathname; /* use the copy so original isn't trashed */ - pb->ioVolIndex = -1; /* use ioNamePtr/ioVRefNum combination */ - } -#if !__MACOSSEVENFIVEONEORLATER - /* Is PBXGetVolInfo available? */ - if ( ( Gestalt(gestaltFSAttr, &response) != noErr ) || ((response & (1L << gestaltFSSupports2TBVols)) == 0) ) - { - /* No, fall back on PBHGetVInfo */ - error = PBHGetVInfoSync((HParmBlkPtr)pb); - if ( error == noErr ) - { - /* calculate the ioVTotalBytes and ioVFreeBytes fields */ - pb->ioVTotalBytes.hi = 0; - pb->ioVTotalBytes.lo = pb->ioVNmAlBlks * pb->ioVAlBlkSiz; /* calculated total number of bytes on volume */ - pb->ioVFreeBytes.hi = 0; - pb->ioVFreeBytes.lo = pb->ioVFrBlk * pb->ioVAlBlkSiz; /* calculated number of free bytes on volume */ - } - } - else -#endif // !__MACOSSEVENFIVEONEORLATER - { - /* Yes, so use it */ - error = PBXGetVolInfoSync(pb); - } - pb->ioNamePtr = NULL; /* ioNamePtr may point to local tempPathname, so don't return it */ - } - else - { - error = paramErr; - } - return ( error ); -} - -// #endif - -/*****************************************************************************/ - -pascal OSErr GetCatInfoNoName(short vRefNum, - long dirID, - ConstStr255Param name, - CInfoPBPtr pb) -{ - Str31 tempName; - OSErr error; - - /* Protection against File Sharing problem */ - if ( (name == NULL) || (name[0] == 0) ) - { - tempName[0] = 0; - pb->dirInfo.ioNamePtr = tempName; - pb->dirInfo.ioFDirIndex = -1; /* use ioDirID */ - } - else - { - pb->dirInfo.ioNamePtr = (StringPtr)name; - pb->dirInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ - } - pb->dirInfo.ioVRefNum = vRefNum; - pb->dirInfo.ioDrDirID = dirID; - error = PBGetCatInfoSync(pb); - pb->dirInfo.ioNamePtr = NULL; - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr DetermineVRefNum(ConstStr255Param pathname, - short vRefNum, - short *realVRefNum) -{ - HParamBlockRec pb; - OSErr error; - - error = GetVolumeInfoNoName(pathname,vRefNum, &pb); - if ( error == noErr ) - { - *realVRefNum = pb.volumeParam.ioVRefNum; - } - return ( error ); -} - -/*****************************************************************************/ - -#if !TARGET_CARBON -pascal OSErr HGetVInfo(short volReference, - StringPtr volName, - short *vRefNum, - unsigned long *freeBytes, - unsigned long *totalBytes) -{ - HParamBlockRec pb; - unsigned long allocationBlockSize; - unsigned short numAllocationBlocks; - unsigned short numFreeBlocks; - VCB *theVCB; - Boolean vcbFound; - OSErr result; - - /* Use the File Manager to get the real vRefNum */ - pb.volumeParam.ioVRefNum = volReference; - pb.volumeParam.ioNamePtr = volName; - pb.volumeParam.ioVolIndex = 0; /* use ioVRefNum only, return volume name */ - result = PBHGetVInfoSync(&pb); - - if ( result == noErr ) - { - /* The volume name was returned in volName (if not NULL) and */ - /* we have the volume's vRefNum and allocation block size */ - *vRefNum = pb.volumeParam.ioVRefNum; - allocationBlockSize = (unsigned long)pb.volumeParam.ioVAlBlkSiz; - - /* System 7.5 (and beyond) pins the number of allocation blocks and */ - /* the number of free allocation blocks returned by PBHGetVInfo to */ - /* a value so that when multiplied by the allocation block size, */ - /* the volume will look like it has $7fffffff bytes or less. This */ - /* was done so older applications that use signed math or that use */ - /* the GetVInfo function (which uses signed math) will continue to work. */ - /* However, the unpinned numbers (which we want) are always available */ - /* in the volume's VCB so we'll get those values from the VCB if possible. */ - - /* Find the volume's VCB */ - vcbFound = false; - theVCB = (VCB *)(GetVCBQHdr()->qHead); - while ( (theVCB != NULL) && !vcbFound ) - { - /* Check VCB signature before using VCB. Don't have to check for */ - /* MFS (0xd2d7) because they can't get big enough to be pinned */ - if ( theVCB->vcbSigWord == 0x4244 ) - { - if ( theVCB->vcbVRefNum == *vRefNum ) - { - vcbFound = true; - } - } - - if ( !vcbFound ) - { - theVCB = (VCB *)(theVCB->qLink); - } - } - - if ( theVCB != NULL ) - { - /* Found a VCB we can use. Get the un-pinned number of allocation blocks */ - /* and the number of free blocks from the VCB. */ - numAllocationBlocks = (unsigned short)theVCB->vcbNmAlBlks; - numFreeBlocks = (unsigned short)theVCB->vcbFreeBks; - } - else - { - /* Didn't find a VCB we can use. Return the number of allocation blocks */ - /* and the number of free blocks returned by PBHGetVInfoSync. */ - numAllocationBlocks = (unsigned short)pb.volumeParam.ioVNmAlBlks; - numFreeBlocks = (unsigned short)pb.volumeParam.ioVFrBlk; - } - - /* Now, calculate freeBytes and totalBytes using unsigned values */ - *freeBytes = numFreeBlocks * allocationBlockSize; - *totalBytes = numAllocationBlocks * allocationBlockSize; - } - - return ( result ); -} -#endif -/*****************************************************************************/ - -/* -** PBXGetVolInfoSync is the glue code needed to make PBXGetVolInfoSync -** File Manager requests from CFM-based programs. At some point, Apple -** will get around to adding this to the standard libraries you link with -** and you'll get a duplicate symbol link error. At that time, just delete -** this code (or comment it out). -** -** Non-CFM 68K programs don't needs this glue (and won't get it) because -** they instead use the inline assembly glue found in the Files.h interface -** file. -*/ - -#if __WANTPASCALELIMINATION -#undef pascal -#endif - -#if !TARGET_CARBON - -#if GENERATINGCFM - -#if UNIVERSAL_INTERFACES_VERSION < 0x0301 - -pascal OSErr PBXGetVolInfoSync(XVolumeParamPtr paramBlock) -{ - enum - { - kXGetVolInfoSelector = 0x0012, /* Selector for XGetVolInfo */ - - uppFSDispatchProcInfo = kRegisterBased - | REGISTER_RESULT_LOCATION(kRegisterD0) - | RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) - | REGISTER_ROUTINE_PARAMETER(1, kRegisterD1, SIZE_CODE(sizeof(long))) /* trap word */ - | REGISTER_ROUTINE_PARAMETER(2, kRegisterD0, SIZE_CODE(sizeof(long))) /* selector */ - | REGISTER_ROUTINE_PARAMETER(3, kRegisterA0, SIZE_CODE(sizeof(XVolumeParamPtr))) - }; - - return ( CallOSTrapUniversalProc(NGetTrapAddress(_FSDispatch, OSTrap), - uppFSDispatchProcInfo, - _FSDispatch, - kXGetVolInfoSelector, - paramBlock) ); -} -#endif - -#endif - -#endif - -#if __WANTPASCALELIMINATION -#define pascal -#endif - -#if !TARGET_CARBON - -/*****************************************************************************/ - -pascal OSErr XGetVInfo(short volReference, - StringPtr volName, - short *vRefNum, - UnsignedWide *freeBytes, - UnsignedWide *totalBytes) -{ - OSErr result; - long response; - XVolumeParam pb; - - /* See if large volume support is available */ - if ( ( Gestalt(gestaltFSAttr, &response) == noErr ) && ((response & (1L << gestaltFSSupports2TBVols)) != 0) ) - { - /* Large volume support is available */ - pb.ioVRefNum = volReference; - pb.ioNamePtr = volName; - pb.ioXVersion = 0; /* this XVolumeParam version (0) */ - pb.ioVolIndex = 0; /* use ioVRefNum only, return volume name */ - result = PBXGetVolInfoSync(&pb); - if ( result == noErr ) - { - /* The volume name was returned in volName (if not NULL) and */ - /* we have the volume's vRefNum and allocation block size */ - *vRefNum = pb.ioVRefNum; - - /* return the freeBytes and totalBytes */ - *totalBytes = UInt64ToUnsignedWide(pb.ioVTotalBytes); - *freeBytes = UInt64ToUnsignedWide(pb.ioVFreeBytes); - } - } - else - { - /* No large volume support */ - - /* Use HGetVInfo to get the results */ - result = HGetVInfo(volReference, volName, vRefNum, &freeBytes->lo, &totalBytes->lo); - if ( result == noErr ) - { - /* zero the high longs of totalBytes and freeBytes */ - totalBytes->hi = 0; - freeBytes->hi = 0; - } - } - return ( result ); -} -#endif -/*****************************************************************************/ - -pascal OSErr CheckVolLock(ConstStr255Param pathname, - short vRefNum) -{ - HParamBlockRec pb; - OSErr error; - - error = GetVolumeInfoNoName(pathname,vRefNum, &pb); - if ( error == noErr ) - { - if ( (pb.volumeParam.ioVAtrb & 0x0080) != 0 ) - { - error = wPrErr; /* volume locked by hardware */ - } - else if ( (pb.volumeParam.ioVAtrb & 0x8000) != 0 ) - { - error = vLckdErr; /* volume locked by software */ - } - } - - return ( error ); -} - -/*****************************************************************************/ - -#if !TARGET_CARBON - -pascal OSErr GetDriverName(short driverRefNum, - Str255 driverName) -{ - OSErr result; - DCtlHandle theDctl; - DRVRHeaderPtr dHeaderPtr; - - theDctl = GetDCtlEntry(driverRefNum); - if ( theDctl != NULL ) - { - if ( (**theDctl).dCtlFlags & 0x40 ) - { - /* dctlDriver is handle - dereference */ - dHeaderPtr = *((DRVRHeaderHandle)(**theDctl).dCtlDriver); - } - else - { - /* dctlDriver is pointer */ - dHeaderPtr = (DRVRHeaderPtr)(**theDctl).dCtlDriver; - } - BlockMoveData((*dHeaderPtr).drvrName, driverName, (*dHeaderPtr).drvrName[0] + 1); - result = noErr; - } - else - { - driverName[0] = 0; - result = badUnitErr; /* bad reference number */ - } - - return ( result ); -} - -#endif -/*****************************************************************************/ -#if !TARGET_CARBON - -pascal OSErr FindDrive(ConstStr255Param pathname, - short vRefNum, - DrvQElPtr *driveQElementPtr) -{ - OSErr result; - HParamBlockRec hPB; - short driveNumber; - - *driveQElementPtr = NULL; - - /* First, use GetVolumeInfoNoName to determine the volume */ - result = GetVolumeInfoNoName(pathname, vRefNum, &hPB); - if ( result == noErr ) - { - /* - ** The volume can be either online, offline, or ejected. What we find in - ** ioVDrvInfo and ioVDRefNum will tell us which it is. - ** See Inside Macintosh: Files page 2-80 and the Technical Note - ** "FL 34 - VCBs and Drive Numbers : The Real Story" - ** Where we get the drive number depends on the state of the volume. - */ - if ( hPB.volumeParam.ioVDrvInfo != 0 ) - { - /* The volume is online and not ejected */ - /* Get the drive number */ - driveNumber = hPB.volumeParam.ioVDrvInfo; - } - else - { - /* The volume's is either offline or ejected */ - /* in either case, the volume is NOT online */ - - /* Is it ejected or just offline? */ - if ( hPB.volumeParam.ioVDRefNum > 0 ) - { - /* It's ejected, the drive number is ioVDRefNum */ - driveNumber = hPB.volumeParam.ioVDRefNum; - } - else - { - /* It's offline, the drive number is the negative of ioVDRefNum */ - driveNumber = (short)-hPB.volumeParam.ioVDRefNum; - } - } - - /* Get pointer to first element in drive queue */ - *driveQElementPtr = (DrvQElPtr)(GetDrvQHdr()->qHead); - - /* Search for a matching drive number */ - while ( (*driveQElementPtr != NULL) && ((*driveQElementPtr)->dQDrive != driveNumber) ) - { - *driveQElementPtr = (DrvQElPtr)(*driveQElementPtr)->qLink; - } - - if ( *driveQElementPtr == NULL ) - { - /* This should never happen since every volume must have a drive, but... */ - result = nsDrvErr; - } - } - - return ( result ); -} -#endif - -/*****************************************************************************/ -#if !TARGET_CARBON - -pascal OSErr GetDiskBlocks(ConstStr255Param pathname, - short vRefNum, - unsigned long *numBlocks) -{ - /* Various constants for GetDiskBlocks() */ - enum - { - /* return format list status code */ - kFmtLstCode = 6, - - /* reference number of .SONY driver */ - kSonyRefNum = 0xfffb, - - /* values returned by DriveStatus in DrvSts.twoSideFmt */ - kSingleSided = 0, - kDoubleSided = -1, - kSingleSidedSize = 800, /* 400K */ - kDoubleSidedSize = 1600, /* 800K */ - - /* values in DrvQEl.qType */ - kWordDrvSiz = 0, - kLongDrvSiz = 1, - - /* more than enough formatListRecords */ - kMaxFormatListRecs = 16 - }; - - DrvQElPtr driveQElementPtr; - unsigned long blocks; - ParamBlockRec pb; - FormatListRec formatListRecords[kMaxFormatListRecs]; - DrvSts status; - short formatListRecIndex; - OSErr result; - - blocks = 0; - - /* Find the drive queue element for this volume */ - result = FindDrive(pathname, vRefNum, &driveQElementPtr); - - /* - ** Make sure this is a real driver (dQRefNum < 0). - ** AOCE's Mail Enclosures volume uses 0 for dQRefNum which will cause - ** problems if you try to use it as a driver refNum. - */ - if ( (result == noErr) && (driveQElementPtr->dQRefNum >= 0) ) - { - result = paramErr; - } - else - { - /* Attempt to get the drive's format list. */ - /* (see the Technical Note "What Your Sony Drives For You") */ - - pb.cntrlParam.ioVRefNum = driveQElementPtr->dQDrive; - pb.cntrlParam.ioCRefNum = driveQElementPtr->dQRefNum; - pb.cntrlParam.csCode = kFmtLstCode; - pb.cntrlParam.csParam[0] = kMaxFormatListRecs; - *(long *)&pb.cntrlParam.csParam[1] = (long)&formatListRecords[0]; - - result = PBStatusSync(&pb); - - if ( result == noErr ) - { - /* The drive supports ReturnFormatList status call. */ - - /* Get the current disk's size. */ - for( formatListRecIndex = 0; - formatListRecIndex < pb.cntrlParam.csParam[0]; - ++formatListRecIndex ) - { - if ( (formatListRecords[formatListRecIndex].formatFlags & - diCIFmtFlagsCurrentMask) != 0 ) - { - blocks = formatListRecords[formatListRecIndex].volSize; - } - } - if ( blocks == 0 ) - { - /* This should never happen */ - result = paramErr; - } - } - else if ( driveQElementPtr->dQRefNum == (short)kSonyRefNum ) - { - /* The drive is a non-SuperDrive floppy which only supports 400K and 800K disks */ - - result = DriveStatus(driveQElementPtr->dQDrive, &status); - if ( result == noErr ) - { - switch ( status.twoSideFmt ) - { - case kSingleSided: - blocks = kSingleSidedSize; - break; - case kDoubleSided: - blocks = kDoubleSidedSize; - break; - default: - /* This should never happen */ - result = paramErr; - break; - } - } - } - else - { - /* The drive is not a floppy and it doesn't support ReturnFormatList */ - /* so use the dQDrvSz field(s) */ - - result = noErr; /* reset result */ - switch ( driveQElementPtr->qType ) - { - case kWordDrvSiz: - blocks = driveQElementPtr->dQDrvSz; - break; - case kLongDrvSiz: - blocks = ((unsigned long)driveQElementPtr->dQDrvSz2 << 16) + - driveQElementPtr->dQDrvSz; - break; - default: - /* This should never happen */ - result = paramErr; - break; - } - } - } - - if ( result == noErr ) - { - *numBlocks = blocks; - } - - return ( result ); -} -#endif - -/*****************************************************************************/ - -pascal OSErr GetVolFileSystemID(ConstStr255Param pathname, - short vRefNum, - short *fileSystemID) -{ - HParamBlockRec pb; - OSErr error; - - error = GetVolumeInfoNoName(pathname,vRefNum, &pb); - if ( error == noErr ) - { - *fileSystemID = pb.volumeParam.ioVFSID; - } - - return ( error ); -} - -/*****************************************************************************/ -#if !TARGET_CARBON - -pascal OSErr GetVolState(ConstStr255Param pathname, - short vRefNum, - Boolean *volumeOnline, - Boolean *volumeEjected, - Boolean *driveEjectable, - Boolean *driverWantsEject) -{ - HParamBlockRec pb; - short driveNumber; - OSErr error; - - error = GetVolumeInfoNoName(pathname,vRefNum, &pb); - if ( error == noErr ) - { - if ( pb.volumeParam.ioVDrvInfo != 0 ) - { - /* the volume is online and not ejected */ - *volumeOnline = true; - *volumeEjected = false; - - /* Get the drive number */ - driveNumber = pb.volumeParam.ioVDrvInfo; - } - else - { - /* the volume's is either offline or ejected */ - /* in either case, the volume is NOT online */ - *volumeOnline = false; - - /* Is it ejected? */ - *volumeEjected = pb.volumeParam.ioVDRefNum > 0; - - if ( *volumeEjected ) - { - /* If ejected, the drive number is ioVDRefNum */ - driveNumber = pb.volumeParam.ioVDRefNum; - } - else - { - /* If offline, the drive number is the negative of ioVDRefNum */ - driveNumber = (short)-pb.volumeParam.ioVDRefNum; - } - } - - { - DrvQElPtr drvQElem; - - /* Find the drive queue element by searching the drive queue */ - drvQElem = (DrvQElPtr)(GetDrvQHdr()->qHead); - while ( (drvQElem != NULL) && (drvQElem->dQDrive != driveNumber) ) - { - drvQElem = (DrvQElPtr)drvQElem->qLink; - } - - if ( drvQElem != NULL ) - { - /* - ** Each drive queue element is preceded by 4 flag bytes. - ** Byte 1 (the second flag byte) has bits that tell us if a - ** drive is ejectable and if its driver wants an eject call. - ** See Inside Macintosh: Files, page 2-85. - */ - { - Ptr flagBytePtr; - - /* point to byte 1 of the flag bytes */ - flagBytePtr = (Ptr)drvQElem; - flagBytePtr -= 3; - - /* - ** The drive is ejectable if flag byte 1 does not contain - ** 0x08 (nonejectable) or 0x48 (nonejectable, but wants eject call). - */ - - *driveEjectable = (*flagBytePtr != 0x08) && (*flagBytePtr != 0x48); - - /* - ** The driver wants an eject call if flag byte 1 does not contain - ** 0x08 (nonejectable). This may seem like a minor point, but some - ** disk drivers use the Eject request to flush their caches to disk - ** and you wouldn't want to skip that step after unmounting a volume. - */ - - *driverWantsEject = (*flagBytePtr != 0x08); - } - } - else - { - /* Didn't find the drive (this should never happen) */ - *driveEjectable = false; - *driverWantsEject = false; - } - } - } - - return ( error ); -} -#endif -/*****************************************************************************/ -#if !TARGET_CARBON - -pascal OSErr UnmountAndEject(ConstStr255Param pathname, - short vRefNum) -{ - HParamBlockRec pb; - short driveNum; - Boolean ejected, wantsEject; - DrvQElPtr drvQElem; - OSErr error; - - error = GetVolumeInfoNoName(pathname, vRefNum, &pb); - if ( error == noErr ) - { - if ( pb.volumeParam.ioVDrvInfo != 0 ) - { - /* the volume is online and not ejected */ - ejected = false; - - /* Get the drive number */ - driveNum = pb.volumeParam.ioVDrvInfo; - } - else - { - /* the volume is ejected or offline */ - - /* Is it ejected? */ - ejected = pb.volumeParam.ioVDRefNum > 0; - - if ( ejected ) - { - /* If ejected, the drive number is ioVDRefNum */ - driveNum = pb.volumeParam.ioVDRefNum; - } - else - { - /* If offline, the drive number is the negative of ioVDRefNum */ - driveNum = (short)-pb.volumeParam.ioVDRefNum; - } - } - - /* find the drive queue element */ - drvQElem = (DrvQElPtr)(GetDrvQHdr()->qHead); - while ( (drvQElem != NULL) && (drvQElem->dQDrive != driveNum) ) - { - drvQElem = (DrvQElPtr)drvQElem->qLink; - } - - if ( drvQElem != NULL ) - { - /* does the drive want an eject call */ - wantsEject = (*((Ptr)((Ptr)drvQElem - 3)) != 8); - } - else - { - /* didn't find the drive!! */ - wantsEject = false; - } - - /* unmount the volume */ - pb.volumeParam.ioNamePtr = NULL; - /* ioVRefNum is already filled in from PBHGetVInfo */ - error = PBUnmountVol((ParmBlkPtr)&pb); - if ( error == noErr ) - { - if ( wantsEject && !ejected ) - { - /* eject the media from the drive if needed */ - pb.volumeParam.ioVRefNum = driveNum; - error = PBEject((ParmBlkPtr)&pb); - } - } - } - - return ( error ); -} -#endif - -/*****************************************************************************/ - -pascal OSErr OnLine(FSSpecPtr volumes, - short reqVolCount, - short *actVolCount, - short *volIndex) -{ - HParamBlockRec pb; - OSErr error = noErr; - FSSpec *endVolArray; - - if ( *volIndex > 0 ) - { - *actVolCount = 0; - for ( endVolArray = volumes + reqVolCount; (volumes < endVolArray) && (error == noErr); ++volumes ) - { - pb.volumeParam.ioNamePtr = (StringPtr) & volumes->name; - pb.volumeParam.ioVolIndex = *volIndex; - error = PBHGetVInfoSync(&pb); - if ( error == noErr ) - { - volumes->parID = fsRtParID; /* the root directory's parent is 1 */ - volumes->vRefNum = pb.volumeParam.ioVRefNum; - ++*volIndex; - ++*actVolCount; - } - } - } - else - { - error = paramErr; - } - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr SetDefault(short newVRefNum, - long newDirID, - short *oldVRefNum, - long *oldDirID) -{ - OSErr error; - - /* Get the current default volume/directory. */ - error = HGetVol(NULL, oldVRefNum, oldDirID); - if ( error == noErr ) - { - /* Set the new default volume/directory */ - error = HSetVol(NULL, newVRefNum, newDirID); - } - - return ( error ); -} - -/*****************************************************************************/ - -#if !TARGET_CARBON - -pascal OSErr RestoreDefault(short oldVRefNum, - long oldDirID) -{ - OSErr error; - short defaultVRefNum; - long defaultDirID; - long defaultProcID; - - /* Determine if the default volume was a wdRefNum. */ - error = GetWDInfo(oldVRefNum, &defaultVRefNum, &defaultDirID, &defaultProcID); - if ( error == noErr ) - { - /* Restore the old default volume/directory, one way or the other. */ - if ( defaultDirID != fsRtDirID ) - { - /* oldVRefNum was a wdRefNum - use SetVol */ - error = SetVol(NULL, oldVRefNum); - } - else - { - /* oldVRefNum was a real vRefNum - use HSetVol */ - error = HSetVol(NULL, oldVRefNum, oldDirID); - } - } - - return ( error ); -} -#endif -/*****************************************************************************/ - -pascal OSErr GetDInfo(short vRefNum, - long dirID, - ConstStr255Param name, - DInfo *fndrInfo) -{ - CInfoPBRec pb; - OSErr error; - - error = GetCatInfoNoName(vRefNum, dirID, name, &pb); - if ( error == noErr ) - { - if ( (pb.dirInfo.ioFlAttrib & ioDirMask) != 0 ) - { - /* it's a directory, return the DInfo */ - *fndrInfo = pb.dirInfo.ioDrUsrWds; - } - else - { - /* oops, a file was passed */ - error = dirNFErr; - } - } - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr FSpGetDInfo(const FSSpec *spec, - DInfo *fndrInfo) -{ - return ( GetDInfo(spec->vRefNum, spec->parID, spec->name, fndrInfo) ); -} - -/*****************************************************************************/ - -pascal OSErr SetDInfo(short vRefNum, - long dirID, - ConstStr255Param name, - const DInfo *fndrInfo) -{ - CInfoPBRec pb; - Str31 tempName; - OSErr error; - - /* Protection against File Sharing problem */ - if ( (name == NULL) || (name[0] == 0) ) - { - tempName[0] = 0; - pb.dirInfo.ioNamePtr = tempName; - pb.dirInfo.ioFDirIndex = -1; /* use ioDirID */ - } - else - { - pb.dirInfo.ioNamePtr = (StringPtr)name; - pb.dirInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ - } - pb.dirInfo.ioVRefNum = vRefNum; - pb.dirInfo.ioDrDirID = dirID; - error = PBGetCatInfoSync(&pb); - if ( error == noErr ) - { - if ( (pb.dirInfo.ioFlAttrib & ioDirMask) != 0 ) - { - /* it's a directory, set the DInfo */ - if ( pb.dirInfo.ioNamePtr == tempName ) - { - pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID; - } - else - { - pb.dirInfo.ioDrDirID = dirID; - } - pb.dirInfo.ioDrUsrWds = *fndrInfo; - error = PBSetCatInfoSync(&pb); - } - else - { - /* oops, a file was passed */ - error = dirNFErr; - } - } - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr FSpSetDInfo(const FSSpec *spec, - const DInfo *fndrInfo) -{ - return ( SetDInfo(spec->vRefNum, spec->parID, spec->name, fndrInfo) ); -} - -/*****************************************************************************/ - -pascal OSErr GetDirectoryID(short vRefNum, - long dirID, - ConstStr255Param name, - long *theDirID, - Boolean *isDirectory) -{ - CInfoPBRec pb; - OSErr error; - - error = GetCatInfoNoName(vRefNum, dirID, name, &pb); - if ( error == noErr ) - { - *isDirectory = (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0; - if ( *isDirectory ) - { - *theDirID = pb.dirInfo.ioDrDirID; - } - else - { - *theDirID = pb.hFileInfo.ioFlParID; - } - } - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr FSpGetDirectoryID(const FSSpec *spec, - long *theDirID, - Boolean *isDirectory) -{ - return ( GetDirectoryID(spec->vRefNum, spec->parID, spec->name, - theDirID, isDirectory) ); -} - -/*****************************************************************************/ - -pascal OSErr GetDirName(short vRefNum, - long dirID, - Str31 name) -{ - CInfoPBRec pb; - OSErr error; - - if ( name != NULL ) - { - pb.dirInfo.ioNamePtr = name; - pb.dirInfo.ioVRefNum = vRefNum; - pb.dirInfo.ioDrDirID = dirID; - pb.dirInfo.ioFDirIndex = -1; /* get information about ioDirID */ - error = PBGetCatInfoSync(&pb); - } - else - { - error = paramErr; - } - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr GetIOACUser(short vRefNum, - long dirID, - ConstStr255Param name, - SInt8 *ioACUser) -{ - CInfoPBRec pb; - OSErr error; - - /* Clear ioACUser before calling PBGetCatInfo since some file systems - ** don't bother to set or clear this field. If ioACUser isn't set by the - ** file system, then you'll get the zero value back (full access) which - ** is the access you have on volumes that don't support ioACUser. - */ - pb.dirInfo.ioACUser = 0; /* ioACUser used to be filler2 */ - error = GetCatInfoNoName(vRefNum, dirID, name, &pb); - if ( error == noErr ) - { - if ( (pb.hFileInfo.ioFlAttrib & ioDirMask) == 0 ) - { - /* oops, a file was passed */ - error = dirNFErr; - } - else - { - *ioACUser = pb.dirInfo.ioACUser; - } - } - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr FSpGetIOACUser(const FSSpec *spec, - SInt8 *ioACUser) -{ - return ( GetIOACUser(spec->vRefNum, spec->parID, spec->name, ioACUser) ); -} - -/*****************************************************************************/ - -pascal OSErr GetParentID(short vRefNum, - long dirID, - ConstStr255Param name, - long *parID) -{ - CInfoPBRec pb; - Str31 tempName; - OSErr error; - short realVRefNum; - - /* Protection against File Sharing problem */ - if ( (name == NULL) || (name[0] == 0) ) - { - tempName[0] = 0; - pb.hFileInfo.ioNamePtr = tempName; - pb.hFileInfo.ioFDirIndex = -1; /* use ioDirID */ - } - else - { - pb.hFileInfo.ioNamePtr = (StringPtr)name; - pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ - } - pb.hFileInfo.ioVRefNum = vRefNum; - pb.hFileInfo.ioDirID = dirID; - error = PBGetCatInfoSync(&pb); - if ( error == noErr ) - { - /* - ** There's a bug in HFS where the wrong parent dir ID can be - ** returned if multiple separators are used at the end of a - ** pathname. For example, if the pathname: - ** 'volumeName:System Folder:Extensions::' - ** is passed, the directory ID of the Extensions folder is - ** returned in the ioFlParID field instead of fsRtDirID. Since - ** multiple separators at the end of a pathname always specifies - ** a directory, we only need to work-around cases where the - ** object is a directory and there are multiple separators at - ** the end of the name parameter. - */ - if ( (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0 ) - { - /* Its a directory */ - - /* is there a pathname? */ - if ( pb.hFileInfo.ioNamePtr == name ) - { - /* could it contain multiple separators? */ - if ( name[0] >= 2 ) - { - /* does it contain multiple separators at the end? */ - if ( (name[name[0]] == ':') && (name[name[0] - 1] == ':') ) - { - /* OK, then do the extra stuff to get the correct parID */ - - /* Get the real vRefNum (this should not fail) */ - error = DetermineVRefNum(name, vRefNum, &realVRefNum); - if ( error == noErr ) - { - /* we don't need the parent's name, but add protect against File Sharing problem */ - tempName[0] = 0; - pb.dirInfo.ioNamePtr = tempName; - pb.dirInfo.ioVRefNum = realVRefNum; - /* pb.dirInfo.ioDrDirID already contains the */ - /* dirID of the directory object */ - pb.dirInfo.ioFDirIndex = -1; /* get information about ioDirID */ - error = PBGetCatInfoSync(&pb); - /* now, pb.dirInfo.ioDrParID contains the correct parID */ - } - } - } - } - } - - if ( error == noErr ) - { - /* if no errors, then pb.hFileInfo.ioFlParID (pb.dirInfo.ioDrParID) */ - /* contains the parent ID */ - *parID = pb.hFileInfo.ioFlParID; - } - } - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr GetFilenameFromPathname(ConstStr255Param pathname, - Str255 filename) -{ - short index; - short nameEnd; - OSErr error; - - /* default to no filename */ - filename[0] = 0; - - /* check for no pathname */ - if ( pathname != NULL ) - { - /* get string length */ - index = pathname[0]; - - /* check for empty string */ - if ( index != 0 ) - { - /* skip over last trailing colon (if any) */ - if ( pathname[index] == ':' ) - { - --index; - } - - /* save the end of the string */ - nameEnd = index; - - /* if pathname ends with multiple colons, then this pathname refers */ - /* to a directory, not a file */ - if ( pathname[index] != ':' ) - { - /* parse backwards until we find a colon or hit the beginning of the pathname */ - while ( (index != 0) && (pathname[index] != ':') ) - { - --index; - } - - /* if we parsed to the beginning of the pathname and the pathname ended */ - /* with a colon, then pathname is a full pathname to a volume, not a file */ - if ( (index != 0) || (pathname[pathname[0]] != ':') ) - { - /* get the filename and return noErr */ - filename[0] = (char)(nameEnd - index); - BlockMoveData(&pathname[index+1], &filename[1], nameEnd - index); - error = noErr; - } - else - { - /* pathname to a volume, not a file */ - error = notAFileErr; - } - } - else - { - /* directory, not a file */ - error = notAFileErr; - } - } - else - { - /* empty string isn't a file */ - error = notAFileErr; - } - } - else - { - /* NULL pathname isn't a file */ - error = notAFileErr; - } - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr GetObjectLocation(short vRefNum, - long dirID, - ConstStr255Param pathname, - short *realVRefNum, - long *realParID, - Str255 realName, - Boolean *isDirectory) -{ - OSErr error; - CInfoPBRec pb; - Str255 tempPathname; - - /* clear results */ - *realVRefNum = 0; - *realParID = 0; - realName[0] = 0; - - /* - ** Get the real vRefNum - */ - error = DetermineVRefNum(pathname, vRefNum, realVRefNum); - if ( error == noErr ) - { - /* - ** Determine if the object already exists and if so, - ** get the real parent directory ID if it's a file - */ - - /* Protection against File Sharing problem */ - if ( (pathname == NULL) || (pathname[0] == 0) ) - { - tempPathname[0] = 0; - pb.hFileInfo.ioNamePtr = tempPathname; - pb.hFileInfo.ioFDirIndex = -1; /* use ioDirID */ - } - else - { - pb.hFileInfo.ioNamePtr = (StringPtr)pathname; - pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ - } - pb.hFileInfo.ioVRefNum = vRefNum; - pb.hFileInfo.ioDirID = dirID; - error = PBGetCatInfoSync(&pb); - if ( error == noErr ) - { - /* - ** The file system object is present and we have the file's real parID - */ - - /* Is it a directory or a file? */ - *isDirectory = (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0; - if ( *isDirectory ) - { - /* - ** It's a directory, get its name and parent dirID, and then we're done - */ - - pb.dirInfo.ioNamePtr = realName; - pb.dirInfo.ioVRefNum = *realVRefNum; - /* pb.dirInfo.ioDrDirID already contains the dirID of the directory object */ - pb.dirInfo.ioFDirIndex = -1; /* get information about ioDirID */ - error = PBGetCatInfoSync(&pb); - - /* get the parent ID here, because the file system can return the */ - /* wrong parent ID from the last call. */ - *realParID = pb.dirInfo.ioDrParID; - } - else - { - /* - ** It's a file - use the parent directory ID from the last call - ** to GetCatInfoparse, get the file name, and then we're done - */ - *realParID = pb.hFileInfo.ioFlParID; - error = GetFilenameFromPathname(pathname, realName); - } - } - else if ( error == fnfErr ) - { - /* - ** The file system object is not present - see if its parent is present - */ - - /* - ** Parse to get the object name from end of pathname - */ - error = GetFilenameFromPathname(pathname, realName); - - /* if we can't get the object name from the end, we can't continue */ - if ( error == noErr ) - { - /* - ** What we want now is the pathname minus the object name - ** for example: - ** if pathname is 'vol:dir:file' tempPathname becomes 'vol:dir:' - ** if pathname is 'vol:dir:file:' tempPathname becomes 'vol:dir:' - ** if pathname is ':dir:file' tempPathname becomes ':dir:' - ** if pathname is ':dir:file:' tempPathname becomes ':dir:' - ** if pathname is ':file' tempPathname becomes ':' - ** if pathname is 'file or file:' tempPathname becomes '' - */ - - /* get a copy of the pathname */ - BlockMoveData(pathname, tempPathname, pathname[0] + 1); - - /* remove the object name */ - tempPathname[0] -= realName[0]; - /* and the trailing colon (if any) */ - if ( pathname[pathname[0]] == ':' ) - { - --tempPathname[0]; - } - - /* OK, now get the parent's directory ID */ - - /* Protection against File Sharing problem */ - pb.hFileInfo.ioNamePtr = (StringPtr)tempPathname; - if ( tempPathname[0] != 0 ) - { - pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ - } - else - { - pb.hFileInfo.ioFDirIndex = -1; /* use ioDirID */ - } - pb.hFileInfo.ioVRefNum = vRefNum; - pb.hFileInfo.ioDirID = dirID; - error = PBGetCatInfoSync(&pb); - *realParID = pb.dirInfo.ioDrDirID; - - *isDirectory = false; /* we don't know what the object is really going to be */ - } - - if ( error != noErr ) - { - error = dirNFErr; /* couldn't find parent directory */ - } - else - { - error = fnfErr; /* we found the parent, but not the file */ - } - } - } - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr GetDirItems(short vRefNum, - long dirID, - ConstStr255Param name, - Boolean getFiles, - Boolean getDirectories, - FSSpecPtr items, - short reqItemCount, - short *actItemCount, - short *itemIndex) /* start with 1, then use what's returned */ -{ - CInfoPBRec pb; - OSErr error; - long theDirID; - Boolean isDirectory; - FSSpec *endItemsArray; - - if ( *itemIndex > 0 ) - { - /* NOTE: If I could be sure that the caller passed a real vRefNum and real directory */ - /* to this routine, I could rip out calls to DetermineVRefNum and GetDirectoryID and this */ - /* routine would be much faster because of the overhead of DetermineVRefNum and */ - /* GetDirectoryID and because GetDirectoryID blows away the directory index hint the Macintosh */ - /* file system keeps for indexed calls. I can't be sure, so for maximum throughput, */ - /* pass a big array of FSSpecs so you can get the directory's contents with few calls */ - /* to this routine. */ - - /* get the real volume reference number */ - error = DetermineVRefNum(name, vRefNum, &pb.hFileInfo.ioVRefNum); - if ( error == noErr ) - { - /* and the real directory ID of this directory (and make sure it IS a directory) */ - error = GetDirectoryID(vRefNum, dirID, name, &theDirID, &isDirectory); - if ( error == noErr ) - { - if ( isDirectory ) - { - *actItemCount = 0; - endItemsArray = items + reqItemCount; - while ( (items < endItemsArray) && (error == noErr) ) - { - pb.hFileInfo.ioNamePtr = (StringPtr) &items->name; - pb.hFileInfo.ioDirID = theDirID; - pb.hFileInfo.ioFDirIndex = *itemIndex; - error = PBGetCatInfoSync(&pb); - if ( error == noErr ) - { - items->parID = pb.hFileInfo.ioFlParID; /* return item's parID */ - items->vRefNum = pb.hFileInfo.ioVRefNum; /* return item's vRefNum */ - ++*itemIndex; /* prepare to get next item in directory */ - - if ( (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0 ) - { - if ( getDirectories ) - { - ++*actItemCount; /* keep this item */ - ++items; /* point to next item */ - } - } - else - { - if ( getFiles ) - { - ++*actItemCount; /* keep this item */ - ++items; /* point to next item */ - } - } - } - } - } - else - { - /* it wasn't a directory */ - error = dirNFErr; - } - } - } - } - else - { - /* bad itemIndex */ - error = paramErr; - } - - return ( error ); -} - -/*****************************************************************************/ - -static void DeleteLevel(long dirToDelete, - DeleteEnumGlobalsPtr theGlobals) -{ - long savedDir; - - do - { - /* prepare to delete directory */ - theGlobals->myPB.ciPB.dirInfo.ioNamePtr = (StringPtr)&theGlobals->itemName; - theGlobals->myPB.ciPB.dirInfo.ioFDirIndex = 1; /* get first item */ - theGlobals->myPB.ciPB.dirInfo.ioDrDirID = dirToDelete; /* in this directory */ - theGlobals->error = PBGetCatInfoSync(&(theGlobals->myPB.ciPB)); - if ( theGlobals->error == noErr ) - { - savedDir = dirToDelete; - /* We have an item. Is it a file or directory? */ - if ( (theGlobals->myPB.ciPB.dirInfo.ioFlAttrib & ioDirMask) != 0 ) - { - /* it's a directory */ - savedDir = theGlobals->myPB.ciPB.dirInfo.ioDrDirID; /* save dirID of directory instead */ - DeleteLevel(theGlobals->myPB.ciPB.dirInfo.ioDrDirID, theGlobals); /* Delete its contents */ - theGlobals->myPB.ciPB.dirInfo.ioNamePtr = NULL; /* prepare to delete directory */ - } - if ( theGlobals->error == noErr ) - { - theGlobals->myPB.ciPB.dirInfo.ioDrDirID = savedDir; /* restore dirID */ - theGlobals->myPB.hPB.fileParam.ioFVersNum = 0; /* just in case it's used on an MFS volume... */ - theGlobals->error = PBHDeleteSync(&(theGlobals->myPB.hPB)); /* delete this item */ - if ( theGlobals->error == fLckdErr ) - { - (void) PBHRstFLockSync(&(theGlobals->myPB.hPB)); /* unlock it */ - theGlobals->error = PBHDeleteSync(&(theGlobals->myPB.hPB)); /* and try again */ - } - } - } - } while ( theGlobals->error == noErr ); - - if ( theGlobals->error == fnfErr ) - { - theGlobals->error = noErr; - } -} - -/*****************************************************************************/ - -pascal OSErr DeleteDirectoryContents(short vRefNum, - long dirID, - ConstStr255Param name) -{ - DeleteEnumGlobals theGlobals; - Boolean isDirectory; - OSErr error; - - /* Get the real dirID and make sure it is a directory. */ - error = GetDirectoryID(vRefNum, dirID, name, &dirID, &isDirectory); - if ( error == noErr ) - { - if ( isDirectory ) - { - /* Get the real vRefNum */ - error = DetermineVRefNum(name, vRefNum, &vRefNum); - if ( error == noErr ) - { - /* Set up the globals we need to access from the recursive routine. */ - theGlobals.myPB.ciPB.dirInfo.ioVRefNum = vRefNum; - - /* Here we go into recursion land... */ - DeleteLevel(dirID, &theGlobals); - error = theGlobals.error; - } - } - else - { - error = dirNFErr; - } - } - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr DeleteDirectory(short vRefNum, - long dirID, - ConstStr255Param name) -{ - OSErr error; - - /* Make sure a directory was specified and then delete its contents */ - error = DeleteDirectoryContents(vRefNum, dirID, name); - if ( error == noErr ) - { - error = HDelete(vRefNum, dirID, name); - if ( error == fLckdErr ) - { - (void) HRstFLock(vRefNum, dirID, name); /* unlock the directory locked by AppleShare */ - error = HDelete(vRefNum, dirID, name); /* and try again */ - } - } - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr CheckObjectLock(short vRefNum, - long dirID, - ConstStr255Param name) -{ - CInfoPBRec pb; - OSErr error; - - error = GetCatInfoNoName(vRefNum, dirID, name, &pb); - if ( error == noErr ) - { - /* check locked bit */ - if ( (pb.hFileInfo.ioFlAttrib & 0x01) != 0 ) - { - error = fLckdErr; - } - } - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr FSpCheckObjectLock(const FSSpec *spec) -{ - return ( CheckObjectLock(spec->vRefNum, spec->parID, spec->name) ); -} - -/*****************************************************************************/ - -pascal OSErr GetFileSize(short vRefNum, - long dirID, - ConstStr255Param fileName, - long *dataSize, - long *rsrcSize) -{ - HParamBlockRec pb; - OSErr error; - - pb.fileParam.ioNamePtr = (StringPtr)fileName; - pb.fileParam.ioVRefNum = vRefNum; - pb.fileParam.ioFVersNum = 0; - pb.fileParam.ioDirID = dirID; - pb.fileParam.ioFDirIndex = 0; - error = PBHGetFInfoSync(&pb); - if ( error == noErr ) - { - *dataSize = pb.fileParam.ioFlLgLen; - *rsrcSize = pb.fileParam.ioFlRLgLen; - } - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr FSpGetFileSize(const FSSpec *spec, - long *dataSize, - long *rsrcSize) -{ - return ( GetFileSize(spec->vRefNum, spec->parID, spec->name, dataSize, rsrcSize) ); -} - -/*****************************************************************************/ - -pascal OSErr BumpDate(short vRefNum, - long dirID, - ConstStr255Param name) -/* Given a file or directory, change its modification date to the current date/time. */ -{ - CInfoPBRec pb; - Str31 tempName; - OSErr error; - unsigned long secs; - - /* Protection against File Sharing problem */ - if ( (name == NULL) || (name[0] == 0) ) - { - tempName[0] = 0; - pb.hFileInfo.ioNamePtr = tempName; - pb.hFileInfo.ioFDirIndex = -1; /* use ioDirID */ - } - else - { - pb.hFileInfo.ioNamePtr = (StringPtr)name; - pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ - } - pb.hFileInfo.ioVRefNum = vRefNum; - pb.hFileInfo.ioDirID = dirID; - error = PBGetCatInfoSync(&pb); - if ( error == noErr ) - { - GetDateTime(&secs); - /* set mod date to current date, or one second into the future - if mod date = current date */ - pb.hFileInfo.ioFlMdDat = (secs == pb.hFileInfo.ioFlMdDat) ? (++secs) : (secs); - if ( pb.dirInfo.ioNamePtr == tempName ) - { - pb.hFileInfo.ioDirID = pb.hFileInfo.ioFlParID; - } - else - { - pb.hFileInfo.ioDirID = dirID; - } - error = PBSetCatInfoSync(&pb); - } - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr FSpBumpDate(const FSSpec *spec) -{ - return ( BumpDate(spec->vRefNum, spec->parID, spec->name) ); -} - -/*****************************************************************************/ - -pascal OSErr ChangeCreatorType(short vRefNum, - long dirID, - ConstStr255Param name, - OSType creator, - OSType fileType) -{ - CInfoPBRec pb; - OSErr error; - short realVRefNum; - long parID; - - pb.hFileInfo.ioNamePtr = (StringPtr)name; - pb.hFileInfo.ioVRefNum = vRefNum; - pb.hFileInfo.ioDirID = dirID; - pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ - error = PBGetCatInfoSync(&pb); - if ( error == noErr ) - { - if ( (pb.hFileInfo.ioFlAttrib & ioDirMask) == 0 ) /* if file */ - { - parID = pb.hFileInfo.ioFlParID; /* save parent dirID for BumpDate call */ - - /* If creator not 0x00000000, change creator */ - if ( creator != (OSType)0x00000000 ) - { - pb.hFileInfo.ioFlFndrInfo.fdCreator = creator; - } - - /* If fileType not 0x00000000, change fileType */ - if ( fileType != (OSType)0x00000000 ) - { - pb.hFileInfo.ioFlFndrInfo.fdType = fileType; - } - - pb.hFileInfo.ioDirID = dirID; - error = PBSetCatInfoSync(&pb); /* now, save the new information back to disk */ - - if ( (error == noErr) && (parID != fsRtParID) ) /* can't bump fsRtParID */ - { - /* get the real vRefNum in case a full pathname was passed */ - error = DetermineVRefNum(name, vRefNum, &realVRefNum); - if ( error == noErr ) - { - error = BumpDate(realVRefNum, parID, NULL); - /* and bump the parent directory's mod date to wake up the Finder */ - /* to the change we just made */ - } - } - } - else - { - /* it was a directory, not a file */ - error = notAFileErr; - } - } - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr FSpChangeCreatorType(const FSSpec *spec, - OSType creator, - OSType fileType) -{ - return ( ChangeCreatorType(spec->vRefNum, spec->parID, spec->name, creator, fileType) ); -} - -/*****************************************************************************/ - -pascal OSErr ChangeFDFlags(short vRefNum, - long dirID, - ConstStr255Param name, - Boolean setBits, - unsigned short flagBits) -{ - CInfoPBRec pb; - Str31 tempName; - OSErr error; - short realVRefNum; - long parID; - - /* Protection against File Sharing problem */ - if ( (name == NULL) || (name[0] == 0) ) - { - tempName[0] = 0; - pb.hFileInfo.ioNamePtr = tempName; - pb.hFileInfo.ioFDirIndex = -1; /* use ioDirID */ - } - else - { - pb.hFileInfo.ioNamePtr = (StringPtr)name; - pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ - } - pb.hFileInfo.ioVRefNum = vRefNum; - pb.hFileInfo.ioDirID = dirID; - error = PBGetCatInfoSync(&pb); - if ( error == noErr ) - { - parID = pb.hFileInfo.ioFlParID; /* save parent dirID for BumpDate call */ - - /* set or clear the appropriate bits in the Finder flags */ - if ( setBits ) - { - /* OR in the bits */ - pb.hFileInfo.ioFlFndrInfo.fdFlags |= flagBits; - } - else - { - /* AND out the bits */ - pb.hFileInfo.ioFlFndrInfo.fdFlags &= ~flagBits; - } - - if ( pb.dirInfo.ioNamePtr == tempName ) - { - pb.hFileInfo.ioDirID = pb.hFileInfo.ioFlParID; - } - else - { - pb.hFileInfo.ioDirID = dirID; - } - - error = PBSetCatInfoSync(&pb); /* now, save the new information back to disk */ - - if ( (error == noErr) && (parID != fsRtParID) ) /* can't bump fsRtParID */ - { - /* get the real vRefNum in case a full pathname was passed */ - error = DetermineVRefNum(name, vRefNum, &realVRefNum); - if ( error == noErr ) - { - error = BumpDate(realVRefNum, parID, NULL); - /* and bump the parent directory's mod date to wake up the Finder */ - /* to the change we just made */ - } - } - } - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr FSpChangeFDFlags(const FSSpec *spec, - Boolean setBits, - unsigned short flagBits) -{ - return ( ChangeFDFlags(spec->vRefNum, spec->parID, spec->name, setBits, flagBits) ); -} - -/*****************************************************************************/ - -pascal OSErr SetIsInvisible(short vRefNum, - long dirID, - ConstStr255Param name) - /* Given a file or directory, make it invisible. */ -{ - return ( ChangeFDFlags(vRefNum, dirID, name, true, kIsInvisible) ); -} - -/*****************************************************************************/ - -pascal OSErr FSpSetIsInvisible(const FSSpec *spec) - /* Given a file or directory, make it invisible. */ -{ - return ( ChangeFDFlags(spec->vRefNum, spec->parID, spec->name, true, kIsInvisible) ); -} - -/*****************************************************************************/ - -pascal OSErr ClearIsInvisible(short vRefNum, - long dirID, - ConstStr255Param name) - /* Given a file or directory, make it visible. */ -{ - return ( ChangeFDFlags(vRefNum, dirID, name, false, kIsInvisible) ); -} - -/*****************************************************************************/ - -pascal OSErr FSpClearIsInvisible(const FSSpec *spec) - /* Given a file or directory, make it visible. */ -{ - return ( ChangeFDFlags(spec->vRefNum, spec->parID, spec->name, false, kIsInvisible) ); -} - -/*****************************************************************************/ - -pascal OSErr SetNameLocked(short vRefNum, - long dirID, - ConstStr255Param name) - /* Given a file or directory, lock its name. */ -{ - return ( ChangeFDFlags(vRefNum, dirID, name, true, kNameLocked) ); -} - -/*****************************************************************************/ - -pascal OSErr FSpSetNameLocked(const FSSpec *spec) - /* Given a file or directory, lock its name. */ -{ - return ( ChangeFDFlags(spec->vRefNum, spec->parID, spec->name, true, kNameLocked) ); -} - -/*****************************************************************************/ - -pascal OSErr ClearNameLocked(short vRefNum, - long dirID, - ConstStr255Param name) - /* Given a file or directory, unlock its name. */ -{ - return ( ChangeFDFlags(vRefNum, dirID, name, false, kNameLocked) ); -} - -/*****************************************************************************/ - -pascal OSErr FSpClearNameLocked(const FSSpec *spec) - /* Given a file or directory, unlock its name. */ -{ - return ( ChangeFDFlags(spec->vRefNum, spec->parID, spec->name, false, kNameLocked) ); -} - -/*****************************************************************************/ - -pascal OSErr SetIsStationery(short vRefNum, - long dirID, - ConstStr255Param name) - /* Given a file, make it a stationery pad. */ -{ - return ( ChangeFDFlags(vRefNum, dirID, name, true, kIsStationery) ); -} - -/*****************************************************************************/ - -pascal OSErr FSpSetIsStationery(const FSSpec *spec) - /* Given a file, make it a stationery pad. */ -{ - return ( ChangeFDFlags(spec->vRefNum, spec->parID, spec->name, true, kIsStationery) ); -} - -/*****************************************************************************/ - -pascal OSErr ClearIsStationery(short vRefNum, - long dirID, - ConstStr255Param name) - /* Given a file, clear the stationery bit. */ -{ - return ( ChangeFDFlags(vRefNum, dirID, name, false, kIsStationery) ); -} - -/*****************************************************************************/ - -pascal OSErr FSpClearIsStationery(const FSSpec *spec) - /* Given a file, clear the stationery bit. */ -{ - return ( ChangeFDFlags(spec->vRefNum, spec->parID, spec->name, false, kIsStationery) ); -} - -/*****************************************************************************/ - -pascal OSErr SetHasCustomIcon(short vRefNum, - long dirID, - ConstStr255Param name) - /* Given a file or directory, indicate that it has a custom icon. */ -{ - return ( ChangeFDFlags(vRefNum, dirID, name, true, kHasCustomIcon) ); -} - -/*****************************************************************************/ - -pascal OSErr FSpSetHasCustomIcon(const FSSpec *spec) - /* Given a file or directory, indicate that it has a custom icon. */ -{ - return ( ChangeFDFlags(spec->vRefNum, spec->parID, spec->name, true, kHasCustomIcon) ); -} - -/*****************************************************************************/ - -pascal OSErr ClearHasCustomIcon(short vRefNum, - long dirID, - ConstStr255Param name) - /* Given a file or directory, indicate that it does not have a custom icon. */ -{ - return ( ChangeFDFlags(vRefNum, dirID, name, false, kHasCustomIcon) ); -} - -/*****************************************************************************/ - -pascal OSErr FSpClearHasCustomIcon(const FSSpec *spec) - /* Given a file or directory, indicate that it does not have a custom icon. */ -{ - return ( ChangeFDFlags(spec->vRefNum, spec->parID, spec->name, false, kHasCustomIcon) ); -} - -/*****************************************************************************/ - -pascal OSErr ClearHasBeenInited(short vRefNum, - long dirID, - ConstStr255Param name) - /* Given a file, clear its "has been inited" bit. */ -{ - return ( ChangeFDFlags(vRefNum, dirID, name, false, kHasBeenInited) ); -} - -/*****************************************************************************/ - -pascal OSErr FSpClearHasBeenInited(const FSSpec *spec) - /* Given a file, clear its "has been inited" bit. */ -{ - return ( ChangeFDFlags(spec->vRefNum, spec->parID, spec->name, false, kHasBeenInited) ); -} - -/*****************************************************************************/ - -pascal OSErr CopyFileMgrAttributes(short srcVRefNum, - long srcDirID, - ConstStr255Param srcName, - short dstVRefNum, - long dstDirID, - ConstStr255Param dstName, - Boolean copyLockBit) -{ - UniversalFMPB pb; - Str31 tempName; - OSErr error; - Boolean objectIsDirectory; - - pb.ciPB.hFileInfo.ioVRefNum = srcVRefNum; - pb.ciPB.hFileInfo.ioDirID = srcDirID; - - /* Protection against File Sharing problem */ - if ( (srcName == NULL) || (srcName[0] == 0) ) - { - tempName[0] = 0; - pb.ciPB.hFileInfo.ioNamePtr = tempName; - pb.ciPB.hFileInfo.ioFDirIndex = -1; /* use ioDirID */ - } - else - { - pb.ciPB.hFileInfo.ioNamePtr = (StringPtr)srcName; - pb.ciPB.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ - } - error = PBGetCatInfoSync(&pb.ciPB); - if ( error == noErr ) - { - objectIsDirectory = ( (pb.ciPB.hFileInfo.ioFlAttrib & ioDirMask) != 0 ); - pb.ciPB.hFileInfo.ioVRefNum = dstVRefNum; - pb.ciPB.hFileInfo.ioDirID = dstDirID; - if ( (dstName != NULL) && (dstName[0] == 0) ) - { - pb.ciPB.hFileInfo.ioNamePtr = NULL; - } - else - { - pb.ciPB.hFileInfo.ioNamePtr = (StringPtr)dstName; - } - /* don't copy the hasBeenInited bit */ - pb.ciPB.hFileInfo.ioFlFndrInfo.fdFlags = ( pb.ciPB.hFileInfo.ioFlFndrInfo.fdFlags & 0xfeff ); - error = PBSetCatInfoSync(&pb.ciPB); - if ( (error == noErr) && (copyLockBit) && ((pb.ciPB.hFileInfo.ioFlAttrib & 0x01) != 0) ) - { - pb.hPB.fileParam.ioFVersNum = 0; - error = PBHSetFLockSync(&pb.hPB); - if ( (error != noErr) && (objectIsDirectory) ) - { - error = noErr; /* ignore lock errors if destination is directory */ - } - } - } - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr FSpCopyFileMgrAttributes(const FSSpec *srcSpec, - const FSSpec *dstSpec, - Boolean copyLockBit) -{ - return ( CopyFileMgrAttributes(srcSpec->vRefNum, srcSpec->parID, srcSpec->name, - dstSpec->vRefNum, dstSpec->parID, dstSpec->name, - copyLockBit) ); -} - -/*****************************************************************************/ - -pascal OSErr HOpenAware(short vRefNum, - long dirID, - ConstStr255Param fileName, - short denyModes, - short *refNum) -{ - HParamBlockRec pb; - OSErr error; - GetVolParmsInfoBuffer volParmsInfo; - long infoSize = sizeof(GetVolParmsInfoBuffer); - - pb.ioParam.ioMisc = NULL; - pb.fileParam.ioFVersNum = 0; - pb.fileParam.ioNamePtr = (StringPtr)fileName; - pb.fileParam.ioVRefNum = vRefNum; - pb.fileParam.ioDirID = dirID; - - /* get volume attributes */ - /* this preflighting is needed because Foreign File Access based file systems don't */ - /* return the correct error result to the OpenDeny call */ - error = HGetVolParms(fileName, vRefNum, &volParmsInfo, &infoSize); - if ( (error == noErr) && hasOpenDeny(volParmsInfo) ) - { - /* if volume supports OpenDeny, use it and return */ - pb.accessParam.ioDenyModes = denyModes; - error = PBHOpenDenySync(&pb); - *refNum = pb.ioParam.ioRefNum; - } - else if ( (error == noErr) || (error == paramErr) ) /* paramErr is OK, it just means this volume doesn't support GetVolParms */ - { - /* OpenDeny isn't supported, so try File Manager Open functions */ - - /* If request includes write permission, then see if the volume is */ - /* locked by hardware or software. The HFS file system doesn't check */ - /* for this when a file is opened - you only find out later when you */ - /* try to write and the write fails with a wPrErr or a vLckdErr. */ - - if ( (denyModes & dmWr) != 0 ) - { - error = CheckVolLock(fileName, vRefNum); - } - else - { - error = noErr; - } - - if ( error == noErr ) - { - /* Set File Manager permissions to closest thing possible */ - if ( (denyModes == dmWr) || (denyModes == dmRdWr) ) - { - pb.ioParam.ioPermssn = fsRdWrShPerm; - } - else - { - pb.ioParam.ioPermssn = denyModes % 4; - } - - error = PBHOpenDFSync(&pb); /* Try OpenDF */ - if ( error == paramErr ) - { - error = PBHOpenSync(&pb); /* OpenDF not supported, so try Open */ - } - *refNum = pb.ioParam.ioRefNum; - } - } - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr FSpOpenAware(const FSSpec *spec, - short denyModes, - short *refNum) -{ - return ( HOpenAware(spec->vRefNum, spec->parID, spec->name, denyModes, refNum) ); -} - -/*****************************************************************************/ - -pascal OSErr HOpenRFAware(short vRefNum, - long dirID, - ConstStr255Param fileName, - short denyModes, - short *refNum) -{ - HParamBlockRec pb; - OSErr error; - GetVolParmsInfoBuffer volParmsInfo; - long infoSize = sizeof(GetVolParmsInfoBuffer); - - pb.ioParam.ioMisc = NULL; - pb.fileParam.ioFVersNum = 0; - pb.fileParam.ioNamePtr = (StringPtr)fileName; - pb.fileParam.ioVRefNum = vRefNum; - pb.fileParam.ioDirID = dirID; - - /* get volume attributes */ - /* this preflighting is needed because Foreign File Access based file systems don't */ - /* return the correct error result to the OpenRFDeny call */ - error = HGetVolParms(fileName, vRefNum, &volParmsInfo, &infoSize); - if ( (error == noErr) && hasOpenDeny(volParmsInfo) ) - { - /* if volume supports OpenRFDeny, use it and return */ - if ( hasOpenDeny(volParmsInfo) ) - { - pb.accessParam.ioDenyModes = denyModes; - error = PBHOpenRFDenySync(&pb); - *refNum = pb.ioParam.ioRefNum; - } - } - else if ( (error == noErr) || (error == paramErr) ) /* paramErr is OK, it just means this volume doesn't support GetVolParms */ - { - /* OpenRFDeny isn't supported, so try File Manager OpenRF function */ - - /* If request includes write permission, then see if the volume is */ - /* locked by hardware or software. The HFS file system doesn't check */ - /* for this when a file is opened - you only find out later when you */ - /* try to write and the write fails with a wPrErr or a vLckdErr. */ - - if ( (denyModes & dmWr) != 0 ) - { - error = CheckVolLock(fileName, vRefNum); - } - else - { - error = noErr; - } - - if ( error == noErr ) - { - /* Set File Manager permissions to closest thing possible */ - if ( (denyModes == dmWr) || (denyModes == dmRdWr) ) - { - pb.ioParam.ioPermssn = fsRdWrShPerm; - } - else - { - pb.ioParam.ioPermssn = denyModes % 4; - } - - error = PBHOpenRFSync(&pb); - *refNum = pb.ioParam.ioRefNum; - } - } - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr FSpOpenRFAware(const FSSpec *spec, - short denyModes, - short *refNum) -{ - return ( HOpenRFAware(spec->vRefNum, spec->parID, spec->name, denyModes, refNum) ); -} - -/*****************************************************************************/ - -pascal OSErr FSReadNoCache(short refNum, - long *count, - void *buffPtr) -{ - ParamBlockRec pb; - OSErr error; - - pb.ioParam.ioRefNum = refNum; - pb.ioParam.ioBuffer = (Ptr)buffPtr; - pb.ioParam.ioReqCount = *count; - pb.ioParam.ioPosMode = fsAtMark + 0x0020; /* fsAtMark + noCacheBit */ - pb.ioParam.ioPosOffset = 0; - error = PBReadSync(&pb); - *count = pb.ioParam.ioActCount; /* always return count */ - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr FSWriteNoCache(short refNum, - long *count, - const void *buffPtr) -{ - ParamBlockRec pb; - OSErr error; - - pb.ioParam.ioRefNum = refNum; - pb.ioParam.ioBuffer = (Ptr)buffPtr; - pb.ioParam.ioReqCount = *count; - pb.ioParam.ioPosMode = fsAtMark + 0x0020; /* fsAtMark + noCacheBit */ - pb.ioParam.ioPosOffset = 0; - error = PBWriteSync(&pb); - *count = pb.ioParam.ioActCount; /* always return count */ - return ( error ); -} - -/*****************************************************************************/ - -/* -** See if numBytes bytes of buffer1 are equal to buffer2. -*/ -static Boolean EqualMemory(const void *buffer1, const void *buffer2, unsigned long numBytes) -{ - register unsigned char *b1 = (unsigned char *)buffer1; - register unsigned char *b2 = (unsigned char *)buffer2; - - if ( b1 != b2 ) /* if buffer pointers are same, then they are equal */ - { - while ( numBytes > 0 ) - { - /* compare the bytes and then increment the pointers */ - if ( (*b1++ - *b2++) != 0 ) - { - return ( false ); - } - --numBytes; - } - } - - return ( true ); -} - -/*****************************************************************************/ - -/* -** Read any number of bytes from an open file using read-verify mode. -** The FSReadVerify function reads any number of bytes from an open file -** and verifies them against the data in the buffer pointed to by buffPtr. -** -** Because of a bug in the HFS file system, only non-block aligned parts of -** the read are verified against the buffer data and the rest is *copied* -** into the buffer. Thus, you shouldn't verify against your original data; -** instead, you should verify against a copy of the original data and then -** compare the read-verified copy against the original data after calling -** FSReadVerify. That's why this function isn't exported - it needs the -** wrapper provided by FSWriteVerify. -*/ -static OSErr FSReadVerify(short refNum, - long *count, - void *buffPtr) -{ - ParamBlockRec pb; - OSErr result; - - pb.ioParam.ioRefNum = refNum; - pb.ioParam.ioBuffer = (Ptr)buffPtr; - pb.ioParam.ioReqCount = *count; - pb.ioParam.ioPosMode = fsAtMark + rdVerify; - pb.ioParam.ioPosOffset = 0; - result = PBReadSync(&pb); - *count = pb.ioParam.ioActCount; /* always return count */ - return ( result ); -} - -/*****************************************************************************/ - -pascal OSErr FSWriteVerify(short refNum, - long *count, - const void *buffPtr) -{ - Ptr verifyBuffer; - long position; - long bufferSize; - long byteCount; - long bytesVerified; - Ptr startVerify; - OSErr result; - - /* - ** Allocate the verify buffer - ** Try to get get a large enough buffer to verify in one pass. - ** If that fails, use GetTempBuffer to get a buffer. - */ - bufferSize = *count; - verifyBuffer = NewPtr(bufferSize); - if ( verifyBuffer == NULL ) - { - verifyBuffer = GetTempBuffer(bufferSize, &bufferSize); - } - if ( verifyBuffer != NULL ) - { - /* Save the current position */ - result = GetFPos(refNum, &position); - if ( result == noErr ) - { - /* Write the data */ - result = FSWrite(refNum, count, buffPtr); - if ( result == noErr ) - { - /* Restore the original position */ - result = SetFPos(refNum, fsFromStart, position); - if ( result == noErr ) - { - /* - ** *count = total number of bytes to verify - ** bufferSize = the size of the verify buffer - ** bytesVerified = number of bytes verified - ** byteCount = number of bytes to verify this pass - ** startVerify = position in buffPtr - */ - bytesVerified = 0; - startVerify = (Ptr)buffPtr; - while ( (bytesVerified < *count) && ( result == noErr ) ) - { - if ( (*count - bytesVerified) > bufferSize ) - { - byteCount = bufferSize; - } - else - { - byteCount = *count - bytesVerified; - } - /* - ** Copy the write buffer into the verify buffer. - ** This step is needed because the File Manager - ** compares the data in any non-block aligned - ** data at the beginning and end of the read-verify - ** request back into the file system's cache - ** to the data in verify Buffer. However, the - ** File Manager does not compare any full blocks - ** and instead copies them into the verify buffer - ** so we still have to compare the buffers again - ** after the read-verify request completes. - */ - BlockMoveData(startVerify, verifyBuffer, byteCount); - - /* Read-verify the data back into the verify buffer */ - result = FSReadVerify(refNum, &byteCount, verifyBuffer); - if ( result == noErr ) - { - /* See if the buffers are the same */ - if ( !EqualMemory(verifyBuffer, startVerify, byteCount) ) - { - result = ioErr; - } - startVerify += byteCount; - bytesVerified += byteCount; - } - } - } - } - } - DisposePtr(verifyBuffer); - } - else - { - result = memFullErr; - } - return ( result ); -} - -/*****************************************************************************/ - -pascal OSErr CopyFork(short srcRefNum, - short dstRefNum, - void *copyBufferPtr, - long copyBufferSize) -{ - ParamBlockRec srcPB; - ParamBlockRec dstPB; - OSErr srcError; - OSErr dstError; - - if ( (copyBufferPtr == NULL) || (copyBufferSize == 0) ) - return ( paramErr ); - - srcPB.ioParam.ioRefNum = srcRefNum; - dstPB.ioParam.ioRefNum = dstRefNum; - - /* preallocate the destination fork and */ - /* ensure the destination fork's EOF is correct after the copy */ - srcError = PBGetEOFSync(&srcPB); - if ( srcError != noErr ) - return ( srcError ); - dstPB.ioParam.ioMisc = srcPB.ioParam.ioMisc; - dstError = PBSetEOFSync(&dstPB); - if ( dstError != noErr ) - return ( dstError ); - - /* reset source fork's mark */ - srcPB.ioParam.ioPosMode = fsFromStart; - srcPB.ioParam.ioPosOffset = 0; - srcError = PBSetFPosSync(&srcPB); - if ( srcError != noErr ) - return ( srcError ); - - /* reset destination fork's mark */ - dstPB.ioParam.ioPosMode = fsFromStart; - dstPB.ioParam.ioPosOffset = 0; - dstError = PBSetFPosSync(&dstPB); - if ( dstError != noErr ) - return ( dstError ); - - /* set up fields that won't change in the loop */ - srcPB.ioParam.ioBuffer = (Ptr)copyBufferPtr; - srcPB.ioParam.ioPosMode = fsAtMark + 0x0020;/* fsAtMark + noCacheBit */ - /* If copyBufferSize is greater than 512 bytes, make it a multiple of 512 bytes */ - /* This will make writes on local volumes faster */ - if ( (copyBufferSize >= 512) && ((copyBufferSize & 0x1ff) != 0) ) - { - srcPB.ioParam.ioReqCount = copyBufferSize & 0xfffffe00; - } - else - { - srcPB.ioParam.ioReqCount = copyBufferSize; - } - dstPB.ioParam.ioBuffer = (Ptr)copyBufferPtr; - dstPB.ioParam.ioPosMode = fsAtMark + 0x0020;/* fsAtMark + noCacheBit */ - - while ( (srcError == noErr) && (dstError == noErr) ) - { - srcError = PBReadSync(&srcPB); - dstPB.ioParam.ioReqCount = srcPB.ioParam.ioActCount; - dstError = PBWriteSync(&dstPB); - } - - /* make sure there were no errors at the destination */ - if ( dstError != noErr ) - return ( dstError ); - - /* make sure the only error at the source was eofErr */ - if ( srcError != eofErr ) - return ( srcError ); - - return ( noErr ); -} - -/*****************************************************************************/ - -pascal OSErr GetFileLocation(short refNum, - short *vRefNum, - long *dirID, - StringPtr fileName) -{ - FCBPBRec pb; - OSErr error; - - pb.ioNamePtr = fileName; - pb.ioVRefNum = 0; - pb.ioRefNum = refNum; - pb.ioFCBIndx = 0; - error = PBGetFCBInfoSync(&pb); - if ( error == noErr ) - { - *vRefNum = pb.ioFCBVRefNum; - *dirID = pb.ioFCBParID; - } - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr FSpGetFileLocation(short refNum, - FSSpec *spec) -{ - return ( GetFileLocation(refNum, &(spec->vRefNum), &(spec->parID), spec->name) ); -} - -/*****************************************************************************/ - -pascal OSErr CopyDirectoryAccess(short srcVRefNum, - long srcDirID, - ConstStr255Param srcName, - short dstVRefNum, - long dstDirID, - ConstStr255Param dstName) -{ - OSErr error; - GetVolParmsInfoBuffer infoBuffer; /* Where PBGetVolParms dumps its info */ - long dstServerAdr; /* AppleTalk server address of destination (if any) */ - long ownerID, groupID, accessRights; - long tempLong; - - /* See if destination supports directory access control */ - tempLong = sizeof(infoBuffer); - error = HGetVolParms(dstName, dstVRefNum, &infoBuffer, &tempLong); - if ( (error == noErr) && hasAccessCntl(infoBuffer) ) - { - if ( hasAccessCntl(infoBuffer) ) - { - dstServerAdr = infoBuffer.vMServerAdr; - - /* See if source supports directory access control and is on same server */ - tempLong = sizeof(infoBuffer); - error = HGetVolParms(srcName, srcVRefNum, &infoBuffer, &tempLong); - if ( error == noErr ) - { - if ( hasAccessCntl(infoBuffer) && (dstServerAdr == infoBuffer.vMServerAdr) ) - { - /* both volumes support directory access control and they are */ - /* on same server, so copy the access information */ - error = HGetDirAccess(srcVRefNum, srcDirID, srcName, &ownerID, &groupID, &accessRights); - if ( error == noErr ) - { - error = HSetDirAccess(dstVRefNum, dstDirID, dstName, ownerID, groupID, accessRights); - } - } - else - { - /* destination doesn't support directory access control or */ - /* they volumes aren't on the same server */ - error = paramErr; - } - } - } - else - { - /* destination doesn't support directory access control */ - error = paramErr; - } - } - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr FSpCopyDirectoryAccess(const FSSpec *srcSpec, - const FSSpec *dstSpec) -{ - return ( CopyDirectoryAccess(srcSpec->vRefNum, srcSpec->parID, srcSpec->name, - dstSpec->vRefNum, dstSpec->parID, dstSpec->name) ); -} - -/*****************************************************************************/ - -pascal OSErr HMoveRenameCompat(short vRefNum, - long srcDirID, - ConstStr255Param srcName, - long dstDirID, - ConstStr255Param dstpathName, - ConstStr255Param copyName) -{ - OSErr error; - GetVolParmsInfoBuffer volParmsInfo; - long infoSize; - short realVRefNum; - long realParID; - Str31 realName; - Boolean isDirectory; - long tempItemsDirID; - long uniqueTempDirID; - Str31 uniqueTempDirName; - unsigned short uniqueNameoverflow; - - /* Get volume attributes */ - infoSize = sizeof(GetVolParmsInfoBuffer); - error = HGetVolParms((StringPtr)srcName, vRefNum, &volParmsInfo, &infoSize); - if ( (error == noErr) && hasMoveRename(volParmsInfo) ) - { - /* If volume supports move and rename, so use it and return */ - error = HMoveRename(vRefNum, srcDirID, srcName, dstDirID, dstpathName, copyName); - } - else if ( (error == noErr) || (error == paramErr) ) /* paramErr is OK, it just means this volume doesn't support GetVolParms */ - { - /* MoveRename isn't supported by this volume, so do it by hand */ - - /* If copyName isn't supplied, we can simply CatMove and return */ - if ( copyName == NULL ) - { - error = CatMove(vRefNum, srcDirID, srcName, dstDirID, dstpathName); - } - else - { - /* Renaming is required, so we have some work to do... */ - - /* Get the object's real name, real parent ID and real vRefNum */ - error = GetObjectLocation(vRefNum, srcDirID, (StringPtr)srcName, - &realVRefNum, &realParID, realName, &isDirectory); - if ( error == noErr ) - { - /* Find the Temporary Items Folder on that volume */ - error = FindFolder(realVRefNum, kTemporaryFolderType, kCreateFolder, - &realVRefNum, &tempItemsDirID); - if ( error == noErr ) - { - /* Create a new uniquely named folder in the temporary items folder. */ - /* This is done to avoid the case where 'realName' or 'copyName' already */ - /* exists in the temporary items folder. */ - - /* Start with current tick count as uniqueTempDirName */ - NumToString(TickCount(), uniqueTempDirName); - uniqueNameoverflow = 0; - do - { - error = DirCreate(realVRefNum, tempItemsDirID, uniqueTempDirName, &uniqueTempDirID); - if ( error == dupFNErr ) - { - /* Duplicate name - change the first character to the next ASCII character */ - ++uniqueTempDirName[1]; - /* Make sure it isn't a colon! */ - if ( uniqueTempDirName[1] == ':' ) - { - ++uniqueTempDirName[1]; - } - /* Don't go too far... */ - ++uniqueNameoverflow; - } - } while ( (error == dupFNErr) && (uniqueNameoverflow <= 64) ); /* 64 new files per 1/60th second - not likely! */ - if ( error == noErr ) - { - /* Move the object to the folder with uniqueTempDirID for renaming */ - error = CatMove(realVRefNum, realParID, realName, uniqueTempDirID, NULL); - if ( error == noErr ) - { - /* Rename the object */ - error = HRename(realVRefNum, uniqueTempDirID, realName, copyName); - if ( error == noErr ) - { - /* Move object to its new home */ - error = CatMove(realVRefNum, uniqueTempDirID, copyName, dstDirID, dstpathName); - if ( error != noErr ) - { - /* Error handling: rename object back to original name - ignore errors */ - (void) HRename(realVRefNum, uniqueTempDirID, copyName, realName); - } - } - if ( error != noErr ) - { - /* Error handling: move object back to original location - ignore errors */ - (void) CatMove(realVRefNum, uniqueTempDirID, realName, realParID, NULL); - } - } - /* Done with ourTempDir, so delete it - ignore errors */ - (void) HDelete(realVRefNum, uniqueTempDirID, NULL); - } - } - } - } - } - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr FSpMoveRenameCompat(const FSSpec *srcSpec, - const FSSpec *dstSpec, - ConstStr255Param copyName) -{ - /* make sure the FSSpecs refer to the same volume */ - if (srcSpec->vRefNum != dstSpec->vRefNum) - return (diffVolErr); - return ( HMoveRenameCompat(srcSpec->vRefNum, srcSpec->parID, srcSpec->name, - dstSpec->parID, dstSpec->name, copyName) ); -} - -/*****************************************************************************/ - -pascal OSErr BuildAFPVolMountInfo(short flags, - char nbpInterval, - char nbpCount, - short uamType, - Str32 zoneName, - Str32 serverName, - Str27 volName, - Str31 userName, - Str8 userPassword, - Str8 volPassword, - AFPVolMountInfoPtr *afpInfoPtr) -{ - MyAFPVolMountInfoPtr infoPtr; - OSErr error; - - /* Allocate the AFPXVolMountInfo record */ - infoPtr = (MyAFPVolMountInfoPtr)NewPtrClear(sizeof(MyAFPVolMountInfo)); - if ( infoPtr != NULL ) - { - /* Fill in an AFPVolMountInfo record that can be passed to VolumeMount */ - infoPtr->length = sizeof(MyAFPVolMountInfo); - infoPtr->media = AppleShareMediaType; - infoPtr->flags = flags; - infoPtr->nbpInterval = nbpInterval; - infoPtr->nbpCount = nbpCount; - infoPtr->uamType = uamType; - - infoPtr->zoneNameOffset = offsetof(MyAFPVolMountInfo, zoneName); - infoPtr->serverNameOffset = offsetof(MyAFPVolMountInfo, serverName); - infoPtr->volNameOffset = offsetof(MyAFPVolMountInfo, volName); - infoPtr->userNameOffset = offsetof(MyAFPVolMountInfo, userName); - infoPtr->userPasswordOffset = offsetof(MyAFPVolMountInfo, userPassword); - infoPtr->volPasswordOffset = offsetof(MyAFPVolMountInfo, volPassword); - - BlockMoveData(zoneName, infoPtr->zoneName, sizeof(Str32)); - BlockMoveData(serverName, infoPtr->serverName, sizeof(Str32)); - BlockMoveData(volName, infoPtr->volName, sizeof(Str27)); - BlockMoveData(userName, infoPtr->userName, sizeof(Str31)); - BlockMoveData(userPassword, infoPtr->userPassword, sizeof(Str8)); - BlockMoveData(volPassword, infoPtr->volPassword, sizeof(Str8)); - - *afpInfoPtr = (AFPVolMountInfoPtr)infoPtr; - error = noErr; - } - else - { - error = memFullErr; - } - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr RetrieveAFPVolMountInfo(AFPVolMountInfoPtr afpInfoPtr, - short *flags, - short *uamType, - StringPtr zoneName, - StringPtr serverName, - StringPtr volName, - StringPtr userName) -{ - StringPtr tempPtr; - OSErr error; - - /* Retrieve the AFP mounting information from an AFPVolMountInfo record. */ - if ( afpInfoPtr->media == AppleShareMediaType ) - { - *flags = afpInfoPtr->flags; - *uamType = afpInfoPtr->uamType; - - if ( afpInfoPtr->zoneNameOffset != 0) - { - tempPtr = (StringPtr)((long)afpInfoPtr + afpInfoPtr->zoneNameOffset); - BlockMoveData(tempPtr, zoneName, tempPtr[0] + 1); - } - - if ( afpInfoPtr->serverNameOffset != 0) - { - tempPtr = (StringPtr)((long)afpInfoPtr + afpInfoPtr->serverNameOffset); - BlockMoveData(tempPtr, serverName, tempPtr[0] + 1); - } - - if ( afpInfoPtr->volNameOffset != 0) - { - tempPtr = (StringPtr)((long)afpInfoPtr + afpInfoPtr->volNameOffset); - BlockMoveData(tempPtr, volName, tempPtr[0] + 1); - } - - if ( afpInfoPtr->userNameOffset != 0) - { - tempPtr = (StringPtr)((long)afpInfoPtr + afpInfoPtr->userNameOffset); - BlockMoveData(tempPtr, userName, tempPtr[0] + 1); - } - - error = noErr; - } - else - { - error = paramErr; - } - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr BuildAFPXVolMountInfo(short flags, - char nbpInterval, - char nbpCount, - short uamType, - Str32 zoneName, - Str32 serverName, - Str27 volName, - Str31 userName, - Str8 userPassword, - Str8 volPassword, - Str32 uamName, - unsigned long alternateAddressLength, - void *alternateAddress, - AFPXVolMountInfoPtr *afpXInfoPtr) -{ - Size infoSize; - MyAFPXVolMountInfoPtr infoPtr; - OSErr error; - - /* Calculate the size of the AFPXVolMountInfo record */ - infoSize = sizeof(MyAFPXVolMountInfo) + alternateAddressLength - 1; - - /* Allocate the AFPXVolMountInfo record */ - infoPtr = (MyAFPXVolMountInfoPtr)NewPtrClear(infoSize); - if ( infoPtr != NULL ) - { - /* Fill in an AFPXVolMountInfo record that can be passed to VolumeMount */ - infoPtr->length = infoSize; - infoPtr->media = AppleShareMediaType; - infoPtr->flags = flags; - if ( alternateAddressLength != 0 ) - { - /* make sure the volMountExtendedFlagsBit is set if there's extended address info */ - infoPtr->flags |= volMountExtendedFlagsMask; - /* and set the only extendedFlags bit we know about */ - infoPtr->extendedFlags = kAFPExtendedFlagsAlternateAddressMask; - } - else - { - /* make sure the volMountExtendedFlagsBit is clear if there's no extended address info */ - infoPtr->flags &= ~volMountExtendedFlagsMask; - /* and clear the extendedFlags */ - infoPtr->extendedFlags = 0; - } - infoPtr->nbpInterval = nbpInterval; - infoPtr->nbpCount = nbpCount; - infoPtr->uamType = uamType; - - infoPtr->zoneNameOffset = offsetof(MyAFPXVolMountInfo, zoneName); - infoPtr->serverNameOffset = offsetof(MyAFPXVolMountInfo, serverName); - infoPtr->volNameOffset = offsetof(MyAFPXVolMountInfo, volName); - infoPtr->userNameOffset = offsetof(MyAFPXVolMountInfo, userName); - infoPtr->userPasswordOffset = offsetof(MyAFPXVolMountInfo, userPassword); - infoPtr->volPasswordOffset = offsetof(MyAFPXVolMountInfo, volPassword); - infoPtr->uamNameOffset = offsetof(MyAFPXVolMountInfo, uamName); - infoPtr->alternateAddressOffset = offsetof(MyAFPXVolMountInfo, alternateAddress); - - BlockMoveData(zoneName, infoPtr->zoneName, sizeof(Str32)); - BlockMoveData(serverName, infoPtr->serverName, sizeof(Str32)); - BlockMoveData(volName, infoPtr->volName, sizeof(Str27)); - BlockMoveData(userName, infoPtr->userName, sizeof(Str31)); - BlockMoveData(userPassword, infoPtr->userPassword, sizeof(Str8)); - BlockMoveData(volPassword, infoPtr->volPassword, sizeof(Str8)); - BlockMoveData(uamName, infoPtr->uamName, sizeof(Str32)); - BlockMoveData(alternateAddress, infoPtr->alternateAddress, alternateAddressLength); - - *afpXInfoPtr = (AFPXVolMountInfoPtr)infoPtr; - error = noErr; - } - else - { - error = memFullErr; - } - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr RetrieveAFPXVolMountInfo(AFPXVolMountInfoPtr afpXInfoPtr, - short *flags, - short *uamType, - StringPtr zoneName, - StringPtr serverName, - StringPtr volName, - StringPtr userName, - StringPtr uamName, - unsigned long *alternateAddressLength, - AFPAlternateAddress **alternateAddress) -{ - StringPtr tempPtr; - Ptr alternateAddressStart; - Ptr alternateAddressEnd; - Size alternateAddressDataSize; - OSErr error; - UInt8 addressCount; - - /* Retrieve the AFP mounting information from an AFPVolMountInfo record. */ - if ( afpXInfoPtr->media == AppleShareMediaType ) - { - /* default to noErr */ - error = noErr; - - /* Is this an extended record? */ - if ( (afpXInfoPtr->flags & volMountExtendedFlagsMask) != 0 ) - { - if ( ((afpXInfoPtr->extendedFlags & kAFPExtendedFlagsAlternateAddressMask) != 0) && - (afpXInfoPtr->alternateAddressOffset != 0) ) - { - - alternateAddressStart = (Ptr)((long)afpXInfoPtr + afpXInfoPtr->alternateAddressOffset); - alternateAddressEnd = alternateAddressStart + 1; /* skip over alternate address version byte */ - addressCount = *(UInt8*)alternateAddressEnd; /* get the address count */ - ++alternateAddressEnd; /* skip over alternate address count byte */ - /* alternateAddressEnd now equals &AFPAlternateAddress.fAddressList[0] */ - while ( addressCount != 0 ) - { - /* parse the address list to find the end */ - alternateAddressEnd += *(UInt8*)alternateAddressEnd; /* add length of each AFPTagData record */ - --addressCount; - } - /* get the size of the alternateAddressData */ - alternateAddressDataSize = alternateAddressEnd - alternateAddressStart; - /* allocate memory for it */ - *alternateAddress = (AFPAlternateAddress *)NewPtr(alternateAddressDataSize); - if ( *alternateAddress != NULL ) - { - /* and return the data */ - BlockMoveData(alternateAddressStart, *alternateAddress, alternateAddressDataSize); - *alternateAddressLength = alternateAddressDataSize; - } - else - { - /* no memory - fail now */ - error = memFullErr; - } - } - - if ( error == noErr ) /* fill in more output parameters if everything is OK */ - { - if ( afpXInfoPtr->uamNameOffset != 0 ) - { - tempPtr = (StringPtr)((long)afpXInfoPtr + afpXInfoPtr->uamNameOffset); - BlockMoveData(tempPtr, uamName, tempPtr[0] + 1); - } - } - } - - if ( error == noErr ) /* fill in more output parameters if everything is OK */ - { - *flags = afpXInfoPtr->flags; - *uamType = afpXInfoPtr->uamType; - - if ( afpXInfoPtr->zoneNameOffset != 0 ) - { - tempPtr = (StringPtr)((long)afpXInfoPtr + afpXInfoPtr->zoneNameOffset); - BlockMoveData(tempPtr, zoneName, tempPtr[0] + 1); - } - - if ( afpXInfoPtr->serverNameOffset != 0 ) - { - tempPtr = (StringPtr)((long)afpXInfoPtr + afpXInfoPtr->serverNameOffset); - BlockMoveData(tempPtr, serverName, tempPtr[0] + 1); - } - - if ( afpXInfoPtr->volNameOffset != 0 ) - { - tempPtr = (StringPtr)((long)afpXInfoPtr + afpXInfoPtr->volNameOffset); - BlockMoveData(tempPtr, volName, tempPtr[0] + 1); - } - - if ( afpXInfoPtr->userNameOffset != 0 ) - { - tempPtr = (StringPtr)((long)afpXInfoPtr + afpXInfoPtr->userNameOffset); - BlockMoveData(tempPtr, userName, tempPtr[0] + 1); - } - } - } - else - { - error = paramErr; - } - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr GetUGEntries(short objType, - UGEntryPtr entries, - long reqEntryCount, - long *actEntryCount, - long *objID) -{ - HParamBlockRec pb; - OSErr error = noErr; - UGEntry *endEntryArray; - - pb.objParam.ioObjType = objType; - *actEntryCount = 0; - for ( endEntryArray = entries + reqEntryCount; (entries < endEntryArray) && (error == noErr); ++entries ) - { - pb.objParam.ioObjNamePtr = (StringPtr)entries->name; - pb.objParam.ioObjID = *objID; - /* Files.h in the universal interfaces, PBGetUGEntrySync takes a CMovePBPtr */ - /* as the parameter. Inside Macintosh and the original glue used HParmBlkPtr. */ - /* A CMovePBPtr works OK, but this will be changed in the future back to */ - /* HParmBlkPtr, so I'm just casting it here. */ - error = PBGetUGEntrySync(&pb); - if ( error == noErr ) - { - entries->objID = *objID = pb.objParam.ioObjID; - entries->objType = objType; - ++*actEntryCount; - } - } - - return ( error ); -} - -/*****************************************************************************/ - diff --git a/src/mac/morefile/MoreExtr.h b/src/mac/morefile/MoreExtr.h deleted file mode 100644 index c0fd7a006b..0000000000 --- a/src/mac/morefile/MoreExtr.h +++ /dev/null @@ -1,3149 +0,0 @@ -/* -** Apple Macintosh Developer Technical Support -** -** A collection of useful high-level File Manager routines. -** -** by Jim Luther, Apple Developer Technical Support Emeritus -** -** File: MoreFilesExtras.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 __MOREFILESEXTRAS__ -#define __MOREFILESEXTRAS__ - -#include -#include - -#ifndef true -#define true 1 -#define false 0 -#endif - -#include "optim.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/*****************************************************************************/ - -/* Constants and types from Universal Interfaces 3.0.1 Files.h */ - -#if UNIVERSAL_INTERFACES_VERSION < 0x0301 - -enum { - volMountNoLoginMsgFlagBit = 0, /* Input to VolumeMount: If set, the file system */ - volMountNoLoginMsgFlagMask = 0x0001, /* should suppresss any log-in message/greeting dialog */ - volMountExtendedFlagsBit = 7, /* Input to VolumeMount: If set, the mount info is a */ - volMountExtendedFlagsMask = 0x0080 /* AFPXVolMountInfo record for 3.7 AppleShare Client */ -}; - -/* AFPXVolMountInfo is the new AFP volume mount info record, requires the 3.7 AppleShare Client */ - -struct AFPXVolMountInfo { - short length; /* length of location data (including self) */ - VolumeType media; /* type of media */ - short flags; /* bits for no messages, no reconnect */ - SInt8 nbpInterval; /* NBP Interval parameter (IM2, p.322) */ - SInt8 nbpCount; /* NBP Interval parameter (IM2, p.322) */ - short uamType; /* User Authentication Method type */ - short zoneNameOffset; /* short positive offset from start of struct to Zone Name */ - short serverNameOffset; /* offset to pascal Server Name string */ - short volNameOffset; /* offset to pascal Volume Name string */ - short userNameOffset; /* offset to pascal User Name string */ - short userPasswordOffset; /* offset to pascal User Password string */ - short volPasswordOffset; /* offset to pascal Volume Password string */ - short extendedFlags; /* extended flags word */ - short uamNameOffset; /* offset to a pascal UAM name string */ - short alternateAddressOffset; /* offset to Alternate Addresses in tagged format */ - char AFPData[176]; /* variable length data may follow */ -}; -typedef struct AFPXVolMountInfo AFPXVolMountInfo; -typedef AFPXVolMountInfo * AFPXVolMountInfoPtr; - -enum { - kAFPExtendedFlagsAlternateAddressMask = 1 /* bit in AFPXVolMountInfo.extendedFlags that means alternateAddressOffset is used*/ -}; - -enum { - /* constants for use in AFPTagData.fType field*/ - kAFPTagTypeIP = 0x01, - kAFPTagTypeIPPort = 0x02, - kAFPTagTypeDDP = 0x03 /* Currently unused*/ -}; - -enum { - /* constants for use in AFPTagData.fLength field*/ - kAFPTagLengthIP = 0x06, - kAFPTagLengthIPPort = 0x08, - kAFPTagLengthDDP = 0x06 -}; - -struct AFPTagData { - UInt8 fLength; /* length of this data tag including the fLength field */ - UInt8 fType; - UInt8 fData[1]; /* variable length data */ -}; -typedef struct AFPTagData AFPTagData; - -struct AFPAlternateAddress { - UInt8 fAddressCount; - UInt8 fAddressList[1]; /* actually variable length packed set of AFPTagData */ -}; -typedef struct AFPAlternateAddress AFPAlternateAddress; - -#endif - -/*****************************************************************************/ - -/* -** Macros to get information out of GetVolParmsInfoBuffer -*/ - -#define isNetworkVolume(volParms) ((volParms).vMServerAdr != 0) -#define hasLimitFCBs(volParms) (((volParms).vMAttrib & (1L << bLimitFCBs)) != 0) -#define hasLocalWList(volParms) (((volParms).vMAttrib & (1L << bLocalWList)) != 0) -#define hasNoMiniFndr(volParms) (((volParms).vMAttrib & (1L << bNoMiniFndr)) != 0) -#define hasNoVNEdit(volParms) (((volParms).vMAttrib & (1L << bNoVNEdit)) != 0) -#define hasNoLclSync(volParms) (((volParms).vMAttrib & (1L << bNoLclSync)) != 0) -#define hasTrshOffLine(volParms) (((volParms).vMAttrib & (1L << bTrshOffLine)) != 0) -#define hasNoSwitchTo(volParms) (((volParms).vMAttrib & (1L << bNoSwitchTo)) != 0) -#define hasNoDeskItems(volParms) (((volParms).vMAttrib & (1L << bNoDeskItems)) != 0) -#define hasNoBootBlks(volParms) (((volParms).vMAttrib & (1L << bNoBootBlks)) != 0) -#define hasAccessCntl(volParms) (((volParms).vMAttrib & (1L << bAccessCntl)) != 0) -#define hasNoSysDir(volParms) (((volParms).vMAttrib & (1L << bNoSysDir)) != 0) -#define hasExtFSVol(volParms) (((volParms).vMAttrib & (1L << bHasExtFSVol)) != 0) -#define hasOpenDeny(volParms) (((volParms).vMAttrib & (1L << bHasOpenDeny)) != 0) -#define hasCopyFile(volParms) (((volParms).vMAttrib & (1L << bHasCopyFile)) != 0) -#define hasMoveRename(volParms) (((volParms).vMAttrib & (1L << bHasMoveRename)) != 0) -#define hasDesktopMgr(volParms) (((volParms).vMAttrib & (1L << bHasDesktopMgr)) != 0) -#define hasShortName(volParms) (((volParms).vMAttrib & (1L << bHasShortName)) != 0) -#define hasFolderLock(volParms) (((volParms).vMAttrib & (1L << bHasFolderLock)) != 0) -#define hasPersonalAccessPrivileges(volParms) \ - (((volParms).vMAttrib & (1L << bHasPersonalAccessPrivileges)) != 0) -#define hasUserGroupList(volParms) (((volParms).vMAttrib & (1L << bHasUserGroupList)) != 0) -#define hasCatSearch(volParms) (((volParms).vMAttrib & (1L << bHasCatSearch)) != 0) -#define hasFileIDs(volParms) (((volParms).vMAttrib & (1L << bHasFileIDs)) != 0) -#define hasBTreeMgr(volParms) (((volParms).vMAttrib & (1L << bHasBTreeMgr)) != 0) -#define hasBlankAccessPrivileges(volParms) \ - (((volParms).vMAttrib & (1L << bHasBlankAccessPrivileges)) != 0) - -/*****************************************************************************/ - - -/* -** Bit masks and macros to get common information out of ioACUser returned -** by PBGetCatInfo (remember to clear ioACUser before calling PBGetCatInfo -** since some file systems don't bother to set this field). -** -** Use the GetDirAccessRestrictions or FSpGetDirAccessRestrictions -** functions to retrieve the ioACUser access restrictions byte for -** a folder. -** -** Note: The access restriction byte returned by PBGetCatInfo is the -** 2's complement of the user's privileges byte returned in -** ioACAccess by PBHGetDirAccess. -*/ - -enum -{ - /* bits defined in ioACUser */ - acUserNoSeeFoldersMask = 0x01, - acUserNoSeeFilesMask = 0x02, - acUserNoMakeChangesMask = 0x04, - acUserNotOwnerMask = 0x80, - - /* mask for just the access restriction bits */ - acUserAccessMask = 0x07, - - /* common access privilege settings */ - acUserFull = 0x00, /* no access restiction bits on */ - acUserNone = acUserAccessMask, /* all access restiction bits on */ - acUserDropBox = acUserNoSeeFoldersMask + acUserNoSeeFilesMask, /* make changes, but not see files or folders */ - acUserBulletinBoard = acUserNoMakeChangesMask /* see files and folders, but not make changes */ -}; - -/* Macros for testing ioACUser bits */ -#define userIsOwner(ioACUser) \ - (((ioACUser) & acUserNotOwnerMask) == 0) -#define userHasFullAccess(ioACUser) \ - (((ioACUser) & (acUserAccessMask)) == acUserFull) -#define userHasDropBoxAccess(ioACUser) \ - (((ioACUser) & acUserAccessMask) == acUserDropBox) -#define userHasBulletinBoard(ioACUser) \ - (((ioACUser) & acUserAccessMask) == acUserBulletinBoard) -#define userHasNoAccess(ioACUser) \ - (((ioACUser) & acUserAccessMask) == acUserNone) - -/*****************************************************************************/ - -/* -** Deny mode permissions for use with the HOpenAware, HOpenRFAware, -** FSpOpenAware, and FSpOpenRFAware functions. -*/ - -enum -{ - dmNone = 0x0000, - dmNoneDenyRd = 0x0010, - dmNoneDenyWr = 0x0020, - dmNoneDenyRdWr = 0x0030, - dmRd = 0x0001, /* Single writer, multiple readers; the readers */ - dmRdDenyRd = 0x0011, - dmRdDenyWr = 0x0021, /* Browsing - equivalent to fsRdPerm */ - dmRdDenyRdWr = 0x0031, - dmWr = 0x0002, - dmWrDenyRd = 0x0012, - dmWrDenyWr = 0x0022, - dmWrDenyRdWr = 0x0032, - dmRdWr = 0x0003, /* Shared access - equivalent to fsRdWrShPerm */ - dmRdWrDenyRd = 0x0013, - dmRdWrDenyWr = 0x0023, /* Single writer, multiple readers; the writer */ - dmRdWrDenyRdWr = 0x0033 /* Exclusive access - equivalent to fsRdWrPerm */ -}; - -/*****************************************************************************/ - -#if PRAGMA_STRUCT_ALIGN - #pragma options align=mac68k -#elif PRAGMA_STRUCT_PACKPUSH - #pragma pack(push, 2) -#elif PRAGMA_STRUCT_PACK - #pragma pack(2) -#endif - -/* -** For those times where you need to use more than one kind of File Manager parameter -** block but don't feel like wasting stack space, here's a parameter block you can reuse. -*/ - -union UniversalFMPB -{ - ParamBlockRec PB; - CInfoPBRec ciPB; - DTPBRec dtPB; - HParamBlockRec hPB; - CMovePBRec cmPB; - WDPBRec wdPB; - FCBPBRec fcbPB; - XVolumeParam xPB; -}; -typedef union UniversalFMPB UniversalFMPB; -typedef UniversalFMPB *UniversalFMPBPtr, **UniversalFMPBHandle; - - -/* -** Used by GetUGEntries to return user or group lists -*/ - -struct UGEntry -{ - short objType; /* object type: -1 = group; 0 = user */ - long objID; /* the user or group ID */ - Str31 name; /* the user or group name */ -}; -typedef struct UGEntry UGEntry; -typedef UGEntry *UGEntryPtr, **UGEntryHandle; - - -typedef unsigned char Str8[9]; - - -/* -** I use the following records instead of the AFPVolMountInfo and AFPXVolMountInfo structures in Files.h -*/ - -struct MyAFPVolMountInfo -{ - short length; /* length of this record */ - VolumeType media; /* type of media, always AppleShareMediaType */ - short flags; /* 0 = normal mount; set bit 0 to inhibit greeting messages */ - char nbpInterval; /* NBP interval parameter; 7 is a good choice */ - char nbpCount; /* NBP count parameter; 5 is a good choice */ - short uamType; /* User Authentication Method */ - short zoneNameOffset; /* offset from start of record to zoneName */ - short serverNameOffset; /* offset from start of record to serverName */ - short volNameOffset; /* offset from start of record to volName */ - short userNameOffset; /* offset from start of record to userName */ - short userPasswordOffset; /* offset from start of record to userPassword */ - short volPasswordOffset; /* offset from start of record to volPassword */ - Str32 zoneName; /* server's AppleTalk zone name */ - char filler1; /* to word align volPassword */ - Str32 serverName; /* server name */ - char filler2; /* to word align volPassword */ - Str27 volName; /* volume name */ - Str31 userName; /* user name (zero length Pascal string for guest) */ - Str8 userPassword; /* user password (zero length Pascal string if no user password) */ - char filler3; /* to word align volPassword */ - Str8 volPassword; /* volume password (zero length Pascal string if no volume password) */ - char filler4; /* to end record on word boundry */ -}; -typedef struct MyAFPVolMountInfo MyAFPVolMountInfo; -typedef MyAFPVolMountInfo *MyAFPVolMountInfoPtr, **MyAFPVolMountInfoHandle; - -struct MyAFPXVolMountInfo -{ - short length; /* length of this record */ - VolumeType media; /* type of media, always AppleShareMediaType */ - short flags; /* bits for no messages, no reconnect, etc */ - char nbpInterval; /* NBP interval parameter; 7 is a good choice */ - char nbpCount; /* NBP count parameter; 5 is a good choice */ - short uamType; /* User Authentication Method */ - short zoneNameOffset; /* offset from start of record to zoneName */ - short serverNameOffset; /* offset from start of record to serverName */ - short volNameOffset; /* offset from start of record to volName */ - short userNameOffset; /* offset from start of record to userName */ - short userPasswordOffset; /* offset from start of record to userPassword */ - short volPasswordOffset; /* offset from start of record to volPassword */ - short extendedFlags; /* extended flags word */ - short uamNameOffset; /* offset to a pascal UAM name string */ - short alternateAddressOffset; /* offset to Alternate Addresses in tagged format */ - Str32 zoneName; /* server's AppleTalk zone name */ - char filler1; /* to word align volPassword */ - Str32 serverName; /* server name */ - char filler2; /* to word align volPassword */ - Str27 volName; /* volume name */ - Str31 userName; /* user name (zero length Pascal string for guest) */ - Str8 userPassword; /* user password (zero length Pascal string if no user password) */ - char filler3; /* to word align volPassword */ - Str8 volPassword; /* volume password (zero length Pascal string if no volume password) */ - char filler4; /* to word align uamNameOffset */ - Str32 uamName; /* UAM name */ - char filler5; /* to word align alternateAddress */ - char alternateAddress[kVariableLengthArray]; /* AFPAlternateAddress */ -}; -typedef struct MyAFPXVolMountInfo MyAFPXVolMountInfo; -typedef MyAFPXVolMountInfo *MyAFPXVolMountInfoPtr, **MyAFPXVolMountInfoHandle; - -#if PRAGMA_STRUCT_ALIGN - #pragma options align=reset -#elif PRAGMA_STRUCT_PACKPUSH - #pragma pack(pop) -#elif PRAGMA_STRUCT_PACK - #pragma pack() -#endif - -/*****************************************************************************/ - -pascal void TruncPString(StringPtr destination, - ConstStr255Param source, - short maxLength); -/* ¦ International friendly string truncate routine. - The TruncPString function copies up to maxLength characters from - the source Pascal string to the destination Pascal string. TruncPString - ensures that the truncated string ends on a single-byte character, or on - the last byte of a multi-byte character. - - destination output: destination Pascal string. - source input: source Pascal string. - maxLength output: The maximum allowable length of the destination - string. -*/ - -/*****************************************************************************/ - -pascal Ptr GetTempBuffer(long buffReqSize, - long *buffActSize); -/* ¦ Allocate a temporary copy or search buffer. - The GetTempBuffer function allocates a temporary buffer for file system - operations which is at least 1024 bytes (1K) and a multiple of - 1024 bytes. - - buffReqSize input: Size you'd like the buffer to be. - buffActSize output: Size of buffer allocated. - function result output: Pointer to memory allocated or nil if no memory - was available. The caller is responsible for - disposing of this buffer with DisposePtr. -*/ - -/*****************************************************************************/ - -pascal OSErr GetVolumeInfoNoName(ConstStr255Param pathname, - short vRefNum, - HParmBlkPtr pb); -/* ¦ Call PBHGetVInfoSync ignoring returned name. - GetVolumeInfoNoName uses pathname and vRefNum to call PBHGetVInfoSync - in cases where the returned volume name is not needed by the caller. - The pathname and vRefNum parameters are not touched, and the pb - parameter is initialized by PBHGetVInfoSync except that ioNamePtr in - the parameter block is always returned as NULL (since it might point - to GetVolumeInfoNoName's local variable tempPathname). - - I noticed using this code in several places, so here it is once. - This reduces the code size of MoreFiles. - - pathName input: Pointer to a full pathname or nil. If you pass in a - partial pathname, it is ignored. A full pathname to a - volume must end with a colon character (:). - vRefNum input: Volume specification (volume reference number, working - directory number, drive number, or 0). - pb input: A pointer to HParamBlockRec. - output: The parameter block as filled in by PBHGetVInfoSync - except that ioNamePtr will always be NULL. - - Result Codes - noErr 0 No error - nsvErr -35 No such volume - paramErr -50 No default volume, or pb was NULL -*/ - -/*****************************************************************************/ - -pascal OSErr XGetVolumeInfoNoName(ConstStr255Param pathname, - short vRefNum, - XVolumeParamPtr pb); -/* ¦ Call PBXGetVolInfoSync ignoring returned name. - XGetVolumeInfoNoName uses pathname and vRefNum to call PBXGetVolInfoSync - in cases where the returned volume name is not needed by the caller. - The pathname and vRefNum parameters are not touched, and the pb - parameter is initialized by PBXGetVolInfoSync except that ioNamePtr in - the parameter block is always returned as NULL (since it might point - to XGetVolumeInfoNoName's local variable tempPathname). - - pathName input: Pointer to a full pathname or nil. If you pass in a - partial pathname, it is ignored. A full pathname to a - volume must end with a colon character (:). - vRefNum input: Volume specification (volume reference number, working - directory number, drive number, or 0). - pb input: A pointer to HParamBlockRec. - output: The parameter block as filled in by PBXGetVolInfoSync - except that ioNamePtr will always be NULL. - - Result Codes - noErr 0 No error - nsvErr -35 No such volume - paramErr -50 No default volume, or pb was NULL -*/ - -/*****************************************************************************/ - -pascal OSErr GetCatInfoNoName(short vRefNum, - long dirID, - ConstStr255Param name, - CInfoPBPtr pb); -/* ¦ Call PBGetCatInfoSync ignoring returned name. - GetCatInfoNoName uses vRefNum, dirID and name to call PBGetCatInfoSync - in cases where the returned object is not needed by the caller. - The vRefNum, dirID and name parameters are not touched, and the pb - parameter is initialized by PBGetCatInfoSync except that ioNamePtr in - the parameter block is always returned as NULL (since it might point - to GetCatInfoNoName's local variable tempName). - - I noticed using this code in several places, so here it is once. - This reduces the code size of MoreFiles. - - 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. - pb input: A pointer to CInfoPBRec. - output: The parameter block as filled in by - PBGetCatInfoSync except that ioNamePtr will - always be NULL. - - 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 - 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 - -*/ - -/*****************************************************************************/ - -pascal OSErr DetermineVRefNum(ConstStr255Param pathname, - short vRefNum, - short *realVRefNum); -/* ¦ Determine the real volume reference number. - The DetermineVRefNum function determines the volume reference number of - a volume from a pathname, a volume specification, or a combination - of the two. - WARNING: Volume names on the Macintosh are *not* unique -- Multiple - mounted volumes can have the same name. For this reason, the use of a - volume name or 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 volume name or full pathname is used, the File Manager - currently uses the first volume it finds with a matching name in the - volume queue. - - pathName input: Pointer to a full pathname or nil. If you pass in a - partial pathname, it is ignored. A full pathname to a - volume must end with a colon character (:). - vRefNum input: Volume specification (volume reference number, working - directory number, drive number, or 0). - realVRefNum output: The real volume reference number. - - Result Codes - noErr 0 No error - nsvErr -35 No such volume - paramErr -50 No default volume -*/ - -/*****************************************************************************/ - -pascal OSErr HGetVInfo(short volReference, - StringPtr volName, - short *vRefNum, - unsigned long *freeBytes, - unsigned long *totalBytes); -/* ¦ Get information about a mounted volume. - The HGetVInfo function returns the name, volume reference number, - available space (in bytes), and total space (in bytes) for the - specified volume. You can specify the volume by providing its drive - number, volume reference number, or 0 for the default volume. - This routine is compatible with volumes up to 4 gigabytes. - - volReference input: The drive number, volume reference number, - or 0 for the default volume. - volName input: A pointer to a buffer (minimum Str27) where - the volume name is to be returned or must - be nil. - output: The volume name. - vRefNum output: The volume reference number. - freeBytes output: The number of free bytes on the volume. - freeBytes is an unsigned long value. - totalBytes output: The total number of bytes on the volume. - totalBytes is an unsigned long value. - - Result Codes - noErr 0 No error - nsvErr -35 No such volume - paramErr -50 No default volume - - __________ - - Also see: XGetVInfo -*/ - -/*****************************************************************************/ - -pascal OSErr XGetVInfo(short volReference, - StringPtr volName, - short *vRefNum, - UnsignedWide *freeBytes, - UnsignedWide *totalBytes); -/* ¦ Get extended information about a mounted volume. - The XGetVInfo function returns the name, volume reference number, - available space (in bytes), and total space (in bytes) for the - specified volume. You can specify the volume by providing its drive - number, volume reference number, or 0 for the default volume. - This routine is compatible with volumes up to 2 terabytes. - - volReference input: The drive number, volume reference number, - or 0 for the default volume. - volName input: A pointer to a buffer (minimum Str27) where - the volume name is to be returned or must - be nil. - output: The volume name. - vRefNum output: The volume reference number. - freeBytes output: The number of free bytes on the volume. - freeBytes is an UnsignedWide value. - totalBytes output: The total number of bytes on the volume. - totalBytes is an UnsignedWide value. - - Result Codes - noErr 0 No error - nsvErr -35 No such volume - paramErr -50 No default volume - - __________ - - Also see: HGetVInfo -*/ - -/*****************************************************************************/ - -pascal OSErr CheckVolLock(ConstStr255Param pathname, - short vRefNum); -/* ¦ Determine if a volume is locked. - The CheckVolLock function determines if a volume is locked - either by - hardware or by software. If CheckVolLock returns noErr, then the volume - is not locked. - - pathName input: Pointer to a full pathname or nil. If you pass in a - partial pathname, it is ignored. A full pathname to a - volume must end with a colon character (:). - vRefNum input: Volume specification (volume reference number, working - directory number, drive number, or 0). - - Result Codes - noErr 0 No error - volume not locked - nsvErr -35 No such volume - wPrErr -44 Volume locked by hardware - vLckdErr -46 Volume locked by software - paramErr -50 No default volume -*/ - -/*****************************************************************************/ - -pascal OSErr GetDriverName(short driverRefNum, - Str255 driverName); -/* ¦ Get a device driver's name. - The GetDriverName function returns a device driver's name. - - driverRefNum input: The driver reference number. - driverName output: The driver's name. - - Result Codes - noErr 0 No error - badUnitErr -21 Bad driver reference number -*/ - -/*****************************************************************************/ - -pascal OSErr FindDrive(ConstStr255Param pathname, - short vRefNum, - DrvQElPtr *driveQElementPtr); -/* ¦ Find a volume's drive queue element in the drive queue. - The FindDrive function returns a pointer to a mounted volume's - drive queue element. - - pathName input: Pointer to a full pathname or nil. If you - pass in a partial pathname, it is ignored. - A full pathname to a volume must end with - a colon character (:). - vRefNum input: Volume specification (volume reference - number, working directory number, drive - number, or 0). - driveQElementPtr output: Pointer to a volume's drive queue element - in the drive queue. DO NOT change the - DrvQEl. - - Result Codes - noErr 0 No error - nsvErr -35 No such volume - paramErr -50 No default volume - nsDrvErr -56 No such drive -*/ - -/*****************************************************************************/ - -pascal OSErr GetDiskBlocks(ConstStr255Param pathname, - short vRefNum, - unsigned long *numBlocks); -/* ¦ Return the number of physical disk blocks on a disk drive. - The GetDiskBlocks function returns the number of physical disk - blocks on a disk drive. NOTE: This is not the same as volume - allocation blocks! - - pathName input: Pointer to a full pathname or nil. If you - pass in a partial pathname, it is ignored. - A full pathname to a volume must end with - a colon character (:). - vRefNum input: Volume specification (volume reference - number, working directory number, drive - number, or 0). - numBlocks output: The number of physical disk blocks on the disk drive. - - Result Codes - noErr 0 No error - nsvErr -35 No such volume - paramErr -50 No default volume, driver reference - number is zero, ReturnFormatList - returned zero blocks, DriveStatus - returned an unknown value, or - driveQElementPtr->qType is unknown - nsDrvErr -56 No such drive - statusErr Ð18 Driver does not respond to this - status request - 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 -*/ - -/*****************************************************************************/ - -pascal OSErr GetVolFileSystemID(ConstStr255Param pathname, - short vRefNum, - short *fileSystemID); -/* ¦ Get a volume's file system ID. - The GetVolFileSystemID function returned the file system ID of - a mounted volume. The file system ID identifies the file system - that handles requests to a particular volume. Here's a partial list - of file system ID numbers (only Apple's file systems are listed): - FSID File System - ----- ----------------------------------------------------- - $0000 Macintosh HFS or MFS - $0100 ProDOS File System - $0101 PowerTalk Mail Enclosures - $4147 ISO 9660 File Access (through Foreign File Access) - $4242 High Sierra File Access (through Foreign File Access) - $464D QuickTake File System (through Foreign File Access) - $4953 Macintosh PC Exchange (MS-DOS) - $4A48 Audio CD Access (through Foreign File Access) - $4D4B Apple Photo Access (through Foreign File Access) - - See the Technical Note "FL 35 - Determining Which File System - Is Active" and the "Guide to the File System Manager" for more - information. - - pathName input: Pointer to a full pathname or nil. If you pass - in a partial pathname, it is ignored. A full - pathname to a volume must contain at least - one colon character (:) and must not start with - a colon character. - vRefNum input: Volume specification (volume reference number, - working directory number, drive number, or 0). - fileSystemID output: The volume's file system ID. - - Result Codes - noErr 0 No error - nsvErr -35 No such volume - paramErr -50 No default volume, or pb was NULL -*/ - -/*****************************************************************************/ - -pascal OSErr GetVolState(ConstStr255Param pathname, - short vRefNum, - Boolean *volumeOnline, - Boolean *volumeEjected, - Boolean *driveEjectable, - Boolean *driverWantsEject); -/* ¦ Returns a volume's online and eject information. - The GetVolState function determines if a volume is online or offline, - if an offline volume is ejected, and if the volume's driver is - ejectable or wants eject calls. - - pathName input: Pointer to a full pathname or nil. - vRefNum input: Volume specification (volume reference number, - working directory number, drive number, or 0). - volumeOnline output: True if the volume is online; - False if the volume is offline. - volumeEjected output: True if the volume is ejected (ejected - volumes are always offline); False if the - volume is not ejected. - driveEjectable output: True if the volume's drive is ejectable; - False if the volume's drive is not ejectable. - driverWantsEject output: True if the volume's driver wants an Eject - request after unmount (even if the drive - is not ejectable); False if the volume's - driver does not need an eject request. - - Result Codes - noErr 0 No error - nsvErr -35 No such volume - paramErr -50 No default volume, or pb was NULL -*/ - -/*****************************************************************************/ - -pascal OSErr UnmountAndEject(ConstStr255Param pathname, - short vRefNum); -/* ¦ Unmount and eject a volume. - The UnmountAndEject function unmounts and ejects a volume. The volume - is ejected only if it is ejectable and not already ejected. - - pathName input: Pointer to a full pathname or nil. If you pass in a - partial pathname, it is ignored. A full pathname to a - volume must end with a colon character (:). - vRefNum input: Volume specification (volume reference number, working - directory number, drive number, or 0). - - Result Codes - noErr 0 No error - nsvErr -35 No such volume - ioErr -36 I/O error - bdNamErr -37 Bad volume name - fBsyErr -47 One or more files are open - paramErr -50 No default volume - nsDrvErr -56 No such drive - extFSErr -58 External file system error - no file - system claimed this call. -*/ - -/*****************************************************************************/ - -pascal OSErr OnLine(FSSpecPtr volumes, - short reqVolCount, - short *actVolCount, - short *volIndex); -/* ¦ Return the list of volumes currently mounted. - The OnLine function returns the list of volumes currently mounted in - an array of FSSpec records. - - A noErr result indicates that the volumes array was filled - (actVolCount == reqVolCount) and there may be additional volumes - mounted. A nsvErr result indicates that the end of the volume list - was found and actVolCount volumes were actually found this time. - - volumes input: Pointer to array of FSSpec where the volume list - is returned. - reqVolCount input: Maximum number of volumes to return (the number of - elements in the volumes array). - actVolCount output: The number of volumes actually returned. - volIndex input: The current volume index position. Set to 1 to - start with the first volume. - output: The volume index position to get the next volume. - Pass this value the next time you call OnLine to - start where you left off. - - Result Codes - noErr 0 No error, but there are more volumes - to list - nsvErr -35 No more volumes to be listed - paramErr -50 volIndex was <= 0 -*/ - -/*****************************************************************************/ - -pascal OSErr SetDefault(short newVRefNum, - long newDirID, - short *oldVRefNum, - long *oldDirID); -/* ¦ Set the default volume before making Standard I/O requests. - The SetDefault function sets the default volume and directory to the - volume specified by newVRefNum and the directory specified by newDirID. - The current default volume reference number and directory ID are - returned in oldVRefNum and oldDir and must be used to restore the - default volume and directory to their previous state *as soon as - possible* with the RestoreDefault function. These two functions are - designed to be used as a wrapper around Standard I/O routines where - the location of the file is implied to be the default volume and - directory. In other words, this is how you should use these functions: - - error = SetDefault(newVRefNum, newDirID, &oldVRefNum, &oldDirID); - if ( error == noErr ) - { - // call the Stdio functions like remove, rename, tmpfile, - // fopen, freopen, etc. or non-ANSI extensions like - // fdopen,fsetfileinfo, -- create, open, unlink, etc. here! - - error = RestoreDefault(oldVRefNum, oldDirID); - } - - By using these functions as a wrapper, you won't need to open a working - directory (because SetDefault and RestoreDefault use HSetVol) and you - won't have to worry about the effects of using HSetVol (documented in - Technical Note "FL 11 - PBHSetVol is Dangerous" and in the - Inside Macintosh: Files book in the description of the HSetVol and - PBHSetVol functions) because the default volume/directory is restored - before giving up control to code that might be affected by HSetVol. - - newVRefNum input: Volume specification (volume reference number, - working directory number, drive number, or 0) of - the new default volume. - newDirID input: Directory ID of the new default directory. - oldVRefNum output: The volume specification to save for use with - RestoreDefault. - oldDirID output: The directory ID to save for use with - RestoreDefault. - - Result Codes - noErr 0 No error - nsvErr -35 No such volume - bdNamErr -37 Bad volume name - fnfErr -43 Directory not found - paramErr -50 No default volume - afpAccessDenied -5000 User does not have access to the directory - - __________ - - Also see: RestoreDefault -*/ - -/*****************************************************************************/ - -pascal OSErr RestoreDefault(short oldVRefNum, - long oldDirID); -/* ¦ Restore the default volume after making Standard C I/O requests. - The RestoreDefault function restores the default volume and directory - to the volume specified by oldVRefNum and the directory specified by - oldDirID. The oldVRefNum and oldDirID parameters were previously - obtained from the SetDefault function. These two functions are designed - to be used as a wrapper around Standard C I/O routines where the - location of the file is implied to be the default volume and directory. - In other words, this is how you should use these functions: - - error = SetDefault(newVRefNum, newDirID, &oldVRefNum, &oldDirID); - if ( error == noErr ) - { - // call the Stdio functions like remove, rename, tmpfile, - // fopen, freopen, etc. or non-ANSI extensions like - // fdopen,fsetfileinfo, -- create, open, unlink, etc. here! - - error = RestoreDefault(oldVRefNum, oldDirID); - } - - By using these functions as a wrapper, you won't need to open a working - directory (because SetDefault and RestoreDefault use HSetVol) and you - won't have to worry about the effects of using HSetVol (documented in - Technical Note "FL 11 - PBHSetVol is Dangerous" and in the - Inside Macintosh: Files book in the description of the HSetVol and - PBHSetVol functions) because the default volume/directory is restored - before giving up control to code that might be affected by HSetVol. - - oldVRefNum input: The volume specification to restore. - oldDirID input: The directory ID to restore. - - Result Codes - noErr 0 No error - nsvErr -35 No such volume - bdNamErr -37 Bad volume name - fnfErr -43 Directory not found - paramErr -50 No default volume - rfNumErr -51 Bad working directory reference number - afpAccessDenied -5000 User does not have access to the directory - - __________ - - Also see: SetDefault -*/ - -/*****************************************************************************/ - -pascal OSErr GetDInfo(short vRefNum, - long dirID, - ConstStr255Param name, - DInfo *fndrInfo); -/* ¦ Get the finder information for a directory. - The GetDInfo function gets the finder information for a directory. - - 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. - fndrInfo output: If the object is a directory, then its DInfo. - - 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 - 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 - - __________ - - Also see: FSpGetDInfo, FSpGetFInfoCompat -*/ - -/*****************************************************************************/ - -pascal OSErr FSpGetDInfo(const FSSpec *spec, - DInfo *fndrInfo); -/* ¦ Get the finder information for a directory. - The FSpGetDInfo function gets the finder information for a directory. - - spec input: An FSSpec record specifying the directory. - fndrInfo output: If the object is a directory, then its DInfo. - - 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 - 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 - - __________ - - Also see: FSpGetFInfoCompat, GetDInfo -*/ - -/*****************************************************************************/ - -pascal OSErr SetDInfo(short vRefNum, - long dirID, - ConstStr255Param name, - const DInfo *fndrInfo); -/* ¦ Set the finder information for a directory. - The SetDInfo function sets the finder information for a directory. - - 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. - fndrInfo input: The DInfo. - - 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 - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - paramErr -50 No default volume - 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 - - __________ - - Also see: FSpSetDInfo, FSpSetFInfoCompat -*/ - -/*****************************************************************************/ - -pascal OSErr FSpSetDInfo(const FSSpec *spec, - const DInfo *fndrInfo); -/* ¦ Set the finder information for a directory. - The FSpSetDInfo function sets the finder information for a directory. - - spec input: An FSSpec record specifying the directory. - fndrInfo input: The DInfo. - - 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 - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - paramErr -50 No default volume - 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 - - __________ - - Also see: FSpSetFInfoCompat, SetDInfo -*/ - -/*****************************************************************************/ - -#if OLDROUTINENAMES -#define GetDirID(vRefNum, dirID, name, theDirID, isDirectory) \ - GetDirectoryID(vRefNum, dirID, name, theDirID, isDirectory) -#endif - -pascal OSErr GetDirectoryID(short vRefNum, - long dirID, - ConstStr255Param name, - long *theDirID, - Boolean *isDirectory); -/* ¦ Get the directory ID number of the directory specified. - The GetDirectoryID function gets the directory ID number of the - directory specified. If a file is specified, then the parent - directory of the file is returned and isDirectory is false. If - a directory is specified, then that directory's ID number is - returned and isDirectory is true. - WARNING: Volume names on the Macintosh are *not* unique -- Multiple - mounted volumes can have the same name. For this reason, the use of a - volume name or 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 volume name or full pathname is used, the File Manager - currently uses the first volume it finds with a matching name in the - volume queue. - - 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. - - 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 - 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 -*/ - -/*****************************************************************************/ - -#if OLDROUTINENAMES -#define DirIDFromFSSpec(spec, theDirID, isDirectory) \ - FSpGetDirectoryID(spec, theDirID, isDirectory) -#endif - -pascal OSErr FSpGetDirectoryID(const FSSpec *spec, - long *theDirID, - Boolean *isDirectory); -/* ¦ Get the directory ID number of a directory. - The FSpGetDirectoryID function gets the directory ID number of the - directory specified by spec. If spec is to a file, then the parent - directory of the file is returned and isDirectory is false. If - spec is to a directory, then that directory's ID number is - returned and isDirectory is true. - - spec input: An FSSpec record specifying the directory. - theDirID output: The directory ID. - isDirectory output: True if object is a directory; false if - object is a file. - - 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 - 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 -*/ - -/*****************************************************************************/ - -pascal OSErr GetDirName(short vRefNum, - long dirID, - Str31 name); -/* ¦ Get the name of a directory from its directory ID. - The GetDirName function gets the name of a directory from its - directory ID. - - vRefNum input: Volume specification. - dirID input: Directory ID. - name output: Points to a Str31 where the directory name is to be - returned. - - 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 - name parameter 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 -*/ - -/*****************************************************************************/ - -pascal OSErr GetIOACUser(short vRefNum, - long dirID, - ConstStr255Param name, - SInt8 *ioACUser); -/* ¦ Get a directory's access restrictions byte. - GetIOACUser returns a directory's access restrictions byte. - Use the masks and macro defined in MoreFilesExtras to check for - specific access priviledges. - - 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. - ioACUser output: The access restriction byte - - 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 - 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 -*/ - -/*****************************************************************************/ - -pascal OSErr FSpGetIOACUser(const FSSpec *spec, - SInt8 *ioACUser); -/* ¦ Get a directory's access restrictions byte. - FSpGetIOACUser returns a directory's access restrictions byte. - Use the masks and macro defined in MoreFilesExtras to check for - specific access priviledges. - - spec input: An FSSpec record specifying the directory. - ioACUser output: The access restriction byte - - 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 - 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 -*/ - -/*****************************************************************************/ - -pascal OSErr GetParentID(short vRefNum, - long dirID, - ConstStr255Param name, - long *parID); -/* ¦ Get the parent directory ID number of the specified object. - The GetParentID function gets the parent directory ID number of the - specified object. - - 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. - parID output: The parent directory ID of the specified object. - - 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 - 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 -*/ - -/*****************************************************************************/ - -pascal OSErr GetFilenameFromPathname(ConstStr255Param pathname, - Str255 filename); -/* ¦ Get the object name from the end of a full or partial pathname. - The GetFilenameFromPathname function gets the file (or directory) name - from the end of a full or partial pathname. Returns notAFileErr if the - pathname is nil, the pathname is empty, or the pathname cannot refer to - a filename (with a noErr result, the pathname could still refer to a - directory). - - pathname input: A full or partial pathname. - filename output: The file (or directory) name. - - Result Codes - noErr 0 No error - notAFileErr -1302 The pathname is nil, the pathname - is empty, or the pathname cannot refer - to a filename - - __________ - - See also: GetObjectLocation. -*/ - -/*****************************************************************************/ - -pascal OSErr GetObjectLocation(short vRefNum, - long dirID, - ConstStr255Param pathname, - short *realVRefNum, - long *realParID, - Str255 realName, - Boolean *isDirectory); -/* ¦ Get a file system object's location. - The GetObjectLocation function gets a file system object's location - - that is, its real volume reference number, real parent directory ID, - and name. While we're at it, determine if the object is a file or directory. - If GetObjectLocation returns fnfErr, then the location information - returned is valid, but it describes an object that doesn't exist. - You can use the location information for another operation, such as - creating a file or directory. - - vRefNum input: Volume specification. - dirID input: Directory ID. - pathname input: Pointer to object name, or nil when dirID specifies - a directory that's the object. - realVRefNum output: The real volume reference number. - realParID output: The parent directory ID of the specified object. - realName output: The name of the specified object (the case of the - object name may not be the same as the object's - catalog entry on disk - since the Macintosh file - system is not case sensitive, it shouldn't matter). - isDirectory output: True if object is a directory; false if object - is a file. - - 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 - dirNFErr -120 Directory not found or incomplete pathname - notAFileErr -1302 The pathname is nil, the pathname - is empty, or the pathname cannot refer - to a filename - afpAccessDenied -5000 User does not have the correct access - afpObjectTypeErr -5025 Directory not found or incomplete pathname - - __________ - - See also: FSMakeFSSpecCompat -*/ - -/*****************************************************************************/ - -pascal OSErr GetDirItems(short vRefNum, - long dirID, - ConstStr255Param name, - Boolean getFiles, - Boolean getDirectories, - FSSpecPtr items, - short reqItemCount, - short *actItemCount, - short *itemIndex); -/* ¦ Return a list of items in a directory. - The GetDirItems function returns a list of items in the specified - directory in an array of FSSpec records. File, subdirectories, or - both can be returned in the list. - - A noErr result indicates that the items array was filled - (actItemCount == reqItemCount) and there may be additional items - left in the directory. A fnfErr result indicates that the end of - the directory list was found and actItemCount items were actually - found this time. - - 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. - getFiles input: Pass true to have files added to the items list. - getDirectories input: Pass true to have directories added to the - items list. - items input: Pointer to array of FSSpec where the item list - is returned. - reqItemCount input: Maximum number of items to return (the number - of elements in the items array). - actItemCount output: The number of items actually returned. - itemIndex input: The current item index position. Set to 1 to - start with the first item in the directory. - output: The item index position to get the next item. - Pass this value the next time you call - GetDirItems to start where you left off. - - Result Codes - noErr 0 No error, but there are more items - to list - nsvErr -35 No such volume - ioErr -36 I/O error - bdNamErr -37 Bad filename - fnfErr -43 File not found, there are no more items - to be listed. - paramErr -50 No default volume or itemIndex was <= 0 - 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 -*/ - -/*****************************************************************************/ - -pascal OSErr DeleteDirectoryContents(short vRefNum, - long dirID, - ConstStr255Param name); -/* ¦ Delete the contents of a directory. - The DeleteDirectoryContents function deletes the contents of a directory. - All files and subdirectories in the specified directory are deleted. - If a locked file or directory is encountered, it is unlocked and then - deleted. If any unexpected errors are encountered, - DeleteDirectoryContents quits and returns to the caller. - - vRefNum input: Volume specification. - dirID input: Directory ID. - name input: Pointer to directory name, or nil when dirID specifies - a directory that's the object. - - 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 - paramErr -50 No default volume - 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 - - __________ - - Also see: DeleteDirectory -*/ - -/*****************************************************************************/ - -pascal OSErr DeleteDirectory(short vRefNum, - long dirID, - ConstStr255Param name); -/* ¦ Delete a directory and its contents. - The DeleteDirectory function deletes a directory and its contents. - All files and subdirectories in the specified directory are deleted. - If a locked file or directory is encountered, it is unlocked and then - deleted. After deleting the directories contents, the directory is - deleted. If any unexpected errors are encountered, DeleteDirectory - quits and returns to the caller. - - vRefNum input: Volume specification. - dirID input: Directory ID. - name input: Pointer to directory name, or nil when dirID specifies - a directory that's the object. - - 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 - paramErr -50 No default volume - 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 - - __________ - - Also see: DeleteDirectoryContents -*/ - -/*****************************************************************************/ - -pascal OSErr CheckObjectLock(short vRefNum, - long dirID, - ConstStr255Param name); -/* ¦ Determine if a file or directory is locked. - The CheckObjectLock function determines if a file or directory is locked. - If CheckObjectLock returns noErr, then the file or directory - is not locked. If CheckObjectLock returns fLckdErr, the it is locked. - - 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. - - 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 - fLckdErr -45 File is locked - paramErr -50 No default volume - 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 - - __________ - - Also see: FSpCheckObjectLock -*/ - -/*****************************************************************************/ - -pascal OSErr FSpCheckObjectLock(const FSSpec *spec); -/* ¦ Determine if a file or directory is locked. - The FSpCheckObjectLock function determines if a file or directory is locked. - If FSpCheckObjectLock returns noErr, then the file or directory - is not locked. - - spec input: An FSSpec record specifying the object. - - 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 - fLckdErr -45 File is locked - paramErr -50 No default volume - 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 - - __________ - - Also see: CheckObjectLock -*/ - -/*****************************************************************************/ - -pascal OSErr GetFileSize(short vRefNum, - long dirID, - ConstStr255Param fileName, - long *dataSize, - long *rsrcSize); -/* ¦ Get the logical sizes of a file's forks. - The GetFileSize function returns the logical size of a file's - data and resource fork. - - vRefNum input: Volume specification. - dirID input: Directory ID. - name input: The name of the file. - dataSize output: The number of bytes in the file's data fork. - rsrcSize output: The number of bytes in 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 - 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 - - __________ - - See also: FSpGetFileSize -*/ - -/*****************************************************************************/ - -pascal OSErr FSpGetFileSize(const FSSpec *spec, - long *dataSize, - long *rsrcSize); -/* ¦ Get the logical sizes of a file's forks. - The FSpGetFileSize function returns the logical size of a file's - data and resource fork. - - spec input: An FSSpec record specifying the file. - dataSize output: The number of bytes in the file's data fork. - rsrcSize output: The number of bytes in 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 - 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 - - __________ - - See also: GetFileSize -*/ - -/*****************************************************************************/ - -pascal OSErr BumpDate(short vRefNum, - long dirID, - ConstStr255Param name); -/* ¦ Update the modification date of a file or directory. - The BumpDate function changes the modification date of a file or - directory to the current date/time. If the modification date is already - equal to the current date/time, then add one second to the - modification date. - - 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. - - 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 - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - paramErr -50 No default volume - 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: FSpBumpDate -*/ - -/*****************************************************************************/ - -pascal OSErr FSpBumpDate(const FSSpec *spec); -/* ¦ Update the modification date of a file or directory. - The FSpBumpDate function changes the modification date of a file or - directory to the current date/time. If the modification date is already - equal to the current date/time, then add one second to the - modification date. - - spec input: An FSSpec record specifying the object. - - 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 - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - paramErr -50 No default volume - 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: BumpDate -*/ - -/*****************************************************************************/ - -pascal OSErr ChangeCreatorType(short vRefNum, - long dirID, - ConstStr255Param name, - OSType creator, - OSType fileType); -/* ¦ Change the creator or file type of a file. - The ChangeCreatorType function changes the creator or file type of a file. - - vRefNum input: Volume specification. - dirID input: Directory ID. - name input: The name of the file. - creator input: The new creator type or 0x00000000 to leave - the creator type alone. - fileType input: The new file type or 0x00000000 to leave the - file type alone. - - 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 - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - paramErr -50 No default volume - dirNFErr -120 Directory not found or incomplete pathname - notAFileErr -1302 Name was not a file - afpAccessDenied -5000 User does not have the correct access - afpObjectTypeErr -5025 Directory not found or incomplete pathname - - __________ - - See also: FSpChangeCreatorType -*/ - -/*****************************************************************************/ - -pascal OSErr FSpChangeCreatorType(const FSSpec *spec, - OSType creator, - OSType fileType); -/* ¦ Change the creator or file type of a file. - The FSpChangeCreatorType function changes the creator or file type of a file. - - spec input: An FSSpec record specifying the file. - creator input: The new creator type or 0x00000000 to leave - the creator type alone. - fileType input: The new file type or 0x00000000 to leave the - file type alone. - - 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 - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - paramErr -50 No default volume - dirNFErr -120 Directory not found or incomplete pathname - notAFileErr -1302 Name was not a file - afpAccessDenied -5000 User does not have the correct access - afpObjectTypeErr -5025 Directory not found or incomplete pathname - - __________ - - See also: ChangeCreatorType -*/ - -/*****************************************************************************/ - -pascal OSErr ChangeFDFlags(short vRefNum, - long dirID, - ConstStr255Param name, - Boolean setBits, - unsigned short flagBits); -/* ¦ Set or clear Finder Flag bits. - The ChangeFDFlags function sets or clears Finder Flag bits in the - fdFlags field of a file or directory's FInfo record. - - 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. - setBits input: If true, then set the bits specified in flagBits. - If false, then clear the bits specified in flagBits. - flagBits input: The flagBits parameter specifies which Finder Flag - bits to set or clear. If a bit in flagBits is set, - then the same bit in fdFlags is either set or - cleared depending on the state of the setBits - parameter. - - 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 - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - paramErr -50 No default volume - 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: FSpChangeFDFlags -*/ - -/*****************************************************************************/ - -pascal OSErr FSpChangeFDFlags(const FSSpec *spec, - Boolean setBits, - unsigned short flagBits); -/* ¦ Set or clear Finder Flag bits. - The FSpChangeFDFlags function sets or clears Finder Flag bits in the - fdFlags field of a file or directory's FInfo record. - - spec input: An FSSpec record specifying the object. - setBits input: If true, then set the bits specified in flagBits. - If false, then clear the bits specified in flagBits. - flagBits input: The flagBits parameter specifies which Finder Flag - bits to set or clear. If a bit in flagBits is set, - then the same bit in fdFlags is either set or - cleared depending on the state of the setBits - parameter. - - 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 - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - paramErr -50 No default volume - 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: ChangeFDFlags -*/ - -/*****************************************************************************/ - -pascal OSErr SetIsInvisible(short vRefNum, - long dirID, - ConstStr255Param name); -/* ¦ Set the invisible Finder Flag bit. - The SetIsInvisible function sets the invisible bit in the fdFlags - word of the specified file or directory's finder information. - - 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. - - 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 - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - paramErr -50 No default volume - 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: FSpSetIsInvisible, ClearIsInvisible, FSpClearIsInvisible -*/ - -/*****************************************************************************/ - -pascal OSErr FSpSetIsInvisible(const FSSpec *spec); -/* ¦ Set the invisible Finder Flag bit. - The FSpSetIsInvisible function sets the invisible bit in the fdFlags - word of the specified file or directory's finder information. - - spec input: An FSSpec record specifying the object. - - 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 - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - paramErr -50 No default volume - 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: SetIsInvisible, ClearIsInvisible, FSpClearIsInvisible -*/ - -/*****************************************************************************/ - -pascal OSErr ClearIsInvisible(short vRefNum, - long dirID, - ConstStr255Param name); -/* ¦ Clear the invisible Finder Flag bit. - The ClearIsInvisible function clears the invisible bit in the fdFlags - word of the specified file or directory's finder information. - - 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. - - 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 - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - paramErr -50 No default volume - 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: SetIsInvisible, FSpSetIsInvisible, FSpClearIsInvisible -*/ - -/*****************************************************************************/ - -pascal OSErr FSpClearIsInvisible(const FSSpec *spec); -/* ¦ Clear the invisible Finder Flag bit. - The FSpClearIsInvisible function clears the invisible bit in the fdFlags - word of the specified file or directory's finder information. - - spec input: An FSSpec record specifying the object. - - 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 - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - paramErr -50 No default volume - 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: SetIsInvisible, FSpSetIsInvisible, ClearIsInvisible -*/ - -/*****************************************************************************/ - -pascal OSErr SetNameLocked(short vRefNum, - long dirID, - ConstStr255Param name); -/* ¦ Set the nameLocked Finder Flag bit. - The SetNameLocked function sets the nameLocked bit in the fdFlags word - of the specified file or directory's finder information. - - 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. - - 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 - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - paramErr -50 No default volume - 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: FSpSetNameLocked, ClearNameLocked, FSpClearNameLocked -*/ - -/*****************************************************************************/ - -pascal OSErr FSpSetNameLocked(const FSSpec *spec); -/* ¦ Set the nameLocked Finder Flag bit. - The FSpSetNameLocked function sets the nameLocked bit in the fdFlags word - of the specified file or directory's finder information. - - spec input: An FSSpec record specifying the object. - - 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 - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - paramErr -50 No default volume - 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: SetNameLocked, ClearNameLocked, FSpClearNameLocked -*/ - -/*****************************************************************************/ - -pascal OSErr ClearNameLocked(short vRefNum, - long dirID, - ConstStr255Param name); -/* ¦ Clear the nameLocked Finder Flag bit. - The ClearNameLocked function clears the nameLocked bit in the fdFlags - word of the specified file or directory's finder information. - - 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. - - 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 - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - paramErr -50 No default volume - 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: SetNameLocked, FSpSetNameLocked, FSpClearNameLocked -*/ - -/*****************************************************************************/ - -pascal OSErr FSpClearNameLocked(const FSSpec *spec); -/* ¦ Clear the nameLocked Finder Flag bit. - The FSpClearNameLocked function clears the nameLocked bit in the fdFlags - word of the specified file or directory's finder information. - - spec input: An FSSpec record specifying the object. - - 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 - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - paramErr -50 No default volume - 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: SetNameLocked, FSpSetNameLocked, ClearNameLocked -*/ - -/*****************************************************************************/ - -pascal OSErr SetIsStationery(short vRefNum, - long dirID, - ConstStr255Param name); -/* ¦ Set the isStationery Finder Flag bit. - The SetIsStationery function sets the isStationery bit in the - fdFlags word of the specified file or directory's finder information. - - 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. - - 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 - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - paramErr -50 No default volume - 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: FSpSetIsStationery, ClearIsStationery, FSpClearIsStationery -*/ - -/*****************************************************************************/ - -pascal OSErr FSpSetIsStationery(const FSSpec *spec); -/* ¦ Set the isStationery Finder Flag bit. - The FSpSetIsStationery function sets the isStationery bit in the - fdFlags word of the specified file or directory's finder information. - - spec input: An FSSpec record specifying the object. - - 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 - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - paramErr -50 No default volume - 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: SetIsStationery, ClearIsStationery, FSpClearIsStationery -*/ - -/*****************************************************************************/ - -pascal OSErr ClearIsStationery(short vRefNum, - long dirID, - ConstStr255Param name); -/* ¦ Clear the isStationery Finder Flag bit. - The ClearIsStationery function clears the isStationery bit in the - fdFlags word of the specified file or directory's finder information. - - 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. - - 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 - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - paramErr -50 No default volume - 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: SetIsStationery, FSpSetIsStationery, FSpClearIsStationery -*/ - -/*****************************************************************************/ - -pascal OSErr FSpClearIsStationery(const FSSpec *spec); -/* ¦ Clear the isStationery Finder Flag bit. - The FSpClearIsStationery function clears the isStationery bit in the - fdFlags word of the specified file or directory's finder information. - - spec input: An FSSpec record specifying the object. - - 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 - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - paramErr -50 No default volume - 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: SetIsStationery, FSpSetIsStationery, ClearIsStationery -*/ - -/*****************************************************************************/ - -pascal OSErr SetHasCustomIcon(short vRefNum, - long dirID, - ConstStr255Param name); -/* ¦ Set the hasCustomIcon Finder Flag bit. - The SetHasCustomIcon function sets the hasCustomIcon bit in the - fdFlags word of the specified file or directory's finder information. - - 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. - - 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 - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - paramErr -50 No default volume - 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: FSpSetHasCustomIcon, ClearHasCustomIcon, FSpClearHasCustomIcon -*/ - -/*****************************************************************************/ - -pascal OSErr FSpSetHasCustomIcon(const FSSpec *spec); -/* ¦ Set the hasCustomIcon Finder Flag bit. - The FSpSetHasCustomIcon function sets the hasCustomIcon bit in the - fdFlags word of the specified file or directory's finder information. - - spec input: An FSSpec record specifying the object. - - 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 - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - paramErr -50 No default volume - 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: SetHasCustomIcon, ClearHasCustomIcon, FSpClearHasCustomIcon -*/ - -/*****************************************************************************/ - -pascal OSErr ClearHasCustomIcon(short vRefNum, - long dirID, - ConstStr255Param name); -/* ¦ Clear the hasCustomIcon Finder Flag bit. - The ClearHasCustomIcon function clears the hasCustomIcon bit in the - fdFlags word of the specified file or directory's finder information. - - 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. - - 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 - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - paramErr -50 No default volume - 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: SetHasCustomIcon, FSpSetHasCustomIcon, FSpClearHasCustomIcon -*/ - -/*****************************************************************************/ - -pascal OSErr FSpClearHasCustomIcon(const FSSpec *spec); -/* ¦ Clear the hasCustomIcon Finder Flag bit. - The FSpClearHasCustomIcon function clears the hasCustomIcon bit in the - fdFlags word of the specified file or directory's finder information. - - spec input: An FSSpec record specifying the object. - - 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 - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - paramErr -50 No default volume - 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: SetHasCustomIcon, FSpSetHasCustomIcon, ClearHasCustomIcon -*/ - -/*****************************************************************************/ - -pascal OSErr ClearHasBeenInited(short vRefNum, - long dirID, - ConstStr255Param name); -/* ¦ Clear the hasBeenInited Finder Flag bit. - The ClearHasBeenInited function clears the hasBeenInited bit in the - fdFlags word of the specified file or directory's finder information. - - 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. - - 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 - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - paramErr -50 No default volume - 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: FSpClearHasBeenInited -*/ - -/*****************************************************************************/ - -pascal OSErr FSpClearHasBeenInited(const FSSpec *spec); -/* ¦ Clear the hasBeenInited Finder Flag bit. - The FSpClearHasBeenInited function clears the hasBeenInited bit in the - fdFlags word of the specified file or directory's finder information. - - spec input: An FSSpec record specifying the object. - - 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 - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - paramErr -50 No default volume - 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: ClearHasBeenInited -*/ - -/*****************************************************************************/ - -pascal OSErr CopyFileMgrAttributes(short srcVRefNum, - long srcDirID, - ConstStr255Param srcName, - short dstVRefNum, - long dstDirID, - ConstStr255Param dstName, - Boolean copyLockBit); -/* ¦ Copy all File Manager attributes from the source to the destination. - The CopyFileMgrAttributes function copies all File Manager attributes - from the source file or directory to the destination file or directory. - If copyLockBit is true, then set the locked state of the destination - to match the source. - - 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. - copyLockBit input: If true, set the locked state of the destination - to match the source. - - 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 - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - paramErr -50 No default volume - 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: FSpCopyFileMgrAttributes -*/ - -/*****************************************************************************/ - -pascal OSErr FSpCopyFileMgrAttributes(const FSSpec *srcSpec, - const FSSpec *dstSpec, - Boolean copyLockBit); -/* ¦ Copy all File Manager attributes from the source to the destination. - The FSpCopyFileMgrAttributes function copies all File Manager attributes - from the source file or directory to the destination file or directory. - If copyLockBit is true, then set the locked state of the destination - to match the source. - - srcSpec input: An FSSpec record specifying the source object. - dstSpec input: An FSSpec record specifying the destination object. - copyLockBit input: If true, set the locked state of the destination - to match the source. - - 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 - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - paramErr -50 No default volume - 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: CopyFileMgrAttributes -*/ - -/*****************************************************************************/ - -pascal OSErr HOpenAware(short vRefNum, - long dirID, - ConstStr255Param fileName, - short denyModes, - short *refNum); -/* ¦ Open the data fork of a file using deny mode permissions. - The HOpenAware function opens the data fork of a file using deny mode - permissions instead the normal File Manager permissions. If OpenDeny - is not available, then HOpenAware translates the deny modes to the - closest File Manager permissions and tries to open the file with - OpenDF first, and then Open if OpenDF isn't available. By using - HOpenAware with deny mode permissions, a program can be "AppleShare - aware" and fall back on the standard File Manager open calls - automatically. - - vRefNum input: Volume specification. - dirID input: Directory ID. - fileName input: The name of the file. - denyModes input: The deny modes access under which to open the file. - refNum output: The file reference number of the opened file. - - Result Codes - noErr 0 No error - nsvErr -35 No such volume - tmfoErr -42 Too many files open - fnfErr -43 File not found - wPrErr -44 Volume locked by hardware - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - opWrErr -49 File already open for writing - paramErr -50 No default volume - permErr -54 File is already open and cannot be opened using specified deny modes - afpAccessDenied -5000 User does not have the correct access to the file - afpDenyConflict -5006 Requested access permission not possible - - __________ - - See also: FSpOpenAware, HOpenRFAware, FSpOpenRFAware -*/ - -/*****************************************************************************/ - -pascal OSErr FSpOpenAware(const FSSpec *spec, - short denyModes, - short *refNum); -/* ¦ Open the data fork of a file using deny mode permissions. - The FSpOpenAware function opens the data fork of a file using deny mode - permissions instead the normal File Manager permissions. If OpenDeny - is not available, then FSpOpenAware translates the deny modes to the - closest File Manager permissions and tries to open the file with - OpenDF first, and then Open if OpenDF isn't available. By using - FSpOpenAware with deny mode permissions, a program can be "AppleShare - aware" and fall back on the standard File Manager open calls - automatically. - - spec input: An FSSpec record specifying the file. - denyModes input: The deny modes access under which to open the file. - refNum output: The file reference number of the opened file. - - Result Codes - noErr 0 No error - nsvErr -35 No such volume - tmfoErr -42 Too many files open - fnfErr -43 File not found - wPrErr -44 Volume locked by hardware - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - opWrErr -49 File already open for writing - paramErr -50 No default volume - permErr -54 File is already open and cannot be opened using specified deny modes - afpAccessDenied -5000 User does not have the correct access to the file - afpDenyConflict -5006 Requested access permission not possible - - __________ - - See also: HOpenAware, HOpenRFAware, FSpOpenRFAware -*/ - -/*****************************************************************************/ - -pascal OSErr HOpenRFAware(short vRefNum, - long dirID, - ConstStr255Param fileName, - short denyModes, - short *refNum); -/* ¦ Open the resource fork of a file using deny mode permissions. - The HOpenRFAware function opens the resource fork of a file using deny - mode permissions instead the normal File Manager permissions. If - OpenRFDeny is not available, then HOpenRFAware translates the deny - modes to the closest File Manager permissions and tries to open the - file with OpenRF. By using HOpenRFAware with deny mode permissions, - a program can be "AppleShare aware" and fall back on the standard - File Manager open calls automatically. - - vRefNum input: Volume specification. - dirID input: Directory ID. - fileName input: The name of the file. - denyModes input: The deny modes access under which to open the file. - refNum output: The file reference number of the opened file. - - Result Codes - noErr 0 No error - nsvErr -35 No such volume - tmfoErr -42 Too many files open - fnfErr -43 File not found - wPrErr -44 Volume locked by hardware - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - opWrErr -49 File already open for writing - paramErr -50 No default volume - permErr -54 File is already open and cannot be opened using specified deny modes - afpAccessDenied -5000 User does not have the correct access to the file - afpDenyConflict -5006 Requested access permission not possible - - __________ - - See also: HOpenAware, FSpOpenAware, FSpOpenRFAware -*/ - -/*****************************************************************************/ - -pascal OSErr FSpOpenRFAware(const FSSpec *spec, - short denyModes, - short *refNum); -/* ¦ Open the resource fork of a file using deny mode permissions. - The FSpOpenRFAware function opens the resource fork of a file using deny - mode permissions instead the normal File Manager permissions. If - OpenRFDeny is not available, then FSpOpenRFAware translates the deny - modes to the closest File Manager permissions and tries to open the - file with OpenRF. By using FSpOpenRFAware with deny mode permissions, - a program can be "AppleShare aware" and fall back on the standard - File Manager open calls automatically. - - spec input: An FSSpec record specifying the file. - denyModes input: The deny modes access under which to open the file. - refNum output: The file reference number of the opened file. - - Result Codes - noErr 0 No error - nsvErr -35 No such volume - tmfoErr -42 Too many files open - fnfErr -43 File not found - wPrErr -44 Volume locked by hardware - fLckdErr -45 File is locked - vLckdErr -46 Volume is locked or read-only - opWrErr -49 File already open for writing - paramErr -50 No default volume - permErr -54 File is already open and cannot be opened using specified deny modes - afpAccessDenied -5000 User does not have the correct access to the file - afpDenyConflict -5006 Requested access permission not possible - - __________ - - See also: HOpenAware, FSpOpenAware, HOpenRFAware -*/ - -/*****************************************************************************/ - -pascal OSErr FSReadNoCache(short refNum, - long *count, - void *buffPtr); -/* ¦ Read any number of bytes from an open file requesting no caching. - The FSReadNoCache function reads any number of bytes from an open file - while asking the file system to bypass its cache mechanism. - - refNum input: The file reference number of an open file. - count input: The number of bytes to read. - output: The number of bytes actually read. - buffPtr input: A pointer to the data buffer into which the bytes are - to be read. - - Result Codes - noErr 0 No error - readErr Ð19 Driver does not respond to read 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 - ioErr Ð36 Data does not match in read-verify mode - fnOpnErr -38 File not open - rfNumErr -51 Bad reference number - afpAccessDenied -5000 User does not have the correct access to - the file - - __________ - - See also: FSWriteNoCache -*/ - -/*****************************************************************************/ - -pascal OSErr FSWriteNoCache(short refNum, - long *count, - const void *buffPtr); -/* ¦ Write any number of bytes to an open file requesting no caching. - The FSReadNoCache function writes any number of bytes to an open file - while asking the file system to bypass its cache mechanism. - - refNum input: The file reference number of an open file. - count input: The number of bytes to write to the file. - output: The number of bytes actually written. - buffPtr input: A pointer to the data buffer from which the bytes are - to be written. - - Result Codes - noErr 0 No error - 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 Disk full - ioErr Ð36 Data does not match in read-verify mode - fnOpnErr -38 File not open - wPrErr -44 Hardware volume lock - fLckdErr -45 File is locked - vLckdErr -46 Software volume lock - rfNumErr -51 Bad reference number - wrPermErr -61 Read/write permission doesnÕt - allow writing - afpAccessDenied -5000 User does not have the correct access to - the file - - __________ - - See also: FSReadNoCache -*/ - -/*****************************************************************************/ - -pascal OSErr FSWriteVerify(short refNum, - long *count, - const void *buffPtr); -/* ¦ Write any number of bytes to an open file and then verify the data was written. - The FSWriteVerify function writes any number of bytes to an open file - and then verifies that the data was actually written to the device. - - refNum input: The file reference number of an open file. - count input: The number of bytes to write to the file. - output: The number of bytes actually written and verified. - buffPtr input: A pointer to the data buffer from which the bytes are - to be written. - - 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 Disk full - ioErr Ð36 Data does not match in read-verify mode - fnOpnErr -38 File not open - eofErr -39 Logical end-of-file reached - posErr -40 Attempt to position mark before start - of file - wPrErr -44 Hardware volume lock - fLckdErr -45 File is locked - vLckdErr -46 Software volume lock - rfNumErr -51 Bad reference number - gfpErr -52 Error during GetFPos - wrPermErr -61 Read/write permission doesnÕt - allow writing - memFullErr -108 Not enough room in heap zone to allocate - verify buffer - afpAccessDenied -5000 User does not have the correct access to - the file -*/ - -/*****************************************************************************/ - -pascal OSErr CopyFork(short srcRefNum, - short dstRefNum, - void *copyBufferPtr, - long copyBufferSize); -/* ¦ Copy all data from the source fork to the destination fork of open file forks. - The CopyFork function copies all data from the source fork to the - destination fork of open file forks and makes sure the destination EOF - is equal to the source EOF. - - srcRefNum input: The source file reference number. - dstRefNum input: The destination file reference number. - copyBufferPtr input: Pointer to buffer to use during copy. The - buffer should be at least 512-bytes minimum. - The larger the buffer, the faster the copy. - copyBufferSize input: The size of the copy buffer. - - 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 Disk full - ioErr Ð36 Data does not match in read-verify mode - fnOpnErr -38 File not open - wPrErr -44 Hardware volume lock - fLckdErr -45 File is locked - vLckdErr -46 Software volume lock - rfNumErr -51 Bad reference number - wrPermErr -61 Read/write permission doesnÕt - allow writing - afpAccessDenied -5000 User does not have the correct access to - the file -*/ - -/*****************************************************************************/ - -pascal OSErr GetFileLocation(short refNum, - short *vRefNum, - long *dirID, - StringPtr fileName); -/* ¦ Get the location of an open file. - The GetFileLocation function gets the location (volume reference number, - directory ID, and fileName) of an open file. - - refNum input: The file reference number of an open file. - vRefNum output: The volume reference number. - dirID output: The parent directory ID. - fileName input: Points to a buffer (minimum Str63) where the - filename is to be returned or must be nil. - output: The filename. - - Result Codes - noErr 0 No error - nsvErr -35 Specified volume doesnÕt exist - fnOpnErr -38 File not open - rfNumErr -51 Reference number specifies nonexistent - access path - - __________ - - See also: FSpGetFileLocation -*/ - -/*****************************************************************************/ - -pascal OSErr FSpGetFileLocation(short refNum, - FSSpec *spec); -/* ¦ Get the location of an open file in an FSSpec record. - The FSpGetFileLocation function gets the location of an open file in - an FSSpec record. - - refNum input: The file reference number of an open file. - spec output: FSSpec record containing the file name and location. - - Result Codes - noErr 0 No error - nsvErr -35 Specified volume doesnÕt exist - fnOpnErr -38 File not open - rfNumErr -51 Reference number specifies nonexistent - access path - - __________ - - See also: GetFileLocation -*/ - -/*****************************************************************************/ - -pascal OSErr CopyDirectoryAccess(short srcVRefNum, - long srcDirID, - ConstStr255Param srcName, - short dstVRefNum, - long dstDirID, - ConstStr255Param dstName); -/* ¦ Copy the AFP directory access privileges. - The CopyDirectoryAccess function copies the AFP directory access - privileges from one directory to another. Both directories must be on - the same file server, but not necessarily on the same server volume. - - srcVRefNum input: Source volume specification. - srcDirID input: Source directory ID. - srcName input: Pointer to source directory name, or nil when - srcDirID specifies the directory. - dstVRefNum input: Destination volume specification. - dstDirID input: Destination directory ID. - dstName input: Pointer to destination directory name, or nil when - dstDirID specifies the directory. - - Result Codes - noErr 0 No error - nsvErr -35 Volume not found - fnfErr -43 Directory not found - vLckdErr -46 Volume is locked or read-only - paramErr -50 Volume doesn't support this function - afpAccessDenied -5000 User does not have the correct access - to the directory - afpObjectTypeErr -5025 Object is a file, not a directory - - __________ - - See also: FSpCopyDirectoryAccess -*/ - -/*****************************************************************************/ - -pascal OSErr FSpCopyDirectoryAccess(const FSSpec *srcSpec, - const FSSpec *dstSpec); -/* ¦ Copy the AFP directory access privileges. - The FSpCopyDirectoryAccess function copies the AFP directory access - privileges from one directory to another. Both directories must be on - the same file server, but not necessarily on the same server volume. - - srcSpec input: An FSSpec record specifying the source directory. - dstSpec input: An FSSpec record specifying the destination directory. - - Result Codes - noErr 0 No error - nsvErr -35 Volume not found - fnfErr -43 Directory not found - vLckdErr -46 Volume is locked or read-only - paramErr -50 Volume doesn't support this function - afpAccessDenied -5000 User does not have the correct access - to the directory - afpObjectTypeErr -5025 Object is a file, not a directory - - __________ - - See also: CopyDirectoryAccess -*/ - -/*****************************************************************************/ - -pascal OSErr HMoveRenameCompat(short vRefNum, - long srcDirID, - ConstStr255Param srcName, - long dstDirID, - ConstStr255Param dstpathName, - ConstStr255Param copyName); -/* ¦ Move a file or directory and optionally rename it. - The HMoveRenameCompat function moves a file or directory and optionally - renames it. The source and destination locations must be on the same - volume. This routine works even if the volume doesn't support MoveRename. - - vRefNum input: Volume specification. - srcDirID input: Source directory ID. - srcName input: The source object name. - dstDirID input: Destination directory ID. - dstName input: Pointer to destination directory name, or - nil when dstDirID specifies a directory. - copyName input: Points to the new name if the object is to be - renamed or nil if the object isn't to be renamed. - - Result Codes - noErr 0 No error - dirFulErr -33 File directory full - dskFulErr -34 Disk is full - nsvErr -35 Volume not found - ioErr -36 I/O error - bdNamErr -37 Bad filename or attempt to move into - a file - fnfErr -43 Source file or directory not found - wPrErr -44 Hardware volume lock - fLckdErr -45 File is locked - vLckdErr -46 Destination volume is read-only - fBsyErr -47 File busy, directory not empty, or - working directory control block open - dupFNErr -48 Destination already exists - paramErr -50 Volume doesn't support this function, - no default volume, or source and - volOfflinErr -53 Volume is offline - fsRnErr -59 Problem during rename - dirNFErr -120 Directory not found or incomplete pathname - badMovErr -122 Attempted to move directory into - offspring - wrgVolTypErr -123 Not an HFS volume (it's a MFS volume) - notAFileErr -1302 The pathname is nil, the pathname - is empty, or the pathname cannot refer - to a filename - diffVolErr -1303 Files on different volumes - afpAccessDenied -5000 The user does not have the right to - move the file or directory - afpObjectTypeErr -5025 Directory not found or incomplete pathname - afpSameObjectErr -5038 Source and destination files are the same - - __________ - - See also: FSpMoveRenameCompat -*/ - -/*****************************************************************************/ - -pascal OSErr FSpMoveRenameCompat(const FSSpec *srcSpec, - const FSSpec *dstSpec, - ConstStr255Param copyName); -/* ¦ Move a file or directory and optionally rename it. - The FSpMoveRenameCompat function moves a file or directory and optionally - renames it. The source and destination locations must be on the same - volume. This routine works even if the volume doesn't support MoveRename. - - srcSpec input: An FSSpec record specifying the source object. - dstSpec input: An FSSpec record specifying the destination - directory. - copyName input: Points to the new name if the object is to be - renamed or nil if the object isn't to be renamed. - - Result Codes - noErr 0 No error - dirFulErr -33 File directory full - dskFulErr -34 Disk is full - nsvErr -35 Volume not found - ioErr -36 I/O error - bdNamErr -37 Bad filename or attempt to move into - a file - fnfErr -43 Source file or directory not found - wPrErr -44 Hardware volume lock - fLckdErr -45 File is locked - vLckdErr -46 Destination volume is read-only - fBsyErr -47 File busy, directory not empty, or - working directory control block open - dupFNErr -48 Destination already exists - paramErr -50 Volume doesn't support this function, - no default volume, or source and - volOfflinErr -53 Volume is offline - fsRnErr -59 Problem during rename - dirNFErr -120 Directory not found or incomplete pathname - badMovErr -122 Attempted to move directory into - offspring - wrgVolTypErr -123 Not an HFS volume (it's a MFS volume) - notAFileErr -1302 The pathname is nil, the pathname - is empty, or the pathname cannot refer - to a filename - diffVolErr -1303 Files on different volumes - afpAccessDenied -5000 The user does not have the right to - move the file or directory - afpObjectTypeErr -5025 Directory not found or incomplete pathname - afpSameObjectErr -5038 Source and destination files are the same - - __________ - - See also: HMoveRenameCompat -*/ - -/*****************************************************************************/ - -pascal OSErr BuildAFPVolMountInfo(short flags, - char nbpInterval, - char nbpCount, - short uamType, - Str32 zoneName, - Str31 serverName, - Str27 volName, - Str31 userName, - Str8 userPassword, - Str8 volPassword, - AFPVolMountInfoPtr *afpInfoPtr); -/* ¦ Allocate and initializes the fields of an AFPVolMountInfo record. - The BuildAFPVolMountInfo function allocates and initializes the fields - of an AFPVolMountInfo record before using that record to call - the VolumeMount function. - - flags input: The AFP mounting flags. 0 = normal mount; - set bit 0 to inhibit greeting messages. - nbpInterval input: The interval used for VolumeMount's - NBP Lookup call. 7 is a good choice. - nbpCount input: The retry count used for VolumeMount's - NBP Lookup call. 5 is a good choice. - uamType input: The user authentication method to use. - zoneName input: The AppleTalk zone name of the server. - serverName input: The AFP server name. - volName input: The AFP volume name. - userName input: The user name (zero length Pascal string for - guest). - userPassWord input: The user password (zero length Pascal string - if no user password) - volPassWord input: The volume password (zero length Pascal string - if no volume password) - afpInfoPtr output: A pointer to the newly created and initialized - AFPVolMountInfo record. If the function fails to - create an AFPVolMountInfo record, it sets - afpInfoPtr to NULL and the function result is - memFullErr. Your program is responsible - for disposing of this pointer when it is finished - with it. - - Result Codes - noErr 0 No error - memFullErr -108 memory full error - - __________ - - Also see: GetVolMountInfoSize, GetVolMountInfo, VolumeMount, - RetrieveAFPVolMountInfo, BuildAFPXVolMountInfo, - RetrieveAFPXVolMountInfo -*/ - -/*****************************************************************************/ - -pascal OSErr RetrieveAFPVolMountInfo(AFPVolMountInfoPtr afpInfoPtr, - short *flags, - short *uamType, - StringPtr zoneName, - StringPtr serverName, - StringPtr volName, - StringPtr userName); -/* ¦ Retrieve the AFP mounting information from an AFPVolMountInfo record. - The RetrieveAFPVolMountInfo function retrieves the AFP mounting - information returned in an AFPVolMountInfo record by the - GetVolMountInfo function. - - afpInfoPtr input: Pointer to AFPVolMountInfo record that contains - the AFP mounting information. - flags output: The AFP mounting flags. - uamType output: The user authentication method used. - zoneName output: The AppleTalk zone name of the server. - serverName output: The AFP server name. - volName output: The AFP volume name. - userName output: The user name (zero length Pascal string for - guest). - - Result Codes - noErr 0 No error - paramErr -50 media field in AFP mounting information - was not AppleShareMediaType - - __________ - - Also see: GetVolMountInfoSize, GetVolMountInfo, VolumeMount, - BuildAFPVolMountInfo, BuildAFPXVolMountInfo, - RetrieveAFPXVolMountInfo -*/ - -/*****************************************************************************/ - -pascal OSErr BuildAFPXVolMountInfo(short flags, - char nbpInterval, - char nbpCount, - short uamType, - Str32 zoneName, - Str31 serverName, - Str27 volName, - Str31 userName, - Str8 userPassword, - Str8 volPassword, - Str32 uamName, - unsigned long alternateAddressLength, - void *alternateAddress, - AFPXVolMountInfoPtr *afpXInfoPtr); -/* ¦ Allocate and initializes the fields of an AFPXVolMountInfo record. - The BuildAFPXVolMountInfo function allocates and initializes the fields - of an AFPXVolMountInfo record before using that record to call - the VolumeMount function. - - flags input: The AFP mounting flags. - nbpInterval input: The interval used for VolumeMount's - NBP Lookup call. 7 is a good choice. - nbpCount input: The retry count used for VolumeMount's - NBP Lookup call. 5 is a good choice. - uamType input: The user authentication method to use. - zoneName input: The AppleTalk zone name of the server. - serverName input: The AFP server name. - volName input: The AFP volume name. - userName input: The user name (zero length Pascal string - for guest). - userPassWord input: The user password (zero length Pascal - string if no user password) - volPassWord input: The volume password (zero length Pascal - string if no volume password) - uamName input: The User Authentication Method name. - alternateAddressLength input: Length of alternateAddress data. - alternateAddress input The AFPAlternateAddress (variable length) - afpXInfoPtr output: A pointer to the newly created and - initialized AFPVolMountInfo record. - If the function fails to create an - AFPVolMountInfo record, it sets - afpInfoPtr to NULL and the function - result is memFullErr. Your program is - responsible for disposing of this pointer - when it is finished with it. - - Result Codes - noErr 0 No error - memFullErr -108 memory full error - - __________ - - Also see: GetVolMountInfoSize, GetVolMountInfo, VolumeMount, - BuildAFPVolMountInfo, RetrieveAFPVolMountInfo, - RetrieveAFPXVolMountInfo -*/ - -/*****************************************************************************/ - -pascal OSErr RetrieveAFPXVolMountInfo(AFPXVolMountInfoPtr afpXInfoPtr, - short *flags, - short *uamType, - StringPtr zoneName, - StringPtr serverName, - StringPtr volName, - StringPtr userName, - StringPtr uamName, - unsigned long *alternateAddressLength, - AFPAlternateAddress **alternateAddress); -/* ¦ Retrieve the AFP mounting information from an AFPXVolMountInfo record. - The RetrieveAFPXVolMountInfo function retrieves the AFP mounting - information returned in an AFPXVolMountInfo record by the - GetVolMountInfo function. - - afpXInfoPtr input: Pointer to AFPXVolMountInfo record that - contains the AFP mounting information. - flags output: The AFP mounting flags. - uamType output: The user authentication method used. - zoneName output: The AppleTalk zone name of the server. - serverName output: The AFP server name. - volName output: The AFP volume name. - userName output: The user name (zero length Pascal - string for guest). - uamName output: The User Authentication Method name. - alternateAddressLength output: Length of alternateAddress data returned. - alternateAddress: output: A pointer to the newly created and - AFPAlternateAddress record (a variable - length record). If the function fails to - create an AFPAlternateAddress record, - it sets alternateAddress to NULL and the - function result is memFullErr. Your - program is responsible for disposing of - this pointer when it is finished with it. - - Result Codes - noErr 0 No error - paramErr -50 media field in AFP mounting information - was not AppleShareMediaType - memFullErr -108 memory full error - - __________ - - Also see: GetVolMountInfoSize, GetVolMountInfo, VolumeMount, - BuildAFPVolMountInfo, RetrieveAFXVolMountInfo, - BuildAFPXVolMountInfo -*/ - -/*****************************************************************************/ - -pascal OSErr GetUGEntries(short objType, - UGEntryPtr entries, - long reqEntryCount, - long *actEntryCount, - long *objID); -/* ¦ Retrieve a list of user or group entries from the local file server. - The GetUGEntries functions retrieves a list of user or group entries - from the local file server. - - objType input: The object type: -1 = group; 0 = user - UGEntries input: Pointer to array of UGEntry records where the list - is returned. - reqEntryCount input: The number of elements in the UGEntries array. - actEntryCount output: The number of entries returned. - objID input: The current index position. Set to 0 to start with - the first entry. - output: The index position to get the next entry. Pass this - value the next time you call GetUGEntries to start - where you left off. - - Result Codes - noErr 0 No error - fnfErr -43 No more users or groups - paramErr -50 Function not supported; or, ioObjID is - negative - - __________ - - Also see: GetUGEntry -*/ - -/*****************************************************************************/ - -#ifdef __cplusplus -} -#endif - -#include "optimend.h" - -#endif /* __MOREFILESEXTRAS__ */ diff --git a/src/mac/morefile/MoreFile.cpp b/src/mac/morefile/MoreFile.cpp deleted file mode 100644 index 581e1b742a..0000000000 --- a/src/mac/morefile/MoreFile.cpp +++ /dev/null @@ -1,628 +0,0 @@ -/* -** 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 -#include -#include - -#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 ); -} - -/*****************************************************************************/ diff --git a/src/mac/morefile/MoreFile.h b/src/mac/morefile/MoreFile.h deleted file mode 100644 index a2b069279c..0000000000 --- a/src/mac/morefile/MoreFile.h +++ /dev/null @@ -1,1244 +0,0 @@ -/* -** 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.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 __MOREFILES__ -#define __MOREFILES__ - -#include -#include - -#ifndef true -#define true 1 -#define false 0 -#endif - -#include "optim.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/*****************************************************************************/ - -pascal OSErr HGetVolParms(ConstStr255Param volName, - short vRefNum, - GetVolParmsInfoBuffer *volParmsInfo, - long *infoSize); -/* ¦ Determine the characteristics of a volume. - The HGetVolParms function returns information about the characteristics - of a volume. A result of paramErr usually just means the volume doesn't - support PBHGetVolParms and the feature you were going to check - for isn't available. - - volName input: A pointer to the name of a mounted volume - or nil. - vRefNum input: Volume specification. - volParmsInfo input: Pointer to GetVolParmsInfoBuffer where the - volume attributes information is returned. - output: Atributes information. - infoSize input: Size of buffer pointed to by volParmsInfo. - output: Size of data actually returned. - - Result Codes - noErr 0 No error - nsvErr -35 Volume not found - paramErr -50 Volume doesn't support this function - - __________ - - Also see the macros for checking attribute bits in MoreFilesExtras.h -*/ - -/*****************************************************************************/ - -pascal OSErr HCreateMinimum(short vRefNum, - long dirID, - ConstStr255Param fileName); -/* ¦ Create a new file with no creator or file type. - The HCreateMinimum function creates a new file without attempting to set - the creator and file type of the new file. This function is needed to - create a file in an AppleShare "drop box" where the user can make - changes, but cannot see folder or files. - - vRefNum input: Volume specification. - dirID input: Directory ID. - fileName input: The name of the new file. - - 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 - - __________ - - Also see: FSpCreateMinimum -*/ - -/*****************************************************************************/ - -pascal OSErr FSpCreateMinimum(const FSSpec *spec); -/* ¦ Create a new file with no creator or file type. - The FSpCreateMinimum function creates a new file without attempting to set - the the creator and file type of the new file. This function is needed to - create a file in an AppleShare "dropbox" where the user can make - changes, but cannot see folder or files. - - spec input: An FSSpec record specifying the file to create. - - 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 - - __________ - - Also see: HCreateMinimum -*/ - -/*****************************************************************************/ - -pascal OSErr ExchangeFiles(short vRefNum, - long srcDirID, - ConstStr255Param srcName, - long dstDirID, - ConstStr255Param dstName); -/* ¦ Exchange the data stored in two files on the same volume. - The ExchangeFiles function swaps the data in two files on the same - volume by changing some of the information in the volume catalog and, - if the files are open, in the file control blocks. - - vRefNum input: Volume specification. - srcDirID input: Source directory ID. - srcName input: Source file name. - dstDirID input: Destination directory ID. - dstName input: Destination file name. - - 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 are the same - - __________ - - Also see: FSpExchangeFilesCompat -*/ - -/*****************************************************************************/ - -pascal OSErr ResolveFileIDRef(ConstStr255Param volName, - short vRefNum, - long fileID, - long *parID, - StringPtr fileName); -/* ¦ Retrieve the location of the file with the specified file ID reference. - The ResolveFileIDRef function returns the filename and parent directory ID - of the file with the specified file ID reference. - - volName input: A pointer to the name of a mounted volume - or nil. - vRefNum input: Volume specification. - fileID input: The file ID reference. - parID output: The parent directory ID of the file. - name input: Points to a buffer (minimum Str63) where the filename - is to be returned or must be nil. - output: The filename. - - Result Codes - noErr 0 No error - nsvErr -35 Volume not found - ioErr -36 I/O error - fnfErr -43 File not found - paramErr -50 Function not supported by volume - volOfflinErr -53 Volume is offline - extFSErr -58 External file system error - no file - system claimed this call. - wrgVolTypErr -123 Not an HFS volume - fidNotFoundErr -1300 File ID reference not found - notAFileErr -1302 Specified file is a directory - afpAccessDenied -5000 User does not have the correct access - afpObjectTypeErr -5025 Specified file is a directory - afpIDNotFound -5034 File ID reference not found - afpBadIDErr -5039 File ID reference not found - - __________ - - Also see: FSpResolveFileIDRef, CreateFileIDRef, FSpCreateFileIDRef, - DeleteFileIDRef -*/ - -/*****************************************************************************/ - -pascal OSErr FSpResolveFileIDRef(ConstStr255Param volName, - short vRefNum, - long fileID, - FSSpecPtr spec); -/* ¦ Retrieve the location of the file with the specified file ID reference. - The FSpResolveFileIDRef function fills in an FSSpec with the location - of the file with the specified file ID reference. - - volName input: A pointer to the name of a mounted volume - or nil. - vRefNum input: Volume specification. - fileID input: The file ID reference. - spec input: A pointer to a FSSpec record. - output: A file system specification to be filled in by - FSpResolveFileIDRef. - - Result Codes - noErr 0 No error - nsvErr -35 Volume not found - ioErr -36 I/O error - fnfErr -43 File not found - paramErr -50 Function not supported by volume or - no default volume - volOfflinErr -53 Volume is offline - extFSErr -58 External file system error - no file - system claimed this call. - wrgVolTypErr -123 Not an HFS volume - fidNotFoundErr -1300 File ID reference not found - notAFileErr -1302 Specified file is a directory - afpAccessDenied -5000 User does not have the correct access - afpObjectTypeErr -5025 Specified file is a directory - afpIDNotFound -5034 File ID reference not found - afpBadIDErr -5039 File ID reference not found - - __________ - - Also see: ResolveFileIDRef, CreateFileIDRef, FSpCreateFileIDRef, - DeleteFileIDRef -*/ - -/*****************************************************************************/ - -pascal OSErr CreateFileIDRef(short vRefNum, - long parID, - ConstStr255Param fileName, - long *fileID); -/* ¦ Establish a file ID reference for a file. - The CreateFileIDRef function creates a file ID reference for the - specified file, or if a file ID reference already exists, supplies - the file ID reference and returns the result code fidExists. - - vRefNum input: Volume specification. - parID input: Directory ID. - fileName input: The name of the file. - fileID output: The file ID reference. - - Result Codes - noErr 0 No error - nsvErr -35 Volume not found - ioErr -36 I/O error - fnfErr -43 File not found - wPrErr -44 Hardware volume lock - vLckdErr -46 Software volume lock - paramErr -50 Function not supported by volume - volOfflinErr -53 Volume is offline - extFSErr -58 External file system error - no file - system claimed this call. - wrgVolTypErr -123 Not an HFS volume - fidExists -1301 File ID reference already exists - notAFileErrn -1302 Specified file is a directory - afpAccessDenied -5000 User does not have the correct access - afpObjectTypeErr -5025 Specified file is a directory - afpIDExists -5035 File ID reference already exists - - __________ - - Also see: FSpResolveFileIDRef, ResolveFileIDRef, FSpCreateFileIDRef, - DeleteFileIDRef -*/ - -/*****************************************************************************/ - -pascal OSErr FSpCreateFileIDRef(const FSSpec *spec, - long *fileID); -/* ¦ Establish a file ID reference for a file. - The FSpCreateFileIDRef function creates a file ID reference for the - specified file, or if a file ID reference already exists, supplies - the file ID reference and returns the result code fidExists. - - spec input: An FSSpec record specifying the file. - fileID output: The file ID reference. - - Result Codes - noErr 0 No error - nsvErr -35 Volume not found - ioErr -36 I/O error - fnfErr -43 File not found - wPrErr -44 Hardware volume lock - vLckdErr -46 Software volume lock - paramErr -50 Function not supported by volume - volOfflinErr -53 Volume is offline - extFSErr -58 External file system error - no file - system claimed this call. - wrgVolTypErr -123 Not an HFS volume - fidExists -1301 File ID reference already exists - notAFileErrn -1302 Specified file is a directory - afpAccessDenied -5000 User does not have the correct access - afpObjectTypeErr -5025 Specified file is a directory - afpIDExists -5035 File ID reference already exists - - __________ - - Also see: FSpResolveFileIDRef, ResolveFileIDRef, CreateFileIDRef, - DeleteFileIDRef -*/ - -/*****************************************************************************/ - -pascal OSErr DeleteFileIDRef(ConstStr255Param volName, - short vRefNum, - long fileID); -/* ¦ Delete a file ID reference. - The DeleteFileIDRef function deletes a file ID reference. - - volName input: A pointer to the name of a mounted volume - or nil. - vRefNum input: Volume specification. - fileID input: The file ID reference. - - Result Codes - noErr 0 No error - nsvErr -35 Volume not found - ioErr -36 I/O error - fnfErr -43 File not found - wPrErr -44 Hardware volume lock - vLckdErr -46 Software volume lock - paramErr -50 Function not supported by volume - volOfflinErr -53 Volume is offline - extFSErr -58 External file system error - no file - system claimed this call. - wrgVolTypErr -123 Function is not supported by volume - fidNotFoundErr -1300 File ID reference not found - afpAccessDenied -5000 User does not have the correct access - afpObjectTypeErr -5025 Specified file is a directory - afpIDNotFound -5034 File ID reference not found - - __________ - - Also see: FSpResolveFileIDRef, ResolveFileIDRef, CreateFileIDRef, - FSpCreateFileIDRef -*/ - -/*****************************************************************************/ - -pascal OSErr FlushFile(short refNum); -/* ¦ Write the contents of a file's access path buffer (the fork data). - The FlushFile function writes the contents of a file's access path - buffer (the fork data) to the volume. Note: some of the file's catalog - information stored on the volume may not be correct until FlushVol - is called. - - refNum input: The file reference number of an open file. - - Result Codes - noErr 0 No error - nsvErr -35 Volume not found - ioErr -36 I/O error - fnOpnErr -38 File not open - fnfErr -43 File not found - rfNumErr -51 Bad reference number - extFSErr -58 External file system error - no file - system claimed this call. -*/ - -/*****************************************************************************/ - -pascal OSErr LockRange(short refNum, - long rangeLength, - long rangeStart); -/* ¦ Lock a portion of a file. - The LockRange function locks (denies access to) a portion of a file - that was opened with shared read/write permission. - - refNum input: The file reference number of an open file. - rangeLength input: The number of bytes in the range. - rangeStart input: The starting byte in the range to lock. - - Result Codes - noErr 0 No error - ioErr -36 I/O error - fnOpnErr -38 File not open - eofErr -39 Logical end-of-file reached - fLckdErr -45 File is locked by another user - paramErr -50 Negative ioReqCount - rfNumErr -51 Bad reference number - extFSErr -58 External file system error - no file - system claimed this call. - volGoneErr -124 Server volume has been disconnected - afpNoMoreLocks -5015 No more ranges can be locked - afpRangeOverlap -5021 Part of range is already locked - - __________ - - Also see: UnlockRange -*/ - -/*****************************************************************************/ - -pascal OSErr UnlockRange(short refNum, - long rangeLength, - long rangeStart); -/* ¦ Unlock a previously locked range. - The UnlockRange function unlocks (allows access to) a previously locked - portion of a file that was opened with shared read/write permission. - - refNum input: The file reference number of an open file. - rangeLength input: The number of bytes in the range. - rangeStart input: The starting byte in the range to unlock. - - Result Codes - noErr 0 No error - ioErr -36 I/O error - fnOpnErr -38 File not open - eofErr -39 Logical end-of-file reached - paramErr -50 Negative ioReqCount - rfNumErr -51 Bad reference number - extFSErr -58 External file system error - no file - system claimed this call. - volGoneErr -124 Server volume has been disconnected - afpRangeNotLocked -5020 Specified range was not locked - - __________ - - Also see: LockRange -*/ - -/*****************************************************************************/ - -pascal OSErr GetForeignPrivs(short vRefNum, - long dirID, - ConstStr255Param name, - void *foreignPrivBuffer, - long *foreignPrivSize, - long *foreignPrivInfo1, - long *foreignPrivInfo2, - long *foreignPrivInfo3, - long *foreignPrivInfo4); -/* ¦ Retrieve the native access-control information. - The GetForeignPrivs function retrieves the native access-control - information for a file or directory stored on a volume managed by - a foreign file system. - - 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. - foreignPrivBuffer input: Pointer to buffer where the privilege - information is returned. - output: Privilege information. - foreignPrivSize input: Size of buffer pointed to by - foreignPrivBuffer. - output: Amount of buffer actually used. - foreignPrivInfo1 output: Information specific to privilege model. - foreignPrivInfo2 output: Information specific to privilege model. - foreignPrivInfo3 output: Information specific to privilege model. - foreignPrivInfo4 output: Information specific to privilege model. - - Result Codes - noErr 0 No error - nsvErr -35 Volume not found - paramErr -50 Volume is HFS or MFS (that is, it has - no foreign privilege model), or foreign - volume does not support these calls - - __________ - - Also see: FSpGetForeignPrivs, SetForeignPrivs, FSpSetForeignPrivs -*/ - -/*****************************************************************************/ - -pascal OSErr FSpGetForeignPrivs(const FSSpec *spec, - void *foreignPrivBuffer, - long *foreignPrivSize, - long *foreignPrivInfo1, - long *foreignPrivInfo2, - long *foreignPrivInfo3, - long *foreignPrivInfo4); -/* ¦ Retrieve the native access-control information. - The FSpGetForeignPrivs function retrieves the native access-control - information for a file or directory stored on a volume managed by - a foreign file system. - - spec input: An FSSpec record specifying the object. - foreignPrivBuffer input: Pointer to buffer where the privilege - information is returned. - output: Privilege information. - foreignPrivSize input: Size of buffer pointed to by - foreignPrivBuffer. - output: Amount of buffer actually used. - foreignPrivInfo1 output: Information specific to privilege model. - foreignPrivInfo2 output: Information specific to privilege model. - foreignPrivInfo3 output: Information specific to privilege model. - foreignPrivInfo4 output: Information specific to privilege model. - - Result Codes - noErr 0 No error - nsvErr -35 Volume not found - paramErr -50 Volume is HFS or MFS (that is, it has - no foreign privilege model), or foreign - volume does not support these calls - - __________ - - Also see: GetForeignPrivs, SetForeignPrivs, FSpSetForeignPrivs -*/ - -/*****************************************************************************/ - -pascal OSErr SetForeignPrivs(short vRefNum, - long dirID, - ConstStr255Param name, - const void *foreignPrivBuffer, - long *foreignPrivSize, - long foreignPrivInfo1, - long foreignPrivInfo2, - long foreignPrivInfo3, - long foreignPrivInfo4); -/* ¦ Change the native access-control information. - The SetForeignPrivs function changes the native access-control - information for a file or directory stored on a volume managed by - a foreign file system. - - 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. - foreignPrivBuffer input: Pointer to privilege information buffer. - foreignPrivSize input: Size of buffer pointed to by - foreignPrivBuffer. - output: Amount of buffer actually used. - foreignPrivInfo1 input: Information specific to privilege model. - foreignPrivInfo2 input: Information specific to privilege model. - foreignPrivInfo3 input: Information specific to privilege model. - foreignPrivInfo4 input: Information specific to privilege model. - - Result Codes - noErr 0 No error - nsvErr -35 Volume not found - paramErr -50 Volume is HFS or MFS (that is, it has - no foreign privilege model), or foreign - volume does not support these calls - - __________ - - Also see: GetForeignPrivs, FSpGetForeignPrivs, FSpSetForeignPrivs -*/ - -/*****************************************************************************/ - -pascal OSErr FSpSetForeignPrivs(const FSSpec *spec, - const void *foreignPrivBuffer, - long *foreignPrivSize, - long foreignPrivInfo1, - long foreignPrivInfo2, - long foreignPrivInfo3, - long foreignPrivInfo4); -/* ¦ Change the native access-control information. - The FSpSetForeignPrivs function changes the native access-control - information for a file or directory stored on a volume managed by - a foreign file system. - - spec input: An FSSpec record specifying the object. - foreignPrivBuffer input: Pointer to privilege information buffer. - foreignPrivSize input: Size of buffer pointed to by - foreignPrivBuffer. - output: Amount of buffer actually used. - foreignPrivInfo1 input: Information specific to privilege model. - foreignPrivInfo2 input: Information specific to privilege model. - foreignPrivInfo3 input: Information specific to privilege model. - foreignPrivInfo4 input: Information specific to privilege model. - - Result Codes - noErr 0 No error - nsvErr -35 Volume not found - paramErr -50 Volume is HFS or MFS (that is, it has - no foreign privilege model), or foreign - volume does not support these calls - - __________ - - Also see: GetForeignPrivs, FSpGetForeignPrivs, SetForeignPrivs -*/ - -/*****************************************************************************/ - -pascal OSErr HGetLogInInfo(ConstStr255Param volName, - short vRefNum, - short *loginMethod, - StringPtr userName); -/* ¦ Get the login method and user name used to log on to a shared volume. - The HGetLogInInfo function retrieves the login method and user name - used to log on to a particular shared volume. - - volName input: A pointer to the name of a mounted volume - or nil. - vRefNum input: The volume reference number. - loginMethod output: The login method used (kNoUserAuthentication, - kPassword, kEncryptPassword, or - kTwoWayEncryptPassword). - userName input: Points to a buffer (minimum Str31) where the user - name is to be returned or must be nil. - output: The user name. - - Result Codes - noErr 0 No error - nsvErr -35 Specified volume doesnÕt exist - paramErr -50 Function not supported by volume - - __________ - - Also see: HGetDirAccess, FSpGetDirAccess, HSetDirAccess, - FSpSetDirAccess, HMapName, HMapID -*/ - -/*****************************************************************************/ - -pascal OSErr HGetDirAccess(short vRefNum, - long dirID, - ConstStr255Param name, - long *ownerID, - long *groupID, - long *accessRights); -/* ¦ Get a directory's access control information on a shared volume. - The HGetDirAccess function retrieves the directory access control - information for a directory on a shared volume. - - vRefNum input: Volume specification. - dirID input: Directory ID. - name input: Pointer to directory name, or nil if dirID - specifies the directory. - ownerID output: The directory's owner ID. - groupID output: The directory's group ID or - 0 if no group affiliation. - accessRights output: The directory's access rights. - - Result Codes - noErr 0 No error - fnfErr -43 Directory not found - paramErr -50 Function not supported by volume - afpAccessDenied -5000 User does not have the correct access - to the directory - - __________ - - Also see: HGetLogInInfo, FSpGetDirAccess, HSetDirAccess, - FSpSetDirAccess, HMapName, HMapID -*/ - -/*****************************************************************************/ - -pascal OSErr FSpGetDirAccess(const FSSpec *spec, - long *ownerID, - long *groupID, - long *accessRights); -/* ¦ Get a directory's access control information on a shared volume. - The FSpGetDirAccess function retrieves the directory access control - information for a directory on a shared volume. - - spec input: An FSSpec record specifying the directory. - ownerID output: The directory's owner ID. - groupID output: The directory's group ID or - 0 if no group affiliation. - accessRights output: The directory's access rights. - - Result Codes - noErr 0 No error - fnfErr -43 Directory not found - paramErr -50 Function not supported by volume - afpAccessDenied -5000 User does not have the correct access - to the directory - - __________ - - Also see: HGetLogInInfo, HGetDirAccess, HSetDirAccess, - FSpSetDirAccess, HMapName, HMapID -*/ - -/*****************************************************************************/ - -pascal OSErr HSetDirAccess(short vRefNum, - long dirID, - ConstStr255Param name, - long ownerID, - long groupID, - long accessRights); -/* ¦ Set a directory's access control information on a shared volume. - The HSetDirAccess function changes the directory access control - information for a directory on a shared volume. You must own a directory - to change its access control information. - - vRefNum input: Volume specification. - dirID input: Directory ID. - name input: Pointer to directory name, or nil if dirID - specifies the directory. - ownerID input: The directory's owner ID. - groupID input: The directory's group ID or - 0 if no group affiliation. - accessRights input: The directory's access rights. - - Result Codes - noErr 0 No error - fnfErr -43 Directory not found - vLckdErr -46 Volume is locked or read-only - paramErr -50 Parameter error - afpAccessDenied -5000 User does not have the correct access - to the directory - afpObjectTypeErr -5025 Object is a file, not a directory - - __________ - - Also see: HGetLogInInfo, HGetDirAccess, FSpGetDirAccess, - FSpSetDirAccess, HMapName, HMapID -*/ - -/*****************************************************************************/ - -pascal OSErr FSpSetDirAccess(const FSSpec *spec, - long ownerID, - long groupID, - long accessRights); -/* ¦ Set a directory's access control information on a shared volume. - The FSpSetDirAccess function changes the directory access control - information for a directory on a shared volume. You must own a directory - to change its access control information. - - spec input: An FSSpec record specifying the directory. - ownerID input: The directory's owner ID. - groupID input: The directory's group ID or - 0 if no group affiliation. - accessRights input: The directory's access rights. - - Result Codes - noErr 0 No error - fnfErr -43 Directory not found - vLckdErr -46 Volume is locked or read-only - paramErr -50 Parameter error - afpAccessDenied -5000 User does not have the correct access - to the directory - afpObjectTypeErr -5025 Object is a file, not a directory - - __________ - - Also see: HGetLogInInfo, HGetDirAccess, FSpGetDirAccess, HSetDirAccess, - HMapName, HMapID -*/ - -/*****************************************************************************/ - -pascal OSErr HMapID(ConstStr255Param volName, - short vRefNum, - long ugID, - short objType, - StringPtr name); -/* ¦ Map a user or group ID to a user or group name. - The HMapID function determines the name of a user or group if you know - the user or group ID. - - volName input: A pointer to the name of a mounted volume - or nil. - vRefNum input: Volume specification. - objType input: The mapping function code: 1 if you're mapping a - user ID to a user name or 2 if you're mapping a - group ID to a group name. - name input: Points to a buffer (minimum Str31) where the user - or group name is to be returned or must be nil. - output: The user or group name. - - Result Codes - noErr 0 No error - fnfErr -43 Unrecognizable owner or group name - paramErr -50 Function not supported by volume - - __________ - - Also see: HGetLogInInfo, HGetDirAccess, FSpGetDirAccess, HSetDirAccess, - FSpSetDirAccess, HMapName -*/ - -/*****************************************************************************/ - -pascal OSErr HMapName(ConstStr255Param volName, - short vRefNum, - ConstStr255Param name, - short objType, - long *ugID); -/* ¦ Map a user or group name to a user or group ID. - The HMapName function determines the user or group ID if you know the - user or group name. - - volName input: A pointer to the name of a mounted volume - or nil. - vRefNum input: Volume specification. - name input: The user or group name. - objType input: The mapping function code: 3 if you're mapping a - user name to a user ID or 4 if you're mapping a - group name to a group ID. - ugID output: The user or group ID. - - Result Codes - noErr 0 No error - fnfErr -43 Unrecognizable owner or group name - paramErr -50 Function not supported by volume - - __________ - - Also see: HGetLogInInfo, HGetDirAccess, FSpGetDirAccess, HSetDirAccess, - FSpSetDirAccess, HMapID -*/ - -/*****************************************************************************/ - -pascal OSErr HCopyFile(short srcVRefNum, - long srcDirID, - ConstStr255Param srcName, - short dstVRefNum, - long dstDirID, - ConstStr255Param dstPathname, - ConstStr255Param copyName); -/* ¦ Duplicate a file on a file server and optionally to rename it. - The HCopyFile function duplicates a file and optionally to renames it. - The source and destination volumes must be on the same file server. - This function instructs the server to copy the file. - - 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. - - Result Codes - noErr 0 No error - dskFulErr -34 Destination volume is full - fnfErr -43 Source file not found, or destination - directory does not exist - 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 - paramErr -50 Function not supported by volume - wrgVolTypErr -123 Function not supported by volume - afpAccessDenied -5000 The user does not have the right to - read the source or write to the - destination - afpDenyConflict -5006 The source or destination file could - not be opened with the correct access - modes - afpObjectTypeErr -5025 Source is a directory - - __________ - - Also see: FSpCopyFile, FileCopy, FSpFileCopy -*/ - -/*****************************************************************************/ - -pascal OSErr FSpCopyFile(const FSSpec *srcSpec, - const FSSpec *dstSpec, - ConstStr255Param copyName); -/* ¦ Duplicate a file on a file server and optionally to rename it. - The FSpCopyFile function duplicates a file and optionally to renames it. - The source and destination volumes must be on the same file server. - This function instructs the server to copy the file. - - 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. - - Result Codes - noErr 0 No error - dskFulErr -34 Destination volume is full - fnfErr -43 Source file not found, or destination - directory does not exist - 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 - paramErr -50 Function not supported by volume - wrgVolTypErr -123 Function not supported by volume - afpAccessDenied -5000 The user does not have the right to - read the source or write to the - destination - afpDenyConflict -5006 The source or destination file could - not be opened with the correct access - modes - afpObjectTypeErr -5025 Source is a directory - - __________ - - Also see: HCopyFile, FileCopy, FSpFileCopy -*/ - -/*****************************************************************************/ - -pascal OSErr HMoveRename(short vRefNum, - long srcDirID, - ConstStr255Param srcName, - long dstDirID, - ConstStr255Param dstpathName, - ConstStr255Param copyName); -/* ¦ Move a file or directory on a file server and optionally to rename it. - The HMoveRename function moves a file or directory and optionally - renames it. The source and destination locations must be on the same - shared volume. - - vRefNum input: Volume specification. - srcDirID input: Source directory ID. - srcName input: The source object name. - dstDirID input: Destination directory ID. - dstName input: Pointer to destination directory name, or - nil when dstDirID specifies a directory. - copyName input: Points to the new name if the object is to be - renamed or nil if the object isn't to be renamed. - - Result Codes - noErr 0 No error - fnfErr -43 Source file or directory not found - fLckdErr -45 File is locked - vLckdErr -46 Destination volume is read-only - dupFNErr -48 Destination already exists - paramErr -50 Function not supported by volume - badMovErr -122 Attempted to move directory into - offspring - afpAccessDenied -5000 The user does not have the right to - move the file or directory - - __________ - - Also see: FSpMoveRename, HMoveRenameCompat, FSpMoveRenameCompat -*/ - -/*****************************************************************************/ - -pascal OSErr FSpMoveRename(const FSSpec *srcSpec, - const FSSpec *dstSpec, - ConstStr255Param copyName); -/* ¦ Move a file or directory on a file server and optionally to rename it. - The FSpMoveRename function moves a file or directory and optionally - renames it. The source and destination locations must be on the same - shared volume. - - srcSpec input: An FSSpec record specifying the source object. - dstSpec input: An FSSpec record specifying the destination - directory. - copyName input: Points to the new name if the object is to be - renamed or nil if the object isn't to be renamed. - - Result Codes - noErr 0 No error - fnfErr -43 Source file or directory not found - fLckdErr -45 File is locked - vLckdErr -46 Destination volume is read-only - dupFNErr -48 Destination already exists - paramErr -50 Function not supported by volume - badMovErr -122 Attempted to move directory into - offspring - afpAccessDenied -5000 The user does not have the right to - move the file or directory - - __________ - - Also see: HMoveRename, HMoveRenameCompat, FSpMoveRenameCompat -*/ - -/*****************************************************************************/ - -pascal OSErr GetVolMountInfoSize(ConstStr255Param volName, - short vRefNum, - short *size); -/* ¦ Get the size of a volume mounting information record. - The GetVolMountInfoSize function determines the how much space the - program needs to allocate for a volume mounting information record. - - volName input: A pointer to the name of a mounted volume - or nil. - vRefNum input: Volume specification. - size output: The space needed (in bytes) of the volume mounting - information record. - - Result Codes - noErr 0 No error - nsvErr -35 Volume not found - paramErr -50 Parameter error - extFSErr -58 External file system error - no file - system claimed this call. - - __________ - - Also see: GetVolMountInfo, VolumeMount BuildAFPVolMountInfo, - RetrieveAFPVolMountInfo -*/ - -/*****************************************************************************/ - -pascal OSErr GetVolMountInfo(ConstStr255Param volName, - short vRefNum, - void *volMountInfo); -/* ¦ Retrieve a volume mounting information record. - The GetVolMountInfo function retrieves a volume mounting information - record containing all the information needed to mount the volume, - except for passwords. - - volName input: A pointer to the name of a mounted volume - or nil. - vRefNum input: Volume specification. - volMountInfo output: Points to a volume mounting information - record where the mounting information is to - be returned. - - Result Codes - noErr 0 No error - nsvErr -35 Volume not found - paramErr -50 Parameter error - extFSErr -58 External file system error - no file - system claimed this call. - - __________ - - Also see: GetVolMountInfoSize, VolumeMount, BuildAFPVolMountInfo, - RetrieveAFPVolMountInfo -*/ - -/*****************************************************************************/ - -pascal OSErr VolumeMount(const void *volMountInfo, - short *vRefNum); -/* ¦ Mount a volume using a volume mounting information record. - The VolumeMount function mounts a volume using a volume mounting - information record. - - volMountInfo input: Points to a volume mounting information record. - vRefNum output: A volume reference number. - - Result Codes - noErr 0 No error - notOpenErr -28 AppleTalk is not open - nsvErr -35 Volume not found - paramErr -50 Parameter error; typically, zone, server, - and volume name combination is not valid - or not complete, or the user name is not - recognized - extFSErr -58 External file system error - no file - system claimed this call. - memFullErr -108 Not enough memory to create a new volume - control block for mounting the volume - afpBadUAM -5002 User authentication method is unknown - afpBadVersNum -5003 Workstation is using an AFP version that - the server doesnÕt recognize - afpNoServer -5016 Server is not responding - afpUserNotAuth -5023 User authentication failed (usually, - password is not correct) - afpPwdExpired -5042 Password has expired on server - afpBadDirIDType -5060 Not a fixed directory ID volume - afpCantMountMoreSrvrs -5061 Maximum number of volumes has been - mounted - afpAlreadyMounted -5062 Volume already mounted - afpSameNodeErr -5063 Attempt to log on to a server running - on the same machine - - __________ - - Also see: GetVolMountInfoSize, GetVolMountInfo, BuildAFPVolMountInfo, - RetrieveAFPVolMountInfo -*/ - -/*****************************************************************************/ - -pascal OSErr Share(short vRefNum, - long dirID, - ConstStr255Param name); -/* ¦ Establish a local volume or directory as a share point. - The Share function establishes a local volume or directory as a - share point. - - vRefNum input: Volume specification. - dirID input: Directory ID. - name input: Pointer to directory name, or nil if dirID - specifies the directory. - - Result Codes - noErr 0 No error - tmfoErr -42 Too many share points - fnfErr -43 File not found - dupFNErr -48 Already a share point with this name - paramErr -50 Function not supported by volume - dirNFErrdirNFErr -120 Directory not found - afpAccessDenied -5000 This directory cannot be shared - afpObjectTypeErr -5025 Object was a file, not a directory - afpContainsSharedErr -5033 The directory contains a share point - afpInsideSharedErr -5043 The directory is inside a shared directory - - __________ - - Also see: FSpShare, Unshare, FSpUnshare -*/ - -/*****************************************************************************/ - -pascal OSErr FSpShare(const FSSpec *spec); -/* ¦ Establish a local volume or directory as a share point. - The FSpShare function establishes a local volume or directory as a - share point. - - spec input: An FSSpec record specifying the share point. - - Result Codes - noErr 0 No error - tmfoErr -42 Too many share points - fnfErr -43 File not found - dupFNErr -48 Already a share point with this name - paramErr -50 Function not supported by volume - dirNFErrdirNFErr -120 Directory not found - afpAccessDenied -5000 This directory cannot be shared - afpObjectTypeErr -5025 Object was a file, not a directory - afpContainsSharedErr -5033 The directory contains a share point - afpInsideSharedErr -5043 The directory is inside a shared directory - - __________ - - Also see: Share, Unshare, FSpUnshare -*/ - -/*****************************************************************************/ - -pascal OSErr Unshare(short vRefNum, - long dirID, - ConstStr255Param name); -/* ¦ Remove a share point. - The Unshare function removes a share point. - - vRefNum input: Volume specification. - dirID input: Directory ID. - name input: Pointer to directory name, or nil if dirID - specifies the directory. - - Result Codes - noErr 0 No error - fnfErr -43 File not found - paramErr -50 Function not supported by volume - dirNFErrdirNFErr -120 Directory not found - afpObjectTypeErr -5025 Object was a file, not a directory; or, - this directory is not a share point - - __________ - - Also see: Share, FSpShare, FSpUnshare -*/ - -/*****************************************************************************/ - -pascal OSErr FSpUnshare(const FSSpec *spec); -/* ¦ Remove a share point. - The FSpUnshare function removes a share point. - - spec input: An FSSpec record specifying the share point. - - Result Codes - noErr 0 No error - fnfErr -43 File not found - paramErr -50 Function not supported by volume - dirNFErrdirNFErr -120 Directory not found - afpObjectTypeErr -5025 Object was a file, not a directory; or, - this directory is not a share point - - __________ - - Also see: Share, FSpShare, Unshare -*/ - -/*****************************************************************************/ - -pascal OSErr GetUGEntry(short objType, - StringPtr objName, - long *objID); -/* ¦ Retrieve a user or group entry from the local file server. - The GetUGEntry function retrieves user or group entries from the - local file server. - - objType input: The object type: -1 = group; 0 = user - objName input: Points to a buffer (minimum Str31) where the user - or group name is to be returned or must be nil. - output: The user or group name. - objID input: O to get the first user or group. If the entry objID - last returned by GetUGEntry is passed, then user or - group whose alphabetically next in the list of entries - is returned. - output: The user or group ID. - - Result Codes - noErr 0 No error - fnfErr -43 No more users or groups - paramErr -50 Function not supported; or, ioObjID is - negative - - __________ - - Also see: GetUGEntries -*/ - -/*****************************************************************************/ - -#ifdef __cplusplus -} -#endif - -#include "optimend.h" - -#endif /* __MOREFILES__ */ diff --git a/src/mac/morefile/MoreFiles.c b/src/mac/morefile/MoreFiles.c new file mode 100644 index 0000000000..8426bdaffe --- /dev/null +++ b/src/mac/morefile/MoreFiles.c @@ -0,0 +1,643 @@ +/* + File: MoreFiles.c + + Contains: The long lost high-level and FSSpec File Manager functions. + + Version: MoreFiles + + Copyright: © 1992-2001 by 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. + + File Ownership: + + DRI: Apple Macintosh Developer Technical Support + + Other Contact: Apple Macintosh Developer Technical Support + + + Technology: DTS Sample Code + + Writers: + + (JL) Jim Luther + + Change History (most recent first): + + <2> 2/7/01 JL Added standard header. Updated names of includes. + <1> 12/06/99 JL MoreFiles 1.5. +*/ + +#include +#include +#include + +#define __COMPILINGMOREFILES + +#include "MoreFiles.h" +#include "MoreFilesExtras.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) || (error == fidExists) || (error == afpIDExists) ) + { + *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 ); +} + +/*****************************************************************************/ diff --git a/src/mac/morefile/MoreFiles.h b/src/mac/morefile/MoreFiles.h new file mode 100644 index 0000000000..25b1fcf13e --- /dev/null +++ b/src/mac/morefile/MoreFiles.h @@ -0,0 +1,1420 @@ +/* + File: MoreFiles.h + + Contains: The long lost high-level and FSSpec File Manager functions. + + Version: Technology: MoreFiles + Release: 1.5.2 + + Copyright: © 1992-2001 by Apple Computer, Inc., all rights reserved. + + Bugs?: For bug reports, consult the following page on + the World Wide Web: + + http://developer.apple.com/bugreporter/ + +*/ + +/* + 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 __MOREFILES__ +#define __MOREFILES__ + +#ifndef __MACTYPES__ +#include +#endif + +#ifndef __FILES__ +#include +#endif + +#include "Optimization.h" + + +#if PRAGMA_ONCE +#pragma once +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if PRAGMA_IMPORT +#pragma import on +#endif + +#if PRAGMA_STRUCT_ALIGN + #pragma options align=mac68k +#elif PRAGMA_STRUCT_PACKPUSH + #pragma pack(push, 2) +#elif PRAGMA_STRUCT_PACK + #pragma pack(2) +#endif + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +HGetVolParms( + ConstStr255Param volName, + short vRefNum, + GetVolParmsInfoBuffer * volParmsInfo, + long * infoSize); + + +/* + The HGetVolParms function returns information about the characteristics + of a volume. A result of paramErr usually just means the volume doesn't + support PBHGetVolParms and the feature you were going to check + for isn't available. + + volName input: A pointer to the name of a mounted volume + or nil. + vRefNum input: Volume specification. + volParmsInfo input: Pointer to GetVolParmsInfoBuffer where the + volume attributes information is returned. + output: Atributes information. + infoSize input: Size of buffer pointed to by volParmsInfo. + output: Size of data actually returned. + + Result Codes + noErr 0 No error + nsvErr -35 Volume not found + paramErr -50 Volume doesn't support this function + + __________ + + Also see the macros for checking attribute bits in MoreFilesExtras.h +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +HCreateMinimum( + short vRefNum, + long dirID, + ConstStr255Param fileName); + + +/* + The HCreateMinimum function creates a new file without attempting to set + the creator and file type of the new file. This function is needed to + create a file in an AppleShare "drop box" where the user can make + changes, but cannot see folder or files. + + vRefNum input: Volume specification. + dirID input: Directory ID. + fileName input: The name of the new file. + + 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 + + __________ + + Also see: FSpCreateMinimum +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpCreateMinimum(const FSSpec * spec); + + +/* + The FSpCreateMinimum function creates a new file without attempting to set + the the creator and file type of the new file. This function is needed to + create a file in an AppleShare "dropbox" where the user can make + changes, but cannot see folder or files. + + spec input: An FSSpec record specifying the file to create. + + 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 + + __________ + + Also see: HCreateMinimum +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +ExchangeFiles( + short vRefNum, + long srcDirID, + ConstStr255Param srcName, + long dstDirID, + ConstStr255Param dstName); + + +/* + The ExchangeFiles function swaps the data in two files on the same + volume by changing some of the information in the volume catalog and, + if the files are open, in the file control blocks. + + vRefNum input: Volume specification. + srcDirID input: Source directory ID. + srcName input: Source file name. + dstDirID input: Destination directory ID. + dstName input: Destination file name. + + 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 are the same + + __________ + + Also see: FSpExchangeFilesCompat +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +ResolveFileIDRef( + ConstStr255Param volName, + short vRefNum, + long fileID, + long * parID, + StringPtr fileName); + + +/* + The ResolveFileIDRef function returns the filename and parent directory ID + of the file with the specified file ID reference. + + volName input: A pointer to the name of a mounted volume + or nil. + vRefNum input: Volume specification. + fileID input: The file ID reference. + parID output: The parent directory ID of the file. + name input: Points to a buffer (minimum Str63) where the filename + is to be returned or must be nil. + output: The filename. + + Result Codes + noErr 0 No error + nsvErr -35 Volume not found + ioErr -36 I/O error + fnfErr -43 File not found + paramErr -50 Function not supported by volume + volOfflinErr -53 Volume is offline + extFSErr -58 External file system error - no file + system claimed this call. + wrgVolTypErr -123 Not an HFS volume + fidNotFoundErr -1300 File ID reference not found + notAFileErr -1302 Specified file is a directory + afpAccessDenied -5000 User does not have the correct access + afpObjectTypeErr -5025 Specified file is a directory + afpIDNotFound -5034 File ID reference not found + afpBadIDErr -5039 File ID reference not found + + __________ + + Also see: FSpResolveFileIDRef, CreateFileIDRef, FSpCreateFileIDRef, + DeleteFileIDRef +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpResolveFileIDRef( + ConstStr255Param volName, + short vRefNum, + long fileID, + FSSpecPtr spec); + + +/* + The FSpResolveFileIDRef function fills in an FSSpec with the location + of the file with the specified file ID reference. + + volName input: A pointer to the name of a mounted volume + or nil. + vRefNum input: Volume specification. + fileID input: The file ID reference. + spec input: A pointer to a FSSpec record. + output: A file system specification to be filled in by + FSpResolveFileIDRef. + + Result Codes + noErr 0 No error + nsvErr -35 Volume not found + ioErr -36 I/O error + fnfErr -43 File not found + paramErr -50 Function not supported by volume or + no default volume + volOfflinErr -53 Volume is offline + extFSErr -58 External file system error - no file + system claimed this call. + wrgVolTypErr -123 Not an HFS volume + fidNotFoundErr -1300 File ID reference not found + notAFileErr -1302 Specified file is a directory + afpAccessDenied -5000 User does not have the correct access + afpObjectTypeErr -5025 Specified file is a directory + afpIDNotFound -5034 File ID reference not found + afpBadIDErr -5039 File ID reference not found + + __________ + + Also see: ResolveFileIDRef, CreateFileIDRef, FSpCreateFileIDRef, + DeleteFileIDRef +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +CreateFileIDRef( + short vRefNum, + long parID, + ConstStr255Param fileName, + long * fileID); + + +/* + The CreateFileIDRef function creates a file ID reference for the + specified file, or if a file ID reference already exists, supplies + the file ID reference and returns the result code fidExists or afpIDExists. + + vRefNum input: Volume specification. + parID input: Directory ID. + fileName input: The name of the file. + fileID output: The file ID reference (if result is noErr, + fidExists, or afpIDExists). + + Result Codes + noErr 0 No error + nsvErr -35 Volume not found + ioErr -36 I/O error + fnfErr -43 File not found + wPrErr -44 Hardware volume lock + vLckdErr -46 Software volume lock + paramErr -50 Function not supported by volume + volOfflinErr -53 Volume is offline + extFSErr -58 External file system error - no file + system claimed this call. + wrgVolTypErr -123 Not an HFS volume + fidExists -1301 File ID reference already exists + notAFileErrn -1302 Specified file is a directory + afpAccessDenied -5000 User does not have the correct access + afpObjectTypeErr -5025 Specified file is a directory + afpIDExists -5035 File ID reference already exists + + __________ + + Also see: FSpResolveFileIDRef, ResolveFileIDRef, FSpCreateFileIDRef, + DeleteFileIDRef +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpCreateFileIDRef( + const FSSpec * spec, + long * fileID); + + +/* + The FSpCreateFileIDRef function creates a file ID reference for the + specified file, or if a file ID reference already exists, supplies + the file ID reference and returns the result code fidExists or afpIDExists. + + spec input: An FSSpec record specifying the file. + fileID output: The file ID reference (if result is noErr, + fidExists, or afpIDExists). + + Result Codes + noErr 0 No error + nsvErr -35 Volume not found + ioErr -36 I/O error + fnfErr -43 File not found + wPrErr -44 Hardware volume lock + vLckdErr -46 Software volume lock + paramErr -50 Function not supported by volume + volOfflinErr -53 Volume is offline + extFSErr -58 External file system error - no file + system claimed this call. + wrgVolTypErr -123 Not an HFS volume + fidExists -1301 File ID reference already exists + notAFileErrn -1302 Specified file is a directory + afpAccessDenied -5000 User does not have the correct access + afpObjectTypeErr -5025 Specified file is a directory + afpIDExists -5035 File ID reference already exists + + __________ + + Also see: FSpResolveFileIDRef, ResolveFileIDRef, CreateFileIDRef, + DeleteFileIDRef +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +DeleteFileIDRef( + ConstStr255Param volName, + short vRefNum, + long fileID); + + +/* + The DeleteFileIDRef function deletes a file ID reference. + + volName input: A pointer to the name of a mounted volume + or nil. + vRefNum input: Volume specification. + fileID input: The file ID reference. + + Result Codes + noErr 0 No error + nsvErr -35 Volume not found + ioErr -36 I/O error + fnfErr -43 File not found + wPrErr -44 Hardware volume lock + vLckdErr -46 Software volume lock + paramErr -50 Function not supported by volume + volOfflinErr -53 Volume is offline + extFSErr -58 External file system error - no file + system claimed this call. + wrgVolTypErr -123 Function is not supported by volume + fidNotFoundErr -1300 File ID reference not found + afpAccessDenied -5000 User does not have the correct access + afpObjectTypeErr -5025 Specified file is a directory + afpIDNotFound -5034 File ID reference not found + + __________ + + Also see: FSpResolveFileIDRef, ResolveFileIDRef, CreateFileIDRef, + FSpCreateFileIDRef +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FlushFile(short refNum); + + +/* + The FlushFile function writes the contents of a file's access path + buffer (the fork data) to the volume. Note: some of the file's catalog + information stored on the volume may not be correct until FlushVol + is called. + + refNum input: The file reference number of an open file. + + Result Codes + noErr 0 No error + nsvErr -35 Volume not found + ioErr -36 I/O error + fnOpnErr -38 File not open + fnfErr -43 File not found + rfNumErr -51 Bad reference number + extFSErr -58 External file system error - no file + system claimed this call. +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +LockRange( + short refNum, + long rangeLength, + long rangeStart); + + +/* + The LockRange function locks (denies access to) a portion of a file + that was opened with shared read/write permission. + + refNum input: The file reference number of an open file. + rangeLength input: The number of bytes in the range. + rangeStart input: The starting byte in the range to lock. + + Result Codes + noErr 0 No error + ioErr -36 I/O error + fnOpnErr -38 File not open + eofErr -39 Logical end-of-file reached + fLckdErr -45 File is locked by another user + paramErr -50 Negative ioReqCount + rfNumErr -51 Bad reference number + extFSErr -58 External file system error - no file + system claimed this call. + volGoneErr -124 Server volume has been disconnected + afpNoMoreLocks -5015 No more ranges can be locked + afpRangeOverlap -5021 Part of range is already locked + + __________ + + Also see: UnlockRange +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +UnlockRange( + short refNum, + long rangeLength, + long rangeStart); + + +/* + The UnlockRange function unlocks (allows access to) a previously locked + portion of a file that was opened with shared read/write permission. + + refNum input: The file reference number of an open file. + rangeLength input: The number of bytes in the range. + rangeStart input: The starting byte in the range to unlock. + + Result Codes + noErr 0 No error + ioErr -36 I/O error + fnOpnErr -38 File not open + eofErr -39 Logical end-of-file reached + paramErr -50 Negative ioReqCount + rfNumErr -51 Bad reference number + extFSErr -58 External file system error - no file + system claimed this call. + volGoneErr -124 Server volume has been disconnected + afpRangeNotLocked -5020 Specified range was not locked + + __________ + + Also see: LockRange +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +GetForeignPrivs( + short vRefNum, + long dirID, + ConstStr255Param name, + void * foreignPrivBuffer, + long * foreignPrivSize, + long * foreignPrivInfo1, + long * foreignPrivInfo2, + long * foreignPrivInfo3, + long * foreignPrivInfo4); + + +/* + The GetForeignPrivs function retrieves the native access-control + information for a file or directory stored on a volume managed by + a foreign file system. + + 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. + foreignPrivBuffer input: Pointer to buffer where the privilege + information is returned. + output: Privilege information. + foreignPrivSize input: Size of buffer pointed to by + foreignPrivBuffer. + output: Amount of buffer actually used. + foreignPrivInfo1 output: Information specific to privilege model. + foreignPrivInfo2 output: Information specific to privilege model. + foreignPrivInfo3 output: Information specific to privilege model. + foreignPrivInfo4 output: Information specific to privilege model. + + Result Codes + noErr 0 No error + nsvErr -35 Volume not found + paramErr -50 Volume is HFS or MFS (that is, it has + no foreign privilege model), or foreign + volume does not support these calls + + __________ + + Also see: FSpGetForeignPrivs, SetForeignPrivs, FSpSetForeignPrivs +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpGetForeignPrivs( + const FSSpec * spec, + void * foreignPrivBuffer, + long * foreignPrivSize, + long * foreignPrivInfo1, + long * foreignPrivInfo2, + long * foreignPrivInfo3, + long * foreignPrivInfo4); + + +/* + The FSpGetForeignPrivs function retrieves the native access-control + information for a file or directory stored on a volume managed by + a foreign file system. + + spec input: An FSSpec record specifying the object. + foreignPrivBuffer input: Pointer to buffer where the privilege + information is returned. + output: Privilege information. + foreignPrivSize input: Size of buffer pointed to by + foreignPrivBuffer. + output: Amount of buffer actually used. + foreignPrivInfo1 output: Information specific to privilege model. + foreignPrivInfo2 output: Information specific to privilege model. + foreignPrivInfo3 output: Information specific to privilege model. + foreignPrivInfo4 output: Information specific to privilege model. + + Result Codes + noErr 0 No error + nsvErr -35 Volume not found + paramErr -50 Volume is HFS or MFS (that is, it has + no foreign privilege model), or foreign + volume does not support these calls + + __________ + + Also see: GetForeignPrivs, SetForeignPrivs, FSpSetForeignPrivs +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +SetForeignPrivs( + short vRefNum, + long dirID, + ConstStr255Param name, + const void * foreignPrivBuffer, + long * foreignPrivSize, + long foreignPrivInfo1, + long foreignPrivInfo2, + long foreignPrivInfo3, + long foreignPrivInfo4); + + +/* + The SetForeignPrivs function changes the native access-control + information for a file or directory stored on a volume managed by + a foreign file system. + + 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. + foreignPrivBuffer input: Pointer to privilege information buffer. + foreignPrivSize input: Size of buffer pointed to by + foreignPrivBuffer. + output: Amount of buffer actually used. + foreignPrivInfo1 input: Information specific to privilege model. + foreignPrivInfo2 input: Information specific to privilege model. + foreignPrivInfo3 input: Information specific to privilege model. + foreignPrivInfo4 input: Information specific to privilege model. + + Result Codes + noErr 0 No error + nsvErr -35 Volume not found + paramErr -50 Volume is HFS or MFS (that is, it has + no foreign privilege model), or foreign + volume does not support these calls + + __________ + + Also see: GetForeignPrivs, FSpGetForeignPrivs, FSpSetForeignPrivs +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpSetForeignPrivs( + const FSSpec * spec, + const void * foreignPrivBuffer, + long * foreignPrivSize, + long foreignPrivInfo1, + long foreignPrivInfo2, + long foreignPrivInfo3, + long foreignPrivInfo4); + + +/* + The FSpSetForeignPrivs function changes the native access-control + information for a file or directory stored on a volume managed by + a foreign file system. + + spec input: An FSSpec record specifying the object. + foreignPrivBuffer input: Pointer to privilege information buffer. + foreignPrivSize input: Size of buffer pointed to by + foreignPrivBuffer. + output: Amount of buffer actually used. + foreignPrivInfo1 input: Information specific to privilege model. + foreignPrivInfo2 input: Information specific to privilege model. + foreignPrivInfo3 input: Information specific to privilege model. + foreignPrivInfo4 input: Information specific to privilege model. + + Result Codes + noErr 0 No error + nsvErr -35 Volume not found + paramErr -50 Volume is HFS or MFS (that is, it has + no foreign privilege model), or foreign + volume does not support these calls + + __________ + + Also see: GetForeignPrivs, FSpGetForeignPrivs, SetForeignPrivs +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +HGetLogInInfo( + ConstStr255Param volName, + short vRefNum, + short * loginMethod, + StringPtr userName); + + +/* + The HGetLogInInfo function retrieves the login method and user name + used to log on to a particular shared volume. + + volName input: A pointer to the name of a mounted volume + or nil. + vRefNum input: The volume reference number. + loginMethod output: The login method used (kNoUserAuthentication, + kPassword, kEncryptPassword, or + kTwoWayEncryptPassword). + userName input: Points to a buffer (minimum Str31) where the user + name is to be returned or must be nil. + output: The user name. + + Result Codes + noErr 0 No error + nsvErr -35 Specified volume doesnÕt exist + paramErr -50 Function not supported by volume + + __________ + + Also see: HGetDirAccess, FSpGetDirAccess, HSetDirAccess, + FSpSetDirAccess, HMapName, HMapID +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +HGetDirAccess( + short vRefNum, + long dirID, + ConstStr255Param name, + long * ownerID, + long * groupID, + long * accessRights); + + +/* + The HGetDirAccess function retrieves the directory access control + information for a directory on a shared volume. + + vRefNum input: Volume specification. + dirID input: Directory ID. + name input: Pointer to directory name, or nil if dirID + specifies the directory. + ownerID output: The directory's owner ID. + groupID output: The directory's group ID or + 0 if no group affiliation. + accessRights output: The directory's access rights. + + Result Codes + noErr 0 No error + fnfErr -43 Directory not found + paramErr -50 Function not supported by volume + afpAccessDenied -5000 User does not have the correct access + to the directory + + __________ + + Also see: HGetLogInInfo, FSpGetDirAccess, HSetDirAccess, + FSpSetDirAccess, HMapName, HMapID +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpGetDirAccess( + const FSSpec * spec, + long * ownerID, + long * groupID, + long * accessRights); + + +/* + The FSpGetDirAccess function retrieves the directory access control + information for a directory on a shared volume. + + spec input: An FSSpec record specifying the directory. + ownerID output: The directory's owner ID. + groupID output: The directory's group ID or + 0 if no group affiliation. + accessRights output: The directory's access rights. + + Result Codes + noErr 0 No error + fnfErr -43 Directory not found + paramErr -50 Function not supported by volume + afpAccessDenied -5000 User does not have the correct access + to the directory + + __________ + + Also see: HGetLogInInfo, HGetDirAccess, HSetDirAccess, + FSpSetDirAccess, HMapName, HMapID +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +HSetDirAccess( + short vRefNum, + long dirID, + ConstStr255Param name, + long ownerID, + long groupID, + long accessRights); + + +/* + The HSetDirAccess function changes the directory access control + information for a directory on a shared volume. You must own a directory + to change its access control information. + + vRefNum input: Volume specification. + dirID input: Directory ID. + name input: Pointer to directory name, or nil if dirID + specifies the directory. + ownerID input: The directory's owner ID. + groupID input: The directory's group ID or + 0 if no group affiliation. + accessRights input: The directory's access rights. + + Result Codes + noErr 0 No error + fnfErr -43 Directory not found + vLckdErr -46 Volume is locked or read-only + paramErr -50 Parameter error + afpAccessDenied -5000 User does not have the correct access + to the directory + afpObjectTypeErr -5025 Object is a file, not a directory + + __________ + + Also see: HGetLogInInfo, HGetDirAccess, FSpGetDirAccess, + FSpSetDirAccess, HMapName, HMapID +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpSetDirAccess( + const FSSpec * spec, + long ownerID, + long groupID, + long accessRights); + + +/* + The FSpSetDirAccess function changes the directory access control + information for a directory on a shared volume. You must own a directory + to change its access control information. + + spec input: An FSSpec record specifying the directory. + ownerID input: The directory's owner ID. + groupID input: The directory's group ID or + 0 if no group affiliation. + accessRights input: The directory's access rights. + + Result Codes + noErr 0 No error + fnfErr -43 Directory not found + vLckdErr -46 Volume is locked or read-only + paramErr -50 Parameter error + afpAccessDenied -5000 User does not have the correct access + to the directory + afpObjectTypeErr -5025 Object is a file, not a directory + + __________ + + Also see: HGetLogInInfo, HGetDirAccess, FSpGetDirAccess, HSetDirAccess, + HMapName, HMapID +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +HMapID( + ConstStr255Param volName, + short vRefNum, + long ugID, + short objType, + StringPtr name); + + +/* + The HMapID function determines the name of a user or group if you know + the user or group ID. + + volName input: A pointer to the name of a mounted volume + or nil. + vRefNum input: Volume specification. + objType input: The mapping function code: 1 if you're mapping a + user ID to a user name or 2 if you're mapping a + group ID to a group name. + name input: Points to a buffer (minimum Str31) where the user + or group name is to be returned or must be nil. + output: The user or group name. + + Result Codes + noErr 0 No error + fnfErr -43 Unrecognizable owner or group name + paramErr -50 Function not supported by volume + + __________ + + Also see: HGetLogInInfo, HGetDirAccess, FSpGetDirAccess, HSetDirAccess, + FSpSetDirAccess, HMapName +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +HMapName( + ConstStr255Param volName, + short vRefNum, + ConstStr255Param name, + short objType, + long * ugID); + + +/* + The HMapName function determines the user or group ID if you know the + user or group name. + + volName input: A pointer to the name of a mounted volume + or nil. + vRefNum input: Volume specification. + name input: The user or group name. + objType input: The mapping function code: 3 if you're mapping a + user name to a user ID or 4 if you're mapping a + group name to a group ID. + ugID output: The user or group ID. + + Result Codes + noErr 0 No error + fnfErr -43 Unrecognizable owner or group name + paramErr -50 Function not supported by volume + + __________ + + Also see: HGetLogInInfo, HGetDirAccess, FSpGetDirAccess, HSetDirAccess, + FSpSetDirAccess, HMapID +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +HCopyFile( + short srcVRefNum, + long srcDirID, + ConstStr255Param srcName, + short dstVRefNum, + long dstDirID, + ConstStr255Param dstPathname, + ConstStr255Param copyName); + + +/* + The HCopyFile function duplicates a file and optionally renames it. + The source and destination volumes must be on the same file server. + This function instructs the server to copy the file. + + 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. + + Result Codes + noErr 0 No error + dskFulErr -34 Destination volume is full + fnfErr -43 Source file not found, or destination + directory does not exist + 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 + paramErr -50 Function not supported by volume + wrgVolTypErr -123 Function not supported by volume + afpAccessDenied -5000 The user does not have the right to + read the source or write to the + destination + afpDenyConflict -5006 The source or destination file could + not be opened with the correct access + modes + afpObjectTypeErr -5025 Source is a directory + + __________ + + Also see: FSpCopyFile, FileCopy, FSpFileCopy +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpCopyFile( + const FSSpec * srcSpec, + const FSSpec * dstSpec, + ConstStr255Param copyName); + + +/* + The FSpCopyFile function duplicates a file and optionally renames it. + The source and destination volumes must be on the same file server. + This function instructs the server to copy the file. + + 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. + + Result Codes + noErr 0 No error + dskFulErr -34 Destination volume is full + fnfErr -43 Source file not found, or destination + directory does not exist + 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 + paramErr -50 Function not supported by volume + wrgVolTypErr -123 Function not supported by volume + afpAccessDenied -5000 The user does not have the right to + read the source or write to the + destination + afpDenyConflict -5006 The source or destination file could + not be opened with the correct access + modes + afpObjectTypeErr -5025 Source is a directory + + __________ + + Also see: HCopyFile, FileCopy, FSpFileCopy +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +HMoveRename( + short vRefNum, + long srcDirID, + ConstStr255Param srcName, + long dstDirID, + ConstStr255Param dstpathName, + ConstStr255Param copyName); + + +/* + The HMoveRename function moves a file or directory and optionally + renames it. The source and destination locations must be on the same + shared volume. + + vRefNum input: Volume specification. + srcDirID input: Source directory ID. + srcName input: The source object name. + dstDirID input: Destination directory ID. + dstName input: Pointer to destination directory name, or + nil when dstDirID specifies a directory. + copyName input: Points to the new name if the object is to be + renamed or nil if the object isn't to be renamed. + + Result Codes + noErr 0 No error + fnfErr -43 Source file or directory not found + fLckdErr -45 File is locked + vLckdErr -46 Destination volume is read-only + dupFNErr -48 Destination already exists + paramErr -50 Function not supported by volume + badMovErr -122 Attempted to move directory into + offspring + afpAccessDenied -5000 The user does not have the right to + move the file or directory + + __________ + + Also see: FSpMoveRename, HMoveRenameCompat, FSpMoveRenameCompat +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpMoveRename( + const FSSpec * srcSpec, + const FSSpec * dstSpec, + ConstStr255Param copyName); + + +/* + The FSpMoveRename function moves a file or directory and optionally + renames it. The source and destination locations must be on the same + shared volume. + + srcSpec input: An FSSpec record specifying the source object. + dstSpec input: An FSSpec record specifying the destination + directory. + copyName input: Points to the new name if the object is to be + renamed or nil if the object isn't to be renamed. + + Result Codes + noErr 0 No error + fnfErr -43 Source file or directory not found + fLckdErr -45 File is locked + vLckdErr -46 Destination volume is read-only + dupFNErr -48 Destination already exists + paramErr -50 Function not supported by volume + badMovErr -122 Attempted to move directory into + offspring + afpAccessDenied -5000 The user does not have the right to + move the file or directory + + __________ + + Also see: HMoveRename, HMoveRenameCompat, FSpMoveRenameCompat +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +GetVolMountInfoSize( + ConstStr255Param volName, + short vRefNum, + short * size); + + +/* + The GetVolMountInfoSize function determines the how much space the + program needs to allocate for a volume mounting information record. + + volName input: A pointer to the name of a mounted volume + or nil. + vRefNum input: Volume specification. + size output: The space needed (in bytes) of the volume mounting + information record. + + Result Codes + noErr 0 No error + nsvErr -35 Volume not found + paramErr -50 Parameter error + extFSErr -58 External file system error - no file + system claimed this call. + + __________ + + Also see: GetVolMountInfo, VolumeMount BuildAFPVolMountInfo, + RetrieveAFPVolMountInfo +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +GetVolMountInfo( + ConstStr255Param volName, + short vRefNum, + void * volMountInfo); + + +/* + The GetVolMountInfo function retrieves a volume mounting information + record containing all the information needed to mount the volume, + except for passwords. + + volName input: A pointer to the name of a mounted volume + or nil. + vRefNum input: Volume specification. + volMountInfo output: Points to a volume mounting information + record where the mounting information is to + be returned. + + Result Codes + noErr 0 No error + nsvErr -35 Volume not found + paramErr -50 Parameter error + extFSErr -58 External file system error - no file + system claimed this call. + + __________ + + Also see: GetVolMountInfoSize, VolumeMount, BuildAFPVolMountInfo, + RetrieveAFPVolMountInfo +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +VolumeMount( + const void * volMountInfo, + short * vRefNum); + + +/* + The VolumeMount function mounts a volume using a volume mounting + information record. + + volMountInfo input: Points to a volume mounting information record. + vRefNum output: A volume reference number. + + Result Codes + noErr 0 No error + notOpenErr -28 AppleTalk is not open + nsvErr -35 Volume not found + paramErr -50 Parameter error; typically, zone, server, + and volume name combination is not valid + or not complete, or the user name is not + recognized + extFSErr -58 External file system error - no file + system claimed this call. + memFullErr -108 Not enough memory to create a new volume + control block for mounting the volume + afpBadUAM -5002 User authentication method is unknown + afpBadVersNum -5003 Workstation is using an AFP version that + the server doesnÕt recognize + afpNoServer -5016 Server is not responding + afpUserNotAuth -5023 User authentication failed (usually, + password is not correct) + afpPwdExpired -5042 Password has expired on server + afpBadDirIDType -5060 Not a fixed directory ID volume + afpCantMountMoreSrvrs -5061 Maximum number of volumes has been + mounted + afpAlreadyMounted -5062 Volume already mounted + afpSameNodeErr -5063 Attempt to log on to a server running + on the same machine + + __________ + + Also see: GetVolMountInfoSize, GetVolMountInfo, BuildAFPVolMountInfo, + RetrieveAFPVolMountInfo +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +Share( + short vRefNum, + long dirID, + ConstStr255Param name); + + +/* + The Share function establishes a local volume or directory as a + share point. + + vRefNum input: Volume specification. + dirID input: Directory ID. + name input: Pointer to directory name, or nil if dirID + specifies the directory. + + Result Codes + noErr 0 No error + tmfoErr -42 Too many share points + fnfErr -43 File not found + dupFNErr -48 Already a share point with this name + paramErr -50 Function not supported by volume + dirNFErrdirNFErr -120 Directory not found + afpAccessDenied -5000 This directory cannot be shared + afpObjectTypeErr -5025 Object was a file, not a directory + afpContainsSharedErr -5033 The directory contains a share point + afpInsideSharedErr -5043 The directory is inside a shared directory + + __________ + + Also see: FSpShare, Unshare, FSpUnshare +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpShare(const FSSpec * spec); + + +/* + The FSpShare function establishes a local volume or directory as a + share point. + + spec input: An FSSpec record specifying the share point. + + Result Codes + noErr 0 No error + tmfoErr -42 Too many share points + fnfErr -43 File not found + dupFNErr -48 Already a share point with this name + paramErr -50 Function not supported by volume + dirNFErrdirNFErr -120 Directory not found + afpAccessDenied -5000 This directory cannot be shared + afpObjectTypeErr -5025 Object was a file, not a directory + afpContainsSharedErr -5033 The directory contains a share point + afpInsideSharedErr -5043 The directory is inside a shared directory + + __________ + + Also see: Share, Unshare, FSpUnshare +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +Unshare( + short vRefNum, + long dirID, + ConstStr255Param name); + + +/* + The Unshare function removes a share point. + + vRefNum input: Volume specification. + dirID input: Directory ID. + name input: Pointer to directory name, or nil if dirID + specifies the directory. + + Result Codes + noErr 0 No error + fnfErr -43 File not found + paramErr -50 Function not supported by volume + dirNFErrdirNFErr -120 Directory not found + afpObjectTypeErr -5025 Object was a file, not a directory; or, + this directory is not a share point + + __________ + + Also see: Share, FSpShare, FSpUnshare +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpUnshare(const FSSpec * spec); + + +/* + The FSpUnshare function removes a share point. + + spec input: An FSSpec record specifying the share point. + + Result Codes + noErr 0 No error + fnfErr -43 File not found + paramErr -50 Function not supported by volume + dirNFErrdirNFErr -120 Directory not found + afpObjectTypeErr -5025 Object was a file, not a directory; or, + this directory is not a share point + + __________ + + Also see: Share, FSpShare, Unshare +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +GetUGEntry( + short objType, + StringPtr objName, + long * objID); + + +/* + The GetUGEntry function retrieves user or group entries from the + local file server. + + objType input: The object type: -1 = group; 0 = user + objName input: Points to a buffer (minimum Str31) where the user + or group name is to be returned or must be nil. + output: The user or group name. + objID input: O to get the first user or group. If the entry objID + last returned by GetUGEntry is passed, then user or + group whose alphabetically next in the list of entries + is returned. + output: The user or group ID. + + Result Codes + noErr 0 No error + fnfErr -43 No more users or groups + paramErr -50 Function not supported; or, ioObjID is + negative + + __________ + + Also see: GetUGEntries +*/ + +/*****************************************************************************/ + +#include "OptimizationEnd.h" + +#if PRAGMA_STRUCT_ALIGN + #pragma options align=reset +#elif PRAGMA_STRUCT_PACKPUSH + #pragma pack(pop) +#elif PRAGMA_STRUCT_PACK + #pragma pack() +#endif + +#ifdef PRAGMA_IMPORT_OFF +#pragma import off +#elif PRAGMA_IMPORT +#pragma import reset +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __MOREFILES__ */ + diff --git a/src/mac/morefile/MoreFilesExtras.c b/src/mac/morefile/MoreFilesExtras.c new file mode 100644 index 0000000000..7a5a083524 --- /dev/null +++ b/src/mac/morefile/MoreFilesExtras.c @@ -0,0 +1,3628 @@ +/* + File: MoreFilesExtras.c + + Contains: A collection of useful high-level File Manager routines + + Version: MoreFiles + + Copyright: © 1992-2001 by 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. + + File Ownership: + + DRI: Jim Luther + + Other Contact: Apple Macintosh Developer Technical Support + + + Technology: DTS Sample Code + + Writers: + + (JL) Jim Luther + + Change History (most recent first): + + <2> 2/7/01 JL [2500429] Changed null output parameters to real variables when + calling GetSharedLibrary to prevent crashes with older versions + of CFM. Added standard header. Updated names of includes. Added + C function implementations of accessors that used to be macros + since the generated Pascal headers no longer contain + implementations. Updated various other routines to use new + calling convention of the accessor functions. + <1> 12/06/99 JL MoreFiles 1.5. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define __COMPILINGMOREFILES + +#include "MoreFiles.h" +#include "MoreDesktopMgr.h" +#include "FSpCompat.h" + +#include "MoreFilesExtras.h" + +/*****************************************************************************/ + +/* Functions to get information out of GetVolParmsInfoBuffer. */ + +/* version 1 field getters */ + +pascal short GetVolParmsInfoVersion(const GetVolParmsInfoBuffer *volParms) +{ + return ( volParms->vMVersion ); +} + +pascal long GetVolParmsInfoAttrib(const GetVolParmsInfoBuffer *volParms) +{ + return ( volParms->vMAttrib ); +} + +pascal Handle GetVolParmsInfoLocalHand(const GetVolParmsInfoBuffer *volParms) +{ + return ( volParms->vMLocalHand ); +} + +pascal long GetVolParmsInfoServerAdr(const GetVolParmsInfoBuffer *volParms) +{ + return ( volParms->vMServerAdr ); +} + +/* version 2 field getters (assume zero result if version < 2) */ + +pascal long GetVolParmsInfoVolumeGrade(const GetVolParmsInfoBuffer *volParms) +{ + return ( (volParms->vMVersion >= 2) ? volParms->vMVolumeGrade : 0 ); +} + +pascal long GetVolParmsInfoForeignPrivID(const GetVolParmsInfoBuffer *volParms) +{ + return ( (volParms->vMVersion >= 2) ? volParms->vMForeignPrivID : 0 ); +} + +/* version 3 field getters (assume zero result if version < 3) */ + +pascal long GetVolParmsInfoExtendedAttributes(const GetVolParmsInfoBuffer *volParms) +{ + return ( (volParms->vMVersion >= 3) ? volParms->vMExtendedAttributes : 0 ); +} + +/* attribute bits supported by all versions of GetVolParmsInfoBuffer */ + +pascal Boolean isNetworkVolume(const GetVolParmsInfoBuffer *volParms) +{ + return ( volParms->vMServerAdr != 0 ); +} + +pascal Boolean hasLimitFCBs(const GetVolParmsInfoBuffer *volParms) +{ + return ( (volParms->vMAttrib & (1L << bLimitFCBs)) != 0 ); +} + +pascal Boolean hasLocalWList(const GetVolParmsInfoBuffer *volParms) +{ + return ( (volParms->vMAttrib & (1L << bLocalWList)) != 0 ); +} + +pascal Boolean hasNoMiniFndr(const GetVolParmsInfoBuffer *volParms) +{ + return ( (volParms->vMAttrib & (1L << bNoMiniFndr)) != 0 ); +} + +pascal Boolean hasNoVNEdit(const GetVolParmsInfoBuffer *volParms) +{ + return ( (volParms->vMAttrib & (1L << bNoVNEdit)) != 0 ); +} + +pascal Boolean hasNoLclSync(const GetVolParmsInfoBuffer *volParms) +{ + return ( (volParms->vMAttrib & (1L << bNoLclSync)) != 0 ); +} + +pascal Boolean hasTrshOffLine(const GetVolParmsInfoBuffer *volParms) +{ + return ( (volParms->vMAttrib & (1L << bTrshOffLine)) != 0 ); +} + +pascal Boolean hasNoSwitchTo(const GetVolParmsInfoBuffer *volParms) +{ + return ( (volParms->vMAttrib & (1L << bNoSwitchTo)) != 0 ); +} + +pascal Boolean hasNoDeskItems(const GetVolParmsInfoBuffer *volParms) +{ + return ( (volParms->vMAttrib & (1L << bNoDeskItems)) != 0 ); +} + +pascal Boolean hasNoBootBlks(const GetVolParmsInfoBuffer *volParms) +{ + return ( (volParms->vMAttrib & (1L << bNoBootBlks)) != 0 ); +} + +pascal Boolean hasAccessCntl(const GetVolParmsInfoBuffer *volParms) +{ + return ( (volParms->vMAttrib & (1L << bAccessCntl)) != 0 ); +} + +pascal Boolean hasNoSysDir(const GetVolParmsInfoBuffer *volParms) +{ + return ( (volParms->vMAttrib & (1L << bNoSysDir)) != 0 ); +} + +pascal Boolean hasExtFSVol(const GetVolParmsInfoBuffer *volParms) +{ + return ( (volParms->vMAttrib & (1L << bHasExtFSVol)) != 0 ); +} + +pascal Boolean hasOpenDeny(const GetVolParmsInfoBuffer *volParms) +{ + return ( (volParms->vMAttrib & (1L << bHasOpenDeny)) != 0 ); +} + +pascal Boolean hasCopyFile(const GetVolParmsInfoBuffer *volParms) +{ + return ( (volParms->vMAttrib & (1L << bHasCopyFile)) != 0 ); +} + +pascal Boolean hasMoveRename(const GetVolParmsInfoBuffer *volParms) +{ + return ( (volParms->vMAttrib & (1L << bHasMoveRename)) != 0 ); +} + +pascal Boolean hasDesktopMgr(const GetVolParmsInfoBuffer *volParms) +{ + return ( (volParms->vMAttrib & (1L << bHasDesktopMgr)) != 0 ); +} + +pascal Boolean hasShortName(const GetVolParmsInfoBuffer *volParms) +{ + return ( (volParms->vMAttrib & (1L << bHasShortName)) != 0 ); +} + +pascal Boolean hasFolderLock(const GetVolParmsInfoBuffer *volParms) +{ + return ( (volParms->vMAttrib & (1L << bHasFolderLock)) != 0 ); +} + +pascal Boolean hasPersonalAccessPrivileges(const GetVolParmsInfoBuffer *volParms) +{ + return ( (volParms->vMAttrib & (1L << bHasPersonalAccessPrivileges)) != 0 ); +} + +pascal Boolean hasUserGroupList(const GetVolParmsInfoBuffer *volParms) +{ + return ( (volParms->vMAttrib & (1L << bHasUserGroupList)) != 0 ); +} + +pascal Boolean hasCatSearch(const GetVolParmsInfoBuffer *volParms) +{ + return ( (volParms->vMAttrib & (1L << bHasCatSearch)) != 0 ); +} + +pascal Boolean hasFileIDs(const GetVolParmsInfoBuffer *volParms) +{ + return ( (volParms->vMAttrib & (1L << bHasFileIDs)) != 0 ); +} + +pascal Boolean hasBTreeMgr(const GetVolParmsInfoBuffer *volParms) +{ + return ( (volParms->vMAttrib & (1L << bHasBTreeMgr)) != 0 ); +} + +pascal Boolean hasBlankAccessPrivileges(const GetVolParmsInfoBuffer *volParms) +{ + return ( (volParms->vMAttrib & (1L << bHasBlankAccessPrivileges)) != 0 ); +} + +pascal Boolean supportsAsyncRequests(const GetVolParmsInfoBuffer *volParms) +{ + return ( (volParms->vMAttrib & (1L << bSupportsAsyncRequests)) != 0 ); +} + +pascal Boolean supportsTrashVolumeCache(const GetVolParmsInfoBuffer *volParms) +{ + return ( (volParms->vMAttrib & (1L << bSupportsTrashVolumeCache)) != 0 ); +} + +/* attribute bits supported by version 3 and greater versions of GetVolParmsInfoBuffer */ + +pascal Boolean volIsEjectable(const GetVolParmsInfoBuffer *volParms) +{ + return ( (GetVolParmsInfoExtendedAttributes(volParms) & (1L << bIsEjectable)) != 0 ); +} + +pascal Boolean volSupportsHFSPlusAPIs(const GetVolParmsInfoBuffer *volParms) +{ + return ( (GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsHFSPlusAPIs)) != 0 ); +} + +pascal Boolean volSupportsFSCatalogSearch(const GetVolParmsInfoBuffer *volParms) +{ + return ( (GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsFSCatalogSearch)) != 0 ); +} + +pascal Boolean volSupportsFSExchangeObjects(const GetVolParmsInfoBuffer *volParms) +{ + return ( (GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsFSExchangeObjects)) != 0 ); +} + +pascal Boolean volSupports2TBFiles(const GetVolParmsInfoBuffer *volParms) +{ + return ( (GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupports2TBFiles)) != 0 ); +} + +pascal Boolean volSupportsLongNames(const GetVolParmsInfoBuffer *volParms) +{ + return ( (GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsLongNames)) != 0 ); +} + +pascal Boolean volSupportsMultiScriptNames(const GetVolParmsInfoBuffer *volParms) +{ + return ( (GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsMultiScriptNames)) != 0 ); +} + +pascal Boolean volSupportsNamedForks(const GetVolParmsInfoBuffer *volParms) +{ + return ( (GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsNamedForks)) != 0 ); +} + +pascal Boolean volSupportsSubtreeIterators(const GetVolParmsInfoBuffer *volParms) +{ + return ( (GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsSubtreeIterators)) != 0 ); +} + +pascal Boolean volL2PCanMapFileBlocks(const GetVolParmsInfoBuffer *volParms) +{ + return ( (GetVolParmsInfoExtendedAttributes(volParms) & (1L << bL2PCanMapFileBlocks)) != 0 ); +} + +/*****************************************************************************/ + +/* Functions for testing ioACUser bits. */ + +pascal Boolean userIsOwner(SInt8 ioACUser) +{ + return ( (ioACUser & kioACUserNotOwnerMask) == 0 ); +} + +pascal Boolean userHasFullAccess(SInt8 ioACUser) +{ + return ( (ioACUser & acUserAccessMask) == acUserFull ); +} + +pascal Boolean userHasDropBoxAccess(SInt8 ioACUser) +{ + return ( (ioACUser & acUserAccessMask) == acUserDropBox ); +} + +pascal Boolean userHasBulletinBoard(SInt8 ioACUser) +{ + return ( (ioACUser & acUserAccessMask) == acUserBulletinBoard ); +} + +pascal Boolean userHasNoAccess(SInt8 ioACUser) +{ + return ( (ioACUser & acUserAccessMask) == acUserNone ); +} + +/*****************************************************************************/ + +/* local data structures */ + +/* The DeleteEnumGlobals structure is used to minimize the amount of +** stack space used when recursively calling DeleteLevel and to hold +** global information that might be needed at any time. */ + +#if PRAGMA_STRUCT_ALIGN + #pragma options align=mac68k +#endif // PRAGMA_STRUCT_ALIGN +struct DeleteEnumGlobals +{ + OSErr error; /* temporary holder of results - saves 2 bytes of stack each level */ + Str63 itemName; /* the name of the current item */ + UniversalFMPB myPB; /* the parameter block used for PBGetCatInfo calls */ +}; +#if PRAGMA_STRUCT_ALIGN + #pragma options align=reset +#endif // PRAGMA_STRUCT_ALIGN + +typedef struct DeleteEnumGlobals DeleteEnumGlobals; +typedef DeleteEnumGlobals *DeleteEnumGlobalsPtr; + +/*****************************************************************************/ + +/* +** CallPBXGetVolInfoSync is the glue code needed to make PBXGetVolInfoSync +** File Manager requests from CFM-based programs. Apple added PBXGetVolInfoSync +** to InterfaceLib in Mac OS 8.5, so if __MACOSEIGHTFIVEORLATER is defined, +** CallPBXGetVolInfoSync is defined back to PBXGetVolInfoSync. +** +** Non-CFM 68K programs don't needs this glue (and won't get it) because +** they instead use the inline assembly glue found in the Files.h interface +** file. +*/ + +#if TARGET_API_MAC_CARBON || !TARGET_RT_MAC_CFM + + // Carbon builds and 68K builds don't need this glue + #define CallPBXGetVolInfoSync PBXGetVolInfoSync + +#else // TARGET_API_MAC_CARBON || !TARGET_RT_MAC_CFM + + #if __WANTPASCALELIMINATION + #undef pascal + #endif // __WANTPASCALELIMINATION + + /* This is exactly like the simple mixed mode glue in InterfaceLib in Mac OS 8.5 and 8.6 */ + static pascal OSErr PBXGetVolInfoSyncGlue(XVolumeParamPtr paramBlock) + { + enum + { + uppFSDispatchProcInfo = kRegisterBased + | REGISTER_RESULT_LOCATION(kRegisterD0) + | RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) + | REGISTER_ROUTINE_PARAMETER(1, kRegisterD0, SIZE_CODE(sizeof(long))) /* selector */ + | REGISTER_ROUTINE_PARAMETER(2, kRegisterD1, SIZE_CODE(sizeof(long))) /* trap word */ + | REGISTER_ROUTINE_PARAMETER(3, kRegisterA0, SIZE_CODE(sizeof(XVolumeParamPtr))) + }; + + static UniversalProcPtr fsDispatchTrapAddress = NULL; + + /* Is this the first time we've been called? */ + if ( fsDispatchTrapAddress == NULL ) + { + /* Yes - Get the trap address of _FSDispatch */ + fsDispatchTrapAddress = NGetTrapAddress(_FSDispatch, OSTrap); + } + return ( CallOSTrapUniversalProc(fsDispatchTrapAddress, + uppFSDispatchProcInfo, + kFSMXGetVolInfo, + _FSDispatch, + paramBlock) ); + } + + /* + ** PBXGetVolInfoSync was added to the File Manager in System software 7.5.2. + ** However, PBXGetVolInfoSync wasn't added to InterfaceLib until Mac OS 8.5. + ** This wrapper calls PBXGetVolInfoSync if it is found in InterfaceLib; + ** otherwise, it calls PBXGetVolInfoSyncGlue. This ensures that your program + ** is calling the latest implementation of PBXGetVolInfoSync. + */ + static pascal OSErr CallPBXGetVolInfoSync(XVolumeParamPtr paramBlock) + { + typedef pascal OSErr (*PBXGetVolInfoProcPtr) (XVolumeParamPtr paramBlock); + + OSErr result; + CFragConnectionID connID; + Ptr mainAddr; + Str255 errMessage; + static PBXGetVolInfoProcPtr PBXGetVolInfoSyncPtr = NULL; + + //* Is this the first time we've been called? */ + if ( PBXGetVolInfoSyncPtr == NULL ) + { + /* Yes - Get our connection ID to InterfaceLib */ + result = GetSharedLibrary("\pInterfaceLib", kPowerPCCFragArch, kLoadCFrag, &connID, &mainAddr, errMessage); + if ( result == noErr ) + { + /* See if PBXGetVolInfoSync is in InterfaceLib */ + if ( FindSymbol(connID, "\pPBXGetVolInfoSync", &(Ptr)PBXGetVolInfoSyncPtr, NULL) != noErr ) + { + /* Use glue code if symbol isn't found */ + PBXGetVolInfoSyncPtr = PBXGetVolInfoSyncGlue; + } + } + } + /* Call PBXGetVolInfoSync if present; otherwise, call PBXGetVolInfoSyncGlue */ + return ( (*PBXGetVolInfoSyncPtr)(paramBlock) ); + } + + #if __WANTPASCALELIMINATION + #define pascal + #endif // __WANTPASCALELIMINATION + +#endif // TARGET_API_MAC_CARBON || !TARGET_RT_MAC_CFM + +/*****************************************************************************/ + +pascal void TruncPString(StringPtr destination, + ConstStr255Param source, + short maxLength) +{ + short charType; + + if ( source != NULL && destination != NULL ) /* don't do anything stupid */ + { + if ( source[0] > maxLength ) + { + /* Make sure the string isn't truncated in the middle of */ + /* a multi-byte character. */ + while (maxLength != 0) + { + // Note: CharacterByteType's textOffset parameter is zero-based from the textPtr parameter + charType = CharacterByteType((Ptr)&source[1], maxLength - 1, smSystemScript); + if ( (charType == smSingleByte) || (charType == smLastByte) ) + break; /* source[maxLength] is now a valid last character */ + --maxLength; + } + } + else + { + maxLength = source[0]; + } + /* Set the destination string length */ + destination[0] = maxLength; + /* and copy maxLength characters (if needed) */ + if ( source != destination ) + { + while ( maxLength != 0 ) + { + destination[maxLength] = source[maxLength]; + --maxLength; + } + } + } +} + +/*****************************************************************************/ + +pascal Ptr GetTempBuffer(long buffReqSize, + long *buffActSize) +{ + enum + { + kSlopMemory = 0x00008000 /* 32K - Amount of free memory to leave when allocating buffers */ + }; + Ptr tempPtr; + + /* Make request a multiple of 1024 bytes */ + buffReqSize = buffReqSize & 0xfffffc00; + + if ( buffReqSize < 0x00000400 ) + { + /* Request was smaller than 1024 bytes - make it 1024 */ + buffReqSize = 0x00000400; + } + + /* Attempt to allocate the memory */ + tempPtr = NewPtr(buffReqSize); + + /* If request failed, go to backup plan */ + if ( (tempPtr == NULL) && (buffReqSize > 0x00000400) ) + { + /* + ** Try to get largest 1024-byte block available + ** leaving some slop for the toolbox if possible + */ + long freeMemory = (FreeMem() - kSlopMemory) & 0xfffffc00; + + buffReqSize = MaxBlock() & 0xfffffc00; + + if ( buffReqSize > freeMemory ) + { + buffReqSize = freeMemory; + } + + if ( buffReqSize == 0 ) + { + buffReqSize = 0x00000400; + } + + tempPtr = NewPtr(buffReqSize); + } + + /* Return bytes allocated */ + if ( tempPtr != NULL ) + { + *buffActSize = buffReqSize; + } + else + { + *buffActSize = 0; + } + + return ( tempPtr ); +} + +/*****************************************************************************/ + +/* +** GetVolumeInfoNoName uses pathname and vRefNum to call PBHGetVInfoSync +** in cases where the returned volume name is not needed by the caller. +** The pathname and vRefNum parameters are not touched, and the pb +** parameter is initialized by PBHGetVInfoSync except that ioNamePtr in +** the parameter block is always returned as NULL (since it might point +** to the local tempPathname). +** +** I noticed using this code in several places, so here it is once. +** This reduces the code size of MoreFiles. +*/ +pascal OSErr GetVolumeInfoNoName(ConstStr255Param pathname, + short vRefNum, + HParmBlkPtr pb) +{ + Str255 tempPathname; + OSErr error; + + /* Make sure pb parameter is not NULL */ + if ( pb != NULL ) + { + pb->volumeParam.ioVRefNum = vRefNum; + if ( pathname == NULL ) + { + pb->volumeParam.ioNamePtr = NULL; + pb->volumeParam.ioVolIndex = 0; /* use ioVRefNum only */ + } + else + { + BlockMoveData(pathname, tempPathname, pathname[0] + 1); /* make a copy of the string and */ + pb->volumeParam.ioNamePtr = (StringPtr)tempPathname; /* use the copy so original isn't trashed */ + pb->volumeParam.ioVolIndex = -1; /* use ioNamePtr/ioVRefNum combination */ + } + error = PBHGetVInfoSync(pb); + pb->volumeParam.ioNamePtr = NULL; /* ioNamePtr may point to local tempPathname, so don't return it */ + } + else + { + error = paramErr; + } + return ( error ); +} + +/*****************************************************************************/ + +/* +** XGetVolumeInfoNoName uses pathname and vRefNum to call PBXGetVolInfoSync +** in cases where the returned volume name is not needed by the caller. +** The pathname and vRefNum parameters are not touched, and the pb +** parameter is initialized by PBXGetVolInfoSync except that ioNamePtr in +** the parameter block is always returned as NULL (since it might point +** to the local tempPathname). +*/ +pascal OSErr XGetVolumeInfoNoName(ConstStr255Param pathname, + short vRefNum, + XVolumeParamPtr pb) +{ + Str255 tempPathname; + OSErr error; + + /* Make sure pb parameter is not NULL */ + if ( pb != NULL ) + { + pb->ioVRefNum = vRefNum; + pb->ioXVersion = 0; /* this XVolumeParam version (0) */ + if ( pathname == NULL ) + { + pb->ioNamePtr = NULL; + pb->ioVolIndex = 0; /* use ioVRefNum only */ + } + else + { + BlockMoveData(pathname, tempPathname, pathname[0] + 1); /* make a copy of the string and */ + pb->ioNamePtr = (StringPtr)tempPathname; /* use the copy so original isn't trashed */ + pb->ioVolIndex = -1; /* use ioNamePtr/ioVRefNum combination */ + } + + { +#if !TARGET_API_MAC_CARBON + long response; + + /* Is PBXGetVolInfo available? */ + if ( ( Gestalt(gestaltFSAttr, &response) != noErr ) || ((response & (1L << gestaltFSSupports2TBVols)) == 0) ) + { + /* No, fall back on PBHGetVInfo */ + error = PBHGetVInfoSync((HParmBlkPtr)pb); + if ( error == noErr ) + { + /* calculate the ioVTotalBytes and ioVFreeBytes fields */ + pb->ioVTotalBytes = U64Multiply(U64SetU(pb->ioVNmAlBlks), U64SetU(pb->ioVAlBlkSiz)); + pb->ioVFreeBytes = U64Multiply(U64SetU(pb->ioVFrBlk), U64SetU(pb->ioVAlBlkSiz)); + } + } + else +#endif + { + /* Yes, so use it */ + error = CallPBXGetVolInfoSync(pb); + } + } + pb->ioNamePtr = NULL; /* ioNamePtr may point to local tempPathname, so don't return it */ + } + else + { + error = paramErr; + } + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr GetCatInfoNoName(short vRefNum, + long dirID, + ConstStr255Param name, + CInfoPBPtr pb) +{ + Str31 tempName; + OSErr error; + + /* Protection against File Sharing problem */ + if ( (name == NULL) || (name[0] == 0) ) + { + tempName[0] = 0; + pb->dirInfo.ioNamePtr = tempName; + pb->dirInfo.ioFDirIndex = -1; /* use ioDirID */ + } + else + { + pb->dirInfo.ioNamePtr = (StringPtr)name; + pb->dirInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ + } + pb->dirInfo.ioVRefNum = vRefNum; + pb->dirInfo.ioDrDirID = dirID; + error = PBGetCatInfoSync(pb); + pb->dirInfo.ioNamePtr = NULL; + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr DetermineVRefNum(ConstStr255Param pathname, + short vRefNum, + short *realVRefNum) +{ + HParamBlockRec pb; + OSErr error; + + error = GetVolumeInfoNoName(pathname,vRefNum, &pb); + if ( error == noErr ) + { + *realVRefNum = pb.volumeParam.ioVRefNum; + } + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr HGetVInfo(short volReference, + StringPtr volName, + short *vRefNum, + unsigned long *freeBytes, + unsigned long *totalBytes) +{ + OSErr result; + UInt64 freeBytes64; + UInt64 totalBytes64; + + // get the best values possible from XGetVInfo + result = XGetVInfo(volReference, volName, vRefNum, &freeBytes64, &totalBytes64); + if ( result == noErr ) + { + // and pin those values if needed + if ( UInt64ToUnsignedWide(freeBytes64).hi != 0 ) + { + // pin to maximum 512-byte block aligned value + *freeBytes = 0xfffffe00; + } + else + { + *freeBytes = U32SetU(freeBytes64); + } + + if ( UInt64ToUnsignedWide(totalBytes64).hi != 0 ) + { + // pin to maximum 512-byte block aligned value + *totalBytes = 0xfffffe00; + } + else + { + *totalBytes = U32SetU(totalBytes64); + } + } + + return ( result ); +} + +/*****************************************************************************/ + +pascal OSErr XGetVInfo(short volReference, + StringPtr volName, + short *vRefNum, + UInt64 *freeBytes, + UInt64 *totalBytes) +{ + OSErr result; + XVolumeParam pb; + +#if !TARGET_API_MAC_CARBON + + long response; + +#endif // !TARGET_API_MAC_CARBON + + pb.ioVRefNum = volReference; + pb.ioNamePtr = volName; + pb.ioXVersion = 0; /* this XVolumeParam version (0) */ + pb.ioVolIndex = 0; /* use ioVRefNum only, return volume name */ + +#if !TARGET_API_MAC_CARBON + + /* See if large volume support is available */ + if ( ( Gestalt(gestaltFSAttr, &response) == noErr ) && ((response & (1L << gestaltFSSupports2TBVols)) != 0) ) + +#endif // !TARGET_API_MAC_CARBON + + { + /* Large volume support is available */ + result = CallPBXGetVolInfoSync(&pb); + if ( result == noErr ) + { + /* The volume name was returned in volName (if not NULL) and */ + /* we have the volume's vRefNum and allocation block size */ + *vRefNum = pb.ioVRefNum; + + /* return the freeBytes and totalBytes */ + *totalBytes = pb.ioVTotalBytes; + *freeBytes = pb.ioVFreeBytes; + } + } + +#if !TARGET_API_MAC_CARBON + + else + { + /* No large volume support */ + /* Use PBHGetVInfoSync to get the results */ + result = PBHGetVInfoSync((HParmBlkPtr)&pb); + if ( result == noErr ) + { + VCB *theVCB; + + /* The volume name was returned in volName (if not NULL) and */ + /* we have the volume's vRefNum */ + *vRefNum = pb.ioVRefNum; + + /* System 7.5 (and beyond) pins the number of allocation blocks and */ + /* the number of free allocation blocks returned by PBHGetVInfo to */ + /* a value so that when multiplied by the allocation block size, */ + /* the volume will look like it has $7fffffff bytes or less. This */ + /* was done so older applications that use signed math or that use */ + /* the GetVInfo function (which uses signed math) will continue to work. */ + /* However, the unpinned numbers (which we want) are always available */ + /* in the volume's VCB so we'll get those values from the VCB. */ + /* Note: Carbon doesn't support the VCB queue, so this code cannot be */ + /* used (and is conditionalized out) by Carbon applications. */ + + /* Find the volume's VCB */ + theVCB = (VCB *)(GetVCBQHdr()->qHead); + while ( theVCB != NULL ) + { + if ( theVCB->vcbVRefNum == *vRefNum ) + { + break; + } + + theVCB = (VCB *)(theVCB->qLink); /* next VCB */ + } + + if ( theVCB != NULL ) + { + /* Found a VCB we can use. Get the un-pinned number of allocation blocks */ + /* and the number of free blocks from the VCB. */ + *freeBytes = U64Multiply(U64SetU((unsigned short)theVCB->vcbFreeBks), U64SetU((unsigned long)pb.ioVAlBlkSiz)); + *totalBytes = U64Multiply(U64SetU((unsigned short)theVCB->vcbNmAlBlks), U64SetU((unsigned long)pb.ioVAlBlkSiz)); + } + else + { + /* Didn't find a VCB we can use. Return the number of allocation blocks */ + /* and the number of free blocks returned by PBHGetVInfoSync. */ + *freeBytes = U64Multiply(U64SetU((unsigned short)pb.ioVFrBlk), U64SetU((unsigned long)pb.ioVAlBlkSiz)); + *totalBytes = U64Multiply(U64SetU((unsigned short)pb.ioVNmAlBlks), U64SetU((unsigned long)pb.ioVAlBlkSiz)); + } + + } + } + +#endif // !TARGET_API_MAC_CARBON + + return ( result ); +} + +/*****************************************************************************/ + +pascal OSErr CheckVolLock(ConstStr255Param pathname, + short vRefNum) +{ + HParamBlockRec pb; + OSErr error; + + error = GetVolumeInfoNoName(pathname,vRefNum, &pb); + if ( error == noErr ) + { + if ( (pb.volumeParam.ioVAtrb & kHFSVolumeHardwareLockMask) != 0 ) + { + error = wPrErr; /* volume locked by hardware */ + } + else if ( (pb.volumeParam.ioVAtrb & kHFSVolumeSoftwareLockMask) != 0 ) + { + error = vLckdErr; /* volume locked by software */ + } + } + + return ( error ); +} + +/*****************************************************************************/ +// +// The following routines call Mac OS routines that are not supported by +// Carbon: +// +// GetDriverName +// FindDrive +// GetDiskBlocks +// GetVolState + +#if !TARGET_API_MAC_CARBON // { + + /*****************************************************************************/ + + pascal OSErr GetDriverName(short driverRefNum, + Str255 driverName) + { + OSErr result; + DCtlHandle theDctl; + DRVRHeaderPtr dHeaderPtr; + + theDctl = GetDCtlEntry(driverRefNum); + if ( theDctl != NULL ) + { + if ( (**theDctl).dCtlFlags & dRAMBasedMask ) + { + /* dctlDriver is handle - dereference */ + dHeaderPtr = *((DRVRHeaderHandle)(**theDctl).dCtlDriver); + } + else + { + /* dctlDriver is pointer */ + dHeaderPtr = (DRVRHeaderPtr)(**theDctl).dCtlDriver; + } + BlockMoveData((*dHeaderPtr).drvrName, driverName, (*dHeaderPtr).drvrName[0] + 1); + result = noErr; + } + else + { + driverName[0] = 0; + result = badUnitErr; /* bad reference number */ + } + + return ( result ); + } + + /*****************************************************************************/ + + pascal OSErr FindDrive(ConstStr255Param pathname, + short vRefNum, + DrvQElPtr *driveQElementPtr) + { + OSErr result; + HParamBlockRec hPB; + short driveNumber; + + *driveQElementPtr = NULL; + + /* First, use GetVolumeInfoNoName to determine the volume */ + result = GetVolumeInfoNoName(pathname, vRefNum, &hPB); + if ( result == noErr ) + { + /* + ** The volume can be either online, offline, or ejected. What we find in + ** ioVDrvInfo and ioVDRefNum will tell us which it is. + ** See Inside Macintosh: Files page 2-80 and the Technical Note + ** "FL 34 - VCBs and Drive Numbers : The Real Story" + ** Where we get the drive number depends on the state of the volume. + */ + if ( hPB.volumeParam.ioVDrvInfo != 0 ) + { + /* The volume is online and not ejected */ + /* Get the drive number */ + driveNumber = hPB.volumeParam.ioVDrvInfo; + } + else + { + /* The volume's is either offline or ejected */ + /* in either case, the volume is NOT online */ + + /* Is it ejected or just offline? */ + if ( hPB.volumeParam.ioVDRefNum > 0 ) + { + /* It's ejected, the drive number is ioVDRefNum */ + driveNumber = hPB.volumeParam.ioVDRefNum; + } + else + { + /* It's offline, the drive number is the negative of ioVDRefNum */ + driveNumber = (short)-hPB.volumeParam.ioVDRefNum; + } + } + + /* Get pointer to first element in drive queue */ + *driveQElementPtr = (DrvQElPtr)(GetDrvQHdr()->qHead); + + /* Search for a matching drive number */ + while ( (*driveQElementPtr != NULL) && ((*driveQElementPtr)->dQDrive != driveNumber) ) + { + *driveQElementPtr = (DrvQElPtr)(*driveQElementPtr)->qLink; + } + + if ( *driveQElementPtr == NULL ) + { + /* This should never happen since every volume must have a drive, but... */ + result = nsDrvErr; + } + } + + return ( result ); + } + + /*****************************************************************************/ + + pascal OSErr GetDiskBlocks(ConstStr255Param pathname, + short vRefNum, + unsigned long *numBlocks) + { + /* Various constants for GetDiskBlocks() */ + enum + { + /* return format list status code */ + kFmtLstCode = 6, + + /* reference number of .SONY driver */ + kSonyRefNum = 0xfffb, + + /* values returned by DriveStatus in DrvSts.twoSideFmt */ + kSingleSided = 0, + kDoubleSided = -1, + kSingleSidedSize = 800, /* 400K */ + kDoubleSidedSize = 1600, /* 800K */ + + /* values in DrvQEl.qType */ + kWordDrvSiz = 0, + kLongDrvSiz = 1, + + /* more than enough formatListRecords */ + kMaxFormatListRecs = 16 + }; + + DrvQElPtr driveQElementPtr; + unsigned long blocks; + ParamBlockRec pb; + FormatListRec formatListRecords[kMaxFormatListRecs]; + DrvSts status; + short formatListRecIndex; + OSErr result; + + blocks = 0; + + /* Find the drive queue element for this volume */ + result = FindDrive(pathname, vRefNum, &driveQElementPtr); + + /* + ** Make sure this is a real driver (dQRefNum < 0). + ** AOCE's Mail Enclosures volume uses 0 for dQRefNum which will cause + ** problems if you try to use it as a driver refNum. + */ + if ( (result == noErr) && (driveQElementPtr->dQRefNum >= 0) ) + { + result = paramErr; + } + else + { + /* Attempt to get the drive's format list. */ + /* (see the Technical Note "What Your Sony Drives For You") */ + + pb.cntrlParam.ioVRefNum = driveQElementPtr->dQDrive; + pb.cntrlParam.ioCRefNum = driveQElementPtr->dQRefNum; + pb.cntrlParam.csCode = kFmtLstCode; + pb.cntrlParam.csParam[0] = kMaxFormatListRecs; + *(long *)&pb.cntrlParam.csParam[1] = (long)&formatListRecords[0]; + + result = PBStatusSync(&pb); + + if ( result == noErr ) + { + /* The drive supports ReturnFormatList status call. */ + + /* Get the current disk's size. */ + for( formatListRecIndex = 0; + formatListRecIndex < pb.cntrlParam.csParam[0]; + ++formatListRecIndex ) + { + if ( (formatListRecords[formatListRecIndex].formatFlags & + diCIFmtFlagsCurrentMask) != 0 ) + { + blocks = formatListRecords[formatListRecIndex].volSize; + } + } + if ( blocks == 0 ) + { + /* This should never happen */ + result = paramErr; + } + } + else if ( driveQElementPtr->dQRefNum == (short)kSonyRefNum ) + { + /* The drive is a non-SuperDrive floppy which only supports 400K and 800K disks */ + + result = DriveStatus(driveQElementPtr->dQDrive, &status); + if ( result == noErr ) + { + switch ( status.twoSideFmt ) + { + case kSingleSided: + blocks = kSingleSidedSize; + break; + case kDoubleSided: + blocks = kDoubleSidedSize; + break; + default: + /* This should never happen */ + result = paramErr; + break; + } + } + } + else + { + /* The drive is not a floppy and it doesn't support ReturnFormatList */ + /* so use the dQDrvSz field(s) */ + + result = noErr; /* reset result */ + switch ( driveQElementPtr->qType ) + { + case kWordDrvSiz: + blocks = driveQElementPtr->dQDrvSz; + break; + case kLongDrvSiz: + blocks = ((unsigned long)driveQElementPtr->dQDrvSz2 << 16) + + driveQElementPtr->dQDrvSz; + break; + default: + /* This should never happen */ + result = paramErr; + break; + } + } + } + + if ( result == noErr ) + { + *numBlocks = blocks; + } + + return ( result ); + } + + /*****************************************************************************/ + + pascal OSErr GetVolState(ConstStr255Param pathname, + short vRefNum, + Boolean *volumeOnline, + Boolean *volumeEjected, + Boolean *driveEjectable, + Boolean *driverWantsEject) + { + HParamBlockRec pb; + short driveNumber; + OSErr error; + + error = GetVolumeInfoNoName(pathname,vRefNum, &pb); + if ( error == noErr ) + { + if ( pb.volumeParam.ioVDrvInfo != 0 ) + { + /* the volume is online and not ejected */ + *volumeOnline = true; + *volumeEjected = false; + + /* Get the drive number */ + driveNumber = pb.volumeParam.ioVDrvInfo; + } + else + { + /* the volume's is either offline or ejected */ + /* in either case, the volume is NOT online */ + *volumeOnline = false; + + /* Is it ejected? */ + *volumeEjected = pb.volumeParam.ioVDRefNum > 0; + + if ( *volumeEjected ) + { + /* If ejected, the drive number is ioVDRefNum */ + driveNumber = pb.volumeParam.ioVDRefNum; + } + else + { + /* If offline, the drive number is the negative of ioVDRefNum */ + driveNumber = (short)-pb.volumeParam.ioVDRefNum; + } + } + + { + DrvQElPtr drvQElem; + + /* Find the drive queue element by searching the drive queue */ + drvQElem = (DrvQElPtr)(GetDrvQHdr()->qHead); + while ( (drvQElem != NULL) && (drvQElem->dQDrive != driveNumber) ) + { + drvQElem = (DrvQElPtr)drvQElem->qLink; + } + + if ( drvQElem != NULL ) + { + /* + ** Each drive queue element is preceded by 4 flag bytes. + ** Byte 1 (the second flag byte) has bits that tell us if a + ** drive is ejectable and if its driver wants an eject call. + ** See Inside Macintosh: Files, page 2-85. + */ + { + Ptr flagBytePtr; + + /* point to byte 1 of the flag bytes */ + flagBytePtr = (Ptr)drvQElem; + flagBytePtr -= 3; + + /* + ** The drive is ejectable if flag byte 1 does not contain + ** 0x08 (nonejectable) or 0x48 (nonejectable, but wants eject call). + */ + + *driveEjectable = (*flagBytePtr != 0x08) && (*flagBytePtr != 0x48); + + /* + ** The driver wants an eject call if flag byte 1 does not contain + ** 0x08 (nonejectable). This may seem like a minor point, but some + ** disk drivers use the Eject request to flush their caches to disk + ** and you wouldn't want to skip that step after unmounting a volume. + */ + + *driverWantsEject = (*flagBytePtr != 0x08); + } + } + else + { + /* Didn't find the drive (this should never happen) */ + *driveEjectable = false; + *driverWantsEject = false; + } + } + } + + return ( error ); + } + + /*****************************************************************************/ + +#endif // } !TARGET_API_MAC_CARBON + +/*****************************************************************************/ + +pascal OSErr GetVolFileSystemID(ConstStr255Param pathname, + short vRefNum, + short *fileSystemID) +{ + HParamBlockRec pb; + OSErr error; + + error = GetVolumeInfoNoName(pathname,vRefNum, &pb); + if ( error == noErr ) + { + *fileSystemID = pb.volumeParam.ioVFSID; + } + + return ( error ); +} + +/*****************************************************************************/ + +// +// Note: Under Carbon there are no drive numbers, so you cannot call +// Eject with a drive number after unmounting a volume. +// When a Carbon application calls UnmountVol, CarbonLib will make +// sure ejectable media is ejected (leaving ejectable media in the +// disk drive makes no sense to Carbon applications). +// +pascal OSErr UnmountAndEject(ConstStr255Param pathname, + short vRefNum) +{ + HParamBlockRec pb; + OSErr error; + + error = GetVolumeInfoNoName(pathname, vRefNum, &pb); + if ( error == noErr ) + { + +#if !TARGET_API_MAC_CARBON + + short driveNum; + Boolean ejected, wantsEject; + DrvQElPtr drvQElem; + + if ( pb.volumeParam.ioVDrvInfo != 0 ) + { + /* the volume is online and not ejected */ + ejected = false; + + /* Get the drive number */ + driveNum = pb.volumeParam.ioVDrvInfo; + } + else + { + /* the volume is ejected or offline */ + + /* Is it ejected? */ + ejected = pb.volumeParam.ioVDRefNum > 0; + + if ( ejected ) + { + /* If ejected, the drive number is ioVDRefNum */ + driveNum = pb.volumeParam.ioVDRefNum; + } + else + { + /* If offline, the drive number is the negative of ioVDRefNum */ + driveNum = (short)-pb.volumeParam.ioVDRefNum; + } + } + + /* find the drive queue element */ + drvQElem = (DrvQElPtr)(GetDrvQHdr()->qHead); + while ( (drvQElem != NULL) && (drvQElem->dQDrive != driveNum) ) + { + drvQElem = (DrvQElPtr)drvQElem->qLink; + } + + if ( drvQElem != NULL ) + { + /* does the drive want an eject call */ + wantsEject = (*((Ptr)((Ptr)drvQElem - 3)) != 8); + } + else + { + /* didn't find the drive!! */ + wantsEject = false; + } + +#endif // !TARGET_API_MAC_CARBON + + /* unmount the volume */ + pb.volumeParam.ioNamePtr = NULL; + /* ioVRefNum is already filled in from PBHGetVInfo */ + error = PBUnmountVol((ParmBlkPtr)&pb); + +#if !TARGET_API_MAC_CARBON + + if ( error == noErr ) + { + if ( wantsEject && !ejected ) + { + /* eject the media from the drive if needed */ + pb.volumeParam.ioVRefNum = driveNum; + error = PBEject((ParmBlkPtr)&pb); + } + } + +#endif // !TARGET_API_MAC_CARBON + + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr OnLine(FSSpecPtr volumes, + short reqVolCount, + short *actVolCount, + short *volIndex) +{ + HParamBlockRec pb; + OSErr error = noErr; + FSSpec *endVolArray; + + if ( *volIndex > 0 ) + { + *actVolCount = 0; + for ( endVolArray = volumes + reqVolCount; (volumes < endVolArray) && (error == noErr); ++volumes ) + { + pb.volumeParam.ioNamePtr = (StringPtr) & volumes->name; + pb.volumeParam.ioVolIndex = *volIndex; + error = PBHGetVInfoSync(&pb); + if ( error == noErr ) + { + volumes->parID = fsRtParID; /* the root directory's parent is 1 */ + volumes->vRefNum = pb.volumeParam.ioVRefNum; + ++*volIndex; + ++*actVolCount; + } + } + } + else + { + error = paramErr; + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr SetDefault(short newVRefNum, + long newDirID, + short *oldVRefNum, + long *oldDirID) +{ + OSErr error; + + /* Get the current default volume/directory. */ + error = HGetVol(NULL, oldVRefNum, oldDirID); + if ( error == noErr ) + { + /* Set the new default volume/directory */ + error = HSetVol(NULL, newVRefNum, newDirID); + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr RestoreDefault(short oldVRefNum, + long oldDirID) +{ + OSErr error; + +#if !TARGET_API_MAC_CARBON + + short defaultVRefNum; + long defaultDirID; + long defaultProcID; + + /* Determine if the default volume was a wdRefNum. */ + error = GetWDInfo(oldVRefNum, &defaultVRefNum, &defaultDirID, &defaultProcID); + if ( error == noErr ) + { + /* Restore the old default volume/directory, one way or the other. */ + if ( defaultDirID != fsRtDirID ) + { + /* oldVRefNum was a wdRefNum - use SetVol */ + error = SetVol(NULL, oldVRefNum); + } + else + { + +#endif // !TARGET_API_MAC_CARBON + + /* oldVRefNum was a real vRefNum - use HSetVol */ + error = HSetVol(NULL, oldVRefNum, oldDirID); + +#if !TARGET_API_MAC_CARBON + + } + } +#endif // !TARGET_API_MAC_CARBON + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr GetDInfo(short vRefNum, + long dirID, + ConstStr255Param name, + DInfo *fndrInfo) +{ + CInfoPBRec pb; + OSErr error; + + error = GetCatInfoNoName(vRefNum, dirID, name, &pb); + if ( error == noErr ) + { + if ( (pb.dirInfo.ioFlAttrib & kioFlAttribDirMask) != 0 ) + { + /* it's a directory, return the DInfo */ + *fndrInfo = pb.dirInfo.ioDrUsrWds; + } + else + { + /* oops, a file was passed */ + error = dirNFErr; + } + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr FSpGetDInfo(const FSSpec *spec, + DInfo *fndrInfo) +{ + return ( GetDInfo(spec->vRefNum, spec->parID, spec->name, fndrInfo) ); +} + +/*****************************************************************************/ + +pascal OSErr SetDInfo(short vRefNum, + long dirID, + ConstStr255Param name, + const DInfo *fndrInfo) +{ + CInfoPBRec pb; + Str31 tempName; + OSErr error; + + /* Protection against File Sharing problem */ + if ( (name == NULL) || (name[0] == 0) ) + { + tempName[0] = 0; + pb.dirInfo.ioNamePtr = tempName; + pb.dirInfo.ioFDirIndex = -1; /* use ioDirID */ + } + else + { + pb.dirInfo.ioNamePtr = (StringPtr)name; + pb.dirInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ + } + pb.dirInfo.ioVRefNum = vRefNum; + pb.dirInfo.ioDrDirID = dirID; + error = PBGetCatInfoSync(&pb); + if ( error == noErr ) + { + if ( (pb.dirInfo.ioFlAttrib & kioFlAttribDirMask) != 0 ) + { + /* it's a directory, set the DInfo */ + if ( pb.dirInfo.ioNamePtr == tempName ) + { + pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID; + } + else + { + pb.dirInfo.ioDrDirID = dirID; + } + pb.dirInfo.ioDrUsrWds = *fndrInfo; + error = PBSetCatInfoSync(&pb); + } + else + { + /* oops, a file was passed */ + error = dirNFErr; + } + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr FSpSetDInfo(const FSSpec *spec, + const DInfo *fndrInfo) +{ + return ( SetDInfo(spec->vRefNum, spec->parID, spec->name, fndrInfo) ); +} + +/*****************************************************************************/ + +pascal OSErr GetDirectoryID(short vRefNum, + long dirID, + ConstStr255Param name, + long *theDirID, + Boolean *isDirectory) +{ + CInfoPBRec pb; + OSErr error; + + error = GetCatInfoNoName(vRefNum, dirID, name, &pb); + if ( error == noErr ) + { + *isDirectory = (pb.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0; + if ( *isDirectory ) + { + *theDirID = pb.dirInfo.ioDrDirID; + } + else + { + *theDirID = pb.hFileInfo.ioFlParID; + } + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr FSpGetDirectoryID(const FSSpec *spec, + long *theDirID, + Boolean *isDirectory) +{ + return ( GetDirectoryID(spec->vRefNum, spec->parID, spec->name, + theDirID, isDirectory) ); +} + +/*****************************************************************************/ + +pascal OSErr GetDirName(short vRefNum, + long dirID, + Str31 name) +{ + CInfoPBRec pb; + OSErr error; + + if ( name != NULL ) + { + pb.dirInfo.ioNamePtr = name; + pb.dirInfo.ioVRefNum = vRefNum; + pb.dirInfo.ioDrDirID = dirID; + pb.dirInfo.ioFDirIndex = -1; /* get information about ioDirID */ + error = PBGetCatInfoSync(&pb); + } + else + { + error = paramErr; + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr GetIOACUser(short vRefNum, + long dirID, + ConstStr255Param name, + SInt8 *ioACUser) +{ + CInfoPBRec pb; + OSErr error; + + /* Clear ioACUser before calling PBGetCatInfo since some file systems + ** don't bother to set or clear this field. If ioACUser isn't set by the + ** file system, then you'll get the zero value back (full access) which + ** is the access you have on volumes that don't support ioACUser. + */ + pb.dirInfo.ioACUser = 0; /* ioACUser used to be filler2 */ + error = GetCatInfoNoName(vRefNum, dirID, name, &pb); + if ( error == noErr ) + { + if ( (pb.hFileInfo.ioFlAttrib & kioFlAttribDirMask) == 0 ) + { + /* oops, a file was passed */ + error = dirNFErr; + } + else + { + *ioACUser = pb.dirInfo.ioACUser; + } + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr FSpGetIOACUser(const FSSpec *spec, + SInt8 *ioACUser) +{ + return ( GetIOACUser(spec->vRefNum, spec->parID, spec->name, ioACUser) ); +} + +/*****************************************************************************/ + +pascal OSErr GetParentID(short vRefNum, + long dirID, + ConstStr255Param name, + long *parID) +{ + CInfoPBRec pb; + Str31 tempName; + OSErr error; + short realVRefNum; + + /* Protection against File Sharing problem */ + if ( (name == NULL) || (name[0] == 0) ) + { + tempName[0] = 0; + pb.hFileInfo.ioNamePtr = tempName; + pb.hFileInfo.ioFDirIndex = -1; /* use ioDirID */ + } + else + { + pb.hFileInfo.ioNamePtr = (StringPtr)name; + pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ + } + pb.hFileInfo.ioVRefNum = vRefNum; + pb.hFileInfo.ioDirID = dirID; + error = PBGetCatInfoSync(&pb); + if ( error == noErr ) + { + /* + ** There's a bug in HFS where the wrong parent dir ID can be + ** returned if multiple separators are used at the end of a + ** pathname. For example, if the pathname: + ** 'volumeName:System Folder:Extensions::' + ** is passed, the directory ID of the Extensions folder is + ** returned in the ioFlParID field instead of fsRtDirID. Since + ** multiple separators at the end of a pathname always specifies + ** a directory, we only need to work-around cases where the + ** object is a directory and there are multiple separators at + ** the end of the name parameter. + */ + if ( (pb.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 ) + { + /* Its a directory */ + + /* is there a pathname? */ + if ( pb.hFileInfo.ioNamePtr == name ) + { + /* could it contain multiple separators? */ + if ( name[0] >= 2 ) + { + /* does it contain multiple separators at the end? */ + if ( (name[name[0]] == ':') && (name[name[0] - 1] == ':') ) + { + /* OK, then do the extra stuff to get the correct parID */ + + /* Get the real vRefNum (this should not fail) */ + error = DetermineVRefNum(name, vRefNum, &realVRefNum); + if ( error == noErr ) + { + /* we don't need the parent's name, but add protect against File Sharing problem */ + tempName[0] = 0; + pb.dirInfo.ioNamePtr = tempName; + pb.dirInfo.ioVRefNum = realVRefNum; + /* pb.dirInfo.ioDrDirID already contains the */ + /* dirID of the directory object */ + pb.dirInfo.ioFDirIndex = -1; /* get information about ioDirID */ + error = PBGetCatInfoSync(&pb); + /* now, pb.dirInfo.ioDrParID contains the correct parID */ + } + } + } + } + } + + if ( error == noErr ) + { + /* if no errors, then pb.hFileInfo.ioFlParID (pb.dirInfo.ioDrParID) */ + /* contains the parent ID */ + *parID = pb.hFileInfo.ioFlParID; + } + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr GetFilenameFromPathname(ConstStr255Param pathname, + Str255 filename) +{ + short index; + short nameEnd; + OSErr error; + + /* default to no filename */ + filename[0] = 0; + + /* check for no pathname */ + if ( pathname != NULL ) + { + /* get string length */ + index = pathname[0]; + + /* check for empty string */ + if ( index != 0 ) + { + /* skip over last trailing colon (if any) */ + if ( pathname[index] == ':' ) + { + --index; + } + + /* save the end of the string */ + nameEnd = index; + + /* if pathname ends with multiple colons, then this pathname refers */ + /* to a directory, not a file */ + if ( pathname[index] != ':' ) + { + /* parse backwards until we find a colon or hit the beginning of the pathname */ + while ( (index != 0) && (pathname[index] != ':') ) + { + --index; + } + + /* if we parsed to the beginning of the pathname and the pathname ended */ + /* with a colon, then pathname is a full pathname to a volume, not a file */ + if ( (index != 0) || (pathname[pathname[0]] != ':') ) + { + /* get the filename and return noErr */ + filename[0] = (char)(nameEnd - index); + BlockMoveData(&pathname[index+1], &filename[1], nameEnd - index); + error = noErr; + } + else + { + /* pathname to a volume, not a file */ + error = notAFileErr; + } + } + else + { + /* directory, not a file */ + error = notAFileErr; + } + } + else + { + /* empty string isn't a file */ + error = notAFileErr; + } + } + else + { + /* NULL pathname isn't a file */ + error = notAFileErr; + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr GetObjectLocation(short vRefNum, + long dirID, + ConstStr255Param pathname, + short *realVRefNum, + long *realParID, + Str255 realName, + Boolean *isDirectory) +{ + OSErr error; + CInfoPBRec pb; + Str255 tempPathname; + + /* clear results */ + *realVRefNum = 0; + *realParID = 0; + realName[0] = 0; + + /* + ** Get the real vRefNum + */ + error = DetermineVRefNum(pathname, vRefNum, realVRefNum); + if ( error == noErr ) + { + /* + ** Determine if the object already exists and if so, + ** get the real parent directory ID if it's a file + */ + + /* Protection against File Sharing problem */ + if ( (pathname == NULL) || (pathname[0] == 0) ) + { + tempPathname[0] = 0; + pb.hFileInfo.ioNamePtr = tempPathname; + pb.hFileInfo.ioFDirIndex = -1; /* use ioDirID */ + } + else + { + pb.hFileInfo.ioNamePtr = (StringPtr)pathname; + pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ + } + pb.hFileInfo.ioVRefNum = vRefNum; + pb.hFileInfo.ioDirID = dirID; + error = PBGetCatInfoSync(&pb); + if ( error == noErr ) + { + /* + ** The file system object is present and we have the file's real parID + */ + + /* Is it a directory or a file? */ + *isDirectory = (pb.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0; + if ( *isDirectory ) + { + /* + ** It's a directory, get its name and parent dirID, and then we're done + */ + + pb.dirInfo.ioNamePtr = realName; + pb.dirInfo.ioVRefNum = *realVRefNum; + /* pb.dirInfo.ioDrDirID already contains the dirID of the directory object */ + pb.dirInfo.ioFDirIndex = -1; /* get information about ioDirID */ + error = PBGetCatInfoSync(&pb); + + /* get the parent ID here, because the file system can return the */ + /* wrong parent ID from the last call. */ + *realParID = pb.dirInfo.ioDrParID; + } + else + { + /* + ** It's a file - use the parent directory ID from the last call + ** to GetCatInfoparse, get the file name, and then we're done + */ + *realParID = pb.hFileInfo.ioFlParID; + error = GetFilenameFromPathname(pathname, realName); + } + } + else if ( error == fnfErr ) + { + /* + ** The file system object is not present - see if its parent is present + */ + + /* + ** Parse to get the object name from end of pathname + */ + error = GetFilenameFromPathname(pathname, realName); + + /* if we can't get the object name from the end, we can't continue */ + if ( error == noErr ) + { + /* + ** What we want now is the pathname minus the object name + ** for example: + ** if pathname is 'vol:dir:file' tempPathname becomes 'vol:dir:' + ** if pathname is 'vol:dir:file:' tempPathname becomes 'vol:dir:' + ** if pathname is ':dir:file' tempPathname becomes ':dir:' + ** if pathname is ':dir:file:' tempPathname becomes ':dir:' + ** if pathname is ':file' tempPathname becomes ':' + ** if pathname is 'file or file:' tempPathname becomes '' + */ + + /* get a copy of the pathname */ + BlockMoveData(pathname, tempPathname, pathname[0] + 1); + + /* remove the object name */ + tempPathname[0] -= realName[0]; + /* and the trailing colon (if any) */ + if ( pathname[pathname[0]] == ':' ) + { + --tempPathname[0]; + } + + /* OK, now get the parent's directory ID */ + + /* Protection against File Sharing problem */ + pb.hFileInfo.ioNamePtr = (StringPtr)tempPathname; + if ( tempPathname[0] != 0 ) + { + pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ + } + else + { + pb.hFileInfo.ioFDirIndex = -1; /* use ioDirID */ + } + pb.hFileInfo.ioVRefNum = vRefNum; + pb.hFileInfo.ioDirID = dirID; + error = PBGetCatInfoSync(&pb); + *realParID = pb.dirInfo.ioDrDirID; + + *isDirectory = false; /* we don't know what the object is really going to be */ + } + + if ( error != noErr ) + { + error = dirNFErr; /* couldn't find parent directory */ + } + else + { + error = fnfErr; /* we found the parent, but not the file */ + } + } + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr GetDirItems(short vRefNum, + long dirID, + ConstStr255Param name, + Boolean getFiles, + Boolean getDirectories, + FSSpecPtr items, + short reqItemCount, + short *actItemCount, + short *itemIndex) /* start with 1, then use what's returned */ +{ + CInfoPBRec pb; + OSErr error; + long theDirID; + Boolean isDirectory; + FSSpec *endItemsArray; + + if ( *itemIndex > 0 ) + { + /* NOTE: If I could be sure that the caller passed a real vRefNum and real directory */ + /* to this routine, I could rip out calls to DetermineVRefNum and GetDirectoryID and this */ + /* routine would be much faster because of the overhead of DetermineVRefNum and */ + /* GetDirectoryID and because GetDirectoryID blows away the directory index hint the Macintosh */ + /* file system keeps for indexed calls. I can't be sure, so for maximum throughput, */ + /* pass a big array of FSSpecs so you can get the directory's contents with few calls */ + /* to this routine. */ + + /* get the real volume reference number */ + error = DetermineVRefNum(name, vRefNum, &pb.hFileInfo.ioVRefNum); + if ( error == noErr ) + { + /* and the real directory ID of this directory (and make sure it IS a directory) */ + error = GetDirectoryID(vRefNum, dirID, name, &theDirID, &isDirectory); + if ( error == noErr ) + { + if ( isDirectory ) + { + *actItemCount = 0; + endItemsArray = items + reqItemCount; + while ( (items < endItemsArray) && (error == noErr) ) + { + pb.hFileInfo.ioNamePtr = (StringPtr) &items->name; + pb.hFileInfo.ioDirID = theDirID; + pb.hFileInfo.ioFDirIndex = *itemIndex; + error = PBGetCatInfoSync(&pb); + if ( error == noErr ) + { + items->parID = pb.hFileInfo.ioFlParID; /* return item's parID */ + items->vRefNum = pb.hFileInfo.ioVRefNum; /* return item's vRefNum */ + ++*itemIndex; /* prepare to get next item in directory */ + + if ( (pb.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 ) + { + if ( getDirectories ) + { + ++*actItemCount; /* keep this item */ + ++items; /* point to next item */ + } + } + else + { + if ( getFiles ) + { + ++*actItemCount; /* keep this item */ + ++items; /* point to next item */ + } + } + } + } + } + else + { + /* it wasn't a directory */ + error = dirNFErr; + } + } + } + } + else + { + /* bad itemIndex */ + error = paramErr; + } + + return ( error ); +} + +/*****************************************************************************/ + +static void DeleteLevel(long dirToDelete, + DeleteEnumGlobalsPtr theGlobals) +{ + long savedDir; + + do + { + /* prepare to delete directory */ + theGlobals->myPB.ciPB.dirInfo.ioNamePtr = (StringPtr)&theGlobals->itemName; + theGlobals->myPB.ciPB.dirInfo.ioFDirIndex = 1; /* get first item */ + theGlobals->myPB.ciPB.dirInfo.ioDrDirID = dirToDelete; /* in this directory */ + theGlobals->error = PBGetCatInfoSync(&(theGlobals->myPB.ciPB)); + if ( theGlobals->error == noErr ) + { + savedDir = dirToDelete; + /* We have an item. Is it a file or directory? */ + if ( (theGlobals->myPB.ciPB.dirInfo.ioFlAttrib & kioFlAttribDirMask) != 0 ) + { + /* it's a directory */ + savedDir = theGlobals->myPB.ciPB.dirInfo.ioDrDirID; /* save dirID of directory instead */ + DeleteLevel(theGlobals->myPB.ciPB.dirInfo.ioDrDirID, theGlobals); /* Delete its contents */ + theGlobals->myPB.ciPB.dirInfo.ioNamePtr = NULL; /* prepare to delete directory */ + } + if ( theGlobals->error == noErr ) + { + theGlobals->myPB.ciPB.dirInfo.ioDrDirID = savedDir; /* restore dirID */ + theGlobals->myPB.hPB.fileParam.ioFVersNum = 0; /* just in case it's used on an MFS volume... */ + theGlobals->error = PBHDeleteSync(&(theGlobals->myPB.hPB)); /* delete this item */ + if ( theGlobals->error == fLckdErr ) + { + (void) PBHRstFLockSync(&(theGlobals->myPB.hPB)); /* unlock it */ + theGlobals->error = PBHDeleteSync(&(theGlobals->myPB.hPB)); /* and try again */ + } + } + } + } while ( theGlobals->error == noErr ); + + if ( theGlobals->error == fnfErr ) + { + theGlobals->error = noErr; + } +} + +/*****************************************************************************/ + +pascal OSErr DeleteDirectoryContents(short vRefNum, + long dirID, + ConstStr255Param name) +{ + DeleteEnumGlobals theGlobals; + Boolean isDirectory; + OSErr error; + + /* Get the real dirID and make sure it is a directory. */ + error = GetDirectoryID(vRefNum, dirID, name, &dirID, &isDirectory); + if ( error == noErr ) + { + if ( isDirectory ) + { + /* Get the real vRefNum */ + error = DetermineVRefNum(name, vRefNum, &vRefNum); + if ( error == noErr ) + { + /* Set up the globals we need to access from the recursive routine. */ + theGlobals.myPB.ciPB.dirInfo.ioVRefNum = vRefNum; + + /* Here we go into recursion land... */ + DeleteLevel(dirID, &theGlobals); + error = theGlobals.error; + } + } + else + { + error = dirNFErr; + } + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr DeleteDirectory(short vRefNum, + long dirID, + ConstStr255Param name) +{ + OSErr error; + + /* Make sure a directory was specified and then delete its contents */ + error = DeleteDirectoryContents(vRefNum, dirID, name); + if ( error == noErr ) + { + error = HDelete(vRefNum, dirID, name); + if ( error == fLckdErr ) + { + (void) HRstFLock(vRefNum, dirID, name); /* unlock the directory locked by AppleShare */ + error = HDelete(vRefNum, dirID, name); /* and try again */ + } + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr CheckObjectLock(short vRefNum, + long dirID, + ConstStr255Param name) +{ + CInfoPBRec pb; + OSErr error; + + error = GetCatInfoNoName(vRefNum, dirID, name, &pb); + if ( error == noErr ) + { + /* check locked bit */ + if ( (pb.hFileInfo.ioFlAttrib & kioFlAttribLockedMask) != 0 ) + { + error = fLckdErr; + } + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr FSpCheckObjectLock(const FSSpec *spec) +{ + return ( CheckObjectLock(spec->vRefNum, spec->parID, spec->name) ); +} + +/*****************************************************************************/ + +pascal OSErr GetFileSize(short vRefNum, + long dirID, + ConstStr255Param fileName, + long *dataSize, + long *rsrcSize) +{ + HParamBlockRec pb; + OSErr error; + + pb.fileParam.ioNamePtr = (StringPtr)fileName; + pb.fileParam.ioVRefNum = vRefNum; + pb.fileParam.ioFVersNum = 0; + pb.fileParam.ioDirID = dirID; + pb.fileParam.ioFDirIndex = 0; + error = PBHGetFInfoSync(&pb); + if ( error == noErr ) + { + *dataSize = pb.fileParam.ioFlLgLen; + *rsrcSize = pb.fileParam.ioFlRLgLen; + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr FSpGetFileSize(const FSSpec *spec, + long *dataSize, + long *rsrcSize) +{ + return ( GetFileSize(spec->vRefNum, spec->parID, spec->name, dataSize, rsrcSize) ); +} + +/*****************************************************************************/ + +pascal OSErr BumpDate(short vRefNum, + long dirID, + ConstStr255Param name) +/* Given a file or directory, change its modification date to the current date/time. */ +{ + CInfoPBRec pb; + Str31 tempName; + OSErr error; + unsigned long secs; + + /* Protection against File Sharing problem */ + if ( (name == NULL) || (name[0] == 0) ) + { + tempName[0] = 0; + pb.hFileInfo.ioNamePtr = tempName; + pb.hFileInfo.ioFDirIndex = -1; /* use ioDirID */ + } + else + { + pb.hFileInfo.ioNamePtr = (StringPtr)name; + pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ + } + pb.hFileInfo.ioVRefNum = vRefNum; + pb.hFileInfo.ioDirID = dirID; + error = PBGetCatInfoSync(&pb); + if ( error == noErr ) + { + GetDateTime(&secs); + /* set mod date to current date, or one second into the future + if mod date = current date */ + pb.hFileInfo.ioFlMdDat = (secs == pb.hFileInfo.ioFlMdDat) ? (++secs) : (secs); + if ( pb.dirInfo.ioNamePtr == tempName ) + { + pb.hFileInfo.ioDirID = pb.hFileInfo.ioFlParID; + } + else + { + pb.hFileInfo.ioDirID = dirID; + } + error = PBSetCatInfoSync(&pb); + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr FSpBumpDate(const FSSpec *spec) +{ + return ( BumpDate(spec->vRefNum, spec->parID, spec->name) ); +} + +/*****************************************************************************/ + +pascal OSErr ChangeCreatorType(short vRefNum, + long dirID, + ConstStr255Param name, + OSType creator, + OSType fileType) +{ + CInfoPBRec pb; + OSErr error; + short realVRefNum; + long parID; + + pb.hFileInfo.ioNamePtr = (StringPtr)name; + pb.hFileInfo.ioVRefNum = vRefNum; + pb.hFileInfo.ioDirID = dirID; + pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ + error = PBGetCatInfoSync(&pb); + if ( error == noErr ) + { + if ( (pb.hFileInfo.ioFlAttrib & kioFlAttribDirMask) == 0 ) /* if file */ + { + parID = pb.hFileInfo.ioFlParID; /* save parent dirID for BumpDate call */ + + /* If creator not 0x00000000, change creator */ + if ( creator != (OSType)0x00000000 ) + { + pb.hFileInfo.ioFlFndrInfo.fdCreator = creator; + } + + /* If fileType not 0x00000000, change fileType */ + if ( fileType != (OSType)0x00000000 ) + { + pb.hFileInfo.ioFlFndrInfo.fdType = fileType; + } + + pb.hFileInfo.ioDirID = dirID; + error = PBSetCatInfoSync(&pb); /* now, save the new information back to disk */ + + if ( (error == noErr) && (parID != fsRtParID) ) /* can't bump fsRtParID */ + { + /* get the real vRefNum in case a full pathname was passed */ + error = DetermineVRefNum(name, vRefNum, &realVRefNum); + if ( error == noErr ) + { + error = BumpDate(realVRefNum, parID, NULL); + /* and bump the parent directory's mod date to wake up the Finder */ + /* to the change we just made */ + } + } + } + else + { + /* it was a directory, not a file */ + error = notAFileErr; + } + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr FSpChangeCreatorType(const FSSpec *spec, + OSType creator, + OSType fileType) +{ + return ( ChangeCreatorType(spec->vRefNum, spec->parID, spec->name, creator, fileType) ); +} + +/*****************************************************************************/ + +pascal OSErr ChangeFDFlags(short vRefNum, + long dirID, + ConstStr255Param name, + Boolean setBits, + unsigned short flagBits) +{ + CInfoPBRec pb; + Str31 tempName; + OSErr error; + short realVRefNum; + long parID; + + /* Protection against File Sharing problem */ + if ( (name == NULL) || (name[0] == 0) ) + { + tempName[0] = 0; + pb.hFileInfo.ioNamePtr = tempName; + pb.hFileInfo.ioFDirIndex = -1; /* use ioDirID */ + } + else + { + pb.hFileInfo.ioNamePtr = (StringPtr)name; + pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ + } + pb.hFileInfo.ioVRefNum = vRefNum; + pb.hFileInfo.ioDirID = dirID; + error = PBGetCatInfoSync(&pb); + if ( error == noErr ) + { + parID = pb.hFileInfo.ioFlParID; /* save parent dirID for BumpDate call */ + + /* set or clear the appropriate bits in the Finder flags */ + if ( setBits ) + { + /* OR in the bits */ + pb.hFileInfo.ioFlFndrInfo.fdFlags |= flagBits; + } + else + { + /* AND out the bits */ + pb.hFileInfo.ioFlFndrInfo.fdFlags &= ~flagBits; + } + + if ( pb.dirInfo.ioNamePtr == tempName ) + { + pb.hFileInfo.ioDirID = pb.hFileInfo.ioFlParID; + } + else + { + pb.hFileInfo.ioDirID = dirID; + } + + error = PBSetCatInfoSync(&pb); /* now, save the new information back to disk */ + + if ( (error == noErr) && (parID != fsRtParID) ) /* can't bump fsRtParID */ + { + /* get the real vRefNum in case a full pathname was passed */ + error = DetermineVRefNum(name, vRefNum, &realVRefNum); + if ( error == noErr ) + { + error = BumpDate(realVRefNum, parID, NULL); + /* and bump the parent directory's mod date to wake up the Finder */ + /* to the change we just made */ + } + } + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr FSpChangeFDFlags(const FSSpec *spec, + Boolean setBits, + unsigned short flagBits) +{ + return ( ChangeFDFlags(spec->vRefNum, spec->parID, spec->name, setBits, flagBits) ); +} + +/*****************************************************************************/ + +pascal OSErr SetIsInvisible(short vRefNum, + long dirID, + ConstStr255Param name) + /* Given a file or directory, make it invisible. */ +{ + return ( ChangeFDFlags(vRefNum, dirID, name, true, kIsInvisible) ); +} + +/*****************************************************************************/ + +pascal OSErr FSpSetIsInvisible(const FSSpec *spec) + /* Given a file or directory, make it invisible. */ +{ + return ( ChangeFDFlags(spec->vRefNum, spec->parID, spec->name, true, kIsInvisible) ); +} + +/*****************************************************************************/ + +pascal OSErr ClearIsInvisible(short vRefNum, + long dirID, + ConstStr255Param name) + /* Given a file or directory, make it visible. */ +{ + return ( ChangeFDFlags(vRefNum, dirID, name, false, kIsInvisible) ); +} + +/*****************************************************************************/ + +pascal OSErr FSpClearIsInvisible(const FSSpec *spec) + /* Given a file or directory, make it visible. */ +{ + return ( ChangeFDFlags(spec->vRefNum, spec->parID, spec->name, false, kIsInvisible) ); +} + +/*****************************************************************************/ + +pascal OSErr SetNameLocked(short vRefNum, + long dirID, + ConstStr255Param name) + /* Given a file or directory, lock its name. */ +{ + return ( ChangeFDFlags(vRefNum, dirID, name, true, kNameLocked) ); +} + +/*****************************************************************************/ + +pascal OSErr FSpSetNameLocked(const FSSpec *spec) + /* Given a file or directory, lock its name. */ +{ + return ( ChangeFDFlags(spec->vRefNum, spec->parID, spec->name, true, kNameLocked) ); +} + +/*****************************************************************************/ + +pascal OSErr ClearNameLocked(short vRefNum, + long dirID, + ConstStr255Param name) + /* Given a file or directory, unlock its name. */ +{ + return ( ChangeFDFlags(vRefNum, dirID, name, false, kNameLocked) ); +} + +/*****************************************************************************/ + +pascal OSErr FSpClearNameLocked(const FSSpec *spec) + /* Given a file or directory, unlock its name. */ +{ + return ( ChangeFDFlags(spec->vRefNum, spec->parID, spec->name, false, kNameLocked) ); +} + +/*****************************************************************************/ + +pascal OSErr SetIsStationery(short vRefNum, + long dirID, + ConstStr255Param name) + /* Given a file, make it a stationery pad. */ +{ + return ( ChangeFDFlags(vRefNum, dirID, name, true, kIsStationery) ); +} + +/*****************************************************************************/ + +pascal OSErr FSpSetIsStationery(const FSSpec *spec) + /* Given a file, make it a stationery pad. */ +{ + return ( ChangeFDFlags(spec->vRefNum, spec->parID, spec->name, true, kIsStationery) ); +} + +/*****************************************************************************/ + +pascal OSErr ClearIsStationery(short vRefNum, + long dirID, + ConstStr255Param name) + /* Given a file, clear the stationery bit. */ +{ + return ( ChangeFDFlags(vRefNum, dirID, name, false, kIsStationery) ); +} + +/*****************************************************************************/ + +pascal OSErr FSpClearIsStationery(const FSSpec *spec) + /* Given a file, clear the stationery bit. */ +{ + return ( ChangeFDFlags(spec->vRefNum, spec->parID, spec->name, false, kIsStationery) ); +} + +/*****************************************************************************/ + +pascal OSErr SetHasCustomIcon(short vRefNum, + long dirID, + ConstStr255Param name) + /* Given a file or directory, indicate that it has a custom icon. */ +{ + return ( ChangeFDFlags(vRefNum, dirID, name, true, kHasCustomIcon) ); +} + +/*****************************************************************************/ + +pascal OSErr FSpSetHasCustomIcon(const FSSpec *spec) + /* Given a file or directory, indicate that it has a custom icon. */ +{ + return ( ChangeFDFlags(spec->vRefNum, spec->parID, spec->name, true, kHasCustomIcon) ); +} + +/*****************************************************************************/ + +pascal OSErr ClearHasCustomIcon(short vRefNum, + long dirID, + ConstStr255Param name) + /* Given a file or directory, indicate that it does not have a custom icon. */ +{ + return ( ChangeFDFlags(vRefNum, dirID, name, false, kHasCustomIcon) ); +} + +/*****************************************************************************/ + +pascal OSErr FSpClearHasCustomIcon(const FSSpec *spec) + /* Given a file or directory, indicate that it does not have a custom icon. */ +{ + return ( ChangeFDFlags(spec->vRefNum, spec->parID, spec->name, false, kHasCustomIcon) ); +} + +/*****************************************************************************/ + +pascal OSErr ClearHasBeenInited(short vRefNum, + long dirID, + ConstStr255Param name) + /* Given a file, clear its "has been inited" bit. */ +{ + return ( ChangeFDFlags(vRefNum, dirID, name, false, kHasBeenInited) ); +} + +/*****************************************************************************/ + +pascal OSErr FSpClearHasBeenInited(const FSSpec *spec) + /* Given a file, clear its "has been inited" bit. */ +{ + return ( ChangeFDFlags(spec->vRefNum, spec->parID, spec->name, false, kHasBeenInited) ); +} + +/*****************************************************************************/ + +pascal OSErr CopyFileMgrAttributes(short srcVRefNum, + long srcDirID, + ConstStr255Param srcName, + short dstVRefNum, + long dstDirID, + ConstStr255Param dstName, + Boolean copyLockBit) +{ + UniversalFMPB pb; + Str31 tempName; + OSErr error; + Boolean objectIsDirectory; + + pb.ciPB.hFileInfo.ioVRefNum = srcVRefNum; + pb.ciPB.hFileInfo.ioDirID = srcDirID; + + /* Protection against File Sharing problem */ + if ( (srcName == NULL) || (srcName[0] == 0) ) + { + tempName[0] = 0; + pb.ciPB.hFileInfo.ioNamePtr = tempName; + pb.ciPB.hFileInfo.ioFDirIndex = -1; /* use ioDirID */ + } + else + { + pb.ciPB.hFileInfo.ioNamePtr = (StringPtr)srcName; + pb.ciPB.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ + } + error = PBGetCatInfoSync(&pb.ciPB); + if ( error == noErr ) + { + objectIsDirectory = ( (pb.ciPB.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 ); + pb.ciPB.hFileInfo.ioVRefNum = dstVRefNum; + pb.ciPB.hFileInfo.ioDirID = dstDirID; + if ( (dstName != NULL) && (dstName[0] == 0) ) + { + pb.ciPB.hFileInfo.ioNamePtr = NULL; + } + else + { + pb.ciPB.hFileInfo.ioNamePtr = (StringPtr)dstName; + } + /* don't copy the hasBeenInited bit */ + pb.ciPB.hFileInfo.ioFlFndrInfo.fdFlags = ( pb.ciPB.hFileInfo.ioFlFndrInfo.fdFlags & ~kHasBeenInited ); + error = PBSetCatInfoSync(&pb.ciPB); + if ( (error == noErr) && (copyLockBit) && ((pb.ciPB.hFileInfo.ioFlAttrib & kioFlAttribLockedMask) != 0) ) + { + pb.hPB.fileParam.ioFVersNum = 0; + error = PBHSetFLockSync(&pb.hPB); + if ( (error != noErr) && (objectIsDirectory) ) + { + error = noErr; /* ignore lock errors if destination is directory */ + } + } + } + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr FSpCopyFileMgrAttributes(const FSSpec *srcSpec, + const FSSpec *dstSpec, + Boolean copyLockBit) +{ + return ( CopyFileMgrAttributes(srcSpec->vRefNum, srcSpec->parID, srcSpec->name, + dstSpec->vRefNum, dstSpec->parID, dstSpec->name, + copyLockBit) ); +} + +/*****************************************************************************/ + +pascal OSErr HOpenAware(short vRefNum, + long dirID, + ConstStr255Param fileName, + short denyModes, + short *refNum) +{ + HParamBlockRec pb; + OSErr error; + GetVolParmsInfoBuffer volParmsInfo; + long infoSize = sizeof(GetVolParmsInfoBuffer); + + pb.ioParam.ioMisc = NULL; + pb.fileParam.ioFVersNum = 0; + pb.fileParam.ioNamePtr = (StringPtr)fileName; + pb.fileParam.ioVRefNum = vRefNum; + pb.fileParam.ioDirID = dirID; + + /* get volume attributes */ + /* this preflighting is needed because Foreign File Access based file systems don't */ + /* return the correct error result to the OpenDeny call */ + error = HGetVolParms(fileName, vRefNum, &volParmsInfo, &infoSize); + if ( (error == noErr) && hasOpenDeny(&volParmsInfo) ) + { + /* if volume supports OpenDeny, use it and return */ + pb.accessParam.ioDenyModes = denyModes; + error = PBHOpenDenySync(&pb); + *refNum = pb.ioParam.ioRefNum; + } + else if ( (error == noErr) || (error == paramErr) ) /* paramErr is OK, it just means this volume doesn't support GetVolParms */ + { + /* OpenDeny isn't supported, so try File Manager Open functions */ + + /* If request includes write permission, then see if the volume is */ + /* locked by hardware or software. The HFS file system doesn't check */ + /* for this when a file is opened - you only find out later when you */ + /* try to write and the write fails with a wPrErr or a vLckdErr. */ + + if ( (denyModes & dmWr) != 0 ) + { + error = CheckVolLock(fileName, vRefNum); + } + else + { + error = noErr; + } + + if ( error == noErr ) + { + /* Set File Manager permissions to closest thing possible */ + if ( (denyModes == dmWr) || (denyModes == dmRdWr) ) + { + pb.ioParam.ioPermssn = fsRdWrShPerm; + } + else + { + pb.ioParam.ioPermssn = denyModes % 4; + } + + error = PBHOpenDFSync(&pb); /* Try OpenDF */ + if ( error == paramErr ) + { + error = PBHOpenSync(&pb); /* OpenDF not supported, so try Open */ + } + *refNum = pb.ioParam.ioRefNum; + } + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr FSpOpenAware(const FSSpec *spec, + short denyModes, + short *refNum) +{ + return ( HOpenAware(spec->vRefNum, spec->parID, spec->name, denyModes, refNum) ); +} + +/*****************************************************************************/ + +pascal OSErr HOpenRFAware(short vRefNum, + long dirID, + ConstStr255Param fileName, + short denyModes, + short *refNum) +{ + HParamBlockRec pb; + OSErr error; + GetVolParmsInfoBuffer volParmsInfo; + long infoSize = sizeof(GetVolParmsInfoBuffer); + + pb.ioParam.ioMisc = NULL; + pb.fileParam.ioFVersNum = 0; + pb.fileParam.ioNamePtr = (StringPtr)fileName; + pb.fileParam.ioVRefNum = vRefNum; + pb.fileParam.ioDirID = dirID; + + /* get volume attributes */ + /* this preflighting is needed because Foreign File Access based file systems don't */ + /* return the correct error result to the OpenRFDeny call */ + error = HGetVolParms(fileName, vRefNum, &volParmsInfo, &infoSize); + if ( (error == noErr) && hasOpenDeny(&volParmsInfo) ) + { + /* if volume supports OpenRFDeny, use it and return */ + if ( hasOpenDeny(&volParmsInfo) ) + { + pb.accessParam.ioDenyModes = denyModes; + error = PBHOpenRFDenySync(&pb); + *refNum = pb.ioParam.ioRefNum; + } + } + else if ( (error == noErr) || (error == paramErr) ) /* paramErr is OK, it just means this volume doesn't support GetVolParms */ + { + /* OpenRFDeny isn't supported, so try File Manager OpenRF function */ + + /* If request includes write permission, then see if the volume is */ + /* locked by hardware or software. The HFS file system doesn't check */ + /* for this when a file is opened - you only find out later when you */ + /* try to write and the write fails with a wPrErr or a vLckdErr. */ + + if ( (denyModes & dmWr) != 0 ) + { + error = CheckVolLock(fileName, vRefNum); + } + else + { + error = noErr; + } + + if ( error == noErr ) + { + /* Set File Manager permissions to closest thing possible */ + if ( (denyModes == dmWr) || (denyModes == dmRdWr) ) + { + pb.ioParam.ioPermssn = fsRdWrShPerm; + } + else + { + pb.ioParam.ioPermssn = denyModes % 4; + } + + error = PBHOpenRFSync(&pb); + *refNum = pb.ioParam.ioRefNum; + } + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr FSpOpenRFAware(const FSSpec *spec, + short denyModes, + short *refNum) +{ + return ( HOpenRFAware(spec->vRefNum, spec->parID, spec->name, denyModes, refNum) ); +} + +/*****************************************************************************/ + +pascal OSErr FSReadNoCache(short refNum, + long *count, + void *buffPtr) +{ + ParamBlockRec pb; + OSErr error; + + pb.ioParam.ioRefNum = refNum; + pb.ioParam.ioBuffer = (Ptr)buffPtr; + pb.ioParam.ioReqCount = *count; + pb.ioParam.ioPosMode = fsAtMark + noCacheMask; /* fsAtMark + noCacheMask */ + pb.ioParam.ioPosOffset = 0; + error = PBReadSync(&pb); + *count = pb.ioParam.ioActCount; /* always return count */ + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr FSWriteNoCache(short refNum, + long *count, + const void *buffPtr) +{ + ParamBlockRec pb; + OSErr error; + + pb.ioParam.ioRefNum = refNum; + pb.ioParam.ioBuffer = (Ptr)buffPtr; + pb.ioParam.ioReqCount = *count; + pb.ioParam.ioPosMode = fsAtMark + noCacheMask; /* fsAtMark + noCacheMask */ + pb.ioParam.ioPosOffset = 0; + error = PBWriteSync(&pb); + *count = pb.ioParam.ioActCount; /* always return count */ + return ( error ); +} + +/*****************************************************************************/ + +/* +** See if numBytes bytes of buffer1 are equal to buffer2. +*/ +static Boolean EqualMemory(const void *buffer1, const void *buffer2, unsigned long numBytes) +{ + register unsigned char *b1 = (unsigned char *)buffer1; + register unsigned char *b2 = (unsigned char *)buffer2; + + if ( b1 != b2 ) /* if buffer pointers are same, then they are equal */ + { + while ( numBytes > 0 ) + { + /* compare the bytes and then increment the pointers */ + if ( (*b1++ - *b2++) != 0 ) + { + return ( false ); + } + --numBytes; + } + } + + return ( true ); +} + +/*****************************************************************************/ + +/* +** Read any number of bytes from an open file using read-verify mode. +** The FSReadVerify function reads any number of bytes from an open file +** and verifies them against the data in the buffer pointed to by buffPtr. +** +** Because of a bug in the HFS file system, only non-block aligned parts of +** the read are verified against the buffer data and the rest is *copied* +** into the buffer. Thus, you shouldn't verify against your original data; +** instead, you should verify against a copy of the original data and then +** compare the read-verified copy against the original data after calling +** FSReadVerify. That's why this function isn't exported - it needs the +** wrapper provided by FSWriteVerify. +*/ +static OSErr FSReadVerify(short refNum, + long *count, + void *buffPtr) +{ + ParamBlockRec pb; + OSErr result; + + pb.ioParam.ioRefNum = refNum; + pb.ioParam.ioBuffer = (Ptr)buffPtr; + pb.ioParam.ioReqCount = *count; + pb.ioParam.ioPosMode = fsAtMark + rdVerify; + pb.ioParam.ioPosOffset = 0; + result = PBReadSync(&pb); + *count = pb.ioParam.ioActCount; /* always return count */ + return ( result ); +} + +/*****************************************************************************/ + +pascal OSErr FSWriteVerify(short refNum, + long *count, + const void *buffPtr) +{ + Ptr verifyBuffer; + long position; + long bufferSize; + long byteCount; + long bytesVerified; + Ptr startVerify; + OSErr result; + + /* + ** Allocate the verify buffer + ** Try to get get a large enough buffer to verify in one pass. + ** If that fails, use GetTempBuffer to get a buffer. + */ + bufferSize = *count; + verifyBuffer = NewPtr(bufferSize); + if ( verifyBuffer == NULL ) + { + verifyBuffer = GetTempBuffer(bufferSize, &bufferSize); + } + if ( verifyBuffer != NULL ) + { + /* Save the current position */ + result = GetFPos(refNum, &position); + if ( result == noErr ) + { + /* Write the data */ + result = FSWrite(refNum, count, buffPtr); + if ( result == noErr ) + { + /* Restore the original position */ + result = SetFPos(refNum, fsFromStart, position); + if ( result == noErr ) + { + /* + ** *count = total number of bytes to verify + ** bufferSize = the size of the verify buffer + ** bytesVerified = number of bytes verified + ** byteCount = number of bytes to verify this pass + ** startVerify = position in buffPtr + */ + bytesVerified = 0; + startVerify = (Ptr)buffPtr; + while ( (bytesVerified < *count) && ( result == noErr ) ) + { + if ( (*count - bytesVerified) > bufferSize ) + { + byteCount = bufferSize; + } + else + { + byteCount = *count - bytesVerified; + } + /* + ** Copy the write buffer into the verify buffer. + ** This step is needed because the File Manager + ** compares the data in any non-block aligned + ** data at the beginning and end of the read-verify + ** request back into the file system's cache + ** to the data in verify Buffer. However, the + ** File Manager does not compare any full blocks + ** and instead copies them into the verify buffer + ** so we still have to compare the buffers again + ** after the read-verify request completes. + */ + BlockMoveData(startVerify, verifyBuffer, byteCount); + + /* Read-verify the data back into the verify buffer */ + result = FSReadVerify(refNum, &byteCount, verifyBuffer); + if ( result == noErr ) + { + /* See if the buffers are the same */ + if ( !EqualMemory(verifyBuffer, startVerify, byteCount) ) + { + result = ioErr; + } + startVerify += byteCount; + bytesVerified += byteCount; + } + } + } + } + } + DisposePtr(verifyBuffer); + } + else + { + result = memFullErr; + } + return ( result ); +} + +/*****************************************************************************/ + +pascal OSErr CopyFork(short srcRefNum, + short dstRefNum, + void *copyBufferPtr, + long copyBufferSize) +{ + ParamBlockRec srcPB; + ParamBlockRec dstPB; + OSErr srcError; + OSErr dstError; + + if ( (copyBufferPtr == NULL) || (copyBufferSize == 0) ) + return ( paramErr ); + + srcPB.ioParam.ioRefNum = srcRefNum; + dstPB.ioParam.ioRefNum = dstRefNum; + + /* preallocate the destination fork and */ + /* ensure the destination fork's EOF is correct after the copy */ + srcError = PBGetEOFSync(&srcPB); + if ( srcError != noErr ) + return ( srcError ); + dstPB.ioParam.ioMisc = srcPB.ioParam.ioMisc; + dstError = PBSetEOFSync(&dstPB); + if ( dstError != noErr ) + return ( dstError ); + + /* reset source fork's mark */ + srcPB.ioParam.ioPosMode = fsFromStart; + srcPB.ioParam.ioPosOffset = 0; + srcError = PBSetFPosSync(&srcPB); + if ( srcError != noErr ) + return ( srcError ); + + /* reset destination fork's mark */ + dstPB.ioParam.ioPosMode = fsFromStart; + dstPB.ioParam.ioPosOffset = 0; + dstError = PBSetFPosSync(&dstPB); + if ( dstError != noErr ) + return ( dstError ); + + /* set up fields that won't change in the loop */ + srcPB.ioParam.ioBuffer = (Ptr)copyBufferPtr; + srcPB.ioParam.ioPosMode = fsAtMark + noCacheMask;/* fsAtMark + noCacheMask */ + /* If copyBufferSize is greater than 512 bytes, make it a multiple of 512 bytes */ + /* This will make writes on local volumes faster */ + if ( (copyBufferSize >= 512) && ((copyBufferSize & 0x1ff) != 0) ) + { + srcPB.ioParam.ioReqCount = copyBufferSize & 0xfffffe00; + } + else + { + srcPB.ioParam.ioReqCount = copyBufferSize; + } + dstPB.ioParam.ioBuffer = (Ptr)copyBufferPtr; + dstPB.ioParam.ioPosMode = fsAtMark + noCacheMask;/* fsAtMark + noCacheMask */ + + while ( (srcError == noErr) && (dstError == noErr) ) + { + srcError = PBReadSync(&srcPB); + dstPB.ioParam.ioReqCount = srcPB.ioParam.ioActCount; + dstError = PBWriteSync(&dstPB); + } + + /* make sure there were no errors at the destination */ + if ( dstError != noErr ) + return ( dstError ); + + /* make sure the only error at the source was eofErr */ + if ( srcError != eofErr ) + return ( srcError ); + + return ( noErr ); +} + +/*****************************************************************************/ + +pascal OSErr GetFileLocation(short refNum, + short *vRefNum, + long *dirID, + StringPtr fileName) +{ + FCBPBRec pb; + OSErr error; + + pb.ioNamePtr = fileName; + pb.ioVRefNum = 0; + pb.ioRefNum = refNum; + pb.ioFCBIndx = 0; + error = PBGetFCBInfoSync(&pb); + if ( error == noErr ) + { + *vRefNum = pb.ioFCBVRefNum; + *dirID = pb.ioFCBParID; + } + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr FSpGetFileLocation(short refNum, + FSSpec *spec) +{ + return ( GetFileLocation(refNum, &(spec->vRefNum), &(spec->parID), spec->name) ); +} + +/*****************************************************************************/ + +pascal OSErr CopyDirectoryAccess(short srcVRefNum, + long srcDirID, + ConstStr255Param srcName, + short dstVRefNum, + long dstDirID, + ConstStr255Param dstName) +{ + OSErr error; + GetVolParmsInfoBuffer infoBuffer; /* Where PBGetVolParms dumps its info */ + long dstServerAdr; /* AppleTalk server address of destination (if any) */ + long ownerID, groupID, accessRights; + long tempLong; + + /* See if destination supports directory access control */ + tempLong = sizeof(infoBuffer); + error = HGetVolParms(dstName, dstVRefNum, &infoBuffer, &tempLong); + if ( (error == noErr) && hasAccessCntl(&infoBuffer) ) + { + if ( hasAccessCntl(&infoBuffer) ) + { + dstServerAdr = infoBuffer.vMServerAdr; + + /* See if source supports directory access control and is on same server */ + tempLong = sizeof(infoBuffer); + error = HGetVolParms(srcName, srcVRefNum, &infoBuffer, &tempLong); + if ( error == noErr ) + { + if ( hasAccessCntl(&infoBuffer) && (dstServerAdr == infoBuffer.vMServerAdr) ) + { + /* both volumes support directory access control and they are */ + /* on same server, so copy the access information */ + error = HGetDirAccess(srcVRefNum, srcDirID, srcName, &ownerID, &groupID, &accessRights); + if ( error == noErr ) + { + error = HSetDirAccess(dstVRefNum, dstDirID, dstName, ownerID, groupID, accessRights); + } + } + else + { + /* destination doesn't support directory access control or */ + /* they volumes aren't on the same server */ + error = paramErr; + } + } + } + else + { + /* destination doesn't support directory access control */ + error = paramErr; + } + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr FSpCopyDirectoryAccess(const FSSpec *srcSpec, + const FSSpec *dstSpec) +{ + return ( CopyDirectoryAccess(srcSpec->vRefNum, srcSpec->parID, srcSpec->name, + dstSpec->vRefNum, dstSpec->parID, dstSpec->name) ); +} + +/*****************************************************************************/ + +pascal OSErr HMoveRenameCompat(short vRefNum, + long srcDirID, + ConstStr255Param srcName, + long dstDirID, + ConstStr255Param dstpathName, + ConstStr255Param copyName) +{ + OSErr error; + GetVolParmsInfoBuffer volParmsInfo; + long infoSize; + short realVRefNum; + long realParID; + Str31 realName; + Boolean isDirectory; + long tempItemsDirID; + long uniqueTempDirID; + Str31 uniqueTempDirName; + unsigned short uniqueNameoverflow; + + /* Get volume attributes */ + infoSize = sizeof(GetVolParmsInfoBuffer); + error = HGetVolParms((StringPtr)srcName, vRefNum, &volParmsInfo, &infoSize); + if ( (error == noErr) && hasMoveRename(&volParmsInfo) ) + { + /* If volume supports move and rename, so use it and return */ + error = HMoveRename(vRefNum, srcDirID, srcName, dstDirID, dstpathName, copyName); + } + else if ( (error == noErr) || (error == paramErr) ) /* paramErr is OK, it just means this volume doesn't support GetVolParms */ + { + /* MoveRename isn't supported by this volume, so do it by hand */ + + /* If copyName isn't supplied, we can simply CatMove and return */ + if ( copyName == NULL ) + { + error = CatMove(vRefNum, srcDirID, srcName, dstDirID, dstpathName); + } + else + { + /* Renaming is required, so we have some work to do... */ + + /* Get the object's real name, real parent ID and real vRefNum */ + error = GetObjectLocation(vRefNum, srcDirID, (StringPtr)srcName, + &realVRefNum, &realParID, realName, &isDirectory); + if ( error == noErr ) + { + /* Find the Temporary Items Folder on that volume */ + error = FindFolder(realVRefNum, kTemporaryFolderType, kCreateFolder, + &realVRefNum, &tempItemsDirID); + if ( error == noErr ) + { + /* Create a new uniquely named folder in the temporary items folder. */ + /* This is done to avoid the case where 'realName' or 'copyName' already */ + /* exists in the temporary items folder. */ + + /* Start with current tick count as uniqueTempDirName */ + NumToString(TickCount(), uniqueTempDirName); + uniqueNameoverflow = 0; + do + { + error = DirCreate(realVRefNum, tempItemsDirID, uniqueTempDirName, &uniqueTempDirID); + if ( error == dupFNErr ) + { + /* Duplicate name - change the first character to the next ASCII character */ + ++uniqueTempDirName[1]; + /* Make sure it isn't a colon! */ + if ( uniqueTempDirName[1] == ':' ) + { + ++uniqueTempDirName[1]; + } + /* Don't go too far... */ + ++uniqueNameoverflow; + } + } while ( (error == dupFNErr) && (uniqueNameoverflow <= 64) ); /* 64 new files per 1/60th second - not likely! */ + if ( error == noErr ) + { + /* Move the object to the folder with uniqueTempDirID for renaming */ + error = CatMove(realVRefNum, realParID, realName, uniqueTempDirID, NULL); + if ( error == noErr ) + { + /* Rename the object */ + error = HRename(realVRefNum, uniqueTempDirID, realName, copyName); + if ( error == noErr ) + { + /* Move object to its new home */ + error = CatMove(realVRefNum, uniqueTempDirID, copyName, dstDirID, dstpathName); + if ( error != noErr ) + { + /* Error handling: rename object back to original name - ignore errors */ + (void) HRename(realVRefNum, uniqueTempDirID, copyName, realName); + } + } + if ( error != noErr ) + { + /* Error handling: move object back to original location - ignore errors */ + (void) CatMove(realVRefNum, uniqueTempDirID, realName, realParID, NULL); + } + } + /* Done with ourTempDir, so delete it - ignore errors */ + (void) HDelete(realVRefNum, uniqueTempDirID, NULL); + } + } + } + } + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr FSpMoveRenameCompat(const FSSpec *srcSpec, + const FSSpec *dstSpec, + ConstStr255Param copyName) +{ + /* make sure the FSSpecs refer to the same volume */ + if (srcSpec->vRefNum != dstSpec->vRefNum) + return (diffVolErr); + return ( HMoveRenameCompat(srcSpec->vRefNum, srcSpec->parID, srcSpec->name, + dstSpec->parID, dstSpec->name, copyName) ); +} + +/*****************************************************************************/ + +pascal OSErr BuildAFPVolMountInfo(short flags, + char nbpInterval, + char nbpCount, + short uamType, + Str32 zoneName, + Str32 serverName, + Str27 volName, + Str31 userName, + Str8 userPassword, + Str8 volPassword, + AFPVolMountInfoPtr *afpInfoPtr) +{ + MyAFPVolMountInfoPtr infoPtr; + OSErr error; + + /* Allocate the AFPXVolMountInfo record */ + infoPtr = (MyAFPVolMountInfoPtr)NewPtrClear(sizeof(MyAFPVolMountInfo)); + if ( infoPtr != NULL ) + { + /* Fill in an AFPVolMountInfo record that can be passed to VolumeMount */ + infoPtr->length = sizeof(MyAFPVolMountInfo); + infoPtr->media = AppleShareMediaType; + infoPtr->flags = flags; + infoPtr->nbpInterval = nbpInterval; + infoPtr->nbpCount = nbpCount; + infoPtr->uamType = uamType; + + infoPtr->zoneNameOffset = offsetof(MyAFPVolMountInfo, zoneName); + infoPtr->serverNameOffset = offsetof(MyAFPVolMountInfo, serverName); + infoPtr->volNameOffset = offsetof(MyAFPVolMountInfo, volName); + infoPtr->userNameOffset = offsetof(MyAFPVolMountInfo, userName); + infoPtr->userPasswordOffset = offsetof(MyAFPVolMountInfo, userPassword); + infoPtr->volPasswordOffset = offsetof(MyAFPVolMountInfo, volPassword); + + BlockMoveData(zoneName, infoPtr->zoneName, sizeof(Str32)); + BlockMoveData(serverName, infoPtr->serverName, sizeof(Str32)); + BlockMoveData(volName, infoPtr->volName, sizeof(Str27)); + BlockMoveData(userName, infoPtr->userName, sizeof(Str31)); + BlockMoveData(userPassword, infoPtr->userPassword, sizeof(Str8)); + BlockMoveData(volPassword, infoPtr->volPassword, sizeof(Str8)); + + *afpInfoPtr = (AFPVolMountInfoPtr)infoPtr; + error = noErr; + } + else + { + error = memFullErr; + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr RetrieveAFPVolMountInfo(AFPVolMountInfoPtr afpInfoPtr, + short *flags, + short *uamType, + StringPtr zoneName, + StringPtr serverName, + StringPtr volName, + StringPtr userName) +{ + StringPtr tempPtr; + OSErr error; + + /* Retrieve the AFP mounting information from an AFPVolMountInfo record. */ + if ( afpInfoPtr->media == AppleShareMediaType ) + { + *flags = afpInfoPtr->flags; + *uamType = afpInfoPtr->uamType; + + if ( afpInfoPtr->zoneNameOffset != 0) + { + tempPtr = (StringPtr)((long)afpInfoPtr + afpInfoPtr->zoneNameOffset); + BlockMoveData(tempPtr, zoneName, tempPtr[0] + 1); + } + + if ( afpInfoPtr->serverNameOffset != 0) + { + tempPtr = (StringPtr)((long)afpInfoPtr + afpInfoPtr->serverNameOffset); + BlockMoveData(tempPtr, serverName, tempPtr[0] + 1); + } + + if ( afpInfoPtr->volNameOffset != 0) + { + tempPtr = (StringPtr)((long)afpInfoPtr + afpInfoPtr->volNameOffset); + BlockMoveData(tempPtr, volName, tempPtr[0] + 1); + } + + if ( afpInfoPtr->userNameOffset != 0) + { + tempPtr = (StringPtr)((long)afpInfoPtr + afpInfoPtr->userNameOffset); + BlockMoveData(tempPtr, userName, tempPtr[0] + 1); + } + + error = noErr; + } + else + { + error = paramErr; + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr BuildAFPXVolMountInfo(short flags, + char nbpInterval, + char nbpCount, + short uamType, + Str32 zoneName, + Str32 serverName, + Str27 volName, + Str31 userName, + Str8 userPassword, + Str8 volPassword, + Str32 uamName, + unsigned long alternateAddressLength, + void *alternateAddress, + AFPXVolMountInfoPtr *afpXInfoPtr) +{ + Size infoSize; + MyAFPXVolMountInfoPtr infoPtr; + OSErr error; + + /* Calculate the size of the AFPXVolMountInfo record */ + infoSize = sizeof(MyAFPXVolMountInfo) + alternateAddressLength - 1; + + /* Allocate the AFPXVolMountInfo record */ + infoPtr = (MyAFPXVolMountInfoPtr)NewPtrClear(infoSize); + if ( infoPtr != NULL ) + { + /* Fill in an AFPXVolMountInfo record that can be passed to VolumeMount */ + infoPtr->length = infoSize; + infoPtr->media = AppleShareMediaType; + infoPtr->flags = flags; + if ( alternateAddressLength != 0 ) + { + /* make sure the volMountExtendedFlagsBit is set if there's extended address info */ + infoPtr->flags |= volMountExtendedFlagsMask; + /* and set the only extendedFlags bit we know about */ + infoPtr->extendedFlags = kAFPExtendedFlagsAlternateAddressMask; + } + else + { + /* make sure the volMountExtendedFlagsBit is clear if there's no extended address info */ + infoPtr->flags &= ~volMountExtendedFlagsMask; + /* and clear the extendedFlags */ + infoPtr->extendedFlags = 0; + } + infoPtr->nbpInterval = nbpInterval; + infoPtr->nbpCount = nbpCount; + infoPtr->uamType = uamType; + + infoPtr->zoneNameOffset = offsetof(MyAFPXVolMountInfo, zoneName); + infoPtr->serverNameOffset = offsetof(MyAFPXVolMountInfo, serverName); + infoPtr->volNameOffset = offsetof(MyAFPXVolMountInfo, volName); + infoPtr->userNameOffset = offsetof(MyAFPXVolMountInfo, userName); + infoPtr->userPasswordOffset = offsetof(MyAFPXVolMountInfo, userPassword); + infoPtr->volPasswordOffset = offsetof(MyAFPXVolMountInfo, volPassword); + infoPtr->uamNameOffset = offsetof(MyAFPXVolMountInfo, uamName); + infoPtr->alternateAddressOffset = offsetof(MyAFPXVolMountInfo, alternateAddress); + + BlockMoveData(zoneName, infoPtr->zoneName, sizeof(Str32)); + BlockMoveData(serverName, infoPtr->serverName, sizeof(Str32)); + BlockMoveData(volName, infoPtr->volName, sizeof(Str27)); + BlockMoveData(userName, infoPtr->userName, sizeof(Str31)); + BlockMoveData(userPassword, infoPtr->userPassword, sizeof(Str8)); + BlockMoveData(volPassword, infoPtr->volPassword, sizeof(Str8)); + BlockMoveData(uamName, infoPtr->uamName, sizeof(Str32)); + BlockMoveData(alternateAddress, infoPtr->alternateAddress, alternateAddressLength); + + *afpXInfoPtr = (AFPXVolMountInfoPtr)infoPtr; + error = noErr; + } + else + { + error = memFullErr; + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr RetrieveAFPXVolMountInfo(AFPXVolMountInfoPtr afpXInfoPtr, + short *flags, + short *uamType, + StringPtr zoneName, + StringPtr serverName, + StringPtr volName, + StringPtr userName, + StringPtr uamName, + unsigned long *alternateAddressLength, + AFPAlternateAddress **alternateAddress) +{ + StringPtr tempPtr; + Ptr alternateAddressStart; + Ptr alternateAddressEnd; + Size alternateAddressDataSize; + OSErr error; + UInt8 addressCount; + + /* Retrieve the AFP mounting information from an AFPVolMountInfo record. */ + if ( afpXInfoPtr->media == AppleShareMediaType ) + { + /* default to noErr */ + error = noErr; + + /* Is this an extended record? */ + if ( (afpXInfoPtr->flags & volMountExtendedFlagsMask) != 0 ) + { + if ( ((afpXInfoPtr->extendedFlags & kAFPExtendedFlagsAlternateAddressMask) != 0) && + (afpXInfoPtr->alternateAddressOffset != 0) ) + { + + alternateAddressStart = (Ptr)((long)afpXInfoPtr + afpXInfoPtr->alternateAddressOffset); + alternateAddressEnd = alternateAddressStart + 1; /* skip over alternate address version byte */ + addressCount = *(UInt8*)alternateAddressEnd; /* get the address count */ + ++alternateAddressEnd; /* skip over alternate address count byte */ + /* alternateAddressEnd now equals &AFPAlternateAddress.fAddressList[0] */ + while ( addressCount != 0 ) + { + /* parse the address list to find the end */ + alternateAddressEnd += *(UInt8*)alternateAddressEnd; /* add length of each AFPTagData record */ + --addressCount; + } + /* get the size of the alternateAddressData */ + alternateAddressDataSize = alternateAddressEnd - alternateAddressStart; + /* allocate memory for it */ + *alternateAddress = (AFPAlternateAddress *)NewPtr(alternateAddressDataSize); + if ( *alternateAddress != NULL ) + { + /* and return the data */ + BlockMoveData(alternateAddressStart, *alternateAddress, alternateAddressDataSize); + *alternateAddressLength = alternateAddressDataSize; + } + else + { + /* no memory - fail now */ + error = memFullErr; + } + } + + if ( error == noErr ) /* fill in more output parameters if everything is OK */ + { + if ( afpXInfoPtr->uamNameOffset != 0 ) + { + tempPtr = (StringPtr)((long)afpXInfoPtr + afpXInfoPtr->uamNameOffset); + BlockMoveData(tempPtr, uamName, tempPtr[0] + 1); + } + } + } + + if ( error == noErr ) /* fill in more output parameters if everything is OK */ + { + *flags = afpXInfoPtr->flags; + *uamType = afpXInfoPtr->uamType; + + if ( afpXInfoPtr->zoneNameOffset != 0 ) + { + tempPtr = (StringPtr)((long)afpXInfoPtr + afpXInfoPtr->zoneNameOffset); + BlockMoveData(tempPtr, zoneName, tempPtr[0] + 1); + } + + if ( afpXInfoPtr->serverNameOffset != 0 ) + { + tempPtr = (StringPtr)((long)afpXInfoPtr + afpXInfoPtr->serverNameOffset); + BlockMoveData(tempPtr, serverName, tempPtr[0] + 1); + } + + if ( afpXInfoPtr->volNameOffset != 0 ) + { + tempPtr = (StringPtr)((long)afpXInfoPtr + afpXInfoPtr->volNameOffset); + BlockMoveData(tempPtr, volName, tempPtr[0] + 1); + } + + if ( afpXInfoPtr->userNameOffset != 0 ) + { + tempPtr = (StringPtr)((long)afpXInfoPtr + afpXInfoPtr->userNameOffset); + BlockMoveData(tempPtr, userName, tempPtr[0] + 1); + } + } + } + else + { + error = paramErr; + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr GetUGEntries(short objType, + UGEntryPtr entries, + long reqEntryCount, + long *actEntryCount, + long *objID) +{ + HParamBlockRec pb; + OSErr error = noErr; + UGEntry *endEntryArray; + + pb.objParam.ioObjType = objType; + *actEntryCount = 0; + for ( endEntryArray = entries + reqEntryCount; (entries < endEntryArray) && (error == noErr); ++entries ) + { + pb.objParam.ioObjNamePtr = (StringPtr)entries->name; + pb.objParam.ioObjID = *objID; + /* Files.h in the universal interfaces, PBGetUGEntrySync takes a CMovePBPtr */ + /* as the parameter. Inside Macintosh and the original glue used HParmBlkPtr. */ + /* A CMovePBPtr works OK, but this will be changed in the future back to */ + /* HParmBlkPtr, so I'm just casting it here. */ + error = PBGetUGEntrySync(&pb); + if ( error == noErr ) + { + entries->objID = *objID = pb.objParam.ioObjID; + entries->objType = objType; + ++*actEntryCount; + } + } + + return ( error ); +} + +/*****************************************************************************/ + diff --git a/src/mac/morefile/MoreFilesExtras.h b/src/mac/morefile/MoreFilesExtras.h new file mode 100644 index 0000000000..285dfa7977 --- /dev/null +++ b/src/mac/morefile/MoreFilesExtras.h @@ -0,0 +1,3597 @@ +/* + File: MoreFilesExtras.h + + Contains: A collection of useful high-level File Manager routines. + + Version: Technology: MoreFiles + Release: 1.5.2 + + Copyright: © 1992-2001 by Apple Computer, Inc., all rights reserved. + + Bugs?: For bug reports, consult the following page on + the World Wide Web: + + http://developer.apple.com/bugreporter/ + +*/ + +/* + 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 __MOREFILESEXTRAS__ +#define __MOREFILESEXTRAS__ + +#ifndef __MACTYPES__ +#include +#endif + +#ifndef __FILES__ +#include +#endif + +#include "Optimization.h" + + +#if PRAGMA_ONCE +#pragma once +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if PRAGMA_IMPORT +#pragma import on +#endif + +#if PRAGMA_STRUCT_ALIGN + #pragma options align=mac68k +#elif PRAGMA_STRUCT_PACKPUSH + #pragma pack(push, 2) +#elif PRAGMA_STRUCT_PACK + #pragma pack(2) +#endif + +/*****************************************************************************/ + +/* +** Bit masks and macros to get common information out of ioACUser returned +** by PBGetCatInfo (remember to clear ioACUser before calling PBGetCatInfo +** since some file systems don't bother to set this field). +** +** Use the GetDirAccessRestrictions or FSpGetDirAccessRestrictions +** functions to retrieve the ioACUser access restrictions byte for +** a folder. +** +** Note: The access restriction byte returned by PBGetCatInfo is the +** 2's complement of the user's privileges byte returned in +** ioACAccess by PBHGetDirAccess. +*/ + +enum { + /* mask for just the access restriction bits */ + acUserAccessMask = (kioACUserNoSeeFolderMask + kioACUserNoSeeFilesMask + kioACUserNoMakeChangesMask), /* common access privilege settings */ + acUserFull = 0x00, /* no access restiction bits on */ + acUserNone = acUserAccessMask, /* all access restiction bits on */ + acUserDropBox = kioACUserNoSeeFolderMask + kioACUserNoSeeFilesMask, /* make changes, but not see files or folders */ + acUserBulletinBoard = kioACUserNoMakeChangesMask /* see files and folders, but not make changes */ +}; + + +/*****************************************************************************/ + +/* +** Deny mode permissions for use with the HOpenAware, HOpenRFAware, +** FSpOpenAware, and FSpOpenRFAware functions. +** Note: Common settings are the ones with comments. +*/ + +enum { + dmNone = 0x0000, + dmNoneDenyRd = fsRdDenyPerm, + dmNoneDenyWr = fsWrDenyPerm, + dmNoneDenyRdWr = (fsRdDenyPerm + fsWrDenyPerm), + dmRd = fsRdPerm, /* Single writer, multiple readers; the readers */ + dmRdDenyRd = (fsRdPerm + fsRdDenyPerm), + dmRdDenyWr = (fsRdPerm + fsWrDenyPerm), /* Browsing - equivalent to fsRdPerm */ + dmRdDenyRdWr = (fsRdPerm + fsRdDenyPerm + fsWrDenyPerm), + dmWr = fsWrPerm, + dmWrDenyRd = (fsWrPerm + fsRdDenyPerm), + dmWrDenyWr = (fsWrPerm + fsWrDenyPerm), + dmWrDenyRdWr = (fsWrPerm + fsRdDenyPerm + fsWrDenyPerm), + dmRdWr = fsRdWrPerm, /* Shared access - equivalent to fsRdWrShPerm */ + dmRdWrDenyRd = (fsRdWrPerm + fsRdDenyPerm), + dmRdWrDenyWr = (fsRdWrPerm + fsWrDenyPerm), /* Single writer, multiple readers; the writer */ + dmRdWrDenyRdWr = (fsRdWrPerm + fsRdDenyPerm + fsWrDenyPerm) /* Exclusive access - equivalent to fsRdWrPerm */ +}; + + +/*****************************************************************************/ + +/* +** For those times where you need to use more than one kind of File Manager parameter +** block but don't feel like wasting stack space, here's a parameter block you can reuse. +*/ + + +union UniversalFMPB { + ParamBlockRec PB; + CInfoPBRec ciPB; + DTPBRec dtPB; + HParamBlockRec hPB; + CMovePBRec cmPB; + WDPBRec wdPB; + FCBPBRec fcbPB; + XVolumeParam xPB; +}; +typedef union UniversalFMPB UniversalFMPB; +typedef UniversalFMPB * UniversalFMPBPtr; +typedef UniversalFMPBPtr * UniversalFMPBHandle; + +/* +** Used by GetUGEntries to return user or group lists +*/ + +struct UGEntry { + short objType; /* object type: -1 = group; 0 = user */ + long objID; /* the user or group ID */ + Str31 name; /* the user or group name */ +}; +typedef struct UGEntry UGEntry; +typedef UGEntry * UGEntryPtr; +typedef UGEntryPtr * UGEntryHandle; + +/* +** I use the following records instead of the AFPVolMountInfo and AFPXVolMountInfo structures in Files.h +*/ +typedef unsigned char Str8[9]; + +struct MyAFPVolMountInfo { + short length; /* length of this record */ + VolumeType media; /* type of media, always AppleShareMediaType */ + short flags; /* 0 = normal mount; set bit 0 to inhibit greeting messages */ + char nbpInterval; /* NBP interval parameter; 7 is a good choice */ + char nbpCount; /* NBP count parameter; 5 is a good choice */ + short uamType; /* User Authentication Method */ + short zoneNameOffset; /* offset from start of record to zoneName */ + short serverNameOffset; /* offset from start of record to serverName */ + short volNameOffset; /* offset from start of record to volName */ + short userNameOffset; /* offset from start of record to userName */ + short userPasswordOffset; /* offset from start of record to userPassword */ + short volPasswordOffset; /* offset from start of record to volPassword */ + Str32 zoneName; /* server's AppleTalk zone name */ + char filler1; /* to word align volPassword */ + Str32 serverName; /* server name */ + char filler2; /* to word align volPassword */ + Str27 volName; /* volume name */ + Str31 userName; /* user name (zero length Pascal string for guest) */ + Str8 userPassword; /* user password (zero length Pascal string if no user password) */ + char filler3; /* to word align volPassword */ + Str8 volPassword; /* volume password (zero length Pascal string if no volume password) */ + char filler4; /* to end record on word boundry */ +}; +typedef struct MyAFPVolMountInfo MyAFPVolMountInfo; +typedef MyAFPVolMountInfo * MyAFPVolMountInfoPtr; +typedef MyAFPVolMountInfoPtr * MyAFPVolMountInfoHandle; + +struct MyAFPXVolMountInfo { + short length; /* length of this record */ + VolumeType media; /* type of media, always AppleShareMediaType */ + short flags; /* bits for no messages, no reconnect, etc */ + char nbpInterval; /* NBP interval parameter; 7 is a good choice */ + char nbpCount; /* NBP count parameter; 5 is a good choice */ + short uamType; /* User Authentication Method */ + short zoneNameOffset; /* offset from start of record to zoneName */ + short serverNameOffset; /* offset from start of record to serverName */ + short volNameOffset; /* offset from start of record to volName */ + short userNameOffset; /* offset from start of record to userName */ + short userPasswordOffset; /* offset from start of record to userPassword */ + short volPasswordOffset; /* offset from start of record to volPassword */ + short extendedFlags; /* extended flags word */ + short uamNameOffset; /* offset to a pascal UAM name string */ + short alternateAddressOffset; /* offset to Alternate Addresses in tagged format */ + Str32 zoneName; /* server's AppleTalk zone name */ + char filler1; /* to word align volPassword */ + Str32 serverName; /* server name */ + char filler2; /* to word align volPassword */ + Str27 volName; /* volume name */ + Str31 userName; /* user name (zero length Pascal string for guest) */ + Str8 userPassword; /* user password (zero length Pascal string if no user password) */ + char filler3; /* to word align volPassword */ + Str8 volPassword; /* volume password (zero length Pascal string if no volume password) */ + char filler4; /* to word align uamNameOffset */ + Str32 uamName; /* UAM name */ + char filler5; /* to word align alternateAddress */ + char alternateAddress[1]; /* AFPAlternateAddress */ +}; +typedef struct MyAFPXVolMountInfo MyAFPXVolMountInfo; +typedef MyAFPXVolMountInfo * MyAFPXVolMountInfoPtr; +typedef MyAFPXVolMountInfoPtr * MyAFPXVolMountInfoHandle; + +/*****************************************************************************/ + +/* Functions to get information out of GetVolParmsInfoBuffer. */ + +/* version 1 field getters */ + +EXTERN_API( short ) +GetVolParmsInfoVersion(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( long ) +GetVolParmsInfoAttrib(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Handle ) +GetVolParmsInfoLocalHand(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( long ) +GetVolParmsInfoServerAdr(const GetVolParmsInfoBuffer * volParms); + + + +/* version 2 field getters (assume zero result if version < 2) */ + +EXTERN_API( long ) +GetVolParmsInfoVolumeGrade(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( long ) +GetVolParmsInfoForeignPrivID(const GetVolParmsInfoBuffer * volParms); + + + +/* version 3 field getters (assume zero result if version < 3) */ + +EXTERN_API( long ) +GetVolParmsInfoExtendedAttributes(const GetVolParmsInfoBuffer * volParms); + + + +/* attribute bits supported by all versions of GetVolParmsInfoBuffer */ + +EXTERN_API( Boolean ) +isNetworkVolume(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +hasLimitFCBs(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +hasLocalWList(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +hasNoMiniFndr(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +hasNoVNEdit(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +hasNoLclSync(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +hasTrshOffLine(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +hasNoSwitchTo(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +hasNoDeskItems(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +hasNoBootBlks(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +hasAccessCntl(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +hasNoSysDir(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +hasExtFSVol(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +hasOpenDeny(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +hasCopyFile(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +hasMoveRename(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +hasDesktopMgr(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +hasShortName(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +hasFolderLock(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +hasPersonalAccessPrivileges(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +hasUserGroupList(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +hasCatSearch(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +hasFileIDs(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +hasBTreeMgr(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +hasBlankAccessPrivileges(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +supportsAsyncRequests(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +supportsTrashVolumeCache(const GetVolParmsInfoBuffer * volParms); + + + +/* attribute bits supported by version 3 and greater versions of GetVolParmsInfoBuffer */ + +EXTERN_API( Boolean ) +volIsEjectable(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +volSupportsHFSPlusAPIs(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +volSupportsFSCatalogSearch(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +volSupportsFSExchangeObjects(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +volSupports2TBFiles(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +volSupportsLongNames(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +volSupportsMultiScriptNames(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +volSupportsNamedForks(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +volSupportsSubtreeIterators(const GetVolParmsInfoBuffer * volParms); + + +EXTERN_API( Boolean ) +volL2PCanMapFileBlocks(const GetVolParmsInfoBuffer * volParms); + + + +/*****************************************************************************/ + +/* Functions for testing ioACUser bits. */ + +EXTERN_API( Boolean ) +userIsOwner(SInt8 ioACUser); + + +EXTERN_API( Boolean ) +userHasFullAccess(SInt8 ioACUser); + + +EXTERN_API( Boolean ) +userHasDropBoxAccess(SInt8 ioACUser); + + +EXTERN_API( Boolean ) +userHasBulletinBoard(SInt8 ioACUser); + + +EXTERN_API( Boolean ) +userHasNoAccess(SInt8 ioACUser); + + + +/*****************************************************************************/ + +EXTERN_API( void ) +TruncPString( + StringPtr destination, + ConstStr255Param source, + short maxLength); + + +/* + The TruncPString function copies up to maxLength characters from + the source Pascal string to the destination Pascal string. TruncPString + ensures that the truncated string ends on a single-byte character, or on + the last byte of a multi-byte character. + + destination output: destination Pascal string. + source input: source Pascal string. + maxLength output: The maximum allowable length of the destination + string. +*/ + +/*****************************************************************************/ + +EXTERN_API( Ptr ) +GetTempBuffer( + long buffReqSize, + long * buffActSize); + + +/* + The GetTempBuffer function allocates a temporary buffer for file system + operations which is at least 1024 bytes (1K) and a multiple of + 1024 bytes. + + buffReqSize input: Size you'd like the buffer to be. + buffActSize output: Size of buffer allocated. + function result output: Pointer to memory allocated or nil if no memory + was available. The caller is responsible for + disposing of this buffer with DisposePtr. +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +GetVolumeInfoNoName( + ConstStr255Param pathname, + short vRefNum, + HParmBlkPtr pb); + + +/* + GetVolumeInfoNoName uses pathname and vRefNum to call PBHGetVInfoSync + in cases where the returned volume name is not needed by the caller. + The pathname and vRefNum parameters are not touched, and the pb + parameter is initialized by PBHGetVInfoSync except that ioNamePtr in + the parameter block is always returned as NULL (since it might point + to GetVolumeInfoNoName's local variable tempPathname). + + I noticed using this code in several places, so here it is once. + This reduces the code size of MoreFiles. + + pathName input: Pointer to a full pathname or nil. If you pass in a + partial pathname, it is ignored. A full pathname to a + volume must end with a colon character (:). + vRefNum input: Volume specification (volume reference number, working + directory number, drive number, or 0). + pb input: A pointer to HParamBlockRec. + output: The parameter block as filled in by PBHGetVInfoSync + except that ioNamePtr will always be NULL. + + Result Codes + noErr 0 No error + nsvErr -35 No such volume + paramErr -50 No default volume, or pb was NULL +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +XGetVolumeInfoNoName( + ConstStr255Param pathname, + short vRefNum, + XVolumeParamPtr pb); + + +/* + XGetVolumeInfoNoName uses pathname and vRefNum to call PBXGetVolInfoSync + in cases where the returned volume name is not needed by the caller. + The pathname and vRefNum parameters are not touched, and the pb + parameter is initialized by PBXGetVolInfoSync except that ioNamePtr in + the parameter block is always returned as NULL (since it might point + to XGetVolumeInfoNoName's local variable tempPathname). + + pathName input: Pointer to a full pathname or nil. If you pass in a + partial pathname, it is ignored. A full pathname to a + volume must end with a colon character (:). + vRefNum input: Volume specification (volume reference number, working + directory number, drive number, or 0). + pb input: A pointer to HParamBlockRec. + output: The parameter block as filled in by PBXGetVolInfoSync + except that ioNamePtr will always be NULL. + + Result Codes + noErr 0 No error + nsvErr -35 No such volume + paramErr -50 No default volume, or pb was NULL +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +GetCatInfoNoName( + short vRefNum, + long dirID, + ConstStr255Param name, + CInfoPBPtr pb); + + +/* + GetCatInfoNoName uses vRefNum, dirID and name to call PBGetCatInfoSync + in cases where the returned object is not needed by the caller. + The vRefNum, dirID and name parameters are not touched, and the pb + parameter is initialized by PBGetCatInfoSync except that ioNamePtr in + the parameter block is always returned as NULL (since it might point + to GetCatInfoNoName's local variable tempName). + + I noticed using this code in several places, so here it is once. + This reduces the code size of MoreFiles. + + 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. + pb input: A pointer to CInfoPBRec. + output: The parameter block as filled in by + PBGetCatInfoSync except that ioNamePtr will + always be NULL. + + 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 + 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 + +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +DetermineVRefNum( + ConstStr255Param pathname, + short vRefNum, + short * realVRefNum); + + +/* + The DetermineVRefNum function determines the volume reference number of + a volume from a pathname, a volume specification, or a combination + of the two. + WARNING: Volume names on the Macintosh are *not* unique -- Multiple + mounted volumes can have the same name. For this reason, the use of a + volume name or 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 volume name or full pathname is used, the File Manager + currently uses the first volume it finds with a matching name in the + volume queue. + + pathName input: Pointer to a full pathname or nil. If you pass in a + partial pathname, it is ignored. A full pathname to a + volume must end with a colon character (:). + vRefNum input: Volume specification (volume reference number, working + directory number, drive number, or 0). + realVRefNum output: The real volume reference number. + + Result Codes + noErr 0 No error + nsvErr -35 No such volume + paramErr -50 No default volume +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +HGetVInfo( + short volReference, + StringPtr volName, + short * vRefNum, + unsigned long * freeBytes, + unsigned long * totalBytes); + + +/* + The HGetVInfo function returns the name, volume reference number, + available space (in bytes), and total space (in bytes) for the + specified volume. You can specify the volume by providing its drive + number, volume reference number, or 0 for the default volume. + This routine is compatible with volumes up to 4 gigabytes. + + volReference input: The drive number, volume reference number, + or 0 for the default volume. + volName input: A pointer to a buffer (minimum Str27) where + the volume name is to be returned or must + be nil. + output: The volume name. + vRefNum output: The volume reference number. + freeBytes output: The number of free bytes on the volume. + freeBytes is an unsigned long value. + totalBytes output: The total number of bytes on the volume. + totalBytes is an unsigned long value. + + Result Codes + noErr 0 No error + nsvErr -35 No such volume + paramErr -50 No default volume + + __________ + + Also see: XGetVInfo +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +XGetVInfo( + short volReference, + StringPtr volName, + short * vRefNum, + UInt64 * freeBytes, + UInt64 * totalBytes); + + +/* + The XGetVInfo function returns the name, volume reference number, + available space (in bytes), and total space (in bytes) for the + specified volume. You can specify the volume by providing its drive + number, volume reference number, or 0 for the default volume. + This routine is compatible with volumes up to 2 terabytes. + + volReference input: The drive number, volume reference number, + or 0 for the default volume. + volName input: A pointer to a buffer (minimum Str27) where + the volume name is to be returned or must + be nil. + output: The volume name. + vRefNum output: The volume reference number. + freeBytes output: The number of free bytes on the volume. + freeBytes is an UnsignedWide value. + totalBytes output: The total number of bytes on the volume. + totalBytes is an UnsignedWide value. + + Result Codes + noErr 0 No error + nsvErr -35 No such volume + paramErr -50 No default volume + + __________ + + Also see: HGetVInfo +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +CheckVolLock( + ConstStr255Param pathname, + short vRefNum); + + +/* + The CheckVolLock function determines if a volume is locked - either by + hardware or by software. If CheckVolLock returns noErr, then the volume + is not locked. + + pathName input: Pointer to a full pathname or nil. If you pass in a + partial pathname, it is ignored. A full pathname to a + volume must end with a colon character (:). + vRefNum input: Volume specification (volume reference number, working + directory number, drive number, or 0). + + Result Codes + noErr 0 No error - volume not locked + nsvErr -35 No such volume + wPrErr -44 Volume locked by hardware + vLckdErr -46 Volume locked by software + paramErr -50 No default volume +*/ + +/*****************************************************************************/ +/* +** The following routines call Mac OS routines that are not supported by +** Carbon: +** +** GetDriverName +** FindDrive +** GetDiskBlocks +** GetVolState +*/ + +#if !TARGET_API_MAC_CARBON // { + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +GetDriverName( + short driverRefNum, + Str255 driverName); + + +/* + The GetDriverName function returns a device driver's name. + + driverRefNum input: The driver reference number. + driverName output: The driver's name. + + Result Codes + noErr 0 No error + badUnitErr -21 Bad driver reference number +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FindDrive( + ConstStr255Param pathname, + short vRefNum, + DrvQElPtr * driveQElementPtr); + + +/* + The FindDrive function returns a pointer to a mounted volume's + drive queue element. + + pathName input: Pointer to a full pathname or nil. If you + pass in a partial pathname, it is ignored. + A full pathname to a volume must end with + a colon character (:). + vRefNum input: Volume specification (volume reference + number, working directory number, drive + number, or 0). + driveQElementPtr output: Pointer to a volume's drive queue element + in the drive queue. DO NOT change the + DrvQEl. + + Result Codes + noErr 0 No error + nsvErr -35 No such volume + paramErr -50 No default volume + nsDrvErr -56 No such drive +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +GetDiskBlocks( + ConstStr255Param pathname, + short vRefNum, + unsigned long * numBlocks); + + +/* + The GetDiskBlocks function returns the number of physical disk + blocks on a disk drive. NOTE: This is not the same as volume + allocation blocks! + + pathName input: Pointer to a full pathname or nil. If you + pass in a partial pathname, it is ignored. + A full pathname to a volume must end with + a colon character (:). + vRefNum input: Volume specification (volume reference + number, working directory number, drive + number, or 0). + numBlocks output: The number of physical disk blocks on the disk drive. + + Result Codes + noErr 0 No error + nsvErr -35 No such volume + paramErr -50 No default volume, driver reference + number is zero, ReturnFormatList + returned zero blocks, DriveStatus + returned an unknown value, or + driveQElementPtr->qType is unknown + nsDrvErr -56 No such drive + statusErr Ð18 Driver does not respond to this + status request + 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +GetVolState( + ConstStr255Param pathname, + short vRefNum, + Boolean * volumeOnline, + Boolean * volumeEjected, + Boolean * driveEjectable, + Boolean * driverWantsEject); + + +/* + The GetVolState function determines if a volume is online or offline, + if an offline volume is ejected, and if the volume's driver is + ejectable or wants eject calls. + + pathName input: Pointer to a full pathname or nil. + vRefNum input: Volume specification (volume reference number, + working directory number, drive number, or 0). + volumeOnline output: True if the volume is online; + False if the volume is offline. + volumeEjected output: True if the volume is ejected (ejected + volumes are always offline); False if the + volume is not ejected. + driveEjectable output: True if the volume's drive is ejectable; + False if the volume's drive is not ejectable. + driverWantsEject output: True if the volume's driver wants an Eject + request after unmount (even if the drive + is not ejectable); False if the volume's + driver does not need an eject request. + + Result Codes + noErr 0 No error + nsvErr -35 No such volume + paramErr -50 No default volume, or pb was NULL +*/ + +/*****************************************************************************/ + +#endif // } !TARGET_API_MAC_CARBON + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +GetVolFileSystemID( + ConstStr255Param pathname, + short vRefNum, + short * fileSystemID); + + +/* + The GetVolFileSystemID function returned the file system ID of + a mounted volume. The file system ID identifies the file system + that handles requests to a particular volume. Here's a partial list + of file system ID numbers (only Apple's file systems are listed): + FSID File System + ----- ----------------------------------------------------- + $0000 Macintosh HFS or MFS + $0100 ProDOS File System + $0101 PowerTalk Mail Enclosures + $4147 ISO 9660 File Access (through Foreign File Access) + $4242 High Sierra File Access (through Foreign File Access) + $464D QuickTake File System (through Foreign File Access) + $4953 Macintosh PC Exchange (MS-DOS) + $4A48 Audio CD Access (through Foreign File Access) + $4D4B Apple Photo Access (through Foreign File Access) + + See the Technical Note "FL 35 - Determining Which File System + Is Active" and the "Guide to the File System Manager" for more + information. + + pathName input: Pointer to a full pathname or nil. If you pass + in a partial pathname, it is ignored. A full + pathname to a volume must contain at least + one colon character (:) and must not start with + a colon character. + vRefNum input: Volume specification (volume reference number, + working directory number, drive number, or 0). + fileSystemID output: The volume's file system ID. + + Result Codes + noErr 0 No error + nsvErr -35 No such volume + paramErr -50 No default volume, or pb was NULL +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +UnmountAndEject( + ConstStr255Param pathname, + short vRefNum); + + +/* + The UnmountAndEject function unmounts and ejects a volume. The volume + is ejected only if it is ejectable and not already ejected. + + pathName input: Pointer to a full pathname or nil. If you pass in a + partial pathname, it is ignored. A full pathname to a + volume must end with a colon character (:). + vRefNum input: Volume specification (volume reference number, working + directory number, drive number, or 0). + + Result Codes + noErr 0 No error + nsvErr -35 No such volume + ioErr -36 I/O error + bdNamErr -37 Bad volume name + fBsyErr -47 One or more files are open + paramErr -50 No default volume + nsDrvErr -56 No such drive + extFSErr -58 External file system error - no file + system claimed this call. +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +OnLine( + FSSpecPtr volumes, + short reqVolCount, + short * actVolCount, + short * volIndex); + + +/* + The OnLine function returns the list of volumes currently mounted in + an array of FSSpec records. + + A noErr result indicates that the volumes array was filled + (actVolCount == reqVolCount) and there may be additional volumes + mounted. A nsvErr result indicates that the end of the volume list + was found and actVolCount volumes were actually found this time. + + volumes input: Pointer to array of FSSpec where the volume list + is returned. + reqVolCount input: Maximum number of volumes to return (the number of + elements in the volumes array). + actVolCount output: The number of volumes actually returned. + volIndex input: The current volume index position. Set to 1 to + start with the first volume. + output: The volume index position to get the next volume. + Pass this value the next time you call OnLine to + start where you left off. + + Result Codes + noErr 0 No error, but there are more volumes + to list + nsvErr -35 No more volumes to be listed + paramErr -50 volIndex was <= 0 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +SetDefault( + short newVRefNum, + long newDirID, + short * oldVRefNum, + long * oldDirID); + + +/* + The SetDefault function sets the default volume and directory to the + volume specified by newVRefNum and the directory specified by newDirID. + The current default volume reference number and directory ID are + returned in oldVRefNum and oldDir and must be used to restore the + default volume and directory to their previous state *as soon as + possible* with the RestoreDefault function. These two functions are + designed to be used as a wrapper around Standard I/O routines where + the location of the file is implied to be the default volume and + directory. In other words, this is how you should use these functions: + + error = SetDefault(newVRefNum, newDirID, &oldVRefNum, &oldDirID); + if ( error == noErr ) + { + // call the Stdio functions like remove, rename, tmpfile, + // fopen, freopen, etc. or non-ANSI extensions like + // fdopen,fsetfileinfo, -- create, open, unlink, etc. here! + + error = RestoreDefault(oldVRefNum, oldDirID); + } + + By using these functions as a wrapper, you won't need to open a working + directory (because SetDefault and RestoreDefault use HSetVol) and you + won't have to worry about the effects of using HSetVol (documented in + Technical Note "FL 11 - PBHSetVol is Dangerous" and in the + Inside Macintosh: Files book in the description of the HSetVol and + PBHSetVol functions) because the default volume/directory is restored + before giving up control to code that might be affected by HSetVol. + + newVRefNum input: Volume specification (volume reference number, + working directory number, drive number, or 0) of + the new default volume. + newDirID input: Directory ID of the new default directory. + oldVRefNum output: The volume specification to save for use with + RestoreDefault. + oldDirID output: The directory ID to save for use with + RestoreDefault. + + Result Codes + noErr 0 No error + nsvErr -35 No such volume + bdNamErr -37 Bad volume name + fnfErr -43 Directory not found + paramErr -50 No default volume + afpAccessDenied -5000 User does not have access to the directory + + __________ + + Also see: RestoreDefault +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +RestoreDefault( + short oldVRefNum, + long oldDirID); + + +/* + The RestoreDefault function restores the default volume and directory + to the volume specified by oldVRefNum and the directory specified by + oldDirID. The oldVRefNum and oldDirID parameters were previously + obtained from the SetDefault function. These two functions are designed + to be used as a wrapper around Standard C I/O routines where the + location of the file is implied to be the default volume and directory. + In other words, this is how you should use these functions: + + error = SetDefault(newVRefNum, newDirID, &oldVRefNum, &oldDirID); + if ( error == noErr ) + { + // call the Stdio functions like remove, rename, tmpfile, + // fopen, freopen, etc. or non-ANSI extensions like + // fdopen,fsetfileinfo, -- create, open, unlink, etc. here! + + error = RestoreDefault(oldVRefNum, oldDirID); + } + + By using these functions as a wrapper, you won't need to open a working + directory (because SetDefault and RestoreDefault use HSetVol) and you + won't have to worry about the effects of using HSetVol (documented in + Technical Note "FL 11 - PBHSetVol is Dangerous" and in the + Inside Macintosh: Files book in the description of the HSetVol and + PBHSetVol functions) because the default volume/directory is restored + before giving up control to code that might be affected by HSetVol. + + oldVRefNum input: The volume specification to restore. + oldDirID input: The directory ID to restore. + + Result Codes + noErr 0 No error + nsvErr -35 No such volume + bdNamErr -37 Bad volume name + fnfErr -43 Directory not found + paramErr -50 No default volume + rfNumErr -51 Bad working directory reference number + afpAccessDenied -5000 User does not have access to the directory + + __________ + + Also see: SetDefault +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +GetDInfo( + short vRefNum, + long dirID, + ConstStr255Param name, + DInfo * fndrInfo); + + +/* + The GetDInfo function gets the finder information for a directory. + + 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. + fndrInfo output: If the object is a directory, then its DInfo. + + 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 + 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 + + __________ + + Also see: FSpGetDInfo, FSpGetFInfoCompat +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpGetDInfo( + const FSSpec * spec, + DInfo * fndrInfo); + + +/* + The FSpGetDInfo function gets the finder information for a directory. + + spec input: An FSSpec record specifying the directory. + fndrInfo output: If the object is a directory, then its DInfo. + + 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 + 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 + + __________ + + Also see: FSpGetFInfoCompat, GetDInfo +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +SetDInfo( + short vRefNum, + long dirID, + ConstStr255Param name, + const DInfo * fndrInfo); + + +/* + The SetDInfo function sets the finder information for a directory. + + 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. + fndrInfo input: The DInfo. + + 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 + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + paramErr -50 No default volume + 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 + + __________ + + Also see: FSpSetDInfo, FSpSetFInfoCompat +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpSetDInfo( + const FSSpec * spec, + const DInfo * fndrInfo); + + +/* + The FSpSetDInfo function sets the finder information for a directory. + + spec input: An FSSpec record specifying the directory. + fndrInfo input: The DInfo. + + 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 + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + paramErr -50 No default volume + 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 + + __________ + + Also see: FSpSetFInfoCompat, SetDInfo +*/ + +/*****************************************************************************/ + +#if OLDROUTINENAMES + #define GetDirID(vRefNum, dirID, name, theDirID, isDirectory) GetDirectoryID(vRefNum, dirID, name, theDirID, isDirectory) +#endif +EXTERN_API( OSErr ) +GetDirectoryID( + short vRefNum, + long dirID, + ConstStr255Param name, + long * theDirID, + Boolean * isDirectory); + + +/* + The GetDirectoryID function gets the directory ID number of the + directory specified. If a file is specified, then the parent + directory of the file is returned and isDirectory is false. If + a directory is specified, then that directory's ID number is + returned and isDirectory is true. + WARNING: Volume names on the Macintosh are *not* unique -- Multiple + mounted volumes can have the same name. For this reason, the use of a + volume name or 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 volume name or full pathname is used, the File Manager + currently uses the first volume it finds with a matching name in the + volume queue. + + 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. + + 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 + 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 +*/ + +/*****************************************************************************/ + +#if OLDROUTINENAMES + #define DirIDFromFSSpec(spec, theDirID, isDirectory) FSpGetDirectoryID(spec, theDirID, isDirectory) +#endif +EXTERN_API( OSErr ) +FSpGetDirectoryID( + const FSSpec * spec, + long * theDirID, + Boolean * isDirectory); + + +/* + The FSpGetDirectoryID function gets the directory ID number of the + directory specified by spec. If spec is to a file, then the parent + directory of the file is returned and isDirectory is false. If + spec is to a directory, then that directory's ID number is + returned and isDirectory is true. + + spec input: An FSSpec record specifying the directory. + theDirID output: The directory ID. + isDirectory output: True if object is a directory; false if + object is a file. + + 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 + 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +GetDirName( + short vRefNum, + long dirID, + Str31 name); + + +/* + The GetDirName function gets the name of a directory from its + directory ID. + + vRefNum input: Volume specification. + dirID input: Directory ID. + name output: Points to a Str31 where the directory name is to be + returned. + + 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 + name parameter 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +GetIOACUser( + short vRefNum, + long dirID, + ConstStr255Param name, + SInt8 * ioACUser); + + +/* + GetIOACUser returns a directory's access restrictions byte. + Use the masks and macro defined in MoreFilesExtras to check for + specific access priviledges. + + 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. + ioACUser output: The access restriction byte + + 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 + 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpGetIOACUser( + const FSSpec * spec, + SInt8 * ioACUser); + + +/* + FSpGetIOACUser returns a directory's access restrictions byte. + Use the masks and macro defined in MoreFilesExtras to check for + specific access priviledges. + + spec input: An FSSpec record specifying the directory. + ioACUser output: The access restriction byte + + 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 + 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +GetParentID( + short vRefNum, + long dirID, + ConstStr255Param name, + long * parID); + + +/* + The GetParentID function gets the parent directory ID number of the + specified object. + + 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. + parID output: The parent directory ID of the specified object. + + 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 + 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +GetFilenameFromPathname( + ConstStr255Param pathname, + Str255 filename); + + +/* + The GetFilenameFromPathname function gets the file (or directory) name + from the end of a full or partial pathname. Returns notAFileErr if the + pathname is nil, the pathname is empty, or the pathname cannot refer to + a filename (with a noErr result, the pathname could still refer to a + directory). + + pathname input: A full or partial pathname. + filename output: The file (or directory) name. + + Result Codes + noErr 0 No error + notAFileErr -1302 The pathname is nil, the pathname + is empty, or the pathname cannot refer + to a filename + + __________ + + See also: GetObjectLocation. +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +GetObjectLocation( + short vRefNum, + long dirID, + ConstStr255Param pathname, + short * realVRefNum, + long * realParID, + Str255 realName, + Boolean * isDirectory); + + +/* + The GetObjectLocation function gets a file system object's location - + that is, its real volume reference number, real parent directory ID, + and name. While we're at it, determine if the object is a file or directory. + If GetObjectLocation returns fnfErr, then the location information + returned is valid, but it describes an object that doesn't exist. + You can use the location information for another operation, such as + creating a file or directory. + + vRefNum input: Volume specification. + dirID input: Directory ID. + pathname input: Pointer to object name, or nil when dirID specifies + a directory that's the object. + realVRefNum output: The real volume reference number. + realParID output: The parent directory ID of the specified object. + realName output: The name of the specified object (the case of the + object name may not be the same as the object's + catalog entry on disk - since the Macintosh file + system is not case sensitive, it shouldn't matter). + isDirectory output: True if object is a directory; false if object + is a file. + + 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 + dirNFErr -120 Directory not found or incomplete pathname + notAFileErr -1302 The pathname is nil, the pathname + is empty, or the pathname cannot refer + to a filename + afpAccessDenied -5000 User does not have the correct access + afpObjectTypeErr -5025 Directory not found or incomplete pathname + + __________ + + See also: FSMakeFSSpecCompat +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +GetDirItems( + short vRefNum, + long dirID, + ConstStr255Param name, + Boolean getFiles, + Boolean getDirectories, + FSSpecPtr items, + short reqItemCount, + short * actItemCount, + short * itemIndex); + + +/* + The GetDirItems function returns a list of items in the specified + directory in an array of FSSpec records. File, subdirectories, or + both can be returned in the list. + + A noErr result indicates that the items array was filled + (actItemCount == reqItemCount) and there may be additional items + left in the directory. A fnfErr result indicates that the end of + the directory list was found and actItemCount items were actually + found this time. + + 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. + getFiles input: Pass true to have files added to the items list. + getDirectories input: Pass true to have directories added to the + items list. + items input: Pointer to array of FSSpec where the item list + is returned. + reqItemCount input: Maximum number of items to return (the number + of elements in the items array). + actItemCount output: The number of items actually returned. + itemIndex input: The current item index position. Set to 1 to + start with the first item in the directory. + output: The item index position to get the next item. + Pass this value the next time you call + GetDirItems to start where you left off. + + Result Codes + noErr 0 No error, but there are more items + to list + nsvErr -35 No such volume + ioErr -36 I/O error + bdNamErr -37 Bad filename + fnfErr -43 File not found, there are no more items + to be listed. + paramErr -50 No default volume or itemIndex was <= 0 + 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 +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +DeleteDirectoryContents( + short vRefNum, + long dirID, + ConstStr255Param name); + + +/* + The DeleteDirectoryContents function deletes the contents of a directory. + All files and subdirectories in the specified directory are deleted. + If a locked file or directory is encountered, it is unlocked and then + deleted. If any unexpected errors are encountered, + DeleteDirectoryContents quits and returns to the caller. + + vRefNum input: Volume specification. + dirID input: Directory ID. + name input: Pointer to directory name, or nil when dirID specifies + a directory that's the object. + + 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 + paramErr -50 No default volume + 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 + + __________ + + Also see: DeleteDirectory +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +DeleteDirectory( + short vRefNum, + long dirID, + ConstStr255Param name); + + +/* + The DeleteDirectory function deletes a directory and its contents. + All files and subdirectories in the specified directory are deleted. + If a locked file or directory is encountered, it is unlocked and then + deleted. After deleting the directories contents, the directory is + deleted. If any unexpected errors are encountered, DeleteDirectory + quits and returns to the caller. + + vRefNum input: Volume specification. + dirID input: Directory ID. + name input: Pointer to directory name, or nil when dirID specifies + a directory that's the object. + + 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 + paramErr -50 No default volume + 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 + + __________ + + Also see: DeleteDirectoryContents +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +CheckObjectLock( + short vRefNum, + long dirID, + ConstStr255Param name); + + +/* + The CheckObjectLock function determines if a file or directory is locked. + If CheckObjectLock returns noErr, then the file or directory + is not locked. If CheckObjectLock returns fLckdErr, the it is locked. + + 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. + + 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 + fLckdErr -45 File is locked + paramErr -50 No default volume + 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 + + __________ + + Also see: FSpCheckObjectLock +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpCheckObjectLock(const FSSpec * spec); + + +/* + The FSpCheckObjectLock function determines if a file or directory is locked. + If FSpCheckObjectLock returns noErr, then the file or directory + is not locked. + + spec input: An FSSpec record specifying the object. + + 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 + fLckdErr -45 File is locked + paramErr -50 No default volume + 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 + + __________ + + Also see: CheckObjectLock +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +GetFileSize( + short vRefNum, + long dirID, + ConstStr255Param fileName, + long * dataSize, + long * rsrcSize); + + +/* + The GetFileSize function returns the logical size of a file's + data and resource fork. + + vRefNum input: Volume specification. + dirID input: Directory ID. + name input: The name of the file. + dataSize output: The number of bytes in the file's data fork. + rsrcSize output: The number of bytes in 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 + 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 + + __________ + + See also: FSpGetFileSize +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpGetFileSize( + const FSSpec * spec, + long * dataSize, + long * rsrcSize); + + +/* + The FSpGetFileSize function returns the logical size of a file's + data and resource fork. + + spec input: An FSSpec record specifying the file. + dataSize output: The number of bytes in the file's data fork. + rsrcSize output: The number of bytes in 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 + 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 + + __________ + + See also: GetFileSize +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +BumpDate( + short vRefNum, + long dirID, + ConstStr255Param name); + + +/* + The BumpDate function changes the modification date of a file or + directory to the current date/time. If the modification date is already + equal to the current date/time, then add one second to the + modification date. + + 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. + + 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 + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + paramErr -50 No default volume + 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: FSpBumpDate +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpBumpDate(const FSSpec * spec); + + +/* + The FSpBumpDate function changes the modification date of a file or + directory to the current date/time. If the modification date is already + equal to the current date/time, then add one second to the + modification date. + + spec input: An FSSpec record specifying the object. + + 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 + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + paramErr -50 No default volume + 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: BumpDate +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +ChangeCreatorType( + short vRefNum, + long dirID, + ConstStr255Param name, + OSType creator, + OSType fileType); + + +/* + The ChangeCreatorType function changes the creator or file type of a file. + + vRefNum input: Volume specification. + dirID input: Directory ID. + name input: The name of the file. + creator input: The new creator type or 0x00000000 to leave + the creator type alone. + fileType input: The new file type or 0x00000000 to leave the + file type alone. + + 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 + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + paramErr -50 No default volume + dirNFErr -120 Directory not found or incomplete pathname + notAFileErr -1302 Name was not a file + afpAccessDenied -5000 User does not have the correct access + afpObjectTypeErr -5025 Directory not found or incomplete pathname + + __________ + + See also: FSpChangeCreatorType +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpChangeCreatorType( + const FSSpec * spec, + OSType creator, + OSType fileType); + + +/* + The FSpChangeCreatorType function changes the creator or file type of a file. + + spec input: An FSSpec record specifying the file. + creator input: The new creator type or 0x00000000 to leave + the creator type alone. + fileType input: The new file type or 0x00000000 to leave the + file type alone. + + 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 + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + paramErr -50 No default volume + dirNFErr -120 Directory not found or incomplete pathname + notAFileErr -1302 Name was not a file + afpAccessDenied -5000 User does not have the correct access + afpObjectTypeErr -5025 Directory not found or incomplete pathname + + __________ + + See also: ChangeCreatorType +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +ChangeFDFlags( + short vRefNum, + long dirID, + ConstStr255Param name, + Boolean setBits, + unsigned short flagBits); + + +/* + The ChangeFDFlags function sets or clears Finder Flag bits in the + fdFlags field of a file or directory's FInfo record. + + 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. + setBits input: If true, then set the bits specified in flagBits. + If false, then clear the bits specified in flagBits. + flagBits input: The flagBits parameter specifies which Finder Flag + bits to set or clear. If a bit in flagBits is set, + then the same bit in fdFlags is either set or + cleared depending on the state of the setBits + parameter. + + 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 + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + paramErr -50 No default volume + 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: FSpChangeFDFlags +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpChangeFDFlags( + const FSSpec * spec, + Boolean setBits, + unsigned short flagBits); + + +/* + The FSpChangeFDFlags function sets or clears Finder Flag bits in the + fdFlags field of a file or directory's FInfo record. + + spec input: An FSSpec record specifying the object. + setBits input: If true, then set the bits specified in flagBits. + If false, then clear the bits specified in flagBits. + flagBits input: The flagBits parameter specifies which Finder Flag + bits to set or clear. If a bit in flagBits is set, + then the same bit in fdFlags is either set or + cleared depending on the state of the setBits + parameter. + + 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 + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + paramErr -50 No default volume + 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: ChangeFDFlags +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +SetIsInvisible( + short vRefNum, + long dirID, + ConstStr255Param name); + + +/* + The SetIsInvisible function sets the invisible bit in the fdFlags + word of the specified file or directory's finder information. + + 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. + + 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 + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + paramErr -50 No default volume + 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: FSpSetIsInvisible, ClearIsInvisible, FSpClearIsInvisible +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpSetIsInvisible(const FSSpec * spec); + + +/* + The FSpSetIsInvisible function sets the invisible bit in the fdFlags + word of the specified file or directory's finder information. + + spec input: An FSSpec record specifying the object. + + 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 + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + paramErr -50 No default volume + 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: SetIsInvisible, ClearIsInvisible, FSpClearIsInvisible +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +ClearIsInvisible( + short vRefNum, + long dirID, + ConstStr255Param name); + + +/* + The ClearIsInvisible function clears the invisible bit in the fdFlags + word of the specified file or directory's finder information. + + 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. + + 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 + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + paramErr -50 No default volume + 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: SetIsInvisible, FSpSetIsInvisible, FSpClearIsInvisible +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpClearIsInvisible(const FSSpec * spec); + + +/* + The FSpClearIsInvisible function clears the invisible bit in the fdFlags + word of the specified file or directory's finder information. + + spec input: An FSSpec record specifying the object. + + 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 + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + paramErr -50 No default volume + 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: SetIsInvisible, FSpSetIsInvisible, ClearIsInvisible +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +SetNameLocked( + short vRefNum, + long dirID, + ConstStr255Param name); + + +/* + The SetNameLocked function sets the nameLocked bit in the fdFlags word + of the specified file or directory's finder information. + + 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. + + 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 + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + paramErr -50 No default volume + 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: FSpSetNameLocked, ClearNameLocked, FSpClearNameLocked +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpSetNameLocked(const FSSpec * spec); + + +/* + The FSpSetNameLocked function sets the nameLocked bit in the fdFlags word + of the specified file or directory's finder information. + + spec input: An FSSpec record specifying the object. + + 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 + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + paramErr -50 No default volume + 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: SetNameLocked, ClearNameLocked, FSpClearNameLocked +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +ClearNameLocked( + short vRefNum, + long dirID, + ConstStr255Param name); + + +/* + The ClearNameLocked function clears the nameLocked bit in the fdFlags + word of the specified file or directory's finder information. + + 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. + + 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 + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + paramErr -50 No default volume + 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: SetNameLocked, FSpSetNameLocked, FSpClearNameLocked +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpClearNameLocked(const FSSpec * spec); + + +/* + The FSpClearNameLocked function clears the nameLocked bit in the fdFlags + word of the specified file or directory's finder information. + + spec input: An FSSpec record specifying the object. + + 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 + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + paramErr -50 No default volume + 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: SetNameLocked, FSpSetNameLocked, ClearNameLocked +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +SetIsStationery( + short vRefNum, + long dirID, + ConstStr255Param name); + + +/* + The SetIsStationery function sets the isStationery bit in the + fdFlags word of the specified file or directory's finder information. + + 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. + + 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 + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + paramErr -50 No default volume + 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: FSpSetIsStationery, ClearIsStationery, FSpClearIsStationery +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpSetIsStationery(const FSSpec * spec); + + +/* + The FSpSetIsStationery function sets the isStationery bit in the + fdFlags word of the specified file or directory's finder information. + + spec input: An FSSpec record specifying the object. + + 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 + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + paramErr -50 No default volume + 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: SetIsStationery, ClearIsStationery, FSpClearIsStationery +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +ClearIsStationery( + short vRefNum, + long dirID, + ConstStr255Param name); + + +/* + The ClearIsStationery function clears the isStationery bit in the + fdFlags word of the specified file or directory's finder information. + + 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. + + 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 + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + paramErr -50 No default volume + 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: SetIsStationery, FSpSetIsStationery, FSpClearIsStationery +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpClearIsStationery(const FSSpec * spec); + + +/* + The FSpClearIsStationery function clears the isStationery bit in the + fdFlags word of the specified file or directory's finder information. + + spec input: An FSSpec record specifying the object. + + 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 + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + paramErr -50 No default volume + 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: SetIsStationery, FSpSetIsStationery, ClearIsStationery +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +SetHasCustomIcon( + short vRefNum, + long dirID, + ConstStr255Param name); + + +/* + The SetHasCustomIcon function sets the hasCustomIcon bit in the + fdFlags word of the specified file or directory's finder information. + + 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. + + 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 + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + paramErr -50 No default volume + 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: FSpSetHasCustomIcon, ClearHasCustomIcon, FSpClearHasCustomIcon +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpSetHasCustomIcon(const FSSpec * spec); + + +/* + The FSpSetHasCustomIcon function sets the hasCustomIcon bit in the + fdFlags word of the specified file or directory's finder information. + + spec input: An FSSpec record specifying the object. + + 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 + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + paramErr -50 No default volume + 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: SetHasCustomIcon, ClearHasCustomIcon, FSpClearHasCustomIcon +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +ClearHasCustomIcon( + short vRefNum, + long dirID, + ConstStr255Param name); + + +/* + The ClearHasCustomIcon function clears the hasCustomIcon bit in the + fdFlags word of the specified file or directory's finder information. + + 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. + + 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 + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + paramErr -50 No default volume + 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: SetHasCustomIcon, FSpSetHasCustomIcon, FSpClearHasCustomIcon +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpClearHasCustomIcon(const FSSpec * spec); + + +/* + The FSpClearHasCustomIcon function clears the hasCustomIcon bit in the + fdFlags word of the specified file or directory's finder information. + + spec input: An FSSpec record specifying the object. + + 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 + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + paramErr -50 No default volume + 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: SetHasCustomIcon, FSpSetHasCustomIcon, ClearHasCustomIcon +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +ClearHasBeenInited( + short vRefNum, + long dirID, + ConstStr255Param name); + + +/* + The ClearHasBeenInited function clears the hasBeenInited bit in the + fdFlags word of the specified file or directory's finder information. + + 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. + + 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 + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + paramErr -50 No default volume + 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: FSpClearHasBeenInited +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpClearHasBeenInited(const FSSpec * spec); + + +/* + The FSpClearHasBeenInited function clears the hasBeenInited bit in the + fdFlags word of the specified file or directory's finder information. + + spec input: An FSSpec record specifying the object. + + 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 + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + paramErr -50 No default volume + 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: ClearHasBeenInited +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +CopyFileMgrAttributes( + short srcVRefNum, + long srcDirID, + ConstStr255Param srcName, + short dstVRefNum, + long dstDirID, + ConstStr255Param dstName, + Boolean copyLockBit); + + +/* + The CopyFileMgrAttributes function copies all File Manager attributes + from the source file or directory to the destination file or directory. + If copyLockBit is true, then set the locked state of the destination + to match the source. + + 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. + copyLockBit input: If true, set the locked state of the destination + to match the source. + + 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 + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + paramErr -50 No default volume + 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: FSpCopyFileMgrAttributes +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpCopyFileMgrAttributes( + const FSSpec * srcSpec, + const FSSpec * dstSpec, + Boolean copyLockBit); + + +/* + The FSpCopyFileMgrAttributes function copies all File Manager attributes + from the source file or directory to the destination file or directory. + If copyLockBit is true, then set the locked state of the destination + to match the source. + + srcSpec input: An FSSpec record specifying the source object. + dstSpec input: An FSSpec record specifying the destination object. + copyLockBit input: If true, set the locked state of the destination + to match the source. + + 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 + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + paramErr -50 No default volume + 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: CopyFileMgrAttributes +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +HOpenAware( + short vRefNum, + long dirID, + ConstStr255Param fileName, + short denyModes, + short * refNum); + + +/* + The HOpenAware function opens the data fork of a file using deny mode + permissions instead the normal File Manager permissions. If OpenDeny + is not available, then HOpenAware translates the deny modes to the + closest File Manager permissions and tries to open the file with + OpenDF first, and then Open if OpenDF isn't available. By using + HOpenAware with deny mode permissions, a program can be "AppleShare + aware" and fall back on the standard File Manager open calls + automatically. + + vRefNum input: Volume specification. + dirID input: Directory ID. + fileName input: The name of the file. + denyModes input: The deny modes access under which to open the file. + refNum output: The file reference number of the opened file. + + Result Codes + noErr 0 No error + nsvErr -35 No such volume + tmfoErr -42 Too many files open + fnfErr -43 File not found + wPrErr -44 Volume locked by hardware + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + opWrErr -49 File already open for writing + paramErr -50 No default volume + permErr -54 File is already open and cannot be opened using specified deny modes + afpAccessDenied -5000 User does not have the correct access to the file + afpDenyConflict -5006 Requested access permission not possible + + __________ + + See also: FSpOpenAware, HOpenRFAware, FSpOpenRFAware +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpOpenAware( + const FSSpec * spec, + short denyModes, + short * refNum); + + +/* + The FSpOpenAware function opens the data fork of a file using deny mode + permissions instead the normal File Manager permissions. If OpenDeny + is not available, then FSpOpenAware translates the deny modes to the + closest File Manager permissions and tries to open the file with + OpenDF first, and then Open if OpenDF isn't available. By using + FSpOpenAware with deny mode permissions, a program can be "AppleShare + aware" and fall back on the standard File Manager open calls + automatically. + + spec input: An FSSpec record specifying the file. + denyModes input: The deny modes access under which to open the file. + refNum output: The file reference number of the opened file. + + Result Codes + noErr 0 No error + nsvErr -35 No such volume + tmfoErr -42 Too many files open + fnfErr -43 File not found + wPrErr -44 Volume locked by hardware + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + opWrErr -49 File already open for writing + paramErr -50 No default volume + permErr -54 File is already open and cannot be opened using specified deny modes + afpAccessDenied -5000 User does not have the correct access to the file + afpDenyConflict -5006 Requested access permission not possible + + __________ + + See also: HOpenAware, HOpenRFAware, FSpOpenRFAware +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +HOpenRFAware( + short vRefNum, + long dirID, + ConstStr255Param fileName, + short denyModes, + short * refNum); + + +/* + The HOpenRFAware function opens the resource fork of a file using deny + mode permissions instead the normal File Manager permissions. If + OpenRFDeny is not available, then HOpenRFAware translates the deny + modes to the closest File Manager permissions and tries to open the + file with OpenRF. By using HOpenRFAware with deny mode permissions, + a program can be "AppleShare aware" and fall back on the standard + File Manager open calls automatically. + + vRefNum input: Volume specification. + dirID input: Directory ID. + fileName input: The name of the file. + denyModes input: The deny modes access under which to open the file. + refNum output: The file reference number of the opened file. + + Result Codes + noErr 0 No error + nsvErr -35 No such volume + tmfoErr -42 Too many files open + fnfErr -43 File not found + wPrErr -44 Volume locked by hardware + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + opWrErr -49 File already open for writing + paramErr -50 No default volume + permErr -54 File is already open and cannot be opened using specified deny modes + afpAccessDenied -5000 User does not have the correct access to the file + afpDenyConflict -5006 Requested access permission not possible + + __________ + + See also: HOpenAware, FSpOpenAware, FSpOpenRFAware +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpOpenRFAware( + const FSSpec * spec, + short denyModes, + short * refNum); + + +/* + The FSpOpenRFAware function opens the resource fork of a file using deny + mode permissions instead the normal File Manager permissions. If + OpenRFDeny is not available, then FSpOpenRFAware translates the deny + modes to the closest File Manager permissions and tries to open the + file with OpenRF. By using FSpOpenRFAware with deny mode permissions, + a program can be "AppleShare aware" and fall back on the standard + File Manager open calls automatically. + + spec input: An FSSpec record specifying the file. + denyModes input: The deny modes access under which to open the file. + refNum output: The file reference number of the opened file. + + Result Codes + noErr 0 No error + nsvErr -35 No such volume + tmfoErr -42 Too many files open + fnfErr -43 File not found + wPrErr -44 Volume locked by hardware + fLckdErr -45 File is locked + vLckdErr -46 Volume is locked or read-only + opWrErr -49 File already open for writing + paramErr -50 No default volume + permErr -54 File is already open and cannot be opened using specified deny modes + afpAccessDenied -5000 User does not have the correct access to the file + afpDenyConflict -5006 Requested access permission not possible + + __________ + + See also: HOpenAware, FSpOpenAware, HOpenRFAware +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSReadNoCache( + short refNum, + long * count, + void * buffPtr); + + +/* + The FSReadNoCache function reads any number of bytes from an open file + while asking the file system to bypass its cache mechanism. + + refNum input: The file reference number of an open file. + count input: The number of bytes to read. + output: The number of bytes actually read. + buffPtr input: A pointer to the data buffer into which the bytes are + to be read. + + Result Codes + noErr 0 No error + readErr Ð19 Driver does not respond to read 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 + ioErr Ð36 Data does not match in read-verify mode + fnOpnErr -38 File not open + rfNumErr -51 Bad reference number + afpAccessDenied -5000 User does not have the correct access to + the file + + __________ + + See also: FSWriteNoCache +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSWriteNoCache( + short refNum, + long * count, + const void * buffPtr); + + +/* + The FSReadNoCache function writes any number of bytes to an open file + while asking the file system to bypass its cache mechanism. + + refNum input: The file reference number of an open file. + count input: The number of bytes to write to the file. + output: The number of bytes actually written. + buffPtr input: A pointer to the data buffer from which the bytes are + to be written. + + Result Codes + noErr 0 No error + 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 Disk full + ioErr Ð36 Data does not match in read-verify mode + fnOpnErr -38 File not open + wPrErr -44 Hardware volume lock + fLckdErr -45 File is locked + vLckdErr -46 Software volume lock + rfNumErr -51 Bad reference number + wrPermErr -61 Read/write permission doesnÕt + allow writing + afpAccessDenied -5000 User does not have the correct access to + the file + + __________ + + See also: FSReadNoCache +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSWriteVerify( + short refNum, + long * count, + const void * buffPtr); + + +/* + The FSWriteVerify function writes any number of bytes to an open file + and then verifies that the data was actually written to the device. + + refNum input: The file reference number of an open file. + count input: The number of bytes to write to the file. + output: The number of bytes actually written and verified. + buffPtr input: A pointer to the data buffer from which the bytes are + to be written. + + 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 Disk full + ioErr Ð36 Data does not match in read-verify mode + fnOpnErr -38 File not open + eofErr -39 Logical end-of-file reached + posErr -40 Attempt to position mark before start + of file + wPrErr -44 Hardware volume lock + fLckdErr -45 File is locked + vLckdErr -46 Software volume lock + rfNumErr -51 Bad reference number + gfpErr -52 Error during GetFPos + wrPermErr -61 Read/write permission doesnÕt + allow writing + memFullErr -108 Not enough room in heap zone to allocate + verify buffer + afpAccessDenied -5000 User does not have the correct access to + the file +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +CopyFork( + short srcRefNum, + short dstRefNum, + void * copyBufferPtr, + long copyBufferSize); + + +/* + The CopyFork function copies all data from the source fork to the + destination fork of open file forks and makes sure the destination EOF + is equal to the source EOF. + + srcRefNum input: The source file reference number. + dstRefNum input: The destination file reference number. + copyBufferPtr input: Pointer to buffer to use during copy. The + buffer should be at least 512-bytes minimum. + The larger the buffer, the faster the copy. + copyBufferSize input: The size of the copy buffer. + + 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 Disk full + ioErr Ð36 Data does not match in read-verify mode + fnOpnErr -38 File not open + wPrErr -44 Hardware volume lock + fLckdErr -45 File is locked + vLckdErr -46 Software volume lock + rfNumErr -51 Bad reference number + wrPermErr -61 Read/write permission doesnÕt + allow writing + afpAccessDenied -5000 User does not have the correct access to + the file +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +GetFileLocation( + short refNum, + short * vRefNum, + long * dirID, + StringPtr fileName); + + +/* + The GetFileLocation function gets the location (volume reference number, + directory ID, and fileName) of an open file. + + refNum input: The file reference number of an open file. + vRefNum output: The volume reference number. + dirID output: The parent directory ID. + fileName input: Points to a buffer (minimum Str63) where the + filename is to be returned or must be nil. + output: The filename. + + Result Codes + noErr 0 No error + nsvErr -35 Specified volume doesnÕt exist + fnOpnErr -38 File not open + rfNumErr -51 Reference number specifies nonexistent + access path + + __________ + + See also: FSpGetFileLocation +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpGetFileLocation( + short refNum, + FSSpec * spec); + + +/* + The FSpGetFileLocation function gets the location of an open file in + an FSSpec record. + + refNum input: The file reference number of an open file. + spec output: FSSpec record containing the file name and location. + + Result Codes + noErr 0 No error + nsvErr -35 Specified volume doesnÕt exist + fnOpnErr -38 File not open + rfNumErr -51 Reference number specifies nonexistent + access path + + __________ + + See also: GetFileLocation +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +CopyDirectoryAccess( + short srcVRefNum, + long srcDirID, + ConstStr255Param srcName, + short dstVRefNum, + long dstDirID, + ConstStr255Param dstName); + + +/* + The CopyDirectoryAccess function copies the AFP directory access + privileges from one directory to another. Both directories must be on + the same file server, but not necessarily on the same server volume. + + srcVRefNum input: Source volume specification. + srcDirID input: Source directory ID. + srcName input: Pointer to source directory name, or nil when + srcDirID specifies the directory. + dstVRefNum input: Destination volume specification. + dstDirID input: Destination directory ID. + dstName input: Pointer to destination directory name, or nil when + dstDirID specifies the directory. + + Result Codes + noErr 0 No error + nsvErr -35 Volume not found + fnfErr -43 Directory not found + vLckdErr -46 Volume is locked or read-only + paramErr -50 Volume doesn't support this function + afpAccessDenied -5000 User does not have the correct access + to the directory + afpObjectTypeErr -5025 Object is a file, not a directory + + __________ + + See also: FSpCopyDirectoryAccess +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpCopyDirectoryAccess( + const FSSpec * srcSpec, + const FSSpec * dstSpec); + + +/* + The FSpCopyDirectoryAccess function copies the AFP directory access + privileges from one directory to another. Both directories must be on + the same file server, but not necessarily on the same server volume. + + srcSpec input: An FSSpec record specifying the source directory. + dstSpec input: An FSSpec record specifying the destination directory. + + Result Codes + noErr 0 No error + nsvErr -35 Volume not found + fnfErr -43 Directory not found + vLckdErr -46 Volume is locked or read-only + paramErr -50 Volume doesn't support this function + afpAccessDenied -5000 User does not have the correct access + to the directory + afpObjectTypeErr -5025 Object is a file, not a directory + + __________ + + See also: CopyDirectoryAccess +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +HMoveRenameCompat( + short vRefNum, + long srcDirID, + ConstStr255Param srcName, + long dstDirID, + ConstStr255Param dstpathName, + ConstStr255Param copyName); + + +/* + The HMoveRenameCompat function moves a file or directory and optionally + renames it. The source and destination locations must be on the same + volume. This routine works even if the volume doesn't support MoveRename. + + vRefNum input: Volume specification. + srcDirID input: Source directory ID. + srcName input: The source object name. + dstDirID input: Destination directory ID. + dstName input: Pointer to destination directory name, or + nil when dstDirID specifies a directory. + copyName input: Points to the new name if the object is to be + renamed or nil if the object isn't to be renamed. + + Result Codes + noErr 0 No error + dirFulErr -33 File directory full + dskFulErr -34 Disk is full + nsvErr -35 Volume not found + ioErr -36 I/O error + bdNamErr -37 Bad filename or attempt to move into + a file + fnfErr -43 Source file or directory not found + wPrErr -44 Hardware volume lock + fLckdErr -45 File is locked + vLckdErr -46 Destination volume is read-only + fBsyErr -47 File busy, directory not empty, or + working directory control block open + dupFNErr -48 Destination already exists + paramErr -50 Volume doesn't support this function, + no default volume, or source and + volOfflinErr -53 Volume is offline + fsRnErr -59 Problem during rename + dirNFErr -120 Directory not found or incomplete pathname + badMovErr -122 Attempted to move directory into + offspring + wrgVolTypErr -123 Not an HFS volume (it's a MFS volume) + notAFileErr -1302 The pathname is nil, the pathname + is empty, or the pathname cannot refer + to a filename + diffVolErr -1303 Files on different volumes + afpAccessDenied -5000 The user does not have the right to + move the file or directory + afpObjectTypeErr -5025 Directory not found or incomplete pathname + afpSameObjectErr -5038 Source and destination files are the same + + __________ + + See also: FSpMoveRenameCompat +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +FSpMoveRenameCompat( + const FSSpec * srcSpec, + const FSSpec * dstSpec, + ConstStr255Param copyName); + + +/* + The FSpMoveRenameCompat function moves a file or directory and optionally + renames it. The source and destination locations must be on the same + volume. This routine works even if the volume doesn't support MoveRename. + + srcSpec input: An FSSpec record specifying the source object. + dstSpec input: An FSSpec record specifying the destination + directory. + copyName input: Points to the new name if the object is to be + renamed or nil if the object isn't to be renamed. + + Result Codes + noErr 0 No error + dirFulErr -33 File directory full + dskFulErr -34 Disk is full + nsvErr -35 Volume not found + ioErr -36 I/O error + bdNamErr -37 Bad filename or attempt to move into + a file + fnfErr -43 Source file or directory not found + wPrErr -44 Hardware volume lock + fLckdErr -45 File is locked + vLckdErr -46 Destination volume is read-only + fBsyErr -47 File busy, directory not empty, or + working directory control block open + dupFNErr -48 Destination already exists + paramErr -50 Volume doesn't support this function, + no default volume, or source and + volOfflinErr -53 Volume is offline + fsRnErr -59 Problem during rename + dirNFErr -120 Directory not found or incomplete pathname + badMovErr -122 Attempted to move directory into + offspring + wrgVolTypErr -123 Not an HFS volume (it's a MFS volume) + notAFileErr -1302 The pathname is nil, the pathname + is empty, or the pathname cannot refer + to a filename + diffVolErr -1303 Files on different volumes + afpAccessDenied -5000 The user does not have the right to + move the file or directory + afpObjectTypeErr -5025 Directory not found or incomplete pathname + afpSameObjectErr -5038 Source and destination files are the same + + __________ + + See also: HMoveRenameCompat +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +BuildAFPVolMountInfo( + short flags, + char nbpInterval, + char nbpCount, + short uamType, + Str32 zoneName, + Str31 serverName, + Str27 volName, + Str31 userName, + Str8 userPassword, + Str8 volPassword, + AFPVolMountInfoPtr * afpInfoPtr); + + +/* + The BuildAFPVolMountInfo function allocates and initializes the fields + of an AFPVolMountInfo record before using that record to call + the VolumeMount function. + + flags input: The AFP mounting flags. 0 = normal mount; + set bit 0 to inhibit greeting messages. + nbpInterval input: The interval used for VolumeMount's + NBP Lookup call. 7 is a good choice. + nbpCount input: The retry count used for VolumeMount's + NBP Lookup call. 5 is a good choice. + uamType input: The user authentication method to use. + zoneName input: The AppleTalk zone name of the server. + serverName input: The AFP server name. + volName input: The AFP volume name. + userName input: The user name (zero length Pascal string for + guest). + userPassWord input: The user password (zero length Pascal string + if no user password) + volPassWord input: The volume password (zero length Pascal string + if no volume password) + afpInfoPtr output: A pointer to the newly created and initialized + AFPVolMountInfo record. If the function fails to + create an AFPVolMountInfo record, it sets + afpInfoPtr to NULL and the function result is + memFullErr. Your program is responsible + for disposing of this pointer when it is finished + with it. + + Result Codes + noErr 0 No error + memFullErr -108 memory full error + + __________ + + Also see: GetVolMountInfoSize, GetVolMountInfo, VolumeMount, + RetrieveAFPVolMountInfo, BuildAFPXVolMountInfo, + RetrieveAFPXVolMountInfo +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +RetrieveAFPVolMountInfo( + AFPVolMountInfoPtr afpInfoPtr, + short * flags, + short * uamType, + StringPtr zoneName, + StringPtr serverName, + StringPtr volName, + StringPtr userName); + + +/* + The RetrieveAFPVolMountInfo function retrieves the AFP mounting + information returned in an AFPVolMountInfo record by the + GetVolMountInfo function. + + afpInfoPtr input: Pointer to AFPVolMountInfo record that contains + the AFP mounting information. + flags output: The AFP mounting flags. + uamType output: The user authentication method used. + zoneName output: The AppleTalk zone name of the server. + serverName output: The AFP server name. + volName output: The AFP volume name. + userName output: The user name (zero length Pascal string for + guest). + + Result Codes + noErr 0 No error + paramErr -50 media field in AFP mounting information + was not AppleShareMediaType + + __________ + + Also see: GetVolMountInfoSize, GetVolMountInfo, VolumeMount, + BuildAFPVolMountInfo, BuildAFPXVolMountInfo, + RetrieveAFPXVolMountInfo +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +BuildAFPXVolMountInfo( + short flags, + char nbpInterval, + char nbpCount, + short uamType, + Str32 zoneName, + Str31 serverName, + Str27 volName, + Str31 userName, + Str8 userPassword, + Str8 volPassword, + Str32 uamName, + unsigned long alternateAddressLength, + void * alternateAddress, + AFPXVolMountInfoPtr * afpXInfoPtr); + + +/* + The BuildAFPXVolMountInfo function allocates and initializes the fields + of an AFPXVolMountInfo record before using that record to call + the VolumeMount function. + + flags input: The AFP mounting flags. + nbpInterval input: The interval used for VolumeMount's + NBP Lookup call. 7 is a good choice. + nbpCount input: The retry count used for VolumeMount's + NBP Lookup call. 5 is a good choice. + uamType input: The user authentication method to use. + zoneName input: The AppleTalk zone name of the server. + serverName input: The AFP server name. + volName input: The AFP volume name. + userName input: The user name (zero length Pascal string + for guest). + userPassWord input: The user password (zero length Pascal + string if no user password) + volPassWord input: The volume password (zero length Pascal + string if no volume password) + uamName input: The User Authentication Method name. + alternateAddressLength input: Length of alternateAddress data. + alternateAddress input The AFPAlternateAddress (variable length) + afpXInfoPtr output: A pointer to the newly created and + initialized AFPVolMountInfo record. + If the function fails to create an + AFPVolMountInfo record, it sets + afpInfoPtr to NULL and the function + result is memFullErr. Your program is + responsible for disposing of this pointer + when it is finished with it. + + Result Codes + noErr 0 No error + memFullErr -108 memory full error + + __________ + + Also see: GetVolMountInfoSize, GetVolMountInfo, VolumeMount, + BuildAFPVolMountInfo, RetrieveAFPVolMountInfo, + RetrieveAFPXVolMountInfo +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +RetrieveAFPXVolMountInfo( + AFPXVolMountInfoPtr afpXInfoPtr, + short * flags, + short * uamType, + StringPtr zoneName, + StringPtr serverName, + StringPtr volName, + StringPtr userName, + StringPtr uamName, + unsigned long * alternateAddressLength, + AFPAlternateAddress ** alternateAddress); + + +/* + The RetrieveAFPXVolMountInfo function retrieves the AFP mounting + information returned in an AFPXVolMountInfo record by the + GetVolMountInfo function. + + afpXInfoPtr input: Pointer to AFPXVolMountInfo record that + contains the AFP mounting information. + flags output: The AFP mounting flags. + uamType output: The user authentication method used. + zoneName output: The AppleTalk zone name of the server. + serverName output: The AFP server name. + volName output: The AFP volume name. + userName output: The user name (zero length Pascal + string for guest). + uamName output: The User Authentication Method name. + alternateAddressLength output: Length of alternateAddress data returned. + alternateAddress: output: A pointer to the newly created and + AFPAlternateAddress record (a variable + length record). If the function fails to + create an AFPAlternateAddress record, + it sets alternateAddress to NULL and the + function result is memFullErr. Your + program is responsible for disposing of + this pointer when it is finished with it. + + Result Codes + noErr 0 No error + paramErr -50 media field in AFP mounting information + was not AppleShareMediaType + memFullErr -108 memory full error + + __________ + + Also see: GetVolMountInfoSize, GetVolMountInfo, VolumeMount, + BuildAFPVolMountInfo, RetrieveAFXVolMountInfo, + BuildAFPXVolMountInfo +*/ + +/*****************************************************************************/ + +EXTERN_API( OSErr ) +GetUGEntries( + short objType, + UGEntryPtr entries, + long reqEntryCount, + long * actEntryCount, + long * objID); + + +/* + The GetUGEntries functions retrieves a list of user or group entries + from the local file server. + + objType input: The object type: -1 = group; 0 = user + UGEntries input: Pointer to array of UGEntry records where the list + is returned. + reqEntryCount input: The number of elements in the UGEntries array. + actEntryCount output: The number of entries returned. + objID input: The current index position. Set to 0 to start with + the first entry. + output: The index position to get the next entry. Pass this + value the next time you call GetUGEntries to start + where you left off. + + Result Codes + noErr 0 No error + fnfErr -43 No more users or groups + paramErr -50 Function not supported; or, ioObjID is + negative + + __________ + + Also see: GetUGEntry +*/ + +/*****************************************************************************/ + + + +#include "OptimizationEnd.h" + +#if PRAGMA_STRUCT_ALIGN + #pragma options align=reset +#elif PRAGMA_STRUCT_PACKPUSH + #pragma pack(pop) +#elif PRAGMA_STRUCT_PACK + #pragma pack() +#endif + +#ifdef PRAGMA_IMPORT_OFF +#pragma import off +#elif PRAGMA_IMPORT +#pragma import reset +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __MOREFILESEXTRAS__ */ + diff --git a/src/mac/morefile/Optim.h b/src/mac/morefile/Optim.h deleted file mode 100644 index ff5a1d5d57..0000000000 --- a/src/mac/morefile/Optim.h +++ /dev/null @@ -1,120 +0,0 @@ -/* -** 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 -*/ - -#if TARGET_CARBON - - #define __MACOSSEVENFIVEONEORLATER 1 - - #define __MACOSSEVENORLATER 1 - - #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 -#else - - // we have a basic requirements of 7.5.3 Rev 2 or 7.6 - - #define __MACOSSEVENFIVEONEORLATER 1 - - #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 -#endif diff --git a/src/mac/morefile/OptimEnd.h b/src/mac/morefile/OptimEnd.h deleted file mode 100644 index 5cab00a593..0000000000 --- a/src/mac/morefile/OptimEnd.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -** 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 diff --git a/src/mac/morefile/Optimization.h b/src/mac/morefile/Optimization.h new file mode 100644 index 0000000000..d2673f9304 --- /dev/null +++ b/src/mac/morefile/Optimization.h @@ -0,0 +1,109 @@ +/* + File: Optimization.h + + Contains: Defines that let you make MoreFiles code more efficient. + + Version: MoreFiles + + Copyright: © 1992-2001 by 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. + + File Ownership: + + DRI: Apple Macintosh Developer Technical Support + + Other Contact: Apple Macintosh Developer Technical Support + + + Technology: DTS Sample Code + + Writers: + + (JL) Jim Luther + + Change History (most recent first): + + <1> 2/7/01 JL first checked in +*/ + +/* + 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 + + If you're compiling 68K code, the default is to include all compatibility code. + If you're compiling PowerPC code (TARGET_RT_MAC_CFM), the default is __MACOSSEVENORLATER + If you're compiling for Carbon code (TARGET_API_MAC_CARBON), the default is __MACOSSEVENFIVEONEORLATER + + 2 -- You may disable Pascal calling conventions in all MoreFiles routines + except for system callbacks that require Pascal calling conventions. + This will make 68K C programs both smaller and faster. + (PowerPC compilers ignore pascal calling conventions.) + 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 +*/ + +#include + +// if we're compiling for Carbon, then we're running on Mac OS 8.1 or later +#ifndef __MACOSSEVENFIVEONEORLATER + #define __MACOSSEVENFIVEONEORLATER TARGET_API_MAC_CARBON +#endif + +#ifndef __MACOSSEVENFIVEORLATER + #define __MACOSSEVENFIVEORLATER __MACOSSEVENFIVEONEORLATER +#endif + +#ifndef __MACOSSEVENORLATER + #if TARGET_RT_MAC_CFM + #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 diff --git a/src/mac/morefile/OptimizationEnd.h b/src/mac/morefile/OptimizationEnd.h new file mode 100644 index 0000000000..10ed02507f --- /dev/null +++ b/src/mac/morefile/OptimizationEnd.h @@ -0,0 +1,56 @@ +/* + File: OptimizationEnd.h + + Contains: Defines that let you make MoreFiles code more efficient. + + Version: MoreFiles + + Copyright: © 1992-2001 by 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. + + File Ownership: + + DRI: Apple Macintosh Developer Technical Support + + Other Contact: Apple Macintosh Developer Technical Support + + + Technology: DTS Sample Code + + Writers: + + (JL) Jim Luther + + Change History (most recent first): + + <1> 2/7/01 JL first checked in +*/ + +/* + 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 diff --git a/src/mac/morefile/Search.c b/src/mac/morefile/Search.c new file mode 100644 index 0000000000..6f7953b830 --- /dev/null +++ b/src/mac/morefile/Search.c @@ -0,0 +1,1300 @@ +/* + File: Search.c + + Contains: IndexedSearch and the PBCatSearch compatibility function. + + Version: MoreFiles + + Copyright: © 1992-2001 by 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. + + File Ownership: + + DRI: Jim Luther + + Other Contact: Apple Macintosh Developer Technical Support + + + Technology: DTS Sample Code + + Writers: + + (JL) Jim Luther + + Change History (most recent first): + + <2> 2/7/01 JL Added standard header. Updated names of includes. Updated + various routines to use new calling convention of the + MoreFilesExtras accessor functions. Added TARGET_API_MAC_CARBON + conditional checks around TimeOutTask. + <1> 12/06/99 JL MoreFiles 1.5. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#define __COMPILINGMOREFILES + +#include "MoreFiles.h" +#include "MoreFilesExtras.h" + +#include "Search.h" + +/*****************************************************************************/ + +enum +{ + /* Number of LevelRecs to add each time the searchStack is grown */ + /* 20 levels is probably more than reasonable for most volumes. */ + /* If more are needed, they are allocated 20 levels at a time. */ + kAdditionalLevelRecs = 20 +}; + +/*****************************************************************************/ + +/* +** LevelRecs are used to store the directory ID and index whenever +** IndexedSearch needs to either scan a sub-directory, or return control +** to the caller because the call has timed out or the number of +** matches requested has been found. LevelRecs are stored in an array +** used as a stack. +*/ +struct LevelRec +{ + long dirModDate; /* for detecting most (but not all) catalog changes */ + long dirID; + short index; +}; +typedef struct LevelRec LevelRec; +typedef LevelRec *LevelRecPtr, **LevelRecHandle; + + +/* +** SearchPositionRec is my version of a CatPositionRec. It holds the +** information I need to resuming searching. +*/ +#if PRAGMA_STRUCT_ALIGN +#pragma options align=mac68k +#endif +struct SearchPositionRec +{ + long initialize; /* Goofy checksum of volume information used to make */ + /* sure we're resuming a search on the same volume. */ + unsigned short stackDepth; /* Current depth on searchStack. */ + short priv[11]; /* For future use... */ +}; +#if PRAGMA_STRUCT_ALIGN +#pragma options align=reset +#endif +typedef struct SearchPositionRec SearchPositionRec; +typedef SearchPositionRec *SearchPositionRecPtr; + + +/* +** ExtendedTMTask is a TMTask record extended to hold the timer flag. +*/ +#if PRAGMA_STRUCT_ALIGN +#pragma options align=mac68k +#endif +struct ExtendedTMTask +{ + TMTask theTask; + Boolean stopSearch; /* the Time Mgr task will set stopSearch to */ + /* true when the timer expires */ +}; +#if PRAGMA_STRUCT_ALIGN +#pragma options align=reset +#endif +typedef struct ExtendedTMTask ExtendedTMTask; +typedef ExtendedTMTask *ExtendedTMTaskPtr; + +/*****************************************************************************/ + +static OSErr CheckVol(ConstStr255Param pathname, + short vRefNum, + short *realVRefNum, + long *volID); + +static OSErr CheckStack(unsigned short stackDepth, + LevelRecHandle searchStack, + Size *searchStackSize); + +static OSErr VerifyUserPB(CSParamPtr userPB, + Boolean *includeFiles, + Boolean *includeDirs, + Boolean *includeNames); + +static Boolean IsSubString(ConstStr255Param aStringPtr, + ConstStr255Param subStringPtr); + +static Boolean CompareMasked(const long *data1, + const long *data2, + const long *mask, + short longsToCompare); + +static void CheckForMatches(CInfoPBPtr cPB, + CSParamPtr userPB, + const Str63 matchName, + Boolean includeFiles, + Boolean includeDirs); + +#if __WANTPASCALELIMINATION +#undef pascal +#endif + +#if TARGET_RT_MAC_CFM || TARGET_API_MAC_CARBON + +static pascal void TimeOutTask(TMTaskPtr tmTaskPtr); + +#else + +static pascal TMTaskPtr GetTMTaskPtr(void); + +static void TimeOutTask(void); + +#endif + +#if __WANTPASCALELIMINATION +#define pascal +#endif + +static long GetDirModDate(short vRefNum, + long dirID); + +/*****************************************************************************/ + +/* +** CheckVol gets the volume's real vRefNum and builds a volID. The volID +** is used to help insure that calls to resume searching with IndexedSearch +** are to the same volume as the last call to IndexedSearch. +*/ +static OSErr CheckVol(ConstStr255Param pathname, + short vRefNum, + short *realVRefNum, + long *volID) +{ + HParamBlockRec pb; + OSErr error; + + error = GetVolumeInfoNoName(pathname, vRefNum, &pb); + if ( error == noErr ) + { + /* Return the real vRefNum */ + *realVRefNum = pb.volumeParam.ioVRefNum; + + /* Add together a bunch of things that aren't supposed to change on */ + /* a mounted volume that's being searched and that should come up with */ + /* a fairly unique number */ + *volID = pb.volumeParam.ioVCrDate + + pb.volumeParam.ioVRefNum + + pb.volumeParam.ioVNmAlBlks + + pb.volumeParam.ioVAlBlkSiz + + pb.volumeParam.ioVFSID; + } + return ( error ); +} + +/*****************************************************************************/ + +/* +** CheckStack checks the size of the search stack (array) to see if there's +** room to push another LevelRec. If not, CheckStack grows the stack by +** another kAdditionalLevelRecs elements. +*/ +static OSErr CheckStack(unsigned short stackDepth, + LevelRecHandle searchStack, + Size *searchStackSize) +{ + OSErr result; + + if ( (*searchStackSize / sizeof(LevelRec)) == (stackDepth + 1) ) + { + /* Time to grow stack */ + SetHandleSize((Handle)searchStack, *searchStackSize + (kAdditionalLevelRecs * sizeof(LevelRec))); + result = MemError(); /* should be noErr */ + *searchStackSize = GetHandleSize((Handle)searchStack); + } + else + { + result = noErr; + } + + return ( result ); +} + +/*****************************************************************************/ + +/* +** VerifyUserPB makes sure the parameter block passed to IndexedSearch has +** valid parameters. By making this check once, we don't have to worry about +** things like NULL pointers, strings being too long, etc. +** VerifyUserPB also determines if the search includes files and/or +** directories, and determines if a full or partial name search was requested. +*/ +static OSErr VerifyUserPB(CSParamPtr userPB, + Boolean *includeFiles, + Boolean *includeDirs, + Boolean *includeNames) +{ + CInfoPBPtr searchInfo1; + CInfoPBPtr searchInfo2; + + searchInfo1 = userPB->ioSearchInfo1; + searchInfo2 = userPB->ioSearchInfo2; + + /* ioMatchPtr cannot be NULL */ + if ( userPB->ioMatchPtr == NULL ) + { + goto ParamErrExit; + } + + /* ioSearchInfo1 cannot be NULL */ + if ( searchInfo1 == NULL ) + { + goto ParamErrExit; + } + + /* If any bits except partialName, fullName, or negate are set, then */ + /* ioSearchInfo2 cannot be NULL because information in ioSearchInfo2 is required */ + if ( ((userPB->ioSearchBits & ~(fsSBPartialName | fsSBFullName | fsSBNegate)) != 0) && + ( searchInfo2 == NULL )) + { + goto ParamErrExit; + } + + *includeFiles = false; + *includeDirs = false; + *includeNames = false; + + if ( (userPB->ioSearchBits & (fsSBPartialName | fsSBFullName)) != 0 ) + { + /* If any kind of name matching is requested, then ioNamePtr in */ + /* ioSearchInfo1 cannot be NULL or a zero-length string */ + if ( (searchInfo1->hFileInfo.ioNamePtr == NULL) || + (searchInfo1->hFileInfo.ioNamePtr[0] == 0) || + (searchInfo1->hFileInfo.ioNamePtr[0] > (sizeof(Str63) - 1)) ) + { + goto ParamErrExit; + } + + *includeNames = true; + } + + if ( (userPB->ioSearchBits & fsSBFlAttrib) != 0 ) + { + /* The only attributes you can search on are the directory flag */ + /* and the locked flag. */ + if ( (searchInfo2->hFileInfo.ioFlAttrib & ~(kioFlAttribDirMask | kioFlAttribLockedMask)) != 0 ) + { + goto ParamErrExit; + } + + /* interested in the directory bit? */ + if ( (searchInfo2->hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 ) + { + /* yes, so do they want just directories or just files? */ + if ( (searchInfo1->hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 ) + { + *includeDirs = true; + } + else + { + *includeFiles = true; + } + } + else + { + /* no interest in directory bit - get both files and directories */ + *includeDirs = true; + *includeFiles = true; + } + } + else + { + /* no attribute checking - get both files and directories */ + *includeDirs = true; + *includeFiles = true; + } + + /* If directories are included in the search, */ + /* then the locked attribute cannot be requested. */ + if ( *includeDirs && + ((userPB->ioSearchBits & fsSBFlAttrib) != 0) && + ((searchInfo2->hFileInfo.ioFlAttrib & kioFlAttribLockedMask) != 0) ) + { + goto ParamErrExit; + } + + /* If files are included in the search, then there cannot be */ + /* a search on the number of files. */ + if ( *includeFiles && + ((userPB->ioSearchBits & fsSBDrNmFls) != 0) ) + { + goto ParamErrExit; + } + + /* If directories are included in the search, then there cannot */ + /* be a search on file lengths. */ + if ( *includeDirs && + ((userPB->ioSearchBits & (fsSBFlLgLen | fsSBFlPyLen | fsSBFlRLgLen | fsSBFlRPyLen)) != 0) ) + { + goto ParamErrExit; + } + + return ( noErr ); + +ParamErrExit: + return ( paramErr ); +} + +/*****************************************************************************/ + +/* +** IsSubString checks to see if a string is a substring of another string. +** Both input strings have already been converted to all uppercase using +** UprString (the same non-international call the File Manager uses). +*/ +static Boolean IsSubString(ConstStr255Param aStringPtr, + ConstStr255Param subStringPtr) +{ + short strLength; /* length of string */ + short subStrLength; /* length of subString */ + Boolean found; /* result of test */ + short index; /* current index into string */ + + found = false; + strLength = aStringPtr[0]; + subStrLength = subStringPtr[0]; + + if ( subStrLength <= strLength) + { + register short count; /* search counter */ + register short strIndex; /* running index into string */ + register short subStrIndex; /* running index into subString */ + + /* start looking at first character */ + index = 1; + + /* continue looking until remaining string is shorter than substring */ + count = strLength - subStrLength + 1; + + do + { + strIndex = index; /* start string index at index */ + subStrIndex = 1; /* start subString index at 1 */ + + while ( !found && (aStringPtr[strIndex] == subStringPtr[subStrIndex]) ) + { + if ( subStrIndex == subStrLength ) + { + /* all characters in subString were found */ + found = true; + } + else + { + /* check next character of substring against next character of string */ + ++subStrIndex; + ++strIndex; + } + } + + if ( !found ) + { + /* start substring search again at next string character */ + ++index; + --count; + } + } while ( count != 0 && (!found) ); + } + + return ( found ); +} + +/*****************************************************************************/ + +/* +** CompareMasked does a bitwise comparison with mask on 1 or more longs. +** data1 and data2 are first exclusive-ORed together resulting with bits set +** where they are different. That value is then ANDed with the mask resulting +** with bits set if the test fails. true is returned if the tests pass. +*/ +static Boolean CompareMasked(const long *data1, + const long *data2, + const long *mask, + short longsToCompare) +{ + Boolean result = true; + + while ( (longsToCompare != 0) && (result == true) ) + { + /* (*data1 ^ *data2) = bits that are different, so... */ + /* ((*data1 ^ *data2) & *mask) = bits that are different that we're interested in */ + + if ( ((*data1 ^ *data2) & *mask) != 0 ) + result = false; + + ++data1; + ++data2; + ++mask; + --longsToCompare; + } + + return ( result ); +} + +/*****************************************************************************/ + +/* +** Check for matches compares the search criteria in userPB to the file +** system object in cPB. If there's a match, then the information in cPB is +** is added to the match array and the actual match count is incremented. +*/ +static void CheckForMatches(CInfoPBPtr cPB, + CSParamPtr userPB, + const Str63 matchName, + Boolean includeFiles, + Boolean includeDirs) +{ + long searchBits; + CInfoPBPtr searchInfo1; + CInfoPBPtr searchInfo2; + Str63 itemName; /* copy of object's name for partial name matching */ + Boolean foundMatch; + + foundMatch = false; /* default to no match */ + + searchBits = userPB->ioSearchBits; + searchInfo1 = userPB->ioSearchInfo1; + searchInfo2 = userPB->ioSearchInfo2; + + /* Into the if statements that go on forever... */ + + if ( (cPB->hFileInfo.ioFlAttrib & kioFlAttribDirMask) == 0 ) + { + if (!includeFiles) + { + goto Failed; + } + } + else + { + if (!includeDirs) + { + goto Failed; + } + } + + if ( (searchBits & fsSBPartialName) != 0 ) + { + if ( (cPB->hFileInfo.ioNamePtr[0] > 0) && + (cPB->hFileInfo.ioNamePtr[0] <= (sizeof(Str63) - 1)) ) + { + /* Make uppercase copy of object name */ + BlockMoveData(cPB->hFileInfo.ioNamePtr, + itemName, + cPB->hFileInfo.ioNamePtr[0] + 1); + /* Use the same non-international call the File Manager uses */ + UpperString(itemName, true); + } + else + { + goto Failed; + } + + { + if ( !IsSubString(itemName, matchName) ) + { + goto Failed; + } + else if ( searchBits == fsSBPartialName ) + { + /* optimize for name matching only since it is most common way to search */ + goto Hit; + } + } + } + + if ( (searchBits & fsSBFullName) != 0 ) + { + /* Use the same non-international call the File Manager uses */ + if ( !EqualString(cPB->hFileInfo.ioNamePtr, matchName, false, true) ) + { + goto Failed; + } + else if ( searchBits == fsSBFullName ) + { + /* optimize for name matching only since it is most common way to search */ + goto Hit; + } + } + + if ( (searchBits & fsSBFlParID) != 0 ) + { + if ( ((unsigned long)(cPB->hFileInfo.ioFlParID) < (unsigned long)(searchInfo1->hFileInfo.ioFlParID)) || + ((unsigned long)(cPB->hFileInfo.ioFlParID) > (unsigned long)(searchInfo2->hFileInfo.ioFlParID)) ) + { + goto Failed; + } + } + + if ( (searchBits & fsSBFlAttrib) != 0 ) + { + if ( ((cPB->hFileInfo.ioFlAttrib ^ searchInfo1->hFileInfo.ioFlAttrib) & + searchInfo2->hFileInfo.ioFlAttrib) != 0 ) + { + goto Failed; + } + } + + if ( (searchBits & fsSBDrNmFls) != 0 ) + { + if ( ((unsigned long)(cPB->dirInfo.ioDrNmFls) < (unsigned long)(searchInfo1->dirInfo.ioDrNmFls)) || + ((unsigned long)(cPB->dirInfo.ioDrNmFls) > (unsigned long)(searchInfo2->dirInfo.ioDrNmFls)) ) + { + goto Failed; + } + } + + if ( (searchBits & fsSBFlFndrInfo) != 0 ) /* fsSBFlFndrInfo is same as fsSBDrUsrWds */ + { + if ( !CompareMasked((long *)&(cPB->hFileInfo.ioFlFndrInfo), + (long *)&(searchInfo1->hFileInfo.ioFlFndrInfo), + (long *)&(searchInfo2->hFileInfo.ioFlFndrInfo), + sizeof(FInfo) / sizeof(long)) ) + { + goto Failed; + } + } + + if ( (searchBits & fsSBFlXFndrInfo) != 0 ) /* fsSBFlXFndrInfo is same as fsSBDrFndrInfo */ + { + if ( !CompareMasked((long *)&(cPB->hFileInfo.ioFlXFndrInfo), + (long *)&(searchInfo1->hFileInfo.ioFlXFndrInfo), + (long *)&(searchInfo2->hFileInfo.ioFlXFndrInfo), + sizeof(FXInfo) / sizeof(long)) ) + { + goto Failed; + } + } + + if ( (searchBits & fsSBFlLgLen) != 0 ) + { + if ( ((unsigned long)(cPB->hFileInfo.ioFlLgLen) < (unsigned long)(searchInfo1->hFileInfo.ioFlLgLen)) || + ((unsigned long)(cPB->hFileInfo.ioFlLgLen) > (unsigned long)(searchInfo2->hFileInfo.ioFlLgLen)) ) + { + goto Failed; + } + } + + if ( (searchBits & fsSBFlPyLen) != 0 ) + { + if ( ((unsigned long)(cPB->hFileInfo.ioFlPyLen) < (unsigned long)(searchInfo1->hFileInfo.ioFlPyLen)) || + ((unsigned long)(cPB->hFileInfo.ioFlPyLen) > (unsigned long)(searchInfo2->hFileInfo.ioFlPyLen)) ) + { + goto Failed; + } + } + + if ( (searchBits & fsSBFlRLgLen) != 0 ) + { + if ( ((unsigned long)(cPB->hFileInfo.ioFlRLgLen) < (unsigned long)(searchInfo1->hFileInfo.ioFlRLgLen)) || + ((unsigned long)(cPB->hFileInfo.ioFlRLgLen) > (unsigned long)(searchInfo2->hFileInfo.ioFlRLgLen)) ) + { + goto Failed; + } + } + + if ( (searchBits & fsSBFlRPyLen) != 0 ) + { + if ( ((unsigned long)(cPB->hFileInfo.ioFlRPyLen) < (unsigned long)(searchInfo1->hFileInfo.ioFlRPyLen)) || + ((unsigned long)(cPB->hFileInfo.ioFlRPyLen) > (unsigned long)(searchInfo2->hFileInfo.ioFlRPyLen)) ) + { + goto Failed; + } + } + + if ( (searchBits & fsSBFlCrDat) != 0 ) /* fsSBFlCrDat is same as fsSBDrCrDat */ + { + if ( ((unsigned long)(cPB->hFileInfo.ioFlCrDat) < (unsigned long)(searchInfo1->hFileInfo.ioFlCrDat)) || + ((unsigned long)(cPB->hFileInfo.ioFlCrDat) > (unsigned long)(searchInfo2->hFileInfo.ioFlCrDat)) ) + { + goto Failed; + } + } + + if ( (searchBits & fsSBFlMdDat) != 0 ) /* fsSBFlMdDat is same as fsSBDrMdDat */ + { + if ( ((unsigned long)(cPB->hFileInfo.ioFlMdDat) < (unsigned long)(searchInfo1->hFileInfo.ioFlMdDat)) || + ((unsigned long)(cPB->hFileInfo.ioFlMdDat) > (unsigned long)(searchInfo2->hFileInfo.ioFlMdDat)) ) + { + goto Failed; + } + } + + if ( (searchBits & fsSBFlBkDat) != 0 ) /* fsSBFlBkDat is same as fsSBDrBkDat */ + { + if ( ((unsigned long)(cPB->hFileInfo.ioFlBkDat) < (unsigned long)(searchInfo1->hFileInfo.ioFlBkDat)) || + ((unsigned long)(cPB->hFileInfo.ioFlBkDat) > (unsigned long)(searchInfo2->hFileInfo.ioFlBkDat)) ) + { + goto Failed; + } + } + + /* Hey, we passed all of the tests! */ + +Hit: + foundMatch = true; + +/* foundMatch is false if code jumps to Failed */ +Failed: + /* Do we reverse our findings? */ + if ( (searchBits & fsSBNegate) != 0 ) + { + foundMatch = !foundMatch; /* matches are not, not matches are */ + } + + if ( foundMatch ) + { + + /* Move the match into the match buffer */ + userPB->ioMatchPtr[userPB->ioActMatchCount].vRefNum = cPB->hFileInfo.ioVRefNum; + userPB->ioMatchPtr[userPB->ioActMatchCount].parID = cPB->hFileInfo.ioFlParID; + if ( cPB->hFileInfo.ioNamePtr[0] > 63 ) + { + cPB->hFileInfo.ioNamePtr[0] = 63; + } + BlockMoveData(cPB->hFileInfo.ioNamePtr, + userPB->ioMatchPtr[userPB->ioActMatchCount].name, + cPB->hFileInfo.ioNamePtr[0] + 1); + + /* increment the actual count */ + ++(userPB->ioActMatchCount); + } +} + +/*****************************************************************************/ + +/* +** TimeOutTask is executed when the timer goes off. It simply sets the +** stopSearch field to true. After each object is found and possibly added +** to the matches buffer, stopSearch is checked to see if the search should +** continue. +*/ + +#if __WANTPASCALELIMINATION +#undef pascal +#endif + +#if TARGET_RT_MAC_CFM || TARGET_API_MAC_CARBON + +static pascal void TimeOutTask(TMTaskPtr tmTaskPtr) +{ + ((ExtendedTMTaskPtr)tmTaskPtr)->stopSearch = true; +} + +#else + +static pascal TMTaskPtr GetTMTaskPtr(void) + ONEWORDINLINE(0x2e89); /* MOVE.L A1,(SP) */ + +static void TimeOutTask(void) +{ + ((ExtendedTMTaskPtr)GetTMTaskPtr())->stopSearch = true; +} + +#endif + +#if __WANTPASCALELIMINATION +#define pascal +#endif + +/*****************************************************************************/ + +/* +** GetDirModDate returns the modification date of a directory. If there is +** an error getting the modification date, -1 is returned to indicate +** something went wrong. +*/ +static long GetDirModDate(short vRefNum, + long dirID) +{ + CInfoPBRec pb; + Str31 tempName; + long modDate; + + /* Protection against File Sharing problem */ + tempName[0] = 0; + pb.dirInfo.ioNamePtr = tempName; + pb.dirInfo.ioVRefNum = vRefNum; + pb.dirInfo.ioDrDirID = dirID; + pb.dirInfo.ioFDirIndex = -1; /* use ioDrDirID */ + + if ( PBGetCatInfoSync(&pb) == noErr ) + { + modDate = pb.dirInfo.ioDrMdDat; + } + else + { + modDate = -1; + } + + return ( modDate ); +} + +/*****************************************************************************/ + +pascal OSErr IndexedSearch(CSParamPtr pb, + long dirID) +{ + static LevelRecHandle searchStack = NULL; /* static handle to LevelRec stack */ + static Size searchStackSize = 0; /* size of static handle */ + SearchPositionRecPtr catPosition; + long modDate; + short index; + ExtendedTMTask timerTask; + OSErr result; + short realVRefNum; + Str63 itemName; + CInfoPBRec cPB; + long tempLong; + Boolean includeFiles; + Boolean includeDirs; + Boolean includeNames; + Str63 upperName; + + timerTask.stopSearch = false; /* don't stop yet! */ + + /* If request has a timeout, install a Time Manager task. */ + if ( pb->ioSearchTime != 0 ) + { + /* Start timer */ + timerTask.theTask.tmAddr = NewTimerUPP(TimeOutTask); + InsTime((QElemPtr)&(timerTask.theTask)); + PrimeTime((QElemPtr)&(timerTask.theTask), pb->ioSearchTime); + } + + /* Check the parameter block passed for things that we don't want to assume */ + /* are OK later in the code. For example, make sure pointers to data structures */ + /* and buffers are not NULL. And while we're in there, see if the request */ + /* specified searching for files, directories, or both, and see if the search */ + /* was by full or partial name. */ + result = VerifyUserPB(pb, &includeFiles, &includeDirs, &includeNames); + if ( result == noErr ) + { + pb->ioActMatchCount = 0; /* no matches yet */ + + if ( includeNames ) + { + /* The search includes seach by full or partial name. */ + /* Make an upper case copy of the match string to pass to */ + /* CheckForMatches. */ + BlockMoveData(pb->ioSearchInfo1->hFileInfo.ioNamePtr, + upperName, + pb->ioSearchInfo1->hFileInfo.ioNamePtr[0] + 1); + /* Use the same non-international call the File Manager uses */ + UpperString(upperName, true); + } + + /* Prevent casting to my type throughout code */ + catPosition = (SearchPositionRecPtr)&pb->ioCatPosition; + + /* Create searchStack first time called */ + if ( searchStack == NULL ) + { + searchStack = (LevelRecHandle)NewHandle(kAdditionalLevelRecs * sizeof(LevelRec)); + } + + /* Make sure searchStack really exists */ + if ( searchStack != NULL ) + { + searchStackSize = GetHandleSize((Handle)searchStack); + + /* See if the search is a new search or a resumed search. */ + if ( catPosition->initialize == 0 ) + { + /* New search. */ + + /* Get the real vRefNum and fill in catPosition->initialize. */ + result = CheckVol(pb->ioNamePtr, pb->ioVRefNum, &realVRefNum, &catPosition->initialize); + if ( result == noErr ) + { + /* clear searchStack */ + catPosition->stackDepth = 0; + + /* use dirID parameter passed and... */ + index = -1; /* start with the passed directory itself! */ + } + } + else + { + /* We're resuming a search. */ + + /* Get the real vRefNum and make sure catPosition->initialize is valid. */ + result = CheckVol(pb->ioNamePtr, pb->ioVRefNum, &realVRefNum, &tempLong); + if ( result == noErr ) + { + /* Make sure the resumed search is to the same volume! */ + if ( catPosition->initialize == tempLong ) + { + /* For resume, catPosition->stackDepth > 0 */ + if ( catPosition->stackDepth > 0 ) + { + /* Position catPosition->stackDepth to access last saved level */ + --(catPosition->stackDepth); + + /* Get the dirID and index for the next item */ + dirID = (*searchStack)[catPosition->stackDepth].dirID; + index = (*searchStack)[catPosition->stackDepth].index; + + /* Check the dir's mod date against the saved mode date on our "stack" */ + modDate = GetDirModDate(realVRefNum, dirID); + if ( modDate != (*searchStack)[catPosition->stackDepth].dirModDate ) + { + result = catChangedErr; + } + } + else + { + /* Invalid catPosition record was passed */ + result = paramErr; + } + } + else + { + /* The volume is not the same */ + result = catChangedErr; + } + } + } + + if ( result == noErr ) + { + /* ioNamePtr and ioVRefNum only need to be set up once. */ + cPB.hFileInfo.ioNamePtr = itemName; + cPB.hFileInfo.ioVRefNum = realVRefNum; + + /* + ** Here's the loop that: + ** Finds the next item on the volume. + ** If noErr, calls the code to check for matches and add matches + ** to the match buffer. + ** Sets up dirID and index for to find the next item on the volume. + ** + ** The looping ends when: + ** (a) an unexpected error is returned by PBGetCatInfo. All that + ** is expected is noErr and fnfErr (after the last item in a + ** directory is found). + ** (b) the caller specified a timeout and our Time Manager task + ** has fired. + ** (c) the number of matches requested by the caller has been found. + ** (d) the last item on the volume was found. + */ + do + { + /* get the next item */ + cPB.hFileInfo.ioFDirIndex = index; + cPB.hFileInfo.ioDirID = dirID; + result = PBGetCatInfoSync(&cPB); + if ( index != -1 ) + { + if ( result == noErr ) + { + /* We found something */ + + CheckForMatches(&cPB, pb, upperName, includeFiles, includeDirs); + + ++index; + if ( (cPB.dirInfo.ioFlAttrib & kioFlAttribDirMask) != 0 ) + { + /* It's a directory */ + + result = CheckStack(catPosition->stackDepth, searchStack, &searchStackSize); + if ( result == noErr ) + { + /* Save the current state on the searchStack */ + /* when we come back, this is where we'll start */ + (*searchStack)[catPosition->stackDepth].dirID = dirID; + (*searchStack)[catPosition->stackDepth].index = index; + (*searchStack)[catPosition->stackDepth].dirModDate = GetDirModDate(realVRefNum, dirID); + + /* position catPosition->stackDepth for next saved level */ + ++(catPosition->stackDepth); + + /* The next item to get is the 1st item in the child directory */ + dirID = cPB.dirInfo.ioDrDirID; + index = 1; + } + } + /* else do nothing for files */ + } + else + { + /* End of directory found (or we had some error and that */ + /* means we have to drop out of this directory). */ + /* Restore last thing put on stack and */ + /* see if we need to continue or quit. */ + if ( catPosition->stackDepth > 0 ) + { + /* position catPosition->stackDepth to access last saved level */ + --(catPosition->stackDepth); + + dirID = (*searchStack)[catPosition->stackDepth].dirID; + index = (*searchStack)[catPosition->stackDepth].index; + + /* Check the dir's mod date against the saved mode date on our "stack" */ + modDate = GetDirModDate(realVRefNum, dirID); + if ( modDate != (*searchStack)[catPosition->stackDepth].dirModDate ) + { + result = catChangedErr; + } + else + { + /* Going back to ancestor directory. */ + /* Clear error so we can continue. */ + result = noErr; + } + } + else + { + /* We hit the bottom of the stack, so we'll let the */ + /* the eofErr drop us out of the loop. */ + result = eofErr; + } + } + } + else + { + /* Special case for index == -1; that means that we're starting */ + /* a new search and so the first item to check is the directory */ + /* passed to us. */ + if ( result == noErr ) + { + /* We found something */ + + CheckForMatches(&cPB, pb, upperName, includeFiles, includeDirs); + + /* Now, set the index to 1 and then we're ready to look inside */ + /* the passed directory. */ + index = 1; + } + } + } while ( (!timerTask.stopSearch) && /* timer hasn't fired */ + (result == noErr) && /* no unexpected errors */ + (pb->ioReqMatchCount > pb->ioActMatchCount) ); /* we haven't found our limit */ + + /* Did we drop out of the loop because of timeout or */ + /* ioReqMatchCount was found? */ + if ( result == noErr ) + { + result = CheckStack(catPosition->stackDepth, searchStack, &searchStackSize); + if ( result == noErr ) + { + /* Either there was a timeout or ioReqMatchCount was reached. */ + /* Save the dirID and index for the next time we're called. */ + + (*searchStack)[catPosition->stackDepth].dirID = dirID; + (*searchStack)[catPosition->stackDepth].index = index; + (*searchStack)[catPosition->stackDepth].dirModDate = GetDirModDate(realVRefNum, dirID); + + /* position catPosition->stackDepth for next saved level */ + + ++(catPosition->stackDepth); + } + } + } + } + else + { + /* searchStack Handle could not be allocated */ + result = memFullErr; + } + } + + if ( pb->ioSearchTime != 0 ) + { + /* Stop Time Manager task here if it was installed */ + RmvTime((QElemPtr)&(timerTask.theTask)); + DisposeTimerUPP(timerTask.theTask.tmAddr); + } + + return ( result ); +} + +/*****************************************************************************/ + +pascal OSErr PBCatSearchSyncCompat(CSParamPtr paramBlock) +{ + OSErr result; + Boolean supportsCatSearch; + GetVolParmsInfoBuffer volParmsInfo; + long infoSize; +#if !__MACOSSEVENORLATER + static Boolean fullExtFSDispatchingtested = false; + static Boolean hasFullExtFSDispatching = false; + long response; +#endif + + result = noErr; + +#if !__MACOSSEVENORLATER + /* See if File Manager will pass CatSearch requests to external file systems */ + /* we'll store the results in a static variable so we don't have to call Gestalt */ + /* everytime we're called. (System 7.0 and later always do this) */ + if ( !fullExtFSDispatchingtested ) + { + fullExtFSDispatchingtested = true; + if ( Gestalt(gestaltFSAttr, &response) == noErr ) + { + hasFullExtFSDispatching = ((response & (1L << gestaltFullExtFSDispatching)) != 0); + } + } +#endif + + /* CatSearch is a per volume attribute, so we have to check each time we're */ + /* called to see if it is available on the volume specified. */ + supportsCatSearch = false; +#if !__MACOSSEVENORLATER + if ( hasFullExtFSDispatching ) +#endif + { + infoSize = sizeof(GetVolParmsInfoBuffer); + result = HGetVolParms(paramBlock->ioNamePtr, paramBlock->ioVRefNum, + &volParmsInfo, &infoSize); + if ( result == noErr ) + { + supportsCatSearch = hasCatSearch(&volParmsInfo); + } + } + + /* noErr or paramErr is OK here. */ + /* paramErr just means that GetVolParms isn't supported by this volume */ + if ( (result == noErr) || (result == paramErr) ) + { + if ( supportsCatSearch ) + { + /* Volume supports CatSearch so use it. */ + /* CatSearch is faster than an indexed search. */ + result = PBCatSearchSync(paramBlock); + } + else + { + /* Volume doesn't support CatSearch so */ + /* search using IndexedSearch from root directory. */ + result = IndexedSearch(paramBlock, fsRtDirID); + } + } + + return ( result ); +} + +/*****************************************************************************/ + +pascal OSErr NameFileSearch(ConstStr255Param volName, + short vRefNum, + ConstStr255Param fileName, + FSSpecPtr matches, + long reqMatchCount, + long *actMatchCount, + Boolean newSearch, + Boolean partial) +{ + CInfoPBRec searchInfo1, searchInfo2; + HParamBlockRec pb; + OSErr error; + static CatPositionRec catPosition; + static short lastVRefNum = 0; + + /* get the real volume reference number */ + error = DetermineVRefNum(volName, vRefNum, &vRefNum); + if ( error != noErr ) + return ( error ); + + pb.csParam.ioNamePtr = NULL; + pb.csParam.ioVRefNum = vRefNum; + pb.csParam.ioMatchPtr = matches; + pb.csParam.ioReqMatchCount = reqMatchCount; + if ( partial ) /* tell CatSearch what we're looking for: */ + { + pb.csParam.ioSearchBits = fsSBPartialName + fsSBFlAttrib; /* partial name file matches or */ + } + else + { + pb.csParam.ioSearchBits = fsSBFullName + fsSBFlAttrib; /* full name file matches */ + } + pb.csParam.ioSearchInfo1 = &searchInfo1; + pb.csParam.ioSearchInfo2 = &searchInfo2; + pb.csParam.ioSearchTime = 0; + if ( (newSearch) || /* If caller specified new search */ + (lastVRefNum != vRefNum) ) /* or if last search was to another volume, */ + { + catPosition.initialize = 0; /* then search from beginning of catalog */ + } + pb.csParam.ioCatPosition = catPosition; + pb.csParam.ioOptBuffer = GetTempBuffer(0x00004000, &pb.csParam.ioOptBufSize); + + /* search for fileName */ + searchInfo1.hFileInfo.ioNamePtr = (StringPtr)fileName; + searchInfo2.hFileInfo.ioNamePtr = NULL; + + /* only match files (not directories) */ + searchInfo1.hFileInfo.ioFlAttrib = 0x00; + searchInfo2.hFileInfo.ioFlAttrib = kioFlAttribDirMask; + + error = PBCatSearchSyncCompat((CSParamPtr)&pb); + + if ( (error == noErr) || /* If no errors or the end of catalog was */ + (error == eofErr) ) /* found, then the call was successful so */ + { + *actMatchCount = pb.csParam.ioActMatchCount; /* return the match count */ + } + else + { + *actMatchCount = 0; /* else no matches found */ + } + + if ( (error == noErr) || /* If no errors */ + (error == catChangedErr) ) /* or there was a change in the catalog */ + { + catPosition = pb.csParam.ioCatPosition; + lastVRefNum = vRefNum; + /* we can probably start the next search where we stopped this time */ + } + else + { + catPosition.initialize = 0; + /* start the next search from beginning of catalog */ + } + + if ( pb.csParam.ioOptBuffer != NULL ) + { + DisposePtr(pb.csParam.ioOptBuffer); + } + + return ( error ); +} + +/*****************************************************************************/ + +pascal OSErr CreatorTypeFileSearch(ConstStr255Param volName, + short vRefNum, + OSType creator, + OSType fileType, + FSSpecPtr matches, + long reqMatchCount, + long *actMatchCount, + Boolean newSearch) +{ + CInfoPBRec searchInfo1, searchInfo2; + HParamBlockRec pb; + OSErr error; + static CatPositionRec catPosition; + static short lastVRefNum = 0; + + /* get the real volume reference number */ + error = DetermineVRefNum(volName, vRefNum, &vRefNum); + if ( error != noErr ) + return ( error ); + + pb.csParam.ioNamePtr = NULL; + pb.csParam.ioVRefNum = vRefNum; + pb.csParam.ioMatchPtr = matches; + pb.csParam.ioReqMatchCount = reqMatchCount; + pb.csParam.ioSearchBits = fsSBFlAttrib + fsSBFlFndrInfo; /* Looking for finder info file matches */ + pb.csParam.ioSearchInfo1 = &searchInfo1; + pb.csParam.ioSearchInfo2 = &searchInfo2; + pb.csParam.ioSearchTime = 0; + if ( (newSearch) || /* If caller specified new search */ + (lastVRefNum != vRefNum) ) /* or if last search was to another volume, */ + { + catPosition.initialize = 0; /* then search from beginning of catalog */ + } + pb.csParam.ioCatPosition = catPosition; + pb.csParam.ioOptBuffer = GetTempBuffer(0x00004000, &pb.csParam.ioOptBufSize); + + /* no fileName */ + searchInfo1.hFileInfo.ioNamePtr = NULL; + searchInfo2.hFileInfo.ioNamePtr = NULL; + + /* only match files (not directories) */ + searchInfo1.hFileInfo.ioFlAttrib = 0x00; + searchInfo2.hFileInfo.ioFlAttrib = kioFlAttribDirMask; + + /* search for creator; if creator = 0x00000000, ignore creator */ + searchInfo1.hFileInfo.ioFlFndrInfo.fdCreator = creator; + if ( creator == (OSType)0x00000000 ) + { + searchInfo2.hFileInfo.ioFlFndrInfo.fdCreator = (OSType)0x00000000; + } + else + { + searchInfo2.hFileInfo.ioFlFndrInfo.fdCreator = (OSType)0xffffffff; + } + + /* search for fileType; if fileType = 0x00000000, ignore fileType */ + searchInfo1.hFileInfo.ioFlFndrInfo.fdType = fileType; + if ( fileType == (OSType)0x00000000 ) + { + searchInfo2.hFileInfo.ioFlFndrInfo.fdType = (OSType)0x00000000; + } + else + { + searchInfo2.hFileInfo.ioFlFndrInfo.fdType = (OSType)0xffffffff; + } + + /* zero all other FInfo fields */ + searchInfo1.hFileInfo.ioFlFndrInfo.fdFlags = 0; + searchInfo1.hFileInfo.ioFlFndrInfo.fdLocation.v = 0; + searchInfo1.hFileInfo.ioFlFndrInfo.fdLocation.h = 0; + searchInfo1.hFileInfo.ioFlFndrInfo.fdFldr = 0; + + searchInfo2.hFileInfo.ioFlFndrInfo.fdFlags = 0; + searchInfo2.hFileInfo.ioFlFndrInfo.fdLocation.v = 0; + searchInfo2.hFileInfo.ioFlFndrInfo.fdLocation.h = 0; + searchInfo2.hFileInfo.ioFlFndrInfo.fdFldr = 0; + + error = PBCatSearchSyncCompat((CSParamPtr)&pb); + + if ( (error == noErr) || /* If no errors or the end of catalog was */ + (error == eofErr) ) /* found, then the call was successful so */ + { + *actMatchCount = pb.csParam.ioActMatchCount; /* return the match count */ + } + else + { + *actMatchCount = 0; /* else no matches found */ + } + + if ( (error == noErr) || /* If no errors */ + (error == catChangedErr) ) /* or there was a change in the catalog */ + { + catPosition = pb.csParam.ioCatPosition; + lastVRefNum = vRefNum; + /* we can probably start the next search where we stopped this time */ + } + else + { + catPosition.initialize = 0; + /* start the next search from beginning of catalog */ + } + + if ( pb.csParam.ioOptBuffer != NULL ) + { + DisposePtr(pb.csParam.ioOptBuffer); + } + + return ( error ); +} + +/*****************************************************************************/ diff --git a/src/mac/morefile/Search.cpp b/src/mac/morefile/Search.cpp deleted file mode 100644 index bdcfd9ff1a..0000000000 --- a/src/mac/morefile/Search.cpp +++ /dev/null @@ -1,1275 +0,0 @@ -/* -** Apple Macintosh Developer Technical Support -** -** IndexedSearch and the PBCatSearch compatibility function. -** -** by Jim Luther, Apple Developer Technical Support Emeritus -** -** File: Search.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 -#include -#include -#include -#include -#include -#include - -#define __COMPILINGMOREFILES - -#include "MoreFile.h" -#include "MoreExtr.h" -#include "Search.h" - -/*****************************************************************************/ - -enum -{ - /* Number of LevelRecs to add each time the searchStack is grown */ - /* 20 levels is probably more than reasonable for most volumes. */ - /* If more are needed, they are allocated 20 levels at a time. */ - kAdditionalLevelRecs = 20 -}; - -/*****************************************************************************/ - -/* -** LevelRecs are used to store the directory ID and index whenever -** IndexedSearch needs to either scan a sub-directory, or return control -** to the caller because the call has timed out or the number of -** matches requested has been found. LevelRecs are stored in an array -** used as a stack. -*/ -struct LevelRec -{ - long dirModDate; /* for detecting most (but not all) catalog changes */ - long dirID; - short index; -}; -typedef struct LevelRec LevelRec; -typedef LevelRec *LevelRecPtr, **LevelRecHandle; - - -/* -** SearchPositionRec is my version of a CatPositionRec. It holds the -** information I need to resuming searching. -*/ -#if PRAGMA_ALIGN_SUPPORTED -#pragma options align=mac68k -#endif -struct SearchPositionRec -{ - long initialize; /* Goofy checksum of volume information used to make */ - /* sure we're resuming a search on the same volume. */ - unsigned short stackDepth; /* Current depth on searchStack. */ - short priv[11]; /* For future use... */ -}; -#if PRAGMA_ALIGN_SUPPORTED -#pragma options align=reset -#endif -typedef struct SearchPositionRec SearchPositionRec; -typedef SearchPositionRec *SearchPositionRecPtr; - - -/* -** ExtendedTMTask is a TMTask record extended to hold the timer flag. -*/ -#if PRAGMA_ALIGN_SUPPORTED -#pragma options align=mac68k -#endif -struct ExtendedTMTask -{ - TMTask theTask; - Boolean stopSearch; /* the Time Mgr task will set stopSearch to */ - /* true when the timer expires */ -}; -#if PRAGMA_ALIGN_SUPPORTED -#pragma options align=reset -#endif -typedef struct ExtendedTMTask ExtendedTMTask; -typedef ExtendedTMTask *ExtendedTMTaskPtr; - -/*****************************************************************************/ - -static OSErr CheckVol(ConstStr255Param pathname, - short vRefNum, - short *realVRefNum, - long *volID); - -static OSErr CheckStack(unsigned short stackDepth, - LevelRecHandle searchStack, - Size *searchStackSize); - -static OSErr VerifyUserPB(CSParamPtr userPB, - Boolean *includeFiles, - Boolean *includeDirs, - Boolean *includeNames); - -static Boolean IsSubString(ConstStr255Param aStringPtr, - ConstStr255Param subStringPtr); - -static Boolean CompareMasked(const long *data1, - const long *data2, - const long *mask, - short longsToCompare); - -static void CheckForMatches(CInfoPBPtr cPB, - CSParamPtr userPB, - const Str63 matchName, - Boolean includeFiles, - Boolean includeDirs); - -#if __WANTPASCALELIMINATION -#undef pascal -#endif - -#if GENERATINGCFM - -static pascal void TimeOutTask(TMTaskPtr tmTaskPtr); - -#else - -static pascal TMTaskPtr GetTMTaskPtr(void); - -static void TimeOutTask(void); - -#endif - -#if __WANTPASCALELIMINATION -#define pascal -#endif - -static long GetDirModDate(short vRefNum, - long dirID); - -/*****************************************************************************/ - -/* -** CheckVol gets the volume's real vRefNum and builds a volID. The volID -** is used to help insure that calls to resume searching with IndexedSearch -** are to the same volume as the last call to IndexedSearch. -*/ -static OSErr CheckVol(ConstStr255Param pathname, - short vRefNum, - short *realVRefNum, - long *volID) -{ - HParamBlockRec pb; - OSErr error; - - error = GetVolumeInfoNoName(pathname, vRefNum, &pb); - if ( error == noErr ) - { - /* Return the real vRefNum */ - *realVRefNum = pb.volumeParam.ioVRefNum; - - /* Add together a bunch of things that aren't supposed to change on */ - /* a mounted volume that's being searched and that should come up with */ - /* a fairly unique number */ - *volID = pb.volumeParam.ioVCrDate + - pb.volumeParam.ioVRefNum + - pb.volumeParam.ioVNmAlBlks + - pb.volumeParam.ioVAlBlkSiz + - pb.volumeParam.ioVFSID; - } - return ( error ); -} - -/*****************************************************************************/ - -/* -** CheckStack checks the size of the search stack (array) to see if there's -** room to push another LevelRec. If not, CheckStack grows the stack by -** another kAdditionalLevelRecs elements. -*/ -static OSErr CheckStack(unsigned short stackDepth, - LevelRecHandle searchStack, - Size *searchStackSize) -{ - OSErr result; - - if ( (*searchStackSize / sizeof(LevelRec)) == (stackDepth + 1) ) - { - /* Time to grow stack */ - SetHandleSize((Handle)searchStack, *searchStackSize + (kAdditionalLevelRecs * sizeof(LevelRec))); - result = MemError(); /* should be noErr */ - *searchStackSize = InlineGetHandleSize((Handle)searchStack); - } - else - { - result = noErr; - } - - return ( result ); -} - -/*****************************************************************************/ - -/* -** VerifyUserPB makes sure the parameter block passed to IndexedSearch has -** valid parameters. By making this check once, we don't have to worry about -** things like NULL pointers, strings being too long, etc. -** VerifyUserPB also determines if the search includes files and/or -** directories, and determines if a full or partial name search was requested. -*/ -static OSErr VerifyUserPB(CSParamPtr userPB, - Boolean *includeFiles, - Boolean *includeDirs, - Boolean *includeNames) -{ - CInfoPBPtr searchInfo1; - CInfoPBPtr searchInfo2; - - searchInfo1 = userPB->ioSearchInfo1; - searchInfo2 = userPB->ioSearchInfo2; - - /* ioMatchPtr cannot be NULL */ - if ( userPB->ioMatchPtr == NULL ) - { - goto ParamErrExit; - } - - /* ioSearchInfo1 cannot be NULL */ - if ( searchInfo1 == NULL ) - { - goto ParamErrExit; - } - - /* If any bits except partialName, fullName, or negate are set, then */ - /* ioSearchInfo2 cannot be NULL because information in ioSearchInfo2 is required */ - if ( ((userPB->ioSearchBits & ~(fsSBPartialName | fsSBFullName | fsSBNegate)) != 0) && - ( searchInfo2 == NULL )) - { - goto ParamErrExit; - } - - *includeFiles = false; - *includeDirs = false; - *includeNames = false; - - if ( (userPB->ioSearchBits & (fsSBPartialName | fsSBFullName)) != 0 ) - { - /* If any kind of name matching is requested, then ioNamePtr in */ - /* ioSearchInfo1 cannot be NULL or a zero-length string */ - if ( (searchInfo1->hFileInfo.ioNamePtr == NULL) || - (searchInfo1->hFileInfo.ioNamePtr[0] == 0) || - (searchInfo1->hFileInfo.ioNamePtr[0] > (sizeof(Str63) - 1)) ) - { - goto ParamErrExit; - } - - *includeNames = true; - } - - if ( (userPB->ioSearchBits & fsSBFlAttrib) != 0 ) - { - /* The only attributes you can search on are the directory flag */ - /* and the locked flag. */ - if ( (searchInfo2->hFileInfo.ioFlAttrib & ~(ioDirMask | 0x01)) != 0 ) - { - goto ParamErrExit; - } - - /* interested in the directory bit? */ - if ( (searchInfo2->hFileInfo.ioFlAttrib & ioDirMask) != 0 ) - { - /* yes, so do they want just directories or just files? */ - if ( (searchInfo1->hFileInfo.ioFlAttrib & ioDirMask) != 0 ) - { - *includeDirs = true; - } - else - { - *includeFiles = true; - } - } - else - { - /* no interest in directory bit - get both files and directories */ - *includeDirs = true; - *includeFiles = true; - } - } - else - { - /* no attribute checking - get both files and directories */ - *includeDirs = true; - *includeFiles = true; - } - - /* If directories are included in the search, */ - /* then the locked attribute cannot be requested. */ - if ( *includeDirs && - ((userPB->ioSearchBits & fsSBFlAttrib) != 0) && - ((searchInfo2->hFileInfo.ioFlAttrib & 0x01) != 0) ) - { - goto ParamErrExit; - } - - /* If files are included in the search, then there cannot be */ - /* a search on the number of files. */ - if ( *includeFiles && - ((userPB->ioSearchBits & fsSBDrNmFls) != 0) ) - { - goto ParamErrExit; - } - - /* If directories are included in the search, then there cannot */ - /* be a search on file lengths. */ - if ( *includeDirs && - ((userPB->ioSearchBits & (fsSBFlLgLen | fsSBFlPyLen | fsSBFlRLgLen | fsSBFlRPyLen)) != 0) ) - { - goto ParamErrExit; - } - - return ( noErr ); - -ParamErrExit: - return ( paramErr ); -} - -/*****************************************************************************/ - -/* -** IsSubString checks to see if a string is a substring of another string. -** Both input strings have already been converted to all uppercase using -** UprString (the same non-international call the File Manager uses). -*/ -static Boolean IsSubString(ConstStr255Param aStringPtr, - ConstStr255Param subStringPtr) -{ - short strLength; /* length of string */ - short subStrLength; /* length of subString */ - Boolean found; /* result of test */ - short index; /* current index into string */ - - found = false; - strLength = aStringPtr[0]; - subStrLength = subStringPtr[0]; - - if ( subStrLength <= strLength) - { - register short count; /* search counter */ - register short strIndex; /* running index into string */ - register short subStrIndex; /* running index into subString */ - - /* start looking at first character */ - index = 1; - - /* continue looking until remaining string is shorter than substring */ - count = strLength - subStrLength + 1; - - do - { - strIndex = index; /* start string index at index */ - subStrIndex = 1; /* start subString index at 1 */ - - while ( !found && (aStringPtr[strIndex] == subStringPtr[subStrIndex]) ) - { - if ( subStrIndex == subStrLength ) - { - /* all characters in subString were found */ - found = true; - } - else - { - /* check next character of substring against next character of string */ - ++subStrIndex; - ++strIndex; - } - } - - if ( !found ) - { - /* start substring search again at next string character */ - ++index; - --count; - } - } while ( count != 0 && (!found) ); - } - - return ( found ); -} - -/*****************************************************************************/ - -/* -** CompareMasked does a bitwise comparison with mask on 1 or more longs. -** data1 and data2 are first exclusive-ORed together resulting with bits set -** where they are different. That value is then ANDed with the mask resulting -** with bits set if the test fails. true is returned if the tests pass. -*/ -static Boolean CompareMasked(const long *data1, - const long *data2, - const long *mask, - short longsToCompare) -{ - Boolean result = true; - - while ( (longsToCompare != 0) && (result == true) ) - { - /* (*data1 ^ *data2) = bits that are different, so... */ - /* ((*data1 ^ *data2) & *mask) = bits that are different that we're interested in */ - - if ( ((*data1 ^ *data2) & *mask) != 0 ) - result = false; - - ++data1; - ++data2; - ++mask; - --longsToCompare; - } - - return ( result ); -} - -/*****************************************************************************/ - -/* -** Check for matches compares the search criteria in userPB to the file -** system object in cPB. If there's a match, then the information in cPB is -** is added to the match array and the actual match count is incremented. -*/ -static void CheckForMatches(CInfoPBPtr cPB, - CSParamPtr userPB, - const Str63 matchName, - Boolean includeFiles, - Boolean includeDirs) -{ - long searchBits; - CInfoPBPtr searchInfo1; - CInfoPBPtr searchInfo2; - Str63 itemName; /* copy of object's name for partial name matching */ - Boolean foundMatch; - - foundMatch = false; /* default to no match */ - - searchBits = userPB->ioSearchBits; - searchInfo1 = userPB->ioSearchInfo1; - searchInfo2 = userPB->ioSearchInfo2; - - /* Into the if statements that go on forever... */ - - if ( (cPB->hFileInfo.ioFlAttrib & ioDirMask) == 0 ) - { - if (!includeFiles) - { - goto Failed; - } - } - else - { - if (!includeDirs) - { - goto Failed; - } - } - - if ( (searchBits & fsSBPartialName) != 0 ) - { - if ( (cPB->hFileInfo.ioNamePtr[0] > 0) && - (cPB->hFileInfo.ioNamePtr[0] <= (sizeof(Str63) - 1)) ) - { - /* Make uppercase copy of object name */ - BlockMoveData(cPB->hFileInfo.ioNamePtr, - itemName, - cPB->hFileInfo.ioNamePtr[0] + 1); - /* Use the same non-international call the File Manager uses */ - UpperString(itemName, true); - } - else - { - goto Failed; - } - - { - if ( !IsSubString(itemName, matchName) ) - { - goto Failed; - } - else if ( searchBits == fsSBPartialName ) - { - /* optimize for name matching only since it is most common way to search */ - goto Hit; - } - } - } - - if ( (searchBits & fsSBFullName) != 0 ) - { - /* Use the same non-international call the File Manager uses */ - if ( !EqualString(cPB->hFileInfo.ioNamePtr, matchName, false, true) ) - { - goto Failed; - } - else if ( searchBits == fsSBFullName ) - { - /* optimize for name matching only since it is most common way to search */ - goto Hit; - } - } - - if ( (searchBits & fsSBFlParID) != 0 ) - { - if ( ((unsigned long)(cPB->hFileInfo.ioFlParID) < (unsigned long)(searchInfo1->hFileInfo.ioFlParID)) || - ((unsigned long)(cPB->hFileInfo.ioFlParID) > (unsigned long)(searchInfo2->hFileInfo.ioFlParID)) ) - { - goto Failed; - } - } - - if ( (searchBits & fsSBFlAttrib) != 0 ) - { - if ( ((cPB->hFileInfo.ioFlAttrib ^ searchInfo1->hFileInfo.ioFlAttrib) & - searchInfo2->hFileInfo.ioFlAttrib) != 0 ) - { - goto Failed; - } - } - - if ( (searchBits & fsSBDrNmFls) != 0 ) - { - if ( ((unsigned long)(cPB->dirInfo.ioDrNmFls) < (unsigned long)(searchInfo1->dirInfo.ioDrNmFls)) || - ((unsigned long)(cPB->dirInfo.ioDrNmFls) > (unsigned long)(searchInfo2->dirInfo.ioDrNmFls)) ) - { - goto Failed; - } - } - - if ( (searchBits & fsSBFlFndrInfo) != 0 ) /* fsSBFlFndrInfo is same as fsSBDrUsrWds */ - { - if ( !CompareMasked((long *)&(cPB->hFileInfo.ioFlFndrInfo), - (long *)&(searchInfo1->hFileInfo.ioFlFndrInfo), - (long *)&(searchInfo2->hFileInfo.ioFlFndrInfo), - sizeof(FInfo) / sizeof(long)) ) - { - goto Failed; - } - } - - if ( (searchBits & fsSBFlXFndrInfo) != 0 ) /* fsSBFlXFndrInfo is same as fsSBDrFndrInfo */ - { - if ( !CompareMasked((long *)&(cPB->hFileInfo.ioFlXFndrInfo), - (long *)&(searchInfo1->hFileInfo.ioFlXFndrInfo), - (long *)&(searchInfo2->hFileInfo.ioFlXFndrInfo), - sizeof(FXInfo) / sizeof(long)) ) - { - goto Failed; - } - } - - if ( (searchBits & fsSBFlLgLen) != 0 ) - { - if ( ((unsigned long)(cPB->hFileInfo.ioFlLgLen) < (unsigned long)(searchInfo1->hFileInfo.ioFlLgLen)) || - ((unsigned long)(cPB->hFileInfo.ioFlLgLen) > (unsigned long)(searchInfo2->hFileInfo.ioFlLgLen)) ) - { - goto Failed; - } - } - - if ( (searchBits & fsSBFlPyLen) != 0 ) - { - if ( ((unsigned long)(cPB->hFileInfo.ioFlPyLen) < (unsigned long)(searchInfo1->hFileInfo.ioFlPyLen)) || - ((unsigned long)(cPB->hFileInfo.ioFlPyLen) > (unsigned long)(searchInfo2->hFileInfo.ioFlPyLen)) ) - { - goto Failed; - } - } - - if ( (searchBits & fsSBFlRLgLen) != 0 ) - { - if ( ((unsigned long)(cPB->hFileInfo.ioFlRLgLen) < (unsigned long)(searchInfo1->hFileInfo.ioFlRLgLen)) || - ((unsigned long)(cPB->hFileInfo.ioFlRLgLen) > (unsigned long)(searchInfo2->hFileInfo.ioFlRLgLen)) ) - { - goto Failed; - } - } - - if ( (searchBits & fsSBFlRPyLen) != 0 ) - { - if ( ((unsigned long)(cPB->hFileInfo.ioFlRPyLen) < (unsigned long)(searchInfo1->hFileInfo.ioFlRPyLen)) || - ((unsigned long)(cPB->hFileInfo.ioFlRPyLen) > (unsigned long)(searchInfo2->hFileInfo.ioFlRPyLen)) ) - { - goto Failed; - } - } - - if ( (searchBits & fsSBFlCrDat) != 0 ) /* fsSBFlCrDat is same as fsSBDrCrDat */ - { - if ( ((unsigned long)(cPB->hFileInfo.ioFlCrDat) < (unsigned long)(searchInfo1->hFileInfo.ioFlCrDat)) || - ((unsigned long)(cPB->hFileInfo.ioFlCrDat) > (unsigned long)(searchInfo2->hFileInfo.ioFlCrDat)) ) - { - goto Failed; - } - } - - if ( (searchBits & fsSBFlMdDat) != 0 ) /* fsSBFlMdDat is same as fsSBDrMdDat */ - { - if ( ((unsigned long)(cPB->hFileInfo.ioFlMdDat) < (unsigned long)(searchInfo1->hFileInfo.ioFlMdDat)) || - ((unsigned long)(cPB->hFileInfo.ioFlMdDat) > (unsigned long)(searchInfo2->hFileInfo.ioFlMdDat)) ) - { - goto Failed; - } - } - - if ( (searchBits & fsSBFlBkDat) != 0 ) /* fsSBFlBkDat is same as fsSBDrBkDat */ - { - if ( ((unsigned long)(cPB->hFileInfo.ioFlBkDat) < (unsigned long)(searchInfo1->hFileInfo.ioFlBkDat)) || - ((unsigned long)(cPB->hFileInfo.ioFlBkDat) > (unsigned long)(searchInfo2->hFileInfo.ioFlBkDat)) ) - { - goto Failed; - } - } - - /* Hey, we passed all of the tests! */ - -Hit: - foundMatch = true; - -/* foundMatch is false if code jumps to Failed */ -Failed: - /* Do we reverse our findings? */ - if ( (searchBits & fsSBNegate) != 0 ) - { - foundMatch = !foundMatch; /* matches are not, not matches are */ - } - - if ( foundMatch ) - { - - /* Move the match into the match buffer */ - userPB->ioMatchPtr[userPB->ioActMatchCount].vRefNum = cPB->hFileInfo.ioVRefNum; - userPB->ioMatchPtr[userPB->ioActMatchCount].parID = cPB->hFileInfo.ioFlParID; - if ( cPB->hFileInfo.ioNamePtr[0] > 63 ) - { - cPB->hFileInfo.ioNamePtr[0] = 63; - } - BlockMoveData(cPB->hFileInfo.ioNamePtr, - userPB->ioMatchPtr[userPB->ioActMatchCount].name, - cPB->hFileInfo.ioNamePtr[0] + 1); - - /* increment the actual count */ - ++(userPB->ioActMatchCount); - } -} - -/*****************************************************************************/ - -/* -** TimeOutTask is executed when the timer goes off. It simply sets the -** stopSearch field to true. After each object is found and possibly added -** to the matches buffer, stopSearch is checked to see if the search should -** continue. -*/ - -#if __WANTPASCALELIMINATION -#undef pascal -#endif - -#if GENERATINGCFM - -static pascal void TimeOutTask(TMTaskPtr tmTaskPtr) -{ - ((ExtendedTMTaskPtr)tmTaskPtr)->stopSearch = true; -} - -#else - -static pascal TMTaskPtr GetTMTaskPtr(void) - ONEWORDINLINE(0x2e89); /* MOVE.L A1,(SP) */ - -static void TimeOutTask(void) -{ - ((ExtendedTMTaskPtr)GetTMTaskPtr())->stopSearch = true; -} - -#endif - -#if __WANTPASCALELIMINATION -#define pascal -#endif - -/*****************************************************************************/ - -/* -** GetDirModDate returns the modification date of a directory. If there is -** an error getting the modification date, -1 is returned to indicate -** something went wrong. -*/ -static long GetDirModDate(short vRefNum, - long dirID) -{ - CInfoPBRec pb; - Str31 tempName; - long modDate; - - /* Protection against File Sharing problem */ - tempName[0] = 0; - pb.dirInfo.ioNamePtr = tempName; - pb.dirInfo.ioVRefNum = vRefNum; - pb.dirInfo.ioDrDirID = dirID; - pb.dirInfo.ioFDirIndex = -1; /* use ioDrDirID */ - - if ( PBGetCatInfoSync(&pb) == noErr ) - { - modDate = pb.dirInfo.ioDrMdDat; - } - else - { - modDate = -1; - } - - return ( modDate ); -} - -/*****************************************************************************/ - -pascal OSErr IndexedSearch(CSParamPtr pb, - long dirID) -{ - static LevelRecHandle searchStack = NULL; /* static handle to LevelRec stack */ - static Size searchStackSize = 0; /* size of static handle */ - SearchPositionRecPtr catPosition; - long modDate; - short index; - ExtendedTMTask timerTask; - OSErr result; - short realVRefNum; - Str63 itemName; - CInfoPBRec cPB; - long tempLong; - Boolean includeFiles; - Boolean includeDirs; - Boolean includeNames; - Str63 upperName; - - timerTask.stopSearch = false; /* don't stop yet! */ - - /* If request has a timeout, install a Time Manager task. */ - if ( pb->ioSearchTime != 0 ) - { - /* Start timer */ - timerTask.theTask.tmAddr = NewTimerProc(TimeOutTask); - InsTime((QElemPtr)&(timerTask.theTask)); - PrimeTime((QElemPtr)&(timerTask.theTask), pb->ioSearchTime); - } - - /* Check the parameter block passed for things that we don't want to assume */ - /* are OK later in the code. For example, make sure pointers to data structures */ - /* and buffers are not NULL. And while we're in there, see if the request */ - /* specified searching for files, directories, or both, and see if the search */ - /* was by full or partial name. */ - result = VerifyUserPB(pb, &includeFiles, &includeDirs, &includeNames); - if ( result == noErr ) - { - pb->ioActMatchCount = 0; /* no matches yet */ - - if ( includeNames ) - { - /* The search includes seach by full or partial name. */ - /* Make an upper case copy of the match string to pass to */ - /* CheckForMatches. */ - BlockMoveData(pb->ioSearchInfo1->hFileInfo.ioNamePtr, - upperName, - pb->ioSearchInfo1->hFileInfo.ioNamePtr[0] + 1); - /* Use the same non-international call the File Manager uses */ - UpperString(upperName, true); - } - - /* Prevent casting to my type throughout code */ - catPosition = (SearchPositionRecPtr)&pb->ioCatPosition; - - /* Create searchStack first time called */ - if ( searchStack == NULL ) - { - searchStack = (LevelRecHandle)NewHandle(kAdditionalLevelRecs * sizeof(LevelRec)); - } - - /* Make sure searchStack really exists */ - if ( searchStack != NULL ) - { - searchStackSize = InlineGetHandleSize((Handle)searchStack); - - /* See if the search is a new search or a resumed search. */ - if ( catPosition->initialize == 0 ) - { - /* New search. */ - - /* Get the real vRefNum and fill in catPosition->initialize. */ - result = CheckVol(pb->ioNamePtr, pb->ioVRefNum, &realVRefNum, &catPosition->initialize); - if ( result == noErr ) - { - /* clear searchStack */ - catPosition->stackDepth = 0; - - /* use dirID parameter passed and... */ - index = -1; /* start with the passed directory itself! */ - } - } - else - { - /* We're resuming a search. */ - - /* Get the real vRefNum and make sure catPosition->initialize is valid. */ - result = CheckVol(pb->ioNamePtr, pb->ioVRefNum, &realVRefNum, &tempLong); - if ( result == noErr ) - { - /* Make sure the resumed search is to the same volume! */ - if ( catPosition->initialize == tempLong ) - { - /* For resume, catPosition->stackDepth > 0 */ - if ( catPosition->stackDepth > 0 ) - { - /* Position catPosition->stackDepth to access last saved level */ - --(catPosition->stackDepth); - - /* Get the dirID and index for the next item */ - dirID = (*searchStack)[catPosition->stackDepth].dirID; - index = (*searchStack)[catPosition->stackDepth].index; - - /* Check the dir's mod date against the saved mode date on our "stack" */ - modDate = GetDirModDate(realVRefNum, dirID); - if ( modDate != (*searchStack)[catPosition->stackDepth].dirModDate ) - { - result = catChangedErr; - } - } - else - { - /* Invalid catPosition record was passed */ - result = paramErr; - } - } - else - { - /* The volume is not the same */ - result = catChangedErr; - } - } - } - - if ( result == noErr ) - { - /* ioNamePtr and ioVRefNum only need to be set up once. */ - cPB.hFileInfo.ioNamePtr = itemName; - cPB.hFileInfo.ioVRefNum = realVRefNum; - - /* - ** Here's the loop that: - ** Finds the next item on the volume. - ** If noErr, calls the code to check for matches and add matches - ** to the match buffer. - ** Sets up dirID and index for to find the next item on the volume. - ** - ** The looping ends when: - ** (a) an unexpected error is returned by PBGetCatInfo. All that - ** is expected is noErr and fnfErr (after the last item in a - ** directory is found). - ** (b) the caller specified a timeout and our Time Manager task - ** has fired. - ** (c) the number of matches requested by the caller has been found. - ** (d) the last item on the volume was found. - */ - do - { - /* get the next item */ - cPB.hFileInfo.ioFDirIndex = index; - cPB.hFileInfo.ioDirID = dirID; - result = PBGetCatInfoSync(&cPB); - if ( index != -1 ) - { - if ( result == noErr ) - { - /* We found something */ - - CheckForMatches(&cPB, pb, upperName, includeFiles, includeDirs); - - ++index; - if ( (cPB.dirInfo.ioFlAttrib & ioDirMask) != 0 ) - { - /* It's a directory */ - - result = CheckStack(catPosition->stackDepth, searchStack, &searchStackSize); - if ( result == noErr ) - { - /* Save the current state on the searchStack */ - /* when we come back, this is where we'll start */ - (*searchStack)[catPosition->stackDepth].dirID = dirID; - (*searchStack)[catPosition->stackDepth].index = index; - (*searchStack)[catPosition->stackDepth].dirModDate = GetDirModDate(realVRefNum, dirID); - - /* position catPosition->stackDepth for next saved level */ - ++(catPosition->stackDepth); - - /* The next item to get is the 1st item in the child directory */ - dirID = cPB.dirInfo.ioDrDirID; - index = 1; - } - } - /* else do nothing for files */ - } - else - { - /* End of directory found (or we had some error and that */ - /* means we have to drop out of this directory). */ - /* Restore last thing put on stack and */ - /* see if we need to continue or quit. */ - if ( catPosition->stackDepth > 0 ) - { - /* position catPosition->stackDepth to access last saved level */ - --(catPosition->stackDepth); - - dirID = (*searchStack)[catPosition->stackDepth].dirID; - index = (*searchStack)[catPosition->stackDepth].index; - - /* Check the dir's mod date against the saved mode date on our "stack" */ - modDate = GetDirModDate(realVRefNum, dirID); - if ( modDate != (*searchStack)[catPosition->stackDepth].dirModDate ) - { - result = catChangedErr; - } - else - { - /* Going back to ancestor directory. */ - /* Clear error so we can continue. */ - result = noErr; - } - } - else - { - /* We hit the bottom of the stack, so we'll let the */ - /* the eofErr drop us out of the loop. */ - result = eofErr; - } - } - } - else - { - /* Special case for index == -1; that means that we're starting */ - /* a new search and so the first item to check is the directory */ - /* passed to us. */ - if ( result == noErr ) - { - /* We found something */ - - CheckForMatches(&cPB, pb, upperName, includeFiles, includeDirs); - - /* Now, set the index to 1 and then we're ready to look inside */ - /* the passed directory. */ - index = 1; - } - } - } while ( (!timerTask.stopSearch) && /* timer hasn't fired */ - (result == noErr) && /* no unexpected errors */ - (pb->ioReqMatchCount > pb->ioActMatchCount) ); /* we haven't found our limit */ - - /* Did we drop out of the loop because of timeout or */ - /* ioReqMatchCount was found? */ - if ( result == noErr ) - { - result = CheckStack(catPosition->stackDepth, searchStack, &searchStackSize); - if ( result == noErr ) - { - /* Either there was a timeout or ioReqMatchCount was reached. */ - /* Save the dirID and index for the next time we're called. */ - - (*searchStack)[catPosition->stackDepth].dirID = dirID; - (*searchStack)[catPosition->stackDepth].index = index; - (*searchStack)[catPosition->stackDepth].dirModDate = GetDirModDate(realVRefNum, dirID); - - /* position catPosition->stackDepth for next saved level */ - - ++(catPosition->stackDepth); - } - } - } - } - else - { - /* searchStack Handle could not be allocated */ - result = memFullErr; - } - } - - if ( pb->ioSearchTime != 0 ) - { - /* Stop Time Manager task here if it was installed */ - RmvTime((QElemPtr)&(timerTask.theTask)); - DisposeRoutineDescriptor(timerTask.theTask.tmAddr); - } - - return ( result ); -} - -/*****************************************************************************/ - -pascal OSErr PBCatSearchSyncCompat(CSParamPtr paramBlock) -{ - static Boolean fullExtFSDispatchingtested = false; - static Boolean hasFullExtFSDispatching = false; - OSErr result; - Boolean supportsCatSearch; - long response; - GetVolParmsInfoBuffer volParmsInfo; - long infoSize; - - result = noErr; - - /* See if File Manager will pass CatSearch requests to external file systems */ - /* we'll store the results in a static variable so we don't have to call Gestalt */ - /* everytime we're called. */ - if ( !fullExtFSDispatchingtested ) - { - fullExtFSDispatchingtested = true; - if ( Gestalt(gestaltFSAttr, &response) == noErr ) - { - hasFullExtFSDispatching = ((response & (1L << gestaltFullExtFSDispatching)) != 0); - } - } - - /* CatSearch is a per volume attribute, so we have to check each time we're */ - /* called to see if it is available on the volume specified. */ - supportsCatSearch = false; - if ( hasFullExtFSDispatching ) - { - infoSize = sizeof(GetVolParmsInfoBuffer); - result = HGetVolParms(paramBlock->ioNamePtr, paramBlock->ioVRefNum, - &volParmsInfo, &infoSize); - if ( result == noErr ) - { - supportsCatSearch = hasCatSearch(volParmsInfo); - } - } - - /* noErr or paramErr is OK here. */ - /* paramErr just means that GetVolParms isn't supported by this volume */ - if ( (result == noErr) || (result == paramErr) ) - { - if ( supportsCatSearch ) - { - /* Volume supports CatSearch so use it. */ - /* CatSearch is faster than an indexed search. */ - result = PBCatSearchSync(paramBlock); - } - else - { - /* Volume doesn't support CatSearch so */ - /* search using IndexedSearch from root directory. */ - result = IndexedSearch(paramBlock, fsRtDirID); - } - } - - return ( result ); -} - -/*****************************************************************************/ - -pascal OSErr NameFileSearch(ConstStr255Param volName, - short vRefNum, - ConstStr255Param fileName, - FSSpecPtr matches, - long reqMatchCount, - long *actMatchCount, - Boolean newSearch, - Boolean partial) -{ - CInfoPBRec searchInfo1, searchInfo2; - HParamBlockRec pb; - OSErr error; - static CatPositionRec catPosition; - static short lastVRefNum = 0; - - /* get the real volume reference number */ - error = DetermineVRefNum(volName, vRefNum, &vRefNum); - if ( error != noErr ) - return ( error ); - - pb.csParam.ioNamePtr = NULL; - pb.csParam.ioVRefNum = vRefNum; - pb.csParam.ioMatchPtr = matches; - pb.csParam.ioReqMatchCount = reqMatchCount; - if ( partial ) /* tell CatSearch what we're looking for: */ - { - pb.csParam.ioSearchBits = fsSBPartialName + fsSBFlAttrib; /* partial name file matches or */ - } - else - { - pb.csParam.ioSearchBits = fsSBFullName + fsSBFlAttrib; /* full name file matches */ - } - pb.csParam.ioSearchInfo1 = &searchInfo1; - pb.csParam.ioSearchInfo2 = &searchInfo2; - pb.csParam.ioSearchTime = 0; - if ( (newSearch) || /* If caller specified new search */ - (lastVRefNum != vRefNum) ) /* or if last search was to another volume, */ - { - catPosition.initialize = 0; /* then search from beginning of catalog */ - } - pb.csParam.ioCatPosition = catPosition; - pb.csParam.ioOptBuffer = GetTempBuffer(0x00004000, &pb.csParam.ioOptBufSize); - - /* search for fileName */ - searchInfo1.hFileInfo.ioNamePtr = (StringPtr)fileName; - searchInfo2.hFileInfo.ioNamePtr = NULL; - - /* only match files (not directories) */ - searchInfo1.hFileInfo.ioFlAttrib = 0x00; - searchInfo2.hFileInfo.ioFlAttrib = ioDirMask; - - error = PBCatSearchSyncCompat((CSParamPtr)&pb); - - if ( (error == noErr) || /* If no errors or the end of catalog was */ - (error == eofErr) ) /* found, then the call was successful so */ - { - *actMatchCount = pb.csParam.ioActMatchCount; /* return the match count */ - } - else - { - *actMatchCount = 0; /* else no matches found */ - } - - if ( (error == noErr) || /* If no errors */ - (error == catChangedErr) ) /* or there was a change in the catalog */ - { - catPosition = pb.csParam.ioCatPosition; - lastVRefNum = vRefNum; - /* we can probably start the next search where we stopped this time */ - } - else - { - catPosition.initialize = 0; - /* start the next search from beginning of catalog */ - } - - if ( pb.csParam.ioOptBuffer != NULL ) - { - DisposePtr(pb.csParam.ioOptBuffer); - } - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr CreatorTypeFileSearch(ConstStr255Param volName, - short vRefNum, - OSType creator, - OSType fileType, - FSSpecPtr matches, - long reqMatchCount, - long *actMatchCount, - Boolean newSearch) -{ - CInfoPBRec searchInfo1, searchInfo2; - HParamBlockRec pb; - OSErr error; - static CatPositionRec catPosition; - static short lastVRefNum = 0; - - /* get the real volume reference number */ - error = DetermineVRefNum(volName, vRefNum, &vRefNum); - if ( error != noErr ) - return ( error ); - - pb.csParam.ioNamePtr = NULL; - pb.csParam.ioVRefNum = vRefNum; - pb.csParam.ioMatchPtr = matches; - pb.csParam.ioReqMatchCount = reqMatchCount; - pb.csParam.ioSearchBits = fsSBFlAttrib + fsSBFlFndrInfo; /* Looking for finder info file matches */ - pb.csParam.ioSearchInfo1 = &searchInfo1; - pb.csParam.ioSearchInfo2 = &searchInfo2; - pb.csParam.ioSearchTime = 0; - if ( (newSearch) || /* If caller specified new search */ - (lastVRefNum != vRefNum) ) /* or if last search was to another volume, */ - { - catPosition.initialize = 0; /* then search from beginning of catalog */ - } - pb.csParam.ioCatPosition = catPosition; - pb.csParam.ioOptBuffer = GetTempBuffer(0x00004000, &pb.csParam.ioOptBufSize); - - /* no fileName */ - searchInfo1.hFileInfo.ioNamePtr = NULL; - searchInfo2.hFileInfo.ioNamePtr = NULL; - - /* only match files (not directories) */ - searchInfo1.hFileInfo.ioFlAttrib = 0x00; - searchInfo2.hFileInfo.ioFlAttrib = ioDirMask; - - /* search for creator; if creator = 0x00000000, ignore creator */ - searchInfo1.hFileInfo.ioFlFndrInfo.fdCreator = creator; - if ( creator == (OSType)0x00000000 ) - { - searchInfo2.hFileInfo.ioFlFndrInfo.fdCreator = (OSType)0x00000000; - } - else - { - searchInfo2.hFileInfo.ioFlFndrInfo.fdCreator = (OSType)0xffffffff; - } - - /* search for fileType; if fileType = 0x00000000, ignore fileType */ - searchInfo1.hFileInfo.ioFlFndrInfo.fdType = fileType; - if ( fileType == (OSType)0x00000000 ) - { - searchInfo2.hFileInfo.ioFlFndrInfo.fdType = (OSType)0x00000000; - } - else - { - searchInfo2.hFileInfo.ioFlFndrInfo.fdType = (OSType)0xffffffff; - } - - /* zero all other FInfo fields */ - searchInfo1.hFileInfo.ioFlFndrInfo.fdFlags = 0; - searchInfo1.hFileInfo.ioFlFndrInfo.fdLocation.v = 0; - searchInfo1.hFileInfo.ioFlFndrInfo.fdLocation.h = 0; - searchInfo1.hFileInfo.ioFlFndrInfo.fdFldr = 0; - - searchInfo2.hFileInfo.ioFlFndrInfo.fdFlags = 0; - searchInfo2.hFileInfo.ioFlFndrInfo.fdLocation.v = 0; - searchInfo2.hFileInfo.ioFlFndrInfo.fdLocation.h = 0; - searchInfo2.hFileInfo.ioFlFndrInfo.fdFldr = 0; - - error = PBCatSearchSyncCompat((CSParamPtr)&pb); - - if ( (error == noErr) || /* If no errors or the end of catalog was */ - (error == eofErr) ) /* found, then the call was successful so */ - { - *actMatchCount = pb.csParam.ioActMatchCount; /* return the match count */ - } - else - { - *actMatchCount = 0; /* else no matches found */ - } - - if ( (error == noErr) || /* If no errors */ - (error == catChangedErr) ) /* or there was a change in the catalog */ - { - catPosition = pb.csParam.ioCatPosition; - lastVRefNum = vRefNum; - /* we can probably start the next search where we stopped this time */ - } - else - { - catPosition.initialize = 0; - /* start the next search from beginning of catalog */ - } - - if ( pb.csParam.ioOptBuffer != NULL ) - { - DisposePtr(pb.csParam.ioOptBuffer); - } - - return ( error ); -} - -/*****************************************************************************/ diff --git a/src/mac/morefile/Search.h b/src/mac/morefile/Search.h index fe79c120fd..3fee03dea8 100644 --- a/src/mac/morefile/Search.h +++ b/src/mac/morefile/Search.h @@ -1,246 +1,304 @@ /* -** 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. + File: Search.h + + Contains: IndexedSearch and the PBCatSearch compatibility function. + + Version: Technology: MoreFiles + Release: 1.5.2 + + Copyright: © 1992-2001 by Apple Computer, Inc., all rights reserved. + + Bugs?: For bug reports, consult the following page on + the World Wide Web: + + http://developer.apple.com/bugreporter/ + +*/ + +/* + 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 +#ifndef __MACTYPES__ +#include +#endif + +#ifndef __FILES__ #include +#endif + +#include "Optimization.h" + -#include "Optim.h" +#if PRAGMA_ONCE +#pragma once +#endif #ifdef __cplusplus extern "C" { #endif +#if PRAGMA_IMPORT +#pragma import on +#endif + +#if PRAGMA_STRUCT_ALIGN + #pragma options align=mac68k +#elif PRAGMA_STRUCT_PACKPUSH + #pragma pack(push, 2) +#elif PRAGMA_STRUCT_PACK + #pragma pack(2) +#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 +EXTERN_API( OSErr ) +IndexedSearch( + CSParamPtr pb, + long dirID); + + +/* + 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 +EXTERN_API( OSErr ) +PBCatSearchSyncCompat(CSParamPtr paramBlock); + + +/* + 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 +EXTERN_API( OSErr ) +NameFileSearch( + ConstStr255Param volName, + short vRefNum, + ConstStr255Param fileName, + FSSpecPtr matches, + long reqMatchCount, + long * actMatchCount, + Boolean newSearch, + Boolean partial); + + +/* + 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 +EXTERN_API( OSErr ) +CreatorTypeFileSearch( + ConstStr255Param volName, + short vRefNum, + OSType creator, + OSType fileType, + FSSpecPtr matches, + long reqMatchCount, + long * actMatchCount, + Boolean newSearch); + + +/* + 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 */ /*****************************************************************************/ +#include "OptimizationEnd.h" + +#if PRAGMA_STRUCT_ALIGN + #pragma options align=reset +#elif PRAGMA_STRUCT_PACKPUSH + #pragma pack(pop) +#elif PRAGMA_STRUCT_PACK + #pragma pack() +#endif + +#ifdef PRAGMA_IMPORT_OFF +#pragma import off +#elif PRAGMA_IMPORT +#pragma import reset +#endif + #ifdef __cplusplus } #endif -#include "OptimEnd.h" +#endif /* __SEARCH__ */ -#endif /* __SEARCH__ */ diff --git a/src/mac/morefile/mfsearch.cpp b/src/mac/morefile/mfsearch.cpp deleted file mode 100644 index 6aed9b934d..0000000000 --- a/src/mac/morefile/mfsearch.cpp +++ /dev/null @@ -1,1313 +0,0 @@ -/* -** Apple Macintosh Developer Technical Support -** -** IndexedSearch and the PBCatSearch compatibility function. -** -** by Jim Luther, Apple Developer Technical Support Emeritus -** -** File: Search.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 -#include -#include -#include -#include -#include -#include - -#define __COMPILINGMOREFILES - -#include "morefile.h" -#include "moreextr.h" -#include "mfsearch.h" - -/*****************************************************************************/ - -enum -{ - /* Number of LevelRecs to add each time the searchStack is grown */ - /* 20 levels is probably more than reasonable for most volumes. */ - /* If more are needed, they are allocated 20 levels at a time. */ - kAdditionalLevelRecs = 20 -}; - -/*****************************************************************************/ - -/* -** LevelRecs are used to store the directory ID and index whenever -** IndexedSearch needs to either scan a sub-directory, or return control -** to the caller because the call has timed out or the number of -** matches requested has been found. LevelRecs are stored in an array -** used as a stack. -*/ -struct LevelRec -{ - long dirModDate; /* for detecting most (but not all) catalog changes */ - long dirID; - short index; -}; -typedef struct LevelRec LevelRec; -typedef LevelRec *LevelRecPtr, **LevelRecHandle; - - -/* -** SearchPositionRec is my version of a CatPositionRec. It holds the -** information I need to resuming searching. -*/ -#if PRAGMA_STRUCT_ALIGN - #pragma options align=mac68k -#elif PRAGMA_STRUCT_PACKPUSH - #pragma pack(push, 2) -#elif PRAGMA_STRUCT_PACK - #pragma pack(2) -#endif -struct SearchPositionRec -{ - long initialize; /* Goofy checksum of volume information used to make */ - /* sure we're resuming a search on the same volume. */ - unsigned short stackDepth; /* Current depth on searchStack. */ - short priv[11]; /* For future use... */ -}; -#if PRAGMA_STRUCT_ALIGN - #pragma options align=reset -#elif PRAGMA_STRUCT_PACKPUSH - #pragma pack(pop) -#elif PRAGMA_STRUCT_PACK - #pragma pack() -#endif -typedef struct SearchPositionRec SearchPositionRec; -typedef SearchPositionRec *SearchPositionRecPtr; - - -/* -** ExtendedTMTask is a TMTask record extended to hold the timer flag. -*/ -#if PRAGMA_STRUCT_ALIGN - #pragma options align=mac68k -#elif PRAGMA_STRUCT_PACKPUSH - #pragma pack(push, 2) -#elif PRAGMA_STRUCT_PACK - #pragma pack(2) -#endif -struct ExtendedTMTask -{ - TMTask theTask; - Boolean stopSearch; /* the Time Mgr task will set stopSearch to */ - /* true when the timer expires */ -}; -#if PRAGMA_STRUCT_ALIGN - #pragma options align=reset -#elif PRAGMA_STRUCT_PACKPUSH - #pragma pack(pop) -#elif PRAGMA_STRUCT_PACK - #pragma pack() -#endif -typedef struct ExtendedTMTask ExtendedTMTask; -typedef ExtendedTMTask *ExtendedTMTaskPtr; - -/*****************************************************************************/ - -static OSErr CheckVol(ConstStr255Param pathname, - short vRefNum, - short *realVRefNum, - long *volID); - -static OSErr CheckStack(unsigned short stackDepth, - LevelRecHandle searchStack, - Size *searchStackSize); - -static OSErr VerifyUserPB(CSParamPtr userPB, - Boolean *includeFiles, - Boolean *includeDirs, - Boolean *includeNames); - -static Boolean IsSubString(ConstStr255Param aStringPtr, - ConstStr255Param subStringPtr); - -static Boolean CompareMasked(const long *data1, - const long *data2, - const long *mask, - short longsToCompare); - -static void CheckForMatches(CInfoPBPtr cPB, - CSParamPtr userPB, - const Str63 matchName, - Boolean includeFiles, - Boolean includeDirs); - -#if __WANTPASCALELIMINATION -#undef pascal -#endif - -#if TARGET_CARBON -static pascal void TimeOutTask(TMTaskPtr tmTaskPtr); - -#else -#if GENERATINGCFM - -static pascal void TimeOutTask(TMTaskPtr tmTaskPtr); - -#else - -static pascal TMTaskPtr GetTMTaskPtr(void); - -static void TimeOutTask(void); - -#endif -#endif - -#if __WANTPASCALELIMINATION -#define pascal -#endif - -static long GetDirModDate(short vRefNum, - long dirID); - -/*****************************************************************************/ - -/* -** CheckVol gets the volume's real vRefNum and builds a volID. The volID -** is used to help insure that calls to resume searching with IndexedSearch -** are to the same volume as the last call to IndexedSearch. -*/ -static OSErr CheckVol(ConstStr255Param pathname, - short vRefNum, - short *realVRefNum, - long *volID) -{ - HParamBlockRec pb; - OSErr error; - - error = GetVolumeInfoNoName(pathname, vRefNum, &pb); - if ( error == noErr ) - { - /* Return the real vRefNum */ - *realVRefNum = pb.volumeParam.ioVRefNum; - - /* Add together a bunch of things that aren't supposed to change on */ - /* a mounted volume that's being searched and that should come up with */ - /* a fairly unique number */ - *volID = pb.volumeParam.ioVCrDate + - pb.volumeParam.ioVRefNum + - pb.volumeParam.ioVNmAlBlks + - pb.volumeParam.ioVAlBlkSiz + - pb.volumeParam.ioVFSID; - } - return ( error ); -} - -/*****************************************************************************/ - -/* -** CheckStack checks the size of the search stack (array) to see if there's -** room to push another LevelRec. If not, CheckStack grows the stack by -** another kAdditionalLevelRecs elements. -*/ -static OSErr CheckStack(unsigned short stackDepth, - LevelRecHandle searchStack, - Size *searchStackSize) -{ - OSErr result; - - if ( (*searchStackSize / sizeof(LevelRec)) == (stackDepth + 1) ) - { - /* Time to grow stack */ - SetHandleSize((Handle)searchStack, *searchStackSize + (kAdditionalLevelRecs * sizeof(LevelRec))); - result = MemError(); /* should be noErr */ -#if TARGET_CARBON - *searchStackSize = GetHandleSize((Handle)searchStack); -#else - *searchStackSize = InlineGetHandleSize((Handle)searchStack); -#endif - } - else - { - result = noErr; - } - - return ( result ); -} - -/*****************************************************************************/ - -/* -** VerifyUserPB makes sure the parameter block passed to IndexedSearch has -** valid parameters. By making this check once, we don't have to worry about -** things like NULL pointers, strings being too long, etc. -** VerifyUserPB also determines if the search includes files and/or -** directories, and determines if a full or partial name search was requested. -*/ -static OSErr VerifyUserPB(CSParamPtr userPB, - Boolean *includeFiles, - Boolean *includeDirs, - Boolean *includeNames) -{ - CInfoPBPtr searchInfo1; - CInfoPBPtr searchInfo2; - - searchInfo1 = userPB->ioSearchInfo1; - searchInfo2 = userPB->ioSearchInfo2; - - /* ioMatchPtr cannot be NULL */ - if ( userPB->ioMatchPtr == NULL ) - { - goto ParamErrExit; - } - - /* ioSearchInfo1 cannot be NULL */ - if ( searchInfo1 == NULL ) - { - goto ParamErrExit; - } - - /* If any bits except partialName, fullName, or negate are set, then */ - /* ioSearchInfo2 cannot be NULL because information in ioSearchInfo2 is required */ - if ( ((userPB->ioSearchBits & ~(fsSBPartialName | fsSBFullName | fsSBNegate)) != 0) && - ( searchInfo2 == NULL )) - { - goto ParamErrExit; - } - - *includeFiles = false; - *includeDirs = false; - *includeNames = false; - - if ( (userPB->ioSearchBits & (fsSBPartialName | fsSBFullName)) != 0 ) - { - /* If any kind of name matching is requested, then ioNamePtr in */ - /* ioSearchInfo1 cannot be NULL or a zero-length string */ - if ( (searchInfo1->hFileInfo.ioNamePtr == NULL) || - (searchInfo1->hFileInfo.ioNamePtr[0] == 0) || - (searchInfo1->hFileInfo.ioNamePtr[0] > (sizeof(Str63) - 1)) ) - { - goto ParamErrExit; - } - - *includeNames = true; - } - - if ( (userPB->ioSearchBits & fsSBFlAttrib) != 0 ) - { - /* The only attributes you can search on are the directory flag */ - /* and the locked flag. */ - if ( (searchInfo2->hFileInfo.ioFlAttrib & ~(ioDirMask | 0x01)) != 0 ) - { - goto ParamErrExit; - } - - /* interested in the directory bit? */ - if ( (searchInfo2->hFileInfo.ioFlAttrib & ioDirMask) != 0 ) - { - /* yes, so do they want just directories or just files? */ - if ( (searchInfo1->hFileInfo.ioFlAttrib & ioDirMask) != 0 ) - { - *includeDirs = true; - } - else - { - *includeFiles = true; - } - } - else - { - /* no interest in directory bit - get both files and directories */ - *includeDirs = true; - *includeFiles = true; - } - } - else - { - /* no attribute checking - get both files and directories */ - *includeDirs = true; - *includeFiles = true; - } - - /* If directories are included in the search, */ - /* then the locked attribute cannot be requested. */ - if ( *includeDirs && - ((userPB->ioSearchBits & fsSBFlAttrib) != 0) && - ((searchInfo2->hFileInfo.ioFlAttrib & 0x01) != 0) ) - { - goto ParamErrExit; - } - - /* If files are included in the search, then there cannot be */ - /* a search on the number of files. */ - if ( *includeFiles && - ((userPB->ioSearchBits & fsSBDrNmFls) != 0) ) - { - goto ParamErrExit; - } - - /* If directories are included in the search, then there cannot */ - /* be a search on file lengths. */ - if ( *includeDirs && - ((userPB->ioSearchBits & (fsSBFlLgLen | fsSBFlPyLen | fsSBFlRLgLen | fsSBFlRPyLen)) != 0) ) - { - goto ParamErrExit; - } - - return ( noErr ); - -ParamErrExit: - return ( paramErr ); -} - -/*****************************************************************************/ - -/* -** IsSubString checks to see if a string is a substring of another string. -** Both input strings have already been converted to all uppercase using -** UprString (the same non-international call the File Manager uses). -*/ -static Boolean IsSubString(ConstStr255Param aStringPtr, - ConstStr255Param subStringPtr) -{ - short strLength; /* length of string */ - short subStrLength; /* length of subString */ - Boolean found; /* result of test */ - short index; /* current index into string */ - - found = false; - strLength = aStringPtr[0]; - subStrLength = subStringPtr[0]; - - if ( subStrLength <= strLength) - { - register short count; /* search counter */ - register short strIndex; /* running index into string */ - register short subStrIndex; /* running index into subString */ - - /* start looking at first character */ - index = 1; - - /* continue looking until remaining string is shorter than substring */ - count = strLength - subStrLength + 1; - - do - { - strIndex = index; /* start string index at index */ - subStrIndex = 1; /* start subString index at 1 */ - - while ( !found && (aStringPtr[strIndex] == subStringPtr[subStrIndex]) ) - { - if ( subStrIndex == subStrLength ) - { - /* all characters in subString were found */ - found = true; - } - else - { - /* check next character of substring against next character of string */ - ++subStrIndex; - ++strIndex; - } - } - - if ( !found ) - { - /* start substring search again at next string character */ - ++index; - --count; - } - } while ( count != 0 && (!found) ); - } - - return ( found ); -} - -/*****************************************************************************/ - -/* -** CompareMasked does a bitwise comparison with mask on 1 or more longs. -** data1 and data2 are first exclusive-ORed together resulting with bits set -** where they are different. That value is then ANDed with the mask resulting -** with bits set if the test fails. true is returned if the tests pass. -*/ -static Boolean CompareMasked(const long *data1, - const long *data2, - const long *mask, - short longsToCompare) -{ - Boolean result = true; - - while ( (longsToCompare != 0) && (result == true) ) - { - /* (*data1 ^ *data2) = bits that are different, so... */ - /* ((*data1 ^ *data2) & *mask) = bits that are different that we're interested in */ - - if ( ((*data1 ^ *data2) & *mask) != 0 ) - result = false; - - ++data1; - ++data2; - ++mask; - --longsToCompare; - } - - return ( result ); -} - -/*****************************************************************************/ - -/* -** Check for matches compares the search criteria in userPB to the file -** system object in cPB. If there's a match, then the information in cPB is -** is added to the match array and the actual match count is incremented. -*/ -static void CheckForMatches(CInfoPBPtr cPB, - CSParamPtr userPB, - const Str63 matchName, - Boolean includeFiles, - Boolean includeDirs) -{ - long searchBits; - CInfoPBPtr searchInfo1; - CInfoPBPtr searchInfo2; - Str63 itemName; /* copy of object's name for partial name matching */ - Boolean foundMatch; - - foundMatch = false; /* default to no match */ - - searchBits = userPB->ioSearchBits; - searchInfo1 = userPB->ioSearchInfo1; - searchInfo2 = userPB->ioSearchInfo2; - - /* Into the if statements that go on forever... */ - - if ( (cPB->hFileInfo.ioFlAttrib & ioDirMask) == 0 ) - { - if (!includeFiles) - { - goto Failed; - } - } - else - { - if (!includeDirs) - { - goto Failed; - } - } - - if ( (searchBits & fsSBPartialName) != 0 ) - { - if ( (cPB->hFileInfo.ioNamePtr[0] > 0) && - (cPB->hFileInfo.ioNamePtr[0] <= (sizeof(Str63) - 1)) ) - { - /* Make uppercase copy of object name */ - BlockMoveData(cPB->hFileInfo.ioNamePtr, - itemName, - cPB->hFileInfo.ioNamePtr[0] + 1); - /* Use the same non-international call the File Manager uses */ - UpperString(itemName, true); - } - else - { - goto Failed; - } - - { - if ( !IsSubString(itemName, matchName) ) - { - goto Failed; - } - else if ( searchBits == fsSBPartialName ) - { - /* optimize for name matching only since it is most common way to search */ - goto Hit; - } - } - } - - if ( (searchBits & fsSBFullName) != 0 ) - { - /* Use the same non-international call the File Manager uses */ - if ( !EqualString(cPB->hFileInfo.ioNamePtr, matchName, false, true) ) - { - goto Failed; - } - else if ( searchBits == fsSBFullName ) - { - /* optimize for name matching only since it is most common way to search */ - goto Hit; - } - } - - if ( (searchBits & fsSBFlParID) != 0 ) - { - if ( ((unsigned long)(cPB->hFileInfo.ioFlParID) < (unsigned long)(searchInfo1->hFileInfo.ioFlParID)) || - ((unsigned long)(cPB->hFileInfo.ioFlParID) > (unsigned long)(searchInfo2->hFileInfo.ioFlParID)) ) - { - goto Failed; - } - } - - if ( (searchBits & fsSBFlAttrib) != 0 ) - { - if ( ((cPB->hFileInfo.ioFlAttrib ^ searchInfo1->hFileInfo.ioFlAttrib) & - searchInfo2->hFileInfo.ioFlAttrib) != 0 ) - { - goto Failed; - } - } - - if ( (searchBits & fsSBDrNmFls) != 0 ) - { - if ( ((unsigned long)(cPB->dirInfo.ioDrNmFls) < (unsigned long)(searchInfo1->dirInfo.ioDrNmFls)) || - ((unsigned long)(cPB->dirInfo.ioDrNmFls) > (unsigned long)(searchInfo2->dirInfo.ioDrNmFls)) ) - { - goto Failed; - } - } - - if ( (searchBits & fsSBFlFndrInfo) != 0 ) /* fsSBFlFndrInfo is same as fsSBDrUsrWds */ - { - if ( !CompareMasked((long *)&(cPB->hFileInfo.ioFlFndrInfo), - (long *)&(searchInfo1->hFileInfo.ioFlFndrInfo), - (long *)&(searchInfo2->hFileInfo.ioFlFndrInfo), - sizeof(FInfo) / sizeof(long)) ) - { - goto Failed; - } - } - - if ( (searchBits & fsSBFlXFndrInfo) != 0 ) /* fsSBFlXFndrInfo is same as fsSBDrFndrInfo */ - { - if ( !CompareMasked((long *)&(cPB->hFileInfo.ioFlXFndrInfo), - (long *)&(searchInfo1->hFileInfo.ioFlXFndrInfo), - (long *)&(searchInfo2->hFileInfo.ioFlXFndrInfo), - sizeof(FXInfo) / sizeof(long)) ) - { - goto Failed; - } - } - - if ( (searchBits & fsSBFlLgLen) != 0 ) - { - if ( ((unsigned long)(cPB->hFileInfo.ioFlLgLen) < (unsigned long)(searchInfo1->hFileInfo.ioFlLgLen)) || - ((unsigned long)(cPB->hFileInfo.ioFlLgLen) > (unsigned long)(searchInfo2->hFileInfo.ioFlLgLen)) ) - { - goto Failed; - } - } - - if ( (searchBits & fsSBFlPyLen) != 0 ) - { - if ( ((unsigned long)(cPB->hFileInfo.ioFlPyLen) < (unsigned long)(searchInfo1->hFileInfo.ioFlPyLen)) || - ((unsigned long)(cPB->hFileInfo.ioFlPyLen) > (unsigned long)(searchInfo2->hFileInfo.ioFlPyLen)) ) - { - goto Failed; - } - } - - if ( (searchBits & fsSBFlRLgLen) != 0 ) - { - if ( ((unsigned long)(cPB->hFileInfo.ioFlRLgLen) < (unsigned long)(searchInfo1->hFileInfo.ioFlRLgLen)) || - ((unsigned long)(cPB->hFileInfo.ioFlRLgLen) > (unsigned long)(searchInfo2->hFileInfo.ioFlRLgLen)) ) - { - goto Failed; - } - } - - if ( (searchBits & fsSBFlRPyLen) != 0 ) - { - if ( ((unsigned long)(cPB->hFileInfo.ioFlRPyLen) < (unsigned long)(searchInfo1->hFileInfo.ioFlRPyLen)) || - ((unsigned long)(cPB->hFileInfo.ioFlRPyLen) > (unsigned long)(searchInfo2->hFileInfo.ioFlRPyLen)) ) - { - goto Failed; - } - } - - if ( (searchBits & fsSBFlCrDat) != 0 ) /* fsSBFlCrDat is same as fsSBDrCrDat */ - { - if ( ((unsigned long)(cPB->hFileInfo.ioFlCrDat) < (unsigned long)(searchInfo1->hFileInfo.ioFlCrDat)) || - ((unsigned long)(cPB->hFileInfo.ioFlCrDat) > (unsigned long)(searchInfo2->hFileInfo.ioFlCrDat)) ) - { - goto Failed; - } - } - - if ( (searchBits & fsSBFlMdDat) != 0 ) /* fsSBFlMdDat is same as fsSBDrMdDat */ - { - if ( ((unsigned long)(cPB->hFileInfo.ioFlMdDat) < (unsigned long)(searchInfo1->hFileInfo.ioFlMdDat)) || - ((unsigned long)(cPB->hFileInfo.ioFlMdDat) > (unsigned long)(searchInfo2->hFileInfo.ioFlMdDat)) ) - { - goto Failed; - } - } - - if ( (searchBits & fsSBFlBkDat) != 0 ) /* fsSBFlBkDat is same as fsSBDrBkDat */ - { - if ( ((unsigned long)(cPB->hFileInfo.ioFlBkDat) < (unsigned long)(searchInfo1->hFileInfo.ioFlBkDat)) || - ((unsigned long)(cPB->hFileInfo.ioFlBkDat) > (unsigned long)(searchInfo2->hFileInfo.ioFlBkDat)) ) - { - goto Failed; - } - } - - /* Hey, we passed all of the tests! */ - -Hit: - foundMatch = true; - -/* foundMatch is false if code jumps to Failed */ -Failed: - /* Do we reverse our findings? */ - if ( (searchBits & fsSBNegate) != 0 ) - { - foundMatch = !foundMatch; /* matches are not, not matches are */ - } - - if ( foundMatch ) - { - - /* Move the match into the match buffer */ - userPB->ioMatchPtr[userPB->ioActMatchCount].vRefNum = cPB->hFileInfo.ioVRefNum; - userPB->ioMatchPtr[userPB->ioActMatchCount].parID = cPB->hFileInfo.ioFlParID; - if ( cPB->hFileInfo.ioNamePtr[0] > 63 ) - { - cPB->hFileInfo.ioNamePtr[0] = 63; - } - BlockMoveData(cPB->hFileInfo.ioNamePtr, - userPB->ioMatchPtr[userPB->ioActMatchCount].name, - cPB->hFileInfo.ioNamePtr[0] + 1); - - /* increment the actual count */ - ++(userPB->ioActMatchCount); - } -} - -/*****************************************************************************/ - -/* -** TimeOutTask is executed when the timer goes off. It simply sets the -** stopSearch field to true. After each object is found and possibly added -** to the matches buffer, stopSearch is checked to see if the search should -** continue. -*/ - -#if __WANTPASCALELIMINATION -#undef pascal -#endif -#if TARGET_CARBON -static pascal void TimeOutTask(TMTaskPtr tmTaskPtr) -{ - ((ExtendedTMTaskPtr)tmTaskPtr)->stopSearch = true; -} -#else -#if GENERATINGCFM - -static pascal void TimeOutTask(TMTaskPtr tmTaskPtr) -{ - ((ExtendedTMTaskPtr)tmTaskPtr)->stopSearch = true; -} - -#else - -static pascal TMTaskPtr GetTMTaskPtr(void) - ONEWORDINLINE(0x2e89); /* MOVE.L A1,(SP) */ - -static void TimeOutTask(void) -{ - ((ExtendedTMTaskPtr)GetTMTaskPtr())->stopSearch = true; -} -#endif -#endif - -#if __WANTPASCALELIMINATION -#define pascal -#endif - -/*****************************************************************************/ - -/* -** GetDirModDate returns the modification date of a directory. If there is -** an error getting the modification date, -1 is returned to indicate -** something went wrong. -*/ -static long GetDirModDate(short vRefNum, - long dirID) -{ - CInfoPBRec pb; - Str31 tempName; - long modDate; - - /* Protection against File Sharing problem */ - tempName[0] = 0; - pb.dirInfo.ioNamePtr = tempName; - pb.dirInfo.ioVRefNum = vRefNum; - pb.dirInfo.ioDrDirID = dirID; - pb.dirInfo.ioFDirIndex = -1; /* use ioDrDirID */ - - if ( PBGetCatInfoSync(&pb) == noErr ) - { - modDate = pb.dirInfo.ioDrMdDat; - } - else - { - modDate = -1; - } - - return ( modDate ); -} - -/*****************************************************************************/ - -pascal OSErr IndexedSearch(CSParamPtr pb, - long dirID) -{ - static LevelRecHandle searchStack = NULL; /* static handle to LevelRec stack */ - static Size searchStackSize = 0; /* size of static handle */ - SearchPositionRecPtr catPosition; - long modDate; - short index; - ExtendedTMTask timerTask; - OSErr result; - short realVRefNum; - Str63 itemName; - CInfoPBRec cPB; - long tempLong; - Boolean includeFiles; - Boolean includeDirs; - Boolean includeNames; - Str63 upperName; - - timerTask.stopSearch = false; /* don't stop yet! */ - - /* If request has a timeout, install a Time Manager task. */ - if ( pb->ioSearchTime != 0 ) - { - /* Start timer */ -#if defined(UNIVERSAL_INTERFACES_VERSION) && (UNIVERSAL_INTERFACES_VERSION >= 0x0340) - timerTask.theTask.tmAddr = NewTimerUPP(TimeOutTask); -#else - timerTask.theTask.tmAddr = NewTimerProc(TimeOutTask); -#endif - InsTime((QElemPtr)&(timerTask.theTask)); - PrimeTime((QElemPtr)&(timerTask.theTask), pb->ioSearchTime); - } - - /* Check the parameter block passed for things that we don't want to assume */ - /* are OK later in the code. For example, make sure pointers to data structures */ - /* and buffers are not NULL. And while we're in there, see if the request */ - /* specified searching for files, directories, or both, and see if the search */ - /* was by full or partial name. */ - result = VerifyUserPB(pb, &includeFiles, &includeDirs, &includeNames); - if ( result == noErr ) - { - pb->ioActMatchCount = 0; /* no matches yet */ - - if ( includeNames ) - { - /* The search includes seach by full or partial name. */ - /* Make an upper case copy of the match string to pass to */ - /* CheckForMatches. */ - BlockMoveData(pb->ioSearchInfo1->hFileInfo.ioNamePtr, - upperName, - pb->ioSearchInfo1->hFileInfo.ioNamePtr[0] + 1); - /* Use the same non-international call the File Manager uses */ - UpperString(upperName, true); - } - - /* Prevent casting to my type throughout code */ - catPosition = (SearchPositionRecPtr)&pb->ioCatPosition; - - /* Create searchStack first time called */ - if ( searchStack == NULL ) - { - searchStack = (LevelRecHandle)NewHandle(kAdditionalLevelRecs * sizeof(LevelRec)); - } - - /* Make sure searchStack really exists */ - if ( searchStack != NULL ) - { -#if TARGET_CARBON - searchStackSize = GetHandleSize((Handle)searchStack); -#else - searchStackSize = InlineGetHandleSize((Handle)searchStack); -#endif - - /* See if the search is a new search or a resumed search. */ - if ( catPosition->initialize == 0 ) - { - /* New search. */ - - /* Get the real vRefNum and fill in catPosition->initialize. */ - result = CheckVol(pb->ioNamePtr, pb->ioVRefNum, &realVRefNum, &catPosition->initialize); - if ( result == noErr ) - { - /* clear searchStack */ - catPosition->stackDepth = 0; - - /* use dirID parameter passed and... */ - index = -1; /* start with the passed directory itself! */ - } - } - else - { - /* We're resuming a search. */ - - /* Get the real vRefNum and make sure catPosition->initialize is valid. */ - result = CheckVol(pb->ioNamePtr, pb->ioVRefNum, &realVRefNum, &tempLong); - if ( result == noErr ) - { - /* Make sure the resumed search is to the same volume! */ - if ( catPosition->initialize == tempLong ) - { - /* For resume, catPosition->stackDepth > 0 */ - if ( catPosition->stackDepth > 0 ) - { - /* Position catPosition->stackDepth to access last saved level */ - --(catPosition->stackDepth); - - /* Get the dirID and index for the next item */ - dirID = (*searchStack)[catPosition->stackDepth].dirID; - index = (*searchStack)[catPosition->stackDepth].index; - - /* Check the dir's mod date against the saved mode date on our "stack" */ - modDate = GetDirModDate(realVRefNum, dirID); - if ( modDate != (*searchStack)[catPosition->stackDepth].dirModDate ) - { - result = catChangedErr; - } - } - else - { - /* Invalid catPosition record was passed */ - result = paramErr; - } - } - else - { - /* The volume is not the same */ - result = catChangedErr; - } - } - } - - if ( result == noErr ) - { - /* ioNamePtr and ioVRefNum only need to be set up once. */ - cPB.hFileInfo.ioNamePtr = itemName; - cPB.hFileInfo.ioVRefNum = realVRefNum; - - /* - ** Here's the loop that: - ** Finds the next item on the volume. - ** If noErr, calls the code to check for matches and add matches - ** to the match buffer. - ** Sets up dirID and index for to find the next item on the volume. - ** - ** The looping ends when: - ** (a) an unexpected error is returned by PBGetCatInfo. All that - ** is expected is noErr and fnfErr (after the last item in a - ** directory is found). - ** (b) the caller specified a timeout and our Time Manager task - ** has fired. - ** (c) the number of matches requested by the caller has been found. - ** (d) the last item on the volume was found. - */ - do - { - /* get the next item */ - cPB.hFileInfo.ioFDirIndex = index; - cPB.hFileInfo.ioDirID = dirID; - result = PBGetCatInfoSync(&cPB); - if ( index != -1 ) - { - if ( result == noErr ) - { - /* We found something */ - - CheckForMatches(&cPB, pb, upperName, includeFiles, includeDirs); - - ++index; - if ( (cPB.dirInfo.ioFlAttrib & ioDirMask) != 0 ) - { - /* It's a directory */ - - result = CheckStack(catPosition->stackDepth, searchStack, &searchStackSize); - if ( result == noErr ) - { - /* Save the current state on the searchStack */ - /* when we come back, this is where we'll start */ - (*searchStack)[catPosition->stackDepth].dirID = dirID; - (*searchStack)[catPosition->stackDepth].index = index; - (*searchStack)[catPosition->stackDepth].dirModDate = GetDirModDate(realVRefNum, dirID); - - /* position catPosition->stackDepth for next saved level */ - ++(catPosition->stackDepth); - - /* The next item to get is the 1st item in the child directory */ - dirID = cPB.dirInfo.ioDrDirID; - index = 1; - } - } - /* else do nothing for files */ - } - else - { - /* End of directory found (or we had some error and that */ - /* means we have to drop out of this directory). */ - /* Restore last thing put on stack and */ - /* see if we need to continue or quit. */ - if ( catPosition->stackDepth > 0 ) - { - /* position catPosition->stackDepth to access last saved level */ - --(catPosition->stackDepth); - - dirID = (*searchStack)[catPosition->stackDepth].dirID; - index = (*searchStack)[catPosition->stackDepth].index; - - /* Check the dir's mod date against the saved mode date on our "stack" */ - modDate = GetDirModDate(realVRefNum, dirID); - if ( modDate != (*searchStack)[catPosition->stackDepth].dirModDate ) - { - result = catChangedErr; - } - else - { - /* Going back to ancestor directory. */ - /* Clear error so we can continue. */ - result = noErr; - } - } - else - { - /* We hit the bottom of the stack, so we'll let the */ - /* the eofErr drop us out of the loop. */ - result = eofErr; - } - } - } - else - { - /* Special case for index == -1; that means that we're starting */ - /* a new search and so the first item to check is the directory */ - /* passed to us. */ - if ( result == noErr ) - { - /* We found something */ - - CheckForMatches(&cPB, pb, upperName, includeFiles, includeDirs); - - /* Now, set the index to 1 and then we're ready to look inside */ - /* the passed directory. */ - index = 1; - } - } - } while ( (!timerTask.stopSearch) && /* timer hasn't fired */ - (result == noErr) && /* no unexpected errors */ - (pb->ioReqMatchCount > pb->ioActMatchCount) ); /* we haven't found our limit */ - - /* Did we drop out of the loop because of timeout or */ - /* ioReqMatchCount was found? */ - if ( result == noErr ) - { - result = CheckStack(catPosition->stackDepth, searchStack, &searchStackSize); - if ( result == noErr ) - { - /* Either there was a timeout or ioReqMatchCount was reached. */ - /* Save the dirID and index for the next time we're called. */ - - (*searchStack)[catPosition->stackDepth].dirID = dirID; - (*searchStack)[catPosition->stackDepth].index = index; - (*searchStack)[catPosition->stackDepth].dirModDate = GetDirModDate(realVRefNum, dirID); - - /* position catPosition->stackDepth for next saved level */ - - ++(catPosition->stackDepth); - } - } - } - } - else - { - /* searchStack Handle could not be allocated */ - result = memFullErr; - } - } - - if ( pb->ioSearchTime != 0 ) - { - /* Stop Time Manager task here if it was installed */ - RmvTime((QElemPtr)&(timerTask.theTask)); - DisposeTimerUPP(timerTask.theTask.tmAddr); - } - - return ( result ); -} - -/*****************************************************************************/ - -pascal OSErr PBCatSearchSyncCompat(CSParamPtr paramBlock) -{ - static Boolean fullExtFSDispatchingtested = false; - static Boolean hasFullExtFSDispatching = false; - OSErr result; - Boolean supportsCatSearch; - long response; - GetVolParmsInfoBuffer volParmsInfo; - long infoSize; - - result = noErr; - - /* See if File Manager will pass CatSearch requests to external file systems */ - /* we'll store the results in a static variable so we don't have to call Gestalt */ - /* everytime we're called. */ - if ( !fullExtFSDispatchingtested ) - { - fullExtFSDispatchingtested = true; - if ( Gestalt(gestaltFSAttr, &response) == noErr ) - { - hasFullExtFSDispatching = ((response & (1L << gestaltFullExtFSDispatching)) != 0); - } - } - - /* CatSearch is a per volume attribute, so we have to check each time we're */ - /* called to see if it is available on the volume specified. */ - supportsCatSearch = false; - if ( hasFullExtFSDispatching ) - { - infoSize = sizeof(GetVolParmsInfoBuffer); - result = HGetVolParms(paramBlock->ioNamePtr, paramBlock->ioVRefNum, - &volParmsInfo, &infoSize); - if ( result == noErr ) - { - supportsCatSearch = hasCatSearch(volParmsInfo); - } - } - - /* noErr or paramErr is OK here. */ - /* paramErr just means that GetVolParms isn't supported by this volume */ - if ( (result == noErr) || (result == paramErr) ) - { - if ( supportsCatSearch ) - { - /* Volume supports CatSearch so use it. */ - /* CatSearch is faster than an indexed search. */ - result = PBCatSearchSync(paramBlock); - } - else - { - /* Volume doesn't support CatSearch so */ - /* search using IndexedSearch from root directory. */ - result = IndexedSearch(paramBlock, fsRtDirID); - } - } - - return ( result ); -} - -/*****************************************************************************/ - -pascal OSErr NameFileSearch(ConstStr255Param volName, - short vRefNum, - ConstStr255Param fileName, - FSSpecPtr matches, - long reqMatchCount, - long *actMatchCount, - Boolean newSearch, - Boolean partial) -{ - CInfoPBRec searchInfo1, searchInfo2; - HParamBlockRec pb; - OSErr error; - static CatPositionRec catPosition; - static short lastVRefNum = 0; - - /* get the real volume reference number */ - error = DetermineVRefNum(volName, vRefNum, &vRefNum); - if ( error != noErr ) - return ( error ); - - pb.csParam.ioNamePtr = NULL; - pb.csParam.ioVRefNum = vRefNum; - pb.csParam.ioMatchPtr = matches; - pb.csParam.ioReqMatchCount = reqMatchCount; - if ( partial ) /* tell CatSearch what we're looking for: */ - { - pb.csParam.ioSearchBits = fsSBPartialName + fsSBFlAttrib; /* partial name file matches or */ - } - else - { - pb.csParam.ioSearchBits = fsSBFullName + fsSBFlAttrib; /* full name file matches */ - } - pb.csParam.ioSearchInfo1 = &searchInfo1; - pb.csParam.ioSearchInfo2 = &searchInfo2; - pb.csParam.ioSearchTime = 0; - if ( (newSearch) || /* If caller specified new search */ - (lastVRefNum != vRefNum) ) /* or if last search was to another volume, */ - { - catPosition.initialize = 0; /* then search from beginning of catalog */ - } - pb.csParam.ioCatPosition = catPosition; - pb.csParam.ioOptBuffer = GetTempBuffer(0x00004000, &pb.csParam.ioOptBufSize); - - /* search for fileName */ - searchInfo1.hFileInfo.ioNamePtr = (StringPtr)fileName; - searchInfo2.hFileInfo.ioNamePtr = NULL; - - /* only match files (not directories) */ - searchInfo1.hFileInfo.ioFlAttrib = 0x00; - searchInfo2.hFileInfo.ioFlAttrib = ioDirMask; - - error = PBCatSearchSyncCompat((CSParamPtr)&pb); - - if ( (error == noErr) || /* If no errors or the end of catalog was */ - (error == eofErr) ) /* found, then the call was successful so */ - { - *actMatchCount = pb.csParam.ioActMatchCount; /* return the match count */ - } - else - { - *actMatchCount = 0; /* else no matches found */ - } - - if ( (error == noErr) || /* If no errors */ - (error == catChangedErr) ) /* or there was a change in the catalog */ - { - catPosition = pb.csParam.ioCatPosition; - lastVRefNum = vRefNum; - /* we can probably start the next search where we stopped this time */ - } - else - { - catPosition.initialize = 0; - /* start the next search from beginning of catalog */ - } - - if ( pb.csParam.ioOptBuffer != NULL ) - { - DisposePtr(pb.csParam.ioOptBuffer); - } - - return ( error ); -} - -/*****************************************************************************/ - -pascal OSErr CreatorTypeFileSearch(ConstStr255Param volName, - short vRefNum, - OSType creator, - OSType fileType, - FSSpecPtr matches, - long reqMatchCount, - long *actMatchCount, - Boolean newSearch) -{ - CInfoPBRec searchInfo1, searchInfo2; - HParamBlockRec pb; - OSErr error; - static CatPositionRec catPosition; - static short lastVRefNum = 0; - - /* get the real volume reference number */ - error = DetermineVRefNum(volName, vRefNum, &vRefNum); - if ( error != noErr ) - return ( error ); - - pb.csParam.ioNamePtr = NULL; - pb.csParam.ioVRefNum = vRefNum; - pb.csParam.ioMatchPtr = matches; - pb.csParam.ioReqMatchCount = reqMatchCount; - pb.csParam.ioSearchBits = fsSBFlAttrib + fsSBFlFndrInfo; /* Looking for finder info file matches */ - pb.csParam.ioSearchInfo1 = &searchInfo1; - pb.csParam.ioSearchInfo2 = &searchInfo2; - pb.csParam.ioSearchTime = 0; - if ( (newSearch) || /* If caller specified new search */ - (lastVRefNum != vRefNum) ) /* or if last search was to another volume, */ - { - catPosition.initialize = 0; /* then search from beginning of catalog */ - } - pb.csParam.ioCatPosition = catPosition; - pb.csParam.ioOptBuffer = GetTempBuffer(0x00004000, &pb.csParam.ioOptBufSize); - - /* no fileName */ - searchInfo1.hFileInfo.ioNamePtr = NULL; - searchInfo2.hFileInfo.ioNamePtr = NULL; - - /* only match files (not directories) */ - searchInfo1.hFileInfo.ioFlAttrib = 0x00; - searchInfo2.hFileInfo.ioFlAttrib = ioDirMask; - - /* search for creator; if creator = 0x00000000, ignore creator */ - searchInfo1.hFileInfo.ioFlFndrInfo.fdCreator = creator; - if ( creator == (OSType)0x00000000 ) - { - searchInfo2.hFileInfo.ioFlFndrInfo.fdCreator = (OSType)0x00000000; - } - else - { - searchInfo2.hFileInfo.ioFlFndrInfo.fdCreator = (OSType)0xffffffff; - } - - /* search for fileType; if fileType = 0x00000000, ignore fileType */ - searchInfo1.hFileInfo.ioFlFndrInfo.fdType = fileType; - if ( fileType == (OSType)0x00000000 ) - { - searchInfo2.hFileInfo.ioFlFndrInfo.fdType = (OSType)0x00000000; - } - else - { - searchInfo2.hFileInfo.ioFlFndrInfo.fdType = (OSType)0xffffffff; - } - - /* zero all other FInfo fields */ - searchInfo1.hFileInfo.ioFlFndrInfo.fdFlags = 0; - searchInfo1.hFileInfo.ioFlFndrInfo.fdLocation.v = 0; - searchInfo1.hFileInfo.ioFlFndrInfo.fdLocation.h = 0; - searchInfo1.hFileInfo.ioFlFndrInfo.fdFldr = 0; - - searchInfo2.hFileInfo.ioFlFndrInfo.fdFlags = 0; - searchInfo2.hFileInfo.ioFlFndrInfo.fdLocation.v = 0; - searchInfo2.hFileInfo.ioFlFndrInfo.fdLocation.h = 0; - searchInfo2.hFileInfo.ioFlFndrInfo.fdFldr = 0; - - error = PBCatSearchSyncCompat((CSParamPtr)&pb); - - if ( (error == noErr) || /* If no errors or the end of catalog was */ - (error == eofErr) ) /* found, then the call was successful so */ - { - *actMatchCount = pb.csParam.ioActMatchCount; /* return the match count */ - } - else - { - *actMatchCount = 0; /* else no matches found */ - } - - if ( (error == noErr) || /* If no errors */ - (error == catChangedErr) ) /* or there was a change in the catalog */ - { - catPosition = pb.csParam.ioCatPosition; - lastVRefNum = vRefNum; - /* we can probably start the next search where we stopped this time */ - } - else - { - catPosition.initialize = 0; - /* start the next search from beginning of catalog */ - } - - if ( pb.csParam.ioOptBuffer != NULL ) - { - DisposePtr(pb.csParam.ioOptBuffer); - } - - return ( error ); -} - -/*****************************************************************************/ diff --git a/src/mac/morefile/mfsearch.h b/src/mac/morefile/mfsearch.h deleted file mode 100644 index 6bd1fdf261..0000000000 --- a/src/mac/morefile/mfsearch.h +++ /dev/null @@ -1,246 +0,0 @@ -/* -** 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 -#include - -#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__ */ diff --git a/src/mac/utils.cpp b/src/mac/utils.cpp index f234da7456..e490ce4583 100644 --- a/src/mac/utils.cpp +++ b/src/mac/utils.cpp @@ -28,8 +28,8 @@ #include #ifndef __DARWIN__ -# include "morefile.h" -# include "moreextr.h" + #include "MoreFiles.h" + #include "MoreFilesExtras.h" #endif #ifndef __DARWIN__