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

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