filespec_carbon.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:49k
- /* ***** BEGIN LICENSE BLOCK *****
- * Source last modified: $Id: filespec_carbon.cpp,v 1.5.32.3 2004/07/09 01:44:13 hubbe Exp $
- *
- * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
- *
- * The contents of this file, and the files included with this file,
- * are subject to the current version of the RealNetworks Public
- * Source License (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the current version of the RealNetworks Community
- * Source License (the "RCSL") available at
- * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
- * will apply. You may also obtain the license terms directly from
- * RealNetworks. You may not use this file except in compliance with
- * the RPSL or, if you have a valid RCSL with RealNetworks applicable
- * to this file, the RCSL. Please see the applicable RPSL or RCSL for
- * the rights, obligations and limitations governing use of the
- * contents of the file.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL") in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your version of
- * this file only under the terms of the GPL, and not to allow others
- * to use your version of this file under the terms of either the RPSL
- * or RCSL, indicate your decision by deleting the provisions above
- * and replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient may
- * use your version of this file under the terms of any one of the
- * RPSL, the RCSL or the GPL.
- *
- * This file is part of the Helix DNA Technology. RealNetworks is the
- * developer of the Original Code and owns the copyrights in the
- * portions it created.
- *
- * This file, and the files included with this file, is distributed
- * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
- * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
- * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
- * ENJOYMENT OR NON-INFRINGEMENT.
- *
- * Technology Compatibility Kit Test Suite(s) Location:
- * http://www.helixcommunity.org/content/tck
- *
- * Contributor(s):
- *
- * ***** END LICENSE BLOCK ***** */
- #include "filespec.h"
- #include "hxstring.h"
- #include "platform/mac/fullpathname.h"
- #ifndef _MAC_UNIX
- #include "platform/mac/maclibrary.h" // for ResolveIndependentPath
- #endif
- #include "platform/mac/hx_moreprocesses.h" // for GetCurrentAppSpec
- #include "platform/mac/cfwrappers.h"
- #include "platform/mac/MoreFilesX.h"
- #define kExtensionSeparator '.'
- inline CFStringEncoding GetStandardPathEncodingForOS()
- {
- // Mach-O path elements are always UTF 8; CFM path elements we
- // system double-byte encoded
- #ifdef _MAC_CFM
- return CFStringGetSystemEncoding();
- #else
- return kCFStringEncodingUTF8;
- #endif
- }
- // ------------------------------------------------------------------------------------
- //
- // CHXMacInternalSpec
- //
- // ------------------------------------------------------------------------------------
- CHXMacInternalSpec::CHXMacInternalSpec()
- {
- InitSpec();
- ClearSpec();
- }
- // ------------------------------------------------------------------------------------
- CHXMacInternalSpec::CHXMacInternalSpec(const FSRef& ref)
- {
- InitSpec();
-
- (void) SetFromFSRef(ref);
- }
- // ------------------------------------------------------------------------------------
- CHXMacInternalSpec::CHXMacInternalSpec(const FSSpec& spec)
- {
- InitSpec();
- (void) SetFromFSSpec(spec);
- }
- // ------------------------------------------------------------------------------------
- CHXMacInternalSpec::CHXMacInternalSpec(AliasHandle alias)
- {
- InitSpec();
- (void) SetFromAlias(alias);
- }
- // ------------------------------------------------------------------------------------
- CHXMacInternalSpec::CHXMacInternalSpec(const char* psz)
- {
- InitSpec();
-
- (void) SetFromPath(psz);
-
- }
- // ------------------------------------------------------------------------------------
- CHXMacInternalSpec::~CHXMacInternalSpec()
- {
- ClearSpec();
- }
- // ------------------------------------------------------------------------------------
- void CHXMacInternalSpec::InitSpec()
- {
- mParentAndLeaf.mpLeafName = NULL;
-
- }
- // ------------------------------------------------------------------------------------
- void CHXMacInternalSpec::ClearSpec()
- {
- ZeroInit(&mItemRef);
- HX_DELETE(mParentAndLeaf.mpLeafName);
- mbRefSet = false;
- mbParentAndLeafSet = false;
- }
- // ------------------------------------------------------------------------------------
- HX_RESULT CHXMacInternalSpec::AllocateLeafName()
- {
- if (mParentAndLeaf.mpLeafName == NULL)
- {
- mParentAndLeaf.mpLeafName = new HFSUniStr255;
- check_nonnull(mParentAndLeaf.mpLeafName);
- }
-
- if (mParentAndLeaf.mpLeafName)
- {
- ZeroInit(mParentAndLeaf.mpLeafName);
- return HXR_OK;
- }
-
- return HXR_FAIL;
- }
- // ------------------------------------------------------------------------------------
- OSErr CHXMacInternalSpec::SetFromFSRef(const FSRef& ref)
- {
- OSErr err;
-
- ClearSpec();
- err = FSRefValid(&ref) ? noErr : paramErr;
- check_noerr(err);
-
- if (err == noErr)
- {
- mItemRef = ref;
- mbRefSet = true;
- }
-
- UpdateDebugOnlyPath();
-
- return err;
- }
- // ------------------------------------------------------------------------------------
- OSErr CHXMacInternalSpec::SetFromPath(const char *pszPath)
- {
- #ifdef _MAC_CFM
- return SetFromHFSPath(pszPath);
- #else
- return SetFromPOSIXPath(pszPath);
- #endif
- }
- // ------------------------------------------------------------------------------------
- HX_RESULT CHXMacInternalSpec::SetFromHFSPath(const char *pszPath)
- {
- OSErr err;
-
- ClearSpec();
-
- if (pszPath && strlen(pszPath))
- {
- FSRef ref;
-
- err = FSRefFromHFSPath(pszPath, &ref);
- if (err == noErr)
- {
- err = SetFromFSRef(ref);
- }
-
- if (err != noErr)
- {
- // we couldn't set it that way; try to make
- // an FSRef for the portion excluding the leaf name
- CHXString strPath, strParent, strLeaf;
-
- (void) FullFromPartialHFSPath(pszPath, strPath);
- SplitPath((const char *) strPath, ':', strParent, strLeaf);
-
- if (strParent.IsEmpty())
- {
- // there's only a leaf; we can't deal with it since we can't
- // make an FSRef for it
- err = paramErr;
- }
- else
- {
- err = FSRefFromHFSPath((const char *) strParent, &ref);
- if (err == noErr)
- {
- err = SetFromParentAndLeaf(ref, (const char *) strLeaf,
- CFStringGetSystemEncoding());
- }
- }
-
-
- }
- }
- else
- {
- err = paramErr;
- }
- UpdateDebugOnlyPath(); // for debugging
- return err;
- }
- // ------------------------------------------------------------------------------------
- OSErr CHXMacInternalSpec::SetFromParentAndLeaf(const FSRef& parentRef, const char * pszName,
- CFStringEncoding encoding)
- {
- HFSUniStr255 leafName;
- OSErr err;
- CHXCFString cfs(pszName, encoding);
- ClearSpec();
-
- if (cfs.IsSet())
- {
- leafName = cfs;
-
- err = SetFromParentAndLeafHFSUni(parentRef, leafName);
- }
- else
- {
- err = paramErr;
- }
-
- return err;
- }
- // ------------------------------------------------------------------------------------
- OSErr CHXMacInternalSpec::SetFromParentAndLeafHFSUni(const FSRef& parentRef, const HFSUniStr255& leafName)
- {
- OSErr err;
-
- ClearSpec();
-
- // try to make a valid ref directly
-
- err = FSMakeFSRefUnicode(&parentRef, leafName.length, leafName.unicode, kTextEncodingUnknown,
- &mItemRef);
- if (err == noErr)
- {
- // we have a good ref
- mbRefSet = true;
- }
- else
- {
- // we can't make a good direct ref, so be sure the parent ref is valid
- // and store the leaf name
-
- if (FSRefValid(&parentRef) && SUCCEEDED(AllocateLeafName()))
- {
- mParentAndLeaf.mItemParentRef = parentRef;
- *mParentAndLeaf.mpLeafName = leafName;
-
- mbParentAndLeafSet = true;
-
- err = noErr;
- }
- else
- {
- check(!"Cannot set from parent and leaf");
- }
- }
-
- UpdateDebugOnlyPath();
- return err;
- }
- // ------------------------------------------------------------------------------------
- OSErr CHXMacInternalSpec::SetFromFSSpec(const FSSpec& spec)
- {
- OSErr err;
-
- ClearSpec();
-
- if (spec.vRefNum != 0)
- {
- err = FSpMakeFSRef(&spec, &mItemRef);
-
- if (err == noErr)
- {
- // the item exists and we have a good ref
- mbRefSet = true;
- }
- else
- {
- // if the item doesn't exist, we need to make a spec for the parent
- // and use the leaf name
- FSRef parentRef;
-
- // make a ref for the parent directory
- err = FSMakeFSRef(spec.vRefNum, spec.parID, "p", &parentRef);
- check_noerr(err);
-
- if (err == noErr)
- {
- CHXString strName;
-
- strName.SetFromStr255(spec.name);
-
- err = SetFromParentAndLeaf(parentRef, (const char *) strName, CFStringGetSystemEncoding());
-
- }
- }
- }
- else
- {
- err = paramErr;
- }
-
- UpdateDebugOnlyPath();
- return err;
- }
- // ------------------------------------------------------------------------------------
- OSErr CHXMacInternalSpec::SetFromAlias(AliasHandle alias)
- {
- OSErr err;
-
- ClearSpec();
- if (alias)
- {
- Boolean changed;
-
- err = FSResolveAliasWithMountFlags(NULL, alias,
- &mItemRef, &changed, kResolveAliasFileNoUI);
- if (err == noErr)
- {
- mbRefSet = true;
- }
- else
- {
- // the item may not exist; try to make an FSSpec
- // from the alias and set from that
- FSSpec fsspec;
-
- err = ResolveAliasWithMountFlags(NULL, alias,
- &fsspec, &changed, kResolveAliasFileNoUI);
- if (err == noErr || err == fnfErr)
- {
- SetFromFSSpec(fsspec);
- }
- }
- }
- UpdateDebugOnlyPath(); // for debugging
-
- return err;
- }
- // ------------------------------------------------------------------------------------
- OSErr CHXMacInternalSpec::SetFromURL(const char *pBuffer)
- {
- Boolean bSuccess;
- CHXCFURL cfurl;
- FSRef ref;
- OSErr err;
- // unset our specifier in case we fail
- ClearSpec();
- require_quiet(pBuffer != NULL && *pBuffer != ' ', CantMakeURL);
- require_quiet(0 == ::strnicmp("file:", pBuffer, 5), CantMakeURL);
- // make a CFURL from which we can get an FSRef
- cfurl = pBuffer;
- require(cfurl.IsSet(), CantMakeURL);
- bSuccess = ::CFURLGetFSRef(cfurl, &ref);
- if (bSuccess)
- {
- err = SetFromFSRef(ref);
- }
- else
- {
- // in case item doesn't exist, try using a pathname
- CHXString strPath;
- if (noErr == PathFromURL(pBuffer, strPath))
- {
- err = SetFromPath((const char *) strPath);
- }
- }
- CantMakeURL:
- return IsSet() ? HXR_OK : HXR_FAILED;
- }
- // ------------------------------------------------------------------------------------
- void CHXMacInternalSpec::SplitPath(const char *pPath, char separator, CHXString& outParent, CHXString& outLeaf)
- {
- CHXString strFull(pPath);
- INT32 offset;
-
- // remove any trailing separator, in case this is a directory
- if (strFull.Right(1) == separator)
- {
- strFull = strFull.Left(strFull.GetLength() - 1);
- }
-
- offset = strFull.ReverseFind(separator);
- if (offset != -1)
- {
- outParent = strFull.Left(offset + 1); // +1 includes the separator
- outLeaf = strFull.Mid(offset + 1);
- }
- else
- {
- outLeaf = strFull;
- }
- }
- // ------------------------------------------------------------------------------------
- CHXMacInternalSpec &CHXMacInternalSpec::operator=(CHXMacInternalSpec& other)
- {
- CopyInternalSpec(other);
- return *this;
- }
- // ------------------------------------------------------------------------------------
- BOOL CHXMacInternalSpec::operator==(const CHXMacInternalSpec &other)
- {
- OSErr err;
- BOOL bSame = FALSE;
-
- if (mbRefSet && other.mbRefSet)
- {
- err = FSCompareFSRefs(&mItemRef, &other.mItemRef);
- if (err == noErr)
- {
- bSame = TRUE;
- }
- }
- else if (mbParentAndLeafSet && other.mbParentAndLeafSet)
- {
- err = FSCompareFSRefs(&mParentAndLeaf.mItemParentRef, &other.mParentAndLeaf.mItemParentRef);
- if (err == noErr)
- {
- if (mParentAndLeaf.mpLeafName->length == other.mParentAndLeaf.mpLeafName->length)
- {
- if (0 == memcmp(&mParentAndLeaf.mpLeafName->unicode, &other.mParentAndLeaf.mpLeafName->unicode,
- mParentAndLeaf.mpLeafName->length * sizeof(UniChar)))
- {
- bSame = TRUE;
- }
- }
- }
- }
-
- return bSame;
- }
- // ------------------------------------------------------------------------------------
- BOOL CHXMacInternalSpec::operator!=(const CHXMacInternalSpec &other)
- {
- return !(*this == other);
- }
- // ------------------------------------------------------------------------------------
- BOOL CHXMacInternalSpec::IsSet() const // object has been set to a file (which may or may not exist)
- {
- return (mbRefSet || mbParentAndLeafSet);
- }
- // ------------------------------------------------------------------------------------
- void CHXMacInternalSpec::Unset()
- {
- ClearSpec();
- }
- // ------------------------------------------------------------------------------------
- CHXString CHXMacInternalSpec::GetPersistentString() const
- {
- FSRef ref;
- OSErr err;
- CHXString strPersistent;
-
- err = GetFSRef(ref);
- if (err == noErr)
- {
- strPersistent = MakePersistentStringForRef(NULL, ref);
- }
- return strPersistent;
-
- }
- // ------------------------------------------------------------------------------------
- CHXString CHXMacInternalSpec::GetRelativePersistentString(const CHXMacInternalSpec& fromFile) const
- {
- CHXString strResult;
- FSRef fromFileRef, targetRef;
- OSErr err;
-
- err = GetFSRef(targetRef);
- require_noerr(err, CantGetTargetRef);
-
- err = fromFile.GetFSRef(fromFileRef);
- require_noerr(err, CantGetFromFileRef);
-
- strResult = MakePersistentStringForRef(&fromFileRef, targetRef);
-
- return strResult;
- CantGetFromFileRef:
- CantGetTargetRef:
- return "";
-
- }
- // ------------------------------------------------------------------------------------
- CHXString CHXMacInternalSpec::MakePersistentStringForRef(const FSRef *pAnchorRef, const FSRef& targetRef)
- {
- HX_RESULT err;
- CHXString str;
- char* pBuff;
- Handle hHexBuffer;
- Size sHexBuffSize;
- AliasHandle hAlias;
-
- // be sure we have a target to specify
-
- err = FSNewAlias(pAnchorRef, &targetRef, &hAlias);
- require_noerr(err, CantMakeAlias);
-
- // fill a temporary buffer with hex of the alias
- hHexBuffer = NewHandle(0);
- err = StuffHexHandle((Handle) hAlias, hHexBuffer);
- require_noerr(err, CantStuff);
-
- // copy our hex buffer to the string
- sHexBuffSize = GetHandleSize(hHexBuffer);
- pBuff = str.GetBuffer(sHexBuffSize + 1); // leave space for terminating null
- BlockMoveData(*hHexBuffer, pBuff, sHexBuffSize);
- pBuff[sHexBuffSize] = 0; // make it a C-string
- str.ReleaseBuffer();
-
- DisposeHandle(hHexBuffer);
- DisposeHandle((Handle) hAlias);
-
- #ifdef _DEBUG
- {
- // during debugging, we'll immediately check that the persistent specifier
- // points to the same place as the actual target
- CHXMacInternalSpec tempAliasTarget;
-
- tempAliasTarget.SetFromPersistentString(str);
-
- if (noErr != FSCompareFSRefs(&targetRef, &tempAliasTarget.mItemRef))
- {
- check(!"Persistent alias doesn't self-resolve");
- }
- }
- #endif
-
- return str;
- // error handling
- CantStuff:
- DisposeHandle(hHexBuffer);
- DisposeHandle((Handle) hAlias);
- CantMakeAlias:
- str = "";
- return str;
- }
- // ------------------------------------------------------------------------------------
- HX_RESULT CHXMacInternalSpec::SetFromPersistentString(const char *pBuffer)
- {
- HX_RESULT err;
- Handle hHexBuffer;
- Size sBufferSize;
- AliasHandle hAlias;
-
- check_nonnull(pBuffer);
-
- sBufferSize = strlen(pBuffer);
-
- // handle empty buffers
- if (sBufferSize == 0)
- {
- ClearSpec();
- return HXR_OK;
- }
-
- // allocate an empty handle to fill
- hAlias = (AliasHandle) NewHandle(0);
-
- // make a temporary buffer with the hex passed in
- err = PtrToHand(pBuffer, &hHexBuffer, sBufferSize);
- require_noerr(err, CantAllocateHexBuffer);
-
- // turn the hex into our binary alias
- err = UnstuffHexHandle(hHexBuffer, (Handle) hAlias);
- DisposeHandle(hHexBuffer);
-
- if (err == noErr)
- {
- SetFromAlias(hAlias);
- }
- else
- {
- // we couldn't interpret it as hex; try it as a full path
- CHXString path(pBuffer);
-
- // resolve 莊old