filespec_carbon.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:49k
源码类别:

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: filespec_carbon.cpp,v 1.5.32.3 2004/07/09 01:44:13 hubbe Exp $
  3.  * 
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  * 
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  * 
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  * 
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  * 
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  * 
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  * 
  46.  * Contributor(s):
  47.  * 
  48.  * ***** END LICENSE BLOCK ***** */
  49. #include "filespec.h"
  50. #include "hxstring.h"
  51. #include "platform/mac/fullpathname.h"
  52. #ifndef _MAC_UNIX
  53. #include "platform/mac/maclibrary.h" // for ResolveIndependentPath
  54. #endif
  55. #include "platform/mac/hx_moreprocesses.h" // for GetCurrentAppSpec
  56. #include "platform/mac/cfwrappers.h"
  57. #include "platform/mac/MoreFilesX.h"
  58. #define kExtensionSeparator '.'
  59. inline CFStringEncoding GetStandardPathEncodingForOS()
  60. {
  61. // Mach-O path elements are always UTF 8; CFM path elements we
  62. // system double-byte encoded
  63. #ifdef _MAC_CFM
  64. return CFStringGetSystemEncoding();
  65. #else
  66. return kCFStringEncodingUTF8;
  67. #endif
  68. }
  69. // ------------------------------------------------------------------------------------
  70. //
  71. // CHXMacInternalSpec
  72. //
  73. // ------------------------------------------------------------------------------------
  74. CHXMacInternalSpec::CHXMacInternalSpec()
  75. {
  76. InitSpec();
  77. ClearSpec();
  78. }
  79. // ------------------------------------------------------------------------------------
  80. CHXMacInternalSpec::CHXMacInternalSpec(const FSRef& ref)
  81. {
  82. InitSpec();
  83. (void) SetFromFSRef(ref);
  84. }
  85. // ------------------------------------------------------------------------------------
  86. CHXMacInternalSpec::CHXMacInternalSpec(const FSSpec& spec)
  87. {
  88. InitSpec();
  89. (void) SetFromFSSpec(spec);
  90. }
  91. // ------------------------------------------------------------------------------------
  92. CHXMacInternalSpec::CHXMacInternalSpec(AliasHandle alias)
  93. {
  94. InitSpec();
  95. (void) SetFromAlias(alias);
  96. }
  97. // ------------------------------------------------------------------------------------
  98. CHXMacInternalSpec::CHXMacInternalSpec(const char* psz)
  99. {
  100. InitSpec();
  101. (void) SetFromPath(psz);
  102. }
  103. // ------------------------------------------------------------------------------------
  104. CHXMacInternalSpec::~CHXMacInternalSpec()
  105. {
  106. ClearSpec();
  107. }
  108. // ------------------------------------------------------------------------------------
  109. void CHXMacInternalSpec::InitSpec()
  110. {
  111. mParentAndLeaf.mpLeafName = NULL;
  112. }
  113. // ------------------------------------------------------------------------------------
  114. void CHXMacInternalSpec::ClearSpec()
  115. {
  116. ZeroInit(&mItemRef);
  117. HX_DELETE(mParentAndLeaf.mpLeafName);
  118. mbRefSet = false;
  119. mbParentAndLeafSet = false;
  120. }
  121. // ------------------------------------------------------------------------------------
  122. HX_RESULT CHXMacInternalSpec::AllocateLeafName()
  123. {
  124. if (mParentAndLeaf.mpLeafName == NULL)
  125. {
  126. mParentAndLeaf.mpLeafName = new HFSUniStr255;
  127. check_nonnull(mParentAndLeaf.mpLeafName);
  128. }
  129. if (mParentAndLeaf.mpLeafName)
  130. {
  131. ZeroInit(mParentAndLeaf.mpLeafName);
  132. return HXR_OK;
  133. }
  134. return HXR_FAIL;
  135. }
  136. // ------------------------------------------------------------------------------------
  137. OSErr CHXMacInternalSpec::SetFromFSRef(const FSRef& ref)
  138. {
  139. OSErr err;
  140. ClearSpec();
  141. err = FSRefValid(&ref) ? noErr : paramErr;
  142. check_noerr(err);
  143. if (err == noErr)
  144. {
  145. mItemRef = ref;
  146. mbRefSet = true;
  147. }
  148. UpdateDebugOnlyPath();
  149. return err;
  150. }
  151. // ------------------------------------------------------------------------------------
  152. OSErr CHXMacInternalSpec::SetFromPath(const char *pszPath)
  153. {
  154. #ifdef _MAC_CFM
  155. return SetFromHFSPath(pszPath);
  156. #else
  157. return SetFromPOSIXPath(pszPath);
  158. #endif
  159. }
  160. // ------------------------------------------------------------------------------------
  161. HX_RESULT CHXMacInternalSpec::SetFromHFSPath(const char *pszPath)
  162. {
  163. OSErr err;
  164. ClearSpec();
  165. if (pszPath && strlen(pszPath)) 
  166. {
  167. FSRef ref;
  168. err = FSRefFromHFSPath(pszPath, &ref);
  169. if (err == noErr)
  170. {
  171. err = SetFromFSRef(ref);
  172. }
  173. if (err != noErr)
  174. {
  175. // we couldn't set it that way; try to make
  176. // an FSRef for the portion excluding the leaf name
  177. CHXString strPath, strParent, strLeaf;
  178. (void) FullFromPartialHFSPath(pszPath, strPath);
  179. SplitPath((const char *) strPath, ':', strParent, strLeaf);
  180. if (strParent.IsEmpty())
  181. {
  182. // there's only a leaf; we can't deal with it since we can't
  183. // make an FSRef for it
  184. err = paramErr;
  185. }
  186. else
  187. {
  188. err = FSRefFromHFSPath((const char *) strParent, &ref);
  189. if (err == noErr)
  190. {
  191. err = SetFromParentAndLeaf(ref, (const char *) strLeaf,
  192. CFStringGetSystemEncoding());
  193. }
  194. }
  195. }
  196. }
  197. else
  198. {
  199. err = paramErr;
  200. }
  201. UpdateDebugOnlyPath(); // for debugging
  202. return err;
  203. }
  204. // ------------------------------------------------------------------------------------
  205. OSErr CHXMacInternalSpec::SetFromParentAndLeaf(const FSRef& parentRef, const char * pszName,
  206.  CFStringEncoding encoding)
  207. {
  208. HFSUniStr255 leafName;
  209. OSErr err;
  210. CHXCFString cfs(pszName, encoding);
  211. ClearSpec();
  212. if (cfs.IsSet())
  213. {
  214. leafName = cfs;
  215. err = SetFromParentAndLeafHFSUni(parentRef, leafName);
  216. }
  217. else
  218. {
  219. err = paramErr;
  220. }
  221. return err;
  222. }
  223. // ------------------------------------------------------------------------------------
  224. OSErr CHXMacInternalSpec::SetFromParentAndLeafHFSUni(const FSRef& parentRef, const HFSUniStr255& leafName)
  225. {
  226. OSErr err;
  227. ClearSpec();
  228. // try to make a valid ref directly
  229. err = FSMakeFSRefUnicode(&parentRef, leafName.length, leafName.unicode, kTextEncodingUnknown,
  230. &mItemRef);
  231. if (err == noErr)
  232. {
  233. // we have a good ref
  234. mbRefSet = true;
  235. }
  236. else
  237. {
  238. // we can't make a good direct ref, so be sure the parent ref is valid
  239. // and store the leaf name
  240. if (FSRefValid(&parentRef) && SUCCEEDED(AllocateLeafName()))
  241. {
  242. mParentAndLeaf.mItemParentRef = parentRef;
  243. *mParentAndLeaf.mpLeafName = leafName;
  244. mbParentAndLeafSet = true;
  245. err = noErr;
  246. }
  247. else
  248. {
  249. check(!"Cannot set from parent and leaf");
  250. }
  251. }
  252. UpdateDebugOnlyPath();
  253. return err;
  254. }
  255. // ------------------------------------------------------------------------------------
  256. OSErr CHXMacInternalSpec::SetFromFSSpec(const FSSpec& spec)
  257. {
  258. OSErr err;
  259. ClearSpec();
  260. if (spec.vRefNum != 0)
  261. {
  262. err = FSpMakeFSRef(&spec, &mItemRef);
  263. if (err == noErr)
  264. {
  265. // the item exists and we have a good ref
  266. mbRefSet = true;
  267. }
  268. else
  269. {
  270. // if the item doesn't exist, we need to make a spec for the parent
  271. // and use the leaf name
  272. FSRef parentRef;
  273. // make a ref for the parent directory
  274. err = FSMakeFSRef(spec.vRefNum, spec.parID, "p", &parentRef);
  275. check_noerr(err);
  276. if (err == noErr)
  277. {
  278. CHXString strName;
  279. strName.SetFromStr255(spec.name);
  280. err = SetFromParentAndLeaf(parentRef, (const char *) strName, CFStringGetSystemEncoding());
  281. }
  282. }
  283. }
  284. else
  285. {
  286. err = paramErr;
  287. }
  288. UpdateDebugOnlyPath();
  289. return err;
  290. }
  291. // ------------------------------------------------------------------------------------
  292. OSErr CHXMacInternalSpec::SetFromAlias(AliasHandle alias)
  293. {
  294. OSErr err;
  295. ClearSpec();
  296. if (alias) 
  297. {
  298. Boolean changed;
  299. err = FSResolveAliasWithMountFlags(NULL, alias,
  300. &mItemRef, &changed, kResolveAliasFileNoUI);
  301. if (err == noErr)
  302. {
  303. mbRefSet = true;
  304. }
  305. else
  306. {
  307. // the item may not exist; try to make an FSSpec
  308. // from the alias and set from that
  309. FSSpec fsspec;
  310. err = ResolveAliasWithMountFlags(NULL, alias,
  311. &fsspec, &changed, kResolveAliasFileNoUI);
  312. if (err == noErr || err == fnfErr)
  313. {
  314. SetFromFSSpec(fsspec);
  315. }
  316. }
  317. UpdateDebugOnlyPath(); // for debugging
  318. return err;
  319. }
  320. // ------------------------------------------------------------------------------------
  321. OSErr CHXMacInternalSpec::SetFromURL(const char *pBuffer)
  322. {
  323. Boolean bSuccess;
  324. CHXCFURL cfurl;
  325. FSRef ref;
  326. OSErr err;
  327. // unset our specifier in case we fail
  328. ClearSpec();
  329. require_quiet(pBuffer != NULL && *pBuffer != '', CantMakeURL);
  330. require_quiet(0 == ::strnicmp("file:", pBuffer, 5), CantMakeURL);
  331. // make a CFURL from which we can get an FSRef
  332. cfurl = pBuffer;
  333. require(cfurl.IsSet(), CantMakeURL);
  334. bSuccess = ::CFURLGetFSRef(cfurl, &ref);
  335. if (bSuccess)
  336. {
  337. err = SetFromFSRef(ref);
  338. }
  339. else
  340. {
  341. // in case item doesn't exist, try using a pathname
  342. CHXString strPath;
  343. if (noErr == PathFromURL(pBuffer, strPath))
  344. {
  345. err = SetFromPath((const char *) strPath);
  346. }
  347. }
  348. CantMakeURL:
  349. return IsSet() ? HXR_OK : HXR_FAILED;
  350. }
  351. // ------------------------------------------------------------------------------------
  352. void CHXMacInternalSpec::SplitPath(const char *pPath, char separator, CHXString& outParent, CHXString& outLeaf)
  353. {
  354. CHXString strFull(pPath);
  355. INT32 offset;
  356. // remove any trailing separator, in case this is a directory
  357. if (strFull.Right(1) == separator)
  358. {
  359. strFull = strFull.Left(strFull.GetLength() - 1);
  360. }
  361. offset = strFull.ReverseFind(separator);
  362. if (offset != -1)
  363. {
  364. outParent = strFull.Left(offset + 1); // +1 includes the separator
  365. outLeaf = strFull.Mid(offset + 1);
  366. }
  367. else
  368. {
  369. outLeaf = strFull;
  370. }
  371. }
  372. // ------------------------------------------------------------------------------------
  373. CHXMacInternalSpec &CHXMacInternalSpec::operator=(CHXMacInternalSpec& other)
  374. {
  375. CopyInternalSpec(other);
  376. return *this;
  377. }
  378. // ------------------------------------------------------------------------------------
  379. BOOL CHXMacInternalSpec::operator==(const CHXMacInternalSpec &other)
  380. {
  381. OSErr err;
  382. BOOL bSame = FALSE;
  383. if (mbRefSet && other.mbRefSet)
  384. {
  385. err = FSCompareFSRefs(&mItemRef, &other.mItemRef);
  386. if (err == noErr)
  387. {
  388. bSame = TRUE;
  389. }
  390. }
  391. else if (mbParentAndLeafSet && other.mbParentAndLeafSet)
  392. {
  393. err = FSCompareFSRefs(&mParentAndLeaf.mItemParentRef, &other.mParentAndLeaf.mItemParentRef);
  394. if (err == noErr)
  395. {
  396. if (mParentAndLeaf.mpLeafName->length == other.mParentAndLeaf.mpLeafName->length)
  397. {
  398. if (0 == memcmp(&mParentAndLeaf.mpLeafName->unicode, &other.mParentAndLeaf.mpLeafName->unicode,
  399. mParentAndLeaf.mpLeafName->length * sizeof(UniChar)))
  400. {
  401. bSame = TRUE;
  402. }
  403. }
  404. }
  405. }
  406. return bSame;
  407. }
  408. // ------------------------------------------------------------------------------------
  409. BOOL CHXMacInternalSpec::operator!=(const CHXMacInternalSpec &other)
  410. {
  411. return !(*this == other);
  412. }
  413. // ------------------------------------------------------------------------------------
  414. BOOL CHXMacInternalSpec::IsSet() const // object has been set to a file (which may or may not exist)
  415. {
  416. return (mbRefSet || mbParentAndLeafSet);
  417. }
  418. // ------------------------------------------------------------------------------------
  419. void CHXMacInternalSpec::Unset()
  420. {
  421. ClearSpec();
  422. }
  423. // ------------------------------------------------------------------------------------
  424. CHXString CHXMacInternalSpec::GetPersistentString() const
  425. {
  426. FSRef ref;
  427. OSErr err;
  428. CHXString strPersistent;
  429. err = GetFSRef(ref);
  430. if (err == noErr)
  431. {
  432. strPersistent = MakePersistentStringForRef(NULL, ref);
  433. }
  434. return strPersistent;
  435. }
  436. // ------------------------------------------------------------------------------------
  437. CHXString CHXMacInternalSpec::GetRelativePersistentString(const CHXMacInternalSpec& fromFile) const
  438. {
  439. CHXString strResult;
  440. FSRef fromFileRef, targetRef;
  441. OSErr err;
  442. err = GetFSRef(targetRef);
  443. require_noerr(err, CantGetTargetRef);
  444. err = fromFile.GetFSRef(fromFileRef);
  445. require_noerr(err, CantGetFromFileRef);
  446. strResult = MakePersistentStringForRef(&fromFileRef, targetRef);
  447. return strResult;
  448. CantGetFromFileRef:
  449. CantGetTargetRef:
  450. return "";
  451. }
  452. // ------------------------------------------------------------------------------------
  453. CHXString CHXMacInternalSpec::MakePersistentStringForRef(const FSRef *pAnchorRef, const FSRef& targetRef)
  454. {
  455. HX_RESULT err;
  456. CHXString str;
  457. char* pBuff;
  458. Handle hHexBuffer;
  459. Size sHexBuffSize;
  460. AliasHandle hAlias;
  461. // be sure we have a target to specify
  462. err = FSNewAlias(pAnchorRef, &targetRef, &hAlias);
  463. require_noerr(err, CantMakeAlias);
  464. // fill a temporary buffer with hex of the alias
  465. hHexBuffer = NewHandle(0);
  466. err = StuffHexHandle((Handle) hAlias, hHexBuffer);
  467. require_noerr(err, CantStuff);
  468. // copy our hex buffer to the string
  469. sHexBuffSize = GetHandleSize(hHexBuffer);
  470. pBuff = str.GetBuffer(sHexBuffSize + 1); // leave space for terminating null
  471. BlockMoveData(*hHexBuffer, pBuff, sHexBuffSize);
  472. pBuff[sHexBuffSize] = 0; // make it a C-string
  473. str.ReleaseBuffer();
  474. DisposeHandle(hHexBuffer);
  475. DisposeHandle((Handle) hAlias);
  476. #ifdef _DEBUG
  477. {
  478. // during debugging, we'll immediately check that the persistent specifier
  479. // points to the same place as the actual target
  480. CHXMacInternalSpec tempAliasTarget;
  481. tempAliasTarget.SetFromPersistentString(str);
  482. if (noErr != FSCompareFSRefs(&targetRef, &tempAliasTarget.mItemRef))
  483. {
  484. check(!"Persistent alias doesn't self-resolve");
  485. }
  486. }
  487. #endif
  488. return str;
  489. // error handling
  490. CantStuff:
  491. DisposeHandle(hHexBuffer);
  492. DisposeHandle((Handle) hAlias);
  493. CantMakeAlias:
  494. str = "";
  495. return str;
  496. }
  497. // ------------------------------------------------------------------------------------
  498. HX_RESULT CHXMacInternalSpec::SetFromPersistentString(const char *pBuffer)
  499. {
  500. HX_RESULT err;
  501. Handle hHexBuffer;
  502. Size sBufferSize;
  503. AliasHandle hAlias;
  504. check_nonnull(pBuffer);
  505. sBufferSize = strlen(pBuffer);
  506. // handle empty buffers
  507. if (sBufferSize == 0)
  508. {
  509. ClearSpec();
  510. return HXR_OK;
  511. }
  512. //  allocate an empty handle to fill
  513. hAlias = (AliasHandle) NewHandle(0);
  514. // make a temporary buffer with the hex passed in
  515. err = PtrToHand(pBuffer, &hHexBuffer, sBufferSize);
  516. require_noerr(err, CantAllocateHexBuffer);
  517. // turn the hex into our binary alias
  518. err = UnstuffHexHandle(hHexBuffer, (Handle) hAlias);
  519. DisposeHandle(hHexBuffer);
  520. if (err == noErr)
  521. {
  522. SetFromAlias(hAlias);
  523. }
  524. else
  525. {
  526. // we couldn't interpret it as hex; try it as a full path
  527. CHXString  path(pBuffer);
  528. // resolve 莊old