File indexing completed on 2025-02-02 03:49:26
0001 /* 0002 This file is part of the KDE project 0003 SPDX-FileCopyrightText: 2004 David Faure <faure@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #ifndef TRASHIMPL_H 0009 #define TRASHIMPL_H 0010 0011 #include "global.h" 0012 #include "udsentry.h" 0013 #include <kio/job.h> 0014 0015 #include <KConfig> 0016 0017 #include <QDateTime> 0018 #include <QMap> 0019 0020 namespace Solid 0021 { 0022 class Device; 0023 } 0024 0025 /** 0026 * Implementation of all low-level operations done by kio_trash. 0027 * The structure of the trash directory follows the freedesktop.org standard: 0028 * https://specifications.freedesktop.org/trash-spec/trashspec-1.0.html 0029 */ 0030 class TrashImpl : public QObject 0031 { 0032 Q_OBJECT 0033 public: 0034 TrashImpl(); 0035 0036 /// Check the "home" trash directory 0037 /// This MUST be called before doing anything else 0038 bool init(); 0039 0040 /// Create info for a file to be trashed 0041 /// Returns trashId and fileId 0042 /// The caller is then responsible for actually trashing the file 0043 bool createInfo(const QString &origPath, int &trashId, QString &fileId); 0044 0045 /// Delete info file for a file to be trashed 0046 /// Usually used for undoing what createInfo did if trashing failed 0047 bool deleteInfo(int trashId, const QString &fileId); 0048 0049 /// Moving a file or directory into the trash. The ids come from createInfo. 0050 bool moveToTrash(const QString &origPath, int trashId, const QString &fileId); 0051 0052 /// Moving a file or directory out of the trash. The ids come from createInfo. 0053 bool moveFromTrash(const QString &origPath, int trashId, const QString &fileId, const QString &relativePath); 0054 0055 /// Copying a file or directory into the trash. The ids come from createInfo. 0056 bool copyToTrash(const QString &origPath, int trashId, const QString &fileId); 0057 0058 /// Copying a file or directory out of the trash. The ids come from createInfo. 0059 bool copyFromTrash(const QString &origPath, int trashId, const QString &fileId, const QString &relativePath); 0060 0061 /// Renaming a file or directory in the trash. 0062 bool moveInTrash(int trashId, const QString &oldFileId, const QString &newFileId); 0063 0064 /// Get rid of a trashed file 0065 bool del(int trashId, const QString &fileId); 0066 0067 /// Empty trash, i.e. delete all trashed files 0068 bool emptyTrash(); 0069 0070 /// Return true if the trash is empty 0071 bool isEmpty() const; 0072 0073 struct TrashedFileInfo { 0074 int trashId; // for the url 0075 QString fileId; // for the url 0076 QString physicalPath; // for stat'ing etc. 0077 QString origPath; // from info file 0078 QDateTime deletionDate; // from info file 0079 }; 0080 /// List trashed files 0081 using TrashedFileInfoList = QList<TrashedFileInfo>; 0082 0083 /// Returns the TrashedFileInfo of all files in all trashes 0084 /// uses scanTrashDirectories() to refresh m_trashDirectories 0085 TrashedFileInfoList list(); 0086 0087 /// Return the info for a given trashed file 0088 bool infoForFile(int trashId, const QString &fileId, TrashedFileInfo &info); 0089 0090 struct TrashSpaceInfo { 0091 qint64 totalSize; // total trash size in bytes 0092 qint64 availableSize; // available trash space in bytes 0093 }; 0094 /// Get the space info for a given trash path 0095 /// Space information is only valid if trashSpaceInfo returns true 0096 bool trashSpaceInfo(const QString &path, TrashSpaceInfo &info); 0097 0098 /// Returns an UDSEntry corresponding to trash:/ 0099 KIO::UDSEntry trashUDSEntry(KIO::StatDetails details); 0100 0101 /// Return the physicalPath for a given trashed file - helper method which 0102 /// encapsulates the call to infoForFile. Don't use if you need more info from TrashedFileInfo. 0103 QString physicalPath(int trashId, const QString &fileId, const QString &relativePath); 0104 0105 /// Move data from the old trash system to the new one 0106 void migrateOldTrash(); 0107 0108 /// KIO error code 0109 int lastErrorCode() const 0110 { 0111 return m_lastErrorCode; 0112 } 0113 QString lastErrorMessage() const 0114 { 0115 return m_lastErrorMessage; 0116 } 0117 0118 QStringList listDir(const QString &physicalPath); 0119 0120 static QUrl makeURL(int trashId, const QString &fileId, const QString &relativePath); 0121 static bool parseURL(const QUrl &url, int &trashId, QString &fileId, QString &relativePath); 0122 0123 using TrashDirMap = QMap<int, QString>; 0124 /// @internal This method is for TestTrash only. Home trash is included (id 0). 0125 TrashDirMap trashDirectories() const; 0126 /// @internal This method is for TestTrash only. No entry with id 0. 0127 TrashDirMap topDirectories() const; 0128 0129 Q_SIGNALS: 0130 void leaveModality(); 0131 0132 private: 0133 /// Helper method. Moves a file or directory using the appropriate method. 0134 bool move(const QString &src, const QString &dest); 0135 bool copy(const QString &src, const QString &dest); 0136 /// Helper method. Tries to call ::rename(src,dest) and does error handling. 0137 bool directRename(const QString &src, const QString &dest); 0138 0139 void fileAdded(); 0140 void fileRemoved(); 0141 0142 bool adaptTrashSize(const QString &origPath, int trashId); 0143 0144 // Warning, returns error code, not a bool 0145 int testDir(const QString &name) const; 0146 void error(int e, const QString &s); 0147 0148 bool readInfoFile(const QString &infoPath, TrashedFileInfo &info, int trashId); 0149 0150 QString infoPath(int trashId, const QString &fileId) const; 0151 QString filesPath(int trashId, const QString &fileId) const; 0152 0153 #ifdef Q_OS_OSX 0154 int idForMountPoint(const QString &mountPoint) const; 0155 #else 0156 int idForDevice(const Solid::Device &device) const; 0157 #endif 0158 void refreshDevices() const; 0159 0160 /// Find the trash dir to use for a given file to delete, based on original path 0161 int findTrashDirectory(const QString &origPath); 0162 0163 QString trashDirectoryPath(int trashId) const; 0164 QString topDirectoryPath(int trashId) const; 0165 0166 bool synchronousDel(const QString &path, bool setLastErrorCode, bool isDir); 0167 0168 void scanTrashDirectories() const; 0169 0170 int idForTrashDirectory(const QString &trashDir) const; 0171 bool initTrashDirectory(const QByteArray &trashDir_c) const; 0172 bool checkTrashSubdirs(const QByteArray &trashDir_c) const; 0173 QString trashForMountPoint(const QString &topdir, bool createIfNeeded) const; 0174 static QString makeRelativePath(const QString &topdir, const QString &path); 0175 0176 void enterLoop(); 0177 0178 private Q_SLOTS: 0179 void jobFinished(KJob *job); 0180 0181 private: 0182 // delete the files and info subdirectories from all known trash directories 0183 // (supposed to be empty!) to make sure OS X sees the trash as empty too. 0184 // Stub except on OS X. 0185 void deleteEmptyTrashInfrastructure(); 0186 // create the trash infrastructure; also called 0187 // to recreate it on OS X. 0188 bool createTrashInfrastructure(int trashId, const QString &path = QString()); 0189 0190 // Inserts a newly found @p trashDir, under @p topdir with @p id 0191 void insertTrashDir(int id, const QString &trashDir, const QString &topdir) const; 0192 0193 /// Last error code stored in class to simplify API. 0194 /// Note that this means almost no method can be const. 0195 int m_lastErrorCode; 0196 QString m_lastErrorMessage; 0197 0198 enum { InitToBeDone, InitOK, InitError } m_initStatus; 0199 0200 // A "trash directory" is a physical directory on disk, 0201 // e.g. $HOME/.local/share/Trash or /mnt/foo/.Trash-$uid 0202 // It has an id (int) and a path. 0203 // The home trash has id 0. 0204 mutable TrashDirMap m_trashDirectories; // id -> path of trash directory 0205 mutable TrashDirMap m_topDirectories; // id -> $topdir of partition 0206 dev_t m_homeDevice; 0207 mutable bool m_trashDirectoriesScanned; 0208 0209 mutable KConfig m_config; 0210 0211 // We don't cache any data related to the trashed files. 0212 // Another KIO worker could change that behind our feet. 0213 // If we want to start caching data - and avoiding some race conditions -, 0214 // we should turn this class into a kded module and use DCOP to talk to it 0215 // from the KIO worker. 0216 }; 0217 0218 #endif