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

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: filespecutils.cpp,v 1.9.2.4 2004/07/09 01:44:23 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 "filespecutils.h"
  50. #include "hxtick.h"
  51. #include "hxrand.h"
  52. #include "dbcs.h"
  53. #define NFS_SUPER_MAGIC 0x6969
  54. #define SMB_SUPER_MAGIC 0x517B
  55. //////////////////////////////////////////////////////////
  56. //
  57. // Utility base class -- CHXFileSpecUtils
  58. //
  59. //////////////////////////////////////////////////////////
  60. //******************************************************************************
  61. #if defined(_FREEBSD) || defined(_OPENBSD) || defined(_NETBSD) || defined (_OSF1) || defined(_MAC_UNIX)
  62. #include <sys/mount.h>
  63. #else
  64. #include <sys/vfs.h>
  65. #endif
  66. #if defined(_SOLARIS) || defined(_LSB_)
  67. #include <sys/statfs.h>
  68. #include <sys/statvfs.h>
  69. #endif
  70. #include <sys/stat.h>
  71. #include <dirent.h>
  72. #include <sys/types.h>
  73. #define ONEGIG (1<<30)
  74. #if defined(_OSF1) || defined(_AIX)
  75. #define STATFS_PATH_TYPE char*
  76. #else
  77. #define STATFS_PATH_TYPE const char*
  78. #endif
  79. #if defined(_SOLARIS) || defined(_LSB_)
  80. #define HXStatfsStruct        struct statvfs
  81. #define HXStatfs(path,sf)     statvfs((STATFS_PATH_TYPE)(path),(sf))
  82. #define HXStatfsBlockSize(sf) ((sf).f_blocks)
  83. #else
  84. #define HXStatfsStruct        struct statfs
  85. #define HXStatfs(path,sf)     statfs((STATFS_PATH_TYPE)(path),(sf))
  86. #define HXStatfsBlockSize(sf) ((sf).f_bsize)
  87. #endif
  88. HX_RESULT CHXFileSpecUtils::GetFreeSpaceOnDisk(const CHXDirSpecifier& volSpec, INT64& freeSpace)
  89. {
  90.     HX_RESULT result = HXR_NOTIMPL;
  91.     const char *szPath = volSpec.GetPathName();
  92.     
  93.     HXStatfsStruct sf;
  94.     if (-1 != HXStatfs(szPath, &sf))
  95.     {
  96. if (geteuid()) 
  97. {
  98.     freeSpace = (UINT64)sf.f_bavail * (UINT64)HXStatfsBlockSize(sf);
  99. }
  100. else 
  101. {
  102.     freeSpace = (UINT64)sf.f_bfree * (UINT64)HXStatfsBlockSize(sf);
  103. }
  104.         result = HXR_OK;
  105.     }
  106.     else
  107.     {
  108. perror("statfs");
  109. freeSpace = (INT64)ONEGIG; 
  110.     }
  111.     return result;
  112. }
  113. //******************************************************************************
  114. HX_RESULT CHXFileSpecUtils::GetTotalSpaceOnDisk(const CHXDirSpecifier& volSpec, 
  115. INT64& totalSpace)
  116.     HX_RESULT result = HXR_NOTIMPL;
  117.     const char *szPath = volSpec.GetPathName();
  118.     
  119.     HXStatfsStruct sf;
  120.     if (-1 != HXStatfs(szPath, &sf))
  121.     {
  122.         totalSpace = (UINT64)sf.f_blocks * (UINT64)HXStatfsBlockSize(sf);
  123.         result = HXR_OK;
  124.     }
  125.     else
  126.     {
  127. perror("statfs");
  128. totalSpace = (INT64)ONEGIG; 
  129.     }
  130.     return result;
  131. }
  132. //******************************************************************************
  133. BOOL CHXFileSpecUtils::IsDiskEjectable(const CHXDirSpecifier& volSpec)
  134. {
  135.     return FALSE;
  136. }
  137. // IsLocal returns TRUE if the file or directory is on a local volume
  138. // (not on a server)
  139. //******************************************************************************
  140. /* Include correct headers to get more fs types below... */
  141. BOOL CHXFileSpecUtils::IsDiskLocal(const CHXDirSpecifier& volSpec)
  142. {
  143.     BOOL result = TRUE;
  144.     const char *szPath = volSpec.GetPathName();
  145.     
  146.     HXStatfsStruct sf;
  147.     if (-1 != HXStatfs(szPath, &sf))
  148.     {
  149. #if !defined(_LSB_)
  150. #if defined(_SOLARIS)
  151.         if (strcmp("nfs", sf.f_basetype) == 0)
  152.         {
  153.             result = FALSE;
  154.         }
  155. #elif defined(_OPENBSD)
  156.         if (strcmp("nfs", sf.f_fstypename) == 0) //XXX untested
  157.         {
  158.             result = FALSE;
  159.         }
  160. #else
  161.         if (sf.f_type == NFS_SUPER_MAGIC ||
  162.             sf.f_type == SMB_SUPER_MAGIC)
  163.         {
  164.             result = FALSE;
  165.         }
  166. #endif
  167. #endif
  168.     }
  169.     else
  170.     {
  171. perror("statfs");
  172.     }
  173.     return result;
  174. }
  175. // file/dir utilities
  176. //******************************************************************** **********
  177. HX_RESULT CHXFileSpecUtils::RemoveDir(const CHXDirSpecifier& dirSpec)
  178. {
  179.     if (-1 != rmdir(dirSpec.GetPathName()))
  180.     {
  181.         return HXR_OK;
  182.     }
  183.     return HXR_FAILED;
  184. };
  185. //******************************************************************** **********
  186. HX_RESULT CHXFileSpecUtils::RemoveFile(const CHXFileSpecifier& fileSpec)
  187. {
  188.     if (-1 != unlink(fileSpec.GetPathName()))
  189.     {
  190.         return HXR_OK;
  191.     }
  192.     return HXR_FAILED;
  193. };
  194. //******************************************************************************
  195. HX_RESULT CHXFileSpecUtils::GetFileSize(const CHXFileSpecifier& fileSpec, INT64& fSize)
  196. {
  197.     HX_RESULT result = HXR_FAIL;
  198.     struct stat st;
  199.     if (-1 != stat(fileSpec.GetPathName(), &st))
  200.     {
  201.         fSize = st.st_size;
  202.         result = HXR_OK;
  203.     }
  204.     return result;
  205. }
  206. //******************************************************************************
  207. HX_RESULT CHXFileSpecUtils::GetDirectorySize(const CHXDirSpecifier& dirSpec, BOOL shouldDescend, INT64& fSize)
  208. {
  209.     DIR *dir = opendir(dirSpec.GetPathName());
  210.     HX_RESULT result = HXR_FAIL;
  211.     while (struct dirent *dirent_ = readdir(dir))
  212.     {
  213.         result = HXR_OK;
  214.         struct stat st;
  215.         if (-1 != stat(dirent_->d_name, &st))
  216.         {
  217.             if (S_ISDIR(st.st_mode))
  218.             {
  219.                 if (shouldDescend)
  220.                 {
  221.                     GetDirectorySize(CHXDirSpecifier(dirent_->d_name), TRUE, fSize);
  222.                 }
  223.             }
  224.             else
  225.             {
  226.                 fSize = st.st_size;
  227.             }
  228.         }
  229.     }
  230.     if (dir)
  231.     {
  232.         closedir(dir);
  233.     }
  234.     return result;
  235. }
  236. //******************************************************************************
  237. CHXFileSpecifier CHXFileSpecUtils::GetCurrentApplication(void)
  238. {
  239.     /* AFAIK there is no way to implement this.  Prove me wrong */
  240.     CHXFileSpecifier spec;
  241.     return spec;
  242. }
  243. //******************************************************************************
  244. CHXDirSpecifier CHXFileSpecUtils::GetCurrentApplicationDir(void)
  245. {
  246.     /* AFAIK there is no way to implement this.  Prove me wrong */
  247.     CHXDirSpecifier  dirSpec;
  248.     return dirSpec;
  249. }
  250. //******************************************************************************
  251. BOOL CHXFileSpecUtils::FileExists(const CHXFileSpecifier& fileSpec)
  252. {
  253.     BOOL result = FALSE;
  254.     struct stat st;
  255.     if (-1 != stat(fileSpec.GetPathName(), &st))
  256.     {
  257.         result = !S_ISDIR(st.st_mode);
  258.     }
  259.     return result;
  260. }
  261. //******************************************************************************
  262. BOOL CHXFileSpecUtils::DirectoryExists(const CHXDirSpecifier& dirSpec)
  263. {
  264.     BOOL result = FALSE;
  265.     struct stat st;
  266.     if (-1 != stat(dirSpec.GetPathName(), &st))
  267.     {
  268.         result = S_ISDIR(st.st_mode);
  269.     }
  270.     return result;
  271. }
  272. //******************************************************************************
  273. HX_RESULT CHXFileSpecUtils::CreateDir(const CHXDirSpecifier& dirSpec)
  274. {
  275. if (-1 != mkdir(dirSpec.GetPathName(), 0700))
  276.             return TRUE;
  277.          
  278. return FALSE;
  279. }
  280. //******************************************************************************
  281. static CHXFileSpecifier GetUniqueFileSpecInternal(const CHXDirSpecifier& locationSpec, 
  282. const char *pszNameFirst, const char *pszTemplate, 
  283. const char *pszWildcard, UINT32 nStartNum);
  284. const UINT32 kNumWrapValue = 9999+1; // limit insertions to 4-digit numbers
  285. CHXFileSpecifier CHXFileSpecUtils::GetUniqueFileSpec(const CHXDirSpecifier& locationSpec, 
  286. const char *pszNameFirst, const char *pszTemplate, 
  287. const char *pszWildcard)
  288. {
  289. return GetUniqueFileSpecInternal(locationSpec, pszNameFirst, pszTemplate, pszWildcard, 0);
  290. }
  291. CHXFileSpecifier CHXFileSpecUtils::GetUniqueTempFileSpec(const CHXDirSpecifier& locationSpec, 
  292. const char *pszTemplate, const char *pszWildcard)
  293. {
  294. CMultiplePrimeRandom  rand(HX_GET_TICKCOUNT());
  295. UINT32 num;
  296. num = rand.GetRandomNumber();
  297. num %= kNumWrapValue;
  298. if (num == 0 || num == 1) num = 2;
  299. return GetUniqueFileSpecInternal(locationSpec, NULL, pszTemplate, pszWildcard, num);
  300. }
  301. static CHXFileSpecifier GetUniqueFileSpecInternal(const CHXDirSpecifier& locationSpec, 
  302.                                                   const char *pszNameFirst, const char *pszTemplate, 
  303.                                                   const char *pszWildcard, UINT32 nStartNum)
  304. {
  305.     CHXFileSpecifier  resultFileSpec;
  306.     require_return(locationSpec.IsSet(), resultFileSpec);
  307.     require_return(pszTemplate != NULL && pszWildcard != NULL, resultFileSpec);
  308.     require_return(pszNameFirst != NULL || nStartNum != 0, resultFileSpec);
  309.     CHXFileSpecifier  testFileSpec;
  310.     CHXDirSpecifier  testDirSpec;
  311.     CHXString strNumber;
  312.     CHXString strName;
  313.     UINT32 nCurrentNum;
  314.     nCurrentNum = nStartNum;
  315.     while (1) 
  316.     {
  317.         // if the number is non-zero, make a string from the template;
  318.         // if the number is zero, user the initial name string
  319.         if (nCurrentNum == 0)
  320.         {
  321.             // replace the wildcard in the template with the number string
  322.             strName = pszNameFirst;
  323.         }
  324.         else
  325.         {
  326.             // replace the wildcard in the template with the number string
  327.             strNumber.Empty();
  328.             strNumber.AppendULONG(nCurrentNum);
  329.             strName = pszTemplate;
  330.             strName.FindAndReplace(pszWildcard, strNumber); // replace first wildcard with number string
  331.         }
  332.         // test if a file or directory exists with that name
  333.         testFileSpec = locationSpec.SpecifyChildFile(strName);
  334.         testDirSpec = locationSpec.SpecifyChildDirectory(strName);
  335.         if (CHXFileSpecUtils::FileExists(testFileSpec)
  336.             || CHXFileSpecUtils::DirectoryExists(testDirSpec))
  337.         {
  338.             // an item already has that name, so increment & wrap the number
  339.             nCurrentNum++;
  340.             nCurrentNum %= kNumWrapValue;
  341.             // don't use 0 again, and skip 1 since "MyFile2.txt" logically follows "MyFile.txt"
  342.             if (nCurrentNum == 0 || nCurrentNum == 1) 
  343.             {
  344.                 nCurrentNum = 2; 
  345.             }
  346.             // a quick sanity check
  347.             if (nCurrentNum == nStartNum)
  348.             {
  349.                 check(!"GetUniqueFileSpecInternal number wrapped");
  350.                 break;
  351.             }
  352.         }
  353.         else
  354.         {
  355.             // the name is unique
  356.             resultFileSpec = testFileSpec;
  357.             break;
  358.         }
  359.     } // while
  360.     return resultFileSpec;
  361. }
  362. //******************************************************************************
  363. CHXDirSpecifier CHXFileSpecUtils::GetSystemTempDirectory()
  364. {
  365.     return CHXDirSpecifier(getenv("TMPDIR") ? getenv("TMPDIR") : "/tmp");
  366. }
  367. BOOL CHXFileSpecUtils::MakeNameLegal(char *pszName)
  368. {
  369.     const char *badChars = "\/:*?"<>| ][()'";
  370.     const char replacementChar = '_';
  371.     const long maxNameLength = 255;
  372.     char *pCurrChar = pszName;
  373.     
  374.     BOOL bChanged;
  375.     
  376.     require_nonnull_return(pszName, FALSE);
  377.     
  378.     bChanged = FALSE;
  379.     
  380.     // replace any illegal characters
  381.     while (*pCurrChar)
  382.     {
  383.         if (strchr(badChars, *pCurrChar))
  384.         {
  385.             *pCurrChar = replacementChar;
  386.             bChanged = TRUE;
  387.         }
  388.         pCurrChar = HXGetNextChar(pCurrChar);
  389.         
  390.         // be sure the name isn't too long
  391.         if (pCurrChar - pszName >= maxNameLength)
  392.         {
  393.             if (pCurrChar - pszName >= maxNameLength + 1)
  394.                 pCurrChar = HXGetPrevChar(pszName, pCurrChar);
  395.             *pCurrChar = 0;
  396.             bChanged = TRUE;
  397.         }
  398.     }
  399.     
  400.     return bChanged;
  401. }
  402. //******************************************************************************
  403. CHXDirSpecifier 
  404. CHXFileSpecUtils::GetAppDataDir(const char* szAppName)
  405. {
  406.     return CHXDirSpecifier("/huh");
  407. }
  408. //******************************************************************************
  409. HX_RESULT CHXFileSpecUtils::ReadBinaryFile(const CHXFileSpecifier& fileSpec, IHXBuffer*& pOutBuffer)
  410. {
  411. HX_ASSERT(!"Not yet implemented on this platform");
  412. return HXR_NOTIMPL;
  413. }
  414. HX_RESULT CHXFileSpecUtils::ReadTextFile(const CHXFileSpecifier& fileSpec, CHXString& outStr)
  415. {
  416. HX_ASSERT(!"Not yet implemented on this platform");
  417. return HXR_NOTIMPL;
  418. }
  419. HX_RESULT CHXFileSpecUtils::WriteBinaryFile(CHXFileSpecifier& fileSpec, IHXBuffer* inBuffer, BOOL bReplaceExistingFile)
  420. {
  421. // the first parameter is not const because on the Mac it can change during the call
  422. HX_ASSERT(!"Not yet implemented on this platform");
  423. return HXR_NOTIMPL;
  424. }
  425. HX_RESULT CHXFileSpecUtils::WriteTextFile(CHXFileSpecifier& fileSpec, const CHXString& inStr, BOOL bReplaceExistingFile)
  426. {
  427. // the first parameter is not const because on the Mac it can change during the call
  428. HX_ASSERT(!"Not yet implemented on this platform");
  429. return HXR_NOTIMPL;
  430. }