__LA_DECL const char * archive_liblzma_version(void);
__LA_DECL const char * archive_bzlib_version(void);
__LA_DECL const char * archive_liblz4_version(void);
+__LA_DECL const char * archive_libzstd_version(void);
/* Declare our basic types. */
struct archive;
unsigned char *out_block;
size_t out_block_size;
int64_t total_out;
+ char endFrame; /* True = not in the middle of a zstd frame. */
char eof; /* True = found end of compressed data. */
char in_stream;
};
self->close = zstd_filter_close;
state->in_stream = 0; /* We're not actually within a stream yet. */
+ state->eof = 0;
+ state->endFrame = 1; /* We could end now without corruption */
return (ARCHIVE_OK);
}
}
in.src = __archive_read_filter_ahead(self->upstream, 1,
&avail_in);
- if (in.src == NULL && avail_in <= 0) {
- archive_set_error(&self->archive->archive,
- ARCHIVE_ERRNO_MISC,
- "Truncated zstd input");
- return (ARCHIVE_FATAL);
+ if (avail_in < 0) {
+ return avail_in;
+ }
+ if (in.src == NULL && avail_in == 0) {
+ if (state->endFrame) {
+ /* end of stream */
+ state->eof = 1;
+ break;
+ } else {
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_MISC,
+ "Truncated zstd input");
+ return (ARCHIVE_FATAL);
+ }
}
in.size = avail_in;
in.pos = 0;
/* Decompressor made some progress */
__archive_read_filter_consume(self->upstream, in.pos);
- /* Found end of the frame */
- if (ret == 0) {
- state->eof = 1;
- }
+ /* Need to know if it's the end of the frame, as if input ends
+ * at any other time it's an error */
+ state->endFrame = (ret == 0);
}
decompressed = out.pos;
#ifdef HAVE_LZ4_H
#include <lz4.h>
#endif
+#ifdef HAVE_ZSTD_H
+#include <zstd.h>
+#endif
#include "archive.h"
#include "archive_private.h"
const char *liblzma = archive_liblzma_version();
const char *bzlib = archive_bzlib_version();
const char *liblz4 = archive_liblz4_version();
+ const char *libzstd = archive_libzstd_version();
if (!init) {
archive_string_init(&str);
archive_strcat(&str, " liblz4/");
archive_strcat(&str, liblz4);
}
+ if (libzstd) {
+ archive_strcat(&str, " libzstd/");
+ archive_strcat(&str, libzstd);
+ }
}
return str.s;
}
return NULL;
#endif
}
+
+const char *
+archive_libzstd_version(void)
+{
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+ return ZSTD_VERSION_STRING;
+#else
+ return NULL;
+#endif
+}