libropkg: convert pkg writer to use bluelib compression streams

This commit is contained in:
2025-08-06 22:04:36 +01:00
parent 231dbe8f7f
commit 46c6a66e44
10 changed files with 59 additions and 887 deletions

View File

@@ -1,86 +0,0 @@
#include "compress.h"
#include <ropkg/compress.h>
#include <stdio.h>
extern const struct ropkg_compression_function ropkg_zstd;
static const struct ropkg_compression_function *functions[] = {
[ROPKG_COMPRESSION_ZSTD] = &ropkg_zstd,
};
static const size_t nr_functions = sizeof functions / sizeof functions[0];
const struct ropkg_compression_function *ropkg_compression_function_for_type(
enum ropkg_compression_type type)
{
if (type >= nr_functions) {
return NULL;
}
return functions[type];
}
enum ropkg_status ropkg_compression_function_get_buffer_size(
const struct ropkg_compression_function *func,
enum ropkg_compression_stream_mode mode,
size_t *in_buffer_size,
size_t *out_buffer_size)
{
if (!func->f_buffer_size) {
return ROPKG_ERR_NOT_SUPPORTED;
}
return func->f_buffer_size(mode, in_buffer_size, out_buffer_size);
}
const char *ropkg_compression_function_get_file_extension(
const struct ropkg_compression_function *func)
{
return func->f_extension;
}
enum ropkg_status ropkg_compression_stream_open(
const struct ropkg_compression_function *func,
void *in_buffer,
size_t in_max,
void *out_buffer,
size_t out_max,
enum ropkg_compression_stream_mode mode,
struct ropkg_compression_stream **out)
{
if (!func->f_open) {
return ROPKG_ERR_NOT_SUPPORTED;
}
return func->f_open(
func,
mode,
in_buffer,
in_max,
out_buffer,
out_max,
out);
}
enum ropkg_status ropkg_compression_stream_process(
struct ropkg_compression_stream *stream,
size_t in_size,
enum ropkg_compression_stream_op op,
size_t *out_size)
{
if (!stream->s_func->f_process) {
return ROPKG_ERR_NOT_SUPPORTED;
}
return stream->s_func->f_process(stream, in_size, op, out_size);
}
enum ropkg_status ropkg_compression_stream_close(
struct ropkg_compression_stream *stream)
{
if (!stream->s_func->f_close) {
return ROPKG_ERR_NOT_SUPPORTED;
}
return stream->s_func->f_close(stream);
}

View File

@@ -1,36 +0,0 @@
#ifndef COMPRESS_H_
#define COMPRESS_H_
#include <ropkg/compress.h>
struct ropkg_compression_function {
const char *f_name;
const char *f_extension;
enum ropkg_status (*f_buffer_size)(
enum ropkg_compression_stream_mode,
size_t *,
size_t *);
enum ropkg_status (*f_open)(
const struct ropkg_compression_function *,
enum ropkg_compression_stream_mode,
void *,
size_t,
void *,
size_t,
struct ropkg_compression_stream **);
enum ropkg_status (*f_close)(struct ropkg_compression_stream *);
enum ropkg_status (*f_process)(
struct ropkg_compression_stream *,
size_t,
enum ropkg_compression_stream_op,
size_t *);
};
struct ropkg_compression_stream {
const struct ropkg_compression_function *s_func;
enum ropkg_compression_stream_mode s_mode;
void *s_in, *s_out;
size_t s_in_max, s_out_max;
};
#endif

View File

