open-source-search-engine/Dir.cpp
2013-12-16 15:39:24 -08:00

204 lines
4.5 KiB
C++

#include "gb-include.h"
#include "Dir.h"
Dir::Dir ( ) {
m_dirname = NULL;
m_dir = NULL;
m_needsClose = false;
}
Dir::~Dir ( ) {
reset();
}
void Dir::reset ( ) {
close();
if ( m_dirname ) free ( m_dirname );
m_dirname = NULL;
}
bool Dir::set ( char *d1 , char *d2 ) {
reset ();
char tmp[1024];
if ( gbstrlen(d1) + gbstrlen(d2) + 1 > 1024 ) {
log("disk: Could not set directory, directory name \"%s/%s\" "
"is too big.",d1,d2);
return false;
}
sprintf ( tmp , "%s/%s", d1 , d2 );
return set ( tmp );
}
bool Dir::set ( char *dirname ) {
reset ();
m_dirname = strdup ( dirname );
if ( m_dirname ) return true;
log("disk: Could not set directory, directory name to \"%s\": %s.",
dirname,mstrerror(g_errno));
return false;
}
bool Dir::close ( ) {
if ( m_dir && m_needsClose ) closedir ( m_dir );
m_needsClose = false;
return true;
}
bool Dir::open ( ) {
close ( );
if ( ! m_dirname ) return false;
retry8:
m_dir = opendir ( m_dirname );
// interrupted system call
if ( ! m_dir && errno == EINTR ) goto retry8;
if ( ! m_dir )
g_errno = errno;
if ( ! m_dir )
return log("disk: opendir(%s) : %s",
m_dirname,strerror( g_errno ) );
m_needsClose = true;
return true;
}
// remove all files in m_dirname
bool Dir::cleanOut ( ) {
char buf[1024];
sprintf ( buf , "rm -r %s/*", m_dirname );
system ( buf );
return true;
}
// create m_dirname
bool Dir::create ( ) {
char buf[1024];
sprintf ( buf , "mkdir %s", m_dirname );
system ( buf );
return true;
}
int Dir::getNumFiles ( char *pattern ) {
int count = 0;
while ( getNextFilename ( pattern ) ) count++;
return count;
}
// rewind to get the first filename
void Dir::rewind ( ) {
rewinddir ( m_dir );
}
char *Dir::getNextFilename ( char *pattern ) {
struct dirent *ent;
long plen = gbstrlen ( pattern );
while ( (ent = readdir ( m_dir )) ) {
char *filename = ent->d_name;
if ( ! pattern ) return filename;
if ( plen>2 && pattern[0] == '*' && pattern[plen-1] == '*' ) {
pattern[plen-1]='\0';
char *s = strstr ( filename , pattern+1 ) ;
pattern[plen-1]='*';
if ( ! s ) continue;
else return filename;
}
if ( pattern[0] == '*' ) {
if ( gbstrlen(filename) < gbstrlen(pattern + 1) ) continue;
char *tail = filename +
gbstrlen ( filename ) -
gbstrlen ( pattern ) + 1;
if ( strcmp ( tail , pattern+1) == 0 ) return filename;
}
if ( pattern[plen-1]=='*' ) {
if ( strncmp ( filename , pattern , plen - 1 ) == 0 )
return filename;
}
}
return NULL;
}
// must call set first
// not recursive!
// return -1 on error
long long Dir::getUsedSpace ( ) {
rewinddir ( m_dir );
long long total = 0;
struct dirent *ent ;
while ( ( ent = readdir ( m_dir ) ) ) {
File tmpfile;
tmpfile.set ( ent->d_name );
long long space = tmpfile.getFileSize ( );
if ( space > 0 ) total += space;
}
return total;
}
// . replace the * in the pattern with a unique id from getNewId()
char *Dir::getFullName ( char *filename ) {
static char buf[1024];
sprintf ( buf , "%s/%s", m_dirname , filename );
return buf;
}
// . replace the * in the pattern with a unique id from getNewId()
char *Dir::getNewFilename ( char *pattern ) {
long long id = getNewId ( pattern );
static char buf[1024];
strcpy ( buf , m_dirname );
int j = gbstrlen ( buf );
for ( int i = 0 ; pattern[i] ; i++ ) {
if ( pattern[i] != '*' ) {buf[j++] = pattern[i]; continue;}
sprintf ( &buf[j] , "%lli" , id );
j = gbstrlen ( buf );
}
buf[j++] = '\0';
return buf;
}
// . a highly specialized function
// . gets a new id represented by files of pattern "pattern"
// . if pattern is "*.data" will return the LUB for *, a long long
long long Dir::getNewId ( char *pattern ) {
rewinddir ( m_dir );
char *filename ;
long long lub = 0;
while ( (filename = getNextFilename ( pattern )) ) {
long long id = getFileId ( filename );
if ( id >= lub ) lub = id + 1;
}
return lub;
}
// . another highly specialized function
// . expects filename to begin with a number
// . return -1 if none exists
long long Dir::getFileId ( char *filename ) {
int end = gbstrlen ( filename ) -1;
while ( end >= 0 && filename [ end ] != '.' ) end--;
if ( end < 0 ) return -1;
end--;
while ( end >= 0 && isdigit ( filename [ end ] ) ) end--;
// now 3 cases:
// 1. end = -1 and filename[0] is NOT a digit
// 2. end = -1 and filename[0] is a digit
// 3. end >= 0 and filename[end+1] is a digit
if ( end < 0 && ! isdigit ( filename[0] ) ) return -1;
if ( end < 0 ) end = 0;
else end++;
long long id = -1;
sscanf ( filename + end , "%lli." , & id );
return id;
}