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