23 # include <sys/utime.h>
24 # include <sys/timeb.h>
26 # include <winsock2.h>
34 # define utimbuf _utimbuf
36 # define ssize_t SSIZE_T
41 # include <sys/time.h>
44 #define LONGFILE "././@LongLink"
61 return create( archive, dir, list );
78 if ( list ) list->clear();
80 for (
int i = 0; i < files.size(); i++ )
82 QString current = files[ i ];
83 QFileInfo f( current );
90 if ( current.endsWith(
"/" ) )
92 current = current.left( current.length() - 1 );
96 process_dir( current, all );
114 if ( list ) *list = all;
121 ofd = open( archive.toLatin1(), O_WRONLY | O_CREAT |
O_BINARY, 0644 );
125 QStringList::iterator it = all.begin();
131 while ( it != all.end() )
133 write_file ( *it++ );
142 unlink( archive.toLatin1() );
153 QStringList files = dir.entryList( QDir::Files | QDir::NoSymLinks );
154 QStringList::Iterator it = files.begin();
157 while( it != files.end() )
159 all << path +
"/" + *it;
163 QStringList dirs = dir.entryList( QDir::Dirs );
167 while ( it != dirs.end() )
169 if ( *it !=
"." && *it !=
".." )
171 all << path +
"/" + *it +
"/";
172 process_dir( path +
"/" + *it, all );
184 #define TUWRITE 00200
187 #define TGWRITE 00020
190 #define TOWRITE 00002
199 int ret = stat( file.toLatin1(), &stats );
202 memset( (
void*) tar_header.h, 0,
sizeof( tar_header ) );
205 if ( file.length() > (int)
sizeof( tar_header.header.name ) - 1 )
206 write_long_filename( file );
208 strcpy( tar_header.header.name, file.toLatin1() );
215 sprintf ( tar_header.header.mode,
"%07o", stats.st_mode & perms );
216 sprintf ( tar_header.header.uid,
"%07o", stats.st_uid );
217 sprintf ( tar_header.header.gid,
"%07o", stats.st_gid );
218 sprintf ( tar_header.header.size,
"%011o", (
unsigned int) stats.st_size );
219 sprintf ( tar_header.header.mtime,
"%011o", (
unsigned int) stats.st_mtime );
222 memcpy( &tar_header.header.chksum,
" ",
sizeof tar_header.header.chksum );
226 if ( f.isDir() ) tar_header.header.typeflag =
'5';
227 else if ( f.isFile() ) tar_header.header.typeflag =
'0';
234 memcpy( tar_header.header.magic,
"ustar ", 6 );
235 memcpy( tar_header.header.version,
" ", 2 );
240 struct passwd* pwbuf = getpwuid( stats.st_uid );
241 if ( pwbuf ) sprintf ( tar_header.header.uname,
"%s", pwbuf->pw_name );
244 struct group* grpbuf = getgrgid( stats.st_gid );
245 if ( grpbuf ) sprintf ( tar_header.header.gname,
"%s", grpbuf->gr_name );
253 char*
p = (
char*) &tar_header;
255 for (
int i =
sizeof tar_header; i-- != 0; )
259 sprintf ( tar_header.header.chksum,
"%06o", sum );
262 memcpy( (
void*) ( buffer + blocks_written *
BLOCK_SIZE ),
263 (
void*) tar_header.h,
273 ifd = open( file.toLatin1(), O_RDONLY |
O_BINARY );
280 if ( full_blocks > 0 && space >= full_blocks )
282 input = read( ifd, buffer + blocks_written * BLOCK_SIZE,
283 full_blocks * BLOCK_SIZE );
284 if ( input != full_blocks * BLOCK_SIZE )
throw TAR_READERROR;
285 blocks_written += full_blocks;
288 else if ( full_blocks > 0 )
290 input = read( ifd, buffer + blocks_written * BLOCK_SIZE,
291 space * BLOCK_SIZE );
292 blocks_written += space;
293 full_blocks -= space;
300 input = read( ifd, buffer, space * BLOCK_SIZE );
302 blocks_written += space;
303 full_blocks -= space;
308 input = read( ifd, buffer, full_blocks * BLOCK_SIZE );
309 if ( input != full_blocks * BLOCK_SIZE )
throw TAR_READERROR;
310 blocks_written += full_blocks;
317 input = read( ifd, buffer + blocks_written * BLOCK_SIZE, BLOCK_SIZE );
323 memset( buffer + blocks_written * BLOCK_SIZE + input, 0,
324 BLOCK_SIZE - input );
339 unsigned int length = (
unsigned int) filename.length() + 1;
342 strcpy( tar_header.header.name,
LONGFILE );
350 sprintf ( tar_header.header.mode,
"%07o", 0 );
351 sprintf ( tar_header.header.uid,
"%07o", 0 );
352 sprintf ( tar_header.header.gid,
"%07o", 0 );
353 sprintf ( tar_header.header.size,
"%011o", length );
354 sprintf ( tar_header.header.mtime,
"%011o", 0 );
357 memcpy( &tar_header.header.chksum,
" ",
sizeof tar_header.header.chksum );
361 tar_header.header.typeflag =
'L';
367 memcpy( tar_header.header.magic,
"ustar ", 6 );
368 memcpy( tar_header.header.version,
" ", 2 );
372 strcpy ( tar_header.header.uname,
"root" );
373 strcpy ( tar_header.header.gname,
"root" );
381 char*
p = (
char*) &tar_header;
383 for (
int i =
sizeof tar_header; i-- != 0; )
388 sprintf ( tar_header.header.chksum,
"%06o", sum );
391 memcpy( (
void*) ( buffer + blocks_written *
BLOCK_SIZE ),
392 (
void*) tar_header.h,
402 for (
int i = 0; i < full_blocks; i++ )
404 memset( (
void*) tar_header.h, 0,
sizeof tar_header );
406 memcpy( (
void*) tar_header.h,
407 (
void*) filename.mid( i * BLOCK_SIZE, BLOCK_SIZE ).constData(),
411 memcpy( (
void*) ( buffer + blocks_written * BLOCK_SIZE ),
412 (
void*) tar_header.h,
421 if ( ( length ) % BLOCK_SIZE )
423 memset( (
void*) tar_header.h, 0,
sizeof tar_header );
425 memcpy( (
void*) tar_header.h,
426 (
void*) filename.mid( full_blocks * BLOCK_SIZE ).constData(),
430 memcpy( (
void*) ( buffer + blocks_written * BLOCK_SIZE ),
431 (
void*) tar_header.h,
440 memset( (
void*) tar_header.h, 0,
sizeof( tar_header ) );
441 memcpy( (
void*) tar_header.h, filename.toLatin1(), 100 );
447 void* location = (
void*) ( buffer + blocks_written *
BLOCK_SIZE );
448 memset( location, 0, BLOCK_SIZE );
454 location = (
void*) ( buffer + blocks_written * BLOCK_SIZE );
455 memset( location, 0, BLOCK_SIZE );
463 if ( blocks_written == 0 )
return;
468 void* location = (
void*) ( buffer + blocks_written *
BLOCK_SIZE );
469 memset( location, 0, size );
472 int ret = write( ofd, buffer,
sizeof buffer );
496 ifd = open( archive.toLatin1(), O_RDONLY |
O_BINARY );
499 if ( list ) list->clear();
515 bool zero = validate_header();
521 bool second_zero = validate_header();
537 if ( tar_header.header.typeflag ==
'L' )
538 filename = get_long_filename();
540 filename = tar_header.header.name;
542 QString uname = tar_header.header.uname;
543 QString gname = tar_header.header.gname;
553 sscanf( tar_header.header.mode,
"%7o", &mode );
555 sscanf( tar_header.header.uid,
"%7o", &uid );
556 sscanf( tar_header.header.gid,
"%7o", &gid );
558 sscanf( tar_header.header.size,
"%11o", &fsize );
559 sscanf( tar_header.header.mtime,
"%11o", &mtime );
562 switch ( tar_header.header.typeflag )
578 if ( list ) list->append( filename );
583 if ( ! f.exists( filename ) )
585 bool success = f.mkdir( filename );
590 dirs.append( filename );
591 times.push_back( mtime );
595 int flags = O_WRONLY | O_CREAT |
O_BINARY | O_TRUNC;
596 ofd = open( filename.toLatin1(), flags, 0644 );
601 unsigned int bytes_to_write = fsize;
608 while ( bytes_to_write >
sizeof buffer )
610 size = read( ifd, buffer,
sizeof buffer );
613 size = write( ofd, buffer,
sizeof buffer );
616 bytes_to_write -=
sizeof buffer;
619 size = read( ifd, buffer, bytes_to_write );
622 size = write( ofd, buffer, bytes_to_write );
626 lseek( ifd, skip, SEEK_CUR );
640 gettimeofday( &tv, NULL );
642 struct _timeb timebuffer;
644 tv.tv_sec = timebuffer.time;
645 tv.tv_usec = timebuffer.millitm * 1000;
649 time.actime = tv.tv_sec;
650 time.modtime = mtime;
651 utime( filename.toLatin1(), &time );
655 chmod( filename.toLatin1(), mode );
658 if ( geteuid() != 0 ) uid = (uid_t) -1;
659 int choerr = chown( filename.toAscii(), uid, gid );
660 if ( choerr != 0 ) uid = (uid_t) -1;
667 if ( ofd > 0 ) close( ofd );
670 for (
size_t i = files.size() -1 ; i <= 0; i++ )
672 unlink( files[i].toLatin1() );
681 for (
int i = 0; i < dirs.size(); i++ )
684 time.actime = times[ i ];
685 time.modtime = times[ i ];
687 utime( dirs[ i ].toLatin1(), &time );
696 ifd = open( archive.toLatin1(), O_RDONLY |
O_BINARY );
707 bool zero = validate_header();
713 bool second_zero = validate_header();
728 if ( tar_header.header.typeflag ==
'L' )
729 filename = get_long_filename();
731 filename = tar_header.header.name;
733 QString uname = tar_header.header.uname;
734 QString gname = tar_header.header.gname;
740 sscanf( tar_header.header.mode,
"%7o", &mode );
741 sscanf( tar_header.header.size,
"%11o", &fsize );
742 sscanf( tar_header.header.mtime,
"%11o", &mtime );
745 switch ( tar_header.header.typeflag )
762 files << format_permissions( mode, directory ) +
" " +
763 uname +
"/" + gname +
" " +
764 s.sprintf(
"%10d", fsize ) +
" " +
765 format_datetime( mtime ) +
" " +
772 sscanf( tar_header.header.size,
"%11o", &fsize );
780 lseek( ifd, fsize + skip, SEEK_CUR );
796 QString s =
"----------";
797 if ( dir ) s = s.replace( 0, 1,
"d" );
798 if ( mode & 0400 ) s = s.replace( 1, 1,
"r" );
799 if ( mode & 0200 ) s = s.replace( 2, 1,
"w" );
800 if ( mode & 0100 ) s = s.replace( 3, 1,
"x" );
801 if ( mode & 0040 ) s = s.replace( 4, 1,
"r" );
802 if ( mode & 0020 ) s = s.replace( 5, 1,
"w" );
803 if ( mode & 0010 ) s = s.replace( 6, 1,
"x" );
804 if ( mode & 0004 ) s = s.replace( 7, 1,
"r" );
805 if ( mode & 0002 ) s = s.replace( 8, 1,
"w" );
806 if ( mode & 0001 ) s = s.replace( 9, 1,
"x" );
814 struct tm* t = localtime( &time );
817 s = s.sprintf(
"%04d-%02d-%02d %02d:%02d",
818 t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min );
826 unsigned char*
p = tar_header.h;
827 int unsigned_sum = 0;
830 for ( i =
sizeof tar_header; i-- != 0; )
832 unsigned_sum += (
unsigned char) (*p++);
838 if ( unsigned_sum == 0 )
return true;
841 for ( i =
sizeof tar_header.header.chksum; i-- != 0; )
843 unsigned_sum -= (
unsigned char) tar_header.header.chksum[i];
846 unsigned_sum +=
' ' *
sizeof tar_header.header.chksum;
849 unsigned int parsed_sum;
850 sscanf( tar_header.header.chksum,
"%6o", &parsed_sum );
852 if ( parsed_sum != (
unsigned int ) unsigned_sum )
858 QString magic = tar_header.header.magic;
859 if ( magic !=
"ustar " )
872 sscanf( tar_header.header.size,
"%11o", &length );
876 int final_block = ( length %
BLOCK_SIZE ) ? 1 : 0;
877 int blocks = length /
BLOCK_SIZE + final_block;
879 for (
int i = 0; i < blocks; i++ )
882 filename.append( (
char*) tar_header.h );
891 ssize_t size = read( ifd, tar_header.h,
BLOCK_SIZE );
902 explanation =
"The (un)tar operation was successful.";
906 explanation =
"Could not create the output file." ;
910 explanation =
"Could not find the input file." ;
914 explanation =
"Could not determine the input file status." ;
918 explanation =
"A file name was too long." ;
922 explanation =
"The internal file type was not a file or a directory." ;
926 explanation =
"Could not read input file." ;
930 explanation =
"Could not write an output file." ;
934 explanation =
"The archive was not formatted properly." ;
938 explanation =
"Could not create a directory." ;
942 explanation =
"Unknown return code: " + error;