• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KIO

karchive.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002    Copyright (C) 2000-2005 David Faure <faure@kde.org>
00003    Copyright (C) 2003 Leo Savernik <l.savernik@aon.at>
00004 
00005    Moved from ktar.cpp by Roberto Teixeira <maragato@kde.org>
00006 
00007    This library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Library General Public
00009    License version 2 as published by the Free Software Foundation.
00010 
00011    This library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Library General Public License for more details.
00015 
00016    You should have received a copy of the GNU Library General Public License
00017    along with this library; see the file COPYING.LIB.  If not, write to
00018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019    Boston, MA 02110-1301, USA.
00020 */
00021 
00022 #include "karchive.h"
00023 #include "klimitediodevice.h"
00024 
00025 #include <config.h>
00026 
00027 #include <kdebug.h>
00028 #include <ksavefile.h>
00029 #include <kde_file.h>
00030 
00031 #include <QStack>
00032 #include <QtCore/QMap>
00033 #include <QtCore/QDir>
00034 #include <QtCore/QFile>
00035 
00036 #include <stdio.h>
00037 #include <stdlib.h>
00038 #include <time.h>
00039 #include <unistd.h>
00040 #include <errno.h>
00041 #include <grp.h>
00042 #include <pwd.h>
00043 #include <assert.h>
00044 #include <sys/types.h>
00045 #include <sys/stat.h>
00046 #ifdef Q_OS_UNIX
00047 #include <limits.h>  // PATH_MAX
00048 #endif
00049 
00050 class KArchivePrivate
00051 {
00052 public:
00053     KArchivePrivate()
00054         : rootDir( 0 ),
00055           saveFile( 0 ),
00056           dev ( 0 ),
00057           fileName(),
00058           mode( QIODevice::NotOpen ),
00059           deviceOwned( false )
00060     {}
00061     ~KArchivePrivate()
00062     {
00063         delete saveFile;
00064         delete rootDir;
00065     }
00066     void abortWriting();
00067 
00068     KArchiveDirectory* rootDir;
00069     KSaveFile* saveFile;
00070     QIODevice * dev;
00071     QString fileName;
00072     QIODevice::OpenMode mode;
00073     bool deviceOwned; // if true, we (KArchive) own dev and must delete it
00074 };
00075 
00076 
00080 
00081 KArchive::KArchive( const QString& fileName )
00082     : d(new KArchivePrivate)
00083 {
00084     Q_ASSERT( !fileName.isEmpty() );
00085     d->fileName = fileName;
00086     // This constructor leaves the device set to 0.
00087     // This is for the use of KSaveFile, see open().
00088 }
00089 
00090 KArchive::KArchive( QIODevice * dev )
00091     : d(new KArchivePrivate)
00092 {
00093     d->dev = dev;
00094 }
00095 
00096 KArchive::~KArchive()
00097 {
00098     if ( isOpen() )
00099         close(); // WARNING: won't call the virtual method close in the derived class!!!
00100 
00101     delete d;
00102 }
00103 
00104 bool KArchive::open( QIODevice::OpenMode mode )
00105 {
00106     Q_ASSERT( mode != QIODevice::NotOpen );
00107 
00108     if ( isOpen() )
00109         close();
00110 
00111     if ( !d->fileName.isEmpty() )
00112     {
00113         Q_ASSERT( !d->dev );
00114         if ( !createDevice( mode ) )
00115             return false;
00116     }
00117 
00118     Q_ASSERT( d->dev );
00119 
00120     if ( !d->dev->isOpen() && !d->dev->open( mode ) )
00121         return false;
00122 
00123     d->mode = mode;
00124 
00125     Q_ASSERT( !d->rootDir );
00126     d->rootDir = 0;
00127 
00128     return openArchive( mode );
00129 }
00130 
00131 bool KArchive::createDevice( QIODevice::OpenMode mode )
00132 {
00133     switch( mode ) {
00134     case QIODevice::WriteOnly:
00135         if ( !d->fileName.isEmpty() ) {
00136             // The use of KSaveFile can't be done in the ctor (no mode known yet)
00137             //kDebug() << "Writing to a file using KSaveFile";
00138             d->saveFile = new KSaveFile( d->fileName );
00139             if ( !d->saveFile->open() ) {
00140                 kWarning() << "KSaveFile creation for " << d->fileName << " failed, " << d->saveFile->errorString();
00141                 delete d->saveFile;
00142                 d->saveFile = 0;
00143                 return false;
00144             }
00145             d->dev = d->saveFile;
00146             Q_ASSERT( d->dev );
00147         }
00148         break;
00149     case QIODevice::ReadOnly:
00150     case QIODevice::ReadWrite:
00151         // ReadWrite mode still uses QFile for now; we'd need to copy to the tempfile, in fact.
00152         if ( !d->fileName.isEmpty() ) {
00153             d->dev = new QFile( d->fileName );
00154             d->deviceOwned = true;
00155         }
00156         break; // continued below
00157     default:
00158         kWarning() << "Unsupported mode " << d->mode;
00159         return false;
00160     }
00161     return true;
00162 }
00163 
00164 bool KArchive::close()
00165 {
00166     if ( !isOpen() )
00167         return false; // already closed (return false or true? arguable...)
00168 
00169     // moved by holger to allow kzip to write the zip central dir
00170     // to the file in closeArchive()
00171     // DF: added d->dev so that we skip closeArchive if saving aborted.
00172     bool closeSucceeded = true;
00173     if ( d->dev ) {
00174         closeSucceeded = closeArchive();
00175         if ( d->mode == QIODevice::WriteOnly && !closeSucceeded )
00176             d->abortWriting();
00177     }
00178 
00179     if ( d->dev )
00180         d->dev->close();
00181 
00182     if ( d->deviceOwned ) {
00183         delete d->dev; // we created it ourselves in open()
00184     }
00185     if ( d->saveFile ) {
00186         closeSucceeded = d->saveFile->finalize();
00187         delete d->saveFile;
00188         d->saveFile = 0;
00189     }
00190 
00191     delete d->rootDir;
00192     d->rootDir = 0;
00193     d->mode = QIODevice::NotOpen;
00194     d->dev = 0;
00195     return closeSucceeded;
00196 }
00197 
00198 const KArchiveDirectory* KArchive::directory() const
00199 {
00200     // rootDir isn't const so that parsing-on-demand is possible
00201     return const_cast<KArchive *>(this)->rootDir();
00202 }
00203 
00204 
00205 bool KArchive::addLocalFile( const QString& fileName, const QString& destName )
00206 {
00207     QFileInfo fileInfo( fileName );
00208     if ( !fileInfo.isFile() && !fileInfo.isSymLink() )
00209     {
00210         kWarning() << fileName << "doesn't exist or is not a regular file.";
00211         return false;
00212     }
00213 
00214     KDE_struct_stat fi;
00215     if (KDE_lstat(QFile::encodeName(fileName),&fi) == -1) {
00216         kWarning() << "stat'ing" << fileName
00217             << "failed:" << strerror(errno);
00218         return false;
00219     }
00220 
00221     if (fileInfo.isSymLink()) {
00222         QString symLinkTarget;
00223         // Do NOT use fileInfo.readLink() for unix symlinks!
00224         // It returns the -full- path to the target, while we want the target string "as is".
00225 #if defined(Q_OS_UNIX) && !defined(Q_OS_OS2EMX)
00226         QByteArray s;
00227         s.resize(PATH_MAX+1);
00228         int len = readlink( QFile::encodeName(fileName).data(), s.data(), PATH_MAX );
00229         if ( len >= 0 ) {
00230             s[len] = '\0';
00231             symLinkTarget = QFile::decodeName(s);
00232         }
00233 #endif
00234         if (symLinkTarget.isEmpty()) // Mac or Windows
00235             symLinkTarget = fileInfo.symLinkTarget();
00236         return writeSymLink(destName, symLinkTarget, fileInfo.owner(),
00237                             fileInfo.group(), fi.st_mode, fi.st_atime, fi.st_mtime,
00238                             fi.st_ctime);
00239     }/*end if*/
00240 
00241     qint64 size = fileInfo.size();
00242 
00243     // the file must be opened before prepareWriting is called, otherwise
00244     // if the opening fails, no content will follow the already written
00245     // header and the tar file is effectively f*cked up
00246     QFile file( fileName );
00247     if ( !file.open( QIODevice::ReadOnly ) )
00248     {
00249         kWarning() << "couldn't open file " << fileName;
00250         return false;
00251     }
00252 
00253     if ( !prepareWriting( destName, fileInfo.owner(), fileInfo.group(), size,
00254             fi.st_mode, fi.st_atime, fi.st_mtime, fi.st_ctime ) )
00255     {
00256         kWarning() << " prepareWriting" << destName << "failed";
00257         return false;
00258     }
00259 
00260     // Read and write data in chunks to minimize memory usage
00261     QByteArray array;
00262     array.resize(8*1024);
00263     qint64 n;
00264     qint64 total = 0;
00265     while ( ( n = file.read( array.data(), array.size() ) ) > 0 )
00266     {
00267         if ( !writeData( array.data(), n ) )
00268         {
00269             kWarning() << "writeData failed";
00270             return false;
00271         }
00272         total += n;
00273     }
00274     Q_ASSERT( total == size );
00275 
00276     if ( !finishWriting( size ) )
00277     {
00278         kWarning() << "finishWriting failed";
00279         return false;
00280     }
00281     return true;
00282 }
00283 
00284 bool KArchive::addLocalDirectory( const QString& path, const QString& destName )
00285 {
00286     QDir dir( path );
00287     if ( !dir.exists() )
00288         return false;
00289     dir.setFilter(dir.filter() | QDir::Hidden);
00290     const QStringList files = dir.entryList();
00291     for ( QStringList::ConstIterator it = files.begin(); it != files.end(); ++it )
00292     {
00293         if ( *it != "." && *it != ".." )
00294         {
00295             QString fileName = path + '/' + *it;
00296 //            kDebug() << "storing " << fileName;
00297             QString dest = destName.isEmpty() ? *it : (destName + '/' + *it);
00298             QFileInfo fileInfo( fileName );
00299 
00300             if ( fileInfo.isFile() || fileInfo.isSymLink() )
00301                 addLocalFile( fileName, dest );
00302             else if ( fileInfo.isDir() )
00303                 addLocalDirectory( fileName, dest );
00304             // We omit sockets
00305         }
00306     }
00307     return true;
00308 }
00309 
00310 bool KArchive::writeFile( const QString& name, const QString& user,
00311                           const QString& group, const char* data, qint64 size,
00312                           mode_t perm, time_t atime, time_t mtime, time_t ctime )
00313 {
00314     if ( !prepareWriting( name, user, group, size, perm, atime, mtime, ctime ) )
00315     {
00316         kWarning() << "prepareWriting failed";
00317         return false;
00318     }
00319 
00320     // Write data
00321     // Note: if data is 0L, don't call write, it would terminate the KFilterDev
00322     if ( data && size && !writeData( data, size ) )
00323     {
00324         kWarning() << "writeData failed";
00325         return false;
00326     }
00327 
00328     if ( !finishWriting( size ) )
00329     {
00330         kWarning() << "finishWriting failed";
00331         return false;
00332     }
00333     return true;
00334 }
00335 
00336 bool KArchive::writeData( const char* data, qint64 size )
00337 {
00338     bool ok = device()->write( data, size ) == size;
00339     if ( !ok )
00340         d->abortWriting();
00341     return ok;
00342 }
00343 
00344 // The writeDir -> doWriteDir pattern allows to avoid propagating the default
00345 // values into all virtual methods of subclasses, and it allows more extensibility:
00346 // if a new argument is needed, we can add a writeDir overload which stores the
00347 // additional argument in the d pointer, and doWriteDir reimplementations can fetch
00348 // it from there.
00349 
00350 bool KArchive::writeDir( const QString& name, const QString& user, const QString& group,
00351                          mode_t perm, time_t atime,
00352                          time_t mtime, time_t ctime )
00353 {
00354     return doWriteDir( name, user, group, perm, atime, mtime, ctime );
00355 }
00356 
00357 bool KArchive::writeSymLink(const QString &name, const QString &target,
00358                             const QString &user, const QString &group,
00359                             mode_t perm, time_t atime,
00360                             time_t mtime, time_t ctime )
00361 {
00362     return doWriteSymLink( name, target, user, group, perm, atime, mtime, ctime );
00363 }
00364 
00365 
00366 bool KArchive::prepareWriting( const QString& name, const QString& user,
00367                                const QString& group, qint64 size,
00368                                mode_t perm, time_t atime,
00369                                time_t mtime, time_t ctime )
00370 {
00371     bool ok = doPrepareWriting( name, user, group, size, perm, atime, mtime, ctime );
00372     if ( !ok )
00373         d->abortWriting();
00374     return ok;
00375 }
00376 
00377 bool KArchive::finishWriting( qint64 size )
00378 {
00379     return doFinishWriting( size );
00380 }
00381 
00382 KArchiveDirectory * KArchive::rootDir()
00383 {
00384     if ( !d->rootDir )
00385     {
00386         //kDebug() << "Making root dir ";
00387         struct passwd* pw =  getpwuid( getuid() );
00388         struct group* grp = getgrgid( getgid() );
00389         QString username = pw ? QFile::decodeName(pw->pw_name) : QString::number( getuid() );
00390         QString groupname = grp ? QFile::decodeName(grp->gr_name) : QString::number( getgid() );
00391 
00392         d->rootDir = new KArchiveDirectory( this, QLatin1String("/"), (int)(0777 + S_IFDIR), 0, username, groupname, QString() );
00393     }
00394     return d->rootDir;
00395 }
00396 
00397 KArchiveDirectory * KArchive::findOrCreate( const QString & path )
00398 {
00399     //kDebug() << path;
00400     if ( path.isEmpty() || path == "/" || path == "." ) // root dir => found
00401     {
00402         //kDebug() << "returning rootdir";
00403         return rootDir();
00404     }
00405     // Important note : for tar files containing absolute paths
00406     // (i.e. beginning with "/"), this means the leading "/" will
00407     // be removed (no KDirectory for it), which is exactly the way
00408     // the "tar" program works (though it displays a warning about it)
00409     // See also KArchiveDirectory::entry().
00410 
00411     // Already created ? => found
00412     const KArchiveEntry* ent = rootDir()->entry( path );
00413     if ( ent )
00414     {
00415         if ( ent->isDirectory() )
00416             //kDebug() << "found it";
00417             return (KArchiveDirectory *) ent;
00418         else
00419             kWarning() << "Found" << path << "but it's not a directory";
00420     }
00421 
00422     // Otherwise go up and try again
00423     int pos = path.lastIndexOf( '/' );
00424     KArchiveDirectory * parent;
00425     QString dirname;
00426     if ( pos == -1 ) // no more slash => create in root dir
00427     {
00428         parent =  rootDir();
00429         dirname = path;
00430     }
00431     else
00432     {
00433         QString left = path.left( pos );
00434         dirname = path.mid( pos + 1 );
00435         parent = findOrCreate( left ); // recursive call... until we find an existing dir.
00436     }
00437 
00438     //kDebug() << "found parent " << parent->name() << " adding " << dirname << " to ensure " << path;
00439     // Found -> add the missing piece
00440     KArchiveDirectory * e = new KArchiveDirectory( this, dirname, d->rootDir->permissions(),
00441                                                    d->rootDir->date(), d->rootDir->user(),
00442                                                    d->rootDir->group(), QString() );
00443     parent->addEntry( e );
00444     return e; // now a directory to <path> exists
00445 }
00446 
00447 void KArchive::setDevice( QIODevice * dev )
00448 {
00449     if ( d->deviceOwned )
00450         delete d->dev;
00451     d->dev = dev;
00452     d->deviceOwned = false;
00453 }
00454 
00455 void KArchive::setRootDir( KArchiveDirectory *rootDir )
00456 {
00457     Q_ASSERT( !d->rootDir ); // Call setRootDir only once during parsing please ;)
00458     d->rootDir = rootDir;
00459 }
00460 
00461 QIODevice::OpenMode KArchive::mode() const
00462 {
00463     return d->mode;
00464 }
00465 
00466 QIODevice * KArchive::device() const
00467 {
00468     return d->dev;
00469 }
00470 
00471 bool KArchive::isOpen() const
00472 {
00473     return d->mode != QIODevice::NotOpen;
00474 }
00475 
00476 QString KArchive::fileName() const
00477 {
00478     return d->fileName;
00479 }
00480 
00481 void KArchivePrivate::abortWriting()
00482 {
00483     if ( saveFile ) {
00484         saveFile->abort();
00485         delete saveFile;
00486         saveFile = 0;
00487         dev = 0;
00488     }
00489 }
00490 
00494 
00495 class KArchiveEntryPrivate
00496 {
00497 public:
00498     KArchiveEntryPrivate( KArchive* _archive, const QString& _name, int _access,
00499                           int _date, const QString& _user, const QString& _group,
00500                           const QString& _symlink) :
00501         name(_name),
00502         date(_date),
00503         access(_access),
00504         user(_user),
00505         group(_group),
00506         symlink(_symlink),
00507         archive(_archive)
00508     {}
00509     QString name;
00510     int date;
00511     mode_t access;
00512     QString user;
00513     QString group;
00514     QString symlink;
00515     KArchive* archive;
00516 };
00517 
00518 KArchiveEntry::KArchiveEntry( KArchive* t, const QString& name, int access, int date,
00519                       const QString& user, const QString& group, const
00520                       QString& symlink) :
00521     d(new KArchiveEntryPrivate(t,name,access,date,user,group,symlink))
00522 {
00523 }
00524 
00525 KArchiveEntry::~KArchiveEntry()
00526 {
00527     delete d;
00528 }
00529 
00530 QDateTime KArchiveEntry::datetime() const
00531 {
00532   QDateTime datetimeobj;
00533   datetimeobj.setTime_t( d->date );
00534   return datetimeobj;
00535 }
00536 
00537 int KArchiveEntry::date() const
00538 {
00539     return d->date;
00540 }
00541 
00542 QString KArchiveEntry::name() const
00543 {
00544     return d->name;
00545 }
00546 
00547 mode_t KArchiveEntry::permissions() const
00548 {
00549     return d->access;
00550 }
00551 
00552 QString KArchiveEntry::user() const
00553 {
00554     return d->user;
00555 }
00556 
00557 QString KArchiveEntry::group() const
00558 {
00559     return d->group;
00560 }
00561 
00562 QString KArchiveEntry::symLinkTarget() const
00563 {
00564     return d->symlink;
00565 }
00566 
00567 bool KArchiveEntry::isFile() const
00568 {
00569     return false;
00570 }
00571 
00572 bool KArchiveEntry::isDirectory() const
00573 {
00574     return false;
00575 }
00576 
00577 KArchive* KArchiveEntry::archive() const
00578 {
00579     return d->archive;
00580 }
00581 
00585 
00586 class KArchiveFilePrivate
00587 {
00588 public:
00589     KArchiveFilePrivate( qint64 _pos, qint64 _size ) :
00590         pos(_pos),
00591         size(_size)
00592     {}
00593     qint64 pos;
00594     qint64 size;
00595 };
00596 
00597 KArchiveFile::KArchiveFile( KArchive* t, const QString& name, int access, int date,
00598                             const QString& user, const QString& group,
00599                             const QString & symlink,
00600                             qint64 pos, qint64 size )
00601   : KArchiveEntry( t, name, access, date, user, group, symlink ),
00602     d( new KArchiveFilePrivate(pos, size) )
00603 {
00604 }
00605 
00606 KArchiveFile::~KArchiveFile()
00607 {
00608     delete d;
00609 }
00610 
00611 qint64 KArchiveFile::position() const
00612 {
00613   return d->pos;
00614 }
00615 
00616 qint64 KArchiveFile::size() const
00617 {
00618   return d->size;
00619 }
00620 
00621 void KArchiveFile::setSize( qint64 s )
00622 {
00623     d->size = s;
00624 }
00625 
00626 QByteArray KArchiveFile::data() const
00627 {
00628   archive()->device()->seek( d->pos );
00629 
00630   // Read content
00631   QByteArray arr;
00632   if ( d->size )
00633   {
00634     assert( arr.data() );
00635     arr = archive()->device()->read( d->size );
00636     Q_ASSERT( arr.size() == d->size );
00637   }
00638   return arr;
00639 }
00640 
00641 QIODevice * KArchiveFile::createDevice() const
00642 {
00643   return new KLimitedIODevice( archive()->device(), d->pos, d->size );
00644 }
00645 
00646 bool KArchiveFile::isFile() const
00647 {
00648     return true;
00649 }
00650 
00651 void KArchiveFile::copyTo(const QString& dest) const
00652 {
00653   QFile f( dest + '/'  + name() );
00654   if ( f.open( QIODevice::ReadWrite | QIODevice::Truncate ) )
00655   {
00656       f.write( data() );
00657       f.close();
00658   }
00659 }
00660 
00664 
00665 class KArchiveDirectoryPrivate
00666 {
00667 public:
00668     ~KArchiveDirectoryPrivate()
00669     {
00670         qDeleteAll(entries);
00671     }
00672     QHash<QString, KArchiveEntry *> entries;
00673 };
00674 
00675 KArchiveDirectory::KArchiveDirectory( KArchive* t, const QString& name, int access,
00676                               int date,
00677                               const QString& user, const QString& group,
00678                               const QString &symlink)
00679   : KArchiveEntry( t, name, access, date, user, group, symlink ),
00680     d( new KArchiveDirectoryPrivate )
00681 {
00682 }
00683 
00684 KArchiveDirectory::~KArchiveDirectory()
00685 {
00686   delete d;
00687 }
00688 
00689 QStringList KArchiveDirectory::entries() const
00690 {
00691   return d->entries.keys();
00692 }
00693 
00694 const KArchiveEntry* KArchiveDirectory::entry( const QString& _name ) const
00695 {
00696   QString name = _name;
00697   int pos = name.indexOf( '/' );
00698   if ( pos == 0 ) // ouch absolute path (see also KArchive::findOrCreate)
00699   {
00700     if (name.length()>1)
00701     {
00702       name = name.mid( 1 ); // remove leading slash
00703       pos = name.indexOf( '/' ); // look again
00704     }
00705     else // "/"
00706       return this;
00707   }
00708   // trailing slash ? -> remove
00709   if ( pos != -1 && pos == name.length()-1 )
00710   {
00711     name = name.left( pos );
00712     pos = name.indexOf( '/' ); // look again
00713   }
00714   if ( pos != -1 )
00715   {
00716     QString left = name.left( pos );
00717     QString right = name.mid( pos + 1 );
00718 
00719     //kDebug() << "left=" << left << "right=" << right;
00720 
00721     const KArchiveEntry* e = d->entries.value( left );
00722     if ( !e || !e->isDirectory() )
00723       return 0;
00724     return static_cast<const KArchiveDirectory*>(e)->entry( right );
00725   }
00726 
00727   return d->entries.value( name );
00728 }
00729 
00730 void KArchiveDirectory::addEntry( KArchiveEntry* entry )
00731 {
00732   Q_ASSERT( !entry->name().isEmpty() );
00733   if( d->entries.value( entry->name() ) ) {
00734       kWarning() << "directory " << name()
00735                   << "has entry" << entry->name() << "already";
00736   }
00737   d->entries.insert( entry->name(), entry );
00738 }
00739 
00740 bool KArchiveDirectory::isDirectory() const
00741 {
00742     return true;
00743 }
00744 
00745 static int sortByPosition( const KArchiveFile* file1, const KArchiveFile* file2 ) {
00746     return file1->position() - file2->position();
00747 }
00748 
00749 void KArchiveDirectory::copyTo(const QString& dest, bool recursiveCopy ) const
00750 {
00751   QDir root;
00752 
00753   QList<const KArchiveFile*> fileList;
00754   QMap<qint64, QString> fileToDir;
00755 
00756   // placeholders for iterated items
00757   QStack<const KArchiveDirectory *> dirStack;
00758   QStack<QString> dirNameStack;
00759 
00760   dirStack.push( this );     // init stack at current directory
00761   dirNameStack.push( dest ); // ... with given path
00762   do {
00763     const KArchiveDirectory* curDir = dirStack.pop();
00764     const QString curDirName = dirNameStack.pop();
00765     root.mkdir(curDirName);
00766 
00767     const QStringList dirEntries = curDir->entries();
00768     for ( QStringList::const_iterator it = dirEntries.begin(); it != dirEntries.end(); ++it ) {
00769       const KArchiveEntry* curEntry = curDir->entry(*it);
00770       if (!curEntry->symLinkTarget().isEmpty()) {
00771           const QString linkName = curDirName+'/'+curEntry->name();
00772 #ifdef Q_OS_UNIX
00773           if (!::symlink(curEntry->symLinkTarget().toLocal8Bit(), linkName.toLocal8Bit())) {
00774               kDebug() << "symlink(" << curEntry->symLinkTarget() << ',' << linkName << ") failed:" << strerror(errno);
00775           }
00776 #else
00777           // TODO - how to create symlinks on other platforms?
00778 #endif
00779       } else {
00780           if ( curEntry->isFile() ) {
00781               const KArchiveFile* curFile = dynamic_cast<const KArchiveFile*>( curEntry );
00782               if (curFile) {
00783                   fileList.append( curFile );
00784                   fileToDir.insert( curFile->position(), curDirName );
00785               }
00786           }
00787 
00788           if ( curEntry->isDirectory() && recursiveCopy ) {
00789               const KArchiveDirectory *ad = dynamic_cast<const KArchiveDirectory*>( curEntry );
00790               if (ad) {
00791                   dirStack.push( ad );
00792                   dirNameStack.push( curDirName + '/' + curEntry->name() );
00793               }
00794           }
00795       }
00796     }
00797   } while (!dirStack.isEmpty());
00798 
00799   qSort( fileList.begin(), fileList.end(), sortByPosition );  // sort on d->pos, so we have a linear access
00800 
00801   for ( QList<const KArchiveFile*>::const_iterator it = fileList.begin(), end = fileList.end() ;
00802         it != end ; ++it ) {
00803       const KArchiveFile* f = *it;
00804       qint64 pos = f->position();
00805       f->copyTo( fileToDir[pos] );
00806   }
00807 }
00808 
00809 void KArchive::virtual_hook( int, void* )
00810 { /*BASE::virtual_hook( id, data )*/; }
00811 
00812 void KArchiveEntry::virtual_hook( int, void* )
00813 { /*BASE::virtual_hook( id, data );*/ }
00814 
00815 void KArchiveFile::virtual_hook( int id, void* data )
00816 { KArchiveEntry::virtual_hook( id, data ); }
00817 
00818 void KArchiveDirectory::virtual_hook( int id, void* data )
00819 { KArchiveEntry::virtual_hook( id, data ); }

KIO

Skip menu "KIO"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • KIO
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal