1
This commit is contained in:
266
filesystem/linux_support.cpp
Normal file
266
filesystem/linux_support.cpp
Normal file
@ -0,0 +1,266 @@
|
||||
//========= 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;
|
||||
int 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;
|
||||
}
|
Reference in New Issue
Block a user