예제 #1
0
void FileSystem::displayResults() {
    vector<DirInfo*>::iterator it;
    DirInfo* dir;

    cout << "Directory Tree: " << endl;
    displayTree(0,this->root);



    for(it = allDirs.begin(); it != allDirs.end(); ++it) {
        dir = (*it);
        if( dir->getNumSimilar() > 0 ) {
            dir->printInfo();
           
            /*
            // Marks for diplicate listing
            dir->isStarred(true); 
            displayTree(0,this->root);
            // Un-Marks in case of no diplicate listing
            dir->isStarred(false);
            */
        }

    }

}
예제 #2
0
/**
  * FileSystem
  * 
  * if path exists, initialize FileSystem class
  * 
  * @param path root node to analyze
  */
FileSystem::FileSystem(string path) {
    // Display debug messages 
    debug = true;

    // Create a boost path object
    boost::filesystem::path p(path);

    // Counts number of duplicate directories discovered    
    this->dupDirCount = 0;

    try {
        // does path exist
        if( exists(p) ) {
            // is path a directory
            if( is_directory(p) ) {
                try {
                    DirInfo* node = new DirInfo( 
                        p.filename().string(), 
                        p.parent_path().string() 
                    );
                    node->isDir(true);

                    debugPrint("root path = "+node->getPath());

                    // Keeps track of node to deconstruct pointer
                    allNodes.push_back(node);
                    // All directories list (for quick dir operations)
                    allDirs.push_back(node);

                    // Spefiy filesystem root and path
                    root = node;
                    path = node->getPath();
                    //TODO Might remove...
                    depth = 0;

                } catch (bad_alloc&) {
                    throw "EXPN_BAD_NODE";
                }
            } else {
                cout << "Error: Not a valid directory"; 
                throw "EXPN_INVALID_ROOT";
            }
        } else {
            cout << "Error: " << p << " does not exist." << endl;
            throw "EXPN_PATH_DNE";
        }

    } catch ( const boost::filesystem::filesystem_error& ex ) {
        cout << ex.what() << endl;   
    }

}
예제 #3
0
FileInfo * LocalDirReadJob::stat( const QString & url,
				  DirTree	* tree,
				  DirInfo	* parent )
{
    struct stat statInfo;
    logDebug() << "url: \"" << url << "\"" << endl;

    if ( lstat( url.toUtf8(), &statInfo ) == 0 ) // lstat() OK
    {
	if ( S_ISDIR( statInfo.st_mode ) )	// directory?
	{
	    DirInfo * dir = new DirInfo( url, &statInfo, tree, parent );
	    CHECK_NEW( dir );

	    if ( parent )
		parent->insertChild( dir );

	    if ( dir && parent &&
		 ! tree->isTopLevel( dir )
		 && dir->device() != parent->device() )
	    {
		logDebug() << dir << " is a mount point" << endl;
		dir->setMountPoint();
	    }

	    return dir;
	}
	else					// no directory
	{
	    FileInfo * file = new FileInfo( url, &statInfo, tree, parent );
	    CHECK_NEW( file );

	    if ( parent )
		parent->insertChild( file );

	    return file;
	}
    }
    else // lstat() failed
    {
	logError() << "lstat() failed for \"" << url << "\"" << endl;
	return 0;
    }
}
예제 #4
0
void CacheReader::addItem()
{
    if ( fieldsCount() < 4 )
    {
	_ok = false;
	emit error();
	return;
    }

    int n = 0;
    char * type		= field( n++ );
    char * raw_path	= field( n++ );
    char * size_str	= field( n++ );
    char * mtime_str	= field( n++ );
    char * blocks_str	= 0;
    char * links_str	= 0;

    while ( fieldsCount() > n+1 )
    {
	char * keyword	= field( n++ );
	char * val_str	= field( n++ );

	if ( strcasecmp( keyword, "blocks:" ) == 0 ) blocks_str = val_str;
	if ( strcasecmp( keyword, "links:"  ) == 0 ) links_str	= val_str;
    }


    // Type

    mode_t mode = S_IFREG;

    if	    ( strcasecmp( type, "F"	   ) == 0 )	mode = S_IFREG;
    else if ( strcasecmp( type, "D"	   ) == 0 )	mode = S_IFDIR;
    else if ( strcasecmp( type, "L"	   ) == 0 )	mode = S_IFLNK;
    else if ( strcasecmp( type, "BlockDev" ) == 0 )	mode = S_IFBLK;
    else if ( strcasecmp( type, "CharDev"  ) == 0 )	mode = S_IFCHR;
    else if ( strcasecmp( type, "FIFO"	   ) == 0 )	mode = S_IFIFO;
    else if ( strcasecmp( type, "Socket"   ) == 0 )	mode = S_IFSOCK;


    // Path

    if ( *raw_path == '/' )
	_lastDir = 0;



    // Size

    char * end = 0;
    FileSize size = strtoll( size_str, &end, 10 );

    if ( end )
    {
	switch ( *end )
	{
	    case 'K':	size *= KB; break;
	    case 'M':	size *= MB; break;
	    case 'G':	size *= GB; break;
	    case 'T':	size *= TB; break;
	    default: break;
	}
    }


    // MTime

    time_t mtime = strtol( mtime_str, 0, 0 );


    // Blocks

    FileSize blocks = blocks_str ? strtoll( blocks_str, 0, 10 ) : -1;


    // Links

    int links = links_str ? atoi( links_str ) : 1;


    //
    // Create a new item
    //

    char * raw_name = raw_path;

    if ( *raw_path == '/' && _tree->root() )
    {
	// Split raw_path in path + name

	raw_name = strrchr( raw_path, '/' );

	if ( raw_name )
	    *raw_name++ = 0;	// Overwrite the last '/' with 0 byte - split string there
	else			// No '/' found
	    raw_name = raw_path;
    }

    // Using a protocol part to avoid directory names with a colon ":"
    // being cut off because it looks like a URL protocol.
    QByteArray protocol = "foo:";

    QString path = QUrl::fromEncoded( protocol + QByteArray( raw_path ) ).path();
    QString name = QUrl::fromEncoded( protocol + QByteArray( raw_name ) ).path();

    if ( _lastExcludedDir )
    {
	if ( path.startsWith( _lastExcludedDirUrl ) )
	{
	    // logDebug() << "Excluding " << path << "/" << name << endl;
	    return;
	}
    }

    // Find parent in tree

    DirInfo * parent = _lastDir;

    if ( ! parent && _tree->root() )
    {
	if ( ! _tree->root()->hasChildren() )
	    parent = _tree->root();

	// Try the easy way first - the starting point of this cache

	if ( ! parent && _toplevel )
	    parent = dynamic_cast<DirInfo *> ( _toplevel->locate( path ) );


	// Fallback: Search the entire tree

	if ( ! parent )
	    parent = dynamic_cast<DirInfo *> ( _tree->locate( path ) );


	if ( ! parent ) // Still nothing?
	{
	    logError() << _fileName << ":" << _lineNo << ": "
		       << "Could not locate parent " << path << endl;

	    return;	// Ignore this cache line completely
	}
    }

    if ( strcasecmp( type, "D" ) == 0 )
    {
	QString url = ( parent == _tree->root() ) ? path + "/" + name : name;
	// logDebug() << "Creating DirInfo  for " << url << " with parent " << parent << endl;
	DirInfo * dir = new DirInfo( _tree, parent, url,
				     mode, size, mtime );
	dir->setReadState( DirReading );
	_lastDir = dir;

	if ( parent )
	    parent->insertChild( dir );

	if ( ! _tree->root() )
	{
	    _tree->setRoot( dir );
	    _toplevel = dir;
	}

	if ( ! _toplevel )
	    _toplevel = dir;

	_tree->childAddedNotify( dir );

	if ( dir != _toplevel )
	{
	    if ( ExcludeRules::instance()->match( dir->url(), dir->name() ) )
	    {
		logDebug() << "Excluding " << name << endl;
		dir->setExcluded();
		dir->setReadState( DirOnRequestOnly );
		_tree->sendFinalizeLocal( dir );
		dir->finalizeLocal();
		_tree->sendReadJobFinished( dir );

		_lastExcludedDir    = dir;
		_lastExcludedDirUrl = _lastExcludedDir->url();
		_lastDir	    = 0;
	    }
	}
    }
    else
    {
	if ( parent )
	{
	    // logDebug() << "Creating FileInfo for " << parent->debugUrl() << "/" << name << endl;

	    FileInfo * item = new FileInfo( _tree, parent, name,
					    mode, size, mtime,
					    blocks, links );
	    parent->insertChild( item );
	    _tree->childAddedNotify( item );
	}
	else
	{
	    logError() << _fileName << ":" << _lineNo << ": "
		       << "No parent for item " << name << endl;
	}
    }
}
예제 #5
0
void LocalDirReadJob::startReading()
{
    struct dirent *	entry;
    struct stat		statInfo;
    QString		dirName		 = _dir->url();
    QString		defaultCacheName = DEFAULT_CACHE_NAME;

    // logDebug() << _dir << endl;

    if ( ( _diskDir = opendir( dirName.toUtf8() ) ) )
    {
	_dir->setReadState( DirReading );

	while ( ( entry = readdir( _diskDir ) ) )
	{
	    QString entryName = entry->d_name;

	    if ( entryName != "."  &&
		 entryName != ".."   )
	    {
		QString fullName = dirName + "/" + entryName;

		if ( lstat( fullName.toUtf8(), &statInfo ) == 0 )	      // lstat() OK
		{
		    if ( S_ISDIR( statInfo.st_mode ) )	// directory child?
		    {
			DirInfo *subDir = new DirInfo( entryName, &statInfo, _tree, _dir );
			CHECK_NEW( subDir );

			_dir->insertChild( subDir );
			childAdded( subDir );

			if ( ExcludeRules::instance()->match( entryName ) )
			{
			    subDir->setExcluded();
			    subDir->setReadState( DirOnRequestOnly );
			    finishReading( subDir );
			}
			else // No exclude rule matched
			{
			    if ( _dir->device() == subDir->device() )	// normal case
			    {
				LocalDirReadJob * job = new LocalDirReadJob( _tree, subDir );
				CHECK_NEW( job );
				_tree->addJob( job );
			    }
			    else	// The subdirectory we just found is a mount point.
			    {
				logDebug() << "Found mount point " << subDir << endl;
				subDir->setMountPoint();

				if ( _tree->crossFileSystems() )
				{
				    LocalDirReadJob * job = new LocalDirReadJob( _tree, subDir );
				    CHECK_NEW( job );
				    _tree->addJob( job );
				}
				else
				{
				    subDir->setReadState( DirOnRequestOnly );
				    finishReading( subDir );
				}
			    }
			}
		    }
		    else		// non-directory child
		    {
			if ( entryName == defaultCacheName )	// .qdirstat.cache.gz found?
			{
			    logDebug() << "Found cache file " << defaultCacheName << endl;

			    //
			    // Read content of this subdirectory from cache file
			    //

			    CacheReadJob * cacheReadJob = new CacheReadJob( _tree, _dir->parent(), fullName );
			    CHECK_NEW( cacheReadJob );
			    QString firstDirInCache = cacheReadJob->reader()->firstDir();

			    if ( firstDirInCache == dirName )	// Does this cache file match this directory?
			    {
				logDebug() << "Using cache file " << fullName << " for " << dirName << endl;

				cacheReadJob->reader()->rewind();  // Read offset was moved by firstDir()
				_tree->addJob( cacheReadJob );	   // Job queue will assume ownership of cacheReadJob

				if ( _dir->parent() )
				    _dir->parent()->setReadState( DirReading );

				//
				// Clean up partially read directory content
				//

				DirTree * tree = _tree;	 // Copy data members to local variables:
				DirInfo * dir  = _dir;	 // This object will be deleted soon by killAll()

				_queue->killAll( _dir, cacheReadJob );	// Will delete this job as well!
				// All data members of this object are invalid from here on!

				logDebug() << "Deleting subtree " << dir << endl;
				tree->deleteSubtree( dir );

				return;
			    }
			    else
			    {
				logWarning() << "NOT using cache file " << fullName
					     << " with dir " << firstDirInCache
					     << " for " << dirName
					     << endl;

				delete cacheReadJob;
			    }
			}
			else
			{
			    FileInfo *child = new FileInfo( entryName, &statInfo, _tree, _dir );
			    CHECK_NEW( child );
			    _dir->insertChild( child );
			    childAdded( child );
			}
		    }
		}
		else			// lstat() error
		{
		    logWarning() << "lstat(" << fullName << ") failed: " << strerror( errno ) << endl;

		    /*
		     * Not much we can do when lstat() didn't work; let's at
		     * least create an (almost empty) entry as a placeholder.
		     */
		    DirInfo *child = new DirInfo( _tree, _dir, entry->d_name );
		    CHECK_NEW( child );
		    child->setReadState( DirError );
		    _dir->insertChild( child );
		    childAdded( child );
		}
	    }
	}

	closedir( _diskDir );
	_dir->setReadState( DirFinished );
	finishReading( _dir );
    }
    else
    {
	_dir->setReadState( DirError );
	logWarning() << "opendir(" << dirName << ") failed" << endl;
	// opendir() doesn't set 'errno' according to POSIX  :-(
	finishReading( _dir );
    }

    finished();
    // Don't add anything after finished() since this deletes this job!
}
예제 #6
0
/**
  * scan
  * 
  * starts from the given node and iterates through all
  * child directories and builds vectors of all file
  * and directory nodes in the FS
  * 
  * @param pnode pointer to DirInfo node to scan
  */