@@ -1,53 +0,0 @@
#ifndef ROPKG_COMPRESS_H_
#define ROPKG_COMPRESS_H_
#include <ropkg/misc.h>
#include <ropkg/status.h>
#include <stddef.h>
struct ropkg_compression_function;
struct ropkg_compression_stream;
enum ropkg_compression_stream_mode {
ROPKG_COMPRESSION_MODE_COMPRESS = 0,
ROPKG_COMPRESSION_MODE_DECOMPRESS,
};
enum ropkg_compression_stream_op {
ROPKG_COMPRESSION_OP_CONTINUE = 0,
ROPKG_COMPRESSION_OP_END,
};
enum ropkg_compression_type {
ROPKG_COMPRESSION_NONE = 0,
ROPKG_COMPRESSION_ZSTD,
};
ROPKG_API const struct ropkg_compression_function *
ropkg_compression_function_for_type(enum ropkg_compression_type type);
ROPKG_API enum ropkg_status ropkg_compression_function_get_buffer_size(
const struct ropkg_compression_function *func,
enum ropkg_compression_stream_mode mode,
size_t *in_buffer_size,
size_t *out_buffer_size);
ROPKG_API const char *ropkg_compression_function_get_file_extension(
const struct ropkg_compression_function *func);
ROPKG_API enum ropkg_status ropkg_compression_stream_open(
const struct ropkg_compression_function *func,
void *in_buffer,
size_t in_max,
void *out_buffer,
size_t out_max,
enum ropkg_compression_stream_mode mode,
struct ropkg_compression_stream **out);
ROPKG_API enum ropkg_status ropkg_compression_stream_process(
struct ropkg_compression_stream *stream,
size_t in_size,
enum ropkg_compression_stream_op op,
size_t *out_size);
ROPKG_API enum ropkg_status ropkg_compression_stream_close(
struct ropkg_compression_stream *stream);
#endif

View File

@@ -1,58 +0,0 @@
#ifndef ROPKG_STREAM_H_
#define ROPKG_STREAM_H_
#include <ropkg/misc.h>
#include <ropkg/status.h>
#include <stdbool.h>
#include <stdio.h>
struct ropkg_stream;
struct ropkg_compression_function;
enum ropkg_stream_mode {
ROPKG_STREAM_READ,
ROPKG_STREAM_WRITE,
};
ROPKG_API enum ropkg_status ropkg_stream_open(
FILE *fp,
const struct ropkg_compression_function *func,
enum ropkg_stream_mode mode,
struct ropkg_stream **out);
ROPKG_API enum ropkg_status ropkg_stream_close(struct ropkg_stream *stream);
ROPKG_API enum ropkg_status ropkg_stream_begin_compressed_section(
struct ropkg_stream *stream);
ROPKG_API enum ropkg_status ropkg_stream_end_compressed_section(
struct ropkg_stream *stream,
size_t *out_nr_written_compressed,
size_t *out_nr_written_uncompressed);
ROPKG_API enum ropkg_status ropkg_stream_read(
struct ropkg_stream *stream,
void *p,
size_t len,
size_t *nr_read);
ROPKG_API enum ropkg_status ropkg_stream_write(
struct ropkg_stream *stream,
const void *p,
size_t len,
size_t *nr_written);
ROPKG_API size_t ropkg_stream_get_cursor_position(struct ropkg_stream *stream);
ROPKG_API enum ropkg_status ropkg_stream_set_cursor_position(
struct ropkg_stream *stream,
size_t pos);
ROPKG_API enum ropkg_status ropkg_stream_restore_cursor_position(
struct ropkg_stream *stream);
ROPKG_API bool ropkg_stream_is_in_compressed_section(
struct ropkg_stream *stream);
ROPKG_API size_t ropkg_stream_get_nr_written(struct ropkg_stream *stream);
ROPKG_API size_t
ropkg_stream_get_nr_written_compressed(struct ropkg_stream *stream);
ROPKG_API size_t
ropkg_stream_get_nr_written_uncompressed(struct ropkg_stream *stream);
#endif

View File

@@ -10,14 +10,14 @@
#define ROPKG_PATH_META "meta.tar" #define ROPKG_PATH_META "meta.tar"
struct ropkg_writer; struct ropkg_writer;
struct ropkg_stream; struct b_cstream;
struct ropkg_writer_file_info { struct ropkg_writer_file_info {
size_t f_length; size_t f_length;
}; };
ROPKG_API enum ropkg_status ropkg_writer_open( ROPKG_API enum ropkg_status ropkg_writer_open(
struct ropkg_stream *fp, struct b_cstream *fp,
struct ropkg_writer **out); struct ropkg_writer **out);
ROPKG_API enum ropkg_status ropkg_writer_close(struct ropkg_writer *pkg); ROPKG_API enum ropkg_status ropkg_writer_close(struct ropkg_writer *pkg);

