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