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

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