Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

330 lines
11 KiB

  1. //===== Copyright � 2005-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose: Helper methods + classes for file access
  4. //
  5. //===========================================================================//
  6. #include "tier2/fileutils.h"
  7. #include "tier2/tier2.h"
  8. #include "tier1/strtools.h"
  9. #include "filesystem.h"
  10. #include "tier0/icommandline.h"
  11. #include "tier1/utlbuffer.h"
  12. // NOTE: This has to be the last file included!
  13. #include "tier0/memdbgon.h"
  14. //-----------------------------------------------------------------------------
  15. // Builds a directory which is a subdirectory of the current mod
  16. //-----------------------------------------------------------------------------
  17. void GetModSubdirectory( const char *pSubDir, char *pBuf, int nBufLen )
  18. {
  19. // Compute starting directory
  20. Assert( g_pFullFileSystem->GetSearchPath( "MOD", false, NULL, 0 ) < nBufLen );
  21. g_pFullFileSystem->GetSearchPath( "MOD", false, pBuf, nBufLen );
  22. char *pSemi = strchr( pBuf, ';' );
  23. if ( pSemi )
  24. {
  25. *pSemi = 0;
  26. }
  27. Q_StripTrailingSlash( pBuf );
  28. if ( pSubDir )
  29. {
  30. int nLen = Q_strlen( pSubDir );
  31. Q_strncat( pBuf, "\\", nBufLen, 1 );
  32. Q_strncat( pBuf, pSubDir, nBufLen, nLen );
  33. }
  34. Q_FixSlashes( pBuf );
  35. }
  36. //-----------------------------------------------------------------------------
  37. // Builds a directory which is a subdirectory of the current mod's *content*
  38. //-----------------------------------------------------------------------------
  39. void GetModContentSubdirectory( const char *pSubDir, char *pBuf, int nBufLen )
  40. {
  41. char pTemp[ MAX_PATH ];
  42. GetModSubdirectory( pSubDir, pTemp, sizeof(pTemp) );
  43. ComputeModContentFilename( pTemp, pBuf, nBufLen );
  44. }
  45. //-----------------------------------------------------------------------------
  46. // Generates a filename under the 'game' subdirectory given a subdirectory of 'content'
  47. //-----------------------------------------------------------------------------
  48. void ComputeModFilename( const char *pContentFileName, char *pBuf, size_t nBufLen )
  49. {
  50. char pRelativePath[ MAX_PATH ];
  51. if ( !g_pFullFileSystem->FullPathToRelativePathEx( pContentFileName, "CONTENT", pRelativePath, sizeof(pRelativePath) ) )
  52. {
  53. Q_strncpy( pBuf, pContentFileName, nBufLen );
  54. return;
  55. }
  56. char pGameRoot[ MAX_PATH ];
  57. g_pFullFileSystem->GetSearchPath( "GAME", false, pGameRoot, sizeof(pGameRoot) );
  58. char *pSemi = strchr( pGameRoot, ';' );
  59. if ( pSemi )
  60. {
  61. *pSemi = 0;
  62. }
  63. Q_ComposeFileName( pGameRoot, pRelativePath, pBuf, nBufLen );
  64. }
  65. //-----------------------------------------------------------------------------
  66. // Generates a filename under the 'content' subdirectory given a subdirectory of 'game'
  67. //-----------------------------------------------------------------------------
  68. void ComputeModContentFilename( const char *pGameFileName, char *pBuf, size_t nBufLen )
  69. {
  70. char pRelativePath[ MAX_PATH ];
  71. if ( !g_pFullFileSystem->FullPathToRelativePathEx( pGameFileName, "GAME", pRelativePath, sizeof(pRelativePath) ) )
  72. {
  73. Q_strncpy( pBuf, pGameFileName, nBufLen );
  74. return;
  75. }
  76. char pContentRoot[ MAX_PATH ];
  77. g_pFullFileSystem->GetSearchPath( "CONTENT", false, pContentRoot, sizeof(pContentRoot) );
  78. char *pSemi = strchr( pContentRoot, ';' );
  79. if ( pSemi )
  80. {
  81. *pSemi = 0;
  82. }
  83. Q_ComposeFileName( pContentRoot, pRelativePath, pBuf, nBufLen );
  84. }
  85. //-----------------------------------------------------------------------------
  86. // Purpose: Generates an Xbox 360 filename from a PC filename
  87. //-----------------------------------------------------------------------------
  88. char *CreatePlatformFilename( const char *pSourceName, char *pTargetName, int targetLen )
  89. {
  90. Q_StripExtension( pSourceName, pTargetName, targetLen );
  91. int idx = Q_strlen( pTargetName );
  92. // restore extension
  93. Q_snprintf( pTargetName, targetLen, "%s" PLATFORM_EXT "%s", pTargetName, &pSourceName[idx] );
  94. return pTargetName;
  95. }
  96. //-----------------------------------------------------------------------------
  97. // Purpose: Generates a PC filename from a possible 360 name.
  98. // Strips the .360. from filename.360.extension.
  99. // Filenames might have multiple '.', need to be careful and only consider the
  100. // last true extension. Complex filenames do occur:
  101. // d:\foo\.\foo.dat
  102. // d:\zip0.360.zip\foo.360.dat
  103. // Returns source if no change needs to occur, othwerwise generates and
  104. // returns target.
  105. //-----------------------------------------------------------------------------
  106. char *RestoreFilename( const char *pSourceName, char *pTargetName, int targetLen )
  107. {
  108. // find extension
  109. // scan backward for '.', but not past a seperator
  110. int end = V_strlen( pSourceName ) - 1;
  111. while ( end > 0 && pSourceName[end] != '.' && !( pSourceName[end] == '\\' || pSourceName[end] == '/' ) )
  112. {
  113. --end;
  114. }
  115. if ( end >= 4 && pSourceName[end] == '.' && ( !V_strncmp( pSourceName + end - 4 , ".360", 4 ) || !V_strnicmp( pSourceName + end - 4 , ".ps3", 4 ) ) )
  116. {
  117. // cull the .360, leave the trailing extension
  118. end -= 4;
  119. int length = MIN( end + 1, targetLen );
  120. V_strncpy( pTargetName, pSourceName, length );
  121. V_strncat( pTargetName, pSourceName + end + 4, targetLen );
  122. return pTargetName;
  123. }
  124. // source filename is as expected
  125. return (char *)pSourceName;
  126. }
  127. //-----------------------------------------------------------------------------
  128. // Generate an Xbox 360 file if it doesn't exist or is out of date. This function determines
  129. // the source and target path and whether the file needs to be generated. The caller provides
  130. // a callback function to do the actual creation of the 360 file. "pExtraData" is for the caller to
  131. // pass the address of any data that the callback function may need to access. This function
  132. // is ONLY to be called by caller's who expect to have 360 versions of their file.
  133. //-----------------------------------------------------------------------------
  134. int UpdateOrCreate( const char *pSourceName, char *pTargetName, int targetLen, const char *pPathID, CreateCallback_t pfnCreate, bool bForce, void *pExtraData )
  135. {
  136. if ( pTargetName )
  137. {
  138. // caller could supply source as PC or 360 name, we want the PC filename
  139. char szFixedSourceName[MAX_PATH];
  140. pSourceName = RestoreFilename( pSourceName, szFixedSourceName, sizeof( szFixedSourceName ) );
  141. // caller wants us to provide 360 named version of source
  142. CreatePlatformFilename( pSourceName, pTargetName, targetLen );
  143. }
  144. // no conversion are performed by the game at runtime anymore
  145. // SMB access was removed by the XDK for Vista....
  146. return UOC_NOT_CREATED;
  147. }
  148. //-----------------------------------------------------------------------------
  149. // Returns the search path as a list of paths
  150. //-----------------------------------------------------------------------------
  151. void GetSearchPath( CUtlVector< CUtlString > &path, const char *pPathID )
  152. {
  153. int nMaxLen = g_pFullFileSystem->GetSearchPath( pPathID, false, NULL, 0 );
  154. char *pBuf = (char*)stackalloc( nMaxLen );
  155. g_pFullFileSystem->GetSearchPath( pPathID, false, pBuf, nMaxLen );
  156. char *pSemi;
  157. while ( NULL != ( pSemi = strchr( pBuf, ';' ) ) )
  158. {
  159. *pSemi = 0;
  160. path.AddToTail( pBuf );
  161. pBuf = pSemi + 1;
  162. }
  163. path.AddToTail( pBuf );
  164. }
  165. //-----------------------------------------------------------------------------
  166. // Given file name in the current dir generate a full path to it.
  167. //-----------------------------------------------------------------------------
  168. bool GenerateFullPath( const char *pFileName, char const *pPathID, char *pBuf, int nBufLen )
  169. {
  170. if ( V_IsAbsolutePath( pFileName ) )
  171. {
  172. V_strncpy( pBuf, pFileName, nBufLen );
  173. return true;
  174. }
  175. const char *pFullPath = g_pFullFileSystem->RelativePathToFullPath( pFileName, pPathID, pBuf, nBufLen );
  176. if ( pFullPath && Q_IsAbsolutePath( pFullPath ) )
  177. return true;
  178. char pDir[ MAX_PATH ];
  179. if ( !g_pFullFileSystem->GetCurrentDirectory( pDir, sizeof( pDir ) ) )
  180. return false;
  181. V_ComposeFileName( pDir, pFileName, pBuf, nBufLen );
  182. V_RemoveDotSlashes( pBuf );
  183. return true;
  184. }
  185. //-----------------------------------------------------------------------------
  186. // Search start directory, recurse into sub directories collecting all files matching the target name.
  187. //-----------------------------------------------------------------------------
  188. void RecursiveFindFilesMatchingName( CUtlVector< CUtlString > *outFileList, const char* szStartDirectory, const char* szTargetFileName, const char *pathID )
  189. {
  190. char searchString[MAX_PATH];
  191. Q_snprintf( searchString, sizeof( searchString ), "%s/*.*", szStartDirectory );
  192. Q_FixSlashes( searchString );
  193. FileFindHandle_t handle;
  194. const char* curFile = g_pFullFileSystem->FindFirstEx( searchString, pathID, &handle );
  195. while ( curFile )
  196. {
  197. if ( *curFile != '.' && g_pFullFileSystem->FindIsDirectory( handle ) )
  198. {
  199. char newSearchPath[MAX_PATH];
  200. Q_snprintf( newSearchPath, sizeof( newSearchPath ), "%s/%s", szStartDirectory, curFile );
  201. RecursiveFindFilesMatchingName( outFileList, newSearchPath, szTargetFileName, pathID );
  202. }
  203. else if ( V_StringMatchesPattern( curFile, szTargetFileName ) )
  204. {
  205. CUtlString outFile;
  206. outFile.Format( "%s/%s", szStartDirectory, curFile );
  207. Q_FixSlashes( outFile.Get() );
  208. outFileList->AddToTail( outFile );
  209. }
  210. curFile = g_pFullFileSystem->FindNext( handle );
  211. }
  212. g_pFullFileSystem->FindClose( handle );
  213. }
  214. //-----------------------------------------------------------------------------
  215. // Builds a list of all files under a directory with a particular extension
  216. //-----------------------------------------------------------------------------
  217. void AddFilesToList( CUtlVector< CUtlString > &list, const char *pDirectory, const char *pPathID, const char *pExtension )
  218. {
  219. char pSearchString[MAX_PATH];
  220. Q_snprintf( pSearchString, MAX_PATH, "%s\\*", pDirectory );
  221. bool bIsAbsolute = Q_IsAbsolutePath( pDirectory );
  222. // get the list of files
  223. FileFindHandle_t hFind;
  224. const char *pFoundFile = g_pFullFileSystem->FindFirstEx( pSearchString, pPathID, &hFind );
  225. // add all the items
  226. CUtlVector< CUtlString > subDirs;
  227. for ( ; pFoundFile; pFoundFile = g_pFullFileSystem->FindNext( hFind ) )
  228. {
  229. char pChildPath[MAX_PATH];
  230. Q_snprintf( pChildPath, MAX_PATH, "%s\\%s", pDirectory, pFoundFile );
  231. if ( g_pFullFileSystem->FindIsDirectory( hFind ) )
  232. {
  233. if ( Q_strnicmp( pFoundFile, ".", 2 ) && Q_strnicmp( pFoundFile, "..", 3 ) )
  234. {
  235. subDirs.AddToTail( pChildPath );
  236. }
  237. continue;
  238. }
  239. // Check the extension matches
  240. if ( Q_stricmp( Q_GetFileExtension( pFoundFile ), pExtension ) )
  241. continue;
  242. char pFullPathBuf[MAX_PATH];
  243. char *pFullPath = pFullPathBuf;
  244. if ( !bIsAbsolute )
  245. {
  246. g_pFullFileSystem->RelativePathToFullPath( pChildPath, pPathID, pFullPathBuf, sizeof(pFullPathBuf) );
  247. }
  248. else
  249. {
  250. pFullPath = pChildPath;
  251. }
  252. V_strlower( pFullPath );
  253. Q_FixSlashes( pFullPath );
  254. list.AddToTail( pFullPath );
  255. }
  256. g_pFullFileSystem->FindClose( hFind );
  257. int nCount = subDirs.Count();
  258. for ( int i = 0; i < nCount; ++i )
  259. {
  260. AddFilesToList( list, subDirs[i], pPathID, pExtension );
  261. }
  262. }
  263. void CBaseFile::ReadLines( CUtlStringList &lineList, int nMaxLineLength )
  264. {
  265. char *pLine = ( char * ) stackalloc( nMaxLineLength );
  266. while( ReadLine( pLine, nMaxLineLength ) )
  267. {
  268. char *pEOL = strchr( pLine, '\n' ); // kill the \n
  269. if ( pEOL )
  270. *pEOL = 0;
  271. lineList.CopyAndAddToTail( pLine );
  272. }
  273. }
  274. void CBaseFile::ReadFile( CUtlBuffer &fileData )
  275. {
  276. int nFileSize = Size();
  277. fileData.EnsureCapacity( Size() );
  278. int nSize = Read( fileData.Base(), nFileSize );
  279. fileData.SeekPut( CUtlBuffer::SEEK_HEAD, nSize );
  280. }