home *** CD-ROM | disk | FTP | other *** search
- /*==================================================================
- File: MacOS_ConnectixUtils.cpp
-
- Contains: Miscellaneous utility routines used in program.
-
- Written by: Various
-
- Copyright: © 1995-2001 Connectix Corporation
- ==================================================================*/
-
- #include "MacOS_ConnectixUtils.h"
-
- #include <Folders.h>
-
-
- // static functions
- static OSErr DetermineVRefNum(ConstStr255Param inPathname, SInt16 inVRefNum, SInt16 * outRealVRefNum);
-
- enum
- {
- kAnyFileType = FOUR_CHAR_CODE('****'),
- kAnyFileCreator = FOUR_CHAR_CODE('****')
- };
-
-
- /*------------------------------------------------------------------
- CompareBytes
-
- This function compares two blocks of bytes. If the first block
- is greater than the second, the result is positive. If the
- converse is true. the result is negative. If the blocks are
- equal, the result is zero.
-
- Parameters:
- In: inSource - the source bytes
- inDest - the destination bytes
- inByteCount - number of bytes to compare
- Out: <return> - positive if 1st > 2nd;
- negative if 1st < 2nd;
- zero if equal
- ------------------------------------------------------------------*/
-
- SInt32
- CompareBytes(const void* inSource, const void* inDest, UInt32 inByteCount)
- {
- // If count is a multiple of four and source and dest
- // are four-byte aligned, perform a faster search.
- if (((inByteCount | reinterpret_cast<const UInt32>(inSource) | reinterpret_cast<const UInt32>(inDest)) & 0x3) == 0)
- {
- SInt32 longResult;
- UInt32 longsLeft = inByteCount >> 2;
- const UInt32* curStr1 = reinterpret_cast<const UInt32*>(inSource);
- const UInt32* curStr2 = reinterpret_cast<const UInt32*>(inDest);
-
- while (longsLeft > 0)
- {
- longResult = *curStr1++ - *curStr2++;
- if (longResult)
- return longResult;
-
- longsLeft--;
- }
- }
- else
- {
- SInt8 byteResult;
- UInt32 bytesLeft = inByteCount;
- const UInt8* curStr1 = reinterpret_cast<const UInt8*>(inSource);
- const UInt8* curStr2 = reinterpret_cast<const UInt8*>(inDest);
-
- while (bytesLeft > 0)
- {
- byteResult = *curStr1++ - *curStr2++;
- if (byteResult)
- return byteResult;
-
- bytesLeft--;
- }
- }
-
- return 0;
- }
-
-
- /*------------------------------------------------------------------
- BytesMatch
-
- This function compares two blocks of bytes for exact equality.
-
- Parameters:
- In: inSource - source bytes
- inDest - destination bytes
- inByteCount - number of bytes to compare
- Out: <return> - true if match
- ------------------------------------------------------------------*/
-
- Boolean
- BytesMatch(const void* inSource, const void* inDest, UInt32 inByteCount)
- {
- return CompareBytes(inSource, inDest, inByteCount) == 0;
- }
-
-
- /*------------------------------------------------------------------
- FillMemory
-
- This function sets the specified range of memory to zero.
-
- Parameters:
- In: inBase - memory base
- inByteCount - number of bytes to zero
- inFillValue - byte to fill
- ------------------------------------------------------------------*/
-
- // This alternate version of FillMemory is for 68K.
-
- void
- FillMemory( void* inBase,
- UInt32 inByteCount,
- UInt8 inFillValue)
- {
- UInt8* curAddr = (UInt8*)inBase;
- double* doubleAddr;
- UInt32 longValue;
- UInt32 rounder;
- double memDouble;
- double regDouble;
-
- longValue = inFillValue | (inFillValue << 8);
- longValue |= longValue << 16;
-
- // Warning: this code assumes doubles are eight bytes in
- // length. On 68K, it's possible that you may have doubles
- // set to 10 bytes. That would be bad.
- check (sizeof(double) == 8);
-
- if (inByteCount < 15)
- {
- while (inByteCount > 0)
- {
- *curAddr++ = inFillValue;
- inByteCount--;
- }
- }
- else
- {
- // first set up our 8-byte fill double.
- ((UInt32*)&memDouble)[0] = longValue;
- ((UInt32*)&memDouble)[1] = longValue;
-
- // then fill up the first 8 bytes regardless.
- *(UInt32*)curAddr = longValue;
- *(UInt32*)(curAddr+4) = longValue;
-
- // figure out how many bytes we need to skip to get
- // to an 8-byte boundary
- rounder = 8 - (7 & (long)curAddr);
-
- // set doubleAddr to be 8 byte prior to that boundary.
- doubleAddr = ((double *)(-8 & (long)curAddr));
-
- // point curAddr past the end of our fill range and fill
- // the last 8 bytes regardless.
- curAddr += inByteCount;
- *(UInt32*)(curAddr - 4) = longValue;
- *(UInt32*)(curAddr - 8) = longValue;
-
- // adjust inByteCount for the fact that we can ignore the
- // bytes prior to the first 8-byte boundary.
- inByteCount -= rounder;
-
- // setup our 8-byte fill double.
- regDouble = memDouble;
-
- // we're going to fill 16 bytes at a time, so if what we
- // have left to fill isn't a multiple of 16 bytes, we'll
- // need an extr 8 filled.
- if (inByteCount & 8) *++doubleAddr = regDouble;
-
- // finally, as long as we have 16 bytes or more to fill,
- // fill them up.
- while (inByteCount > 15)
- {
- *++doubleAddr = regDouble;
- *++doubleAddr = regDouble;
- inByteCount -= 16;
- }
- }
- }
-
-
- /*------------------------------------------------------------------
- ZeroMemory
-
- This function sets the specified range of memory to zero.
-
- Parameters:
- In: inBase - memory base
- inByteCount - number of bytes to zero
- ------------------------------------------------------------------*/
-
- // Alternate version of ZeroMemory for 68K.
-
- void
- ZeroMemory(void* inBase, UInt32 inByteCount)
- {
- FillMemory(inBase, inByteCount, 0);
- }
-
-
- /*------------------------------------------------------------------
- FSpGetDirInfo
-
- This routine calls PBGetCatInfoSync with the FSSpec.
-
- Parameters:
- In: inFileSpec - file spec
- Out: outCInfoPB - ptr to a CInfoPBRec
- (return) - noErr or file system error
- ------------------------------------------------------------------*/
-
- OSErr
- FSpGetDirInfo( const FSSpec * inFileSpec,
- CInfoPBPtr outCInfoPB)
- {
- OSErr err = noErr;
-
- ZeroMemory(outCInfoPB, sizeof(CInfoPBRec));
-
- outCInfoPB->dirInfo.ioVRefNum = inFileSpec->vRefNum;
- outCInfoPB->dirInfo.ioDrDirID = inFileSpec->parID;
- outCInfoPB->dirInfo.ioNamePtr = (StringPtr) inFileSpec->name;
-
- err = PBGetCatInfoSync(outCInfoPB);
-
- if (!err && !(outCInfoPB->hFileInfo.ioFlAttrib & ioDirMask))
- err = dirNFErr;
-
- return err;
- }
-
-
- /*------------------------------------------------------------------
- FindFolderItemByTypeAndCreator
-
- You may pass a wildcard for either type ('****')
- ------------------------------------------------------------------*/
-
- OSErr
- FindFolderItemByTypeAndCreator(
- short inVRefNum,
- OSType inFolderType,
- Boolean inSearchSubdirectories,
- OSType inFileType,
- OSType inFileCreator,
- FSSpec * outFileSpec)
- {
- OSErr error = noErr;
-
- short folderVRefNum;
- long folderDirID;
- error = ::FindFolder( inVRefNum,
- inFolderType,
- kDontCreateFolder,
- &folderVRefNum,
- &folderDirID );
- if (error == noErr)
- {
- error = FindDirectoryItemByTypeAndCreator( folderVRefNum,
- folderDirID,
- inSearchSubdirectories,
- inFileType,
- inFileCreator,
- outFileSpec);
- }
-
- return error;
- }
-
- /*------------------------------------------------------------------
- FindDirectoryItemByTypeAndCreator
-
- Returns first match.
- You may pass a wildcard for either type ('****').
- ------------------------------------------------------------------*/
-
- OSErr
- FindDirectoryItemByTypeAndCreator(
- short inVRefNum,
- long inDirID,
- Boolean inSearchSubdirectories,
- OSType inFileType,
- OSType inFileCreator,
- FSSpec * outFileSpec)
- {
- OSErr error = noErr;
-
- // Make a spec for the directory
- //
- FSSpec dirSpec;
- error = ::FSMakeFSSpec( inVRefNum,
- inDirID,
- "\p",
- &dirSpec );
- require(error == noErr, FatalError);
-
- // Verify the item is a directory, and get the real dirID
- //
- long dirID;
- error = FSGetDirectoryID(&dirSpec, &dirID);
- require(error == noErr, FatalError);
-
- // Get the real vRefNum
- //
- short vRefNum;
- error = DetermineVRefNum("\p", inVRefNum, &vRefNum);
- require(error == noErr, FatalError);
-
- // Build the CInfo block
- //
- StrFileName itemName = "\p";
- CInfoPBRec catInfo;
- ::ZeroMemory(&catInfo, sizeof(catInfo));
- catInfo.dirInfo.ioNamePtr = itemName;
- catInfo.dirInfo.ioVRefNum = vRefNum;
-
- // Iterate through directory
- //
- Boolean found = false;
- for (short index = 1; !found && error == noErr; index++)
- {
- // Get catalog info for indexed item
- //
- catInfo.dirInfo.ioFDirIndex = index;
- catInfo.dirInfo.ioDrDirID = dirID;
- error = ::PBGetCatInfoSync(&catInfo); // will generete fnfErr at end of iteration
- require(error == noErr || error == fnfErr, FatalError);
-
- if (error == noErr)
- {
- // Determine if item is a file or a directory
- //
- if ((catInfo.hFileInfo.ioFlAttrib & kioFlAttribDirMask) == 0) // a file
- {
- // Check for match
- //
- OSType fileType = catInfo.hFileInfo.ioFlFndrInfo.fdType;
- OSType fileCreator = catInfo.hFileInfo.ioFlFndrInfo.fdCreator;
- if ( (inFileType == kAnyFileType || inFileType == fileType)
- && (inFileCreator == kAnyFileCreator || inFileCreator == fileCreator ) )
- {
- // Match found: Set quit flag and output spec
- //
- found = true;
- error = ::FSMakeFSSpec( catInfo.hFileInfo.ioVRefNum,
- catInfo.hFileInfo.ioFlParID,
- itemName,
- outFileSpec );
- }
- }
- else // a directory
- {
- if (inSearchSubdirectories) // recurse to subdirectories
- {
- error = FindDirectoryItemByTypeAndCreator( catInfo.hFileInfo.ioVRefNum,
- catInfo.dirInfo.ioDrDirID,
- inSearchSubdirectories,
- inFileType,
- inFileCreator,
- outFileSpec );
- if (error == noErr) // a match was found: stop search
- { found = true; }
- else if (error == fnfErr) // normal termination of iteration: keep looking
- { error = noErr; }
- else if (error == afpAccessDenied) // non-fatal permission error: keep looking
- { error = noErr; }
- else // general error: abort with error
- {}
- }
- }
- }
- }
-
- FatalError:
-
- return error;
- }
-
-
- /*------------------------------------------------------------------
- FSGetDirectoryID
-
- This routine gets the ioDrDirID from an FSSpec.
-
- Parameters:
- In: inFileSpec - file spec
- Out: dirID - ioDrDirID
- (return) - noErr or file system error
- ------------------------------------------------------------------*/
-
- OSErr
- FSGetDirectoryID( const FSSpec * inFileSpec,
- long * outDirID)
- {
- OSErr err = noErr;
- CInfoPBRec cInfoPB;
-
- err = FSpGetDirInfo(inFileSpec, &cInfoPB);
- if (err == noErr)
- *outDirID = cInfoPB.dirInfo.ioDrDirID;
-
- return err;
- }
-
-
- /*------------------------------------------------------------------
- GetVolumeInfoNoName
-
- Stolen from MoreFilesExtras for use in GetParentID.
- ------------------------------------------------------------------*/
-
- static OSErr
- GetVolumeInfoNoName(
- ConstStr255Param inPathname,
- SInt16 inVRefNum,
- HParmBlkPtr outPB)
- {
- Str255 tempPathname;
- OSErr err;
-
- /* Make sure pb parameter is not NULL */
- if (outPB != NULL)
- {
- outPB->volumeParam.ioVRefNum = inVRefNum;
- if (inPathname == NULL)
- {
- outPB->volumeParam.ioNamePtr = NULL;
- outPB->volumeParam.ioVolIndex = 0; /* use ioVRefNum only */
- }
- else
- {
- ::BlockMoveData(inPathname, tempPathname, inPathname[0] + 1); /* make a copy of the string and */
- outPB->volumeParam.ioNamePtr = tempPathname; /* use the copy so the original isn't trashed */
- outPB->volumeParam.ioVolIndex = -1; /* use ioNamePtr/ioVRefNum combination */
- }
- err = ::PBHGetVInfoSync(outPB);
- outPB->volumeParam.ioNamePtr = NULL; /* ioNamePtr may point to local tempPathname, so don't return it */
- }
- else
- {
- err = paramErr;
- }
-
- return err;
- }
-
-
- /*------------------------------------------------------------------
- DetermineVRefNum
-
- Stolen from MoreFilesExtras for use in GetParentID.
- ------------------------------------------------------------------*/
-
- static OSErr
- DetermineVRefNum(
- ConstStr255Param inPathname,
- SInt16 inVRefNum,
- SInt16 * outRealVRefNum)
- {
- HParamBlockRec pb;
- OSErr err;
-
- err = GetVolumeInfoNoName(inPathname, inVRefNum, &pb);
-
- if (err == noErr)
- {
- *outRealVRefNum = pb.volumeParam.ioVRefNum;
- }
-
- return err;
- }
-
-
- /*------------------------------------------------------------------
- MakeFSSpec
-
- This routine creates a file specification record from the given
- parameters. It replaces the API call FSMakeFSSpec() because
- FSMakeFSSpec() does not properly handle creating an fsspec for
- the root directory of a PC Exchange volume.
-
- Parameters:
- In: inVRefNum - the volume
- inDirID - the directory ID
- inName - the item name or partial pathname
- Out: outFileSpec - file spec to folder
- (return) - true if found
- ------------------------------------------------------------------*/
-
- OSErr
- MakeFSSpec( SInt16 inVRefNum,
- SInt32 inDirID,
- ConstStr255Param inName,
- FSSpec* outFileSpec)
- {
- OSErr status;
- HParamBlockRec params;
- Str255 name;
-
- if (inDirID != fsRtDirID || StrLength(inName) != 0)
- {
- status = ::FSMakeFSSpec(inVRefNum, inDirID, inName, outFileSpec);
- }
- else
- {
- // Get the root directory name
- params.volumeParam.ioCompletion = NULL;
- BlockMoveData(inName, name, 256);
- params.volumeParam.ioNamePtr = name;
- params.volumeParam.ioVRefNum = inVRefNum;
- params.volumeParam.ioVolIndex = 0; // find using vRefNum only
-
- status = ::PBHGetVInfoSync(¶ms);
- if (status != noErr)
- return(status);
-
- status = ::FSMakeFSSpec(inVRefNum,
- fsRtParID,
- name,
- outFileSpec);
- }
-
- return status;
- }
-
-
- /*------------------------------------------------------------------
- FSpGetCatInfo
-
- This function returns the catalog info for a specified file.
-
- Parameter:
- In: inSpec - a file system spec
- Out: outCatInfo - the catalog info
- (return) - non-zero indicates an error
- ------------------------------------------------------------------*/
-
- OSErr
- FSpGetCatInfo( const FSSpec* inSpec,
- CInfoPBPtr outCatInfo)
- {
- outCatInfo->hFileInfo.ioCompletion = NULL;
- outCatInfo->hFileInfo.ioVRefNum = inSpec->vRefNum;
- outCatInfo->hFileInfo.ioNamePtr = const_cast<StringPtr>(inSpec->name);
- outCatInfo->hFileInfo.ioFDirIndex = 0;
- outCatInfo->hFileInfo.ioDirID = inSpec->parID;
- return PBGetCatInfoSync(outCatInfo);
- }
-
-
-