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
00255
00256 case 'L': name = decodeEntryName(longlink); break;
00257 case 'K': symlink = decodeEntryName(longlink); break;
00258 }
00259 } else {
00260 break;
00261 }
00262 }
00263
00264
00265 if (name.isEmpty())
00266
00267
00268
00269 name = decodeEntryName(QCString(buffer, 101));
00270 if (symlink.isEmpty())
00271
00272 symlink = decodeEntryName(QCString(buffer + 0x9d, 101));
00273
00274 return 0x200;
00275 }
00276
00277
00278
00279
00280
00281
00282 bool KTar::KTarPrivate::fillTempFile( const QString & filename) {
00283 if ( ! tmpFile )
00284 return true;
00285
00286 kdDebug( 7041 ) <<
00287 "KTar::openArchive: filling tmpFile of mimetype '" << mimetype <<
00288 "' ... " << endl;
00289
00290 bool forced = false;
00291 if( "application/x-gzip" == mimetype
00292 || "application/x-bzip2" == mimetype)
00293 forced = true;
00294
00295 QIODevice *filterDev = KFilterDev::deviceForFile( filename, mimetype, forced );
00296
00297 if( filterDev ) {
00298 QFile* file = tmpFile->file();
00299 file->close();
00300 if ( ! file->open( IO_WriteOnly ) )
00301 {
00302 delete filterDev;
00303 return false;
00304 }
00305 QByteArray buffer(8*1024);
00306 if ( ! filterDev->open( IO_ReadOnly ) )
00307 {
00308 delete filterDev;
00309 return false;
00310 }
00311 Q_LONG len = -1;
00312 while ( !filterDev->atEnd() && len != 0) {
00313 len = filterDev->readBlock(buffer.data(),buffer.size());
00314 if ( len < 0 ) {
00315 delete filterDev;
00316 return false;
00317 }
00318 file->writeBlock(buffer.data(),len);
00319 }
00320 filterDev->close();
00321 delete filterDev;
00322
00323 file->close();
00324 if ( ! file->open( IO_ReadOnly ) )
00325 return false;
00326 }
00327 else
00328 kdDebug( 7041 ) << "KTar::openArchive: no filterdevice found!" << endl;
00329
00330 kdDebug( 7041 ) << "KTar::openArchive: filling tmpFile finished." << endl;
00331 return true;
00332 }
00333
00334 bool KTar::openArchive( int mode )
00335 {
00336 kdDebug( 7041 ) << "KTar::openArchive" << endl;
00337 if ( !(mode & IO_ReadOnly) )
00338 return true;
00339
00340 if ( !d->fillTempFile( m_filename ) )
00341 return false;
00342
00343
00344
00345
00346
00347
00348 d->dirList.clear();
00349 QIODevice* dev = device();
00350
00351 if ( !dev )
00352 return false;
00353
00354
00355 char buffer[ 0x200 ];
00356 bool ende = false;
00357 do
00358 {
00359 QString name;
00360 QString symlink;
00361
00362
00363 Q_LONG n = readHeader(buffer,name,symlink);
00364 if (n < 0) return false;
00365 if (n == 0x200)
00366 {
00367 bool isdir = false;
00368 QString nm;
00369
00370 if ( name.right(1) == "/" )
00371 {
00372 isdir = true;
00373 name = name.left( name.length() - 1 );
00374 }
00375
00376 int pos = name.findRev( '/' );
00377 if ( pos == -1 )
00378 nm = name;
00379 else
00380 nm = name.mid( pos + 1 );
00381
00382
00383 buffer[ 0x6b ] = 0;
00384 char *dummy;
00385 const char* p = buffer + 0x64;
00386 while( *p == ' ' ) ++p;
00387 int access = (int)strtol( p, &dummy, 8 );
00388
00389
00390 QString user( buffer + 0x109 );
00391 QString group( buffer + 0x129 );
00392
00393
00394 buffer[ 0x93 ] = 0;
00395 p = buffer + 0x88;
00396 while( *p == ' ' ) ++p;
00397 int time = (int)strtol( p, &dummy, 8 );
00398
00399
00400 char typeflag = buffer[ 0x9c ];
00401
00402
00403
00404 if ( typeflag == '5' )
00405 isdir = true;
00406
00407 bool isDumpDir = false;
00408 if ( typeflag == 'D' )
00409 {
00410 isdir = false;
00411 isDumpDir = true;
00412 }
00413
00414
00415
00416 if (isdir)
00417 access |= S_IFDIR;
00418
00419 KArchiveEntry* e;
00420 if ( isdir )
00421 {
00422
00423 e = new KArchiveDirectory( this, nm, access, time, user, group, symlink );
00424 }
00425 else
00426 {
00427
00428 buffer[ 0x88 ] = 0;
00429 char *dummy;
00430 const char* p = buffer + 0x7c;
00431 while( *p == ' ' ) ++p;
00432 int size = (int)strtol( p, &dummy, 8 );
00433
00434
00435 if ( isDumpDir )
00436 {
00437
00438 e = new KArchiveDirectory( this, nm, access, time, user, group, symlink );
00439 }
00440 else
00441 {
00442
00443
00444 if ( typeflag == '1' )
00445 {
00446 kdDebug(7041) << "HARD LINK, setting size to 0 instead of " << size << endl;
00447 size = 0;
00448 }
00449
00450
00451 e = new KArchiveFile( this, nm, access, time, user, group, symlink,
00452 dev->at(), size );
00453 }
00454
00455
00456 int rest = size % 0x200;
00457 int skip = size + (rest ? 0x200 - rest : 0);
00458
00459 if (! dev->at( dev->at() + skip ) )
00460 kdWarning(7041) << "KTar::openArchive skipping " << skip << " failed" << endl;
00461 }
00462
00463 if ( pos == -1 )
00464 {
00465 if ( nm == "." )
00466 {
00467 Q_ASSERT( isdir );
00468 if ( isdir )
00469 setRootDir( static_cast<KArchiveDirectory *>( e ) );
00470 }
00471 else
00472 rootDir()->addEntry( e );
00473 }
00474 else
00475 {
00476
00477 QString path = QDir::cleanDirPath( name.left( pos ) );
00478
00479 KArchiveDirectory * d = findOrCreate( path );
00480 d->addEntry( e );
00481 }
00482 }
00483 else
00484 {
00485
00486 d->tarEnd = dev->at() - n;
00487 ende = true;
00488 }
00489 } while( !ende );
00490 return true;
00491 }
00492
00493
00494
00495
00496
00497
00498 bool KTar::KTarPrivate::writeBackTempFile( const QString & filename ) {
00499 if ( ! tmpFile )
00500 return true;
00501
00502 kdDebug(7041) << "Write temporary file to compressed file" << endl;
00503 kdDebug(7041) << filename << " " << mimetype << endl;
00504
00505 bool forced = false;
00506 if( "application/x-gzip" == mimetype
00507 || "application/x-bzip2" == mimetype)
00508 forced = true;
00509
00510
00511 QIODevice *dev = KFilterDev::deviceForFile( filename, mimetype, forced );
00512 if( dev ) {
00513 QFile* file = tmpFile->file();
00514 file->close();
00515 if ( ! file->open(IO_ReadOnly) || ! dev->open(IO_WriteOnly) )
00516 {
00517 file->close();
00518 delete dev;
00519 return false;
00520 }
00521 if ( forced )
00522 static_cast<KFilterDev *>(dev)->setOrigFileName( origFileName );
00523 QByteArray buffer(8*1024);
00524 Q_LONG len;
00525 while ( ! file->atEnd()) {
00526 len = file->readBlock(buffer.data(),buffer.size());
00527 dev->writeBlock(buffer.data(),len);
00528 }
00529 file->close();
00530 dev->close();
00531 delete dev;
00532 }
00533
00534 kdDebug(7041) << "Write temporary file to compressed file done." << endl;
00535 return true;
00536 }
00537
00538 bool KTar::closeArchive()
00539 {
00540 d->dirList.clear();
00541
00542
00543
00544
00545 if( mode() == IO_WriteOnly)
00546 return d->writeBackTempFile( m_filename );
00547
00548 return true;
00549 }
00550
00551 bool KTar::writeDir( const QString& name, const QString& user, const QString& group )
00552 {
00553 mode_t perm = 040755;
00554 time_t the_time = time(0);
00555 return writeDir(name,user,group,perm,the_time,the_time,the_time);
00556 #if 0
00557 if ( !isOpened() )
00558 {
00559 kdWarning(7041) << "KTar::writeDir: You must open the tar file before writing to it\n";
00560 return false;
00561 }
00562
00563 if ( !(mode() & IO_WriteOnly) )
00564 {
00565 kdWarning(7041) << "KTar::writeDir: You must open the tar file for writing\n";
00566 return false;
00567 }
00568
00569
00570 QString dirName ( QDir::cleanDirPath( name ) );
00571
00572
00573 if ( dirName.right(1) != "/" )
00574 dirName += "/";
00575
00576 if ( d->dirList.contains( dirName ) )
00577 return true;
00578
00579 char buffer[ 0x201 ];
00580 memset( buffer, 0, 0x200 );
00581 if ( mode() & IO_ReadWrite ) device()->at(d->tarEnd);
00582
00583
00584 if ( dirName.length() > 99 )
00585 {
00586 strcpy( buffer, "././@LongLink" );
00587 fillBuffer( buffer, " 0", dirName.length()+1, 'L', user.local8Bit(), group.local8Bit() );
00588 device()->writeBlock( buffer, 0x200 );
00589 strncpy( buffer, QFile::encodeName(dirName), 0x200 );
00590 buffer[0x200] = 0;
00591
00592 device()->writeBlock( buffer, 0x200 );
00593
00594 }
00595 else
00596 {
00597
00598 strncpy( buffer, QFile::encodeName(dirName), 0x200 );
00599 buffer[0x200] = 0;
00600 }
00601
00602 fillBuffer( buffer, " 40755", 0, 0x35, user.local8Bit(), group.local8Bit());
00603
00604
00605 device()->writeBlock( buffer, 0x200 );
00606 if ( mode() & IO_ReadWrite ) d->tarEnd = device()->at();
00607
00608 d->dirList.append( dirName );
00609 return true;
00610 #endif
00611 }
00612
00613 bool KTar::prepareWriting( const QString& name, const QString& user, const QString& group, uint size )
00614 {
00615 mode_t dflt_perm = 0100644;
00616 time_t the_time = time(0);
00617 return prepareWriting(name,user,group,size,dflt_perm,
00618 the_time,the_time,the_time);
00619 }
00620
00621 bool KTar::doneWriting( uint size )
00622 {
00623
00624 int rest = size % 0x200;
00625 if ( mode() & IO_ReadWrite )
00626 d->tarEnd = device()->at() + (rest ? 0x200 - rest : 0);
00627 if ( rest )
00628 {
00629 char buffer[ 0x201 ];
00630 for( uint i = 0; i < 0x200; ++i )
00631 buffer[i] = 0;
00632 Q_LONG nwritten = device()->writeBlock( buffer, 0x200 - rest );
00633 return nwritten == 0x200 - rest;
00634 }
00635 return true;
00636 }
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661 void KTar::fillBuffer( char * buffer,
00662 const char * mode, int size, time_t mtime, char typeflag,
00663 const char * uname, const char * gname )
00664 {
00665
00666 assert( strlen(mode) == 6 );
00667 strcpy( buffer+0x64, mode );
00668 buffer[ 0x6a ] = ' ';
00669 buffer[ 0x6b ] = '\0';
00670
00671
00672 strcpy( buffer + 0x6c, " 765 ");
00673
00674 strcpy( buffer + 0x74, " 144 ");
00675
00676
00677 QCString s;
00678 s.sprintf("%o", size);
00679 s = s.rightJustify( 11, ' ' );
00680 strcpy( buffer + 0x7c, s.data() );
00681 buffer[ 0x87 ] = ' ';
00682
00683
00684 s.sprintf("%lo", static_cast<unsigned long>(mtime) );
00685 s = s.rightJustify( 11, ' ' );
00686 strcpy( buffer + 0x88, s.data() );
00687 buffer[ 0x93 ] = ' ';
00688
00689
00690 buffer[ 0x94 ] = 0x20;
00691 buffer[ 0x95 ] = 0x20;
00692 buffer[ 0x96 ] = 0x20;
00693 buffer[ 0x97 ] = 0x20;
00694 buffer[ 0x98 ] = 0x20;
00695 buffer[ 0x99 ] = 0x20;
00696
00697
00698
00699
00700
00701
00702 buffer[ 0x9a ] = '\0';
00703 buffer[ 0x9b ] = ' ';
00704
00705
00706 buffer[ 0x9c ] = typeflag;
00707
00708
00709 strcpy( buffer + 0x101, "ustar");
00710 strcpy( buffer + 0x107, "00" );
00711
00712
00713 strcpy( buffer + 0x109, uname );
00714
00715 strcpy( buffer + 0x129, gname );
00716
00717
00718 int check = 32;
00719 for( uint j = 0; j < 0x200; ++j )
00720 check += buffer[j];
00721 s.sprintf("%o", check );
00722 s = s.rightJustify( 7, ' ' );
00723 strcpy( buffer + 0x94, s.data() );
00724 }
00725
00726 void KTar::writeLonglink(char *buffer, const QCString &name, char typeflag,
00727 const char *uname, const char *gname) {
00728 strcpy( buffer, "././@LongLink" );
00729 int namelen = name.length() + 1;
00730 fillBuffer( buffer, " 0", namelen, 0, typeflag, uname, gname );
00731 device()->writeBlock( buffer, 0x200 );
00732 int offset = 0;
00733 while (namelen > 0) {
00734 int chunksize = QMIN(namelen, 0x200);
00735 memcpy(buffer, name.data()+offset, chunksize);
00736
00737 device()->writeBlock( buffer, 0x200 );
00738
00739 namelen -= chunksize;
00740 offset += 0x200;
00741 }
00742 }
00743
00744 bool KTar::prepareWriting(const QString& name, const QString& user,
00745 const QString& group, uint size, mode_t perm,
00746 time_t atime, time_t mtime, time_t ctime) {
00747 return KArchive::prepareWriting(name,user,group,size,perm,atime,mtime,ctime);
00748 }
00749
00750 bool KTar::prepareWriting_impl(const QString &name, const QString &user,
00751 const QString &group, uint size, mode_t perm,
00752 time_t , time_t mtime, time_t ) {
00753 if ( !isOpened() )
00754 {
00755 kdWarning(7041) << "KTar::prepareWriting: You must open the tar file before writing to it\n";
00756 return false;
00757 }
00758
00759 if ( !(mode() & IO_WriteOnly) )
00760 {
00761 kdWarning(7041) << "KTar::prepareWriting: You must open the tar file for writing\n";
00762 return false;
00763 }
00764
00765
00766 QString fileName ( QDir::cleanDirPath( name ) );
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787 char buffer[ 0x201 ];
00788 memset( buffer, 0, 0x200 );
00789 if ( mode() & IO_ReadWrite ) device()->at(d->tarEnd);
00790
00791
00792 QCString encodedFilename = QFile::encodeName(fileName);
00793 QCString uname = user.local8Bit();
00794 QCString gname = group.local8Bit();
00795
00796
00797 if ( fileName.length() > 99 )
00798 writeLonglink(buffer,encodedFilename,'L',uname,gname);
00799
00800
00801 strncpy( buffer, encodedFilename, 99 );
00802 buffer[99] = 0;
00803
00804 memset(buffer+0x9d, 0, 0x200 - 0x9d);
00805
00806 QCString permstr;
00807 permstr.sprintf("%o",perm);
00808 permstr = permstr.rightJustify(6, ' ');
00809 fillBuffer(buffer, permstr, size, mtime, 0x30, uname, gname);
00810
00811
00812 return device()->writeBlock( buffer, 0x200 ) == 0x200;
00813 }
00814
00815 bool KTar::writeDir(const QString& name, const QString& user,
00816 const QString& group, mode_t perm,
00817 time_t atime, time_t mtime, time_t ctime) {
00818 return KArchive::writeDir(name,user,group,perm,atime,mtime,ctime);
00819 }
00820
00821 bool KTar::writeDir_impl(const QString &name, const QString &user,
00822 const QString &group, mode_t perm,
00823 time_t , time_t mtime, time_t ) {
00824 if ( !isOpened() )
00825 {
00826 kdWarning(7041) << "KTar::writeDir: You must open the tar file before writing to it\n";
00827 return false;
00828 }
00829
00830 if ( !(mode() & IO_WriteOnly) )
00831 {
00832 kdWarning(7041) << "KTar::writeDir: You must open the tar file for writing\n";
00833 return false;
00834 }
00835
00836
00837 QString dirName ( QDir::cleanDirPath( name ) );
00838
00839
00840 if ( dirName.right(1) != "/" )
00841 dirName += "/";
00842
00843 if ( d->dirList.contains( dirName ) )
00844 return true;
00845
00846 char buffer[ 0x201 ];
00847 memset( buffer, 0, 0x200 );
00848 if ( mode() & IO_ReadWrite ) device()->at(d->tarEnd);
00849
00850
00851 QCString encodedDirname = QFile::encodeName(dirName);
00852 QCString uname = user.local8Bit();
00853 QCString gname = group.local8Bit();
00854
00855
00856 if ( dirName.length() > 99 )
00857 writeLonglink(buffer,encodedDirname,'L',uname,gname);
00858
00859
00860 strncpy( buffer, encodedDirname, 99 );
00861 buffer[99] = 0;
00862
00863 memset(buffer+0x9d, 0, 0x200 - 0x9d);
00864
00865 QCString permstr;
00866 permstr.sprintf("%o",perm);
00867 permstr = permstr.rightJustify(6, ' ');
00868 fillBuffer( buffer, permstr, 0, mtime, 0x35, uname, gname);
00869
00870
00871 device()->writeBlock( buffer, 0x200 );
00872 if ( mode() & IO_ReadWrite ) d->tarEnd = device()->at();
00873
00874 d->dirList.append( dirName );
00875 return true;
00876 }
00877
00878 bool KTar::writeSymLink(const QString &name, const QString &target,
00879 const QString &user, const QString &group,
00880 mode_t perm, time_t atime, time_t mtime, time_t ctime) {
00881 return KArchive::writeSymLink(name,target,user,group,perm,atime,mtime,ctime);
00882 }
00883
00884 bool KTar::writeSymLink_impl(const QString &name, const QString &target,
00885 const QString &user, const QString &group,
00886 mode_t perm, time_t , time_t mtime, time_t ) {
00887 if ( !isOpened() )
00888 {
00889 kdWarning(7041) << "KTar::writeSymLink: You must open the tar file before writing to it\n";
00890 return false;
00891 }
00892
00893 if ( !(mode() & IO_WriteOnly) )
00894 {
00895 kdWarning(7041) << "KTar::writeSymLink: You must open the tar file for writing\n";
00896 return false;
00897 }
00898
00899 device()->flush();
00900
00901
00902 QString fileName ( QDir::cleanDirPath( name ) );
00903
00904 char buffer[ 0x201 ];
00905 memset( buffer, 0, 0x200 );
00906 if ( mode() & IO_ReadWrite ) device()->at(d->tarEnd);
00907
00908
00909 QCString encodedFilename = QFile::encodeName(fileName);
00910 QCString encodedTarget = QFile::encodeName(target);
00911 QCString uname = user.local8Bit();
00912 QCString gname = group.local8Bit();
00913
00914
00915 if (target.length() > 99)
00916 writeLonglink(buffer,encodedTarget,'K',uname,gname);
00917 if ( fileName.length() > 99 )
00918 writeLonglink(buffer,encodedFilename,'L',uname,gname);
00919
00920
00921 strncpy( buffer, encodedFilename, 99 );
00922 buffer[99] = 0;
00923
00924 strncpy(buffer+0x9d, encodedTarget, 99);
00925 buffer[0x9d+99] = 0;
00926
00927 memset(buffer+0x9d+100, 0, 0x200 - 100 - 0x9d);
00928
00929 QCString permstr;
00930 permstr.sprintf("%o",perm);
00931 permstr = permstr.rightJustify(6, ' ');
00932 fillBuffer(buffer, permstr, 0, mtime, 0x32, uname, gname);
00933
00934
00935 bool retval = device()->writeBlock( buffer, 0x200 ) == 0x200;
00936 if ( mode() & IO_ReadWrite ) d->tarEnd = device()->at();
00937 return retval;
00938 }
00939
00940 void KTar::virtual_hook( int id, void* data ) {
00941 switch (id) {
00942 case VIRTUAL_WRITE_SYMLINK: {
00943 WriteSymlinkParams *params = reinterpret_cast<WriteSymlinkParams *>(data);
00944 params->retval = writeSymLink_impl(*params->name,*params->target,
00945 *params->user,*params->group,params->perm,
00946 params->atime,params->mtime,params->ctime);
00947 break;
00948 }
00949 case VIRTUAL_WRITE_DIR: {
00950 WriteDirParams *params = reinterpret_cast<WriteDirParams *>(data);
00951 params->retval = writeDir_impl(*params->name,*params->user,
00952 *params->group,params->perm,
00953 params->atime,params->mtime,params->ctime);
00954 break;
00955 }
00956 case VIRTUAL_PREPARE_WRITING: {
00957 PrepareWritingParams *params = reinterpret_cast<PrepareWritingParams *>(data);
00958 params->retval = prepareWriting_impl(*params->name,*params->user,
00959 *params->group,params->size,params->perm,
00960 params->atime,params->mtime,params->ctime);
00961 break;
00962 }
00963 default:
00964 KArchive::virtual_hook( id, data );
00965 }
00966 }
00967