90 lines
2.3 KiB
C
90 lines
2.3 KiB
C
#include "lzw.h"
|
|
#include "utils.h"
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.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)
|
|
{
|
|
char* outfilename;
|
|
FILE *fp, *outfp;
|
|
int i;
|
|
unsigned int ifnlen, ofnlen;
|
|
struct lzw_ctx* lzw;
|
|
unsigned long int copied_bytes = 0;
|
|
size_t read_available, read_consumed, decompress_consumed;
|
|
|
|
lzw = (struct lzw_ctx*)malloc(sizeof(struct lzw_ctx));
|
|
if (lzw == NULL)
|
|
return 0;
|
|
lzw_init(lzw);
|
|
|
|
fp = fopen(filename, "rb");
|
|
if (fp == NULL) {
|
|
perror("fopen()");
|
|
return -1;
|
|
}
|
|
|
|
ifnlen = strlen(filename);
|
|
ofnlen = ifnlen + 5;
|
|
outfilename = (char*)malloc(ofnlen);
|
|
strlcpy(outfilename, filename, ofnlen);
|
|
for (i = ifnlen - 1; i > 0 && outfilename[i] != '/'; i--)
|
|
if (outfilename[i] == '.') {
|
|
outfilename[i] = '\0';
|
|
break;
|
|
}
|
|
if (strcmp(filename, outfilename) == 0)
|
|
strlcat(outfilename, ".out", ofnlen);
|
|
|
|
printf("Writing to %s\n", outfilename);
|
|
outfp = fopen(outfilename, "wb");
|
|
if (outfp == NULL) {
|
|
perror("fopen()");
|
|
free(outfilename);
|
|
return -1;
|
|
}
|
|
|
|
read_available = read_consumed = decompress_consumed = 0;
|
|
while (1) {
|
|
if (read_consumed >= read_available) {
|
|
read_available = fread(read_buffer, 1, READ_BUFFER_SIZE, fp);
|
|
read_consumed = 0;
|
|
}
|
|
if (decompress_consumed >= DECOMPRESS_BUFFER_SIZE || ((lzw->eos != 0 || read_available == 0) && decompress_consumed > 0)) {
|
|
fwrite(decompress_buffer, 1, decompress_consumed, outfp);
|
|
copied_bytes += decompress_consumed;
|
|
decompress_consumed = 0;
|
|
}
|
|
if (lzw->eos || read_available == 0)
|
|
break;
|
|
lzw_decompress(lzw, read_buffer, read_available, &read_consumed, decompress_buffer, DECOMPRESS_BUFFER_SIZE, &decompress_consumed);
|
|
}
|
|
|
|
free(outfilename);
|
|
fclose(outfp);
|
|
fclose(fp);
|
|
|
|
printf("Extracted %lu bytes", copied_bytes);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char* argv[])
|
|
{
|
|
int i;
|
|
|
|
for (i = 1; i < argc; i++) {
|
|
printf("Decompressing %s\n", argv[i]);
|
|
decompress_file(argv[i]);
|
|
}
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|