예제 #1
0
bool
squash_mapped_file_destroy (SquashMappedFile* mapped, bool success) {
  if (mapped->data != MAP_FAILED) {
    munmap (mapped->data - mapped->window_offset, mapped->size + mapped->window_offset);
    mapped->data = MAP_FAILED;

    if (success) {
      const int sres = fseeko (mapped->fp, mapped->size, SEEK_CUR);
      if (SQUASH_LIKELY(sres != -1)) {
        if (mapped->writable) {
          const off_t pos = ftello (mapped->fp);
          if (SQUASH_LIKELY(pos != -1)) {
            const int tr = ftruncate (fileno (mapped->fp), pos);
            return SQUASH_LIKELY(tr != -1) ? true : false;
          } else {
            return false;
          }
        }
      } else {
        return false;
      }
    }
  }

  return true;
}
예제 #2
0
파일: file.c 프로젝트: jibsen/squash
/**
 * @brief Close a file
 *
 * If @a file is a compressor the stream will finish compressing,
 * writing any buffered data.  For codecs which do not provide a
 * native streaming interface, *all* of the actual compression will
 * take place during this call.  In other words, it may block for a
 * non-trivial period.  If this is a problem please file a bug against
 * Squash (including your use case), and we can discuss adding a
 * function call which will simply abort compression.
 *
 * In addition to freeing the @ref SquashFile instance, this function
 * will close the underlying *FILE* pointer.  If you wish to continue
 * using the *FILE* for something else, use @ref squash_file_free
 * instead.
 *
 * @param file file to close
 * @return @ref SQUASH_OK on success or a negative error code on
 *   failure
 */
