/*-
* Copyright (c) 2017 Sean Purcell
+ * Copyright (c) 2023-2024 Klara, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
resetting,
} state;
int frame_per_file;
- size_t min_frame_size;
- size_t max_frame_size;
+ size_t min_frame_in;
+ size_t max_frame_in;
+ size_t min_frame_out;
+ size_t max_frame_out;
size_t cur_frame;
size_t cur_frame_in;
size_t cur_frame_out;
data->long_distance = 0;
#if HAVE_ZSTD_H && HAVE_LIBZSTD_COMPRESSOR
data->frame_per_file = 0;
- data->min_frame_size = 0;
- data->max_frame_size = SIZE_MAX;
+ data->min_frame_in = 0;
+ data->max_frame_in = SIZE_MAX;
+ data->min_frame_out = 0;
+ data->max_frame_out = SIZE_MAX;
data->cur_frame_in = 0;
data->cur_frame_out = 0;
data->cstream = ZSTD_createCStream();
return (ARCHIVE_OK);
}
-static int string_to_number(const char *string, intmax_t *numberp)
+static int
+string_to_number(const char *string, intmax_t *numberp)
{
char *end;
return (ARCHIVE_OK);
}
+static int
+string_to_size(const char *string, size_t *numberp)
+{
+ uintmax_t number;
+ char *end;
+ unsigned int shift = 0;
+
+ if (string == NULL || *string == '\0' || *string == '-')
+ return (ARCHIVE_WARN);
+ number = strtoumax(string, &end, 10);
+ if (end > string) {
+ if (*end == 'K' || *end == 'k') {
+ shift = 10;
+ end++;
+ } else if (*end == 'M' || *end == 'm') {
+ shift = 20;
+ end++;
+ } else if (*end == 'G' || *end == 'g') {
+ shift = 30;
+ end++;
+ }
+ if (*end == 'B' || *end == 'b') {
+ end++;
+ }
+ }
+ if (end == string || *end != '\0' || errno == EOVERFLOW) {
+ return (ARCHIVE_WARN);
+ }
+ if (number > (uintmax_t)SIZE_MAX >> shift) {
+ return (ARCHIVE_WARN);
+ }
+ *numberp = (size_t)(number << shift);
+ return (ARCHIVE_OK);
+}
+
/*
* Set write options.
*/
} else if (strcmp(key, "frame-per-file") == 0) {
data->frame_per_file = 1;
return (ARCHIVE_OK);
- } else if (strcmp(key, "min-frame-size") == 0) {
- intmax_t min_frame_size;
- if (string_to_number(value, &min_frame_size) != ARCHIVE_OK) {
+ } else if (strcmp(key, "min-frame-in") == 0) {
+ if (string_to_size(value, &data->min_frame_in) != ARCHIVE_OK) {
return (ARCHIVE_WARN);
}
- if (min_frame_size < 0) {
+ return (ARCHIVE_OK);
+ } else if (strcmp(key, "min-frame-out") == 0 ||
+ strcmp(key, "min-frame-size") == 0) {
+ if (string_to_size(value, &data->min_frame_out) != ARCHIVE_OK) {
return (ARCHIVE_WARN);
}
- data->min_frame_size = min_frame_size;
return (ARCHIVE_OK);
- } else if (strcmp(key, "max-frame-size") == 0) {
- intmax_t max_frame_size;
- if (string_to_number(value, &max_frame_size) != ARCHIVE_OK) {
+ } else if (strcmp(key, "max-frame-in") == 0 ||
+ strcmp(key, "max-frame-size") == 0) {
+ if (string_to_size(value, &data->max_frame_in) != ARCHIVE_OK ||
+ data->max_frame_in < 1024) {
return (ARCHIVE_WARN);
}
- if (max_frame_size < 1024) {
+ return (ARCHIVE_OK);
+ } else if (strcmp(key, "max-frame-out") == 0) {
+ if (string_to_size(value, &data->max_frame_out) != ARCHIVE_OK ||
+ data->max_frame_out < 1024) {
return (ARCHIVE_WARN);
}
- data->max_frame_size = max_frame_size;
return (ARCHIVE_OK);
#endif
}
{
struct private_data *data = (struct private_data *)f->data;
- if (data->frame_per_file && data->state == running &&
- data->cur_frame_out > data->min_frame_size)
- data->state = finishing;
+ if (data->frame_per_file && data->state == running) {
+ if (data->cur_frame_in > data->min_frame_in &&
+ data->cur_frame_out > data->min_frame_out) {
+ data->state = finishing;
+ }
+ }
return (drive_compressor(f, data, 1, NULL, 0));
}
data->total_in += in.pos - ipos;
data->cur_frame_in += in.pos - ipos;
data->cur_frame_out += data->out.pos - opos;
- if (data->state == running &&
- data->cur_frame_in >= data->max_frame_size) {
- data->state = finishing;
+ if (data->state == running) {
+ if (data->cur_frame_in >= data->max_frame_in ||
+ data->cur_frame_out >= data->max_frame_out) {
+ data->state = finishing;
+ }
}
if (data->out.pos == data->out.size ||
(flush && data->out.pos > 0)) {
/* frame-per-file: boolean */
assertEqualIntA(a, ARCHIVE_OK,
archive_write_set_filter_option(a, NULL, "frame-per-file", ""));
- /* min-frame-size: >= 0 */
+ /* min-frame-in: >= 0 */
assertEqualIntA(a, ARCHIVE_FAILED,
- archive_write_set_filter_option(a, NULL, "min-frame-size", ""));
+ archive_write_set_filter_option(a, NULL, "min-frame-out", ""));
assertEqualIntA(a, ARCHIVE_FAILED,
- archive_write_set_filter_option(a, NULL, "min-frame-size", "-1"));
+ archive_write_set_filter_option(a, NULL, "min-frame-out", "-1"));
assertEqualIntA(a, ARCHIVE_OK,
- archive_write_set_filter_option(a, NULL, "min-frame-size", "0"));
+ archive_write_set_filter_option(a, NULL, "min-frame-out", "0"));
assertEqualIntA(a, ARCHIVE_OK,
- archive_write_set_filter_option(a, NULL, "min-frame-size", "1048576"));
- /* max-frame-size: >= 1024 */
+ archive_write_set_filter_option(a, NULL, "min-frame-out", "1048576"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "min-frame-out", "1k"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "min-frame-out", "1kB"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "min-frame-out", "1M"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "min-frame-out", "1MB"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "min-frame-out", "1G"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "min-frame-out", "1GB"));
+ /* min-frame-out: >= 0 */
+ assertEqualIntA(a, ARCHIVE_FAILED,
+ archive_write_set_filter_option(a, NULL, "min-frame-in", ""));
+ assertEqualIntA(a, ARCHIVE_FAILED,
+ archive_write_set_filter_option(a, NULL, "min-frame-in", "-1"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "min-frame-in", "0"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "min-frame-in", "1048576"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "min-frame-in", "1k"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "min-frame-in", "1kB"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "min-frame-in", "1M"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "min-frame-in", "1MB"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "min-frame-in", "1G"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "min-frame-in", "1GB"));
+ /* max-frame-in: >= 1024 */
+ assertEqualIntA(a, ARCHIVE_FAILED,
+ archive_write_set_filter_option(a, NULL, "max-frame-in", ""));
assertEqualIntA(a, ARCHIVE_FAILED,
- archive_write_set_filter_option(a, NULL, "max-frame-size", ""));
+ archive_write_set_filter_option(a, NULL, "max-frame-in", "-1"));
assertEqualIntA(a, ARCHIVE_FAILED,
- archive_write_set_filter_option(a, NULL, "max-frame-size", "-1"));
+ archive_write_set_filter_option(a, NULL, "max-frame-in", "0"));
assertEqualIntA(a, ARCHIVE_FAILED,
- archive_write_set_filter_option(a, NULL, "max-frame-size", "0"));
+ archive_write_set_filter_option(a, NULL, "max-frame-in", "1023"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "max-frame-in", "1024"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "max-frame-in", "1048576"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "max-frame-in", "1k"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "max-frame-in", "1kB"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "max-frame-in", "1M"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "max-frame-in", "1MB"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "max-frame-in", "1G"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "max-frame-in", "1GB"));
+ /* max-frame-out: >= 1024 */
+ assertEqualIntA(a, ARCHIVE_FAILED,
+ archive_write_set_filter_option(a, NULL, "max-frame-out", ""));
assertEqualIntA(a, ARCHIVE_FAILED,
- archive_write_set_filter_option(a, NULL, "max-frame-size", "1023"));
+ archive_write_set_filter_option(a, NULL, "max-frame-out", "-1"));
+ assertEqualIntA(a, ARCHIVE_FAILED,
+ archive_write_set_filter_option(a, NULL, "max-frame-out", "0"));
+ assertEqualIntA(a, ARCHIVE_FAILED,
+ archive_write_set_filter_option(a, NULL, "max-frame-out", "1023"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "max-frame-out", "1024"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "max-frame-out", "1048576"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "max-frame-out", "1k"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "max-frame-out", "1kB"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "max-frame-out", "1M"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "max-frame-out", "1MB"));
assertEqualIntA(a, ARCHIVE_OK,
- archive_write_set_filter_option(a, NULL, "max-frame-size", "1024"));
+ archive_write_set_filter_option(a, NULL, "max-frame-out", "1G"));
assertEqualIntA(a, ARCHIVE_OK,
- archive_write_set_filter_option(a, NULL, "max-frame-size", "1048576"));
+ archive_write_set_filter_option(a, NULL, "max-frame-out", "1GB"));
#endif
#if ZSTD_VERSION_NUMBER >= MINVER_LONG
if ((int)(sizeof(size_t) == 4))