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