summaryrefslogtreecommitdiffstats
path: root/softmagic.c
diff options
context:
space:
mode:
Diffstat (limited to 'softmagic.c')
-rw-r--r--softmagic.c191
1 files changed, 99 insertions, 92 deletions
diff --git a/softmagic.c b/softmagic.c
index 21a0148..39a7fc8 100644
--- a/softmagic.c
+++ b/softmagic.c
@@ -38,11 +38,11 @@
#ifndef lint
-FILE_RCSID("@(#)$File: softmagic.c,v 1.103 2007/12/27 16:35:59 christos Exp $")
+FILE_RCSID("@(#)$File: softmagic.c,v 1.120 2008/07/28 17:25:21 christos Exp $")
#endif /* lint */
private int match(struct magic_set *, struct magic *, uint32_t,
- const unsigned char *, size_t);
+ const unsigned char *, size_t, int);
private int mget(struct magic_set *, const unsigned char *,
struct magic *, size_t, unsigned int);
private int magiccheck(struct magic_set *, struct magic *);
@@ -58,17 +58,23 @@ private void cvt_32(union VALUETYPE *, const struct magic *);
private void cvt_64(union VALUETYPE *, const struct magic *);
/*
+ * Macro to give description string according to whether we want plain
+ * text or MIME type
+ */
+#define MAGIC_DESC ((ms->flags & MAGIC_MIME) ? m->mimetype : m->desc)
+
+/*
* softmagic - lookup one file in parsed, in-memory copy of database
* Passed the name and FILE * of one file to be typed.
*/
/*ARGSUSED1*/ /* nbytes passed for regularity, maybe need later */
protected int
-file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes)
+file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes, int mode)
{
struct mlist *ml;
int rv;
for (ml = ms->mlist->next; ml != ms->mlist; ml = ml->next)
- if ((rv = match(ms, ml->magic, ml->nmagic, buf, nbytes)) != 0)
+ if ((rv = match(ms, ml->magic, ml->nmagic, buf, nbytes, mode)) != 0)
return rv;
return 0;
@@ -103,7 +109,7 @@ file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes)
*/
private int
match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
- const unsigned char *s, size_t nbytes)
+ const unsigned char *s, size_t nbytes, int mode)
{
uint32_t magindex = 0;
unsigned int cont_level = 0;
@@ -117,17 +123,26 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
for (magindex = 0; magindex < nmagic; magindex++) {
int flush;
+ struct magic *m = &magic[magindex];
- ms->offset = magic[magindex].offset;
- ms->line = magic[magindex].lineno;
+ if ((m->flag & BINTEST) != mode) {
+ /* Skip sub-tests */
+ while (magic[magindex + 1].cont_level != 0 &&
+ ++magindex < nmagic)
+ continue;
+ continue; /* Skip to next top-level test*/
+ }
+
+ ms->offset = m->offset;
+ ms->line = m->lineno;
/* if main entry matches, print it... */
- flush = !mget(ms, s, &magic[magindex], nbytes, cont_level);
+ flush = !mget(ms, s, m, nbytes, cont_level);
if (flush) {
- if (magic[magindex].reln == '!')
+ if (m->reln == '!')
flush = 0;
} else {
- switch (magiccheck(ms, &magic[magindex])) {
+ switch (magiccheck(ms, m)) {
case -1:
return -1;
case 0:
@@ -152,15 +167,14 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
* If we are going to print something, we'll need to print
* a blank before we print something else.
*/
- if (magic[magindex].desc[0]) {
+ if (*MAGIC_DESC) {
need_separator = 1;
printed_something = 1;
if (print_sep(ms, firstline) == -1)
return -1;
}
- if ((ms->c.li[cont_level].off = mprint(ms, &magic[magindex]))
- == -1)
+ if ((ms->c.li[cont_level].off = mprint(ms, m)) == -1)
return -1;
/* and any continuations that match */
@@ -169,36 +183,36 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
while (magic[magindex+1].cont_level != 0 &&
++magindex < nmagic) {
- ms->line = magic[magindex].lineno; /* for messages */
+ m = &magic[magindex];
+ ms->line = m->lineno; /* for messages */
- if (cont_level < magic[magindex].cont_level)
+ if (cont_level < m->cont_level)
continue;
- if (cont_level > magic[magindex].cont_level) {
+ if (cont_level > m->cont_level) {
/*
* We're at the end of the level
* "cont_level" continuations.
*/
- cont_level = magic[magindex].cont_level;
+ cont_level = m->cont_level;
}
- ms->offset = magic[magindex].offset;
- if (magic[magindex].flag & OFFADD) {
+ ms->offset = m->offset;
+ if (m->flag & OFFADD) {
ms->offset +=
ms->c.li[cont_level - 1].off;
}
#ifdef ENABLE_CONDITIONALS
- if (magic[magindex].cond == COND_ELSE ||
- magic[magindex].cond == COND_ELIF) {
+ if (m->cond == COND_ELSE ||
+ m->cond == COND_ELIF) {
if (ms->c.li[cont_level].last_match == 1)
continue;
}
#endif
- flush = !mget(ms, s, &magic[magindex], nbytes,
- cont_level);
- if (flush && magic[magindex].reln != '!')
+ flush = !mget(ms, s, m, nbytes, cont_level);
+ if (flush && m->reln != '!')
continue;
- switch (flush ? 1 : magiccheck(ms, &magic[magindex])) {
+ switch (flush ? 1 : magiccheck(ms, m)) {
case -1:
return -1;
case 0:
@@ -210,7 +224,7 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
#ifdef ENABLE_CONDITIONALS
ms->c.li[cont_level].last_match = 1;
#endif
- if (magic[magindex].type != FILE_DEFAULT)
+ if (m->type != FILE_DEFAULT)
ms->c.li[cont_level].got_match = 1;
else if (ms->c.li[cont_level].got_match) {
ms->c.li[cont_level].got_match = 0;
@@ -220,7 +234,7 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
* If we are going to print something,
* make sure that we have a separator first.
*/
- if (magic[magindex].desc[0]) {
+ if (*MAGIC_DESC) {
printed_something = 1;
if (print_sep(ms, firstline) == -1)
return -1;
@@ -233,15 +247,15 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
*/
/* space if previous printed */
if (need_separator
- && (magic[magindex].nospflag == 0)
- && (magic[magindex].desc[0] != '\0')) {
+ && ((m->flag & NOSPACE) == 0)
+ && *MAGIC_DESC) {
if (file_printf(ms, " ") == -1)
return -1;
need_separator = 0;
}
- if ((ms->c.li[cont_level].off = mprint(ms, &magic[magindex])) == -1)
+ if ((ms->c.li[cont_level].off = mprint(ms, m)) == -1)
return -1;
- if (magic[magindex].desc[0])
+ if (*MAGIC_DESC)
need_separator = 1;
/*
@@ -271,7 +285,7 @@ check_fmt(struct magic_set *ms, struct magic *m)
regex_t rx;
int rc;
- if (strchr(m->desc, '%') == NULL)
+ if (strchr(MAGIC_DESC, '%') == NULL)
return 0;
rc = regcomp(&rx, "%[-0-9\\.]*s", REG_EXTENDED|REG_NOSUB);
@@ -281,7 +295,7 @@ check_fmt(struct magic_set *ms, struct magic *m)
file_magerror(ms, "regex error %d, (%s)", rc, errmsg);
return -1;
} else {
- rc = regexec(&rx, m->desc, 0, 0, 0);
+ rc = regexec(&rx, MAGIC_DESC, 0, 0, 0);
regfree(&rx);
return !rc;
}
@@ -314,7 +328,7 @@ mprint(struct magic_set *ms, struct magic *m)
float vf;
double vd;
int64_t t = 0;
- char buf[512];
+ char *buf;
union VALUETYPE *p = &ms->ms_value;
switch (m->type) {
@@ -324,14 +338,13 @@ mprint(struct magic_set *ms, struct magic *m)
case -1:
return -1;
case 1:
- if (snprintf(buf, sizeof(buf), "%c",
- (unsigned char)v) < 0)
+ if (asprintf(&buf, "%c", (unsigned char)v) < 0)
return -1;
- if (file_printf(ms, m->desc, buf) == -1)
+ if (file_printf(ms, MAGIC_DESC, buf) == -1)
return -1;
break;
default:
- if (file_printf(ms, m->desc, (unsigned char) v) == -1)
+ if (file_printf(ms, MAGIC_DESC, (unsigned char) v) == -1)
return -1;
break;
}
@@ -346,14 +359,13 @@ mprint(struct magic_set *ms, struct magic *m)
case -1:
return -1;
case 1:
- if (snprintf(buf, sizeof(buf), "%hu",
- (unsigned short)v) < 0)
+ if (asprintf(&buf, "%hu", (unsigned short)v) < 0)
return -1;
- if (file_printf(ms, m->desc, buf) == -1)
+ if (file_printf(ms, MAGIC_DESC, buf) == -1)
return -1;
break;
default:
- if (file_printf(ms, m->desc, (unsigned short) v) == -1)
+ if (file_printf(ms, MAGIC_DESC, (unsigned short) v) == -1)
return -1;
break;
}
@@ -369,13 +381,13 @@ mprint(struct magic_set *ms, struct magic *m)
case -1:
return -1;
case 1:
- if (snprintf(buf, sizeof(buf), "%u", (uint32_t)v) < 0)
+ if (asprintf(&buf, "%u", (uint32_t)v) < 0)
return -1;
- if (file_printf(ms, m->desc, buf) == -1)
+ if (file_printf(ms, MAGIC_DESC, buf) == -1)
return -1;
break;
default:
- if (file_printf(ms, m->desc, (uint32_t) v) == -1)
+ if (file_printf(ms, MAGIC_DESC, (uint32_t) v) == -1)
return -1;
break;
}
@@ -386,7 +398,7 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_BEQUAD:
case FILE_LEQUAD:
v = file_signextend(ms, m, p->q);
- if (file_printf(ms, m->desc, (uint64_t) v) == -1)
+ if (file_printf(ms, MAGIC_DESC, (uint64_t) v) == -1)
return -1;
t = ms->offset + sizeof(int64_t);
break;
@@ -396,16 +408,18 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_BESTRING16:
case FILE_LESTRING16:
if (m->reln == '=' || m->reln == '!') {
- if (file_printf(ms, m->desc, m->value.s) == -1)
+ if (file_printf(ms, MAGIC_DESC, m->value.s) == -1)
return -1;
t = ms->offset + m->vallen;
}
else {
if (*m->value.s == '\0')
p->s[strcspn(p->s, "\n")] = '\0';
- if (file_printf(ms, m->desc, p->s) == -1)
+ if (file_printf(ms, MAGIC_DESC, p->s) == -1)
return -1;
t = ms->offset + strlen(p->s);
+ if (m->type == FILE_PSTRING)
+ t++;
}
break;
@@ -413,7 +427,7 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_BEDATE:
case FILE_LEDATE:
case FILE_MEDATE:
- if (file_printf(ms, m->desc, file_fmttime(p->l, 1)) == -1)
+ if (file_printf(ms, MAGIC_DESC, file_fmttime(p->l, 1)) == -1)
return -1;
t = ms->offset + sizeof(time_t);
break;
@@ -422,7 +436,7 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_BELDATE:
case FILE_LELDATE:
case FILE_MELDATE:
- if (file_printf(ms, m->desc, file_fmttime(p->l, 0)) == -1)
+ if (file_printf(ms, MAGIC_DESC, file_fmttime(p->l, 0)) == -1)
return -1;
t = ms->offset + sizeof(time_t);
break;
@@ -430,7 +444,7 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_QDATE:
case FILE_BEQDATE:
case FILE_LEQDATE:
- if (file_printf(ms, m->desc, file_fmttime((uint32_t)p->q, 1))
+ if (file_printf(ms, MAGIC_DESC, file_fmttime((uint32_t)p->q, 1))
== -1)
return -1;
t = ms->offset + sizeof(uint64_t);
@@ -439,7 +453,7 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_QLDATE:
case FILE_BEQLDATE:
case FILE_LEQLDATE:
- if (file_printf(ms, m->desc, file_fmttime((uint32_t)p->q, 0))
+ if (file_printf(ms, MAGIC_DESC, file_fmttime((uint32_t)p->q, 0))
== -1)
return -1;
t = ms->offset + sizeof(uint64_t);
@@ -453,13 +467,13 @@ mprint(struct magic_set *ms, struct magic *m)
case -1:
return -1;
case 1:
- if (snprintf(buf, sizeof(buf), "%g", vf) < 0)
+ if (asprintf(&buf, "%g", vf) < 0)
return -1;
- if (file_printf(ms, m->desc, buf) == -1)
+ if (file_printf(ms, MAGIC_DESC, buf) == -1)
return -1;
break;
default:
- if (file_printf(ms, m->desc, vf) == -1)
+ if (file_printf(ms, MAGIC_DESC, vf) == -1)
return -1;
break;
}
@@ -474,13 +488,13 @@ mprint(struct magic_set *ms, struct magic *m)
case -1:
return -1;
case 1:
- if (snprintf(buf, sizeof(buf), "%g", vd) < 0)
+ if (asprintf(&buf, "%g", vd) < 0)
return -1;
- if (file_printf(ms, m->desc, buf) == -1)
+ if (file_printf(ms, MAGIC_DESC, buf) == -1)
return -1;
break;
default:
- if (file_printf(ms, m->desc, vd) == -1)
+ if (file_printf(ms, MAGIC_DESC, vd) == -1)
return -1;
break;
}
@@ -496,7 +510,7 @@ mprint(struct magic_set *ms, struct magic *m)
file_oomem(ms, ms->search.rm_len);
return -1;
}
- rval = file_printf(ms, m->desc, cp);
+ rval = file_printf(ms, MAGIC_DESC, cp);
free(cp);
if (rval == -1)
@@ -510,7 +524,7 @@ mprint(struct magic_set *ms, struct magic *m)
}
case FILE_SEARCH:
- if (file_printf(ms, m->desc, m->value.s) == -1)
+ if (file_printf(ms, MAGIC_DESC, m->value.s) == -1)
return -1;
if ((m->str_flags & REGEX_OFFSET_START))
t = ms->search.offset;
@@ -519,7 +533,7 @@ mprint(struct magic_set *ms, struct magic *m)
break;
case FILE_DEFAULT:
- if (file_printf(ms, m->desc, m->value.s) == -1)
+ if (file_printf(ms, MAGIC_DESC, m->value.s) == -1)
return -1;
t = ms->offset;
break;
@@ -646,13 +660,14 @@ mconvert(struct magic_set *ms, struct magic *m)
case FILE_STRING:
case FILE_BESTRING16:
case FILE_LESTRING16: {
- size_t len;
-
/* Null terminate and eat *trailing* return */
p->s[sizeof(p->s) - 1] = '\0';
+#if 0
+ /* Why? breaks magic numbers that end with \xa */
len = strlen(p->s);
if (len-- && p->s[len] == '\n')
p->s[len] = '\0';
+#endif
return 1;
}
case FILE_PSTRING: {
@@ -663,9 +678,12 @@ mconvert(struct magic_set *ms, struct magic *m)
while (len--)
*ptr1++ = *ptr2++;
*ptr1 = '\0';
+#if 0
+ /* Why? breaks magic numbers that end with \xa */
len = strlen(p->s);
if (len-- && p->s[len] == '\n')
p->s[len] = '\0';
+#endif
return 1;
}
case FILE_BESHORT:
@@ -682,10 +700,11 @@ mconvert(struct magic_set *ms, struct magic *m)
case FILE_BEQUAD:
case FILE_BEQDATE:
case FILE_BEQLDATE:
- p->q = (int64_t)
- (((int64_t)p->hq[0]<<56)|((int64_t)p->hq[1]<<48)|
- ((int64_t)p->hq[2]<<40)|((int64_t)p->hq[3]<<32)|
- (p->hq[4]<<24)|(p->hq[5]<<16)|(p->hq[6]<<8)|(p->hq[7]));
+ p->q = (uint64_t)
+ (((uint64_t)p->hq[0]<<56)|((uint64_t)p->hq[1]<<48)|
+ ((uint64_t)p->hq[2]<<40)|((uint64_t)p->hq[3]<<32)|
+ ((uint64_t)p->hq[4]<<24)|((uint64_t)p->hq[5]<<16)|
+ ((uint64_t)p->hq[6]<<8)|((uint64_t)p->hq[7]));
cvt_64(p, m);
return 1;
case FILE_LESHORT:
@@ -702,10 +721,11 @@ mconvert(struct magic_set *ms, struct magic *m)
case FILE_LEQUAD:
case FILE_LEQDATE:
case FILE_LEQLDATE:
- p->q = (int64_t)
- (((int64_t)p->hq[7]<<56)|((int64_t)p->hq[6]<<48)|
- ((int64_t)p->hq[5]<<40)|((int64_t)p->hq[4]<<32)|
- (p->hq[3]<<24)|(p->hq[2]<<16)|(p->hq[1]<<8)|(p->hq[0]));
+ p->q = (uint64_t)
+ (((uint64_t)p->hq[7]<<56)|((uint64_t)p->hq[6]<<48)|
+ ((uint64_t)p->hq[5]<<40)|((uint64_t)p->hq[4]<<32)|
+ ((uint64_t)p->hq[3]<<24)|((uint64_t)p->hq[2]<<16)|
+ ((uint64_t)p->hq[1]<<8)|((uint64_t)p->hq[0]));
cvt_64(p, m);
return 1;
case FILE_MELONG:
@@ -778,13 +798,10 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
case FILE_SEARCH:
ms->search.s = (const char *)s + offset;
ms->search.s_len = nbytes - offset;
+ ms->search.offset = offset;
return 0;
case FILE_REGEX: {
- /*
- * offset is interpreted as last line to search,
- * (starting at 1), not as bytes-from start-of-file
- */
const char *b;
const char *c;
const char *last; /* end of search region */
@@ -879,7 +896,7 @@ mget(struct magic_set *ms, const unsigned char *s,
struct magic *m, size_t nbytes, unsigned int cont_level)
{
uint32_t offset = ms->offset;
- uint32_t count = m->str_count;
+ uint32_t count = m->str_range;
union VALUETYPE *p = &ms->ms_value;
if (mcopy(ms, p, m->type, m->flag & INDIR, s, offset, nbytes, count) == -1)
@@ -893,8 +910,8 @@ mget(struct magic_set *ms, const unsigned char *s,
if (m->flag & INDIR) {
int off = m->in_offset;
if (m->in_op & FILE_OPINDIRECT) {
- const union VALUETYPE *q =
- ((const void *)(s + offset + off));
+ const union VALUETYPE *q = CAST(const union VALUETYPE *,
+ ((const void *)(s + offset + off)));
switch (m->in_type) {
case FILE_BYTE:
off = q->b;
@@ -1340,13 +1357,6 @@ mget(struct magic_set *ms, const unsigned char *s,
case FILE_OPMODULO:
offset = p->l % off;
break;
- /* case TOOMANYSWITCHBLOCKS:
- * ugh = p->eye % m->strain;
- * rub;
- * case BEER:
- * off = p->tab & m->in_gest;
- * sleep;
- */
}
} else
offset = p->l;
@@ -1443,10 +1453,8 @@ file_strncmp(const char *s1, const char *s2, size_t len, uint32_t flags)
uint64_t v;
/*
- * What we want here is:
- * v = strncmp(m->value.s, p->s, m->vallen);
- * but ignoring any nulls. bcmp doesn't give -/+/0
- * and isn't universally available anyway.
+ * What we want here is v = strncmp(s1, s2, len),
+ * but ignoring any nulls.
*/
v = 0;
if (0L == flags) { /* normal string: do it fast */
@@ -1646,15 +1654,14 @@ magiccheck(struct magic_set *ms, struct magic *m)
slen = MIN(m->vallen, sizeof(m->value.s));
l = 0;
v = 0;
- ms->search.offset = m->offset;
- for (idx = 0; m->str_count == 0 || idx < m->str_count; idx++) {
+ for (idx = 0; m->str_range == 0 || idx < m->str_range; idx++) {
if (slen + idx > ms->search.s_len)
break;
v = file_strncmp(m->value.s, ms->search.s + idx, slen, m->str_flags);
if (v == 0) { /* found match */
- ms->search.offset = m->offset + idx;
+ ms->search.offset += idx;
break;
}
}
OpenPOWER on IntegriCloud