diff --git a/thumbnail/thumbnail.h b/thumbnail/thumbnail.h --- a/thumbnail/thumbnail.h +++ b/thumbnail/thumbnail.h @@ -20,6 +20,7 @@ #ifndef _THUMBNAIL_H_ #define _THUMBNAIL_H_ +#include #include #include #include @@ -69,6 +70,13 @@ **/ bool drawSubThumbnail(QPainter& p, const QString& filePath, int width, int height, int xPos, int yPos, int frameWidth); + + /** + * Checks if path is on the same filesystem as thumbnail cache directory. + * Returns true if so. False otherwise or if filesystem couldn't be checked. + */ + bool sharesFilesystemWithThumbRoot(const QString &path); + private: QString m_mimeType; int m_width; @@ -83,6 +91,10 @@ QSet m_propagationDirectories; QString m_thumbBasePath; qint64 m_maxFileSize; +#ifndef Q_OS_WIN + static const dev_t deviceIdUnset = std::numeric_limits::max(); + dev_t m_thumbnailDirDeviceId = deviceIdUnset; +#endif }; #endif diff --git a/thumbnail/thumbnail.cpp b/thumbnail/thumbnail.cpp --- a/thumbnail/thumbnail.cpp +++ b/thumbnail/thumbnail.cpp @@ -28,6 +28,7 @@ #ifndef Q_OS_WIN #include #include +#include #include // nice() #endif @@ -55,6 +56,10 @@ #include #include #include +#include +#include +#include +#include #include #include @@ -62,6 +67,7 @@ #include #include #include +#include "thumbnail-logsettings.h" #include #include @@ -552,8 +558,9 @@ } dir.next(); + QString canonicalFilePath = dir.fileInfo().canonicalFilePath(); - if (validThumbnails > 0 && hadFirstThumbnail == dir.filePath()) { + if (validThumbnails > 0 && hadFirstThumbnail == canonicalFilePath) { break; // Never show the same thumbnail twice } @@ -563,7 +570,7 @@ continue; } - if (!drawSubThumbnail(p, dir.filePath(), segmentWidth, segmentHeight, xPos, yPos, frameWidth)) { + if (!drawSubThumbnail(p, canonicalFilePath, segmentWidth, segmentHeight, xPos, yPos, frameWidth)) { continue; } @@ -726,6 +733,16 @@ if (!thumbnail.load(thumbPath.absoluteFilePath(thumbName))) { // no cached version is available, a new thumbnail must be created + // If file is on encrypted filesystem, we can't cache it unless it's on the same filesystem as thumbnail directory + bool allowCache; + allowCache = sharesFilesystemWithThumbRoot(filePath); + if (!allowCache) { + Solid::Device device = Solid::Device::storageAccessFromPath(filePath); + if (device.is()) { + allowCache = device.as()->usage() != Solid::StorageVolume::UsageType::Encrypted; + } + } + QSaveFile thumbnailfile(thumbPath.absoluteFilePath(thumbName)); bool savedCorrectly = false; if (subCreator->create(filePath, cacheSize, cacheSize, thumbnail)) { @@ -733,7 +750,7 @@ // The thumbnail has been created successfully. Store the thumbnail // to the cache for future access. - if (thumbnailfile.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + if (allowCache && thumbnailfile.open(QIODevice::WriteOnly | QIODevice::Truncate)) { savedCorrectly = thumbnail.save(&thumbnailfile, "PNG"); } } else { @@ -750,6 +767,28 @@ return true; } +bool ThumbnailProtocol::sharesFilesystemWithThumbRoot(const QString& path) +{ +#ifndef Q_OS_WIN + if (m_thumbnailDirDeviceId == deviceIdUnset) { + struct stat baseStat; + if (lstat(QFile::encodeName(m_thumbBasePath).data(), &baseStat) == -1) { + qCWarning(KIO_THUMBNAIL_LOG) << "Cannot read information about filesystem under path \"" << m_thumbBasePath << "\""; + return false; + } + m_thumbnailDirDeviceId = baseStat.st_dev; + } + struct stat fileStat; + if (lstat(QFile::encodeName(path).data(), &fileStat) == -1) { + qCWarning(KIO_THUMBNAIL_LOG) << "Cannot read information about filesystem under path \"" << path << "\""; + return false; + } + return m_thumbnailDirDeviceId == fileStat.st_dev; +#else + return false; +#endif +} + void ThumbnailProtocol::scaleDownImage(QImage& img, int maxWidth, int maxHeight) { if (img.width() > maxWidth || img.height() > maxHeight) {