cdf.c revision 302221
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 38302221SdelphijFILE_RCSID("@(#)$File: cdf.c,v 1.82 2016/06/01 22:25:25 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))) 76284237Sdelphij#define CDF_TOLE(x) (/*CONSTCOND*/sizeof(x) == 2 ? \ 77284237Sdelphij CDF_TOLE2(CAST(uint16_t, x)) : \ 78284237Sdelphij (/*CONSTCOND*/sizeof(x) == 4 ? \ 79284237Sdelphij CDF_TOLE4(CAST(uint32_t, x)) : \ 80284237Sdelphij CDF_TOLE8(CAST(uint64_t, x)))) 81226048Sobrien#define CDF_GETUINT32(x, y) cdf_getuint32(x, y) 82191739Sobrien 83234250Sobrien 84191739Sobrien/* 85191739Sobrien * swap a short 86191739Sobrien */ 87226048Sobrienstatic uint16_t 88226048Sobrien_cdf_tole2(uint16_t sv) 89191739Sobrien{ 90191739Sobrien uint16_t rv; 91226048Sobrien uint8_t *s = (uint8_t *)(void *)&sv; 92226048Sobrien uint8_t *d = (uint8_t *)(void *)&rv; 93191739Sobrien d[0] = s[1]; 94191739Sobrien d[1] = s[0]; 95191739Sobrien return rv; 96191739Sobrien} 97191739Sobrien 98191739Sobrien/* 99191739Sobrien * swap an int 100191739Sobrien */ 101226048Sobrienstatic uint32_t 102226048Sobrien_cdf_tole4(uint32_t sv) 103191739Sobrien{ 104191739Sobrien uint32_t rv; 105226048Sobrien uint8_t *s = (uint8_t *)(void *)&sv; 106226048Sobrien uint8_t *d = (uint8_t *)(void *)&rv; 107191739Sobrien d[0] = s[3]; 108191739Sobrien d[1] = s[2]; 109191739Sobrien d[2] = s[1]; 110191739Sobrien d[3] = s[0]; 111191739Sobrien return rv; 112191739Sobrien} 113191739Sobrien 114191739Sobrien/* 115191739Sobrien * swap a quad 116191739Sobrien */ 117226048Sobrienstatic uint64_t 118226048Sobrien_cdf_tole8(uint64_t sv) 119191739Sobrien{ 120191739Sobrien uint64_t rv; 121226048Sobrien uint8_t *s = (uint8_t *)(void *)&sv; 122226048Sobrien uint8_t *d = (uint8_t *)(void *)&rv; 123191739Sobrien d[0] = s[7]; 124191739Sobrien d[1] = s[6]; 125191739Sobrien d[2] = s[5]; 126191739Sobrien d[3] = s[4]; 127191739Sobrien d[4] = s[3]; 128191739Sobrien d[5] = s[2]; 129191739Sobrien d[6] = s[1]; 130191739Sobrien d[7] = s[0]; 131191739Sobrien return rv; 132191739Sobrien} 133191739Sobrien 134226048Sobrien/* 135226048Sobrien * grab a uint32_t from a possibly unaligned address, and return it in 136226048Sobrien * the native host order. 137226048Sobrien */ 138226048Sobrienstatic uint32_t 139226048Sobriencdf_getuint32(const uint8_t *p, size_t offs) 140226048Sobrien{ 141226048Sobrien uint32_t rv; 142226048Sobrien (void)memcpy(&rv, p + offs * sizeof(uint32_t), sizeof(rv)); 143226048Sobrien return CDF_TOLE4(rv); 144226048Sobrien} 145226048Sobrien 146191739Sobrien#define CDF_UNPACK(a) \ 147191739Sobrien (void)memcpy(&(a), &buf[len], sizeof(a)), len += sizeof(a) 148191739Sobrien#define CDF_UNPACKA(a) \ 149191739Sobrien (void)memcpy((a), &buf[len], sizeof(a)), len += sizeof(a) 150191739Sobrien 151226048Sobrienuint16_t 152226048Sobriencdf_tole2(uint16_t sv) 153226048Sobrien{ 154226048Sobrien return CDF_TOLE2(sv); 155226048Sobrien} 156226048Sobrien 157226048Sobrienuint32_t 158226048Sobriencdf_tole4(uint32_t sv) 159226048Sobrien{ 160226048Sobrien return CDF_TOLE4(sv); 161226048Sobrien} 162226048Sobrien 163226048Sobrienuint64_t 164226048Sobriencdf_tole8(uint64_t sv) 165226048Sobrien{ 166226048Sobrien return CDF_TOLE8(sv); 167226048Sobrien} 168226048Sobrien 169191739Sobrienvoid 170191739Sobriencdf_swap_header(cdf_header_t *h) 171191739Sobrien{ 172191739Sobrien size_t i; 173191739Sobrien 174191739Sobrien h->h_magic = CDF_TOLE8(h->h_magic); 175191739Sobrien h->h_uuid[0] = CDF_TOLE8(h->h_uuid[0]); 176191739Sobrien h->h_uuid[1] = CDF_TOLE8(h->h_uuid[1]); 177191739Sobrien h->h_revision = CDF_TOLE2(h->h_revision); 178191739Sobrien h->h_version = CDF_TOLE2(h->h_version); 179191739Sobrien h->h_byte_order = CDF_TOLE2(h->h_byte_order); 180191739Sobrien h->h_sec_size_p2 = CDF_TOLE2(h->h_sec_size_p2); 181191739Sobrien h->h_short_sec_size_p2 = CDF_TOLE2(h->h_short_sec_size_p2); 182191739Sobrien h->h_num_sectors_in_sat = CDF_TOLE4(h->h_num_sectors_in_sat); 183191739Sobrien h->h_secid_first_directory = CDF_TOLE4(h->h_secid_first_directory); 184191739Sobrien h->h_min_size_standard_stream = 185191739Sobrien CDF_TOLE4(h->h_min_size_standard_stream); 186191739Sobrien h->h_secid_first_sector_in_short_sat = 187226048Sobrien CDF_TOLE4((uint32_t)h->h_secid_first_sector_in_short_sat); 188191739Sobrien h->h_num_sectors_in_short_sat = 189191739Sobrien CDF_TOLE4(h->h_num_sectors_in_short_sat); 190191739Sobrien h->h_secid_first_sector_in_master_sat = 191226048Sobrien CDF_TOLE4((uint32_t)h->h_secid_first_sector_in_master_sat); 192191739Sobrien h->h_num_sectors_in_master_sat = 193191739Sobrien CDF_TOLE4(h->h_num_sectors_in_master_sat); 194191739Sobrien for (i = 0; i < __arraycount(h->h_master_sat); i++) 195226048Sobrien h->h_master_sat[i] = CDF_TOLE4((uint32_t)h->h_master_sat[i]); 196191739Sobrien} 197191739Sobrien 198191739Sobrienvoid 199191739Sobriencdf_unpack_header(cdf_header_t *h, char *buf) 200191739Sobrien{ 201191739Sobrien size_t i; 202191739Sobrien size_t len = 0; 203191739Sobrien 204191739Sobrien CDF_UNPACK(h->h_magic); 205191739Sobrien CDF_UNPACKA(h->h_uuid); 206191739Sobrien CDF_UNPACK(h->h_revision); 207191739Sobrien CDF_UNPACK(h->h_version); 208191739Sobrien CDF_UNPACK(h->h_byte_order); 209191739Sobrien CDF_UNPACK(h->h_sec_size_p2); 210191739Sobrien CDF_UNPACK(h->h_short_sec_size_p2); 211191739Sobrien CDF_UNPACKA(h->h_unused0); 212191739Sobrien CDF_UNPACK(h->h_num_sectors_in_sat); 213191739Sobrien CDF_UNPACK(h->h_secid_first_directory); 214191739Sobrien CDF_UNPACKA(h->h_unused1); 215191739Sobrien CDF_UNPACK(h->h_min_size_standard_stream); 216191739Sobrien CDF_UNPACK(h->h_secid_first_sector_in_short_sat); 217191739Sobrien CDF_UNPACK(h->h_num_sectors_in_short_sat); 218191739Sobrien CDF_UNPACK(h->h_secid_first_sector_in_master_sat); 219191739Sobrien CDF_UNPACK(h->h_num_sectors_in_master_sat); 220191739Sobrien for (i = 0; i < __arraycount(h->h_master_sat); i++) 221191739Sobrien CDF_UNPACK(h->h_master_sat[i]); 222191739Sobrien} 223191739Sobrien 224191739Sobrienvoid 225191739Sobriencdf_swap_dir(cdf_directory_t *d) 226191739Sobrien{ 227191739Sobrien d->d_namelen = CDF_TOLE2(d->d_namelen); 228226048Sobrien d->d_left_child = CDF_TOLE4((uint32_t)d->d_left_child); 229226048Sobrien d->d_right_child = CDF_TOLE4((uint32_t)d->d_right_child); 230226048Sobrien d->d_storage = CDF_TOLE4((uint32_t)d->d_storage); 231191739Sobrien d->d_storage_uuid[0] = CDF_TOLE8(d->d_storage_uuid[0]); 232191739Sobrien d->d_storage_uuid[1] = CDF_TOLE8(d->d_storage_uuid[1]); 233191739Sobrien d->d_flags = CDF_TOLE4(d->d_flags); 234226048Sobrien d->d_created = CDF_TOLE8((uint64_t)d->d_created); 235226048Sobrien d->d_modified = CDF_TOLE8((uint64_t)d->d_modified); 236226048Sobrien d->d_stream_first_sector = CDF_TOLE4((uint32_t)d->d_stream_first_sector); 237191739Sobrien d->d_size = CDF_TOLE4(d->d_size); 238191739Sobrien} 239191739Sobrien 240191739Sobrienvoid 241191739Sobriencdf_swap_class(cdf_classid_t *d) 242191739Sobrien{ 243191739Sobrien d->cl_dword = CDF_TOLE4(d->cl_dword); 244191739Sobrien d->cl_word[0] = CDF_TOLE2(d->cl_word[0]); 245191739Sobrien d->cl_word[1] = CDF_TOLE2(d->cl_word[1]); 246191739Sobrien} 247191739Sobrien 248191739Sobrienvoid 249191739Sobriencdf_unpack_dir(cdf_directory_t *d, char *buf) 250191739Sobrien{ 251191739Sobrien size_t len = 0; 252191739Sobrien 253191739Sobrien CDF_UNPACKA(d->d_name); 254191739Sobrien CDF_UNPACK(d->d_namelen); 255191739Sobrien CDF_UNPACK(d->d_type); 256191739Sobrien CDF_UNPACK(d->d_color); 257191739Sobrien CDF_UNPACK(d->d_left_child); 258191739Sobrien CDF_UNPACK(d->d_right_child); 259191739Sobrien CDF_UNPACK(d->d_storage); 260191739Sobrien CDF_UNPACKA(d->d_storage_uuid); 261191739Sobrien CDF_UNPACK(d->d_flags); 262191739Sobrien CDF_UNPACK(d->d_created); 263191739Sobrien CDF_UNPACK(d->d_modified); 264191739Sobrien CDF_UNPACK(d->d_stream_first_sector); 265191739Sobrien CDF_UNPACK(d->d_size); 266191739Sobrien CDF_UNPACK(d->d_unused0); 267191739Sobrien} 268191739Sobrien 269192348Sdelphijstatic int 270299736Sdelphijcdf_zero_stream(cdf_stream_t *scn) 271299736Sdelphij{ 272299736Sdelphij scn->sst_len = 0; 273299736Sdelphij scn->sst_dirlen = 0; 274299736Sdelphij scn->sst_ss = 0; 275299736Sdelphij free(scn->sst_tab); 276299736Sdelphij scn->sst_tab = NULL; 277299736Sdelphij return -1; 278299736Sdelphij} 279299736Sdelphij 280299736Sdelphijstatic size_t 281299736Sdelphijcdf_check_stream(const cdf_stream_t *sst, const cdf_header_t *h) 282299736Sdelphij{ 283299736Sdelphij size_t ss = sst->sst_dirlen < h->h_min_size_standard_stream ? 284299736Sdelphij CDF_SHORT_SEC_SIZE(h) : CDF_SEC_SIZE(h); 285299736Sdelphij assert(ss == sst->sst_ss); 286299736Sdelphij return sst->sst_ss; 287299736Sdelphij} 288299736Sdelphij 289299736Sdelphijstatic int 290226048Sobriencdf_check_stream_offset(const cdf_stream_t *sst, const cdf_header_t *h, 291226048Sobrien const void *p, size_t tail, int line) 292192348Sdelphij{ 293192348Sdelphij const char *b = (const char *)sst->sst_tab; 294192348Sdelphij const char *e = ((const char *)p) + tail; 295299736Sdelphij size_t ss = cdf_check_stream(sst, h); 296284237Sdelphij /*LINTED*/(void)&line; 297267843Sdelphij if (e >= b && (size_t)(e - b) <= ss * sst->sst_len) 298192348Sdelphij return 0; 299267843Sdelphij DPRINTF(("%d: offset begin %p < end %p || %" SIZE_T_FORMAT "u" 300267843Sdelphij " > %" SIZE_T_FORMAT "u [%" SIZE_T_FORMAT "u %" 301226048Sobrien SIZE_T_FORMAT "u]\n", line, b, e, (size_t)(e - b), 302267843Sdelphij ss * sst->sst_len, ss, sst->sst_len)); 303192348Sdelphij errno = EFTYPE; 304192348Sdelphij return -1; 305192348Sdelphij} 306192348Sdelphij 307192348Sdelphijstatic ssize_t 308192348Sdelphijcdf_read(const cdf_info_t *info, off_t off, void *buf, size_t len) 309192348Sdelphij{ 310192348Sdelphij size_t siz = (size_t)off + len; 311192348Sdelphij 312299736Sdelphij if ((off_t)(off + len) != (off_t)siz) 313299736Sdelphij goto out; 314192348Sdelphij 315192348Sdelphij if (info->i_buf != NULL && info->i_len >= siz) { 316192348Sdelphij (void)memcpy(buf, &info->i_buf[off], len); 317192348Sdelphij return (ssize_t)len; 318192348Sdelphij } 319192348Sdelphij 320192348Sdelphij if (info->i_fd == -1) 321299736Sdelphij goto out; 322192348Sdelphij 323267843Sdelphij if (pread(info->i_fd, buf, len, off) != (ssize_t)len) 324192348Sdelphij return -1; 325192348Sdelphij 326192348Sdelphij return (ssize_t)len; 327299736Sdelphijout: 328299736Sdelphij errno = EINVAL; 329299736Sdelphij return -1; 330192348Sdelphij} 331192348Sdelphij 332191739Sobrienint 333192348Sdelphijcdf_read_header(const cdf_info_t *info, cdf_header_t *h) 334191739Sobrien{ 335192348Sdelphij char buf[512]; 336192348Sdelphij 337191739Sobrien (void)memcpy(cdf_bo.s, "\01\02\03\04", 4); 338192348Sdelphij if (cdf_read(info, (off_t)0, buf, sizeof(buf)) == -1) 339191739Sobrien return -1; 340191739Sobrien cdf_unpack_header(h, buf); 341191739Sobrien cdf_swap_header(h); 342191739Sobrien if (h->h_magic != CDF_MAGIC) { 343226048Sobrien DPRINTF(("Bad magic 0x%" INT64_T_FORMAT "x != 0x%" 344226048Sobrien INT64_T_FORMAT "x\n", 345192348Sdelphij (unsigned long long)h->h_magic, 346192348Sdelphij (unsigned long long)CDF_MAGIC)); 347192348Sdelphij goto out; 348191739Sobrien } 349192348Sdelphij if (h->h_sec_size_p2 > 20) { 350192348Sdelphij DPRINTF(("Bad sector size 0x%u\n", h->h_sec_size_p2)); 351192348Sdelphij goto out; 352192348Sdelphij } 353192348Sdelphij if (h->h_short_sec_size_p2 > 20) { 354192348Sdelphij DPRINTF(("Bad short sector size 0x%u\n", 355192348Sdelphij h->h_short_sec_size_p2)); 356192348Sdelphij goto out; 357192348Sdelphij } 358191739Sobrien return 0; 359192348Sdelphijout: 360192348Sdelphij errno = EFTYPE; 361192348Sdelphij return -1; 362191739Sobrien} 363191739Sobrien 364191739Sobrien 365191739Sobrienssize_t 366192348Sdelphijcdf_read_sector(const cdf_info_t *info, void *buf, size_t offs, size_t len, 367191739Sobrien const cdf_header_t *h, cdf_secid_t id) 368191739Sobrien{ 369234250Sobrien size_t ss = CDF_SEC_SIZE(h); 370234250Sobrien size_t pos = CDF_SEC_POS(h, id); 371234250Sobrien assert(ss == len); 372234250Sobrien return cdf_read(info, (off_t)pos, ((char *)buf) + offs, len); 373191739Sobrien} 374191739Sobrien 375191739Sobrienssize_t 376191739Sobriencdf_read_short_sector(const cdf_stream_t *sst, void *buf, size_t offs, 377191739Sobrien size_t len, const cdf_header_t *h, cdf_secid_t id) 378191739Sobrien{ 379234250Sobrien size_t ss = CDF_SHORT_SEC_SIZE(h); 380234250Sobrien size_t pos = CDF_SHORT_SEC_POS(h, id); 381234250Sobrien assert(ss == len); 382267843Sdelphij if (pos + len > CDF_SEC_SIZE(h) * sst->sst_len) { 383234250Sobrien DPRINTF(("Out of bounds read %" SIZE_T_FORMAT "u > %" 384234250Sobrien SIZE_T_FORMAT "u\n", 385267843Sdelphij pos + len, CDF_SEC_SIZE(h) * sst->sst_len)); 386299736Sdelphij goto out; 387234250Sobrien } 388191739Sobrien (void)memcpy(((char *)buf) + offs, 389234250Sobrien ((const char *)sst->sst_tab) + pos, len); 390191739Sobrien return len; 391299736Sdelphijout: 392299736Sdelphij errno = EFTYPE; 393299736Sdelphij return -1; 394191739Sobrien} 395191739Sobrien 396191739Sobrien/* 397191739Sobrien * Read the sector allocation table. 398191739Sobrien */ 399191739Sobrienint 400192348Sdelphijcdf_read_sat(const cdf_info_t *info, cdf_header_t *h, cdf_sat_t *sat) 401191739Sobrien{ 402191739Sobrien size_t i, j, k; 403191739Sobrien size_t ss = CDF_SEC_SIZE(h); 404192348Sdelphij cdf_secid_t *msa, mid, sec; 405192348Sdelphij size_t nsatpersec = (ss / sizeof(mid)) - 1; 406191739Sobrien 407191739Sobrien for (i = 0; i < __arraycount(h->h_master_sat); i++) 408191739Sobrien if (h->h_master_sat[i] == CDF_SECID_FREE) 409191739Sobrien break; 410191739Sobrien 411192348Sdelphij#define CDF_SEC_LIMIT (UINT32_MAX / (4 * ss)) 412226048Sobrien if ((nsatpersec > 0 && 413226048Sobrien h->h_num_sectors_in_master_sat > CDF_SEC_LIMIT / nsatpersec) || 414192348Sdelphij i > CDF_SEC_LIMIT) { 415226048Sobrien DPRINTF(("Number of sectors in master SAT too big %u %" 416226048Sobrien SIZE_T_FORMAT "u\n", h->h_num_sectors_in_master_sat, i)); 417192348Sdelphij errno = EFTYPE; 418192348Sdelphij return -1; 419192348Sdelphij } 420192348Sdelphij 421192348Sdelphij sat->sat_len = h->h_num_sectors_in_master_sat * nsatpersec + i; 422226048Sobrien DPRINTF(("sat_len = %" SIZE_T_FORMAT "u ss = %" SIZE_T_FORMAT "u\n", 423226048Sobrien sat->sat_len, ss)); 424226048Sobrien if ((sat->sat_tab = CAST(cdf_secid_t *, calloc(sat->sat_len, ss))) 425226048Sobrien == NULL) 426191739Sobrien return -1; 427191739Sobrien 428191739Sobrien for (i = 0; i < __arraycount(h->h_master_sat); i++) { 429191739Sobrien if (h->h_master_sat[i] < 0) 430191739Sobrien break; 431192348Sdelphij if (cdf_read_sector(info, sat->sat_tab, ss * i, ss, h, 432191739Sobrien h->h_master_sat[i]) != (ssize_t)ss) { 433191739Sobrien DPRINTF(("Reading sector %d", h->h_master_sat[i])); 434191739Sobrien goto out1; 435191739Sobrien } 436191739Sobrien } 437191739Sobrien 438226048Sobrien if ((msa = CAST(cdf_secid_t *, calloc(1, ss))) == NULL) 439191739Sobrien goto out1; 440191739Sobrien 441191739Sobrien mid = h->h_secid_first_sector_in_master_sat; 442191739Sobrien for (j = 0; j < h->h_num_sectors_in_master_sat; j++) { 443192348Sdelphij if (mid < 0) 444192348Sdelphij goto out; 445191739Sobrien if (j >= CDF_LOOP_LIMIT) { 446191739Sobrien DPRINTF(("Reading master sector loop limit")); 447299736Sdelphij goto out3; 448191739Sobrien } 449192348Sdelphij if (cdf_read_sector(info, msa, 0, ss, h, mid) != (ssize_t)ss) { 450191739Sobrien DPRINTF(("Reading master sector %d", mid)); 451191739Sobrien goto out2; 452191739Sobrien } 453192348Sdelphij for (k = 0; k < nsatpersec; k++, i++) { 454226048Sobrien sec = CDF_TOLE4((uint32_t)msa[k]); 455192348Sdelphij if (sec < 0) 456192348Sdelphij goto out; 457192348Sdelphij if (i >= sat->sat_len) { 458234250Sobrien DPRINTF(("Out of bounds reading MSA %" SIZE_T_FORMAT 459234250Sobrien "u >= %" SIZE_T_FORMAT "u", i, sat->sat_len)); 460299736Sdelphij goto out3; 461192348Sdelphij } 462192348Sdelphij if (cdf_read_sector(info, sat->sat_tab, ss * i, ss, h, 463192348Sdelphij sec) != (ssize_t)ss) { 464191739Sobrien DPRINTF(("Reading sector %d", 465191739Sobrien CDF_TOLE4(msa[k]))); 466191739Sobrien goto out2; 467191739Sobrien } 468192348Sdelphij } 469226048Sobrien mid = CDF_TOLE4((uint32_t)msa[nsatpersec]); 470191739Sobrien } 471192348Sdelphijout: 472192348Sdelphij sat->sat_len = i; 473191739Sobrien free(msa); 474191739Sobrien return 0; 475299736Sdelphijout3: 476299736Sdelphij errno = EFTYPE; 477191739Sobrienout2: 478191739Sobrien free(msa); 479191739Sobrienout1: 480191739Sobrien free(sat->sat_tab); 481191739Sobrien return -1; 482191739Sobrien} 483191739Sobrien 484191739Sobriensize_t 485192348Sdelphijcdf_count_chain(const cdf_sat_t *sat, cdf_secid_t sid, size_t size) 486191739Sobrien{ 487192348Sdelphij size_t i, j; 488267843Sdelphij cdf_secid_t maxsector = (cdf_secid_t)((sat->sat_len * size) 489267843Sdelphij / sizeof(maxsector)); 490191739Sobrien 491191739Sobrien DPRINTF(("Chain:")); 492275698Sdelphij if (sid == CDF_SECID_END_OF_CHAIN) { 493275698Sdelphij /* 0-length chain. */ 494275698Sdelphij DPRINTF((" empty\n")); 495275698Sdelphij return 0; 496275698Sdelphij } 497275698Sdelphij 498191739Sobrien for (j = i = 0; sid >= 0; i++, j++) { 499191739Sobrien DPRINTF((" %d", sid)); 500191739Sobrien if (j >= CDF_LOOP_LIMIT) { 501191739Sobrien DPRINTF(("Counting chain loop limit")); 502299736Sdelphij goto out; 503191739Sobrien } 504267843Sdelphij if (sid >= maxsector) { 505267843Sdelphij DPRINTF(("Sector %d >= %d\n", sid, maxsector)); 506299736Sdelphij goto out; 507191739Sobrien } 508226048Sobrien sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]); 509191739Sobrien } 510267843Sdelphij if (i == 0) { 511267843Sdelphij DPRINTF((" none, sid: %d\n", sid)); 512299736Sdelphij goto out; 513267843Sdelphij 514267843Sdelphij } 515191739Sobrien DPRINTF(("\n")); 516191739Sobrien return i; 517299736Sdelphijout: 518299736Sdelphij errno = EFTYPE; 519299736Sdelphij return (size_t)-1; 520191739Sobrien} 521191739Sobrien 522191739Sobrienint 523192348Sdelphijcdf_read_long_sector_chain(const cdf_info_t *info, const cdf_header_t *h, 524192348Sdelphij const cdf_sat_t *sat, cdf_secid_t sid, size_t len, cdf_stream_t *scn) 525191739Sobrien{ 526191739Sobrien size_t ss = CDF_SEC_SIZE(h), i, j; 527191739Sobrien ssize_t nr; 528299736Sdelphij scn->sst_tab = NULL; 529192348Sdelphij scn->sst_len = cdf_count_chain(sat, sid, ss); 530191739Sobrien scn->sst_dirlen = len; 531299736Sdelphij scn->sst_ss = ss; 532191739Sobrien 533191739Sobrien if (scn->sst_len == (size_t)-1) 534299736Sdelphij goto out; 535191739Sobrien 536191739Sobrien scn->sst_tab = calloc(scn->sst_len, ss); 537191739Sobrien if (scn->sst_tab == NULL) 538299736Sdelphij return cdf_zero_stream(scn); 539191739Sobrien 540191739Sobrien for (j = i = 0; sid >= 0; i++, j++) { 541192348Sdelphij if (j >= CDF_LOOP_LIMIT) { 542192348Sdelphij DPRINTF(("Read long sector chain loop limit")); 543192348Sdelphij goto out; 544192348Sdelphij } 545192348Sdelphij if (i >= scn->sst_len) { 546192348Sdelphij DPRINTF(("Out of bounds reading long sector chain " 547234250Sobrien "%" SIZE_T_FORMAT "u > %" SIZE_T_FORMAT "u\n", i, 548234250Sobrien scn->sst_len)); 549192348Sdelphij goto out; 550192348Sdelphij } 551192348Sdelphij if ((nr = cdf_read_sector(info, scn->sst_tab, i * ss, ss, h, 552191739Sobrien sid)) != (ssize_t)ss) { 553191739Sobrien if (i == scn->sst_len - 1 && nr > 0) { 554191739Sobrien /* Last sector might be truncated */ 555191739Sobrien return 0; 556191739Sobrien } 557191739Sobrien DPRINTF(("Reading long sector chain %d", sid)); 558191739Sobrien goto out; 559191739Sobrien } 560226048Sobrien sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]); 561191739Sobrien } 562191739Sobrien return 0; 563191739Sobrienout: 564299736Sdelphij errno = EFTYPE; 565299736Sdelphij return cdf_zero_stream(scn); 566191739Sobrien} 567191739Sobrien 568191739Sobrienint 569191739Sobriencdf_read_short_sector_chain(const cdf_header_t *h, 570191739Sobrien const cdf_sat_t *ssat, const cdf_stream_t *sst, 571191739Sobrien cdf_secid_t sid, size_t len, cdf_stream_t *scn) 572191739Sobrien{ 573191739Sobrien size_t ss = CDF_SHORT_SEC_SIZE(h), i, j; 574299736Sdelphij scn->sst_tab = NULL; 575302221Sdelphij scn->sst_len = cdf_count_chain(ssat, sid, CDF_SEC_SIZE(h)); 576191739Sobrien scn->sst_dirlen = len; 577299736Sdelphij scn->sst_ss = ss; 578191739Sobrien 579302221Sdelphij if (scn->sst_len == (size_t)-1) 580299736Sdelphij goto out; 581191739Sobrien 582191739Sobrien scn->sst_tab = calloc(scn->sst_len, ss); 583191739Sobrien if (scn->sst_tab == NULL) 584299736Sdelphij return cdf_zero_stream(scn); 585191739Sobrien 586191739Sobrien for (j = i = 0; sid >= 0; i++, j++) { 587191739Sobrien if (j >= CDF_LOOP_LIMIT) { 588191739Sobrien DPRINTF(("Read short sector chain loop limit")); 589191739Sobrien goto out; 590191739Sobrien } 591192348Sdelphij if (i >= scn->sst_len) { 592192348Sdelphij DPRINTF(("Out of bounds reading short sector chain " 593234250Sobrien "%" SIZE_T_FORMAT "u > %" SIZE_T_FORMAT "u\n", 594234250Sobrien i, scn->sst_len)); 595192348Sdelphij goto out; 596192348Sdelphij } 597191739Sobrien if (cdf_read_short_sector(sst, scn->sst_tab, i * ss, ss, h, 598191739Sobrien sid) != (ssize_t)ss) { 599191739Sobrien DPRINTF(("Reading short sector chain %d", sid)); 600191739Sobrien goto out; 601191739Sobrien } 602226048Sobrien sid = CDF_TOLE4((uint32_t)ssat->sat_tab[sid]); 603191739Sobrien } 604191739Sobrien return 0; 605191739Sobrienout: 606299736Sdelphij errno = EFTYPE; 607299736Sdelphij return cdf_zero_stream(scn); 608191739Sobrien} 609191739Sobrien 610191739Sobrienint 611192348Sdelphijcdf_read_sector_chain(const cdf_info_t *info, const cdf_header_t *h, 612192348Sdelphij const cdf_sat_t *sat, const cdf_sat_t *ssat, const cdf_stream_t *sst, 613191739Sobrien cdf_secid_t sid, size_t len, cdf_stream_t *scn) 614191739Sobrien{ 615191739Sobrien 616226048Sobrien if (len < h->h_min_size_standard_stream && sst->sst_tab != NULL) 617191739Sobrien return cdf_read_short_sector_chain(h, ssat, sst, sid, len, 618191739Sobrien scn); 619191739Sobrien else 620192348Sdelphij return cdf_read_long_sector_chain(info, h, sat, sid, len, scn); 621191739Sobrien} 622191739Sobrien 623191739Sobrienint 624192348Sdelphijcdf_read_dir(const cdf_info_t *info, const cdf_header_t *h, 625192348Sdelphij const cdf_sat_t *sat, cdf_dir_t *dir) 626191739Sobrien{ 627191739Sobrien size_t i, j; 628191739Sobrien size_t ss = CDF_SEC_SIZE(h), ns, nd; 629191739Sobrien char *buf; 630191739Sobrien cdf_secid_t sid = h->h_secid_first_directory; 631191739Sobrien 632192348Sdelphij ns = cdf_count_chain(sat, sid, ss); 633191739Sobrien if (ns == (size_t)-1) 634191739Sobrien return -1; 635191739Sobrien 636191739Sobrien nd = ss / CDF_DIRECTORY_SIZE; 637191739Sobrien 638191739Sobrien dir->dir_len = ns * nd; 639226048Sobrien dir->dir_tab = CAST(cdf_directory_t *, 640226048Sobrien calloc(dir->dir_len, sizeof(dir->dir_tab[0]))); 641191739Sobrien if (dir->dir_tab == NULL) 642191739Sobrien return -1; 643191739Sobrien 644226048Sobrien if ((buf = CAST(char *, malloc(ss))) == NULL) { 645191739Sobrien free(dir->dir_tab); 646191739Sobrien return -1; 647191739Sobrien } 648191739Sobrien 649191739Sobrien for (j = i = 0; i < ns; i++, j++) { 650191739Sobrien if (j >= CDF_LOOP_LIMIT) { 651191739Sobrien DPRINTF(("Read dir loop limit")); 652191739Sobrien goto out; 653191739Sobrien } 654192348Sdelphij if (cdf_read_sector(info, buf, 0, ss, h, sid) != (ssize_t)ss) { 655191739Sobrien DPRINTF(("Reading directory sector %d", sid)); 656191739Sobrien goto out; 657191739Sobrien } 658191739Sobrien for (j = 0; j < nd; j++) { 659191739Sobrien cdf_unpack_dir(&dir->dir_tab[i * nd + j], 660191739Sobrien &buf[j * CDF_DIRECTORY_SIZE]); 661191739Sobrien } 662226048Sobrien sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]); 663191739Sobrien } 664191739Sobrien if (NEED_SWAP) 665191739Sobrien for (i = 0; i < dir->dir_len; i++) 666191739Sobrien cdf_swap_dir(&dir->dir_tab[i]); 667191739Sobrien free(buf); 668191739Sobrien return 0; 669191739Sobrienout: 670191739Sobrien free(dir->dir_tab); 671191739Sobrien free(buf); 672299736Sdelphij errno = EFTYPE; 673191739Sobrien return -1; 674191739Sobrien} 675191739Sobrien 676191739Sobrien 677191739Sobrienint 678192348Sdelphijcdf_read_ssat(const cdf_info_t *info, const cdf_header_t *h, 679192348Sdelphij const cdf_sat_t *sat, cdf_sat_t *ssat) 680191739Sobrien{ 681191739Sobrien size_t i, j; 682191739Sobrien size_t ss = CDF_SEC_SIZE(h); 683191739Sobrien cdf_secid_t sid = h->h_secid_first_sector_in_short_sat; 684191739Sobrien 685299736Sdelphij ssat->sat_tab = NULL; 686302221Sdelphij ssat->sat_len = cdf_count_chain(sat, sid, ss); 687191739Sobrien if (ssat->sat_len == (size_t)-1) 688299736Sdelphij goto out; 689191739Sobrien 690226048Sobrien ssat->sat_tab = CAST(cdf_secid_t *, calloc(ssat->sat_len, ss)); 691191739Sobrien if (ssat->sat_tab == NULL) 692299736Sdelphij goto out1; 693191739Sobrien 694191739Sobrien for (j = i = 0; sid >= 0; i++, j++) { 695191739Sobrien if (j >= CDF_LOOP_LIMIT) { 696191739Sobrien DPRINTF(("Read short sat sector loop limit")); 697191739Sobrien goto out; 698191739Sobrien } 699192348Sdelphij if (i >= ssat->sat_len) { 700192348Sdelphij DPRINTF(("Out of bounds reading short sector chain " 701234250Sobrien "%" SIZE_T_FORMAT "u > %" SIZE_T_FORMAT "u\n", i, 702234250Sobrien ssat->sat_len)); 703192348Sdelphij goto out; 704192348Sdelphij } 705192348Sdelphij if (cdf_read_sector(info, ssat->sat_tab, i * ss, ss, h, sid) != 706191739Sobrien (ssize_t)ss) { 707191739Sobrien DPRINTF(("Reading short sat sector %d", sid)); 708299736Sdelphij goto out1; 709191739Sobrien } 710226048Sobrien sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]); 711191739Sobrien } 712191739Sobrien return 0; 713191739Sobrienout: 714299736Sdelphij errno = EFTYPE; 715299736Sdelphijout1: 716191739Sobrien free(ssat->sat_tab); 717191739Sobrien return -1; 718191739Sobrien} 719191739Sobrien 720191739Sobrienint 721192348Sdelphijcdf_read_short_stream(const cdf_info_t *info, const cdf_header_t *h, 722267843Sdelphij const cdf_sat_t *sat, const cdf_dir_t *dir, cdf_stream_t *scn, 723267843Sdelphij const cdf_directory_t **root) 724191739Sobrien{ 725191739Sobrien size_t i; 726191739Sobrien const cdf_directory_t *d; 727191739Sobrien 728267843Sdelphij *root = NULL; 729191739Sobrien for (i = 0; i < dir->dir_len; i++) 730191739Sobrien if (dir->dir_tab[i].d_type == CDF_DIR_TYPE_ROOT_STORAGE) 731191739Sobrien break; 732191739Sobrien 733192348Sdelphij /* If the it is not there, just fake it; some docs don't have it */ 734192348Sdelphij if (i == dir->dir_len) 735192348Sdelphij goto out; 736191739Sobrien d = &dir->dir_tab[i]; 737267843Sdelphij *root = d; 738191739Sobrien 739191739Sobrien /* If the it is not there, just fake it; some docs don't have it */ 740192348Sdelphij if (d->d_stream_first_sector < 0) 741192348Sdelphij goto out; 742191739Sobrien 743299736Sdelphij return cdf_read_long_sector_chain(info, h, sat, 744191739Sobrien d->d_stream_first_sector, d->d_size, scn); 745192348Sdelphijout: 746192348Sdelphij scn->sst_tab = NULL; 747299736Sdelphij (void)cdf_zero_stream(scn); 748299736Sdelphij errno = EFTYPE; 749299736Sdelphij return -1; 750191739Sobrien} 751191739Sobrien 752191739Sobrienstatic int 753191739Sobriencdf_namecmp(const char *d, const uint16_t *s, size_t l) 754191739Sobrien{ 755191739Sobrien for (; l--; d++, s++) 756191739Sobrien if (*d != CDF_TOLE2(*s)) 757191739Sobrien return (unsigned char)*d - CDF_TOLE2(*s); 758191739Sobrien return 0; 759191739Sobrien} 760191739Sobrien 761191739Sobrienint 762192348Sdelphijcdf_read_summary_info(const cdf_info_t *info, const cdf_header_t *h, 763191739Sobrien const cdf_sat_t *sat, const cdf_sat_t *ssat, const cdf_stream_t *sst, 764191739Sobrien const cdf_dir_t *dir, cdf_stream_t *scn) 765191739Sobrien{ 766267843Sdelphij return cdf_read_user_stream(info, h, sat, ssat, sst, dir, 767267843Sdelphij "\05SummaryInformation", scn); 768267843Sdelphij} 769267843Sdelphij 770267843Sdelphijint 771267843Sdelphijcdf_read_user_stream(const cdf_info_t *info, const cdf_header_t *h, 772267843Sdelphij const cdf_sat_t *sat, const cdf_sat_t *ssat, const cdf_stream_t *sst, 773267843Sdelphij const cdf_dir_t *dir, const char *name, cdf_stream_t *scn) 774267843Sdelphij{ 775191739Sobrien const cdf_directory_t *d; 776284237Sdelphij int i = cdf_find_stream(dir, name, CDF_DIR_TYPE_USER_STREAM); 777191739Sobrien 778299736Sdelphij if (i <= 0) { 779299736Sdelphij memset(scn, 0, sizeof(*scn)); 780284237Sdelphij return -1; 781299736Sdelphij } 782284237Sdelphij 783284237Sdelphij d = &dir->dir_tab[i - 1]; 784284237Sdelphij return cdf_read_sector_chain(info, h, sat, ssat, sst, 785284237Sdelphij d->d_stream_first_sector, d->d_size, scn); 786284237Sdelphij} 787284237Sdelphij 788284237Sdelphijint 789284237Sdelphijcdf_find_stream(const cdf_dir_t *dir, const char *name, int type) 790284237Sdelphij{ 791284237Sdelphij size_t i, name_len = strlen(name) + 1; 792284237Sdelphij 793226048Sobrien for (i = dir->dir_len; i > 0; i--) 794284237Sdelphij if (dir->dir_tab[i - 1].d_type == type && 795267843Sdelphij cdf_namecmp(name, dir->dir_tab[i - 1].d_name, name_len) 796191739Sobrien == 0) 797191739Sobrien break; 798284237Sdelphij if (i > 0) 799284237Sdelphij return i; 800191739Sobrien 801284237Sdelphij DPRINTF(("Cannot find type %d `%s'\n", type, name)); 802284237Sdelphij errno = ESRCH; 803284237Sdelphij return 0; 804191739Sobrien} 805191739Sobrien 806191739Sobrienint 807226048Sobriencdf_read_property_info(const cdf_stream_t *sst, const cdf_header_t *h, 808226048Sobrien uint32_t offs, cdf_property_info_t **info, size_t *count, size_t *maxcount) 809191739Sobrien{ 810191739Sobrien const cdf_section_header_t *shp; 811191739Sobrien cdf_section_header_t sh; 812226048Sobrien const uint8_t *p, *q, *e; 813191739Sobrien int16_t s16; 814191739Sobrien int32_t s32; 815191739Sobrien uint32_t u32; 816191739Sobrien int64_t s64; 817191739Sobrien uint64_t u64; 818191739Sobrien cdf_timestamp_t tp; 819226048Sobrien size_t i, o, o4, nelements, j; 820191739Sobrien cdf_property_info_t *inp; 821191739Sobrien 822192348Sdelphij if (offs > UINT32_MAX / 4) { 823192348Sdelphij errno = EFTYPE; 824192348Sdelphij goto out; 825192348Sdelphij } 826226048Sobrien shp = CAST(const cdf_section_header_t *, (const void *) 827226048Sobrien ((const char *)sst->sst_tab + offs)); 828226048Sobrien if (cdf_check_stream_offset(sst, h, shp, sizeof(*shp), __LINE__) == -1) 829192348Sdelphij goto out; 830191739Sobrien sh.sh_len = CDF_TOLE4(shp->sh_len); 831192348Sdelphij#define CDF_SHLEN_LIMIT (UINT32_MAX / 8) 832192348Sdelphij if (sh.sh_len > CDF_SHLEN_LIMIT) { 833192348Sdelphij errno = EFTYPE; 834192348Sdelphij goto out; 835192348Sdelphij } 836191739Sobrien sh.sh_properties = CDF_TOLE4(shp->sh_properties); 837192348Sdelphij#define CDF_PROP_LIMIT (UINT32_MAX / (4 * sizeof(*inp))) 838192348Sdelphij if (sh.sh_properties > CDF_PROP_LIMIT) 839192348Sdelphij goto out; 840192348Sdelphij DPRINTF(("section len: %u properties %u\n", sh.sh_len, 841191739Sobrien sh.sh_properties)); 842191739Sobrien if (*maxcount) { 843192348Sdelphij if (*maxcount > CDF_PROP_LIMIT) 844192348Sdelphij goto out; 845191739Sobrien *maxcount += sh.sh_properties; 846226048Sobrien inp = CAST(cdf_property_info_t *, 847226048Sobrien realloc(*info, *maxcount * sizeof(*inp))); 848191739Sobrien } else { 849191739Sobrien *maxcount = sh.sh_properties; 850226048Sobrien inp = CAST(cdf_property_info_t *, 851226048Sobrien malloc(*maxcount * sizeof(*inp))); 852191739Sobrien } 853191739Sobrien if (inp == NULL) 854299736Sdelphij goto out1; 855191739Sobrien *info = inp; 856191739Sobrien inp += *count; 857191739Sobrien *count += sh.sh_properties; 858226048Sobrien p = CAST(const uint8_t *, (const void *) 859226048Sobrien ((const char *)(const void *)sst->sst_tab + 860226048Sobrien offs + sizeof(sh))); 861226048Sobrien e = CAST(const uint8_t *, (const void *) 862226048Sobrien (((const char *)(const void *)shp) + sh.sh_len)); 863226048Sobrien if (cdf_check_stream_offset(sst, h, e, 0, __LINE__) == -1) 864192348Sdelphij goto out; 865191739Sobrien for (i = 0; i < sh.sh_properties; i++) { 866267843Sdelphij size_t tail = (i << 1) + 1; 867275698Sdelphij size_t ofs; 868267843Sdelphij if (cdf_check_stream_offset(sst, h, p, tail * sizeof(uint32_t), 869267843Sdelphij __LINE__) == -1) 870267843Sdelphij goto out; 871275698Sdelphij ofs = CDF_GETUINT32(p, tail); 872226048Sobrien q = (const uint8_t *)(const void *) 873234250Sobrien ((const char *)(const void *)p + ofs 874234250Sobrien - 2 * sizeof(uint32_t)); 875275698Sdelphij if (q < p) { 876275698Sdelphij DPRINTF(("Wrapped around %p < %p\n", q, p)); 877275698Sdelphij goto out; 878275698Sdelphij } 879191739Sobrien if (q > e) { 880191739Sobrien DPRINTF(("Ran of the end %p > %p\n", q, e)); 881191739Sobrien goto out; 882191739Sobrien } 883226048Sobrien inp[i].pi_id = CDF_GETUINT32(p, i << 1); 884226048Sobrien inp[i].pi_type = CDF_GETUINT32(q, 0); 885234250Sobrien DPRINTF(("%" SIZE_T_FORMAT "u) id=%x type=%x offs=0x%tx,0x%x\n", 886234250Sobrien i, inp[i].pi_id, inp[i].pi_type, q - p, offs)); 887191739Sobrien if (inp[i].pi_type & CDF_VECTOR) { 888226048Sobrien nelements = CDF_GETUINT32(q, 1); 889267843Sdelphij if (nelements == 0) { 890267843Sdelphij DPRINTF(("CDF_VECTOR with nelements == 0\n")); 891267843Sdelphij goto out; 892267843Sdelphij } 893191739Sobrien o = 2; 894191739Sobrien } else { 895191739Sobrien nelements = 1; 896191739Sobrien o = 1; 897191739Sobrien } 898226048Sobrien o4 = o * sizeof(uint32_t); 899191739Sobrien if (inp[i].pi_type & (CDF_ARRAY|CDF_BYREF|CDF_RESERVED)) 900191739Sobrien goto unknown; 901191739Sobrien switch (inp[i].pi_type & CDF_TYPEMASK) { 902226048Sobrien case CDF_NULL: 903191739Sobrien case CDF_EMPTY: 904191739Sobrien break; 905191739Sobrien case CDF_SIGNED16: 906191739Sobrien if (inp[i].pi_type & CDF_VECTOR) 907191739Sobrien goto unknown; 908226048Sobrien (void)memcpy(&s16, &q[o4], sizeof(s16)); 909191739Sobrien inp[i].pi_s16 = CDF_TOLE2(s16); 910191739Sobrien break; 911191739Sobrien case CDF_SIGNED32: 912191739Sobrien if (inp[i].pi_type & CDF_VECTOR) 913191739Sobrien goto unknown; 914226048Sobrien (void)memcpy(&s32, &q[o4], sizeof(s32)); 915226048Sobrien inp[i].pi_s32 = CDF_TOLE4((uint32_t)s32); 916191739Sobrien break; 917191739Sobrien case CDF_BOOL: 918191739Sobrien case CDF_UNSIGNED32: 919191739Sobrien if (inp[i].pi_type & CDF_VECTOR) 920191739Sobrien goto unknown; 921226048Sobrien (void)memcpy(&u32, &q[o4], sizeof(u32)); 922191739Sobrien inp[i].pi_u32 = CDF_TOLE4(u32); 923191739Sobrien break; 924191739Sobrien case CDF_SIGNED64: 925191739Sobrien if (inp[i].pi_type & CDF_VECTOR) 926191739Sobrien goto unknown; 927226048Sobrien (void)memcpy(&s64, &q[o4], sizeof(s64)); 928226048Sobrien inp[i].pi_s64 = CDF_TOLE8((uint64_t)s64); 929191739Sobrien break; 930191739Sobrien case CDF_UNSIGNED64: 931191739Sobrien if (inp[i].pi_type & CDF_VECTOR) 932191739Sobrien goto unknown; 933226048Sobrien (void)memcpy(&u64, &q[o4], sizeof(u64)); 934226048Sobrien inp[i].pi_u64 = CDF_TOLE8((uint64_t)u64); 935191739Sobrien break; 936234250Sobrien case CDF_FLOAT: 937234250Sobrien if (inp[i].pi_type & CDF_VECTOR) 938234250Sobrien goto unknown; 939234250Sobrien (void)memcpy(&u32, &q[o4], sizeof(u32)); 940234250Sobrien u32 = CDF_TOLE4(u32); 941234250Sobrien memcpy(&inp[i].pi_f, &u32, sizeof(inp[i].pi_f)); 942234250Sobrien break; 943234250Sobrien case CDF_DOUBLE: 944234250Sobrien if (inp[i].pi_type & CDF_VECTOR) 945234250Sobrien goto unknown; 946234250Sobrien (void)memcpy(&u64, &q[o4], sizeof(u64)); 947234250Sobrien u64 = CDF_TOLE8((uint64_t)u64); 948234250Sobrien memcpy(&inp[i].pi_d, &u64, sizeof(inp[i].pi_d)); 949234250Sobrien break; 950191739Sobrien case CDF_LENGTH32_STRING: 951226048Sobrien case CDF_LENGTH32_WSTRING: 952191739Sobrien if (nelements > 1) { 953191739Sobrien size_t nelem = inp - *info; 954192348Sdelphij if (*maxcount > CDF_PROP_LIMIT 955192348Sdelphij || nelements > CDF_PROP_LIMIT) 956192348Sdelphij goto out; 957191739Sobrien *maxcount += nelements; 958226048Sobrien inp = CAST(cdf_property_info_t *, 959226048Sobrien realloc(*info, *maxcount * sizeof(*inp))); 960191739Sobrien if (inp == NULL) 961299736Sdelphij goto out1; 962191739Sobrien *info = inp; 963191739Sobrien inp = *info + nelem; 964191739Sobrien } 965234250Sobrien DPRINTF(("nelements = %" SIZE_T_FORMAT "u\n", 966234250Sobrien nelements)); 967267843Sdelphij for (j = 0; j < nelements && i < sh.sh_properties; 968267843Sdelphij j++, i++) 969267843Sdelphij { 970226048Sobrien uint32_t l = CDF_GETUINT32(q, o); 971191739Sobrien inp[i].pi_str.s_len = l; 972226048Sobrien inp[i].pi_str.s_buf = (const char *) 973226048Sobrien (const void *)(&q[o4 + sizeof(l)]); 974234250Sobrien DPRINTF(("l = %d, r = %" SIZE_T_FORMAT 975234250Sobrien "u, s = %s\n", l, 976191739Sobrien CDF_ROUND(l, sizeof(l)), 977191739Sobrien inp[i].pi_str.s_buf)); 978234250Sobrien if (l & 1) 979234250Sobrien l++; 980234250Sobrien o += l >> 1; 981234250Sobrien if (q + o >= e) 982234250Sobrien goto out; 983226048Sobrien o4 = o * sizeof(uint32_t); 984191739Sobrien } 985191739Sobrien i--; 986191739Sobrien break; 987191739Sobrien case CDF_FILETIME: 988191739Sobrien if (inp[i].pi_type & CDF_VECTOR) 989191739Sobrien goto unknown; 990226048Sobrien (void)memcpy(&tp, &q[o4], sizeof(tp)); 991226048Sobrien inp[i].pi_tp = CDF_TOLE8((uint64_t)tp); 992191739Sobrien break; 993191739Sobrien case CDF_CLIPBOARD: 994191739Sobrien if (inp[i].pi_type & CDF_VECTOR) 995191739Sobrien goto unknown; 996191739Sobrien break; 997191739Sobrien default: 998191739Sobrien unknown: 999191739Sobrien DPRINTF(("Don't know how to deal with %x\n", 1000191739Sobrien inp[i].pi_type)); 1001234250Sobrien break; 1002191739Sobrien } 1003191739Sobrien } 1004191739Sobrien return 0; 1005191739Sobrienout: 1006299736Sdelphij errno = EFTYPE; 1007299736Sdelphijout1: 1008191739Sobrien free(*info); 1009191739Sobrien return -1; 1010191739Sobrien} 1011191739Sobrien 1012191739Sobrienint 1013226048Sobriencdf_unpack_summary_info(const cdf_stream_t *sst, const cdf_header_t *h, 1014226048Sobrien cdf_summary_info_header_t *ssi, cdf_property_info_t **info, size_t *count) 1015191739Sobrien{ 1016267843Sdelphij size_t maxcount; 1017226048Sobrien const cdf_summary_info_header_t *si = 1018226048Sobrien CAST(const cdf_summary_info_header_t *, sst->sst_tab); 1019226048Sobrien const cdf_section_declaration_t *sd = 1020226048Sobrien CAST(const cdf_section_declaration_t *, (const void *) 1021226048Sobrien ((const char *)sst->sst_tab + CDF_SECTION_DECLARATION_OFFSET)); 1022191739Sobrien 1023226048Sobrien if (cdf_check_stream_offset(sst, h, si, sizeof(*si), __LINE__) == -1 || 1024226048Sobrien cdf_check_stream_offset(sst, h, sd, sizeof(*sd), __LINE__) == -1) 1025192348Sdelphij return -1; 1026191739Sobrien ssi->si_byte_order = CDF_TOLE2(si->si_byte_order); 1027191739Sobrien ssi->si_os_version = CDF_TOLE2(si->si_os_version); 1028191739Sobrien ssi->si_os = CDF_TOLE2(si->si_os); 1029191739Sobrien ssi->si_class = si->si_class; 1030191739Sobrien cdf_swap_class(&ssi->si_class); 1031267843Sdelphij ssi->si_count = CDF_TOLE4(si->si_count); 1032191739Sobrien *count = 0; 1033191739Sobrien maxcount = 0; 1034191739Sobrien *info = NULL; 1035267843Sdelphij if (cdf_read_property_info(sst, h, CDF_TOLE4(sd->sd_offset), info, 1036267843Sdelphij count, &maxcount) == -1) 1037267843Sdelphij return -1; 1038191739Sobrien return 0; 1039191739Sobrien} 1040191739Sobrien 1041191739Sobrien 1042284237Sdelphij#define extract_catalog_field(t, f, l) \ 1043284237Sdelphij if (b + l + sizeof(cep->f) > eb) { \ 1044284237Sdelphij cep->ce_namlen = 0; \ 1045284237Sdelphij break; \ 1046284237Sdelphij } \ 1047284237Sdelphij memcpy(&cep->f, b + (l), sizeof(cep->f)); \ 1048284237Sdelphij ce[i].f = CAST(t, CDF_TOLE(cep->f)) 1049191739Sobrien 1050191739Sobrienint 1051275698Sdelphijcdf_unpack_catalog(const cdf_header_t *h, const cdf_stream_t *sst, 1052275698Sdelphij cdf_catalog_t **cat) 1053275698Sdelphij{ 1054299736Sdelphij size_t ss = cdf_check_stream(sst, h); 1055275698Sdelphij const char *b = CAST(const char *, sst->sst_tab); 1056275698Sdelphij const char *eb = b + ss * sst->sst_len; 1057284237Sdelphij size_t nr, i, j, k; 1058275698Sdelphij cdf_catalog_entry_t *ce; 1059275698Sdelphij uint16_t reclen; 1060275698Sdelphij const uint16_t *np; 1061275698Sdelphij 1062284237Sdelphij for (nr = 0;; nr++) { 1063275698Sdelphij memcpy(&reclen, b, sizeof(reclen)); 1064275698Sdelphij reclen = CDF_TOLE2(reclen); 1065275698Sdelphij if (reclen == 0) 1066275698Sdelphij break; 1067275698Sdelphij b += reclen; 1068284237Sdelphij if (b > eb) 1069284237Sdelphij break; 1070275698Sdelphij } 1071302221Sdelphij if (nr == 0) 1072302221Sdelphij return -1; 1073284237Sdelphij nr--; 1074275698Sdelphij *cat = CAST(cdf_catalog_t *, 1075275698Sdelphij malloc(sizeof(cdf_catalog_t) + nr * sizeof(*ce))); 1076299736Sdelphij if (*cat == NULL) 1077299736Sdelphij return -1; 1078275698Sdelphij ce = (*cat)->cat_e; 1079284237Sdelphij memset(ce, 0, nr * sizeof(*ce)); 1080275698Sdelphij b = CAST(const char *, sst->sst_tab); 1081284237Sdelphij for (j = i = 0; i < nr; b += reclen) { 1082284237Sdelphij cdf_catalog_entry_t *cep = &ce[j]; 1083284237Sdelphij uint16_t rlen; 1084284237Sdelphij 1085284237Sdelphij extract_catalog_field(uint16_t, ce_namlen, 0); 1086284237Sdelphij extract_catalog_field(uint16_t, ce_num, 4); 1087284237Sdelphij extract_catalog_field(uint64_t, ce_timestamp, 8); 1088284237Sdelphij reclen = cep->ce_namlen; 1089284237Sdelphij 1090284237Sdelphij if (reclen < 14) { 1091284237Sdelphij cep->ce_namlen = 0; 1092284237Sdelphij continue; 1093275698Sdelphij } 1094284237Sdelphij 1095284237Sdelphij cep->ce_namlen = __arraycount(cep->ce_name) - 1; 1096284237Sdelphij rlen = reclen - 14; 1097284237Sdelphij if (cep->ce_namlen > rlen) 1098284237Sdelphij cep->ce_namlen = rlen; 1099284237Sdelphij 1100284237Sdelphij np = CAST(const uint16_t *, CAST(const void *, (b + 16))); 1101284237Sdelphij if (CAST(const char *, np + cep->ce_namlen) > eb) { 1102284237Sdelphij cep->ce_namlen = 0; 1103284237Sdelphij break; 1104284237Sdelphij } 1105284237Sdelphij 1106284237Sdelphij for (k = 0; k < cep->ce_namlen; k++) 1107284237Sdelphij cep->ce_name[k] = np[k]; /* XXX: CDF_TOLE2? */ 1108284237Sdelphij cep->ce_name[cep->ce_namlen] = 0; 1109284237Sdelphij j = i; 1110284237Sdelphij i++; 1111275698Sdelphij } 1112284237Sdelphij (*cat)->cat_num = j; 1113275698Sdelphij return 0; 1114275698Sdelphij} 1115275698Sdelphij 1116275698Sdelphijint 1117191739Sobriencdf_print_classid(char *buf, size_t buflen, const cdf_classid_t *id) 1118191739Sobrien{ 1119191739Sobrien return snprintf(buf, buflen, "%.8x-%.4x-%.4x-%.2x%.2x-" 1120191739Sobrien "%.2x%.2x%.2x%.2x%.2x%.2x", id->cl_dword, id->cl_word[0], 1121191739Sobrien id->cl_word[1], id->cl_two[0], id->cl_two[1], id->cl_six[0], 1122191739Sobrien id->cl_six[1], id->cl_six[2], id->cl_six[3], id->cl_six[4], 1123191739Sobrien id->cl_six[5]); 1124191739Sobrien} 1125191739Sobrien 1126191739Sobrienstatic const struct { 1127191739Sobrien uint32_t v; 1128191739Sobrien const char *n; 1129191739Sobrien} vn[] = { 1130191739Sobrien { CDF_PROPERTY_CODE_PAGE, "Code page" }, 1131191739Sobrien { CDF_PROPERTY_TITLE, "Title" }, 1132191739Sobrien { CDF_PROPERTY_SUBJECT, "Subject" }, 1133191739Sobrien { CDF_PROPERTY_AUTHOR, "Author" }, 1134191739Sobrien { CDF_PROPERTY_KEYWORDS, "Keywords" }, 1135191739Sobrien { CDF_PROPERTY_COMMENTS, "Comments" }, 1136191739Sobrien { CDF_PROPERTY_TEMPLATE, "Template" }, 1137191739Sobrien { CDF_PROPERTY_LAST_SAVED_BY, "Last Saved By" }, 1138191739Sobrien { CDF_PROPERTY_REVISION_NUMBER, "Revision Number" }, 1139191739Sobrien { CDF_PROPERTY_TOTAL_EDITING_TIME, "Total Editing Time" }, 1140191739Sobrien { CDF_PROPERTY_LAST_PRINTED, "Last Printed" }, 1141191739Sobrien { CDF_PROPERTY_CREATE_TIME, "Create Time/Date" }, 1142191739Sobrien { CDF_PROPERTY_LAST_SAVED_TIME, "Last Saved Time/Date" }, 1143191739Sobrien { CDF_PROPERTY_NUMBER_OF_PAGES, "Number of Pages" }, 1144191739Sobrien { CDF_PROPERTY_NUMBER_OF_WORDS, "Number of Words" }, 1145191739Sobrien { CDF_PROPERTY_NUMBER_OF_CHARACTERS, "Number of Characters" }, 1146191739Sobrien { CDF_PROPERTY_THUMBNAIL, "Thumbnail" }, 1147191739Sobrien { CDF_PROPERTY_NAME_OF_APPLICATION, "Name of Creating Application" }, 1148191739Sobrien { CDF_PROPERTY_SECURITY, "Security" }, 1149191739Sobrien { CDF_PROPERTY_LOCALE_ID, "Locale ID" }, 1150191739Sobrien}; 1151191739Sobrien 1152191739Sobrienint 1153191739Sobriencdf_print_property_name(char *buf, size_t bufsiz, uint32_t p) 1154191739Sobrien{ 1155191739Sobrien size_t i; 1156191739Sobrien 1157191739Sobrien for (i = 0; i < __arraycount(vn); i++) 1158191739Sobrien if (vn[i].v == p) 1159191739Sobrien return snprintf(buf, bufsiz, "%s", vn[i].n); 1160191739Sobrien return snprintf(buf, bufsiz, "0x%x", p); 1161191739Sobrien} 1162191739Sobrien 1163191739Sobrienint 1164191739Sobriencdf_print_elapsed_time(char *buf, size_t bufsiz, cdf_timestamp_t ts) 1165191739Sobrien{ 1166226048Sobrien int len = 0; 1167191739Sobrien int days, hours, mins, secs; 1168191739Sobrien 1169191739Sobrien ts /= CDF_TIME_PREC; 1170226048Sobrien secs = (int)(ts % 60); 1171191739Sobrien ts /= 60; 1172226048Sobrien mins = (int)(ts % 60); 1173191739Sobrien ts /= 60; 1174226048Sobrien hours = (int)(ts % 24); 1175191739Sobrien ts /= 24; 1176226048Sobrien days = (int)ts; 1177191739Sobrien 1178191739Sobrien if (days) { 1179191739Sobrien len += snprintf(buf + len, bufsiz - len, "%dd+", days); 1180226048Sobrien if ((size_t)len >= bufsiz) 1181191739Sobrien return len; 1182191739Sobrien } 1183191739Sobrien 1184191739Sobrien if (days || hours) { 1185191739Sobrien len += snprintf(buf + len, bufsiz - len, "%.2d:", hours); 1186226048Sobrien if ((size_t)len >= bufsiz) 1187191739Sobrien return len; 1188191739Sobrien } 1189191739Sobrien 1190191739Sobrien len += snprintf(buf + len, bufsiz - len, "%.2d:", mins); 1191226048Sobrien if ((size_t)len >= bufsiz) 1192191739Sobrien return len; 1193191739Sobrien 1194191739Sobrien len += snprintf(buf + len, bufsiz - len, "%.2d", secs); 1195191739Sobrien return len; 1196191739Sobrien} 1197191739Sobrien 1198275698Sdelphijchar * 1199275698Sdelphijcdf_u16tos8(char *buf, size_t len, const uint16_t *p) 1200275698Sdelphij{ 1201275698Sdelphij size_t i; 1202275698Sdelphij for (i = 0; i < len && p[i]; i++) 1203275698Sdelphij buf[i] = (char)p[i]; 1204275698Sdelphij buf[i] = '\0'; 1205275698Sdelphij return buf; 1206275698Sdelphij} 1207191739Sobrien 1208191739Sobrien#ifdef CDF_DEBUG 1209191739Sobrienvoid 1210191739Sobriencdf_dump_header(const cdf_header_t *h) 1211191739Sobrien{ 1212191739Sobrien size_t i; 1213191739Sobrien 1214192348Sdelphij#define DUMP(a, b) (void)fprintf(stderr, "%40.40s = " a "\n", # b, h->h_ ## b) 1215192348Sdelphij#define DUMP2(a, b) (void)fprintf(stderr, "%40.40s = " a " (" a ")\n", # b, \ 1216192348Sdelphij h->h_ ## b, 1 << h->h_ ## b) 1217191739Sobrien DUMP("%d", revision); 1218191739Sobrien DUMP("%d", version); 1219191739Sobrien DUMP("0x%x", byte_order); 1220192348Sdelphij DUMP2("%d", sec_size_p2); 1221192348Sdelphij DUMP2("%d", short_sec_size_p2); 1222191739Sobrien DUMP("%d", num_sectors_in_sat); 1223191739Sobrien DUMP("%d", secid_first_directory); 1224191739Sobrien DUMP("%d", min_size_standard_stream); 1225191739Sobrien DUMP("%d", secid_first_sector_in_short_sat); 1226191739Sobrien DUMP("%d", num_sectors_in_short_sat); 1227191739Sobrien DUMP("%d", secid_first_sector_in_master_sat); 1228191739Sobrien DUMP("%d", num_sectors_in_master_sat); 1229191739Sobrien for (i = 0; i < __arraycount(h->h_master_sat); i++) { 1230191739Sobrien if (h->h_master_sat[i] == CDF_SECID_FREE) 1231191739Sobrien break; 1232275698Sdelphij (void)fprintf(stderr, "%35.35s[%.3" SIZE_T_FORMAT "u] = %d\n", 1233191739Sobrien "master_sat", i, h->h_master_sat[i]); 1234191739Sobrien } 1235191739Sobrien} 1236191739Sobrien 1237191739Sobrienvoid 1238192348Sdelphijcdf_dump_sat(const char *prefix, const cdf_sat_t *sat, size_t size) 1239191739Sobrien{ 1240192348Sdelphij size_t i, j, s = size / sizeof(cdf_secid_t); 1241191739Sobrien 1242191739Sobrien for (i = 0; i < sat->sat_len; i++) { 1243234250Sobrien (void)fprintf(stderr, "%s[%" SIZE_T_FORMAT "u]:\n%.6" 1244234250Sobrien SIZE_T_FORMAT "u: ", prefix, i, i * s); 1245191739Sobrien for (j = 0; j < s; j++) { 1246192348Sdelphij (void)fprintf(stderr, "%5d, ", 1247192348Sdelphij CDF_TOLE4(sat->sat_tab[s * i + j])); 1248191739Sobrien if ((j + 1) % 10 == 0) 1249234250Sobrien (void)fprintf(stderr, "\n%.6" SIZE_T_FORMAT 1250234250Sobrien "u: ", i * s + j + 1); 1251191739Sobrien } 1252192348Sdelphij (void)fprintf(stderr, "\n"); 1253191739Sobrien } 1254191739Sobrien} 1255191739Sobrien 1256191739Sobrienvoid 1257284237Sdelphijcdf_dump(const void *v, size_t len) 1258191739Sobrien{ 1259191739Sobrien size_t i, j; 1260284237Sdelphij const unsigned char *p = v; 1261191739Sobrien char abuf[16]; 1262284237Sdelphij 1263192348Sdelphij (void)fprintf(stderr, "%.4x: ", 0); 1264191739Sobrien for (i = 0, j = 0; i < len; i++, p++) { 1265192348Sdelphij (void)fprintf(stderr, "%.2x ", *p); 1266191739Sobrien abuf[j++] = isprint(*p) ? *p : '.'; 1267191739Sobrien if (j == 16) { 1268191739Sobrien j = 0; 1269191739Sobrien abuf[15] = '\0'; 1270234250Sobrien (void)fprintf(stderr, "%s\n%.4" SIZE_T_FORMAT "x: ", 1271234250Sobrien abuf, i + 1); 1272191739Sobrien } 1273191739Sobrien } 1274192348Sdelphij (void)fprintf(stderr, "\n"); 1275191739Sobrien} 1276191739Sobrien 1277191739Sobrienvoid 1278191739Sobriencdf_dump_stream(const cdf_header_t *h, const cdf_stream_t *sst) 1279191739Sobrien{ 1280299736Sdelphij size_t ss = sst->sst_ss; 1281191739Sobrien cdf_dump(sst->sst_tab, ss * sst->sst_len); 1282191739Sobrien} 1283191739Sobrien 1284191739Sobrienvoid 1285192348Sdelphijcdf_dump_dir(const cdf_info_t *info, const cdf_header_t *h, 1286192348Sdelphij const cdf_sat_t *sat, const cdf_sat_t *ssat, const cdf_stream_t *sst, 1287191739Sobrien const cdf_dir_t *dir) 1288191739Sobrien{ 1289191739Sobrien size_t i, j; 1290191739Sobrien cdf_directory_t *d; 1291191739Sobrien char name[__arraycount(d->d_name)]; 1292191739Sobrien cdf_stream_t scn; 1293191739Sobrien struct timespec ts; 1294191739Sobrien 1295191739Sobrien static const char *types[] = { "empty", "user storage", 1296191739Sobrien "user stream", "lockbytes", "property", "root storage" }; 1297191739Sobrien 1298191739Sobrien for (i = 0; i < dir->dir_len; i++) { 1299267843Sdelphij char buf[26]; 1300191739Sobrien d = &dir->dir_tab[i]; 1301191739Sobrien for (j = 0; j < sizeof(name); j++) 1302191739Sobrien name[j] = (char)CDF_TOLE2(d->d_name[j]); 1303226048Sobrien (void)fprintf(stderr, "Directory %" SIZE_T_FORMAT "u: %s\n", 1304226048Sobrien i, name); 1305191739Sobrien if (d->d_type < __arraycount(types)) 1306192348Sdelphij (void)fprintf(stderr, "Type: %s\n", types[d->d_type]); 1307191739Sobrien else 1308192348Sdelphij (void)fprintf(stderr, "Type: %d\n", d->d_type); 1309192348Sdelphij (void)fprintf(stderr, "Color: %s\n", 1310192348Sdelphij d->d_color ? "black" : "red"); 1311192348Sdelphij (void)fprintf(stderr, "Left child: %d\n", d->d_left_child); 1312192348Sdelphij (void)fprintf(stderr, "Right child: %d\n", d->d_right_child); 1313192348Sdelphij (void)fprintf(stderr, "Flags: 0x%x\n", d->d_flags); 1314191739Sobrien cdf_timestamp_to_timespec(&ts, d->d_created); 1315267843Sdelphij (void)fprintf(stderr, "Created %s", cdf_ctime(&ts.tv_sec, buf)); 1316191739Sobrien cdf_timestamp_to_timespec(&ts, d->d_modified); 1317267843Sdelphij (void)fprintf(stderr, "Modified %s", 1318267843Sdelphij cdf_ctime(&ts.tv_sec, buf)); 1319192348Sdelphij (void)fprintf(stderr, "Stream %d\n", d->d_stream_first_sector); 1320192348Sdelphij (void)fprintf(stderr, "Size %d\n", d->d_size); 1321191739Sobrien switch (d->d_type) { 1322191739Sobrien case CDF_DIR_TYPE_USER_STORAGE: 1323192348Sdelphij (void)fprintf(stderr, "Storage: %d\n", d->d_storage); 1324191739Sobrien break; 1325191739Sobrien case CDF_DIR_TYPE_USER_STREAM: 1326191739Sobrien if (sst == NULL) 1327191739Sobrien break; 1328192348Sdelphij if (cdf_read_sector_chain(info, h, sat, ssat, sst, 1329191739Sobrien d->d_stream_first_sector, d->d_size, &scn) == -1) { 1330191739Sobrien warn("Can't read stream for %s at %d len %d", 1331191739Sobrien name, d->d_stream_first_sector, d->d_size); 1332191739Sobrien break; 1333191739Sobrien } 1334191739Sobrien cdf_dump_stream(h, &scn); 1335191739Sobrien free(scn.sst_tab); 1336191739Sobrien break; 1337191739Sobrien default: 1338191739Sobrien break; 1339191739Sobrien } 1340226048Sobrien 1341191739Sobrien } 1342191739Sobrien} 1343191739Sobrien 1344191739Sobrienvoid 1345191739Sobriencdf_dump_property_info(const cdf_property_info_t *info, size_t count) 1346191739Sobrien{ 1347191739Sobrien cdf_timestamp_t tp; 1348191739Sobrien struct timespec ts; 1349191739Sobrien char buf[64]; 1350226048Sobrien size_t i, j; 1351191739Sobrien 1352191739Sobrien for (i = 0; i < count; i++) { 1353191739Sobrien cdf_print_property_name(buf, sizeof(buf), info[i].pi_id); 1354226048Sobrien (void)fprintf(stderr, "%" SIZE_T_FORMAT "u) %s: ", i, buf); 1355191739Sobrien switch (info[i].pi_type) { 1356226048Sobrien case CDF_NULL: 1357226048Sobrien break; 1358191739Sobrien case CDF_SIGNED16: 1359192348Sdelphij (void)fprintf(stderr, "signed 16 [%hd]\n", 1360192348Sdelphij info[i].pi_s16); 1361191739Sobrien break; 1362191739Sobrien case CDF_SIGNED32: 1363192348Sdelphij (void)fprintf(stderr, "signed 32 [%d]\n", 1364192348Sdelphij info[i].pi_s32); 1365191739Sobrien break; 1366191739Sobrien case CDF_UNSIGNED32: 1367192348Sdelphij (void)fprintf(stderr, "unsigned 32 [%u]\n", 1368192348Sdelphij info[i].pi_u32); 1369191739Sobrien break; 1370234250Sobrien case CDF_FLOAT: 1371234250Sobrien (void)fprintf(stderr, "float [%g]\n", 1372234250Sobrien info[i].pi_f); 1373234250Sobrien break; 1374234250Sobrien case CDF_DOUBLE: 1375234250Sobrien (void)fprintf(stderr, "double [%g]\n", 1376234250Sobrien info[i].pi_d); 1377234250Sobrien break; 1378191739Sobrien case CDF_LENGTH32_STRING: 1379192348Sdelphij (void)fprintf(stderr, "string %u [%.*s]\n", 1380192348Sdelphij info[i].pi_str.s_len, 1381191739Sobrien info[i].pi_str.s_len, info[i].pi_str.s_buf); 1382191739Sobrien break; 1383226048Sobrien case CDF_LENGTH32_WSTRING: 1384226048Sobrien (void)fprintf(stderr, "string %u [", 1385226048Sobrien info[i].pi_str.s_len); 1386226048Sobrien for (j = 0; j < info[i].pi_str.s_len - 1; j++) 1387226048Sobrien (void)fputc(info[i].pi_str.s_buf[j << 1], stderr); 1388226048Sobrien (void)fprintf(stderr, "]\n"); 1389226048Sobrien break; 1390191739Sobrien case CDF_FILETIME: 1391191739Sobrien tp = info[i].pi_tp; 1392191739Sobrien if (tp < 1000000000000000LL) { 1393191739Sobrien cdf_print_elapsed_time(buf, sizeof(buf), tp); 1394192348Sdelphij (void)fprintf(stderr, "timestamp %s\n", buf); 1395191739Sobrien } else { 1396284237Sdelphij char tbuf[26]; 1397191739Sobrien cdf_timestamp_to_timespec(&ts, tp); 1398192348Sdelphij (void)fprintf(stderr, "timestamp %s", 1399284237Sdelphij cdf_ctime(&ts.tv_sec, tbuf)); 1400191739Sobrien } 1401191739Sobrien break; 1402191739Sobrien case CDF_CLIPBOARD: 1403192348Sdelphij (void)fprintf(stderr, "CLIPBOARD %u\n", info[i].pi_u32); 1404191739Sobrien break; 1405191739Sobrien default: 1406191739Sobrien DPRINTF(("Don't know how to deal with %x\n", 1407191739Sobrien info[i].pi_type)); 1408191739Sobrien break; 1409191739Sobrien } 1410191739Sobrien } 1411191739Sobrien} 1412191739Sobrien 1413191739Sobrien 1414191739Sobrienvoid 1415191739Sobriencdf_dump_summary_info(const cdf_header_t *h, const cdf_stream_t *sst) 1416191739Sobrien{ 1417191739Sobrien char buf[128]; 1418191739Sobrien cdf_summary_info_header_t ssi; 1419191739Sobrien cdf_property_info_t *info; 1420191739Sobrien size_t count; 1421191739Sobrien 1422191739Sobrien (void)&h; 1423226048Sobrien if (cdf_unpack_summary_info(sst, h, &ssi, &info, &count) == -1) 1424191739Sobrien return; 1425192348Sdelphij (void)fprintf(stderr, "Endian: %x\n", ssi.si_byte_order); 1426192348Sdelphij (void)fprintf(stderr, "Os Version %d.%d\n", ssi.si_os_version & 0xff, 1427275698Sdelphij ssi.si_os_version >> 8); 1428192348Sdelphij (void)fprintf(stderr, "Os %d\n", ssi.si_os); 1429191739Sobrien cdf_print_classid(buf, sizeof(buf), &ssi.si_class); 1430192348Sdelphij (void)fprintf(stderr, "Class %s\n", buf); 1431192348Sdelphij (void)fprintf(stderr, "Count %d\n", ssi.si_count); 1432191739Sobrien cdf_dump_property_info(info, count); 1433191739Sobrien free(info); 1434191739Sobrien} 1435191739Sobrien 1436275698Sdelphij 1437275698Sdelphijvoid 1438275698Sdelphijcdf_dump_catalog(const cdf_header_t *h, const cdf_stream_t *sst) 1439275698Sdelphij{ 1440275698Sdelphij cdf_catalog_t *cat; 1441275698Sdelphij cdf_unpack_catalog(h, sst, &cat); 1442275698Sdelphij const cdf_catalog_entry_t *ce = cat->cat_e; 1443275698Sdelphij struct timespec ts; 1444275698Sdelphij char tbuf[64], sbuf[256]; 1445275698Sdelphij size_t i; 1446275698Sdelphij 1447275698Sdelphij printf("Catalog:\n"); 1448275698Sdelphij for (i = 0; i < cat->cat_num; i++) { 1449275698Sdelphij cdf_timestamp_to_timespec(&ts, ce[i].ce_timestamp); 1450275698Sdelphij printf("\t%d %s %s", ce[i].ce_num, 1451275698Sdelphij cdf_u16tos8(sbuf, ce[i].ce_namlen, ce[i].ce_name), 1452275698Sdelphij cdf_ctime(&ts.tv_sec, tbuf)); 1453275698Sdelphij } 1454275698Sdelphij free(cat); 1455275698Sdelphij} 1456275698Sdelphij 1457191739Sobrien#endif 1458191739Sobrien 1459191739Sobrien#ifdef TEST 1460191739Sobrienint 1461191739Sobrienmain(int argc, char *argv[]) 1462191739Sobrien{ 1463192348Sdelphij int i; 1464191739Sobrien cdf_header_t h; 1465191739Sobrien cdf_sat_t sat, ssat; 1466191739Sobrien cdf_stream_t sst, scn; 1467191739Sobrien cdf_dir_t dir; 1468192348Sdelphij cdf_info_t info; 1469275698Sdelphij const cdf_directory_t *root; 1470284237Sdelphij#ifdef __linux__ 1471284237Sdelphij#define getprogname() __progname 1472284237Sdelphij extern char *__progname; 1473284237Sdelphij#endif 1474191739Sobrien if (argc < 2) { 1475191739Sobrien (void)fprintf(stderr, "Usage: %s <filename>\n", getprogname()); 1476191739Sobrien return -1; 1477191739Sobrien } 1478191739Sobrien 1479192348Sdelphij info.i_buf = NULL; 1480192348Sdelphij info.i_len = 0; 1481191739Sobrien for (i = 1; i < argc; i++) { 1482192348Sdelphij if ((info.i_fd = open(argv[1], O_RDONLY)) == -1) 1483191739Sobrien err(1, "Cannot open `%s'", argv[1]); 1484191739Sobrien 1485192348Sdelphij if (cdf_read_header(&info, &h) == -1) 1486191739Sobrien err(1, "Cannot read header"); 1487191739Sobrien#ifdef CDF_DEBUG 1488191739Sobrien cdf_dump_header(&h); 1489191739Sobrien#endif 1490191739Sobrien 1491192348Sdelphij if (cdf_read_sat(&info, &h, &sat) == -1) 1492191739Sobrien err(1, "Cannot read sat"); 1493191739Sobrien#ifdef CDF_DEBUG 1494192348Sdelphij cdf_dump_sat("SAT", &sat, CDF_SEC_SIZE(&h)); 1495191739Sobrien#endif 1496191739Sobrien 1497192348Sdelphij if (cdf_read_ssat(&info, &h, &sat, &ssat) == -1) 1498191739Sobrien err(1, "Cannot read ssat"); 1499191739Sobrien#ifdef CDF_DEBUG 1500226048Sobrien cdf_dump_sat("SSAT", &ssat, CDF_SHORT_SEC_SIZE(&h)); 1501191739Sobrien#endif 1502191739Sobrien 1503192348Sdelphij if (cdf_read_dir(&info, &h, &sat, &dir) == -1) 1504191739Sobrien err(1, "Cannot read dir"); 1505191739Sobrien 1506275698Sdelphij if (cdf_read_short_stream(&info, &h, &sat, &dir, &sst, &root) 1507275698Sdelphij == -1) 1508191739Sobrien err(1, "Cannot read short stream"); 1509191739Sobrien#ifdef CDF_DEBUG 1510191739Sobrien cdf_dump_stream(&h, &sst); 1511191739Sobrien#endif 1512191739Sobrien 1513191739Sobrien#ifdef CDF_DEBUG 1514192348Sdelphij cdf_dump_dir(&info, &h, &sat, &ssat, &sst, &dir); 1515191739Sobrien#endif 1516191739Sobrien 1517191739Sobrien 1518192348Sdelphij if (cdf_read_summary_info(&info, &h, &sat, &ssat, &sst, &dir, 1519191739Sobrien &scn) == -1) 1520275698Sdelphij warn("Cannot read summary info"); 1521191739Sobrien#ifdef CDF_DEBUG 1522275698Sdelphij else 1523275698Sdelphij cdf_dump_summary_info(&h, &scn); 1524191739Sobrien#endif 1525284237Sdelphij if (cdf_read_user_stream(&info, &h, &sat, &ssat, &sst, 1526284237Sdelphij &dir, "Catalog", &scn) == -1) 1527275698Sdelphij warn("Cannot read catalog"); 1528275698Sdelphij#ifdef CDF_DEBUG 1529275698Sdelphij else 1530275698Sdelphij cdf_dump_catalog(&h, &scn); 1531275698Sdelphij#endif 1532191739Sobrien 1533192348Sdelphij (void)close(info.i_fd); 1534191739Sobrien } 1535191739Sobrien 1536191739Sobrien return 0; 1537191739Sobrien} 1538191739Sobrien#endif 1539