kar.cpp
/* This file is part of the KDE libraries
Copyright (C) 2002 Laurence Anderson <l.d.anderson@warwick.ac.uk>
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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include <qfile.h>
#include <qdir.h>
#include <time.h>
#include <kdebug.h>
#include <qptrlist.h>
#include <kmimetype.h>
#include <qregexp.h>
#include "kfilterdev.h"
#include "kar.h"
//#include "klimitediodevice.h"
class KAr::KArPrivate
{
public:
KArPrivate() {}
};
KAr::KAr( const QString& filename )
: KArchive( 0L )
{
//kdDebug(7042) << "KAr(filename) reached." << endl;
m_filename = filename;
d = new KArPrivate;
setDevice( new QFile( filename ) );
}
KAr::KAr( QIODevice * dev )
: KArchive( dev )
{
//kdDebug(7042) << "KAr::KAr( QIODevice * dev) reached." << endl;
d = new KArPrivate;
}
KAr::~KAr()
{
// mjarrett: Closes to prevent ~KArchive from aborting w/o device
//kdDebug(7042) << "~KAr reached." << endl;
if( isOpened() )
close();
if ( !m_filename.isEmpty() )
delete device(); // we created it ourselves
delete d;
}
bool KAr::openArchive( int mode )
{
// Open archive
//kdDebug(7042) << "openarchive reached." << endl;
if ( mode == IO_WriteOnly )
return true;
if ( mode != IO_ReadOnly && mode != IO_ReadWrite )
{
kdWarning(7042) << "Unsupported mode " << mode << endl;
return false;
}
QIODevice* dev = device();
if ( !dev )
return false;
char magic[8];
dev->readBlock (magic, 8);
if (qstrncmp(magic, "!<arch>", 7) != 0) {
kdWarning(7042) << "Invalid main magic" << endl;
return false;
}
char *ar_longnames = 0;
while (! dev->atEnd()) {
QCString ar_header;
ar_header.resize(61);
QCString name;
int date, uid, gid, mode, size;
dev->at( dev->at() + (2 - (dev->at() % 2)) % 2 ); // Ar headers are padded to byte boundary
if ( dev->readBlock (ar_header.data(), 60) != 60 ) { // Read ar header
kdWarning(7042) << "Couldn't read header" << endl;
delete[] ar_longnames;
//return false;
return true; // Probably EOF / trailing junk
}
if (ar_header.right(2) != "`\n") { // Check header magic
kdWarning(7042) << "Invalid magic" << endl;
delete[] ar_longnames;
return false;
}
name = ar_header.mid( 0, 16 ); // Process header
date = ar_header.mid( 16, 12 ).toInt();
uid = ar_header.mid( 28, 6 ).toInt();
gid = ar_header.mid( 34, 6 ).toInt();
mode = ar_header.mid( 40, 8 ).toInt();
size = ar_header.mid( 48, 10 ).toInt();
bool skip_entry = false; // Deal with special entries
if (name.mid(0, 1) == "/") {
if (name.mid(1, 1) == "/") { // Longfilename table entry
delete[] ar_longnames;
ar_longnames = new char[size + 1];
ar_longnames[size] = '\0';
dev->readBlock (ar_longnames, size);
skip_entry = true;
kdDebug(7042) << "Read in longnames entry" << endl;
} else if (name.mid(1, 1) == " ") { // Symbol table entry
kdDebug(7042) << "Skipped symbol entry" << endl;
dev->at( dev->at() + size );
skip_entry = true;
} else { // Longfilename
kdDebug(7042) << "Longfilename #" << name.mid(1, 15).toInt() << endl;
if (! ar_longnames) {
kdWarning(7042) << "Invalid longfilename reference" << endl;
return false;
}
name = &ar_longnames[name.mid(1, 15).toInt()];
name = name.left(name.find("/"));
}
}
if (skip_entry) continue;
name = name.stripWhiteSpace(); // Process filename
name.replace( "/", "" );
kdDebug(7042) << "Filename: " << name << " Size: " << size << endl;
KArchiveEntry* entry;
entry = new KArchiveFile(this, name, mode, date, /*uid*/ 0, /*gid*/ 0, 0, dev->at(), size);
rootDir()->addEntry(entry); // Ar files don't support directorys, so everything in root
dev->at( dev->at() + size ); // Skip contents
}
delete[] ar_longnames;
return true;
}
bool KAr::closeArchive()
{
// Close the archive
return true;
}
void KAr::virtual_hook( int id, void* data )
{ KArchive::virtual_hook( id, data ); }
KAr::closeArchive
virtual bool closeArchive()
Closes the archive.
Definition: kar.cpp:163
KArchive::rootDir
virtual KArchiveDirectory * rootDir()
Retrieves or create the root directory.
Definition: karchive.cpp:368
KArchive::close
virtual void close()
Closes the archive.
Definition: karchive.cpp:108
KArchive
KArchive is a base class for reading and writing archives.
Definition: karchive.h:42
KArchiveEntry
A base class for entries in an KArchive.
Definition: karchive.h:395
KArchive::mode
int mode() const
Returns the mode in which the archive was opened.
Definition: karchive.h:90
KArchive::device
QIODevice * device() const
The underlying device.
Definition: karchive.h:96
KAr::KAr
KAr(const QString &filename)
Creates an instance that operates on the given filename.
Definition: kar.cpp:42
KAr::openArchive
virtual bool openArchive(int mode)
Opens the archive for reading.
Definition: kar.cpp:69
KArchive::isOpened
bool isOpened() const
Checks whether the archive is open.
Definition: karchive.h:83
KArchiveFile
Represents a file entry in a KArchive.
Definition: karchive.h:490
KAr::~KAr
virtual ~KAr()
If the ar file is still opened, then it will be closed automatically by the destructor.
Definition: kar.cpp:58

KDE Home | KDE Accessibility Home | Description of Access Keys