Team Fortress 2 Source Code as on 22/4/2020
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.

266 lines
5.5 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "linux_support.h"
  8. #include "tier0/threadtools.h" // For ThreadInMainThread()
  9. #include "tier1/strtools.h"
  10. char selectBuf[PATH_MAX];
  11. int FileSelect(const struct dirent *ent)
  12. {
  13. const char *mask=selectBuf;
  14. const char *name=ent->d_name;
  15. //printf("Test:%s %s\n",mask,name);
  16. if(!strcmp(name,".") || !strcmp(name,"..") ) return 0;
  17. if(!strcmp(selectBuf,"*.*")) return 1;
  18. while( *mask && *name )
  19. {
  20. if(*mask=='*')
  21. {
  22. mask++; // move to the next char in the mask
  23. if(!*mask) // if this is the end of the mask its a match
  24. {
  25. return 1;
  26. }
  27. while(*name && toupper(*name)!=toupper(*mask))
  28. { // while the two don't meet up again
  29. name++;
  30. }
  31. if(!*name)
  32. { // end of the name
  33. break;
  34. }
  35. }
  36. else if (*mask!='?')
  37. {
  38. if( toupper(*mask) != toupper(*name) )
  39. { // mismatched!
  40. return 0;
  41. }
  42. else
  43. {
  44. mask++;
  45. name++;
  46. if( !*mask && !*name)
  47. { // if its at the end of the buffer
  48. return 1;
  49. }
  50. }
  51. }
  52. else /* mask is "?", we don't care*/
  53. {
  54. mask++;
  55. name++;
  56. }
  57. }
  58. return( !*mask && !*name ); // both of the strings are at the end
  59. }
  60. int FillDataStruct(FIND_DATA *dat)
  61. {
  62. struct stat fileStat;
  63. if(dat->curMatch >= dat->numMatches)
  64. return -1;
  65. char szFullPath[MAX_PATH];
  66. Q_snprintf( szFullPath, sizeof(szFullPath), "%s/%s", dat->cBaseDir, dat->namelist[dat->curMatch]->d_name );
  67. if(!stat(szFullPath,&fileStat))
  68. {
  69. dat->dwFileAttributes=fileStat.st_mode;
  70. }
  71. else
  72. {
  73. dat->dwFileAttributes=0;
  74. }
  75. // now just put the filename in the output data
  76. Q_snprintf( dat->cFileName, sizeof(dat->cFileName), "%s", dat->namelist[dat->curMatch]->d_name );
  77. //printf("%s\n", dat->namelist[dat->curMatch]->d_name);
  78. free(dat->namelist[dat->curMatch]);
  79. dat->curMatch++;
  80. return 1;
  81. }
  82. HANDLE FindFirstFile( const char *fileName, FIND_DATA *dat)
  83. {
  84. char nameStore[PATH_MAX];
  85. char *dir=NULL;
  86. int n,iret=-1;
  87. Q_strncpy(nameStore,fileName, sizeof( nameStore ) );
  88. if(strrchr(nameStore,'/') )
  89. {
  90. dir=nameStore;
  91. while(strrchr(dir,'/') )
  92. {
  93. struct stat dirChk;
  94. // zero this with the dir name
  95. dir=strrchr(nameStore,'/');
  96. if ( dir == nameStore ) // special case for root dir, '/'
  97. {
  98. dir[1] = '\0';
  99. }
  100. else
  101. {
  102. *dir='\0';
  103. dir=nameStore;
  104. }
  105. if (stat(dir,&dirChk) < 0)
  106. {
  107. continue;
  108. }
  109. if( S_ISDIR( dirChk.st_mode ) )
  110. {
  111. break;
  112. }
  113. }
  114. }
  115. else
  116. {
  117. // couldn't find a dir seperator...
  118. return (HANDLE)-1;
  119. }
  120. if( strlen(dir)>0 )
  121. {
  122. if ( strlen(dir) == 1 ) // if it was the root dir
  123. Q_strncpy(selectBuf,fileName+1, sizeof( selectBuf ) );
  124. else
  125. Q_strncpy(selectBuf,fileName+strlen(dir)+1, sizeof( selectBuf ) );
  126. Q_strncpy(dat->cBaseDir,dir, sizeof( dat->cBaseDir ) );
  127. dat->namelist = NULL;
  128. n = scandir(dir, &dat->namelist, FileSelect, alphasort);
  129. if (n < 0)
  130. {
  131. if ( dat->namelist )
  132. free(dat->namelist);
  133. // silently return, nothing interesting
  134. }
  135. else
  136. {
  137. dat->numMatches = n;
  138. dat->curMatch = 0;
  139. iret=FillDataStruct(dat);
  140. if(iret<0)
  141. {
  142. if ( dat->namelist )
  143. free(dat->namelist);
  144. dat->namelist = NULL;
  145. }
  146. }
  147. }
  148. // printf("Returning: %i \n",iret);
  149. return (HANDLE)iret;
  150. }
  151. bool FindNextFile(HANDLE handle, FIND_DATA *dat)
  152. {
  153. if(dat->curMatch >= dat->numMatches)
  154. {
  155. if ( dat->namelist != NULL )
  156. free(dat->namelist);
  157. dat->namelist = NULL;
  158. return false; // no matches left
  159. }
  160. FillDataStruct(dat);
  161. return true;
  162. }
  163. bool FindClose(HANDLE handle)
  164. {
  165. return true;
  166. }
  167. // Pass this function a full path and it will look for files in the specified
  168. // directory that match the file name but potentially with different case.
  169. // The directory name itself is not treated specially.
  170. // If multiple names that match are found then lowercase letters take precedence.
  171. bool findFileInDirCaseInsensitive( const char *file, char* output, size_t bufSize)
  172. {
  173. // Make sure the output buffer is always null-terminated.
  174. output[0] = 0;
  175. // Find where the file part starts.
  176. const char *dirSep = strrchr(file,'/');
  177. if( !dirSep )
  178. {
  179. dirSep=strrchr(file,'\\');
  180. if( !dirSep )
  181. {
  182. return false;
  183. }
  184. }
  185. // Allocate space for the directory portion.
  186. size_t dirSize = ( dirSep - file ) + 1;
  187. char *dirName = static_cast<char *>( alloca( dirSize ) );
  188. V_strncpy( dirName , file, dirSize );
  189. DIR* pDir = opendir( dirName );
  190. if ( !pDir )
  191. return false;
  192. const char* filePart = dirSep + 1;
  193. // The best matching file name will be placed in this array.
  194. char outputFileName[ MAX_PATH ];
  195. bool foundMatch = false;
  196. // Scan through the directory.
  197. for ( dirent* pEntry = NULL; ( pEntry = readdir( pDir ) ); /**/ )
  198. {
  199. if ( strcasecmp( pEntry->d_name, filePart ) == 0 )
  200. {
  201. // If we don't have an existing candidate or if this name is
  202. // a better candidate then copy it in. A 'better' candidate
  203. // means that test beats tesT which beats tEst -- more lowercase
  204. // letters earlier equals victory.
  205. if ( !foundMatch || strcmp( outputFileName, pEntry->d_name ) < 0 )
  206. {
  207. foundMatch = true;
  208. V_strcpy_safe( outputFileName, pEntry->d_name );
  209. }
  210. }
  211. }
  212. closedir( pDir );
  213. // If we didn't find any matching names then lowercase the passed in
  214. // file name and use that.
  215. if ( !foundMatch )
  216. {
  217. V_strcpy_safe( outputFileName, filePart );
  218. V_strlower( outputFileName );
  219. }
  220. Q_snprintf( output, bufSize, "%s/%s", dirName, outputFileName );
  221. return foundMatch;
  222. }