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