static void exif_mnote_data_canon_save (ExifMnoteData *ne, unsigned char **buf, unsigned int *buf_size) { ExifMnoteDataCanon *n = (ExifMnoteDataCanon *) ne; unsigned int i, o, s, doff; if (!n || !buf || !buf_size) return; /* * Allocate enough memory for all entries and the number * of entries. */ *buf_size = 2 + n->count * 12 + 4; *buf = exif_mem_alloc (ne->mem, sizeof (char) * *buf_size); if (!*buf) return; /* Save the number of entries */ exif_set_short (*buf, n->order, (ExifShort) n->count); /* Save each entry */ for (i = 0; i < n->count; i++) { o = 2 + i * 12; exif_set_short (*buf + o + 0, n->order, (ExifShort) n->entries[i].tag); exif_set_short (*buf + o + 2, n->order, (ExifShort) n->entries[i].format); exif_set_long (*buf + o + 4, n->order, n->entries[i].components); o += 8; s = exif_format_get_size (n->entries[i].format) * n->entries[i].components; if (s > 4) { *buf_size += s; /* Ensure even offsets. Set padding bytes to 0. */ if (s & 1) *buf_size += 1; *buf = exif_mem_realloc (ne->mem, *buf, sizeof (char) * *buf_size); if (!*buf) return; doff = *buf_size - s; if (s & 1) { doff--; *(*buf + *buf_size - 1) = '\0'; } exif_set_long (*buf + o, n->order, n->offset + doff); } else doff = o; /* * Write the data. Fill unneeded bytes with 0. Do not * crash if data is NULL. */ if (!n->entries[i].data) memset (*buf + doff, 0, s); else memcpy (*buf + doff, n->entries[i].data, s); if (s < 4) memset (*buf + doff + s, 0, (4 - s)); } }
static void exif_mnote_data_canon_load (ExifMnoteData *ne, const unsigned char *buf, unsigned int buf_size) { ExifMnoteDataCanon *n = (ExifMnoteDataCanon *) ne; ExifShort c; unsigned int i, o, s; if (!n || !buf || !buf_size || (buf_size < 6 + n->offset + 2)) return; /* Read the number of entries and remove old ones. */ c = exif_get_short (buf + 6 + n->offset, n->order); exif_mnote_data_canon_clear (n); /* Parse the entries */ for (i = 0; i < c; i++) { o = 6 + 2 + n->offset + 12 * i; if (o + 8 > buf_size) return; n->count = i + 1; n->entries = exif_mem_realloc (ne->mem, n->entries, sizeof (MnoteCanonEntry) * (i+1)); memset (&n->entries[i], 0, sizeof (MnoteCanonEntry)); n->entries[i].tag = exif_get_short (buf + o, n->order); n->entries[i].format = exif_get_short (buf + o + 2, n->order); n->entries[i].components = exif_get_long (buf + o + 4, n->order); n->entries[i].order = n->order; /* * Size? If bigger than 4 bytes, the actual data is not * in the entry but somewhere else (offset). */ s = exif_format_get_size (n->entries[i].format) * n->entries[i].components; if (!s) return; o += 8; if (s > 4) o = exif_get_long (buf + o, n->order) + 6; if (o + s > buf_size) return; /* Sanity check */ n->entries[i].data = exif_mem_alloc (ne->mem, sizeof (char) * s); if (!n->entries[i].data) return; n->entries[i].size = s; memcpy (n->entries[i].data, buf + o, s); } }
void exif_content_remove_entry (ExifContent *c, ExifEntry *e) { unsigned int i; if (!c || !c->priv || !e || (e->parent != c)) return; /* Search the entry */ for (i = 0; i < c->count; i++) if (c->entries[i] == e) break; if (i == c->count) return; /* Remove the entry */ memmove (&c->entries[i], &c->entries[i + 1], sizeof (ExifEntry*) * (c->count - i - 1)); c->count--; e->parent = NULL; exif_entry_unref (e); c->entries = exif_mem_realloc (c->priv->mem, c->entries, sizeof(ExifEntry*) * c->count); }
void exif_content_remove_entry (ExifContent *c, ExifEntry *e) { unsigned int i; ExifEntry **t, *temp; if (!c || !c->priv || !e || (e->parent != c)) return; for (i = 0; i < c->count; i++) if (c->entries[i] == e) break; if (i == c->count) return; temp = c->entries[c->count-1]; if (c->count > 1) { t = exif_mem_realloc (c->priv->mem, c->entries, sizeof(ExifEntry*) * (c->count - 1)); if (!t) { return; } c->entries = t; c->count--; if (i != c->count) { memmove (&t[i], &t[i + 1], sizeof (ExifEntry*) * (c->count - i - 1)); t[c->count-1] = temp; } } else { exif_mem_free (c->priv->mem, c->entries); c->entries = NULL; c->count = 0; } e->parent = NULL; exif_entry_unref (e); }
void exif_content_add_entry (ExifContent *c, ExifEntry *entry) { ExifEntry **entries; if (!c || !c->priv || !entry || entry->parent) return; if (exif_content_get_entry (c, entry->tag)) { exif_log (c->priv->log, EXIF_LOG_CODE_DEBUG, "ExifContent", "An attempt has been made to add " "the tag '%s' twice to an IFD. This is against " "specification.", exif_tag_get_name (entry->tag)); return; } entries = exif_mem_realloc (c->priv->mem, c->entries, sizeof (ExifEntry*) * (c->count + 1)); if (!entries) return; entry->parent = c; entries[c->count++] = entry; c->entries = entries; exif_entry_ref (entry); }
/** * @brief save the MnoteData from ne to buf * * @param ne extract the data from this structure * @param *buf write the mnoteData to this buffer (buffer will be allocated) * @param buf_size the size of the buffer */ static void exif_mnote_data_olympus_save (ExifMnoteData *ne, unsigned char **buf, unsigned int *buf_size) { ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) ne; size_t i, o, s, doff, base = 0, o2 = 6 + 2; size_t datao = 0; unsigned char *t; size_t ts; if (!n || !buf || !buf_size) return; /* * Allocate enough memory for all entries and the number of entries. */ *buf_size = 6 + 2 + 2 + n->count * 12; switch (n->version) { case olympusV1: case sanyoV1: case epsonV1: *buf = exif_mem_alloc (ne->mem, *buf_size); if (!*buf) { EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size); return; } /* Write the header and the number of entries. */ strcpy ((char *)*buf, n->version==sanyoV1?"SANYO": (n->version==epsonV1?"EPSON":"OLYMP")); exif_set_short (*buf + 6, n->order, (ExifShort) 1); datao = n->offset; break; case olympusV2: *buf_size += 8-6 + 4; *buf = exif_mem_alloc (ne->mem, *buf_size); if (!*buf) { EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size); return; } /* Write the header and the number of entries. */ strcpy ((char *)*buf, "OLYMPUS"); exif_set_short (*buf + 8, n->order, (ExifShort) ( (n->order == EXIF_BYTE_ORDER_INTEL) ? ('I' << 8) | 'I' : ('M' << 8) | 'M')); exif_set_short (*buf + 10, n->order, (ExifShort) 3); o2 += 4; break; case nikonV1: base = MNOTE_NIKON1_TAG_BASE; /* v1 has offsets based to main IFD, not makernote IFD */ datao += n->offset + 10; /* subtract the size here, so the increment in the next case will not harm us */ *buf_size -= 8 + 2; /* Fall through */ case nikonV2: *buf_size += 8 + 2; *buf_size += 4; /* Next IFD pointer */ *buf = exif_mem_alloc (ne->mem, *buf_size); if (!*buf) { EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size); return; } /* Write the header and the number of entries. */ strcpy ((char *)*buf, "Nikon"); (*buf)[6] = n->version; if (n->version == nikonV2) { exif_set_short (*buf + 10, n->order, (ExifShort) ( (n->order == EXIF_BYTE_ORDER_INTEL) ? ('I' << 8) | 'I' : ('M' << 8) | 'M')); exif_set_short (*buf + 12, n->order, (ExifShort) 0x2A); exif_set_long (*buf + 14, n->order, (ExifShort) 8); o2 += 2 + 8; } datao -= 10; /* Reset next IFD pointer */ exif_set_long (*buf + o2 + 2 + n->count * 12, n->order, 0); break; default: return; } exif_set_short (*buf + o2, n->order, (ExifShort) n->count); o2 += 2; /* Save each entry */ for (i = 0; i < n->count; i++) { o = o2 + i * 12; exif_set_short (*buf + o + 0, n->order, (ExifShort) (n->entries[i].tag - base)); exif_set_short (*buf + o + 2, n->order, (ExifShort) n->entries[i].format); exif_set_long (*buf + o + 4, n->order, n->entries[i].components); o += 8; s = exif_format_get_size (n->entries[i].format) * n->entries[i].components; if (s > 65536) { /* Corrupt data: EXIF data size is limited to the * maximum size of a JPEG segment (64 kb). */ continue; } if (s > 4) { doff = *buf_size; ts = *buf_size + s; t = exif_mem_realloc (ne->mem, *buf, sizeof (char) * ts); if (!t) { EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", ts); return; } *buf = t; *buf_size = ts; exif_set_long (*buf + o, n->order, datao + doff); } else doff = o; /* Write the data. */ if (n->entries[i].data) { memcpy (*buf + doff, n->entries[i].data, s); } else { /* Most certainly damaged input file */ memset (*buf + doff, 0, s); } } }
/** * @brief save the MnoteData from ne to buf * * @param ne extract the data from this structure * @param *buf write the mnoteData to this buffer (buffer will be allocated) * @param buf_size the final size of the buffer */ static void exif_mnote_data_pentax_save (ExifMnoteData *ne, unsigned char **buf, unsigned int *buf_size) { ExifMnoteDataPentax *n = (ExifMnoteDataPentax *) ne; size_t i, base = 0, /* internal MakerNote tag number offset */ o2 = 4 + 2; /* offset to first tag entry, past header */ size_t datao = n->offset; /* this MakerNote style uses offsets based on main IFD, not makernote IFD */ if (!n || !buf || !buf_size) return; /* * Allocate enough memory for header, the number of entries, entries, * and next IFD pointer */ *buf_size = o2 + 2 + n->count * 12 + 4; switch (n->version) { case casioV2: base = MNOTE_PENTAX2_TAG_BASE; *buf = exif_mem_alloc (ne->mem, *buf_size); if (!*buf) { EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataPentax", *buf_size); return; } /* Write the magic header */ strcpy ((char *)*buf, "QVC"); exif_set_short (*buf + 4, n->order, (ExifShort) 0); break; case pentaxV3: base = MNOTE_PENTAX2_TAG_BASE; *buf = exif_mem_alloc (ne->mem, *buf_size); if (!*buf) { EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataPentax", *buf_size); return; } /* Write the magic header */ strcpy ((char *)*buf, "AOC"); exif_set_short (*buf + 4, n->order, (ExifShort) ( (n->order == EXIF_BYTE_ORDER_INTEL) ? ('I' << 8) | 'I' : ('M' << 8) | 'M')); break; case pentaxV2: base = MNOTE_PENTAX2_TAG_BASE; *buf = exif_mem_alloc (ne->mem, *buf_size); if (!*buf) { EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataPentax", *buf_size); return; } /* Write the magic header */ strcpy ((char *)*buf, "AOC"); exif_set_short (*buf + 4, n->order, (ExifShort) 0); break; case pentaxV1: /* It looks like this format doesn't have a magic header as * such, just has a fixed number of entries equal to 0x001b */ *buf_size -= 6; o2 -= 6; *buf = exif_mem_alloc (ne->mem, *buf_size); if (!*buf) { EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataPentax", *buf_size); return; } break; default: /* internal error */ return; } /* Write the number of entries. */ exif_set_short (*buf + o2, n->order, (ExifShort) n->count); o2 += 2; /* Save each entry */ for (i = 0; i < n->count; i++) { size_t doff; /* offset to current data portion of tag */ size_t s; unsigned char *t; size_t o = o2 + i * 12; /* current offset into output buffer */ exif_set_short (*buf + o + 0, n->order, (ExifShort) (n->entries[i].tag - base)); exif_set_short (*buf + o + 2, n->order, (ExifShort) n->entries[i].format); exif_set_long (*buf + o + 4, n->order, n->entries[i].components); o += 8; s = exif_format_get_size (n->entries[i].format) * n->entries[i].components; if (s > 65536) { /* Corrupt data: EXIF data size is limited to the * maximum size of a JPEG segment (64 kb). */ continue; } if (s > 4) { size_t ts = *buf_size + s; doff = *buf_size; t = exif_mem_realloc (ne->mem, *buf, sizeof (char) * ts); if (!t) { EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataPentax", ts); return; } *buf = t; *buf_size = ts; exif_set_long (*buf + o, n->order, datao + doff); } else doff = o; /* Write the data. */ if (n->entries[i].data) { memcpy (*buf + doff, n->entries[i].data, s); } else { /* Most certainly damaged input file */ memset (*buf + doff, 0, s); } } /* Sanity check the buffer size */ if (*buf_size < (o2 + n->count * 12 + 4)) { exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifMnoteDataPentax", "Buffer overflow"); } /* Reset next IFD pointer */ exif_set_long (*buf + o2 + n->count * 12, n->order, 0); }
static void exif_data_save_data_content (ExifData *data, ExifContent *ifd, unsigned char **d, unsigned int *ds, unsigned int offset) { unsigned int j, n_ptr = 0, n_thumb = 0; ExifIfd i; unsigned char *t; unsigned int ts; if (!data || !data->priv || !ifd || !d || !ds) return; for (i = 0; i < EXIF_IFD_COUNT; i++) if (ifd == data->ifd[i]) break; if (i == EXIF_IFD_COUNT) return; /* error */ /* * Check if we need some extra entries for pointers or the thumbnail. */ switch (i) { case EXIF_IFD_0: /* * The pointer to IFD_EXIF is in IFD_0. The pointer to * IFD_INTEROPERABILITY is in IFD_EXIF. */ if (data->ifd[EXIF_IFD_EXIF]->count || data->ifd[EXIF_IFD_INTEROPERABILITY]->count) n_ptr++; /* The pointer to IFD_GPS is in IFD_0. */ if (data->ifd[EXIF_IFD_GPS]->count) n_ptr++; break; case EXIF_IFD_1: if (data->size) n_thumb = 2; break; case EXIF_IFD_EXIF: if (data->ifd[EXIF_IFD_INTEROPERABILITY]->count) n_ptr++; default: break; } /* * Allocate enough memory for all entries * and the number of entries. */ ts = *ds + (2 + (ifd->count + n_ptr + n_thumb) * 12 + 4); t = exif_mem_realloc (data->priv->mem, *d, ts); if (!t) { EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", ts); return; } *d = t; *ds = ts; /* Save the number of entries */ exif_set_short (*d + 6 + offset, data->priv->order, (ExifShort) (ifd->count + n_ptr + n_thumb)); offset += 2; /* * Save each entry. Make sure that no memcpys from NULL pointers are * performed */ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", "Saving %i entries (IFD '%s', offset: %i)...", ifd->count, exif_ifd_get_name (i), offset); for (j = 0; j < ifd->count; j++) { if (ifd->entries[j]) { exif_data_save_data_entry (data, ifd->entries[j], d, ds, offset + 12 * j); } } offset += 12 * ifd->count; /* Now save special entries. */ switch (i) { case EXIF_IFD_0: /* * The pointer to IFD_EXIF is in IFD_0. * However, the pointer to IFD_INTEROPERABILITY is in IFD_EXIF, * therefore, if IFD_INTEROPERABILITY is not empty, we need * IFD_EXIF even if latter is empty. */ if (data->ifd[EXIF_IFD_EXIF]->count || data->ifd[EXIF_IFD_INTEROPERABILITY]->count) { exif_set_short (*d + 6 + offset + 0, data->priv->order, EXIF_TAG_EXIF_IFD_POINTER); exif_set_short (*d + 6 + offset + 2, data->priv->order, EXIF_FORMAT_LONG); exif_set_long (*d + 6 + offset + 4, data->priv->order, 1); exif_set_long (*d + 6 + offset + 8, data->priv->order, *ds - 6); exif_data_save_data_content (data, data->ifd[EXIF_IFD_EXIF], d, ds, *ds - 6); offset += 12; } /* The pointer to IFD_GPS is in IFD_0, too. */ if (data->ifd[EXIF_IFD_GPS]->count) { exif_set_short (*d + 6 + offset + 0, data->priv->order, EXIF_TAG_GPS_INFO_IFD_POINTER); exif_set_short (*d + 6 + offset + 2, data->priv->order, EXIF_FORMAT_LONG); exif_set_long (*d + 6 + offset + 4, data->priv->order, 1); exif_set_long (*d + 6 + offset + 8, data->priv->order, *ds - 6); exif_data_save_data_content (data, data->ifd[EXIF_IFD_GPS], d, ds, *ds - 6); offset += 12; } break; case EXIF_IFD_EXIF: /* * The pointer to IFD_INTEROPERABILITY is in IFD_EXIF. * See note above. */ if (data->ifd[EXIF_IFD_INTEROPERABILITY]->count) { exif_set_short (*d + 6 + offset + 0, data->priv->order, EXIF_TAG_INTEROPERABILITY_IFD_POINTER); exif_set_short (*d + 6 + offset + 2, data->priv->order, EXIF_FORMAT_LONG); exif_set_long (*d + 6 + offset + 4, data->priv->order, 1); exif_set_long (*d + 6 + offset + 8, data->priv->order, *ds - 6); exif_data_save_data_content (data, data->ifd[EXIF_IFD_INTEROPERABILITY], d, ds, *ds - 6); offset += 12; } break; case EXIF_IFD_1: /* * Information about the thumbnail (if any) is saved in * IFD_1. */ if (data->size) { /* EXIF_TAG_JPEG_INTERCHANGE_FORMAT */ exif_set_short (*d + 6 + offset + 0, data->priv->order, EXIF_TAG_JPEG_INTERCHANGE_FORMAT); exif_set_short (*d + 6 + offset + 2, data->priv->order, EXIF_FORMAT_LONG); exif_set_long (*d + 6 + offset + 4, data->priv->order, 1); exif_set_long (*d + 6 + offset + 8, data->priv->order, *ds - 6); ts = *ds + data->size; t = exif_mem_realloc (data->priv->mem, *d, ts); if (!t) { EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", ts); return; } *d = t; *ds = ts; memcpy (*d + *ds - data->size, data->data, data->size); offset += 12; /* EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH */ exif_set_short (*d + 6 + offset + 0, data->priv->order, EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH); exif_set_short (*d + 6 + offset + 2, data->priv->order, EXIF_FORMAT_LONG); exif_set_long (*d + 6 + offset + 4, data->priv->order, 1); exif_set_long (*d + 6 + offset + 8, data->priv->order, data->size); offset += 12; } break; default: break; } /* Sort the directory according to TIFF specification */ qsort (*d + 6 + offset - (ifd->count + n_ptr + n_thumb) * 12, (ifd->count + n_ptr + n_thumb), 12, (data->priv->order == EXIF_BYTE_ORDER_INTEL) ? cmp_func_intel : cmp_func_motorola); /* Correctly terminate the directory */ if (i == EXIF_IFD_0 && (data->ifd[EXIF_IFD_1]->count || data->size)) { /* * We are saving IFD 0. Tell where IFD 1 starts and save * IFD 1. */ exif_set_long (*d + 6 + offset, data->priv->order, *ds - 6); exif_data_save_data_content (data, data->ifd[EXIF_IFD_1], d, ds, *ds - 6); } else exif_set_long (*d + 6 + offset, data->priv->order, 0); }
static void exif_data_save_data_entry (ExifData *data, ExifEntry *e, unsigned char **d, unsigned int *ds, unsigned int offset) { unsigned int doff, s; unsigned int ts; if (!data || !data->priv) return; /* * Each entry is 12 bytes long. The memory for the entry has * already been allocated. */ exif_set_short (*d + 6 + offset + 0, data->priv->order, (ExifShort) e->tag); exif_set_short (*d + 6 + offset + 2, data->priv->order, (ExifShort) e->format); if (!(data->priv->options & EXIF_DATA_OPTION_DONT_CHANGE_MAKER_NOTE)) { /* If this is the maker note tag, update it. */ if ((e->tag == EXIF_TAG_MAKER_NOTE) && data->priv->md) { /* TODO: this is using the wrong ExifMem to free e->data */ exif_mem_free (data->priv->mem, e->data); e->data = NULL; e->size = 0; exif_mnote_data_set_offset (data->priv->md, *ds - 6); exif_mnote_data_save (data->priv->md, &e->data, &e->size); e->components = e->size; } } exif_set_long (*d + 6 + offset + 4, data->priv->order, e->components); /* * Size? If bigger than 4 bytes, the actual data is not in * the entry but somewhere else. */ s = exif_format_get_size (e->format) * e->components; if (s > 4) { unsigned char *t; doff = *ds - 6; ts = *ds + s; /* * According to the TIFF specification, * the offset must be an even number. If we need to introduce * a padding byte, we set it to 0. */ if (s & 1) ts++; t = exif_mem_realloc (data->priv->mem, *d, ts); if (!t) { EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", ts); return; } *d = t; *ds = ts; exif_set_long (*d + 6 + offset + 8, data->priv->order, doff); if (s & 1) *(*d + *ds - 1) = '\0'; } else doff = offset + 8; /* Write the data. Fill unneeded bytes with 0. Do not crash with * e->data is NULL */ if (e->data) { memcpy (*d + 6 + doff, e->data, s); } else { memset (*d + 6 + doff, 0, s); } if (s < 4) memset (*d + 6 + doff + s, 0, (4 - s)); }
static void exif_mnote_data_canon_save (ExifMnoteData *ne, unsigned char **buf, unsigned int *buf_size) { ExifMnoteDataCanon *n = (ExifMnoteDataCanon *) ne; size_t i, o, s, doff; unsigned char *t; size_t ts; if (!n || !buf || !buf_size) return; /* * Allocate enough memory for all entries and the number * of entries. */ *buf_size = 2 + n->count * 12 + 4; *buf = exif_mem_alloc (ne->mem, sizeof (char) * *buf_size); if (!*buf) { EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteCanon", *buf_size); return; } /* Save the number of entries */ exif_set_short (*buf, n->order, (ExifShort) n->count); /* Save each entry */ for (i = 0; i < n->count; i++) { o = 2 + i * 12; exif_set_short (*buf + o + 0, n->order, (ExifShort) n->entries[i].tag); exif_set_short (*buf + o + 2, n->order, (ExifShort) n->entries[i].format); exif_set_long (*buf + o + 4, n->order, n->entries[i].components); o += 8; s = exif_format_get_size (n->entries[i].format) * n->entries[i].components; if (s > 65536) { /* Corrupt data: EXIF data size is limited to the * maximum size of a JPEG segment (64 kb). */ continue; } if (s > 4) { ts = *buf_size + s; /* Ensure even offsets. Set padding bytes to 0. */ if (s & 1) ts += 1; t = exif_mem_realloc (ne->mem, *buf, sizeof (char) * ts); if (!t) { EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteCanon", ts); return; } *buf = t; *buf_size = ts; doff = *buf_size - s; if (s & 1) { doff--; *(*buf + *buf_size - 1) = '\0'; } exif_set_long (*buf + o, n->order, n->offset + doff); } else doff = o; /* * Write the data. Fill unneeded bytes with 0. Do not * crash if data is NULL. */ if (!n->entries[i].data) memset (*buf + doff, 0, s); else memcpy (*buf + doff, n->entries[i].data, s); if (s < 4) memset (*buf + doff + s, 0, (4 - s)); } }
static void exif_mnote_data_fuji_save (ExifMnoteData *ne, unsigned char **buf, unsigned int *buf_size) { ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) ne; size_t i, o, s, doff; unsigned char *t; size_t ts; if (!n || !buf || !buf_size) return; /* * Allocate enough memory for all entries and the number * of entries. */ *buf_size = 8 + 4 + 2 + n->count * 12 + 4; *buf = exif_mem_alloc (ne->mem, *buf_size); if (!*buf) { *buf_size = 0; return; } /* * Header: "FUJIFILM" and 4 bytes offset to the first entry. * As the first entry will start right thereafter, the offset is 12. */ memcpy (*buf, "FUJIFILM", 8); exif_set_long (*buf + 8, n->order, 12); /* Save the number of entries */ exif_set_short (*buf + 8 + 4, n->order, (ExifShort) n->count); /* Save each entry */ for (i = 0; i < n->count; i++) { o = 8 + 4 + 2 + i * 12; exif_set_short (*buf + o + 0, n->order, (ExifShort) n->entries[i].tag); exif_set_short (*buf + o + 2, n->order, (ExifShort) n->entries[i].format); exif_set_long (*buf + o + 4, n->order, n->entries[i].components); o += 8; s = exif_format_get_size (n->entries[i].format) * n->entries[i].components; if (s > 65536) { /* Corrupt data: EXIF data size is limited to the * maximum size of a JPEG segment (64 kb). */ continue; } if (s > 4) { ts = *buf_size + s; /* Ensure even offsets. Set padding bytes to 0. */ if (s & 1) ts += 1; t = exif_mem_realloc (ne->mem, *buf, ts); if (!t) { return; } *buf = t; *buf_size = ts; doff = *buf_size - s; if (s & 1) { doff--; *(*buf + *buf_size - 1) = '\0'; } exif_set_long (*buf + o, n->order, doff); } else doff = o; /* * Write the data. Fill unneeded bytes with 0. Do not * crash if data is NULL. */ if (!n->entries[i].data) memset (*buf + doff, 0, s); else memcpy (*buf + doff, n->entries[i].data, s); } }