mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-08-13 09:34:53 +02:00
Do not crash when the collection folders contains cycles (symlinks).
Example: /my/collection/subfolder/link -> /my/collection Use canonicalFilePath to detect cycles and also check m_newdirtimes for an existing timestamp before recursing into subfolders.
This commit is contained in:
committed by
Christian Muehlhaeuser
parent
04d30913f9
commit
9af6ff7911
@@ -65,7 +65,7 @@ DirLister::go()
|
|||||||
void
|
void
|
||||||
DirLister::scanDir( QDir dir, int depth, DirLister::Mode mode )
|
DirLister::scanDir( QDir dir, int depth, DirLister::Mode mode )
|
||||||
{
|
{
|
||||||
qDebug() << "DirLister::scanDir scanning: " << dir.absolutePath() << " with mode " << mode;
|
qDebug() << "DirLister::scanDir scanning: " << dir.canonicalPath() << " with mode " << mode;
|
||||||
|
|
||||||
if( !dir.exists() )
|
if( !dir.exists() )
|
||||||
{
|
{
|
||||||
@@ -74,16 +74,16 @@ DirLister::scanDir( QDir dir, int depth, DirLister::Mode mode )
|
|||||||
}
|
}
|
||||||
|
|
||||||
QFileInfoList dirs;
|
QFileInfoList dirs;
|
||||||
const uint mtime = QFileInfo( dir.absolutePath() ).lastModified().toUTC().toTime_t();
|
const uint mtime = QFileInfo( dir.canonicalPath() ).lastModified().toUTC().toTime_t();
|
||||||
m_newdirmtimes.insert( dir.absolutePath(), mtime );
|
m_newdirmtimes.insert( dir.canonicalPath(), mtime );
|
||||||
|
|
||||||
if ( m_dirmtimes.contains( dir.absolutePath() ) && mtime == m_dirmtimes.value( dir.absolutePath() ) )
|
if ( m_dirmtimes.contains( dir.canonicalPath() ) && mtime == m_dirmtimes.value( dir.canonicalPath() ) )
|
||||||
{
|
{
|
||||||
// dont scan this dir, unchanged since last time.
|
// dont scan this dir, unchanged since last time.
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if( m_dirmtimes.contains( dir.absolutePath() ) || !m_recursive )
|
if( m_dirmtimes.contains( dir.canonicalPath() ) || !m_recursive )
|
||||||
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( new DatabaseCommand_DeleteFiles( dir, SourceList::instance()->getLocal() ) ) );
|
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( new DatabaseCommand_DeleteFiles( dir, SourceList::instance()->getLocal() ) ) );
|
||||||
|
|
||||||
dir.setFilter( QDir::Files | QDir::Readable | QDir::NoDotAndDotDot );
|
dir.setFilter( QDir::Files | QDir::Readable | QDir::NoDotAndDotDot );
|
||||||
@@ -99,10 +99,13 @@ DirLister::scanDir( QDir dir, int depth, DirLister::Mode mode )
|
|||||||
|
|
||||||
foreach( const QFileInfo& di, dirs )
|
foreach( const QFileInfo& di, dirs )
|
||||||
{
|
{
|
||||||
qDebug() << "Considering dir " << di.absoluteFilePath();
|
const QString canonical = di.canonicalFilePath();
|
||||||
qDebug() << "m_dirmtimes contains it? " << (m_dirmtimes.contains( di.absoluteFilePath() ) ? "true" : "false");
|
qDebug() << "Considering dir " << canonical;
|
||||||
if( mode == DirLister::Recursive || !m_dirmtimes.contains( di.absoluteFilePath() ) )
|
const bool haveDi = m_dirmtimes.contains( canonical );
|
||||||
scanDir( di.absoluteFilePath(), depth + 1, DirLister::Recursive );
|
qDebug() << "m_dirmtimes contains it?" << haveDi;
|
||||||
|
if( !m_newdirmtimes.contains( canonical ) && ( mode == DirLister::Recursive || !haveDi ) ) {
|
||||||
|
scanDir( di.canonicalFilePath(), depth + 1, DirLister::Recursive );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,20 +320,20 @@ MusicScanner::readFile( const QFileInfo& fi )
|
|||||||
if( m_scanned % 3 == 0 )
|
if( m_scanned % 3 == 0 )
|
||||||
SourceList::instance()->getLocal()->scanningProgress( m_scanned );
|
SourceList::instance()->getLocal()->scanningProgress( m_scanned );
|
||||||
if( m_scanned % 100 == 0 )
|
if( m_scanned % 100 == 0 )
|
||||||
qDebug() << "SCAN" << m_scanned << fi.absoluteFilePath();
|
qDebug() << "SCAN" << m_scanned << fi.canonicalFilePath();
|
||||||
|
|
||||||
#ifdef COMPLEX_TAGLIB_FILENAME
|
#ifdef COMPLEX_TAGLIB_FILENAME
|
||||||
const wchar_t *encodedName = reinterpret_cast< const wchar_t * >( fi.absoluteFilePath().utf16() );
|
const wchar_t *encodedName = reinterpret_cast< const wchar_t * >( fi.canonicalFilePath().utf16() );
|
||||||
#else
|
#else
|
||||||
QByteArray fileName = QFile::encodeName( fi.absoluteFilePath() );
|
QByteArray fileName = QFile::encodeName( fi.canonicalFilePath() );
|
||||||
const char *encodedName = fileName.constData();
|
const char *encodedName = fileName.constData();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TagLib::FileRef f( encodedName );
|
TagLib::FileRef f( encodedName );
|
||||||
if ( f.isNull() || !f.tag() )
|
if ( f.isNull() || !f.tag() )
|
||||||
{
|
{
|
||||||
// qDebug() << "Doesn't seem to be a valid audiofile:" << fi.absoluteFilePath();
|
// qDebug() << "Doesn't seem to be a valid audiofile:" << fi.canonicalFilePath();
|
||||||
m_skippedFiles << fi.absoluteFilePath();
|
m_skippedFiles << fi.canonicalFilePath();
|
||||||
m_skipped++;
|
m_skipped++;
|
||||||
return QVariantMap();
|
return QVariantMap();
|
||||||
}
|
}
|
||||||
@@ -351,8 +354,8 @@ MusicScanner::readFile( const QFileInfo& fi )
|
|||||||
if ( artist.isEmpty() || track.isEmpty() )
|
if ( artist.isEmpty() || track.isEmpty() )
|
||||||
{
|
{
|
||||||
// FIXME: do some clever filename guessing
|
// FIXME: do some clever filename guessing
|
||||||
// qDebug() << "No tags found, skipping" << fi.absoluteFilePath();
|
// qDebug() << "No tags found, skipping" << fi.canonicalFilePath();
|
||||||
m_skippedFiles << fi.absoluteFilePath();
|
m_skippedFiles << fi.canonicalFilePath();
|
||||||
m_skipped++;
|
m_skipped++;
|
||||||
return QVariantMap();
|
return QVariantMap();
|
||||||
}
|
}
|
||||||
@@ -361,7 +364,7 @@ MusicScanner::readFile( const QFileInfo& fi )
|
|||||||
QString url( "file://%1" );
|
QString url( "file://%1" );
|
||||||
|
|
||||||
QVariantMap m;
|
QVariantMap m;
|
||||||
m["url"] = url.arg( fi.absoluteFilePath() );
|
m["url"] = url.arg( fi.canonicalFilePath() );
|
||||||
m["mtime"] = fi.lastModified().toUTC().toTime_t();
|
m["mtime"] = fi.lastModified().toUTC().toTime_t();
|
||||||
m["size"] = (unsigned int)fi.size();
|
m["size"] = (unsigned int)fi.size();
|
||||||
m["mimetype"] = mimetype;
|
m["mimetype"] = mimetype;
|
||||||
|
@@ -46,7 +46,7 @@ public:
|
|||||||
MTimeOnly
|
MTimeOnly
|
||||||
};
|
};
|
||||||
|
|
||||||
DirLister( QStringList dirs, QMap<QString, unsigned int>& mtimes, bool recursive )
|
DirLister( const QStringList& dirs, const QMap<QString, unsigned int>& mtimes, bool recursive )
|
||||||
: QObject(), m_dirs( dirs ), m_dirmtimes( mtimes ), m_recursive( recursive )
|
: QObject(), m_dirs( dirs ), m_dirmtimes( mtimes ), m_recursive( recursive )
|
||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO;
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
Reference in New Issue
Block a user