File indexing completed on 2024-05-05 16:13:54

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