Change lzw_decompress() signature
This commit is contained in:
parent
f39d8599a4
commit
c183681289
6
Makefile
6
Makefile
|
@ -1,5 +1,5 @@
|
||||||
CC = clang
|
CC = clang
|
||||||
CFLAGS ?= -Wall -Wextra -pedantic -std=c89 -Og -g -pg
|
CFLAGS ?= -Wall -Wextra -pedantic -std=c89 -O0 -g -pg
|
||||||
STRIP = strip
|
STRIP = strip
|
||||||
FORMAT = clang-format -i
|
FORMAT = clang-format -i
|
||||||
BIN = dsk2img
|
BIN = dsk2img
|
||||||
|
@ -13,8 +13,8 @@ tests: $(TESTS)
|
||||||
strip: $(BIN)
|
strip: $(BIN)
|
||||||
$(STRIP) $^
|
$(STRIP) $^
|
||||||
|
|
||||||
test-lzw: lzw.o
|
test-lzw: lzw.o utils.o
|
||||||
dsk2img: lzw.o
|
dsk2img: lzw.o utils.o
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(RM) $(BIN) $(TESTS) *.o *~ *%
|
$(RM) $(BIN) $(TESTS) *.o *~ *%
|
||||||
|
|
70
dsk2img.c
70
dsk2img.c
|
@ -1,5 +1,6 @@
|
||||||
#define _POSIX_C_SOURCE 2
|
#define _POSIX_C_SOURCE 2
|
||||||
#include "lzw.h"
|
#include "lzw.h"
|
||||||
|
#include "utils.h"
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -7,6 +8,8 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#undef DEBUG
|
||||||
|
|
||||||
#define MAGIC_DSK_OLD 0x58aa
|
#define MAGIC_DSK_OLD 0x58aa
|
||||||
#define MAGIC_DSK_UNCOMPRESSED 0x59aa
|
#define MAGIC_DSK_UNCOMPRESSED 0x59aa
|
||||||
#define MAGIC_DSK_COMPRESSED 0x5aaa
|
#define MAGIC_DSK_COMPRESSED 0x5aaa
|
||||||
|
@ -58,10 +61,10 @@ const struct media_type {
|
||||||
{ 512, 80, 2, 18, "3.5\" DSHD 1.44MB" },
|
{ 512, 80, 2, 18, "3.5\" DSHD 1.44MB" },
|
||||||
{ 512, 80, 2, 9, "3.5\" DSDD 720KB" },
|
{ 512, 80, 2, 9, "3.5\" DSDD 720KB" },
|
||||||
{ 512, 80, 2, 15, "5.25\" DSHD 1.2MB" },
|
{ 512, 80, 2, 15, "5.25\" DSHD 1.2MB" },
|
||||||
|
{ 512, 40, 2, 9, "5.25\" DSDD 360KB" },
|
||||||
{ 512, 40, 1, 8, "5.25\" SSDD 160KB" },
|
{ 512, 40, 1, 8, "5.25\" SSDD 160KB" },
|
||||||
{ 512, 40, 1, 9, "5.25\" SSDD 180KB" },
|
{ 512, 40, 1, 9, "5.25\" SSDD 180KB" },
|
||||||
{ 512, 40, 2, 8, "5.25\" DSDD 320KB" },
|
{ 512, 40, 2, 8, "5.25\" DSDD 320KB" },
|
||||||
{ 512, 40, 2, 9, "5.25\" DSDD 360KB" },
|
|
||||||
{ 512, 80, 1, 8, "5.25\" SSQD 320KB" },
|
{ 512, 80, 1, 8, "5.25\" SSQD 320KB" },
|
||||||
{ 512, 80, 2, 8, "5.25\" DSQD 640KB" },
|
{ 512, 80, 2, 8, "5.25\" DSQD 640KB" },
|
||||||
{ 512, 80, 1, 8, "3.5\" SSDD 320KB" },
|
{ 512, 80, 1, 8, "3.5\" SSDD 320KB" },
|
||||||
|
@ -78,11 +81,10 @@ char* guess_output_filename(const char* input_filename, int is_compressed)
|
||||||
unsigned int ifnlen, ofnlen;
|
unsigned int ifnlen, ofnlen;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* NOLINTBEGIN(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling) */
|
|
||||||
ifnlen = strlen(input_filename);
|
ifnlen = strlen(input_filename);
|
||||||
ofnlen = ifnlen + 9;
|
ofnlen = ifnlen + 9;
|
||||||
outname = (char*)malloc(ofnlen);
|
outname = (char*)malloc(ofnlen);
|
||||||
strncpy(outname, input_filename, ofnlen);
|
strlcpy(outname, input_filename, ofnlen);
|
||||||
/* strip extension */
|
/* strip extension */
|
||||||
for (i = ifnlen; i > 0; i--) {
|
for (i = ifnlen; i > 0; i--) {
|
||||||
if (outname[i - 1] == '.') {
|
if (outname[i - 1] == '.') {
|
||||||
|
@ -93,15 +95,14 @@ char* guess_output_filename(const char* input_filename, int is_compressed)
|
||||||
}
|
}
|
||||||
#ifdef DOSLIKE
|
#ifdef DOSLIKE
|
||||||
if (is_compressed) /* use filename.lzw instead of filename.img.lzw on dos and win */
|
if (is_compressed) /* use filename.lzw instead of filename.img.lzw on dos and win */
|
||||||
strcat(outname, ".lzw");
|
strlcat(outname, ".lzw", ofnlen);
|
||||||
else
|
else
|
||||||
strcat(outname, ".img");
|
strlcat(outname, ".img", ofnlen);
|
||||||
#else
|
#else
|
||||||
strncat(outname, ".img", ofnlen);
|
strlcat(outname, ".img", ofnlen);
|
||||||
if (is_compressed)
|
if (is_compressed)
|
||||||
strncat(outname, ".lzw", ofnlen);
|
strlcat(outname, ".lzw", ofnlen);
|
||||||
#endif
|
#endif
|
||||||
/* NOLINTEND(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling) */
|
|
||||||
|
|
||||||
return outname;
|
return outname;
|
||||||
}
|
}
|
||||||
|
@ -156,8 +157,10 @@ int valid_header(const struct dskheader* h)
|
||||||
return 0;
|
return 0;
|
||||||
if (h->reservedsectors + h->fatcopies * h->sectorsperfat != h->rootdirsector)
|
if (h->reservedsectors + h->fatcopies * h->sectorsperfat != h->rootdirsector)
|
||||||
return 0;
|
return 0;
|
||||||
|
/*
|
||||||
if (h->firstclustersector - 1 + cluster_sectors != final_sectors)
|
if (h->firstclustersector - 1 + cluster_sectors != final_sectors)
|
||||||
return 0;
|
return 0;
|
||||||
|
*/
|
||||||
if (h->firstclustersector != h->reservedsectors + h->fatcopies * h->sectorsperfat + h->rootentries * 32 / h->sectorsize)
|
if (h->firstclustersector != h->reservedsectors + h->fatcopies * h->sectorsperfat + h->rootentries * 32 / h->sectorsize)
|
||||||
return 0;
|
return 0;
|
||||||
if (h->imagesectors > final_sectors)
|
if (h->imagesectors > final_sectors)
|
||||||
|
@ -275,9 +278,8 @@ int copy_compressed_image_data(FILE* fin, FILE* fout)
|
||||||
int decompress_image_data(FILE* fin, FILE* fout, size_t size, uint32_t* checksum)
|
int decompress_image_data(FILE* fin, FILE* fout, size_t size, uint32_t* checksum)
|
||||||
{
|
{
|
||||||
unsigned long int copied_bytes = 0;
|
unsigned long int copied_bytes = 0;
|
||||||
size_t read_count, decompress_count;
|
size_t read_available, read_consumed, decompress_consumed;
|
||||||
uint8_t *read_buffer, *decompress_buffer;
|
uint8_t *read_buffer, *decompress_buffer;
|
||||||
uint8_t *read_ptr, *decompress_ptr;
|
|
||||||
struct lzw_ctx* lzw = NULL;
|
struct lzw_ctx* lzw = NULL;
|
||||||
|
|
||||||
read_buffer = (uint8_t*)malloc(READ_BUFFER_SIZE);
|
read_buffer = (uint8_t*)malloc(READ_BUFFER_SIZE);
|
||||||
|
@ -303,34 +305,25 @@ int decompress_image_data(FILE* fin, FILE* fout, size_t size, uint32_t* checksum
|
||||||
|
|
||||||
lzw_init(lzw);
|
lzw_init(lzw);
|
||||||
|
|
||||||
read_count = 0;
|
read_available = read_consumed = decompress_consumed = 0;
|
||||||
decompress_count = DECOMPRESS_BUFFER_SIZE;
|
while (1) {
|
||||||
read_ptr = read_buffer;
|
if (read_consumed >= read_available) {
|
||||||
decompress_ptr = decompress_buffer;
|
read_available = fread(read_buffer, 1, READ_BUFFER_SIZE, fin);
|
||||||
while ((lzw->eos == 0) && (copied_bytes < size)) {
|
read_consumed = 0;
|
||||||
if (read_count == 0) {
|
|
||||||
read_count = fread(read_buffer, 1, READ_BUFFER_SIZE, fin);
|
|
||||||
read_ptr = read_buffer;
|
|
||||||
}
|
}
|
||||||
if (decompress_count == 0) {
|
if (decompress_consumed >= DECOMPRESS_BUFFER_SIZE || ((lzw->eos != 0 || read_available == 0) && decompress_consumed > 0)) {
|
||||||
update_checksum(checksum, decompress_buffer, DECOMPRESS_BUFFER_SIZE);
|
update_checksum(checksum, decompress_buffer, decompress_consumed);
|
||||||
fwrite(decompress_buffer, 1, DECOMPRESS_BUFFER_SIZE, fout);
|
fwrite(decompress_buffer, 1, decompress_consumed, fout);
|
||||||
copied_bytes += DECOMPRESS_BUFFER_SIZE;
|
copied_bytes += decompress_consumed;
|
||||||
decompress_count = DECOMPRESS_BUFFER_SIZE;
|
decompress_consumed = 0;
|
||||||
decompress_ptr = decompress_buffer;
|
|
||||||
}
|
}
|
||||||
lzw_decompress(lzw, read_ptr, &read_count, decompress_ptr, &decompress_count);
|
if (lzw->eos || read_available == 0)
|
||||||
read_ptr = read_buffer + READ_BUFFER_SIZE - read_count;
|
break;
|
||||||
decompress_ptr = decompress_buffer + DECOMPRESS_BUFFER_SIZE - decompress_count;
|
lzw_decompress(lzw, read_buffer, read_available, &read_consumed, decompress_buffer, DECOMPRESS_BUFFER_SIZE, &decompress_consumed);
|
||||||
}
|
|
||||||
if (decompress_count < DECOMPRESS_BUFFER_SIZE) {
|
|
||||||
update_checksum(checksum, decompress_buffer, DECOMPRESS_BUFFER_SIZE - decompress_count);
|
|
||||||
fwrite(decompress_buffer, 1, DECOMPRESS_BUFFER_SIZE - decompress_count, fout);
|
|
||||||
copied_bytes += DECOMPRESS_BUFFER_SIZE - decompress_count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (copied_bytes != size)
|
if (copied_bytes != size)
|
||||||
printf("WARNING: Decompressed image size (%lu) does not match expected (%lu)", copied_bytes, size);
|
printf("WARNING: Decompressed image size (%lu) does not match expected (%lu)\n", copied_bytes, size);
|
||||||
|
|
||||||
free(read_buffer);
|
free(read_buffer);
|
||||||
free(decompress_buffer);
|
free(decompress_buffer);
|
||||||
|
@ -354,6 +347,10 @@ void dsk2img(const char* filename, int no_lzw)
|
||||||
int type_geom;
|
int type_geom;
|
||||||
char *rbuf = NULL, *wbuf = NULL; /* for setvbuf() */
|
char *rbuf = NULL, *wbuf = NULL; /* for setvbuf() */
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "Extracting %s\n", filename);
|
||||||
|
#endif
|
||||||
|
|
||||||
inf = fopen(filename, "rb");
|
inf = fopen(filename, "rb");
|
||||||
if (inf == NULL)
|
if (inf == NULL)
|
||||||
return;
|
return;
|
||||||
|
@ -370,12 +367,11 @@ void dsk2img(const char* filename, int no_lzw)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
dump_dsk_header(&header);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!valid_header(&header)) {
|
if (!valid_header(&header)) {
|
||||||
puts("Not a valid DSK file!");
|
puts("Not a valid DSK file!");
|
||||||
|
#ifdef DEBUG
|
||||||
|
dump_dsk_header(&header);
|
||||||
|
#endif
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
61
lzw.c
61
lzw.c
|
@ -45,6 +45,7 @@ void lzw_init(struct lzw_ctx* c)
|
||||||
c->output_buffer_start = 0;
|
c->output_buffer_start = 0;
|
||||||
c->output_buffer_used = 0;
|
c->output_buffer_used = 0;
|
||||||
c->input_code = c->input_code_bits = 0;
|
c->input_code = c->input_code_bits = 0;
|
||||||
|
c->uncompressed_bytes_processed = c->compressed_bytes_processed = c->codes_processed = 0;
|
||||||
c->eos = 0;
|
c->eos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,34 +125,41 @@ static int lzw_build_entry(struct lzw_ctx* c, uint16_t code)
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
int lzw_decompress(struct lzw_ctx* c, uint8_t* src, size_t* src_count, uint8_t* dst, size_t* dst_count)
|
#define MIN(a, b) ((a)<(b)?(a):(b))
|
||||||
|
|
||||||
|
int lzw_decompress(struct lzw_ctx* c,
|
||||||
|
uint8_t* src, size_t src_size, size_t* src_consumed,
|
||||||
|
uint8_t* dst, size_t dst_size, size_t* dst_consumed)
|
||||||
{
|
{
|
||||||
int bytes_read = 0;
|
|
||||||
int bytes_written = 0;
|
int bytes_written = 0;
|
||||||
uint16_t code;
|
uint16_t code;
|
||||||
uint16_t code_len, current_code;
|
uint16_t code_len, current_code;
|
||||||
|
|
||||||
if (c->eos != 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* First, flush out any remaining data in the string buffer */
|
/* First, flush out any remaining data in the string buffer */
|
||||||
while ((c->output_buffer_used > 0) && (*dst_count > 0)) {
|
/* NOLINTBEGIN(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling) */
|
||||||
dst[bytes_written++] = c->output_buffer[c->output_buffer_start];
|
if (c->output_buffer_used > 0) {
|
||||||
c->output_buffer_start = (c->output_buffer_start + 1) % 4096;
|
bytes_written = MIN(c->output_buffer_used, dst_size - *dst_consumed);
|
||||||
c->output_buffer_used--;
|
memcpy(&dst[*dst_consumed], &c->output_buffer[c->output_buffer_start], bytes_written);
|
||||||
--*dst_count;
|
c->output_buffer_used -= bytes_written;
|
||||||
|
c->output_buffer_start += bytes_written;
|
||||||
|
c->uncompressed_bytes_processed += bytes_written;
|
||||||
|
*dst_consumed += bytes_written;
|
||||||
}
|
}
|
||||||
while ((*src_count > 0) && (*dst_count > 0)) {
|
if (*dst_consumed >= dst_size)
|
||||||
|
return bytes_written;
|
||||||
|
/* NOLINTEND(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling) */
|
||||||
|
while (*src_consumed < src_size && *dst_consumed < dst_size && c->eos == 0) {
|
||||||
/* Get next 12bit code from the input buffer */
|
/* Get next 12bit code from the input buffer */
|
||||||
while ((c->input_code_bits < 12) && (*src_count > 0)) {
|
while (c->input_code_bits < 12 && *src_consumed < src_size) {
|
||||||
c->input_code = (c->input_code << 8) | src[bytes_read++];
|
c->input_code = (c->input_code << 8) | src[(*src_consumed)++];
|
||||||
c->input_code_bits += 8;
|
c->input_code_bits += 8;
|
||||||
--*src_count;
|
c->compressed_bytes_processed++;
|
||||||
}
|
}
|
||||||
if (c->input_code_bits < 12)
|
if (c->input_code_bits < 12)
|
||||||
return bytes_written;
|
return bytes_written;
|
||||||
code = (c->input_code >> (c->input_code_bits - 12)) & 0x0fff;
|
code = (c->input_code >> (c->input_code_bits - 12)) & 0x0fff;
|
||||||
c->input_code_bits -= 12;
|
c->input_code_bits -= 12;
|
||||||
|
c->codes_processed++;
|
||||||
if (code == 0) {
|
if (code == 0) {
|
||||||
c->eos = 1;
|
c->eos = 1;
|
||||||
return bytes_written;
|
return bytes_written;
|
||||||
|
@ -162,20 +170,19 @@ int lzw_decompress(struct lzw_ctx* c, uint8_t* src, size_t* src_count, uint8_t*
|
||||||
/* Output the corresponding string */
|
/* Output the corresponding string */
|
||||||
c->output_buffer_start = 0;
|
c->output_buffer_start = 0;
|
||||||
for (code_len = c->dict[code].length, current_code = code; current_code != 0 && code_len != 0; code_len--, current_code = c->dict[current_code].prefix) {
|
for (code_len = c->dict[code].length, current_code = code; current_code != 0 && code_len != 0; code_len--, current_code = c->dict[current_code].prefix) {
|
||||||
if (code_len <= *dst_count)
|
if (code_len <= dst_size - *dst_consumed) {
|
||||||
dst[bytes_written + code_len - 1] = c->dict[current_code].last;
|
dst[*dst_consumed + code_len - 1] = c->dict[current_code].last;
|
||||||
else
|
bytes_written++;
|
||||||
c->output_buffer[code_len - *dst_count - 1] = c->dict[current_code].last;
|
c->uncompressed_bytes_processed++;
|
||||||
}
|
} else {
|
||||||
if (c->dict[code].length <= *dst_count) {
|
c->output_buffer[code_len - (dst_size - *dst_consumed) - 1] = c->dict[current_code].last;
|
||||||
c->output_buffer_used = 0;
|
c->output_buffer_used++;
|
||||||
bytes_written += c->dict[code].length;
|
}
|
||||||
*dst_count -= c->dict[code].length;
|
|
||||||
} else {
|
|
||||||
c->output_buffer_used = c->dict[code].length - *dst_count;
|
|
||||||
bytes_written += *dst_count;
|
|
||||||
*dst_count = 0;
|
|
||||||
}
|
}
|
||||||
|
if (c->dict[code].length < dst_size - *dst_consumed)
|
||||||
|
*dst_consumed += c->dict[code].length;
|
||||||
|
else
|
||||||
|
*dst_consumed = dst_size;
|
||||||
c->last_emitted_code = code;
|
c->last_emitted_code = code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
5
lzw.h
5
lzw.h
|
@ -27,9 +27,12 @@ struct lzw_ctx {
|
||||||
uint16_t output_buffer_used;
|
uint16_t output_buffer_used;
|
||||||
uint16_t input_code;
|
uint16_t input_code;
|
||||||
uint16_t input_code_bits;
|
uint16_t input_code_bits;
|
||||||
|
size_t compressed_bytes_processed;
|
||||||
|
size_t uncompressed_bytes_processed;
|
||||||
|
size_t codes_processed;
|
||||||
};
|
};
|
||||||
|
|
||||||
void lzw_init(struct lzw_ctx* c);
|
void lzw_init(struct lzw_ctx* c);
|
||||||
int lzw_decompress(struct lzw_ctx* c, uint8_t* src, size_t* src_count, uint8_t* dst, size_t* dst_count);
|
int lzw_decompress(struct lzw_ctx* c, uint8_t* src, size_t src_count, size_t* src_consumed, uint8_t* dst, size_t dst_count, size_t* dst_consumed);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
56
test-lzw.c
56
test-lzw.c
|
@ -1,25 +1,29 @@
|
||||||
#include "lzw.h"
|
#include "lzw.h"
|
||||||
|
#include "utils.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#define READ_BUFFER_SIZE 4096
|
||||||
|
#define DECOMPRESS_BUFFER_SIZE 4096
|
||||||
|
|
||||||
|
uint8_t read_buffer[READ_BUFFER_SIZE], decompress_buffer[DECOMPRESS_BUFFER_SIZE];
|
||||||
|
|
||||||
int decompress_file(char* filename)
|
int decompress_file(char* filename)
|
||||||
{
|
{
|
||||||
char* outfilename;
|
char* outfilename;
|
||||||
FILE *fp, *outfp;
|
FILE *fp, *outfp;
|
||||||
int i;
|
int i;
|
||||||
unsigned int ifnlen, ofnlen;
|
unsigned int ifnlen, ofnlen;
|
||||||
struct lzw_ctx* ctx;
|
struct lzw_ctx* lzw;
|
||||||
uint8_t bufin[4096], bufout[4096];
|
unsigned long int copied_bytes = 0;
|
||||||
uint8_t *pin, *pout;
|
size_t read_available, read_consumed, decompress_consumed;
|
||||||
size_t to_decompress, space;
|
|
||||||
int res;
|
|
||||||
|
|
||||||
ctx = (struct lzw_ctx*)malloc(sizeof(struct lzw_ctx));
|
lzw = (struct lzw_ctx*)malloc(sizeof(struct lzw_ctx));
|
||||||
if (ctx == NULL)
|
if (lzw == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
lzw_init(ctx);
|
lzw_init(lzw);
|
||||||
|
|
||||||
fp = fopen(filename, "rb");
|
fp = fopen(filename, "rb");
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
|
@ -27,19 +31,17 @@ int decompress_file(char* filename)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NOLINTBEGIN(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling) */
|
|
||||||
ifnlen = strlen(filename);
|
ifnlen = strlen(filename);
|
||||||
ofnlen = ifnlen + 5;
|
ofnlen = ifnlen + 5;
|
||||||
outfilename = (char*)malloc(ofnlen);
|
outfilename = (char*)malloc(ofnlen);
|
||||||
strncpy(outfilename, filename, ofnlen);
|
strlcpy(outfilename, filename, ofnlen);
|
||||||
for (i = ifnlen - 1; i > 0 && outfilename[i] != '/'; i--)
|
for (i = ifnlen - 1; i > 0 && outfilename[i] != '/'; i--)
|
||||||
if (outfilename[i] == '.') {
|
if (outfilename[i] == '.') {
|
||||||
outfilename[i] = '\0';
|
outfilename[i] = '\0';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (strcmp(filename, outfilename) == 0)
|
if (strcmp(filename, outfilename) == 0)
|
||||||
strncat(outfilename, ".out", ofnlen);
|
strlcat(outfilename, ".out", ofnlen);
|
||||||
/* NOLINTEND(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling) */
|
|
||||||
|
|
||||||
printf("Writing to %s\n", outfilename);
|
printf("Writing to %s\n", outfilename);
|
||||||
outfp = fopen(outfilename, "wb");
|
outfp = fopen(outfilename, "wb");
|
||||||
|
@ -49,30 +51,28 @@ int decompress_file(char* filename)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
to_decompress = 0;
|
read_available = read_consumed = decompress_consumed = 0;
|
||||||
space = sizeof(bufout);
|
while (1) {
|
||||||
pout = bufout;
|
if (read_consumed >= read_available) {
|
||||||
while (ctx->eos == 0) {
|
read_available = fread(read_buffer, 1, READ_BUFFER_SIZE, fp);
|
||||||
if (to_decompress == 0) {
|
read_consumed = 0;
|
||||||
to_decompress = fread(bufin, 1, sizeof(bufin), fp);
|
|
||||||
pin = bufin;
|
|
||||||
}
|
}
|
||||||
if (space == 0) {
|
if (decompress_consumed >= DECOMPRESS_BUFFER_SIZE || ((lzw->eos != 0 || read_available == 0) && decompress_consumed > 0)) {
|
||||||
fwrite(bufout, 1, sizeof(bufout), outfp);
|
fwrite(decompress_buffer, 1, decompress_consumed, outfp);
|
||||||
space = sizeof(bufout);
|
copied_bytes += decompress_consumed;
|
||||||
pout = bufout;
|
decompress_consumed = 0;
|
||||||
}
|
}
|
||||||
res = lzw_decompress(ctx, pin, &to_decompress, pout, &space);
|
if (lzw->eos || read_available == 0)
|
||||||
pin = bufin + sizeof(bufin) - to_decompress;
|
break;
|
||||||
pout = bufout + sizeof(bufout) - space;
|
lzw_decompress(lzw, read_buffer, read_available, &read_consumed, decompress_buffer, DECOMPRESS_BUFFER_SIZE, &decompress_consumed);
|
||||||
}
|
}
|
||||||
if (space < sizeof(bufout))
|
|
||||||
fwrite(bufout, 1, sizeof(bufout) - space, outfp);
|
|
||||||
|
|
||||||
free(outfilename);
|
free(outfilename);
|
||||||
fclose(outfp);
|
fclose(outfp);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
|
printf("Extracted %lu bytes", copied_bytes);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* Taken from the FreeBSD source code */
|
||||||
|
|
||||||
|
#ifndef strlcpy
|
||||||
|
/*
|
||||||
|
* Copy string src to buffer dst of size dsize. At most dsize-1
|
||||||
|
* chars will be copied. Always NUL terminates (unless dsize == 0).
|
||||||
|
* Returns strlen(src); if retval >= dsize, truncation occurred.
|
||||||
|
*/
|
||||||
|
size_t
|
||||||
|
strlcpy(char* __restrict dst, const char* __restrict src, size_t dsize)
|
||||||
|
{
|
||||||
|
const char* osrc = src;
|
||||||
|
size_t nleft = dsize;
|
||||||
|
|
||||||
|
/* Copy as many bytes as will fit. */
|
||||||
|
if (nleft != 0) {
|
||||||
|
while (--nleft != 0) {
|
||||||
|
if ((*dst++ = *src++) == '\0')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not enough room in dst, add NUL and traverse rest of src. */
|
||||||
|
if (nleft == 0) {
|
||||||
|
if (dsize != 0)
|
||||||
|
*dst = '\0'; /* NUL-terminate dst */
|
||||||
|
while (*src++)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (src - osrc - 1); /* count does not include NUL */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef strlcat
|
||||||
|
/*
|
||||||
|
* Appends src to string dst of size siz (unlike strncat, siz is the
|
||||||
|
* full size of dst, not space left). At most siz-1 characters
|
||||||
|
* will be copied. Always NUL terminates (unless siz <= strlen(dst)).
|
||||||
|
* Returns strlen(src) + MIN(siz, strlen(initial dst)).
|
||||||
|
* If retval >= siz, truncation occurred.
|
||||||
|
*/
|
||||||
|
size_t
|
||||||
|
strlcat(char* dst, const char* src, size_t siz)
|
||||||
|
{
|
||||||
|
char* d = dst;
|
||||||
|
const char* s = src;
|
||||||
|
size_t n = siz;
|
||||||
|
size_t dlen;
|
||||||
|
|
||||||
|
/* Find the end of dst and adjust bytes left but don't go past end */
|
||||||
|
while (n-- != 0 && *d != '\0')
|
||||||
|
d++;
|
||||||
|
dlen = d - dst;
|
||||||
|
n = siz - dlen;
|
||||||
|
|
||||||
|
if (n == 0)
|
||||||
|
return (dlen + strlen(s));
|
||||||
|
while (*s != '\0') {
|
||||||
|
if (n != 1) {
|
||||||
|
*d++ = *s;
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
*d = '\0';
|
||||||
|
|
||||||
|
return (dlen + (s - src)); /* count does not include NUL */
|
||||||
|
}
|
||||||
|
#endif
|
Loading…
Reference in New Issue