/* This file is part of the KDE libraries
Copyright (C) 2000 David Faure <faure@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef __ktar_h
#define __ktar_h
#include <sys/stat.h>
#include <sys/types.h>
#include <zlib.h>
#include <qdatetime.h>
#include <qstring.h>
#include <qstringlist.h>
#include <qdict.h>
class KTarDirectory;
class KTarFile;
/**
* @short generic class for reading/writing tar archives
* Common functionality for KTarGz and KTarData
* @author David Faure <faure@kde.org>
*/
class KTarBase
{
protected:
KTarBase();
virtual ~KTarBase();
public:
/**
* Opens the tar file/data for reading or writing.
*
* @param mode may be IO_ReadOnly or IO_WriteOnly
*
* @see #close
*/
virtual bool open( int mode );
/**
* Closes the tar file/data.
*
* @see #open
*/
virtual void close();
/**
* @return true if the file is opened
*/
bool isOpened() const { return m_open; }
/**
* If a tar file is opened for writing then you can add new directories
* using this function. KTar won't write one directory twice.
*/
void writeDir( const QString& name, const QString& user, const QString& group );
/**
* If a tar file is opened for writing then you can add a new file
* using this function. If the file name is for example "mydir/test1" then
* the directory "mydir" is automatically appended first if that did not
* happen yet.
*/
void writeFile( const QString& name, const QString& user, const QString& group, uint size, const char* data );
/**
* If a tar file is opened for reading, then the contents
* of the file can be accessed via this function.
*/
const KTarDirectory* directory() const;
protected:
/**
* Read @p len data into @p buffer - reimplemented
* @return length read
*/
virtual int read( char * buffer, int len ) = 0;
/**
* Write @p len data from @p buffer - reimplemented
*/
virtual void write( const char * buffer, int len ) = 0;
/**
* @return the current position - reimplemented
*/
virtual int position() = 0;
/**
* Ensure path exists, create otherwise.
* This handles tar files missing directory entries, like mico-2.3.0.tar.gz :)
* @internal
*/
KTarDirectory * findOrCreate( const QString & path );
/**
* @internal
* Fills @p buffer for writing a file as required by the tar format
* Has to be called LAST, since it does the checksum
* (normally, only the name has to be filled in before)
* @param mode is expected to be 6 chars long, [uname and gname 31].
*/
void fillBuffer( char * buffer, const char * mode, int size, char typeflag, const char * uname, const char * gname );
KTarDirectory* m_dir;
bool m_open;
QStringList m_dirList;
char m_mode;
};
/**
* @short A class for reading/writing gzipped tar balls.
* @author Torben Weis <weis@kde.org>
*/
class KTarGz : public KTarBase
{
public:
/**
* Creates an instance that operates on the given filename.
*
* @param filename has the format "/home/weis/myfile.tgz" or something
* like that.
*
* @see #open
*/
KTarGz( const QString& filename );
/**
* If the tar ball is still opened, then it will be
* closed automatically by the destructor.
*/
virtual ~KTarGz();
/**
* Opens the tar file for reading or writing.
*
* @param mode may be IO_ReadOnly or IO_WriteOnly
*
* @see #close
*/
virtual bool open( int mode );
/**
* Closes the tar file.
*
* @see #open
*/
virtual void close();
/**
* The name of the tar file, as passed to the constructor
*/
QString fileName() { return m_filename; }
private:
/**
* Read @p len data into @p buffer
* @return length read
*/
virtual int read( char * buffer, int len );
/**
* Write @p len data from @p buffer
*/
virtual void write( const char * buffer, int len );
/**
* @return the current position
*/
virtual int position();
gzFile m_f;
QString m_filename;
};
/**
* For compatibility with old naming
* May become the real name again at some point...
*/
#define KTar KTarGz;
/**
* This class operates on a QDataStream, which is assumed to
* be a normal tar archive (not gzipped). This is mainly for use in kio_tar,
* where the encoding/decoding can be done by any filtering protocol (gzip,
* bzip2,...) and the data being given by any protocol (file, ftp, http, ...)
* Using a data stream allows to process a memory buffer (QByteArray) or a file.
*/
class KTarData : public KTarBase
{
public:
/**
* Constructor, probably
*/
KTarData( QDataStream * str );
virtual ~KTarData();
/**
* Opens the tar data for reading or writing.
* @param mode may be IO_ReadOnly or IO_WriteOnly
*/
virtual bool open( int mode );
/**
* For symmetry
*/
virtual void close() {}
private:
/**
* Read @p len data into @p buffer
* @return length read
*/
virtual int read( char * buffer, int len );
/**
* Write @p len data from @p buffer
*/
virtual void write( const char * buffer, int len );
/**
* @return the current position
*/
virtual int position();
QDataStream * m_str;
};
/**
* @short Base class for the tar-file's directory structure.
*
* @see KTarFile
* @see KTarDirectory
*/
class KTarEntry
{
public:
KTarEntry( KTarBase* tar, const QString& name, int access, int date,
const QString& user, const QString& group,
const QString &symlink );
virtual ~KTarEntry() { }
/**
* Creation date of the file.
*/
QDateTime datetime() const;
int date() const { return m_date; }
/**
* Name of the file without path.
*/
QString name() const { return m_name; }
/**
* The permissions and mode flags as returned by the stat() function
* in st_mode.
*/
mode_t permissions() const { return m_access; }
/**
* User who created the file.
*/
QString user() const { return m_user; }
/**
* Group of the user who created the file.
*/
QString group() const { return m_group; }
/**
* Symlink if there is one
*/
QString symlink() const { return m_symlink; }
/**
* @return true if this entry is a file
*/
virtual bool isFile() const { return false; }
/**
* @return true if this entry is a directory
*/
virtual bool isDirectory() const { return false; }
protected:
KTarBase* tar() { return m_tar; }
private:
QString m_name;
int m_date;
mode_t m_access;
QString m_user;
QString m_group;
QString m_symlink;
KTarBase* m_tar;
};
/**
* @short A file in a tar-file's directory structure.
*
* @see KTar
* @see KTarDirectory
*/
class KTarFile : public KTarEntry
{
public:
KTarFile( KTarBase* tar, const QString& name, int access, int date,
const QString& user, const QString& group, const QString &symlink,
int pos, int size, const QByteArray& data );
virtual ~KTarFile() { }
/**
* Position of the data in the uncompressed tar file.
*/
int position() const;
/**
* Size of the data.
*/
int size() const;
/**
* @return the content of this file.
*/
QByteArray data() const;
/**
* @return true, since this entry is a file
*/
virtual bool isFile() const { return true; }
private:
int m_pos;
int m_size;
QByteArray m_data;
};
/**
* @short A directory in a tar-file's directory structure.
*
* @see KTar
* @see KTarFile
*/
class KTarDirectory : public KTarEntry
{
public:
KTarDirectory( KTarBase* tar, const QString& name, int access, int date,
const QString& user, const QString& group,
const QString& symlink);
virtual ~KTarDirectory() { }
/**
* @return the names of all entries in this directory (filenames, no path).
*/
QStringList entries() const;
/**
* @return a pointer to the entry in the directory.
*
* @param name may be "test1", "mydir/test3", "mydir/mysubdir/test3", etc.
*/
KTarEntry* entry( QString name );
const KTarEntry* entry( QString name ) const;
/**
* @internal
* Adds a new entry to the directory.
*/
void addEntry( KTarEntry* );
/**
* @return true, since this entry is a directory
*/
virtual bool isDirectory() const { return true; }
private:
QDict<KTarEntry> m_entries;
};
#endif