XS-libbrotli
view release on metacpan or search on metacpan
brotli/c/tools/brotli.c view on Meta::CPAN
/* Copyright 2014 Google Inc. All Rights Reserved.
Distributed under MIT license.
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/
/* Command line interface for Brotli library. */
/* Mute strerror/strcpy warnings. */
#if !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <errno.h>
#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>
#include <brotli/types.h>
#include "../common/constants.h"
#include "../common/version.h"
#if defined(_WIN32)
#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 _fileno(stdin)
#define STDOUT_FILENO _fileno(stdout)
#define S_IRUSR S_IREAD
#define S_IWUSR S_IWRITE
#endif
#define fdopen _fdopen
#define isatty _isatty
#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;
}
#else /* !defined(_WIN32) */
#include <unistd.h>
#include <utime.h>
#define MAKE_BINARY(FILENO) (FILENO)
#endif /* defined(_WIN32) */
#if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200809L)
#define HAVE_UTIMENSAT 1
#elif defined(_ATFILE_SOURCE)
#define HAVE_UTIMENSAT 1
#else
#define HAVE_UTIMENSAT 0
#endif
#if HAVE_UTIMENSAT
#if defined(__APPLE__)
#define ATIME_NSEC(S) ((S)->st_atimespec.tv_nsec)
#define MTIME_NSEC(S) ((S)->st_mtimespec.tv_nsec)
#else /* defined(__APPLE__) */
#define ATIME_NSEC(S) ((S)->st_atim.tv_nsec)
#define MTIME_NSEC(S) ((S)->st_mtim.tv_nsec)
#endif
#endif /* HAVE_UTIMENSAT */
typedef enum {
COMMAND_COMPRESS,
COMMAND_DECOMPRESS,
COMMAND_HELP,
COMMAND_INVALID,
COMMAND_TEST_INTEGRITY,
COMMAND_NOOP,
COMMAND_VERSION
} Command;
#define DEFAULT_LGWIN 24
#define DEFAULT_SUFFIX ".br"
#define MAX_OPTIONS 20
typedef struct {
/* Parameters */
int quality;
int lgwin;
int verbosity;
brotli/c/tools/brotli.c view on Meta::CPAN
*f = fdopen(fd, "wb");
if (!*f) {
fprintf(stderr, "failed to open output file [%s]: %s\n",
PrintablePath(output_path), strerror(errno));
return BROTLI_FALSE;
}
return BROTLI_TRUE;
}
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;
}
static int CopyTimeStat(const struct stat* statbuf, const char* output_path) {
#if HAVE_UTIMENSAT
struct timespec times[2];
times[0].tv_sec = statbuf->st_atime;
times[0].tv_nsec = ATIME_NSEC(statbuf);
times[1].tv_sec = statbuf->st_mtime;
times[1].tv_nsec = MTIME_NSEC(statbuf);
return utimensat(AT_FDCWD, output_path, times, AT_SYMLINK_NOFOLLOW);
#else
struct utimbuf times;
times.actime = statbuf->st_atime;
times.modtime = statbuf->st_mtime;
return utime(output_path, ×);
#endif
}
/* Copy file times and permissions.
TODO(eustas): 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;
int res;
if (input_path == 0 || output_path == 0) {
return;
}
if (stat(input_path, &statbuf) != 0) {
return;
}
res = CopyTimeStat(&statbuf, output_path);
res = chmod(output_path, statbuf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO));
if (res != 0) {
fprintf(stderr, "setting access bits failed for [%s]: %s\n",
PrintablePath(output_path), strerror(errno));
}
res = chown(output_path, (uid_t)-1, statbuf.st_gid);
if (res != 0) {
fprintf(stderr, "setting group failed for [%s]: %s\n",
PrintablePath(output_path), strerror(errno));
}
res = chown(output_path, statbuf.st_uid, (gid_t)-1);
if (res != 0) {
fprintf(stderr, "setting user failed for [%s]: %s\n",
PrintablePath(output_path), strerror(errno));
}
}
/* Result ownership is passed to caller.
|*dictionary_size| is set to resulting buffer size. */
static BROTLI_BOOL ReadDictionary(Context* context, Command command) {
static const int kMaxDictionarySize =
BROTLI_MAX_DISTANCE - BROTLI_MAX_BACKWARD_LIMIT(24);
FILE* f;
int64_t file_size_64;
uint8_t* buffer;
size_t bytes_read;
if (context->dictionary_path == NULL) return BROTLI_TRUE;
f = fopen(context->dictionary_path, "rb");
if (f == NULL) {
fprintf(stderr, "failed to open dictionary file [%s]: %s\n",
PrintablePath(context->dictionary_path), strerror(errno));
return BROTLI_FALSE;
}
file_size_64 = FileSize(context->dictionary_path);
if (file_size_64 == -1) {
fprintf(stderr, "could not get size of dictionary file [%s]",
PrintablePath(context->dictionary_path));
fclose(f);
return BROTLI_FALSE;
}
if (file_size_64 > kMaxDictionarySize) {
fprintf(stderr, "dictionary [%s] is larger than maximum allowed: %d\n",
PrintablePath(context->dictionary_path), kMaxDictionarySize);
fclose(f);
return BROTLI_FALSE;
}
context->dictionary_size = (size_t)file_size_64;
buffer = (uint8_t*)malloc(context->dictionary_size);
if (!buffer) {
fprintf(stderr, "could not read dictionary: out of memory\n");
fclose(f);
return BROTLI_FALSE;
}
bytes_read = fread(buffer, sizeof(uint8_t), context->dictionary_size, f);
if (bytes_read != context->dictionary_size) {
free(buffer);
fprintf(stderr, "failed to read dictionary [%s]: %s\n",
PrintablePath(context->dictionary_path), strerror(errno));
fclose(f);
return BROTLI_FALSE;
}
fclose(f);
context->dictionary = buffer;
if (command == COMMAND_COMPRESS) {
context->prepared_dictionary = BrotliEncoderPrepareDictionary(
BROTLI_SHARED_DICTIONARY_RAW, context->dictionary_size,
context->dictionary, BROTLI_MAX_QUALITY, NULL, NULL, NULL);
( run in 2.834 seconds using v1.01-cache-2.11-cpan-b16cb0d3907 )