View File

@@ -1,355 +0,0 @@
#include "stream.h"
#include <ropkg/compress.h>
#include <ropkg/stream.h>
#include <stdlib.h>
#include <string.h>
enum ropkg_status ropkg_stream_open(
FILE *fp,
const struct ropkg_compression_function *func,
enum ropkg_stream_mode mode,
struct ropkg_stream **out)
{
switch (mode) {
case ROPKG_STREAM_READ:
case ROPKG_STREAM_WRITE:
break;
default:
return ROPKG_ERR_INVALID_ARGUMENT;
}
struct ropkg_stream *stream = malloc(sizeof *stream);
if (!stream) {
return ROPKG_ERR_NO_MEMORY;
}
memset(stream, 0x0, sizeof *stream);
stream->s_fp = fp;
stream->s_mode = mode;
if (!func) {
*out = stream;
return ROPKG_SUCCESS;
}
struct ropkg_stream_compressor *c = &stream->s_compressor;
enum ropkg_compression_stream_mode c_mode;
switch (mode) {
case ROPKG_STREAM_READ:
c_mode = ROPKG_COMPRESSION_MODE_DECOMPRESS;
break;
case ROPKG_STREAM_WRITE:
c_mode = ROPKG_COMPRESSION_MODE_COMPRESS;
break;
default:
/* this won't happen */
return ROPKG_ERR_INVALID_ARGUMENT;
}
enum ropkg_status status = ropkg_compression_function_get_buffer_size(
func,
c_mode,
&c->c_in_max,
&c->c_out_max);
if (status != ROPKG_SUCCESS) {
free(stream);
return status;
}
c->c_in_buf = malloc(c->c_in_max);
if (!c->c_in_buf) {
free(stream);
return ROPKG_ERR_NO_MEMORY;
}
c->c_out_buf = malloc(c->c_out_max);
if (!c->c_out_buf) {
free(c->c_in_buf);
free(stream);
return ROPKG_ERR_NO_MEMORY;
}
status = ropkg_compression_stream_open(
func,
c->c_in_buf,
c->c_in_max,
c->c_out_buf,
c->c_out_max,
c_mode,
&c->c_stream);
if (status != ROPKG_SUCCESS) {
free(c->c_in_buf);
free(c->c_out_buf);
free(stream);
return status;
}
c->c_func = func;
*out = stream;
return ROPKG_SUCCESS;
}
enum ropkg_status ropkg_stream_close(struct ropkg_stream *stream)
{
while (stream->s_compression_depth > 0) {
ropkg_stream_end_compressed_section(stream, NULL, NULL);
}
if (stream->s_compressor.c_in_buf) {
free(stream->s_compressor.c_in_buf);
}
if (stream->s_compressor.c_out_buf) {
free(stream->s_compressor.c_out_buf);
}
if (stream->s_compressor.c_stream) {
ropkg_compression_stream_close(stream->s_compressor.c_stream);
}
free(stream);
return ROPKG_SUCCESS;
}
enum ropkg_status ropkg_stream_begin_compressed_section(
struct ropkg_stream *stream)
{
if (stream->s_flags & ROPKG_STREAM_F_CURSOR_MOVED) {
return ROPKG_ERR_BAD_STATE;
}
if (stream->s_compression_depth > 0) {
stream->s_compression_depth++;
return ROPKG_SUCCESS;
}
stream->s_compression_depth = 1;
stream->s_compressor.c_in_count = 0;
stream->s_compressor.c_nr_written_compressed = 0;
stream->s_compressor.c_nr_written_uncompressed = 0;
return ROPKG_SUCCESS;
}
enum ropkg_status ropkg_stream_end_compressed_section(
struct ropkg_stream *stream,
size_t *out_nr_written_compressed,
size_t *out_nr_written_uncompressed)
{
if (stream->s_flags & ROPKG_STREAM_F_CURSOR_MOVED) {
return ROPKG_ERR_BAD_STATE;
}
if (stream->s_compression_depth == 0) {
return ROPKG_ERR_BAD_STATE;
}
if (stream->s_compression_depth > 1) {
stream->s_compression_depth--;
return ROPKG_SUCCESS;
}
stream->s_compression_depth = 0;
struct ropkg_stream_compressor *c = &stream->s_compressor;
if (out_nr_written_compressed) {
*out_nr_written_compressed = c->c_nr_written_compressed;
}
if (out_nr_written_uncompressed) {
*out_nr_written_uncompressed = c->c_nr_written_uncompressed;
}
if (c->c_nr_written_uncompressed == 0) {
return ROPKG_SUCCESS;
}
size_t out_size = 0;
ropkg_compression_stream_process(
c->c_stream,
c->c_in_count,
ROPKG_COMPRESSION_OP_END,
&out_size);
size_t nr_written = fwrite(c->c_out_buf, 1, out_size, stream->s_fp);
if (nr_written != out_size) {
return ROPKG_ERR_IO_FAILURE;
}
c->c_nr_written_compressed += nr_written;
stream->s_nr_written += out_size;
if (out_nr_written_compressed) {
*out_nr_written_compressed = c->c_nr_written_compressed;
}
stream->s_compressor.c_in_count = 0;
stream->s_compressor.c_nr_written_compressed = 0;
stream->s_compressor.c_nr_written_uncompressed = 0;
return ROPKG_SUCCESS;
}
enum ropkg_status ropkg_stream_read(
struct ropkg_stream *stream,
void *p,
size_t len,
size_t *nr_read)
{
if (stream->s_mode != ROPKG_STREAM_READ) {
return ROPKG_ERR_BAD_STATE;
}
return ROPKG_SUCCESS;
}
static enum ropkg_status flush_compressed_buffer(struct ropkg_stream *stream)
{
struct ropkg_stream_compressor *c = &stream->s_compressor;
size_t out_size;
enum ropkg_status status = ropkg_compression_stream_process(
c->c_stream,
c->c_in_count,
ROPKG_COMPRESSION_OP_CONTINUE,
&out_size);
if (status != ROPKG_SUCCESS) {
return status;
}
size_t written = fwrite(c->c_out_buf, 1, out_size, stream->s_fp);
c->c_nr_written_compressed += c->c_in_count;
stream->s_nr_written_compressed = c->c_in_count;
stream->s_nr_written += out_size;
return ROPKG_SUCCESS;
}
enum ropkg_status ropkg_stream_write(
struct ropkg_stream *stream,
const void *p,
size_t len,
size_t *nr_written)
{
if (stream->s_mode != ROPKG_STREAM_WRITE) {
return ROPKG_ERR_BAD_STATE;
}
size_t w = 0;
if (stream->s_compression_depth == 0) {
w = fwrite(p, 1, len, stream->s_fp);
*nr_written = w;
if (w != len) {
return ROPKG_ERR_IO_FAILURE;
}
if (!(stream->s_flags & ROPKG_STREAM_F_CURSOR_MOVED)) {
stream->s_nr_written_uncompressed += w;
stream->s_nr_written += w;
}
return ROPKG_SUCCESS;
}
if (stream->s_flags & ROPKG_STREAM_F_CURSOR_MOVED) {
return ROPKG_ERR_BAD_STATE;
}
struct ropkg_stream_compressor *c = &stream->s_compressor;
const unsigned char *src = p;
enum ropkg_status status = ROPKG_SUCCESS;
size_t remaining = len;
while (remaining > 0 && status == ROPKG_SUCCESS) {
unsigned char *dest = c->c_in_buf + c->c_in_count;
size_t space_remaining = c->c_in_max - c->c_in_count;
size_t to_copy = remaining;
if (to_copy > space_remaining) {
to_copy = space_remaining;
}
memcpy(dest, src, to_copy);
c->c_in_count += to_copy;
c->c_nr_written_uncompressed += to_copy;
stream->s_nr_written_uncompressed += to_copy;
space_remaining -= to_copy;
remaining -= to_copy;
w += to_copy;
if (space_remaining == 0) {
status = flush_compressed_buffer(stream);
}
}
*nr_written = w;
return status;
}
size_t ropkg_stream_get_cursor_position(struct ropkg_stream *stream)
{
return ftell(stream->s_fp);
}
enum ropkg_status ropkg_stream_set_cursor_position(
struct ropkg_stream *stream,
size_t pos)
{
if (stream->s_flags & ROPKG_STREAM_F_CURSOR_MOVED) {
return ROPKG_ERR_BAD_STATE;
}
if (stream->s_compression_depth > 0) {
return ROPKG_ERR_BAD_STATE;
}
stream->s_saved_cursor = ftell(stream->s_fp);
fseek(stream->s_fp, pos, SEEK_SET);
stream->s_flags |= ROPKG_STREAM_F_CURSOR_MOVED;
return ROPKG_SUCCESS;
}
enum ropkg_status ropkg_stream_restore_cursor_position(
struct ropkg_stream *stream)
{
if (!(stream->s_flags & ROPKG_STREAM_F_CURSOR_MOVED)) {
return ROPKG_ERR_BAD_STATE;
}
fseek(stream->s_fp, stream->s_saved_cursor, SEEK_SET);
stream->s_saved_cursor = 0;
stream->s_flags &= ~ROPKG_STREAM_F_CURSOR_MOVED;
return ROPKG_SUCCESS;
}
bool ropkg_stream_is_in_compressed_section(struct ropkg_stream *stream)
{
return stream->s_compression_depth > 0;
}
size_t ropkg_stream_get_nr_written(struct ropkg_stream *stream)
{
return stream->s_nr_written;
}
size_t ropkg_stream_get_nr_written_compressed(struct ropkg_stream *stream)
{
return stream->s_nr_written_compressed;
}
size_t ropkg_stream_get_nr_written_uncompressed(struct ropkg_stream *stream)
{
return stream->s_nr_written_uncompressed;
}

