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, &times);
#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 )