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

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: hxdir.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_MoreProcesses.h"
  51. #include "pn_morefiles.h"
  52. #include "fullpathname.h"
  53. #include "hxstrutl.h"
  54. #ifndef _CARBON
  55. #include "morefilesextras.h"
  56. #include "filecopy.h"
  57. #else
  58. #include "MoreFilesX.h"
  59. #include "filespecutils.h"
  60. #endif
  61. #include "hxheap.h"
  62. #ifdef _DEBUG
  63. #undef HX_THIS_FILE
  64. static const char HX_THIS_FILE[] = __FILE__;
  65. #endif
  66. // Mac paths:   full pathnames:  "Hard Disk:"  "Hard Disk:dev folder:"
  67. //               partial paths:  ":dev folder:"  "myfile"
  68. //
  69. // The ending colon for paths to folders is strongly recommended.
  70. // A word without a colon is a file name; a word followed by a colon
  71. // is a drive name (and the full path of the root directory of the drive.)
  72. static Boolean IsFullMacPath(const CHXString& strPath)
  73. {
  74. // a full Mac pathname has a colon, but not as the first character
  75. // (it's also non-empty)
  76. return (strPath.Find(OS_SEPARATOR_CHAR) > 0
  77. && strPath.GetAt(0) != OS_SEPARATOR_CHAR);
  78. }
  79. static Boolean IsPartialMacPath(const CHXString& strPath)
  80. {
  81. // a partial Mac pathname is either a name without colons
  82. // or else starts with a colon
  83. return (strPath.Find(OS_SEPARATOR_CHAR) == -1
  84. || strPath.GetAt(0) == OS_SEPARATOR_CHAR);
  85. }
  86. CHXDirectory::CHXDirectory() : m_pCurrentFileName(NULL), m_pNextFileName(NULL), m_pPattern(NULL),
  87.        m_nDefaultVRefNum(0), m_nDirItems(0)
  88. {
  89. // call SetPath to initialize both the path string and the path FSSpec
  90. // to the "current directory"
  91. SetPath("");
  92. }
  93. CHXDirectory::~CHXDirectory()
  94. {
  95.     if (m_pCurrentFileName)
  96.     {
  97. delete [] m_pCurrentFileName;
  98. m_pCurrentFileName = 0;
  99.     }
  100.     if (m_pNextFileName)
  101.     {
  102. delete [] m_pNextFileName;
  103. m_pNextFileName = 0;
  104.     }
  105.     if (m_pPattern)
  106.     {
  107. delete [] m_pPattern;
  108. m_pPattern = 0;
  109.     }
  110. }
  111. void
  112. CHXDirectory::SetPath(const char* szPath)
  113. {
  114. if (szPath)
  115. {
  116. // coerce path to a CHXString, then to a FSSpec,
  117. // and store in our object
  118. CHXString pathStr(szPath);
  119. // make sure path ends with a ':' 
  120. if ((pathStr.GetLength() > 0) && (pathStr[pathStr.GetLength()-1] != ':'))
  121. pathStr += ':';
  122. // it is ok for path not to be valid yet
  123. m_dirSpec = pathStr;
  124. }
  125. XHXDirectory::SetPath(szPath);
  126. }
  127. /* folderType is actually a Mac FindFolder type - 
  128.    if != kExtensionFolderType, kChewableItemsFolderType (or kTemporaryFolderType) is used 
  129.    kExtensionFolderType is used when we need a temp folder to load DLLs from.
  130.  */
  131. BOOL
  132. CHXDirectory::SetTempPath(HXXHANDLE folderType, const char* szRelPath)
  133. {
  134.     CHXString tempStr;
  135.     
  136. short tempVRefNum;
  137. long tempDirID;
  138. FSSpec tempSpec;
  139. OSErr err;
  140. FSSpec appSpec;
  141. #ifndef USE_APP_DIR
  142. if (kExtensionFolderType == folderType)
  143. {
  144.     err = FindFolder(kOnSystemDisk, kExtensionFolderType, kCreateFolder, &tempVRefNum, &tempDirID);
  145. }
  146. else if (kInstallerLogsFolderType == folderType)
  147. {
  148.     // if >= Sys 8.5, use Installer Logs folder
  149.     long sysVersion;
  150.     char* bytes=(char*)&sysVersion;
  151.     ::Gestalt(gestaltSystemVersion,&sysVersion);
  152.     if (bytes[2]>8 || ((bytes[2]==8) && (bytes[3] >= 0x50)))
  153.      err = FindFolder(kOnSystemDisk, kInstallerLogsFolderType, kCreateFolder, &tempVRefNum, &tempDirID);
  154.     else
  155.     {
  156. GetCurrentAppSpec(&appSpec);
  157. tempVRefNum = appSpec.vRefNum;
  158. tempDirID = appSpec.parID;
  159. err = noErr;
  160.     }
  161. }
  162. else
  163. {
  164.       err = FindFolder(kOnSystemDisk, kChewableItemsFolderType, kCreateFolder, &tempVRefNum, &tempDirID);
  165. }
  166. if (err != noErr)
  167. {
  168. err = FindFolder(kOnSystemDisk, kTemporaryFolderType, kCreateFolder, &tempVRefNum, &tempDirID);
  169. }
  170. #else
  171. // use the app's folder rather than the temporary items folder
  172. if (GetCurrentAppSpec(&appSpec))
  173. {
  174. tempVRefNum = appSpec.vRefNum;
  175. tempDirID = appSpec.parID;
  176. err = noErr;
  177. }
  178. else
  179. {
  180. err = fnfErr;
  181. }
  182. #endif
  183. if (err != noErr)
  184. {
  185. tempVRefNum = -1; // boot disk
  186. tempDirID = fsRtDirID; // root directory
  187. }
  188. // we have the temporary folder's dirID and vRefNum
  189. //
  190. // make a FSSpec for the folder
  191. err = FSMakeFSSpec(tempVRefNum, tempDirID, "p", &tempSpec);
  192. check_noerr(err);
  193. CHXString tempPath;
  194. tempPath = tempSpec; // coerce to a full pathname
  195. tempPath += szRelPath;
  196. SetPath(tempPath);
  197. return true;
  198. }
  199. /* Creates directory. */
  200. BOOL 
  201. CHXDirectory::Create()
  202. {
  203. OSErr err;
  204. long newDirID;
  205. if (EnsureValidPathSpec())
  206. {
  207. err = FSpDirCreate(&m_dirSpec, smSystemScript, &newDirID);
  208. }
  209. else
  210. {
  211. err = fnfErr;
  212. }
  213. return (err == noErr);
  214. }
  215. /* Checks if directory exists. */    
  216. BOOL 
  217. CHXDirectory::IsValid()
  218. {
  219.     FSSpec dirSpec;
  220.     CInfoPBRec cinfo;
  221.     OSErr err;
  222.     Boolean dirFlag;
  223.     
  224.     dirFlag = false;
  225.     err = noErr;
  226.     
  227. if (EnsureValidPathSpec())
  228. {
  229. // make a copy of the filespec so that PBGetCatInfo doesn't munge 
  230. // the name field (paranoid, since that shouldn't happen to a 
  231. // canonical FSSpec like this)
  232. dirSpec = m_dirSpec;
  233. // check that it's a valid folder or volume
  234. cinfo.dirInfo.ioNamePtr = dirSpec.name;
  235. cinfo.dirInfo.ioVRefNum = dirSpec.vRefNum;
  236. cinfo.dirInfo.ioDrDirID = dirSpec.parID;
  237. cinfo.dirInfo.ioFDirIndex = 0; // use name and dirID
  238. err = PBGetCatInfoSync(&cinfo);
  239. if (noErr == err)
  240. {
  241. // check the folder/volume bit
  242.     dirFlag = ((cinfo.dirInfo.ioFlAttrib & ioDirMask) != 0);
  243. }
  244.     }
  245.     
  246.     return ((err == noErr) && dirFlag);
  247. }
  248. /* Deletes empty directory */
  249. BOOL 
  250. CHXDirectory::DeleteDirectory()
  251. {
  252. OSErr err;
  253. if (EnsureValidPathSpec())
  254. {
  255. err = FSpDelete(&m_dirSpec);
  256. }
  257. else
  258. {
  259. err = fnfErr;
  260. }
  261. return (err == noErr);
  262. }
  263. /* EnsureValidPathSpec
  264.    If the path was so speculative when it was set that
  265.    we couldn't make a FSSpec then, make one now.
  266.    
  267.    Note that this *doesn't* guarantee that the object
  268.    exists, just that the m_dirSpec matches the path. 
  269.    
  270.    Returns true if the FSSpec is valid, false if no
  271.    FSSpec can be made for the current path. 
  272.    
  273.    Call this at the start of any routine that expects
  274.    a valid FSSpec to have been already set. */
  275.    
  276. BOOL 
  277. CHXDirectory::EnsureValidPathSpec()
  278. {
  279. // to avoid the cost of conversion again,
  280. // generate the FSSpec only if it's not 
  281. // currently valid
  282. if (m_dirSpec.vRefNum == 0) 
  283. {
  284. m_dirSpec = m_strPath;
  285. }
  286. return (m_dirSpec.vRefNum != 0);
  287. }
  288. /* Destroys directory */
  289. BOOL 
  290. CHXDirectory::Destroy(BOOL bRemoveContents)
  291. {
  292.     OSErr err;
  293. if (EnsureValidPathSpec())
  294. {
  295. if (bRemoveContents)
  296.     {
  297.      // use MoreFilesExtras' routine for this
  298. err = ::DeleteDirectory(m_dirSpec.vRefNum, m_dirSpec.parID, m_dirSpec.name);
  299. return (err == noErr);
  300.     }
  301.     else
  302.     {
  303.      return DeleteDirectory();
  304.     }
  305. }
  306. else
  307. {
  308. // invalid path
  309. return false;
  310. }
  311. }
  312. /* Starts enumeration process. */
  313. CHXDirectory::FSOBJ 
  314. CHXDirectory::FindFirst(const char* szPattern, char* szPath, UINT16 nSize)
  315. {
  316.     FSOBJ RetVal = FSOBJ_NOTVALID;
  317.     int len;
  318.     OSErr err = noErr;
  319.     CHXString tempStr;
  320.     
  321.     if (err == noErr)
  322.     {
  323. m_nIndex = 0;
  324. BOOL bContinue;
  325. FSSpec nextFSpec;
  326. char* patternStart;
  327. if (!m_pPattern)
  328. {
  329.     m_pPattern     = new char[31];
  330.     *m_pPattern = 0;
  331. }
  332. SafeStrCpy(m_pPattern, szPattern, 31);
  333.      tempStr = m_strPath;
  334.      if (m_strPath.GetLength())
  335.      {
  336.          if (tempStr[tempStr.GetLength()-1] != ':')
  337.           tempStr += ":";
  338.      }
  339.      tempStr += szPattern;
  340.      (void) FSSpecFromPathName(tempStr,&nextFSpec);
  341. if (IsFolder(&nextFSpec))
  342. {
  343.     SafeStrCpy(szPath, (const char*)tempStr, nSize);
  344.     ++m_nIndex;
  345.     return FSOBJ_DIRECTORY;
  346. }
  347.      (void) FSSpecFromPathName(m_strPath,&m_fileSpec);
  348. CInfoPBRec pb;
  349. OSErr err=noErr;
  350. memset(&pb,0,sizeof(pb));
  351. pb.hFileInfo.ioVRefNum=m_fileSpec.vRefNum;
  352. pb.hFileInfo.ioFDirIndex=0;
  353. pb.hFileInfo.ioNamePtr=m_fileSpec.name;
  354. pb.hFileInfo.ioDirID=m_fileSpec.parID;
  355. err = PBGetCatInfoSync(&pb);
  356. // if m_fileSpec doesn't point to a directory
  357. // check if szPath + szPattern (nextFSpec) points to a valid file
  358. if (noErr != err)
  359. {
  360.     if (noErr == ::FSMakeFSSpec(nextFSpec.vRefNum, nextFSpec.parID, nextFSpec.name, &nextFSpec))
  361.     {
  362.      tempStr = nextFSpec;
  363.      SafeStrCpy(szPath, (const char*)tempStr, nSize);
  364.      return FSOBJ_FILE;
  365.     }
  366. }
  367. m_nDirItems = pb.dirInfo.ioDrNmFls;
  368.     
  369. while (::FSpIterateDirectory(&m_fileSpec, ++m_nIndex, &nextFSpec))
  370. {
  371.     bContinue = TRUE;
  372.     if (!m_pNextFileName)
  373.     {
  374. m_pNextFileName     = new char[_MAX_PATH];
  375. *m_pNextFileName = 0;
  376.     }
  377.     
  378.     if (!m_pCurrentFileName)
  379.     {
  380. m_pCurrentFileName     = new char[_MAX_PATH];
  381. *m_pCurrentFileName = 0;
  382.     }
  383.     
  384.     // matches pattern(extension)? (eg. DLL)
  385.     len = nextFSpec.name[0];
  386.     if (szPattern)
  387.     {
  388.      if ( 0 == strcmp("*.*", szPattern) ||
  389.           ((szPattern[0] == '*') && (strlen(szPattern) == 1)) )
  390.          bContinue = TRUE;
  391.      else
  392.      {
  393.          INT16 patlen = strlen(szPattern);
  394.          if (szPattern[0] == '*')
  395.          {
  396.           if (0 != strncasecmp((char*)&nextFSpec.name[len-2], &szPattern[strlen(szPattern)-3], 3))
  397.               bContinue = FALSE;
  398.          }
  399.          else if ((patternStart = strchr(m_pPattern, '*')) != 0) //eg. pncrt*.dll
  400.          {
  401.           INT16 patternOffset = patternStart-m_pPattern;
  402.           if (0 != strncasecmp((char*)&nextFSpec.name[1], m_pPattern, patternOffset))
  403.               bContinue = FALSE;
  404.           if (bContinue && (patternOffset < patlen))
  405.           {
  406.               int nCompareLen = (patlen > nextFSpec.name[0]) ? nextFSpec.name[0] - patternOffset
  407.                   : patlen - patternOffset - 1;
  408.               int nSpecPos = nextFSpec.name[0] - nCompareLen + 1;
  409.               if (0 != strncasecmp((char*)&nextFSpec.name[nSpecPos], &m_pPattern[patternOffset+1], nCompareLen))
  410.                bContinue = FALSE;
  411.           }
  412.          }
  413.          else
  414.          {
  415.           if ((patlen != nextFSpec.name[0]) ||
  416.           (0 != strncasecmp((char*)&nextFSpec.name[1], szPattern, patlen)))
  417.               bContinue = FALSE;
  418.          }
  419.      }
  420.     }
  421.     if (bContinue)
  422.     {
  423.      strncpy(m_pNextFileName, (char*)&nextFSpec.name[1], len); /* Flawfinder: ignore */
  424.      m_pNextFileName[len] = 0;
  425.      tempStr = m_strPath;
  426.      if (m_strPath.GetLength())
  427.      {
  428.          if (tempStr[tempStr.GetLength()-1] != ':')
  429.           tempStr += ":";
  430.      }
  431.      tempStr += m_pNextFileName;
  432.      SafeStrCpy(szPath, (const char*)tempStr, nSize);
  433.      if (IsFolder(&nextFSpec))
  434.          return FSOBJ_DIRECTORY;
  435.      else
  436.          return FSOBJ_FILE;
  437.     }
  438. }
  439.         RetVal = FindNext(szPath, nSize);
  440.     }
  441.     return RetVal;
  442. }
  443. /* Continues enumeration process. */
  444. CHXDirectory::FSOBJ 
  445. CHXDirectory::FindNext(char* szPath, UINT16 nSize)
  446. {
  447.     FSOBJ RetVal = FSOBJ_NOTVALID;
  448.     CHXString tempStr;
  449.     FSSpec nextFSpec;
  450.     BOOL bContinue;
  451.     if (m_pNextFileName)
  452.     {
  453. SafeStrCpy(m_pCurrentFileName, m_pNextFileName, nSize);
  454.     }
  455.     else
  456.     {
  457. if (m_pCurrentFileName)
  458. {
  459.     delete [] m_pCurrentFileName;
  460.     m_pCurrentFileName = NULL;
  461. }
  462.     }
  463. /*
  464.     tempStr = szPath;
  465.     ::FSMakeFSSpec(0,0,*((Str255*)tempStr),&nextFSpec);
  466.     if (IsFolder(&nextFSpec, 1))
  467.     {
  468. strcpy(szPath, (const char*)tempStr);
  469. return FSOBJ_DIRECTORY;
  470.     }
  471. */    
  472.     if (m_pNextFileName)
  473.     {
  474. INT16 len = 0;
  475. char* patternStart;
  476. CInfoPBRec pb;
  477. OSErr err=noErr;
  478. memset(&pb,0,sizeof(pb));
  479. pb.hFileInfo.ioVRefNum=m_fileSpec.vRefNum;
  480. pb.hFileInfo.ioFDirIndex=0;
  481. pb.hFileInfo.ioNamePtr=m_fileSpec.name;
  482. pb.hFileInfo.ioDirID=m_fileSpec.parID;
  483. err = PBGetCatInfoSync(&pb);
  484. UINT16 dirItems = pb.dirInfo.ioDrNmFls;
  485. if (dirItems < m_nDirItems) // items have been deleted
  486. {
  487.     m_nIndex -= (m_nDirItems - dirItems);
  488.     m_nDirItems = dirItems;
  489. }
  490. while (::FSpIterateDirectory(&m_fileSpec, ++m_nIndex, &nextFSpec))
  491. {
  492.     bContinue = TRUE;
  493.     if (m_pPattern)
  494.     {
  495.      INT16 patlen = strlen(m_pPattern);
  496.      if ( 0 == strcmp("*.*", m_pPattern) || // *.*
  497.           ((m_pPattern[0] == '*') && (strlen(m_pPattern) == 1)) ) // *
  498.          bContinue = TRUE;
  499.      else
  500.      {
  501.          if (m_pPattern[0] == '*') //eg. *.dll
  502.          {
  503.           if (0 != strncasecmp((char*)&nextFSpec.name[len-2], &m_pPattern[strlen(m_pPattern)-3], 3))
  504.               bContinue = FALSE;
  505.          }
  506.          else if ((patternStart = strchr(m_pPattern, '*')) != 0) //eg. pncrt*.dll
  507.          {
  508.           INT16 patternOffset = patternStart-m_pPattern;
  509.           if (0 != strncasecmp((char*)&nextFSpec.name[1], m_pPattern, patternOffset))
  510.               bContinue = FALSE;
  511.           if (bContinue && (patternOffset < patlen))
  512.           {
  513.               int nCompareLen = (patlen > nextFSpec.name[0]) ? nextFSpec.name[0] - patternOffset
  514.                   : patlen - patternOffset - 1;
  515.               int nSpecPos = nextFSpec.name[0] - nCompareLen + 1;
  516.               if (0 != strncasecmp((char*)&nextFSpec.name[nSpecPos], &m_pPattern[patternOffset+1], nCompareLen))
  517.                bContinue = FALSE;
  518.           }
  519.          }
  520.          else // eg. pncrtd.dll
  521.          {
  522.           if (0 != strncasecmp((char*)&nextFSpec.name[1], m_pPattern, patlen))
  523.               bContinue = FALSE;
  524.          }
  525.      }
  526.     }
  527.     
  528.     
  529.     if (bContinue)
  530.     {
  531. len = nextFSpec.name[0];
  532. strncpy(m_pNextFileName, (char*)&nextFSpec.name[1], len); /* Flawfinder: ignore */
  533. m_pNextFileName[len] = 0;
  534.      tempStr = m_strPath;
  535.      if (m_strPath.GetLength())
  536.      {
  537.          if (tempStr[tempStr.GetLength()-1] != ':')
  538.           tempStr += ":";
  539.      }
  540. tempStr += m_pNextFileName;
  541. SafeStrCpy(szPath, (const char*)tempStr, nSize);
  542.      if (IsFolder(&nextFSpec))
  543.          return FSOBJ_DIRECTORY;
  544.      else
  545.          return FSOBJ_FILE;
  546.     }
  547. }
  548. if (RetVal != FSOBJ_FILE)
  549. {
  550.     delete [] m_pNextFileName;
  551.     m_pNextFileName = 0;
  552. }
  553.     }
  554.     return RetVal;
  555. }
  556. OSErr 
  557. CHXDirectory::GetDirID(long& dirID)
  558. {
  559. FSSpec dirSpec;
  560. CInfoPBRec cinfo;
  561. OSErr err;
  562. Boolean dirFlag;
  563. if (EnsureValidPathSpec())
  564. {
  565. dirSpec = m_dirSpec;
  566. // call GetCatInfo to get it's dirID
  567. cinfo.dirInfo.ioNamePtr = dirSpec.name;
  568. cinfo.dirInfo.ioVRefNum = dirSpec.vRefNum;
  569. cinfo.dirInfo.ioDrDirID = dirSpec.parID;
  570. cinfo.dirInfo.ioFDirIndex = 0; // use name and dirID
  571. err = PBGetCatInfoSync(&cinfo);
  572. // be sure it's really a directory
  573. if (err == noErr)
  574. {
  575. dirFlag = ((cinfo.dirInfo.ioFlAttrib & ioDirMask) != 0);
  576. if (!dirFlag) err = dirNFErr;
  577. }
  578. if (err == noErr)
  579. {
  580. dirID = cinfo.dirInfo.ioDrDirID;
  581. }
  582. }
  583. else
  584. {
  585. // invalid path
  586. err = fnfErr;
  587. }
  588. return err;
  589. }
  590. BOOL 
  591. CHXDirectory::DeleteFile(const char* szRelPath)
  592. {
  593. CHXString relativeStr(szRelPath);
  594. CHXString  fullFileStr;
  595. FSSpec fileSpec;
  596. OSErr err;
  597. // make a full pathname to the file if we don't have a 
  598. // directory set (since some callers use a null dir
  599. // just to delete files)
  600. if (IsPartialMacPath(relativeStr) && (m_strPath.GetLength() > 0))
  601. {
  602. // we're deleting for a partial path from the current obj directory
  603. fullFileStr = m_strPath;
  604. // add seperator if needed
  605. if ((fullFileStr.GetLength() > 0) && (fullFileStr[fullFileStr.GetLength()-1] != ':'))
  606.     fullFileStr += ':';
  607. fullFileStr += relativeStr;
  608. }
  609. else
  610. {
  611. HX_ASSERT(IsFullMacPath(relativeStr));  // object's dir not set, so this works only for full paths
  612. fullFileStr = relativeStr;
  613. }
  614. // delete the file
  615. fileSpec = fullFileStr;
  616. err = FSpDelete(&fileSpec);
  617. // we really should return an error
  618. // this gets called frequently if the file doesn't exist - not an error 
  619. // so return error only if file is busy
  620. return (err != fBsyErr);
  621. }
  622. /* Sets itself to current directory. */
  623. BOOL 
  624. CHXDirectory::SetCurrentDir()
  625. {
  626. // This was never implemented, doesn't work reliably on
  627. // Macs, and since it's a bad idea, it's not worth implementing.
  628.     long  dirID;
  629.     short vRefNum;
  630.     OSErr err = ::HGetVol(NULL, &vRefNum, &dirID);
  631.     err = ::FSMakeFSSpec(vRefNum, dirID, "p", &m_dirSpec);
  632.     if (noErr == err)
  633.     {
  634.      m_strPath = m_dirSpec;
  635.      m_strPath = m_strPath.Left(m_strPath.GetLength()-1);
  636.      return TRUE;
  637.     }
  638.     return FALSE;
  639. }
  640. /* Makes itself a current directory. */
  641. BOOL 
  642. CHXDirectory::MakeCurrentDir()
  643. {
  644. // Relying on a global current default directory is a bad
  645. // idea, so never call this.
  646. //
  647. // Also beware that calling GetVol() won't work properly
  648. // after this, anyway.  See ch. 2 of Inside Mac: Files
  649. // (under Manipulating the Default Volume and Directory)
  650. // for an explanation of why.
  651. //
  652. // SetVol, GetVol, and everything using
  653. // WDRefNums has been obsolete since 1987.
  654. // Use FSSpecs (or full pathnames, if necessary) instead.
  655. OSErr err;
  656. long  dirID;
  657. err = GetDirID(dirID);
  658. if (err == noErr)
  659. {
  660. err = HSetVol(NULL, m_dirSpec.vRefNum, dirID);
  661. }
  662. return (err == noErr);
  663. }
  664. UINT32 
  665. CHXDirectory::Rename(const char* szOldName, const char* szNewName)
  666. {
  667. UINT32 err;
  668. // Unfortunately, the semantics of the parameters for this call aren't clear
  669. //
  670. // presumably, szOldName is a full path, or a partial path in the current directory
  671. // presumably, szNewName is a full path, or just a name
  672. CHXString oldFileStr(szOldName);
  673. CHXString newFileStr(szNewName);
  674. StringPtr newNamePtr;
  675. FSSpec oldFileSpec;
  676. FSSpec newFileSpec;
  677. FSSpec destDirSpec;
  678. (void) EnsureValidPathSpec();
  679. oldFileSpec.vRefNum = 0;
  680. if (oldFileStr.Find(':') >= 0)
  681. {
  682. // the old name has a colon; convert it to a file spec
  683. oldFileSpec = oldFileStr;
  684. }
  685. if (oldFileSpec.vRefNum == 0)
  686. {
  687. // we couldn't get a valid FSSpec for the old name,
  688. // so assume it's relative to the current directory,
  689. // and make a file spec for it
  690. oldFileStr = m_dirSpec;
  691. oldFileStr += ":";
  692. oldFileStr += szOldName;
  693. oldFileSpec = oldFileStr;
  694. }
  695. require_action(oldFileSpec.vRefNum != 0, CantGetSourceForRename, err = fnfErr);
  696. newFileSpec.vRefNum = 0;
  697. if (newFileStr.Find(':') >= 0)
  698. {
  699. // the new name has a colon; try to convert it to a file spec
  700. newFileSpec = newFileStr;
  701. }
  702. // make a filespec for the destination folder
  703. //
  704. // use the directory of the new file if it was specified, otherwise use
  705. //   the directory of the old file
  706. err = FSMakeFSSpec(newFileSpec.vRefNum, 
  707. (newFileSpec.vRefNum == 0 ? oldFileSpec.parID : newFileSpec.parID), 
  708. "p", &destDirSpec);
  709. check_noerr(err);
  710. // make sure we're not trying to move to another volume
  711. require_action(destDirSpec.vRefNum == oldFileSpec.vRefNum, CantChangeVolumes, err = HXR_FAILED);
  712. // they're on the same drive; possibly in different folders
  713. // use the name from the new file spec, if we have one, or else from the parameter
  714. newNamePtr = (newFileSpec.vRefNum ? newFileSpec.name : newFileStr);
  715. // use morefiles' Move/Rename call
  716. err = FSpMoveRenameCompat(&oldFileSpec, &destDirSpec, newNamePtr);
  717. if (err == dupFNErr)
  718. {
  719. err = FSpDelete(&newFileSpec);
  720. if (err == noErr)
  721. {
  722. err = FSpMoveRenameCompat(&oldFileSpec, &destDirSpec, newNamePtr);
  723. }
  724. }
  725. CantChangeVolumes:
  726. CantGetSourceForRename:
  727. if (err == noErr)  err = HXR_OK;
  728. else err = HXR_FAILED;
  729. return err;
  730. }
  731. // this moves or copies and renames a file
  732. BOOL
  733. CHXDirectory::MoveRename(const char* szSrcName, const char* szDestName, BOOL bMove)
  734. {
  735.     OSErr err;
  736.     FSSpec srcSpec, destSpec, deleteSpec;
  737.     CHXString strSourcePath(szSrcName);
  738.     srcSpec = strSourcePath;
  739.     
  740.     CHXString strDestFilePath(szDestName);
  741.     CHXString strDestFile;
  742.     strDestFile = (strrchr(szDestName, OS_SEPARATOR_CHAR)+1);
  743.     CHXString strDestPath(szDestName);
  744.     strDestPath = strDestPath.Left(strDestPath.ReverseFind(OS_SEPARATOR_CHAR));
  745.     destSpec = strDestPath;
  746.     
  747.     if (noErr == FSSpecFromPathName(strDestFilePath, &deleteSpec))
  748.     {
  749. err = ::FSpDelete(&deleteSpec); //delete existing file
  750.     }
  751.     // Note, FSpMoveRenameCompat doesn't move across volumes, 
  752.     // so copy, then delete original (below) if a move has to be done??
  753.     
  754.     if (bMove)
  755.     {
  756.      err = FSpMoveRenameCompat(&srcSpec, &destSpec, *((Str255*)strDestFile));
  757.     }
  758.     if (!bMove || (diffVolErr == err))
  759.     {
  760.      char* buffer = new char[0x40000];
  761. err = FSpFileCopy(&srcSpec,&destSpec, (ConstStr255Param)strDestFile, buffer, 0x40000, FALSE);
  762. delete buffer;
  763.     }
  764.     return (err == noErr);
  765. }
  766. /* Checks if directory is on CD or removable drive. */    
  767. BOOL 
  768. CHXDirectory::IsRemovable()
  769. {
  770. #ifdef _CARBON
  771. if (EnsureValidPathSpec())
  772. {
  773. return CHXFileSpecUtils::IsDiskEjectable(m_dirSpec);
  774. }
  775. return FALSE;
  776. #else
  777. OSErr err;
  778. HParamBlockRec hpb;
  779. DrvQElPtr queueElPtr;
  780.     QHdrPtr     queueHeader;
  781.     Ptr         p;
  782. if (EnsureValidPathSpec())
  783. {
  784. hpb.volumeParam.ioVRefNum = m_dirSpec.vRefNum;
  785. hpb.volumeParam.ioNamePtr = NULL;
  786. hpb.volumeParam.ioVolIndex = 0; // use vRefNum only
  787. err = PBHGetVInfoSync(&hpb);
  788. check_noerr(err);
  789. if (err != noErr) return false;
  790. // check the flag bits in the drive queue (from Technote FL 530)
  791.     queueHeader = GetDrvQHdr();
  792.     queueElPtr = (DrvQElPtr) queueHeader->qHead;
  793.     while (queueElPtr != nil)
  794.     {
  795.         if (queueElPtr->dQDrive == hpb.volumeParam.ioVDrvInfo) 
  796.         {
  797.             p = (Ptr) queueElPtr;
  798.             p -= 3; /* to get to the byte with eject info */
  799.             if ((*p) & 8) return false; // non-ejectable
  800.             else return true; // ejectable
  801.         }
  802.         queueElPtr = (DrvQElPtr) queueElPtr->qLink;
  803.     }
  804. }
  805. return false; // we can't find this drive
  806. #endif
  807. }