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