SquashStatus
squash_file_close (SquashFile* file) {
  FILE* fp = NULL;
  SquashStatus res = squash_file_free (file, &fp);
  if (res > SQUASH_OK)
    res = SQUASH_OK;

  if (fp != NULL) {
    const SquashStatus cres = SQUASH_LIKELY(fclose (fp) == 0) ? SQUASH_OK : squash_error (SQUASH_IO);
    if (SQUASH_LIKELY(res > 0))
      res = cres;
  }
  return res;
}
예제 #3
0
static SquashStatus
squash_brotli_decompress_stream (SquashStream* stream, SquashOperation operation) {
  SquashBrotliStream* s = (SquashBrotliStream*) stream;

  if (s->finished) {
    return SQUASH_OK;
  }

  try {
    size_t total_out;
    BrotliResult res = BrotliDecompressStream (&s->base_object.avail_in, &s->base_object.next_in,
                                               &s->base_object.avail_out, &s->base_object.next_out,
                                               &total_out, s->decompressor);
    if (res == BROTLI_RESULT_SUCCESS) {
      s->finished = true;
      return SQUASH_OK;
    }
    if (SQUASH_LIKELY(res ==  BROTLI_RESULT_NEEDS_MORE_OUTPUT || res == BROTLI_RESULT_NEEDS_MORE_INPUT)) {
      return (res == BROTLI_RESULT_NEEDS_MORE_OUTPUT) ? SQUASH_PROCESSING : SQUASH_OK;
    }
    return squash_error (SQUASH_FAILED);
  } catch (const std::bad_alloc& e) {
    (void) e;
    return squash_error (SQUASH_MEMORY);
  } catch (...) {
    return squash_error (SQUASH_FAILED);
  }
}
예제 #4
0
파일: file.c 프로젝트: jibsen/squash
SquashStatus
squash_file_printf (SquashFile* file,
                    const char* format,
                    ...) {
  SquashStatus res = SQUASH_OK;
  va_list ap;
  int size;
  char buf[256];
  char* heap_buf = NULL;

  va_start (ap, format);
#if defined(_WIN32)
  size = _vscprintf (format, ap);
#else
  size = vsnprintf (buf, sizeof (buf), format, ap);
  if (size >= (int) sizeof (buf))
#endif
  {
    heap_buf = malloc (size);
    if (SQUASH_UNLIKELY(heap_buf == NULL))
      res = squash_error (SQUASH_MEMORY);

    const int written = vsnprintf (heap_buf, size, format, ap);
    if (SQUASH_UNLIKELY(written != size - 1))
      res = squash_error (SQUASH_FAILED);
  }
  va_end (ap);

  if (SQUASH_LIKELY(res == SQUASH_OK))
    res = squash_file_write (file, size, (uint8_t*) ((heap_buf == NULL) ? buf : heap_buf));

  free (heap_buf);

  return res;
}
예제 #5
0
static size_t
squash_pithy_get_uncompressed_size (SquashCodec* codec,
                                    size_t compressed_size,
                                    const uint8_t compressed[SQUASH_ARRAY_PARAM(compressed_size)]) {
  size_t uncompressed_size = 0;

  int r = pithy_GetDecompressedLength ((const char*) compressed, compressed_size, &uncompressed_size);

  return SQUASH_LIKELY(r > 0) ? uncompressed_size : 0;
}
예제 #6
0
static SquashStatus
squash_brotli_decompress_buffer (SquashCodec* codec,
                                 size_t* decompressed_size,
                                 uint8_t decompressed[SQUASH_ARRAY_PARAM(*decompressed_size)],
                                 size_t compressed_size,
                                 const uint8_t compressed[SQUASH_ARRAY_PARAM(compressed_size)],
                                 SquashOptions* options) {
  const BrotliResult res = BrotliDecompressBuffer(compressed_size, compressed, decompressed_size, decompressed);

  return SQUASH_LIKELY(res == BROTLI_RESULT_SUCCESS) ? SQUASH_OK : squash_error (SQUASH_BUFFER_FULL);
}
예제 #7
0
static SquashStatus
squash_wflz_compress_buffer (SquashCodec* codec,
                             size_t* compressed_size,
                             uint8_t compressed[SQUASH_ARRAY_PARAM(*compressed_size)],
                             size_t uncompressed_size,
                             const uint8_t uncompressed[SQUASH_ARRAY_PARAM(uncompressed_size)],
                             SquashOptions* options) {
  const char* codec_name = squash_codec_get_name (codec);
  const uint32_t swap = ((uint32_t) squash_options_get_int_at (options, codec, SQUASH_WFLZ_OPT_ENDIANNESS) != SQUASH_WFLZ_HOST_ORDER);
  const int level = squash_options_get_int_at (options, codec, SQUASH_WFLZ_OPT_LEVEL);

#if UINT32_MAX < SIZE_MAX
  if (SQUASH_UNLIKELY(UINT32_MAX < uncompressed_size))
    return squash_error (SQUASH_RANGE);
#endif

  if (*compressed_size < wfLZ_GetMaxCompressedSize ((uint32_t) uncompressed_size)) {
    return squash_error (SQUASH_BUFFER_FULL);
  }

  uint8_t* work_mem = (uint8_t*) malloc (wfLZ_GetWorkMemSize ());
  uint32_t wres;

  if (codec_name[4] == '\0') {
    if (level == 1) {
      wres = wfLZ_CompressFast (uncompressed, (uint32_t) uncompressed_size,
                                compressed, work_mem, swap);
    } else {
      wres = wfLZ_Compress (uncompressed, (uint32_t) uncompressed_size,
                            compressed, work_mem, swap);
    }
  } else {
    wres =
      wfLZ_ChunkCompress ((uint8_t*) uncompressed, (uint32_t) uncompressed_size,
                          squash_options_get_size_at (options, codec, SQUASH_WFLZ_OPT_CHUNK_SIZE),
                          compressed, work_mem, swap, level == 1 ? 1 : 0);
  }

#if SIZE_MAX < UINT32_MAX
  if (SQUASH_UNLIKELY(SIZE_MAX < wres)) {
    free (work_mem);
    return squash_error (SQUASH_RANGE);
  }
#endif

  *compressed_size = (size_t) wres;

  free (work_mem);

  return SQUASH_LIKELY(*compressed_size > 0) ? SQUASH_OK : squash_error (SQUASH_FAILED);
}
예제 #8
0
extern "C" SquashStatus
squash_plugin_init_codec (SquashCodec* codec, SquashCodecImpl* impl) {
  const char* name = squash_codec_get_name (codec);

  if (SQUASH_LIKELY(strcmp ("csc", name) == 0)) {
    impl->options = squash_csc_options;
    impl->splice = squash_csc_splice;
    impl->get_max_compressed_size = squash_csc_get_max_compressed_size;
  } else {
    return squash_error (SQUASH_UNABLE_TO_LOAD);
  }

  return SQUASH_OK;
}
예제 #9
0
SquashStatus
squash_plugin_init_codec (SquashCodec* codec, SquashCodecImpl* impl) {
  const char* name = squash_codec_get_name (codec);

  if (SQUASH_LIKELY(strcmp ("brieflz", name) == 0)) {
    impl->get_uncompressed_size = squash_brieflz_get_uncompressed_size;
    impl->get_max_compressed_size = squash_brieflz_get_max_compressed_size;
    impl->decompress_buffer = squash_brieflz_decompress_buffer;
    impl->compress_buffer_unsafe = squash_brieflz_compress_buffer;
  } else {
    return squash_error (SQUASH_UNABLE_TO_LOAD);
  }

  return SQUASH_OK;
}
예제 #10
0
SquashStatus
squash_plugin_init_codec (SquashCodec* codec, SquashCodecImpl* impl) {
  const char* name = squash_codec_get_name (codec);

  if (SQUASH_LIKELY(strcmp ("density", name) == 0)) {
    impl->options = squash_density_options;
    impl->create_stream = squash_density_create_stream;
    impl->process_stream = squash_density_process_stream;
    impl->get_max_compressed_size = squash_density_get_max_compressed_size;
  } else {
    return squash_error (SQUASH_UNABLE_TO_LOAD);
  }

  return SQUASH_OK;
}
예제 #11
0
static SquashStatus
squash_brotli_compress_buffer (SquashCodec* codec,
                               size_t* compressed_size,
                               uint8_t compressed[SQUASH_ARRAY_PARAM(*compressed_size)],
                               size_t uncompressed_size,
                               const uint8_t uncompressed[SQUASH_ARRAY_PARAM(uncompressed_size)],
                               SquashOptions* options) {
  const int quality = squash_options_get_int_at (options, codec, SQUASH_BROTLI_OPT_LEVEL);
  const int lgwin = squash_options_get_int_at (options, codec, SQUASH_BROTLI_OPT_WINDOW_SIZE);
  const BrotliEncoderMode mode = (BrotliEncoderMode)
    squash_options_get_int_at (options, codec, SQUASH_BROTLI_OPT_MODE);

  const int res = BrotliEncoderCompress (quality, lgwin, mode, uncompressed_size, uncompressed, compressed_size, compressed);

  return SQUASH_LIKELY(res == 1) ? SQUASH_OK : squash_error (SQUASH_BUFFER_FULL);
}
예제 #12
0
SquashStatus
squash_plugin_init_lz4f (SquashCodec* codec, SquashCodecImpl* impl) {
  const char* name = squash_codec_get_name (codec);

  if (SQUASH_LIKELY(strcmp ("lz4", name) == 0)) {
    impl->info = SQUASH_CODEC_INFO_CAN_FLUSH;
    impl->options = squash_lz4f_options;
    impl->get_max_compressed_size = squash_lz4f_get_max_compressed_size;
    impl->create_stream = squash_lz4f_create_stream;
    impl->process_stream = squash_lz4f_process_stream;
  } else {
    return SQUASH_UNABLE_TO_LOAD;
  }

  return SQUASH_OK;
}
예제 #13
0
static
#endif
SquashStatus
squash_file_vwprintf (SquashFile* file,
                      const wchar_t* format,
                      va_list ap) {
  SquashStatus res = SQUASH_OK;
  int size;
  wchar_t* buf = NULL;

  assert (file != NULL);
  assert (format != NULL);

  size = _vscwprintf (format, ap);
  if (SQUASH_UNLIKELY(size < 0))
    return squash_error (SQUASH_FAILED);

  buf = calloc (size + 1, sizeof (wchar_t));
  if (SQUASH_UNLIKELY(buf == NULL))
    return squash_error (SQUASH_MEMORY);

#if !defined(_WIN32)
  const int written = vswprintf (buf, size + 1, format, ap);
#else
  const int written = _vsnwprintf (buf, size + 1, format, ap);
#endif
  if (SQUASH_UNLIKELY(written != size)) {
    res = squash_error (SQUASH_FAILED);
  } else {
    size_t data_size;
    char* data;
    bool conv_success =
      squash_charset_convert (&data_size, &data, "UTF-8",
                              size * sizeof(wchar_t), (char*) buf, squash_charset_get_wide ());

    if (SQUASH_LIKELY(conv_success))
      res = squash_file_write (file, data_size, (uint8_t*) data);
    else
      res = squash_error (SQUASH_FAILED);
  }

  squash_free (buf);

  return res;
}
예제 #14
0
static SquashStatus
squash_pithy_decompress_buffer (SquashCodec* codec,
                                size_t* decompressed_size,
                                uint8_t decompressed[SQUASH_ARRAY_PARAM(*decompressed_size)],
                                size_t compressed_size,
                                const uint8_t compressed[SQUASH_ARRAY_PARAM(compressed_size)],
                                SquashOptions* options) {
  size_t outlen = squash_pithy_get_uncompressed_size(codec, compressed_size, compressed);
  if (SQUASH_UNLIKELY(*decompressed_size < outlen))
    return squash_error (SQUASH_BUFFER_FULL);

  if (SQUASH_LIKELY(pithy_Decompress ((const char*) compressed, compressed_size, (char*) decompressed, outlen))) {
    *decompressed_size = outlen;
    return SQUASH_OK;
  } else {
    return squash_error (SQUASH_FAILED);
  }
}
예제 #15
0
SquashStatus
squash_plugin_init_codec (SquashCodec* codec, SquashCodecImpl* impl) {
  const char* name = squash_codec_get_name (codec);

  if (SQUASH_LIKELY(strcmp ("brotli", name) == 0)) {
    impl->info = SQUASH_CODEC_INFO_CAN_FLUSH;
    impl->options = squash_brotli_options;
    impl->get_max_compressed_size = squash_brotli_get_max_compressed_size;
    impl->create_stream = squash_brotli_create_stream;
    impl->process_stream = squash_brotli_process_stream;
    impl->decompress_buffer = squash_brotli_decompress_buffer;
    impl->compress_buffer = squash_brotli_compress_buffer;
  } else {
    return squash_error (SQUASH_UNABLE_TO_LOAD);
  }

  return SQUASH_OK;
}
예제 #16
0
SquashStatus
squash_file_vprintf (SquashFile* file,
                     const char* format,
                     va_list ap) {
  SquashStatus res = SQUASH_OK;
  int size;
  char* heap_buf = NULL;

  assert (file != NULL);
  assert (format != NULL);

#if defined(_WIN32)
  size = _vscprintf (format, ap);
  if (SQUASH_UNLIKELY(size < 0))
    return squash_error (SQUASH_FAILED);
#else
  char buf[256];
  size = vsnprintf (buf, sizeof (buf), format, ap);
  if (SQUASH_UNLIKELY(size < 0))
    return squash_error (SQUASH_FAILED);
  else if (size >= (int) sizeof (buf))
#endif
  {
    heap_buf = squash_malloc (size + 1);
    if (SQUASH_UNLIKELY(heap_buf == NULL))
      return squash_error (SQUASH_MEMORY);

    const int written = vsnprintf (heap_buf, size + 1, format, ap);
    if (SQUASH_UNLIKELY(written != size))
      res = squash_error (SQUASH_FAILED);
  }

  if (SQUASH_LIKELY(res == SQUASH_OK)) {
    res = squash_file_write (file, size,
#if !defined(_WIN32)
                             (heap_buf == NULL) ? (uint8_t*) buf :
#endif
                             (uint8_t*) heap_buf);
  }

  squash_free (heap_buf);

  return res;
}
예제 #17
0
파일: plugin.c 프로젝트: Dr-Emann/squash
/**
 * @brief Initialize a codec
 * @private
 *
 * @param plugin The plugin.
 * @param codec The codec to initialize.
 * @param impl The function table to fill.
 * @returns A status code.
 */
