]> granicus.if.org Git - file/commitdiff
float and double formats from behanw@websterwood.com (Behan Webster)
authorChristos Zoulas <christos@zoulas.com>
Thu, 8 Nov 2007 00:31:37 +0000 (00:31 +0000)
committerChristos Zoulas <christos@zoulas.com>
Thu, 8 Nov 2007 00:31:37 +0000 (00:31 +0000)
ChangeLog
doc/magic.man
magic/Magdir/animation
magic/Magdir/archive
src/apprentice.c
src/file.h
src/print.c
src/softmagic.c

index e9f7d985021d53c92313a5109cd295933227a447..b64b4939e1ff8039c4ae6c4cf5d8e8880e6768ea 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+
+2007-10-28 20:48 Christos Zoulas <christos@zoulas.com>
+
+       * float and double magic support (Behan Webster) 
+
 2007-10-28 20:48 Christos Zoulas <christos@zoulas.com>
 
        * Convert fortran to a soft test (Reuben Thomas)
index e98f915b9b7115e5676aa9d8472cd8dc8f0fe067..3842b6481c309ec5138576e838e46ea2882ce521 100644 (file)
@@ -1,4 +1,4 @@
-.\" $File: magic.man,v 1.38 2007/01/27 00:52:08 ljt Exp $
+.\" $File: magic.man,v 1.39 2007/11/08 00:31:37 christos Exp $
 .Dd January 10, 2007
 .Dt MAGIC __FSECTION__
 .Os
@@ -45,6 +45,10 @@ A two-byte value (on most systems) in this machine's native byte order.
 A four-byte value (on most systems) in this machine's native byte order.
 .It Dv quad
 An eight-byte value (on most systems) in this machine's native byte order.
+.It Dv float
+A 32-bit (on most systems) single precision IEEE floating point number in this machine's native byte order.
+.It Dv double
+A 64-bit (on most systems) double precision IEEE floating point number in this machine's native byte order.
 .It Dv string
 A string of bytes.
 The string type specification can be optionally followed
@@ -87,6 +91,10 @@ A two-byte value (on most systems) in big-endian byte order.
 A four-byte value (on most systems) in big-endian byte order.
 .It Dv bequad
 An eight-byte value (on most systems) in big-endian byte order.
+.It Dv befloat
+A 32-bit (on most systems) single precision IEEE floating point number in big-endian byte order.
+.It Dv bedouble
+A 64-bit (on most systems) double precision IEEE floating point number in big-endian byte order.
 .It Dv bedate
 A four-byte value (on most systems) in big-endian byte order,
 interpreted as a Unix date.
@@ -109,6 +117,10 @@ A two-byte value (on most systems) in little-endian byte order.
 A four-byte value (on most systems) in little-endian byte order.
 .It Dv lequad
 An eight-byte value (on most systems) in little-endian byte order.
+.It Dv lefloat
+A 32-bit (on most systems) single precision IEEE floating point number in little-endian byte order.
+.It Dv ledouble
+A 64-bit (on most systems) double precision IEEE floating point number in little-endian byte order.
 .It Dv ledate
 A four-byte value (on most systems) in little-endian byte order,
 interpreted as a UNIX date.
@@ -214,6 +226,12 @@ the value specified after is negated before tested.
 to specify that any value will match.
 If the character is omitted, it is assumed to be
 .Dv = .
+Operators
+.Dv \*[Am] ,
+.Dv ^ ,
+and
+.Dv ~
+don't work with floats and doubles.
 For all tests except
 .Em string
 and
@@ -450,4 +468,4 @@ a system on which the lengths are invariant.
 .\" the changes I posted to the S5R2 version.
 .\"
 .\" Modified for Ian Darwin's version of the file command.
-.\" @(#)$Id: magic.man,v 1.38 2007/01/27 00:52:08 ljt Exp $
+.\" @(#)$Id: magic.man,v 1.39 2007/11/08 00:31:37 christos Exp $
index 38399275baf3b0ec8d3eed2dbf3eaba4b54d18d9..6392f850887e8eb8648481c098a21837d60dce76 100644 (file)
 
 # From: Behan Webster <behanw@websterwood.com>
 # NuppelVideo used by Mythtv (*.nuv)
-0      regex           NuppelVideo|MythTVVideo         MythTV NuppelVideo
+0      regex           NuppelVideo|MythTVVideo MythTV NuppelVideo
 >12    string          x               v%s
->20    long            x               (%d
->24    long            x               \bx%d
->36    string          P               progressive
->36    string          I               interlaced
->72    byte            x               \b)
-
+>20    lelong          x               (%d
+>24    lelong          x               \bx%d),
+>36    string          P               \bprogressive,
+>36    string          I               \binterlaced,
+>40    ledouble        x               \baspect:%.2f,
+>48    ledouble        x               \bfps:%.2f
index ef8430e63e7ed214266d1e34df5d072ff1d26c1c..dae81d918f6efeeaa26f2033547d79afa8737ad3 100644 (file)
 
 # ZIP archives (Greg Roelofs, c/o zip-bugs@wkuvx1.wku.edu)
 0      string          PK\003\004
->      byte            0x00            Zip archive data
+>4     byte            0x00            Zip archive data
 >4     byte            0x09            Zip archive data, at least v0.9 to extract
 >4     byte            0x0a            Zip archive data, at least v1.0 to extract
 >4     byte            0x0b            Zip archive data, at least v1.1 to extract
index c421b2ac7791437aedb12389fce477699083e6f7..8b12853aef324fc6db9f246bef8c7253439fdd4b 100644 (file)
@@ -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;
index cc8b4d299206119a09f2c105b6dece0a37cc5a51..ce0f4e2630222f171819adb21558539feebc0085 100644 (file)
@@ -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 */
index d1d1ec108e14c38c5769697b677f3e8d171d1c13..d41bb739f72866d866d544d966ac639c855f77bd 100644 (file)
@@ -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;
index efa63e94874f53c49a751c37a43b73ff7993bad0..ba2faa3832e623ff681046ca5bbdee038a5a79be 100644 (file)
@@ -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;