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
266 lines
5.5 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
|
|
#include "linux_support.h" |
|
#include "tier0/threadtools.h" // For ThreadInMainThread() |
|
#include "tier1/strtools.h" |
|
|
|
char selectBuf[PATH_MAX]; |
|
|
|
int FileSelect(const struct dirent *ent) |
|
{ |
|
const char *mask=selectBuf; |
|
const char *name=ent->d_name; |
|
|
|
//printf("Test:%s %s\n",mask,name); |
|
|
|
if(!strcmp(name,".") || !strcmp(name,"..") ) return 0; |
|
|
|
if(!strcmp(selectBuf,"*.*")) return 1; |
|
|
|
while( *mask && *name ) |
|
{ |
|
if(*mask=='*') |
|
{ |
|
mask++; // move to the next char in the mask |
|
if(!*mask) // if this is the end of the mask its a match |
|
{ |
|
return 1; |
|
} |
|
while(*name && toupper(*name)!=toupper(*mask)) |
|
{ // while the two don't meet up again |
|
name++; |
|
} |
|
if(!*name) |
|
{ // end of the name |
|
break; |
|
} |
|
} |
|
else if (*mask!='?') |
|
{ |
|
if( toupper(*mask) != toupper(*name) ) |
|
{ // mismatched! |
|
return 0; |
|
} |
|
else |
|
{ |
|
mask++; |
|
name++; |
|
if( !*mask && !*name) |
|
{ // if its at the end of the buffer |
|
return 1; |
|
} |
|
|
|
} |
|
|
|
} |
|
else /* mask is "?", we don't care*/ |
|
{ |
|
mask++; |
|
name++; |
|
} |
|
} |
|
|
|
return( !*mask && !*name ); // both of the strings are at the end |
|
} |
|
|
|
int FillDataStruct(FIND_DATA *dat) |
|
{ |
|
struct stat fileStat; |
|
|
|
if(dat->curMatch >= dat->numMatches) |
|
return -1; |
|
|
|
char szFullPath[MAX_PATH]; |
|
Q_snprintf( szFullPath, sizeof(szFullPath), "%s/%s", dat->cBaseDir, dat->namelist[dat->curMatch]->d_name ); |
|
|
|
if(!stat(szFullPath,&fileStat)) |
|
{ |
|
dat->dwFileAttributes=fileStat.st_mode; |
|
} |
|
else |
|
{ |
|
dat->dwFileAttributes=0; |
|
} |
|
|
|
// now just put the filename in the output data |
|
Q_snprintf( dat->cFileName, sizeof(dat->cFileName), "%s", dat->namelist[dat->curMatch]->d_name ); |
|
|
|
//printf("%s\n", dat->namelist[dat->curMatch]->d_name); |
|
free(dat->namelist[dat->curMatch]); |
|
|
|
dat->curMatch++; |
|
return 1; |
|
} |
|
|
|
|
|
HANDLE FindFirstFile( const char *fileName, FIND_DATA *dat) |
|
{ |
|
char nameStore[PATH_MAX]; |
|
char *dir=NULL; |
|
intp n,iret=-1; |
|
|
|
Q_strncpy(nameStore,fileName, sizeof( nameStore ) ); |
|
|
|
if(strrchr(nameStore,'/') ) |
|
{ |
|
dir=nameStore; |
|
while(strrchr(dir,'/') ) |
|
{ |
|
struct stat dirChk; |
|
|
|
// zero this with the dir name |
|
dir=strrchr(nameStore,'/'); |
|
if ( dir == nameStore ) // special case for root dir, '/' |
|
{ |
|
dir[1] = '\0'; |
|
} |
|
else |
|
{ |
|
*dir='\0'; |
|
dir=nameStore; |
|
} |
|
|
|
|
|
if (stat(dir,&dirChk) < 0) |
|
{ |
|
continue; |
|
} |
|
|
|
if( S_ISDIR( dirChk.st_mode ) ) |
|
{ |
|
break; |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
// couldn't find a dir seperator... |
|
return (HANDLE)-1; |
|
} |
|
|
|
if( strlen(dir)>0 ) |
|
{ |
|
if ( strlen(dir) == 1 ) // if it was the root dir |
|
Q_strncpy(selectBuf,fileName+1, sizeof( selectBuf ) ); |
|
else |
|
Q_strncpy(selectBuf,fileName+strlen(dir)+1, sizeof( selectBuf ) ); |
|
|
|
Q_strncpy(dat->cBaseDir,dir, sizeof( dat->cBaseDir ) ); |
|
dat->namelist = NULL; |
|
n = scandir(dir, &dat->namelist, FileSelect, alphasort); |
|
if (n < 0) |
|
{ |
|
if ( dat->namelist ) |
|
free(dat->namelist); |
|
// silently return, nothing interesting |
|
} |
|
else |
|
{ |
|
dat->numMatches = n; |
|
dat->curMatch = 0; |
|
iret=FillDataStruct(dat); |
|
if(iret<0) |
|
{ |
|
if ( dat->namelist ) |
|
free(dat->namelist); |
|
dat->namelist = NULL; |
|
} |
|
|
|
} |
|
} |
|
|
|
// printf("Returning: %i \n",iret); |
|
return (HANDLE)iret; |
|
} |
|
|
|
bool FindNextFile(HANDLE handle, FIND_DATA *dat) |
|
{ |
|
if(dat->curMatch >= dat->numMatches) |
|
{ |
|
if ( dat->namelist != NULL ) |
|
free(dat->namelist); |
|
dat->namelist = NULL; |
|
return false; // no matches left |
|
} |
|
|
|
FillDataStruct(dat); |
|
return true; |
|
} |
|
|
|
bool FindClose(HANDLE handle) |
|
{ |
|
return true; |
|
} |
|
|
|
|
|
|
|
// Pass this function a full path and it will look for files in the specified |
|
// directory that match the file name but potentially with different case. |
|
// The directory name itself is not treated specially. |
|
// If multiple names that match are found then lowercase letters take precedence. |
|
bool findFileInDirCaseInsensitive( const char *file, char* output, size_t bufSize) |
|
{ |
|
// Make sure the output buffer is always null-terminated. |
|
output[0] = 0; |
|
|
|
// Find where the file part starts. |
|
const char *dirSep = strrchr(file,'/'); |
|
if( !dirSep ) |
|
{ |
|
dirSep=strrchr(file,'\\'); |
|
if( !dirSep ) |
|
{ |
|
return false; |
|
} |
|
} |
|
|
|
// Allocate space for the directory portion. |
|
size_t dirSize = ( dirSep - file ) + 1; |
|
char *dirName = static_cast<char *>( alloca( dirSize ) ); |
|
|
|
V_strncpy( dirName , file, dirSize ); |
|
|
|
DIR* pDir = opendir( dirName ); |
|
if ( !pDir ) |
|
return false; |
|
|
|
const char* filePart = dirSep + 1; |
|
// The best matching file name will be placed in this array. |
|
char outputFileName[ MAX_PATH ]; |
|
bool foundMatch = false; |
|
|
|
// Scan through the directory. |
|
for ( dirent* pEntry = NULL; ( pEntry = readdir( pDir ) ); /**/ ) |
|
{ |
|
if ( strcasecmp( pEntry->d_name, filePart ) == 0 ) |
|
{ |
|
// If we don't have an existing candidate or if this name is |
|
// a better candidate then copy it in. A 'better' candidate |
|
// means that test beats tesT which beats tEst -- more lowercase |
|
// letters earlier equals victory. |
|
if ( !foundMatch || strcmp( outputFileName, pEntry->d_name ) < 0 ) |
|
{ |
|
foundMatch = true; |
|
V_strcpy_safe( outputFileName, pEntry->d_name ); |
|
} |
|
} |
|
} |
|
|
|
closedir( pDir ); |
|
|
|
// If we didn't find any matching names then lowercase the passed in |
|
// file name and use that. |
|
if ( !foundMatch ) |
|
{ |
|
V_strcpy_safe( outputFileName, filePart ); |
|
V_strlower( outputFileName ); |
|
} |
|
|
|
Q_snprintf( output, bufSize, "%s/%s", dirName, outputFileName ); |
|
return foundMatch; |
|
}
|
|
|