123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368 |
- /*
- * Copyright (c) Ian F. Darwin 1986-1995.
- * Software written by Ian F. Darwin and others;
- * maintained 1995-present by Christos Zoulas and others.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice immediately at the beginning of the file, without modification,
- * this list of conditions, and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
- /*
- * print.c - debugging printout routines
- */
- #include "file.h"
- #ifndef lint
- FILE_RCSID("@(#)$File: print.c,v 1.99 2023/07/17 16:40:57 christos Exp $")
- #endif /* lint */
- #include <string.h>
- #include <stdarg.h>
- #include <stdlib.h>
- #ifdef HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- #include <time.h>
- #include "cdf.h"
- #ifndef COMPILE_ONLY
- file_protected void
- file_mdump(struct magic *m)
- {
- static const char optyp[] = { FILE_OPS };
- char tbuf[256];
- (void) fprintf(stderr, "%u: %.*s %d", m->lineno,
- (m->cont_level & 7) + 1, ">>>>>>>>", m->offset);
- if (m->flag & INDIR) {
- (void) fprintf(stderr, "(%s,",
- /* Note: type is unsigned */
- (m->in_type < file_nnames) ? file_names[m->in_type] :
- "*bad in_type*");
- if (m->in_op & FILE_OPINVERSE)
- (void) fputc('~', stderr);
- (void) fprintf(stderr, "%c%d),",
- (CAST(size_t, m->in_op & FILE_OPS_MASK) <
- __arraycount(optyp)) ?
- optyp[m->in_op & FILE_OPS_MASK] : '?', m->in_offset);
- }
- (void) fprintf(stderr, " %s%s", (m->flag & UNSIGNED) ? "u" : "",
- /* Note: type is unsigned */
- (m->type < file_nnames) ? file_names[m->type] : "*bad type");
- if (m->mask_op & FILE_OPINVERSE)
- (void) fputc('~', stderr);
- if (IS_STRING(m->type)) {
- if (m->str_flags) {
- (void) fputc('/', stderr);
- if (m->str_flags & STRING_COMPACT_WHITESPACE)
- (void) fputc(CHAR_COMPACT_WHITESPACE, stderr);
- if (m->str_flags & STRING_COMPACT_OPTIONAL_WHITESPACE)
- (void) fputc(CHAR_COMPACT_OPTIONAL_WHITESPACE,
- stderr);
- if (m->str_flags & STRING_IGNORE_LOWERCASE)
- (void) fputc(CHAR_IGNORE_LOWERCASE, stderr);
- if (m->str_flags & STRING_IGNORE_UPPERCASE)
- (void) fputc(CHAR_IGNORE_UPPERCASE, stderr);
- if (m->str_flags & REGEX_OFFSET_START)
- (void) fputc(CHAR_REGEX_OFFSET_START, stderr);
- if (m->str_flags & STRING_TEXTTEST)
- (void) fputc(CHAR_TEXTTEST, stderr);
- if (m->str_flags & STRING_BINTEST)
- (void) fputc(CHAR_BINTEST, stderr);
- if (m->str_flags & PSTRING_1_BE)
- (void) fputc(CHAR_PSTRING_1_BE, stderr);
- if (m->str_flags & PSTRING_2_BE)
- (void) fputc(CHAR_PSTRING_2_BE, stderr);
- if (m->str_flags & PSTRING_2_LE)
- (void) fputc(CHAR_PSTRING_2_LE, stderr);
- if (m->str_flags & PSTRING_4_BE)
- (void) fputc(CHAR_PSTRING_4_BE, stderr);
- if (m->str_flags & PSTRING_4_LE)
- (void) fputc(CHAR_PSTRING_4_LE, stderr);
- if (m->str_flags & PSTRING_LENGTH_INCLUDES_ITSELF)
- (void) fputc(
- CHAR_PSTRING_LENGTH_INCLUDES_ITSELF,
- stderr);
- }
- if (m->str_range)
- (void) fprintf(stderr, "/%u", m->str_range);
- }
- else {
- if (CAST(size_t, m->mask_op & FILE_OPS_MASK) <
- __arraycount(optyp))
- (void) fputc(optyp[m->mask_op & FILE_OPS_MASK], stderr);
- else
- (void) fputc('?', stderr);
- if (m->num_mask) {
- (void) fprintf(stderr, "%.8llx",
- CAST(unsigned long long, m->num_mask));
- }
- }
- (void) fprintf(stderr, ",%c", m->reln);
- if (m->reln != 'x') {
- switch (m->type) {
- case FILE_BYTE:
- case FILE_SHORT:
- case FILE_LONG:
- case FILE_LESHORT:
- case FILE_LELONG:
- case FILE_MELONG:
- case FILE_BESHORT:
- case FILE_BELONG:
- case FILE_INDIRECT:
- (void) fprintf(stderr, "%d", CAST(int32_t, m->value.l));
- break;
- case FILE_BEQUAD:
- case FILE_LEQUAD:
- case FILE_QUAD:
- case FILE_OFFSET:
- (void) fprintf(stderr, "%" INT64_T_FORMAT "d",
- CAST(long long, m->value.q));
- break;
- case FILE_PSTRING:
- case FILE_STRING:
- case FILE_REGEX:
- case FILE_BESTRING16:
- case FILE_LESTRING16:
- case FILE_SEARCH:
- file_showstr(stderr, m->value.s,
- CAST(size_t, m->vallen));
- break;
- case FILE_DATE:
- case FILE_LEDATE:
- case FILE_BEDATE:
- case FILE_MEDATE:
- (void)fprintf(stderr, "%s,",
- file_fmtdatetime(tbuf, sizeof(tbuf), m->value.l, 0));
- break;
- case FILE_LDATE:
- case FILE_LELDATE:
- case FILE_BELDATE:
- case FILE_MELDATE:
- (void)fprintf(stderr, "%s,",
- file_fmtdatetime(tbuf, sizeof(tbuf), m->value.l,
- FILE_T_LOCAL));
- break;
- case FILE_QDATE:
- case FILE_LEQDATE:
- case FILE_BEQDATE:
- (void)fprintf(stderr, "%s,",
- file_fmtdatetime(tbuf, sizeof(tbuf), m->value.q, 0));
- break;
- case FILE_QLDATE:
- case FILE_LEQLDATE:
- case FILE_BEQLDATE:
- (void)fprintf(stderr, "%s,",
- file_fmtdatetime(tbuf, sizeof(tbuf), m->value.q,
- FILE_T_LOCAL));
- break;
- case FILE_QWDATE:
- case FILE_LEQWDATE:
- case FILE_BEQWDATE:
- (void)fprintf(stderr, "%s,",
- file_fmtdatetime(tbuf, sizeof(tbuf), m->value.q,
- FILE_T_WINDOWS));
- break;
- case FILE_FLOAT:
- case FILE_BEFLOAT:
- case FILE_LEFLOAT:
- (void) fprintf(stderr, "%G", m->value.f);
- break;
- case FILE_DOUBLE:
- case FILE_BEDOUBLE:
- case FILE_LEDOUBLE:
- (void) fprintf(stderr, "%G", m->value.d);
- break;
- case FILE_LEVARINT:
- case FILE_BEVARINT:
- (void)fprintf(stderr, "%s", file_fmtvarint(
- tbuf, sizeof(tbuf), m->value.us, m->type));
- break;
- case FILE_MSDOSDATE:
- case FILE_BEMSDOSDATE:
- case FILE_LEMSDOSDATE:
- (void)fprintf(stderr, "%s,",
- file_fmtdate(tbuf, sizeof(tbuf), m->value.h));
- break;
- case FILE_MSDOSTIME:
- case FILE_BEMSDOSTIME:
- case FILE_LEMSDOSTIME:
- (void)fprintf(stderr, "%s,",
- file_fmttime(tbuf, sizeof(tbuf), m->value.h));
- break;
- case FILE_OCTAL:
- (void)fprintf(stderr, "%s",
- file_fmtnum(tbuf, sizeof(tbuf), m->value.s, 8));
- break;
- case FILE_DEFAULT:
- /* XXX - do anything here? */
- break;
- case FILE_USE:
- case FILE_NAME:
- case FILE_DER:
- (void) fprintf(stderr, "'%s'", m->value.s);
- break;
- case FILE_GUID:
- (void) file_print_guid(tbuf, sizeof(tbuf),
- m->value.guid);
- (void) fprintf(stderr, "%s", tbuf);
- break;
- default:
- (void) fprintf(stderr, "*bad type %d*", m->type);
- break;
- }
- }
- (void) fprintf(stderr, ",\"%s\"]\n", m->desc);
- }
- #endif
- /*VARARGS*/
- file_protected void
- file_magwarn(struct magic_set *ms, const char *f, ...)
- {
- va_list va;
- /* cuz we use stdout for most, stderr here */
- (void) fflush(stdout);
- if (ms && ms->file)
- (void) fprintf(stderr, "%s, %lu: ", ms->file,
- CAST(unsigned long, ms->line));
- (void) fprintf(stderr, "Warning: ");
- va_start(va, f);
- (void) vfprintf(stderr, f, va);
- va_end(va);
- (void) fputc('\n', stderr);
- }
- file_protected const char *
- file_fmtvarint(char *buf, size_t blen, const unsigned char *us, int t)
- {
- snprintf(buf, blen, "%jd", CAST(intmax_t,
- file_varint2uintmax_t(us, t, NULL)));
- return buf;
- }
- file_protected const char *
- file_fmtdatetime(char *buf, size_t bsize, uint64_t v, int flags)
- {
- char *pp;
- time_t t;
- struct tm *tm, tmz;
- if (flags & FILE_T_WINDOWS) {
- struct timespec ts;
- cdf_timestamp_to_timespec(&ts, CAST(cdf_timestamp_t, v));
- t = ts.tv_sec;
- } else {
- // XXX: perhaps detect and print something if overflow
- // on 32 bit time_t?
- t = CAST(time_t, v);
- }
- if (t > MAX_CTIME)
- goto out;
- if (flags & FILE_T_LOCAL) {
- tm = localtime_r(&t, &tmz);
- } else {
- tm = gmtime_r(&t, &tmz);
- }
- if (tm == NULL)
- goto out;
- pp = asctime_r(tm, buf);
- if (pp == NULL)
- goto out;
- pp[strcspn(pp, "\n")] = '\0';
- return pp;
- out:
- strlcpy(buf, "*Invalid datetime*", bsize);
- return buf;
- }
- /*
- * https://docs.microsoft.com/en-us/windows/win32/api/winbase/\
- * nf-winbase-dosdatetimetofiletime?redirectedfrom=MSDN
- */
- file_protected const char *
- file_fmtdate(char *buf, size_t bsize, uint16_t v)
- {
- struct tm tm;
- memset(&tm, 0, sizeof(tm));
- tm.tm_mday = v & 0x1f;
- tm.tm_mon = ((v >> 5) & 0xf) - 1;
- tm.tm_year = (v >> 9) + 80;
- if (strftime(buf, bsize, "%a, %b %d %Y", &tm) == 0)
- goto out;
- return buf;
- out:
- strlcpy(buf, "*Invalid date*", bsize);
- return buf;
- }
- file_protected const char *
- file_fmttime(char *buf, size_t bsize, uint16_t v)
- {
- struct tm tm;
- memset(&tm, 0, sizeof(tm));
- tm.tm_sec = (v & 0x1f) * 2;
- tm.tm_min = ((v >> 5) & 0x3f);
- tm.tm_hour = (v >> 11);
- if (strftime(buf, bsize, "%T", &tm) == 0)
- goto out;
- return buf;
- out:
- strlcpy(buf, "*Invalid time*", bsize);
- return buf;
- }
- file_protected const char *
- file_fmtnum(char *buf, size_t blen, const char *us, int base)
- {
- char *endptr;
- unsigned long long val;
- errno = 0;
- val = strtoull(us, &endptr, base);
- if (*endptr || errno) {
- bad: strlcpy(buf, "*Invalid number*", blen);
- return buf;
- }
- if (snprintf(buf, blen, "%llu", val) < 0)
- goto bad;
- return buf;
- }
|