KDECore
kar.cpp
Go to the documentation of this file.
00001 00002 /* This file is part of the KDE libraries 00003 Copyright (C) 2002 Laurence Anderson <l.d.anderson@warwick.ac.uk> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License version 2 as published by the Free Software Foundation. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Library General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public License 00015 along with this library; see the file COPYING.LIB. If not, write to 00016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00017 Boston, MA 02110-1301, USA. 00018 */ 00019 00020 #include "kar.h" 00021 00022 #include <QtCore/QFile> 00023 #include <QtCore/QDir> 00024 #include <time.h> 00025 #include <kdebug.h> 00026 #include <kmimetype.h> 00027 #include <QtCore/QRegExp> 00028 00029 #include "kfilterdev.h" 00030 //#include "klimitediodevice_p.h" 00031 00035 00036 class KAr::KArPrivate 00037 { 00038 public: 00039 KArPrivate() {} 00040 }; 00041 00042 KAr::KAr( const QString& filename ) 00043 : KArchive( filename ), d(new KArPrivate) 00044 { 00045 } 00046 00047 KAr::KAr( QIODevice * dev ) 00048 : KArchive( dev ), d(new KArPrivate) 00049 { 00050 } 00051 00052 KAr::~KAr() 00053 { 00054 if( isOpen() ) 00055 close(); 00056 delete d; 00057 } 00058 00059 bool KAr::doPrepareWriting( const QString&, const QString&, const QString&, 00060 qint64, mode_t, time_t, time_t, time_t ) 00061 { 00062 return false; 00063 } 00064 00065 bool KAr::doFinishWriting( qint64 ) 00066 { 00067 return false; 00068 } 00069 00070 bool KAr::doWriteDir( const QString&, const QString&, const QString&, 00071 mode_t, time_t, time_t, time_t ) 00072 { 00073 return false; 00074 } 00075 00076 bool KAr::doWriteSymLink( const QString&, const QString&, const QString&, 00077 const QString&, mode_t, time_t, time_t, time_t ) 00078 { 00079 return false; 00080 } 00081 00082 bool KAr::openArchive( QIODevice::OpenMode mode ) 00083 { 00084 // Open archive 00085 00086 if ( mode == QIODevice::WriteOnly ) 00087 return true; 00088 if ( mode != QIODevice::ReadOnly && mode != QIODevice::ReadWrite ) 00089 { 00090 kWarning(7042) << "Unsupported mode " << mode; 00091 return false; 00092 } 00093 00094 QIODevice* dev = device(); 00095 if ( !dev ) 00096 return false; 00097 00098 QByteArray magic = dev->read( 7 ); 00099 if ( magic != "!<arch>" ) { 00100 kWarning(7042) << "Invalid main magic"; 00101 return false; 00102 } 00103 00104 char *ar_longnames = 0; 00105 while (! dev->atEnd()) { 00106 QByteArray ar_header; 00107 ar_header.resize(61); 00108 QByteArray name; 00109 int date, uid, gid, mode; 00110 qint64 size; 00111 00112 dev->seek( dev->pos() + (2 - (dev->pos() % 2)) % 2 ); // Ar headers are padded to byte boundary 00113 00114 if ( dev->read(ar_header.data(), 60) != 60 ) { // Read ar header 00115 kWarning(7042) << "Couldn't read header"; 00116 delete[] ar_longnames; 00117 //return false; 00118 return true; // Probably EOF / trailing junk 00119 } 00120 00121 if (!ar_header.endsWith("`\n")) { // Check header magic // krazy:exclude=strings 00122 kWarning(7042) << "Invalid magic"; 00123 delete[] ar_longnames; 00124 return false; 00125 } 00126 00127 name = ar_header.mid( 0, 16 ); // Process header 00128 date = ar_header.mid( 16, 12 ).toInt(); 00129 uid = ar_header.mid( 28, 6 ).toInt(); 00130 gid = ar_header.mid( 34, 6 ).toInt(); 00131 mode = ar_header.mid( 40, 8 ).toInt(); 00132 size = ar_header.mid( 48, 10 ).toInt(); 00133 00134 bool skip_entry = false; // Deal with special entries 00135 if (name.mid(0, 1) == "/") { 00136 if (name.mid(1, 1) == "/") { // Longfilename table entry 00137 delete[] ar_longnames; 00138 ar_longnames = new char[size + 1]; 00139 ar_longnames[size] = '\0'; 00140 dev->read(ar_longnames, size); 00141 skip_entry = true; 00142 kDebug(7042) << "Read in longnames entry"; 00143 } else if (name.mid(1, 1) == " ") { // Symbol table entry 00144 kDebug(7042) << "Skipped symbol entry"; 00145 dev->seek( dev->pos() + size ); 00146 skip_entry = true; 00147 } else { // Longfilename 00148 kDebug(7042) << "Longfilename #" << name.mid(1, 15).toInt(); 00149 if (! ar_longnames) { 00150 kWarning(7042) << "Invalid longfilename reference"; 00151 delete[] ar_longnames; 00152 return false; 00153 } 00154 name = &ar_longnames[name.mid(1, 15).toInt()]; 00155 name = name.left(name.indexOf("/")); 00156 } 00157 } 00158 if (skip_entry) continue; 00159 00160 name = name.trimmed(); // Process filename 00161 name.replace( '/', QByteArray() ); 00162 kDebug(7042) << "Filename: " << name << " Size: " << size; 00163 00164 KArchiveEntry* entry = new KArchiveFile(this, QString::fromLocal8Bit(name), mode, date, 00165 /*uid*/ QString(), /*gid*/ QString(), /*symlink*/ QString(), 00166 dev->pos(), size); 00167 rootDir()->addEntry(entry); // Ar files don't support directories, so everything in root 00168 00169 dev->seek( dev->pos() + size ); // Skip contents 00170 } 00171 delete[] ar_longnames; 00172 00173 return true; 00174 } 00175 00176 bool KAr::closeArchive() 00177 { 00178 // Close the archive 00179 return true; 00180 } 00181 00182 void KAr::virtual_hook( int id, void* data ) 00183 { KArchive::virtual_hook( id, data ); }
KDE 4.6 API Reference