diff options
author | Christos Zoulas <christos@zoulas.com> | 2007-11-08 00:31:37 +0000 |
---|---|---|
committer | Christos Zoulas <christos@zoulas.com> | 2007-11-08 00:31:37 +0000 |
commit | 41b716d047cc61522770090157ca207dbcade41e (patch) | |
tree | a49e0d03bb652a275a01c051adcb45f92938538c /src | |
parent | e0d26fb3276d881211945647dc6e6192da52dba8 (diff) | |
download | file-git-41b716d047cc61522770090157ca207dbcade41e.tar.gz |
float and double formats from behanw@websterwood.com (Behan Webster)
Diffstat (limited to 'src')
-rw-r--r-- | src/apprentice.c | 73 | ||||
-rw-r--r-- | src/file.h | 14 | ||||
-rw-r--r-- | src/print.c | 12 | ||||
-rw-r--r-- | src/softmagic.c | 183 |
4 files changed, 277 insertions, 5 deletions
diff --git a/src/apprentice.c b/src/apprentice.c index c421b2ac..8b12853a 100644 --- a/src/apprentice.c +++ b/src/apprentice.c @@ -46,7 +46,7 @@ #endif #ifndef lint -FILE_RCSID("@(#)$File: apprentice.c,v 1.106 2007/10/23 19:58:59 christos Exp $") +FILE_RCSID("@(#)$File: apprentice.c,v 1.107 2007/11/08 00:31:37 christos Exp $") #endif /* lint */ #define EATAB {while (isascii((unsigned char) *l) && \ @@ -188,6 +188,12 @@ static const struct type_tbl_s { { XX("qldate"), FILE_QLDATE, FILE_FMT_STR }, { XX("leqldate"), FILE_LEQLDATE, FILE_FMT_STR }, { XX("beqldate"), FILE_BEQLDATE, FILE_FMT_STR }, + { XX("float"), FILE_FLOAT, FILE_FMT_FLOAT }, + { XX("befloat"), FILE_BEFLOAT, FILE_FMT_FLOAT }, + { XX("lefloat"), FILE_LEFLOAT, FILE_FMT_FLOAT }, + { XX("double"), FILE_DOUBLE, FILE_FMT_DOUBLE }, + { XX("bedouble"), FILE_BEDOUBLE, FILE_FMT_DOUBLE }, + { XX("ledouble"), FILE_LEDOUBLE, FILE_FMT_DOUBLE }, { XX_NULL, FILE_INVALID, FILE_FMT_NONE }, # undef XX # undef XX_NULL @@ -432,6 +438,9 @@ apprentice_magic_strength(const struct magic *m) case FILE_LELDATE: case FILE_BELDATE: case FILE_MELDATE: + case FILE_FLOAT: + case FILE_BEFLOAT: + case FILE_LEFLOAT: val += 4 * MULT; break; @@ -444,6 +453,9 @@ apprentice_magic_strength(const struct magic *m) case FILE_QLDATE: case FILE_LEQLDATE: case FILE_BEQLDATE: + case FILE_DOUBLE: + case FILE_BEDOUBLE: + case FILE_LEDOUBLE: val += 8 * MULT; break; @@ -647,6 +659,9 @@ file_signextend(struct magic_set *ms, struct magic *m, uint64_t v) case FILE_BELONG: case FILE_LELONG: case FILE_MELONG: + case FILE_FLOAT: + case FILE_BEFLOAT: + case FILE_LEFLOAT: v = (int32_t) v; break; case FILE_QUAD: @@ -658,6 +673,9 @@ file_signextend(struct magic_set *ms, struct magic *m, uint64_t v) case FILE_BEQLDATE: case FILE_LEQDATE: case FILE_LEQLDATE: + case FILE_DOUBLE: + case FILE_BEDOUBLE: + case FILE_LEDOUBLE: v = (int64_t) v; break; case FILE_STRING: @@ -960,6 +978,16 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp, case 'B': m->in_type = FILE_BYTE; break; + case 'e': + case 'f': + case 'g': + m->in_type = FILE_LEDOUBLE; + break; + case 'E': + case 'F': + case 'G': + m->in_type = FILE_BEDOUBLE; + break; default: if (ms->flags & MAGIC_CHECK) file_magwarn(ms, @@ -1253,6 +1281,31 @@ check_format_type(const char *ptr, int type) return -1; } + case FILE_FMT_FLOAT: + case FILE_FMT_DOUBLE: + if (*ptr == '-') + ptr++; + if (*ptr == '.') + ptr++; + while (isdigit((unsigned char)*ptr)) ptr++; + if (*ptr == '.') + ptr++; + while (isdigit((unsigned char)*ptr)) ptr++; + + switch (*ptr++) { + case 'e': + case 'E': + case 'f': + case 'F': + case 'g': + case 'G': + return 0; + + default: + return -1; + } + + case FILE_FMT_STR: if (*ptr == '-') ptr++; @@ -1359,6 +1412,24 @@ getvalue(struct magic_set *ms, struct magic *m, const char **p, int action) } m->vallen = slen; return 0; + case FILE_FLOAT: + case FILE_BEFLOAT: + case FILE_LEFLOAT: + if (m->reln != 'x') { + char *ep; + m->value.f = strtof(*p, &ep); + *p = ep; + } + return 0; + case FILE_DOUBLE: + case FILE_BEDOUBLE: + case FILE_LEDOUBLE: + if (m->reln != 'x') { + char *ep; + m->value.d = strtod(*p, &ep); + *p = ep; + } + return 0; default: if (m->reln != 'x') { char *ep; @@ -27,7 +27,7 @@ */ /* * file.h - definitions for file(1) program - * @(#)$File: file.h,v 1.91 2007/03/25 03:13:47 christos Exp $ + * @(#)$File: file.h,v 1.92 2007/11/08 00:31:37 christos Exp $ */ #ifndef __file_h__ @@ -146,7 +146,13 @@ struct magic { #define FILE_QLDATE 30 #define FILE_LEQLDATE 31 #define FILE_BEQLDATE 32 -#define FILE_NAMES_SIZE 33/* size of array to contain all names */ +#define FILE_FLOAT 33 +#define FILE_BEFLOAT 34 +#define FILE_LEFLOAT 35 +#define FILE_DOUBLE 36 +#define FILE_BEDOUBLE 37 +#define FILE_LEDOUBLE 38 +#define FILE_NAMES_SIZE 39/* size of array to contain all names */ #define IS_STRING(t) \ ((t) == FILE_STRING || \ @@ -161,6 +167,8 @@ struct magic { #define FILE_FMT_NUM 1 /* "cduxXi" */ #define FILE_FMT_STR 2 /* "s" */ #define FILE_FMT_QUAD 3 /* "ll" */ +#define FILE_FMT_FLOAT 4 /* "eEfFgG" */ +#define FILE_FMT_DOUBLE 5 /* "eEfFgG" */ /* Word 3 */ uint8_t in_op; /* operator for indirection */ @@ -224,6 +232,8 @@ struct magic { uint8_t hl[4]; /* 4 bytes of a fixed-endian "long" */ uint8_t hq[8]; /* 8 bytes of a fixed-endian "quad" */ char s[MAXstring]; /* the search string or regex pattern */ + float f; + double d; } value; /* either number or string */ /* Words 17..31 */ char desc[MAXDESC]; /* description */ diff --git a/src/print.c b/src/print.c index d1d1ec10..d41bb739 100644 --- a/src/print.c +++ b/src/print.c @@ -41,7 +41,7 @@ #include <time.h> #ifndef lint -FILE_RCSID("@(#)$File: print.c,v 1.59 2007/03/05 02:41:29 christos Exp $") +FILE_RCSID("@(#)$File: print.c,v 1.60 2007/11/08 00:31:37 christos Exp $") #endif /* lint */ #define SZOF(a) (sizeof(a) / sizeof(a[0])) @@ -157,6 +157,16 @@ file_mdump(struct magic *m) (void)fprintf(stderr, "%s,", file_fmttime((uint32_t)m->value.q, 0)); 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_DEFAULT: /* XXX - do anything here? */ break; diff --git a/src/softmagic.c b/src/softmagic.c index efa63e94..ba2faa38 100644 --- a/src/softmagic.c +++ b/src/softmagic.c @@ -38,7 +38,7 @@ #ifndef lint -FILE_RCSID("@(#)$File: softmagic.c,v 1.101 2007/10/17 19:33:31 christos Exp $") +FILE_RCSID("@(#)$File: softmagic.c,v 1.102 2007/11/08 00:31:37 christos Exp $") #endif /* lint */ private int match(struct magic_set *, struct magic *, uint32_t, @@ -311,6 +311,8 @@ private int32_t mprint(struct magic_set *ms, struct magic *m) { uint64_t v; + float vf; + double vd; int64_t t = 0; char buf[512]; union VALUETYPE *p = &ms->ms_value; @@ -446,6 +448,48 @@ mprint(struct magic_set *ms, struct magic *m) t = ms->offset + sizeof(uint64_t); 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 (snprintf(buf, sizeof(buf), "%g", vf) < 0) + return -1; + if (file_printf(ms, m->desc, buf) == -1) + return -1; + break; + default: + if (file_printf(ms, m->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 (snprintf(buf, sizeof(buf), "%g", vd) < 0) + return -1; + if (file_printf(ms, m->desc, buf) == -1) + return -1; + break; + default: + if (file_printf(ms, m->desc, vd) == -1) + return -1; + break; + } + t = ms->offset + sizeof(double); + break; + case FILE_REGEX: { char *cp; int rval; @@ -546,6 +590,35 @@ cvt_64(union VALUETYPE *p, const struct magic *m) 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 * While we're here, let's apply the mask operation @@ -645,6 +718,36 @@ mconvert(struct magic_set *ms, struct magic *m) ((p->hl[1]<<24)|(p->hl[0]<<16)|(p->hl[3]<<8)|(p->hl[2])); cvt_32(p, m); 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_SEARCH: case FILE_DEFAULT: @@ -1294,10 +1397,20 @@ mget(struct magic_set *ms, const unsigned char *s, case FILE_BELDATE: case FILE_LELDATE: case FILE_MELDATE: + case FILE_FLOAT: + case FILE_BEFLOAT: + case FILE_LEFLOAT: if (nbytes < (offset + 4)) return 0; break; + case FILE_DOUBLE: + case FILE_BEDOUBLE: + case FILE_LEDOUBLE: + if (nbytes < (offset + 8)) + return 0; + break; + case FILE_STRING: case FILE_PSTRING: case FILE_SEARCH: @@ -1400,6 +1513,8 @@ magiccheck(struct magic_set *ms, struct magic *m) { uint64_t l = m->value.q; uint64_t v; + float fl, fv; + double dl, dv; int matched; union VALUETYPE *p = &ms->ms_value; @@ -1441,6 +1556,72 @@ magiccheck(struct magic_set *ms, struct magic *m) v = p->q; 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: l = 0; v = 0; |