Fixed up base64_dump() users and interfaces to fix memory leaks
[jigit.git] / mkimage.c
index e6389cb..2a87dd3 100644 (file)
--- a/mkimage.c
+++ b/mkimage.c
@@ -8,7 +8,7 @@
  * GPL v2 - see COPYING
  */
 
-#undef BZ2_SUPPORT
+#define BZ2_SUPPORT
 
 #include <errno.h>
 #include <math.h>
 #include <stdio.h>
 #include <string.h>
 #include <limits.h>
-#include <zlib.h>
-#ifdef BZ2_SUPPORT
-#   include <bzlib.h>
-#endif
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <sys/mman.h>
 #include "endian.h"
-#include "md5.h"
 #include "jigdb.h"
-
-typedef long long INT64;
-typedef unsigned long long UINT64;
-typedef unsigned long      UINT32;
-
-#ifndef LLONG_MAX
-#   define LLONG_MAX (INT64)INT_MAX * INT_MAX
-#endif
-
-#define BUF_SIZE 65536
-#define MISSING -1
-
-#ifndef MIN
-#define MIN(x,y)        ( ((x) < (y)) ? (x) : (y))
-#endif
-
-#define COMP_GZIP 2
-#define COMP_BZIP 8
-
-FILE *logfile = NULL;
-FILE *outfile = NULL;
-FILE *missing_file = NULL;
-long long start_offset = 0;
-long long end_offset = 0;
-int quick = 0;
-int verbose = 0;
-UINT64 out_size = 0;
-char *missing_filename = NULL;
+#include "jte.h"
+
+FILE *G_logfile = NULL;
+FILE *G_outfile = NULL;
+FILE *G_missing_file = NULL;
+long long G_start_offset = 0;
+long long G_end_offset = 0;
+int G_quick = 0;
+int G_verbose = 0;
+UINT64 G_out_size = 0;
+char *G_missing_filename = NULL;
 
 typedef enum state_
 {
@@ -67,83 +45,32 @@ typedef enum state_
     ERROR
 } e_state;
 
-typedef struct match_list_
-{
-    struct match_list_ *next;
-    char *match;
-    char *mirror_path;
-} match_list_t;
-
-match_list_t *match_list_head = NULL;
-match_list_t *match_list_tail = NULL;
-
-typedef struct md5_list_
-{
-    struct md5_list_ *next;
-    INT64 file_size;
-    char *md5;
-    char *full_path;
-} md5_list_t;
-
-md5_list_t *md5_list_head = NULL;
-md5_list_t *md5_list_tail = NULL;
-
-struct
-{
-    char   *data_buf;
-    INT64   buf_size;
-    INT64   offset_in_curr_buf;
-    INT64   total_offset;
-} zip_state;
+match_list_t *G_match_list_head = NULL;
+match_list_t *G_match_list_tail = NULL;
 
-/* Grab the file component from a full path */
-static char *file_base_name(char *path)
-{
-    char *endptr = path;
-    char *ptr = path;
-    
-    while (*ptr != '\0')
-    {
-        if ('/' == *ptr)
-            endptr = ++ptr;
-        else
-            ++ptr;
-    }
-    return endptr;
-}
+md5_list_t *G_md5_list_head = NULL;
+md5_list_t *G_md5_list_tail = NULL;
 
-static void write_missing_entry(char *missing, char *filename)
+extern void file_missing(char *missing, char *filename)
 {
-    if (!missing_file)
+    if (!G_missing_file)
     {
-        missing_file = fopen(missing, "wb");
-        if (!missing_file)
+        G_missing_file = fopen(missing, "wb");
+        if (!G_missing_file)
         {
-            fprintf(logfile, "write_missing_entry: Unable to open missing log %s; error %d\n", missing, errno);
+            fprintf(G_logfile, "file_missing: Unable to open missing log %s; error %d\n", missing, errno);
             exit(1);
         }
     }
-    fprintf(missing_file, "%s\n", filename);
+    fprintf(G_missing_file, "%s\n", filename);
 }
 
-static INT64 get_file_size(char *filename)
-{
-    struct stat sb;
-    int error = 0;
-    
-    error = stat(filename, &sb);
-    if (error)
-        return MISSING;
-    else
-        return sb.st_size;
-}
-
-static void display_progress(FILE *file, char *text)
+extern void display_progress(FILE *file, char *text)
 {
     INT64 written = ftello(file);
-    if (out_size > 0)
-        fprintf(logfile, "\r %5.2f%%  %-60.60s",
-               100.0 * written / out_size, text);
+    if (G_out_size > 0)
+        fprintf(G_logfile, "\r %5.2f%%  %-60.60s",
+               100.0 * written / G_out_size, text);
 }
 
 static int add_match_entry(char *match)