View File

@@ -1,39 +0,0 @@
#ifndef _ROPKG_STREAM_H_
#define _ROPKG_STREAM_H_
#include <ropkg/stream.h>
#include <stdio.h>
struct ropkg_compression_function;
struct ropkg_compression_stream;
enum ropkg_stream_flags {
ROPKG_STREAM_F_CURSOR_MOVED = 0x01u,
};
struct ropkg_stream_compressor {
const struct ropkg_compression_function *c_func;
struct ropkg_compression_stream *c_stream;
size_t c_in_max, c_out_max;
void *c_in_buf, *c_out_buf;
size_t c_in_count;
size_t c_nr_written_compressed, c_nr_written_uncompressed;
};
struct ropkg_stream {
FILE *s_fp;
enum ropkg_stream_flags s_flags;
enum ropkg_stream_mode s_mode;
unsigned int s_compression_depth;
struct ropkg_stream_compressor s_compressor;
size_t s_saved_cursor;
size_t s_nr_written;
size_t s_nr_written_compressed;
size_t s_nr_written_uncompressed;
};
#endif

24
libropkg/tar.h Normal file
View File

@@ -0,0 +1,24 @@
#ifndef _TAR_H_
#define _TAR_H_
struct ustar_header {
char tar_filename[100];
char tar_mode[8];
char tar_uid[8];
char tar_gid[8];
char tar_filesize[12];
char tar_mtime[12];
char tar_checksum[8];
char tar_type[1];
char tar_linkname[100];
char tar_ustar_id[6];
char tar_ustar_version[2];
char tar_owner_name[32];
char tar_owner_group[32];
char tar_dev_major[8];
char tar_dev_minor[8];
char tar_filename_prefix[155];
char tar_padding[12];
};
#endif

