mirror of
https://github.com/cuberite/libdeflate.git
synced 2025-09-08 03:39:25 -04:00
programs/gzip: add support for the '-t' option (test file integrity)
The '-t' option of GNU gzip allows checking whether a gzip file is valid without writing the data anywhere. It's relatively straightforward to support in libdeflate-gzip too, so add support for it. Resolves https://github.com/ebiggers/libdeflate/issues/125 [EB - updated commit message]
This commit is contained in:
parent
fbada10aa9
commit
72c81b3332
@ -43,11 +43,12 @@ struct options {
|
|||||||
bool decompress;
|
bool decompress;
|
||||||
bool force;
|
bool force;
|
||||||
bool keep;
|
bool keep;
|
||||||
|
bool test;
|
||||||
int compression_level;
|
int compression_level;
|
||||||
const tchar *suffix;
|
const tchar *suffix;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const tchar *const optstring = T("1::2::3::4::5::6::7::8::9::cdfhknS:V");
|
static const tchar *const optstring = T("1::2::3::4::5::6::7::8::9::cdfhknS:tV");
|
||||||
|
|
||||||
static void
|
static void
|
||||||
show_usage(FILE *fp)
|
show_usage(FILE *fp)
|
||||||
@ -66,6 +67,7 @@ show_usage(FILE *fp)
|
|||||||
" -h print this help\n"
|
" -h print this help\n"
|
||||||
" -k don't delete input files\n"
|
" -k don't delete input files\n"
|
||||||
" -S SUF use suffix SUF instead of .gz\n"
|
" -S SUF use suffix SUF instead of .gz\n"
|
||||||
|
" -t test file integrity\n"
|
||||||
" -V show version and legal information\n",
|
" -V show version and legal information\n",
|
||||||
prog_invocation_name);
|
prog_invocation_name);
|
||||||
}
|
}
|
||||||
@ -183,7 +185,8 @@ load_u32_gzip(const u8 *p)
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
do_decompress(struct libdeflate_decompressor *decompressor,
|
do_decompress(struct libdeflate_decompressor *decompressor,
|
||||||
struct file_stream *in, struct file_stream *out)
|
struct file_stream *in, struct file_stream *out,
|
||||||
|
const struct options *options)
|
||||||
{
|
{
|
||||||
const u8 *compressed_data = in->mmap_mem;
|
const u8 *compressed_data = in->mmap_mem;
|
||||||
size_t compressed_size = in->mmap_size;
|
size_t compressed_size = in->mmap_size;
|
||||||
@ -258,9 +261,11 @@ do_decompress(struct libdeflate_decompressor *decompressor,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = full_write(out, uncompressed_data, actual_out_nbytes);
|
if (!options->test) {
|
||||||
if (ret != 0)
|
ret = full_write(out, uncompressed_data, actual_out_nbytes);
|
||||||
goto out;
|
if (ret != 0)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
compressed_data += actual_in_nbytes;
|
compressed_data += actual_in_nbytes;
|
||||||
compressed_size -= actual_in_nbytes;
|
compressed_size -= actual_in_nbytes;
|
||||||
@ -425,7 +430,7 @@ decompress_file(struct libdeflate_decompressor *decompressor, const tchar *path,
|
|||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
goto out_close_out;
|
goto out_close_out;
|
||||||
|
|
||||||
ret = do_decompress(decompressor, &in, &out);
|
ret = do_decompress(decompressor, &in, &out, options);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
goto out_close_out;
|
goto out_close_out;
|
||||||
|
|
||||||
@ -534,6 +539,7 @@ tmain(int argc, tchar *argv[])
|
|||||||
options.decompress = is_gunzip();
|
options.decompress = is_gunzip();
|
||||||
options.force = false;
|
options.force = false;
|
||||||
options.keep = false;
|
options.keep = false;
|
||||||
|
options.test = false;
|
||||||
options.compression_level = 6;
|
options.compression_level = 6;
|
||||||
options.suffix = T(".gz");
|
options.suffix = T(".gz");
|
||||||
|
|
||||||
@ -583,6 +589,17 @@ tmain(int argc, tchar *argv[])
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 't':
|
||||||
|
options.test = true;
|
||||||
|
options.decompress = true;
|
||||||
|
options.to_stdout = true;
|
||||||
|
/*
|
||||||
|
* -t behaves just like the more commonly used -c
|
||||||
|
* option, except that -t doesn't actually write
|
||||||
|
* anything. For ease of implementation, just pretend
|
||||||
|
* that -c was specified too.
|
||||||
|
*/
|
||||||
|
break;
|
||||||
case 'V':
|
case 'V':
|
||||||
show_version();
|
show_version();
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -463,6 +463,26 @@ for prog in gzip gunzip; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
|
|
||||||
|
begin_test '-t (test) option works'
|
||||||
|
good_files=(
|
||||||
|
'H4sIAAAAAAAAA3PMSVTITVTIzi9JVABTIJ5jzpGZelwAX+86ehsAAAA='
|
||||||
|
'H4sIAAAAAAAAAwvJSFUoLM1MzlZIKsovz1NIy69QyCrNLShWyC9LLVIoAUrnJFZVKqTkp+txAQBqzFDrLQAAAA==')
|
||||||
|
bad_files=(
|
||||||
|
'H4sIAO1YYmAAA3PMSVTITVTIzi9JVABTIJ5jzpGZelwAX+46ehsAAAA='
|
||||||
|
'H4sIAO1YYmAAA3PMSVTITVTIzi85VABTIJ5jzpGZelwAX+86ehsAAAA='
|
||||||
|
'H4sIAAAAAAAAA3PMSVTITVTIzi9JVABTIJ5jzpGZelwAX+86ehsBAAA='
|
||||||
|
'H4sIAAAAAAAAAwvJSFUoLM1MzlZIKsovz1NIy69QyCrNLShWyC9LLVIogUrnJFZVKqTkp+txAQBqzFDrLQAAAA=='
|
||||||
|
'H4sIAAAAAAAAAwvJSFUoLM1MzlZIKsovz1NIy69QyCrNLShWyC9L')
|
||||||
|
for contents in "${good_files[@]}"; do
|
||||||
|
echo "$contents" | base64 -d | gzip -t
|
||||||
|
done
|
||||||
|
for contents in "${bad_files[@]}"; do
|
||||||
|
echo "$contents" | base64 -d > file
|
||||||
|
assert_error '\<invalid compressed data|file corrupt|unexpected end of file|Out of memory\>' \
|
||||||
|
gzip -t file
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
begin_test 'Version information'
|
begin_test 'Version information'
|
||||||
gzip -V | grep -q Copyright
|
gzip -V | grep -q Copyright
|
||||||
gunzip -V | grep -q Copyright
|
gunzip -V | grep -q Copyright
|
||||||
|
Loading…
x
Reference in New Issue
Block a user