@@ -167,7 +94,7 @@ static int add_match_entry(char *match)
 
     if (!mirror_path)
     {
-        fprintf(logfile, "Could not parse malformed match entry \"%s\"\n", match);
+        fprintf(G_logfile, "Could not parse malformed match entry \"%s\"\n", match);
         return EINVAL;
     }        
     
@@ -175,857 +102,20 @@ static int add_match_entry(char *match)
     if (!entry)
         return ENOMEM;
 
-    fprintf(logfile, "Adding match entry %s:%s\n", match, mirror_path);
+    fprintf(G_logfile, "Adding match entry %s:%s\n", match, mirror_path);
 
     entry->match = match;
     entry->mirror_path = mirror_path;
     
-    if (!match_list_head)
-    {
-        match_list_head = entry;
-        match_list_tail = entry;
-    }
-    else
-    {
-        match_list_tail->next = entry;
-        match_list_tail = entry;
-    }
-    
-    return 0;
-}
-
-static int file_exists(char *path, INT64 *size)
-{
-    struct stat sb;
-    int error = 0;
-    
-    error = stat(path, &sb);
-    if (!error && S_ISREG(sb.st_mode))
-    {
-        *size = sb.st_size;
-        return 1;
-    }
-    
-    /* else */
-    return 0;
-}
-
-static md5_list_t *find_file_in_md5_list(unsigned char *base64_md5)
-{
-    md5_list_t *md5_list_entry = md5_list_head;
-    
-    while (md5_list_entry)
-    {        
-        if (!memcmp(md5_list_entry->md5, base64_md5, 16))
-            return md5_list_entry;
-        /* else */
-        md5_list_entry = md5_list_entry->next;
-    }
-    return NULL; /* Not found */
-}
-
-static int find_file_in_mirror(char *jigdo_match, char *jigdo_name,
-                               char *match, INT64 *file_size, char **mirror_path)
-{
-    match_list_t *entry = match_list_head;
-    char path[PATH_MAX];
-
-    while (entry)
-    {
-        if (!strcmp(entry->match, match))
-        {
-            sprintf(path, "%s/%s", entry->mirror_path, jigdo_name);
-            if (file_exists(path, file_size))
-            {
-                *mirror_path = strdup(path);
-                return 0;
-            }
-        }
-        entry = entry->next;
-    }
-    
-    *mirror_path = jigdo_name;
-    return ENOENT;
-}
-
-
-static int add_md5_entry(INT64 size, char *md5, char *path)
-{
-    md5_list_t *new = NULL;    
-    new = calloc(1, sizeof(*new));
-    if (!new)
-        return ENOMEM;
-
-    new->md5 = md5;
-    new->full_path = path;
-    new->file_size = size;
-    
-    if (!md5_list_head)
-    {
-        md5_list_head = new;
-        md5_list_tail = new;
-    }
-    else
-    {
-        md5_list_tail->next = new;
-        md5_list_tail = new;
-    }
-    
-    return 0;
-}
-
-static int parse_md5_entry(char *md5_entry)
-{
-    int error = 0;
-    char *file_name = NULL;
-    char *md5 = NULL;
-    INT64 file_size = 0;
-
-    md5_entry[22] = 0;
-    md5_entry[23] = 0;
-
-    md5 = md5_entry;
-    file_name = &md5_entry[24];
-
-    if ('\n' == file_name[strlen(file_name) -1])
-        file_name[strlen(file_name) - 1] = 0;
-    
-    file_size = get_file_size(file_name);
-
-    error = add_md5_entry(file_size, md5, file_name);
-    return 0;
-}
-
-static int parse_md5_file(char *filename)
-{
-    char buf[2048];
-    FILE *file = NULL;
-    char *ret = NULL;
-    int error = 0;
-
-    file = fopen(filename, "rb");
-    if (!file)
-    {
-        fprintf(logfile, "Failed to open MD5 file %s, error %d!\n", filename, errno);
-        return errno;
-    }
-    
-    while(1)
-    {
-        ret = fgets(buf, sizeof(buf), file);
-        if (NULL == ret)
-            break;
-        error = parse_md5_entry(strdup(buf));
-    }
-    return 0;
-}
-
-/* DELIBERATELY do not sort these, or do anything clever with
-   insertion. The entries in the jigdo file should be in the same
-   order as the ones we'll want from the template. Simply add to the
-   end of the singly-linked list each time! */
-static int add_file_entry(char *jigdo_entry)
-{
-    int error = 0;
-    char *file_name = NULL;
-    INT64 file_size = 0;
-    char *ptr = jigdo_entry;
-    char *base64_md5 = NULL;
-    char *match = NULL;
-    char *jigdo_name = NULL;
-    
-    /* Grab out the component strings from the entry in the jigdo file */
-    base64_md5 = jigdo_entry;
-    while (0 != *ptr)
-    {
-        if ('=' == *ptr)
-        {
-            *ptr = 0;
-            ptr++;
-            match = ptr;
-        }
-        else if (':' == *ptr)
-        {
-            *ptr = 0;
-            ptr++;
-            jigdo_name = ptr;
-        }
-        else if ('\n' == *ptr)
-            *ptr = 0;
-        else
-            ptr++;
-    }
-
-    if (find_file_in_md5_list(base64_md5))
-        return 0; /* We already have an entry for this file; don't
-                   * waste any more time on it */
-
-    /* else look for the file in the filesystem */
-    if (NULL == match || NULL == jigdo_name)
-    {
-        fprintf(logfile, "Could not parse malformed jigdo entry \"%s\"\n", jigdo_entry);
-        return EINVAL;
-    }
-    error = find_file_in_mirror(match, jigdo_name, match, &file_size, &file_name);
-
-    if (error)
-       {
-               if (missing_filename)
-                       add_md5_entry(MISSING, base64_md5, file_name);
-               else
-               {
-                       fprintf(logfile, "Unable to find a file to match %s\n", file_name);
-                       fprintf(logfile, "Abort!\n");
-                       exit (ENOENT);
-               }
-       }
-    else
-        add_md5_entry(file_size, base64_md5, file_name);
-    return 0;
-}
-
-static int parse_jigdo_file(char *filename)
-{
-    char buf[2048];
-    gzFile *file = NULL;
-    char *ret = NULL;
-    int error = 0;
-    
-    file = gzopen(filename, "rb");
-    if (!file)
-    {
-        fprintf(logfile, "Failed to open jigdo file %s, error %d!\n", filename, errno);
-        return errno;
-    }
-
-    /* Find the [Parts] section of the jigdo file */
-    while (1)
-    {
-        ret = gzgets(file, buf, sizeof(buf));
-        if (NULL == ret)
-            break;
-        if (!strncmp(buf, "[Parts]", 7))
-            break;
-    }
-
-    /* Now grab the individual file entries and build a list */
-    while (1)
-    {
-        ret = gzgets(file, buf, sizeof(buf));
-        if (NULL == ret || !strcmp(buf, "\n"))
-            break;
-        if (!strcmp(buf, "[") || !strcmp(buf, "#"))
-            continue;
-        error = add_file_entry(strdup(buf));
-        if (error)
-            break;
-    }
-
-    gzclose(file);
-    return error;
-}
-
-static int ungzip_data_block(char *in_buf, INT64 in_len, char *out_buf, INT64 out_len)
-{
-    int error = 0;
-    z_stream uc_stream;
-    
-    uc_stream.zalloc = NULL;
-    uc_stream.zfree = NULL;
-    uc_stream.opaque = NULL;
-    uc_stream.next_in = (unsigned char *)in_buf;
-    uc_stream.avail_in = in_len;
-
-    error = inflateInit(&uc_stream);
-    if (Z_OK != error)
-    {
-        fprintf(logfile, "ungzip_data_block: failed to init, error %d\n", error);
-        return EIO;
-    }
-    
-    uc_stream.next_out = (unsigned char *)out_buf;
-    uc_stream.avail_out = out_len;
-
-    error = inflate(&uc_stream, Z_FINISH);
-    if (Z_OK != error && Z_STREAM_END != error)
-    {
-        fprintf(logfile, "ungzip_data_block: failed to decompress, error %d\n", error);
-        return EIO;
-    }
-    
-    error = inflateEnd(&uc_stream);
-    if (Z_OK != error)
-    {
-        fprintf(logfile, "ungzip_data_block: failed to end, error %d\n", error);
-        return EIO;
-    }
-    
-    return 0;
-}    
-
-#ifdef BZ2_SUPPORT
-static int unbzip_data_block(char *in_buf, INT64 in_len, char *out_buf, INT64 out_len)
-{
-    int error = 0;
-    bz_stream uc_stream;
-    
-    uc_stream.bzalloc = NULL;
-    uc_stream.bzfree = NULL;
-    uc_stream.opaque = NULL;
-    uc_stream.next_in = in_buf;
-    uc_stream.avail_in = in_len;
-
-    error = BZ2_bzDecompressInit(&uc_stream, 0, 0);
-    if (BZ_OK != error)
-    {
-        fprintf(logfile, "unbzip_data_block: failed to init, error %d\n", error);
-        return EIO;
-    }
-    
-    uc_stream.next_out = out_buf;
-    uc_stream.avail_out = out_len;
-
-    error = BZ2_bzDecompress(&uc_stream);
-    if (BZ_OK != error && BZ_STREAM_END != error)
+    if (!G_match_list_head)
     {
-        fprintf(logfile, "unbzip_data_block: failed to decompress, error %d\n", error);
-        return EIO;
+        G_match_list_head = entry;
+        G_match_list_tail = entry;
     }
-    
-    error = BZ2_bzDecompressEnd(&uc_stream);
-    if (BZ_OK != error)
-    {
-        fprintf(logfile, "unbzip_data_block: failed to end, error %d\n", error);
-        return EIO;
-    }
-    
-    return 0;
-}    
-#endif
-
-static int decompress_data_block(char *in_buf, INT64 in_len, char *out_buf,
-                                 INT64 out_len, int compress_type)
-{
-#ifdef BZ2_SUPPORT
-    if (COMP_BZIP == compress_type)
-        return unbzip_data_block(in_buf, in_len, out_buf, out_len);
     else
-#endif
-        return ungzip_data_block(in_buf, in_len, out_buf, out_len);
-}
-
-static int read_data_block(FILE *template_file, int compress_type)
-{
-    char inbuf[1024];
-    INT64 i = 0;
-    static INT64 template_offset = -1;
-    INT64 compressed_len = 0;
-    INT64 uncompressed_len = 0;
-    char *comp_buf = NULL;
-    int read_num = 0;
-    int error = 0;
-
-    if (-1 == template_offset)
-    {
-        fseek(template_file, 0, SEEK_SET);
-        fread(inbuf, sizeof(inbuf), 1, template_file);
-        for (i = 0; i < sizeof(inbuf); i++)
-        {
-            if (!strncmp(&inbuf[i], "DATA", 4))
-            {
-                template_offset = i;
-                break;
-            }
-        }
-        if (-1 == template_offset)
-        {
-            fprintf(logfile, "Unable to locate DATA block in template (offset %lld)\n",
-                    template_offset);
-            return EINVAL;
-        }    
-    }
-    
-    fseek(template_file, template_offset, SEEK_SET);
-    fread(inbuf, 16, 1, template_file);
-    if (strncmp(inbuf, "DATA", 4))
-    {
-        fprintf(logfile, "Unable to locate DATA block in template (offset %lld)\n",
-                template_offset);
-        return EINVAL;
-    }    
-    
-    compressed_len = read_le48((unsigned char *)&inbuf[4]);
-    uncompressed_len = read_le48((unsigned char *)&inbuf[10]);
-
-    comp_buf = calloc(1, compressed_len);
-    if (!comp_buf)
-    {
-        fprintf(logfile, "Unable to locate DATA block in template (offset %lld)\n",
-                template_offset);
-        return ENOMEM;
-    }
-    
-    zip_state.data_buf = calloc(1, uncompressed_len);
-    if (!zip_state.data_buf)
-    {
-        fprintf(logfile, "Unable to allocate %lld bytes for decompression\n",
-                uncompressed_len);
-        return ENOMEM;
-    }
-
-    read_num = fread(comp_buf, compressed_len, 1, template_file);
-    if (0 == read_num)
-    {
-        fprintf(logfile, "Unable to read %lld bytes for decompression\n",
-                uncompressed_len);
-        return EIO;
-    }
-
-    error = decompress_data_block(comp_buf, compressed_len,
-                                  zip_state.data_buf, uncompressed_len, compress_type);
-    if (error)
-    {
-        fprintf(logfile, "Unable to decompress data block, error %d\n", error);
-        return error;
-    }
-        
-    template_offset += compressed_len;
-    zip_state.buf_size = uncompressed_len;
-    zip_state.offset_in_curr_buf = 0;
-    free (comp_buf);
-    return 0;
-}
-
-static int skip_data_block(INT64 data_size, FILE *template_file, int compress_type)
-{
-    int error = 0;
-    INT64 remaining = data_size;
-    INT64 size = 0;
-
-    /* If we're coming in in the middle of the image, we'll need to
-       skip through some compressed data */
-    while (remaining)
-    {
-        if (!zip_state.data_buf)
-        {
-            error = read_data_block(template_file, compress_type);
-            if (error)
-            {
-                fprintf(logfile, "Unable to decompress template data, error %d\n",
-                        error);
-                return error;
-            }
-        }
-        size = MIN((zip_state.buf_size - zip_state.offset_in_curr_buf), remaining);
-        zip_state.offset_in_curr_buf += size;
-        remaining -= size;
-        
-        if (zip_state.offset_in_curr_buf == zip_state.buf_size)
-        {
-            free(zip_state.data_buf);
-            zip_state.data_buf = NULL;
-        }
-    }
-    
-    fprintf(logfile, "skip_data_block: skipped %lld bytes of unmatched data\n", data_size);
-    return error;
-}
-
-static int parse_data_block(INT64 data_size, FILE *template_file,
-                            struct mk_MD5Context *context, int compress_type)
-{
-    int error = 0;
-    INT64 remaining = data_size;
-    INT64 size = 0;
-    int out_size = 0;
-
-    while (remaining)
-    {
-        if (!zip_state.data_buf)
-        {
-            error = read_data_block(template_file, compress_type);
-            if (error)
-            {
-                fprintf(logfile, "Unable to decompress template data, error %d\n",
-                        error);
-                return error;
-            }
-        }
-        size = MIN((zip_state.buf_size - zip_state.offset_in_curr_buf), remaining);
-        out_size = fwrite(&zip_state.data_buf[zip_state.offset_in_curr_buf], size, 1, outfile);
-        if (!out_size)
-        {
-            fprintf(logfile, "parse_data_block: fwrite %lld failed with error %d; aborting\n", size, ferror(outfile));
-            return ferror(outfile);
-        }
-
-        if (verbose)
-            display_progress(outfile, "template data");
-
-        if (!quick)
-            mk_MD5Update(context,
-                                                (unsigned char *)&zip_state.data_buf[zip_state.offset_in_curr_buf],
-                                                size);
-        zip_state.offset_in_curr_buf += size;
-        remaining -= size;
-        
-        if (zip_state.offset_in_curr_buf == zip_state.buf_size)
-        {
-            free(zip_state.data_buf);
-            zip_state.data_buf = NULL;
-        }
-    }
-    if (verbose > 1)
-        fprintf(logfile, "parse_data_block: wrote %lld bytes of unmatched data\n", data_size);
-    return error;
-}
-
-static int read_file_data(char *filename, char *missing, INT64 offset, INT64 data_size,
-                          struct mk_MD5Context *file_context, struct mk_MD5Context *image_context)
-{
-    FILE *input_file = NULL;
-    INT64 remaining = data_size;
-    char buf[BUF_SIZE];
-    int num_read = 0;
-    int out_size = 0;
-
-    input_file = fopen(filename, "rb");
-    if (!input_file)
-    {
-        fprintf(logfile, "Unable to open mirror file %s, error %d\n",
-                filename, errno);
-        return errno;
-    }
-
-    if (missing)
-    {
-        fclose(input_file);
-        return 0;
-    }
-    
-    fseek(input_file, offset, SEEK_SET);
-    while (remaining)
-    {
-        int size = MIN(BUF_SIZE, remaining);
-        memset(buf, 0, BUF_SIZE);
-        
-        num_read = fread(buf, size, 1, input_file);
-        if (!num_read)
-        {
-            fprintf(logfile, "Unable to read from mirror file %s, error %d (offset %ld, length %d)\n",
-                    filename, errno, ftell(input_file), size);
-            fclose(input_file);
-            return errno;
-        }
-        if (file_context)
-        {
-            mk_MD5Update(image_context, (unsigned char *)buf, size);
-            mk_MD5Update(file_context, (unsigned char *)buf, size);
-        }
-        
-        out_size = fwrite(buf, size, 1, outfile);
-        if (!out_size)
-        {
-            fprintf(logfile, "read_file_data: fwrite %d failed with error %d; aborting\n", size, ferror(outfile));
-            return ferror(outfile);
-        }
-        
-        if (verbose)
-            display_progress(outfile, file_base_name(filename));
-        
-        remaining -= size;
-    }
-    if (verbose > 1)
-        fprintf(logfile, "read_file_data: wrote %lld bytes of data from %s\n",
-                data_size, filename);
-    fclose(input_file);
-    return 0;
-}
-
-static int parse_file_block(INT64 offset, INT64 data_size, INT64 file_size, JIGDB *dbp,
-                            unsigned char *md5, struct mk_MD5Context *image_context,
-                            char *missing)
-{
-    char *base64_md5 = base64_dump(md5, 16);
-    struct mk_MD5Context file_context;
-    struct mk_MD5Context *use_context = NULL;
-    unsigned char file_md5[16];
-    md5_list_t *md5_list_entry = NULL;
-    db_entry_t *db_entry = NULL;
-    int error = 0;
-    char *filename = NULL;
-
-    if (!quick)
-    {
-        use_context = &file_context;
-        mk_MD5Init(use_context);
-    }
-
-    /* Try the DB first if we have one */
-    if (dbp)
-    {
-        error = db_lookup_by_md5(dbp, base64_md5, &db_entry);
-        if (!error)
-            filename = db_entry->filename;
-    }
-
-    /* No joy; fall back to the MD5 list */
-    if (!filename)
-    {
-        md5_list_entry = find_file_in_md5_list(base64_md5);
-        if (md5_list_entry && file_size == md5_list_entry->file_size)
-            filename = md5_list_entry->full_path;
-    }
-
-    if (filename)
-    {
-        error = read_file_data(filename, missing, offset, data_size,
-                               use_context, image_context);
-        
-        if (error && (ENOENT != error))
-        {
-            fprintf(logfile, "Failed to read file %s, error %d\n", filename, error);
-            return error;
-        }
-        
-        if (!quick)
-        {
-            mk_MD5Final(file_md5, &file_context);
-            
-            if (memcmp(file_md5, md5, 16))
-            {
-                fprintf(logfile, "MD5 MISMATCH for file %s\n", filename);
-                fprintf(logfile, "    template looking for %s\n", md5);
-                fprintf(logfile, "    file %s is    %s\n", filename, file_md5);
-                return EINVAL;
-            }
-        }
-        return 0;
-    }
-    
-    /* No file found. Add it to the list of missing files, or complain */
-    if ( missing &&
-         (MISSING == md5_list_entry->file_size) &&
-         (!memcmp(md5_list_entry->md5, base64_md5, 16) ) )
-    {
-        write_missing_entry(missing, md5_list_entry->full_path);
-        return 0;
-    }
-    /* else */
-    return ENOENT;
-}
-
-static int parse_template_file(char *filename, int sizeonly,
-                               char *missing, char *output_name, char *db_filename)
-{
-    INT64 template_offset = 0;
-    INT64 bytes = 0;
-    char *buf = NULL;
-    FILE *file = NULL;
-    INT64 file_size = 0;
-    INT64 desc_start = 0;
-    INT64 written_length = 0;
-    INT64 output_offset = 0;
-    int i = 0;
-    int error = 0;
-    struct mk_MD5Context template_context;
-    unsigned char image_md5sum[16];
-    JIGDB *dbp = NULL;
-
-    zip_state.total_offset = 0;
-    
-    file = fopen(filename, "rb");
-    if (!file)
-    {
-        fprintf(logfile, "Failed to open template file %s, error %d!\n", filename, errno);
-        return errno;
-    }
-
-    if (db_filename)
-    {
-        dbp = db_open(db_filename);
-        if (!dbp)
-        {
-            fprintf(logfile, "Failed to open DB file %s, error %d\n", db_filename, errno);
-            return errno;
-        }
-    }
-
-    buf = malloc(BUF_SIZE);
-    if (!buf)
-    {
-        fprintf(logfile, "Failed to malloc %d bytes. Abort!\n", BUF_SIZE);
-        fclose(file);
-        return ENOMEM;
-    }
-
-    /* Find the beginning of the desc block */
-    file_size = get_file_size(filename);
-    fseek(file, file_size - 6, SEEK_SET);
-    fread(buf, 6, 1, file);
-    desc_start = file_size - read_le48((unsigned char *)buf);
-
-    /* Now seek back to the beginning image desc block to grab the MD5
-       and image length */
-    fseek(file, file_size - 33, SEEK_SET);
-    fread(buf, BUF_SIZE, 1, file);
-    if (buf[0] != 5) /* image data */
-    {
-        fprintf(logfile, "Failed to find image desc in the template file\n");
-        fclose(file);
-        return EINVAL;
-    }
-
-    if (sizeonly)
-    {
-        fclose(file);
-        printf("%lld\n", read_le48((unsigned char *)&buf[1]));
-        return 0;
-    }
-
-    if (verbose)
-    {
-        fprintf(logfile, "Image MD5 should be    ");
-        for (i = 0; i < 16; i++)
-            fprintf(logfile, "%2.2x", (unsigned char)buf[i+7]);
-        fprintf(logfile, "\n");
-        fprintf(logfile, "Image size should be   %lld bytes\n", read_le48((unsigned char *)&buf[1]));
-    }
-
-    out_size = read_le48((unsigned char *)&buf[1]);
-    
-    /* Now seek back to the start of the desc block */
-    fseek(file, desc_start, SEEK_SET);
-    fread(buf, 10, 1, file);
-    if (strncmp(buf, "DESC", 4))
-    {
-        fprintf(logfile, "Failed to find desc start in the template file\n");
-        fclose(file);
-        return EINVAL;
-    }
-    if ((file_size - desc_start) != read_le48((unsigned char *)&buf[4]))
-    {
-        fprintf(logfile, "Inconsistent desc length in the template file!\n");
-        fprintf(logfile, "Final chunk says %lld, first chunk says %lld\n",
-                file_size - desc_start, read_le48((unsigned char *)&buf[4]));
-        fclose(file);
-        return EINVAL;
-    }
-
-    if (!quick)
-        mk_MD5Init(&template_context);
-    template_offset = desc_start + 10;
-
-    if (1 == verbose)
-        fprintf(logfile, "Creating ISO image %s\n", output_name);
-
-    /* Main loop - walk through the template file and expand each entry we find */
-    while (1)
     {
-        INT64 extent_size;
-        INT64 skip = 0;
-        INT64 read_length = 0;
-
-        if (template_offset >= (file_size - 33))
-        {
-            if (verbose > 1)
-                fprintf(logfile, "Reached end of template file\n");
-            break; /* Finished! */
-        }
-        
-        if (output_offset > end_offset) /* Past the range we were asked for */
-        {
-            fprintf(logfile, "Reached end of range requested\n");            
-            break;
-        }
-        
-        fseek(file, template_offset, SEEK_SET);
-        bytes = fread(buf, (MIN (BUF_SIZE, file_size - template_offset)), 1, file);
-        if (1 != bytes)
-        {
-            fprintf(logfile, "Failed to read template file!\n");
-            fclose(file);
-            return EINVAL;
-        }
-        
-        extent_size = read_le48((unsigned char *)&buf[1]);
-        read_length = extent_size;
-        
-        if (start_offset > output_offset)
-            skip = start_offset - output_offset;
-        if ((output_offset + extent_size) > end_offset)
-            read_length -= (output_offset + extent_size - end_offset - 1);
-        read_length -= skip;
-        
-        switch (buf[0])
-        {
-            
-            case 2: /* unmatched data, gzip */
-            case 8: /* unmatched data, bzip2 */
-                template_offset += 7;
-                if (missing)
-                    break;
-                if ((output_offset + extent_size) >= start_offset)
-                {
-                    if (skip)
-                        error = skip_data_block(skip, file, buf[0]);
-                    if (error)
-                    {
-                        fprintf(logfile, "Unable to read data block to skip, error %d\n", error);
-                        fclose(file);
-                        return error;
-                    }
-                    error = parse_data_block(read_length, file, &template_context, buf[0]);
-                    if (error)
-                    {
-                        fprintf(logfile, "Unable to read data block, error %d\n", error);
-                        fclose(file);
-                        return error;
-                    }
-                    written_length += read_length;
-                }
-                else
-                    error = skip_data_block(extent_size, file, buf[0]);
-                break;
-            case 6:
-                template_offset += 31;
-                if ((output_offset + extent_size) >= start_offset)
-                {
-                    error = parse_file_block(skip, read_length, extent_size, dbp,
-                                             (unsigned char *)&buf[15], &template_context, missing);
-                    if (error)
-                    {
-                        fprintf(logfile, "Unable to read file block, error %d\n", error);
-                        fclose(file);
-                        return error;
-                    }
-                    written_length += read_length;
-                }
-                break;
-            default:
-                fprintf(logfile, "Unknown block type %d!\n", buf[0]);
-                fclose(file);
-                return EINVAL;
-        }
-        output_offset += extent_size;
-    }
-
-    if (missing && missing_file)
-        return ENOENT;
-    
-    fclose(file);
-    if (verbose)
-    {
-        fprintf(logfile, "\n");
-        if (!quick)
-        {
-            mk_MD5Final (image_md5sum, &template_context);
-            fprintf(logfile, "Output image MD5 is    ");
-            for (i = 0; i < 16; i++)
-                fprintf(logfile, "%2.2x", image_md5sum[i]);
-            fprintf(logfile, "\n");
-        }
-        fprintf(logfile, "Output image length is %lld bytes\n", written_length);
+        G_match_list_tail->next = entry;
+        G_match_list_tail = entry;
     }
     
     return 0;
@@ -1066,11 +156,11 @@ int main(int argc, char **argv)
     int c = -1;
     int error = 0;
     int sizeonly = 0;
+    JIGDB *dbp = NULL;
+    db_template_entry_t *template;
 
-    logfile = stderr;
-    outfile = stdout;
-
-    bzero(&zip_state, sizeof(zip_state));
+    G_logfile = stderr;
+    G_outfile = stdout;
 
     while(1)
     {
@@ -1081,24 +171,24 @@ int main(int argc, char **argv)
         switch(c)
         {
             case 'v':
-                verbose++;
+                G_verbose++;
                 break;
             case 'q':
-                quick = 1;
+                G_quick = 1;
                 break;
             case 'l':
-                logfile = fopen(optarg, "ab");
-                if (!logfile)
+                G_logfile = fopen(optarg, "ab");
+                if (!G_logfile)
                 {
                     fprintf(stderr, "Unable to open log file %s\n", optarg);
                     return errno;
                 }
-                setlinebuf(logfile);
+                setlinebuf(G_logfile);
                 break;
             case 'o':
                 output_name = optarg;
-                outfile = fopen(output_name, "wb");
-                if (!outfile)
+                G_outfile = fopen(output_name, "wb");
+                if (!G_outfile)
                 {
                     fprintf(stderr, "Unable to open output file %s\n", optarg);
                     return errno;
@@ -1107,7 +197,7 @@ int main(int argc, char **argv)
             case 'j':
                 if (jigdo_filename)
                 {
-                    fprintf(logfile, "Can only specify one jigdo file!\n");
+                    fprintf(G_logfile, "Can only specify one jigdo file!\n");
                     return EINVAL;
                 }
                 /* else */
@@ -1116,7 +206,7 @@ int main(int argc, char **argv)
             case 't':
                 if (template_filename)
                 {
-                    fprintf(logfile, "Can only specify one template file!\n");
+                    fprintf(G_logfile, "Can only specify one template file!\n");
                     return EINVAL;
                 }
                 /* else */
@@ -1125,7 +215,7 @@ int main(int argc, char **argv)
             case 'f':
                 if (md5_filename)
                 {
-                    fprintf(logfile, "Can only specify one MD5 file!\n");
+                    fprintf(G_logfile, "Can only specify one MD5 file!\n");
                     return EINVAL;
                 }
                 /* else */
@@ -1134,7 +224,7 @@ int main(int argc, char **argv)
             case 'd':
                 if (db_filename)
                 {
-                    fprintf(logfile, "Can only specify one db file!\n");
+                    fprintf(G_logfile, "Can only specify one db file!\n");
                     return EINVAL;
                 }
                 /* else */
@@ -1146,10 +236,10 @@ int main(int argc, char **argv)
                     return error;
                 break;
             case 'M':
-                missing_filename = optarg;
+                G_missing_filename = optarg;
                 break;
             case ':':
-                fprintf(logfile, "Missing argument!\n");
+                fprintf(G_logfile, "Missing argument!\n");
                 return EINVAL;
                 break;
             case 'h':
@@ -1158,40 +248,40 @@ int main(int argc, char **argv)
                 return 0;
                 break;
             case 's':
-                start_offset = strtoull(optarg, NULL, 10);
-                if (start_offset != 0)
-                    quick = 1;
+                G_start_offset = strtoull(optarg, NULL, 10);
+                if (G_start_offset != 0)
+                    G_quick = 1;
                 break;
             case 'e':
-                end_offset = strtoull(optarg, NULL, 10);
-                if (end_offset != 0)
-                    quick = 1;
+                G_end_offset = strtoull(optarg, NULL, 10);
+                if (G_end_offset != 0)
+                    G_quick = 1;
                 break;
             case 'z':
                 sizeonly = 1;
                 break;
             default:
-                fprintf(logfile, "Unknown option!\n");
+                fprintf(G_logfile, "Unknown option!\n");
                 return EINVAL;
         }
     }
 
-    if (0 == end_offset)
-        end_offset = LLONG_MAX;
+    if (0 == G_end_offset)
+        G_end_offset = LLONG_MAX;
 
     if ((NULL == jigdo_filename) &&
         (NULL == md5_filename) && 
         (NULL == db_filename) && 
         !sizeonly)
     {
-        fprintf(logfile, "No jigdo file, DB file or MD5 file specified!\n");
+        fprintf(G_logfile, "No jigdo file, DB file or MD5 file specified!\n");
         usage(argv[0]);
         return EINVAL;
     }
     
     if (NULL == template_filename)
     {
-        fprintf(logfile, "No template file specified!\n");
+        fprintf(G_logfile, "No template file specified!\n");
         usage(argv[0]);
         return EINVAL;
     }    
@@ -1202,7 +292,7 @@ int main(int argc, char **argv)
         error = parse_md5_file(md5_filename);
         if (error)
         {
-            fprintf(logfile, "Unable to parse the MD5 file %s\n", md5_filename);
+            fprintf(G_logfile, "Unable to parse the MD5 file %s\n", md5_filename);
             return error;
         }
     }
@@ -1213,25 +303,48 @@ int main(int argc, char **argv)
         error = parse_jigdo_file(jigdo_filename);
         if (error)
         {
-            fprintf(logfile, "Unable to parse the jigdo file %s\n", jigdo_filename);
+            fprintf(G_logfile, "Unable to parse the jigdo file %s\n", jigdo_filename);
             return error;
         }
     }
 
     if (!output_name)
         output_name = "to stdout";
