#include "gb-include.h" #include "Dir.h" Dir::Dir ( ) { m_dirname = NULL; m_dir = NULL; } 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 ) closedir ( m_dir ); 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; g_errno = errno; if ( ! m_dir ) return log("disk: opendir(%s) : %s", m_dirname,strerror( g_errno ) ); 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; }