"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "zutils.cc" between
zutils-1.8.tar.lz and zutils-1.9.tar.lz

About: Zutils is a collection of utilities able to deal with any combination of compressed and non-compressed files transparently. The utilities zcat, zcmp, zdiff, zgrep and ztest supports the compressors bzip2, gzip, lzip and xz.

zutils.cc  (zutils-1.8.tar.lz):zutils.cc  (zutils-1.9.tar.lz)
/* Zutils - Utilities dealing with compressed files /* Zutils - Utilities dealing with compressed files
Copyright (C) 2009-2019 Antonio Diaz Diaz. Copyright (C) 2009-2020 Antonio Diaz Diaz.
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or the Free Software Foundation, either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#define _FILE_OFFSET_BITS 64 #define _FILE_OFFSET_BITS 64
#include <cerrno> #include <cerrno>
#include <csignal> #include <csignal>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <string> #include <string>
#include <vector> #include <vector>
#include <stdint.h> #include <stdint.h>
#include <unistd.h> #include <unistd.h>
#include <sys/wait.h> #include <sys/wait.h>
#include "rc.h" #include "rc.h"
#include "zutils.h" #include "zutils.h"
namespace { namespace {
// first magic byte must be different among formats inline bool isvalid_ds( const uint8_t ds ) // lzip valid dictionary_size
enum { bzip2_magic_size = 3, {
gzip_magic_size = 2, enum { min_dictionary_size = 1 << 12,
lzip_magic_size = 4, max_dictionary_size = 1 << 29 };
xz_magic_size = 5 }; unsigned dictionary_size = ( 1 << ( ds & 0x1F ) );
const uint8_t bzip2_magic[bzip2_magic_size] = if( dictionary_size > min_dictionary_size )
{ 0x42, 0x5A, 0x68 }; // "BZh" dictionary_size -= ( dictionary_size / 16 ) * ( ( ds >> 5 ) & 7 );
const uint8_t gzip_magic[gzip_magic_size] = return ( dictionary_size >= min_dictionary_size &&
{ 0x1F, 0x8B }; dictionary_size <= max_dictionary_size );
const uint8_t lzip_magic[lzip_magic_size] = }
{ 0x4C, 0x5A, 0x49, 0x50 }; // "LZIP"
const uint8_t xz_magic[xz_magic_size] =
{ 0xFD, 0x37, 0x7A, 0x58, 0x5A }; // 0xFD, "7zXZ"
// Returns -1 if child not terminated, 2 in case of error, or /* Returns -1 if child not terminated, 2 in case of error, or exit status of
// exit status of child process 'pid'. child process 'pid'.
// */
int child_status( const pid_t pid, const char * const name ) int child_status( const pid_t pid, const char * const name )
{ {
int status; int status;
while( true ) while( true )
{ {
const int tmp = waitpid( pid, &status, WNOHANG ); const int tmp = waitpid( pid, &status, WNOHANG );
if( tmp == -1 && errno != EINTR ) if( tmp == -1 && errno != EINTR )
{ {
if( verbosity >= 0 ) if( verbosity >= 0 )
std::fprintf( stderr, "%s: Error checking status of '%s': %s\n", std::fprintf( stderr, "%s: Error checking status of '%s': %s\n",
program_name, name, std::strerror( errno ) ); program_name, name, std::strerror( errno ) );
_exit( 2 ); _exit( 2 );
} }
if( tmp == 0 ) return -1; // child not terminated if( tmp == 0 ) return -1; // child not terminated
if( tmp == pid ) break; // child terminated if( tmp == pid ) break; // child terminated
} }
if( WIFEXITED( status ) ) return WEXITSTATUS( status ); if( WIFEXITED( status ) ) return WEXITSTATUS( status );
if( WIFSIGNALED( status ) && WTERMSIG( status ) == SIGPIPE ) return 0;
return 2; return 2;
} }
} // end namespace } // end namespace
// Returns the number of bytes really read. /* Returns the number of bytes really read.
// If (returned value < size) and (errno == 0), means EOF was reached. If (returned value < size) and (errno == 0), means EOF was reached.
// */
int readblock( const int fd, uint8_t * const buf, const int size ) int readblock( const int fd, uint8_t * const buf, const int size )
{ {
int sz = 0; int sz = 0;
errno = 0; errno = 0;
while( sz < size ) while( sz < size )
{ {
const int n = read( fd, buf + sz, size - sz ); const int n = read( fd, buf + sz, size - sz );
if( n > 0 ) sz += n; if( n > 0 ) sz += n;
else if( n == 0 ) break; // EOF else if( n == 0 ) break; // EOF
else if( errno != EINTR ) break; else if( errno != EINTR ) break;
errno = 0; errno = 0;
} }
return sz; return sz;
} }
// Returns the number of bytes really written. /* Returns the number of bytes really written.
// If (returned value < size), it is always an error. If (returned value < size), it is always an error.
// */
int writeblock( const int fd, const uint8_t * const buf, const int size ) int writeblock( const int fd, const uint8_t * const buf, const int size )
{ {
int sz = 0; int sz = 0;
errno = 0; errno = 0;
while( sz < size ) while( sz < size )
{ {
const int n = write( fd, buf + sz, size - sz ); const int n = write( fd, buf + sz, size - sz );
if( n > 0 ) sz += n; if( n > 0 ) sz += n;
else if( n < 0 && errno != EINTR ) break; else if( n < 0 && errno != EINTR ) break;
errno = 0; errno = 0;
skipping to change at line 141 skipping to change at line 139
bool good_status( const Children & children, const bool finished ) bool good_status( const Children & children, const bool finished )
{ {
bool error = false; bool error = false;
for( int i = 0; i < 2; ++i ) for( int i = 0; i < 2; ++i )
{ {
const pid_t pid = children.pid[i]; const pid_t pid = children.pid[i];
if( pid ) if( pid )
{ {
const char * const name = const char * const name =
( i & 1 ) ? children.compressor_name : "data feeder"; ( i == 0 ) ? "data feeder" : children.compressor_name;
if( !finished ) // even if compressor finished, trailing data may remain in data feeder
if( i == 0 || !finished )
{ {
const int tmp = child_status( pid, name ); const int tmp = child_status( pid, name );
if( tmp < 0 ) // child not terminated if( tmp < 0 ) // child not terminated
{ kill( pid, SIGTERM ); wait_for_child( pid, name ); } { kill( pid, SIGTERM ); wait_for_child( pid, name ); }
else if( tmp != 0 ) error = true; // child status != 0 else if( tmp != 0 ) error = true; // child status != 0
} }
else else
if( wait_for_child( pid, name ) != 0 ) error = true; if( wait_for_child( pid, name ) != 0 ) error = true;
} }
} }
return !error; return !error;
} }
bool set_data_feeder( const std::string & filename, int * const infdp, bool set_data_feeder( const std::string & filename, int * const infdp,
Children & children, int format_index ) Children & children, int format_index )
{ {
const uint8_t * magic_data = 0; uint8_t magic_data[magic_buf_size];
int magic_size = 0; int magic_size = 0;
if( format_index < 0 ) if( format_index < 0 )
format_index = test_format( *infdp, &magic_data, &magic_size ); format_index = test_format( *infdp, magic_data, &magic_size );
children.compressor_name = get_compressor_name( format_index ); children.compressor_name = get_compressor_name( format_index );
if( children.compressor_name ) // compressed if( children.compressor_name ) // compressed
{ {
int fda[2]; // pipe from feeder int fda[2]; // pipe from feeder
int fda2[2]; // pipe from compressor int fda2[2]; // pipe from compressor
if( pipe( fda ) < 0 || pipe( fda2 ) < 0 ) if( pipe( fda ) < 0 || pipe( fda2 ) < 0 )
{ show_error( "Can't create pipe", errno ); return false; } { show_error( "Can't create pipe", errno ); return false; }
const int old_infd = *infdp; const int old_infd = *infdp;
*infdp = fda2[0]; *infdp = fda2[0];
skipping to change at line 242 skipping to change at line 241
} }
if( pid < 0 ) // parent if( pid < 0 ) // parent
{ show_fork_error( "data feeder" ); return false; } { show_fork_error( "data feeder" ); return false; }
close( fda[1] ); close( fda[1] );
children.pid[0] = pid; children.pid[0] = pid;
children.pid[1] = 0; children.pid[1] = 0;
} }
return true; return true;
} }
int test_format( const int infd, const uint8_t ** const magic_datap, // Returns format index or -1 if uncompressed
//
int test_format( const int infd, uint8_t magic_data[],
int * const magic_sizep ) int * const magic_sizep )
{ {
enum { buf_size = 5 }; enum { bzip2_magic_size = 3,
static uint8_t buf[buf_size]; gzip_magic_size = 2,
int i = 0; lzip_magic_size = 5,
if( readblock( infd, buf, 1 ) == 1 ) xz_magic_size = 5 };
const uint8_t bzip2_magic[bzip2_magic_size] =
{ 0x42, 0x5A, 0x68 }; // "BZh"
const uint8_t gzip_magic[gzip_magic_size] =
{ 0x1F, 0x8B };
const uint8_t lzip_magic[lzip_magic_size] =
{ 0x4C, 0x5A, 0x49, 0x50, 0x01 }; // "LZIP\001"
const uint8_t xz_magic[xz_magic_size] =
{ 0xFD, 0x37, 0x7A, 0x58, 0x5A }; // 0xFD, "7zXZ"
*magic_sizep = readblock( infd, magic_data, magic_buf_size );
if( *magic_sizep == magic_buf_size )
{ {
++i; if( std::memcmp( magic_data, bzip2_magic, bzip2_magic_size ) == 0 &&
if( buf[0] == bzip2_magic[0] ) magic_data[3] >= '1' && magic_data[3] <= '9' &&
{ std::memcmp( magic_data + 4, "1AY&SY", 6 ) == 0 )
if( readblock( infd, &buf[i], 1 ) == 1 && buf[i++] == bzip2_magic[1] && return fmt_bz2;
readblock( infd, &buf[i], 1 ) == 1 && buf[i++] == bzip2_magic[2] ) if( std::memcmp( magic_data, gzip_magic, gzip_magic_size ) == 0 )
{ *magic_datap = bzip2_magic; *magic_sizep = bzip2_magic_size; return fmt_gz;
return fmt_bz2; } if( std::memcmp( magic_data, lzip_magic, lzip_magic_size ) == 0 &&
} isvalid_ds( magic_data[lzip_magic_size] ) )
else if( buf[0] == gzip_magic[0] ) return fmt_lz;
{ if( std::memcmp( magic_data, xz_magic, xz_magic_size ) == 0 )
if( readblock( infd, &buf[i], 1 ) == 1 && buf[i++] == gzip_magic[1] ) return fmt_xz;
{ *magic_datap = gzip_magic; *magic_sizep = gzip_magic_size;
return fmt_gz; }
}
else if( buf[0] == lzip_magic[0] )
{
if( readblock( infd, &buf[i], 1 ) == 1 && buf[i++] == lzip_magic[1] &&
readblock( infd, &buf[i], 1 ) == 1 && buf[i++] == lzip_magic[2] &&
readblock( infd, &buf[i], 1 ) == 1 && buf[i++] == lzip_magic[3] )
{ *magic_datap = lzip_magic; *magic_sizep = lzip_magic_size;
return fmt_lz; }
}
else if( buf[0] == xz_magic[0] )
{
if( readblock( infd, &buf[i], 1 ) == 1 && buf[i++] == xz_magic[1] &&
readblock( infd, &buf[i], 1 ) == 1 && buf[i++] == xz_magic[2] &&
readblock( infd, &buf[i], 1 ) == 1 && buf[i++] == xz_magic[3] &&
readblock( infd, &buf[i], 1 ) == 1 && buf[i++] == xz_magic[4] )
{ *magic_datap = xz_magic; *magic_sizep = xz_magic_size;
return fmt_xz; }
}
} }
*magic_datap = buf; *magic_sizep = i;
return -1; return -1;
} }
 End of changes. 15 change blocks. 
76 lines changed or deleted 67 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)