summaryrefslogtreecommitdiffstats
path: root/contrib/file/apprentice.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/file/apprentice.c')
-rw-r--r--contrib/file/apprentice.c370
1 files changed, 330 insertions, 40 deletions
diff --git a/contrib/file/apprentice.c b/contrib/file/apprentice.c
index 1c4664b..f9225e7 100644
--- a/contrib/file/apprentice.c
+++ b/contrib/file/apprentice.c
@@ -30,10 +30,15 @@
#include <string.h>
#include <ctype.h>
#include <errno.h>
+#ifdef QUICK
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#endif
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$Id: apprentice.c,v 1.33 2000/08/05 17:36:47 christos Exp $")
+FILE_RCSID("@(#)$Id: apprentice.c,v 1.34 2001/03/11 20:29:16 christos Exp $")
#endif /* lint */
#define EATAB {while (isascii((unsigned char) *l) && \
@@ -52,27 +57,94 @@ FILE_RCSID("@(#)$Id: apprentice.c,v 1.33 2000/08/05 17:36:47 christos Exp $")
static int getvalue __P((struct magic *, char **));
static int hextoint __P((int));
static char *getstr __P((char *, char *, int, int *));
-static int parse __P((char *, int *, int));
+static int parse __P((struct magic **, uint32 *, char *, int));
static void eatsize __P((char **));
+static int apprentice_1 __P((const char *, int));
+static int apprentice_file __P((struct magic **, uint32 *,
+ const char *, int));
+#ifdef QUICK
+static void byteswap __P((struct magic *, uint32));
+static void bs1 __P((struct magic *));
+static uint16 swap2 __P((uint16));
+static uint32 swap4 __P((uint32));
+static char * mkdbname __P((const char *));
+static int apprentice_map __P((struct magic **, uint32 *,
+ const char *, int));
+static int apprentice_compile __P((struct magic **, uint32 *,
+ const char *, int));
+#endif
static int maxmagic = 0;
-static int apprentice_1 __P((const char *, int));
+struct mlist mlist;
+
+
+/*
+ * Handle one file.
+ */
+static int
+apprentice_1(fn, action)
+ const char *fn;
+ int action;
+{
+ struct magic *magic = NULL;
+ uint32 nmagic = 0;
+ struct mlist *ml;
+ int rv = -1;
+
+#ifdef QUICK
+ if (action == COMPILE) {
+ rv = apprentice_file(&magic, &nmagic, fn, action);
+ if (rv == 0)
+ return apprentice_compile(&magic, &nmagic, fn, action);
+ else
+ return rv;
+ }
+ if ((rv = apprentice_map(&magic, &nmagic, fn, action)) != 0)
+ (void)fprintf(stderr, "%s: Using regular magic file `%s'\n",
+ progname, fn);
+#endif
+
+ if (rv != 0)
+ rv = apprentice_file(&magic, &nmagic, fn, action);
+
+ if (rv != 0)
+ return rv;
+
+ if ((ml = malloc(sizeof(*ml))) == NULL) {
+ (void) fprintf(stderr, "%s: Out of memory.\n", progname);
+ if (action == CHECK)
+ return -1;
+ }
+
+ if (magic == NULL || nmagic == 0)
+ return rv;
+
+ ml->magic = magic;
+ ml->nmagic = nmagic;
+
+ mlist.prev->next = ml;
+ ml->prev = mlist.prev;
+ ml->next = &mlist;
+ mlist.prev = ml;
+
+ return rv;
+}
+
int
-apprentice(fn, check)
+apprentice(fn, action)
const char *fn; /* list of magic files */
- int check; /* non-zero? checking-only run. */
+ int action;
{
char *p, *mfn;
int file_err, errs = -1;
- maxmagic = MAXMAGIS;
- magic = (struct magic *) calloc(sizeof(struct magic), maxmagic);
+ mlist.next = mlist.prev = &mlist;
mfn = malloc(strlen(fn)+1);
- if (magic == NULL || mfn == NULL) {
+ if (mfn == NULL) {
(void) fprintf(stderr, "%s: Out of memory.\n", progname);
- if (check)
+ if (action == CHECK)
return -1;
else
exit(1);
@@ -83,25 +155,30 @@ apprentice(fn, check)
p = strchr(fn, PATHSEP);
if (p)
*p++ = '\0';
- file_err = apprentice_1(fn, check);
+ file_err = apprentice_1(fn, action);
if (file_err > errs)
errs = file_err;
fn = p;
}
if (errs == -1)
(void) fprintf(stderr, "%s: couldn't find any magic files!\n",
- progname);
- if (!check && errs)
+ progname);
+ if (action == CHECK && errs)
exit(1);
free(mfn);
return errs;
}
+/*
+ * parse from a file
+ */
static int
-apprentice_1(fn, check)
+apprentice_file(magicp, nmagicp, fn, action)
+ struct magic **magicp;
+ uint32 *nmagicp;
const char *fn; /* name of magic file */
- int check; /* non-zero? checking-only run. */
+ int action;
{
static const char hdr[] =
"cont\toffset\ttype\topcode\tmask\tvalue\tdesc";
@@ -110,7 +187,7 @@ apprentice_1(fn, check)
int errs = 0;
f = fopen(fn, "r");
- if (f==NULL) {
+ if (f == NULL) {
if (errno != ENOENT)
(void) fprintf(stderr,
"%s: can't read magic file %s (%s)\n",
@@ -118,8 +195,16 @@ apprentice_1(fn, check)
return -1;
}
+ maxmagic = MAXMAGIS;
+ *magicp = (struct magic *) calloc(sizeof(struct magic), maxmagic);
+ if (*magicp == NULL) {
+ (void) fprintf(stderr, "%s: Out of memory.\n", progname);
+ if (action == CHECK)
+ return -1;
+ }
+
/* parse it */
- if (check) /* print silly verbose header for USG compat. */
+ if (action == CHECK) /* print silly verbose header for USG compat. */
(void) printf("%s\n", hdr);
for (lineno = 1;fgets(line, BUFSIZ, f) != NULL; lineno++) {
@@ -128,11 +213,16 @@ apprentice_1(fn, check)
if (strlen(line) <= (unsigned)1) /* null line, garbage, etc */
continue;
line[strlen(line)-1] = '\0'; /* delete newline */
- if (parse(line, &nmagic, check) != 0)
+ if (parse(magicp, nmagicp, line, action) != 0)
errs = 1;
}
(void) fclose(f);
+ if (errs) {
+ free(*magicp);
+ *magicp = NULL;
+ *nmagicp = 0;
+ }
return errs;
}
@@ -181,32 +271,35 @@ signextend(m, v)
* parse one line from magic file, put into magic[index++] if valid
*/
static int
-parse(l, ndx, check)
+parse(magicp, nmagicp, l, action)
+ struct magic **magicp;
+ uint32 *nmagicp;
char *l;
- int *ndx, check;
+ int action;
{
- int i = 0, nd = *ndx;
+ int i = 0;
struct magic *m;
char *t, *s;
#define ALLOC_INCR 200
- if (nd+1 >= maxmagic){
+ if (*nmagicp + 1 >= maxmagic){
maxmagic += ALLOC_INCR;
- if ((m = (struct magic *) realloc(magic, sizeof(struct magic) *
- maxmagic)) == NULL) {
+ if ((m = (struct magic *) realloc(*magicp,
+ sizeof(struct magic) * maxmagic)) == NULL) {
(void) fprintf(stderr, "%s: Out of memory.\n",
progname);
- if (magic)
- free(magic);
- if (check)
+ if (*magicp)
+ free(*magicp);
+ if (action == CHECK)
return -1;
else
exit(1);
}
- magic = m;
- memset(&magic[*ndx], 0, sizeof(struct magic) * ALLOC_INCR);
+ *magicp = m;
+ memset(&(*magicp)[*nmagicp], 0, sizeof(struct magic)
+ * ALLOC_INCR);
}
- m = &magic[*ndx];
+ m = &(*magicp)[*nmagicp];
m->flag = 0;
m->cont_level = 0;
@@ -231,8 +324,8 @@ parse(l, ndx, check)
l = t;
if (m->flag & INDIR) {
- m->in.type = LONG;
- m->in.offset = 0;
+ m->in_type = LONG;
+ m->in_offset = 0;
/*
* read [.lbs][+-]nnnnn)
*/
@@ -240,24 +333,24 @@ parse(l, ndx, check)
l++;
switch (*l) {
case 'l':
- m->in.type = LELONG;
+ m->in_type = LELONG;
break;
case 'L':
- m->in.type = BELONG;
+ m->in_type = BELONG;
break;
case 'h':
case 's':
- m->in.type = LESHORT;
+ m->in_type = LESHORT;
break;
case 'H':
case 'S':
- m->in.type = BESHORT;
+ m->in_type = BESHORT;
break;
case 'c':
case 'b':
case 'C':
case 'B':
- m->in.type = BYTE;
+ m->in_type = BYTE;
break;
default:
magwarn("indirect offset type %c invalid", *l);
@@ -268,8 +361,8 @@ parse(l, ndx, check)
s = l;
if (*l == '+' || *l == '-') l++;
if (isdigit((unsigned char)*l)) {
- m->in.offset = strtoul(l, &t, 0);
- if (*s == '-') m->in.offset = - m->in.offset;
+ m->in_offset = strtoul(l, &t, 0);
+ if (*s == '-') m->in_offset = - m->in_offset;
}
else
t = l;
@@ -430,10 +523,10 @@ GetDesc:
while ((m->desc[i++] = *l++) != '\0' && i<MAXDESC)
/* NULLBODY */;
- if (check) {
+ if (action == CHECK) {
mdump(m);
}
- ++(*ndx); /* make room for next */
+ ++(*nmagicp); /* make room for next */
return 0;
}
@@ -670,3 +763,200 @@ eatsize(p)
*p = l;
}
+
+#ifdef QUICK
+/*
+ * handle an mmaped file.
+ */
+static int
+apprentice_map(magicp, nmagicp, fn, action)
+ struct magic **magicp;
+ uint32 *nmagicp;
+ const char *fn;
+ int action;
+{
+ int fd;
+ struct stat st;
+ uint32 *ptr;
+ uint32 version;
+ int needsbyteswap;
+ char *dbname = mkdbname(fn);
+
+ if ((fd = open(dbname, O_RDONLY)) == -1)
+ return -1;
+
+ if (fstat(fd, &st) == -1) {
+ (void)fprintf(stderr, "%s: Cannot stat `%s' (%s)\n",
+ progname, dbname, strerror(errno));
+ goto error;
+ }
+
+ if ((*magicp = mmap(0, (size_t)st.st_size, PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_FILE, fd, (off_t)0)) == MAP_FAILED) {
+ (void)fprintf(stderr, "%s: Cannot map `%s' (%s)\n",
+ progname, dbname, strerror(errno));
+ goto error;
+ }
+ (void)close(fd);
+ ptr = (uint32 *) *magicp;
+ if (*ptr != MAGICNO) {
+ if (swap4(*ptr) != MAGICNO) {
+ (void)fprintf(stderr, "%s: Bad magic in `%s'\n",
+ progname, dbname);
+ goto error;
+ }
+ needsbyteswap = 1;
+ } else
+ needsbyteswap = 0;
+ if (needsbyteswap)
+ version = swap4(ptr[1]);
+ else
+ version = ptr[1];
+ if (version != VERSIONNO) {
+ (void)fprintf(stderr,
+ "%s: version mismatch (%d != %d) in `%s'\n",
+ progname, version, VERSION, dbname);
+ goto error;
+ }
+ *nmagicp = (st.st_size / sizeof(struct magic)) - 1;
+ (*magicp)++;
+ if (needsbyteswap)
+ byteswap(*magicp, *nmagicp);
+ return 0;
+
+error:
+ if (fd != -1)
+ (void)close(fd);
+ if (*magicp)
+ (void)munmap(*magicp, (size_t)st.st_size);
+ else {
+ *magicp = NULL;
+ *nmagicp = 0;
+ }
+ return -1;
+}
+
+/*
+ * handle an mmaped file.
+ */
+static int
+apprentice_compile(magicp, nmagicp, fn, action)
+ struct magic **magicp;
+ uint32 *nmagicp;
+ const char *fn;
+ int action;
+{
+ int fd;
+ char *dbname = mkdbname(fn);
+ static const uint32 ar[] = {
+ MAGICNO, VERSIONNO
+ };
+
+ if ((fd = open(dbname, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) {
+ (void)fprintf(stderr, "%s: Cannot open `%s' (%s)\n",
+ progname, dbname, strerror(errno));
+ return -1;
+ }
+
+ if (write(fd, ar, sizeof(ar)) != sizeof(ar)) {
+ (void)fprintf(stderr, "%s: error writing `%s' (%s)\n",
+ progname, dbname, strerror(errno));
+ return -1;
+ }
+
+ if (lseek(fd, sizeof(struct magic), SEEK_SET) != sizeof(struct magic)) {
+ (void)fprintf(stderr, "%s: error seeking `%s' (%s)\n",
+ progname, dbname, strerror(errno));
+ return -1;
+ }
+
+ if (write(fd, *magicp, sizeof(struct magic) * *nmagicp)
+ != sizeof(struct magic) * *nmagicp) {
+ (void)fprintf(stderr, "%s: error writing `%s' (%s)\n",
+ progname, dbname, strerror(errno));
+ return -1;
+ }
+
+ (void)close(fd);
+ return 0;
+}
+
+/*
+ * make a dbname
+ */
+char *
+mkdbname(fn)
+ const char *fn;
+{
+ static const char ext[] = ".mgc";
+ static char *buf = NULL;
+ size_t len = strlen(fn) + sizeof(ext) + 1;
+ if (buf == NULL)
+ buf = malloc(len);
+ else
+ buf = realloc(buf, len);
+ (void)strcpy(buf, fn);
+ (void)strcat(buf, ext);
+ return buf;
+}
+
+/*
+ * Byteswap an mmap'ed file if needed
+ */
+static void
+byteswap(magic, nmagic)
+ struct magic *magic;
+ uint32 nmagic;
+{
+ uint32 i;
+ for (i = 0; i < nmagic; i++)
+ bs1(&magic[i]);
+}
+
+/*
+ * swap a short
+ */
+static uint16
+swap2(sv)
+ uint16 sv;
+{
+ uint16 rv;
+ uint8 *s = (uint8 *) &sv;
+ uint8 *d = (uint8 *) &rv;
+ d[0] = s[1];
+ d[1] = s[0];
+ return rv;
+}
+
+/*
+ * swap an int
+ */
+static uint32
+swap4(sv)
+ uint32 sv;
+{
+ uint32 rv;
+ uint8 *s = (uint8 *) &sv;
+ uint8 *d = (uint8 *) &rv;
+ d[0] = s[3];
+ d[1] = s[2];
+ d[2] = s[1];
+ d[3] = s[0];
+ return rv;
+}
+
+/*
+ * byteswap a single magic entry
+ */
+static
+void bs1(m)
+ struct magic *m;
+{
+ m->cont_level = swap2(m->cont_level);
+ m->offset = swap4(m->offset);
+ m->in_offset = swap4(m->in_offset);
+ if (m->type != STRING)
+ m->value.l = swap4(m->value.l);
+ m->mask = swap4(m->mask);
+}
+#endif
OpenPOWER on IntegriCloud