From: Reuben Thomas Date: Sat, 20 Feb 2010 15:19:53 +0000 (+0000) Subject: Clarify which sort of CDF we mean. X-Git-Tag: FILE5_07~169 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0d433910d12d61a520c06a57f0a07a595ce2d6b1;p=file Clarify which sort of CDF we mean. --- diff --git a/ChangeLog b/ChangeLog index 330b20a7..8838a3c6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2010-02-20 15:18 Reuben Thomas + + * Clarify which sort of CDF we mean. + 2010-02-14 22:58 Reuben Thomas * Re-jig Zip file type magic so that unsupported special diff --git a/src/cdf.c b/src/cdf.c index d59e52b1..1e374385 100644 --- a/src/cdf.c +++ b/src/cdf.c @@ -24,15 +24,18 @@ * POSSIBILITY OF SUCH DAMAGE. */ /* - * Parse composite document files, the format used in Microsoft Office - * document files before they switched to zipped xml. + * Parse Composite Document Files, the format used in Microsoft Office + * document files before they switched to zipped XML. * Info from: http://sc.openoffice.org/compdocfileformat.pdf + * + * N.B. This is the "Composite Document File" format, and not the + * "Compound Document Format", nor the "Channel Definition Format". */ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: cdf.c,v 1.35 2009/09/13 23:25:16 christos Exp $") +FILE_RCSID("@(#)$File: cdf.c,v 1.36 2010/01/22 20:56:26 christos Exp $") #endif #include @@ -65,8 +68,8 @@ FILE_RCSID("@(#)$File: cdf.c,v 1.35 2009/09/13 23:25:16 christos Exp $") #endif static union { - char s[4]; - uint32_t u; + char s[4]; + uint32_t u; } cdf_bo; #define NEED_SWAP (cdf_bo.u == (uint32_t)0x01020304) @@ -81,12 +84,12 @@ static union { uint16_t cdf_tole2(uint16_t sv) { - uint16_t rv; - uint8_t *s = (uint8_t *)(void *)&sv; - uint8_t *d = (uint8_t *)(void *)&rv; - d[0] = s[1]; - d[1] = s[0]; - return rv; + uint16_t rv; + uint8_t *s = (uint8_t *)(void *)&sv; + uint8_t *d = (uint8_t *)(void *)&rv; + d[0] = s[1]; + d[1] = s[0]; + return rv; } /* @@ -95,14 +98,14 @@ cdf_tole2(uint16_t sv) uint32_t cdf_tole4(uint32_t sv) { - uint32_t rv; - uint8_t *s = (uint8_t *)(void *)&sv; - uint8_t *d = (uint8_t *)(void *)&rv; - d[0] = s[3]; - d[1] = s[2]; - d[2] = s[1]; - d[3] = s[0]; - return rv; + uint32_t rv; + uint8_t *s = (uint8_t *)(void *)&sv; + uint8_t *d = (uint8_t *)(void *)&rv; + d[0] = s[3]; + d[1] = s[2]; + d[2] = s[1]; + d[3] = s[0]; + return rv; } /* @@ -111,18 +114,18 @@ cdf_tole4(uint32_t sv) uint64_t cdf_tole8(uint64_t sv) { - uint64_t rv; - uint8_t *s = (uint8_t *)(void *)&sv; - uint8_t *d = (uint8_t *)(void *)&rv; - d[0] = s[7]; - d[1] = s[6]; - d[2] = s[5]; - d[3] = s[4]; - d[4] = s[3]; - d[5] = s[2]; - d[6] = s[1]; - d[7] = s[0]; - return rv; + uint64_t rv; + uint8_t *s = (uint8_t *)(void *)&sv; + uint8_t *d = (uint8_t *)(void *)&rv; + d[0] = s[7]; + d[1] = s[6]; + d[2] = s[5]; + d[3] = s[4]; + d[4] = s[3]; + d[5] = s[2]; + d[6] = s[1]; + d[7] = s[0]; + return rv; } #define CDF_UNPACK(a) \ @@ -133,175 +136,175 @@ cdf_tole8(uint64_t sv) void cdf_swap_header(cdf_header_t *h) { - size_t i; - - h->h_magic = CDF_TOLE8(h->h_magic); - h->h_uuid[0] = CDF_TOLE8(h->h_uuid[0]); - h->h_uuid[1] = CDF_TOLE8(h->h_uuid[1]); - h->h_revision = CDF_TOLE2(h->h_revision); - h->h_version = CDF_TOLE2(h->h_version); - h->h_byte_order = CDF_TOLE2(h->h_byte_order); - h->h_sec_size_p2 = CDF_TOLE2(h->h_sec_size_p2); - h->h_short_sec_size_p2 = CDF_TOLE2(h->h_short_sec_size_p2); - h->h_num_sectors_in_sat = CDF_TOLE4(h->h_num_sectors_in_sat); - h->h_secid_first_directory = CDF_TOLE4(h->h_secid_first_directory); - h->h_min_size_standard_stream = - CDF_TOLE4(h->h_min_size_standard_stream); - h->h_secid_first_sector_in_short_sat = - CDF_TOLE4((uint32_t)h->h_secid_first_sector_in_short_sat); - h->h_num_sectors_in_short_sat = - CDF_TOLE4(h->h_num_sectors_in_short_sat); - h->h_secid_first_sector_in_master_sat = - CDF_TOLE4((uint32_t)h->h_secid_first_sector_in_master_sat); - h->h_num_sectors_in_master_sat = - CDF_TOLE4(h->h_num_sectors_in_master_sat); - for (i = 0; i < __arraycount(h->h_master_sat); i++) - h->h_master_sat[i] = CDF_TOLE4((uint32_t)h->h_master_sat[i]); + size_t i; + + h->h_magic = CDF_TOLE8(h->h_magic); + h->h_uuid[0] = CDF_TOLE8(h->h_uuid[0]); + h->h_uuid[1] = CDF_TOLE8(h->h_uuid[1]); + h->h_revision = CDF_TOLE2(h->h_revision); + h->h_version = CDF_TOLE2(h->h_version); + h->h_byte_order = CDF_TOLE2(h->h_byte_order); + h->h_sec_size_p2 = CDF_TOLE2(h->h_sec_size_p2); + h->h_short_sec_size_p2 = CDF_TOLE2(h->h_short_sec_size_p2); + h->h_num_sectors_in_sat = CDF_TOLE4(h->h_num_sectors_in_sat); + h->h_secid_first_directory = CDF_TOLE4(h->h_secid_first_directory); + h->h_min_size_standard_stream = + CDF_TOLE4(h->h_min_size_standard_stream); + h->h_secid_first_sector_in_short_sat = + CDF_TOLE4((uint32_t)h->h_secid_first_sector_in_short_sat); + h->h_num_sectors_in_short_sat = + CDF_TOLE4(h->h_num_sectors_in_short_sat); + h->h_secid_first_sector_in_master_sat = + CDF_TOLE4((uint32_t)h->h_secid_first_sector_in_master_sat); + h->h_num_sectors_in_master_sat = + CDF_TOLE4(h->h_num_sectors_in_master_sat); + for (i = 0; i < __arraycount(h->h_master_sat); i++) + h->h_master_sat[i] = CDF_TOLE4((uint32_t)h->h_master_sat[i]); } void cdf_unpack_header(cdf_header_t *h, char *buf) { - size_t i; - size_t len = 0; - - CDF_UNPACK(h->h_magic); - CDF_UNPACKA(h->h_uuid); - CDF_UNPACK(h->h_revision); - CDF_UNPACK(h->h_version); - CDF_UNPACK(h->h_byte_order); - CDF_UNPACK(h->h_sec_size_p2); - CDF_UNPACK(h->h_short_sec_size_p2); - CDF_UNPACKA(h->h_unused0); - CDF_UNPACK(h->h_num_sectors_in_sat); - CDF_UNPACK(h->h_secid_first_directory); - CDF_UNPACKA(h->h_unused1); - CDF_UNPACK(h->h_min_size_standard_stream); - CDF_UNPACK(h->h_secid_first_sector_in_short_sat); - CDF_UNPACK(h->h_num_sectors_in_short_sat); - CDF_UNPACK(h->h_secid_first_sector_in_master_sat); - CDF_UNPACK(h->h_num_sectors_in_master_sat); - for (i = 0; i < __arraycount(h->h_master_sat); i++) - CDF_UNPACK(h->h_master_sat[i]); + size_t i; + size_t len = 0; + + CDF_UNPACK(h->h_magic); + CDF_UNPACKA(h->h_uuid); + CDF_UNPACK(h->h_revision); + CDF_UNPACK(h->h_version); + CDF_UNPACK(h->h_byte_order); + CDF_UNPACK(h->h_sec_size_p2); + CDF_UNPACK(h->h_short_sec_size_p2); + CDF_UNPACKA(h->h_unused0); + CDF_UNPACK(h->h_num_sectors_in_sat); + CDF_UNPACK(h->h_secid_first_directory); + CDF_UNPACKA(h->h_unused1); + CDF_UNPACK(h->h_min_size_standard_stream); + CDF_UNPACK(h->h_secid_first_sector_in_short_sat); + CDF_UNPACK(h->h_num_sectors_in_short_sat); + CDF_UNPACK(h->h_secid_first_sector_in_master_sat); + CDF_UNPACK(h->h_num_sectors_in_master_sat); + for (i = 0; i < __arraycount(h->h_master_sat); i++) + CDF_UNPACK(h->h_master_sat[i]); } void cdf_swap_dir(cdf_directory_t *d) { - d->d_namelen = CDF_TOLE2(d->d_namelen); - d->d_left_child = CDF_TOLE4((uint32_t)d->d_left_child); - d->d_right_child = CDF_TOLE4((uint32_t)d->d_right_child); - d->d_storage = CDF_TOLE4((uint32_t)d->d_storage); - d->d_storage_uuid[0] = CDF_TOLE8(d->d_storage_uuid[0]); - d->d_storage_uuid[1] = CDF_TOLE8(d->d_storage_uuid[1]); - d->d_flags = CDF_TOLE4(d->d_flags); - d->d_created = CDF_TOLE8((uint64_t)d->d_created); - d->d_modified = CDF_TOLE8((uint64_t)d->d_modified); - d->d_stream_first_sector = CDF_TOLE4((uint32_t)d->d_stream_first_sector); - d->d_size = CDF_TOLE4(d->d_size); + d->d_namelen = CDF_TOLE2(d->d_namelen); + d->d_left_child = CDF_TOLE4((uint32_t)d->d_left_child); + d->d_right_child = CDF_TOLE4((uint32_t)d->d_right_child); + d->d_storage = CDF_TOLE4((uint32_t)d->d_storage); + d->d_storage_uuid[0] = CDF_TOLE8(d->d_storage_uuid[0]); + d->d_storage_uuid[1] = CDF_TOLE8(d->d_storage_uuid[1]); + d->d_flags = CDF_TOLE4(d->d_flags); + d->d_created = CDF_TOLE8((uint64_t)d->d_created); + d->d_modified = CDF_TOLE8((uint64_t)d->d_modified); + d->d_stream_first_sector = CDF_TOLE4((uint32_t)d->d_stream_first_sector); + d->d_size = CDF_TOLE4(d->d_size); } void cdf_swap_class(cdf_classid_t *d) { - d->cl_dword = CDF_TOLE4(d->cl_dword); - d->cl_word[0] = CDF_TOLE2(d->cl_word[0]); - d->cl_word[1] = CDF_TOLE2(d->cl_word[1]); + d->cl_dword = CDF_TOLE4(d->cl_dword); + d->cl_word[0] = CDF_TOLE2(d->cl_word[0]); + d->cl_word[1] = CDF_TOLE2(d->cl_word[1]); } void cdf_unpack_dir(cdf_directory_t *d, char *buf) { - size_t len = 0; - - CDF_UNPACKA(d->d_name); - CDF_UNPACK(d->d_namelen); - CDF_UNPACK(d->d_type); - CDF_UNPACK(d->d_color); - CDF_UNPACK(d->d_left_child); - CDF_UNPACK(d->d_right_child); - CDF_UNPACK(d->d_storage); - CDF_UNPACKA(d->d_storage_uuid); - CDF_UNPACK(d->d_flags); - CDF_UNPACK(d->d_created); - CDF_UNPACK(d->d_modified); - CDF_UNPACK(d->d_stream_first_sector); - CDF_UNPACK(d->d_size); - CDF_UNPACK(d->d_unused0); + size_t len = 0; + + CDF_UNPACKA(d->d_name); + CDF_UNPACK(d->d_namelen); + CDF_UNPACK(d->d_type); + CDF_UNPACK(d->d_color); + CDF_UNPACK(d->d_left_child); + CDF_UNPACK(d->d_right_child); + CDF_UNPACK(d->d_storage); + CDF_UNPACKA(d->d_storage_uuid); + CDF_UNPACK(d->d_flags); + CDF_UNPACK(d->d_created); + CDF_UNPACK(d->d_modified); + CDF_UNPACK(d->d_stream_first_sector); + CDF_UNPACK(d->d_size); + CDF_UNPACK(d->d_unused0); } static int cdf_check_stream_offset(const cdf_stream_t *sst, const void *p, size_t tail, int line) { - const char *b = (const char *)sst->sst_tab; - const char *e = ((const char *)p) + tail; - (void)&line; - if (e >= b && (size_t)(e - b) < sst->sst_dirlen * sst->sst_len) - return 0; - DPRINTF(("%d: offset begin %p end %p %zu >= %zu [%zu %zu]\n", - line, b, e, (size_t)(e - b), sst->sst_dirlen * sst->sst_len, - sst->sst_dirlen, sst->sst_len)); - errno = EFTYPE; - return -1; + const char *b = (const char *)sst->sst_tab; + const char *e = ((const char *)p) + tail; + (void)&line; + if (e >= b && (size_t)(e - b) < sst->sst_dirlen * sst->sst_len) + return 0; + DPRINTF(("%d: offset begin %p end %p %zu >= %zu [%zu %zu]\n", + line, b, e, (size_t)(e - b), sst->sst_dirlen * sst->sst_len, + sst->sst_dirlen, sst->sst_len)); + errno = EFTYPE; + return -1; } static ssize_t cdf_read(const cdf_info_t *info, off_t off, void *buf, size_t len) { - size_t siz = (size_t)off + len; + size_t siz = (size_t)off + len; - if ((off_t)(off + len) != (off_t)siz) { - errno = EINVAL; - return -1; - } + if ((off_t)(off + len) != (off_t)siz) { + errno = EINVAL; + return -1; + } - if (info->i_buf != NULL && info->i_len >= siz) { - (void)memcpy(buf, &info->i_buf[off], len); - return (ssize_t)len; - } + if (info->i_buf != NULL && info->i_len >= siz) { + (void)memcpy(buf, &info->i_buf[off], len); + return (ssize_t)len; + } - if (info->i_fd == -1) - return -1; + if (info->i_fd == -1) + return -1; - if (lseek(info->i_fd, off, SEEK_SET) == (off_t)-1) - return -1; + if (lseek(info->i_fd, off, SEEK_SET) == (off_t)-1) + return -1; - if (read(info->i_fd, buf, len) != (ssize_t)len) - return -1; + if (read(info->i_fd, buf, len) != (ssize_t)len) + return -1; - return (ssize_t)len; + return (ssize_t)len; } int cdf_read_header(const cdf_info_t *info, cdf_header_t *h) { - char buf[512]; - - (void)memcpy(cdf_bo.s, "\01\02\03\04", 4); - if (cdf_read(info, (off_t)0, buf, sizeof(buf)) == -1) - return -1; - cdf_unpack_header(h, buf); - cdf_swap_header(h); - if (h->h_magic != CDF_MAGIC) { - DPRINTF(("Bad magic 0x%llx != 0x%llx\n", - (unsigned long long)h->h_magic, - (unsigned long long)CDF_MAGIC)); - goto out; - } - if (h->h_sec_size_p2 > 20) { - DPRINTF(("Bad sector size 0x%u\n", h->h_sec_size_p2)); - goto out; - } - if (h->h_short_sec_size_p2 > 20) { - DPRINTF(("Bad short sector size 0x%u\n", - h->h_short_sec_size_p2)); - goto out; - } - return 0; + char buf[512]; + + (void)memcpy(cdf_bo.s, "\01\02\03\04", 4); + if (cdf_read(info, (off_t)0, buf, sizeof(buf)) == -1) + return -1; + cdf_unpack_header(h, buf); + cdf_swap_header(h); + if (h->h_magic != CDF_MAGIC) { + DPRINTF(("Bad magic 0x%llx != 0x%llx\n", + (unsigned long long)h->h_magic, + (unsigned long long)CDF_MAGIC)); + goto out; + } + if (h->h_sec_size_p2 > 20) { + DPRINTF(("Bad sector size 0x%u\n", h->h_sec_size_p2)); + goto out; + } + if (h->h_short_sec_size_p2 > 20) { + DPRINTF(("Bad short sector size 0x%u\n", + h->h_short_sec_size_p2)); + goto out; + } + return 0; out: - errno = EFTYPE; - return -1; + errno = EFTYPE; + return -1; } @@ -309,19 +312,19 @@ ssize_t cdf_read_sector(const cdf_info_t *info, void *buf, size_t offs, size_t len, const cdf_header_t *h, cdf_secid_t id) { - assert((size_t)CDF_SEC_SIZE(h) == len); - return cdf_read(info, (off_t)CDF_SEC_POS(h, id), - ((char *)buf) + offs, len); + assert((size_t)CDF_SEC_SIZE(h) == len); + return cdf_read(info, (off_t)CDF_SEC_POS(h, id), + ((char *)buf) + offs, len); } ssize_t cdf_read_short_sector(const cdf_stream_t *sst, void *buf, size_t offs, size_t len, const cdf_header_t *h, cdf_secid_t id) { - assert((size_t)CDF_SHORT_SEC_SIZE(h) == len); - (void)memcpy(((char *)buf) + offs, - ((const char *)sst->sst_tab) + CDF_SHORT_SEC_POS(h, id), len); - return len; + assert((size_t)CDF_SHORT_SEC_SIZE(h) == len); + (void)memcpy(((char *)buf) + offs, + ((const char *)sst->sst_tab) + CDF_SHORT_SEC_POS(h, id), len); + return len; } /* @@ -330,154 +333,154 @@ cdf_read_short_sector(const cdf_stream_t *sst, void *buf, size_t offs, int cdf_read_sat(const cdf_info_t *info, cdf_header_t *h, cdf_sat_t *sat) { - size_t i, j, k; - size_t ss = CDF_SEC_SIZE(h); - cdf_secid_t *msa, mid, sec; - size_t nsatpersec = (ss / sizeof(mid)) - 1; + size_t i, j, k; + size_t ss = CDF_SEC_SIZE(h); + cdf_secid_t *msa, mid, sec; + size_t nsatpersec = (ss / sizeof(mid)) - 1; - for (i = 0; i < __arraycount(h->h_master_sat); i++) - if (h->h_master_sat[i] == CDF_SECID_FREE) - break; + for (i = 0; i < __arraycount(h->h_master_sat); i++) + if (h->h_master_sat[i] == CDF_SECID_FREE) + break; #define CDF_SEC_LIMIT (UINT32_MAX / (4 * ss)) - if (h->h_num_sectors_in_master_sat > CDF_SEC_LIMIT / nsatpersec || - i > CDF_SEC_LIMIT) { - DPRINTF(("Number of sectors in master SAT too big %u %zu\n", - h->h_num_sectors_in_master_sat, i)); - errno = EFTYPE; - return -1; - } - - sat->sat_len = h->h_num_sectors_in_master_sat * nsatpersec + i; - DPRINTF(("sat_len = %zu ss = %zu\n", sat->sat_len, ss)); - if ((sat->sat_tab = CAST(cdf_secid_t *, calloc(sat->sat_len, ss))) - == NULL) - return -1; - - for (i = 0; i < __arraycount(h->h_master_sat); i++) { - if (h->h_master_sat[i] < 0) - break; - if (cdf_read_sector(info, sat->sat_tab, ss * i, ss, h, - h->h_master_sat[i]) != (ssize_t)ss) { - DPRINTF(("Reading sector %d", h->h_master_sat[i])); - goto out1; - } - } - - if ((msa = CAST(cdf_secid_t *, calloc(1, ss))) == NULL) - goto out1; - - mid = h->h_secid_first_sector_in_master_sat; - for (j = 0; j < h->h_num_sectors_in_master_sat; j++) { - if (mid < 0) - goto out; - if (j >= CDF_LOOP_LIMIT) { - DPRINTF(("Reading master sector loop limit")); - errno = EFTYPE; - goto out2; - } - if (cdf_read_sector(info, msa, 0, ss, h, mid) != (ssize_t)ss) { - DPRINTF(("Reading master sector %d", mid)); - goto out2; - } - for (k = 0; k < nsatpersec; k++, i++) { - sec = CDF_TOLE4((uint32_t)msa[k]); - if (sec < 0) - goto out; - if (i >= sat->sat_len) { - DPRINTF(("Out of bounds reading MSA %u >= %u", - i, sat->sat_len)); - errno = EFTYPE; - goto out2; - } - if (cdf_read_sector(info, sat->sat_tab, ss * i, ss, h, - sec) != (ssize_t)ss) { - DPRINTF(("Reading sector %d", - CDF_TOLE4(msa[k]))); - goto out2; - } - } - mid = CDF_TOLE4((uint32_t)msa[nsatpersec]); - } + if (h->h_num_sectors_in_master_sat > CDF_SEC_LIMIT / nsatpersec || + i > CDF_SEC_LIMIT) { + DPRINTF(("Number of sectors in master SAT too big %u %zu\n", + h->h_num_sectors_in_master_sat, i)); + errno = EFTYPE; + return -1; + } + + sat->sat_len = h->h_num_sectors_in_master_sat * nsatpersec + i; + DPRINTF(("sat_len = %zu ss = %zu\n", sat->sat_len, ss)); + if ((sat->sat_tab = CAST(cdf_secid_t *, calloc(sat->sat_len, ss))) + == NULL) + return -1; + + for (i = 0; i < __arraycount(h->h_master_sat); i++) { + if (h->h_master_sat[i] < 0) + break; + if (cdf_read_sector(info, sat->sat_tab, ss * i, ss, h, + h->h_master_sat[i]) != (ssize_t)ss) { + DPRINTF(("Reading sector %d", h->h_master_sat[i])); + goto out1; + } + } + + if ((msa = CAST(cdf_secid_t *, calloc(1, ss))) == NULL) + goto out1; + + mid = h->h_secid_first_sector_in_master_sat; + for (j = 0; j < h->h_num_sectors_in_master_sat; j++) { + if (mid < 0) + goto out; + if (j >= CDF_LOOP_LIMIT) { + DPRINTF(("Reading master sector loop limit")); + errno = EFTYPE; + goto out2; + } + if (cdf_read_sector(info, msa, 0, ss, h, mid) != (ssize_t)ss) { + DPRINTF(("Reading master sector %d", mid)); + goto out2; + } + for (k = 0; k < nsatpersec; k++, i++) { + sec = CDF_TOLE4((uint32_t)msa[k]); + if (sec < 0) + goto out; + if (i >= sat->sat_len) { + DPRINTF(("Out of bounds reading MSA %u >= %u", + i, sat->sat_len)); + errno = EFTYPE; + goto out2; + } + if (cdf_read_sector(info, sat->sat_tab, ss * i, ss, h, + sec) != (ssize_t)ss) { + DPRINTF(("Reading sector %d", + CDF_TOLE4(msa[k]))); + goto out2; + } + } + mid = CDF_TOLE4((uint32_t)msa[nsatpersec]); + } out: - sat->sat_len = i; - free(msa); - return 0; + sat->sat_len = i; + free(msa); + return 0; out2: - free(msa); + free(msa); out1: - free(sat->sat_tab); - return -1; + free(sat->sat_tab); + return -1; } size_t cdf_count_chain(const cdf_sat_t *sat, cdf_secid_t sid, size_t size) { - size_t i, j; - cdf_secid_t maxsector = (cdf_secid_t)(sat->sat_len * size); - - DPRINTF(("Chain:")); - for (j = i = 0; sid >= 0; i++, j++) { - DPRINTF((" %d", sid)); - if (j >= CDF_LOOP_LIMIT) { - DPRINTF(("Counting chain loop limit")); - errno = EFTYPE; - return (size_t)-1; - } - if (sid > maxsector) { - DPRINTF(("Sector %d > %d\n", sid, maxsector)); - errno = EFTYPE; - return (size_t)-1; - } - sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]); - } - DPRINTF(("\n")); - return i; + size_t i, j; + cdf_secid_t maxsector = (cdf_secid_t)(sat->sat_len * size); + + DPRINTF(("Chain:")); + for (j = i = 0; sid >= 0; i++, j++) { + DPRINTF((" %d", sid)); + if (j >= CDF_LOOP_LIMIT) { + DPRINTF(("Counting chain loop limit")); + errno = EFTYPE; + return (size_t)-1; + } + if (sid > maxsector) { + DPRINTF(("Sector %d > %d\n", sid, maxsector)); + errno = EFTYPE; + return (size_t)-1; + } + sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]); + } + DPRINTF(("\n")); + return i; } int cdf_read_long_sector_chain(const cdf_info_t *info, const cdf_header_t *h, const cdf_sat_t *sat, cdf_secid_t sid, size_t len, cdf_stream_t *scn) { - size_t ss = CDF_SEC_SIZE(h), i, j; - ssize_t nr; - scn->sst_len = cdf_count_chain(sat, sid, ss); - scn->sst_dirlen = len; - - if (scn->sst_len == (size_t)-1) - return -1; - - scn->sst_tab = calloc(scn->sst_len, ss); - if (scn->sst_tab == NULL) - return -1; - - for (j = i = 0; sid >= 0; i++, j++) { - if (j >= CDF_LOOP_LIMIT) { - DPRINTF(("Read long sector chain loop limit")); - errno = EFTYPE; - goto out; - } - if (i >= scn->sst_len) { - DPRINTF(("Out of bounds reading long sector chain " - "%u > %u\n", i, scn->sst_len)); - errno = EFTYPE; - goto out; - } - if ((nr = cdf_read_sector(info, scn->sst_tab, i * ss, ss, h, - sid)) != (ssize_t)ss) { - if (i == scn->sst_len - 1 && nr > 0) { - /* Last sector might be truncated */ - return 0; - } - DPRINTF(("Reading long sector chain %d", sid)); - goto out; - } - sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]); - } - return 0; + size_t ss = CDF_SEC_SIZE(h), i, j; + ssize_t nr; + scn->sst_len = cdf_count_chain(sat, sid, ss); + scn->sst_dirlen = len; + + if (scn->sst_len == (size_t)-1) + return -1; + + scn->sst_tab = calloc(scn->sst_len, ss); + if (scn->sst_tab == NULL) + return -1; + + for (j = i = 0; sid >= 0; i++, j++) { + if (j >= CDF_LOOP_LIMIT) { + DPRINTF(("Read long sector chain loop limit")); + errno = EFTYPE; + goto out; + } + if (i >= scn->sst_len) { + DPRINTF(("Out of bounds reading long sector chain " + "%u > %u\n", i, scn->sst_len)); + errno = EFTYPE; + goto out; + } + if ((nr = cdf_read_sector(info, scn->sst_tab, i * ss, ss, h, + sid)) != (ssize_t)ss) { + if (i == scn->sst_len - 1 && nr > 0) { + /* Last sector might be truncated */ + return 0; + } + DPRINTF(("Reading long sector chain %d", sid)); + goto out; + } + sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]); + } + return 0; out: - free(scn->sst_tab); - return -1; + free(scn->sst_tab); + return -1; } int @@ -485,40 +488,40 @@ cdf_read_short_sector_chain(const cdf_header_t *h, const cdf_sat_t *ssat, const cdf_stream_t *sst, cdf_secid_t sid, size_t len, cdf_stream_t *scn) { - size_t ss = CDF_SHORT_SEC_SIZE(h), i, j; - scn->sst_len = cdf_count_chain(ssat, sid, CDF_SEC_SIZE(h)); - scn->sst_dirlen = len; - - if (sst->sst_tab == NULL || scn->sst_len == (size_t)-1) - return -1; - - scn->sst_tab = calloc(scn->sst_len, ss); - if (scn->sst_tab == NULL) - return -1; - - for (j = i = 0; sid >= 0; i++, j++) { - if (j >= CDF_LOOP_LIMIT) { - DPRINTF(("Read short sector chain loop limit")); - errno = EFTYPE; - goto out; - } - if (i >= scn->sst_len) { - DPRINTF(("Out of bounds reading short sector chain " - "%u > %u\n", i, scn->sst_len)); - errno = EFTYPE; - goto out; - } - if (cdf_read_short_sector(sst, scn->sst_tab, i * ss, ss, h, - sid) != (ssize_t)ss) { - DPRINTF(("Reading short sector chain %d", sid)); - goto out; - } - sid = CDF_TOLE4((uint32_t)ssat->sat_tab[sid]); - } - return 0; + size_t ss = CDF_SHORT_SEC_SIZE(h), i, j; + scn->sst_len = cdf_count_chain(ssat, sid, CDF_SEC_SIZE(h)); + scn->sst_dirlen = len; + + if (sst->sst_tab == NULL || scn->sst_len == (size_t)-1) + return -1; + + scn->sst_tab = calloc(scn->sst_len, ss); + if (scn->sst_tab == NULL) + return -1; + + for (j = i = 0; sid >= 0; i++, j++) { + if (j >= CDF_LOOP_LIMIT) { + DPRINTF(("Read short sector chain loop limit")); + errno = EFTYPE; + goto out; + } + if (i >= scn->sst_len) { + DPRINTF(("Out of bounds reading short sector chain " + "%u > %u\n", i, scn->sst_len)); + errno = EFTYPE; + goto out; + } + if (cdf_read_short_sector(sst, scn->sst_tab, i * ss, ss, h, + sid) != (ssize_t)ss) { + DPRINTF(("Reading short sector chain %d", sid)); + goto out; + } + sid = CDF_TOLE4((uint32_t)ssat->sat_tab[sid]); + } + return 0; out: - free(scn->sst_tab); - return -1; + free(scn->sst_tab); + return -1; } int @@ -527,64 +530,64 @@ cdf_read_sector_chain(const cdf_info_t *info, const cdf_header_t *h, cdf_secid_t sid, size_t len, cdf_stream_t *scn) { - if (len < h->h_min_size_standard_stream && sst->sst_tab != NULL) - return cdf_read_short_sector_chain(h, ssat, sst, sid, len, - scn); - else - return cdf_read_long_sector_chain(info, h, sat, sid, len, scn); + if (len < h->h_min_size_standard_stream && sst->sst_tab != NULL) + return cdf_read_short_sector_chain(h, ssat, sst, sid, len, + scn); + else + return cdf_read_long_sector_chain(info, h, sat, sid, len, scn); } int cdf_read_dir(const cdf_info_t *info, const cdf_header_t *h, const cdf_sat_t *sat, cdf_dir_t *dir) { - size_t i, j; - size_t ss = CDF_SEC_SIZE(h), ns, nd; - char *buf; - cdf_secid_t sid = h->h_secid_first_directory; - - ns = cdf_count_chain(sat, sid, ss); - if (ns == (size_t)-1) - return -1; - - nd = ss / CDF_DIRECTORY_SIZE; - - dir->dir_len = ns * nd; - dir->dir_tab = CAST(cdf_directory_t *, - calloc(dir->dir_len, sizeof(dir->dir_tab[0]))); - if (dir->dir_tab == NULL) - return -1; - - if ((buf = CAST(char *, malloc(ss))) == NULL) { - free(dir->dir_tab); - return -1; - } - - for (j = i = 0; i < ns; i++, j++) { - if (j >= CDF_LOOP_LIMIT) { - DPRINTF(("Read dir loop limit")); - errno = EFTYPE; - goto out; - } - if (cdf_read_sector(info, buf, 0, ss, h, sid) != (ssize_t)ss) { - DPRINTF(("Reading directory sector %d", sid)); - goto out; - } - for (j = 0; j < nd; j++) { - cdf_unpack_dir(&dir->dir_tab[i * nd + j], - &buf[j * CDF_DIRECTORY_SIZE]); - } - sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]); - } - if (NEED_SWAP) - for (i = 0; i < dir->dir_len; i++) - cdf_swap_dir(&dir->dir_tab[i]); - free(buf); - return 0; + size_t i, j; + size_t ss = CDF_SEC_SIZE(h), ns, nd; + char *buf; + cdf_secid_t sid = h->h_secid_first_directory; + + ns = cdf_count_chain(sat, sid, ss); + if (ns == (size_t)-1) + return -1; + + nd = ss / CDF_DIRECTORY_SIZE; + + dir->dir_len = ns * nd; + dir->dir_tab = CAST(cdf_directory_t *, + calloc(dir->dir_len, sizeof(dir->dir_tab[0]))); + if (dir->dir_tab == NULL) + return -1; + + if ((buf = CAST(char *, malloc(ss))) == NULL) { + free(dir->dir_tab); + return -1; + } + + for (j = i = 0; i < ns; i++, j++) { + if (j >= CDF_LOOP_LIMIT) { + DPRINTF(("Read dir loop limit")); + errno = EFTYPE; + goto out; + } + if (cdf_read_sector(info, buf, 0, ss, h, sid) != (ssize_t)ss) { + DPRINTF(("Reading directory sector %d", sid)); + goto out; + } + for (j = 0; j < nd; j++) { + cdf_unpack_dir(&dir->dir_tab[i * nd + j], + &buf[j * CDF_DIRECTORY_SIZE]); + } + sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]); + } + if (NEED_SWAP) + for (i = 0; i < dir->dir_len; i++) + cdf_swap_dir(&dir->dir_tab[i]); + free(buf); + return 0; out: - free(dir->dir_tab); - free(buf); - return -1; + free(dir->dir_tab); + free(buf); + return -1; } @@ -592,79 +595,79 @@ int cdf_read_ssat(const cdf_info_t *info, const cdf_header_t *h, const cdf_sat_t *sat, cdf_sat_t *ssat) { - size_t i, j; - size_t ss = CDF_SEC_SIZE(h); - cdf_secid_t sid = h->h_secid_first_sector_in_short_sat; - - ssat->sat_len = cdf_count_chain(sat, sid, CDF_SEC_SIZE(h)); - if (ssat->sat_len == (size_t)-1) - return -1; - - ssat->sat_tab = CAST(cdf_secid_t *, calloc(ssat->sat_len, ss)); - if (ssat->sat_tab == NULL) - return -1; - - for (j = i = 0; sid >= 0; i++, j++) { - if (j >= CDF_LOOP_LIMIT) { - DPRINTF(("Read short sat sector loop limit")); - errno = EFTYPE; - goto out; - } - if (i >= ssat->sat_len) { - DPRINTF(("Out of bounds reading short sector chain " - "%u > %u\n", i, ssat->sat_len)); - errno = EFTYPE; - goto out; - } - if (cdf_read_sector(info, ssat->sat_tab, i * ss, ss, h, sid) != - (ssize_t)ss) { - DPRINTF(("Reading short sat sector %d", sid)); - goto out; - } - sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]); - } - return 0; + size_t i, j; + size_t ss = CDF_SEC_SIZE(h); + cdf_secid_t sid = h->h_secid_first_sector_in_short_sat; + + ssat->sat_len = cdf_count_chain(sat, sid, CDF_SEC_SIZE(h)); + if (ssat->sat_len == (size_t)-1) + return -1; + + ssat->sat_tab = CAST(cdf_secid_t *, calloc(ssat->sat_len, ss)); + if (ssat->sat_tab == NULL) + return -1; + + for (j = i = 0; sid >= 0; i++, j++) { + if (j >= CDF_LOOP_LIMIT) { + DPRINTF(("Read short sat sector loop limit")); + errno = EFTYPE; + goto out; + } + if (i >= ssat->sat_len) { + DPRINTF(("Out of bounds reading short sector chain " + "%u > %u\n", i, ssat->sat_len)); + errno = EFTYPE; + goto out; + } + if (cdf_read_sector(info, ssat->sat_tab, i * ss, ss, h, sid) != + (ssize_t)ss) { + DPRINTF(("Reading short sat sector %d", sid)); + goto out; + } + sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]); + } + return 0; out: - free(ssat->sat_tab); - return -1; + free(ssat->sat_tab); + return -1; } int cdf_read_short_stream(const cdf_info_t *info, const cdf_header_t *h, const cdf_sat_t *sat, const cdf_dir_t *dir, cdf_stream_t *scn) { - size_t i; - const cdf_directory_t *d; + size_t i; + const cdf_directory_t *d; - for (i = 0; i < dir->dir_len; i++) - if (dir->dir_tab[i].d_type == CDF_DIR_TYPE_ROOT_STORAGE) - break; + for (i = 0; i < dir->dir_len; i++) + if (dir->dir_tab[i].d_type == CDF_DIR_TYPE_ROOT_STORAGE) + break; - /* If the it is not there, just fake it; some docs don't have it */ - if (i == dir->dir_len) - goto out; - d = &dir->dir_tab[i]; + /* If the it is not there, just fake it; some docs don't have it */ + if (i == dir->dir_len) + goto out; + d = &dir->dir_tab[i]; - /* If the it is not there, just fake it; some docs don't have it */ - if (d->d_stream_first_sector < 0) - goto out; + /* If the it is not there, just fake it; some docs don't have it */ + if (d->d_stream_first_sector < 0) + goto out; - return cdf_read_long_sector_chain(info, h, sat, - d->d_stream_first_sector, d->d_size, scn); + return cdf_read_long_sector_chain(info, h, sat, + d->d_stream_first_sector, d->d_size, scn); out: - scn->sst_tab = NULL; - scn->sst_len = 0; - scn->sst_dirlen = 0; - return 0; + scn->sst_tab = NULL; + scn->sst_len = 0; + scn->sst_dirlen = 0; + return 0; } static int cdf_namecmp(const char *d, const uint16_t *s, size_t l) { - for (; l--; d++, s++) - if (*d != CDF_TOLE2(*s)) - return (unsigned char)*d - CDF_TOLE2(*s); - return 0; + for (; l--; d++, s++) + if (*d != CDF_TOLE2(*s)) + return (unsigned char)*d - CDF_TOLE2(*s); + return 0; } int @@ -672,227 +675,227 @@ cdf_read_summary_info(const cdf_info_t *info, const cdf_header_t *h, const cdf_sat_t *sat, const cdf_sat_t *ssat, const cdf_stream_t *sst, const cdf_dir_t *dir, cdf_stream_t *scn) { - size_t i; - const cdf_directory_t *d; - static const char name[] = "\05SummaryInformation"; - - for (i = dir->dir_len; i > 0; i--) - if (dir->dir_tab[i - 1].d_type == CDF_DIR_TYPE_USER_STREAM && - cdf_namecmp(name, dir->dir_tab[i - 1].d_name, sizeof(name)) - == 0) - break; - - if (i == 0) { - DPRINTF(("Cannot find summary information section\n")); - errno = ESRCH; - return -1; - } - d = &dir->dir_tab[i - 1]; - return cdf_read_sector_chain(info, h, sat, ssat, sst, - d->d_stream_first_sector, d->d_size, scn); + size_t i; + const cdf_directory_t *d; + static const char name[] = "\05SummaryInformation"; + + for (i = dir->dir_len; i > 0; i--) + if (dir->dir_tab[i - 1].d_type == CDF_DIR_TYPE_USER_STREAM && + cdf_namecmp(name, dir->dir_tab[i - 1].d_name, sizeof(name)) + == 0) + break; + + if (i == 0) { + DPRINTF(("Cannot find summary information section\n")); + errno = ESRCH; + return -1; + } + d = &dir->dir_tab[i - 1]; + return cdf_read_sector_chain(info, h, sat, ssat, sst, + d->d_stream_first_sector, d->d_size, scn); } int cdf_read_property_info(const cdf_stream_t *sst, uint32_t offs, cdf_property_info_t **info, size_t *count, size_t *maxcount) { - const cdf_section_header_t *shp; - cdf_section_header_t sh; - const uint32_t *p, *q, *e; - int16_t s16; - int32_t s32; - uint32_t u32; - int64_t s64; - uint64_t u64; - cdf_timestamp_t tp; - size_t i, o, nelements, j; - cdf_property_info_t *inp; - - if (offs > UINT32_MAX / 4) { - errno = EFTYPE; - goto out; - } - shp = CAST(const cdf_section_header_t *, (const void *) - ((const char *)sst->sst_tab + offs)); - if (cdf_check_stream_offset(sst, shp, sizeof(*shp), __LINE__) == -1) - goto out; - sh.sh_len = CDF_TOLE4(shp->sh_len); + const cdf_section_header_t *shp; + cdf_section_header_t sh; + const uint32_t *p, *q, *e; + int16_t s16; + int32_t s32; + uint32_t u32; + int64_t s64; + uint64_t u64; + cdf_timestamp_t tp; + size_t i, o, nelements, j; + cdf_property_info_t *inp; + + if (offs > UINT32_MAX / 4) { + errno = EFTYPE; + goto out; + } + shp = CAST(const cdf_section_header_t *, (const void *) + ((const char *)sst->sst_tab + offs)); + if (cdf_check_stream_offset(sst, shp, sizeof(*shp), __LINE__) == -1) + goto out; + sh.sh_len = CDF_TOLE4(shp->sh_len); #define CDF_SHLEN_LIMIT (UINT32_MAX / 8) - if (sh.sh_len > CDF_SHLEN_LIMIT) { - errno = EFTYPE; - goto out; - } - sh.sh_properties = CDF_TOLE4(shp->sh_properties); + if (sh.sh_len > CDF_SHLEN_LIMIT) { + errno = EFTYPE; + goto out; + } + sh.sh_properties = CDF_TOLE4(shp->sh_properties); #define CDF_PROP_LIMIT (UINT32_MAX / (4 * sizeof(*inp))) - if (sh.sh_properties > CDF_PROP_LIMIT) - goto out; - DPRINTF(("section len: %u properties %u\n", sh.sh_len, - sh.sh_properties)); - if (*maxcount) { - if (*maxcount > CDF_PROP_LIMIT) - goto out; - *maxcount += sh.sh_properties; - inp = CAST(cdf_property_info_t *, - realloc(*info, *maxcount * sizeof(*inp))); - } else { - *maxcount = sh.sh_properties; - inp = CAST(cdf_property_info_t *, - malloc(*maxcount * sizeof(*inp))); - } - if (inp == NULL) - goto out; - *info = inp; - inp += *count; - *count += sh.sh_properties; - p = CAST(const uint32_t *, (const void *) - ((const char *)(const void *)sst->sst_tab + - offs + sizeof(sh))); - e = CAST(const uint32_t *, (const void *) - (((const char *)(const void *)shp) + sh.sh_len)); - if (cdf_check_stream_offset(sst, e, 0, __LINE__) == -1) - goto out; - for (i = 0; i < sh.sh_properties; i++) { - q = (const uint32_t *)(const void *) - ((const char *)(const void *)p + - CDF_TOLE4(p[(i << 1) + 1])) - 2; - if (q > e) { - DPRINTF(("Ran of the end %p > %p\n", q, e)); - goto out; - } - inp[i].pi_id = CDF_TOLE4(p[i << 1]); - inp[i].pi_type = CDF_TOLE4(q[0]); - DPRINTF(("%d) id=%x type=%x offs=%x\n", i, inp[i].pi_id, - inp[i].pi_type, (const char *)q - (const char *)p)); - if (inp[i].pi_type & CDF_VECTOR) { - nelements = CDF_TOLE4(q[1]); - o = 2; - } else { - nelements = 1; - o = 1; - } - if (inp[i].pi_type & (CDF_ARRAY|CDF_BYREF|CDF_RESERVED)) - goto unknown; - switch (inp[i].pi_type & CDF_TYPEMASK) { - case CDF_NULL: - case CDF_EMPTY: - break; - case CDF_SIGNED16: - if (inp[i].pi_type & CDF_VECTOR) - goto unknown; - (void)memcpy(&s16, &q[o], sizeof(s16)); - inp[i].pi_s16 = CDF_TOLE2(s16); - break; - case CDF_SIGNED32: - if (inp[i].pi_type & CDF_VECTOR) - goto unknown; - (void)memcpy(&s32, &q[o], sizeof(s32)); - inp[i].pi_s32 = CDF_TOLE4((uint32_t)s32); - break; - case CDF_BOOL: - case CDF_UNSIGNED32: - if (inp[i].pi_type & CDF_VECTOR) - goto unknown; - (void)memcpy(&u32, &q[o], sizeof(u32)); - inp[i].pi_u32 = CDF_TOLE4(u32); - break; - case CDF_SIGNED64: - if (inp[i].pi_type & CDF_VECTOR) - goto unknown; - (void)memcpy(&s64, &q[o], sizeof(s64)); - inp[i].pi_s64 = CDF_TOLE8((uint64_t)s64); - break; - case CDF_UNSIGNED64: - if (inp[i].pi_type & CDF_VECTOR) - goto unknown; - (void)memcpy(&u64, &q[o], sizeof(u64)); - inp[i].pi_u64 = CDF_TOLE8((uint64_t)u64); - break; - case CDF_LENGTH32_STRING: - case CDF_LENGTH32_WSTRING: - if (nelements > 1) { - size_t nelem = inp - *info; - if (*maxcount > CDF_PROP_LIMIT - || nelements > CDF_PROP_LIMIT) - goto out; - *maxcount += nelements; - inp = CAST(cdf_property_info_t *, - realloc(*info, *maxcount * sizeof(*inp))); - if (inp == NULL) - goto out; - *info = inp; - inp = *info + nelem; - } - DPRINTF(("nelements = %d\n", nelements)); - for (j = 0; j < nelements; j++, i++) { - uint32_t l = CDF_TOLE4(q[o]); - inp[i].pi_str.s_len = l; - inp[i].pi_str.s_buf = - (const char *)(const void *)(&q[o+1]); - DPRINTF(("l = %d, r = %d, s = %s\n", l, - CDF_ROUND(l, sizeof(l)), - inp[i].pi_str.s_buf)); - l = 4 + (uint32_t)CDF_ROUND(l, sizeof(l)); - o += l >> 2; - } - i--; - break; - case CDF_FILETIME: - if (inp[i].pi_type & CDF_VECTOR) - goto unknown; - (void)memcpy(&tp, &q[o], sizeof(tp)); - inp[i].pi_tp = CDF_TOLE8((uint64_t)tp); - break; - case CDF_CLIPBOARD: - if (inp[i].pi_type & CDF_VECTOR) - goto unknown; - break; - default: - unknown: - DPRINTF(("Don't know how to deal with %x\n", - inp[i].pi_type)); - goto out; - } - } - return 0; + if (sh.sh_properties > CDF_PROP_LIMIT) + goto out; + DPRINTF(("section len: %u properties %u\n", sh.sh_len, + sh.sh_properties)); + if (*maxcount) { + if (*maxcount > CDF_PROP_LIMIT) + goto out; + *maxcount += sh.sh_properties; + inp = CAST(cdf_property_info_t *, + realloc(*info, *maxcount * sizeof(*inp))); + } else { + *maxcount = sh.sh_properties; + inp = CAST(cdf_property_info_t *, + malloc(*maxcount * sizeof(*inp))); + } + if (inp == NULL) + goto out; + *info = inp; + inp += *count; + *count += sh.sh_properties; + p = CAST(const uint32_t *, (const void *) + ((const char *)(const void *)sst->sst_tab + + offs + sizeof(sh))); + e = CAST(const uint32_t *, (const void *) + (((const char *)(const void *)shp) + sh.sh_len)); + if (cdf_check_stream_offset(sst, e, 0, __LINE__) == -1) + goto out; + for (i = 0; i < sh.sh_properties; i++) { + q = (const uint32_t *)(const void *) + ((const char *)(const void *)p + + CDF_TOLE4(p[(i << 1) + 1])) - 2; + if (q > e) { + DPRINTF(("Ran of the end %p > %p\n", q, e)); + goto out; + } + inp[i].pi_id = CDF_TOLE4(p[i << 1]); + inp[i].pi_type = CDF_TOLE4(q[0]); + DPRINTF(("%d) id=%x type=%x offs=%x\n", i, inp[i].pi_id, + inp[i].pi_type, (const char *)q - (const char *)p)); + if (inp[i].pi_type & CDF_VECTOR) { + nelements = CDF_TOLE4(q[1]); + o = 2; + } else { + nelements = 1; + o = 1; + } + if (inp[i].pi_type & (CDF_ARRAY|CDF_BYREF|CDF_RESERVED)) + goto unknown; + switch (inp[i].pi_type & CDF_TYPEMASK) { + case CDF_NULL: + case CDF_EMPTY: + break; + case CDF_SIGNED16: + if (inp[i].pi_type & CDF_VECTOR) + goto unknown; + (void)memcpy(&s16, &q[o], sizeof(s16)); + inp[i].pi_s16 = CDF_TOLE2(s16); + break; + case CDF_SIGNED32: + if (inp[i].pi_type & CDF_VECTOR) + goto unknown; + (void)memcpy(&s32, &q[o], sizeof(s32)); + inp[i].pi_s32 = CDF_TOLE4((uint32_t)s32); + break; + case CDF_BOOL: + case CDF_UNSIGNED32: + if (inp[i].pi_type & CDF_VECTOR) + goto unknown; + (void)memcpy(&u32, &q[o], sizeof(u32)); + inp[i].pi_u32 = CDF_TOLE4(u32); + break; + case CDF_SIGNED64: + if (inp[i].pi_type & CDF_VECTOR) + goto unknown; + (void)memcpy(&s64, &q[o], sizeof(s64)); + inp[i].pi_s64 = CDF_TOLE8((uint64_t)s64); + break; + case CDF_UNSIGNED64: + if (inp[i].pi_type & CDF_VECTOR) + goto unknown; + (void)memcpy(&u64, &q[o], sizeof(u64)); + inp[i].pi_u64 = CDF_TOLE8((uint64_t)u64); + break; + case CDF_LENGTH32_STRING: + case CDF_LENGTH32_WSTRING: + if (nelements > 1) { + size_t nelem = inp - *info; + if (*maxcount > CDF_PROP_LIMIT + || nelements > CDF_PROP_LIMIT) + goto out; + *maxcount += nelements; + inp = CAST(cdf_property_info_t *, + realloc(*info, *maxcount * sizeof(*inp))); + if (inp == NULL) + goto out; + *info = inp; + inp = *info + nelem; + } + DPRINTF(("nelements = %d\n", nelements)); + for (j = 0; j < nelements; j++, i++) { + uint32_t l = CDF_TOLE4(q[o]); + inp[i].pi_str.s_len = l; + inp[i].pi_str.s_buf = + (const char *)(const void *)(&q[o+1]); + DPRINTF(("l = %d, r = %d, s = %s\n", l, + CDF_ROUND(l, sizeof(l)), + inp[i].pi_str.s_buf)); + l = 4 + (uint32_t)CDF_ROUND(l, sizeof(l)); + o += l >> 2; + } + i--; + break; + case CDF_FILETIME: + if (inp[i].pi_type & CDF_VECTOR) + goto unknown; + (void)memcpy(&tp, &q[o], sizeof(tp)); + inp[i].pi_tp = CDF_TOLE8((uint64_t)tp); + break; + case CDF_CLIPBOARD: + if (inp[i].pi_type & CDF_VECTOR) + goto unknown; + break; + default: + unknown: + DPRINTF(("Don't know how to deal with %x\n", + inp[i].pi_type)); + goto out; + } + } + return 0; out: - free(*info); - return -1; + free(*info); + return -1; } int cdf_unpack_summary_info(const cdf_stream_t *sst, cdf_summary_info_header_t *ssi, cdf_property_info_t **info, size_t *count) { - size_t i, maxcount; - const cdf_summary_info_header_t *si = - CAST(const cdf_summary_info_header_t *, sst->sst_tab); - const cdf_section_declaration_t *sd = - CAST(const cdf_section_declaration_t *, (const void *) - ((const char *)sst->sst_tab + CDF_SECTION_DECLARATION_OFFSET)); - - if (cdf_check_stream_offset(sst, si, sizeof(*si), __LINE__) == -1 || - cdf_check_stream_offset(sst, sd, sizeof(*sd), __LINE__) == -1) - return -1; - ssi->si_byte_order = CDF_TOLE2(si->si_byte_order); - ssi->si_os_version = CDF_TOLE2(si->si_os_version); - ssi->si_os = CDF_TOLE2(si->si_os); - ssi->si_class = si->si_class; - cdf_swap_class(&ssi->si_class); - ssi->si_count = CDF_TOLE2(si->si_count); - *count = 0; - maxcount = 0; - *info = NULL; - for (i = 0; i < CDF_TOLE4(si->si_count); i++) { - if (i >= CDF_LOOP_LIMIT) { - DPRINTF(("Unpack summary info loop limit")); - errno = EFTYPE; - return -1; - } - if (cdf_read_property_info(sst, CDF_TOLE4(sd->sd_offset), - info, count, &maxcount) == -1) - return -1; - } - return 0; + size_t i, maxcount; + const cdf_summary_info_header_t *si = + CAST(const cdf_summary_info_header_t *, sst->sst_tab); + const cdf_section_declaration_t *sd = + CAST(const cdf_section_declaration_t *, (const void *) + ((const char *)sst->sst_tab + CDF_SECTION_DECLARATION_OFFSET)); + + if (cdf_check_stream_offset(sst, si, sizeof(*si), __LINE__) == -1 || + cdf_check_stream_offset(sst, sd, sizeof(*sd), __LINE__) == -1) + return -1; + ssi->si_byte_order = CDF_TOLE2(si->si_byte_order); + ssi->si_os_version = CDF_TOLE2(si->si_os_version); + ssi->si_os = CDF_TOLE2(si->si_os); + ssi->si_class = si->si_class; + cdf_swap_class(&ssi->si_class); + ssi->si_count = CDF_TOLE2(si->si_count); + *count = 0; + maxcount = 0; + *info = NULL; + for (i = 0; i < CDF_TOLE4(si->si_count); i++) { + if (i >= CDF_LOOP_LIMIT) { + DPRINTF(("Unpack summary info loop limit")); + errno = EFTYPE; + return -1; + } + if (cdf_read_property_info(sst, CDF_TOLE4(sd->sd_offset), + info, count, &maxcount) == -1) + return -1; + } + return 0; } @@ -900,83 +903,83 @@ cdf_unpack_summary_info(const cdf_stream_t *sst, cdf_summary_info_header_t *ssi, int cdf_print_classid(char *buf, size_t buflen, const cdf_classid_t *id) { - return snprintf(buf, buflen, "%.8x-%.4x-%.4x-%.2x%.2x-" - "%.2x%.2x%.2x%.2x%.2x%.2x", id->cl_dword, id->cl_word[0], - id->cl_word[1], id->cl_two[0], id->cl_two[1], id->cl_six[0], - id->cl_six[1], id->cl_six[2], id->cl_six[3], id->cl_six[4], - id->cl_six[5]); + return snprintf(buf, buflen, "%.8x-%.4x-%.4x-%.2x%.2x-" + "%.2x%.2x%.2x%.2x%.2x%.2x", id->cl_dword, id->cl_word[0], + id->cl_word[1], id->cl_two[0], id->cl_two[1], id->cl_six[0], + id->cl_six[1], id->cl_six[2], id->cl_six[3], id->cl_six[4], + id->cl_six[5]); } static const struct { - uint32_t v; - const char *n; + uint32_t v; + const char *n; } vn[] = { - { CDF_PROPERTY_CODE_PAGE, "Code page" }, - { CDF_PROPERTY_TITLE, "Title" }, - { CDF_PROPERTY_SUBJECT, "Subject" }, - { CDF_PROPERTY_AUTHOR, "Author" }, - { CDF_PROPERTY_KEYWORDS, "Keywords" }, - { CDF_PROPERTY_COMMENTS, "Comments" }, - { CDF_PROPERTY_TEMPLATE, "Template" }, - { CDF_PROPERTY_LAST_SAVED_BY, "Last Saved By" }, - { CDF_PROPERTY_REVISION_NUMBER, "Revision Number" }, - { CDF_PROPERTY_TOTAL_EDITING_TIME, "Total Editing Time" }, - { CDF_PROPERTY_LAST_PRINTED, "Last Printed" }, - { CDF_PROPERTY_CREATE_TIME, "Create Time/Date" }, - { CDF_PROPERTY_LAST_SAVED_TIME, "Last Saved Time/Date" }, - { CDF_PROPERTY_NUMBER_OF_PAGES, "Number of Pages" }, - { CDF_PROPERTY_NUMBER_OF_WORDS, "Number of Words" }, - { CDF_PROPERTY_NUMBER_OF_CHARACTERS, "Number of Characters" }, - { CDF_PROPERTY_THUMBNAIL, "Thumbnail" }, - { CDF_PROPERTY_NAME_OF_APPLICATION, "Name of Creating Application" }, - { CDF_PROPERTY_SECURITY, "Security" }, - { CDF_PROPERTY_LOCALE_ID, "Locale ID" }, + { CDF_PROPERTY_CODE_PAGE, "Code page" }, + { CDF_PROPERTY_TITLE, "Title" }, + { CDF_PROPERTY_SUBJECT, "Subject" }, + { CDF_PROPERTY_AUTHOR, "Author" }, + { CDF_PROPERTY_KEYWORDS, "Keywords" }, + { CDF_PROPERTY_COMMENTS, "Comments" }, + { CDF_PROPERTY_TEMPLATE, "Template" }, + { CDF_PROPERTY_LAST_SAVED_BY, "Last Saved By" }, + { CDF_PROPERTY_REVISION_NUMBER, "Revision Number" }, + { CDF_PROPERTY_TOTAL_EDITING_TIME, "Total Editing Time" }, + { CDF_PROPERTY_LAST_PRINTED, "Last Printed" }, + { CDF_PROPERTY_CREATE_TIME, "Create Time/Date" }, + { CDF_PROPERTY_LAST_SAVED_TIME, "Last Saved Time/Date" }, + { CDF_PROPERTY_NUMBER_OF_PAGES, "Number of Pages" }, + { CDF_PROPERTY_NUMBER_OF_WORDS, "Number of Words" }, + { CDF_PROPERTY_NUMBER_OF_CHARACTERS, "Number of Characters" }, + { CDF_PROPERTY_THUMBNAIL, "Thumbnail" }, + { CDF_PROPERTY_NAME_OF_APPLICATION, "Name of Creating Application" }, + { CDF_PROPERTY_SECURITY, "Security" }, + { CDF_PROPERTY_LOCALE_ID, "Locale ID" }, }; int cdf_print_property_name(char *buf, size_t bufsiz, uint32_t p) { - size_t i; + size_t i; - for (i = 0; i < __arraycount(vn); i++) - if (vn[i].v == p) - return snprintf(buf, bufsiz, "%s", vn[i].n); - return snprintf(buf, bufsiz, "0x%x", p); + for (i = 0; i < __arraycount(vn); i++) + if (vn[i].v == p) + return snprintf(buf, bufsiz, "%s", vn[i].n); + return snprintf(buf, bufsiz, "0x%x", p); } int cdf_print_elapsed_time(char *buf, size_t bufsiz, cdf_timestamp_t ts) { - int len = 0; - int days, hours, mins, secs; - - ts /= CDF_TIME_PREC; - secs = (int)(ts % 60); - ts /= 60; - mins = (int)(ts % 60); - ts /= 60; - hours = (int)(ts % 24); - ts /= 24; - days = (int)ts; - - if (days) { - len += snprintf(buf + len, bufsiz - len, "%dd+", days); - if ((size_t)len >= bufsiz) - return len; - } - - if (days || hours) { - len += snprintf(buf + len, bufsiz - len, "%.2d:", hours); - if ((size_t)len >= bufsiz) - return len; - } - - len += snprintf(buf + len, bufsiz - len, "%.2d:", mins); - if ((size_t)len >= bufsiz) - return len; - - len += snprintf(buf + len, bufsiz - len, "%.2d", secs); - return len; + int len = 0; + int days, hours, mins, secs; + + ts /= CDF_TIME_PREC; + secs = (int)(ts % 60); + ts /= 60; + mins = (int)(ts % 60); + ts /= 60; + hours = (int)(ts % 24); + ts /= 24; + days = (int)ts; + + if (days) { + len += snprintf(buf + len, bufsiz - len, "%dd+", days); + if ((size_t)len >= bufsiz) + return len; + } + + if (days || hours) { + len += snprintf(buf + len, bufsiz - len, "%.2d:", hours); + if ((size_t)len >= bufsiz) + return len; + } + + len += snprintf(buf + len, bufsiz - len, "%.2d:", mins); + if ((size_t)len >= bufsiz) + return len; + + len += snprintf(buf + len, bufsiz - len, "%.2d", secs); + return len; } @@ -984,74 +987,74 @@ cdf_print_elapsed_time(char *buf, size_t bufsiz, cdf_timestamp_t ts) void cdf_dump_header(const cdf_header_t *h) { - size_t i; + size_t i; #define DUMP(a, b) (void)fprintf(stderr, "%40.40s = " a "\n", # b, h->h_ ## b) #define DUMP2(a, b) (void)fprintf(stderr, "%40.40s = " a " (" a ")\n", # b, \ h->h_ ## b, 1 << h->h_ ## b) - DUMP("%d", revision); - DUMP("%d", version); - DUMP("0x%x", byte_order); - DUMP2("%d", sec_size_p2); - DUMP2("%d", short_sec_size_p2); - DUMP("%d", num_sectors_in_sat); - DUMP("%d", secid_first_directory); - DUMP("%d", min_size_standard_stream); - DUMP("%d", secid_first_sector_in_short_sat); - DUMP("%d", num_sectors_in_short_sat); - DUMP("%d", secid_first_sector_in_master_sat); - DUMP("%d", num_sectors_in_master_sat); - for (i = 0; i < __arraycount(h->h_master_sat); i++) { - if (h->h_master_sat[i] == CDF_SECID_FREE) - break; - (void)fprintf(stderr, "%35.35s[%.3zu] = %d\n", - "master_sat", i, h->h_master_sat[i]); - } + DUMP("%d", revision); + DUMP("%d", version); + DUMP("0x%x", byte_order); + DUMP2("%d", sec_size_p2); + DUMP2("%d", short_sec_size_p2); + DUMP("%d", num_sectors_in_sat); + DUMP("%d", secid_first_directory); + DUMP("%d", min_size_standard_stream); + DUMP("%d", secid_first_sector_in_short_sat); + DUMP("%d", num_sectors_in_short_sat); + DUMP("%d", secid_first_sector_in_master_sat); + DUMP("%d", num_sectors_in_master_sat); + for (i = 0; i < __arraycount(h->h_master_sat); i++) { + if (h->h_master_sat[i] == CDF_SECID_FREE) + break; + (void)fprintf(stderr, "%35.35s[%.3zu] = %d\n", + "master_sat", i, h->h_master_sat[i]); + } } void cdf_dump_sat(const char *prefix, const cdf_sat_t *sat, size_t size) { - size_t i, j, s = size / sizeof(cdf_secid_t); - - for (i = 0; i < sat->sat_len; i++) { - (void)fprintf(stderr, "%s[%zu]:\n%.6d: ", prefix, i, i * s); - for (j = 0; j < s; j++) { - (void)fprintf(stderr, "%5d, ", - CDF_TOLE4(sat->sat_tab[s * i + j])); - if ((j + 1) % 10 == 0) - (void)fprintf(stderr, "\n%.6d: ", - i * s + j + 1); - } - (void)fprintf(stderr, "\n"); - } + size_t i, j, s = size / sizeof(cdf_secid_t); + + for (i = 0; i < sat->sat_len; i++) { + (void)fprintf(stderr, "%s[%zu]:\n%.6d: ", prefix, i, i * s); + for (j = 0; j < s; j++) { + (void)fprintf(stderr, "%5d, ", + CDF_TOLE4(sat->sat_tab[s * i + j])); + if ((j + 1) % 10 == 0) + (void)fprintf(stderr, "\n%.6d: ", + i * s + j + 1); + } + (void)fprintf(stderr, "\n"); + } } void cdf_dump(void *v, size_t len) { - size_t i, j; - unsigned char *p = v; - char abuf[16]; - (void)fprintf(stderr, "%.4x: ", 0); - for (i = 0, j = 0; i < len; i++, p++) { - (void)fprintf(stderr, "%.2x ", *p); - abuf[j++] = isprint(*p) ? *p : '.'; - if (j == 16) { - j = 0; - abuf[15] = '\0'; - (void)fprintf(stderr, "%s\n%.4x: ", abuf, i + 1); - } - } - (void)fprintf(stderr, "\n"); + size_t i, j; + unsigned char *p = v; + char abuf[16]; + (void)fprintf(stderr, "%.4x: ", 0); + for (i = 0, j = 0; i < len; i++, p++) { + (void)fprintf(stderr, "%.2x ", *p); + abuf[j++] = isprint(*p) ? *p : '.'; + if (j == 16) { + j = 0; + abuf[15] = '\0'; + (void)fprintf(stderr, "%s\n%.4x: ", abuf, i + 1); + } + } + (void)fprintf(stderr, "\n"); } void cdf_dump_stream(const cdf_header_t *h, const cdf_stream_t *sst) { - size_t ss = sst->sst_dirlen < h->h_min_size_standard_stream ? - CDF_SHORT_SEC_SIZE(h) : CDF_SEC_SIZE(h); - cdf_dump(sst->sst_tab, ss * sst->sst_len); + size_t ss = sst->sst_dirlen < h->h_min_size_standard_stream ? + CDF_SHORT_SEC_SIZE(h) : CDF_SEC_SIZE(h); + cdf_dump(sst->sst_tab, ss * sst->sst_len); } void @@ -1059,139 +1062,139 @@ cdf_dump_dir(const cdf_info_t *info, const cdf_header_t *h, const cdf_sat_t *sat, const cdf_sat_t *ssat, const cdf_stream_t *sst, const cdf_dir_t *dir) { - size_t i, j; - cdf_directory_t *d; - char name[__arraycount(d->d_name)]; - cdf_stream_t scn; - struct timespec ts; - - static const char *types[] = { "empty", "user storage", - "user stream", "lockbytes", "property", "root storage" }; - - for (i = 0; i < dir->dir_len; i++) { - d = &dir->dir_tab[i]; - for (j = 0; j < sizeof(name); j++) - name[j] = (char)CDF_TOLE2(d->d_name[j]); - (void)fprintf(stderr, "Directory %zu: %s\n", i, name); - if (d->d_type < __arraycount(types)) - (void)fprintf(stderr, "Type: %s\n", types[d->d_type]); - else - (void)fprintf(stderr, "Type: %d\n", d->d_type); - (void)fprintf(stderr, "Color: %s\n", - d->d_color ? "black" : "red"); - (void)fprintf(stderr, "Left child: %d\n", d->d_left_child); - (void)fprintf(stderr, "Right child: %d\n", d->d_right_child); - (void)fprintf(stderr, "Flags: 0x%x\n", d->d_flags); - cdf_timestamp_to_timespec(&ts, d->d_created); - (void)fprintf(stderr, "Created %s", ctime(&ts.tv_sec)); - cdf_timestamp_to_timespec(&ts, d->d_modified); - (void)fprintf(stderr, "Modified %s", ctime(&ts.tv_sec)); - (void)fprintf(stderr, "Stream %d\n", d->d_stream_first_sector); - (void)fprintf(stderr, "Size %d\n", d->d_size); - switch (d->d_type) { - case CDF_DIR_TYPE_USER_STORAGE: - (void)fprintf(stderr, "Storage: %d\n", d->d_storage); - break; - case CDF_DIR_TYPE_USER_STREAM: - if (sst == NULL) - break; - if (cdf_read_sector_chain(info, h, sat, ssat, sst, - d->d_stream_first_sector, d->d_size, &scn) == -1) { - warn("Can't read stream for %s at %d len %d", - name, d->d_stream_first_sector, d->d_size); - break; - } - cdf_dump_stream(h, &scn); - free(scn.sst_tab); - break; - default: - break; - } - - } + size_t i, j; + cdf_directory_t *d; + char name[__arraycount(d->d_name)]; + cdf_stream_t scn; + struct timespec ts; + + static const char *types[] = { "empty", "user storage", + "user stream", "lockbytes", "property", "root storage" }; + + for (i = 0; i < dir->dir_len; i++) { + d = &dir->dir_tab[i]; + for (j = 0; j < sizeof(name); j++) + name[j] = (char)CDF_TOLE2(d->d_name[j]); + (void)fprintf(stderr, "Directory %zu: %s\n", i, name); + if (d->d_type < __arraycount(types)) + (void)fprintf(stderr, "Type: %s\n", types[d->d_type]); + else + (void)fprintf(stderr, "Type: %d\n", d->d_type); + (void)fprintf(stderr, "Color: %s\n", + d->d_color ? "black" : "red"); + (void)fprintf(stderr, "Left child: %d\n", d->d_left_child); + (void)fprintf(stderr, "Right child: %d\n", d->d_right_child); + (void)fprintf(stderr, "Flags: 0x%x\n", d->d_flags); + cdf_timestamp_to_timespec(&ts, d->d_created); + (void)fprintf(stderr, "Created %s", ctime(&ts.tv_sec)); + cdf_timestamp_to_timespec(&ts, d->d_modified); + (void)fprintf(stderr, "Modified %s", ctime(&ts.tv_sec)); + (void)fprintf(stderr, "Stream %d\n", d->d_stream_first_sector); + (void)fprintf(stderr, "Size %d\n", d->d_size); + switch (d->d_type) { + case CDF_DIR_TYPE_USER_STORAGE: + (void)fprintf(stderr, "Storage: %d\n", d->d_storage); + break; + case CDF_DIR_TYPE_USER_STREAM: + if (sst == NULL) + break; + if (cdf_read_sector_chain(info, h, sat, ssat, sst, + d->d_stream_first_sector, d->d_size, &scn) == -1) { + warn("Can't read stream for %s at %d len %d", + name, d->d_stream_first_sector, d->d_size); + break; + } + cdf_dump_stream(h, &scn); + free(scn.sst_tab); + break; + default: + break; + } + + } } void cdf_dump_property_info(const cdf_property_info_t *info, size_t count) { - cdf_timestamp_t tp; - struct timespec ts; - char buf[64]; - size_t i, j; - - for (i = 0; i < count; i++) { - cdf_print_property_name(buf, sizeof(buf), info[i].pi_id); - (void)fprintf(stderr, "%zu) %s: ", i, buf); - switch (info[i].pi_type) { - case CDF_NULL: - break; - case CDF_SIGNED16: - (void)fprintf(stderr, "signed 16 [%hd]\n", - info[i].pi_s16); - break; - case CDF_SIGNED32: - (void)fprintf(stderr, "signed 32 [%d]\n", - info[i].pi_s32); - break; - case CDF_UNSIGNED32: - (void)fprintf(stderr, "unsigned 32 [%u]\n", - info[i].pi_u32); - break; - case CDF_LENGTH32_STRING: - (void)fprintf(stderr, "string %u [%.*s]\n", - info[i].pi_str.s_len, - info[i].pi_str.s_len, info[i].pi_str.s_buf); - break; - case CDF_LENGTH32_WSTRING: - (void)fprintf(stderr, "string %u [", - info[i].pi_str.s_len); - for (j = 0; j < info[i].pi_str.s_len - 1; j++) - (void)fputc(info[i].pi_str.s_buf[j << 1], stderr); - (void)fprintf(stderr, "]\n"); - break; - case CDF_FILETIME: - tp = info[i].pi_tp; - if (tp < 1000000000000000LL) { - cdf_print_elapsed_time(buf, sizeof(buf), tp); - (void)fprintf(stderr, "timestamp %s\n", buf); - } else { - cdf_timestamp_to_timespec(&ts, tp); - (void)fprintf(stderr, "timestamp %s", - ctime(&ts.tv_sec)); - } - break; - case CDF_CLIPBOARD: - (void)fprintf(stderr, "CLIPBOARD %u\n", info[i].pi_u32); - break; - default: - DPRINTF(("Don't know how to deal with %x\n", - info[i].pi_type)); - break; - } - } + cdf_timestamp_t tp; + struct timespec ts; + char buf[64]; + size_t i, j; + + for (i = 0; i < count; i++) { + cdf_print_property_name(buf, sizeof(buf), info[i].pi_id); + (void)fprintf(stderr, "%zu) %s: ", i, buf); + switch (info[i].pi_type) { + case CDF_NULL: + break; + case CDF_SIGNED16: + (void)fprintf(stderr, "signed 16 [%hd]\n", + info[i].pi_s16); + break; + case CDF_SIGNED32: + (void)fprintf(stderr, "signed 32 [%d]\n", + info[i].pi_s32); + break; + case CDF_UNSIGNED32: + (void)fprintf(stderr, "unsigned 32 [%u]\n", + info[i].pi_u32); + break; + case CDF_LENGTH32_STRING: + (void)fprintf(stderr, "string %u [%.*s]\n", + info[i].pi_str.s_len, + info[i].pi_str.s_len, info[i].pi_str.s_buf); + break; + case CDF_LENGTH32_WSTRING: + (void)fprintf(stderr, "string %u [", + info[i].pi_str.s_len); + for (j = 0; j < info[i].pi_str.s_len - 1; j++) + (void)fputc(info[i].pi_str.s_buf[j << 1], stderr); + (void)fprintf(stderr, "]\n"); + break; + case CDF_FILETIME: + tp = info[i].pi_tp; + if (tp < 1000000000000000LL) { + cdf_print_elapsed_time(buf, sizeof(buf), tp); + (void)fprintf(stderr, "timestamp %s\n", buf); + } else { + cdf_timestamp_to_timespec(&ts, tp); + (void)fprintf(stderr, "timestamp %s", + ctime(&ts.tv_sec)); + } + break; + case CDF_CLIPBOARD: + (void)fprintf(stderr, "CLIPBOARD %u\n", info[i].pi_u32); + break; + default: + DPRINTF(("Don't know how to deal with %x\n", + info[i].pi_type)); + break; + } + } } void cdf_dump_summary_info(const cdf_header_t *h, const cdf_stream_t *sst) { - char buf[128]; - cdf_summary_info_header_t ssi; - cdf_property_info_t *info; - size_t count; - - (void)&h; - if (cdf_unpack_summary_info(sst, &ssi, &info, &count) == -1) - return; - (void)fprintf(stderr, "Endian: %x\n", ssi.si_byte_order); - (void)fprintf(stderr, "Os Version %d.%d\n", ssi.si_os_version & 0xff, - ssi.si_os_version >> 8); - (void)fprintf(stderr, "Os %d\n", ssi.si_os); - cdf_print_classid(buf, sizeof(buf), &ssi.si_class); - (void)fprintf(stderr, "Class %s\n", buf); - (void)fprintf(stderr, "Count %d\n", ssi.si_count); - cdf_dump_property_info(info, count); - free(info); + char buf[128]; + cdf_summary_info_header_t ssi; + cdf_property_info_t *info; + size_t count; + + (void)&h; + if (cdf_unpack_summary_info(sst, &ssi, &info, &count) == -1) + return; + (void)fprintf(stderr, "Endian: %x\n", ssi.si_byte_order); + (void)fprintf(stderr, "Os Version %d.%d\n", ssi.si_os_version & 0xff, + ssi.si_os_version >> 8); + (void)fprintf(stderr, "Os %d\n", ssi.si_os); + cdf_print_classid(buf, sizeof(buf), &ssi.si_class); + (void)fprintf(stderr, "Class %s\n", buf); + (void)fprintf(stderr, "Count %d\n", ssi.si_count); + cdf_dump_property_info(info, count); + free(info); } #endif @@ -1200,66 +1203,66 @@ cdf_dump_summary_info(const cdf_header_t *h, const cdf_stream_t *sst) int main(int argc, char *argv[]) { - int i; - cdf_header_t h; - cdf_sat_t sat, ssat; - cdf_stream_t sst, scn; - cdf_dir_t dir; - cdf_info_t info; - - if (argc < 2) { - (void)fprintf(stderr, "Usage: %s \n", getprogname()); - return -1; - } - - info.i_buf = NULL; - info.i_len = 0; - for (i = 1; i < argc; i++) { - if ((info.i_fd = open(argv[1], O_RDONLY)) == -1) - err(1, "Cannot open `%s'", argv[1]); - - if (cdf_read_header(&info, &h) == -1) - err(1, "Cannot read header"); + int i; + cdf_header_t h; + cdf_sat_t sat, ssat; + cdf_stream_t sst, scn; + cdf_dir_t dir; + cdf_info_t info; + + if (argc < 2) { + (void)fprintf(stderr, "Usage: %s \n", getprogname()); + return -1; + } + + info.i_buf = NULL; + info.i_len = 0; + for (i = 1; i < argc; i++) { + if ((info.i_fd = open(argv[1], O_RDONLY)) == -1) + err(1, "Cannot open `%s'", argv[1]); + + if (cdf_read_header(&info, &h) == -1) + err(1, "Cannot read header"); #ifdef CDF_DEBUG - cdf_dump_header(&h); + cdf_dump_header(&h); #endif - if (cdf_read_sat(&info, &h, &sat) == -1) - err(1, "Cannot read sat"); + if (cdf_read_sat(&info, &h, &sat) == -1) + err(1, "Cannot read sat"); #ifdef CDF_DEBUG - cdf_dump_sat("SAT", &sat, CDF_SEC_SIZE(&h)); + cdf_dump_sat("SAT", &sat, CDF_SEC_SIZE(&h)); #endif - if (cdf_read_ssat(&info, &h, &sat, &ssat) == -1) - err(1, "Cannot read ssat"); + if (cdf_read_ssat(&info, &h, &sat, &ssat) == -1) + err(1, "Cannot read ssat"); #ifdef CDF_DEBUG - cdf_dump_sat("SSAT", &ssat, CDF_SHORT_SEC_SIZE(&h)); + cdf_dump_sat("SSAT", &ssat, CDF_SHORT_SEC_SIZE(&h)); #endif - if (cdf_read_dir(&info, &h, &sat, &dir) == -1) - err(1, "Cannot read dir"); + if (cdf_read_dir(&info, &h, &sat, &dir) == -1) + err(1, "Cannot read dir"); - if (cdf_read_short_stream(&info, &h, &sat, &dir, &sst) == -1) - err(1, "Cannot read short stream"); + if (cdf_read_short_stream(&info, &h, &sat, &dir, &sst) == -1) + err(1, "Cannot read short stream"); #ifdef CDF_DEBUG - cdf_dump_stream(&h, &sst); + cdf_dump_stream(&h, &sst); #endif #ifdef CDF_DEBUG - cdf_dump_dir(&info, &h, &sat, &ssat, &sst, &dir); + cdf_dump_dir(&info, &h, &sat, &ssat, &sst, &dir); #endif - if (cdf_read_summary_info(&info, &h, &sat, &ssat, &sst, &dir, - &scn) == -1) - err(1, "Cannot read summary info"); + if (cdf_read_summary_info(&info, &h, &sat, &ssat, &sst, &dir, + &scn) == -1) + err(1, "Cannot read summary info"); #ifdef CDF_DEBUG - cdf_dump_summary_info(&h, &scn); + cdf_dump_summary_info(&h, &scn); #endif - (void)close(info.i_fd); - } + (void)close(info.i_fd); + } - return 0; + return 0; } #endif diff --git a/src/cdf.h b/src/cdf.h index 6fa3fc69..16314e97 100644 --- a/src/cdf.h +++ b/src/cdf.h @@ -24,7 +24,12 @@ * POSSIBILITY OF SUCH DAMAGE. */ /* - * Info from: http://sc.openoffice.org/compdocfileformat.pdf + * Parse Composite Document Files, the format used in Microsoft Office + * document files before they switched to zipped XML. + * Info from: http://sc.openoffice.org/compdocfileformat.pdf + * + * N.B. This is the "Composite Document File" format, and not the + * "Compound Document Format", nor the "Channel Definition Format". */ #ifndef _H_CDF_ @@ -41,24 +46,24 @@ typedef int32_t cdf_secid_t; #define CDF_SECID_MASTER_SECTOR_ALLOCATION_TABLE -4 typedef struct { - uint64_t h_magic; + uint64_t h_magic; #define CDF_MAGIC 0xE11AB1A1E011CFD0LL - uint64_t h_uuid[2]; - uint16_t h_revision; - uint16_t h_version; - uint16_t h_byte_order; - uint16_t h_sec_size_p2; - uint16_t h_short_sec_size_p2; - uint8_t h_unused0[10]; - uint32_t h_num_sectors_in_sat; - uint32_t h_secid_first_directory; - uint8_t h_unused1[4]; - uint32_t h_min_size_standard_stream; - cdf_secid_t h_secid_first_sector_in_short_sat; - uint32_t h_num_sectors_in_short_sat; - cdf_secid_t h_secid_first_sector_in_master_sat; - uint32_t h_num_sectors_in_master_sat; - cdf_secid_t h_master_sat[436/4]; + uint64_t h_uuid[2]; + uint16_t h_revision; + uint16_t h_version; + uint16_t h_byte_order; + uint16_t h_sec_size_p2; + uint16_t h_short_sec_size_p2; + uint8_t h_unused0[10]; + uint32_t h_num_sectors_in_sat; + uint32_t h_secid_first_directory; + uint8_t h_unused1[4]; + uint32_t h_min_size_standard_stream; + cdf_secid_t h_secid_first_sector_in_short_sat; + uint32_t h_num_sectors_in_short_sat; + cdf_secid_t h_secid_first_sector_in_master_sat; + uint32_t h_num_sectors_in_master_sat; + cdf_secid_t h_master_sat[436/4]; } cdf_header_t; #define CDF_SEC_SIZE(h) (1 << (h)->h_sec_size_p2) @@ -74,92 +79,92 @@ typedef int64_t cdf_timestamp_t; #define CDF_TIME_PREC 10000000 typedef struct { - uint16_t d_name[32]; - uint16_t d_namelen; - uint8_t d_type; + uint16_t d_name[32]; + uint16_t d_namelen; + uint8_t d_type; #define CDF_DIR_TYPE_EMPTY 0 #define CDF_DIR_TYPE_USER_STORAGE 1 #define CDF_DIR_TYPE_USER_STREAM 2 #define CDF_DIR_TYPE_LOCKBYTES 3 #define CDF_DIR_TYPE_PROPERTY 4 #define CDF_DIR_TYPE_ROOT_STORAGE 5 - uint8_t d_color; + uint8_t d_color; #define CDF_DIR_COLOR_READ 0 #define CDF_DIR_COLOR_BLACK 1 - cdf_dirid_t d_left_child; - cdf_dirid_t d_right_child; - cdf_dirid_t d_storage; - uint64_t d_storage_uuid[2]; - uint32_t d_flags; - cdf_timestamp_t d_created; - cdf_timestamp_t d_modified; - cdf_secid_t d_stream_first_sector; - uint32_t d_size; - uint32_t d_unused0; + cdf_dirid_t d_left_child; + cdf_dirid_t d_right_child; + cdf_dirid_t d_storage; + uint64_t d_storage_uuid[2]; + uint32_t d_flags; + cdf_timestamp_t d_created; + cdf_timestamp_t d_modified; + cdf_secid_t d_stream_first_sector; + uint32_t d_size; + uint32_t d_unused0; } cdf_directory_t; #define CDF_DIRECTORY_SIZE 128 typedef struct { - cdf_secid_t *sat_tab; - size_t sat_len; + cdf_secid_t *sat_tab; + size_t sat_len; } cdf_sat_t; typedef struct { - cdf_directory_t *dir_tab; - size_t dir_len; + cdf_directory_t *dir_tab; + size_t dir_len; } cdf_dir_t; typedef struct { - void *sst_tab; - size_t sst_len; - size_t sst_dirlen; + void *sst_tab; + size_t sst_len; + size_t sst_dirlen; } cdf_stream_t; typedef struct { - uint32_t cl_dword; - uint16_t cl_word[2]; - uint8_t cl_two[2]; - uint8_t cl_six[6]; + uint32_t cl_dword; + uint16_t cl_word[2]; + uint8_t cl_two[2]; + uint8_t cl_six[6]; } cdf_classid_t; typedef struct { - uint16_t si_byte_order; - uint16_t si_zero; - uint16_t si_os_version; - uint16_t si_os; - cdf_classid_t si_class; - uint32_t si_count; + uint16_t si_byte_order; + uint16_t si_zero; + uint16_t si_os_version; + uint16_t si_os; + cdf_classid_t si_class; + uint32_t si_count; } cdf_summary_info_header_t; #define CDF_SECTION_DECLARATION_OFFSET 0x1c typedef struct { - cdf_classid_t sd_class; - uint32_t sd_offset; + cdf_classid_t sd_class; + uint32_t sd_offset; } cdf_section_declaration_t; typedef struct { - uint32_t sh_len; - uint32_t sh_properties; + uint32_t sh_len; + uint32_t sh_properties; } cdf_section_header_t; typedef struct { - uint32_t pi_id; - uint32_t pi_type; - union { - uint16_t _pi_u16; - int16_t _pi_s16; - uint32_t _pi_u32; - int32_t _pi_s32; - uint64_t _pi_u64; - int64_t _pi_s64; - cdf_timestamp_t _pi_tp; - struct { - uint32_t s_len; - const char *s_buf; - } _pi_str; - } pi_val; + uint32_t pi_id; + uint32_t pi_type; + union { + uint16_t _pi_u16; + int16_t _pi_s16; + uint32_t _pi_u32; + int32_t _pi_s32; + uint64_t _pi_u64; + int64_t _pi_s64; + cdf_timestamp_t _pi_tp; + struct { + uint32_t s_len; + const char *s_buf; + } _pi_str; + } pi_val; #define pi_u64 pi_val._pi_u64 #define pi_s64 pi_val._pi_s64 #define pi_u32 pi_val._pi_u32 @@ -226,7 +231,7 @@ typedef struct { #define CDF_PROPERTY_SUBJECT 0x00000003 #define CDF_PROPERTY_AUTHOR 0x00000004 #define CDF_PROPERTY_KEYWORDS 0x00000005 -#define CDF_PROPERTY_COMMENTS 0x00000006 +#define CDF_PROPERTY_COMMENTS 0x00000006 #define CDF_PROPERTY_TEMPLATE 0x00000007 #define CDF_PROPERTY_LAST_SAVED_BY 0x00000008 #define CDF_PROPERTY_REVISION_NUMBER 0x00000009 @@ -243,9 +248,9 @@ typedef struct { #define CDF_PROPERTY_LOCALE_ID 0x80000000 typedef struct { - int i_fd; - const unsigned char *i_buf; - size_t i_len; + int i_fd; + const unsigned char *i_buf; + size_t i_len; } cdf_info_t; struct timespec; diff --git a/src/readcdf.c b/src/readcdf.c index 312d7c32..67b47d0e 100644 --- a/src/readcdf.c +++ b/src/readcdf.c @@ -26,7 +26,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: readcdf.c,v 1.21 2009/09/13 23:23:31 christos Exp $") +FILE_RCSID("@(#)$File: readcdf.c,v 1.22 2010/01/20 01:36:55 christos Exp $") #endif #include @@ -44,241 +44,241 @@ private int cdf_file_property_info(struct magic_set *ms, const cdf_property_info_t *info, size_t count) { - size_t i; - cdf_timestamp_t tp; - struct timespec ts; - char buf[64]; - const char *str = "vnd.ms-office"; - const char *s; - int len; + size_t i; + cdf_timestamp_t tp; + struct timespec ts; + char buf[64]; + const char *str = "vnd.ms-office"; + const char *s; + int len; - for (i = 0; i < count; i++) { - cdf_print_property_name(buf, sizeof(buf), info[i].pi_id); - switch (info[i].pi_type) { - case CDF_NULL: - break; - case CDF_SIGNED16: - if (NOTMIME(ms) && file_printf(ms, ", %s: %hd", buf, - info[i].pi_s16) == -1) - return -1; - break; - case CDF_SIGNED32: - if (NOTMIME(ms) && file_printf(ms, ", %s: %d", buf, - info[i].pi_s32) == -1) - return -1; - break; - case CDF_UNSIGNED32: - if (NOTMIME(ms) && file_printf(ms, ", %s: %u", buf, - info[i].pi_u32) == -1) - return -1; - break; - case CDF_LENGTH32_STRING: - case CDF_LENGTH32_WSTRING: - len = info[i].pi_str.s_len; - if (len > 1) { - char vbuf[1024]; - size_t j, k = 1; + for (i = 0; i < count; i++) { + cdf_print_property_name(buf, sizeof(buf), info[i].pi_id); + switch (info[i].pi_type) { + case CDF_NULL: + break; + case CDF_SIGNED16: + if (NOTMIME(ms) && file_printf(ms, ", %s: %hd", buf, + info[i].pi_s16) == -1) + return -1; + break; + case CDF_SIGNED32: + if (NOTMIME(ms) && file_printf(ms, ", %s: %d", buf, + info[i].pi_s32) == -1) + return -1; + break; + case CDF_UNSIGNED32: + if (NOTMIME(ms) && file_printf(ms, ", %s: %u", buf, + info[i].pi_u32) == -1) + return -1; + break; + case CDF_LENGTH32_STRING: + case CDF_LENGTH32_WSTRING: + len = info[i].pi_str.s_len; + if (len > 1) { + char vbuf[1024]; + size_t j, k = 1; - if (info[i].pi_type == CDF_LENGTH32_WSTRING) - k++; - s = info[i].pi_str.s_buf; - for (j = 0; j < sizeof(vbuf) && len--; - j++, s += k) { - if (*s == '\0') - break; - if (isprint((unsigned char)*s)) - vbuf[j] = *s; - } - if (j == sizeof(vbuf)) - --j; - vbuf[j] = '\0'; - if (NOTMIME(ms)) { - if (vbuf[0]) { - if (file_printf(ms, ", %s: %s", - buf, vbuf) == -1) - return -1; - } - } else if (info[i].pi_id == - CDF_PROPERTY_NAME_OF_APPLICATION) { - if (strstr(vbuf, "Word")) - str = "msword"; - else if (strstr(vbuf, "Excel")) - str = "vnd.ms-excel"; - else if (strstr(vbuf, "Powerpoint")) - str = "vnd.ms-powerpoint"; - else if (strstr(vbuf, - "Crystal Reports")) - str = "x-rpt"; - } - } - break; - case CDF_FILETIME: - tp = info[i].pi_tp; - if (tp != 0) { - if (tp < 1000000000000000LL) { - char tbuf[64]; - cdf_print_elapsed_time(tbuf, - sizeof(tbuf), tp); - if (NOTMIME(ms) && file_printf(ms, - ", %s: %s", buf, tbuf) == -1) - return -1; - } else { - char *c, *ec; - cdf_timestamp_to_timespec(&ts, tp); - c = ctime(&ts.tv_sec); - if ((ec = strchr(c, '\n')) != NULL) - *ec = '\0'; + if (info[i].pi_type == CDF_LENGTH32_WSTRING) + k++; + s = info[i].pi_str.s_buf; + for (j = 0; j < sizeof(vbuf) && len--; + j++, s += k) { + if (*s == '\0') + break; + if (isprint((unsigned char)*s)) + vbuf[j] = *s; + } + if (j == sizeof(vbuf)) + --j; + vbuf[j] = '\0'; + if (NOTMIME(ms)) { + if (vbuf[0]) { + if (file_printf(ms, ", %s: %s", + buf, vbuf) == -1) + return -1; + } + } else if (info[i].pi_id == + CDF_PROPERTY_NAME_OF_APPLICATION) { + if (strstr(vbuf, "Word")) + str = "msword"; + else if (strstr(vbuf, "Excel")) + str = "vnd.ms-excel"; + else if (strstr(vbuf, "Powerpoint")) + str = "vnd.ms-powerpoint"; + else if (strstr(vbuf, + "Crystal Reports")) + str = "x-rpt"; + } + } + break; + case CDF_FILETIME: + tp = info[i].pi_tp; + if (tp != 0) { + if (tp < 1000000000000000LL) { + char tbuf[64]; + cdf_print_elapsed_time(tbuf, + sizeof(tbuf), tp); + if (NOTMIME(ms) && file_printf(ms, + ", %s: %s", buf, tbuf) == -1) + return -1; + } else { + char *c, *ec; + cdf_timestamp_to_timespec(&ts, tp); + c = ctime(&ts.tv_sec); + if ((ec = strchr(c, '\n')) != NULL) + *ec = '\0'; - if (NOTMIME(ms) && file_printf(ms, - ", %s: %s", buf, c) == -1) - return -1; - } - } - break; - case CDF_CLIPBOARD: - break; - default: - return -1; - } - } - if (!NOTMIME(ms)) { - if (file_printf(ms, "application/%s", str) == -1) - return -1; - } - return 1; + if (NOTMIME(ms) && file_printf(ms, + ", %s: %s", buf, c) == -1) + return -1; + } + } + break; + case CDF_CLIPBOARD: + break; + default: + return -1; + } + } + if (!NOTMIME(ms)) { + if (file_printf(ms, "application/%s", str) == -1) + return -1; + } + return 1; } private int cdf_file_summary_info(struct magic_set *ms, const cdf_stream_t *sst) { - cdf_summary_info_header_t si; - cdf_property_info_t *info; - size_t count; - int m; + cdf_summary_info_header_t si; + cdf_property_info_t *info; + size_t count; + int m; - if (cdf_unpack_summary_info(sst, &si, &info, &count) == -1) - return -1; + if (cdf_unpack_summary_info(sst, &si, &info, &count) == -1) + return -1; - if (NOTMIME(ms)) { - if (file_printf(ms, "CDF V2 Document") == -1) - return -1; + if (NOTMIME(ms)) { + if (file_printf(ms, "Composite Document File V2 Document") == -1) + return -1; - if (file_printf(ms, ", %s Endian", - si.si_byte_order == 0xfffe ? "Little" : "Big") == -1) - return -1; - switch (si.si_os) { - case 2: - if (file_printf(ms, ", Os: Windows, Version %d.%d", - si.si_os_version & 0xff, - (uint32_t)si.si_os_version >> 8) == -1) - return -1; - break; - case 1: - if (file_printf(ms, ", Os: MacOS, Version %d.%d", - (uint32_t)si.si_os_version >> 8, - si.si_os_version & 0xff) == -1) - return -1; - break; - default: - if (file_printf(ms, ", Os %d, Version: %d.%d", si.si_os, - si.si_os_version & 0xff, - (uint32_t)si.si_os_version >> 8) == -1) - return -1; - break; - } - } + if (file_printf(ms, ", %s Endian", + si.si_byte_order == 0xfffe ? "Little" : "Big") == -1) + return -1; + switch (si.si_os) { + case 2: + if (file_printf(ms, ", Os: Windows, Version %d.%d", + si.si_os_version & 0xff, + (uint32_t)si.si_os_version >> 8) == -1) + return -1; + break; + case 1: + if (file_printf(ms, ", Os: MacOS, Version %d.%d", + (uint32_t)si.si_os_version >> 8, + si.si_os_version & 0xff) == -1) + return -1; + break; + default: + if (file_printf(ms, ", Os %d, Version: %d.%d", si.si_os, + si.si_os_version & 0xff, + (uint32_t)si.si_os_version >> 8) == -1) + return -1; + break; + } + } - m = cdf_file_property_info(ms, info, count); - free(info); + m = cdf_file_property_info(ms, info, count); + free(info); - return m; + return m; } protected int file_trycdf(struct magic_set *ms, int fd, const unsigned char *buf, size_t nbytes) { - cdf_info_t info; - cdf_header_t h; - cdf_sat_t sat, ssat; - cdf_stream_t sst, scn; - cdf_dir_t dir; - int i; - const char *expn = ""; - const char *corrupt = "corrupt: "; + cdf_info_t info; + cdf_header_t h; + cdf_sat_t sat, ssat; + cdf_stream_t sst, scn; + cdf_dir_t dir; + int i; + const char *expn = ""; + const char *corrupt = "corrupt: "; - info.i_fd = fd; - info.i_buf = buf; - info.i_len = nbytes; - if (ms->flags & MAGIC_APPLE) - return 0; - if (cdf_read_header(&info, &h) == -1) - return 0; + info.i_fd = fd; + info.i_buf = buf; + info.i_len = nbytes; + if (ms->flags & MAGIC_APPLE) + return 0; + if (cdf_read_header(&info, &h) == -1) + return 0; #ifdef CDF_DEBUG - cdf_dump_header(&h); + cdf_dump_header(&h); #endif - if ((i = cdf_read_sat(&info, &h, &sat)) == -1) { - expn = "Can't read SAT"; - goto out0; - } + if ((i = cdf_read_sat(&info, &h, &sat)) == -1) { + expn = "Can't read SAT"; + goto out0; + } #ifdef CDF_DEBUG - cdf_dump_sat("SAT", &sat, CDF_SEC_SIZE(&h)); + cdf_dump_sat("SAT", &sat, CDF_SEC_SIZE(&h)); #endif - if ((i = cdf_read_ssat(&info, &h, &sat, &ssat)) == -1) { - expn = "Can't read SSAT"; - goto out1; - } + if ((i = cdf_read_ssat(&info, &h, &sat, &ssat)) == -1) { + expn = "Can't read SSAT"; + goto out1; + } #ifdef CDF_DEBUG - cdf_dump_sat("SSAT", &ssat, CDF_SHORT_SEC_SIZE(&h)); + cdf_dump_sat("SSAT", &ssat, CDF_SHORT_SEC_SIZE(&h)); #endif - if ((i = cdf_read_dir(&info, &h, &sat, &dir)) == -1) { - expn = "Can't read directory"; - goto out2; - } + if ((i = cdf_read_dir(&info, &h, &sat, &dir)) == -1) { + expn = "Can't read directory"; + goto out2; + } - if ((i = cdf_read_short_stream(&info, &h, &sat, &dir, &sst)) == -1) { - expn = "Cannot read short stream"; - goto out3; - } + if ((i = cdf_read_short_stream(&info, &h, &sat, &dir, &sst)) == -1) { + expn = "Cannot read short stream"; + goto out3; + } #ifdef CDF_DEBUG - cdf_dump_dir(&info, &h, &sat, &ssat, &sst, &dir); + cdf_dump_dir(&info, &h, &sat, &ssat, &sst, &dir); #endif - if ((i = cdf_read_summary_info(&info, &h, &sat, &ssat, &sst, &dir, - &scn)) == -1) { - if (errno == ESRCH) { - corrupt = expn; - expn = "No summary info"; - } else { - expn = "Cannot read summary info"; - } - goto out4; - } + if ((i = cdf_read_summary_info(&info, &h, &sat, &ssat, &sst, &dir, + &scn)) == -1) { + if (errno == ESRCH) { + corrupt = expn; + expn = "No summary info"; + } else { + expn = "Cannot read summary info"; + } + goto out4; + } #ifdef CDF_DEBUG - cdf_dump_summary_info(&h, &scn); + cdf_dump_summary_info(&h, &scn); #endif - if ((i = cdf_file_summary_info(ms, &scn)) == -1) - expn = "Can't expand summary_info"; - free(scn.sst_tab); + if ((i = cdf_file_summary_info(ms, &scn)) == -1) + expn = "Can't expand summary_info"; + free(scn.sst_tab); out4: - free(sst.sst_tab); + free(sst.sst_tab); out3: - free(dir.dir_tab); + free(dir.dir_tab); out2: - free(ssat.sat_tab); + free(ssat.sat_tab); out1: - free(sat.sat_tab); + free(sat.sat_tab); out0: - if (i != 1) { - if (file_printf(ms, "CDF V2 Document") == -1) - return -1; - if (*expn) - if (file_printf(ms, ", %s%s", corrupt, expn) == -1) - return -1; - i = 1; - } - return i; + if (i != 1) { + if (file_printf(ms, "Composite Document File V2 Document") == -1) + return -1; + if (*expn) + if (file_printf(ms, ", %s%s", corrupt, expn) == -1) + return -1; + i = 1; + } + return i; }