hxdir_carbon.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:16k
源码类别:

Symbian

开发平台:

C/C++

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