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

source code of kio/src/kioworkers/trash/trashimpl.h