SquashStatus
squash_plugin_init_codec (SquashPlugin* plugin, SquashCodec* codec, SquashCodecImpl* impl) {
    SquashStatus res = SQUASH_OK;

    assert (plugin != NULL);

    if (plugin->plugin == NULL) {
        res = squash_plugin_init (plugin);
        if (res != SQUASH_OK) {
            return res;
        }
    }

    if (codec->initialized == 0) {
        SquashStatus (*init_codec_func) (SquashCodec*, SquashCodecImpl*);

#if !defined(_WIN32)
        *(void **) (&init_codec_func) = dlsym (plugin->plugin, "squash_plugin_init_codec");
#else
        *(void **) (&init_codec_func) = GetProcAddress (plugin->plugin, "squash_plugin_init_codec");
#endif

        if (SQUASH_UNLIKELY(init_codec_func == NULL)) {
            return squash_error (SQUASH_UNABLE_TO_LOAD);
        }

        SQUASH_MTX_LOCK(codec_init);
        if (SQUASH_LIKELY(codec->initialized == 0)) {
            res = init_codec_func (codec, impl);
            codec->initialized = (res == SQUASH_OK);

            assert ((codec->impl.info & SQUASH_CODEC_INFO_AUTO_MASK) == 0);
            if (codec->impl.process_stream != NULL)
                codec->impl.info |= (SquashCodecInfo) SQUASH_CODEC_INFO_NATIVE_STREAMING;
            if (codec->impl.get_uncompressed_size != NULL || (codec->impl.info & SQUASH_CODEC_INFO_WRAP_SIZE))
                codec->impl.info |= (SquashCodecInfo) SQUASH_CODEC_INFO_KNOWS_UNCOMPRESSED_SIZE;
        }
        SQUASH_MTX_UNLOCK(codec_init);
    }

    return res;
}
예제 #18
0
/**
 * @brief Decrement the reference count on an object.
 *
 * Once the reference count reaches 0 the object will be freed.
 *
 * @param obj The object to decrease the reference count of.
 * @return NULL
 */
