karchive.cpp
00001 /* This file is part of the KDE libraries 00002 Copyright (C) 2000 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 <stdio.h> 00023 #include <stdlib.h> 00024 #include <time.h> 00025 #include <unistd.h> 00026 #include <errno.h> 00027 #include <grp.h> 00028 #include <pwd.h> 00029 #include <assert.h> 00030 #include <sys/types.h> 00031 #include <sys/stat.h> 00032 00033 #include <tqptrlist.h> 00034 #include <tqptrstack.h> 00035 #include <tqvaluestack.h> 00036 #include <tqmap.h> 00037 #include <tqcstring.h> 00038 #include <tqdir.h> 00039 #include <tqfile.h> 00040 00041 #include <kdebug.h> 00042 #include <kfilterdev.h> 00043 #include <kfilterbase.h> 00044 #include <kde_file.h> 00045 00046 #include "karchive.h" 00047 #include "klimitediodevice.h" 00048 00049 template class TQDict<KArchiveEntry>; 00050 00051 00052 class KArchive::KArchivePrivate 00053 { 00054 public: 00055 KArchiveDirectory* rootDir; 00056 bool closeSucceeded; 00057 }; 00058 00059 class PosSortedPtrList : public TQPtrList<KArchiveFile> { 00060 protected: 00061 int compareItems( TQPtrCollection::Item i1, 00062 TQPtrCollection::Item i2 ) 00063 { 00064 int pos1 = static_cast<KArchiveFile*>( i1 )->position(); 00065 int pos2 = static_cast<KArchiveFile*>( i2 )->position(); 00066 return ( pos1 - pos2 ); 00067 } 00068 }; 00069 00070 00074 00075 KArchive::KArchive( TQIODevice * dev ) 00076 { 00077 d = new KArchivePrivate; 00078 d->rootDir = 0; 00079 m_dev = dev; 00080 m_open = false; 00081 } 00082 00083 KArchive::~KArchive() 00084 { 00085 if ( m_open ) 00086 close(); 00087 delete d->rootDir; 00088 delete d; 00089 } 00090 00091 bool KArchive::open( int mode ) 00092 { 00093 if ( m_dev && !m_dev->open( mode ) ) 00094 return false; 00095 00096 if ( m_open ) 00097 close(); 00098 00099 m_mode = mode; 00100 m_open = true; 00101 00102 Q_ASSERT( d->rootDir == 0L ); 00103 d->rootDir = 0L; 00104 00105 return openArchive( mode ); 00106 } 00107 00108 void KArchive::close() 00109 { 00110 if ( !m_open ) 00111 return; 00112 // moved by holger to allow kzip to write the zip central dir 00113 // to the file in closeArchive() 00114 d->closeSucceeded = closeArchive(); 00115 00116 if ( m_dev ) 00117 m_dev->close(); 00118 00119 delete d->rootDir; 00120 d->rootDir = 0; 00121 m_open = false; 00122 } 00123 00124 bool KArchive::closeSucceeded() const 00125 { 00126 return d->closeSucceeded; 00127 } 00128 00129 const KArchiveDirectory* KArchive::directory() const 00130 { 00131 // rootDir isn't const so that parsing-on-demand is possible 00132 return const_cast<KArchive *>(this)->rootDir(); 00133 } 00134 00135 00136 bool KArchive::addLocalFile( const TQString& fileName, const TQString& destName ) 00137 { 00138 TQFileInfo fileInfo( fileName ); 00139 if ( !fileInfo.isFile() && !fileInfo.isSymLink() ) 00140 { 00141 kdWarning() << "KArchive::addLocalFile " << fileName << " doesn't exist or is not a regular file." << endl; 00142 return false; 00143 } 00144 00145 KDE_struct_stat fi; 00146 if (KDE_lstat(TQFile::encodeName(fileName),&fi) == -1) { 00147 kdWarning() << "KArchive::addLocalFile stating " << fileName 00148 << " failed: " << strerror(errno) << endl; 00149 return false; 00150 } 00151 00152 if (fileInfo.isSymLink()) { 00153 return writeSymLink(destName, fileInfo.readLink(), fileInfo.owner(), 00154 fileInfo.group(), fi.st_mode, fi.st_atime, fi.st_mtime, 00155 fi.st_ctime); 00156 }/*end if*/ 00157 00158 uint size = fileInfo.size(); 00159 00160 // the file must be opened before prepareWriting is called, otherwise 00161 // if the opening fails, no content will follow the already written 00162 // header and the tar file is effectively f*cked up 00163 TQFile file( fileName ); 00164 if ( !file.open( IO_ReadOnly ) ) 00165 { 00166 kdWarning() << "KArchive::addLocalFile couldn't open file " << fileName << endl; 00167 return false; 00168 } 00169 00170 if ( !prepareWriting( destName, fileInfo.owner(), fileInfo.group(), size, 00171 fi.st_mode, fi.st_atime, fi.st_mtime, fi.st_ctime ) ) 00172 { 00173 kdWarning() << "KArchive::addLocalFile prepareWriting " << destName << " failed" << endl; 00174 return false; 00175 } 00176 00177 // Read and write data in chunks to minimize memory usage 00178 TQByteArray array(8*1024); 00179 int n; 00180 uint total = 0; 00181 while ( ( n = file.readBlock( array.data(), array.size() ) ) > 0 ) 00182 { 00183 if ( !writeData( array.data(), n ) ) 00184 { 00185 kdWarning() << "KArchive::addLocalFile writeData failed" << endl; 00186 return false; 00187 } 00188 total += n; 00189 } 00190 Q_ASSERT( total == size ); 00191 00192 if ( !doneWriting( size ) ) 00193 { 00194 kdWarning() << "KArchive::addLocalFile doneWriting failed" << endl; 00195 return false; 00196 } 00197 return true; 00198 } 00199 00200 bool KArchive::addLocalDirectory( const TQString& path, const TQString& destName ) 00201 { 00202 TQString dot = "."; 00203 TQString dotdot = ".."; 00204 TQDir dir( path ); 00205 if ( !dir.exists() ) 00206 return false; 00207 dir.setFilter(dir.filter() | TQDir::Hidden); 00208 TQStringList files = dir.entryList(); 00209 for ( TQStringList::Iterator it = files.begin(); it != files.end(); ++it ) 00210 { 00211 if ( *it != dot && *it != dotdot ) 00212 { 00213 TQString fileName = path + "/" + *it; 00214 // kdDebug() << "storing " << fileName << endl; 00215 TQString dest = destName.isEmpty() ? *it : (destName + "/" + *it); 00216 TQFileInfo fileInfo( fileName ); 00217 00218 if ( fileInfo.isFile() || fileInfo.isSymLink() ) 00219 addLocalFile( fileName, dest ); 00220 else if ( fileInfo.isDir() ) 00221 addLocalDirectory( fileName, dest ); 00222 // We omit sockets 00223 } 00224 } 00225 return true; 00226 } 00227 00228 bool KArchive::writeFile( const TQString& name, const TQString& user, const TQString& group, uint size, const char* data ) 00229 { 00230 mode_t perm = 0100644; 00231 time_t the_time = time(0); 00232 return writeFile(name,user,group,size,perm,the_time,the_time,the_time,data); 00233 } 00234 00235 bool KArchive::prepareWriting( const TQString& name, const TQString& user, 00236 const TQString& group, uint size, mode_t perm, 00237 time_t atime, time_t mtime, time_t ctime ) { 00238 PrepareWritingParams params; 00239 params.name = &name; 00240 params.user = &user; 00241 params.group = &group; 00242 params.size = size; 00243 params.perm = perm; 00244 params.atime = atime; 00245 params.mtime = mtime; 00246 params.ctime = ctime; 00247 virtual_hook(VIRTUAL_PREPARE_WRITING,¶ms); 00248 return params.retval; 00249 } 00250 00251 bool KArchive::prepareWriting_impl(const TQString &name, const TQString &user, 00252 const TQString &group, uint size, mode_t /*perm*/, 00253 time_t /*atime*/, time_t /*mtime*/, time_t /*ctime*/ ) { 00254 kdWarning(7040) << "New prepareWriting API not implemented in this class." << endl 00255 << "Falling back to old API (metadata information will be lost)" << endl; 00256 return prepareWriting(name,user,group,size); 00257 } 00258 00259 bool KArchive::writeFile( const TQString& name, const TQString& user, 00260 const TQString& group, uint size, mode_t perm, 00261 time_t atime, time_t mtime, time_t ctime, 00262 const char* data ) { 00263 WriteFileParams params; 00264 params.name = &name; 00265 params.user = &user; 00266 params.group = &group; 00267 params.size = size; 00268 params.perm = perm; 00269 params.atime = atime; 00270 params.mtime = mtime; 00271 params.ctime = ctime; 00272 params.data = data; 00273 virtual_hook(VIRTUAL_WRITE_FILE,¶ms); 00274 return params.retval; 00275 } 00276 00277 bool KArchive::writeFile_impl( const TQString& name, const TQString& user, 00278 const TQString& group, uint size, mode_t perm, 00279 time_t atime, time_t mtime, time_t ctime, 00280 const char* data ) { 00281 00282 if ( !prepareWriting( name, user, group, size, perm, atime, mtime, ctime ) ) 00283 { 00284 kdWarning() << "KArchive::writeFile prepareWriting failed" << endl; 00285 return false; 00286 } 00287 00288 // Write data 00289 // Note: if data is 0L, don't call writeBlock, it would terminate the KFilterDev 00290 if ( data && size && !writeData( data, size ) ) 00291 { 00292 kdWarning() << "KArchive::writeFile writeData failed" << endl; 00293 return false; 00294 } 00295 00296 if ( !doneWriting( size ) ) 00297 { 00298 kdWarning() << "KArchive::writeFile doneWriting failed" << endl; 00299 return false; 00300 } 00301 return true; 00302 } 00303 00304 bool KArchive::writeDir(const TQString& name, const TQString& user, 00305 const TQString& group, mode_t perm, 00306 time_t atime, time_t mtime, time_t ctime) { 00307 WriteDirParams params; 00308 params.name = &name; 00309 params.user = &user; 00310 params.group = &group; 00311 params.perm = perm; 00312 params.atime = atime; 00313 params.mtime = mtime; 00314 params.ctime = ctime; 00315 virtual_hook(VIRTUAL_WRITE_DIR,¶ms); 00316 return params.retval; 00317 } 00318 00319 bool KArchive::writeDir_impl(const TQString &name, const TQString &user, 00320 const TQString &group, mode_t /*perm*/, 00321 time_t /*atime*/, time_t /*mtime*/, time_t /*ctime*/ ) { 00322 kdWarning(7040) << "New writeDir API not implemented in this class." << endl 00323 << "Falling back to old API (metadata information will be lost)" << endl; 00324 return writeDir(name,user,group); 00325 } 00326 00327 bool KArchive::writeSymLink(const TQString &name, const TQString &target, 00328 const TQString &user, const TQString &group, 00329 mode_t perm, time_t atime, time_t mtime, time_t ctime) { 00330 WriteSymlinkParams params; 00331 params.name = &name; 00332 params.target = ⌖ 00333 params.user = &user; 00334 params.group = &group; 00335 params.perm = perm; 00336 params.atime = atime; 00337 params.mtime = mtime; 00338 params.ctime = ctime; 00339 virtual_hook(VIRTUAL_WRITE_SYMLINK,¶ms); 00340 return params.retval; 00341 } 00342 00343 bool KArchive::writeSymLink_impl(const TQString &/*name*/,const TQString &/*target*/, 00344 const TQString &/*user*/, const TQString &/*group*/, 00345 mode_t /*perm*/, time_t /*atime*/, time_t /*mtime*/, 00346 time_t /*ctime*/) { 00347 kdWarning(7040) << "writeSymLink not implemented in this class." << endl 00348 << "No fallback available." << endl; 00349 // FIXME: better return true here for compatibility with KDE < 3.2 00350 return false; 00351 } 00352 00353 bool KArchive::writeData( const char* data, uint size ) 00354 { 00355 WriteDataParams params; 00356 params.data = data; 00357 params.size = size; 00358 virtual_hook( VIRTUAL_WRITE_DATA, ¶ms ); 00359 return params.retval; 00360 } 00361 00362 bool KArchive::writeData_impl( const char* data, uint size ) 00363 { 00364 Q_ASSERT( device() ); 00365 return device()->writeBlock( data, size ) == (TQ_LONG)size; 00366 } 00367 00368 KArchiveDirectory * KArchive::rootDir() 00369 { 00370 if ( !d->rootDir ) 00371 { 00372 //kdDebug() << "Making root dir " << endl; 00373 struct passwd* pw = getpwuid( getuid() ); 00374 struct group* grp = getgrgid( getgid() ); 00375 TQString username = pw ? TQFile::decodeName(pw->pw_name) : TQString::number( getuid() ); 00376 TQString groupname = grp ? TQFile::decodeName(grp->gr_name) : TQString::number( getgid() ); 00377 00378 d->rootDir = new KArchiveDirectory( this, TQString::fromLatin1("/"), (int)(0777 + S_IFDIR), 0, username, groupname, TQString::null ); 00379 } 00380 return d->rootDir; 00381 } 00382 00383 KArchiveDirectory * KArchive::findOrCreate( const TQString & path ) 00384 { 00385 //kdDebug() << "KArchive::findOrCreate " << path << endl; 00386 if ( path.isEmpty() || path == "/" || path == "." ) // root dir => found 00387 { 00388 //kdDebug() << "KArchive::findOrCreate returning rootdir" << endl; 00389 return rootDir(); 00390 } 00391 // Important note : for tar files containing absolute paths 00392 // (i.e. beginning with "/"), this means the leading "/" will 00393 // be removed (no KDirectory for it), which is exactly the way 00394 // the "tar" program works (though it displays a warning about it) 00395 // See also KArchiveDirectory::entry(). 00396 00397 // Already created ? => found 00398 KArchiveEntry* ent = rootDir()->entry( path ); 00399 if ( ent ) 00400 { 00401 if ( ent->isDirectory() ) 00402 //kdDebug() << "KArchive::findOrCreate found it" << endl; 00403 return (KArchiveDirectory *) ent; 00404 else 00405 kdWarning() << "Found " << path << " but it's not a directory" << endl; 00406 } 00407 00408 // Otherwise go up and try again 00409 int pos = path.findRev( '/' ); 00410 KArchiveDirectory * parent; 00411 TQString dirname; 00412 if ( pos == -1 ) // no more slash => create in root dir 00413 { 00414 parent = rootDir(); 00415 dirname = path; 00416 } 00417 else 00418 { 00419 TQString left = path.left( pos ); 00420 dirname = path.mid( pos + 1 ); 00421 parent = findOrCreate( left ); // recursive call... until we find an existing dir. 00422 } 00423 00424 //kdDebug() << "KTar : found parent " << parent->name() << " adding " << dirname << " to ensure " << path << endl; 00425 // Found -> add the missing piece 00426 KArchiveDirectory * e = new KArchiveDirectory( this, dirname, d->rootDir->permissions(), 00427 d->rootDir->date(), d->rootDir->user(), 00428 d->rootDir->group(), TQString::null ); 00429 parent->addEntry( e ); 00430 return e; // now a directory to <path> exists 00431 } 00432 00433 void KArchive::setDevice( TQIODevice * dev ) 00434 { 00435 m_dev = dev; 00436 } 00437 00438 void KArchive::setRootDir( KArchiveDirectory *rootDir ) 00439 { 00440 Q_ASSERT( !d->rootDir ); // Call setRootDir only once during parsing please ;) 00441 d->rootDir = rootDir; 00442 } 00443 00447 KArchiveEntry::KArchiveEntry( KArchive* t, const TQString& name, int access, int date, 00448 const TQString& user, const TQString& group, const 00449 TQString& symlink) 00450 { 00451 m_name = name; 00452 m_access = access; 00453 m_date = date; 00454 m_user = user; 00455 m_group = group; 00456 m_symlink = symlink; 00457 m_archive = t; 00458 00459 } 00460 00461 TQDateTime KArchiveEntry::datetime() const 00462 { 00463 TQDateTime d; 00464 d.setTime_t( m_date ); 00465 return d; 00466 } 00467 00471 00472 KArchiveFile::KArchiveFile( KArchive* t, const TQString& name, int access, int date, 00473 const TQString& user, const TQString& group, 00474 const TQString & symlink, 00475 int pos, int size ) 00476 : KArchiveEntry( t, name, access, date, user, group, symlink ) 00477 { 00478 m_pos = pos; 00479 m_size = size; 00480 } 00481 00482 int KArchiveFile::position() const 00483 { 00484 return m_pos; 00485 } 00486 00487 int KArchiveFile::size() const 00488 { 00489 return m_size; 00490 } 00491 00492 TQByteArray KArchiveFile::data() const 00493 { 00494 archive()->device()->at( m_pos ); 00495 00496 // Read content 00497 TQByteArray arr( m_size ); 00498 if ( m_size ) 00499 { 00500 assert( arr.data() ); 00501 int n = archive()->device()->readBlock( arr.data(), m_size ); 00502 if ( n != m_size ) 00503 arr.resize( n ); 00504 } 00505 return arr; 00506 } 00507 00508 // ** This should be a virtual method, and this code should be in ktar.cpp 00509 TQIODevice *KArchiveFile::device() const 00510 { 00511 return new KLimitedIODevice( archive()->device(), m_pos, m_size ); 00512 } 00513 00514 void KArchiveFile::copyTo(const TQString& dest) const 00515 { 00516 TQFile f( dest + "/" + name() ); 00517 f.open( IO_ReadWrite | IO_Truncate ); 00518 f.writeBlock( data() ); 00519 f.close(); 00520 } 00521 00525 00526 00527 KArchiveDirectory::KArchiveDirectory( KArchive* t, const TQString& name, int access, 00528 int date, 00529 const TQString& user, const TQString& group, 00530 const TQString &symlink) 00531 : KArchiveEntry( t, name, access, date, user, group, symlink ) 00532 { 00533 m_entries.setAutoDelete( true ); 00534 } 00535 00536 TQStringList KArchiveDirectory::entries() const 00537 { 00538 TQStringList l; 00539 00540 TQDictIterator<KArchiveEntry> it( m_entries ); 00541 for( ; it.current(); ++it ) 00542 l.append( it.currentKey() ); 00543 00544 return l; 00545 } 00546 00547 KArchiveEntry* KArchiveDirectory::entry( TQString name ) 00548 // not "const TQString & name" since we want a local copy 00549 // (to remove leading slash if any) 00550 { 00551 int pos = name.find( '/' ); 00552 if ( pos == 0 ) // ouch absolute path (see also KArchive::findOrCreate) 00553 { 00554 if (name.length()>1) 00555 { 00556 name = name.mid( 1 ); // remove leading slash 00557 pos = name.find( '/' ); // look again 00558 } 00559 else // "/" 00560 return this; 00561 } 00562 // trailing slash ? -> remove 00563 if ( pos != -1 && pos == (int)name.length()-1 ) 00564 { 00565 name = name.left( pos ); 00566 pos = name.find( '/' ); // look again 00567 } 00568 if ( pos != -1 ) 00569 { 00570 TQString left = name.left( pos ); 00571 TQString right = name.mid( pos + 1 ); 00572 00573 //kdDebug() << "KArchiveDirectory::entry left=" << left << " right=" << right << endl; 00574 00575 KArchiveEntry* e = m_entries[ left ]; 00576 if ( !e || !e->isDirectory() ) 00577 return 0; 00578 return ((KArchiveDirectory*)e)->entry( right ); 00579 } 00580 00581 return m_entries[ name ]; 00582 } 00583 00584 const KArchiveEntry* KArchiveDirectory::entry( TQString name ) const 00585 { 00586 return ((KArchiveDirectory*)this)->entry( name ); 00587 } 00588 00589 void KArchiveDirectory::addEntry( KArchiveEntry* entry ) 00590 { 00591 if( entry->name().isEmpty() ) { 00592 return; 00593 } 00594 if( m_entries[ entry->name() ] ) { 00595 kdWarning() << "KArchiveDirectory::addEntry: directory " << name() 00596 << " has entry " << entry->name() << " already" << endl; 00597 } 00598 m_entries.insert( entry->name(), entry ); 00599 } 00600 00601 void KArchiveDirectory::copyTo(const TQString& dest, bool recursiveCopy ) const 00602 { 00603 TQDir root; 00604 const TQString destDir(TQDir(dest).absPath()); // get directory path without any "." or ".." 00605 00606 PosSortedPtrList fileList; 00607 TQMap<int, TQString> fileToDir; 00608 00609 TQStringList::Iterator it; 00610 00611 // placeholders for iterated items 00612 KArchiveDirectory* curDir; 00613 TQString curDirName; 00614 00615 TQStringList dirEntries; 00616 KArchiveEntry* curEntry; 00617 KArchiveFile* curFile; 00618 00619 00620 TQPtrStack<KArchiveDirectory> dirStack; 00621 TQValueStack<TQString> dirNameStack; 00622 00623 dirStack.push( this ); // init stack at current directory 00624 dirNameStack.push( destDir ); // ... with given path 00625 do { 00626 curDir = dirStack.pop(); 00627 00628 // extract only to specified folder if it is located within archive's extraction folder 00629 // otherwise put file under root position in extraction folder 00630 TQString curDirName = dirNameStack.pop(); 00631 if (!TQDir(curDirName).absPath().startsWith(destDir)) { 00632 kdWarning() << "Attempted export into folder" << curDirName 00633 << "which is outside of the extraction root folder" << destDir << "." 00634 << "Changing export of contained files to extraction root folder."; 00635 curDirName = destDir; 00636 } 00637 root.mkdir(curDirName); 00638 00639 dirEntries = curDir->entries(); 00640 for ( it = dirEntries.begin(); it != dirEntries.end(); ++it ) { 00641 curEntry = curDir->entry(*it); 00642 if (!curEntry->symlink().isEmpty()) { 00643 const TQString linkName = curDirName+'/'+curEntry->name(); 00644 kdDebug() << "symlink(" << curEntry->symlink() << ',' << linkName << ')'; 00645 #ifdef Q_OS_UNIX 00646 if (!::symlink(curEntry->symlink().local8Bit(), linkName.local8Bit())) { 00647 kdDebug() << "symlink(" << curEntry->symlink() << ',' << linkName << ") failed:" << strerror(errno); 00648 } 00649 #endif 00650 } else { 00651 if ( curEntry->isFile() ) { 00652 curFile = dynamic_cast<KArchiveFile*>( curEntry ); 00653 if (curFile) { 00654 fileList.append( curFile ); 00655 fileToDir.insert( curFile->position(), curDirName ); 00656 } 00657 } 00658 00659 if ( curEntry->isDirectory() ) 00660 if ( recursiveCopy ) { 00661 KArchiveDirectory *ad = dynamic_cast<KArchiveDirectory*>( curEntry ); 00662 if (ad) { 00663 dirStack.push( ad ); 00664 dirNameStack.push( curDirName + "/" + curEntry->name() ); 00665 } 00666 } 00667 } 00668 } 00669 } while (!dirStack.isEmpty()); 00670 00671 fileList.sort(); // sort on m_pos, so we have a linear access 00672 00673 KArchiveFile* f; 00674 for ( f = fileList.first(); f; f = fileList.next() ) { 00675 int pos = f->position(); 00676 f->copyTo( fileToDir[pos] ); 00677 } 00678 } 00679 00680 void KArchive::virtual_hook( int id, void* data ) 00681 { 00682 switch (id) { 00683 case VIRTUAL_WRITE_DATA: { 00684 WriteDataParams* params = reinterpret_cast<WriteDataParams *>(data); 00685 params->retval = writeData_impl( params->data, params->size ); 00686 break; 00687 } 00688 case VIRTUAL_WRITE_SYMLINK: { 00689 WriteSymlinkParams *params = reinterpret_cast<WriteSymlinkParams *>(data); 00690 params->retval = writeSymLink_impl(*params->name,*params->target, 00691 *params->user,*params->group,params->perm, 00692 params->atime,params->mtime,params->ctime); 00693 break; 00694 } 00695 case VIRTUAL_WRITE_DIR: { 00696 WriteDirParams *params = reinterpret_cast<WriteDirParams *>(data); 00697 params->retval = writeDir_impl(*params->name,*params->user, 00698 *params->group,params->perm, 00699 params->atime,params->mtime,params->ctime); 00700 break; 00701 } 00702 case VIRTUAL_WRITE_FILE: { 00703 WriteFileParams *params = reinterpret_cast<WriteFileParams *>(data); 00704 params->retval = writeFile_impl(*params->name,*params->user, 00705 *params->group,params->size,params->perm, 00706 params->atime,params->mtime,params->ctime, 00707 params->data); 00708 break; 00709 } 00710 case VIRTUAL_PREPARE_WRITING: { 00711 PrepareWritingParams *params = reinterpret_cast<PrepareWritingParams *>(data); 00712 params->retval = prepareWriting_impl(*params->name,*params->user, 00713 *params->group,params->size,params->perm, 00714 params->atime,params->mtime,params->ctime); 00715 break; 00716 } 00717 default: 00718 /*BASE::virtual_hook( id, data )*/; 00719 }/*end switch*/ 00720 } 00721 00722 void KArchiveEntry::virtual_hook( int, void* ) 00723 { /*BASE::virtual_hook( id, data );*/ } 00724 00725 void KArchiveFile::virtual_hook( int id, void* data ) 00726 { KArchiveEntry::virtual_hook( id, data ); } 00727 00728 void KArchiveDirectory::virtual_hook( int id, void* data ) 00729 { KArchiveEntry::virtual_hook( id, data ); }