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
35 * \inmodule KArchive
36 *
37 * \brief Generic class for reading/writing archives.
38 */
39class KARCHIVE_EXPORT KArchive
40{
41 Q_DECLARE_TR_FUNCTIONS(KArchive)
42
43protected:
44 /*!
45 * Base constructor (protected since this is a pure virtual class).
46 *
47 * \a 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 *
56 * \a dev the I/O device where the archive reads its data
57 *
58 * Note that this can be a file, but also a data buffer, a compression filter, etc.
59 * For a file in writing mode it is better to use the other constructor
60 * though, to benefit from the use of QSaveFile when saving.
61 */
62 explicit KArchive(QIODevice *dev);
63
64public:
65 virtual ~KArchive();
66
67 /*!
68 * Opens the archive for reading or writing.
69 *
70 * Inherited classes might want to reimplement openArchive instead.
71 *
72 * \a mode may be QIODevice::ReadOnly or QIODevice::WriteOnly
73 * \sa close
74 */
75 virtual bool open(QIODevice::OpenMode mode);
76
77 /*!
78 * Closes the archive.
79 *
80 * Inherited classes might want to reimplement closeArchive instead.
81 *
82 * Returns true if close succeeded without problems
83 * \sa open
84 */
85 virtual bool close();
86
87 /*!
88 * Returns a description of the last error
89 * \since 5.29
90 */
91 QString errorString() const;
92
93 /*!
94 * Checks whether the archive is open.
95 *
96 * Returns true if the archive is opened
97 */
98 bool isOpen() const;
99
100 /*!
101 * Returns the mode in which the archive was opened (QIODevice::ReadOnly or QIODevice::WriteOnly)
102 * \sa open()
103 */
104 QIODevice::OpenMode mode() const;
105
106 /*!
107 * Returns the underlying device.
108 */
109 QIODevice *device() const;
110
111 /*!
112 * The name of the archive file, as passed to the constructor that takes a
113 * fileName, or an empty string if you used the QIODevice constructor.
114 *
115 * Returns the name of the file, or QString() if unknown
116 */
117 QString fileName() const;
118
119 /*!
120 * If an archive is opened for reading, then the contents
121 * of the archive can be accessed via this function.
122 * Returns the directory of the archive
123 */
124 const KArchiveDirectory *directory() const;
125
126 /*!
127 * Writes a local file into the archive. The main difference with writeFile,
128 * is that this method minimizes memory usage, by not loading the whole file
129 * into memory in one go.
130 *
131 * If \a fileName is a symbolic link, it will be written as is, i.e.
132 * it will not be resolved before.
133 *
134 * \a fileName full path to an existing local file, to be added to the archive.
135 *
136 * \a destName the resulting name (or relative path) of the file in the archive.
137 */
138 bool addLocalFile(const QString &fileName, const QString &destName);
139
140 /*!
141 * Writes a local directory into the archive, including all its contents, recursively.
142 * Calls addLocalFile for each file to be added.
143 *
144 * It will also add a \a path that is a symbolic link to a
145 * directory. The symbolic link will be dereferenced and the content of the
146 * directory it is pointing to added recursively. However, symbolic links
147 * *under* \a path will be stored as is.
148 *
149 * \a path full path to an existing local directory, to be added to the archive.
150 *
151 * \a destName the resulting name (or relative path) of the file in the archive.
152 */
153 bool addLocalDirectory(const QString &path, const QString &destName);
154
155 /*!
156 * If an archive is opened for writing then you can add new directories
157 * using this function. KArchive won't write one directory twice.
158 *
159 * This method also allows some file metadata to be set.
160 * However, depending on the archive type not all metadata might be regarded.
161 *
162 * \a name the name of the directory
163 *
164 * \a user the user that owns the directory
165 *
166 * \a group the group that owns the directory
167 *
168 * \a perm permissions of the directory
169 *
170 * \a atime time the file was last accessed
171 *
172 * \a mtime modification time of the file
173 *
174 * \a ctime time of last status change
175 */
176 bool writeDir(const QString &name,
177 const QString &user = QString(),
178 const QString &group = QString(),
179 mode_t perm = 040755,
180 const QDateTime &atime = QDateTime(),
181 const QDateTime &mtime = QDateTime(),
182 const QDateTime &ctime = QDateTime());
183
184 /*!
185 * Writes a symbolic link to the archive if supported.
186 * The archive must be opened for writing.
187 *
188 * \a name name of symbolic link
189 *
190 * \a target target of symbolic link
191 *
192 * \a user the user that owns the directory
193 *
194 * \a group the group that owns the directory
195 *
196 * \a perm permissions of the directory
197 *
198 * \a atime time the file was last accessed
199 *
200 * \a mtime modification time of the file
201 *
202 * \a ctime time of last status change
203 */
204 bool writeSymLink(const QString &name,
205 const QString &target,
206 const QString &user = QString(),
207 const QString &group = QString(),
208 mode_t perm = 0120755,
209 const QDateTime &atime = QDateTime(),
210 const QDateTime &mtime = QDateTime(),
211 const QDateTime &ctime = QDateTime());
212
213 /*!
214 * Writes a new file into the archive.
215 *
216 * The archive must be opened for writing first.
217 *
218 * The necessary parent directories are created automatically
219 * if needed. For instance, writing "mydir/test1" does not
220 * require creating the directory "mydir" first.
221 *
222 * This method also allows some file metadata to be
223 * set. However, depending on the archive type not all metadata might be
224 * written out.
225 *
226 * \a name the name of the file
227 *
228 * \a data the data to write
229 *
230 * \a perm permissions of the file
231 *
232 * \a user the user that owns the file
233 *
234 * \a group the group that owns the file
235 *
236 * \a atime time the file was last accessed
237 *
238 * \a mtime modification time of the file
239 *
240 * \a ctime time of last status change
241 *
242 * \since 6.0
243 */
244 bool writeFile(const QString &name,
245 QByteArrayView data,
246 mode_t perm = 0100644,
247 const QString &user = QString(),
248 const QString &group = QString(),
249 const QDateTime &atime = QDateTime(),
250 const QDateTime &mtime = QDateTime(),
251 const QDateTime &ctime = QDateTime());
252
253 /*!
254 * Here's another way of writing a file into an archive:
255 * Call prepareWriting(), then call writeData()
256 * as many times as wanted then call finishWriting( totalSize ).
257 * For tar.gz files, you need to know the size before hand, it is needed in the header!
258 * For zip files, size isn't used.
259 *
260 * This method also allows some file metadata to be
261 * set. However, depending on the archive type not all metadata might be
262 * regarded.
263 *
264 * \a name the name of the file
265 *
266 * \a user the user that owns the file
267 *
268 * \a group the group that owns the file
269 *
270 * \a size the size of the file
271 *
272 * \a perm permissions of the file
273 *
274 * \a atime time the file was last accessed
275 *
276 * \a mtime modification time of the file
277 *
278 * \a ctime time of last status change
279 */
280 bool prepareWriting(const QString &name,
281 const QString &user,
282 const QString &group,
283 qint64 size,
284 mode_t perm = 0100644,
285 const QDateTime &atime = QDateTime(),
286 const QDateTime &mtime = QDateTime(),
287 const QDateTime &ctime = QDateTime());
288
289 /*!
290 * Write data into the current file - to be called after calling prepareWriting
291 *
292 * \a data a pointer to the data
293 *
294 * \a size the size of the chunk
295 *
296 * Returns \c true if successful, \c false otherwise
297 */
298 bool writeData(const char *data, qint64 size);
299
300 /*!
301 * Overload for writeData(const char *, qint64);
302 * \since 6.0
303 */
304 bool writeData(QByteArrayView data);
305
306 /*!
307 * Call finishWriting after writing the data.
308 *
309 * \a size the size of the file
310 * \sa prepareWriting()
311 */
312 bool finishWriting(qint64 size);
313
314protected:
315 /*!
316 * Opens an archive for reading or writing.
317 *
318 * Called by open.
319 *
320 * \a mode may be QIODevice::ReadOnly or QIODevice::WriteOnly
321 */
322 virtual bool openArchive(QIODevice::OpenMode mode) = 0;
323
324 /*!
325 * Closes the archive.
326 *
327 * Called by close.
328 */
329 virtual bool closeArchive() = 0;
330
331 /*!
332 * Sets error description
333 *
334 * \a errorStr error description
335 *
336 * \since 5.29
337 */
338 void setErrorString(const QString &errorStr);
339
340 /*!
341 * Retrieves or create the root directory.
342 *
343 * The default implementation assumes that openArchive() did the parsing,
344 * so it creates a dummy rootdir if none was set (write mode, or no '/' in the archive).
345 *
346 * Reimplement this to provide parsing/listing on demand.
347 *
348 * Returns the root directory
349 */
350 virtual KArchiveDirectory *rootDir();
351
352 /*!
353 * Write a directory to the archive.
354 * This virtual method must be implemented by subclasses.
355 *
356 * Depending on the archive type not all metadata might be used.
357 *
358 * \a name the name of the directory
359 *
360 * \a user the user that owns the directory
361 *
362 * \a group the group that owns the directory
363 *
364 * \a perm permissions of the directory. Use 040755 if you don't have any other information.
365 *
366 * \a atime time the file was last accessed
367 *
368 * \a mtime modification time of the file
369 *
370 * \a ctime time of last status change
371 *
372 * \sa writeDir
373 */
374 virtual bool doWriteDir(const QString &name,
375 const QString &user,
376 const QString &group,
377 mode_t perm,
378 const QDateTime &atime,
379 const QDateTime &mtime,
380 const QDateTime &ctime) = 0;
381
382 /*!
383 * Writes a symbolic link to the archive.
384 * This virtual method must be implemented by subclasses.
385 *
386 * \a name name of symbolic link
387 *
388 * \a target target of symbolic link
389 *
390 * \a user the user that owns the directory
391 *
392 * \a group the group that owns the directory
393 *
394 * \a perm permissions of the directory
395 *
396 * \a atime time the file was last accessed
397 *
398 * \a mtime modification time of the file
399 *
400 * \a ctime time of last status change
401 * \sa writeSymLink
402 */
403 virtual bool doWriteSymLink(const QString &name,
404 const QString &target,
405 const QString &user,
406 const QString &group,
407 mode_t perm,
408 const QDateTime &atime,
409 const QDateTime &mtime,
410 const QDateTime &ctime) = 0;
411
412 /*!
413 * This virtual method must be implemented by subclasses.
414 *
415 * Depending on the archive type not all metadata might be used.
416 *
417 * \a name the name of the file
418 *
419 * \a user the user that owns the file
420 *
421 * \a group the group that owns the file
422 *
423 * \a size the size of the file
424 *
425 * \a perm permissions of the file. Use 0100644 if you don't have any more specific permissions to set.
426 *
427 * \a atime time the file was last accessed
428 *
429 * \a mtime modification time of the file
430 *
431 * \a ctime time of last status change
432 *
433 * \sa prepareWriting
434 */
435 virtual bool doPrepareWriting(const QString &name,
436 const QString &user,
437 const QString &group,
438 qint64 size,
439 mode_t perm,
440 const QDateTime &atime,
441 const QDateTime &mtime,
442 const QDateTime &ctime) = 0;
443
444 /*!
445 * Write data into the current file.
446 * Called by writeData.
447 *
448 * \a data a pointer to the data
449 *
450 * \a size the size of the chunk
451 *
452 * Returns \c true if successful, \c false otherwise
453 *
454 * \sa writeData
455 * \since 6.0
456 */
457 virtual bool doWriteData(const char *data, qint64 size);
458
459 /*!
460 * Called after writing the data.
461 *
462 * This virtual method must be implemented by subclasses.
463 *
464 * \a size the size of the file
465 * \sa finishWriting()
466 */
467 virtual bool doFinishWriting(qint64 size) = 0;
468
469 /*!
470 * Ensures that \a path exists, create otherwise.
471 *
472 * This handles e.g. tar files missing directory entries, like mico-2.3.0.tar.gz :)
473 *
474 * \a path the path of the directory
475 *
476 * Returns the directory with the given \a path
477 */
478 KArchiveDirectory *findOrCreate(const QString &path);
479
480 /*!
481 * Can be reimplemented in order to change the creation of the device
482 * (when using the fileName constructor). By default this method uses
483 * QSaveFile when saving, and a simple QFile on reading.
484 *
485 * This method is called by open().
486 */
487 virtual bool createDevice(QIODevice::OpenMode mode);
488
489 /*!
490 * Can be called by derived classes in order to set the underlying device.
491 *
492 * Note that KArchive will -not- own the device, it must be deleted by the derived class.
493 */
494 void setDevice(QIODevice *dev);
495
496 /*!
497 * Derived classes call setRootDir from openArchive,
498 * to set the root directory after parsing an existing archive.
499 */
500 void setRootDir(KArchiveDirectory *rootDir);
501
502protected:
503 virtual void virtual_hook(int id, void *data);
504
505private:
506 friend class KArchivePrivate;
507 KArchivePrivate *const d;
508};
509
510// for source compat
511#include "karchivedirectory.h"
512#include "karchivefile.h"
513
514#endif
515

source code of karchive/src/karchive.h