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 | |
34 | class KArchiveDirectory; |
35 | class KArchiveFile; |
36 | |
37 | class 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 | */ |
43 | class KDECORE_EXPORT KArchive |
44 | { |
45 | protected: |
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 | |
63 | public: |
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 | |
240 | protected: |
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 | |
355 | protected: |
356 | virtual void virtual_hook( int id, void* data ); |
357 | private: |
358 | KArchivePrivate* const d; |
359 | }; |
360 | |
361 | class 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 | */ |
369 | class KDECORE_EXPORT KArchiveEntry |
370 | { |
371 | public: |
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 | |
440 | protected: |
441 | KArchive* archive() const; |
442 | |
443 | protected: |
444 | virtual void virtual_hook( int id, void* data ); |
445 | private: |
446 | KArchiveEntryPrivate* const d; |
447 | }; |
448 | |
449 | class 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 | */ |
457 | class KDECORE_EXPORT KArchiveFile : public KArchiveEntry |
458 | { |
459 | public: |
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 | |
528 | protected: |
529 | virtual void virtual_hook( int id, void* data ); |
530 | private: |
531 | KArchiveFilePrivate* const d; |
532 | }; |
533 | |
534 | class 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 | */ |
542 | class KDECORE_EXPORT KArchiveDirectory : public KArchiveEntry |
543 | { |
544 | public: |
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 | |
602 | protected: |
603 | virtual void virtual_hook( int id, void* data ); |
604 | private: |
605 | KArchiveDirectoryPrivate* const d; |
606 | }; |
607 | |
608 | #endif |
609 | |