cdf.c revision 234250
1191739Sobrien/*- 2191739Sobrien * Copyright (c) 2008 Christos Zoulas 3191739Sobrien * All rights reserved. 4191739Sobrien * 5191739Sobrien * Redistribution and use in source and binary forms, with or without 6191739Sobrien * modification, are permitted provided that the following conditions 7191739Sobrien * are met: 8191739Sobrien * 1. Redistributions of source code must retain the above copyright 9191739Sobrien * notice, this list of conditions and the following disclaimer. 10191739Sobrien * 2. Redistributions in binary form must reproduce the above copyright 11191739Sobrien * notice, this list of conditions and the following disclaimer in the 12191739Sobrien * documentation and/or other materials provided with the distribution. 13191739Sobrien * 14191739Sobrien * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 15191739Sobrien * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 16191739Sobrien * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17191739Sobrien * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 18191739Sobrien * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19191739Sobrien * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20191739Sobrien * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21191739Sobrien * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22191739Sobrien * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23191739Sobrien * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24191739Sobrien * POSSIBILITY OF SUCH DAMAGE. 25191739Sobrien */ 26191739Sobrien/* 27226048Sobrien * Parse Composite Document Files, the format used in Microsoft Office 28226048Sobrien * document files before they switched to zipped XML. 29191739Sobrien * Info from: http://sc.openoffice.org/compdocfileformat.pdf 30226048Sobrien * 31226048Sobrien * N.B. This is the "Composite Document File" format, and not the 32226048Sobrien * "Compound Document Format", nor the "Channel Definition Format". 33191739Sobrien */ 34191739Sobrien 35191739Sobrien#include "file.h" 36191739Sobrien 37191739Sobrien#ifndef lint 38234250SobrienFILE_RCSID("@(#)$File: cdf.c,v 1.50 2012/02/20 22:35:29 christos Exp $") 39191739Sobrien#endif 40191739Sobrien 41191739Sobrien#include <assert.h> 42191739Sobrien#ifdef CDF_DEBUG 43191739Sobrien#include <err.h> 44191739Sobrien#endif 45191739Sobrien#include <stdlib.h> 46191739Sobrien#include <unistd.h> 47191739Sobrien#include <string.h> 48191739Sobrien#include <time.h> 49191739Sobrien#include <ctype.h> 50226048Sobrien#ifdef HAVE_LIMITS_H 51226048Sobrien#include <limits.h> 52226048Sobrien#endif 53191739Sobrien 54191739Sobrien#ifndef EFTYPE 55191739Sobrien#define EFTYPE EINVAL 56191739Sobrien#endif 57191739Sobrien 58191739Sobrien#include "cdf.h" 59191739Sobrien 60191739Sobrien#ifdef CDF_DEBUG 61192348Sdelphij#define DPRINTF(a) printf a, fflush(stdout) 62191739Sobrien#else 63191739Sobrien#define DPRINTF(a) 64191739Sobrien#endif 65191739Sobrien 66191739Sobrienstatic union { 67191739Sobrien char s[4]; 68191739Sobrien uint32_t u; 69191739Sobrien} cdf_bo; 70191739Sobrien 71191739Sobrien#define NEED_SWAP (cdf_bo.u == (uint32_t)0x01020304) 72191739Sobrien 73226048Sobrien#define CDF_TOLE8(x) ((uint64_t)(NEED_SWAP ? _cdf_tole8(x) : (uint64_t)(x))) 74226048Sobrien#define CDF_TOLE4(x) ((uint32_t)(NEED_SWAP ? _cdf_tole4(x) : (uint32_t)(x))) 75226048Sobrien#define CDF_TOLE2(x) ((uint16_t)(NEED_SWAP ? _cdf_tole2(x) : (uint16_t)(x))) 76226048Sobrien#define CDF_GETUINT32(x, y) cdf_getuint32(x, y) 77191739Sobrien 78234250Sobrien 79191739Sobrien/* 80191739Sobrien * swap a short 81191739Sobrien */ 82226048Sobrienstatic uint16_t 83226048Sobrien_cdf_tole2(uint16_t sv) 84191739Sobrien{ 85191739Sobrien uint16_t rv; 86226048Sobrien uint8_t *s = (uint8_t *)(void *)&sv; 87226048Sobrien uint8_t *d = (uint8_t *)(void *)&rv; 88191739Sobrien d[0] = s[1]; 89191739Sobrien d[1] = s[0]; 90191739Sobrien return rv; 91191739Sobrien} 92191739Sobrien 93191739Sobrien/* 94191739Sobrien * swap an int 95191739Sobrien */ 96226048Sobrienstatic uint32_t 97226048Sobrien_cdf_tole4(uint32_t sv) 98191739Sobrien{ 99191739Sobrien uint32_t rv; 100226048Sobrien uint8_t *s = (uint8_t *)(void *)&sv; 101226048Sobrien uint8_t *d = (uint8_t *)(void *)&rv; 102191739Sobrien d[0] = s[3]; 103191739Sobrien d[1] = s[2]; 104191739Sobrien d[2] = s[1]; 105191739Sobrien d[3] = s[0]; 106191739Sobrien return rv; 107191739Sobrien} 108191739Sobrien 109191739Sobrien/* 110191739Sobrien * swap a quad 111191739Sobrien */ 112226048Sobrienstatic uint64_t 113226048Sobrien_cdf_tole8(uint64_t sv) 114191739Sobrien{ 115191739Sobrien uint64_t rv; 116226048Sobrien uint8_t *s = (uint8_t *)(void *)&sv; 117226048Sobrien uint8_t *d = (uint8_t *)(void *)&rv; 118191739Sobrien d[0] = s[7]; 119191739Sobrien d[1] = s[6]; 120191739Sobrien d[2] = s[5]; 121191739Sobrien d[3] = s[4]; 122191739Sobrien d[4] = s[3]; 123191739Sobrien d[5] = s[2]; 124191739Sobrien d[6] = s[1]; 125191739Sobrien d[7] = s[0]; 126191739Sobrien return rv; 127191739Sobrien} 128191739Sobrien 129226048Sobrien/* 130226048Sobrien * grab a uint32_t from a possibly unaligned address, and return it in 131226048Sobrien * the native host order. 132226048Sobrien */ 133226048Sobrienstatic uint32_t 134226048Sobriencdf_getuint32(const uint8_t *p, size_t offs) 135226048Sobrien{ 136226048Sobrien uint32_t rv; 137226048Sobrien (void)memcpy(&rv, p + offs * sizeof(uint32_t), sizeof(rv)); 138226048Sobrien return CDF_TOLE4(rv); 139226048Sobrien} 140226048Sobrien 141191739Sobrien#define CDF_UNPACK(a) \ 142191739Sobrien (void)memcpy(&(a), &buf[len], sizeof(a)), len += sizeof(a) 143191739Sobrien#define CDF_UNPACKA(a) \ 144191739Sobrien (void)memcpy((a), &buf[len], sizeof(a)), len += sizeof(a) 145191739Sobrien 146226048Sobrienuint16_t 147226048Sobriencdf_tole2(uint16_t sv) 148226048Sobrien{ 149226048Sobrien return CDF_TOLE2(sv); 150226048Sobrien} 151226048Sobrien 152226048Sobrienuint32_t 153226048Sobriencdf_tole4(uint32_t sv) 154226048Sobrien{ 155226048Sobrien return CDF_TOLE4(sv); 156226048Sobrien} 157226048Sobrien 158226048Sobrienuint64_t 159226048Sobriencdf_tole8(uint64_t sv) 160226048Sobrien{ 161226048Sobrien return CDF_TOLE8(sv); 162226048Sobrien} 163226048Sobrien 164191739Sobrienvoid 165191739Sobriencdf_swap_header(cdf_header_t *h) 166191739Sobrien{ 167191739Sobrien size_t i; 168191739Sobrien 169191739Sobrien h->h_magic = CDF_TOLE8(h->h_magic); 170191739Sobrien h->h_uuid[0] = CDF_TOLE8(h->h_uuid[0]); 171191739Sobrien h->h_uuid[1] = CDF_TOLE8(h->h_uuid[1]); 172191739Sobrien h->h_revision = CDF_TOLE2(h->h_revision); 173191739Sobrien h->h_version = CDF_TOLE2(h->h_version); 174191739Sobrien h->h_byte_order = CDF_TOLE2(h->h_byte_order); 175191739Sobrien h->h_sec_size_p2 = CDF_TOLE2(h->h_sec_size_p2); 176191739Sobrien h->h_short_sec_size_p2 = CDF_TOLE2(h->h_short_sec_size_p2); 177191739Sobrien h->h_num_sectors_in_sat = CDF_TOLE4(h->h_num_sectors_in_sat); 178191739Sobrien h->h_secid_first_directory = CDF_TOLE4(h->h_secid_first_directory); 179191739Sobrien h->h_min_size_standard_stream = 180191739Sobrien CDF_TOLE4(h->h_min_size_standard_stream); 181191739Sobrien h->h_secid_first_sector_in_short_sat = 182226048Sobrien CDF_TOLE4((uint32_t)h->h_secid_first_sector_in_short_sat); 183191739Sobrien h->h_num_sectors_in_short_sat = 184191739Sobrien CDF_TOLE4(h->h_num_sectors_in_short_sat); 185191739Sobrien h->h_secid_first_sector_in_master_sat = 186226048Sobrien CDF_TOLE4((uint32_t)h->h_secid_first_sector_in_master_sat); 187191739Sobrien h->h_num_sectors_in_master_sat = 188191739Sobrien CDF_TOLE4(h->h_num_sectors_in_master_sat); 189191739Sobrien for (i = 0; i < __arraycount(h->h_master_sat); i++) 190226048Sobrien h->h_master_sat[i] = CDF_TOLE4((uint32_t)h->h_master_sat[i]); 191191739Sobrien} 192191739Sobrien 193191739Sobrienvoid 194191739Sobriencdf_unpack_header(cdf_header_t *h, char *buf) 195191739Sobrien{ 196191739Sobrien size_t i; 197191739Sobrien size_t len = 0; 198191739Sobrien 199191739Sobrien CDF_UNPACK(h->h_magic); 200191739Sobrien CDF_UNPACKA(h->h_uuid); 201191739Sobrien CDF_UNPACK(h->h_revision); 202191739Sobrien CDF_UNPACK(h->h_version); 203191739Sobrien CDF_UNPACK(h->h_byte_order); 204191739Sobrien CDF_UNPACK(h->h_sec_size_p2); 205191739Sobrien CDF_UNPACK(h->h_short_sec_size_p2); 206191739Sobrien CDF_UNPACKA(h->h_unused0); 207191739Sobrien CDF_UNPACK(h->h_num_sectors_in_sat); 208191739Sobrien CDF_UNPACK(h->h_secid_first_directory); 209191739Sobrien CDF_UNPACKA(h->h_unused1); 210191739Sobrien CDF_UNPACK(h->h_min_size_standard_stream); 211191739Sobrien CDF_UNPACK(h->h_secid_first_sector_in_short_sat); 212191739Sobrien CDF_UNPACK(h->h_num_sectors_in_short_sat); 213191739Sobrien CDF_UNPACK(h->h_secid_first_sector_in_master_sat); 214191739Sobrien CDF_UNPACK(h->h_num_sectors_in_master_sat); 215191739Sobrien for (i = 0; i < __arraycount(h->h_master_sat); i++) 216191739Sobrien CDF_UNPACK(h->h_master_sat[i]); 217191739Sobrien} 218191739Sobrien 219191739Sobrienvoid 220191739Sobriencdf_swap_dir(cdf_directory_t *d) 221191739Sobrien{ 222191739Sobrien d->d_namelen = CDF_TOLE2(d->d_namelen); 223226048Sobrien d->d_left_child = CDF_TOLE4((uint32_t)d->d_left_child); 224226048Sobrien d->d_right_child = CDF_TOLE4((uint32_t)d->d_right_child); 225226048Sobrien d->d_storage = CDF_TOLE4((uint32_t)d->d_storage); 226191739Sobrien d->d_storage_uuid[0] = CDF_TOLE8(d->d_storage_uuid[0]); 227191739Sobrien d->d_storage_uuid[1] = CDF_TOLE8(d->d_storage_uuid[1]); 228191739Sobrien d->d_flags = CDF_TOLE4(d->d_flags); 229226048Sobrien d->d_created = CDF_TOLE8((uint64_t)d->d_created); 230226048Sobrien d->d_modified = CDF_TOLE8((uint64_t)d->d_modified); 231226048Sobrien d->d_stream_first_sector = CDF_TOLE4((uint32_t)d->d_stream_first_sector); 232191739Sobrien d->d_size = CDF_TOLE4(d->d_size); 233191739Sobrien} 234191739Sobrien 235191739Sobrienvoid 236191739Sobriencdf_swap_class(cdf_classid_t *d) 237191739Sobrien{ 238191739Sobrien d->cl_dword = CDF_TOLE4(d->cl_dword); 239191739Sobrien d->cl_word[0] = CDF_TOLE2(d->cl_word[0]); 240191739Sobrien d->cl_word[1] = CDF_TOLE2(d->cl_word[1]); 241191739Sobrien} 242191739Sobrien 243191739Sobrienvoid 244191739Sobriencdf_unpack_dir(cdf_directory_t *d, char *buf) 245191739Sobrien{ 246191739Sobrien size_t len = 0; 247191739Sobrien 248191739Sobrien CDF_UNPACKA(d->d_name); 249191739Sobrien CDF_UNPACK(d->d_namelen); 250191739Sobrien CDF_UNPACK(d->d_type); 251191739Sobrien CDF_UNPACK(d->d_color); 252191739Sobrien CDF_UNPACK(d->d_left_child); 253191739Sobrien CDF_UNPACK(d->d_right_child); 254191739Sobrien CDF_UNPACK(d->d_storage); 255191739Sobrien CDF_UNPACKA(d->d_storage_uuid); 256191739Sobrien CDF_UNPACK(d->d_flags); 257191739Sobrien CDF_UNPACK(d->d_created); 258191739Sobrien CDF_UNPACK(d->d_modified); 259191739Sobrien CDF_UNPACK(d->d_stream_first_sector); 260191739Sobrien CDF_UNPACK(d->d_size); 261191739Sobrien CDF_UNPACK(d->d_unused0); 262191739Sobrien} 263191739Sobrien 264192348Sdelphijstatic int 265226048Sobriencdf_check_stream_offset(const cdf_stream_t *sst, const cdf_header_t *h, 266226048Sobrien const void *p, size_t tail, int line) 267192348Sdelphij{ 268192348Sdelphij const char *b = (const char *)sst->sst_tab; 269192348Sdelphij const char *e = ((const char *)p) + tail; 270226048Sobrien (void)&line; 271226048Sobrien if (e >= b && (size_t)(e - b) < CDF_SEC_SIZE(h) * sst->sst_len) 272192348Sdelphij return 0; 273226048Sobrien DPRINTF(("%d: offset begin %p end %p %" SIZE_T_FORMAT "u" 274226048Sobrien " >= %" SIZE_T_FORMAT "u [%" SIZE_T_FORMAT "u %" 275226048Sobrien SIZE_T_FORMAT "u]\n", line, b, e, (size_t)(e - b), 276226048Sobrien CDF_SEC_SIZE(h) * sst->sst_len, CDF_SEC_SIZE(h), sst->sst_len)); 277192348Sdelphij errno = EFTYPE; 278192348Sdelphij return -1; 279192348Sdelphij} 280192348Sdelphij 281192348Sdelphijstatic ssize_t 282192348Sdelphijcdf_read(const cdf_info_t *info, off_t off, void *buf, size_t len) 283192348Sdelphij{ 284192348Sdelphij size_t siz = (size_t)off + len; 285192348Sdelphij 286192348Sdelphij if ((off_t)(off + len) != (off_t)siz) { 287192348Sdelphij errno = EINVAL; 288192348Sdelphij return -1; 289192348Sdelphij } 290192348Sdelphij 291192348Sdelphij if (info->i_buf != NULL && info->i_len >= siz) { 292192348Sdelphij (void)memcpy(buf, &info->i_buf[off], len); 293192348Sdelphij return (ssize_t)len; 294192348Sdelphij } 295192348Sdelphij 296192348Sdelphij if (info->i_fd == -1) 297192348Sdelphij return -1; 298192348Sdelphij 299192348Sdelphij if (lseek(info->i_fd, off, SEEK_SET) == (off_t)-1) 300192348Sdelphij return -1; 301192348Sdelphij 302192348Sdelphij if (read(info->i_fd, buf, len) != (ssize_t)len) 303192348Sdelphij return -1; 304192348Sdelphij 305192348Sdelphij return (ssize_t)len; 306192348Sdelphij} 307192348Sdelphij 308191739Sobrienint 309192348Sdelphijcdf_read_header(const cdf_info_t *info, cdf_header_t *h) 310191739Sobrien{ 311192348Sdelphij char buf[512]; 312192348Sdelphij 313191739Sobrien (void)memcpy(cdf_bo.s, "\01\02\03\04", 4); 314192348Sdelphij if (cdf_read(info, (off_t)0, buf, sizeof(buf)) == -1) 315191739Sobrien return -1; 316191739Sobrien cdf_unpack_header(h, buf); 317191739Sobrien cdf_swap_header(h); 318191739Sobrien if (h->h_magic != CDF_MAGIC) { 319226048Sobrien DPRINTF(("Bad magic 0x%" INT64_T_FORMAT "x != 0x%" 320226048Sobrien INT64_T_FORMAT "x\n", 321192348Sdelphij (unsigned long long)h->h_magic, 322192348Sdelphij (unsigned long long)CDF_MAGIC)); 323192348Sdelphij goto out; 324191739Sobrien } 325192348Sdelphij if (h->h_sec_size_p2 > 20) { 326192348Sdelphij DPRINTF(("Bad sector size 0x%u\n", h->h_sec_size_p2)); 327192348Sdelphij goto out; 328192348Sdelphij } 329192348Sdelphij if (h->h_short_sec_size_p2 > 20) { 330192348Sdelphij DPRINTF(("Bad short sector size 0x%u\n", 331192348Sdelphij h->h_short_sec_size_p2)); 332192348Sdelphij goto out; 333192348Sdelphij } 334191739Sobrien return 0; 335192348Sdelphijout: 336192348Sdelphij errno = EFTYPE; 337192348Sdelphij return -1; 338191739Sobrien} 339191739Sobrien 340191739Sobrien 341191739Sobrienssize_t 342192348Sdelphijcdf_read_sector(const cdf_info_t *info, void *buf, size_t offs, size_t len, 343191739Sobrien const cdf_header_t *h, cdf_secid_t id) 344191739Sobrien{ 345234250Sobrien size_t ss = CDF_SEC_SIZE(h); 346234250Sobrien size_t pos = CDF_SEC_POS(h, id); 347234250Sobrien assert(ss == len); 348234250Sobrien return cdf_read(info, (off_t)pos, ((char *)buf) + offs, len); 349191739Sobrien} 350191739Sobrien 351191739Sobrienssize_t 352191739Sobriencdf_read_short_sector(const cdf_stream_t *sst, void *buf, size_t offs, 353191739Sobrien size_t len, const cdf_header_t *h, cdf_secid_t id) 354191739Sobrien{ 355234250Sobrien size_t ss = CDF_SHORT_SEC_SIZE(h); 356234250Sobrien size_t pos = CDF_SHORT_SEC_POS(h, id); 357234250Sobrien assert(ss == len); 358234250Sobrien if (pos > CDF_SEC_SIZE(h) * sst->sst_len) { 359234250Sobrien DPRINTF(("Out of bounds read %" SIZE_T_FORMAT "u > %" 360234250Sobrien SIZE_T_FORMAT "u\n", 361234250Sobrien pos, CDF_SEC_SIZE(h) * sst->sst_len)); 362234250Sobrien return -1; 363234250Sobrien } 364191739Sobrien (void)memcpy(((char *)buf) + offs, 365234250Sobrien ((const char *)sst->sst_tab) + pos, len); 366191739Sobrien return len; 367191739Sobrien} 368191739Sobrien 369191739Sobrien/* 370191739Sobrien * Read the sector allocation table. 371191739Sobrien */ 372191739Sobrienint 373192348Sdelphijcdf_read_sat(const cdf_info_t *info, cdf_header_t *h, cdf_sat_t *sat) 374191739Sobrien{ 375191739Sobrien size_t i, j, k; 376191739Sobrien size_t ss = CDF_SEC_SIZE(h); 377192348Sdelphij cdf_secid_t *msa, mid, sec; 378192348Sdelphij size_t nsatpersec = (ss / sizeof(mid)) - 1; 379191739Sobrien 380191739Sobrien for (i = 0; i < __arraycount(h->h_master_sat); i++) 381191739Sobrien if (h->h_master_sat[i] == CDF_SECID_FREE) 382191739Sobrien break; 383191739Sobrien 384192348Sdelphij#define CDF_SEC_LIMIT (UINT32_MAX / (4 * ss)) 385226048Sobrien if ((nsatpersec > 0 && 386226048Sobrien h->h_num_sectors_in_master_sat > CDF_SEC_LIMIT / nsatpersec) || 387192348Sdelphij i > CDF_SEC_LIMIT) { 388226048Sobrien DPRINTF(("Number of sectors in master SAT too big %u %" 389226048Sobrien SIZE_T_FORMAT "u\n", h->h_num_sectors_in_master_sat, i)); 390192348Sdelphij errno = EFTYPE; 391192348Sdelphij return -1; 392192348Sdelphij } 393192348Sdelphij 394192348Sdelphij sat->sat_len = h->h_num_sectors_in_master_sat * nsatpersec + i; 395226048Sobrien DPRINTF(("sat_len = %" SIZE_T_FORMAT "u ss = %" SIZE_T_FORMAT "u\n", 396226048Sobrien sat->sat_len, ss)); 397226048Sobrien if ((sat->sat_tab = CAST(cdf_secid_t *, calloc(sat->sat_len, ss))) 398226048Sobrien == NULL) 399191739Sobrien return -1; 400191739Sobrien 401191739Sobrien for (i = 0; i < __arraycount(h->h_master_sat); i++) { 402191739Sobrien if (h->h_master_sat[i] < 0) 403191739Sobrien break; 404192348Sdelphij if (cdf_read_sector(info, sat->sat_tab, ss * i, ss, h, 405191739Sobrien h->h_master_sat[i]) != (ssize_t)ss) { 406191739Sobrien DPRINTF(("Reading sector %d", h->h_master_sat[i])); 407191739Sobrien goto out1; 408191739Sobrien } 409191739Sobrien } 410191739Sobrien 411226048Sobrien if ((msa = CAST(cdf_secid_t *, calloc(1, ss))) == NULL) 412191739Sobrien goto out1; 413191739Sobrien 414191739Sobrien mid = h->h_secid_first_sector_in_master_sat; 415191739Sobrien for (j = 0; j < h->h_num_sectors_in_master_sat; j++) { 416192348Sdelphij if (mid < 0) 417192348Sdelphij goto out; 418191739Sobrien if (j >= CDF_LOOP_LIMIT) { 419191739Sobrien DPRINTF(("Reading master sector loop limit")); 420191739Sobrien errno = EFTYPE; 421191739Sobrien goto out2; 422191739Sobrien } 423192348Sdelphij if (cdf_read_sector(info, msa, 0, ss, h, mid) != (ssize_t)ss) { 424191739Sobrien DPRINTF(("Reading master sector %d", mid)); 425191739Sobrien goto out2; 426191739Sobrien } 427192348Sdelphij for (k = 0; k < nsatpersec; k++, i++) { 428226048Sobrien sec = CDF_TOLE4((uint32_t)msa[k]); 429192348Sdelphij if (sec < 0) 430192348Sdelphij goto out; 431192348Sdelphij if (i >= sat->sat_len) { 432234250Sobrien DPRINTF(("Out of bounds reading MSA %" SIZE_T_FORMAT 433234250Sobrien "u >= %" SIZE_T_FORMAT "u", i, sat->sat_len)); 434192348Sdelphij errno = EFTYPE; 435192348Sdelphij goto out2; 436192348Sdelphij } 437192348Sdelphij if (cdf_read_sector(info, sat->sat_tab, ss * i, ss, h, 438192348Sdelphij sec) != (ssize_t)ss) { 439191739Sobrien DPRINTF(("Reading sector %d", 440191739Sobrien CDF_TOLE4(msa[k]))); 441191739Sobrien goto out2; 442191739Sobrien } 443192348Sdelphij } 444226048Sobrien mid = CDF_TOLE4((uint32_t)msa[nsatpersec]); 445191739Sobrien } 446192348Sdelphijout: 447192348Sdelphij sat->sat_len = i; 448191739Sobrien free(msa); 449191739Sobrien return 0; 450191739Sobrienout2: 451191739Sobrien free(msa); 452191739Sobrienout1: 453191739Sobrien free(sat->sat_tab); 454191739Sobrien return -1; 455191739Sobrien} 456191739Sobrien 457191739Sobriensize_t 458192348Sdelphijcdf_count_chain(const cdf_sat_t *sat, cdf_secid_t sid, size_t size) 459191739Sobrien{ 460192348Sdelphij size_t i, j; 461192348Sdelphij cdf_secid_t maxsector = (cdf_secid_t)(sat->sat_len * size); 462191739Sobrien 463191739Sobrien DPRINTF(("Chain:")); 464191739Sobrien for (j = i = 0; sid >= 0; i++, j++) { 465191739Sobrien DPRINTF((" %d", sid)); 466191739Sobrien if (j >= CDF_LOOP_LIMIT) { 467191739Sobrien DPRINTF(("Counting chain loop limit")); 468191739Sobrien errno = EFTYPE; 469191739Sobrien return (size_t)-1; 470191739Sobrien } 471191739Sobrien if (sid > maxsector) { 472191739Sobrien DPRINTF(("Sector %d > %d\n", sid, maxsector)); 473191739Sobrien errno = EFTYPE; 474191739Sobrien return (size_t)-1; 475191739Sobrien } 476226048Sobrien sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]); 477191739Sobrien } 478191739Sobrien DPRINTF(("\n")); 479191739Sobrien return i; 480191739Sobrien} 481191739Sobrien 482191739Sobrienint 483192348Sdelphijcdf_read_long_sector_chain(const cdf_info_t *info, const cdf_header_t *h, 484192348Sdelphij const cdf_sat_t *sat, cdf_secid_t sid, size_t len, cdf_stream_t *scn) 485191739Sobrien{ 486191739Sobrien size_t ss = CDF_SEC_SIZE(h), i, j; 487191739Sobrien ssize_t nr; 488192348Sdelphij scn->sst_len = cdf_count_chain(sat, sid, ss); 489191739Sobrien scn->sst_dirlen = len; 490191739Sobrien 491191739Sobrien if (scn->sst_len == (size_t)-1) 492191739Sobrien return -1; 493191739Sobrien 494191739Sobrien scn->sst_tab = calloc(scn->sst_len, ss); 495191739Sobrien if (scn->sst_tab == NULL) 496191739Sobrien return -1; 497191739Sobrien 498191739Sobrien for (j = i = 0; sid >= 0; i++, j++) { 499192348Sdelphij if (j >= CDF_LOOP_LIMIT) { 500192348Sdelphij DPRINTF(("Read long sector chain loop limit")); 501192348Sdelphij errno = EFTYPE; 502192348Sdelphij goto out; 503192348Sdelphij } 504192348Sdelphij if (i >= scn->sst_len) { 505192348Sdelphij DPRINTF(("Out of bounds reading long sector chain " 506234250Sobrien "%" SIZE_T_FORMAT "u > %" SIZE_T_FORMAT "u\n", i, 507234250Sobrien scn->sst_len)); 508192348Sdelphij errno = EFTYPE; 509192348Sdelphij goto out; 510192348Sdelphij } 511192348Sdelphij if ((nr = cdf_read_sector(info, scn->sst_tab, i * ss, ss, h, 512191739Sobrien sid)) != (ssize_t)ss) { 513191739Sobrien if (i == scn->sst_len - 1 && nr > 0) { 514191739Sobrien /* Last sector might be truncated */ 515191739Sobrien return 0; 516191739Sobrien } 517191739Sobrien DPRINTF(("Reading long sector chain %d", sid)); 518191739Sobrien goto out; 519191739Sobrien } 520226048Sobrien sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]); 521191739Sobrien } 522191739Sobrien return 0; 523191739Sobrienout: 524191739Sobrien free(scn->sst_tab); 525192348Sdelphij return -1; 526191739Sobrien} 527191739Sobrien 528191739Sobrienint 529191739Sobriencdf_read_short_sector_chain(const cdf_header_t *h, 530191739Sobrien const cdf_sat_t *ssat, const cdf_stream_t *sst, 531191739Sobrien cdf_secid_t sid, size_t len, cdf_stream_t *scn) 532191739Sobrien{ 533191739Sobrien size_t ss = CDF_SHORT_SEC_SIZE(h), i, j; 534192348Sdelphij scn->sst_len = cdf_count_chain(ssat, sid, CDF_SEC_SIZE(h)); 535191739Sobrien scn->sst_dirlen = len; 536191739Sobrien 537192348Sdelphij if (sst->sst_tab == NULL || scn->sst_len == (size_t)-1) 538191739Sobrien return -1; 539191739Sobrien 540191739Sobrien scn->sst_tab = calloc(scn->sst_len, ss); 541191739Sobrien if (scn->sst_tab == NULL) 542191739Sobrien return -1; 543191739Sobrien 544191739Sobrien for (j = i = 0; sid >= 0; i++, j++) { 545191739Sobrien if (j >= CDF_LOOP_LIMIT) { 546191739Sobrien DPRINTF(("Read short sector chain loop limit")); 547191739Sobrien errno = EFTYPE; 548191739Sobrien goto out; 549191739Sobrien } 550192348Sdelphij if (i >= scn->sst_len) { 551192348Sdelphij DPRINTF(("Out of bounds reading short sector chain " 552234250Sobrien "%" SIZE_T_FORMAT "u > %" SIZE_T_FORMAT "u\n", 553234250Sobrien i, scn->sst_len)); 554192348Sdelphij errno = EFTYPE; 555192348Sdelphij goto out; 556192348Sdelphij } 557191739Sobrien if (cdf_read_short_sector(sst, scn->sst_tab, i * ss, ss, h, 558191739Sobrien sid) != (ssize_t)ss) { 559191739Sobrien DPRINTF(("Reading short sector chain %d", sid)); 560191739Sobrien goto out; 561191739Sobrien } 562226048Sobrien sid = CDF_TOLE4((uint32_t)ssat->sat_tab[sid]); 563191739Sobrien } 564191739Sobrien return 0; 565191739Sobrienout: 566191739Sobrien free(scn->sst_tab); 567192348Sdelphij return -1; 568191739Sobrien} 569191739Sobrien 570191739Sobrienint 571192348Sdelphijcdf_read_sector_chain(const cdf_info_t *info, const cdf_header_t *h, 572192348Sdelphij const cdf_sat_t *sat, const cdf_sat_t *ssat, const cdf_stream_t *sst, 573191739Sobrien cdf_secid_t sid, size_t len, cdf_stream_t *scn) 574191739Sobrien{ 575191739Sobrien 576226048Sobrien if (len < h->h_min_size_standard_stream && sst->sst_tab != NULL) 577191739Sobrien return cdf_read_short_sector_chain(h, ssat, sst, sid, len, 578191739Sobrien scn); 579191739Sobrien else 580192348Sdelphij return cdf_read_long_sector_chain(info, h, sat, sid, len, scn); 581191739Sobrien} 582191739Sobrien 583191739Sobrienint 584192348Sdelphijcdf_read_dir(const cdf_info_t *info, const cdf_header_t *h, 585192348Sdelphij const cdf_sat_t *sat, cdf_dir_t *dir) 586191739Sobrien{ 587191739Sobrien size_t i, j; 588191739Sobrien size_t ss = CDF_SEC_SIZE(h), ns, nd; 589191739Sobrien char *buf; 590191739Sobrien cdf_secid_t sid = h->h_secid_first_directory; 591191739Sobrien 592192348Sdelphij ns = cdf_count_chain(sat, sid, ss); 593191739Sobrien if (ns == (size_t)-1) 594191739Sobrien return -1; 595191739Sobrien 596191739Sobrien nd = ss / CDF_DIRECTORY_SIZE; 597191739Sobrien 598191739Sobrien dir->dir_len = ns * nd; 599226048Sobrien dir->dir_tab = CAST(cdf_directory_t *, 600226048Sobrien calloc(dir->dir_len, sizeof(dir->dir_tab[0]))); 601191739Sobrien if (dir->dir_tab == NULL) 602191739Sobrien return -1; 603191739Sobrien 604226048Sobrien if ((buf = CAST(char *, malloc(ss))) == NULL) { 605191739Sobrien free(dir->dir_tab); 606191739Sobrien return -1; 607191739Sobrien } 608191739Sobrien 609191739Sobrien for (j = i = 0; i < ns; i++, j++) { 610191739Sobrien if (j >= CDF_LOOP_LIMIT) { 611191739Sobrien DPRINTF(("Read dir loop limit")); 612191739Sobrien errno = EFTYPE; 613191739Sobrien goto out; 614191739Sobrien } 615192348Sdelphij if (cdf_read_sector(info, buf, 0, ss, h, sid) != (ssize_t)ss) { 616191739Sobrien DPRINTF(("Reading directory sector %d", sid)); 617191739Sobrien goto out; 618191739Sobrien } 619191739Sobrien for (j = 0; j < nd; j++) { 620191739Sobrien cdf_unpack_dir(&dir->dir_tab[i * nd + j], 621191739Sobrien &buf[j * CDF_DIRECTORY_SIZE]); 622191739Sobrien } 623226048Sobrien sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]); 624191739Sobrien } 625191739Sobrien if (NEED_SWAP) 626191739Sobrien for (i = 0; i < dir->dir_len; i++) 627191739Sobrien cdf_swap_dir(&dir->dir_tab[i]); 628191739Sobrien free(buf); 629191739Sobrien return 0; 630191739Sobrienout: 631191739Sobrien free(dir->dir_tab); 632191739Sobrien free(buf); 633191739Sobrien return -1; 634191739Sobrien} 635191739Sobrien 636191739Sobrien 637191739Sobrienint 638192348Sdelphijcdf_read_ssat(const cdf_info_t *info, const cdf_header_t *h, 639192348Sdelphij const cdf_sat_t *sat, cdf_sat_t *ssat) 640191739Sobrien{ 641191739Sobrien size_t i, j; 642191739Sobrien size_t ss = CDF_SEC_SIZE(h); 643191739Sobrien cdf_secid_t sid = h->h_secid_first_sector_in_short_sat; 644191739Sobrien 645192348Sdelphij ssat->sat_len = cdf_count_chain(sat, sid, CDF_SEC_SIZE(h)); 646191739Sobrien if (ssat->sat_len == (size_t)-1) 647191739Sobrien return -1; 648191739Sobrien 649226048Sobrien ssat->sat_tab = CAST(cdf_secid_t *, calloc(ssat->sat_len, ss)); 650191739Sobrien if (ssat->sat_tab == NULL) 651191739Sobrien return -1; 652191739Sobrien 653191739Sobrien for (j = i = 0; sid >= 0; i++, j++) { 654191739Sobrien if (j >= CDF_LOOP_LIMIT) { 655191739Sobrien DPRINTF(("Read short sat sector loop limit")); 656191739Sobrien errno = EFTYPE; 657191739Sobrien goto out; 658191739Sobrien } 659192348Sdelphij if (i >= ssat->sat_len) { 660192348Sdelphij DPRINTF(("Out of bounds reading short sector chain " 661234250Sobrien "%" SIZE_T_FORMAT "u > %" SIZE_T_FORMAT "u\n", i, 662234250Sobrien ssat->sat_len)); 663192348Sdelphij errno = EFTYPE; 664192348Sdelphij goto out; 665192348Sdelphij } 666192348Sdelphij if (cdf_read_sector(info, ssat->sat_tab, i * ss, ss, h, sid) != 667191739Sobrien (ssize_t)ss) { 668191739Sobrien DPRINTF(("Reading short sat sector %d", sid)); 669191739Sobrien goto out; 670191739Sobrien } 671226048Sobrien sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]); 672191739Sobrien } 673191739Sobrien return 0; 674191739Sobrienout: 675191739Sobrien free(ssat->sat_tab); 676191739Sobrien return -1; 677191739Sobrien} 678191739Sobrien 679191739Sobrienint 680192348Sdelphijcdf_read_short_stream(const cdf_info_t *info, const cdf_header_t *h, 681192348Sdelphij const cdf_sat_t *sat, const cdf_dir_t *dir, cdf_stream_t *scn) 682191739Sobrien{ 683191739Sobrien size_t i; 684191739Sobrien const cdf_directory_t *d; 685191739Sobrien 686191739Sobrien for (i = 0; i < dir->dir_len; i++) 687191739Sobrien if (dir->dir_tab[i].d_type == CDF_DIR_TYPE_ROOT_STORAGE) 688191739Sobrien break; 689191739Sobrien 690192348Sdelphij /* If the it is not there, just fake it; some docs don't have it */ 691192348Sdelphij if (i == dir->dir_len) 692192348Sdelphij goto out; 693191739Sobrien d = &dir->dir_tab[i]; 694191739Sobrien 695191739Sobrien /* If the it is not there, just fake it; some docs don't have it */ 696192348Sdelphij if (d->d_stream_first_sector < 0) 697192348Sdelphij goto out; 698191739Sobrien 699226048Sobrien return cdf_read_long_sector_chain(info, h, sat, 700191739Sobrien d->d_stream_first_sector, d->d_size, scn); 701192348Sdelphijout: 702192348Sdelphij scn->sst_tab = NULL; 703192348Sdelphij scn->sst_len = 0; 704192348Sdelphij scn->sst_dirlen = 0; 705192348Sdelphij return 0; 706191739Sobrien} 707191739Sobrien 708191739Sobrienstatic int 709191739Sobriencdf_namecmp(const char *d, const uint16_t *s, size_t l) 710191739Sobrien{ 711191739Sobrien for (; l--; d++, s++) 712191739Sobrien if (*d != CDF_TOLE2(*s)) 713191739Sobrien return (unsigned char)*d - CDF_TOLE2(*s); 714191739Sobrien return 0; 715191739Sobrien} 716191739Sobrien 717191739Sobrienint 718192348Sdelphijcdf_read_summary_info(const cdf_info_t *info, const cdf_header_t *h, 719191739Sobrien const cdf_sat_t *sat, const cdf_sat_t *ssat, const cdf_stream_t *sst, 720191739Sobrien const cdf_dir_t *dir, cdf_stream_t *scn) 721191739Sobrien{ 722191739Sobrien size_t i; 723191739Sobrien const cdf_directory_t *d; 724191739Sobrien static const char name[] = "\05SummaryInformation"; 725191739Sobrien 726226048Sobrien for (i = dir->dir_len; i > 0; i--) 727226048Sobrien if (dir->dir_tab[i - 1].d_type == CDF_DIR_TYPE_USER_STREAM && 728226048Sobrien cdf_namecmp(name, dir->dir_tab[i - 1].d_name, sizeof(name)) 729191739Sobrien == 0) 730191739Sobrien break; 731191739Sobrien 732226048Sobrien if (i == 0) { 733191739Sobrien DPRINTF(("Cannot find summary information section\n")); 734226048Sobrien errno = ESRCH; 735191739Sobrien return -1; 736191739Sobrien } 737226048Sobrien d = &dir->dir_tab[i - 1]; 738192348Sdelphij return cdf_read_sector_chain(info, h, sat, ssat, sst, 739191739Sobrien d->d_stream_first_sector, d->d_size, scn); 740191739Sobrien} 741191739Sobrien 742191739Sobrienint 743226048Sobriencdf_read_property_info(const cdf_stream_t *sst, const cdf_header_t *h, 744226048Sobrien uint32_t offs, cdf_property_info_t **info, size_t *count, size_t *maxcount) 745191739Sobrien{ 746191739Sobrien const cdf_section_header_t *shp; 747191739Sobrien cdf_section_header_t sh; 748226048Sobrien const uint8_t *p, *q, *e; 749191739Sobrien int16_t s16; 750191739Sobrien int32_t s32; 751191739Sobrien uint32_t u32; 752191739Sobrien int64_t s64; 753191739Sobrien uint64_t u64; 754191739Sobrien cdf_timestamp_t tp; 755226048Sobrien size_t i, o, o4, nelements, j; 756191739Sobrien cdf_property_info_t *inp; 757191739Sobrien 758192348Sdelphij if (offs > UINT32_MAX / 4) { 759192348Sdelphij errno = EFTYPE; 760192348Sdelphij goto out; 761192348Sdelphij } 762226048Sobrien shp = CAST(const cdf_section_header_t *, (const void *) 763226048Sobrien ((const char *)sst->sst_tab + offs)); 764226048Sobrien if (cdf_check_stream_offset(sst, h, shp, sizeof(*shp), __LINE__) == -1) 765192348Sdelphij goto out; 766191739Sobrien sh.sh_len = CDF_TOLE4(shp->sh_len); 767192348Sdelphij#define CDF_SHLEN_LIMIT (UINT32_MAX / 8) 768192348Sdelphij if (sh.sh_len > CDF_SHLEN_LIMIT) { 769192348Sdelphij errno = EFTYPE; 770192348Sdelphij goto out; 771192348Sdelphij } 772191739Sobrien sh.sh_properties = CDF_TOLE4(shp->sh_properties); 773192348Sdelphij#define CDF_PROP_LIMIT (UINT32_MAX / (4 * sizeof(*inp))) 774192348Sdelphij if (sh.sh_properties > CDF_PROP_LIMIT) 775192348Sdelphij goto out; 776192348Sdelphij DPRINTF(("section len: %u properties %u\n", sh.sh_len, 777191739Sobrien sh.sh_properties)); 778191739Sobrien if (*maxcount) { 779192348Sdelphij if (*maxcount > CDF_PROP_LIMIT) 780192348Sdelphij goto out; 781191739Sobrien *maxcount += sh.sh_properties; 782226048Sobrien inp = CAST(cdf_property_info_t *, 783226048Sobrien realloc(*info, *maxcount * sizeof(*inp))); 784191739Sobrien } else { 785191739Sobrien *maxcount = sh.sh_properties; 786226048Sobrien inp = CAST(cdf_property_info_t *, 787226048Sobrien malloc(*maxcount * sizeof(*inp))); 788191739Sobrien } 789191739Sobrien if (inp == NULL) 790191739Sobrien goto out; 791191739Sobrien *info = inp; 792191739Sobrien inp += *count; 793191739Sobrien *count += sh.sh_properties; 794226048Sobrien p = CAST(const uint8_t *, (const void *) 795226048Sobrien ((const char *)(const void *)sst->sst_tab + 796226048Sobrien offs + sizeof(sh))); 797226048Sobrien e = CAST(const uint8_t *, (const void *) 798226048Sobrien (((const char *)(const void *)shp) + sh.sh_len)); 799226048Sobrien if (cdf_check_stream_offset(sst, h, e, 0, __LINE__) == -1) 800192348Sdelphij goto out; 801191739Sobrien for (i = 0; i < sh.sh_properties; i++) { 802234250Sobrien size_t ofs = CDF_GETUINT32(p, (i << 1) + 1); 803226048Sobrien q = (const uint8_t *)(const void *) 804234250Sobrien ((const char *)(const void *)p + ofs 805234250Sobrien - 2 * sizeof(uint32_t)); 806191739Sobrien if (q > e) { 807191739Sobrien DPRINTF(("Ran of the end %p > %p\n", q, e)); 808191739Sobrien goto out; 809191739Sobrien } 810226048Sobrien inp[i].pi_id = CDF_GETUINT32(p, i << 1); 811226048Sobrien inp[i].pi_type = CDF_GETUINT32(q, 0); 812234250Sobrien DPRINTF(("%" SIZE_T_FORMAT "u) id=%x type=%x offs=0x%tx,0x%x\n", 813234250Sobrien i, inp[i].pi_id, inp[i].pi_type, q - p, offs)); 814191739Sobrien if (inp[i].pi_type & CDF_VECTOR) { 815226048Sobrien nelements = CDF_GETUINT32(q, 1); 816191739Sobrien o = 2; 817191739Sobrien } else { 818191739Sobrien nelements = 1; 819191739Sobrien o = 1; 820191739Sobrien } 821226048Sobrien o4 = o * sizeof(uint32_t); 822191739Sobrien if (inp[i].pi_type & (CDF_ARRAY|CDF_BYREF|CDF_RESERVED)) 823191739Sobrien goto unknown; 824191739Sobrien switch (inp[i].pi_type & CDF_TYPEMASK) { 825226048Sobrien case CDF_NULL: 826191739Sobrien case CDF_EMPTY: 827191739Sobrien break; 828191739Sobrien case CDF_SIGNED16: 829191739Sobrien if (inp[i].pi_type & CDF_VECTOR) 830191739Sobrien goto unknown; 831226048Sobrien (void)memcpy(&s16, &q[o4], sizeof(s16)); 832191739Sobrien inp[i].pi_s16 = CDF_TOLE2(s16); 833191739Sobrien break; 834191739Sobrien case CDF_SIGNED32: 835191739Sobrien if (inp[i].pi_type & CDF_VECTOR) 836191739Sobrien goto unknown; 837226048Sobrien (void)memcpy(&s32, &q[o4], sizeof(s32)); 838226048Sobrien inp[i].pi_s32 = CDF_TOLE4((uint32_t)s32); 839191739Sobrien break; 840191739Sobrien case CDF_BOOL: 841191739Sobrien case CDF_UNSIGNED32: 842191739Sobrien if (inp[i].pi_type & CDF_VECTOR) 843191739Sobrien goto unknown; 844226048Sobrien (void)memcpy(&u32, &q[o4], sizeof(u32)); 845191739Sobrien inp[i].pi_u32 = CDF_TOLE4(u32); 846191739Sobrien break; 847191739Sobrien case CDF_SIGNED64: 848191739Sobrien if (inp[i].pi_type & CDF_VECTOR) 849191739Sobrien goto unknown; 850226048Sobrien (void)memcpy(&s64, &q[o4], sizeof(s64)); 851226048Sobrien inp[i].pi_s64 = CDF_TOLE8((uint64_t)s64); 852191739Sobrien break; 853191739Sobrien case CDF_UNSIGNED64: 854191739Sobrien if (inp[i].pi_type & CDF_VECTOR) 855191739Sobrien goto unknown; 856226048Sobrien (void)memcpy(&u64, &q[o4], sizeof(u64)); 857226048Sobrien inp[i].pi_u64 = CDF_TOLE8((uint64_t)u64); 858191739Sobrien break; 859234250Sobrien case CDF_FLOAT: 860234250Sobrien if (inp[i].pi_type & CDF_VECTOR) 861234250Sobrien goto unknown; 862234250Sobrien (void)memcpy(&u32, &q[o4], sizeof(u32)); 863234250Sobrien u32 = CDF_TOLE4(u32); 864234250Sobrien memcpy(&inp[i].pi_f, &u32, sizeof(inp[i].pi_f)); 865234250Sobrien break; 866234250Sobrien case CDF_DOUBLE: 867234250Sobrien if (inp[i].pi_type & CDF_VECTOR) 868234250Sobrien goto unknown; 869234250Sobrien (void)memcpy(&u64, &q[o4], sizeof(u64)); 870234250Sobrien u64 = CDF_TOLE8((uint64_t)u64); 871234250Sobrien memcpy(&inp[i].pi_d, &u64, sizeof(inp[i].pi_d)); 872234250Sobrien break; 873191739Sobrien case CDF_LENGTH32_STRING: 874226048Sobrien case CDF_LENGTH32_WSTRING: 875191739Sobrien if (nelements > 1) { 876191739Sobrien size_t nelem = inp - *info; 877192348Sdelphij if (*maxcount > CDF_PROP_LIMIT 878192348Sdelphij || nelements > CDF_PROP_LIMIT) 879192348Sdelphij goto out; 880191739Sobrien *maxcount += nelements; 881226048Sobrien inp = CAST(cdf_property_info_t *, 882226048Sobrien realloc(*info, *maxcount * sizeof(*inp))); 883191739Sobrien if (inp == NULL) 884191739Sobrien goto out; 885191739Sobrien *info = inp; 886191739Sobrien inp = *info + nelem; 887191739Sobrien } 888234250Sobrien DPRINTF(("nelements = %" SIZE_T_FORMAT "u\n", 889234250Sobrien nelements)); 890191739Sobrien for (j = 0; j < nelements; j++, i++) { 891226048Sobrien uint32_t l = CDF_GETUINT32(q, o); 892191739Sobrien inp[i].pi_str.s_len = l; 893226048Sobrien inp[i].pi_str.s_buf = (const char *) 894226048Sobrien (const void *)(&q[o4 + sizeof(l)]); 895234250Sobrien DPRINTF(("l = %d, r = %" SIZE_T_FORMAT 896234250Sobrien "u, s = %s\n", l, 897191739Sobrien CDF_ROUND(l, sizeof(l)), 898191739Sobrien inp[i].pi_str.s_buf)); 899234250Sobrien if (l & 1) 900234250Sobrien l++; 901234250Sobrien o += l >> 1; 902234250Sobrien if (q + o >= e) 903234250Sobrien goto out; 904226048Sobrien o4 = o * sizeof(uint32_t); 905191739Sobrien } 906191739Sobrien i--; 907191739Sobrien break; 908191739Sobrien case CDF_FILETIME: 909191739Sobrien if (inp[i].pi_type & CDF_VECTOR) 910191739Sobrien goto unknown; 911226048Sobrien (void)memcpy(&tp, &q[o4], sizeof(tp)); 912226048Sobrien inp[i].pi_tp = CDF_TOLE8((uint64_t)tp); 913191739Sobrien break; 914191739Sobrien case CDF_CLIPBOARD: 915191739Sobrien if (inp[i].pi_type & CDF_VECTOR) 916191739Sobrien goto unknown; 917191739Sobrien break; 918191739Sobrien default: 919191739Sobrien unknown: 920191739Sobrien DPRINTF(("Don't know how to deal with %x\n", 921191739Sobrien inp[i].pi_type)); 922234250Sobrien break; 923191739Sobrien } 924191739Sobrien } 925191739Sobrien return 0; 926191739Sobrienout: 927191739Sobrien free(*info); 928191739Sobrien return -1; 929191739Sobrien} 930191739Sobrien 931191739Sobrienint 932226048Sobriencdf_unpack_summary_info(const cdf_stream_t *sst, const cdf_header_t *h, 933226048Sobrien cdf_summary_info_header_t *ssi, cdf_property_info_t **info, size_t *count) 934191739Sobrien{ 935191739Sobrien size_t i, maxcount; 936226048Sobrien const cdf_summary_info_header_t *si = 937226048Sobrien CAST(const cdf_summary_info_header_t *, sst->sst_tab); 938226048Sobrien const cdf_section_declaration_t *sd = 939226048Sobrien CAST(const cdf_section_declaration_t *, (const void *) 940226048Sobrien ((const char *)sst->sst_tab + CDF_SECTION_DECLARATION_OFFSET)); 941191739Sobrien 942226048Sobrien if (cdf_check_stream_offset(sst, h, si, sizeof(*si), __LINE__) == -1 || 943226048Sobrien cdf_check_stream_offset(sst, h, sd, sizeof(*sd), __LINE__) == -1) 944192348Sdelphij return -1; 945191739Sobrien ssi->si_byte_order = CDF_TOLE2(si->si_byte_order); 946191739Sobrien ssi->si_os_version = CDF_TOLE2(si->si_os_version); 947191739Sobrien ssi->si_os = CDF_TOLE2(si->si_os); 948191739Sobrien ssi->si_class = si->si_class; 949191739Sobrien cdf_swap_class(&ssi->si_class); 950191739Sobrien ssi->si_count = CDF_TOLE2(si->si_count); 951191739Sobrien *count = 0; 952191739Sobrien maxcount = 0; 953191739Sobrien *info = NULL; 954191739Sobrien for (i = 0; i < CDF_TOLE4(si->si_count); i++) { 955191739Sobrien if (i >= CDF_LOOP_LIMIT) { 956191739Sobrien DPRINTF(("Unpack summary info loop limit")); 957191739Sobrien errno = EFTYPE; 958191739Sobrien return -1; 959191739Sobrien } 960226048Sobrien if (cdf_read_property_info(sst, h, CDF_TOLE4(sd->sd_offset), 961234250Sobrien info, count, &maxcount) == -1) { 962191739Sobrien return -1; 963234250Sobrien } 964191739Sobrien } 965191739Sobrien return 0; 966191739Sobrien} 967191739Sobrien 968191739Sobrien 969191739Sobrien 970191739Sobrienint 971191739Sobriencdf_print_classid(char *buf, size_t buflen, const cdf_classid_t *id) 972191739Sobrien{ 973191739Sobrien return snprintf(buf, buflen, "%.8x-%.4x-%.4x-%.2x%.2x-" 974191739Sobrien "%.2x%.2x%.2x%.2x%.2x%.2x", id->cl_dword, id->cl_word[0], 975191739Sobrien id->cl_word[1], id->cl_two[0], id->cl_two[1], id->cl_six[0], 976191739Sobrien id->cl_six[1], id->cl_six[2], id->cl_six[3], id->cl_six[4], 977191739Sobrien id->cl_six[5]); 978191739Sobrien} 979191739Sobrien 980191739Sobrienstatic const struct { 981191739Sobrien uint32_t v; 982191739Sobrien const char *n; 983191739Sobrien} vn[] = { 984191739Sobrien { CDF_PROPERTY_CODE_PAGE, "Code page" }, 985191739Sobrien { CDF_PROPERTY_TITLE, "Title" }, 986191739Sobrien { CDF_PROPERTY_SUBJECT, "Subject" }, 987191739Sobrien { CDF_PROPERTY_AUTHOR, "Author" }, 988191739Sobrien { CDF_PROPERTY_KEYWORDS, "Keywords" }, 989191739Sobrien { CDF_PROPERTY_COMMENTS, "Comments" }, 990191739Sobrien { CDF_PROPERTY_TEMPLATE, "Template" }, 991191739Sobrien { CDF_PROPERTY_LAST_SAVED_BY, "Last Saved By" }, 992191739Sobrien { CDF_PROPERTY_REVISION_NUMBER, "Revision Number" }, 993191739Sobrien { CDF_PROPERTY_TOTAL_EDITING_TIME, "Total Editing Time" }, 994191739Sobrien { CDF_PROPERTY_LAST_PRINTED, "Last Printed" }, 995191739Sobrien { CDF_PROPERTY_CREATE_TIME, "Create Time/Date" }, 996191739Sobrien { CDF_PROPERTY_LAST_SAVED_TIME, "Last Saved Time/Date" }, 997191739Sobrien { CDF_PROPERTY_NUMBER_OF_PAGES, "Number of Pages" }, 998191739Sobrien { CDF_PROPERTY_NUMBER_OF_WORDS, "Number of Words" }, 999191739Sobrien { CDF_PROPERTY_NUMBER_OF_CHARACTERS, "Number of Characters" }, 1000191739Sobrien { CDF_PROPERTY_THUMBNAIL, "Thumbnail" }, 1001191739Sobrien { CDF_PROPERTY_NAME_OF_APPLICATION, "Name of Creating Application" }, 1002191739Sobrien { CDF_PROPERTY_SECURITY, "Security" }, 1003191739Sobrien { CDF_PROPERTY_LOCALE_ID, "Locale ID" }, 1004191739Sobrien}; 1005191739Sobrien 1006191739Sobrienint 1007191739Sobriencdf_print_property_name(char *buf, size_t bufsiz, uint32_t p) 1008191739Sobrien{ 1009191739Sobrien size_t i; 1010191739Sobrien 1011191739Sobrien for (i = 0; i < __arraycount(vn); i++) 1012191739Sobrien if (vn[i].v == p) 1013191739Sobrien return snprintf(buf, bufsiz, "%s", vn[i].n); 1014191739Sobrien return snprintf(buf, bufsiz, "0x%x", p); 1015191739Sobrien} 1016191739Sobrien 1017191739Sobrienint 1018191739Sobriencdf_print_elapsed_time(char *buf, size_t bufsiz, cdf_timestamp_t ts) 1019191739Sobrien{ 1020226048Sobrien int len = 0; 1021191739Sobrien int days, hours, mins, secs; 1022191739Sobrien 1023191739Sobrien ts /= CDF_TIME_PREC; 1024226048Sobrien secs = (int)(ts % 60); 1025191739Sobrien ts /= 60; 1026226048Sobrien mins = (int)(ts % 60); 1027191739Sobrien ts /= 60; 1028226048Sobrien hours = (int)(ts % 24); 1029191739Sobrien ts /= 24; 1030226048Sobrien days = (int)ts; 1031191739Sobrien 1032191739Sobrien if (days) { 1033191739Sobrien len += snprintf(buf + len, bufsiz - len, "%dd+", days); 1034226048Sobrien if ((size_t)len >= bufsiz) 1035191739Sobrien return len; 1036191739Sobrien } 1037191739Sobrien 1038191739Sobrien if (days || hours) { 1039191739Sobrien len += snprintf(buf + len, bufsiz - len, "%.2d:", hours); 1040226048Sobrien if ((size_t)len >= bufsiz) 1041191739Sobrien return len; 1042191739Sobrien } 1043191739Sobrien 1044191739Sobrien len += snprintf(buf + len, bufsiz - len, "%.2d:", mins); 1045226048Sobrien if ((size_t)len >= bufsiz) 1046191739Sobrien return len; 1047191739Sobrien 1048191739Sobrien len += snprintf(buf + len, bufsiz - len, "%.2d", secs); 1049191739Sobrien return len; 1050191739Sobrien} 1051191739Sobrien 1052191739Sobrien 1053191739Sobrien#ifdef CDF_DEBUG 1054191739Sobrienvoid 1055191739Sobriencdf_dump_header(const cdf_header_t *h) 1056191739Sobrien{ 1057191739Sobrien size_t i; 1058191739Sobrien 1059192348Sdelphij#define DUMP(a, b) (void)fprintf(stderr, "%40.40s = " a "\n", # b, h->h_ ## b) 1060192348Sdelphij#define DUMP2(a, b) (void)fprintf(stderr, "%40.40s = " a " (" a ")\n", # b, \ 1061192348Sdelphij h->h_ ## b, 1 << h->h_ ## b) 1062191739Sobrien DUMP("%d", revision); 1063191739Sobrien DUMP("%d", version); 1064191739Sobrien DUMP("0x%x", byte_order); 1065192348Sdelphij DUMP2("%d", sec_size_p2); 1066192348Sdelphij DUMP2("%d", short_sec_size_p2); 1067191739Sobrien DUMP("%d", num_sectors_in_sat); 1068191739Sobrien DUMP("%d", secid_first_directory); 1069191739Sobrien DUMP("%d", min_size_standard_stream); 1070191739Sobrien DUMP("%d", secid_first_sector_in_short_sat); 1071191739Sobrien DUMP("%d", num_sectors_in_short_sat); 1072191739Sobrien DUMP("%d", secid_first_sector_in_master_sat); 1073191739Sobrien DUMP("%d", num_sectors_in_master_sat); 1074191739Sobrien for (i = 0; i < __arraycount(h->h_master_sat); i++) { 1075191739Sobrien if (h->h_master_sat[i] == CDF_SECID_FREE) 1076191739Sobrien break; 1077192348Sdelphij (void)fprintf(stderr, "%35.35s[%.3zu] = %d\n", 1078191739Sobrien "master_sat", i, h->h_master_sat[i]); 1079191739Sobrien } 1080191739Sobrien} 1081191739Sobrien 1082191739Sobrienvoid 1083192348Sdelphijcdf_dump_sat(const char *prefix, const cdf_sat_t *sat, size_t size) 1084191739Sobrien{ 1085192348Sdelphij size_t i, j, s = size / sizeof(cdf_secid_t); 1086191739Sobrien 1087191739Sobrien for (i = 0; i < sat->sat_len; i++) { 1088234250Sobrien (void)fprintf(stderr, "%s[%" SIZE_T_FORMAT "u]:\n%.6" 1089234250Sobrien SIZE_T_FORMAT "u: ", prefix, i, i * s); 1090191739Sobrien for (j = 0; j < s; j++) { 1091192348Sdelphij (void)fprintf(stderr, "%5d, ", 1092192348Sdelphij CDF_TOLE4(sat->sat_tab[s * i + j])); 1093191739Sobrien if ((j + 1) % 10 == 0) 1094234250Sobrien (void)fprintf(stderr, "\n%.6" SIZE_T_FORMAT 1095234250Sobrien "u: ", i * s + j + 1); 1096191739Sobrien } 1097192348Sdelphij (void)fprintf(stderr, "\n"); 1098191739Sobrien } 1099191739Sobrien} 1100191739Sobrien 1101191739Sobrienvoid 1102191739Sobriencdf_dump(void *v, size_t len) 1103191739Sobrien{ 1104191739Sobrien size_t i, j; 1105191739Sobrien unsigned char *p = v; 1106191739Sobrien char abuf[16]; 1107192348Sdelphij (void)fprintf(stderr, "%.4x: ", 0); 1108191739Sobrien for (i = 0, j = 0; i < len; i++, p++) { 1109192348Sdelphij (void)fprintf(stderr, "%.2x ", *p); 1110191739Sobrien abuf[j++] = isprint(*p) ? *p : '.'; 1111191739Sobrien if (j == 16) { 1112191739Sobrien j = 0; 1113191739Sobrien abuf[15] = '\0'; 1114234250Sobrien (void)fprintf(stderr, "%s\n%.4" SIZE_T_FORMAT "x: ", 1115234250Sobrien abuf, i + 1); 1116191739Sobrien } 1117191739Sobrien } 1118192348Sdelphij (void)fprintf(stderr, "\n"); 1119191739Sobrien} 1120191739Sobrien 1121191739Sobrienvoid 1122191739Sobriencdf_dump_stream(const cdf_header_t *h, const cdf_stream_t *sst) 1123191739Sobrien{ 1124191739Sobrien size_t ss = sst->sst_dirlen < h->h_min_size_standard_stream ? 1125191739Sobrien CDF_SHORT_SEC_SIZE(h) : CDF_SEC_SIZE(h); 1126191739Sobrien cdf_dump(sst->sst_tab, ss * sst->sst_len); 1127191739Sobrien} 1128191739Sobrien 1129191739Sobrienvoid 1130192348Sdelphijcdf_dump_dir(const cdf_info_t *info, const cdf_header_t *h, 1131192348Sdelphij const cdf_sat_t *sat, const cdf_sat_t *ssat, const cdf_stream_t *sst, 1132191739Sobrien const cdf_dir_t *dir) 1133191739Sobrien{ 1134191739Sobrien size_t i, j; 1135191739Sobrien cdf_directory_t *d; 1136191739Sobrien char name[__arraycount(d->d_name)]; 1137191739Sobrien cdf_stream_t scn; 1138191739Sobrien struct timespec ts; 1139191739Sobrien 1140191739Sobrien static const char *types[] = { "empty", "user storage", 1141191739Sobrien "user stream", "lockbytes", "property", "root storage" }; 1142191739Sobrien 1143191739Sobrien for (i = 0; i < dir->dir_len; i++) { 1144191739Sobrien d = &dir->dir_tab[i]; 1145191739Sobrien for (j = 0; j < sizeof(name); j++) 1146191739Sobrien name[j] = (char)CDF_TOLE2(d->d_name[j]); 1147226048Sobrien (void)fprintf(stderr, "Directory %" SIZE_T_FORMAT "u: %s\n", 1148226048Sobrien i, name); 1149191739Sobrien if (d->d_type < __arraycount(types)) 1150192348Sdelphij (void)fprintf(stderr, "Type: %s\n", types[d->d_type]); 1151191739Sobrien else 1152192348Sdelphij (void)fprintf(stderr, "Type: %d\n", d->d_type); 1153192348Sdelphij (void)fprintf(stderr, "Color: %s\n", 1154192348Sdelphij d->d_color ? "black" : "red"); 1155192348Sdelphij (void)fprintf(stderr, "Left child: %d\n", d->d_left_child); 1156192348Sdelphij (void)fprintf(stderr, "Right child: %d\n", d->d_right_child); 1157192348Sdelphij (void)fprintf(stderr, "Flags: 0x%x\n", d->d_flags); 1158191739Sobrien cdf_timestamp_to_timespec(&ts, d->d_created); 1159226048Sobrien (void)fprintf(stderr, "Created %s", cdf_ctime(&ts.tv_sec)); 1160191739Sobrien cdf_timestamp_to_timespec(&ts, d->d_modified); 1161226048Sobrien (void)fprintf(stderr, "Modified %s", cdf_ctime(&ts.tv_sec)); 1162192348Sdelphij (void)fprintf(stderr, "Stream %d\n", d->d_stream_first_sector); 1163192348Sdelphij (void)fprintf(stderr, "Size %d\n", d->d_size); 1164191739Sobrien switch (d->d_type) { 1165191739Sobrien case CDF_DIR_TYPE_USER_STORAGE: 1166192348Sdelphij (void)fprintf(stderr, "Storage: %d\n", d->d_storage); 1167191739Sobrien break; 1168191739Sobrien case CDF_DIR_TYPE_USER_STREAM: 1169191739Sobrien if (sst == NULL) 1170191739Sobrien break; 1171192348Sdelphij if (cdf_read_sector_chain(info, h, sat, ssat, sst, 1172191739Sobrien d->d_stream_first_sector, d->d_size, &scn) == -1) { 1173191739Sobrien warn("Can't read stream for %s at %d len %d", 1174191739Sobrien name, d->d_stream_first_sector, d->d_size); 1175191739Sobrien break; 1176191739Sobrien } 1177191739Sobrien cdf_dump_stream(h, &scn); 1178191739Sobrien free(scn.sst_tab); 1179191739Sobrien break; 1180191739Sobrien default: 1181191739Sobrien break; 1182191739Sobrien } 1183226048Sobrien 1184191739Sobrien } 1185191739Sobrien} 1186191739Sobrien 1187191739Sobrienvoid 1188191739Sobriencdf_dump_property_info(const cdf_property_info_t *info, size_t count) 1189191739Sobrien{ 1190191739Sobrien cdf_timestamp_t tp; 1191191739Sobrien struct timespec ts; 1192191739Sobrien char buf[64]; 1193226048Sobrien size_t i, j; 1194191739Sobrien 1195191739Sobrien for (i = 0; i < count; i++) { 1196191739Sobrien cdf_print_property_name(buf, sizeof(buf), info[i].pi_id); 1197226048Sobrien (void)fprintf(stderr, "%" SIZE_T_FORMAT "u) %s: ", i, buf); 1198191739Sobrien switch (info[i].pi_type) { 1199226048Sobrien case CDF_NULL: 1200226048Sobrien break; 1201191739Sobrien case CDF_SIGNED16: 1202192348Sdelphij (void)fprintf(stderr, "signed 16 [%hd]\n", 1203192348Sdelphij info[i].pi_s16); 1204191739Sobrien break; 1205191739Sobrien case CDF_SIGNED32: 1206192348Sdelphij (void)fprintf(stderr, "signed 32 [%d]\n", 1207192348Sdelphij info[i].pi_s32); 1208191739Sobrien break; 1209191739Sobrien case CDF_UNSIGNED32: 1210192348Sdelphij (void)fprintf(stderr, "unsigned 32 [%u]\n", 1211192348Sdelphij info[i].pi_u32); 1212191739Sobrien break; 1213234250Sobrien case CDF_FLOAT: 1214234250Sobrien (void)fprintf(stderr, "float [%g]\n", 1215234250Sobrien info[i].pi_f); 1216234250Sobrien break; 1217234250Sobrien case CDF_DOUBLE: 1218234250Sobrien (void)fprintf(stderr, "double [%g]\n", 1219234250Sobrien info[i].pi_d); 1220234250Sobrien break; 1221191739Sobrien case CDF_LENGTH32_STRING: 1222192348Sdelphij (void)fprintf(stderr, "string %u [%.*s]\n", 1223192348Sdelphij info[i].pi_str.s_len, 1224191739Sobrien info[i].pi_str.s_len, info[i].pi_str.s_buf); 1225191739Sobrien break; 1226226048Sobrien case CDF_LENGTH32_WSTRING: 1227226048Sobrien (void)fprintf(stderr, "string %u [", 1228226048Sobrien info[i].pi_str.s_len); 1229226048Sobrien for (j = 0; j < info[i].pi_str.s_len - 1; j++) 1230226048Sobrien (void)fputc(info[i].pi_str.s_buf[j << 1], stderr); 1231226048Sobrien (void)fprintf(stderr, "]\n"); 1232226048Sobrien break; 1233191739Sobrien case CDF_FILETIME: 1234191739Sobrien tp = info[i].pi_tp; 1235191739Sobrien if (tp < 1000000000000000LL) { 1236191739Sobrien cdf_print_elapsed_time(buf, sizeof(buf), tp); 1237192348Sdelphij (void)fprintf(stderr, "timestamp %s\n", buf); 1238191739Sobrien } else { 1239191739Sobrien cdf_timestamp_to_timespec(&ts, tp); 1240192348Sdelphij (void)fprintf(stderr, "timestamp %s", 1241226048Sobrien cdf_ctime(&ts.tv_sec)); 1242191739Sobrien } 1243191739Sobrien break; 1244191739Sobrien case CDF_CLIPBOARD: 1245192348Sdelphij (void)fprintf(stderr, "CLIPBOARD %u\n", info[i].pi_u32); 1246191739Sobrien break; 1247191739Sobrien default: 1248191739Sobrien DPRINTF(("Don't know how to deal with %x\n", 1249191739Sobrien info[i].pi_type)); 1250191739Sobrien break; 1251191739Sobrien } 1252191739Sobrien } 1253191739Sobrien} 1254191739Sobrien 1255191739Sobrien 1256191739Sobrienvoid 1257191739Sobriencdf_dump_summary_info(const cdf_header_t *h, const cdf_stream_t *sst) 1258191739Sobrien{ 1259191739Sobrien char buf[128]; 1260191739Sobrien cdf_summary_info_header_t ssi; 1261191739Sobrien cdf_property_info_t *info; 1262191739Sobrien size_t count; 1263191739Sobrien 1264191739Sobrien (void)&h; 1265226048Sobrien if (cdf_unpack_summary_info(sst, h, &ssi, &info, &count) == -1) 1266191739Sobrien return; 1267192348Sdelphij (void)fprintf(stderr, "Endian: %x\n", ssi.si_byte_order); 1268192348Sdelphij (void)fprintf(stderr, "Os Version %d.%d\n", ssi.si_os_version & 0xff, 1269191739Sobrien ssi.si_os_version >> 8); 1270192348Sdelphij (void)fprintf(stderr, "Os %d\n", ssi.si_os); 1271191739Sobrien cdf_print_classid(buf, sizeof(buf), &ssi.si_class); 1272192348Sdelphij (void)fprintf(stderr, "Class %s\n", buf); 1273192348Sdelphij (void)fprintf(stderr, "Count %d\n", ssi.si_count); 1274191739Sobrien cdf_dump_property_info(info, count); 1275191739Sobrien free(info); 1276191739Sobrien} 1277191739Sobrien 1278191739Sobrien#endif 1279191739Sobrien 1280191739Sobrien#ifdef TEST 1281191739Sobrienint 1282191739Sobrienmain(int argc, char *argv[]) 1283191739Sobrien{ 1284192348Sdelphij int i; 1285191739Sobrien cdf_header_t h; 1286191739Sobrien cdf_sat_t sat, ssat; 1287191739Sobrien cdf_stream_t sst, scn; 1288191739Sobrien cdf_dir_t dir; 1289192348Sdelphij cdf_info_t info; 1290191739Sobrien 1291191739Sobrien if (argc < 2) { 1292191739Sobrien (void)fprintf(stderr, "Usage: %s <filename>\n", getprogname()); 1293191739Sobrien return -1; 1294191739Sobrien } 1295191739Sobrien 1296192348Sdelphij info.i_buf = NULL; 1297192348Sdelphij info.i_len = 0; 1298191739Sobrien for (i = 1; i < argc; i++) { 1299192348Sdelphij if ((info.i_fd = open(argv[1], O_RDONLY)) == -1) 1300191739Sobrien err(1, "Cannot open `%s'", argv[1]); 1301191739Sobrien 1302192348Sdelphij if (cdf_read_header(&info, &h) == -1) 1303191739Sobrien err(1, "Cannot read header"); 1304191739Sobrien#ifdef CDF_DEBUG 1305191739Sobrien cdf_dump_header(&h); 1306191739Sobrien#endif 1307191739Sobrien 1308192348Sdelphij if (cdf_read_sat(&info, &h, &sat) == -1) 1309191739Sobrien err(1, "Cannot read sat"); 1310191739Sobrien#ifdef CDF_DEBUG 1311192348Sdelphij cdf_dump_sat("SAT", &sat, CDF_SEC_SIZE(&h)); 1312191739Sobrien#endif 1313191739Sobrien 1314192348Sdelphij if (cdf_read_ssat(&info, &h, &sat, &ssat) == -1) 1315191739Sobrien err(1, "Cannot read ssat"); 1316191739Sobrien#ifdef CDF_DEBUG 1317226048Sobrien cdf_dump_sat("SSAT", &ssat, CDF_SHORT_SEC_SIZE(&h)); 1318191739Sobrien#endif 1319191739Sobrien 1320192348Sdelphij if (cdf_read_dir(&info, &h, &sat, &dir) == -1) 1321191739Sobrien err(1, "Cannot read dir"); 1322191739Sobrien 1323192348Sdelphij if (cdf_read_short_stream(&info, &h, &sat, &dir, &sst) == -1) 1324191739Sobrien err(1, "Cannot read short stream"); 1325191739Sobrien#ifdef CDF_DEBUG 1326191739Sobrien cdf_dump_stream(&h, &sst); 1327191739Sobrien#endif 1328191739Sobrien 1329191739Sobrien#ifdef CDF_DEBUG 1330192348Sdelphij cdf_dump_dir(&info, &h, &sat, &ssat, &sst, &dir); 1331191739Sobrien#endif 1332191739Sobrien 1333191739Sobrien 1334192348Sdelphij if (cdf_read_summary_info(&info, &h, &sat, &ssat, &sst, &dir, 1335191739Sobrien &scn) == -1) 1336191739Sobrien err(1, "Cannot read summary info"); 1337191739Sobrien#ifdef CDF_DEBUG 1338191739Sobrien cdf_dump_summary_info(&h, &scn); 1339191739Sobrien#endif 1340191739Sobrien 1341192348Sdelphij (void)close(info.i_fd); 1342191739Sobrien } 1343191739Sobrien 1344191739Sobrien return 0; 1345191739Sobrien} 1346191739Sobrien#endif 1347