diff --git a/.gitignore b/.gitignore
index b43a45da8f5da56f47189b6fd95604144557744e..ff631349d57d051192090b7b979270d847e27da0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@
 /myunzip0
 /inflate
 /huffman
+/myunzip
diff --git a/Makefile b/Makefile
index 4df46b940405ec0b1cc6ea5e170df8a1ac5e5611..b92daedbffffd80234196b8d8523732ebaa618c8 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-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
diff --git a/include/inflate.h b/include/inflate.h
index 1afc34a6721e194a06d779df6a38d443373684fe..9e4d1e5fe7004a4fa98712dbba8c4ae051db9728 100644
--- a/include/inflate.h
+++ b/include/inflate.h
@@ -1,3 +1,5 @@
+#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
diff --git a/src/inflate/inflate.c b/src/inflate/inflate.c
index c75a2fa8e459c9979bd54134f51841cc29ce2aca..e53928755974ce0a46002bf95512c01a328469f3 100644
--- a/src/inflate/inflate.c
+++ b/src/inflate/inflate.c
@@ -283,14 +283,14 @@ 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);
 
     /* Next two bits are BTYPE */ 
     int btype = get_n_bits(buf, 2, true); 
-
+    
     /* By default, use fixed mapping */ 
     huffman_t *hf = &HUFFMAN_FIXED; 
     huffman_t *hf_dist = &HUFFMAN_FIXED_DISTS; 
@@ -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);
diff --git a/src/inflate/main.c b/src/inflate/main.c
index 852bd9fecbc63081c08f3dbfe1cc2ce11188d1db..58d27e1eb87041f44b9e9be76a3cceb105da7b74 100644
--- a/src/inflate/main.c
+++ b/src/inflate/main.c
@@ -1,8 +1,24 @@
 #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");
@@ -12,13 +28,18 @@ int main(int argc, char *argv[]) {
     char *fname = argv[1];
 
     FILE *fp = fopen(fname, "rb");
-    
+        
     if (!fp) {
         fprintf(stderr, "error: file not found\n");
         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;
diff --git a/src/myunzip/myunzip.c b/src/myunzip/myunzip.c
new file mode 100644
index 0000000000000000000000000000000000000000..bb8d64e25d2da52227fb9dfa0a7a5c54bda15c6c
--- /dev/null
+++ b/src/myunzip/myunzip.c
@@ -0,0 +1,89 @@
+#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; 
+}