File indexing completed on 2024-04-28 15:18:41

0001 /* This file is part of the KDE libraries
0002    SPDX-FileCopyrightText: 2000-2005 David Faure <faure@kde.org>
0003    SPDX-FileCopyrightText: 2003 Leo Savernik <l.savernik@aon.at>
0004 
0005    Moved from ktar.h by Roberto Teixeira <maragato@kde.org>
0006 
0007    SPDX-License-Identifier: LGPL-2.0-or-later
0008 */
0009 #ifndef KARCHIVE_H
0010 #define KARCHIVE_H
0011 
0012 #include <sys/stat.h>
0013 #include <sys/types.h>
0014 
0015 #include <QCoreApplication>
0016 #include <QDate>
0017 #include <QHash>
0018 #include <QIODevice>
0019 #include <QString>
0020 #include <QStringList>
0021 
0022 #include <karchive_export.h>
0023 
0024 #ifdef Q_OS_WIN
0025 #include <qplatformdefs.h> // mode_t
0026 #endif
0027 
0028 class KArchiveDirectory;
0029 class KArchiveFile;
0030 
0031 class KArchivePrivate;
0032 /**
0033  * @class KArchive karchive.h KArchive
0034  *
0035  * KArchive is a base class for reading and writing archives.
0036  * @short generic class for reading/writing archives
0037  * @author David Faure <faure@kde.org>
0038  */
0039 class KARCHIVE_EXPORT KArchive
0040 {
0041     Q_DECLARE_TR_FUNCTIONS(KArchive)
0042 
0043 protected:
0044     /**
0045      * Base constructor (protected since this is a pure virtual class).
0046      * @param fileName is a local path (e.g. "/tmp/myfile.ext"),
0047      * from which the archive will be read from, or into which the archive
0048      * will be written, depending on the mode given to open().
0049      */
0050     KArchive(const QString &fileName);
0051 
0052     /**
0053      * Base constructor (protected since this is a pure virtual class).
0054      * @param dev the I/O device where the archive reads its data
0055      * Note that this can be a file, but also a data buffer, a compression filter, etc.
0056      * For a file in writing mode it is better to use the other constructor
0057      * though, to benefit from the use of QSaveFile when saving.
0058      */
0059     KArchive(QIODevice *dev);
0060 
0061 public:
0062     virtual ~KArchive();
0063 
0064     /**
0065      * Opens the archive for reading or writing.
0066      * Inherited classes might want to reimplement openArchive instead.
0067      * @param mode may be QIODevice::ReadOnly or QIODevice::WriteOnly
0068      * @see close
0069      */
0070     virtual bool open(QIODevice::OpenMode mode);
0071 
0072     /**
0073      * Closes the archive.
0074      * Inherited classes might want to reimplement closeArchive instead.
0075      *
0076      * @return true if close succeeded without problems
0077      * @see open
0078      */
0079     virtual bool close();
0080 
0081     /**
0082      * Returns a description of the last error
0083      * @since 5.29
0084      */
0085     QString errorString() const;
0086 
0087     /**
0088      * Checks whether the archive is open.
0089      * @return true if the archive is opened
0090      */
0091     bool isOpen() const;
0092 
0093     /**
0094      * Returns the mode in which the archive was opened
0095      * @return the mode in which the archive was opened (QIODevice::ReadOnly or QIODevice::WriteOnly)
0096      * @see open()
0097      */
0098     QIODevice::OpenMode mode() const;
0099 
0100     /**
0101      * The underlying device.
0102      * @return the underlying device.
0103      */
0104     QIODevice *device() const;
0105 
0106     /**
0107      * The name of the archive file, as passed to the constructor that takes a
0108      * fileName, or an empty string if you used the QIODevice constructor.
0109      * @return the name of the file, or QString() if unknown
0110      */
0111     QString fileName() const;
0112 
0113     /**
0114      * If an archive is opened for reading, then the contents
0115      * of the archive can be accessed via this function.
0116      * @return the directory of the archive
0117      */
0118     const KArchiveDirectory *directory() const;
0119 
0120     /**
0121      * Writes a local file into the archive. The main difference with writeFile,
0122      * is that this method minimizes memory usage, by not loading the whole file
0123      * into memory in one go.
0124      *
0125      * If @p fileName is a symbolic link, it will be written as is, i. e.
0126      * it will not be resolved before.
0127      * @param fileName full path to an existing local file, to be added to the archive.
0128      * @param destName the resulting name (or relative path) of the file in the archive.
0129      */
0130     bool addLocalFile(const QString &fileName, const QString &destName);
0131 
0132     /**
0133      * Writes a local directory into the archive, including all its contents, recursively.
0134      * Calls addLocalFile for each file to be added.
0135      *
0136      * It will also add a @p path that is a symbolic link to a
0137      * directory. The symbolic link will be dereferenced and the content of the
0138      * directory it is pointing to added recursively. However, symbolic links
0139      * *under* @p path will be stored as is.
0140      * @param path full path to an existing local directory, to be added to the archive.
0141      * @param destName the resulting name (or relative path) of the file in the archive.
0142      */
0143     bool addLocalDirectory(const QString &path, const QString &destName);
0144 
0145     /**
0146      * If an archive is opened for writing then you can add new directories
0147      * using this function. KArchive won't write one directory twice.
0148      *
0149      * This method also allows some file metadata to be set.
0150      * However, depending on the archive type not all metadata might be regarded.
0151      *
0152      * @param name the name of the directory
0153      * @param user the user that owns the directory
0154      * @param group the group that owns the directory
0155      * @param perm permissions of the directory
0156      * @param atime time the file was last accessed
0157      * @param mtime modification time of the file
0158      * @param ctime time of last status change
0159      */
0160     bool writeDir(const QString &name,
0161                   const QString &user = QString(),
0162                   const QString &group = QString(),
0163                   mode_t perm = 040755,
0164                   const QDateTime &atime = QDateTime(),
0165                   const QDateTime &mtime = QDateTime(),
0166                   const QDateTime &ctime = QDateTime());
0167 
0168     /**
0169      * Writes a symbolic link to the archive if supported.
0170      * The archive must be opened for writing.
0171      *
0172      * @param name name of symbolic link
0173      * @param target target of symbolic link
0174      * @param user the user that owns the directory
0175      * @param group the group that owns the directory
0176      * @param perm permissions of the directory
0177      * @param atime time the file was last accessed
0178      * @param mtime modification time of the file
0179      * @param ctime time of last status change
0180      */
0181     bool writeSymLink(const QString &name,
0182                       const QString &target,
0183                       const QString &user = QString(),
0184                       const QString &group = QString(),
0185                       mode_t perm = 0120755,
0186                       const QDateTime &atime = QDateTime(),
0187                       const QDateTime &mtime = QDateTime(),
0188                       const QDateTime &ctime = QDateTime());
0189 
0190 #if KARCHIVE_ENABLE_DEPRECATED_SINCE(5, 0)
0191     /**
0192      * @deprecated since 5.0, use writeFile(const QString&, const QByteArray&, mode_t, const QString&, const QString&, const QDateTime&, const QDateTime&, const
0193      * QDateTime&)
0194      */
0195     KARCHIVE_DEPRECATED_VERSION(5,
0196                                 0,
0197                                 "Use KArchive::writeFile(const QString&, const QByteArray&, mode_t, const QString&, const QString&, const QDateTime&, const "
0198                                 "QDateTime&, const QDateTime&)")
0199     bool writeFile(const QString &name,
0200                    const QString &user,
0201                    const QString &group,
0202                    const char *data,
0203                    qint64 size,
0204                    mode_t perm = 0100644,
0205                    const QDateTime &atime = QDateTime(),
0206                    const QDateTime &mtime = QDateTime(),
0207                    const QDateTime &ctime = QDateTime())
0208     {
0209         QByteArray array(data, size);
0210         return writeFile(name, array, perm, user, group, atime, mtime, ctime);
0211     }
0212     // The above can lead to ambiguous calls when using "..." for the first 4 arguments,
0213     // but that's good, better than unexpected behavior due to the signature change.
0214 #endif
0215 
0216     /**
0217      * Writes a new file into the archive.
0218      *
0219      * The archive must be opened for writing first.
0220      *
0221      * The necessary parent directories are created automatically
0222      * if needed. For instance, writing "mydir/test1" does not
0223      * require creating the directory "mydir" first.
0224      *
0225      * This method also allows some file metadata to be
0226      * set. However, depending on the archive type not all metadata might be
0227      * written out.
0228      *
0229      * @param name the name of the file
0230      * @param data the data to write
0231      * @param perm permissions of the file
0232      * @param user the user that owns the file
0233      * @param group the group that owns the file
0234      * @param atime time the file was last accessed
0235      * @param mtime modification time of the file
0236      * @param ctime time of last status change
0237      */
0238     bool writeFile(const QString &name,
0239                    const QByteArray &data,
0240                    mode_t perm = 0100644,
0241                    const QString &user = QString(),
0242                    const QString &group = QString(),
0243                    const QDateTime &atime = QDateTime(),
0244                    const QDateTime &mtime = QDateTime(),
0245                    const QDateTime &ctime = QDateTime());
0246 
0247     /**
0248      * Here's another way of writing a file into an archive:
0249      * Call prepareWriting(), then call writeData()
0250      * as many times as wanted then call finishWriting( totalSize ).
0251      * For tar.gz files, you need to know the size before hand, it is needed in the header!
0252      * For zip files, size isn't used.
0253      *
0254      * This method also allows some file metadata to be
0255      * set. However, depending on the archive type not all metadata might be
0256      * regarded.
0257      * @param name the name of the file
0258      * @param user the user that owns the file
0259      * @param group the group that owns the file
0260      * @param size the size of the file
0261      * @param perm permissions of the file
0262      * @param atime time the file was last accessed
0263      * @param mtime modification time of the file
0264      * @param ctime time of last status change
0265      */
0266     bool prepareWriting(const QString &name,
0267                         const QString &user,
0268                         const QString &group,
0269                         qint64 size,
0270                         mode_t perm = 0100644,
0271                         const QDateTime &atime = QDateTime(),
0272                         const QDateTime &mtime = QDateTime(),
0273                         const QDateTime &ctime = QDateTime());
0274 
0275     /**
0276      * Write data into the current file - to be called after calling prepareWriting
0277      */
0278     virtual bool writeData(const char *data, qint64 size);
0279 
0280     /**
0281      * Call finishWriting after writing the data.
0282      * @param size the size of the file
0283      * @see prepareWriting()
0284      */
0285     bool finishWriting(qint64 size);
0286 
0287 protected:
0288     /**
0289      * Opens an archive for reading or writing.
0290      * Called by open.
0291      * @param mode may be QIODevice::ReadOnly or QIODevice::WriteOnly
0292      */
0293     virtual bool openArchive(QIODevice::OpenMode mode) = 0;
0294 
0295     /**
0296      * Closes the archive.
0297      * Called by close.
0298      */
0299     virtual bool closeArchive() = 0;
0300 
0301     /**
0302      * Sets error description
0303      * @param errorStr error description
0304      * @since 5.29
0305      */
0306     void setErrorString(const QString &errorStr);
0307 
0308     /**
0309      * Retrieves or create the root directory.
0310      * The default implementation assumes that openArchive() did the parsing,
0311      * so it creates a dummy rootdir if none was set (write mode, or no '/' in the archive).
0312      * Reimplement this to provide parsing/listing on demand.
0313      * @return the root directory
0314      */
0315     virtual KArchiveDirectory *rootDir();
0316 
0317     /**
0318      * Write a directory to the archive.
0319      * This virtual method must be implemented by subclasses.
0320      *
0321      * Depending on the archive type not all metadata might be used.
0322      *
0323      * @param name the name of the directory
0324      * @param user the user that owns the directory
0325      * @param group the group that owns the directory
0326      * @param perm permissions of the directory. Use 040755 if you don't have any other information.
0327      * @param atime time the file was last accessed
0328      * @param mtime modification time of the file
0329      * @param ctime time of last status change
0330      * @see writeDir
0331      */
0332     virtual bool doWriteDir(const QString &name,
0333                             const QString &user,
0334                             const QString &group,
0335                             mode_t perm,
0336                             const QDateTime &atime,
0337                             const QDateTime &mtime,
0338                             const QDateTime &ctime) = 0;
0339 
0340     /**
0341      * Writes a symbolic link to the archive.
0342      * This virtual method must be implemented by subclasses.
0343      *
0344      * @param name name of symbolic link
0345      * @param target target of symbolic link
0346      * @param user the user that owns the directory
0347      * @param group the group that owns the directory
0348      * @param perm permissions of the directory
0349      * @param atime time the file was last accessed
0350      * @param mtime modification time of the file
0351      * @param ctime time of last status change
0352      * @see writeSymLink
0353      */
0354     virtual bool doWriteSymLink(const QString &name,
0355                                 const QString &target,
0356                                 const QString &user,
0357                                 const QString &group,
0358                                 mode_t perm,
0359                                 const QDateTime &atime,
0360                                 const QDateTime &mtime,
0361                                 const QDateTime &ctime) = 0;
0362 
0363     /**
0364      * This virtual method must be implemented by subclasses.
0365      *
0366      * Depending on the archive type not all metadata might be used.
0367      *
0368      * @param name the name of the file
0369      * @param user the user that owns the file
0370      * @param group the group that owns the file
0371      * @param size the size of the file
0372      * @param perm permissions of the file. Use 0100644 if you don't have any more specific permissions to set.
0373      * @param atime time the file was last accessed
0374      * @param mtime modification time of the file
0375      * @param ctime time of last status change
0376      * @see prepareWriting
0377      */
0378     virtual bool doPrepareWriting(const QString &name,
0379                                   const QString &user,
0380                                   const QString &group,
0381                                   qint64 size,
0382                                   mode_t perm,
0383                                   const QDateTime &atime,
0384                                   const QDateTime &mtime,
0385                                   const QDateTime &ctime) = 0;
0386 
0387     /**
0388      * Called after writing the data.
0389      * This virtual method must be implemented by subclasses.
0390      *
0391      * @param size the size of the file
0392      * @see finishWriting()
0393      */
0394     virtual bool doFinishWriting(qint64 size) = 0;
0395 
0396     /**
0397      * Ensures that @p path exists, create otherwise.
0398      * This handles e.g. tar files missing directory entries, like mico-2.3.0.tar.gz :)
0399      * @param path the path of the directory
0400      * @return the directory with the given @p path
0401      */
0402     KArchiveDirectory *findOrCreate(const QString &path);
0403 
0404     /**
0405      * Can be reimplemented in order to change the creation of the device
0406      * (when using the fileName constructor). By default this method uses
0407      * QSaveFile when saving, and a simple QFile on reading.
0408      * This method is called by open().
0409      */
0410     virtual bool createDevice(QIODevice::OpenMode mode);
0411 
0412     /**
0413      * Can be called by derived classes in order to set the underlying device.
0414      * Note that KArchive will -not- own the device, it must be deleted by the derived class.
0415      */
0416     void setDevice(QIODevice *dev);
0417 
0418     /**
0419      * Derived classes call setRootDir from openArchive,
0420      * to set the root directory after parsing an existing archive.
0421      */
0422     void setRootDir(KArchiveDirectory *rootDir);
0423 
0424 protected:
0425     virtual void virtual_hook(int id, void *data);
0426 
0427 private:
0428     friend class KArchivePrivate;
0429     KArchivePrivate *const d;
0430 };
0431 
0432 // for source compat
0433 #include "karchivedirectory.h"
0434 #include "karchivefile.h"
0435 
0436 #endif