1 /* 2 This file is part of the KDE project 3 SPDX-FileCopyrightText: 2004 David Faure <faure@kde.org> 4 5 SPDX-License-Identifier: LGPL-2.0-or-later 6 */ 7 8 #ifndef TRASHIMPL_H 9 #define TRASHIMPL_H 10 11 #include <kio/job.h> 12 13 #include <KConfig> 14 15 #include <QDateTime> 16 #include <QMap> 17 18 namespace Solid 19 { 20 class Device; 21 } 22 23 /** 24 * Implementation of all low-level operations done by kio_trash. 25 * The structure of the trash directory follows the freedesktop.org standard: 26 * https://specifications.freedesktop.org/trash-spec/trashspec-1.0.html 27 */ 28 class TrashImpl : public QObject 29 { 30 Q_OBJECT 31 public: 32 TrashImpl(); 33 34 /// Check the "home" trash directory 35 /// This MUST be called before doing anything else 36 bool init(); 37 38 /// Create info for a file to be trashed 39 /// Returns trashId and fileId 40 /// The caller is then responsible for actually trashing the file 41 bool createInfo(const QString &origPath, int &trashId, QString &fileId); 42 43 /// Delete info file for a file to be trashed 44 /// Usually used for undoing what createInfo did if trashing failed 45 bool deleteInfo(int trashId, const QString &fileId); 46 47 /// Moving a file or directory into the trash. The ids come from createInfo. 48 bool moveToTrash(const QString &origPath, int trashId, const QString &fileId); 49 50 /// Moving a file or directory out of the trash. The ids come from createInfo. 51 bool moveFromTrash(const QString &origPath, int trashId, const QString &fileId, const QString &relativePath); 52 53 /// Copying a file or directory into the trash. The ids come from createInfo. 54 bool copyToTrash(const QString &origPath, int trashId, const QString &fileId); 55 56 /// Copying a file or directory out of the trash. The ids come from createInfo. 57 bool copyFromTrash(const QString &origPath, int trashId, const QString &fileId, const QString &relativePath); 58 59 /// Renaming a file or directory in the trash. 60 bool moveInTrash(int trashId, const QString &oldFileId, const QString &newFileId); 61 62 /// Get rid of a trashed file 63 bool del(int trashId, const QString &fileId); 64 65 /// Empty trash, i.e. delete all trashed files 66 bool emptyTrash(); 67 68 /// Return true if the trash is empty 69 bool isEmpty() const; 70 71 struct TrashedFileInfo { 72 int trashId; // for the url 73 QString fileId; // for the url 74 QString physicalPath; // for stat'ing etc. 75 QString origPath; // from info file 76 QDateTime deletionDate; // from info file 77 }; 78 /// List trashed files 79 using TrashedFileInfoList = QList<TrashedFileInfo>; 80 81 /// Returns the TrashedFileInfo of all files in all trashes 82 /// uses scanTrashDirectories() to refresh m_trashDirectories 83 TrashedFileInfoList list(); 84 85 /// Return the info for a given trashed file 86 bool infoForFile(int trashId, const QString &fileId, TrashedFileInfo &info); 87 88 struct TrashSpaceInfo { 89 qint64 totalSize; // total trash size in bytes 90 qint64 availableSize; // available trash space in bytes 91 }; 92 /// Get the space info for a given trash path 93 /// Space information is only valid if trashSpaceInfo returns true 94 bool trashSpaceInfo(const QString &path, TrashSpaceInfo &info); 95 96 /// Returns an UDSEntry corresponding to trash:/ 97 KIO::UDSEntry trashUDSEntry(KIO::StatDetails details); 98 99 /// Return the physicalPath for a given trashed file - helper method which 100 /// encapsulates the call to infoForFile. Don't use if you need more info from TrashedFileInfo. 101 QString physicalPath(int trashId, const QString &fileId, const QString &relativePath); 102 103 /// Move data from the old trash system to the new one 104 void migrateOldTrash(); 105 106 /// KIO error code lastErrorCode()107 int lastErrorCode() const 108 { 109 return m_lastErrorCode; 110 } lastErrorMessage()111 QString lastErrorMessage() const 112 { 113 return m_lastErrorMessage; 114 } 115 116 QStringList listDir(const QString &physicalPath); 117 118 static QUrl makeURL(int trashId, const QString &fileId, const QString &relativePath); 119 static bool parseURL(const QUrl &url, int &trashId, QString &fileId, QString &relativePath); 120 121 using TrashDirMap = QMap<int, QString>; 122 /// @internal This method is for TestTrash only. Home trash is included (id 0). 123 TrashDirMap trashDirectories() const; 124 /// @internal This method is for TestTrash only. No entry with id 0. 125 TrashDirMap topDirectories() const; 126 127 Q_SIGNALS: 128 void leaveModality(); 129 130 private: 131 /// Helper method. Moves a file or directory using the appropriate method. 132 bool move(const QString &src, const QString &dest); 133 bool copy(const QString &src, const QString &dest); 134 /// Helper method. Tries to call ::rename(src,dest) and does error handling. 135 bool directRename(const QString &src, const QString &dest); 136 137 void fileAdded(); 138 void fileRemoved(); 139 140 bool adaptTrashSize(const QString &origPath, int trashId); 141 142 // Warning, returns error code, not a bool 143 int testDir(const QString &name) const; 144 void error(int e, const QString &s); 145 146 bool readInfoFile(const QString &infoPath, TrashedFileInfo &info, int trashId); 147 148 QString infoPath(int trashId, const QString &fileId) const; 149 QString filesPath(int trashId, const QString &fileId) const; 150 151 #ifdef Q_OS_OSX 152 int idForMountPoint(const QString &mountPoint) const; 153 #else 154 int idForDevice(const Solid::Device &device) const; 155 #endif 156 void refreshDevices() const; 157 158 /// Find the trash dir to use for a given file to delete, based on original path 159 int findTrashDirectory(const QString &origPath); 160 161 QString trashDirectoryPath(int trashId) const; 162 QString topDirectoryPath(int trashId) const; 163 164 bool synchronousDel(const QString &path, bool setLastErrorCode, bool isDir); 165 166 void scanTrashDirectories() const; 167 168 int idForTrashDirectory(const QString &trashDir) const; 169 bool initTrashDirectory(const QByteArray &trashDir_c) const; 170 bool checkTrashSubdirs(const QByteArray &trashDir_c) const; 171 QString trashForMountPoint(const QString &topdir, bool createIfNeeded) const; 172 static QString makeRelativePath(const QString &topdir, const QString &path); 173 174 void enterLoop(); 175 176 private Q_SLOTS: 177 void jobFinished(KJob *job); 178 179 private: 180 // delete the files and info subdirectories from all known trash directories 181 // (supposed to be empty!) to make sure OS X sees the trash as empty too. 182 // Stub except on OS X. 183 void deleteEmptyTrashInfrastructure(); 184 // create the trash infrastructure; also called 185 // to recreate it on OS X. 186 bool createTrashInfrastructure(int trashId, const QString &path = QString()); 187 188 // Inserts a newly found @p trashDir, under @p topdir with @p id 189 void insertTrashDir(int id, const QString &trashDir, const QString &topdir) const; 190 191 /// Last error code stored in class to simplify API. 192 /// Note that this means almost no method can be const. 193 int m_lastErrorCode; 194 QString m_lastErrorMessage; 195 196 enum { InitToBeDone, InitOK, InitError } m_initStatus; 197 198 // A "trash directory" is a physical directory on disk, 199 // e.g. $HOME/.local/share/Trash or /mnt/foo/.Trash-$uid 200 // It has an id (int) and a path. 201 // The home trash has id 0. 202 mutable TrashDirMap m_trashDirectories; // id -> path of trash directory 203 mutable TrashDirMap m_topDirectories; // id -> $topdir of partition 204 dev_t m_homeDevice; 205 mutable bool m_trashDirectoriesScanned; 206 207 mutable KConfig m_config; 208 209 // We don't cache any data related to the trashed files. 210 // Another kioslave could change that behind our feet. 211 // If we want to start caching data - and avoiding some race conditions -, 212 // we should turn this class into a kded module and use DCOP to talk to it 213 // from the kioslave. 214 }; 215 216 #endif 217