/src/libexif/libexif/pentax/exif-mnote-data-pentax.c
Line | Count | Source |
1 | | /* exif-mnote-data-pentax.c |
2 | | * |
3 | | * Copyright (c) 2002, 2003 Lutz Mueller <lutz@users.sourceforge.net> |
4 | | * |
5 | | * This library is free software; you can redistribute it and/or |
6 | | * modify it under the terms of the GNU Lesser General Public |
7 | | * License as published by the Free Software Foundation; either |
8 | | * version 2 of the License, or (at your option) any later version. |
9 | | * |
10 | | * This library is distributed in the hope that it will be useful, |
11 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | | * Lesser General Public License for more details. |
14 | | * |
15 | | * You should have received a copy of the GNU Lesser General Public |
16 | | * License along with this library; if not, write to the |
17 | | * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
18 | | * Boston, MA 02110-1301 USA. |
19 | | * |
20 | | * SPDX-License-Identifier: LGPL-2.0-or-later |
21 | | */ |
22 | | |
23 | | #include "config.h" |
24 | | #include "exif-mnote-data-pentax.h" |
25 | | |
26 | | #include <stdlib.h> |
27 | | #include <string.h> |
28 | | #include <stdio.h> |
29 | | |
30 | | #include <libexif/exif-byte-order.h> |
31 | | #include <libexif/exif-utils.h> |
32 | | |
33 | 28.9k | #define CHECKOVERFLOW(offset,datasize,structsize) (( (offset) >= (datasize)) || ((structsize) > (datasize)) || ((offset) > (datasize) - (structsize) )) |
34 | | |
35 | | static void |
36 | | exif_mnote_data_pentax_clear (ExifMnoteDataPentax *n) |
37 | 2.12k | { |
38 | 2.12k | ExifMnoteData *d = (ExifMnoteData *) n; |
39 | 2.12k | unsigned int i; |
40 | | |
41 | 2.12k | if (!n) return; |
42 | | |
43 | 2.12k | if (n->entries) { |
44 | 18.9k | for (i = 0; i < n->count; i++) |
45 | 18.0k | if (n->entries[i].data) { |
46 | 7.35k | exif_mem_free (d->mem, n->entries[i].data); |
47 | 7.35k | n->entries[i].data = NULL; |
48 | 7.35k | } |
49 | 987 | exif_mem_free (d->mem, n->entries); |
50 | 987 | n->entries = NULL; |
51 | 987 | n->count = 0; |
52 | 987 | } |
53 | 2.12k | } |
54 | | |
55 | | static void |
56 | | exif_mnote_data_pentax_free (ExifMnoteData *n) |
57 | 1.14k | { |
58 | 1.14k | if (!n) return; |
59 | | |
60 | 1.14k | exif_mnote_data_pentax_clear ((ExifMnoteDataPentax *) n); |
61 | 1.14k | } |
62 | | |
63 | | static char * |
64 | | exif_mnote_data_pentax_get_value (ExifMnoteData *d, unsigned int i, char *val, unsigned int maxlen) |
65 | 12.5k | { |
66 | 12.5k | ExifMnoteDataPentax *n = (ExifMnoteDataPentax *) d; |
67 | | |
68 | 12.5k | if (!n) return NULL; |
69 | 12.5k | if (n->count <= i) return NULL; |
70 | 12.5k | return mnote_pentax_entry_get_value (&n->entries[i], val, maxlen); |
71 | 12.5k | } |
72 | | |
73 | | /** |
74 | | * @brief save the MnoteData from ne to buf |
75 | | * |
76 | | * @param ne extract the data from this structure |
77 | | * @param *buf write the mnoteData to this buffer (buffer will be allocated) |
78 | | * @param buf_size the final size of the buffer |
79 | | */ |
80 | | static void |
81 | | exif_mnote_data_pentax_save (ExifMnoteData *ne, |
82 | | unsigned char **buf, unsigned int *buf_size) |
83 | 0 | { |
84 | 0 | ExifMnoteDataPentax *n = (ExifMnoteDataPentax *) ne; |
85 | 0 | size_t i, datao, |
86 | 0 | base = 0, /* internal MakerNote tag number offset */ |
87 | 0 | o2 = 4 + 2; /* offset to first tag entry, past header */ |
88 | |
|
89 | 0 | if (!n || !buf || !buf_size) return; |
90 | 0 | datao = n->offset; /* this MakerNote style uses offsets |
91 | | based on main IFD, not makernote IFD */ |
92 | | |
93 | | /* |
94 | | * Allocate enough memory for header, the number of entries, entries, |
95 | | * and next IFD pointer |
96 | | */ |
97 | 0 | *buf_size = o2 + 2 + n->count * 12 + 4; |
98 | 0 | switch (n->version) { |
99 | 0 | case casioV2: |
100 | 0 | base = MNOTE_PENTAX2_TAG_BASE; |
101 | 0 | *buf = exif_mem_alloc (ne->mem, *buf_size); |
102 | 0 | if (!*buf) { |
103 | 0 | EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataPentax", *buf_size); |
104 | 0 | return; |
105 | 0 | } |
106 | | /* Write the magic header */ |
107 | 0 | strcpy ((char *)*buf, "QVC"); |
108 | 0 | exif_set_short (*buf + 4, n->order, (ExifShort) 0); |
109 | |
|
110 | 0 | break; |
111 | | |
112 | 0 | case pentaxV3: |
113 | 0 | base = MNOTE_PENTAX2_TAG_BASE; |
114 | 0 | *buf = exif_mem_alloc (ne->mem, *buf_size); |
115 | 0 | if (!*buf) { |
116 | 0 | EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataPentax", *buf_size); |
117 | 0 | return; |
118 | 0 | } |
119 | | |
120 | | /* Write the magic header */ |
121 | 0 | strcpy ((char *)*buf, "AOC"); |
122 | 0 | exif_set_short (*buf + 4, n->order, (ExifShort) ( |
123 | 0 | (n->order == EXIF_BYTE_ORDER_INTEL) ? |
124 | 0 | ('I' << 8) | 'I' : |
125 | 0 | ('M' << 8) | 'M')); |
126 | 0 | break; |
127 | | |
128 | 0 | case pentaxV2: |
129 | 0 | base = MNOTE_PENTAX2_TAG_BASE; |
130 | 0 | *buf = exif_mem_alloc (ne->mem, *buf_size); |
131 | 0 | if (!*buf) { |
132 | 0 | EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataPentax", *buf_size); |
133 | 0 | return; |
134 | 0 | } |
135 | | |
136 | | /* Write the magic header */ |
137 | 0 | strcpy ((char *)*buf, "AOC"); |
138 | 0 | exif_set_short (*buf + 4, n->order, (ExifShort) 0); |
139 | 0 | break; |
140 | | |
141 | 0 | case pentaxV1: |
142 | | /* It looks like this format doesn't have a magic header as |
143 | | * such, just has a fixed number of entries equal to 0x001b */ |
144 | 0 | *buf_size -= 6; |
145 | 0 | o2 -= 6; |
146 | 0 | *buf = exif_mem_alloc (ne->mem, *buf_size); |
147 | 0 | if (!*buf) { |
148 | 0 | EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataPentax", *buf_size); |
149 | 0 | return; |
150 | 0 | } |
151 | 0 | break; |
152 | | |
153 | 0 | default: |
154 | | /* internal error */ |
155 | 0 | return; |
156 | 0 | } |
157 | | |
158 | | /* Write the number of entries. */ |
159 | 0 | exif_set_short (*buf + o2, n->order, (ExifShort) n->count); |
160 | 0 | o2 += 2; |
161 | | |
162 | | /* Save each entry */ |
163 | 0 | for (i = 0; i < n->count; i++) { |
164 | 0 | size_t doff; /* offset to current data portion of tag */ |
165 | 0 | size_t s; |
166 | 0 | unsigned char *t; |
167 | 0 | size_t o = o2 + i * 12; /* current offset into output buffer */ |
168 | 0 | exif_set_short (*buf + o + 0, n->order, |
169 | 0 | (ExifShort) (n->entries[i].tag - base)); |
170 | 0 | exif_set_short (*buf + o + 2, n->order, |
171 | 0 | (ExifShort) n->entries[i].format); |
172 | 0 | exif_set_long (*buf + o + 4, n->order, |
173 | 0 | n->entries[i].components); |
174 | 0 | o += 8; |
175 | 0 | s = exif_format_get_size (n->entries[i].format) * |
176 | 0 | n->entries[i].components; |
177 | 0 | if (s > 65536) { |
178 | | /* Corrupt data: EXIF data size is limited to the |
179 | | * maximum size of a JPEG segment (64 kb). |
180 | | */ |
181 | 0 | continue; |
182 | 0 | } |
183 | 0 | if (s > 4) { |
184 | 0 | size_t ts = *buf_size + s; |
185 | 0 | doff = *buf_size; |
186 | 0 | t = exif_mem_realloc (ne->mem, *buf, |
187 | 0 | sizeof (char) * ts); |
188 | 0 | if (!t) { |
189 | 0 | EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataPentax", ts); |
190 | 0 | return; |
191 | 0 | } |
192 | 0 | *buf = t; |
193 | 0 | *buf_size = ts; |
194 | 0 | exif_set_long (*buf + o, n->order, datao + doff); |
195 | 0 | } else |
196 | 0 | doff = o; |
197 | | |
198 | | /* Write the data. */ |
199 | 0 | if (n->entries[i].data) { |
200 | 0 | memcpy (*buf + doff, n->entries[i].data, s); |
201 | 0 | } else { |
202 | | /* Most certainly damaged input file */ |
203 | 0 | memset (*buf + doff, 0, s); |
204 | 0 | } |
205 | 0 | } |
206 | | |
207 | | /* Sanity check the buffer size */ |
208 | 0 | if (*buf_size < (o2 + n->count * 12 + 4)) { |
209 | 0 | exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifMnoteDataPentax", |
210 | 0 | "Buffer overflow"); |
211 | 0 | } |
212 | | |
213 | | /* Reset next IFD pointer */ |
214 | 0 | exif_set_long (*buf + o2 + n->count * 12, n->order, 0); |
215 | 0 | } |
216 | | |
217 | | static void |
218 | | exif_mnote_data_pentax_load (ExifMnoteData *en, |
219 | | const unsigned char *buf, unsigned int buf_size) |
220 | 1.14k | { |
221 | 1.14k | ExifMnoteDataPentax *n = (ExifMnoteDataPentax *) en; |
222 | 1.14k | size_t i, tcount, o, datao, base = 0; |
223 | 1.14k | ExifShort c; |
224 | | |
225 | 1.14k | if (!n) return; |
226 | | |
227 | 1.14k | if (!buf || !buf_size) { |
228 | 0 | exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, |
229 | 0 | "ExifMnoteDataPentax", "Short MakerNote"); |
230 | 0 | return; |
231 | 0 | } |
232 | 1.14k | datao = 6 + n->offset; |
233 | 1.14k | if (CHECKOVERFLOW(datao, buf_size, 8)) { |
234 | 18 | exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, |
235 | 18 | "ExifMnoteDataPentax", "Short MakerNote"); |
236 | 18 | return; |
237 | 18 | } |
238 | | |
239 | | /* Detect variant of Pentax/Casio MakerNote found */ |
240 | 1.12k | if (!memcmp(buf + datao, "AOC", 4)) { |
241 | 530 | if ((buf[datao + 4] == 'I') && (buf[datao + 5] == 'I')) { |
242 | 4 | n->version = pentaxV3; |
243 | 4 | n->order = EXIF_BYTE_ORDER_INTEL; |
244 | 526 | } else if ((buf[datao + 4] == 'M') && (buf[datao + 5] == 'M')) { |
245 | 3 | n->version = pentaxV3; |
246 | 3 | n->order = EXIF_BYTE_ORDER_MOTOROLA; |
247 | 523 | } else { |
248 | | /* Uses Casio v2 tags */ |
249 | 523 | n->version = pentaxV2; |
250 | 523 | } |
251 | 530 | exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataPentax", |
252 | 530 | "Parsing Pentax maker note v%d...", (int)n->version); |
253 | 530 | datao += 4 + 2; |
254 | 530 | base = MNOTE_PENTAX2_TAG_BASE; |
255 | 592 | } else if (!memcmp(buf + datao, "QVC", 4)) { |
256 | 31 | exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataPentax", |
257 | 31 | "Parsing Casio maker note v2..."); |
258 | 31 | n->version = casioV2; |
259 | 31 | base = MNOTE_CASIO2_TAG_BASE; |
260 | 31 | datao += 4 + 2; |
261 | 561 | } else { |
262 | | /* probably assert(!memcmp(buf + datao, "\x00\x1b", 2)) */ |
263 | 561 | exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataPentax", |
264 | 561 | "Parsing Pentax maker note v1..."); |
265 | 561 | n->version = pentaxV1; |
266 | 561 | } |
267 | | |
268 | | /* Read the number of tags */ |
269 | 1.12k | c = exif_get_short (buf + datao, n->order); |
270 | 1.12k | datao += 2; |
271 | | |
272 | | /* Just use an arbitrary max tag limit here to avoid needing to much memory or time. There are 102 named tags currently. |
273 | | * The format allows specifying the same range of memory as often as it can, so this multiplies quickly. */ |
274 | 1.12k | if (c > 200) { |
275 | 135 | exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifMnoteDataPentax", "Too much tags (%d) in Pentax MakerNote", c); |
276 | 135 | return; |
277 | 135 | } |
278 | | |
279 | | |
280 | | /* Remove any old entries */ |
281 | 987 | exif_mnote_data_pentax_clear (n); |
282 | | |
283 | | /* Reserve enough space for all the possible MakerNote tags */ |
284 | 987 | n->entries = exif_mem_alloc (en->mem, sizeof (MnotePentaxEntry) * c); |
285 | 987 | if (!n->entries) { |
286 | 0 | EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteDataPentax", sizeof (MnotePentaxEntry) * c); |
287 | 0 | return; |
288 | 0 | } |
289 | | |
290 | | /* Parse all c entries, storing ones that are successfully parsed */ |
291 | 987 | tcount = 0; |
292 | 19.7k | for (i = c, o = datao; i; --i, o += 12) { |
293 | 19.7k | size_t s; |
294 | | |
295 | 19.7k | memset(&n->entries[tcount], 0, sizeof(MnotePentaxEntry)); |
296 | 19.7k | if (CHECKOVERFLOW(o,buf_size,12)) { |
297 | 774 | exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, |
298 | 774 | "ExifMnoteDataPentax", "Short MakerNote"); |
299 | 774 | break; |
300 | 774 | } |
301 | | |
302 | 18.9k | n->entries[tcount].tag = exif_get_short (buf + o + 0, n->order) + base; |
303 | 18.9k | n->entries[tcount].format = exif_get_short (buf + o + 2, n->order); |
304 | 18.9k | n->entries[tcount].components = exif_get_long (buf + o + 4, n->order); |
305 | 18.9k | n->entries[tcount].order = n->order; |
306 | | |
307 | 18.9k | exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnotePentax", |
308 | 18.9k | "Loading entry 0x%x ('%s')...", n->entries[tcount].tag, |
309 | 18.9k | mnote_pentax_tag_get_name (n->entries[tcount].tag)); |
310 | | |
311 | | /* Check if we overflow the multiplication. Use buf_size as the max size for integer overflow detection, |
312 | | * we will check the buffer sizes closer later. */ |
313 | 18.9k | if ( exif_format_get_size (n->entries[tcount].format) && |
314 | 10.0k | buf_size / exif_format_get_size (n->entries[tcount].format) < n->entries[tcount].components |
315 | 18.9k | ) { |
316 | 198 | exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, |
317 | 198 | "ExifMnoteDataPentax", "Tag size overflow detected (%u * %lu)", exif_format_get_size (n->entries[tcount].format), n->entries[tcount].components); |
318 | 198 | break; |
319 | 198 | } |
320 | | /* |
321 | | * Size? If bigger than 4 bytes, the actual data is not |
322 | | * in the entry but somewhere else (offset). |
323 | | */ |
324 | 18.7k | s = exif_format_get_size (n->entries[tcount].format) * |
325 | 18.7k | n->entries[tcount].components; |
326 | 18.7k | n->entries[tcount].size = s; |
327 | 18.7k | if (s) { |
328 | 8.09k | size_t dataofs = o + 8; |
329 | 8.09k | if (s > 4) |
330 | | /* The data in this case is merely a pointer */ |
331 | 2.43k | dataofs = exif_get_long (buf + dataofs, n->order) + 6; |
332 | | |
333 | 8.09k | if (CHECKOVERFLOW(dataofs, buf_size, s)) { |
334 | 742 | exif_log (en->log, EXIF_LOG_CODE_DEBUG, |
335 | 742 | "ExifMnoteDataPentax", "Tag data past end " |
336 | 742 | "of buffer (%u > %u)", (unsigned)(dataofs + s), buf_size); |
337 | 742 | continue; |
338 | 742 | } |
339 | | |
340 | 7.35k | n->entries[tcount].data = exif_mem_alloc (en->mem, s); |
341 | 7.35k | if (!n->entries[tcount].data) { |
342 | 0 | EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteDataPentax", s); |
343 | 0 | continue; |
344 | 0 | } |
345 | 7.35k | memcpy (n->entries[tcount].data, buf + dataofs, s); |
346 | 7.35k | } |
347 | | |
348 | | /* Tag was successfully parsed */ |
349 | 18.0k | ++tcount; |
350 | 18.0k | } |
351 | | /* Store the count of successfully parsed tags */ |
352 | 987 | n->count = tcount; |
353 | 987 | } |
354 | | |
355 | | static unsigned int |
356 | | exif_mnote_data_pentax_count (ExifMnoteData *n) |
357 | 1.14k | { |
358 | 1.14k | return n ? ((ExifMnoteDataPentax *) n)->count : 0; |
359 | 1.14k | } |
360 | | |
361 | | static unsigned int |
362 | | exif_mnote_data_pentax_get_id (ExifMnoteData *d, unsigned int n) |
363 | 0 | { |
364 | 0 | ExifMnoteDataPentax *note = (ExifMnoteDataPentax *) d; |
365 | |
|
366 | 0 | if (!note) return 0; |
367 | 0 | if (note->count <= n) return 0; |
368 | 0 | return note->entries[n].tag; |
369 | 0 | } |
370 | | |
371 | | static const char * |
372 | | exif_mnote_data_pentax_get_name (ExifMnoteData *d, unsigned int n) |
373 | 12.8k | { |
374 | 12.8k | ExifMnoteDataPentax *note = (ExifMnoteDataPentax *) d; |
375 | | |
376 | 12.8k | if (!note) return NULL; |
377 | 12.8k | if (note->count <= n) return NULL; |
378 | 12.8k | return mnote_pentax_tag_get_name (note->entries[n].tag); |
379 | 12.8k | } |
380 | | |
381 | | static const char * |
382 | | exif_mnote_data_pentax_get_title (ExifMnoteData *d, unsigned int n) |
383 | 12.5k | { |
384 | 12.5k | ExifMnoteDataPentax *note = (ExifMnoteDataPentax *) d; |
385 | | |
386 | 12.5k | if (!note) return NULL; |
387 | 12.5k | if (note->count <= n) return NULL; |
388 | 12.5k | return mnote_pentax_tag_get_title (note->entries[n].tag); |
389 | 12.5k | } |
390 | | |
391 | | static const char * |
392 | | exif_mnote_data_pentax_get_description (ExifMnoteData *d, unsigned int n) |
393 | 12.5k | { |
394 | 12.5k | ExifMnoteDataPentax *note = (ExifMnoteDataPentax *) d; |
395 | | |
396 | 12.5k | if (!note) return NULL; |
397 | 12.5k | if (note->count <= n) return NULL; |
398 | 12.5k | return mnote_pentax_tag_get_description (note->entries[n].tag); |
399 | 12.5k | } |
400 | | |
401 | | static void |
402 | | exif_mnote_data_pentax_set_offset (ExifMnoteData *d, unsigned int o) |
403 | 1.14k | { |
404 | 1.14k | if (d) ((ExifMnoteDataPentax *) d)->offset = o; |
405 | 1.14k | } |
406 | | |
407 | | static void |
408 | | exif_mnote_data_pentax_set_byte_order (ExifMnoteData *d, ExifByteOrder o) |
409 | 1.14k | { |
410 | 1.14k | ExifByteOrder o_orig; |
411 | 1.14k | ExifMnoteDataPentax *n = (ExifMnoteDataPentax *) d; |
412 | 1.14k | unsigned int i; |
413 | | |
414 | 1.14k | if (!n) return; |
415 | | |
416 | 1.14k | o_orig = n->order; |
417 | 1.14k | n->order = o; |
418 | 1.14k | for (i = 0; i < n->count; i++) { |
419 | 0 | if (n->entries[i].components && (n->entries[i].size/n->entries[i].components < exif_format_get_size (n->entries[i].format))) |
420 | 0 | continue; |
421 | 0 | n->entries[i].order = o; |
422 | 0 | exif_array_set_byte_order (n->entries[i].format, n->entries[i].data, |
423 | 0 | n->entries[i].components, o_orig, o); |
424 | 0 | } |
425 | 1.14k | } |
426 | | |
427 | | int |
428 | | exif_mnote_data_pentax_identify (const ExifData *ed, const ExifEntry *e) |
429 | 1.33k | { |
430 | 1.33k | (void) ed; /* unused */ |
431 | 1.33k | if ((e->size >= 8) && !memcmp (e->data, "AOC", 4)) { |
432 | 565 | if (((e->data[4] == 'I') && (e->data[5] == 'I')) || |
433 | 561 | ((e->data[4] == 'M') && (e->data[5] == 'M'))) |
434 | 7 | return pentaxV3; |
435 | 558 | else |
436 | | /* Uses Casio v2 tags */ |
437 | 558 | return pentaxV2; |
438 | 565 | } |
439 | | |
440 | 771 | if ((e->size >= 8) && !memcmp (e->data, "QVC", 4)) |
441 | 39 | return casioV2; |
442 | | |
443 | | /* This isn't a very robust test, so make sure it's done last */ |
444 | | /* Maybe we should additionally check for a make of Asahi or Pentax */ |
445 | 732 | if ((e->size >= 2) && (e->data[0] == 0x00) && (e->data[1] == 0x1b)) |
446 | 536 | return pentaxV1; |
447 | | |
448 | 196 | return 0; |
449 | 732 | } |
450 | | |
451 | | ExifMnoteData * |
452 | | exif_mnote_data_pentax_new (ExifMem *mem) |
453 | 1.14k | { |
454 | 1.14k | ExifMnoteData *d; |
455 | | |
456 | 1.14k | if (!mem) return NULL; |
457 | | |
458 | 1.14k | d = exif_mem_alloc (mem, sizeof (ExifMnoteDataPentax)); |
459 | 1.14k | if (!d) return NULL; |
460 | | |
461 | 1.14k | exif_mnote_data_construct (d, mem); |
462 | | |
463 | | /* Set up function pointers */ |
464 | 1.14k | d->methods.free = exif_mnote_data_pentax_free; |
465 | 1.14k | d->methods.set_byte_order = exif_mnote_data_pentax_set_byte_order; |
466 | 1.14k | d->methods.set_offset = exif_mnote_data_pentax_set_offset; |
467 | 1.14k | d->methods.load = exif_mnote_data_pentax_load; |
468 | 1.14k | d->methods.save = exif_mnote_data_pentax_save; |
469 | 1.14k | d->methods.count = exif_mnote_data_pentax_count; |
470 | 1.14k | d->methods.get_id = exif_mnote_data_pentax_get_id; |
471 | 1.14k | d->methods.get_name = exif_mnote_data_pentax_get_name; |
472 | 1.14k | d->methods.get_title = exif_mnote_data_pentax_get_title; |
473 | 1.14k | d->methods.get_description = exif_mnote_data_pentax_get_description; |
474 | 1.14k | d->methods.get_value = exif_mnote_data_pentax_get_value; |
475 | | |
476 | 1.14k | return d; |
477 | 1.14k | } |