00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "ktar.h"
00021
00022 #include <stdlib.h>
00023 #include <time.h>
00024 #include <assert.h>
00025
00026 #include <QtCore/QDir>
00027 #include <QtCore/QFile>
00028 #include <kdebug.h>
00029 #include <kmimetype.h>
00030 #include <ktemporaryfile.h>
00031
00032 #include <kfilterdev.h>
00033 #include <kfilterbase.h>
00034
00035 #include <kstandarddirs.h>
00036
00040
00041 class KTar::KTarPrivate
00042 {
00043 public:
00044 KTarPrivate(KTar *parent)
00045 : q(parent),
00046 tarEnd( 0 ),
00047 tmpFile( 0 )
00048 {
00049 }
00050
00051 KTar *q;
00052 QStringList dirList;
00053 qint64 tarEnd;
00054 KTemporaryFile* tmpFile;
00055 QString mimetype;
00056 QByteArray origFileName;
00057
00058 bool fillTempFile(const QString & fileName);
00059 bool writeBackTempFile( const QString & fileName );
00060 void fillBuffer( char * buffer, const char * mode, qint64 size, time_t mtime,
00061 char typeflag, const char * uname, const char * gname );
00062 void writeLonglink(char *buffer, const QByteArray &name, char typeflag,
00063 const char *uname, const char *gname);
00064 qint64 readRawHeader(char *buffer);
00065 bool readLonglink(char *buffer, QByteArray &longlink);
00066 qint64 readHeader(char *buffer, QString &name, QString &symlink);
00067 };
00068
00069 KTar::KTar( const QString& fileName, const QString & _mimetype )
00070 : KArchive( fileName ), d(new KTarPrivate(this))
00071 {
00072 d->mimetype = _mimetype;
00073 }
00074
00075 KTar::KTar( QIODevice * dev )
00076 : KArchive( dev ),d(new KTarPrivate(this))
00077 {
00078 Q_ASSERT( dev );
00079 }
00080
00081
00082 bool KTar::createDevice( QIODevice::OpenMode mode )
00083 {
00084 Q_UNUSED( mode );
00085 if ( d->mimetype.isEmpty() )
00086 {
00087 if ( mode != QIODevice::WriteOnly && QFile::exists( fileName() ) )
00088 d->mimetype = KMimeType::findByFileContent( fileName() )->name();
00089 else
00090 d->mimetype = KMimeType::findByPath( fileName(), 0, true )->name();
00091 kDebug(7041) << "mimetype=" << d->mimetype;
00092
00093 if ( d->mimetype == "application/x-compressed-tar"
00094 || d->mimetype == "application/x-tgz"
00095 || d->mimetype == "application/x-targz"
00096 || d->mimetype == "application/x-webarchive" )
00097 {
00098
00099 d->mimetype = "application/x-gzip";
00100 }
00101 else if ( d->mimetype == "application/x-bzip-compressed-tar" )
00102 {
00103 d->mimetype = "application/x-bzip";
00104 }
00105 else
00106 {
00107
00108 QFile file( fileName() );
00109 if ( file.open( QIODevice::ReadOnly ) )
00110 {
00111 char firstByte, secondByte, thirdByte;
00112 if ( file.getChar( &firstByte ) &&
00113 file.getChar( &secondByte ) &&
00114 file.getChar( &thirdByte ) ) {
00115 if ( firstByte == 0037 && static_cast<uchar>(secondByte) == static_cast<uchar>(0213) )
00116 d->mimetype = "application/x-gzip";
00117 else if ( firstByte == 'B' && secondByte == 'Z' && thirdByte == 'h' )
00118 d->mimetype = "application/x-bzip";
00119 else if ( firstByte == 'P' && secondByte == 'K' && thirdByte == 3 )
00120 {
00121 char fourthByte;
00122 if ( file.getChar(&fourthByte) && fourthByte == 4 )
00123 d->mimetype = "application/zip";
00124 }
00125 }
00126 }
00127 file.close();
00128 }
00129 }
00130
00131 if( d->mimetype == "application/x-tar" )
00132 {
00133 return KArchive::createDevice( mode );
00134 }
00135 else
00136 {
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147 Q_ASSERT(!d->tmpFile);
00148 d->tmpFile = new KTemporaryFile();
00149 d->tmpFile->setPrefix("ktar-");
00150 d->tmpFile->setSuffix(".tar");
00151 d->tmpFile->open();
00152 kDebug( 7041 ) << "creating tempfile:" << d->tmpFile->fileName();
00153
00154 setDevice( d->tmpFile );
00155 return true;
00156 }
00157 }
00158
00159 KTar::~KTar()
00160 {
00161
00162 if( isOpen() )
00163 close();
00164
00165 delete d->tmpFile;
00166 delete d;
00167 }
00168
00169 void KTar::setOrigFileName( const QByteArray & fileName ) {
00170 if ( !isOpen() || !(mode() & QIODevice::WriteOnly) )
00171 {
00172 kWarning(7041) << "KTar::setOrigFileName: File must be opened for writing first.\n";
00173 return;
00174 }
00175 d->origFileName = fileName;
00176 }
00177
00178 qint64 KTar::KTarPrivate::readRawHeader( char *buffer ) {
00179
00180 qint64 n = q->device()->read( buffer, 0x200 );
00181 if ( n == 0x200 && buffer[0] != 0 ) {
00182
00183 if (strncmp(buffer + 257, "ustar", 5)) {
00184
00185
00186 int check = 0;
00187 for( uint j = 0; j < 0x200; ++j )
00188 check += buffer[j];
00189
00190
00191 for( uint j = 0; j < 8 ; j++ )
00192 check -= buffer[148 + j];
00193 check += 8 * ' ';
00194
00195 QByteArray s = QByteArray::number( check, 8 );
00196
00197
00198
00199
00200 if( strncmp( buffer + 148 + 6 - s.length(), s.data(), s.length() )
00201 && strncmp( buffer + 148 + 7 - s.length(), s.data(), s.length() )
00202 && strncmp( buffer + 148 + 8 - s.length(), s.data(), s.length() ) ) {
00203 kWarning(7041) << "KTar: invalid TAR file. Header is:" << QByteArray( buffer+257, 5 )
00204 << "instead of ustar. Reading from wrong pos in file?"
00205 << "checksum=" << QByteArray( buffer + 148 + 6 - s.length(), s.length() );
00206 return -1;
00207 }
00208 }
00209 } else {
00210
00211 if (n == 0x200) n = 0;
00212 }
00213 return n;
00214 }
00215
00216 bool KTar::KTarPrivate::readLonglink(char *buffer,QByteArray &longlink) {
00217 qint64 n = 0;
00218
00219 QIODevice *dev = q->device();
00220
00221
00222 qint64 size = QByteArray( buffer + 0x7c, 12 ).trimmed().toLongLong( 0, 8 );
00223
00224 size--;
00225 longlink.resize(size);
00226 qint64 offset = 0;
00227 while (size > 0) {
00228 int chunksize = qMin(size, 0x200LL);
00229 n = dev->read( longlink.data() + offset, chunksize );
00230 if (n == -1) return false;
00231 size -= chunksize;
00232 offset += 0x200;
00233 }
00234
00235 const int skip = 0x200 - (n % 0x200);
00236 if (skip < 0x200) {
00237 if (dev->read(buffer,skip) != skip)
00238 return false;
00239 }
00240 return true;
00241 }
00242
00243 qint64 KTar::KTarPrivate::readHeader( char *buffer, QString &name, QString &symlink ) {
00244 name.truncate(0);
00245 symlink.truncate(0);
00246 while (true) {
00247 qint64 n = readRawHeader(buffer);
00248 if (n != 0x200) return n;
00249
00250
00251 if (strcmp(buffer,"././@LongLink") == 0) {
00252 char typeflag = buffer[0x9c];
00253 QByteArray longlink;
00254 readLonglink(buffer,longlink);
00255 switch (typeflag) {
00256 case 'L': name = QFile::decodeName(longlink); break;
00257 case 'K': symlink = QFile::decodeName(longlink); break;
00258 }
00259 } else {
00260 break;
00261 }
00262 }
00263
00264
00265 if (name.isEmpty())
00266
00267
00268 name = QFile::decodeName(QByteArray(buffer, 100));
00269 if (symlink.isEmpty())
00270 symlink = QFile::decodeName(QByteArray(buffer + 0x9d , 100));
00271
00272 return 0x200;
00273 }
00274
00275
00276
00277
00278
00279
00280 bool KTar::KTarPrivate::fillTempFile( const QString & fileName) {
00281 if ( ! tmpFile )
00282 return true;
00283
00284 kDebug( 7041 ) << "filling tmpFile of mimetype" << mimetype;
00285
00286 bool forced = false;
00287 if( "application/x-gzip" == mimetype
00288 || "application/x-bzip" == mimetype)
00289 forced = true;
00290
00291 QIODevice *filterDev = KFilterDev::deviceForFile( fileName, mimetype, forced );
00292
00293 if( filterDev ) {
00294 QFile* file = tmpFile;
00295 Q_ASSERT(file->isOpen());
00296 Q_ASSERT(file->openMode() & QIODevice::WriteOnly);
00297 file->seek(0);
00298 QByteArray buffer;
00299 buffer.resize(8*1024);
00300 if ( ! filterDev->open( QIODevice::ReadOnly ) )
00301 {
00302 delete filterDev;
00303 return false;
00304 }
00305 qint64 len = -1;
00306 while ( !filterDev->atEnd() && len != 0 ) {
00307 len = filterDev->read(buffer.data(),buffer.size());
00308 if ( len < 0 ) {
00309 delete filterDev;
00310 return false;
00311 }
00312 if ( file->write(buffer.data(), len) != len ) {
00313 delete filterDev;
00314 return false;
00315 }
00316 }
00317 filterDev->close();
00318 delete filterDev;
00319
00320 file->flush();
00321 file->seek(0);
00322 Q_ASSERT(file->isOpen());
00323 Q_ASSERT(file->openMode() & QIODevice::ReadOnly);
00324 }
00325 else
00326 kDebug( 7041 ) << "no filterdevice found!";
00327
00328
00329 return true;
00330 }
00331
00332 bool KTar::openArchive( QIODevice::OpenMode mode ) {
00333
00334 if ( !(mode & QIODevice::ReadOnly) )
00335 return true;
00336
00337 if ( !d->fillTempFile( fileName() ) )
00338 return false;
00339
00340
00341
00342
00343
00344
00345 d->dirList.clear();
00346 QIODevice* dev = device();
00347
00348 if ( !dev )
00349 return false;
00350
00351
00352 char buffer[ 0x200 ];
00353 bool ende = false;
00354 do
00355 {
00356 QString name;
00357 QString symlink;
00358
00359
00360 qint64 n = d->readHeader( buffer, name, symlink );
00361 if (n < 0) return false;
00362 if (n == 0x200)
00363 {
00364 bool isdir = false;
00365
00366 if ( name.endsWith( QLatin1Char( '/' ) ) )
00367 {
00368 isdir = true;
00369 name.truncate( name.length() - 1 );
00370 }
00371
00372 int pos = name.lastIndexOf( '/' );
00373 QString nm = ( pos == -1 ) ? name : name.mid( pos + 1 );
00374
00375
00376 buffer[ 0x6b ] = 0;
00377 char *dummy;
00378 const char* p = buffer + 0x64;
00379 while( *p == ' ' ) ++p;
00380 int access = (int)strtol( p, &dummy, 8 );
00381
00382
00383 QString user( buffer + 0x109 );
00384 QString group( buffer + 0x129 );
00385
00386
00387 buffer[ 0x93 ] = 0;
00388 p = buffer + 0x88;
00389 while( *p == ' ' ) ++p;
00390 int time = (int)strtol( p, &dummy, 8 );
00391
00392
00393 char typeflag = buffer[ 0x9c ];
00394
00395
00396
00397 if ( typeflag == '5' )
00398 isdir = true;
00399
00400 bool isDumpDir = false;
00401 if ( typeflag == 'D' )
00402 {
00403 isdir = false;
00404 isDumpDir = true;
00405 }
00406
00407
00408 if (isdir)
00409 access |= S_IFDIR;
00410
00411 KArchiveEntry* e;
00412 if ( isdir )
00413 {
00414
00415 e = new KArchiveDirectory( this, nm, access, time, user, group, symlink );
00416 }
00417 else
00418 {
00419
00420 QByteArray sizeBuffer( buffer + 0x7c, 12 );
00421 qint64 size = sizeBuffer.trimmed().toLongLong( 0, 8 );
00422
00423
00424
00425 if ( isDumpDir )
00426 {
00427
00428 e = new KArchiveDirectory( this, nm, access, time, user, group, symlink );
00429 }
00430 else
00431 {
00432
00433
00434 if ( typeflag == '1' )
00435 {
00436 kDebug(7041) << "HARD LINK, setting size to 0 instead of " << size;
00437 size = 0;
00438 }
00439
00440
00441 e = new KArchiveFile( this, nm, access, time, user, group, symlink,
00442 dev->pos(), size );
00443 }
00444
00445
00446 int rest = size % 0x200;
00447 int skip = size + (rest ? 0x200 - rest : 0);
00448
00449 if (! dev->seek( dev->pos() + skip ) )
00450 kWarning(7041) << "skipping" << skip << "failed";
00451 }
00452
00453 if ( pos == -1 )
00454 {
00455 if ( nm == "." )
00456 {
00457 Q_ASSERT( isdir );
00458 if ( isdir )
00459 setRootDir( static_cast<KArchiveDirectory *>( e ) );
00460 }
00461 else
00462 rootDir()->addEntry( e );
00463 }
00464 else
00465 {
00466
00467 QString path = QDir::cleanPath( name.left( pos ) );
00468
00469 KArchiveDirectory * d = findOrCreate( path );
00470 d->addEntry( e );
00471 }
00472 }
00473 else
00474 {
00475
00476 d->tarEnd = dev->pos() - n;
00477 ende = true;
00478 }
00479 } while( !ende );
00480 return true;
00481 }
00482
00483
00484
00485
00486
00487
00488 bool KTar::KTarPrivate::writeBackTempFile( const QString & fileName ) {
00489 if ( ! tmpFile )
00490 return true;
00491
00492 kDebug(7041) << "Write temporary file to compressed file";
00493 kDebug(7041) << fileName << " " << mimetype;
00494
00495 bool forced = false;
00496 if( "application/x-gzip" == mimetype
00497 || "application/x-bzip" == mimetype)
00498 forced = true;
00499
00500
00501
00502
00503
00504 QIODevice *dev = KFilterDev::deviceForFile( fileName, mimetype, forced );
00505 if( dev ) {
00506 QFile* file = tmpFile;
00507 if ( !dev->open(QIODevice::WriteOnly) )
00508 {
00509 file->close();
00510 delete dev;
00511 return false;
00512 }
00513 if ( forced )
00514 static_cast<KFilterDev *>(dev)->setOrigFileName( origFileName );
00515 file->seek(0);
00516 QByteArray buffer;
00517 buffer.resize(8*1024);
00518 qint64 len;
00519 while ( !file->atEnd()) {
00520 len = file->read(buffer.data(), buffer.size());
00521 dev->write(buffer.data(),len);
00522 }
00523 file->close();
00524 dev->close();
00525 delete dev;
00526 }
00527
00528 kDebug(7041) << "Write temporary file to compressed file done.";
00529 return true;
00530 }
00531
00532 bool KTar::closeArchive() {
00533 d->dirList.clear();
00534
00535 bool ok = true;
00536
00537
00538
00539
00540 if( mode() == QIODevice::WriteOnly) {
00541 ok = d->writeBackTempFile( fileName() );
00542 delete d->tmpFile;
00543 d->tmpFile = 0;
00544 setDevice(0);
00545 }
00546
00547 return ok;
00548 }
00549
00550 bool KTar::doFinishWriting( qint64 size ) {
00551
00552 int rest = size % 0x200;
00553 if ( ( mode() & QIODevice::ReadWrite ) == QIODevice::ReadWrite )
00554 d->tarEnd = device()->pos() + (rest ? 0x200 - rest : 0);
00555 if ( rest )
00556 {
00557 char buffer[ 0x201 ];
00558 for( uint i = 0; i < 0x200; ++i )
00559 buffer[i] = 0;
00560 qint64 nwritten = device()->write( buffer, 0x200 - rest );
00561 return nwritten == 0x200 - rest;
00562 }
00563 return true;
00564 }
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589 void KTar::KTarPrivate::fillBuffer( char * buffer,
00590 const char * mode, qint64 size, time_t mtime, char typeflag,
00591 const char * uname, const char * gname ) {
00592
00593 assert( strlen(mode) == 6 );
00594 memcpy( buffer+0x64, mode, 6 );
00595 buffer[ 0x6a ] = ' ';
00596 buffer[ 0x6b ] = '\0';
00597
00598
00599 strcpy( buffer + 0x6c, " 765 ");
00600
00601 strcpy( buffer + 0x74, " 144 ");
00602
00603
00604 QByteArray s = QByteArray::number( size, 8 );
00605 s = s.rightJustified( 11, '0' );
00606 memcpy( buffer + 0x7c, s.data(), 11 );
00607 buffer[ 0x87 ] = ' ';
00608
00609
00610 s = QByteArray::number( static_cast<qulonglong>(mtime), 8 );
00611 s = s.rightJustified( 11, '0' );
00612 memcpy( buffer + 0x88, s.data(), 11 );
00613 buffer[ 0x93 ] = ' ';
00614
00615
00616 buffer[ 0x94 ] = 0x20;
00617 buffer[ 0x95 ] = 0x20;
00618 buffer[ 0x96 ] = 0x20;
00619 buffer[ 0x97 ] = 0x20;
00620 buffer[ 0x98 ] = 0x20;
00621 buffer[ 0x99 ] = 0x20;
00622
00623
00624
00625
00626
00627
00628 buffer[ 0x9a ] = '\0';
00629 buffer[ 0x9b ] = ' ';
00630
00631
00632 buffer[ 0x9c ] = typeflag;
00633
00634
00635 strcpy( buffer + 0x101, "ustar");
00636 strcpy( buffer + 0x107, "00" );
00637
00638
00639 strcpy( buffer + 0x109, uname );
00640
00641 strcpy( buffer + 0x129, gname );
00642
00643
00644 int check = 32;
00645 for( uint j = 0; j < 0x200; ++j )
00646 check += buffer[j];
00647 s = QByteArray::number( check, 8 );
00648 s = s.rightJustified( 6, '0' );
00649 memcpy( buffer + 0x94, s.constData(), 6 );
00650 }
00651
00652 void KTar::KTarPrivate::writeLonglink(char *buffer, const QByteArray &name, char typeflag,
00653 const char *uname, const char *gname) {
00654 strcpy( buffer, "././@LongLink" );
00655 qint64 namelen = name.length() + 1;
00656 fillBuffer( buffer, " 0", namelen, 0, typeflag, uname, gname );
00657 q->device()->write( buffer, 0x200 );
00658 qint64 offset = 0;
00659 while (namelen > 0) {
00660 int chunksize = qMin(namelen, 0x200LL);
00661 memcpy(buffer, name.data()+offset, chunksize);
00662
00663 q->device()->write( buffer, 0x200 );
00664
00665 namelen -= chunksize;
00666 offset += 0x200;
00667 }
00668 }
00669
00670 bool KTar::doPrepareWriting(const QString &name, const QString &user,
00671 const QString &group, qint64 size, mode_t perm,
00672 time_t , time_t mtime, time_t ) {
00673 if ( !isOpen() )
00674 {
00675 kWarning(7041) << "You must open the tar file before writing to it\n";
00676 return false;
00677 }
00678
00679 if ( !(mode() & QIODevice::WriteOnly) )
00680 {
00681 kWarning(7041) << "You must open the tar file for writing\n";
00682 return false;
00683 }
00684
00685
00686 QString fileName ( QDir::cleanPath( name ) );
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707 char buffer[ 0x201 ];
00708 memset( buffer, 0, 0x200 );
00709 if ( ( mode() & QIODevice::ReadWrite ) == QIODevice::ReadWrite )
00710 device()->seek(d->tarEnd);
00711
00712
00713 const QByteArray encodedFileName = QFile::encodeName(fileName);
00714 const QByteArray uname = user.toLocal8Bit();
00715 const QByteArray gname = group.toLocal8Bit();
00716
00717
00718 if ( fileName.length() > 99 )
00719 d->writeLonglink(buffer,encodedFileName,'L',uname,gname);
00720
00721
00722 strncpy( buffer, encodedFileName, 99 );
00723 buffer[99] = 0;
00724
00725 memset(buffer+0x9d, 0, 0x200 - 0x9d);
00726
00727 QByteArray permstr = QByteArray::number( (unsigned int)perm, 8 );
00728 permstr = permstr.rightJustified(6, '0');
00729 d->fillBuffer(buffer, permstr, size, mtime, 0x30, uname, gname);
00730
00731
00732 return device()->write( buffer, 0x200 ) == 0x200;
00733 }
00734
00735 bool KTar::doWriteDir(const QString &name, const QString &user,
00736 const QString &group, mode_t perm,
00737 time_t , time_t mtime, time_t ) {
00738 if ( !isOpen() )
00739 {
00740 kWarning(7041) << "You must open the tar file before writing to it\n";
00741 return false;
00742 }
00743
00744 if ( !(mode() & QIODevice::WriteOnly) )
00745 {
00746 kWarning(7041) << "You must open the tar file for writing\n";
00747 return false;
00748 }
00749
00750
00751 QString dirName ( QDir::cleanPath( name ) );
00752
00753
00754 if ( !dirName.endsWith( QLatin1Char( '/' ) ) )
00755 dirName += QLatin1Char( '/' );
00756
00757 if ( d->dirList.contains( dirName ) )
00758 return true;
00759
00760 char buffer[ 0x201 ];
00761 memset( buffer, 0, 0x200 );
00762 if ( ( mode() & QIODevice::ReadWrite ) == QIODevice::ReadWrite )
00763 device()->seek(d->tarEnd);
00764
00765
00766 QByteArray encodedDirname = QFile::encodeName(dirName);
00767 QByteArray uname = user.toLocal8Bit();
00768 QByteArray gname = group.toLocal8Bit();
00769
00770
00771 if ( dirName.length() > 99 )
00772 d->writeLonglink(buffer,encodedDirname,'L',uname,gname);
00773
00774
00775 strncpy( buffer, encodedDirname, 99 );
00776 buffer[99] = 0;
00777
00778 memset(buffer+0x9d, 0, 0x200 - 0x9d);
00779
00780 QByteArray permstr = QByteArray::number( (unsigned int)perm, 8 );
00781 permstr = permstr.rightJustified(6, ' ');
00782 d->fillBuffer( buffer, permstr, 0, mtime, 0x35, uname, gname);
00783
00784
00785 device()->write( buffer, 0x200 );
00786 if ( ( mode() & QIODevice::ReadWrite ) == QIODevice::ReadWrite )
00787 d->tarEnd = device()->pos();
00788
00789 d->dirList.append( dirName );
00790 return true;
00791 }
00792
00793 bool KTar::doWriteSymLink(const QString &name, const QString &target,
00794 const QString &user, const QString &group,
00795 mode_t perm, time_t , time_t mtime, time_t ) {
00796 if ( !isOpen() )
00797 {
00798 kWarning(7041) << "You must open the tar file before writing to it\n";
00799 return false;
00800 }
00801
00802 if ( !(mode() & QIODevice::WriteOnly) )
00803 {
00804 kWarning(7041) << "You must open the tar file for writing\n";
00805 return false;
00806 }
00807
00808
00809 QString fileName ( QDir::cleanPath( name ) );
00810
00811 char buffer[ 0x201 ];
00812 memset( buffer, 0, 0x200 );
00813 if ( ( mode() & QIODevice::ReadWrite ) == QIODevice::ReadWrite )
00814 device()->seek(d->tarEnd);
00815
00816
00817 QByteArray encodedFileName = QFile::encodeName(fileName);
00818 QByteArray encodedTarget = QFile::encodeName(target);
00819 QByteArray uname = user.toLocal8Bit();
00820 QByteArray gname = group.toLocal8Bit();
00821
00822
00823 if (target.length() > 99)
00824 d->writeLonglink(buffer,encodedTarget,'K',uname,gname);
00825 if ( fileName.length() > 99 )
00826 d->writeLonglink(buffer,encodedFileName,'L',uname,gname);
00827
00828
00829 strncpy( buffer, encodedFileName, 99 );
00830 buffer[99] = 0;
00831
00832 strncpy(buffer+0x9d, encodedTarget, 99);
00833 buffer[0x9d+99] = 0;
00834
00835 memset(buffer+0x9d+100, 0, 0x200 - 100 - 0x9d);
00836
00837 QByteArray permstr = QByteArray::number( (unsigned int)perm, 8 );
00838 permstr = permstr.rightJustified(6, ' ');
00839 d->fillBuffer(buffer, permstr, 0, mtime, 0x32, uname, gname);
00840
00841
00842 bool retval = device()->write( buffer, 0x200 ) == 0x200;
00843 if ( ( mode() & QIODevice::ReadWrite ) == QIODevice::ReadWrite )
00844 d->tarEnd = device()->pos();
00845 return retval;
00846 }
00847
00848 void KTar::virtual_hook( int id, void* data ) {
00849 KArchive::virtual_hook( id, data );
00850 }