ce62c55ba7227b30beecbb2a9265424a9c9ccfed
[geeqie.git] / src / format_raw.c
1 /*
2  *  GQView
3  *  (C) 2005 John Ellis
4  *
5  *  Authors:
6  *    Original version 2005 Lars Ellenberg, base on dcraw by David coffin.
7  *
8  * This software is released under the GNU General Public License (GNU GPL).
9  * Please read the included file COPYING for more information.
10  * This software comes with no warranty of any kind, use at your own risk!
11  */
12
13 #ifdef HAVE_CONFIG_H
14 #  include "config.h"
15 #endif
16
17
18 #include <stdio.h>
19 #include <string.h>
20 #include <unistd.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <sys/mman.h>
24
25 #include <glib.h>
26
27 #include "intl.h"
28
29 #include "format_raw.h"
30
31 #include "format_canon.h"
32 #include "format_fuji.h"
33
34
35 typedef struct _FormatEntry FormatEntry;
36 struct _FormatEntry {
37         const void *header_pattern;
38         const guint header_length;
39         const gchar *description;
40         FormatRawParseFunc func_parse;
41 };
42
43
44 static FormatEntry format_list[] = {
45         FORMAT_RAW_CANON,
46         FORMAT_RAW_FUJI,
47         { NULL, 0, NULL, NULL }
48 };
49
50
51 static FormatEntry *format_raw_find(const void *data, const guint len)
52 {
53         gint n;
54
55         n = 0;
56         while (format_list[n].header_pattern)
57                 {
58                 if (format_list[n].header_length <= len &&
59                     memcmp(data, format_list[n].header_pattern, format_list[n].header_length) == 0)
60                         {
61                         return &format_list[n];
62                         }
63                 n++;
64                 }
65
66         return NULL;
67 }
68
69 static gint format_raw_parse(FormatEntry *entry,
70                              const void *data, const guint len,
71                              guint *image_offset, guint *exif_offset)
72 {
73         guint io = 0;
74         guint eo = 0;
75         gint found;
76
77         if (!entry || !entry->func_parse) return FALSE;
78
79         found = entry->func_parse(data, len, &io, &eo);
80
81         if (!found ||
82             io >= len - 4 ||
83             eo >= len)
84                 {
85                 return FALSE;
86                 }
87
88         if (image_offset) *image_offset = io;
89         if (exif_offset) *exif_offset = eo;
90
91         return TRUE;
92 }
93
94 gint format_raw_img_exif_offsets(const void *data, const guint len,
95                                  guint *image_offset, guint *exif_offset)
96 {
97         FormatEntry *entry;
98
99         if (!data || len < 1) return FALSE;
100
101         entry = format_raw_find(data, len);
102
103         if (!entry || !entry->func_parse) return FALSE;
104
105         return format_raw_parse(entry, data, len, image_offset, exif_offset);
106 }
107
108
109 gint format_raw_img_exif_offsets_fd(int fd, const void *header_data, const guint header_len,
110                                     guint *image_offset, guint *exif_offset)
111 {
112         FormatEntry *entry;
113         void *map_data = NULL;
114         size_t map_len = 0;
115         struct stat st;
116         gint success;
117
118         if (!header_data || fd < 0) return FALSE;
119
120         entry = format_raw_find(header_data, header_len);
121
122         if (!entry || !entry->func_parse) return FALSE;
123
124         if (fstat(fd, &st) == -1)
125                 {
126                 printf("Failed to stat file %d\n", fd);
127                 return FALSE;
128                 }
129         map_len = st.st_size;
130         map_data = mmap(0, map_len, PROT_READ, MAP_PRIVATE, fd, 0);
131         if (map_data == MAP_FAILED)
132                 {
133                 printf("Failed to mmap file %d\n", fd);
134                 return FALSE;
135                 }
136
137         success = format_raw_parse(entry, map_data, map_len, image_offset, exif_offset);
138
139         if (munmap(map_data, map_len) == -1)
140                 {
141                 printf("Failed to unmap file %d\n", fd);
142                 }
143
144         if (success && image_offset)
145                 {
146                 if (lseek(fd, *image_offset, SEEK_SET) != *image_offset)
147                         {
148                         printf("Failed to seek to embedded image\n");
149
150                         *image_offset = 0;
151                         if (*exif_offset) *exif_offset = 0;
152                         success = FALSE;
153                         }
154                 }
155
156         return success;
157 }
158
159