X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/9b5eee6ed7d8fd2433a44afdbeeb44c0cf345187..420b39aa4b6117a0cf192266ea6f3ed61cbcc1e0:/src/osx/carbon/morefile/MoreFilesExtras.c diff --git a/src/osx/carbon/morefile/MoreFilesExtras.c b/src/osx/carbon/morefile/MoreFilesExtras.c deleted file mode 100644 index f9bda4d855..0000000000 --- a/src/osx/carbon/morefile/MoreFilesExtras.c +++ /dev/null @@ -1,3632 +0,0 @@ -/* - 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 -#if !TARGET_CARBON -#include -#include -#include -#else -#include -#endif -#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; - } - } - } -} - -/*****************************************************************************/ - -static 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 ); -} - -/*****************************************************************************/ -