+
+    if (db_filename)
+    {
+        dbp = db_open(db_filename);
+        if (!dbp)
+        {
+            fprintf(G_logfile, "Failed to open DB file %s, error %d\n", db_filename, errno);
+            return errno;
+        }
+        /* If we have a DB, then we should cache the template
+         * information in it too. Check and see if there is
+         * information about this template file in the database
+         * already. */
+    }
+
+    /* See if we know about this template file */
+    error = db_lookup_template_by_path(dbp, template_filename, &template);
+    if (error)
+    {
+        /* Not found. Parse it and put the details in the database */
+        
+    }
+
     /* Read the template file and actually build the image to <outfile> */
-    error = parse_template_file(template_filename, sizeonly,
-                                missing_filename, output_name, db_filename);
+    error = parse_template_file(template_filename, sizeonly, G_missing_filename,
+                                G_outfile, output_name, dbp);
     if (error)
     {
-        fprintf(logfile, "Unable to recreate image from template file %s\n", template_filename);
-        if (missing_filename)
-            fprintf(logfile, "%s contains the list of missing files\n", missing_filename);
+        fprintf(G_logfile, "Unable to recreate image from template file %s\n", template_filename);
+        if (G_missing_filename)
+            fprintf(G_logfile, "%s contains the list of missing files\n", G_missing_filename);
         return error;
     }        
 
-    fclose(logfile);
+    fclose(G_logfile);
     return 0;
 }