Commit a2f22dc5 authored by Mike Iovine's avatar Mike Iovine
Browse files

Implement myunzip

parent ea230a0f
No related merge requests found
Pipeline #30575 failed with stage
in 0 seconds
Showing with 128 additions and 31 deletions
+128 -31
......@@ -2,3 +2,4 @@
/myunzip0
/inflate
/huffman
/myunzip
all : myzip0 myunzip0 huffman inflate test_inflate
all : myzip0 myunzip0 huffman inflate test_inflate myunzip
myzip0 : myzip0.c
cc myzip0.c -o myzip0
......@@ -12,9 +12,12 @@ huffman : huffman.c
inflate : include/inflate.h src/inflate/main.c src/inflate/inflate.c
gcc -I include src/inflate/main.c src/inflate/inflate.c -o inflate
myunzip : include/inflate.h src/inflate/inflate.c src/myunzip/myunzip.c
gcc -I include src/inflate/inflate.c src/myunzip/myunzip.c -o myunzip
test_inflate : src/inflate/inflate.c tests/inflate_test.cpp
g++ -I include src/inflate/inflate.c tests/inflate_test.cpp -o test_inflate -l gtest
./test_inflate
clean :
rm myzip0 myunzip0 huffman inflate test_inflate
rm myzip0 myunzip0 huffman inflate test_inflate myunzip
#include <stdbool.h>
#ifndef _INFLATE_H_
#define _INFLATE_H_
......@@ -67,11 +69,11 @@ int *read_lens(char *buf, huffman_t *hf_codes,
* Read a single block from the buffer, and write the deflated
* results to "out".
*/
void read_block(char *buf, FILE *out);
bool read_block(char *buf, FILE *out);
/*
* Inflate the file fp.
*/
void inflate(FILE *fp, char *fname);
void inflate(FILE *fp, long size, char *fname);
#endif
......@@ -283,7 +283,7 @@ int *read_lens(char *buf, huffman_t *hf_codes, int num_symbols, int num_codes) {
return lens;
}
void read_block(char *buf, FILE *out) {
bool read_block(char *buf, FILE *out) {
/* First bit is the BFINAL flag */
bool bfinal = get_next_bit(buf);
......@@ -346,7 +346,6 @@ void read_block(char *buf, FILE *out) {
{
/* Match a huffman code */
chunk_val = read_chunk(buf, *hf);
printf("%d\n", chunk_val);
/* Literal, just write to output buffer */
if (chunk_val < 256) {
fwrite(&chunk_val, 1, sizeof(char), out);
......@@ -381,32 +380,15 @@ void read_block(char *buf, FILE *out) {
destroy_huffman(hf);
destroy_huffman(hf_dist);
}
}
void truncate_suffix(char *fname) {
char *dot = strrchr(fname, '.');
const char *suffix = ".deflate";
for (int i = 0; i < 8; i++) {
if (dot == NULL || *(dot + i) != suffix[i]) {
fprintf(stderr, "error: must be a .deflate file");
exit(1);
}
}
*dot = '\0';
return bfinal;
}
void inflate(FILE *fp, char *fname) {
truncate_suffix(fname);
void inflate(FILE *fp, long size, char *fname) {
/* Create output file */
FILE *out = fopen(fname, "wb+");
/* Read the file into a buffer */
fseek(fp, 0, SEEK_END);
long size = ftell(fp);
rewind(fp);
char *buf = (char *) malloc(size);
if (!buf) {
fprintf(stderr, "error: memory error\n");
......@@ -414,9 +396,8 @@ void inflate(FILE *fp, char *fname) {
}
fread(buf, 1, size, fp);
while (_CUR_BIT < 8 * size) {
read_block(buf, out);
}
/* Read until last block */
while (!read_block(buf, out)) {}
fclose(out);
free(buf);
......
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <inflate.h>
void truncate_suffix(char *fname) {
char *dot = strrchr(fname, '.');
const char *suffix = ".deflate";
for (int i = 0; i < 8; i++) {
if (dot == NULL || *(dot + i) != suffix[i]) {
fprintf(stderr, "error: must be a .deflate file\n");
exit(1);
}
}
*dot = '\0';
}
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "usage: inflate [file]\n");
......@@ -18,7 +34,12 @@ int main(int argc, char *argv[]) {
return 1;
}
inflate(fp, fname);
fseek(fp, 0, SEEK_END);
long size = ftell(fp);
rewind(fp);
truncate_suffix(fname);
inflate(fp, size, fname);
fclose(fp);
return 0;
......
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <inflate.h>
struct file_record {
uint32_t signature;
uint16_t version;
uint16_t flag;
uint16_t compression;
uint16_t mod_time;
uint16_t mod_date;
uint32_t crc32;
uint32_t compressed_size;
uint32_t uncompressed_size;
uint16_t file_name_len;
uint16_t extra_len;
}
/* Don't pad this struct, i.e. guaranteed that sizeof(struct file_record) =
* sum of the sizes of its elements. This makes the code a bit nicer;
* we can just fread() the first sizeof(struct file_record) bytes in the
* file directly into the struct.
*/
__attribute__((packed));
typedef struct file_record file_record_t;
const int UNCOMPRESSED = 0;
const int DEFLATE = 8;
void unzip(FILE *fp) {
file_record_t *record = (file_record_t *) malloc(sizeof(file_record_t));
if (!record) {
fprintf(stderr, "error: memory error\n");
exit(1);
}
/* Read metadata */
fread(record, 1, sizeof(file_record_t), fp);
char *fname = (char *) malloc(record->file_name_len);
fread(fname, 1, record->file_name_len, fp);
/* Move pointer to start of file data */
fseek(fp, record->extra_len, SEEK_CUR);
int size;
if (record->compression == UNCOMPRESSED) {
FILE *out = fopen(fname, "wb");
size = record->uncompressed_size;
char *buf = (char *) malloc(size * sizeof(char));
fread(buf, 1, size, fp);
fwrite(buf, 1, size, out);
fclose(out);
} else if (record->compression == DEFLATE) {
inflate(fp, record->compressed_size, fname);
} else {
fprintf(stderr, "error: invalid compression\n");
exit(1);
}
free(record);
}
int main(int argc, char *argv[]) {
FILE *fp;
if (argc != 2) {
fprintf(stderr, "usage: myunzip0 [filename]\n");
return 1;
}
fp = fopen(argv[1], "rb");
if (!fp) {
fprintf(stderr, "error: no such file\n");
return 1;
}
unzip(fp);
fclose(fp);
return 0;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment