File indexing completed on 2024-04-21 11:25:58

0001 /* This file is part of the KDE libraries
0002    SPDX-FileCopyrightText: 2014 David Faure <faure@kde.org>
0003 
0004    SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "krcc.h"
0008 #include "karchive_p.h"
0009 #include "loggingcategory.h"
0010 
0011 #include <QDateTime>
0012 #include <QDebug>
0013 #include <QDir>
0014 #include <QFile>
0015 #include <QFileInfo>
0016 #include <QResource>
0017 #include <QUuid>
0018 
0019 class Q_DECL_HIDDEN KRcc::KRccPrivate
0020 {
0021 public:
0022     KRccPrivate()
0023     {
0024     }
0025     void createEntries(const QDir &dir, KArchiveDirectory *parentDir, KRcc *q);
0026 
0027     QString m_prefix; // '/' + uuid
0028 };
0029 
0030 /**
0031  * A KRccFileEntry represents a file in a rcc archive.
0032  */
0033 class KRccFileEntry : public KArchiveFile
0034 {
0035 public:
0036     KRccFileEntry(KArchive *archive,
0037                   const QString &name,
0038                   int access,
0039                   const QDateTime &date,
0040                   const QString &user,
0041                   const QString &group,
0042                   qint64 size,
0043                   const QString &resourcePath)
0044         : KArchiveFile(archive, name, access, date, user, group, QString(), 0, size)
0045         , m_resourcePath(resourcePath)
0046     {
0047     }
0048 
0049     QByteArray data() const override
0050     {
0051         QFile f(m_resourcePath);
0052         if (f.open(QIODevice::ReadOnly)) {
0053             return f.readAll();
0054         }
0055         qCWarning(KArchiveLog) << "Couldn't open" << m_resourcePath;
0056         return QByteArray();
0057     }
0058     QIODevice *createDevice() const override
0059     {
0060         return new QFile(m_resourcePath);
0061     }
0062 
0063 private:
0064     QString m_resourcePath;
0065 };
0066 
0067 KRcc::KRcc(const QString &filename)
0068     : KArchive(filename)
0069     , d(new KRccPrivate)
0070 {
0071 }
0072 
0073 KRcc::~KRcc()
0074 {
0075     if (isOpen()) {
0076         close();
0077     }
0078     delete d;
0079 }
0080 
0081 bool KRcc::doPrepareWriting(const QString &, const QString &, const QString &, qint64, mode_t, const QDateTime &, const QDateTime &, const QDateTime &)
0082 {
0083     setErrorString(tr("Cannot write to RCC file"));
0084     qCWarning(KArchiveLog) << "doPrepareWriting not implemented for KRcc";
0085     return false;
0086 }
0087 
0088 bool KRcc::doFinishWriting(qint64)
0089 {
0090     setErrorString(tr("Cannot write to RCC file"));
0091     qCWarning(KArchiveLog) << "doFinishWriting not implemented for KRcc";
0092     return false;
0093 }
0094 
0095 bool KRcc::doWriteDir(const QString &, const QString &, const QString &, mode_t, const QDateTime &, const QDateTime &, const QDateTime &)
0096 {
0097     setErrorString(tr("Cannot write to RCC file"));
0098     qCWarning(KArchiveLog) << "doWriteDir not implemented for KRcc";
0099     return false;
0100 }
0101 
0102 bool KRcc::doWriteSymLink(const QString &, const QString &, const QString &, const QString &, mode_t, const QDateTime &, const QDateTime &, const QDateTime &)
0103 {
0104     setErrorString(tr("Cannot write to RCC file"));
0105     qCWarning(KArchiveLog) << "doWriteSymLink not implemented for KRcc";
0106     return false;
0107 }
0108 
0109 bool KRcc::openArchive(QIODevice::OpenMode mode)
0110 {
0111     // Open archive
0112 
0113     if (mode == QIODevice::WriteOnly) {
0114         return true;
0115     }
0116     if (mode != QIODevice::ReadOnly && mode != QIODevice::ReadWrite) {
0117         setErrorString(tr("Unsupported mode %1").arg(mode));
0118         return false;
0119     }
0120 
0121     QUuid uuid = QUuid::createUuid();
0122     d->m_prefix = QLatin1Char('/') + uuid.toString();
0123     if (!QResource::registerResource(fileName(), d->m_prefix)) {
0124         setErrorString(tr("Failed to register resource %1 under prefix %2").arg(fileName(), d->m_prefix));
0125         return false;
0126     }
0127 
0128     QDir dir(QLatin1Char(':') + d->m_prefix);
0129     d->createEntries(dir, rootDir(), this);
0130     return true;
0131 }
0132 
0133 void KRcc::KRccPrivate::createEntries(const QDir &dir, KArchiveDirectory *parentDir, KRcc *q)
0134 {
0135     for (const QString &fileName : dir.entryList()) {
0136         const QString entryPath = dir.path() + QLatin1Char('/') + fileName;
0137         const QFileInfo info(entryPath);
0138         if (info.isFile()) {
0139             KArchiveEntry *entry = new KRccFileEntry(q, fileName, 0444, info.lastModified(), parentDir->user(), parentDir->group(), info.size(), entryPath);
0140             parentDir->addEntry(entry);
0141         } else {
0142             KArchiveDirectory *entry =
0143                 new KArchiveDirectory(q, fileName, 0555, info.lastModified(), parentDir->user(), parentDir->group(), /*symlink*/ QString());
0144             if (parentDir->addEntryV2(entry)) {
0145                 createEntries(QDir(entryPath), entry, q);
0146             }
0147         }
0148     }
0149 }
0150 
0151 bool KRcc::closeArchive()
0152 {
0153     // Close the archive
0154     QResource::unregisterResource(fileName(), d->m_prefix);
0155     // ignore errors
0156     return true;
0157 }
0158 
0159 void KRcc::virtual_hook(int id, void *data)
0160 {
0161     KArchive::virtual_hook(id, data);
0162 }