version 1.13, 2008/05/08 01:40:56 |
version 1.14, 2009/04/24 18:54:34 |
|
|
#endif /* lint */ |
#endif /* lint */ |
|
|
private int match(struct magic_set *, struct magic *, uint32_t, |
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 *, |
private int mget(struct magic_set *, const unsigned char *, |
struct magic *, size_t, unsigned int); |
struct magic *, size_t, unsigned int); |
private int magiccheck(struct magic_set *, struct magic *); |
private int magiccheck(struct magic_set *, struct magic *); |
|
|
private void cvt_64(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 |
* softmagic - lookup one file in parsed, in-memory copy of database |
* Passed the name and FILE * of one file to be typed. |
* Passed the name and FILE * of one file to be typed. |
*/ |
*/ |
/*ARGSUSED1*/ /* nbytes passed for regularity, maybe need later */ |
/*ARGSUSED1*/ /* nbytes passed for regularity, maybe need later */ |
protected int |
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; |
struct mlist *ml; |
int rv; |
int rv; |
for (ml = ms->mlist->next; ml != ms->mlist; ml = ml->next) |
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 rv; |
|
|
return 0; |
return 0; |
|
|
*/ |
*/ |
private int |
private int |
match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, |
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; |
uint32_t magindex = 0; |
unsigned int cont_level = 0; |
unsigned int cont_level = 0; |
|
|
|
|
for (magindex = 0; magindex < nmagic; magindex++) { |
for (magindex = 0; magindex < nmagic; magindex++) { |
int flush; |
int flush; |
|
struct magic *m = &magic[magindex]; |
|
|
ms->offset = magic[magindex].offset; |
if ((m->flag & BINTEST) != mode) { |
ms->line = magic[magindex].lineno; |
/* 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... */ |
/* 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 (flush) { |
if (magic[magindex].reln == '!') |
if (m->reln == '!') |
flush = 0; |
flush = 0; |
} else { |
} else { |
switch (magiccheck(ms, &magic[magindex])) { |
switch (magiccheck(ms, m)) { |
case -1: |
case -1: |
return -1; |
return -1; |
case 0: |
case 0: |
|
|
* If we are going to print something, we'll need to print |
* If we are going to print something, we'll need to print |
* a blank before we print something else. |
* a blank before we print something else. |
*/ |
*/ |
if (magic[magindex].desc[0]) { |
if (*MAGIC_DESC) { |
need_separator = 1; |
need_separator = 1; |
printed_something = 1; |
printed_something = 1; |
if (print_sep(ms, firstline) == -1) |
if (print_sep(ms, firstline) == -1) |
return -1; |
return -1; |
} |
} |
|
|
if ((ms->c.li[cont_level].off = mprint(ms, &magic[magindex])) |
if ((ms->c.li[cont_level].off = mprint(ms, m)) == -1) |
== -1) |
|
return -1; |
return -1; |
|
|
/* and any continuations that match */ |
/* and any continuations that match */ |
|
|
|
|
while (magic[magindex+1].cont_level != 0 && |
while (magic[magindex+1].cont_level != 0 && |
++magindex < nmagic) { |
++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; |
continue; |
if (cont_level > magic[magindex].cont_level) { |
if (cont_level > m->cont_level) { |
/* |
/* |
* We're at the end of the level |
* We're at the end of the level |
* "cont_level" continuations. |
* "cont_level" continuations. |
*/ |
*/ |
cont_level = magic[magindex].cont_level; |
cont_level = m->cont_level; |
} |
} |
ms->offset = magic[magindex].offset; |
ms->offset = m->offset; |
if (magic[magindex].flag & OFFADD) { |
if (m->flag & OFFADD) { |
ms->offset += |
ms->offset += |
ms->c.li[cont_level - 1].off; |
ms->c.li[cont_level - 1].off; |
} |
} |
|
|
#ifdef ENABLE_CONDITIONALS |
#ifdef ENABLE_CONDITIONALS |
if (magic[magindex].cond == COND_ELSE || |
if (m->cond == COND_ELSE || |
magic[magindex].cond == COND_ELIF) { |
m->cond == COND_ELIF) { |
if (ms->c.li[cont_level].last_match == 1) |
if (ms->c.li[cont_level].last_match == 1) |
continue; |
continue; |
} |
} |
#endif |
#endif |
flush = !mget(ms, s, &magic[magindex], nbytes, |
flush = !mget(ms, s, m, nbytes, cont_level); |
cont_level); |
if (flush && m->reln != '!') |
if (flush && magic[magindex].reln != '!') |
|
continue; |
continue; |
|
|
switch (flush ? 1 : magiccheck(ms, &magic[magindex])) { |
switch (flush ? 1 : magiccheck(ms, m)) { |
case -1: |
case -1: |
return -1; |
return -1; |
case 0: |
case 0: |
|
|
#ifdef ENABLE_CONDITIONALS |
#ifdef ENABLE_CONDITIONALS |
ms->c.li[cont_level].last_match = 1; |
ms->c.li[cont_level].last_match = 1; |
#endif |
#endif |
if (magic[magindex].type != FILE_DEFAULT) |
if (m->type != FILE_DEFAULT) |
ms->c.li[cont_level].got_match = 1; |
ms->c.li[cont_level].got_match = 1; |
else if (ms->c.li[cont_level].got_match) { |
else if (ms->c.li[cont_level].got_match) { |
ms->c.li[cont_level].got_match = 0; |
ms->c.li[cont_level].got_match = 0; |
|
|
* If we are going to print something, |
* If we are going to print something, |
* make sure that we have a separator first. |
* make sure that we have a separator first. |
*/ |
*/ |
if (magic[magindex].desc[0]) { |
if (*MAGIC_DESC) { |
printed_something = 1; |
printed_something = 1; |
if (print_sep(ms, firstline) == -1) |
if (print_sep(ms, firstline) == -1) |
return -1; |
return -1; |
|
|
*/ |
*/ |
/* space if previous printed */ |
/* space if previous printed */ |
if (need_separator |
if (need_separator |
&& (magic[magindex].nospflag == 0) |
&& ((m->flag & NOSPACE) == 0) |
&& (magic[magindex].desc[0] != '\0')) { |
&& *MAGIC_DESC) { |
if (file_printf(ms, " ") == -1) |
if (file_printf(ms, " ") == -1) |
return -1; |
return -1; |
need_separator = 0; |
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; |
return -1; |
if (magic[magindex].desc[0]) |
if (*MAGIC_DESC) |
need_separator = 1; |
need_separator = 1; |
|
|
/* |
/* |
|
|
break; |
break; |
} |
} |
} |
} |
firstline = 0; |
if (printed_something) { |
if (printed_something) |
firstline = 0; |
returnval = 1; |
returnval = 1; |
|
} |
if ((ms->flags & MAGIC_CONTINUE) == 0 && printed_something) { |
if ((ms->flags & MAGIC_CONTINUE) == 0 && printed_something) { |
return 1; /* don't keep searching */ |
return 1; /* don't keep searching */ |
} |
} |
|
|
regex_t rx; |
regex_t rx; |
int rc; |
int rc; |
|
|
if (strchr(m->desc, '%') == NULL) |
if (strchr(MAGIC_DESC, '%') == NULL) |
return 0; |
return 0; |
|
|
rc = regcomp(&rx, "%[-0-9\\.]*s", REG_EXTENDED|REG_NOSUB); |
rc = regcomp(&rx, "%[-0-9\\.]*s", REG_EXTENDED|REG_NOSUB); |
|
|
file_magerror(ms, "regex error %d, (%s)", rc, errmsg); |
file_magerror(ms, "regex error %d, (%s)", rc, errmsg); |
return -1; |
return -1; |
} else { |
} else { |
rc = regexec(&rx, m->desc, 0, 0, 0); |
rc = regexec(&rx, MAGIC_DESC, 0, 0, 0); |
regfree(&rx); |
regfree(&rx); |
return !rc; |
return !rc; |
} |
} |
|
|
mprint(struct magic_set *ms, struct magic *m) |
mprint(struct magic_set *ms, struct magic *m) |
{ |
{ |
uint64_t v; |
uint64_t v; |
|
float vf; |
|
double vd; |
int64_t t = 0; |
int64_t t = 0; |
char buf[512]; |
char *buf; |
union VALUETYPE *p = &ms->ms_value; |
union VALUETYPE *p = &ms->ms_value; |
|
|
switch (m->type) { |
switch (m->type) { |
|
|
case -1: |
case -1: |
return -1; |
return -1; |
case 1: |
case 1: |
if (snprintf(buf, sizeof(buf), "%c", |
if (asprintf(&buf, "%c", (unsigned char)v) < 0) |
(unsigned char)v) < 0) |
|
return -1; |
return -1; |
if (file_printf(ms, m->desc, buf) == -1) |
if (file_printf(ms, MAGIC_DESC, buf) == -1) |
return -1; |
return -1; |
break; |
break; |
default: |
default: |
if (file_printf(ms, m->desc, (unsigned char) v) == -1) |
if (file_printf(ms, MAGIC_DESC, (unsigned char) v) == -1) |
return -1; |
return -1; |
break; |
break; |
} |
} |
|
|
case -1: |
case -1: |
return -1; |
return -1; |
case 1: |
case 1: |
if (snprintf(buf, sizeof(buf), "%hu", |
if (asprintf(&buf, "%hu", (unsigned short)v) < 0) |
(unsigned short)v) < 0) |
|
return -1; |
return -1; |
if (file_printf(ms, m->desc, buf) == -1) |
if (file_printf(ms, MAGIC_DESC, buf) == -1) |
return -1; |
return -1; |
break; |
break; |
default: |
default: |
if (file_printf(ms, m->desc, (unsigned short) v) == -1) |
if (file_printf(ms, MAGIC_DESC, (unsigned short) v) == -1) |
return -1; |
return -1; |
break; |
break; |
} |
} |
|
|
case -1: |
case -1: |
return -1; |
return -1; |
case 1: |
case 1: |
if (snprintf(buf, sizeof(buf), "%u", (uint32_t)v) < 0) |
if (asprintf(&buf, "%u", (uint32_t)v) < 0) |
return -1; |
return -1; |
if (file_printf(ms, m->desc, buf) == -1) |
if (file_printf(ms, MAGIC_DESC, buf) == -1) |
return -1; |
return -1; |
break; |
break; |
default: |
default: |
if (file_printf(ms, m->desc, (uint32_t) v) == -1) |
if (file_printf(ms, MAGIC_DESC, (uint32_t) v) == -1) |
return -1; |
return -1; |
break; |
break; |
} |
} |
|
|
case FILE_BEQUAD: |
case FILE_BEQUAD: |
case FILE_LEQUAD: |
case FILE_LEQUAD: |
v = file_signextend(ms, m, p->q); |
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; |
return -1; |
t = ms->offset + sizeof(int64_t); |
t = ms->offset + sizeof(int64_t); |
break; |
break; |
|
|
case FILE_BESTRING16: |
case FILE_BESTRING16: |
case FILE_LESTRING16: |
case FILE_LESTRING16: |
if (m->reln == '=' || m->reln == '!') { |
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; |
return -1; |
t = ms->offset + m->vallen; |
t = ms->offset + m->vallen; |
} |
} |
else { |
else { |
if (*m->value.s == '\0') |
if (*m->value.s == '\0') |
p->s[strcspn(p->s, "\n")] = '\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; |
return -1; |
t = ms->offset + strlen(p->s); |
t = ms->offset + strlen(p->s); |
|
if (m->type == FILE_PSTRING) |
|
t++; |
} |
} |
break; |
break; |
|
|
|
|
case FILE_BEDATE: |
case FILE_BEDATE: |
case FILE_LEDATE: |
case FILE_LEDATE: |
case FILE_MEDATE: |
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; |
return -1; |
t = ms->offset + sizeof(time_t); |
t = ms->offset + sizeof(time_t); |
break; |
break; |
|
|
case FILE_BELDATE: |
case FILE_BELDATE: |
case FILE_LELDATE: |
case FILE_LELDATE: |
case FILE_MELDATE: |
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; |
return -1; |
t = ms->offset + sizeof(time_t); |
t = ms->offset + sizeof(time_t); |
break; |
break; |
|
|
case FILE_QDATE: |
case FILE_QDATE: |
case FILE_BEQDATE: |
case FILE_BEQDATE: |
case FILE_LEQDATE: |
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) |
== -1) |
return -1; |
return -1; |
t = ms->offset + sizeof(uint64_t); |
t = ms->offset + sizeof(uint64_t); |
|
|
case FILE_QLDATE: |
case FILE_QLDATE: |
case FILE_BEQLDATE: |
case FILE_BEQLDATE: |
case FILE_LEQLDATE: |
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) |
== -1) |
return -1; |
return -1; |
t = ms->offset + sizeof(uint64_t); |
t = ms->offset + sizeof(uint64_t); |
break; |
break; |
|
|
|
case FILE_FLOAT: |
|
case FILE_BEFLOAT: |
|
case FILE_LEFLOAT: |
|
vf = p->f; |
|
switch (check_fmt(ms, m)) { |
|
case -1: |
|
return -1; |
|
case 1: |
|
if (asprintf(&buf, "%g", vf) < 0) |
|
return -1; |
|
if (file_printf(ms, MAGIC_DESC, buf) == -1) |
|
return -1; |
|
break; |
|
default: |
|
if (file_printf(ms, MAGIC_DESC, vf) == -1) |
|
return -1; |
|
break; |
|
} |
|
t = ms->offset + sizeof(float); |
|
break; |
|
|
|
case FILE_DOUBLE: |
|
case FILE_BEDOUBLE: |
|
case FILE_LEDOUBLE: |
|
vd = p->d; |
|
switch (check_fmt(ms, m)) { |
|
case -1: |
|
return -1; |
|
case 1: |
|
if (asprintf(&buf, "%g", vd) < 0) |
|
return -1; |
|
if (file_printf(ms, MAGIC_DESC, buf) == -1) |
|
return -1; |
|
break; |
|
default: |
|
if (file_printf(ms, MAGIC_DESC, vd) == -1) |
|
return -1; |
|
break; |
|
} |
|
t = ms->offset + sizeof(double); |
|
break; |
|
|
case FILE_REGEX: { |
case FILE_REGEX: { |
char *cp; |
char *cp; |
int rval; |
int rval; |
|
|
file_oomem(ms, ms->search.rm_len); |
file_oomem(ms, ms->search.rm_len); |
return -1; |
return -1; |
} |
} |
rval = file_printf(ms, m->desc, cp); |
rval = file_printf(ms, MAGIC_DESC, cp); |
free(cp); |
free(cp); |
|
|
if (rval == -1) |
if (rval == -1) |
|
|
} |
} |
|
|
case FILE_SEARCH: |
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; |
return -1; |
if ((m->str_flags & REGEX_OFFSET_START)) |
if ((m->str_flags & REGEX_OFFSET_START)) |
t = ms->search.offset; |
t = ms->search.offset; |
|
|
break; |
break; |
|
|
case FILE_DEFAULT: |
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; |
return -1; |
t = ms->offset; |
t = ms->offset; |
break; |
break; |
|
|
DO_CVT(q, (uint64_t)); |
DO_CVT(q, (uint64_t)); |
} |
} |
|
|
|
#define DO_CVT2(fld, cast) \ |
|
if (m->num_mask) \ |
|
switch (m->mask_op & FILE_OPS_MASK) { \ |
|
case FILE_OPADD: \ |
|
p->fld += cast m->num_mask; \ |
|
break; \ |
|
case FILE_OPMINUS: \ |
|
p->fld -= cast m->num_mask; \ |
|
break; \ |
|
case FILE_OPMULTIPLY: \ |
|
p->fld *= cast m->num_mask; \ |
|
break; \ |
|
case FILE_OPDIVIDE: \ |
|
p->fld /= cast m->num_mask; \ |
|
break; \ |
|
} \ |
|
|
|
private void |
|
cvt_float(union VALUETYPE *p, const struct magic *m) |
|
{ |
|
DO_CVT2(f, (float)); |
|
} |
|
|
|
private void |
|
cvt_double(union VALUETYPE *p, const struct magic *m) |
|
{ |
|
DO_CVT2(d, (double)); |
|
} |
|
|
/* |
/* |
* Convert the byte order of the data we are looking at |
* Convert the byte order of the data we are looking at |
* While we're here, let's apply the mask operation |
* While we're here, let's apply the mask operation |
|
|
case FILE_BEQUAD: |
case FILE_BEQUAD: |
case FILE_BEQDATE: |
case FILE_BEQDATE: |
case FILE_BEQLDATE: |
case FILE_BEQLDATE: |
p->q = (int64_t) |
p->q = (uint64_t) |
(((int64_t)p->hq[0]<<56)|((int64_t)p->hq[1]<<48)| |
(((uint64_t)p->hq[0]<<56)|((uint64_t)p->hq[1]<<48)| |
((int64_t)p->hq[2]<<40)|((int64_t)p->hq[3]<<32)| |
((uint64_t)p->hq[2]<<40)|((uint64_t)p->hq[3]<<32)| |
(p->hq[4]<<24)|(p->hq[5]<<16)|(p->hq[6]<<8)|(p->hq[7])); |
((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); |
cvt_64(p, m); |
return 1; |
return 1; |
case FILE_LESHORT: |
case FILE_LESHORT: |
|
|
case FILE_LEQUAD: |
case FILE_LEQUAD: |
case FILE_LEQDATE: |
case FILE_LEQDATE: |
case FILE_LEQLDATE: |
case FILE_LEQLDATE: |
p->q = (int64_t) |
p->q = (uint64_t) |
(((int64_t)p->hq[7]<<56)|((int64_t)p->hq[6]<<48)| |
(((uint64_t)p->hq[7]<<56)|((uint64_t)p->hq[6]<<48)| |
((int64_t)p->hq[5]<<40)|((int64_t)p->hq[4]<<32)| |
((uint64_t)p->hq[5]<<40)|((uint64_t)p->hq[4]<<32)| |
(p->hq[3]<<24)|(p->hq[2]<<16)|(p->hq[1]<<8)|(p->hq[0])); |
((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); |
cvt_64(p, m); |
return 1; |
return 1; |
case FILE_MELONG: |
case FILE_MELONG: |
|
|
((p->hl[1]<<24)|(p->hl[0]<<16)|(p->hl[3]<<8)|(p->hl[2])); |
((p->hl[1]<<24)|(p->hl[0]<<16)|(p->hl[3]<<8)|(p->hl[2])); |
cvt_32(p, m); |
cvt_32(p, m); |
return 1; |
return 1; |
|
case FILE_FLOAT: |
|
cvt_float(p, m); |
|
return 1; |
|
case FILE_BEFLOAT: |
|
p->l = ((uint32_t)p->hl[0]<<24)|((uint32_t)p->hl[1]<<16)| |
|
((uint32_t)p->hl[2]<<8) |((uint32_t)p->hl[3]); |
|
cvt_float(p, m); |
|
return 1; |
|
case FILE_LEFLOAT: |
|
p->l = ((uint32_t)p->hl[3]<<24)|((uint32_t)p->hl[2]<<16)| |
|
((uint32_t)p->hl[1]<<8) |((uint32_t)p->hl[0]); |
|
cvt_float(p, m); |
|
return 1; |
|
case FILE_DOUBLE: |
|
cvt_double(p, m); |
|
return 1; |
|
case FILE_BEDOUBLE: |
|
p->q = ((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_double(p, m); |
|
return 1; |
|
case FILE_LEDOUBLE: |
|
p->q = ((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_double(p, m); |
|
return 1; |
case FILE_REGEX: |
case FILE_REGEX: |
case FILE_SEARCH: |
case FILE_SEARCH: |
case FILE_DEFAULT: |
case FILE_DEFAULT: |
|
|
case FILE_SEARCH: |
case FILE_SEARCH: |
ms->search.s = (const char *)s + offset; |
ms->search.s = (const char *)s + offset; |
ms->search.s_len = nbytes - offset; |
ms->search.s_len = nbytes - offset; |
|
ms->search.offset = offset; |
return 0; |
return 0; |
|
|
case FILE_REGEX: { |
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 *b; |
const char *c; |
const char *c; |
const char *last; /* end of search region */ |
const char *last; /* end of search region */ |
|
|
offset); |
offset); |
return -1; |
return -1; |
} |
} |
for (/*EMPTY*/; src < esrc; src++, dst++) { |
for (/*EMPTY*/; src < esrc; src += 2, dst++) { |
if (dst < edst) |
if (dst < edst) |
*dst = *src++; |
*dst = *src; |
else |
else |
break; |
break; |
if (*dst == '\0') |
if (*dst == '\0') { |
*dst = ' '; |
if (type == FILE_BESTRING16 ? |
|
*(src - 1) != '\0' : |
|
*(src + 1) != '\0') |
|
*dst = ' '; |
|
} |
} |
} |
*edst = '\0'; |
*edst = '\0'; |
return 0; |
return 0; |
|
|
struct magic *m, size_t nbytes, unsigned int cont_level) |
struct magic *m, size_t nbytes, unsigned int cont_level) |
{ |
{ |
uint32_t offset = ms->offset; |
uint32_t offset = ms->offset; |
uint32_t count = m->str_count; |
uint32_t count = m->str_range; |
union VALUETYPE *p = &ms->ms_value; |
union VALUETYPE *p = &ms->ms_value; |
|
|
if (mcopy(ms, p, m->type, m->flag & INDIR, s, offset, nbytes, count) == -1) |
if (mcopy(ms, p, m->type, m->flag & INDIR, s, offset, nbytes, count) == -1) |
|
|
case FILE_OPMODULO: |
case FILE_OPMODULO: |
offset = p->l % off; |
offset = p->l % off; |
break; |
break; |
/* case TOOMANYSWITCHBLOCKS: |
|
* ugh = p->eye % m->strain; |
|
* rub; |
|
* case BEER: |
|
* off = p->tab & m->in_gest; |
|
* sleep; |
|
*/ |
|
} |
} |
} else |
} else |
offset = p->l; |
offset = p->l; |
|
|
case FILE_BELDATE: |
case FILE_BELDATE: |
case FILE_LELDATE: |
case FILE_LELDATE: |
case FILE_MELDATE: |
case FILE_MELDATE: |
|
case FILE_FLOAT: |
|
case FILE_BEFLOAT: |
|
case FILE_LEFLOAT: |
if (nbytes < (offset + 4)) |
if (nbytes < (offset + 4)) |
return 0; |
return 0; |
break; |
break; |
|
|
|
case FILE_DOUBLE: |
|
case FILE_BEDOUBLE: |
|
case FILE_LEDOUBLE: |
|
if (nbytes < (offset + 8)) |
|
return 0; |
|
break; |
|
|
case FILE_STRING: |
case FILE_STRING: |
case FILE_PSTRING: |
case FILE_PSTRING: |
case FILE_SEARCH: |
case FILE_SEARCH: |
|
|
uint64_t v; |
uint64_t v; |
|
|
/* |
/* |
* What we want here is: |
* What we want here is v = strncmp(s1, s2, len), |
* v = strncmp(m->value.s, p->s, m->vallen); |
* but ignoring any nulls. |
* but ignoring any nulls. bcmp doesn't give -/+/0 |
|
* and isn't universally available anyway. |
|
*/ |
*/ |
v = 0; |
v = 0; |
if (0L == flags) { /* normal string: do it fast */ |
if (0L == flags) { /* normal string: do it fast */ |
|
|
{ |
{ |
uint64_t l = m->value.q; |
uint64_t l = m->value.q; |
uint64_t v; |
uint64_t v; |
|
float fl, fv; |
|
double dl, dv; |
int matched; |
int matched; |
union VALUETYPE *p = &ms->ms_value; |
union VALUETYPE *p = &ms->ms_value; |
|
|
|
|
v = p->q; |
v = p->q; |
break; |
break; |
|
|
|
case FILE_FLOAT: |
|
case FILE_BEFLOAT: |
|
case FILE_LEFLOAT: |
|
fl = m->value.f; |
|
fv = p->f; |
|
switch (m->reln) { |
|
case 'x': |
|
matched = 1; |
|
break; |
|
|
|
case '!': |
|
matched = fv != fl; |
|
break; |
|
|
|
case '=': |
|
matched = fv == fl; |
|
break; |
|
|
|
case '>': |
|
matched = fv > fl; |
|
break; |
|
|
|
case '<': |
|
matched = fv < fl; |
|
break; |
|
|
|
default: |
|
matched = 0; |
|
file_magerror(ms, "cannot happen with float: invalid relation `%c'", m->reln); |
|
return -1; |
|
} |
|
return matched; |
|
|
|
case FILE_DOUBLE: |
|
case FILE_BEDOUBLE: |
|
case FILE_LEDOUBLE: |
|
dl = m->value.d; |
|
dv = p->d; |
|
switch (m->reln) { |
|
case 'x': |
|
matched = 1; |
|
break; |
|
|
|
case '!': |
|
matched = dv != dl; |
|
break; |
|
|
|
case '=': |
|
matched = dv == dl; |
|
break; |
|
|
|
case '>': |
|
matched = dv > dl; |
|
break; |
|
|
|
case '<': |
|
matched = dv < dl; |
|
break; |
|
|
|
default: |
|
matched = 0; |
|
file_magerror(ms, "cannot happen with double: invalid relation `%c'", m->reln); |
|
return -1; |
|
} |
|
return matched; |
|
|
case FILE_DEFAULT: |
case FILE_DEFAULT: |
l = 0; |
l = 0; |
v = 0; |
v = 0; |
|
|
slen = MIN(m->vallen, sizeof(m->value.s)); |
slen = MIN(m->vallen, sizeof(m->value.s)); |
l = 0; |
l = 0; |
v = 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) |
if (slen + idx > ms->search.s_len) |
break; |
break; |
|
|
v = file_strncmp(m->value.s, ms->search.s + idx, slen, m->str_flags); |
v = file_strncmp(m->value.s, ms->search.s + idx, slen, m->str_flags); |
if (v == 0) { /* found match */ |
if (v == 0) { /* found match */ |
ms->search.offset = m->offset + idx; |
ms->search.offset += idx; |
break; |
break; |
} |
} |
} |
} |