// Standard C #include #include // System #include // zlib #include static void usage(void) { (void) fprintf(stderr, "compress [-d] infile outfile\n"); exit(EXIT_FAILURE); } unsigned long get_filesize(FILE *file) { (void) fseek(file, 0, SEEK_END); unsigned long size = ftell(file); (void) fseek(file, 0, SEEK_SET); return size; } void do_compress(FILE *in_file, FILE *out_file, int compress_level) { const unsigned long in_size = get_filesize(in_file); (void) fwrite(&in_size, sizeof in_size, 1, out_file); unsigned char *in_data = malloc(in_size); (void) fread(in_data, 1, in_size, in_file); unsigned long out_size = compressBound(in_size); unsigned char *out_data = malloc(out_size); const int error = compress2(out_data, &out_size, in_data, in_size, compress_level); if ( !error ) { (void) fwrite(out_data, 1, out_size, out_file); } else { printf("Error: %d\n", error); } free(out_data); free(in_data); } void do_uncompress(FILE *in_file, FILE *out_file) { const unsigned long in_size = get_filesize(in_file); unsigned char *in_data = malloc(in_size); (void) fread(in_data, 1, in_size, in_file); unsigned long out_size = *(unsigned long *) in_data; unsigned char *out_data = malloc(out_size); unsigned long tmp = in_size - sizeof(unsigned long); const int error = uncompress2(out_data, &out_size, in_data + sizeof(unsigned long), &tmp); if ( !error ) { (void) fwrite(out_data, 1, out_size, out_file); } else { printf("Error: %d\n", error); } free(out_data); free(in_data); } int main(int argc, char *argv[]) { int decompress = 0; int compress_level = 5; int opt = 0; while ( (opt = getopt(argc, argv, "dl")) != -1 ) { switch ( opt ) { case 'd': decompress = 1; break; case 'l': compress_level = 9; break; case '?': default: usage(); break; } } argc -= optind; argv += optind; if ( argc != 2 ) { usage(); } FILE *in_file = fopen(argv[0], "rb"); FILE *out_file = fopen(argv[1], "wb"); if ( !decompress ) { do_compress(in_file, out_file, compress_level); } else { do_uncompress(in_file, out_file); } (void) fclose(out_file); (void) fclose(in_file); return EXIT_SUCCESS; }