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