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 38328875SeadlerFILE_RCSID("@(#)$File: cdf.c,v 1.106 2017/04/30 17:05:02 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))) 76284778Sdelphij#define CDF_TOLE(x) (/*CONSTCOND*/sizeof(x) == 2 ? \ 77284778Sdelphij CDF_TOLE2(CAST(uint16_t, x)) : \ 78284778Sdelphij (/*CONSTCOND*/sizeof(x) == 4 ? \ 79284778Sdelphij CDF_TOLE4(CAST(uint32_t, x)) : \ 80284778Sdelphij CDF_TOLE8(CAST(uint64_t, x)))) 81226048Sobrien#define CDF_GETUINT32(x, y) cdf_getuint32(x, y) 82191739Sobrien 83328875Seadler#define CDF_MALLOC(n) cdf_malloc(__FILE__, __LINE__, (n)) 84328875Seadler#define CDF_REALLOC(p, n) cdf_realloc(__FILE__, __LINE__, (p), (n)) 85328875Seadler#define CDF_CALLOC(n, u) cdf_calloc(__FILE__, __LINE__, (n), (u)) 86234250Sobrien 87328875Seadler 88328875Seadlerstatic void * 89328875Seadlercdf_malloc(const char *file __attribute__((__unused__)), 90328875Seadler size_t line __attribute__((__unused__)), size_t n) 91328875Seadler{ 92328875Seadler DPRINTF(("%s,%zu: %s %zu\n", file, line, __func__, n)); 93328875Seadler return malloc(n); 94328875Seadler} 95328875Seadler 96328875Seadlerstatic void * 97328875Seadlercdf_realloc(const char *file __attribute__((__unused__)), 98328875Seadler size_t line __attribute__((__unused__)), void *p, size_t n) 99328875Seadler{ 100328875Seadler DPRINTF(("%s,%zu: %s %zu\n", file, line, __func__, n)); 101328875Seadler return realloc(p, n); 102328875Seadler} 103328875Seadler 104328875Seadlerstatic void * 105328875Seadlercdf_calloc(const char *file __attribute__((__unused__)), 106328875Seadler size_t line __attribute__((__unused__)), size_t n, size_t u) 107328875Seadler{ 108328875Seadler DPRINTF(("%s,%zu: %s %zu %zu\n", file, line, __func__, n, u)); 109328875Seadler return calloc(n, u); 110328875Seadler} 111328875Seadler 112191739Sobrien/* 113191739Sobrien * swap a short 114191739Sobrien */ 115226048Sobrienstatic uint16_t 116226048Sobrien_cdf_tole2(uint16_t sv) 117191739Sobrien{ 118191739Sobrien uint16_t rv; 119226048Sobrien uint8_t *s = (uint8_t *)(void *)&sv; 120226048Sobrien uint8_t *d = (uint8_t *)(void *)&rv; 121191739Sobrien d[0] = s[1]; 122191739Sobrien d[1] = s[0]; 123191739Sobrien return rv; 124191739Sobrien} 125191739Sobrien 126191739Sobrien/* 127191739Sobrien * swap an int 128191739Sobrien */ 129226048Sobrienstatic uint32_t 130226048Sobrien_cdf_tole4(uint32_t sv) 131191739Sobrien{ 132191739Sobrien uint32_t rv; 133226048Sobrien uint8_t *s = (uint8_t *)(void *)&sv; 134226048Sobrien uint8_t *d = (uint8_t *)(void *)&rv; 135191739Sobrien d[0] = s[3]; 136191739Sobrien d[1] = s[2]; 137191739Sobrien d[2] = s[1]; 138191739Sobrien d[3] = s[0]; 139191739Sobrien return rv; 140191739Sobrien} 141191739Sobrien 142191739Sobrien/* 143191739Sobrien * swap a quad 144191739Sobrien */ 145226048Sobrienstatic uint64_t 146226048Sobrien_cdf_tole8(uint64_t sv) 147191739Sobrien{ 148191739Sobrien uint64_t rv; 149226048Sobrien uint8_t *s = (uint8_t *)(void *)&sv; 150226048Sobrien uint8_t *d = (uint8_t *)(void *)&rv; 151191739Sobrien d[0] = s[7]; 152191739Sobrien d[1] = s[6]; 153191739Sobrien d[2] = s[5]; 154191739Sobrien d[3] = s[4]; 155191739Sobrien d[4] = s[3]; 156191739Sobrien d[5] = s[2]; 157191739Sobrien d[6] = s[1]; 158191739Sobrien d[7] = s[0]; 159191739Sobrien return rv; 160191739Sobrien} 161191739Sobrien 162226048Sobrien/* 163226048Sobrien * grab a uint32_t from a possibly unaligned address, and return it in 164226048Sobrien * the native host order. 165226048Sobrien */ 166226048Sobrienstatic uint32_t 167226048Sobriencdf_getuint32(const uint8_t *p, size_t offs) 168226048Sobrien{ 169226048Sobrien uint32_t rv; 170226048Sobrien (void)memcpy(&rv, p + offs * sizeof(uint32_t), sizeof(rv)); 171226048Sobrien return CDF_TOLE4(rv); 172226048Sobrien} 173226048Sobrien 174191739Sobrien#define CDF_UNPACK(a) \ 175191739Sobrien (void)memcpy(&(a), &buf[len], sizeof(a)), len += sizeof(a) 176191739Sobrien#define CDF_UNPACKA(a) \ 177191739Sobrien (void)memcpy((a), &buf[len], sizeof(a)), len += sizeof(a) 178191739Sobrien 179226048Sobrienuint16_t 180226048Sobriencdf_tole2(uint16_t sv) 181226048Sobrien{ 182226048Sobrien return CDF_TOLE2(sv); 183226048Sobrien} 184226048Sobrien 185226048Sobrienuint32_t 186226048Sobriencdf_tole4(uint32_t sv) 187226048Sobrien{ 188226048Sobrien return CDF_TOLE4(sv); 189226048Sobrien} 190226048Sobrien 191226048Sobrienuint64_t 192226048Sobriencdf_tole8(uint64_t sv) 193226048Sobrien{ 194226048Sobrien return CDF_TOLE8(sv); 195226048Sobrien} 196226048Sobrien 197191739Sobrienvoid 198191739Sobriencdf_swap_header(cdf_header_t *h) 199191739Sobrien{ 200191739Sobrien size_t i; 201191739Sobrien 202191739Sobrien h->h_magic = CDF_TOLE8(h->h_magic); 203191739Sobrien h->h_uuid[0] = CDF_TOLE8(h->h_uuid[0]); 204191739Sobrien h->h_uuid[1] = CDF_TOLE8(h->h_uuid[1]); 205191739Sobrien h->h_revision = CDF_TOLE2(h->h_revision); 206191739Sobrien h->h_version = CDF_TOLE2(h->h_version); 207191739Sobrien h->h_byte_order = CDF_TOLE2(h->h_byte_order); 208191739Sobrien h->h_sec_size_p2 = CDF_TOLE2(h->h_sec_size_p2); 209191739Sobrien h->h_short_sec_size_p2 = CDF_TOLE2(h->h_short_sec_size_p2); 210191739Sobrien h->h_num_sectors_in_sat = CDF_TOLE4(h->h_num_sectors_in_sat); 211191739Sobrien h->h_secid_first_directory = CDF_TOLE4(h->h_secid_first_directory); 212191739Sobrien h->h_min_size_standard_stream = 213191739Sobrien CDF_TOLE4(h->h_min_size_standard_stream); 214191739Sobrien h->h_secid_first_sector_in_short_sat = 215226048Sobrien CDF_TOLE4((uint32_t)h->h_secid_first_sector_in_short_sat); 216191739Sobrien h->h_num_sectors_in_short_sat = 217191739Sobrien CDF_TOLE4(h->h_num_sectors_in_short_sat); 218191739Sobrien h->h_secid_first_sector_in_master_sat = 219226048Sobrien CDF_TOLE4((uint32_t)h->h_secid_first_sector_in_master_sat); 220191739Sobrien h->h_num_sectors_in_master_sat = 221191739Sobrien CDF_TOLE4(h->h_num_sectors_in_master_sat); 222191739Sobrien for (i = 0; i < __arraycount(h->h_master_sat); i++) 223226048Sobrien h->h_master_sat[i] = CDF_TOLE4((uint32_t)h->h_master_sat[i]); 224191739Sobrien} 225191739Sobrien 226191739Sobrienvoid 227191739Sobriencdf_unpack_header(cdf_header_t *h, char *buf) 228191739Sobrien{ 229191739Sobrien size_t i; 230191739Sobrien size_t len = 0; 231191739Sobrien 232191739Sobrien CDF_UNPACK(h->h_magic); 233191739Sobrien CDF_UNPACKA(h->h_uuid); 234191739Sobrien CDF_UNPACK(h->h_revision); 235191739Sobrien CDF_UNPACK(h->h_version); 236191739Sobrien CDF_UNPACK(h->h_byte_order); 237191739Sobrien CDF_UNPACK(h->h_sec_size_p2); 238191739Sobrien CDF_UNPACK(h->h_short_sec_size_p2); 239191739Sobrien CDF_UNPACKA(h->h_unused0); 240191739Sobrien CDF_UNPACK(h->h_num_sectors_in_sat); 241191739Sobrien CDF_UNPACK(h->h_secid_first_directory); 242191739Sobrien CDF_UNPACKA(h->h_unused1); 243191739Sobrien CDF_UNPACK(h->h_min_size_standard_stream); 244191739Sobrien CDF_UNPACK(h->h_secid_first_sector_in_short_sat); 245191739Sobrien CDF_UNPACK(h->h_num_sectors_in_short_sat); 246191739Sobrien CDF_UNPACK(h->h_secid_first_sector_in_master_sat); 247191739Sobrien CDF_UNPACK(h->h_num_sectors_in_master_sat); 248191739Sobrien for (i = 0; i < __arraycount(h->h_master_sat); i++) 249191739Sobrien CDF_UNPACK(h->h_master_sat[i]); 250191739Sobrien} 251191739Sobrien 252191739Sobrienvoid 253191739Sobriencdf_swap_dir(cdf_directory_t *d) 254191739Sobrien{ 255191739Sobrien d->d_namelen = CDF_TOLE2(d->d_namelen); 256226048Sobrien d->d_left_child = CDF_TOLE4((uint32_t)d->d_left_child); 257226048Sobrien d->d_right_child = CDF_TOLE4((uint32_t)d->d_right_child); 258226048Sobrien d->d_storage = CDF_TOLE4((uint32_t)d->d_storage); 259191739Sobrien d->d_storage_uuid[0] = CDF_TOLE8(d->d_storage_uuid[0]); 260191739Sobrien d->d_storage_uuid[1] = CDF_TOLE8(d->d_storage_uuid[1]); 261191739Sobrien d->d_flags = CDF_TOLE4(d->d_flags); 262226048Sobrien d->d_created = CDF_TOLE8((uint64_t)d->d_created); 263226048Sobrien d->d_modified = CDF_TOLE8((uint64_t)d->d_modified); 264226048Sobrien d->d_stream_first_sector = CDF_TOLE4((uint32_t)d->d_stream_first_sector); 265191739Sobrien d->d_size = CDF_TOLE4(d->d_size); 266191739Sobrien} 267191739Sobrien 268191739Sobrienvoid 269191739Sobriencdf_swap_class(cdf_classid_t *d) 270191739Sobrien{ 271191739Sobrien d->cl_dword = CDF_TOLE4(d->cl_dword); 272191739Sobrien d->cl_word[0] = CDF_TOLE2(d->cl_word[0]); 273191739Sobrien d->cl_word[1] = CDF_TOLE2(d->cl_word[1]); 274191739Sobrien} 275191739Sobrien 276191739Sobrienvoid 277191739Sobriencdf_unpack_dir(cdf_directory_t *d, char *buf) 278191739Sobrien{ 279191739Sobrien size_t len = 0; 280191739Sobrien 281191739Sobrien CDF_UNPACKA(d->d_name); 282191739Sobrien CDF_UNPACK(d->d_namelen); 283191739Sobrien CDF_UNPACK(d->d_type); 284191739Sobrien CDF_UNPACK(d->d_color); 285191739Sobrien CDF_UNPACK(d->d_left_child); 286191739Sobrien CDF_UNPACK(d->d_right_child); 287191739Sobrien CDF_UNPACK(d->d_storage); 288191739Sobrien CDF_UNPACKA(d->d_storage_uuid); 289191739Sobrien CDF_UNPACK(d->d_flags); 290191739Sobrien CDF_UNPACK(d->d_created); 291191739Sobrien CDF_UNPACK(d->d_modified); 292191739Sobrien CDF_UNPACK(d->d_stream_first_sector); 293191739Sobrien CDF_UNPACK(d->d_size); 294191739Sobrien CDF_UNPACK(d->d_unused0); 295191739Sobrien} 296191739Sobrien 297309848Sdelphijint 298300899Sdelphijcdf_zero_stream(cdf_stream_t *scn) 299300899Sdelphij{ 300300899Sdelphij scn->sst_len = 0; 301300899Sdelphij scn->sst_dirlen = 0; 302300899Sdelphij scn->sst_ss = 0; 303300899Sdelphij free(scn->sst_tab); 304300899Sdelphij scn->sst_tab = NULL; 305300899Sdelphij return -1; 306300899Sdelphij} 307300899Sdelphij 308300899Sdelphijstatic size_t 309300899Sdelphijcdf_check_stream(const cdf_stream_t *sst, const cdf_header_t *h) 310300899Sdelphij{ 311300899Sdelphij size_t ss = sst->sst_dirlen < h->h_min_size_standard_stream ? 312300899Sdelphij CDF_SHORT_SEC_SIZE(h) : CDF_SEC_SIZE(h); 313300899Sdelphij assert(ss == sst->sst_ss); 314300899Sdelphij return sst->sst_ss; 315300899Sdelphij} 316300899Sdelphij 317300899Sdelphijstatic int 318226048Sobriencdf_check_stream_offset(const cdf_stream_t *sst, const cdf_header_t *h, 319226048Sobrien const void *p, size_t tail, int line) 320192348Sdelphij{ 321192348Sdelphij const char *b = (const char *)sst->sst_tab; 322192348Sdelphij const char *e = ((const char *)p) + tail; 323300899Sdelphij size_t ss = cdf_check_stream(sst, h); 324284778Sdelphij /*LINTED*/(void)&line; 325267843Sdelphij if (e >= b && (size_t)(e - b) <= ss * sst->sst_len) 326192348Sdelphij return 0; 327267843Sdelphij DPRINTF(("%d: offset begin %p < end %p || %" SIZE_T_FORMAT "u" 328267843Sdelphij " > %" SIZE_T_FORMAT "u [%" SIZE_T_FORMAT "u %" 329226048Sobrien SIZE_T_FORMAT "u]\n", line, b, e, (size_t)(e - b), 330267843Sdelphij ss * sst->sst_len, ss, sst->sst_len)); 331192348Sdelphij errno = EFTYPE; 332192348Sdelphij return -1; 333192348Sdelphij} 334192348Sdelphij 335192348Sdelphijstatic ssize_t 336192348Sdelphijcdf_read(const cdf_info_t *info, off_t off, void *buf, size_t len) 337192348Sdelphij{ 338192348Sdelphij size_t siz = (size_t)off + len; 339192348Sdelphij 340300899Sdelphij if ((off_t)(off + len) != (off_t)siz) 341300899Sdelphij goto out; 342192348Sdelphij 343192348Sdelphij if (info->i_buf != NULL && info->i_len >= siz) { 344192348Sdelphij (void)memcpy(buf, &info->i_buf[off], len); 345192348Sdelphij return (ssize_t)len; 346192348Sdelphij } 347192348Sdelphij 348192348Sdelphij if (info->i_fd == -1) 349300899Sdelphij goto out; 350192348Sdelphij 351267843Sdelphij if (pread(info->i_fd, buf, len, off) != (ssize_t)len) 352192348Sdelphij return -1; 353192348Sdelphij 354192348Sdelphij return (ssize_t)len; 355300899Sdelphijout: 356300899Sdelphij errno = EINVAL; 357300899Sdelphij return -1; 358192348Sdelphij} 359192348Sdelphij 360191739Sobrienint 361192348Sdelphijcdf_read_header(const cdf_info_t *info, cdf_header_t *h) 362191739Sobrien{ 363192348Sdelphij char buf[512]; 364192348Sdelphij 365191739Sobrien (void)memcpy(cdf_bo.s, "\01\02\03\04", 4); 366192348Sdelphij if (cdf_read(info, (off_t)0, buf, sizeof(buf)) == -1) 367191739Sobrien return -1; 368191739Sobrien cdf_unpack_header(h, buf); 369191739Sobrien cdf_swap_header(h); 370191739Sobrien if (h->h_magic != CDF_MAGIC) { 371328875Seadler DPRINTF(("Bad magic %#" INT64_T_FORMAT "x != %#" 372226048Sobrien INT64_T_FORMAT "x\n", 373192348Sdelphij (unsigned long long)h->h_magic, 374192348Sdelphij (unsigned long long)CDF_MAGIC)); 375192348Sdelphij goto out; 376191739Sobrien } 377192348Sdelphij if (h->h_sec_size_p2 > 20) { 378328875Seadler DPRINTF(("Bad sector size %hu\n", h->h_sec_size_p2)); 379192348Sdelphij goto out; 380192348Sdelphij } 381192348Sdelphij if (h->h_short_sec_size_p2 > 20) { 382328875Seadler DPRINTF(("Bad short sector size %hu\n", 383192348Sdelphij h->h_short_sec_size_p2)); 384192348Sdelphij goto out; 385192348Sdelphij } 386191739Sobrien return 0; 387192348Sdelphijout: 388192348Sdelphij errno = EFTYPE; 389192348Sdelphij return -1; 390191739Sobrien} 391191739Sobrien 392191739Sobrien 393191739Sobrienssize_t 394192348Sdelphijcdf_read_sector(const cdf_info_t *info, void *buf, size_t offs, size_t len, 395191739Sobrien const cdf_header_t *h, cdf_secid_t id) 396191739Sobrien{ 397234250Sobrien size_t ss = CDF_SEC_SIZE(h); 398234250Sobrien size_t pos = CDF_SEC_POS(h, id); 399234250Sobrien assert(ss == len); 400234250Sobrien return cdf_read(info, (off_t)pos, ((char *)buf) + offs, len); 401191739Sobrien} 402191739Sobrien 403191739Sobrienssize_t 404191739Sobriencdf_read_short_sector(const cdf_stream_t *sst, void *buf, size_t offs, 405191739Sobrien size_t len, const cdf_header_t *h, cdf_secid_t id) 406191739Sobrien{ 407234250Sobrien size_t ss = CDF_SHORT_SEC_SIZE(h); 408234250Sobrien size_t pos = CDF_SHORT_SEC_POS(h, id); 409234250Sobrien assert(ss == len); 410267843Sdelphij if (pos + len > CDF_SEC_SIZE(h) * sst->sst_len) { 411234250Sobrien DPRINTF(("Out of bounds read %" SIZE_T_FORMAT "u > %" 412234250Sobrien SIZE_T_FORMAT "u\n", 413267843Sdelphij pos + len, CDF_SEC_SIZE(h) * sst->sst_len)); 414300899Sdelphij goto out; 415234250Sobrien } 416191739Sobrien (void)memcpy(((char *)buf) + offs, 417234250Sobrien ((const char *)sst->sst_tab) + pos, len); 418191739Sobrien return len; 419300899Sdelphijout: 420300899Sdelphij errno = EFTYPE; 421300899Sdelphij return -1; 422191739Sobrien} 423191739Sobrien 424191739Sobrien/* 425191739Sobrien * Read the sector allocation table. 426191739Sobrien */ 427191739Sobrienint 428192348Sdelphijcdf_read_sat(const cdf_info_t *info, cdf_header_t *h, cdf_sat_t *sat) 429191739Sobrien{ 430191739Sobrien size_t i, j, k; 431191739Sobrien size_t ss = CDF_SEC_SIZE(h); 432192348Sdelphij cdf_secid_t *msa, mid, sec; 433192348Sdelphij size_t nsatpersec = (ss / sizeof(mid)) - 1; 434191739Sobrien 435191739Sobrien for (i = 0; i < __arraycount(h->h_master_sat); i++) 436191739Sobrien if (h->h_master_sat[i] == CDF_SECID_FREE) 437191739Sobrien break; 438191739Sobrien 439328875Seadler#define CDF_SEC_LIMIT (UINT32_MAX / (8 * ss)) 440226048Sobrien if ((nsatpersec > 0 && 441226048Sobrien h->h_num_sectors_in_master_sat > CDF_SEC_LIMIT / nsatpersec) || 442192348Sdelphij i > CDF_SEC_LIMIT) { 443226048Sobrien DPRINTF(("Number of sectors in master SAT too big %u %" 444226048Sobrien SIZE_T_FORMAT "u\n", h->h_num_sectors_in_master_sat, i)); 445192348Sdelphij errno = EFTYPE; 446192348Sdelphij return -1; 447192348Sdelphij } 448192348Sdelphij 449192348Sdelphij sat->sat_len = h->h_num_sectors_in_master_sat * nsatpersec + i; 450226048Sobrien DPRINTF(("sat_len = %" SIZE_T_FORMAT "u ss = %" SIZE_T_FORMAT "u\n", 451226048Sobrien sat->sat_len, ss)); 452328875Seadler if ((sat->sat_tab = CAST(cdf_secid_t *, CDF_CALLOC(sat->sat_len, ss))) 453226048Sobrien == NULL) 454191739Sobrien return -1; 455191739Sobrien 456191739Sobrien for (i = 0; i < __arraycount(h->h_master_sat); i++) { 457191739Sobrien if (h->h_master_sat[i] < 0) 458191739Sobrien break; 459192348Sdelphij if (cdf_read_sector(info, sat->sat_tab, ss * i, ss, h, 460191739Sobrien h->h_master_sat[i]) != (ssize_t)ss) { 461191739Sobrien DPRINTF(("Reading sector %d", h->h_master_sat[i])); 462191739Sobrien goto out1; 463191739Sobrien } 464191739Sobrien } 465191739Sobrien 466328875Seadler if ((msa = CAST(cdf_secid_t *, CDF_CALLOC(1, ss))) == NULL) 467191739Sobrien goto out1; 468191739Sobrien 469191739Sobrien mid = h->h_secid_first_sector_in_master_sat; 470191739Sobrien for (j = 0; j < h->h_num_sectors_in_master_sat; j++) { 471192348Sdelphij if (mid < 0) 472192348Sdelphij goto out; 473191739Sobrien if (j >= CDF_LOOP_LIMIT) { 474191739Sobrien DPRINTF(("Reading master sector loop limit")); 475300899Sdelphij goto out3; 476191739Sobrien } 477192348Sdelphij if (cdf_read_sector(info, msa, 0, ss, h, mid) != (ssize_t)ss) { 478191739Sobrien DPRINTF(("Reading master sector %d", mid)); 479191739Sobrien goto out2; 480191739Sobrien } 481192348Sdelphij for (k = 0; k < nsatpersec; k++, i++) { 482226048Sobrien sec = CDF_TOLE4((uint32_t)msa[k]); 483192348Sdelphij if (sec < 0) 484192348Sdelphij goto out; 485192348Sdelphij if (i >= sat->sat_len) { 486234250Sobrien DPRINTF(("Out of bounds reading MSA %" SIZE_T_FORMAT 487234250Sobrien "u >= %" SIZE_T_FORMAT "u", i, sat->sat_len)); 488300899Sdelphij goto out3; 489192348Sdelphij } 490192348Sdelphij if (cdf_read_sector(info, sat->sat_tab, ss * i, ss, h, 491192348Sdelphij sec) != (ssize_t)ss) { 492191739Sobrien DPRINTF(("Reading sector %d", 493191739Sobrien CDF_TOLE4(msa[k]))); 494191739Sobrien goto out2; 495191739Sobrien } 496192348Sdelphij } 497226048Sobrien mid = CDF_TOLE4((uint32_t)msa[nsatpersec]); 498191739Sobrien } 499192348Sdelphijout: 500192348Sdelphij sat->sat_len = i; 501191739Sobrien free(msa); 502191739Sobrien return 0; 503300899Sdelphijout3: 504300899Sdelphij errno = EFTYPE; 505191739Sobrienout2: 506191739Sobrien free(msa); 507191739Sobrienout1: 508191739Sobrien free(sat->sat_tab); 509191739Sobrien return -1; 510191739Sobrien} 511191739Sobrien 512191739Sobriensize_t 513192348Sdelphijcdf_count_chain(const cdf_sat_t *sat, cdf_secid_t sid, size_t size) 514191739Sobrien{ 515192348Sdelphij size_t i, j; 516267843Sdelphij cdf_secid_t maxsector = (cdf_secid_t)((sat->sat_len * size) 517267843Sdelphij / sizeof(maxsector)); 518191739Sobrien 519191739Sobrien DPRINTF(("Chain:")); 520276415Sdelphij if (sid == CDF_SECID_END_OF_CHAIN) { 521276415Sdelphij /* 0-length chain. */ 522276415Sdelphij DPRINTF((" empty\n")); 523276415Sdelphij return 0; 524276415Sdelphij } 525276415Sdelphij 526191739Sobrien for (j = i = 0; sid >= 0; i++, j++) { 527191739Sobrien DPRINTF((" %d", sid)); 528191739Sobrien if (j >= CDF_LOOP_LIMIT) { 529191739Sobrien DPRINTF(("Counting chain loop limit")); 530300899Sdelphij goto out; 531191739Sobrien } 532267843Sdelphij if (sid >= maxsector) { 533267843Sdelphij DPRINTF(("Sector %d >= %d\n", sid, maxsector)); 534300899Sdelphij goto out; 535191739Sobrien } 536226048Sobrien sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]); 537191739Sobrien } 538267843Sdelphij if (i == 0) { 539267843Sdelphij DPRINTF((" none, sid: %d\n", sid)); 540300899Sdelphij goto out; 541267843Sdelphij 542267843Sdelphij } 543191739Sobrien DPRINTF(("\n")); 544191739Sobrien return i; 545300899Sdelphijout: 546300899Sdelphij errno = EFTYPE; 547300899Sdelphij return (size_t)-1; 548191739Sobrien} 549191739Sobrien 550191739Sobrienint 551192348Sdelphijcdf_read_long_sector_chain(const cdf_info_t *info, const cdf_header_t *h, 552192348Sdelphij const cdf_sat_t *sat, cdf_secid_t sid, size_t len, cdf_stream_t *scn) 553191739Sobrien{ 554191739Sobrien size_t ss = CDF_SEC_SIZE(h), i, j; 555191739Sobrien ssize_t nr; 556300899Sdelphij scn->sst_tab = NULL; 557192348Sdelphij scn->sst_len = cdf_count_chain(sat, sid, ss); 558328875Seadler scn->sst_dirlen = MAX(h->h_min_size_standard_stream, len); 559300899Sdelphij scn->sst_ss = ss; 560191739Sobrien 561328875Seadler if (sid == CDF_SECID_END_OF_CHAIN || len == 0) 562328875Seadler return cdf_zero_stream(scn); 563328875Seadler 564191739Sobrien if (scn->sst_len == (size_t)-1) 565300899Sdelphij goto out; 566191739Sobrien 567328875Seadler scn->sst_tab = CDF_CALLOC(scn->sst_len, ss); 568191739Sobrien if (scn->sst_tab == NULL) 569300899Sdelphij return cdf_zero_stream(scn); 570191739Sobrien 571191739Sobrien for (j = i = 0; sid >= 0; i++, j++) { 572192348Sdelphij if (j >= CDF_LOOP_LIMIT) { 573192348Sdelphij DPRINTF(("Read long sector chain loop limit")); 574192348Sdelphij goto out; 575192348Sdelphij } 576192348Sdelphij if (i >= scn->sst_len) { 577192348Sdelphij DPRINTF(("Out of bounds reading long sector chain " 578234250Sobrien "%" SIZE_T_FORMAT "u > %" SIZE_T_FORMAT "u\n", i, 579234250Sobrien scn->sst_len)); 580192348Sdelphij goto out; 581192348Sdelphij } 582192348Sdelphij if ((nr = cdf_read_sector(info, scn->sst_tab, i * ss, ss, h, 583191739Sobrien sid)) != (ssize_t)ss) { 584191739Sobrien if (i == scn->sst_len - 1 && nr > 0) { 585191739Sobrien /* Last sector might be truncated */ 586191739Sobrien return 0; 587191739Sobrien } 588191739Sobrien DPRINTF(("Reading long sector chain %d", sid)); 589191739Sobrien goto out; 590191739Sobrien } 591226048Sobrien sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]); 592191739Sobrien } 593191739Sobrien return 0; 594191739Sobrienout: 595300899Sdelphij errno = EFTYPE; 596300899Sdelphij return cdf_zero_stream(scn); 597191739Sobrien} 598191739Sobrien 599191739Sobrienint 600191739Sobriencdf_read_short_sector_chain(const cdf_header_t *h, 601191739Sobrien const cdf_sat_t *ssat, const cdf_stream_t *sst, 602191739Sobrien cdf_secid_t sid, size_t len, cdf_stream_t *scn) 603191739Sobrien{ 604191739Sobrien size_t ss = CDF_SHORT_SEC_SIZE(h), i, j; 605300899Sdelphij scn->sst_tab = NULL; 606302555Sdelphij scn->sst_len = cdf_count_chain(ssat, sid, CDF_SEC_SIZE(h)); 607191739Sobrien scn->sst_dirlen = len; 608300899Sdelphij scn->sst_ss = ss; 609191739Sobrien 610302555Sdelphij if (scn->sst_len == (size_t)-1) 611300899Sdelphij goto out; 612191739Sobrien 613328875Seadler scn->sst_tab = CDF_CALLOC(scn->sst_len, ss); 614191739Sobrien if (scn->sst_tab == NULL) 615300899Sdelphij return cdf_zero_stream(scn); 616191739Sobrien 617191739Sobrien for (j = i = 0; sid >= 0; i++, j++) { 618191739Sobrien if (j >= CDF_LOOP_LIMIT) { 619191739Sobrien DPRINTF(("Read short sector chain loop limit")); 620191739Sobrien goto out; 621191739Sobrien } 622192348Sdelphij if (i >= scn->sst_len) { 623192348Sdelphij DPRINTF(("Out of bounds reading short sector chain " 624234250Sobrien "%" SIZE_T_FORMAT "u > %" SIZE_T_FORMAT "u\n", 625234250Sobrien i, scn->sst_len)); 626192348Sdelphij goto out; 627192348Sdelphij } 628191739Sobrien if (cdf_read_short_sector(sst, scn->sst_tab, i * ss, ss, h, 629191739Sobrien sid) != (ssize_t)ss) { 630191739Sobrien DPRINTF(("Reading short sector chain %d", sid)); 631191739Sobrien goto out; 632191739Sobrien } 633226048Sobrien sid = CDF_TOLE4((uint32_t)ssat->sat_tab[sid]); 634191739Sobrien } 635191739Sobrien return 0; 636191739Sobrienout: 637300899Sdelphij errno = EFTYPE; 638300899Sdelphij return cdf_zero_stream(scn); 639191739Sobrien} 640191739Sobrien 641191739Sobrienint 642192348Sdelphijcdf_read_sector_chain(const cdf_info_t *info, const cdf_header_t *h, 643192348Sdelphij const cdf_sat_t *sat, const cdf_sat_t *ssat, const cdf_stream_t *sst, 644191739Sobrien cdf_secid_t sid, size_t len, cdf_stream_t *scn) 645191739Sobrien{ 646191739Sobrien 647226048Sobrien if (len < h->h_min_size_standard_stream && sst->sst_tab != NULL) 648191739Sobrien return cdf_read_short_sector_chain(h, ssat, sst, sid, len, 649191739Sobrien scn); 650191739Sobrien else 651192348Sdelphij return cdf_read_long_sector_chain(info, h, sat, sid, len, scn); 652191739Sobrien} 653191739Sobrien 654191739Sobrienint 655192348Sdelphijcdf_read_dir(const cdf_info_t *info, const cdf_header_t *h, 656192348Sdelphij const cdf_sat_t *sat, cdf_dir_t *dir) 657191739Sobrien{ 658191739Sobrien size_t i, j; 659191739Sobrien size_t ss = CDF_SEC_SIZE(h), ns, nd; 660191739Sobrien char *buf; 661191739Sobrien cdf_secid_t sid = h->h_secid_first_directory; 662191739Sobrien 663192348Sdelphij ns = cdf_count_chain(sat, sid, ss); 664191739Sobrien if (ns == (size_t)-1) 665191739Sobrien return -1; 666191739Sobrien 667191739Sobrien nd = ss / CDF_DIRECTORY_SIZE; 668191739Sobrien 669191739Sobrien dir->dir_len = ns * nd; 670226048Sobrien dir->dir_tab = CAST(cdf_directory_t *, 671328875Seadler CDF_CALLOC(dir->dir_len, sizeof(dir->dir_tab[0]))); 672191739Sobrien if (dir->dir_tab == NULL) 673191739Sobrien return -1; 674191739Sobrien 675328875Seadler if ((buf = CAST(char *, CDF_MALLOC(ss))) == NULL) { 676191739Sobrien free(dir->dir_tab); 677191739Sobrien return -1; 678191739Sobrien } 679191739Sobrien 680191739Sobrien for (j = i = 0; i < ns; i++, j++) { 681191739Sobrien if (j >= CDF_LOOP_LIMIT) { 682191739Sobrien DPRINTF(("Read dir loop limit")); 683191739Sobrien goto out; 684191739Sobrien } 685192348Sdelphij if (cdf_read_sector(info, buf, 0, ss, h, sid) != (ssize_t)ss) { 686191739Sobrien DPRINTF(("Reading directory sector %d", sid)); 687191739Sobrien goto out; 688191739Sobrien } 689191739Sobrien for (j = 0; j < nd; j++) { 690191739Sobrien cdf_unpack_dir(&dir->dir_tab[i * nd + j], 691191739Sobrien &buf[j * CDF_DIRECTORY_SIZE]); 692191739Sobrien } 693226048Sobrien sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]); 694191739Sobrien } 695191739Sobrien if (NEED_SWAP) 696191739Sobrien for (i = 0; i < dir->dir_len; i++) 697191739Sobrien cdf_swap_dir(&dir->dir_tab[i]); 698191739Sobrien free(buf); 699191739Sobrien return 0; 700191739Sobrienout: 701191739Sobrien free(dir->dir_tab); 702191739Sobrien free(buf); 703300899Sdelphij errno = EFTYPE; 704191739Sobrien return -1; 705191739Sobrien} 706191739Sobrien 707191739Sobrien 708191739Sobrienint 709192348Sdelphijcdf_read_ssat(const cdf_info_t *info, const cdf_header_t *h, 710192348Sdelphij const cdf_sat_t *sat, cdf_sat_t *ssat) 711191739Sobrien{ 712191739Sobrien size_t i, j; 713191739Sobrien size_t ss = CDF_SEC_SIZE(h); 714191739Sobrien cdf_secid_t sid = h->h_secid_first_sector_in_short_sat; 715191739Sobrien 716300899Sdelphij ssat->sat_tab = NULL; 717302555Sdelphij ssat->sat_len = cdf_count_chain(sat, sid, ss); 718191739Sobrien if (ssat->sat_len == (size_t)-1) 719300899Sdelphij goto out; 720191739Sobrien 721328875Seadler ssat->sat_tab = CAST(cdf_secid_t *, CDF_CALLOC(ssat->sat_len, ss)); 722191739Sobrien if (ssat->sat_tab == NULL) 723300899Sdelphij goto out1; 724191739Sobrien 725191739Sobrien for (j = i = 0; sid >= 0; i++, j++) { 726191739Sobrien if (j >= CDF_LOOP_LIMIT) { 727191739Sobrien DPRINTF(("Read short sat sector loop limit")); 728191739Sobrien goto out; 729191739Sobrien } 730192348Sdelphij if (i >= ssat->sat_len) { 731192348Sdelphij DPRINTF(("Out of bounds reading short sector chain " 732234250Sobrien "%" SIZE_T_FORMAT "u > %" SIZE_T_FORMAT "u\n", i, 733234250Sobrien ssat->sat_len)); 734192348Sdelphij goto out; 735192348Sdelphij } 736192348Sdelphij if (cdf_read_sector(info, ssat->sat_tab, i * ss, ss, h, sid) != 737191739Sobrien (ssize_t)ss) { 738191739Sobrien DPRINTF(("Reading short sat sector %d", sid)); 739300899Sdelphij goto out1; 740191739Sobrien } 741226048Sobrien sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]); 742191739Sobrien } 743191739Sobrien return 0; 744191739Sobrienout: 745300899Sdelphij errno = EFTYPE; 746300899Sdelphijout1: 747191739Sobrien free(ssat->sat_tab); 748191739Sobrien return -1; 749191739Sobrien} 750191739Sobrien 751191739Sobrienint 752192348Sdelphijcdf_read_short_stream(const cdf_info_t *info, const cdf_header_t *h, 753267843Sdelphij const cdf_sat_t *sat, const cdf_dir_t *dir, cdf_stream_t *scn, 754267843Sdelphij const cdf_directory_t **root) 755191739Sobrien{ 756191739Sobrien size_t i; 757191739Sobrien const cdf_directory_t *d; 758191739Sobrien 759267843Sdelphij *root = NULL; 760191739Sobrien for (i = 0; i < dir->dir_len; i++) 761191739Sobrien if (dir->dir_tab[i].d_type == CDF_DIR_TYPE_ROOT_STORAGE) 762191739Sobrien break; 763191739Sobrien 764192348Sdelphij /* If the it is not there, just fake it; some docs don't have it */ 765309848Sdelphij if (i == dir->dir_len) { 766309848Sdelphij DPRINTF(("Cannot find root storage dir\n")); 767192348Sdelphij goto out; 768309848Sdelphij } 769191739Sobrien d = &dir->dir_tab[i]; 770267843Sdelphij *root = d; 771191739Sobrien 772191739Sobrien /* If the it is not there, just fake it; some docs don't have it */ 773309848Sdelphij if (d->d_stream_first_sector < 0) { 774309848Sdelphij DPRINTF(("No first secror in dir\n")); 775192348Sdelphij goto out; 776309848Sdelphij } 777191739Sobrien 778300899Sdelphij return cdf_read_long_sector_chain(info, h, sat, 779191739Sobrien d->d_stream_first_sector, d->d_size, scn); 780192348Sdelphijout: 781192348Sdelphij scn->sst_tab = NULL; 782300899Sdelphij (void)cdf_zero_stream(scn); 783309848Sdelphij return 0; 784191739Sobrien} 785191739Sobrien 786191739Sobrienstatic int 787191739Sobriencdf_namecmp(const char *d, const uint16_t *s, size_t l) 788191739Sobrien{ 789191739Sobrien for (; l--; d++, s++) 790191739Sobrien if (*d != CDF_TOLE2(*s)) 791191739Sobrien return (unsigned char)*d - CDF_TOLE2(*s); 792191739Sobrien return 0; 793191739Sobrien} 794191739Sobrien 795191739Sobrienint 796309848Sdelphijcdf_read_doc_summary_info(const cdf_info_t *info, const cdf_header_t *h, 797309848Sdelphij const cdf_sat_t *sat, const cdf_sat_t *ssat, const cdf_stream_t *sst, 798309848Sdelphij const cdf_dir_t *dir, cdf_stream_t *scn) 799309848Sdelphij{ 800309848Sdelphij return cdf_read_user_stream(info, h, sat, ssat, sst, dir, 801309848Sdelphij "\05DocumentSummaryInformation", scn); 802309848Sdelphij} 803309848Sdelphij 804309848Sdelphijint 805192348Sdelphijcdf_read_summary_info(const cdf_info_t *info, const cdf_header_t *h, 806191739Sobrien const cdf_sat_t *sat, const cdf_sat_t *ssat, const cdf_stream_t *sst, 807191739Sobrien const cdf_dir_t *dir, cdf_stream_t *scn) 808191739Sobrien{ 809267843Sdelphij return cdf_read_user_stream(info, h, sat, ssat, sst, dir, 810267843Sdelphij "\05SummaryInformation", scn); 811267843Sdelphij} 812267843Sdelphij 813267843Sdelphijint 814267843Sdelphijcdf_read_user_stream(const cdf_info_t *info, const cdf_header_t *h, 815267843Sdelphij const cdf_sat_t *sat, const cdf_sat_t *ssat, const cdf_stream_t *sst, 816267843Sdelphij const cdf_dir_t *dir, const char *name, cdf_stream_t *scn) 817267843Sdelphij{ 818191739Sobrien const cdf_directory_t *d; 819284778Sdelphij int i = cdf_find_stream(dir, name, CDF_DIR_TYPE_USER_STREAM); 820191739Sobrien 821300899Sdelphij if (i <= 0) { 822300899Sdelphij memset(scn, 0, sizeof(*scn)); 823284778Sdelphij return -1; 824300899Sdelphij } 825284778Sdelphij 826284778Sdelphij d = &dir->dir_tab[i - 1]; 827284778Sdelphij return cdf_read_sector_chain(info, h, sat, ssat, sst, 828284778Sdelphij d->d_stream_first_sector, d->d_size, scn); 829284778Sdelphij} 830284778Sdelphij 831284778Sdelphijint 832284778Sdelphijcdf_find_stream(const cdf_dir_t *dir, const char *name, int type) 833284778Sdelphij{ 834284778Sdelphij size_t i, name_len = strlen(name) + 1; 835284778Sdelphij 836226048Sobrien for (i = dir->dir_len; i > 0; i--) 837284778Sdelphij if (dir->dir_tab[i - 1].d_type == type && 838267843Sdelphij cdf_namecmp(name, dir->dir_tab[i - 1].d_name, name_len) 839191739Sobrien == 0) 840191739Sobrien break; 841284778Sdelphij if (i > 0) 842328875Seadler return CAST(int, i); 843191739Sobrien 844284778Sdelphij DPRINTF(("Cannot find type %d `%s'\n", type, name)); 845284778Sdelphij errno = ESRCH; 846284778Sdelphij return 0; 847191739Sobrien} 848191739Sobrien 849328875Seadler#define CDF_SHLEN_LIMIT (UINT32_MAX / 8) 850328875Seadler#define CDF_PROP_LIMIT (UINT32_MAX / (8 * sizeof(cdf_property_info_t))) 851328875Seadler 852328875Seadlerstatic const void * 853328875Seadlercdf_offset(const void *p, size_t l) 854328875Seadler{ 855328875Seadler return CAST(const void *, CAST(const uint8_t *, p) + l); 856328875Seadler} 857328875Seadler 858328875Seadlerstatic const uint8_t * 859328875Seadlercdf_get_property_info_pos(const cdf_stream_t *sst, const cdf_header_t *h, 860328875Seadler const uint8_t *p, const uint8_t *e, size_t i) 861328875Seadler{ 862328875Seadler size_t tail = (i << 1) + 1; 863328875Seadler size_t ofs; 864328875Seadler const uint8_t *q; 865328875Seadler 866328875Seadler if (p >= e) { 867328875Seadler DPRINTF(("Past end %p < %p\n", e, p)); 868328875Seadler return NULL; 869328875Seadler } 870328875Seadler if (cdf_check_stream_offset(sst, h, p, (tail + 1) * sizeof(uint32_t), 871328875Seadler __LINE__) == -1) 872328875Seadler return NULL; 873328875Seadler ofs = CDF_GETUINT32(p, tail); 874328875Seadler q = CAST(const uint8_t *, cdf_offset(CAST(const void *, p), 875328875Seadler ofs - 2 * sizeof(uint32_t))); 876328875Seadler 877328875Seadler if (q < p) { 878328875Seadler DPRINTF(("Wrapped around %p < %p\n", q, p)); 879328875Seadler return NULL; 880328875Seadler } 881328875Seadler 882328875Seadler if (q >= e) { 883328875Seadler DPRINTF(("Ran off the end %p >= %p\n", q, e)); 884328875Seadler return NULL; 885328875Seadler } 886328875Seadler return q; 887328875Seadler} 888328875Seadler 889328875Seadlerstatic cdf_property_info_t * 890328875Seadlercdf_grow_info(cdf_property_info_t **info, size_t *maxcount, size_t incr) 891328875Seadler{ 892328875Seadler cdf_property_info_t *inp; 893328875Seadler size_t newcount = *maxcount + incr; 894328875Seadler 895328875Seadler if (newcount > CDF_PROP_LIMIT) { 896328875Seadler DPRINTF(("exceeded property limit %zu > %zu\n", 897328875Seadler newcount, CDF_PROP_LIMIT)); 898328875Seadler goto out; 899328875Seadler } 900328875Seadler inp = CAST(cdf_property_info_t *, 901328875Seadler CDF_REALLOC(*info, newcount * sizeof(*inp))); 902328875Seadler if (inp == NULL) 903328875Seadler goto out; 904328875Seadler 905328875Seadler *info = inp; 906328875Seadler *maxcount = newcount; 907328875Seadler return inp; 908328875Seadlerout: 909328875Seadler free(*info); 910328875Seadler *maxcount = 0; 911328875Seadler *info = NULL; 912328875Seadler return NULL; 913328875Seadler} 914328875Seadler 915328875Seadlerstatic int 916328875Seadlercdf_copy_info(cdf_property_info_t *inp, const void *p, const void *e, 917328875Seadler size_t len) 918328875Seadler{ 919328875Seadler if (inp->pi_type & CDF_VECTOR) 920328875Seadler return 0; 921328875Seadler 922328875Seadler if ((size_t)(CAST(const char *, e) - CAST(const char *, p)) < len) 923328875Seadler return 0; 924328875Seadler 925328875Seadler (void)memcpy(&inp->pi_val, p, len); 926328875Seadler 927328875Seadler switch (len) { 928328875Seadler case 2: 929328875Seadler inp->pi_u16 = CDF_TOLE2(inp->pi_u16); 930328875Seadler break; 931328875Seadler case 4: 932328875Seadler inp->pi_u32 = CDF_TOLE4(inp->pi_u32); 933328875Seadler break; 934328875Seadler case 8: 935328875Seadler inp->pi_u64 = CDF_TOLE8(inp->pi_u64); 936328875Seadler break; 937328875Seadler default: 938328875Seadler abort(); 939328875Seadler } 940328875Seadler return 1; 941328875Seadler} 942328875Seadler 943191739Sobrienint 944226048Sobriencdf_read_property_info(const cdf_stream_t *sst, const cdf_header_t *h, 945226048Sobrien uint32_t offs, cdf_property_info_t **info, size_t *count, size_t *maxcount) 946191739Sobrien{ 947191739Sobrien const cdf_section_header_t *shp; 948191739Sobrien cdf_section_header_t sh; 949226048Sobrien const uint8_t *p, *q, *e; 950328875Seadler size_t i, o4, nelements, j, slen, left; 951191739Sobrien cdf_property_info_t *inp; 952191739Sobrien 953192348Sdelphij if (offs > UINT32_MAX / 4) { 954192348Sdelphij errno = EFTYPE; 955192348Sdelphij goto out; 956192348Sdelphij } 957328875Seadler shp = CAST(const cdf_section_header_t *, 958328875Seadler cdf_offset(sst->sst_tab, offs)); 959226048Sobrien if (cdf_check_stream_offset(sst, h, shp, sizeof(*shp), __LINE__) == -1) 960192348Sdelphij goto out; 961191739Sobrien sh.sh_len = CDF_TOLE4(shp->sh_len); 962192348Sdelphij if (sh.sh_len > CDF_SHLEN_LIMIT) { 963192348Sdelphij errno = EFTYPE; 964192348Sdelphij goto out; 965192348Sdelphij } 966328875Seadler 967328875Seadler if (cdf_check_stream_offset(sst, h, shp, sh.sh_len, __LINE__) == -1) 968328875Seadler goto out; 969328875Seadler 970191739Sobrien sh.sh_properties = CDF_TOLE4(shp->sh_properties); 971328875Seadler DPRINTF(("section len: %u properties %u\n", sh.sh_len, 972328875Seadler sh.sh_properties)); 973192348Sdelphij if (sh.sh_properties > CDF_PROP_LIMIT) 974192348Sdelphij goto out; 975328875Seadler inp = cdf_grow_info(info, maxcount, sh.sh_properties); 976191739Sobrien if (inp == NULL) 977328875Seadler goto out; 978191739Sobrien inp += *count; 979191739Sobrien *count += sh.sh_properties; 980328875Seadler p = CAST(const uint8_t *, cdf_offset(sst->sst_tab, offs + sizeof(sh))); 981328875Seadler e = CAST(const uint8_t *, cdf_offset(shp, sh.sh_len)); 982328875Seadler if (p >= e || cdf_check_stream_offset(sst, h, e, 0, __LINE__) == -1) 983192348Sdelphij goto out; 984328875Seadler 985191739Sobrien for (i = 0; i < sh.sh_properties; i++) { 986328875Seadler if ((q = cdf_get_property_info_pos(sst, h, p, e, i)) == NULL) 987267843Sdelphij goto out; 988328875Seadler inp[i].pi_id = CDF_GETUINT32(p, i << 1); 989328875Seadler left = CAST(size_t, e - q); 990328875Seadler if (left < sizeof(uint32_t)) { 991328875Seadler DPRINTF(("short info (no type)_\n")); 992276415Sdelphij goto out; 993276415Sdelphij } 994226048Sobrien inp[i].pi_type = CDF_GETUINT32(q, 0); 995328875Seadler DPRINTF(("%" SIZE_T_FORMAT "u) id=%#x type=%#x offs=%#tx,%#x\n", 996234250Sobrien i, inp[i].pi_id, inp[i].pi_type, q - p, offs)); 997191739Sobrien if (inp[i].pi_type & CDF_VECTOR) { 998328875Seadler if (left < sizeof(uint32_t) * 2) { 999328875Seadler DPRINTF(("missing CDF_VECTOR length\n")); 1000328875Seadler goto out; 1001328875Seadler } 1002226048Sobrien nelements = CDF_GETUINT32(q, 1); 1003267843Sdelphij if (nelements == 0) { 1004267843Sdelphij DPRINTF(("CDF_VECTOR with nelements == 0\n")); 1005267843Sdelphij goto out; 1006267843Sdelphij } 1007328875Seadler slen = 2; 1008191739Sobrien } else { 1009191739Sobrien nelements = 1; 1010328875Seadler slen = 1; 1011191739Sobrien } 1012328875Seadler o4 = slen * sizeof(uint32_t); 1013191739Sobrien if (inp[i].pi_type & (CDF_ARRAY|CDF_BYREF|CDF_RESERVED)) 1014191739Sobrien goto unknown; 1015191739Sobrien switch (inp[i].pi_type & CDF_TYPEMASK) { 1016226048Sobrien case CDF_NULL: 1017191739Sobrien case CDF_EMPTY: 1018191739Sobrien break; 1019191739Sobrien case CDF_SIGNED16: 1020328875Seadler if (!cdf_copy_info(&inp[i], &q[o4], e, sizeof(int16_t))) 1021191739Sobrien goto unknown; 1022191739Sobrien break; 1023191739Sobrien case CDF_SIGNED32: 1024191739Sobrien case CDF_BOOL: 1025191739Sobrien case CDF_UNSIGNED32: 1026328875Seadler case CDF_FLOAT: 1027328875Seadler if (!cdf_copy_info(&inp[i], &q[o4], e, sizeof(int32_t))) 1028191739Sobrien goto unknown; 1029191739Sobrien break; 1030191739Sobrien case CDF_SIGNED64: 1031191739Sobrien case CDF_UNSIGNED64: 1032234250Sobrien case CDF_DOUBLE: 1033328875Seadler case CDF_FILETIME: 1034328875Seadler if (!cdf_copy_info(&inp[i], &q[o4], e, sizeof(int64_t))) 1035234250Sobrien goto unknown; 1036234250Sobrien break; 1037191739Sobrien case CDF_LENGTH32_STRING: 1038226048Sobrien case CDF_LENGTH32_WSTRING: 1039191739Sobrien if (nelements > 1) { 1040191739Sobrien size_t nelem = inp - *info; 1041328875Seadler inp = cdf_grow_info(info, maxcount, nelements); 1042328875Seadler if (inp == NULL) 1043192348Sdelphij goto out; 1044328875Seadler inp += nelem; 1045191739Sobrien } 1046234250Sobrien DPRINTF(("nelements = %" SIZE_T_FORMAT "u\n", 1047234250Sobrien nelements)); 1048267843Sdelphij for (j = 0; j < nelements && i < sh.sh_properties; 1049267843Sdelphij j++, i++) 1050267843Sdelphij { 1051328875Seadler uint32_t l; 1052328875Seadler 1053328875Seadler if (o4 + sizeof(uint32_t) > left) 1054328875Seadler goto out; 1055328875Seadler 1056328875Seadler l = CDF_GETUINT32(q, slen); 1057328875Seadler o4 += sizeof(uint32_t); 1058328875Seadler if (o4 + l > left) 1059328875Seadler goto out; 1060328875Seadler 1061191739Sobrien inp[i].pi_str.s_len = l; 1062328875Seadler inp[i].pi_str.s_buf = CAST(const char *, 1063328875Seadler CAST(const void *, &q[o4])); 1064328875Seadler 1065328875Seadler DPRINTF(("o=%zu l=%d(%" SIZE_T_FORMAT 1066328875Seadler "u), t=%zu s=%s\n", o4, l, 1067328875Seadler CDF_ROUND(l, sizeof(l)), left, 1068191739Sobrien inp[i].pi_str.s_buf)); 1069328875Seadler 1070234250Sobrien if (l & 1) 1071234250Sobrien l++; 1072328875Seadler 1073328875Seadler slen += l >> 1; 1074328875Seadler o4 = slen * sizeof(uint32_t); 1075191739Sobrien } 1076191739Sobrien i--; 1077191739Sobrien break; 1078191739Sobrien case CDF_CLIPBOARD: 1079191739Sobrien if (inp[i].pi_type & CDF_VECTOR) 1080191739Sobrien goto unknown; 1081191739Sobrien break; 1082191739Sobrien default: 1083191739Sobrien unknown: 1084328875Seadler memset(&inp[i].pi_val, 0, sizeof(inp[i].pi_val)); 1085328875Seadler DPRINTF(("Don't know how to deal with %#x\n", 1086191739Sobrien inp[i].pi_type)); 1087234250Sobrien break; 1088191739Sobrien } 1089191739Sobrien } 1090191739Sobrien return 0; 1091191739Sobrienout: 1092328875Seadler free(*info); 1093328875Seadler *info = NULL; 1094328875Seadler *count = 0; 1095328875Seadler *maxcount = 0; 1096300899Sdelphij errno = EFTYPE; 1097191739Sobrien return -1; 1098191739Sobrien} 1099191739Sobrien 1100191739Sobrienint 1101226048Sobriencdf_unpack_summary_info(const cdf_stream_t *sst, const cdf_header_t *h, 1102226048Sobrien cdf_summary_info_header_t *ssi, cdf_property_info_t **info, size_t *count) 1103191739Sobrien{ 1104267843Sdelphij size_t maxcount; 1105226048Sobrien const cdf_summary_info_header_t *si = 1106226048Sobrien CAST(const cdf_summary_info_header_t *, sst->sst_tab); 1107226048Sobrien const cdf_section_declaration_t *sd = 1108226048Sobrien CAST(const cdf_section_declaration_t *, (const void *) 1109226048Sobrien ((const char *)sst->sst_tab + CDF_SECTION_DECLARATION_OFFSET)); 1110191739Sobrien 1111226048Sobrien if (cdf_check_stream_offset(sst, h, si, sizeof(*si), __LINE__) == -1 || 1112226048Sobrien cdf_check_stream_offset(sst, h, sd, sizeof(*sd), __LINE__) == -1) 1113192348Sdelphij return -1; 1114191739Sobrien ssi->si_byte_order = CDF_TOLE2(si->si_byte_order); 1115191739Sobrien ssi->si_os_version = CDF_TOLE2(si->si_os_version); 1116191739Sobrien ssi->si_os = CDF_TOLE2(si->si_os); 1117191739Sobrien ssi->si_class = si->si_class; 1118191739Sobrien cdf_swap_class(&ssi->si_class); 1119267843Sdelphij ssi->si_count = CDF_TOLE4(si->si_count); 1120191739Sobrien *count = 0; 1121191739Sobrien maxcount = 0; 1122191739Sobrien *info = NULL; 1123267843Sdelphij if (cdf_read_property_info(sst, h, CDF_TOLE4(sd->sd_offset), info, 1124267843Sdelphij count, &maxcount) == -1) 1125267843Sdelphij return -1; 1126191739Sobrien return 0; 1127191739Sobrien} 1128191739Sobrien 1129191739Sobrien 1130284778Sdelphij#define extract_catalog_field(t, f, l) \ 1131284778Sdelphij if (b + l + sizeof(cep->f) > eb) { \ 1132284778Sdelphij cep->ce_namlen = 0; \ 1133284778Sdelphij break; \ 1134284778Sdelphij } \ 1135284778Sdelphij memcpy(&cep->f, b + (l), sizeof(cep->f)); \ 1136284778Sdelphij ce[i].f = CAST(t, CDF_TOLE(cep->f)) 1137191739Sobrien 1138191739Sobrienint 1139276415Sdelphijcdf_unpack_catalog(const cdf_header_t *h, const cdf_stream_t *sst, 1140276415Sdelphij cdf_catalog_t **cat) 1141276415Sdelphij{ 1142300899Sdelphij size_t ss = cdf_check_stream(sst, h); 1143276415Sdelphij const char *b = CAST(const char *, sst->sst_tab); 1144328875Seadler const char *nb, *eb = b + ss * sst->sst_len; 1145284778Sdelphij size_t nr, i, j, k; 1146276415Sdelphij cdf_catalog_entry_t *ce; 1147276415Sdelphij uint16_t reclen; 1148276415Sdelphij const uint16_t *np; 1149276415Sdelphij 1150284778Sdelphij for (nr = 0;; nr++) { 1151276415Sdelphij memcpy(&reclen, b, sizeof(reclen)); 1152276415Sdelphij reclen = CDF_TOLE2(reclen); 1153276415Sdelphij if (reclen == 0) 1154276415Sdelphij break; 1155276415Sdelphij b += reclen; 1156284778Sdelphij if (b > eb) 1157284778Sdelphij break; 1158276415Sdelphij } 1159302555Sdelphij if (nr == 0) 1160302555Sdelphij return -1; 1161284778Sdelphij nr--; 1162276415Sdelphij *cat = CAST(cdf_catalog_t *, 1163328875Seadler CDF_MALLOC(sizeof(cdf_catalog_t) + nr * sizeof(*ce))); 1164300899Sdelphij if (*cat == NULL) 1165300899Sdelphij return -1; 1166276415Sdelphij ce = (*cat)->cat_e; 1167284778Sdelphij memset(ce, 0, nr * sizeof(*ce)); 1168276415Sdelphij b = CAST(const char *, sst->sst_tab); 1169284778Sdelphij for (j = i = 0; i < nr; b += reclen) { 1170284778Sdelphij cdf_catalog_entry_t *cep = &ce[j]; 1171284778Sdelphij uint16_t rlen; 1172284778Sdelphij 1173284778Sdelphij extract_catalog_field(uint16_t, ce_namlen, 0); 1174284778Sdelphij extract_catalog_field(uint16_t, ce_num, 4); 1175284778Sdelphij extract_catalog_field(uint64_t, ce_timestamp, 8); 1176284778Sdelphij reclen = cep->ce_namlen; 1177284778Sdelphij 1178284778Sdelphij if (reclen < 14) { 1179284778Sdelphij cep->ce_namlen = 0; 1180284778Sdelphij continue; 1181276415Sdelphij } 1182284778Sdelphij 1183284778Sdelphij cep->ce_namlen = __arraycount(cep->ce_name) - 1; 1184284778Sdelphij rlen = reclen - 14; 1185284778Sdelphij if (cep->ce_namlen > rlen) 1186284778Sdelphij cep->ce_namlen = rlen; 1187284778Sdelphij 1188284778Sdelphij np = CAST(const uint16_t *, CAST(const void *, (b + 16))); 1189328875Seadler nb = CAST(const char *, CAST(const void *, 1190328875Seadler (np + cep->ce_namlen))); 1191328875Seadler if (nb > eb) { 1192284778Sdelphij cep->ce_namlen = 0; 1193284778Sdelphij break; 1194284778Sdelphij } 1195284778Sdelphij 1196284778Sdelphij for (k = 0; k < cep->ce_namlen; k++) 1197284778Sdelphij cep->ce_name[k] = np[k]; /* XXX: CDF_TOLE2? */ 1198284778Sdelphij cep->ce_name[cep->ce_namlen] = 0; 1199284778Sdelphij j = i; 1200284778Sdelphij i++; 1201276415Sdelphij } 1202284778Sdelphij (*cat)->cat_num = j; 1203276415Sdelphij return 0; 1204276415Sdelphij} 1205276415Sdelphij 1206276415Sdelphijint 1207191739Sobriencdf_print_classid(char *buf, size_t buflen, const cdf_classid_t *id) 1208191739Sobrien{ 1209191739Sobrien return snprintf(buf, buflen, "%.8x-%.4x-%.4x-%.2x%.2x-" 1210191739Sobrien "%.2x%.2x%.2x%.2x%.2x%.2x", id->cl_dword, id->cl_word[0], 1211191739Sobrien id->cl_word[1], id->cl_two[0], id->cl_two[1], id->cl_six[0], 1212191739Sobrien id->cl_six[1], id->cl_six[2], id->cl_six[3], id->cl_six[4], 1213191739Sobrien id->cl_six[5]); 1214191739Sobrien} 1215191739Sobrien 1216191739Sobrienstatic const struct { 1217191739Sobrien uint32_t v; 1218191739Sobrien const char *n; 1219191739Sobrien} vn[] = { 1220191739Sobrien { CDF_PROPERTY_CODE_PAGE, "Code page" }, 1221191739Sobrien { CDF_PROPERTY_TITLE, "Title" }, 1222191739Sobrien { CDF_PROPERTY_SUBJECT, "Subject" }, 1223191739Sobrien { CDF_PROPERTY_AUTHOR, "Author" }, 1224191739Sobrien { CDF_PROPERTY_KEYWORDS, "Keywords" }, 1225191739Sobrien { CDF_PROPERTY_COMMENTS, "Comments" }, 1226191739Sobrien { CDF_PROPERTY_TEMPLATE, "Template" }, 1227191739Sobrien { CDF_PROPERTY_LAST_SAVED_BY, "Last Saved By" }, 1228191739Sobrien { CDF_PROPERTY_REVISION_NUMBER, "Revision Number" }, 1229191739Sobrien { CDF_PROPERTY_TOTAL_EDITING_TIME, "Total Editing Time" }, 1230191739Sobrien { CDF_PROPERTY_LAST_PRINTED, "Last Printed" }, 1231191739Sobrien { CDF_PROPERTY_CREATE_TIME, "Create Time/Date" }, 1232191739Sobrien { CDF_PROPERTY_LAST_SAVED_TIME, "Last Saved Time/Date" }, 1233191739Sobrien { CDF_PROPERTY_NUMBER_OF_PAGES, "Number of Pages" }, 1234191739Sobrien { CDF_PROPERTY_NUMBER_OF_WORDS, "Number of Words" }, 1235191739Sobrien { CDF_PROPERTY_NUMBER_OF_CHARACTERS, "Number of Characters" }, 1236191739Sobrien { CDF_PROPERTY_THUMBNAIL, "Thumbnail" }, 1237191739Sobrien { CDF_PROPERTY_NAME_OF_APPLICATION, "Name of Creating Application" }, 1238191739Sobrien { CDF_PROPERTY_SECURITY, "Security" }, 1239191739Sobrien { CDF_PROPERTY_LOCALE_ID, "Locale ID" }, 1240191739Sobrien}; 1241191739Sobrien 1242191739Sobrienint 1243191739Sobriencdf_print_property_name(char *buf, size_t bufsiz, uint32_t p) 1244191739Sobrien{ 1245191739Sobrien size_t i; 1246191739Sobrien 1247191739Sobrien for (i = 0; i < __arraycount(vn); i++) 1248191739Sobrien if (vn[i].v == p) 1249191739Sobrien return snprintf(buf, bufsiz, "%s", vn[i].n); 1250328875Seadler return snprintf(buf, bufsiz, "%#x", p); 1251191739Sobrien} 1252191739Sobrien 1253191739Sobrienint 1254191739Sobriencdf_print_elapsed_time(char *buf, size_t bufsiz, cdf_timestamp_t ts) 1255191739Sobrien{ 1256226048Sobrien int len = 0; 1257191739Sobrien int days, hours, mins, secs; 1258191739Sobrien 1259191739Sobrien ts /= CDF_TIME_PREC; 1260226048Sobrien secs = (int)(ts % 60); 1261191739Sobrien ts /= 60; 1262226048Sobrien mins = (int)(ts % 60); 1263191739Sobrien ts /= 60; 1264226048Sobrien hours = (int)(ts % 24); 1265191739Sobrien ts /= 24; 1266226048Sobrien days = (int)ts; 1267191739Sobrien 1268191739Sobrien if (days) { 1269191739Sobrien len += snprintf(buf + len, bufsiz - len, "%dd+", days); 1270226048Sobrien if ((size_t)len >= bufsiz) 1271191739Sobrien return len; 1272191739Sobrien } 1273191739Sobrien 1274191739Sobrien if (days || hours) { 1275191739Sobrien len += snprintf(buf + len, bufsiz - len, "%.2d:", hours); 1276226048Sobrien if ((size_t)len >= bufsiz) 1277191739Sobrien return len; 1278191739Sobrien } 1279191739Sobrien 1280191739Sobrien len += snprintf(buf + len, bufsiz - len, "%.2d:", mins); 1281226048Sobrien if ((size_t)len >= bufsiz) 1282191739Sobrien return len; 1283191739Sobrien 1284191739Sobrien len += snprintf(buf + len, bufsiz - len, "%.2d", secs); 1285191739Sobrien return len; 1286191739Sobrien} 1287191739Sobrien 1288276415Sdelphijchar * 1289276415Sdelphijcdf_u16tos8(char *buf, size_t len, const uint16_t *p) 1290276415Sdelphij{ 1291276415Sdelphij size_t i; 1292276415Sdelphij for (i = 0; i < len && p[i]; i++) 1293276415Sdelphij buf[i] = (char)p[i]; 1294276415Sdelphij buf[i] = '\0'; 1295276415Sdelphij return buf; 1296276415Sdelphij} 1297191739Sobrien 1298191739Sobrien#ifdef CDF_DEBUG 1299191739Sobrienvoid 1300191739Sobriencdf_dump_header(const cdf_header_t *h) 1301191739Sobrien{ 1302191739Sobrien size_t i; 1303191739Sobrien 1304192348Sdelphij#define DUMP(a, b) (void)fprintf(stderr, "%40.40s = " a "\n", # b, h->h_ ## b) 1305192348Sdelphij#define DUMP2(a, b) (void)fprintf(stderr, "%40.40s = " a " (" a ")\n", # b, \ 1306192348Sdelphij h->h_ ## b, 1 << h->h_ ## b) 1307191739Sobrien DUMP("%d", revision); 1308191739Sobrien DUMP("%d", version); 1309328875Seadler DUMP("%#x", byte_order); 1310192348Sdelphij DUMP2("%d", sec_size_p2); 1311192348Sdelphij DUMP2("%d", short_sec_size_p2); 1312191739Sobrien DUMP("%d", num_sectors_in_sat); 1313191739Sobrien DUMP("%d", secid_first_directory); 1314191739Sobrien DUMP("%d", min_size_standard_stream); 1315191739Sobrien DUMP("%d", secid_first_sector_in_short_sat); 1316191739Sobrien DUMP("%d", num_sectors_in_short_sat); 1317191739Sobrien DUMP("%d", secid_first_sector_in_master_sat); 1318191739Sobrien DUMP("%d", num_sectors_in_master_sat); 1319191739Sobrien for (i = 0; i < __arraycount(h->h_master_sat); i++) { 1320191739Sobrien if (h->h_master_sat[i] == CDF_SECID_FREE) 1321191739Sobrien break; 1322276415Sdelphij (void)fprintf(stderr, "%35.35s[%.3" SIZE_T_FORMAT "u] = %d\n", 1323191739Sobrien "master_sat", i, h->h_master_sat[i]); 1324191739Sobrien } 1325191739Sobrien} 1326191739Sobrien 1327191739Sobrienvoid 1328192348Sdelphijcdf_dump_sat(const char *prefix, const cdf_sat_t *sat, size_t size) 1329191739Sobrien{ 1330192348Sdelphij size_t i, j, s = size / sizeof(cdf_secid_t); 1331191739Sobrien 1332191739Sobrien for (i = 0; i < sat->sat_len; i++) { 1333234250Sobrien (void)fprintf(stderr, "%s[%" SIZE_T_FORMAT "u]:\n%.6" 1334234250Sobrien SIZE_T_FORMAT "u: ", prefix, i, i * s); 1335191739Sobrien for (j = 0; j < s; j++) { 1336192348Sdelphij (void)fprintf(stderr, "%5d, ", 1337192348Sdelphij CDF_TOLE4(sat->sat_tab[s * i + j])); 1338191739Sobrien if ((j + 1) % 10 == 0) 1339234250Sobrien (void)fprintf(stderr, "\n%.6" SIZE_T_FORMAT 1340234250Sobrien "u: ", i * s + j + 1); 1341191739Sobrien } 1342192348Sdelphij (void)fprintf(stderr, "\n"); 1343191739Sobrien } 1344191739Sobrien} 1345191739Sobrien 1346191739Sobrienvoid 1347284778Sdelphijcdf_dump(const void *v, size_t len) 1348191739Sobrien{ 1349191739Sobrien size_t i, j; 1350284778Sdelphij const unsigned char *p = v; 1351191739Sobrien char abuf[16]; 1352284778Sdelphij 1353192348Sdelphij (void)fprintf(stderr, "%.4x: ", 0); 1354191739Sobrien for (i = 0, j = 0; i < len; i++, p++) { 1355192348Sdelphij (void)fprintf(stderr, "%.2x ", *p); 1356191739Sobrien abuf[j++] = isprint(*p) ? *p : '.'; 1357191739Sobrien if (j == 16) { 1358191739Sobrien j = 0; 1359191739Sobrien abuf[15] = '\0'; 1360234250Sobrien (void)fprintf(stderr, "%s\n%.4" SIZE_T_FORMAT "x: ", 1361234250Sobrien abuf, i + 1); 1362191739Sobrien } 1363191739Sobrien } 1364192348Sdelphij (void)fprintf(stderr, "\n"); 1365191739Sobrien} 1366191739Sobrien 1367191739Sobrienvoid 1368309848Sdelphijcdf_dump_stream(const cdf_stream_t *sst) 1369191739Sobrien{ 1370300899Sdelphij size_t ss = sst->sst_ss; 1371191739Sobrien cdf_dump(sst->sst_tab, ss * sst->sst_len); 1372191739Sobrien} 1373191739Sobrien 1374191739Sobrienvoid 1375192348Sdelphijcdf_dump_dir(const cdf_info_t *info, const cdf_header_t *h, 1376192348Sdelphij const cdf_sat_t *sat, const cdf_sat_t *ssat, const cdf_stream_t *sst, 1377191739Sobrien const cdf_dir_t *dir) 1378191739Sobrien{ 1379191739Sobrien size_t i, j; 1380191739Sobrien cdf_directory_t *d; 1381191739Sobrien char name[__arraycount(d->d_name)]; 1382191739Sobrien cdf_stream_t scn; 1383191739Sobrien struct timespec ts; 1384191739Sobrien 1385191739Sobrien static const char *types[] = { "empty", "user storage", 1386191739Sobrien "user stream", "lockbytes", "property", "root storage" }; 1387191739Sobrien 1388191739Sobrien for (i = 0; i < dir->dir_len; i++) { 1389267843Sdelphij char buf[26]; 1390191739Sobrien d = &dir->dir_tab[i]; 1391191739Sobrien for (j = 0; j < sizeof(name); j++) 1392191739Sobrien name[j] = (char)CDF_TOLE2(d->d_name[j]); 1393226048Sobrien (void)fprintf(stderr, "Directory %" SIZE_T_FORMAT "u: %s\n", 1394226048Sobrien i, name); 1395191739Sobrien if (d->d_type < __arraycount(types)) 1396192348Sdelphij (void)fprintf(stderr, "Type: %s\n", types[d->d_type]); 1397191739Sobrien else 1398192348Sdelphij (void)fprintf(stderr, "Type: %d\n", d->d_type); 1399192348Sdelphij (void)fprintf(stderr, "Color: %s\n", 1400192348Sdelphij d->d_color ? "black" : "red"); 1401192348Sdelphij (void)fprintf(stderr, "Left child: %d\n", d->d_left_child); 1402192348Sdelphij (void)fprintf(stderr, "Right child: %d\n", d->d_right_child); 1403328875Seadler (void)fprintf(stderr, "Flags: %#x\n", d->d_flags); 1404191739Sobrien cdf_timestamp_to_timespec(&ts, d->d_created); 1405267843Sdelphij (void)fprintf(stderr, "Created %s", cdf_ctime(&ts.tv_sec, buf)); 1406191739Sobrien cdf_timestamp_to_timespec(&ts, d->d_modified); 1407267843Sdelphij (void)fprintf(stderr, "Modified %s", 1408267843Sdelphij cdf_ctime(&ts.tv_sec, buf)); 1409192348Sdelphij (void)fprintf(stderr, "Stream %d\n", d->d_stream_first_sector); 1410192348Sdelphij (void)fprintf(stderr, "Size %d\n", d->d_size); 1411191739Sobrien switch (d->d_type) { 1412191739Sobrien case CDF_DIR_TYPE_USER_STORAGE: 1413192348Sdelphij (void)fprintf(stderr, "Storage: %d\n", d->d_storage); 1414191739Sobrien break; 1415191739Sobrien case CDF_DIR_TYPE_USER_STREAM: 1416191739Sobrien if (sst == NULL) 1417191739Sobrien break; 1418192348Sdelphij if (cdf_read_sector_chain(info, h, sat, ssat, sst, 1419191739Sobrien d->d_stream_first_sector, d->d_size, &scn) == -1) { 1420191739Sobrien warn("Can't read stream for %s at %d len %d", 1421191739Sobrien name, d->d_stream_first_sector, d->d_size); 1422191739Sobrien break; 1423191739Sobrien } 1424309848Sdelphij cdf_dump_stream(&scn); 1425191739Sobrien free(scn.sst_tab); 1426191739Sobrien break; 1427191739Sobrien default: 1428191739Sobrien break; 1429191739Sobrien } 1430226048Sobrien 1431191739Sobrien } 1432191739Sobrien} 1433191739Sobrien 1434191739Sobrienvoid 1435191739Sobriencdf_dump_property_info(const cdf_property_info_t *info, size_t count) 1436191739Sobrien{ 1437191739Sobrien cdf_timestamp_t tp; 1438191739Sobrien struct timespec ts; 1439191739Sobrien char buf[64]; 1440226048Sobrien size_t i, j; 1441191739Sobrien 1442191739Sobrien for (i = 0; i < count; i++) { 1443191739Sobrien cdf_print_property_name(buf, sizeof(buf), info[i].pi_id); 1444226048Sobrien (void)fprintf(stderr, "%" SIZE_T_FORMAT "u) %s: ", i, buf); 1445191739Sobrien switch (info[i].pi_type) { 1446226048Sobrien case CDF_NULL: 1447226048Sobrien break; 1448191739Sobrien case CDF_SIGNED16: 1449192348Sdelphij (void)fprintf(stderr, "signed 16 [%hd]\n", 1450192348Sdelphij info[i].pi_s16); 1451191739Sobrien break; 1452191739Sobrien case CDF_SIGNED32: 1453192348Sdelphij (void)fprintf(stderr, "signed 32 [%d]\n", 1454192348Sdelphij info[i].pi_s32); 1455191739Sobrien break; 1456191739Sobrien case CDF_UNSIGNED32: 1457192348Sdelphij (void)fprintf(stderr, "unsigned 32 [%u]\n", 1458192348Sdelphij info[i].pi_u32); 1459191739Sobrien break; 1460234250Sobrien case CDF_FLOAT: 1461234250Sobrien (void)fprintf(stderr, "float [%g]\n", 1462234250Sobrien info[i].pi_f); 1463234250Sobrien break; 1464234250Sobrien case CDF_DOUBLE: 1465234250Sobrien (void)fprintf(stderr, "double [%g]\n", 1466234250Sobrien info[i].pi_d); 1467234250Sobrien break; 1468191739Sobrien case CDF_LENGTH32_STRING: 1469192348Sdelphij (void)fprintf(stderr, "string %u [%.*s]\n", 1470192348Sdelphij info[i].pi_str.s_len, 1471191739Sobrien info[i].pi_str.s_len, info[i].pi_str.s_buf); 1472191739Sobrien break; 1473226048Sobrien case CDF_LENGTH32_WSTRING: 1474226048Sobrien (void)fprintf(stderr, "string %u [", 1475226048Sobrien info[i].pi_str.s_len); 1476226048Sobrien for (j = 0; j < info[i].pi_str.s_len - 1; j++) 1477226048Sobrien (void)fputc(info[i].pi_str.s_buf[j << 1], stderr); 1478226048Sobrien (void)fprintf(stderr, "]\n"); 1479226048Sobrien break; 1480191739Sobrien case CDF_FILETIME: 1481191739Sobrien tp = info[i].pi_tp; 1482191739Sobrien if (tp < 1000000000000000LL) { 1483191739Sobrien cdf_print_elapsed_time(buf, sizeof(buf), tp); 1484192348Sdelphij (void)fprintf(stderr, "timestamp %s\n", buf); 1485191739Sobrien } else { 1486284778Sdelphij char tbuf[26]; 1487191739Sobrien cdf_timestamp_to_timespec(&ts, tp); 1488192348Sdelphij (void)fprintf(stderr, "timestamp %s", 1489284778Sdelphij cdf_ctime(&ts.tv_sec, tbuf)); 1490191739Sobrien } 1491191739Sobrien break; 1492191739Sobrien case CDF_CLIPBOARD: 1493192348Sdelphij (void)fprintf(stderr, "CLIPBOARD %u\n", info[i].pi_u32); 1494191739Sobrien break; 1495191739Sobrien default: 1496328875Seadler DPRINTF(("Don't know how to deal with %#x\n", 1497191739Sobrien info[i].pi_type)); 1498191739Sobrien break; 1499191739Sobrien } 1500191739Sobrien } 1501191739Sobrien} 1502191739Sobrien 1503191739Sobrien 1504191739Sobrienvoid 1505191739Sobriencdf_dump_summary_info(const cdf_header_t *h, const cdf_stream_t *sst) 1506191739Sobrien{ 1507191739Sobrien char buf[128]; 1508191739Sobrien cdf_summary_info_header_t ssi; 1509191739Sobrien cdf_property_info_t *info; 1510191739Sobrien size_t count; 1511191739Sobrien 1512191739Sobrien (void)&h; 1513226048Sobrien if (cdf_unpack_summary_info(sst, h, &ssi, &info, &count) == -1) 1514191739Sobrien return; 1515328875Seadler (void)fprintf(stderr, "Endian: %#x\n", ssi.si_byte_order); 1516192348Sdelphij (void)fprintf(stderr, "Os Version %d.%d\n", ssi.si_os_version & 0xff, 1517276415Sdelphij ssi.si_os_version >> 8); 1518192348Sdelphij (void)fprintf(stderr, "Os %d\n", ssi.si_os); 1519191739Sobrien cdf_print_classid(buf, sizeof(buf), &ssi.si_class); 1520192348Sdelphij (void)fprintf(stderr, "Class %s\n", buf); 1521192348Sdelphij (void)fprintf(stderr, "Count %d\n", ssi.si_count); 1522191739Sobrien cdf_dump_property_info(info, count); 1523191739Sobrien free(info); 1524191739Sobrien} 1525191739Sobrien 1526276415Sdelphij 1527276415Sdelphijvoid 1528276415Sdelphijcdf_dump_catalog(const cdf_header_t *h, const cdf_stream_t *sst) 1529276415Sdelphij{ 1530276415Sdelphij cdf_catalog_t *cat; 1531276415Sdelphij cdf_unpack_catalog(h, sst, &cat); 1532276415Sdelphij const cdf_catalog_entry_t *ce = cat->cat_e; 1533276415Sdelphij struct timespec ts; 1534276415Sdelphij char tbuf[64], sbuf[256]; 1535276415Sdelphij size_t i; 1536276415Sdelphij 1537276415Sdelphij printf("Catalog:\n"); 1538276415Sdelphij for (i = 0; i < cat->cat_num; i++) { 1539276415Sdelphij cdf_timestamp_to_timespec(&ts, ce[i].ce_timestamp); 1540276415Sdelphij printf("\t%d %s %s", ce[i].ce_num, 1541276415Sdelphij cdf_u16tos8(sbuf, ce[i].ce_namlen, ce[i].ce_name), 1542276415Sdelphij cdf_ctime(&ts.tv_sec, tbuf)); 1543276415Sdelphij } 1544276415Sdelphij free(cat); 1545276415Sdelphij} 1546276415Sdelphij 1547191739Sobrien#endif 1548191739Sobrien 1549191739Sobrien#ifdef TEST 1550191739Sobrienint 1551191739Sobrienmain(int argc, char *argv[]) 1552191739Sobrien{ 1553192348Sdelphij int i; 1554191739Sobrien cdf_header_t h; 1555191739Sobrien cdf_sat_t sat, ssat; 1556191739Sobrien cdf_stream_t sst, scn; 1557191739Sobrien cdf_dir_t dir; 1558192348Sdelphij cdf_info_t info; 1559276415Sdelphij const cdf_directory_t *root; 1560284778Sdelphij#ifdef __linux__ 1561284778Sdelphij#define getprogname() __progname 1562284778Sdelphij extern char *__progname; 1563284778Sdelphij#endif 1564191739Sobrien if (argc < 2) { 1565191739Sobrien (void)fprintf(stderr, "Usage: %s <filename>\n", getprogname()); 1566191739Sobrien return -1; 1567191739Sobrien } 1568191739Sobrien 1569192348Sdelphij info.i_buf = NULL; 1570192348Sdelphij info.i_len = 0; 1571191739Sobrien for (i = 1; i < argc; i++) { 1572192348Sdelphij if ((info.i_fd = open(argv[1], O_RDONLY)) == -1) 1573191739Sobrien err(1, "Cannot open `%s'", argv[1]); 1574191739Sobrien 1575192348Sdelphij if (cdf_read_header(&info, &h) == -1) 1576191739Sobrien err(1, "Cannot read header"); 1577191739Sobrien#ifdef CDF_DEBUG 1578191739Sobrien cdf_dump_header(&h); 1579191739Sobrien#endif 1580191739Sobrien 1581192348Sdelphij if (cdf_read_sat(&info, &h, &sat) == -1) 1582191739Sobrien err(1, "Cannot read sat"); 1583191739Sobrien#ifdef CDF_DEBUG 1584192348Sdelphij cdf_dump_sat("SAT", &sat, CDF_SEC_SIZE(&h)); 1585191739Sobrien#endif 1586191739Sobrien 1587192348Sdelphij if (cdf_read_ssat(&info, &h, &sat, &ssat) == -1) 1588191739Sobrien err(1, "Cannot read ssat"); 1589191739Sobrien#ifdef CDF_DEBUG 1590226048Sobrien cdf_dump_sat("SSAT", &ssat, CDF_SHORT_SEC_SIZE(&h)); 1591191739Sobrien#endif 1592191739Sobrien 1593192348Sdelphij if (cdf_read_dir(&info, &h, &sat, &dir) == -1) 1594191739Sobrien err(1, "Cannot read dir"); 1595191739Sobrien 1596276415Sdelphij if (cdf_read_short_stream(&info, &h, &sat, &dir, &sst, &root) 1597276415Sdelphij == -1) 1598191739Sobrien err(1, "Cannot read short stream"); 1599191739Sobrien#ifdef CDF_DEBUG 1600309848Sdelphij cdf_dump_stream(&sst); 1601191739Sobrien#endif 1602191739Sobrien 1603191739Sobrien#ifdef CDF_DEBUG 1604192348Sdelphij cdf_dump_dir(&info, &h, &sat, &ssat, &sst, &dir); 1605191739Sobrien#endif 1606191739Sobrien 1607191739Sobrien 1608192348Sdelphij if (cdf_read_summary_info(&info, &h, &sat, &ssat, &sst, &dir, 1609191739Sobrien &scn) == -1) 1610276415Sdelphij warn("Cannot read summary info"); 1611191739Sobrien#ifdef CDF_DEBUG 1612276415Sdelphij else 1613276415Sdelphij cdf_dump_summary_info(&h, &scn); 1614191739Sobrien#endif 1615284778Sdelphij if (cdf_read_user_stream(&info, &h, &sat, &ssat, &sst, 1616284778Sdelphij &dir, "Catalog", &scn) == -1) 1617276415Sdelphij warn("Cannot read catalog"); 1618276415Sdelphij#ifdef CDF_DEBUG 1619276415Sdelphij else 1620276415Sdelphij cdf_dump_catalog(&h, &scn); 1621276415Sdelphij#endif 1622191739Sobrien 1623192348Sdelphij (void)close(info.i_fd); 1624191739Sobrien } 1625191739Sobrien 1626191739Sobrien return 0; 1627191739Sobrien} 1628191739Sobrien#endif 1629