summaryrefslogtreecommitdiff
path: root/source/fitz/directory.c
diff options
context:
space:
mode:
authorSebastian Rasmussen <sebras@gmail.com>2016-08-13 17:45:14 +0800
committerSebastian Rasmussen <sebras@gmail.com>2016-09-08 18:53:00 +0800
commit15cab201d3c98dc6580c8cf592d94ab226f96db5 (patch)
tree352861e9bf8b5ec8289810501faa0007c19b7f68 /source/fitz/directory.c
parent793ae6a3c2d23743e66039b124f826b232a5a04e (diff)
downloadmupdf-15cab201d3c98dc6580c8cf592d94ab226f96db5.tar.xz
Make fz_archive a generic archive type.
Previously it was inherently tied to zip archives and directories. Now these are separated out into distinct subclasses. This prepares for support for further archive formats.
Diffstat (limited to 'source/fitz/directory.c')
-rw-r--r--source/fitz/directory.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/source/fitz/directory.c b/source/fitz/directory.c
new file mode 100644
index 00000000..aba11eb9
--- /dev/null
+++ b/source/fitz/directory.c
@@ -0,0 +1,87 @@
+#include "mupdf/fitz.h"
+
+typedef struct fz_directory_s fz_directory;
+struct fz_directory_s
+{
+ fz_archive super;
+
+ char *path;
+};
+
+static void drop_directory(fz_context *ctx, fz_archive *arch)
+{
+ fz_directory *dir = (fz_directory *) arch;
+
+ fz_free(ctx, dir->path);
+}
+
+static fz_stream *open_dir_entry(fz_context *ctx, fz_archive *arch, const char *name)
+{
+ fz_directory *dir = (fz_directory *) arch;
+ char path[2048];
+ fz_strlcpy(path, dir->path, sizeof path);
+ fz_strlcat(path, "/", sizeof path);
+ fz_strlcat(path, name, sizeof path);
+ return fz_open_file(ctx, path);
+}
+
+static fz_buffer *read_dir_entry(fz_context *ctx, fz_archive *arch, const char *name)
+{
+ fz_directory *dir = (fz_directory *) arch;
+ char path[2048];
+ fz_strlcpy(path, dir->path, sizeof path);
+ fz_strlcat(path, "/", sizeof path);
+ fz_strlcat(path, name, sizeof path);
+ return fz_read_file(ctx, path);
+}
+
+static int has_dir_entry(fz_context *ctx, fz_archive *arch, const char *name)
+{
+ fz_directory *dir = (fz_directory *) arch;
+ char path[2048];
+ fz_strlcpy(path, dir->path, sizeof path);
+ fz_strlcat(path, "/", sizeof path);
+ fz_strlcat(path, name, sizeof path);
+ return fz_file_exists(ctx, path);
+}
+
+int
+fz_is_directory(fz_context *ctx, const char *path)
+{
+ struct stat info;
+
+ if (stat(path, &info) < 0)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "cannot stat: %s", strerror(errno));
+
+ return info.st_mode & S_IFDIR;
+}
+
+fz_archive *
+fz_open_directory(fz_context *ctx, const char *path)
+{
+ fz_directory *dir = NULL;
+
+ fz_var(dir);
+
+ fz_try(ctx)
+ {
+ if (!fz_is_directory(ctx, path))
+ fz_throw(ctx, FZ_ERROR_GENERIC, "'%s' is not a directory", path);
+
+ dir = fz_new_archive(ctx, NULL, fz_directory);
+ dir->super.format = "dir";
+ dir->super.has_entry = has_dir_entry;
+ dir->super.read_entry = read_dir_entry;
+ dir->super.open_entry = open_dir_entry;
+ dir->super.drop_archive = drop_directory;
+
+ dir->path = fz_strdup(ctx, path);
+ }
+ fz_catch(ctx)
+ {
+ fz_drop_archive(ctx, &dir->super);
+ fz_rethrow(ctx);
+ }
+
+ return &dir->super;
+}