bool FileSystem::scan(DirInfo* pnode) {
    debugPrint("Scanning Node: " + pnode->getPath());

    // Check if given path exists
    if ( !boost::filesystem::exists( pnode->getPath() ) ) {
        cout << pnode->getPath() << " doesn't exist" << endl;
        return false;
    }

    if (pnode->isHidden()) {
        return false;
    }

    // Create a boost directory iterator
    boost::filesystem::directory_iterator end_itr;
    try {

    for ( boost::filesystem::directory_iterator itr( pnode->getPath() ); 
          itr != end_itr; 
          ++itr ) {

        // Is iterated object a directory
        if ( is_directory(itr->status()) ) {

            DirInfo* dir = new DirInfo(itr->path().filename().string(), pnode);

            // Keeps track of node to deconstruct pointer
            allNodes.push_back(dir);
            // All directories list (for quick dir operations)
            allDirs.push_back(dir);
            // Add this node to it's parent children list
            pnode->addChild(dir);

            // Create a boost path object to extract fs info
            boost::filesystem::path p(dir->getPath());
            dir->setModifyTime( last_write_time(p) );
            dir->isDir(true);

            // Recursively scan dirs
            scan(dir);

            // directory size is only available after all dir and files add their
            // sizes to their parent dirs to be added here
            pnode->addSize(dir->getSize());

        // If iterated object is not directory, then it must be a file
        } else {

            FileInfo* file = new FileInfo(itr->path().filename().string(), pnode);

            // Keeps track of node to deconstruct pointer
            allNodes.push_back(file);
            // All files list (for quick file operations)
            allFiles.push_back(file);
            // Add this node to it's parent children list
            pnode->addChild(file);

            // Create a boost path object to extract fs info
            boost::filesystem::path p(file->getPath());
            try {
                file->setSize( file_size(p) );
            } catch (boost::filesystem::filesystem_error err) {
                file->setSize( 0 );
            }

            try {
                file->setModifyTime( last_write_time(p) );
            } catch (boost::filesystem::filesystem_error err) {
                file->setModifyTime( 0 );
            }
            // Update parent size
            file->getParent()->addSize(file->getSize());

        }
    }
    } catch (boost::filesystem::filesystem_error) {
        cout << "Cannot open file: " << pnode->getPath() << ". Permission denied!" << endl;
    }
 
    return true;
}