1/* This file is part of the KDE libraries
2 SPDX-FileCopyrightText: 2000-2005 David Faure <faure@kde.org>
3 SPDX-FileCopyrightText: 2003 Leo Savernik <l.savernik@aon.at>
4
5 Moved from ktar.h by Roberto Teixeira <maragato@kde.org>
6
7 SPDX-License-Identifier: LGPL-2.0-or-later
8*/
9#ifndef KARCHIVE_H
10#define KARCHIVE_H
11
12#include <sys/stat.h>
13#include <sys/types.h>
14
15#include <QByteArrayView>
16#include <QCoreApplication>
17#include <QDate>
18#include <QHash>
19#include <QIODevice>
20#include <QString>
21#include <QStringList>
22
23#include <karchive_export.h>
24
25#ifdef Q_OS_WIN
26#include <qplatformdefs.h> // mode_t
27#endif
28
29class KArchiveDirectory;
30class KArchiveFile;
31
32class KArchivePrivate;
33/**
34 * @class KArchive karchive.h KArchive
35 *
36 * KArchive is a base class for reading and writing archives.
37 * @short generic class for reading/writing archives
38 * @author David Faure <faure@kde.org>
39 */
40class KARCHIVE_EXPORT KArchive
41{
42 Q_DECLARE_TR_FUNCTIONS(KArchive)
43
44protected:
45 /**
46 * Base constructor (protected since this is a pure virtual class).
47 * @param fileName is a local path (e.g. "/tmp/myfile.ext"),
48 * from which the archive will be read from, or into which the archive
49 * will be written, depending on the mode given to open().
50 */
51 explicit KArchive(const QString &fileName);
52
53 /**
54 * Base constructor (protected since this is a pure virtual class).
55 * @param dev the I/O device where the archive reads its data
56 * Note that this can be a file, but also a data buffer, a compression filter, etc.
57 * For a file in writing mode it is better to use the other constructor
58 * though, to benefit from the use of QSaveFile when saving.
59 */
60 explicit KArchive(QIODevice *dev);
61
62public:
63 virtual ~KArchive();
64
65 /**
66 * Opens the archive for reading or writing.
67 * Inherited classes might want to reimplement openArchive instead.
68 * @param mode may be QIODevice::ReadOnly or QIODevice::WriteOnly
69 * @see close
70 */
71 virtual bool open(QIODevice::OpenMode mode);
72
73 /**
74 * Closes the archive.
75 * Inherited classes might want to reimplement closeArchive instead.
76 *
77 * @return true if close succeeded without problems
78 * @see open
79 */
80 virtual bool close();
81
82 /**
83 * Returns a description of the last error
84 * @since 5.29
85 */
86 QString errorString() const;
87
88 /**
89 * Checks whether the archive is open.
90 * @return true if the archive is opened
91 */
92 bool isOpen() const;
93
94 /**
95 * Returns the mode in which the archive was opened
96 * @return the mode in which the archive was opened (QIODevice::ReadOnly or QIODevice::WriteOnly)
97 * @see open()
98 */
99 QIODevice::OpenMode mode() const;
100
101 /**
102 * The underlying device.
103 * @return the underlying device.
104 */
105 QIODevice *device() const;
106
107 /**
108 * The name of the archive file, as passed to the constructor that takes a
109 * fileName, or an empty string if you used the QIODevice constructor.
110 * @return the name of the file, or QString() if unknown
111 */
112 QString fileName() const;
113
114 /**
115 * If an archive is opened for reading, then the contents
116 * of the archive can be accessed via this function.
117 * @return the directory of the archive
118 */
119 const KArchiveDirectory *directory() const;
120
121 /**
122 * Writes a local file into the archive. The main difference with writeFile,
123 * is that this method minimizes memory usage, by not loading the whole file
124 * into memory in one go.
125 *
126 * If @p fileName is a symbolic link, it will be written as is, i.e.
127 * it will not be resolved before.
128 * @param fileName full path to an existing local file, to be added to the archive.
129 * @param destName the resulting name (or relative path) of the file in the archive.
130 */
131 bool addLocalFile(const QString &fileName, const QString &destName);
132
133 /**
134 * Writes a local directory into the archive, including all its contents, recursively.
135 * Calls addLocalFile for each file to be added.
136 *
137 * It will also add a @p path that is a symbolic link to a
138 * directory. The symbolic link will be dereferenced and the content of the
139 * directory it is pointing to added recursively. However, symbolic links
140 * *under* @p path will be stored as is.
141 * @param path full path to an existing local directory, to be added to the archive.
142 * @param destName the resulting name (or relative path) of the file in the archive.
143 */
144 bool addLocalDirectory(const QString &path, const QString &destName);
145
146 /**
147 * If an archive is opened for writing then you can add new directories
148 * using this function. KArchive won't write one directory twice.
149 *
150 * This method also allows some file metadata to be set.
151 * However, depending on the archive type not all metadata might be regarded.
152 *
153 * @param name the name of the directory
154 * @param user the user that owns the directory
155 * @param group the group that owns the directory
156 * @param perm permissions of the directory
157 * @param atime time the file was last accessed
158 * @param mtime modification time of the file
159 * @param ctime time of last status change
160 */
161 bool writeDir(const QString &name,
162 const QString &user = QString(),
163 const QString &group = QString(),
164 mode_t perm = 040755,
165 const QDateTime &atime = QDateTime(),
166 const QDateTime &mtime = QDateTime(),
167 const QDateTime &ctime = QDateTime());
168
169 /**
170 * Writes a symbolic link to the archive if supported.
171 * The archive must be opened for writing.
172 *
173 * @param name name of symbolic link
174 * @param target target of symbolic link
175 * @param user the user that owns the directory
176 * @param group the group that owns the directory
177 * @param perm permissions of the directory
178 * @param atime time the file was last accessed
179 * @param mtime modification time of the file
180 * @param ctime time of last status change
181 */
182 bool writeSymLink(const QString &name,
183 const QString &target,
184 const QString &user = QString(),
185 const QString &group = QString(),
186 mode_t perm = 0120755,
187 const QDateTime &atime = QDateTime(),
188 const QDateTime &mtime = QDateTime(),
189 const QDateTime &ctime = QDateTime());
190
191 /**
192 * Writes a new file into the archive.
193 *
194 * The archive must be opened for writing first.
195 *
196 * The necessary parent directories are created automatically
197 * if needed. For instance, writing "mydir/test1" does not
198 * require creating the directory "mydir" first.
199 *
200 * This method also allows some file metadata to be
201 * set. However, depending on the archive type not all metadata might be
202 * written out.
203 *
204 * @param name the name of the file
205 * @param data the data to write
206 * @param perm permissions of the file
207 * @param user the user that owns the file
208 * @param group the group that owns the file
209 * @param atime time the file was last accessed
210 * @param mtime modification time of the file
211 * @param ctime time of last status change
212 * @since 6.0
213 */
214 bool writeFile(const QString &name,
215 QByteArrayView data,
216 mode_t perm = 0100644,
217 const QString &user = QString(),
218 const QString &group = QString(),
219 const QDateTime &atime = QDateTime(),
220 const QDateTime &mtime = QDateTime(),
221 const QDateTime &ctime = QDateTime());
222
223 /**
224 * Here's another way of writing a file into an archive:
225 * Call prepareWriting(), then call writeData()
226 * as many times as wanted then call finishWriting( totalSize ).
227 * For tar.gz files, you need to know the size before hand, it is needed in the header!
228 * For zip files, size isn't used.
229 *
230 * This method also allows some file metadata to be
231 * set. However, depending on the archive type not all metadata might be
232 * regarded.
233 * @param name the name of the file
234 * @param user the user that owns the file
235 * @param group the group that owns the file
236 * @param size the size of the file
237 * @param perm permissions of the file
238 * @param atime time the file was last accessed
239 * @param mtime modification time of the file
240 * @param ctime time of last status change
241 */
242 bool prepareWriting(const QString &name,
243 const QString &user,
244 const QString &group,
245 qint64 size,
246 mode_t perm = 0100644,
247 const QDateTime &atime = QDateTime(),
248 const QDateTime &mtime = QDateTime(),
249 const QDateTime &ctime = QDateTime());
250
251 /**
252 * Write data into the current file - to be called after calling prepareWriting
253 * @param data a pointer to the data
254 * @param size the size of the chunk
255 * @return @c true if successful, @c false otherwise
256 */
257 bool writeData(const char *data, qint64 size);
258
259 /**
260 * Overload for writeData(const char *, qint64);
261 * @since 6.0
262 */
263 bool writeData(QByteArrayView data);
264
265 /**
266 * Call finishWriting after writing the data.
267 * @param size the size of the file
268 * @see prepareWriting()
269 */
270 bool finishWriting(qint64 size);
271
272protected:
273 /**
274 * Opens an archive for reading or writing.
275 * Called by open.
276 * @param mode may be QIODevice::ReadOnly or QIODevice::WriteOnly
277 */
278 virtual bool openArchive(QIODevice::OpenMode mode) = 0;
279
280 /**
281 * Closes the archive.
282 * Called by close.
283 */
284 virtual bool closeArchive() = 0;
285
286 /**
287 * Sets error description
288 * @param errorStr error description
289 * @since 5.29
290 */
291 void setErrorString(const QString &errorStr);
292
293 /**
294 * Retrieves or create the root directory.
295 * The default implementation assumes that openArchive() did the parsing,
296 * so it creates a dummy rootdir if none was set (write mode, or no '/' in the archive).
297 * Reimplement this to provide parsing/listing on demand.
298 * @return the root directory
299 */
300 virtual KArchiveDirectory *rootDir();
301
302 /**
303 * Write a directory to the archive.
304 * This virtual method must be implemented by subclasses.
305 *
306 * Depending on the archive type not all metadata might be used.
307 *
308 * @param name the name of the directory
309 * @param user the user that owns the directory
310 * @param group the group that owns the directory
311 * @param perm permissions of the directory. Use 040755 if you don't have any other information.
312 * @param atime time the file was last accessed
313 * @param mtime modification time of the file
314 * @param ctime time of last status change
315 * @see writeDir
316 */
317 virtual bool doWriteDir(const QString &name,
318 const QString &user,
319 const QString &group,
320 mode_t perm,
321 const QDateTime &atime,
322 const QDateTime &mtime,
323 const QDateTime &ctime) = 0;
324
325 /**
326 * Writes a symbolic link to the archive.
327 * This virtual method must be implemented by subclasses.
328 *
329 * @param name name of symbolic link
330 * @param target target of symbolic link
331 * @param user the user that owns the directory
332 * @param group the group that owns the directory
333 * @param perm permissions of the directory
334 * @param atime time the file was last accessed
335 * @param mtime modification time of the file
336 * @param ctime time of last status change
337 * @see writeSymLink
338 */
339 virtual bool doWriteSymLink(const QString &name,
340 const QString &target,
341 const QString &user,
342 const QString &group,
343 mode_t perm,
344 const QDateTime &atime,
345 const QDateTime &mtime,
346 const QDateTime &ctime) = 0;
347
348 /**
349 * This virtual method must be implemented by subclasses.
350 *
351 * Depending on the archive type not all metadata might be used.
352 *
353 * @param name the name of the file
354 * @param user the user that owns the file
355 * @param group the group that owns the file
356 * @param size the size of the file
357 * @param perm permissions of the file. Use 0100644 if you don't have any more specific permissions to set.
358 * @param atime time the file was last accessed
359 * @param mtime modification time of the file
360 * @param ctime time of last status change
361 * @see prepareWriting
362 */
363 virtual bool doPrepareWriting(const QString &name,
364 const QString &user,
365 const QString &group,
366 qint64 size,
367 mode_t perm,
368 const QDateTime &atime,
369 const QDateTime &mtime,
370 const QDateTime &ctime) = 0;
371
372 /**
373 * Write data into the current file.
374 * Called by writeData.
375 *
376 * @param data a pointer to the data
377 * @param size the size of the chunk
378 * @return @c true if successful, @c false otherwise
379 * @see writeData
380 * @since 6.0
381 */
382 virtual bool doWriteData(const char *data, qint64 size);
383
384 /**
385 * Called after writing the data.
386 * This virtual method must be implemented by subclasses.
387 *
388 * @param size the size of the file
389 * @see finishWriting()
390 */
391 virtual bool doFinishWriting(qint64 size) = 0;
392
393 /**
394 * Ensures that @p path exists, create otherwise.
395 * This handles e.g. tar files missing directory entries, like mico-2.3.0.tar.gz :)
396 * @param path the path of the directory
397 * @return the directory with the given @p path
398 */
399 KArchiveDirectory *findOrCreate(const QString &path);
400
401 /**
402 * Can be reimplemented in order to change the creation of the device
403 * (when using the fileName constructor). By default this method uses
404 * QSaveFile when saving, and a simple QFile on reading.
405 * This method is called by open().
406 */
407 virtual bool createDevice(QIODevice::OpenMode mode);
408
409 /**
410 * Can be called by derived classes in order to set the underlying device.
411 * Note that KArchive will -not- own the device, it must be deleted by the derived class.
412 */
413 void setDevice(QIODevice *dev);
414
415 /**
416 * Derived classes call setRootDir from openArchive,
417 * to set the root directory after parsing an existing archive.
418 */
419 void setRootDir(KArchiveDirectory *rootDir);
420
421protected:
422 virtual void virtual_hook(int id, void *data);
423
424private:
425 friend class KArchivePrivate;
426 KArchivePrivate *const d;
427};
428
429// for source compat
430#include "karchivedirectory.h"
431#include "karchivefile.h"
432
433#endif
434

source code of karchive/src/karchive.h