1 #include "mupdf/fitz.h"
2
3 #include <string.h>
4 #include <errno.h>
5 #include <sys/stat.h>
6
7 #ifdef _MSC_VER
8 #define stat _stat
9 #endif
10
11 typedef struct
12 {
13 fz_archive super;
14
15 char *path;
16 } fz_directory;
17
drop_directory(fz_context * ctx,fz_archive * arch)18 static void drop_directory(fz_context *ctx, fz_archive *arch)
19 {
20 fz_directory *dir = (fz_directory *) arch;
21
22 fz_free(ctx, dir->path);
23 }
24
open_dir_entry(fz_context * ctx,fz_archive * arch,const char * name)25 static fz_stream *open_dir_entry(fz_context *ctx, fz_archive *arch, const char *name)
26 {
27 fz_directory *dir = (fz_directory *) arch;
28 char path[2048];
29 fz_strlcpy(path, dir->path, sizeof path);
30 fz_strlcat(path, "/", sizeof path);
31 fz_strlcat(path, name, sizeof path);
32 return fz_open_file(ctx, path);
33 }
34
read_dir_entry(fz_context * ctx,fz_archive * arch,const char * name)35 static fz_buffer *read_dir_entry(fz_context *ctx, fz_archive *arch, const char *name)
36 {
37 fz_directory *dir = (fz_directory *) arch;
38 char path[2048];
39 fz_strlcpy(path, dir->path, sizeof path);
40 fz_strlcat(path, "/", sizeof path);
41 fz_strlcat(path, name, sizeof path);
42 return fz_read_file(ctx, path);
43 }
44
has_dir_entry(fz_context * ctx,fz_archive * arch,const char * name)45 static int has_dir_entry(fz_context *ctx, fz_archive *arch, const char *name)
46 {
47 fz_directory *dir = (fz_directory *) arch;
48 char path[2048];
49 fz_strlcpy(path, dir->path, sizeof path);
50 fz_strlcat(path, "/", sizeof path);
51 fz_strlcat(path, name, sizeof path);
52 return fz_file_exists(ctx, path);
53 }
54
55 int
fz_is_directory(fz_context * ctx,const char * path)56 fz_is_directory(fz_context *ctx, const char *path)
57 {
58 struct stat info;
59
60 if (stat(path, &info) < 0)
61 return 0;
62
63 return S_ISDIR(info.st_mode);
64 }
65
66 fz_archive *
fz_open_directory(fz_context * ctx,const char * path)67 fz_open_directory(fz_context *ctx, const char *path)
68 {
69 fz_directory *dir;
70
71 if (!fz_is_directory(ctx, path))
72 fz_throw(ctx, FZ_ERROR_GENERIC, "'%s' is not a directory", path);
73
74 dir = fz_new_derived_archive(ctx, NULL, fz_directory);
75 dir->super.format = "dir";
76 dir->super.has_entry = has_dir_entry;
77 dir->super.read_entry = read_dir_entry;
78 dir->super.open_entry = open_dir_entry;
79 dir->super.drop_archive = drop_directory;
80
81 fz_try(ctx)
82 {
83 dir->path = fz_strdup(ctx, path);
84 }
85 fz_catch(ctx)
86 {
87 fz_drop_archive(ctx, &dir->super);
88 fz_rethrow(ctx);
89 }
90
91 return &dir->super;
92 }
93