示例#1
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;
    }
}
示例#2
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!
}