diff options
Diffstat (limited to 'c/tools/bro.c')
-rw-r--r-- | c/tools/bro.c | 521 |
1 files changed, 0 insertions, 521 deletions
diff --git a/c/tools/bro.c b/c/tools/bro.c deleted file mode 100644 index 07cef95..0000000 --- a/c/tools/bro.c +++ /dev/null @@ -1,521 +0,0 @@ -/* Copyright 2014 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Example main() function for Brotli library. */ - -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <time.h> - -#include <brotli/decode.h> -#include <brotli/encode.h> - -#if !defined(_WIN32) -#include <unistd.h> -#include <utime.h> -#else -#include <io.h> -#include <share.h> -#include <sys/utime.h> - -#define MAKE_BINARY(FILENO) (_setmode((FILENO), _O_BINARY), (FILENO)) - -#if !defined(__MINGW32__) -#define STDIN_FILENO MAKE_BINARY(_fileno(stdin)) -#define STDOUT_FILENO MAKE_BINARY(_fileno(stdout)) -#define S_IRUSR S_IREAD -#define S_IWUSR S_IWRITE -#endif - -#define fdopen _fdopen -#define unlink _unlink -#define utimbuf _utimbuf -#define utime _utime - -#define fopen ms_fopen -#define open ms_open - -#define chmod(F, P) (0) -#define chown(F, O, G) (0) - -#if defined(_MSC_VER) && (_MSC_VER >= 1400) -#define fseek _fseeki64 -#define ftell _ftelli64 -#endif - -static FILE* ms_fopen(const char *filename, const char *mode) { - FILE* result = 0; - fopen_s(&result, filename, mode); - return result; -} - -static int ms_open(const char *filename, int oflag, int pmode) { - int result = -1; - _sopen_s(&result, filename, oflag | O_BINARY, _SH_DENYNO, pmode); - return result; -} -#endif /* WIN32 */ - -static int ParseQuality(const char* s, int* quality) { - if (s[0] >= '0' && s[0] <= '9') { - *quality = s[0] - '0'; - if (s[1] >= '0' && s[1] <= '9') { - *quality = *quality * 10 + s[1] - '0'; - return (s[2] == 0) ? 1 : 0; - } - return (s[1] == 0) ? 1 : 0; - } - return 0; -} - -static void ParseArgv(int argc, char **argv, - char **input_path, - char **output_path, - char **dictionary_path, - int *force, - int *quality, - int *decompress, - int *repeat, - int *verbose, - int *lgwin, - int *copy_stat) { - int k; - *force = 0; - *input_path = 0; - *output_path = 0; - *repeat = 1; - *verbose = 0; - *lgwin = 22; - *copy_stat = 1; - { - size_t argv0_len = strlen(argv[0]); - *decompress = - argv0_len >= 5 && strcmp(&argv[0][argv0_len - 5], "unbro") == 0; - } - for (k = 1; k < argc; ++k) { - if (!strcmp("--force", argv[k]) || - !strcmp("-f", argv[k])) { - if (*force != 0) { - goto error; - } - *force = 1; - continue; - } else if (!strcmp("--decompress", argv[k]) || - !strcmp("--uncompress", argv[k]) || - !strcmp("-d", argv[k])) { - *decompress = 1; - continue; - } else if (!strcmp("--verbose", argv[k]) || - !strcmp("-v", argv[k])) { - if (*verbose != 0) { - goto error; - } - *verbose = 1; - continue; - } else if (!strcmp("--no-copy-stat", argv[k])) { - if (*copy_stat == 0) { - goto error; - } - *copy_stat = 0; - continue; - } - if (k < argc - 1) { - if (!strcmp("--input", argv[k]) || - !strcmp("--in", argv[k]) || - !strcmp("-i", argv[k])) { - if (*input_path != 0) { - goto error; - } - *input_path = argv[k + 1]; - ++k; - continue; - } else if (!strcmp("--output", argv[k]) || - !strcmp("--out", argv[k]) || - !strcmp("-o", argv[k])) { - if (*output_path != 0) { - goto error; - } - *output_path = argv[k + 1]; - ++k; - continue; - } else if (!strcmp("--custom-dictionary", argv[k])) { - if (*dictionary_path != 0) { - goto error; - } - *dictionary_path = argv[k + 1]; - ++k; - continue; - } else if (!strcmp("--quality", argv[k]) || - !strcmp("-q", argv[k])) { - if (!ParseQuality(argv[k + 1], quality)) { - goto error; - } - ++k; - continue; - } else if (!strcmp("--repeat", argv[k]) || - !strcmp("-r", argv[k])) { - if (!ParseQuality(argv[k + 1], repeat)) { - goto error; - } - ++k; - continue; - } else if (!strcmp("--window", argv[k]) || - !strcmp("-w", argv[k])) { - if (!ParseQuality(argv[k + 1], lgwin)) { - goto error; - } - if (*lgwin < 10 || *lgwin >= 25) { - goto error; - } - ++k; - continue; - } - } - goto error; - } - return; -error: - fprintf(stderr, - "Usage: %s [--force] [--quality n] [--decompress]" - " [--input filename] [--output filename] [--repeat iters]" - " [--verbose] [--window n] [--custom-dictionary filename]" - " [--no-copy-stat]\n", - argv[0]); - exit(1); -} - -static FILE* OpenInputFile(const char* input_path) { - FILE* f; - if (input_path == 0) { - return fdopen(STDIN_FILENO, "rb"); - } - f = fopen(input_path, "rb"); - if (f == 0) { - perror("fopen"); - exit(1); - } - return f; -} - -static FILE *OpenOutputFile(const char *output_path, const int force) { - int fd; - if (output_path == 0) { - return fdopen(STDOUT_FILENO, "wb"); - } - fd = open(output_path, O_CREAT | (force ? 0 : O_EXCL) | O_WRONLY | O_TRUNC, - S_IRUSR | S_IWUSR); - if (fd < 0) { - if (!force) { - struct stat statbuf; - if (stat(output_path, &statbuf) == 0) { - fprintf(stderr, "output file exists\n"); - exit(1); - } - } - perror("open"); - exit(1); - } - return fdopen(fd, "wb"); -} - -static int64_t FileSize(const char *path) { - FILE *f = fopen(path, "rb"); - int64_t retval; - if (f == NULL) { - return -1; - } - if (fseek(f, 0L, SEEK_END) != 0) { - fclose(f); - return -1; - } - retval = ftell(f); - if (fclose(f) != 0) { - return -1; - } - return retval; -} - -/* Copy file times and permissions. - TODO: this is a "best effort" implementation; honest cross-platform - fully featured implementation is way too hacky; add more hacks by request. */ -static void CopyStat(const char* input_path, const char* output_path) { - struct stat statbuf; - struct utimbuf times; - int res; - if (input_path == 0 || output_path == 0) { - return; - } - if (stat(input_path, &statbuf) != 0) { - return; - } - times.actime = statbuf.st_atime; - times.modtime = statbuf.st_mtime; - utime(output_path, ×); - res = chmod(output_path, statbuf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)); - if (res != 0) - perror("chmod failed"); - res = chown(output_path, (uid_t)-1, statbuf.st_gid); - if (res != 0) - perror("chown failed"); - res = chown(output_path, statbuf.st_uid, (gid_t)-1); - if (res != 0) - perror("chown failed"); -} - -/* Result ownersip is passed to caller. - |*dictionary_size| is set to resulting buffer size. */ -static uint8_t* ReadDictionary(const char* path, size_t* dictionary_size) { - static const int kMaxDictionarySize = (1 << 24) - 16; - FILE *f = fopen(path, "rb"); - int64_t file_size_64; - uint8_t* buffer; - size_t bytes_read; - - if (f == NULL) { - perror("fopen"); - exit(1); - } - - file_size_64 = FileSize(path); - if (file_size_64 == -1) { - fprintf(stderr, "could not get size of dictionary file"); - exit(1); - } - - if (file_size_64 > kMaxDictionarySize) { - fprintf(stderr, "dictionary is larger than maximum allowed: %d\n", - kMaxDictionarySize); - exit(1); - } - *dictionary_size = (size_t)file_size_64; - - buffer = (uint8_t*)malloc(*dictionary_size); - if (!buffer) { - fprintf(stderr, "could not read dictionary: out of memory\n"); - exit(1); - } - bytes_read = fread(buffer, sizeof(uint8_t), *dictionary_size, f); - if (bytes_read != *dictionary_size) { - fprintf(stderr, "could not read dictionary\n"); - exit(1); - } - fclose(f); - return buffer; -} - -static const size_t kFileBufferSize = 65536; - -static int Decompress(FILE* fin, FILE* fout, const char* dictionary_path) { - /* Dictionary should be kept during first rounds of decompression. */ - uint8_t* dictionary = NULL; - uint8_t* input; - uint8_t* output; - size_t available_in; - const uint8_t* next_in; - size_t available_out = kFileBufferSize; - uint8_t* next_out; - BrotliDecoderResult result = BROTLI_DECODER_RESULT_ERROR; - BrotliDecoderState* s = BrotliDecoderCreateInstance(NULL, NULL, NULL); - if (!s) { - fprintf(stderr, "out of memory\n"); - return 0; - } - if (dictionary_path != NULL) { - size_t dictionary_size = 0; - dictionary = ReadDictionary(dictionary_path, &dictionary_size); - BrotliDecoderSetCustomDictionary(s, dictionary_size, dictionary); - } - input = (uint8_t*)malloc(kFileBufferSize); - output = (uint8_t*)malloc(kFileBufferSize); - if (!input || !output) { - fprintf(stderr, "out of memory\n"); - goto end; - } - next_out = output; - result = BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT; - while (1) { - if (result == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT) { - if (feof(fin)) { - break; - } - available_in = fread(input, 1, kFileBufferSize, fin); - next_in = input; - if (ferror(fin)) { - break; - } - } else if (result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) { - fwrite(output, 1, kFileBufferSize, fout); - if (ferror(fout)) { - break; - } - available_out = kFileBufferSize; - next_out = output; - } else { - break; /* Error or success. */ - } - result = BrotliDecoderDecompressStream( - s, &available_in, &next_in, &available_out, &next_out, 0); - } - if (next_out != output) { - fwrite(output, 1, (size_t)(next_out - output), fout); - } - - if ((result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) || ferror(fout)) { - fprintf(stderr, "failed to write output\n"); - } else if (result != BROTLI_DECODER_RESULT_SUCCESS) { - /* Error or needs more input. */ - fprintf(stderr, "corrupt input\n"); - } - -end: - free(dictionary); - free(input); - free(output); - BrotliDecoderDestroyInstance(s); - return (result == BROTLI_DECODER_RESULT_SUCCESS) ? 1 : 0; -} - -static int Compress(int quality, int lgwin, FILE* fin, FILE* fout, - const char *dictionary_path) { - BrotliEncoderState* s = BrotliEncoderCreateInstance(0, 0, 0); - uint8_t* buffer = (uint8_t*)malloc(kFileBufferSize << 1); - uint8_t* input = buffer; - uint8_t* output = buffer + kFileBufferSize; - size_t available_in = 0; - const uint8_t* next_in = NULL; - size_t available_out = kFileBufferSize; - uint8_t* next_out = output; - int is_eof = 0; - int is_ok = 1; - - if (!s || !buffer) { - is_ok = 0; - goto finish; - } - - BrotliEncoderSetParameter(s, BROTLI_PARAM_QUALITY, (uint32_t)quality); - BrotliEncoderSetParameter(s, BROTLI_PARAM_LGWIN, (uint32_t)lgwin); - if (dictionary_path != NULL) { - size_t dictionary_size = 0; - uint8_t* dictionary = ReadDictionary(dictionary_path, &dictionary_size); - BrotliEncoderSetCustomDictionary(s, dictionary_size, dictionary); - free(dictionary); - } - - while (1) { - if (available_in == 0 && !is_eof) { - available_in = fread(input, 1, kFileBufferSize, fin); - next_in = input; - if (ferror(fin)) break; - is_eof = feof(fin); - } - - if (!BrotliEncoderCompressStream(s, - is_eof ? BROTLI_OPERATION_FINISH : BROTLI_OPERATION_PROCESS, - &available_in, &next_in, &available_out, &next_out, NULL)) { - is_ok = 0; - break; - } - - if (available_out != kFileBufferSize) { - size_t out_size = kFileBufferSize - available_out; - fwrite(output, 1, out_size, fout); - if (ferror(fout)) break; - available_out = kFileBufferSize; - next_out = output; - } - - if (BrotliEncoderIsFinished(s)) break; - } - -finish: - free(buffer); - BrotliEncoderDestroyInstance(s); - - if (!is_ok) { - /* Should detect OOM? */ - fprintf(stderr, "failed to compress data\n"); - return 0; - } else if (ferror(fout)) { - fprintf(stderr, "failed to write output\n"); - return 0; - } else if (ferror(fin)) { - fprintf(stderr, "failed to read input\n"); - return 0; - } - return 1; -} - -int main(int argc, char** argv) { - char *input_path = 0; - char *output_path = 0; - char *dictionary_path = 0; - int force = 0; - int quality = 11; - int decompress = 0; - int repeat = 1; - int verbose = 0; - int lgwin = 0; - int copy_stat = 1; - clock_t clock_start; - int i; - ParseArgv(argc, argv, &input_path, &output_path, &dictionary_path, &force, - &quality, &decompress, &repeat, &verbose, &lgwin, ©_stat); - clock_start = clock(); - for (i = 0; i < repeat; ++i) { - FILE* fin = OpenInputFile(input_path); - FILE* fout = OpenOutputFile(output_path, force || (repeat > 1)); - int is_ok = 0; - if (decompress) { - is_ok = Decompress(fin, fout, dictionary_path); - } else { - is_ok = Compress(quality, lgwin, fin, fout, dictionary_path); - } - if (!is_ok) { - unlink(output_path); - exit(1); - } - if (fclose(fout) != 0) { - perror("fclose"); - exit(1); - } - /* TOCTOU violation, but otherwise it is impossible to set file times. */ - if (copy_stat && (i + 1 == repeat)) { - CopyStat(input_path, output_path); - } - if (fclose(fin) != 0) { - perror("fclose"); - exit(1); - } - } - if (verbose) { - clock_t clock_end = clock(); - double duration = (double)(clock_end - clock_start) / CLOCKS_PER_SEC; - int64_t uncompressed_size; - double uncompressed_bytes_in_MB; - if (duration < 1e-9) { - duration = 1e-9; - } - uncompressed_size = FileSize(decompress ? output_path : input_path); - if (uncompressed_size == -1) { - fprintf(stderr, "failed to determine uncompressed file size\n"); - exit(1); - } - uncompressed_bytes_in_MB = - (double)(repeat * uncompressed_size) / (1024.0 * 1024.0); - if (decompress) { - printf("Brotli decompression speed: "); - } else { - printf("Brotli compression speed: "); - } - printf("%g MB/s\n", uncompressed_bytes_in_MB / duration); - } - return 0; -} |