]> git.tdb.fi Git - ext/subsurface.git/blobdiff - file.c
updated/corrected comment
[ext/subsurface.git] / file.c
diff --git a/file.c b/file.c
index 5db36a849d10acc39332f3b2465a1380dcec676b..aff1d51f2d2c87b470f2b61b23d6c8b945870f73 100644 (file)
--- a/file.c
+++ b/file.c
@@ -2,19 +2,17 @@
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <stdlib.h>
+#include <string.h>
 #include <errno.h>
 
 #include "dive.h"
-
-struct memblock {
-       void *buffer;
-       size_t size;
-};
+#include "file.h"
 
 static int readfile(const char *filename, struct memblock *mem)
 {
        int ret, fd = open(filename, O_RDONLY);
        struct stat st;
+       char *buf;
 
        mem->buffer = NULL;
        mem->size = 0;
@@ -31,15 +29,17 @@ static int readfile(const char *filename, struct memblock *mem)
        ret = 0;
        if (!st.st_size)
                goto out;
-       mem->buffer = malloc(st.st_size);
+       buf = malloc(st.st_size+1);
        ret = -1;
        errno = ENOMEM;
-       if (!mem->buffer)
+       if (!buf)
                goto out;
+       mem->buffer = buf;
        mem->size = st.st_size;
-       ret = read(fd, mem->buffer, mem->size);
+       ret = read(fd, buf, mem->size);
        if (ret < 0)
                goto free;
+       buf[ret] = 0;
        if (ret == mem->size)
                goto out;
        errno = EIO;
@@ -53,6 +53,69 @@ out:
        return ret;
 }
 
+#ifdef LIBZIP
+#include <zip.h>
+
+static void suunto_read(struct zip_file *file, GError **error)
+{
+       int size = 1024, n, read = 0;
+       char *mem = malloc(size);
+
+       while ((n = zip_fread(file, mem+read, size-read)) > 0) {
+               read += n;
+               size = read * 3 / 2;
+               mem = realloc(mem, size);
+       }
+       parse_xml_buffer("SDE file", mem, read, error);
+       free(mem);
+}
+#endif
+
+static int try_to_open_suunto(const char *filename, struct memblock *mem, GError **error)
+{
+       int success = 0;
+#ifdef LIBZIP
+       /* Grr. libzip needs to re-open the file, it can't take a buffer */
+       struct zip *zip = zip_open(filename, ZIP_CHECKCONS, NULL);
+
+       if (zip) {
+               int index;
+               for (index = 0; ;index++) {
+                       struct zip_file *file = zip_fopen_index(zip, index, 0);
+                       if (!file)
+                               break;
+                       suunto_read(file, error);
+                       zip_fclose(file);
+                       success++;
+               }
+               zip_close(zip);
+       }
+#endif
+       return success;
+}
+
+static int open_by_filename(const char *filename, const char *fmt, struct memblock *mem, GError **error)
+{
+       /* Suunto Dive Manager files: SDE */
+       if (!strcasecmp(fmt, "SDE"))
+               return try_to_open_suunto(filename, mem, error);
+
+       /* Truly nasty intentionally obfuscated Cochran Anal software */
+       if (!strcasecmp(fmt, "CAN"))
+               return try_to_open_cochran(filename, mem, error);
+
+       return 0;
+}
+
+static void parse_file_buffer(const char *filename, struct memblock *mem, GError **error)
+{
+       char *fmt = strrchr(filename, '.');
+       if (fmt && open_by_filename(filename, fmt+1, mem, error))
+               return;
+
+       parse_xml_buffer(filename, mem->buffer, mem->size, error);
+}
+
 void parse_file(const char *filename, GError **error)
 {
        struct memblock mem;
@@ -68,6 +131,6 @@ void parse_file(const char *filename, GError **error)
                return;
        }
 
-       parse_xml_buffer(filename, mem.buffer, mem.size, error);
+       parse_file_buffer(filename, &mem, error);
        free(mem.buffer);
 }