summaryrefslogtreecommitdiffstats
path: root/contrib/file/src/cdf.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/file/src/cdf.c')
-rw-r--r--contrib/file/src/cdf.c115
1 files changed, 108 insertions, 7 deletions
diff --git a/contrib/file/src/cdf.c b/contrib/file/src/cdf.c
index 106fc7a..9e3cf9f 100644
--- a/contrib/file/src/cdf.c
+++ b/contrib/file/src/cdf.c
@@ -35,7 +35,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: cdf.c,v 1.63 2014/06/09 13:04:37 christos Exp $")
+FILE_RCSID("@(#)$File: cdf.c,v 1.69 2014/12/04 15:56:46 christos Exp $")
#endif
#include <assert.h>
@@ -73,6 +73,8 @@ static union {
#define CDF_TOLE8(x) ((uint64_t)(NEED_SWAP ? _cdf_tole8(x) : (uint64_t)(x)))
#define CDF_TOLE4(x) ((uint32_t)(NEED_SWAP ? _cdf_tole4(x) : (uint32_t)(x)))
#define CDF_TOLE2(x) ((uint16_t)(NEED_SWAP ? _cdf_tole2(x) : (uint16_t)(x)))
+#define CDF_TOLE(x) (sizeof(x) == 2 ? CDF_TOLE2(x) : (sizeof(x) == 4 ? \
+ CDF_TOLE4(x) : CDF_TOLE8(x)))
#define CDF_GETUINT32(x, y) cdf_getuint32(x, y)
@@ -461,6 +463,12 @@ cdf_count_chain(const cdf_sat_t *sat, cdf_secid_t sid, size_t size)
/ sizeof(maxsector));
DPRINTF(("Chain:"));
+ if (sid == CDF_SECID_END_OF_CHAIN) {
+ /* 0-length chain. */
+ DPRINTF((" empty\n"));
+ return 0;
+ }
+
for (j = i = 0; sid >= 0; i++, j++) {
DPRINTF((" %d", sid));
if (j >= CDF_LOOP_LIMIT) {
@@ -817,13 +825,18 @@ cdf_read_property_info(const cdf_stream_t *sst, const cdf_header_t *h,
goto out;
for (i = 0; i < sh.sh_properties; i++) {
size_t tail = (i << 1) + 1;
+ size_t ofs;
if (cdf_check_stream_offset(sst, h, p, tail * sizeof(uint32_t),
__LINE__) == -1)
goto out;
- size_t ofs = CDF_GETUINT32(p, tail);
+ ofs = CDF_GETUINT32(p, tail);
q = (const uint8_t *)(const void *)
((const char *)(const void *)p + ofs
- 2 * sizeof(uint32_t));
+ if (q < p) {
+ DPRINTF(("Wrapped around %p < %p\n", q, p));
+ goto out;
+ }
if (q > e) {
DPRINTF(("Ran of the end %p > %p\n", q, e));
goto out;
@@ -985,6 +998,54 @@ cdf_unpack_summary_info(const cdf_stream_t *sst, const cdf_header_t *h,
}
+#define extract_catalog_field(f, l) \
+ memcpy(&ce[i].f, b + (l), sizeof(ce[i].f)); \
+ ce[i].f = CDF_TOLE(ce[i].f)
+
+int
+cdf_unpack_catalog(const cdf_header_t *h, const cdf_stream_t *sst,
+ cdf_catalog_t **cat)
+{
+ size_t ss = sst->sst_dirlen < h->h_min_size_standard_stream ?
+ CDF_SHORT_SEC_SIZE(h) : CDF_SEC_SIZE(h);
+ const char *b = CAST(const char *, sst->sst_tab);
+ const char *eb = b + ss * sst->sst_len;
+ size_t nr, i, k;
+ cdf_catalog_entry_t *ce;
+ uint16_t reclen;
+ const uint16_t *np;
+
+ for (nr = 0; b < eb; nr++) {
+ memcpy(&reclen, b, sizeof(reclen));
+ reclen = CDF_TOLE2(reclen);
+ if (reclen == 0)
+ break;
+ b += reclen;
+ }
+ *cat = CAST(cdf_catalog_t *,
+ malloc(sizeof(cdf_catalog_t) + nr * sizeof(*ce)));
+ (*cat)->cat_num = nr;
+ ce = (*cat)->cat_e;
+ b = CAST(const char *, sst->sst_tab);
+ for (i = 0; i < nr; i++) {
+ extract_catalog_field(ce_namlen, 0);
+ extract_catalog_field(ce_num, 2);
+ extract_catalog_field(ce_timestamp, 6);
+ reclen = ce[i].ce_namlen;
+ ce[i].ce_namlen =
+ sizeof(ce[i].ce_name) / sizeof(ce[i].ce_name[0]) - 1;
+ if (ce[i].ce_namlen > reclen - 14)
+ ce[i].ce_namlen = reclen - 14;
+ np = CAST(const uint16_t *, (b + 16));
+ for (k = 0; k < ce[i].ce_namlen; k++) {
+ ce[i].ce_name[k] = np[k];
+ CDF_TOLE2(ce[i].ce_name[k]);
+ }
+ ce[i].ce_name[ce[i].ce_namlen] = 0;
+ b += reclen;
+ }
+ return 0;
+}
int
cdf_print_classid(char *buf, size_t buflen, const cdf_classid_t *id)
@@ -1068,6 +1129,15 @@ cdf_print_elapsed_time(char *buf, size_t bufsiz, cdf_timestamp_t ts)
return len;
}
+char *
+cdf_u16tos8(char *buf, size_t len, const uint16_t *p)
+{
+ size_t i;
+ for (i = 0; i < len && p[i]; i++)
+ buf[i] = (char)p[i];
+ buf[i] = '\0';
+ return buf;
+}
#ifdef CDF_DEBUG
void
@@ -1093,7 +1163,7 @@ cdf_dump_header(const cdf_header_t *h)
for (i = 0; i < __arraycount(h->h_master_sat); i++) {
if (h->h_master_sat[i] == CDF_SECID_FREE)
break;
- (void)fprintf(stderr, "%35.35s[%.3zu] = %d\n",
+ (void)fprintf(stderr, "%35.35s[%.3" SIZE_T_FORMAT "u] = %d\n",
"master_sat", i, h->h_master_sat[i]);
}
}
@@ -1288,7 +1358,7 @@ cdf_dump_summary_info(const cdf_header_t *h, const cdf_stream_t *sst)
return;
(void)fprintf(stderr, "Endian: %x\n", ssi.si_byte_order);
(void)fprintf(stderr, "Os Version %d.%d\n", ssi.si_os_version & 0xff,
- ssi.si_os_version >> 8);
+ ssi.si_os_version >> 8);
(void)fprintf(stderr, "Os %d\n", ssi.si_os);
cdf_print_classid(buf, sizeof(buf), &ssi.si_class);
(void)fprintf(stderr, "Class %s\n", buf);
@@ -1297,6 +1367,27 @@ cdf_dump_summary_info(const cdf_header_t *h, const cdf_stream_t *sst)
free(info);
}
+
+void
+cdf_dump_catalog(const cdf_header_t *h, const cdf_stream_t *sst)
+{
+ cdf_catalog_t *cat;
+ cdf_unpack_catalog(h, sst, &cat);
+ const cdf_catalog_entry_t *ce = cat->cat_e;
+ struct timespec ts;
+ char tbuf[64], sbuf[256];
+ size_t i;
+
+ printf("Catalog:\n");
+ for (i = 0; i < cat->cat_num; i++) {
+ cdf_timestamp_to_timespec(&ts, ce[i].ce_timestamp);
+ printf("\t%d %s %s", ce[i].ce_num,
+ cdf_u16tos8(sbuf, ce[i].ce_namlen, ce[i].ce_name),
+ cdf_ctime(&ts.tv_sec, tbuf));
+ }
+ free(cat);
+}
+
#endif
#ifdef TEST
@@ -1309,6 +1400,7 @@ main(int argc, char *argv[])
cdf_stream_t sst, scn;
cdf_dir_t dir;
cdf_info_t info;
+ const cdf_directory_t *root;
if (argc < 2) {
(void)fprintf(stderr, "Usage: %s <filename>\n", getprogname());
@@ -1342,7 +1434,8 @@ main(int argc, char *argv[])
if (cdf_read_dir(&info, &h, &sat, &dir) == -1)
err(1, "Cannot read dir");
- if (cdf_read_short_stream(&info, &h, &sat, &dir, &sst) == -1)
+ if (cdf_read_short_stream(&info, &h, &sat, &dir, &sst, &root)
+ == -1)
err(1, "Cannot read short stream");
#ifdef CDF_DEBUG
cdf_dump_stream(&h, &sst);
@@ -1355,9 +1448,17 @@ main(int argc, char *argv[])
if (cdf_read_summary_info(&info, &h, &sat, &ssat, &sst, &dir,
&scn) == -1)
- err(1, "Cannot read summary info");
+ warn("Cannot read summary info");
+#ifdef CDF_DEBUG
+ else
+ cdf_dump_summary_info(&h, &scn);
+#endif
+ if (cdf_read_catalog(&info, &h, &sat, &ssat, &sst, &dir,
+ &scn) == -1)
+ warn("Cannot read catalog");
#ifdef CDF_DEBUG
- cdf_dump_summary_info(&h, &scn);
+ else
+ cdf_dump_catalog(&h, &scn);
#endif
(void)close(info.i_fd);
OpenPOWER on IntegriCloud