hxdir_carbon.cpp
Upload User: dangjiwu
Upload Date: 2013-07-19
Package Size: 42019k
Code Size: 17k
Category:

Symbian

Development Platform:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: hxdir_carbon.cpp,v 1.4.36.3 2004/07/09 01:44:14 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 "hxdir.h"
  50. #include "hx_morefiles.h"
  51. #include "fullpathname.h"
  52. #include "hxstrutl.h"
  53. #include "MoreFilesX.h"
  54. #include "filespecutils.h"
  55. #include "hxheap.h"
  56. #ifdef _DEBUG
  57. #undef HX_THIS_FILE
  58. static const char HX_THIS_FILE[] = __FILE__;
  59. #endif
  60. #include "macff.h" // for CMacFindFile::pmatch
  61. // Mac paths:   full pathnames:  "Hard Disk:"  "Hard Disk:dev folder:"
  62. //               partial paths:  ":dev folder:"  "myfile"
  63. //
  64. // The ending colon for paths to folders is strongly recommended.
  65. // A word without a colon is a file name; a word followed by a colon
  66. // is a drive name (and the full path of the root directory of the drive.)
  67. static Boolean IsFullMacPath(const CHXString& strPath)
  68. {
  69. // a full Mac pathname has a colon, but not as the first character
  70. // (it's also non-empty)
  71. return (strPath.Find(OS_SEPARATOR_CHAR) > 0
  72. && strPath.GetAt(0) != OS_SEPARATOR_CHAR);
  73. }
  74. static Boolean IsPartialMacPath(const CHXString& strPath)
  75. {
  76. // a partial Mac pathname is either a name without colons
  77. // or else starts with a colon
  78. return (strPath.Find(OS_SEPARATOR_CHAR) == -1
  79. || strPath.GetAt(0) == OS_SEPARATOR_CHAR);
  80. }
  81. CHXDirectory::CHXDirectory()
  82. {
  83. // call SetPath to initialize both the path string and the path FSSpec
  84. // to the "current directory"
  85. SetPath("");
  86. m_FSIterator = 0;
  87. }
  88. CHXDirectory::~CHXDirectory()
  89. {
  90. if (m_FSIterator)
  91. {
  92. (void) FSCloseIterator(m_FSIterator);
  93. m_FSIterator = 0;
  94. }
  95. }
  96. void
  97. CHXDirectory::SetPath(const char* szPath)
  98. {
  99. // parent class saves the path in m_strPath
  100. XHXDirectory::SetPath(szPath);
  101. }
  102. /* folderType is actually a Mac FindFolder type - 
  103.    if != kExtensionFolderType, kChewableItemsFolderType (or kTemporaryFolderType) is used 
  104.    kExtensionFolderType is used when we need a temp folder to load DLLs from.
  105.  */
  106. BOOL
  107. CHXDirectory::SetTempPath(HXXHANDLE folderType, const char* szRelPath)
  108. {
  109. CHXDirSpecifier dirSpec;
  110. CHXString tempPath;
  111. if (folderType != kExtensionFolderType && folderType != kInstallerLogsFolderType)
  112. {
  113. folderType = kChewableItemsFolderType;
  114. }
  115. dirSpec = CHXFileSpecUtils::MacFindFolder(kOnAppropriateDisk, folderType);
  116. check(dirSpec.IsSet());
  117. tempPath = dirSpec.GetPathName();
  118. tempPath += szRelPath;
  119. SetPath(tempPath);
  120. return TRUE;
  121. }
  122. /* Creates directory. */
  123. BOOL 
  124. CHXDirectory::Create()
  125. {
  126. OSErr err = fnfErr;
  127. CHXDirSpecifier dirSpec(m_strPath);
  128. if (dirSpec.IsSet())
  129. {
  130. // create the file if it doesn't already exist
  131. FSRef parentRef;
  132. HFSUniStr255 hfsName;
  133. FSRef newRef;
  134. UInt32 newDirID;
  135. parentRef = (FSRef) dirSpec.GetParentDirectory();
  136. hfsName = dirSpec.GetNameHFSUniStr255();
  137. FSCatalogInfo * kDontSetCatInfo = NULL;
  138. FSSpec *kDontWantSpec = NULL;
  139. err = FSCreateDirectoryUnicode(&parentRef, hfsName.length,
  140. hfsName.unicode, kFSCatInfoNone, kDontSetCatInfo,
  141. &newRef, kDontWantSpec, &newDirID);
  142. }
  143. return (err == noErr);
  144. }
  145. /* Checks if directory exists. */    
  146. BOOL 
  147. CHXDirectory::IsValid()
  148. {
  149. OSErr err = fnfErr;
  150. CHXDirSpecifier dirSpec(m_strPath);
  151. return dirSpec.IsSet() && CHXFileSpecUtils::DirectoryExists(dirSpec);
  152. }
  153. /* Deletes empty directory */
  154. BOOL 
  155. CHXDirectory::DeleteDirectory()
  156. {
  157. OSErr err = fnfErr;
  158. CHXDirSpecifier dirSpec(m_strPath);
  159. return (dirSpec.IsSet() && CHXFileSpecUtils::RemoveDir(dirSpec));
  160. }
  161. /* Destroys directory */
  162. BOOL 
  163. CHXDirectory::Destroy(BOOL bRemoveContents)
  164. {
  165. OSErr err;
  166. if (bRemoveContents)
  167. {
  168. CHXDirSpecifier dirSpec(m_strPath);
  169. if (dirSpec.IsSet())
  170. {
  171. FSRef dirRef = (FSRef) dirSpec;
  172. // use MoreFilesX's routine for this
  173. err = FSDeleteContainer(&dirRef);
  174. return (err == noErr);
  175. }
  176. }
  177. else
  178. {
  179. return DeleteDirectory();
  180. }
  181. return FALSE;
  182. }
  183. /* Starts enumeration process. */
  184. CHXDirectory::FSOBJ 
  185. CHXDirectory::FindFirst(const char* szPattern, char* szPath, UINT16 nSize)
  186. {
  187. OSErr err;
  188. CHXDirSpecifier dirSpec(m_strPath);
  189. require(dirSpec.IsSet() && CHXFileSpecUtils::DirectoryExists(dirSpec), bail);
  190. // if there is already an iterator, dispose it
  191. if (m_FSIterator)
  192. {
  193. err = FSCloseIterator(m_FSIterator);
  194. check_noerr(err);
  195. m_FSIterator = 0;
  196. }
  197. err = FSOpenIterator((FSRef *) dirSpec, kFSIterateFlat, &m_FSIterator);
  198. require_noerr(err, bail);
  199. m_strFindPattern = szPattern;
  200. return FindNext(szPath, nSize);
  201. bail:
  202. return FSOBJ_NOTVALID;
  203. }
  204. CHXDirectory::FSOBJ 
  205. CHXDirectory::FindNext(char* szPath, UINT16 nSize)
  206. {
  207. FSOBJ resultObjType;
  208. OSErr err;
  209. Boolean bIsDir;
  210. CHXString strTemp;
  211. BOOL bNameMatchesPattern;
  212. const ItemCount kWantOneItem = 1;
  213. Boolean * kDontCareIfContainerChanged = NULL;
  214. FSSpec * kDontWantFSSpecs = NULL;
  215. FSRef itemFSRef;
  216. HFSUniStr255 uniName;
  217. ItemCount actualCount;
  218. FSCatalogInfo catInfo;
  219. require_nonnull(m_FSIterator, bail); 
  220. // get an item, looping if it doesn't match the pattern
  221. do
  222. {
  223. err = FSGetCatalogInfoBulk(m_FSIterator, 
  224. kWantOneItem, &actualCount,
  225. kDontCareIfContainerChanged,
  226. kFSCatInfoNodeFlags, &catInfo,
  227. &itemFSRef, kDontWantFSSpecs,
  228. &uniName);
  229. if (err == noErr)
  230. {
  231. strTemp.SetFromHFSUniStr255(uniName, CFStringGetSystemEncoding());
  232. bNameMatchesPattern = CMacFindFile::pmatch((const char *) m_strFindPattern, (const char *) strTemp);
  233. }
  234. } while (err == noErr && !bNameMatchesPattern);
  235. if (err == noErr)
  236. {
  237. // got a file or directory that matches
  238. err = HFSPathFromFSRef(&itemFSRef, strTemp);
  239. require_noerr(err, bail);
  240. if (nSize >= (1 + strTemp.GetLength()))
  241. {
  242.     SafeStrCpy(szPath, (const char *) strTemp, nSize);
  243. }
  244. bIsDir = ((catInfo.nodeFlags & kFSNodeIsDirectoryMask) != 0);
  245. resultObjType = (bIsDir ? FSOBJ_DIRECTORY : FSOBJ_FILE);
  246. }
  247. else
  248. {
  249. // no more found
  250. resultObjType = FSOBJ_NOTVALID;
  251. }
  252. return resultObjType;
  253. bail:
  254. return FSOBJ_NOTVALID;
  255. }
  256. OSErr 
  257. CHXDirectory::GetDirID(long& dirID)
  258. {
  259. CHXDirSpecifier dirSpec(m_strPath);
  260. if (dirSpec.IsSet())
  261. {
  262. dirID = dirSpec.GetDirID();
  263. return (dirID != 0 ? noErr : fnfErr);
  264. }
  265. return fnfErr;
  266. }
  267. BOOL 
  268. CHXDirectory::DeleteFile(const char* szRelPath)
  269. {
  270. CHXString relativeStr(szRelPath);
  271. CHXString  fullFileStr;
  272. OSErr err;
  273. // make a full pathname to the file if we don't have a 
  274. // directory set (since some callers use a null dir
  275. // just to delete files)
  276. if (IsPartialMacPath(relativeStr) && (m_strPath.GetLength() > 0))
  277. {
  278. // we're deleting for a partial path from the current obj directory
  279. fullFileStr = m_strPath;
  280. // add seperator if needed
  281. if ((fullFileStr.GetLength() > 0) && (fullFileStr.Right(1) != ':'))
  282. {
  283.     fullFileStr += ':';
  284. }
  285. fullFileStr += relativeStr;
  286. }
  287. else
  288. {
  289. HX_ASSERT(IsFullMacPath(relativeStr));  // object's dir not set, so this works only for full paths
  290. fullFileStr = relativeStr;
  291. }
  292. // delete the file
  293. err = CHXFileSpecUtils::RemoveFile(fullFileStr);
  294. // we really should return an error
  295. // this gets called frequently if the file doesn't exist - not an error 
  296. // so return error only if file is busy
  297. return (err != fBsyErr);
  298. }
  299. /* Sets itself to current directory. */
  300. BOOL 
  301. CHXDirectory::SetCurrentDir()
  302. {
  303. OSErr err;
  304. long dirID;
  305. short vRefNum;
  306. FSRef currDir;
  307. err = HGetVol(NULL, &vRefNum, &dirID);
  308. if (err == noErr)
  309. {
  310. err = FSMakeFSRef(vRefNum, dirID, NULL, &currDir);
  311. if (err == noErr)
  312. {
  313. CHXDirSpecifier dirSpec(currDir);
  314. SetPath(dirSpec.GetPathName());
  315. }
  316. }
  317. return (err == noErr);
  318. }
  319. /* Makes itself a current directory. */
  320. BOOL 
  321. CHXDirectory::MakeCurrentDir()
  322. {
  323. CHXDirSpecifier dirSpec(m_strPath);
  324. if (dirSpec.IsSet())
  325. {
  326. FSRef newDir, oldDir;
  327. OSErr err;
  328. newDir = (FSRef) dirSpec;
  329. err = FSSetDefault(&newDir, &oldDir);
  330. return (err == noErr);
  331. }
  332. return FALSE;
  333. }
  334. UINT32 
  335. CHXDirectory::Rename(const char* szOldName, const char* szNewName)
  336. {
  337. UINT32 err;
  338. // Unfortunately, the semantics of the parameters for this call aren't clear
  339. //
  340. // presumably, szOldName is a full path, or a partial path in the current directory
  341. // presumably, szNewName is a full path, or just a name
  342. CHXString oldFileStr(szOldName);
  343. CHXString newFileStr(szNewName);
  344. CHXFileSpecifier oldFileSpec;
  345. CHXFileSpecifier newFileSpec;
  346. CHXDirSpecifier destDirSpec;
  347. if (oldFileStr.Find(':') >= 0)
  348. {
  349. // the old name has a colon; convert it to a file spec
  350. oldFileSpec = oldFileStr;
  351. }
  352. if (!oldFileSpec.IsSet())
  353. {
  354. // we couldn't get a valid FSSpec for the old name,
  355. // so assume it's relative to the current directory,
  356. // and make a file spec for it
  357. CHXDirSpecifier currPathSpec(m_strPath);
  358. oldFileSpec = currPathSpec.SpecifyChildFile((const char *) oldFileStr);
  359. }
  360. require_action(oldFileSpec.IsSet(), CantGetSourceForRename, err = fnfErr);
  361. if (newFileStr.Find(':') >= 0)
  362. {
  363. // the new name has a colon; try to convert it to a file spec
  364. newFileSpec = newFileStr;
  365. }
  366. // make a filespec for the destination folder
  367. //
  368. // use the directory of the new file if it was specified, otherwise use
  369. //   the directory of the old file
  370. FSRef destFSRef;
  371. if (newFileSpec.IsSet())
  372. {
  373. CHXDirSpecifier newParentDir = newFileSpec.GetParentDirectory();
  374. err = FSMakeFSRef(newFileSpec.GetVRefNum(), newParentDir.GetDirID(),
  375. NULL, &destFSRef);
  376. }
  377. else
  378. {
  379. CHXDirSpecifier oldParentDir = oldFileSpec.GetParentDirectory();
  380. err = FSMakeFSRef(oldFileSpec.GetVRefNum(), oldParentDir.GetDirID(),
  381. NULL, &destFSRef);
  382. }
  383. check_noerr(err);
  384. destDirSpec = destFSRef;
  385. // make sure we're not trying to move to another volume
  386. require_action(destDirSpec.GetVRefNum() == oldFileSpec.GetVRefNum(), CantChangeVolumes, err = HXR_FAILED);
  387. // they're on the same drive; possibly in different folders
  388. // use the name from the new file spec, if we have one, or else from the parameter
  389. HFSUniStr255 uniName;
  390. if (newFileSpec.IsSet())
  391. {
  392. uniName = newFileSpec.GetNameHFSUniStr255();
  393. }
  394. else
  395. {
  396. newFileStr.MakeHFSUniStr255(uniName, CFStringGetSystemEncoding());
  397. }
  398. FSRef newFSRef;
  399. err = FSMoveRenameObjectUnicode(oldFileSpec, destDirSpec, uniName.length, uniName.unicode,
  400. kTextEncodingUnknown, &newFSRef);
  401. if (err == dupFNErr)
  402. {
  403. err = FSDeleteObject(newFileSpec);
  404. if (err == noErr)
  405. {
  406. err = FSMoveRenameObjectUnicode(oldFileSpec, destDirSpec, uniName.length, uniName.unicode,
  407. kTextEncodingUnknown, &newFSRef);
  408. }
  409. }
  410. CantChangeVolumes:
  411. CantGetSourceForRename:
  412. if (err == noErr)  err = HXR_OK;
  413. else err = HXR_FAILED;
  414. return err;
  415. }
  416. // this moves or copies and renames a file
  417. //
  418. // This is not related to the current directory
  419. BOOL
  420. CHXDirectory::MoveRename(const char* szSrcName, const char* szDestName, BOOL bMove)
  421. {
  422.     OSErr err;
  423.     BOOL bOnSameVolume;
  424.     Str255 pascDestFileName;
  425.     
  426.     CHXFileSpecifier srcFileSpec = szSrcName;
  427.     CHXFileSpecifier destFileSpec = szDestName;
  428.     
  429.     CHXDirSpecifier destFileDir = destFileSpec.GetParentDirectory();
  430.     CHXString strDestFileName = destFileSpec.GetName();
  431.     
  432.     // delete anything at our target location
  433.     CHXFileSpecUtils::RemoveFile(destFileSpec);
  434.     
  435.     bOnSameVolume = (srcFileSpec.GetVRefNum() == destFileSpec.GetVRefNum());
  436.     if (bMove && bOnSameVolume)
  437.     {
  438.      strDestFileName.MakeStr255(pascDestFileName);
  439.      err = FSpMoveRenameCompat((FSSpec *) srcFileSpec, (FSSpec *) destFileDir, 
  440.      pascDestFileName);
  441.     }
  442.     
  443.     if (!bMove || !bOnSameVolume)
  444.     {
  445.      CHXString strBuffer;
  446.      const int kBufferSize = 40000;
  447.     
  448.      char *pBuff = strBuffer.GetBuffer(kBufferSize);
  449.      check_nonnull(pBuff);
  450.     
  451.      strDestFileName.MakeStr255(pascDestFileName);
  452.      err = FSpFileCopy((FSSpec *) srcFileSpec, (FSSpec *) destFileDir, 
  453.      pascDestFileName, pBuff, kBufferSize, FALSE);
  454.     }
  455.     
  456.     // should we delete the source if bMove and we successfully copied it?
  457.     
  458.     return (err == noErr);
  459. }
  460. /* Checks if directory is on CD or removable drive. */    
  461. BOOL 
  462. CHXDirectory::IsRemovable()
  463. {
  464. return CHXFileSpecUtils::IsDiskEjectable(m_strPath);
  465. }
  466. #ifdef _DEBUG
  467. void CHXDirectory::TestHXDir()
  468. {
  469. char *pszTestDir = "Tenspot:123456789a123456789b123456789c123456789d:";
  470. char *pszScanDir = "Tenspot:";
  471. char *pszFakeDir = "Tenspot:123456789a123456789b123456789c123456789dXXX:";
  472. CHXDirectory dirTest;
  473. dirTest.SetPath(pszTestDir);
  474. CHXDirectory dirInvalid;
  475. dirInvalid.SetPath(pszFakeDir);
  476. BOOL bIsValid = dirTest.IsValid();
  477. check(bIsValid);
  478. bIsValid = dirInvalid.IsValid();
  479. check(!bIsValid);
  480. CHXDirectory dirTemp;
  481. dirTemp.SetTempPath(0, "");
  482. bIsValid = dirTemp.IsValid();
  483. check(bIsValid);
  484. dirTemp.SetTempPath(0, "NotInTemp");
  485. bIsValid = dirTemp.IsValid();
  486. check(!bIsValid);
  487. CHXDirectory dirNew;
  488. CHXString strNewPath;
  489. strNewPath = pszTestDir;
  490. strNewPath += "New Folder";
  491. dirNew.SetPath(strNewPath);
  492. bIsValid = dirNew.IsValid();
  493. check(!bIsValid);
  494. dirNew.Create();
  495. bIsValid = dirNew.IsValid();
  496. check(bIsValid);
  497. dirNew.Destroy(TRUE);
  498. bIsValid = dirNew.IsValid();
  499. check(!bIsValid);
  500. CHXDirectory oldCurrentDir, newCurrentDir;
  501. oldCurrentDir.SetCurrentDir();
  502. dirTest.MakeCurrentDir();
  503. newCurrentDir.SetCurrentDir();
  504. check(strcmp(oldCurrentDir.GetPath(), dirTest.GetPath()));
  505. check(!strcmp(newCurrentDir.GetPath(), dirTest.GetPath()));
  506. oldCurrentDir.MakeCurrentDir();
  507. BOOL bIsRemovable = dirTest.IsRemovable();
  508. check(!bIsRemovable);
  509. CHXDirectory scanDir;
  510. scanDir.SetPath(pszScanDir);
  511. FSOBJ obj;
  512. char foundPath[4000]; /* Flawfinder: ignore */
  513. obj = scanDir.FindFirst("*.*", foundPath, 4000);
  514. while (obj != FSOBJ_NOTVALID)
  515. {
  516. obj = scanDir.FindNext(foundPath, 4000);
  517. }
  518. long dirID;
  519. OSErr err;
  520. err = scanDir.GetDirID(dirID);
  521. FSSpec spec = scanDir.GetFSSpec();
  522. /*
  523. CHXString strTemp(pszScanDir);
  524. CHXString strTempFrog(pszScanDir);
  525. scanDir.Rename("test", "test frog");
  526. strTempFrog += "test frog";
  527. strTemp += "test";
  528. scanDir.Rename(strTempFrog, strTemp);
  529. */
  530. scanDir.DeleteFile("123456789a123456789b123456789c123456789d copy 1.png");
  531. }
  532. #endif _DEBUG