+
+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)
-.\" $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
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
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.
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.
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
.\" 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 $
# 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
# 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
#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) && \
{ 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
case FILE_LELDATE:
case FILE_BELDATE:
case FILE_MELDATE:
+ case FILE_FLOAT:
+ case FILE_BEFLOAT:
+ case FILE_LEFLOAT:
val += 4 * MULT;
break;
case FILE_QLDATE:
case FILE_LEQLDATE:
case FILE_BEQLDATE:
+ case FILE_DOUBLE:
+ case FILE_BEDOUBLE:
+ case FILE_LEDOUBLE:
val += 8 * MULT;
break;
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:
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:
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,
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++;
}
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;
*/
/*
* 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__
#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 || \
#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 */
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 */
#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]))
(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;
#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,
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;
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;
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
((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:
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:
{
uint64_t l = m->value.q;
uint64_t v;
+ float fl, fv;
+ double dl, dv;
int matched;
union VALUETYPE *p = &ms->ms_value;
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;