summaryrefslogtreecommitdiff
path: root/filesystem/linux_support.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'filesystem/linux_support.cpp')
-rw-r--r--filesystem/linux_support.cpp266
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;
+}