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