View File

@@ -1,31 +1,12 @@
#include <ropkg/compress.h> #include "tar.h"
#include <ropkg/stream.h>
#include <blue/compress/cstream.h>
#include <ropkg/writer.h> #include <ropkg/writer.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
struct ustar_header {
char tar_filename[100];
char tar_mode[8];
char tar_uid[8];
char tar_gid[8];
char tar_filesize[12];
char tar_mtime[12];
char tar_checksum[8];
char tar_type[1];
char tar_linkname[100];
char tar_ustar_id[6];
char tar_ustar_version[2];
char tar_owner_name[32];
char tar_owner_group[32];
char tar_dev_major[8];
char tar_dev_minor[8];
char tar_filename_prefix[155];
char tar_padding[12];
};
struct ropkg_writer { struct ropkg_writer {
struct ropkg_stream *w_fp; b_cstream *w_fp;
struct ustar_header w_file_header; struct ustar_header w_file_header;
size_t w_file_header_offset; size_t w_file_header_offset;
@@ -34,9 +15,7 @@ struct ropkg_writer {
static const char zero_padding[512] = {0}; static const char zero_padding[512] = {0};
enum ropkg_status ropkg_writer_open( enum ropkg_status ropkg_writer_open(b_cstream *fp, struct ropkg_writer **out)
struct ropkg_stream *fp,
struct ropkg_writer **out)
{ {
struct ropkg_writer *writer = malloc(sizeof *writer); struct ropkg_writer *writer = malloc(sizeof *writer);
if (!writer) { if (!writer) {
@@ -56,24 +35,24 @@ enum ropkg_status ropkg_writer_close(struct ropkg_writer *pkg)
memset(&pkg->w_file_header, 0x0, sizeof pkg->w_file_header); memset(&pkg->w_file_header, 0x0, sizeof pkg->w_file_header);
size_t nr_written; size_t nr_written;
enum ropkg_status status = ropkg_stream_write( b_status status = b_cstream_write(
pkg->w_fp, pkg->w_fp,
&pkg->w_file_header, &pkg->w_file_header,
sizeof pkg->w_file_header, sizeof pkg->w_file_header,
&nr_written); &nr_written);
if (status != ROPKG_SUCCESS) { if (!B_OK(status)) {
return status; return ROPKG_ERR_IO_FAILURE;
} }
status = ropkg_stream_write( status = b_cstream_write(
pkg->w_fp, pkg->w_fp,
&pkg->w_file_header, &pkg->w_file_header,
sizeof pkg->w_file_header, sizeof pkg->w_file_header,
&nr_written); &nr_written);
if (status != ROPKG_SUCCESS) { if (!B_OK(status)) {
return status; return ROPKG_ERR_IO_FAILURE;
} }
if (nr_written != sizeof pkg->w_file_header) { if (nr_written != sizeof pkg->w_file_header) {
@@ -129,12 +108,12 @@ enum ropkg_status ropkg_writer_begin_file(
const char *path, const char *path,
const struct ropkg_writer_file_info *info) const struct ropkg_writer_file_info *info)
{ {
if (ropkg_stream_is_in_compressed_section(pkg->w_fp)) { if (b_cstream_in_compressed_section(pkg->w_fp)) {
pkg->w_file_header_offset b_cstream_tx_bytes_uncompressed(
= ropkg_stream_get_nr_written_uncompressed(pkg->w_fp); pkg->w_fp,
&pkg->w_file_header_offset);
} else { } else {
pkg->w_file_header_offset b_cstream_tx_bytes(pkg->w_fp, &pkg->w_file_header_offset);
= ropkg_stream_get_nr_written(pkg->w_fp);
} }
enum ropkg_status status enum ropkg_status status
@@ -144,14 +123,14 @@ enum ropkg_status ropkg_writer_begin_file(
} }
size_t nr_written; size_t nr_written;
status = ropkg_stream_write( b_status status2 = b_cstream_write(
pkg->w_fp, pkg->w_fp,
&pkg->w_file_header, &pkg->w_file_header,
sizeof pkg->w_file_header, sizeof pkg->w_file_header,
&nr_written); &nr_written);
if (status != ROPKG_SUCCESS) { if (!B_OK(status2)) {
return status; return ROPKG_ERR_IO_FAILURE;
} }
if (nr_written != sizeof pkg->w_file_header) { if (nr_written != sizeof pkg->w_file_header) {
@@ -163,26 +142,26 @@ enum ropkg_status ropkg_writer_begin_file(
enum ropkg_status ropkg_writer_end_file(struct ropkg_writer *pkg) enum ropkg_status ropkg_writer_end_file(struct ropkg_writer *pkg)
{ {
enum ropkg_status status; b_status status;
size_t written, file_length, pos; size_t written, file_length, pos;
if (ropkg_stream_is_in_compressed_section(pkg->w_fp)) { if (b_cstream_in_compressed_section(pkg->w_fp)) {
pos = ropkg_stream_get_nr_written_uncompressed(pkg->w_fp); b_cstream_tx_bytes_uncompressed(pkg->w_fp, &pos);
} else { } else {
pos = ropkg_stream_get_nr_written(pkg->w_fp); b_cstream_tx_bytes(pkg->w_fp, &pos);
} }
file_length file_length
= pos - pkg->w_file_header_offset - sizeof pkg->w_file_header; = pos - pkg->w_file_header_offset - sizeof pkg->w_file_header;
size_t required_padding = 512 - (file_length % 512); size_t required_padding = 512 - (file_length % 512);
status = ropkg_stream_write( status = b_cstream_write(
pkg->w_fp, pkg->w_fp,
zero_padding, zero_padding,
required_padding, required_padding,
&written); &written);
if (status != ROPKG_SUCCESS) { if (!B_OK(status)) {
return status; return ROPKG_ERR_IO_FAILURE;
} }
to_octal( to_octal(
@@ -191,16 +170,16 @@ enum ropkg_status ropkg_writer_end_file(struct ropkg_writer *pkg)
sizeof pkg->w_file_header.tar_filesize); sizeof pkg->w_file_header.tar_filesize);
refresh_header_checksum(&pkg->w_file_header); refresh_header_checksum(&pkg->w_file_header);
status = ropkg_stream_set_cursor_position( status = b_cstream_set_cursor_position(
pkg->w_fp, pkg->w_fp,
pkg->w_file_header_offset); pkg->w_file_header_offset);
if (status == ROPKG_SUCCESS) { if (B_OK(status)) {
ropkg_stream_write( b_cstream_write(
pkg->w_fp, pkg->w_fp,
&pkg->w_file_header, &pkg->w_file_header,
sizeof pkg->w_file_header, sizeof pkg->w_file_header,
&written); &written);
ropkg_stream_restore_cursor_position(pkg->w_fp); b_cstream_restore_cursor_position(pkg->w_fp);
} }
return ROPKG_SUCCESS; return ROPKG_SUCCESS;
@@ -212,10 +191,9 @@ enum ropkg_status ropkg_writer_write(
size_t len, size_t len,
size_t *nr_written) size_t *nr_written)
{ {
enum ropkg_status status b_status status = b_cstream_write(pkg->w_fp, p, len, nr_written);
= ropkg_stream_write(pkg->w_fp, p, len, nr_written); if (!B_OK(status)) {
if (status != ROPKG_SUCCESS) { return ROPKG_ERR_IO_FAILURE;
return status;
} }
pkg->w_file_nr_written += len; pkg->w_file_nr_written += len;

View File

@@ -1,203 +0,0 @@
#include "compress.h"
#include <stdlib.h>
#include <string.h>
#include <zstd.h>
struct zstd_stream {
struct ropkg_compression_stream s_base;
union {
ZSTD_CCtx *c;
ZSTD_DCtx *d;
} s_ctx;
};
static enum ropkg_status zstd_buffer_size(
enum ropkg_compression_stream_mode mode,
size_t *in_buffer_size,
size_t *out_buffer_size)
{
switch (mode) {
case ROPKG_COMPRESSION_MODE_COMPRESS:
if (in_buffer_size) {
*in_buffer_size = ZSTD_CStreamInSize();
}
if (out_buffer_size) {
*out_buffer_size = ZSTD_CStreamOutSize();
}
return ROPKG_SUCCESS;
case ROPKG_COMPRESSION_MODE_DECOMPRESS:
if (in_buffer_size) {
*in_buffer_size = ZSTD_DStreamInSize();
}
if (out_buffer_size) {
*out_buffer_size = ZSTD_DStreamOutSize();
}
return ROPKG_SUCCESS;
default:
return ROPKG_ERR_INVALID_ARGUMENT;
}
}
static enum ropkg_status zstd_open(
const struct ropkg_compression_function *func,
enum ropkg_compression_stream_mode mode,
void *in_buffer,
size_t in_max,
void *out_buffer,
size_t out_max,
struct ropkg_compression_stream **out)
{
struct zstd_stream *stream = malloc(sizeof *stream);
if (!stream) {
return ROPKG_ERR_NO_MEMORY;
}
memset(stream, 0x0, sizeof *stream);
stream->s_base.s_in = in_buffer;
stream->s_base.s_in_max = in_max;
stream->s_base.s_out = out_buffer;
stream->s_base.s_out_max = out_max;
stream->s_base.s_func = func;
stream->s_base.s_mode = mode;
switch (mode) {
case ROPKG_COMPRESSION_MODE_COMPRESS:
stream->s_ctx.c = ZSTD_createCCtx();
if (!stream->s_ctx.c) {
free(stream);
return ROPKG_ERR_NO_MEMORY;
}
ZSTD_CCtx_setParameter(
stream->s_ctx.c,
ZSTD_c_compressionLevel,
10);
ZSTD_CCtx_setParameter(stream->s_ctx.c, ZSTD_c_checksumFlag, 1);
break;
case ROPKG_COMPRESSION_MODE_DECOMPRESS:
stream->s_ctx.d = ZSTD_createDCtx();
if (!stream->s_ctx.d) {
free(stream);
return ROPKG_ERR_NO_MEMORY;
}
break;
default:
free(stream);
return ROPKG_ERR_INVALID_ARGUMENT;
}
*out = &stream->s_base;
return ROPKG_SUCCESS;
}
static enum ropkg_status zstd_close(struct ropkg_compression_stream *stream)
{
struct zstd_stream *zstream = (struct zstd_stream *)stream;
switch (stream->s_mode) {
case ROPKG_COMPRESSION_MODE_COMPRESS:
ZSTD_freeCCtx(zstream->s_ctx.c);
break;
case ROPKG_COMPRESSION_MODE_DECOMPRESS:
ZSTD_freeDCtx(zstream->s_ctx.d);
break;
default:
return ROPKG_ERR_BAD_STATE;
}
free(stream);
return ROPKG_SUCCESS;
}
static enum ropkg_status zstd_compress(
struct zstd_stream *zstream,
enum ropkg_compression_stream_op op,
ZSTD_inBuffer *in,
ZSTD_outBuffer *out)
{
ZSTD_EndDirective zop;
switch (op) {
case ROPKG_COMPRESSION_OP_CONTINUE:
zop = ZSTD_e_continue;
break;
case ROPKG_COMPRESSION_OP_END:
zop = ZSTD_e_end;
break;
default:
return ROPKG_ERR_INVALID_ARGUMENT;
}
do {
size_t ret
= ZSTD_compressStream2(zstream->s_ctx.c, out, in, zop);
if (ret == 0) {
break;
}
} while (in->pos < in->size);
return ROPKG_SUCCESS;
}
static enum ropkg_status zstd_decompress(
struct zstd_stream *zstream,
ZSTD_inBuffer *in,
ZSTD_outBuffer *out)
{
size_t ret = 0;
while (in->pos < in->size) {
ret = ZSTD_decompressStream(zstream->s_ctx.d, out, in);
}
if (ret != 0) {
return ROPKG_ERR_INTERNAL_FAILURE;
}
return ROPKG_SUCCESS;
}
static enum ropkg_status zstd_process(
struct ropkg_compression_stream *stream,
size_t in_size,
enum ropkg_compression_stream_op op,
size_t *out_size)
{
struct zstd_stream *zstream = (struct zstd_stream *)stream;
ZSTD_inBuffer in = {.src = stream->s_in, .size = in_size};
ZSTD_outBuffer out = {.dst = stream->s_out, .size = stream->s_out_max};
enum ropkg_status status;
switch (stream->s_mode) {
case ROPKG_COMPRESSION_MODE_COMPRESS:
status = zstd_compress(zstream, op, &in, &out);
break;
case ROPKG_COMPRESSION_MODE_DECOMPRESS:
status = zstd_decompress(zstream, &in, &out);
break;
default:
return ROPKG_ERR_BAD_STATE;
}
if (out_size) {
*out_size = out.pos;
}
return ROPKG_SUCCESS;
}
const struct ropkg_compression_function ropkg_zstd = {
.f_name = "zstd",
.f_extension = ".zst",
.f_buffer_size = zstd_buffer_size,
.f_open = zstd_open,
.f_close = zstd_close,
.f_process = zstd_process,
};