summaryrefslogtreecommitdiff
path: root/utils/tfstats/tfstatsosinterface.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/tfstats/tfstatsosinterface.cpp')
-rw-r--r--utils/tfstats/tfstatsosinterface.cpp349
1 files changed, 349 insertions, 0 deletions
diff --git a/utils/tfstats/tfstatsosinterface.cpp b/utils/tfstats/tfstatsosinterface.cpp
new file mode 100644
index 0000000..88680f5
--- /dev/null
+++ b/utils/tfstats/tfstatsosinterface.cpp
@@ -0,0 +1,349 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Contains the Implementations of the OS Interfaces
+//
+// $Workfile: $
+// $Date: $
+//
+//------------------------------------------------------------------------------------------------------
+// $Log: $
+//
+// $NoKeywords: $
+//=============================================================================//
+#include "TFStatsOSInterface.h"
+#include "util.h"
+
+//------------------------------------------------------------------------------------------------------
+// Function: getNextDirectory
+// Purpose: a wrapper for strtok, to return the next directory name out of a path
+// Input: path - the path (will be modified by the call to strtok)
+// Output: char*
+//------------------------------------------------------------------------------------------------------
+char* CTFStatsOSInterface::getNextDirectory(char* path)
+{
+ char seps[3];
+ seps[0]=pathSeperator();
+ seps[1]=0;
+
+ return strtok( path, seps );
+}
+
+
+//------------------------------------------------------------------------------------------------------
+// Function: makeDirectory
+// Purpose: makes a directory hierarchy. because mkdir can't make nested dirs
+// Input: dir - the string of the path to make
+// Output: Returns true on success, false on failure.
+// Note: Notice how easy the linux part of this function is... no drive letters. :)
+//------------------------------------------------------------------------------------------------------
+bool CTFStatsOSInterface::makeHier(string dir)
+{
+ errno=0;
+ //printf("TRYING TO MAKE %s\n",dir.c_str());
+ char startingDir[500];
+ this->getcwd(startingDir,500);
+
+ bool retval=true;
+ const char* nextDir=NULL;
+ char path[500];
+ char* dirs=path;
+ strcpy(path,dir.c_str());
+ //have to parse out directories one at a time. because mkdir just can't handle making nested directories that don't exist (just like md.)
+ //in otherwords, it's lame.
+
+
+#ifdef WIN32
+ //get drive out of path change to it.
+ //if it's only one character, then interpret it as a path, make it and return;
+ //only do this test because the tests below rely on at least 2 characters in the path
+ if (strlen(path)<2)
+ {
+ this->mkdir(path);
+ return true;
+ }
+
+ //what should we do with remote machines?
+ //hmm, let's force users to use mapped drives.
+ if (path[0]=='\\' && path[1]=='\\')
+ {
+ Util::debug_dir_printf("Cannot make a directory on a remote machine.\nMap the share to a drive and specify that drive instead.\n");
+ retval=false;
+ goto end;
+ }
+ //if it's a drive specification
+ if (path[0]=='\\')
+ {
+ if (this->chdir("\\")!=0)
+ Util::debug_dir_printf("Could not change to root on drive %c\n",this->getdrive() + 'a' - 1);
+ dirs=&path[1];
+ }
+ else if (path[1]==':')
+ {
+ //this little formula turns a drive number into the drive letter
+ int drive=path[0]+1 - 'a';
+ if (this->chdrive(drive)!=0)
+ {
+ Util::debug_dir_printf("Drive \"%c:\" does not exist\n",path[0]);
+ retval=false;
+ goto end;
+ }
+ if (path[2]=='\\')
+ {
+ if (this->chdir("\\")!=0)
+ {
+ Util::debug_dir_printf("Could not change to root on drive %c\n",path[0]);
+ retval=false;
+ goto end;
+ }
+ dirs=&path[3];
+ }
+ else
+ {
+ dirs=&path[2];
+ }
+ }
+#else // if linux
+ if (path[0]=='/')
+ {
+ this->chdir("/");
+ dirs=&path[1];
+ char temp[100];
+ this->getcwd(temp,100);
+ Util::debug_dir_printf("switched to root. current dir is %s\n",temp);
+ }
+#endif
+
+ if (dirs[0]==0)
+ {
+ retval=true;
+ goto end;
+ }
+
+ //parse out directories. keep trying to changedir into them one by one
+ // when one fails, make it, and continue.
+ nextDir=getNextDirectory(path);
+ do
+ {
+ if (this->chdir(nextDir)!=0)
+ {
+ if (this->mkdir(nextDir)!=0)
+ {
+ char buf[500];
+ Util::debug_dir_printf("Could not create directory (current directory is %s) (failed on %s)\n",getcwd(buf,500),nextDir);
+ retval=false;
+ goto end;
+ }
+
+ else
+ Util::debug_dir_printf("created %s\n",nextDir);
+
+ //try one more time
+ if (this->chdir(nextDir)!=0)
+ {
+ char buf[500];
+ Util::debug_dir_printf("Could not create directory (current directory is %s) failed on second attempt to change to %s\n",getcwd(buf,500),nextDir);
+ retval=false;
+ goto end;
+ }
+ char temp[200];
+ this->getcwd(temp,200);
+ Util::debug_dir_printf("Now in %s\n",temp);
+ }
+ nextDir=getNextDirectory(NULL);
+ }while(nextDir);
+ retval=true;
+end:
+ this->chdir(startingDir);
+ Util::debug_dir_printf("changingDirectory to %s\n",startingDir);
+ return retval;
+}
+
+
+
+string& CTFStatsOSInterface::addDirSlash(string& tempbuf)
+{
+ if (tempbuf!="")
+ {
+ int buflen=tempbuf.length();
+ if (tempbuf.at(buflen-1) != pathSeperator())
+ tempbuf+= pathSeperator();
+ }
+ return tempbuf;
+}
+string& CTFStatsOSInterface::removeDirSlash(string& tempbuf)
+{
+ int buflen=tempbuf.length();
+ if (buflen > 0 && tempbuf.at(buflen-1) == pathSeperator())
+ tempbuf.erase(tempbuf.length()-1,1);
+ return tempbuf;
+}
+
+#ifdef WIN32
+#include <io.h>
+bool CTFStatsWin32Interface::findfirstfile(char* filemask,string& filename)
+{
+ if (hFindFile!=-1)
+ return false;
+
+ _finddata_t fd;
+ hFindFile=_findfirst(filemask,&fd);
+ filename=fd.name;
+
+ return hFindFile != -1;
+}
+bool CTFStatsWin32Interface::findnextfile(string& filename)
+{
+ filename="";
+ if (hFindFile==-1)
+ return false;
+
+ _finddata_t fd;
+ int result=_findnext(hFindFile,&fd);
+ filename=fd.name;
+ return result!=-1;
+}
+
+bool CTFStatsWin32Interface::findfileclose()
+{
+ if (hFindFile==-1)
+ return false;
+
+ int result = _findclose(hFindFile);
+ return result != -1;
+}
+#endif
+
+#ifndef WIN32
+#include <dirent.h>
+string CTFStatsLinuxInterface::filemask;
+bool CTFStatsLinuxInterface::findfirstfile(char* filemask,string& filename)
+{
+ if (foundFileIterator >= 0)
+ findfileclose();
+
+ foundFileIterator=-1;
+ numFiles=0;
+ foundFiles=NULL;
+
+ struct dirent** namelist;
+ int n;
+
+ CTFStatsLinuxInterface::filemask=filemask;
+ n=scandir(".",&namelist,CTFStatsLinuxInterface::filenameCompare,alphasort);
+
+ if (n<0)
+ return false;
+
+ foundFileIterator=0;
+ numFiles=n;
+ foundFiles=namelist;
+
+ return findnextfile(filename);
+
+}
+bool CTFStatsLinuxInterface::findnextfile(string& filename)
+{
+ if (foundFileIterator == -1 || foundFiles == NULL || numFiles == 0)
+ return false;
+
+ if (foundFileIterator >= numFiles)
+ return false;
+
+ filename=foundFiles[foundFileIterator]->d_name;
+ free(foundFiles[foundFileIterator]);
+ foundFileIterator++;
+ return true;
+}
+
+bool CTFStatsLinuxInterface::findfileclose()
+{
+ free(foundFiles);
+ return true;
+}
+
+void CTFStatsLinuxInterface::filemask2RegExp(char* buf)
+{
+ char* read=filemask.c_str();
+ char* write=buf;
+ while (*read)
+ {
+ if (*read=='?')
+ {
+ *write='.';
+ }
+ else if (*read=='*')
+ {
+ *write='.';
+ write++;
+ *write='*';
+ }
+ else if (*read=='.' || *read=='*' || *read=='?' || *read=='+' || *read=='(' || *read==')' || *read=='{' || *read=='}' || *read=='[' || *read==']' || *read=='^' || *read=='$' )
+ {
+ *write='\\';
+ write++;
+ *write=*read;
+ }
+ else
+ *write=*read;
+ read++;
+ write++;
+ }
+ *write=0;
+}
+
+#include <regex>
+int CTFStatsLinuxInterface::filenameCompare(dirent* file)
+{
+ //scan the filemask, turn it into a regular expression
+ //then fire up the regex engine and scan the filename;
+
+ char buf[5000];
+ filemask2RegExp(buf);
+
+ //printf("trying to match %s against %s\n",buf,file->d_name);
+
+ string sbuf=buf;
+ regex expression(sbuf);
+ cmatch what;
+
+ bool result=query_match((const char*)file->d_name, (const char*)(file->d_name + strlen(file->d_name)), what, expression);
+
+ //if (result)
+// printf("\tsuccessful\n");
+// else
+ //printf("\tno dice\n");
+
+ return result?1:0;
+}
+
+char* CTFStatsLinuxInterface::ultoa(unsigned long theNum, char* buf,int radix)
+{
+{
+ char ascii[]={"0123456789abcdefghijklmnopqrstuvwxyz"};
+ if (radix > 36)
+ {
+ buf[0]=0;
+ return NULL;
+ }
+
+ string holder;
+ while (theNum)
+ {
+ char next;
+ int i=theNum % radix;
+ next=ascii[i];
+ holder+=next;
+ theNum/=radix;
+ }
+
+ int i=0;
+ string::reverse_iterator it;
+ for (it=holder.rbegin();it!=holder.rend();++it)
+ {
+ buf[i++]=*it;
+ }
+ buf[i]=0;
+ return buf;
+}
+}
+#endif \ No newline at end of file