karchive.cpp   karchive.cpp 
skipping to change at line 45 skipping to change at line 45
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
#include <assert.h> #include <assert.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#ifdef Q_OS_UNIX #ifdef Q_OS_UNIX
#include <limits.h> // PATH_MAX #include <limits.h> // PATH_MAX
#endif #endif
#ifndef WIN32 #ifndef Q_OS_WIN
#include <grp.h> #include <grp.h>
#include <pwd.h> #include <pwd.h>
#else #else
#include "kdewin32/grp.h" #include "kdewin32/grp.h"
#include "kdewin32/pwd.h" #include "kdewin32/pwd.h"
#include "kdewin32/unistd.h" #include "kdewin32/unistd.h"
#endif #endif
class KArchivePrivate class KArchivePrivate
{ {
public: public:
KArchivePrivate() KArchivePrivate()
: rootDir( 0 ), : rootDir( 0 ),
// saveFile( 0 ), // saveFile( 0 ),
dev ( 0 ), dev ( 0 ),
fileName(), fileName(),
mode( QIODevice::NotOpen ), mode( QIODevice::NotOpen ),
deviceOwned( false ) deviceOwned( false )
{} {}
~KArchivePrivate() ~KArchivePrivate()
{ {
// delete saveFile; // delete saveFile;
delete rootDir; delete rootDir;
} }
void abortWriting(); void abortWriting();
KArchiveDirectory* rootDir; KArchiveDirectory* rootDir;
// KSaveFile* saveFile; // KSaveFile* saveFile;
QIODevice * dev; QIODevice * dev;
QString fileName; QString fileName;
QIODevice::OpenMode mode; QIODevice::OpenMode mode;
bool deviceOwned; // if true, we (KArchive) own dev and must delete it bool deviceOwned; // if true, we (KArchive) own dev and must delete
it
}; };
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
/////////////////////////// KArchive /////////////////////////////////// /////////////////////////// KArchive ///////////////////////////////////
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
KArchive::KArchive( const QString& fileName ) KArchive::KArchive( const QString& fileName )
: d(new KArchivePrivate) : d(new KArchivePrivate)
{ {
Q_ASSERT( !fileName.isEmpty() ); Q_ASSERT( !fileName.isEmpty() );
d->fileName = fileName; d->fileName = fileName;
// This constructor leaves the device set to 0. // This constructor leaves the device set to 0.
// This is for the use of KSaveFile, see open(). // This is for the use of KSaveFile, see open().
} }
KArchive::KArchive( QIODevice * dev ) KArchive::KArchive( QIODevice * dev )
: d(new KArchivePrivate) : d(new KArchivePrivate)
{ {
d->dev = dev; d->dev = dev;
} }
KArchive::~KArchive() KArchive::~KArchive()
{ {
if ( isOpen() ) if ( isOpen() )
close(); // WARNING: won't call the virtual method close in the der close(); // WARNING: won't call the virtual method close in
ived class!!! the derived class!!!
delete d; delete d;
} }
bool KArchive::open( QIODevice::OpenMode mode ) bool KArchive::open( QIODevice::OpenMode mode )
{ {
Q_ASSERT( mode != QIODevice::NotOpen ); Q_ASSERT( mode != QIODevice::NotOpen );
if ( isOpen() ) if ( isOpen() )
close(); close();
if ( !d->fileName.isEmpty() ) if ( !d->fileName.isEmpty() )
{ {
Q_ASSERT( !d->dev ); Q_ASSERT( !d->dev );
if ( !createDevice( mode ) ) if ( !createDevice( mode ) )
return false; return false;
} }
Q_ASSERT( d->dev ); Q_ASSERT( d->dev );
if ( !d->dev->isOpen() && !d->dev->open( mode ) ) if ( !d->dev->isOpen() && !d->dev->open( mode ) )
return false; return false;
d->mode = mode; d->mode = mode;
Q_ASSERT( !d->rootDir ); Q_ASSERT( !d->rootDir );
d->rootDir = 0; d->rootDir = 0;
return openArchive( mode ); return openArchive( mode );
} }
bool KArchive::createDevice( QIODevice::OpenMode mode ) bool KArchive::createDevice( QIODevice::OpenMode mode )
{ {
switch( mode ) { switch( mode ) {
case QIODevice::WriteOnly: case QIODevice::WriteOnly:
// if ( !d->fileName.isEmpty() ) { // if ( !d->fileName.isEmpty() ) {
// // The use of KSaveFile can't be done in the ctor (no mode k nown yet) // // The use of KSaveFile can't be done in the ctor (no mode k nown yet)
// //qDebug() << "Writing to a file using KSaveFile"; // //qDebug() << "Writing to a file using KSaveFile";
// d->saveFile = new KSaveFile( d->fileName ); // d->saveFile = new KSaveFile( d->fileName );
// if ( !d->saveFile->open() ) { // if ( !d->saveFile->open() ) {
// qWarning() << "KSaveFile creation for " << d->fileName < < " failed, " << d->saveFile->errorString(); // qWarning() << "KSaveFile creation for " << d->fileName < < " failed, " << d->saveFile->errorString();
// delete d->saveFile; // delete d->saveFile;
// d->saveFile = 0; // d->saveFile = 0;
// return false; // return false;
// } // }
// d->dev = d->saveFile; // d->dev = d->saveFile;
// Q_ASSERT( d->dev ); // Q_ASSERT( d->dev );
// } // }
Q_ASSERT(0); // Unsupported for Stellarium Q_ASSERT(0); // Unsupported for Stellarium
break; break;
case QIODevice::ReadOnly: case QIODevice::ReadOnly:
case QIODevice::ReadWrite: case QIODevice::ReadWrite:
// ReadWrite mode still uses QFile for now; we'd need to copy to th // ReadWrite mode still uses QFile for now; we'd need to cop
e tempfile, in fact. y to the tempfile, in fact.
if ( !d->fileName.isEmpty() ) { if ( !d->fileName.isEmpty() ) {
d->dev = new QFile( d->fileName ); d->dev = new QFile( d->fileName );
d->deviceOwned = true; d->deviceOwned = true;
} }
break; // continued below break; // continued below
default: default:
qWarning() << "Unsupported mode " << d->mode; qWarning() << "Unsupported mode " << d->mode;
return false; return false;
} }
return true; return true;
} }
bool KArchive::close() bool KArchive::close()
{ {
if ( !isOpen() ) if ( !isOpen() )
return false; // already closed (return false or true? arguable...) return false; // already closed (return false or true? argua
ble...)
// moved by holger to allow kzip to write the zip central dir // moved by holger to allow kzip to write the zip central dir
// to the file in closeArchive() // to the file in closeArchive()
// DF: added d->dev so that we skip closeArchive if saving aborted. // DF: added d->dev so that we skip closeArchive if saving aborted.
bool closeSucceeded = true; bool closeSucceeded = true;
if ( d->dev ) { if ( d->dev ) {
closeSucceeded = closeArchive(); closeSucceeded = closeArchive();
if ( d->mode == QIODevice::WriteOnly && !closeSucceeded ) if ( d->mode == QIODevice::WriteOnly && !closeSucceeded )
d->abortWriting(); d->abortWriting();
} }
if ( d->dev ) if ( d->dev )
d->dev->close(); d->dev->close();
if ( d->deviceOwned ) { if ( d->deviceOwned ) {
delete d->dev; // we created it ourselves in open() delete d->dev; // we created it ourselves in open()
} }
// Disabled for Stellarium // Disabled for Stellarium
// if ( d->saveFile ) { // if ( d->saveFile ) {
// closeSucceeded = d->saveFile->finalize(); // closeSucceeded = d->saveFile->finalize();
// delete d->saveFile; // delete d->saveFile;
// d->saveFile = 0; // d->saveFile = 0;
// } // }
delete d->rootDir; delete d->rootDir;
d->rootDir = 0; d->rootDir = 0;
d->mode = QIODevice::NotOpen; d->mode = QIODevice::NotOpen;
d->dev = 0; d->dev = 0;
return closeSucceeded; return closeSucceeded;
} }
const KArchiveDirectory* KArchive::directory() const const KArchiveDirectory* KArchive::directory() const
{ {
// rootDir isn't const so that parsing-on-demand is possible // rootDir isn't const so that parsing-on-demand is possible
return const_cast<KArchive *>(this)->rootDir(); return const_cast<KArchive *>(this)->rootDir();
} }
bool KArchive::addLocalFile( const QString& fileName, const QString& destNa me ) bool KArchive::addLocalFile( const QString& fileName, const QString& destNa me )
{ {
Q_ASSERT(0); // Disabled for Stellarium Q_ASSERT(0); // Disabled for Stellarium
return true; return true;
// QFileInfo fileInfo( fileName ); // QFileInfo fileInfo( fileName );
// if ( !fileInfo.isFile() && !fileInfo.isSymLink() ) // if ( !fileInfo.isFile() && !fileInfo.isSymLink() )
// { // {
// qWarning() << fileName << "doesn't exist or is not a regular fil e."; // qWarning() << fileName << "doesn't exist or is not a regular fil e.";
skipping to change at line 292 skipping to change at line 292
// if ( !finishWriting( size ) ) // if ( !finishWriting( size ) )
// { // {
// qWarning() << "finishWriting failed"; // qWarning() << "finishWriting failed";
// return false; // return false;
// } // }
// return true; // return true;
} }
bool KArchive::addLocalDirectory( const QString& path, const QString& destN ame ) bool KArchive::addLocalDirectory( const QString& path, const QString& destN ame )
{ {
QDir dir( path ); QDir dir( path );
if ( !dir.exists() ) if ( !dir.exists() )
return false; return false;
dir.setFilter(dir.filter() | QDir::Hidden); dir.setFilter(dir.filter() | QDir::Hidden);
const QStringList files = dir.entryList(); const QStringList files = dir.entryList();
for ( QStringList::ConstIterator it = files.begin(); it != files.end(); for ( QStringList::ConstIterator it = files.begin(); it != files.end
++it ) (); ++it )
{ {
if ( *it != "." && *it != ".." ) if ( *it != "." && *it != ".." )
{ {
QString fileName = path + '/' + *it; QString fileName = path + '/' + *it;
// qDebug() << "storing " << fileName; // qDebug() << "storing " << fileName;
QString dest = destName.isEmpty() ? *it : (destName + '/' + *it QString dest = destName.isEmpty() ? *it : (destName
); + '/' + *it);
QFileInfo fileInfo( fileName ); QFileInfo fileInfo( fileName );
if ( fileInfo.isFile() || fileInfo.isSymLink() ) if ( fileInfo.isFile() || fileInfo.isSymLink() )
addLocalFile( fileName, dest ); addLocalFile( fileName, dest );
else if ( fileInfo.isDir() ) else if ( fileInfo.isDir() )
addLocalDirectory( fileName, dest ); addLocalDirectory( fileName, dest );
// We omit sockets // We omit sockets
} }
} }
return true; return true;
} }
bool KArchive::writeFile( const QString& name, const QString& user, bool KArchive::writeFile( const QString& name, const QString& user,
const QString& group, const char* data, qint64 si const QString& group, cons
ze, t char* data, qint64 size,
mode_t perm, time_t atime, time_t mtime, time_t c mode_t perm, time_t atime,
time ) time_t mtime, time_t ctime )
{ {
if ( !prepareWriting( name, user, group, size, perm, atime, mtime, ctim if ( !prepareWriting( name, user, group, size, perm, atime, mtime, c
e ) ) time ) )
{ {
qWarning() << "prepareWriting failed"; qWarning() << "prepareWriting failed";
return false; return false;
} }
// Write data // Write data
// Note: if data is 0L, don't call write, it would terminate the KFilte // Note: if data is 0L, don't call write, it would terminate the KFi
rDev lterDev
if ( data && size && !writeData( data, size ) ) if ( data && size && !writeData( data, size ) )
{ {
qWarning() << "writeData failed"; qWarning() << "writeData failed";
return false; return false;
} }
if ( !finishWriting( size ) ) if ( !finishWriting( size ) )
{ {
qWarning() << "finishWriting failed"; qWarning() << "finishWriting failed";
return false; return false;
} }
return true; return true;
} }
bool KArchive::writeData( const char* data, qint64 size ) bool KArchive::writeData( const char* data, qint64 size )
{ {
bool ok = device()->write( data, size ) == size; bool ok = device()->write( data, size ) == size;
if ( !ok ) if ( !ok )
d->abortWriting(); d->abortWriting();
return ok; return ok;
} }
// The writeDir -> doWriteDir pattern allows to avoid propagating the defau lt // The writeDir -> doWriteDir pattern allows to avoid propagating the defau lt
// values into all virtual methods of subclasses, and it allows more extens ibility: // values into all virtual methods of subclasses, and it allows more extens ibility:
// if a new argument is needed, we can add a writeDir overload which stores the // if a new argument is needed, we can add a writeDir overload which stores the
// additional argument in the d pointer, and doWriteDir reimplementations c an fetch // additional argument in the d pointer, and doWriteDir reimplementations c an fetch
// it from there. // it from there.
bool KArchive::writeDir( const QString& name, const QString& user, const QS tring& group, bool KArchive::writeDir( const QString& name, const QString& user, const QS tring& group,
mode_t perm, time_t atime, mode_t perm, time_t atime,
time_t mtime, time_t ctime ) time_t mtime, time_t ctime
)
{ {
return doWriteDir( name, user, group, perm, atime, mtime, ctime ); return doWriteDir( name, user, group, perm, atime, mtime, ctime );
} }
bool KArchive::writeSymLink(const QString &name, const QString &target, bool KArchive::writeSymLink(const QString &name, const QString &target,
const QString &user, const QString &group, const QString &user,
mode_t perm, time_t atime, const QString &group,
time_t mtime, time_t ctime ) mode_t perm, time_t
atime,
time_t mtime, time_t
ctime )
{ {
return doWriteSymLink( name, target, user, group, perm, atime, mtime, c time ); return doWriteSymLink( name, target, user, group, perm, atime, mtime , ctime );
} }
bool KArchive::prepareWriting( const QString& name, const QString& user, bool KArchive::prepareWriting( const QString& name, const QString& user,
const QString& group, qint64 size, const QString& gr
mode_t perm, time_t atime, oup, qint64 size,
time_t mtime, time_t ctime ) mode_t perm, time
{ _t atime,
bool ok = doPrepareWriting( name, user, group, size, perm, atime, mtime time_t mtime, tim
, ctime ); e_t ctime )
if ( !ok ) {
d->abortWriting(); bool ok = doPrepareWriting( name, user, group, size, perm, atime, mt
return ok; ime, ctime );
if ( !ok )
d->abortWriting();
return ok;
} }
bool KArchive::finishWriting( qint64 size ) bool KArchive::finishWriting( qint64 size )
{ {
return doFinishWriting( size ); return doFinishWriting( size );
} }
KArchiveDirectory * KArchive::rootDir() KArchiveDirectory * KArchive::rootDir()
{ {
if ( !d->rootDir ) if ( !d->rootDir )
{ {
//qDebug() << "Making root dir "; //qDebug() << "Making root dir ";
struct passwd* pw = getpwuid( getuid() ); struct passwd* pw = getpwuid( getuid() );
struct group* grp = getgrgid( getgid() ); struct group* grp = getgrgid( getgid() );
QString username = pw ? QFile::decodeName(pw->pw_name) : QString::n QString username = pw ? QFile::decodeName(pw->pw_name) : QSt
umber( getuid() ); ring::number( getuid() );
QString groupname = grp ? QFile::decodeName(grp->gr_name) : QString QString groupname = grp ? QFile::decodeName(grp->gr_name) :
::number( getgid() ); QString::number( getgid() );
d->rootDir = new KArchiveDirectory( this, QLatin1String("/"), (int) d->rootDir = new KArchiveDirectory( this, QLatin1String("/")
(0777 + S_IFDIR), 0, username, groupname, QString() ); , (int)(0777 + S_IFDIR), 0, username, groupname, QString() );
} }
return d->rootDir; return d->rootDir;
} }
KArchiveDirectory * KArchive::findOrCreate( const QString & path ) KArchiveDirectory * KArchive::findOrCreate( const QString & path )
{ {
//qDebug() << path; //qDebug() << path;
if ( path.isEmpty() || path == "/" || path == "." ) // root dir => foun if ( path.isEmpty() || path == "/" || path == "." ) // root dir => f
d ound
{ {
//qDebug() << "returning rootdir"; //qDebug() << "returning rootdir";
return rootDir(); return rootDir();
} }
// Important note : for tar files containing absolute paths // Important note : for tar files containing absolute paths
// (i.e. beginning with "/"), this means the leading "/" will // (i.e. beginning with "/"), this means the leading "/" will
// be removed (no KDirectory for it), which is exactly the way // be removed (no KDirectory for it), which is exactly the way
// the "tar" program works (though it displays a warning about it) // the "tar" program works (though it displays a warning about it)
// See also KArchiveDirectory::entry(). // See also KArchiveDirectory::entry().
// Already created ? => found // Already created ? => found
const KArchiveEntry* ent = rootDir()->entry( path ); const KArchiveEntry* ent = rootDir()->entry( path );
if ( ent ) if ( ent )
{ {
if ( ent->isDirectory() ) if ( ent->isDirectory() )
//qDebug() << "found it"; //qDebug() << "found it";
return (KArchiveDirectory *) ent; return (KArchiveDirectory *) ent;
else else
qWarning() << "Found" << path << "but it's not a directory"; qWarning() << "Found" << path << "but it's not a dir
} ectory";
}
// Otherwise go up and try again
int pos = path.lastIndexOf( '/' ); // Otherwise go up and try again
KArchiveDirectory * parent; int pos = path.lastIndexOf( '/' );
QString dirname; KArchiveDirectory * parent;
if ( pos == -1 ) // no more slash => create in root dir QString dirname;
{ if ( pos == -1 ) // no more slash => create in root dir
parent = rootDir(); {
dirname = path; parent = rootDir();
} dirname = path;
else }
{ else
QString left = path.left( pos ); {
dirname = path.mid( pos + 1 ); QString left = path.left( pos );
parent = findOrCreate( left ); // recursive call... until we find a dirname = path.mid( pos + 1 );
n existing dir. parent = findOrCreate( left ); // recursive call... until we
} find an existing dir.
}
//qDebug() << "found parent " << parent->name() << " adding " << dirnam
e << " to ensure " << path; //qDebug() << "found parent " << parent->name() << " adding " << dir
// Found -> add the missing piece name << " to ensure " << path;
KArchiveDirectory * e = new KArchiveDirectory( this, dirname, d->rootDi // Found -> add the missing piece
r->permissions(), KArchiveDirectory * e = new KArchiveDirectory( this, dirname, d->roo
d->rootDir->date(), d->r tDir->permissions(),
ootDir->user(),
d->rootDir->group(), QSt d->rootDir->date(), d->rootDir->user(),
ring() );
parent->addEntry( e ); d->rootDir->group(), QString() );
return e; // now a directory to <path> exists parent->addEntry( e );
return e; // now a directory to <path> exists
} }
void KArchive::setDevice( QIODevice * dev ) void KArchive::setDevice( QIODevice * dev )
{ {
if ( d->deviceOwned ) if ( d->deviceOwned )
delete d->dev; delete d->dev;
d->dev = dev; d->dev = dev;
d->deviceOwned = false; d->deviceOwned = false;
} }
void KArchive::setRootDir( KArchiveDirectory *rootDir ) void KArchive::setRootDir( KArchiveDirectory *rootDir )
{ {
Q_ASSERT( !d->rootDir ); // Call setRootDir only once during parsing pl Q_ASSERT( !d->rootDir ); // Call setRootDir only once during parsing
ease ;) please ;)
d->rootDir = rootDir; d->rootDir = rootDir;
} }
QIODevice::OpenMode KArchive::mode() const QIODevice::OpenMode KArchive::mode() const
{ {
return d->mode; return d->mode;
} }
QIODevice * KArchive::device() const QIODevice * KArchive::device() const
{ {
return d->dev; return d->dev;
} }
bool KArchive::isOpen() const bool KArchive::isOpen() const
{ {
return d->mode != QIODevice::NotOpen; return d->mode != QIODevice::NotOpen;
} }
QString KArchive::fileName() const QString KArchive::fileName() const
{ {
return d->fileName; return d->fileName;
} }
void KArchivePrivate::abortWriting() void KArchivePrivate::abortWriting()
{ {
// Disabled for Stellarium // Disabled for Stellarium
// if ( saveFile ) { // if ( saveFile ) {
// saveFile->abort(); // saveFile->abort();
// delete saveFile; // delete saveFile;
// saveFile = 0; // saveFile = 0;
// dev = 0; // dev = 0;
// } // }
} }
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
/////////////////////// KArchiveEntry ////////////////////////////////// /////////////////////// KArchiveEntry //////////////////////////////////
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
class KArchiveEntryPrivate class KArchiveEntryPrivate
{ {
public: public:
KArchiveEntryPrivate( KArchive* _archive, const QString& _name, int _ac KArchiveEntryPrivate( KArchive* _archive, const QString& _name, int
cess, _access,
int _date, const QString& _user, const QString& _ int _date, const QString&
group, _user, const QString& _group,
const QString& _symlink) : const QString& _symlink) :
name(_name), name(_name),
date(_date), date(_date),
access(_access), access(_access),
user(_user), user(_user),
group(_group), group(_group),
symlink(_symlink), symlink(_symlink),
archive(_archive) archive(_archive)
{} {}
QString name; QString name;
int date; int date;
mode_t access; mode_t access;
QString user; QString user;
QString group; QString group;
QString symlink; QString symlink;
KArchive* archive; KArchive* archive;
}; };
KArchiveEntry::KArchiveEntry( KArchive* t, const QString& name, int access, int date, KArchiveEntry::KArchiveEntry( KArchive* t, const QString& name, int access, int date,
const QString& user, const QString& group, const const QString& user, const QString
QString& symlink) : & group, const
d(new KArchiveEntryPrivate(t,name,access,date,user,group,symlink)) QString& symlink) :
d(new KArchiveEntryPrivate(t,name,access,date,user,group,symlink))
{ {
} }
KArchiveEntry::~KArchiveEntry() KArchiveEntry::~KArchiveEntry()
{ {
delete d; delete d;
} }
QDateTime KArchiveEntry::datetime() const QDateTime KArchiveEntry::datetime() const
{ {
QDateTime datetimeobj; QDateTime datetimeobj;
datetimeobj.setTime_t( d->date ); datetimeobj.setTime_t( d->date );
return datetimeobj; return datetimeobj;
} }
int KArchiveEntry::date() const int KArchiveEntry::date() const
{ {
return d->date; return d->date;
} }
QString KArchiveEntry::name() const QString KArchiveEntry::name() const
{ {
return d->name; return d->name;
} }
mode_t KArchiveEntry::permissions() const mode_t KArchiveEntry::permissions() const
{ {
return d->access; return d->access;
} }
QString KArchiveEntry::user() const QString KArchiveEntry::user() const
{ {
return d->user; return d->user;
} }
QString KArchiveEntry::group() const QString KArchiveEntry::group() const
{ {
return d->group; return d->group;
} }
QString KArchiveEntry::symLinkTarget() const QString KArchiveEntry::symLinkTarget() const
{ {
return d->symlink; return d->symlink;
} }
bool KArchiveEntry::isFile() const bool KArchiveEntry::isFile() const
{ {
return false; return false;
} }
bool KArchiveEntry::isDirectory() const bool KArchiveEntry::isDirectory() const
{ {
return false; return false;
} }
KArchive* KArchiveEntry::archive() const KArchive* KArchiveEntry::archive() const
{ {
return d->archive; return d->archive;
} }
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
/////////////////////// KArchiveFile /////////////////////////////////// /////////////////////// KArchiveFile ///////////////////////////////////
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
class KArchiveFilePrivate class KArchiveFilePrivate
{ {
public: public:
KArchiveFilePrivate( qint64 _pos, qint64 _size ) : KArchiveFilePrivate( qint64 _pos, qint64 _size ) :
pos(_pos), pos(_pos),
size(_size) size(_size)
{} {}
qint64 pos; qint64 pos;
qint64 size; qint64 size;
}; };
KArchiveFile::KArchiveFile( KArchive* t, const QString& name, int access, i nt date, KArchiveFile::KArchiveFile( KArchive* t, const QString& name, int access, i nt date,
const QString& user, const QString& group, const QString& user,
const QString & symlink, const QString& group,
qint64 pos, qint64 size ) const QString & syml
ink,
qint64 pos, qint64 s
ize )
: KArchiveEntry( t, name, access, date, user, group, symlink ), : KArchiveEntry( t, name, access, date, user, group, symlink ),
d( new KArchiveFilePrivate(pos, size) ) d( new KArchiveFilePrivate(pos, size) )
{ {
} }
KArchiveFile::~KArchiveFile() KArchiveFile::~KArchiveFile()
{ {
delete d; delete d;
} }
qint64 KArchiveFile::position() const qint64 KArchiveFile::position() const
{ {
return d->pos; return d->pos;
} }
qint64 KArchiveFile::size() const qint64 KArchiveFile::size() const
{ {
return d->size; return d->size;
} }
void KArchiveFile::setSize( qint64 s ) void KArchiveFile::setSize( qint64 s )
{ {
d->size = s; d->size = s;
} }
QByteArray KArchiveFile::data() const QByteArray KArchiveFile::data() const
{ {
archive()->device()->seek( d->pos ); archive()->device()->seek( d->pos );
// Read content // Read content
QByteArray arr; QByteArray arr;
if ( d->size ) if ( d->size )
{ {
assert( arr.data() ); assert( arr.data() );
arr = archive()->device()->read( d->size ); arr = archive()->device()->read( d->size );
Q_ASSERT( arr.size() == d->size ); Q_ASSERT( arr.size() == d->size );
} }
return arr; return arr;
} }
QIODevice * KArchiveFile::createDevice() const QIODevice * KArchiveFile::createDevice() const
{ {
return new KLimitedIODevice( archive()->device(), d->pos, d->size ); return new KLimitedIODevice( archive()->device(), d->pos, d->size );
} }
bool KArchiveFile::isFile() const bool KArchiveFile::isFile() const
{ {
return true; return true;
} }
void KArchiveFile::copyTo(const QString& dest) const void KArchiveFile::copyTo(const QString& dest) const
{ {
QFile f( dest + '/' + name() ); QFile f( dest + '/' + name() );
if ( f.open( QIODevice::ReadWrite | QIODevice::Truncate ) ) if ( f.open( QIODevice::ReadWrite | QIODevice::Truncate ) )
{ {
f.write( data() ); f.write( data() );
f.close(); f.close();
} }
} }
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
//////////////////////// KArchiveDirectory //////////////////////////////// / //////////////////////// KArchiveDirectory //////////////////////////////// /
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
class KArchiveDirectoryPrivate class KArchiveDirectoryPrivate
{ {
public: public:
~KArchiveDirectoryPrivate() ~KArchiveDirectoryPrivate()
{ {
qDeleteAll(entries); qDeleteAll(entries);
} }
QHash<QString, KArchiveEntry *> entries; QHash<QString, KArchiveEntry *> entries;
}; };
KArchiveDirectory::KArchiveDirectory( KArchive* t, const QString& name, int access, KArchiveDirectory::KArchiveDirectory( KArchive* t, const QString& name, int access,
int date, int date,
const QString& user, const QString& group, const QString& use
const QString &symlink) r, const QString& group,
const QString &sym
link)
: KArchiveEntry( t, name, access, date, user, group, symlink ), : KArchiveEntry( t, name, access, date, user, group, symlink ),
d( new KArchiveDirectoryPrivate ) d( new KArchiveDirectoryPrivate )
{ {
} }
KArchiveDirectory::~KArchiveDirectory() KArchiveDirectory::~KArchiveDirectory()
{ {
delete d; delete d;
} }
QStringList KArchiveDirectory::entries() const QStringList KArchiveDirectory::entries() const
{ {
return d->entries.keys(); return d->entries.keys();
} }
const KArchiveEntry* KArchiveDirectory::entry( const QString& _name ) const const KArchiveEntry* KArchiveDirectory::entry( const QString& _name ) const
{ {
QString name = _name; QString name = _name;
int pos = name.indexOf( '/' ); int pos = name.indexOf( '/' );
if ( pos == 0 ) // ouch absolute path (see also KArchive::findOrCreate) if ( pos == 0 ) // ouch absolute path (see also KArchive::findOrCreate)
{ {
if (name.length()>1) if (name.length()>1)
{ {
name = name.mid( 1 ); // remove leading slash name = name.mid( 1 ); // remove leading slash
pos = name.indexOf( '/' ); // look again pos = name.indexOf( '/' ); // look again
} }
else // "/" else // "/"
return this; return this;
} }
// trailing slash ? -> remove // trailing slash ? -> remove
if ( pos != -1 && pos == name.length()-1 ) if ( pos != -1 && pos == name.length()-1 )
{ {
name = name.left( pos ); name = name.left( pos );
pos = name.indexOf( '/' ); // look again pos = name.indexOf( '/' ); // look again
} }
if ( pos != -1 ) if ( pos != -1 )
{ {
QString left = name.left( pos ); QString left = name.left( pos );
QString right = name.mid( pos + 1 ); QString right = name.mid( pos + 1 );
//qDebug() << "left=" << left << "right=" << right; //qDebug() << "left=" << left << "right=" << right;
const KArchiveEntry* e = d->entries.value( left ); const KArchiveEntry* e = d->entries.value( left );
if ( !e || !e->isDirectory() ) if ( !e || !e->isDirectory() )
return 0; return 0;
return static_cast<const KArchiveDirectory*>(e)->entry( right ); return static_cast<const KArchiveDirectory*>(e)->entry( right );
} }
return d->entries.value( name ); return d->entries.value( name );
} }
void KArchiveDirectory::addEntry( KArchiveEntry* entry ) void KArchiveDirectory::addEntry( KArchiveEntry* entry )
{ {
Q_ASSERT( !entry->name().isEmpty() ); Q_ASSERT( !entry->name().isEmpty() );
if( d->entries.value( entry->name() ) ) { if( d->entries.value( entry->name() ) ) {
qWarning() << "directory " << name() qWarning() << "directory " << name()
<< "has entry" << entry->name() << "already"; << "has entry" << entry->name() << "alread
y";
} }
d->entries.insert( entry->name(), entry ); d->entries.insert( entry->name(), entry );
} }
bool KArchiveDirectory::isDirectory() const bool KArchiveDirectory::isDirectory() const
{ {
return true; return true;
} }
static int sortByPosition( const KArchiveFile* file1, const KArchiveFile* f ile2 ) { static int sortByPosition( const KArchiveFile* file1, const KArchiveFile* f ile2 ) {
return file1->position() - file2->position(); return file1->position() - file2->position();
} }
void KArchiveDirectory::copyTo(const QString& dest, bool recursiveCopy ) co nst void KArchiveDirectory::copyTo(const QString& dest, bool recursiveCopy ) co nst
{ {
QDir root; QDir root;
QList<const KArchiveFile*> fileList; QList<const KArchiveFile*> fileList;
QMap<qint64, QString> fileToDir; QMap<qint64, QString> fileToDir;
// placeholders for iterated items // placeholders for iterated items
QStack<const KArchiveDirectory *> dirStack; QStack<const KArchiveDirectory *> dirStack;
QStack<QString> dirNameStack; QStack<QString> dirNameStack;
dirStack.push( this ); // init stack at current directory dirStack.push( this ); // init stack at current directory
dirNameStack.push( dest ); // ... with given path dirNameStack.push( dest ); // ... with given path
do { do {
const KArchiveDirectory* curDir = dirStack.pop(); const KArchiveDirectory* curDir = dirStack.pop();
const QString curDirName = dirNameStack.pop(); const QString curDirName = dirNameStack.pop();
root.mkdir(curDirName); root.mkdir(curDirName);
const QStringList dirEntries = curDir->entries(); const QStringList dirEntries = curDir->entries();
for ( QStringList::const_iterator it = dirEntries.begin(); it != dirEnt for ( QStringList::const_iterator it = dirEntries.begin(); it != dir
ries.end(); ++it ) { Entries.end(); ++it ) {
const KArchiveEntry* curEntry = curDir->entry(*it); const KArchiveEntry* curEntry = curDir->entry(*it);
if (!curEntry->symLinkTarget().isEmpty()) { if (!curEntry->symLinkTarget().isEmpty()) {
const QString linkName = curDirName+'/'+curEntry->name(); const QString linkName = curDirName+'/'+curEntry->name();
#ifdef Q_OS_UNIX #ifdef Q_OS_UNIX
if (!::symlink(curEntry->symLinkTarget().toLocal8Bit(), linkName. if (!::symlink(curEntry->symLinkTarget().toLocal8Bit(), li
toLocal8Bit())) { nkName.toLocal8Bit())) {
qDebug() << "symlink(" << curEntry->symLinkTarget() << ',' << qDebug() << "symlink(" << curEntry->symLinkTarget(
linkName << ") failed:" << strerror(errno); ) << ',' << linkName << ") failed:" << strerror(errno);
} }
#else #else
// TODO - how to create symlinks on other platforms? // TODO - how to create symlinks on other platforms?
#endif #endif
} else { } else {
if ( curEntry->isFile() ) { if ( curEntry->isFile() ) {
const KArchiveFile* curFile = dynamic_cast<const KArchiveFile const KArchiveFile* curFile = dynamic_cast<const K
*>( curEntry ); ArchiveFile*>( curEntry );
if (curFile) { if (curFile) {
fileList.append( curFile ); fileList.append( curFile );
fileToDir.insert( curFile->position(), curDirName ); fileToDir.insert( curFile->position(), cur
} DirName );
} }
}
if ( curEntry->isDirectory() && recursiveCopy ) {
const KArchiveDirectory *ad = dynamic_cast<const KArchiveDire if ( curEntry->isDirectory() && recursiveCopy ) {
ctory*>( curEntry ); const KArchiveDirectory *ad = dynamic_cast<const K
if (ad) { ArchiveDirectory*>( curEntry );
dirStack.push( ad ); if (ad) {
dirNameStack.push( curDirName + '/' + curEntry->name() ); dirStack.push( ad );
} dirNameStack.push( curDirName + '/' + curE
} ntry->name() );
} }
} }
}
}
} while (!dirStack.isEmpty()); } while (!dirStack.isEmpty());
qSort( fileList.begin(), fileList.end(), sortByPosition ); // sort on d- >pos, so we have a linear access qSort( fileList.begin(), fileList.end(), sortByPosition ); // sort on d- >pos, so we have a linear access
for ( QList<const KArchiveFile*>::const_iterator it = fileList.constBegin (), end = fileList.constEnd() ; for ( QList<const KArchiveFile*>::const_iterator it = fileList.constBegin (), end = fileList.constEnd() ;
it != end ; ++it ) { it != end ; ++it ) {
const KArchiveFile* f = *it; const KArchiveFile* f = *it;
qint64 pos = f->position(); qint64 pos = f->position();
f->copyTo( fileToDir[pos] ); f->copyTo( fileToDir[pos] );
} }
} }
void KArchive::virtual_hook( int, void* ) void KArchive::virtual_hook( int, void* )
{ /*BASE::virtual_hook( id, data )*/; } { /*BASE::virtual_hook( id, data )*/; }
void KArchiveEntry::virtual_hook( int, void* ) void KArchiveEntry::virtual_hook( int, void* )
{ /*BASE::virtual_hook( id, data );*/ } { /*BASE::virtual_hook( id, data );*/ }
void KArchiveFile::virtual_hook( int id, void* data ) void KArchiveFile::virtual_hook( int id, void* data )
 End of changes. 80 change blocks. 
351 lines changed or deleted 370 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/