1/* This file is part of the KDE libraries
2 Copyright (C) 2000-2005 David Faure <faure@kde.org>
3 Copyright (C) 2003 Leo Savernik <l.savernik@aon.at>
4
5 Moved from ktar.h by Roberto Teixeira <maragato@kde.org>
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License version 2 as published by the Free Software Foundation.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*/
21#ifndef KARCHIVE_H
22#define KARCHIVE_H
23
24#include <sys/stat.h>
25#include <sys/types.h>
26
27#include <QtCore/QDate>
28#include <QtCore/QString>
29#include <QtCore/QStringList>
30#include <QtCore/QHash>
31
32#include <kdecore_export.h>
33
34class KArchiveDirectory;
35class KArchiveFile;
36
37class KArchivePrivate;
38/**
39 * KArchive is a base class for reading and writing archives.
40 * @short generic class for reading/writing archives
41 * @author David Faure <faure@kde.org>
42 */
43class KDECORE_EXPORT KArchive
44{
45protected:
46 /**
47 * Base constructor (protected since this is a pure virtual class).
48 * @param fileName is a local path (e.g. "/tmp/myfile.ext"),
49 * from which the archive will be read from, or into which the archive
50 * will be written, depending on the mode given to open().
51 */
52 KArchive( const QString& fileName );
53
54 /**
55 * Base constructor (protected since this is a pure virtual class).
56 * @param dev the I/O device where the archive reads its data
57 * Note that this can be a file, but also a data buffer, a compression filter, etc.
58 * For a file in writing mode it is better to use the other constructor
59 * though, to benefit from the use of KSaveFile when saving.
60 */
61 KArchive( QIODevice * dev );
62
63public:
64 virtual ~KArchive();
65
66 /**
67 * Opens the archive for reading or writing.
68 * Inherited classes might want to reimplement openArchive instead.
69 * @param mode may be QIODevice::ReadOnly or QIODevice::WriteOnly
70 * @see close
71 */
72 virtual bool open( QIODevice::OpenMode mode );
73
74 /**
75 * Closes the archive.
76 * Inherited classes might want to reimplement closeArchive instead.
77 *
78 * @return true if close succeeded without problems
79 * @see open
80 */
81 virtual bool close();
82
83 /**
84 * Checks whether the archive is open.
85 * @return true if the archive is opened
86 */
87 bool isOpen() const;
88
89 /**
90 * Returns the mode in which the archive was opened
91 * @return the mode in which the archive was opened (QIODevice::ReadOnly or QIODevice::WriteOnly)
92 * @see open()
93 */
94 QIODevice::OpenMode mode() const;
95
96 /**
97 * The underlying device.
98 * @return the underlying device.
99 */
100 QIODevice * device() const;
101
102 /**
103 * The name of the archive file, as passed to the constructor that takes a
104 * fileName, or an empty string if you used the QIODevice constructor.
105 * @return the name of the file, or QString() if unknown
106 */
107 QString fileName() const;
108
109 /**
110 * If an archive is opened for reading, then the contents
111 * of the archive can be accessed via this function.
112 * @return the directory of the archive
113 */
114 const KArchiveDirectory* directory() const;
115
116 /**
117 * Writes a local file into the archive. The main difference with writeFile,
118 * is that this method minimizes memory usage, by not loading the whole file
119 * into memory in one go.
120 *
121 * If @p fileName is a symbolic link, it will be written as is, i. e.
122 * it will not be resolved before.
123 * @param fileName full path to an existing local file, to be added to the archive.
124 * @param destName the resulting name (or relative path) of the file in the archive.
125 */
126 bool addLocalFile( const QString& fileName, const QString& destName );
127
128 /**
129 * Writes a local directory into the archive, including all its contents, recursively.
130 * Calls addLocalFile for each file to be added.
131 *
132 * Since KDE 3.2 it will also add a @p path that is a symbolic link to a
133 * directory. The symbolic link will be dereferenced and the content of the
134 * directory it is pointing to added recursively. However, symbolic links
135 * *under* @p path will be stored as is.
136 * @param path full path to an existing local directory, to be added to the archive.
137 * @param destName the resulting name (or relative path) of the file in the archive.
138 */
139 bool addLocalDirectory( const QString& path, const QString& destName );
140
141 enum { UnknownTime = static_cast<time_t>( -1 ) };
142
143 /**
144 * If an archive is opened for writing then you can add new directories
145 * using this function. KArchive won't write one directory twice.
146 *
147 * This method also allows some file metadata to be set.
148 * However, depending on the archive type not all metadata might be regarded.
149 *
150 * @param name the name of the directory
151 * @param user the user that owns the directory
152 * @param group the group that owns the directory
153 * @param perm permissions of the directory
154 * @param atime time the file was last accessed
155 * @param mtime modification time of the file
156 * @param ctime time of last status change
157 */
158 virtual bool writeDir( const QString& name, const QString& user, const QString& group,
159 mode_t perm = 040755, time_t atime = UnknownTime,
160 time_t mtime = UnknownTime, time_t ctime = UnknownTime );
161
162 /**
163 * Writes a symbolic link to the archive if supported.
164 * The archive must be opened for writing.
165 *
166 * @param name name of symbolic link
167 * @param target target of symbolic link
168 * @param user the user that owns the directory
169 * @param group the group that owns the directory
170 * @param perm permissions of the directory
171 * @param atime time the file was last accessed
172 * @param mtime modification time of the file
173 * @param ctime time of last status change
174 */
175 virtual bool writeSymLink(const QString &name, const QString &target,
176 const QString &user, const QString &group,
177 mode_t perm = 0120755, time_t atime = UnknownTime,
178 time_t mtime = UnknownTime, time_t ctime = UnknownTime );
179
180 /**
181 * If an archive is opened for writing then you can add a new file
182 * using this function. If the file name is for example "mydir/test1" then
183 * the directory "mydir" is automatically appended first if that did not
184 * happen yet.
185 *
186 * This method also allows some file metadata to be
187 * set. However, depending on the archive type not all metadata might be
188 * regarded.
189 * @param name the name of the file
190 * @param user the user that owns the file
191 * @param group the group that owns the file
192 * @param data the data to write (@p size bytes)
193 * @param size the size of the file
194 * @param perm permissions of the file
195 * @param atime time the file was last accessed
196 * @param mtime modification time of the file
197 * @param ctime time of last status change
198 */
199 virtual bool writeFile( const QString& name, const QString& user, const QString& group,
200 const char* data, qint64 size,
201 mode_t perm = 0100644, time_t atime = UnknownTime,
202 time_t mtime = UnknownTime, time_t ctime = UnknownTime );
203
204 /**
205 * Here's another way of writing a file into an archive:
206 * Call prepareWriting(), then call writeData()
207 * as many times as wanted then call finishWriting( totalSize ).
208 * For tar.gz files, you need to know the size before hand, it is needed in the header!
209 * For zip files, size isn't used.
210 *
211 * This method also allows some file metadata to be
212 * set. However, depending on the archive type not all metadata might be
213 * regarded.
214 * @param name the name of the file
215 * @param user the user that owns the file
216 * @param group the group that owns the file
217 * @param size the size of the file
218 * @param perm permissions of the file
219 * @param atime time the file was last accessed
220 * @param mtime modification time of the file
221 * @param ctime time of last status change
222 */
223 virtual bool prepareWriting( const QString& name, const QString& user,
224 const QString& group, qint64 size,
225 mode_t perm = 0100644, time_t atime = UnknownTime,
226 time_t mtime = UnknownTime, time_t ctime = UnknownTime );
227
228 /**
229 * Write data into the current file - to be called after calling prepareWriting
230 */
231 virtual bool writeData( const char* data, qint64 size );
232
233 /**
234 * Call finishWriting after writing the data.
235 * @param size the size of the file
236 * @see prepareWriting()
237 */
238 virtual bool finishWriting( qint64 size );
239
240protected:
241 /**
242 * Opens an archive for reading or writing.
243 * Called by open.
244 * @param mode may be QIODevice::ReadOnly or QIODevice::WriteOnly
245 */
246 virtual bool openArchive( QIODevice::OpenMode mode ) = 0;
247
248 /**
249 * Closes the archive.
250 * Called by close.
251 */
252 virtual bool closeArchive() = 0;
253
254 /**
255 * Retrieves or create the root directory.
256 * The default implementation assumes that openArchive() did the parsing,
257 * so it creates a dummy rootdir if none was set (write mode, or no '/' in the archive).
258 * Reimplement this to provide parsing/listing on demand.
259 * @return the root directory
260 */
261 virtual KArchiveDirectory* rootDir();
262
263 /**
264 * Write a directory to the archive.
265 * This virtual method must be implemented by subclasses.
266 *
267 * Depending on the archive type not all metadata might be used.
268 *
269 * @param name the name of the directory
270 * @param user the user that owns the directory
271 * @param group the group that owns the directory
272 * @param perm permissions of the directory. Use 040755 if you don't have any other information.
273 * @param atime time the file was last accessed
274 * @param mtime modification time of the file
275 * @param ctime time of last status change
276 * @see writeDir
277 */
278 virtual bool doWriteDir( const QString& name, const QString& user, const QString& group,
279 mode_t perm, time_t atime, time_t mtime, time_t ctime ) = 0;
280
281 /**
282 * Writes a symbolic link to the archive.
283 * This virtual method must be implemented by subclasses.
284 *
285 * @param name name of symbolic link
286 * @param target target of symbolic link
287 * @param user the user that owns the directory
288 * @param group the group that owns the directory
289 * @param perm permissions of the directory
290 * @param atime time the file was last accessed
291 * @param mtime modification time of the file
292 * @param ctime time of last status change
293 * @see writeSymLink
294 */
295 virtual bool doWriteSymLink(const QString &name, const QString &target,
296 const QString &user, const QString &group,
297 mode_t perm, time_t atime, time_t mtime, time_t ctime) = 0;
298
299 /**
300 * This virtual method must be implemented by subclasses.
301 *
302 * Depending on the archive type not all metadata might be used.
303 *
304 * @param name the name of the file
305 * @param user the user that owns the file
306 * @param group the group that owns the file
307 * @param size the size of the file
308 * @param perm permissions of the file. Use 0100644 if you don't have any more specific permissions to set.
309 * @param atime time the file was last accessed
310 * @param mtime modification time of the file
311 * @param ctime time of last status change
312 * @see prepareWriting
313 */
314 virtual bool doPrepareWriting( const QString& name, const QString& user,
315 const QString& group, qint64 size, mode_t perm,
316 time_t atime, time_t mtime, time_t ctime ) = 0;
317
318 /**
319 * Called after writing the data.
320 * This virtual method must be implemented by subclasses.
321 *
322 * @param size the size of the file
323 * @see finishWriting()
324 */
325 virtual bool doFinishWriting( qint64 size ) = 0;
326
327 /**
328 * Ensures that @p path exists, create otherwise.
329 * This handles e.g. tar files missing directory entries, like mico-2.3.0.tar.gz :)
330 * @param path the path of the directory
331 * @return the directory with the given @p path
332 */
333 KArchiveDirectory * findOrCreate( const QString & path );
334
335 /**
336 * Can be reimplemented in order to change the creation of the device
337 * (when using the fileName constructor). By default this method uses
338 * KSaveFile when saving, and a simple QFile on reading.
339 * This method is called by open().
340 */
341 virtual bool createDevice( QIODevice::OpenMode mode );
342
343 /**
344 * Can be called by derived classes in order to set the underlying device.
345 * Note that KArchive will -not- own the device, it must be deleted by the derived class.
346 */
347 void setDevice( QIODevice *dev );
348
349 /**
350 * Derived classes call setRootDir from openArchive,
351 * to set the root directory after parsing an existing archive.
352 */
353 void setRootDir( KArchiveDirectory *rootDir );
354
355protected:
356 virtual void virtual_hook( int id, void* data );
357private:
358 KArchivePrivate* const d;
359};
360
361class KArchiveEntryPrivate;
362/**
363 * A base class for entries in an KArchive.
364 * @short Base class for the archive-file's directory structure.
365 *
366 * @see KArchiveFile
367 * @see KArchiveDirectory
368 */
369class KDECORE_EXPORT KArchiveEntry
370{
371public:
372 /**
373 * Creates a new entry.
374 * @param archive the entries archive
375 * @param name the name of the entry
376 * @param access the permissions in unix format
377 * @param date the date (in seconds since 1970)
378 * @param user the user that owns the entry
379 * @param group the group that owns the entry
380 * @param symlink the symlink, or QString()
381 */
382 KArchiveEntry( KArchive* archive, const QString& name, int access, int date,
383 const QString& user, const QString& group,
384 const QString& symlink );
385
386 virtual ~KArchiveEntry();
387
388 /**
389 * Creation date of the file.
390 * @return the creation date
391 */
392 QDateTime datetime() const;
393
394 /**
395 * Creation date of the file.
396 * @return the creation date in seconds since 1970
397 */
398 int date() const;
399
400 /**
401 * Name of the file without path.
402 * @return the file name without path
403 */
404 QString name() const;
405 /**
406 * The permissions and mode flags as returned by the stat() function
407 * in st_mode.
408 * @return the permissions
409 */
410 mode_t permissions() const;
411 /**
412 * User who created the file.
413 * @return the owner of the file
414 */
415 QString user() const;
416 /**
417 * Group of the user who created the file.
418 * @return the group of the file
419 */
420 QString group() const;
421
422 /**
423 * Symlink if there is one.
424 * @return the symlink, or QString()
425 */
426 QString symLinkTarget() const;
427
428 /**
429 * Checks whether the entry is a file.
430 * @return true if this entry is a file
431 */
432 virtual bool isFile() const;
433
434 /**
435 * Checks whether the entry is a directory.
436 * @return true if this entry is a directory
437 */
438 virtual bool isDirectory() const;
439
440protected:
441 KArchive* archive() const;
442
443protected:
444 virtual void virtual_hook( int id, void* data );
445private:
446 KArchiveEntryPrivate* const d;
447};
448
449class KArchiveFilePrivate;
450/**
451 * Represents a file entry in a KArchive.
452 * @short A file in an archive.
453 *
454 * @see KArchive
455 * @see KArchiveDirectory
456 */
457class KDECORE_EXPORT KArchiveFile : public KArchiveEntry
458{
459public:
460 /**
461 * Creates a new file entry. Do not call this, KArchive takes care of it.
462 * @param archive the entries archive
463 * @param name the name of the entry
464 * @param access the permissions in unix format
465 * @param date the date (in seconds since 1970)
466 * @param user the user that owns the entry
467 * @param group the group that owns the entry
468 * @param symlink the symlink, or QString()
469 * @param pos the position of the file in the directory
470 * @param size the size of the file
471 */
472 KArchiveFile( KArchive* archive, const QString& name, int access, int date,
473 const QString& user, const QString& group, const QString &symlink,
474 qint64 pos, qint64 size );
475
476 /**
477 * Destructor. Do not call this, KArchive takes care of it.
478 */
479 virtual ~KArchiveFile();
480
481 /**
482 * Position of the data in the [uncompressed] archive.
483 * @return the position of the file
484 */
485 qint64 position() const;
486 /**
487 * Size of the data.
488 * @return the size of the file
489 */
490 qint64 size() const;
491 /**
492 * Set size of data, usually after writing the file.
493 * @param s the new size of the file
494 */
495 void setSize( qint64 s );
496
497 /**
498 * Returns the data of the file.
499 * Call data() with care (only once per file), this data isn't cached.
500 * @return the content of this file.
501 */
502 virtual QByteArray data() const;
503
504 /**
505 * This method returns QIODevice (internal class: KLimitedIODevice)
506 * on top of the underlying QIODevice. This is obviously for reading only.
507 *
508 * WARNING: Note that the ownership of the device is being transferred to the caller,
509 * who will have to delete it.
510 *
511 * The returned device auto-opens (in readonly mode), no need to open it.
512 * @return the QIODevice of the file
513 */
514 virtual QIODevice *createDevice() const;
515
516 /**
517 * Checks whether this entry is a file.
518 * @return true, since this entry is a file
519 */
520 virtual bool isFile() const;
521
522 /**
523 * Extracts the file to the directory @p dest
524 * @param dest the directory to extract to
525 */
526 void copyTo(const QString& dest) const;
527
528protected:
529 virtual void virtual_hook( int id, void* data );
530private:
531 KArchiveFilePrivate* const d;
532};
533
534class KArchiveDirectoryPrivate;
535/**
536 * Represents a directory entry in a KArchive.
537 * @short A directory in an archive.
538 *
539 * @see KArchive
540 * @see KArchiveFile
541 */
542class KDECORE_EXPORT KArchiveDirectory : public KArchiveEntry
543{
544public:
545 /**
546 * Creates a new directory entry.
547 * @param archive the entries archive
548 * @param name the name of the entry
549 * @param access the permissions in unix format
550 * @param date the date (in seconds since 1970)
551 * @param user the user that owns the entry
552 * @param group the group that owns the entry
553 * @param symlink the symlink, or QString()
554 */
555 KArchiveDirectory( KArchive* archive, const QString& name, int access, int date,
556 const QString& user, const QString& group,
557 const QString& symlink);
558
559 virtual ~KArchiveDirectory();
560
561 /**
562 * Returns a list of sub-entries.
563 * Note that the list is not sorted, it's even in random order (due to using a hashtable).
564 * Use sort() on the result to sort the list by filename.
565 *
566 * @return the names of all entries in this directory (filenames, no path).
567 */
568 QStringList entries() const;
569 /**
570 * Returns the entry with the given name.
571 * @param name may be "test1", "mydir/test3", "mydir/mysubdir/test3", etc.
572 * @return a pointer to the entry in the directory.
573 */
574 const KArchiveEntry* entry( const QString& name ) const;
575
576 /**
577 * @internal
578 * Adds a new entry to the directory.
579 */
580 void addEntry( KArchiveEntry* );
581
582 /**
583 * @internal
584 * Adds a new entry to the directory.
585 */
586 void removeEntry( KArchiveEntry* );
587
588 /**
589 * Checks whether this entry is a directory.
590 * @return true, since this entry is a directory
591 */
592 virtual bool isDirectory() const;
593
594 /**
595 * Extracts all entries in this archive directory to the directory
596 * @p dest.
597 * @param dest the directory to extract to
598 * @param recursive if set to true, subdirectories are extracted as well
599 */
600 void copyTo(const QString& dest, bool recursive = true) const;
601
602protected:
603 virtual void virtual_hook( int id, void* data );
604private:
605 KArchiveDirectoryPrivate* const d;
606};
607
608#endif
609