void*
squash_object_unref (void* obj) {
  if (obj == NULL)
    return NULL;

  SquashObject* object = (SquashObject*) obj;

  unsigned int ref_count = squash_atomic_dec (&(object->ref_count));

  if (ref_count == 1) {
    if (SQUASH_LIKELY(object->destroy_notify != NULL))
      object->destroy_notify (obj);

    squash_free (obj);

    return NULL;
  } else {
    return NULL;
  }
}
예제 #19
0
SquashStatus
squash_plugin_init_codec (SquashCodec* codec, SquashCodecImpl* impl) {
    const char* name = squash_codec_get_name (codec);

    if (SQUASH_LIKELY(strcmp ("lznt1", name) == 0 ||
                      strcmp ("xpress", name) == 0 ||
                      strcmp ("xpress-huffman", name) == 0)) {
        impl->get_max_compressed_size = squash_ms_get_max_compressed_size;
        impl->decompress_buffer       = squash_ms_decompress_buffer;
        impl->compress_buffer         = squash_ms_compress_buffer;
        if (strcmp ("lznt1", name) == 0) {
            impl->info                    = SQUASH_CODEC_INFO_CAN_FLUSH;
            impl->create_stream           = squash_ms_create_stream;
            impl->process_stream          = squash_ms_process_stream;
        }
    } else {
        return squash_error (SQUASH_UNABLE_TO_LOAD);
    }

    return SQUASH_OK;
}
예제 #20
0
static SquashStatus
squash_brotli_compress_buffer (SquashCodec* codec,
                               size_t* compressed_size,
                               uint8_t compressed[SQUASH_ARRAY_PARAM(*compressed_size)],
                               size_t uncompressed_size,
                               const uint8_t uncompressed[SQUASH_ARRAY_PARAM(uncompressed_size)],
                               SquashOptions* options) {
  brotli::BrotliParams params;
  params.quality = squash_options_get_int_at (options, codec, SQUASH_BROTLI_OPT_LEVEL);
  params.mode = (brotli::BrotliParams::Mode) squash_options_get_int_at (options, codec, SQUASH_BROTLI_OPT_MODE);
  try {
    int res = brotli::BrotliCompressBuffer (params,
                                            uncompressed_size, uncompressed,
                                            compressed_size, compressed);
    return SQUASH_LIKELY(res == 1) ? SQUASH_OK : squash_error (SQUASH_FAILED);
  } catch (const std::bad_alloc& e) {
    (void) e;
    return squash_error (SQUASH_MEMORY);
  } catch (...) {
    return squash_error (SQUASH_FAILED);
  }
}
예제 #21
0
파일: codec.c 프로젝트: eevans/squash-deb
/**
 * @brief Get a list of options applicable to the codec
 *
 * @param codec The codec
 * @return a list of options, terminated by an option with a NULL name
 */
