1/* This file is part of the KDE libraries
2 SPDX-FileCopyrightText: 2014 David Faure <faure@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "krcc.h"
8#include "karchive_p.h"
9#include "loggingcategory.h"
10
11#include <QDateTime>
12#include <QDebug>
13#include <QDir>
14#include <QFile>
15#include <QFileInfo>
16#include <QResource>
17#include <QUuid>
18
19class Q_DECL_HIDDEN KRcc::KRccPrivate
20{
21public:
22 KRccPrivate()
23 {
24 }
25 void createEntries(const QDir &dir, KArchiveDirectory *parentDir, KRcc *q);
26
27 QString m_prefix; // '/' + uuid
28};
29
30/**
31 * A KRccFileEntry represents a file in a rcc archive.
32 */
33class KRccFileEntry : public KArchiveFile
34{
35public:
36 KRccFileEntry(KArchive *archive,
37 const QString &name,
38 int access,
39 const QDateTime &date,
40 const QString &user,
41 const QString &group,
42 qint64 size,
43 const QString &resourcePath)
44 : KArchiveFile(archive, name, access, date, user, group, QString(), 0, size)
45 , m_resourcePath(resourcePath)
46 {
47 }
48
49 QByteArray data() const override
50 {
51 QFile f(m_resourcePath);
52 if (f.open(flags: QIODevice::ReadOnly)) {
53 return f.readAll();
54 }
55 qCWarning(KArchiveLog) << "Couldn't open" << m_resourcePath;
56 return QByteArray();
57 }
58 QIODevice *createDevice() const override
59 {
60 return new QFile(m_resourcePath);
61 }
62
63private:
64 QString m_resourcePath;
65};
66
67KRcc::KRcc(const QString &filename)
68 : KArchive(filename)
69 , d(new KRccPrivate)
70{
71}
72
73KRcc::~KRcc()
74{
75 if (isOpen()) {
76 close();
77 }
78 delete d;
79}
80
81bool KRcc::doPrepareWriting(const QString &, const QString &, const QString &, qint64, mode_t, const QDateTime &, const QDateTime &, const QDateTime &)
82{
83 setErrorString(tr(sourceText: "Cannot write to RCC file"));
84 qCWarning(KArchiveLog) << "doPrepareWriting not implemented for KRcc";
85 return false;
86}
87
88bool KRcc::doFinishWriting(qint64)
89{
90 setErrorString(tr(sourceText: "Cannot write to RCC file"));
91 qCWarning(KArchiveLog) << "doFinishWriting not implemented for KRcc";
92 return false;
93}
94
95bool KRcc::doWriteDir(const QString &, const QString &, const QString &, mode_t, const QDateTime &, const QDateTime &, const QDateTime &)
96{
97 setErrorString(tr(sourceText: "Cannot write to RCC file"));
98 qCWarning(KArchiveLog) << "doWriteDir not implemented for KRcc";
99 return false;
100}
101
102bool KRcc::doWriteSymLink(const QString &, const QString &, const QString &, const QString &, mode_t, const QDateTime &, const QDateTime &, const QDateTime &)
103{
104 setErrorString(tr(sourceText: "Cannot write to RCC file"));
105 qCWarning(KArchiveLog) << "doWriteSymLink not implemented for KRcc";
106 return false;
107}
108
109bool KRcc::openArchive(QIODevice::OpenMode mode)
110{
111 // Open archive
112
113 if (mode == QIODevice::WriteOnly) {
114 return true;
115 }
116 if (mode != QIODevice::ReadOnly && mode != QIODevice::ReadWrite) {
117 setErrorString(tr(sourceText: "Unsupported mode %1").arg(a: mode));
118 return false;
119 }
120
121 QUuid uuid = QUuid::createUuid();
122 d->m_prefix = QLatin1Char('/') + uuid.toString();
123 if (!QResource::registerResource(rccFilename: fileName(), resourceRoot: d->m_prefix)) {
124 setErrorString(tr(sourceText: "Failed to register resource %1 under prefix %2").arg(args: fileName(), args&: d->m_prefix));
125 return false;
126 }
127
128 QDir dir(QLatin1Char(':') + d->m_prefix);
129 d->createEntries(dir, parentDir: rootDir(), q: this);
130 return true;
131}
132
133void KRcc::KRccPrivate::createEntries(const QDir &dir, KArchiveDirectory *parentDir, KRcc *q)
134{
135 for (const QString &fileName : dir.entryList()) {
136 const QString entryPath = dir.path() + QLatin1Char('/') + fileName;
137 const QFileInfo info(entryPath);
138 if (info.isFile()) {
139 KArchiveEntry *entry = new KRccFileEntry(q, fileName, 0444, info.lastModified(), parentDir->user(), parentDir->group(), info.size(), entryPath);
140 parentDir->addEntry(entry);
141 } else {
142 KArchiveDirectory *entry =
143 new KArchiveDirectory(q, fileName, 0555, info.lastModified(), parentDir->user(), parentDir->group(), /*symlink*/ QString());
144 if (parentDir->addEntryV2(entry)) {
145 createEntries(dir: QDir(entryPath), parentDir: entry, q);
146 }
147 }
148 }
149}
150
151bool KRcc::closeArchive()
152{
153 // Close the archive
154 QResource::unregisterResource(rccFilename: fileName(), resourceRoot: d->m_prefix);
155 // ignore errors
156 return true;
157}
158
159void KRcc::virtual_hook(int id, void *data)
160{
161 KArchive::virtual_hook(id, data);
162}
163

source code of karchive/src/krcc.cpp