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.
349 lines
7.9 KiB
349 lines
7.9 KiB
5 years ago
|
//========= 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
|