const SquashOptionInfo*
squash_codec_get_option_info (SquashCodec* codec) {
  SquashCodecImpl* impl = squash_codec_get_impl (codec);
  return SQUASH_LIKELY(impl != NULL) ? impl->options : NULL;
}
예제 #22
0
파일: plugin.c 프로젝트: Dr-Emann/squash
/**
 * @brief load a %SquashPlugin
 *
 * @note This function is generally only useful inside of a callback
 * passed to ::squash_foreach_plugin.  Every other way to get a plugin
 * (such as ::squash_get_plugin) will initialize the plugin as well
 * (and return *NULL* instead of the plugin if initialization fails).
 * The foreach functions, however, do not initialize the plugin since
 * doing so requires actually loading the plugin.
 *
 * @param plugin The plugin to load.
 * @return A status code.
 * @retval SQUASH_OK The plugin has been loaded.
 * @retval SQUASH_UNABLE_TO_LOAD Unable to load plugin.
 */
SquashStatus
squash_plugin_init (SquashPlugin* plugin) {
    if (plugin->plugin == NULL) {
#if !defined(_WIN32)
        void* handle;
#else
        HMODULE handle;
#endif
        char* plugin_file_name;

        plugin_file_name = squash_strdup_printf ("%s/%ssquash%s-plugin-%s%s", plugin->directory, SQUASH_SHARED_LIBRARY_PREFIX, SQUASH_VERSION_API, plugin->name, SQUASH_SHARED_LIBRARY_SUFFIX);
        if (plugin_file_name == NULL)
            return squash_error (SQUASH_MEMORY);

#if !defined(_WIN32)
        handle = dlopen (plugin_file_name, RTLD_LAZY);
#else
        handle = LoadLibrary (TEXT(plugin_file_name));
        if (handle == NULL) {
            squash_free (plugin_file_name);
#if defined(_DEBUG)
            plugin_file_name = squash_strdup_printf ("%s/Debug/%ssquash%s-plugin-%s%s", plugin->directory, SQUASH_SHARED_LIBRARY_PREFIX, SQUASH_VERSION_API, plugin->name, SQUASH_SHARED_LIBRARY_SUFFIX);
#else
            plugin_file_name = squash_strdup_printf ("%s/Release/%ssquash%s-plugin-%s%s", plugin->directory, SQUASH_SHARED_LIBRARY_PREFIX, SQUASH_VERSION_API, plugin->name, SQUASH_SHARED_LIBRARY_SUFFIX);
#endif
            handle = LoadLibrary (TEXT(plugin_file_name));
        }
#endif

        squash_free (plugin_file_name);

        if (SQUASH_LIKELY(handle != NULL)) {
            SQUASH_MTX_LOCK(plugin_init);
            if (plugin->plugin == NULL) {
                plugin->plugin = handle;
                handle = NULL;
            }
            SQUASH_MTX_UNLOCK(plugin_init);
        } else {
            return squash_error (SQUASH_UNABLE_TO_LOAD);
        }

        if (handle != NULL) {
#if !defined(_WIN32)
            dlclose (handle);
#else
            FreeLibrary (handle);
#endif
        } else {
            SquashStatus (*init_func) (SquashPlugin*);
#if !defined(_WIN32)
            *(void **) (&init_func) = dlsym (plugin->plugin, "squash_plugin_init_plugin");
#else
            *(void **) (&init_func) = GetProcAddress (plugin->plugin, "squash_plugin_init_plugin");
#endif
            if (init_func != NULL) {
                init_func (plugin);
            }
        }
    }

    return SQUASH_LIKELY(plugin->plugin != NULL) ? SQUASH_OK : squash_error (SQUASH_UNABLE_TO_LOAD);
}