diff options
Diffstat (limited to 'filesystem/linux_support.cpp')
| -rw-r--r-- | filesystem/linux_support.cpp | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/filesystem/linux_support.cpp b/filesystem/linux_support.cpp new file mode 100644 index 0000000..c68967c --- /dev/null +++ b/filesystem/linux_support.cpp @@ -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; +} |