]> granicus.if.org Git - file/commitdiff
reorg
authorChristos Zoulas <christos@zoulas.com>
Sun, 23 Mar 2003 04:06:04 +0000 (04:06 +0000)
committerChristos Zoulas <christos@zoulas.com>
Sun, 23 Mar 2003 04:06:04 +0000 (04:06 +0000)
13 files changed:
src/apprentice.c
src/ascmagic.c
src/compress.c
src/file.c
src/file.h
src/fsmagic.c
src/is_tar.c
src/names.h
src/patchlevel.h
src/print.c
src/readelf.c
src/readelf.h
src/softmagic.c

index ba93fc281d6124dc44f6de4745798dcfc743f34d..260449bee955c8f7b58fcb5fb7d1de7db8182e6a 100644 (file)
@@ -26,6 +26,7 @@
  */
 
 #include "file.h"
+#include "magic.h"
 #include <stdlib.h>
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #include <string.h>
 #include <ctype.h>
 #include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/param.h>
 #ifdef QUICK
 #include <sys/mman.h>
 #endif
 
 #ifndef        lint
-FILE_RCSID("@(#)$Id: apprentice.c,v 1.51 2003/03/11 14:52:56 christos Exp $")
+FILE_RCSID("@(#)$Id: apprentice.c,v 1.52 2003/03/23 04:06:04 christos Exp $")
 #endif /* lint */
 
 #define        EATAB {while (isascii((unsigned char) *l) && \
@@ -70,24 +73,25 @@ FILE_RCSID("@(#)$Id: apprentice.c,v 1.51 2003/03/11 14:52:56 christos Exp $")
 #endif
 
 
-static int getvalue(struct magic *, char **);
-static int hextoint(int);
-static char *getstr(char *, char *, int, int *);
-static int parse(struct magic **, uint32_t *, char *, int);
-static void eatsize(char **);
-static int apprentice_1(const char *, int);
-static int apprentice_file(struct magic **, uint32_t *, const char *, int);
-static void byteswap(struct magic *, uint32_t);
-static void bs1(struct magic *);
-static uint16_t swap2(uint16_t);
-static uint32_t swap4(uint32_t);
-static char *mkdbname(const char *);
-static int apprentice_map(struct magic **, uint32_t *, const char *, int);
-static int apprentice_compile(struct magic **, uint32_t *, const char *, int);
-
-static int maxmagic = 0;
-
-struct mlist mlist;
+private int getvalue(struct magic_set *ms, struct magic *, char **);
+private int hextoint(int);
+private char *getstr(struct magic_set *, char *, char *, int, int *);
+private int parse(struct magic_set *, struct magic **, uint32_t *, char *, int);
+private void eatsize(char **);
+private int apprentice_1(struct magic_set *, const char *, int, struct mlist *);
+private int apprentice_file(struct magic_set *, struct magic **, uint32_t *,
+    const char *, int);
+private void byteswap(struct magic *, uint32_t);
+private void bs1(struct magic *);
+private uint16_t swap2(uint16_t);
+private uint32_t swap4(uint32_t);
+private char *mkdbname(struct magic_set *, const char *, char *, size_t);
+private int apprentice_map(struct magic_set *, struct magic **, uint32_t *,
+    const char *, int);
+private int apprentice_compile(struct magic_set *, struct magic **, uint32_t *,
+    const char *, int);
+
+private int maxmagic = 0;
 
 #ifdef COMPILE_ONLY
 const char *magicfile;
@@ -112,7 +116,7 @@ main(int argc, char *argv[])
        }
        magicfile = argv[1];
 
-       exit(apprentice(magicfile, COMPILE));
+       exit(apprentice(magicfile, COMPILE, MAGIC_CHECK));
 }
 #endif /* COMPILE_ONLY */
 
@@ -120,140 +124,144 @@ main(int argc, char *argv[])
 /*
  * Handle one file.
  */
-static int
-apprentice_1(const char *fn, int action)
+private int
+apprentice_1(struct magic_set *ms, const char *fn, int action,
+    struct mlist *mlist)
 {
        struct magic *magic = NULL;
        uint32_t nmagic = 0;
        struct mlist *ml;
        int rv = -1;
+       int mapped;
 
        if (action == COMPILE) {
-               rv = apprentice_file(&magic, &nmagic, fn, action);
-               if (rv == 0)
-                       return apprentice_compile(&magic, &nmagic, fn, action);
-               else
-                       return rv;
+               rv = apprentice_file(ms, &magic, &nmagic, fn, action);
+               if (rv == 0) {
+                       rv = apprentice_compile(ms, &magic, &nmagic, fn,
+                           action);
+                       free(magic);
+               }
+               return rv;
        }
 #ifndef COMPILE_ONLY
-       if ((rv = apprentice_map(&magic, &nmagic, fn, action)) != 0)
-               (void)fprintf(stderr, "%s: Using regular magic file `%s'\n",
-                   progname, fn);
-               
-       if (rv != 0)
-               rv = apprentice_file(&magic, &nmagic, fn, action);
-
-       if (rv != 0)
+       if ((rv = apprentice_map(ms, &magic, &nmagic, fn, action)) == -1) {
+               if (ms->flags & MAGIC_CHECK)
+                       file_magwarn("Using regular magic file `%s'", fn);
+               rv = apprentice_file(ms, &magic, &nmagic, fn, action);
+               mapped = 0;
+       }
+
+       if (rv == -1)
                return rv;
+       mapped = rv;
             
        if ((ml = malloc(sizeof(*ml))) == NULL) {
-               (void) fprintf(stderr, "%s: Out of memory (%s).\n", progname,
-                   strerror(errno));
-               if (action == CHECK)
-                       return -1;
+               file_oomem(ms);
+               return -1;
        }
 
        if (magic == NULL || nmagic == 0)
-               return rv;
+               return -1;
 
        ml->magic = magic;
        ml->nmagic = nmagic;
+       ml->mapped = mapped;
 
-       mlist.prev->next = ml;
-       ml->prev = mlist.prev;
-       ml->next = &mlist;
-       mlist.prev = ml;
+       mlist->prev->next = ml;
+       ml->prev = mlist->prev;
+       ml->next = mlist;
+       mlist->prev = ml;
 
-       return rv;
+       return 0;
 #endif /* COMPILE_ONLY */
 }
 
 
 /* const char *fn: list of magic files */
-int
-apprentice(const char *fn, int action)
+protected struct mlist *
+file_apprentice(struct magic_set *ms, const char *fn, int action)
 {
        char *p, *mfn;
        int file_err, errs = -1;
+       struct mlist *mlist;
 
-       mlist.next = mlist.prev = &mlist;
-       mfn = malloc(strlen(fn)+1);
-       if (mfn == NULL) {
-               (void) fprintf(stderr, "%s: Out of memory (%s).\n", progname,
-                   strerror(errno));
-               if (action == CHECK)
-                       return -1;
-               else
-                       exit(1);
+       if ((fn = mfn = strdup(fn)) == NULL) {
+               file_oomem(ms);
+               return NULL;
        }
-       fn = strcpy(mfn, fn);
-  
+       if ((mlist = malloc(sizeof(*mlist))) == NULL) {
+               free(mfn);
+               file_oomem(ms);
+               return NULL;
+       }
+       mlist->next = mlist->prev = mlist;
+
        while (fn) {
                p = strchr(fn, PATHSEP);
                if (p)
                        *p++ = '\0';
-               file_err = apprentice_1(fn, action);
+               file_err = apprentice_1(ms, fn, action, mlist);
                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 (action == CHECK && errs)
-               exit(1);
-
+       if (errs == -1) {
+               free(mfn);
+               free(mlist);
+               mlist = NULL;
+               file_error(ms, "Couldn't find any magic files!");
+               return NULL;
+       }
        free(mfn);
-       return errs;
+       return mlist;
 }
 
 /*
  * parse from a file
  * const char *fn: name of magic file
  */
-static int
-apprentice_file(struct magic **magicp, uint32_t *nmagicp, const char *fn,
-               int action)
+private int
+apprentice_file(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
+    const char *fn, int action)
 {
-       static const char hdr[] =
+       private const char hdr[] =
                "cont\toffset\ttype\topcode\tmask\tvalue\tdesc";
        FILE *f;
        char line[BUFSIZ+1];
+       int lineno;
        int errs = 0;
 
        f = fopen(fn, "r");
        if (f == NULL) {
                if (errno != ENOENT)
-                       (void) fprintf(stderr,
-                           "%s: can't read magic file %s (%s)\n", 
-                           progname, fn, strerror(errno));
+                       file_error(ms, "Can't read magic file %s (%s)",
+                           fn, strerror(errno));
                return -1;
        }
 
         maxmagic = MAXMAGIS;
        *magicp = (struct magic *) calloc(maxmagic, sizeof(struct magic));
        if (*magicp == NULL) {
-               (void) fprintf(stderr, "%s: Out of memory (%s).\n", progname,
-                   strerror(errno));
-               if (action == CHECK)
-                       return -1;
+               (void)fclose(f);
+               file_oomem(ms);
+               return -1;
        }
 
        /* parse it */
        if (action == CHECK)    /* print silly verbose header for USG compat. */
                (void) printf("%s\n", hdr);
 
-       for (lineno = 1;fgets(line, BUFSIZ, f) != NULL; lineno++) {
+       for (lineno = 1; fgets(line, BUFSIZ, f) != NULL; lineno++) {
                if (line[0]=='#')       /* comment, do not parse */
                        continue;
                if (strlen(line) <= (unsigned)1) /* null line, garbage, etc */
                        continue;
                line[strlen(line)-1] = '\0'; /* delete newline */
-               if (parse(magicp, nmagicp, line, action) != 0)
+               if (parse(ms, magicp, nmagicp, line, action) != 0)
                        errs = 1;
        }
 
-       (void) fclose(f);
+       (void)fclose(f);
        if (errs) {
                free(*magicp);
                *magicp = NULL;
@@ -265,8 +273,8 @@ apprentice_file(struct magic **magicp, uint32_t *nmagicp, const char *fn,
 /*
  * extend the sign bit if the comparison is to be signed
  */
-uint32_t
-signextend(struct magic *m, uint32_t v)
+protected uint32_t
+file_signextend(struct magic_set *ms, struct magic *m, uint32_t v)
 {
        if (!(m->flag & UNSIGNED))
                switch(m->type) {
@@ -300,8 +308,9 @@ signextend(struct magic *m, uint32_t v)
                case REGEX:
                        break;
                default:
-                       magwarn("can't happen: m->type=%d\n",
-                               m->type);
+                       if (ms->flags & MAGIC_CHECK)
+                           file_magwarn("can't happen: m->type=%d\n",
+                                   m->type);
                        return -1;
                }
        return v;
@@ -310,8 +319,9 @@ signextend(struct magic *m, uint32_t v)
 /*
  * parse one line from magic file, put into magic[index++] if valid
  */
-static int
-parse(struct magic **magicp, uint32_t *nmagicp, char *l, int action)
+private int
+parse(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp, char *l,
+    int action)
 {
        int i = 0;
        struct magic *m;
@@ -322,14 +332,10 @@ parse(struct magic **magicp, uint32_t *nmagicp, char *l, int action)
                maxmagic += ALLOC_INCR;
                if ((m = (struct magic *) realloc(*magicp,
                    sizeof(struct magic) * maxmagic)) == NULL) {
-                       (void) fprintf(stderr, "%s: Out of memory (%s).\n",
-                           progname, strerror(errno));
+                       file_oomem(ms);
                        if (*magicp)
                                free(*magicp);
-                       if (action == CHECK)
-                               return -1;
-                       else
-                               exit(1);
+                       return -1;
                }
                *magicp = m;
                memset(&(*magicp)[*nmagicp], 0, sizeof(struct magic)
@@ -356,7 +362,8 @@ parse(struct magic **magicp, uint32_t *nmagicp, char *l, int action)
        /* get offset, then skip over it */
        m->offset = (int) strtoul(l,&t,0);
         if (l == t)
-               magwarn("offset %s invalid", l);
+               if (ms->flags & MAGIC_CHECK)
+                       file_magwarn("offset %s invalid", l);
         l = t;
 
        if (m->flag & INDIR) {
@@ -389,7 +396,10 @@ parse(struct magic **magicp, uint32_t *nmagicp, char *l, int action)
                                m->in_type = BYTE;
                                break;
                        default:
-                               magwarn("indirect offset type %c invalid", *l);
+                               if (ms->flags & MAGIC_CHECK)
+                                       file_magwarn(
+                                           "indirect offset type %c invalid",
+                                           *l);
                                break;
                        }
                        l++;
@@ -437,7 +447,8 @@ parse(struct magic **magicp, uint32_t *nmagicp, char *l, int action)
                else
                        t = l;
                if (*t++ != ')') 
-                       magwarn("missing ')' in indirect offset");
+                       if (ms->flags & MAGIC_CHECK)
+                               file_magwarn("missing ')' in indirect offset");
                l = t;
        }
 
@@ -521,7 +532,8 @@ parse(struct magic **magicp, uint32_t *nmagicp, char *l, int action)
                m->type = REGEX;
                l += sizeof("regex");
        } else {
-               magwarn("type %s invalid", l);
+               if (ms->flags & MAGIC_CHECK)
+                       file_magwarn("type %s invalid", l);
                return -1;
        }
        /* New-style anding: "0 byte&0x80 =0x80 dynamically linked" */
@@ -535,50 +547,50 @@ parse(struct magic **magicp, uint32_t *nmagicp, char *l, int action)
        case '&':
                m->mask_op |= OPAND;
                ++l;
-               m->mask = signextend(m, strtoul(l, &l, 0));
+               m->mask = file_signextend(ms, m, strtoul(l, &l, 0));
                eatsize(&l);
                break;
        case '|':
                m->mask_op |= OPOR;
                ++l;
-               m->mask = signextend(m, strtoul(l, &l, 0));
+               m->mask = file_signextend(ms, m, strtoul(l, &l, 0));
                eatsize(&l);
                break;
        case '^':
                m->mask_op |= OPXOR;
                ++l;
-               m->mask = signextend(m, strtoul(l, &l, 0));
+               m->mask = file_signextend(ms, m, strtoul(l, &l, 0));
                eatsize(&l);
                break;
        case '+':
                m->mask_op |= OPADD;
                ++l;
-               m->mask = signextend(m, strtoul(l, &l, 0));
+               m->mask = file_signextend(ms, m, strtoul(l, &l, 0));
                eatsize(&l);
                break;
        case '-':
                m->mask_op |= OPMINUS;
                ++l;
-               m->mask = signextend(m, strtoul(l, &l, 0));
+               m->mask = file_signextend(ms, m, strtoul(l, &l, 0));
                eatsize(&l);
                break;
        case '*':
                m->mask_op |= OPMULTIPLY;
                ++l;
-               m->mask = signextend(m, strtoul(l, &l, 0));
+               m->mask = file_signextend(ms, m, strtoul(l, &l, 0));
                eatsize(&l);
                break;
        case '%':
                m->mask_op |= OPMODULO;
                ++l;
-               m->mask = signextend(m, strtoul(l, &l, 0));
+               m->mask = file_signextend(ms, m, strtoul(l, &l, 0));
                eatsize(&l);
                break;
        case '/':
                if (STRING != m->type && PSTRING != m->type) {
                        m->mask_op |= OPDIVIDE;
                        ++l;
-                       m->mask = signextend(m, strtoul(l, &l, 0));
+                       m->mask = file_signextend(ms, m, strtoul(l, &l, 0));
                        eatsize(&l);
                } else {
                        m->mask = 0L;
@@ -595,8 +607,10 @@ parse(struct magic **magicp, uint32_t *nmagicp, char *l, int action)
                                            STRING_COMPACT_OPTIONAL_BLANK;
                                        break;
                                default:
-                                       magwarn("string extension %c invalid",
-                                           *l);
+                                       if (ms->flags & MAGIC_CHECK)
+                                               file_magwarn(
+                                               "string extension %c invalid",
+                                               *l);
                                        return -1;
                                }
                        }
@@ -640,7 +654,7 @@ parse(struct magic **magicp, uint32_t *nmagicp, char *l, int action)
        }
        EATAB;
   
-       if (getvalue(m, &l))
+       if (getvalue(ms, m, &l))
                return -1;
        /*
         * TODO finish this macro and start using it!
@@ -667,7 +681,7 @@ GetDesc:
 
 #ifndef COMPILE_ONLY
        if (action == CHECK) {
-               mdump(m);
+               file_mdump(m);
        }
 #endif
        ++(*nmagicp);           /* make room for next */
@@ -679,17 +693,19 @@ GetDesc:
  * pointer, according to the magic type.  Update the string pointer to point 
  * just after the number read.  Return 0 for success, non-zero for failure.
  */
-static int
-getvalue(struct magic *m, char **p)
+private int
+getvalue(struct magic_set *ms, struct magic *m, char **p)
 {
        int slen;
 
        if (m->type == STRING || m->type == PSTRING || m->type == REGEX) {
-               *p = getstr(*p, m->value.s, sizeof(m->value.s), &slen);
+               *p = getstr(ms, *p, m->value.s, sizeof(m->value.s), &slen);
+               if (*p == NULL)
+                       return -1;
                m->vallen = slen;
        } else
                if (m->reln != 'x') {
-                       m->value.l = signextend(m, strtoul(*p, p, 0));
+                       m->value.l = file_signextend(ms, m, strtoul(*p, p, 0));
                        eatsize(p);
                }
        return 0;
@@ -701,8 +717,8 @@ getvalue(struct magic *m, char **p)
  * Copy the converted version to "p", returning its length in *slen.
  * Return updated scan pointer as function result.
  */
-static char *
-getstr(char *s, char *p, int plen, int *slen)
+private char *
+getstr(struct magic_set *ms, char *s, char *p, int plen, int *slen)
 {
        char    *origs = s, *origp = p;
        char    *pmax = p + plen - 1;
@@ -713,8 +729,8 @@ getstr(char *s, char *p, int plen, int *slen)
                if (isspace((unsigned char) c))
                        break;
                if (p >= pmax) {
-                       fprintf(stderr, "String too long: %s\n", origs);
-                       break;
+                       file_error(ms, "String too long: `%s'", origs);
+                       return NULL;
                }
                if(c == '\\') {
                        switch(c = *s++) {
@@ -801,7 +817,7 @@ out:
 
 
 /* Single hex char to int; -1 if not a hex char. */
-static int
+private int
 hextoint(int c)
 {
        if (!isascii((unsigned char) c))
@@ -819,8 +835,8 @@ hextoint(int c)
 /*
  * Print a string containing C character escapes.
  */
-void
-showstr(FILE *fp, const char *s, int len)
+protected void
+file_showstr(FILE *fp, const char *s, int len)
 {
        char    c;
 
@@ -875,7 +891,7 @@ showstr(FILE *fp, const char *s, int len)
 /*
  * eatsize(): Eat the size spec from a number [eg. 10UL]
  */
-static void
+private void
 eatsize(char **p)
 {
        char *l = *p;
@@ -901,16 +917,17 @@ eatsize(char **p)
 /*
  * handle a compiled file.
  */
-static int
-apprentice_map(struct magic **magicp, uint32_t *nmagicp, const char *fn,
-    int action)
+private int
+apprentice_map(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
+    const char *fn, int action)
 {
        int fd;
        struct stat st;
        uint32_t *ptr;
        uint32_t version;
        int needsbyteswap;
-       char *dbname = mkdbname(fn);
+       char buf[MAXPATHLEN];
+       char *dbname = mkdbname(ms, fn, buf, sizeof(buf));
        void *mm;
 
        if (dbname == NULL)
@@ -920,27 +937,24 @@ apprentice_map(struct magic **magicp, uint32_t *nmagicp, const char *fn,
                return -1;
 
        if (fstat(fd, &st) == -1) {
-               (void)fprintf(stderr, "%s: Cannot stat `%s' (%s)\n",
-                   progname, dbname, strerror(errno));
+               file_error(ms, "Cannot stat `%s' (%s)", dbname,
+                   strerror(errno));
                goto error;
        }
 
 #ifdef QUICK
        if ((mm = 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));
+               file_error(ms, "Cannot map `%s' (%s)", dbname, strerror(errno));
                goto error;
        }
 #else
        if ((mm = malloc((size_t)st.st_size)) == NULL) {
-               (void) fprintf(stderr, "%s: Out of memory (%s).\n", progname,
-                    strerror(errno));
+               file_oomem(ms);
                goto error;
        }
        if (read(fd, mm, (size_t)st.st_size) != (size_t)st.st_size) {
-               (void) fprintf(stderr, "%s: Read failed (%s).\n", progname,
-                   strerror(errno));
+               file_error(ms, "Read failed (%s)", strerror(errno));
                goto error;
        }
 #endif
@@ -950,8 +964,7 @@ apprentice_map(struct magic **magicp, uint32_t *nmagicp, const char *fn,
        ptr = (uint32_t *) *magicp;
        if (*ptr != MAGICNO) {
                if (swap4(*ptr) != MAGICNO) {
-                       (void)fprintf(stderr, "%s: Bad magic in `%s'\n",
-                           progname, dbname);
+                       file_error(ms, "Bad magic in `%s'", dbname);
                        goto error;
                }
                needsbyteswap = 1;
@@ -962,9 +975,8 @@ apprentice_map(struct magic **magicp, uint32_t *nmagicp, const char *fn,
        else
                version = ptr[1];
        if (version != VERSIONNO) {
-               (void)fprintf(stderr, 
-                   "%s: version mismatch (%d != %d) in `%s'\n",
-                   progname, version, VERSIONNO, dbname);
+               file_error(ms, "version mismatch (%d != %d) in `%s'",
+                   version, VERSIONNO, dbname);
                goto error;
        }
        *nmagicp = (st.st_size / sizeof(struct magic)) - 1;
@@ -989,44 +1001,44 @@ error:
        return -1;
 }
 
+private const uint32_t ar[] = {
+    MAGICNO, VERSIONNO
+};
 /*
  * handle an mmaped file.
  */
-static int
-apprentice_compile(struct magic **magicp, uint32_t *nmagicp, const char *fn,
-    int action)
+private int
+apprentice_compile(struct magic_set *ms, struct magic **magicp,
+    uint32_t *nmagicp, const char *fn, int action)
 {
        int fd;
-       char *dbname = mkdbname(fn);
-       static const uint32_t ar[] = {
-           MAGICNO, VERSIONNO
-       };
+       char buf[MAXPATHLEN];
+       char *dbname = mkdbname(ms, fn, buf, sizeof(buf));
 
        if (dbname == NULL) 
                return -1;
 
        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));
+               file_error(ms, "Cannot open `%s' (%s)", 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));
+               file_error(ms, "Error writing `%s' (%s)", 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));
+               file_error(ms, "Error seeking `%s' (%s)", 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));
+               file_error(ms, "Error writing `%s' (%s)", dbname,
+                   strerror(errno));
                return -1;
        }
 
@@ -1034,36 +1046,26 @@ apprentice_compile(struct magic **magicp, uint32_t *nmagicp, const char *fn,
        return 0;
 }
 
+private const char ext[] = ".mgc";
 /*
  * make a dbname
  */
-char *
-mkdbname(const char *fn)
+private char *
+mkdbname(struct magic_set *ms, const char *fn, char *buf, size_t bufsiz)
 {
-       static const char ext[] = ".mgc";
-       static char *buf = NULL;
-       const char *tail = strrchr(fn, '/');
-       size_t len;
-       tail = tail == NULL ? fn : ++tail;
-       len = strlen(tail) + sizeof(ext) + 1;
-       if (buf == NULL)
-               buf = malloc(len);
+       const char *p;
+       if ((p = strrchr(fn, '/')) != NULL)
+               p++;
        else
-               buf = realloc(buf, len);
-       if (buf == NULL) {
-               (void) fprintf(stderr, "%s: Out of memory (%s).\n", progname,
-                   strerror(errno));
-               return NULL;
-       }
-       (void)strcpy(buf, tail);
-       (void)strcat(buf, ext);
+               p = fn;
+       snprintf(buf, bufsiz, "%s%s", p, ext);
        return buf;
 }
 
 /*
  * Byteswap an mmap'ed file if needed
  */
-static void
+private void
 byteswap(struct magic *magic, uint32_t nmagic)
 {
        uint32_t i;
@@ -1074,7 +1076,7 @@ byteswap(struct magic *magic, uint32_t nmagic)
 /*
  * swap a short
  */
-static uint16_t
+private uint16_t
 swap2(uint16_t sv)
 {
        uint16_t rv;
@@ -1088,7 +1090,7 @@ swap2(uint16_t sv)
 /*
  * swap an int
  */
-static uint32_t
+private uint32_t
 swap4(uint32_t sv)
 {
        uint32_t rv;
@@ -1104,8 +1106,8 @@ swap4(uint32_t sv)
 /*
  * byteswap a single magic entry
  */
-static
-void bs1(struct magic *m)
+private void
+bs1(struct magic *m)
 {
        m->cont_level = swap2(m->cont_level);
        m->offset = swap4(m->offset);
index 8217f19422f68135f1d6bdf1423b2cb8030b9a9c..e8b8e121307e99c52d49ca5974a41493c993fbe4 100644 (file)
@@ -34,7 +34,9 @@
  * 4. This notice may not be removed or altered.
  */
 
+#include "magic.h"
 #include "file.h"
+#include <stdio.h>
 #include <string.h>
 #include <memory.h>
 #include <ctype.h>
@@ -45,7 +47,7 @@
 #include "names.h"
 
 #ifndef        lint
-FILE_RCSID("@(#)$Id: ascmagic.c,v 1.33 2003/02/08 18:33:53 christos Exp $")
+FILE_RCSID("@(#)$Id: ascmagic.c,v 1.34 2003/03/23 04:06:04 christos Exp $")
 #endif /* lint */
 
 typedef unsigned long unichar;
@@ -54,29 +56,29 @@ typedef unsigned long unichar;
 #define ISSPC(x) ((x) == ' ' || (x) == '\t' || (x) == '\r' || (x) == '\n' \
                  || (x) == 0x85 || (x) == '\f')
 
-static int looks_ascii(const unsigned char *, int, unichar *, int *);
-static int looks_utf8(const unsigned char *, int, unichar *, int *);
-static int looks_unicode(const unsigned char *, int, unichar *, int *);
-static int looks_latin1(const unsigned char *, int, unichar *, int *);
-static int looks_extended(const unsigned char *, int, unichar *, int *);
-static void from_ebcdic(const unsigned char *, int, unsigned char *);
-static int ascmatch(const unsigned char *, const unichar *, int);
-
-/* int nbytes: size actually read */
-int
-ascmagic(unsigned char *buf, int nbytes)
+private int looks_ascii(const unsigned char *, size_t, unichar *, size_t *);
+private int looks_utf8(const unsigned char *, size_t, unichar *, size_t *);
+private int looks_unicode(const unsigned char *, size_t, unichar *, size_t *);
+private int looks_latin1(const unsigned char *, size_t, unichar *, size_t *);
+private int looks_extended(const unsigned char *, size_t, unichar *, size_t *);
+private void from_ebcdic(const unsigned char *, size_t, unsigned char *);
+private int ascmatch(const unsigned char *, const unichar *, size_t);
+
+
+protected int
+file_ascmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes)
 {
-       int i;
+       size_t i;
        unsigned char nbuf[HOWMANY+1];  /* one extra for terminating '\0' */
        unichar ubuf[HOWMANY+1];        /* one extra for terminating '\0' */
-       int ulen;
+       size_t ulen;
        struct names *p;
 
-       char *code = NULL;
-       char *code_mime = NULL;
-       char *type = NULL;
-       char *subtype = NULL;
-       char *subtype_mime = NULL;
+       const char *code = NULL;
+       const char *code_mime = NULL;
+       const char *type = NULL;
+       const char *subtype = NULL;
+       const char *subtype_mime = NULL;
 
        int has_escapes = 0;
        int has_backspace = 0;
@@ -93,13 +95,16 @@ ascmagic(unsigned char *buf, int nbytes)
         * Do the tar test first, because if the first file in the tar
         * archive starts with a dot, we can confuse it with an nroff file.
         */
-       switch (is_tar(buf, nbytes)) {
+       switch (file_is_tar(buf, nbytes)) {
        case 1:
-               ckfputs(iflag ? "application/x-tar" : "tar archive", stdout);
+               if (file_printf(ms, (ms->flags & MAGIC_MIME) ?
+                   "application/x-tar" : "tar archive") == -1)
+                       return -1;
                return 1;
        case 2:
-               ckfputs(iflag ? "application/x-tar, POSIX"
-                               : "POSIX tar archive", stdout);
+               if (file_printf(ms, (ms->flags & MAGIC_MIME) ?
+                   "application/x-tar, POSIX" : "POSIX tar archive") == -1)
+                       return -1;
                return 1;
        }
 
@@ -190,7 +195,7 @@ ascmagic(unsigned char *buf, int nbytes)
 
        i = 0;
        while (i < ulen) {
-               int end;
+               size_t end;
 
                /*
                 * skip past any leading space
@@ -211,7 +216,7 @@ ascmagic(unsigned char *buf, int nbytes)
                 * compare the word thus isolated against the token list
                 */
                for (p = names; p < names + NNAMES; p++) {
-                       if (ascmatch((unsigned char *)p->name, ubuf + i,
+                       if (ascmatch((const unsigned char *)p->name, ubuf + i,
                            end - i)) {
                                subtype = types[p->type].human;
                                subtype_mime = types[p->type].mime;
@@ -254,29 +259,40 @@ subtype_identified:
                }
        }
 
-       if (iflag) {
-               if (subtype_mime)
-                       ckfputs(subtype_mime, stdout);
-               else
-                       ckfputs("text/plain", stdout);
+       if ((ms->flags & MAGIC_MIME)) {
+               if (subtype_mime) {
+                       if (file_printf(ms, subtype_mime) == -1)
+                               return -1;
+               } else {
+                       if (file_printf(ms, "text/plain") == -1)
+                               return -1;
+               }
 
                if (code_mime) {
-                       ckfputs("; charset=", stdout);
-                       ckfputs(code_mime, stdout);
+                       if (file_printf(ms, "; charset=") == -1)
+                               return -1;
+                       if (file_printf(ms, code_mime) == -1)
+                               return -1;
                }
        } else {
-               ckfputs(code, stdout);
+               if (file_printf(ms, code) == -1)
+                       return -1;
 
                if (subtype) {
-                       ckfputs(" ", stdout);
-                       ckfputs(subtype, stdout);
+                       if (file_printf(ms, " ") == -1)
+                               return -1;
+                       if (file_printf(ms, subtype) == -1)
+                               return -1;
                }
 
-               ckfputs(" ", stdout);
-               ckfputs(type, stdout);
+               if (file_printf(ms, " ") == -1)
+                       return -1;
+               if (file_printf(ms, type) == -1)
+                       return -1;
 
                if (has_long_lines)
-                       ckfputs(", with very long lines", stdout);
+                       if (file_printf(ms, ", with very long lines") == -1)
+                               return -1;
 
                /*
                 * Only report line terminators if we find one other than LF,
@@ -284,44 +300,56 @@ subtype_identified:
                 */
                if ((n_crlf == 0 && n_cr == 0 && n_nel == 0 && n_lf == 0) ||
                    (n_crlf != 0 || n_cr != 0 || n_nel != 0)) {
-                       ckfputs(", with", stdout);
+                       if (file_printf(ms, ", with") == -1)
+                               return -1;
 
-                       if (n_crlf == 0 && n_cr == 0 && n_nel == 0 && n_lf == 0)
-                               ckfputs(" no", stdout);
-                       else {
+                       if (n_crlf == 0 && n_cr == 0 && n_nel == 0 && n_lf == 0)                        {
+                               if (file_printf(ms, " no") == -1)
+                                       return -1;
+                       } else {
                                if (n_crlf) {
-                                       ckfputs(" CRLF", stdout);
+                                       if (file_printf(ms, " CRLF") == -1)
+                                               return -1;
                                        if (n_cr || n_lf || n_nel)
-                                               ckfputs(",", stdout);
+                                               if (file_printf(ms, ",") == -1)
+                                                       return -1;
                                }
                                if (n_cr) {
-                                       ckfputs(" CR", stdout);
+                                       if (file_printf(ms, " CR") == -1)
+                                               return -1;
                                        if (n_lf || n_nel)
-                                               ckfputs(",", stdout);
+                                               if (file_printf(ms, ",") == -1)
+                                                       return -1;
                                }
                                if (n_lf) {
-                                       ckfputs(" LF", stdout);
+                                       if (file_printf(ms, " LF") == -1)
+                                               return -1;
                                        if (n_nel)
-                                               ckfputs(",", stdout);
+                                               if (file_printf(ms, ",") == -1)
+                                                       return -1;
                                }
                                if (n_nel)
-                                       ckfputs(" NEL", stdout);
+                                       if (file_printf(ms, " NEL") == -1)
+                                               return -1;
                        }
 
-                       ckfputs(" line terminators", stdout);
+                       if (file_printf(ms, " line terminators") == -1)
+                               return -1;
                }
 
                if (has_escapes)
-                       ckfputs(", with escape sequences", stdout);
+                       if (file_printf(ms, ", with escape sequences") == -1)
+                               return -1;
                if (has_backspace)
-                       ckfputs(", with overstriking", stdout);
+                       if (file_printf(ms, ", with overstriking") == -1)
+                               return -1;
        }
 
        return 1;
 }
 
-static int
-ascmatch(const unsigned char *s, const unichar *us, int ulen)
+private int
+ascmatch(const unsigned char *s, const unichar *us, size_t ulen)
 {
        size_t i;
 
@@ -393,7 +421,7 @@ ascmatch(const unsigned char *s, const unichar *us, int ulen)
 #define I 2   /* character appears in ISO-8859 text */
 #define X 3   /* character appears in non-ISO extended ASCII (Mac, IBM PC) */
 
-static char text_chars[256] = {
+private char text_chars[256] = {
        /*                  BEL BS HT LF    FF CR    */
        F, F, F, F, F, F, F, T, T, T, T, F, T, T, F, F,  /* 0x0X */
         /*                              ESC          */
@@ -415,8 +443,9 @@ static char text_chars[256] = {
        I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I   /* 0xfX */
 };
 
-static int
-looks_ascii(const unsigned char *buf, int nbytes, unichar *ubuf, int *ulen)
+private int
+looks_ascii(const unsigned char *buf, size_t nbytes, unichar *ubuf,
+    size_t *ulen)
 {
        int i;
 
@@ -434,8 +463,8 @@ looks_ascii(const unsigned char *buf, int nbytes, unichar *ubuf, int *ulen)
        return 1;
 }
 
-static int
-looks_latin1(const unsigned char *buf, int nbytes, unichar *ubuf, int *ulen)
+private int
+looks_latin1(const unsigned char *buf, size_t nbytes, unichar *ubuf, size_t *ulen)
 {
        int i;
 
@@ -453,8 +482,9 @@ looks_latin1(const unsigned char *buf, int nbytes, unichar *ubuf, int *ulen)
        return 1;
 }
 
-static int
-looks_extended(const unsigned char *buf, int nbytes, unichar *ubuf, int *ulen)
+private int
+looks_extended(const unsigned char *buf, size_t nbytes, unichar *ubuf,
+    size_t *ulen)
 {
        int i;
 
@@ -472,8 +502,8 @@ looks_extended(const unsigned char *buf, int nbytes, unichar *ubuf, int *ulen)
        return 1;
 }
 
-int
-looks_utf8(const unsigned char *buf, int nbytes, unichar *ubuf, int *ulen)
+private int
+looks_utf8(const unsigned char *buf, size_t nbytes, unichar *ubuf, size_t *ulen)
 {
        int i, n;
        unichar c;
@@ -534,8 +564,9 @@ done:
        return gotone;   /* don't claim it's UTF-8 if it's all 7-bit */
 }
 
-static int
-looks_unicode(const unsigned char *buf, int nbytes, unichar *ubuf, int *ulen)
+private int
+looks_unicode(const unsigned char *buf, size_t nbytes, unichar *ubuf,
+    size_t *ulen)
 {
        int bigend;
        int i;
@@ -596,7 +627,7 @@ looks_unicode(const unsigned char *buf, int nbytes, unichar *ubuf, int *ulen)
  * between old-style and internationalized examples of text.
  */
 
-unsigned char ebcdic_to_ascii[] = {
+private unsigned char ebcdic_to_ascii[] = {
   0,   1,   2,   3, 156,   9, 134, 127, 151, 141, 142,  11,  12,  13,  14,  15,
  16,  17,  18,  19, 157, 133,   8, 135,  24,  25, 146, 143,  28,  29,  30,  31,
 128, 129, 130, 131, 132,  10,  23,  27, 136, 137, 138, 139, 140,   5,   6,   7,
@@ -615,6 +646,7 @@ unsigned char ebcdic_to_ascii[] = {
 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 250, 251, 252, 253, 254, 255
 };
 
+#ifdef notdef
 /*
  * The following EBCDIC-to-ASCII table may relate more closely to reality,
  * or at least to modern reality.  It comes from
@@ -629,7 +661,7 @@ unsigned char ebcdic_to_ascii[] = {
  * cases for the NEL character can be taken out of the code.
  */
 
-unsigned char ebcdic_1047_to_8859[] = {
+private unsigned char ebcdic_1047_to_8859[] = {
 0x00,0x01,0x02,0x03,0x9C,0x09,0x86,0x7F,0x97,0x8D,0x8E,0x0B,0x0C,0x0D,0x0E,0x0F,
 0x10,0x11,0x12,0x13,0x9D,0x0A,0x08,0x87,0x18,0x19,0x92,0x8F,0x1C,0x1D,0x1E,0x1F,
 0x80,0x81,0x82,0x83,0x84,0x85,0x17,0x1B,0x88,0x89,0x8A,0x8B,0x8C,0x05,0x06,0x07,
@@ -647,12 +679,13 @@ unsigned char ebcdic_1047_to_8859[] = {
 0x5C,0xF7,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0xB2,0xD4,0xD6,0xD2,0xD3,0xD5,
 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0xB3,0xDB,0xDC,0xD9,0xDA,0x9F
 };
+#endif
 
 /*
  * Copy buf[0 ... nbytes-1] into out[], translating EBCDIC to ASCII.
  */
-static void
-from_ebcdic(const unsigned char *buf, int nbytes, unsigned char *out)
+private void
+from_ebcdic(const unsigned char *buf, size_t nbytes, unsigned char *out)
 {
        int i;
 
index 4e1219c9912f884b2263901333508991f8755d7d..185d422130cb0cd8efb908b4b10366e95cac5aaf 100644 (file)
@@ -5,12 +5,16 @@
  *     uncompress(method, old, n, newch) - uncompress old into new, 
  *                                         using method, return sizeof new
  */
+#include "magic.h"
 #include "file.h"
+#include <stdio.h>
 #include <stdlib.h>
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
 #include <string.h>
+#include <errno.h>
+#include <sys/types.h>
 #ifdef HAVE_SYS_WAIT_H
 #include <sys/wait.h>
 #endif
 #endif
 
 #ifndef lint
-FILE_RCSID("@(#)$Id: compress.c,v 1.25 2002/07/03 18:26:37 christos Exp $")
+FILE_RCSID("@(#)$Id: compress.c,v 1.26 2003/03/23 04:06:05 christos Exp $")
 #endif
 
 
-static struct {
+private struct {
        const char *magic;
        int   maglen;
        const char *const argv[3];
@@ -41,47 +45,52 @@ static struct {
        { "BZh",      3, { "bzip2", "-cd", NULL }, 1 },         /* bzip2-ed */
 };
 
-static int ncompr = sizeof(compr) / sizeof(compr[0]);
+private int ncompr = sizeof(compr) / sizeof(compr[0]);
 
 
-static int swrite(int, const void *, size_t);
-static int sread(int, void *, size_t);
-static int uncompressbuf(int, const unsigned char *, unsigned char **, int);
+private int swrite(int, const void *, size_t);
+private int sread(int, void *, size_t);
+private size_t uncompressbuf(struct magic_set *ms, int, const unsigned char *,
+    unsigned char **, size_t);
 #ifdef HAVE_LIBZ
-static int uncompressgzipped(const unsigned char *, unsigned char **, int);
+private size_t uncompressgzipped(struct magic_set *ms, const unsigned char *,
+    unsigned char **, size_t);
 #endif
 
-int
-zmagic(const char *fname, unsigned char *buf, int nbytes)
+protected int
+file_zmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes)
 {
        unsigned char *newbuf;
-       int newsize;
-       int i;
+       size_t nsz;
+       size_t i;
+
+       if ((ms->flags & MAGIC_COMPRESS) == 0)
+               return 0;
 
        for (i = 0; i < ncompr; i++) {
                if (nbytes < compr[i].maglen)
                        continue;
                if (memcmp(buf, compr[i].magic, compr[i].maglen) == 0 &&
-                   (newsize = uncompressbuf(i, buf, &newbuf, nbytes)) != 0) {
-                       tryit(fname, newbuf, newsize, 1);
+                   (nsz = uncompressbuf(ms, i, buf, &newbuf, nbytes)) != 0) {
                        free(newbuf);
-                       printf(" (");
-                       tryit(fname, buf, nbytes, 0);
-                       printf(")");
+                       if (file_printf(ms, " (") == -1)
+                               return -1;
+                       ms->flags &= ~MAGIC_COMPRESS;
+                       (void)magic_buf(ms, buf, nbytes);
+                       ms->flags |= MAGIC_COMPRESS;
+                       if (file_printf(ms, ")") == -1)
+                               return -1;
                        return 1;
                }
        }
 
-       if (i == ncompr)
-               return 0;
-
-       return 1;
+       return 0;
 }
 
 /*
  * `safe' write for sockets and pipes.
  */
-static int
+private int
 swrite(int fd, const void *buf, size_t n)
 {
        int rv;
@@ -106,7 +115,7 @@ swrite(int fd, const void *buf, size_t n)
 /*
  * `safe' read for sockets and pipes.
  */
-static int
+private int
 sread(int fd, void *buf, size_t n)
 {
        int rv;
@@ -129,8 +138,9 @@ sread(int fd, void *buf, size_t n)
        return rn;
 }
 
-int
-pipe2file(int fd, void *startbuf, size_t nbytes)
+protected int
+file_pipe2file(struct magic_set *ms, int fd, const void *startbuf,
+    size_t nbytes)
 {
        char buf[4096];
        int r, tfd;
@@ -151,9 +161,9 @@ pipe2file(int fd, void *startbuf, size_t nbytes)
        errno = r;
 #endif
        if (tfd == -1) {
-               error("Can't create temporary file for pipe copy (%s)\n",
+               file_error(ms, "Can't create temporary file for pipe copy (%s)",
                    strerror(errno));
-               /*NOTREACHED*/
+               return -1;
        }
 
        if (swrite(tfd, startbuf, nbytes) != nbytes)
@@ -166,15 +176,15 @@ pipe2file(int fd, void *startbuf, size_t nbytes)
 
        switch (r) {
        case -1:
-               error("Error copying from pipe to temp file (%s)\n",
+               file_error(ms, "Error copying from pipe to temp file (%s)",
                    strerror(errno));
-               /*NOTREACHED*/
+               return -1;
        case 0:
                break;
        default:
-               error("Error while writing to temp file (%s)\n",
+               file_error(ms, "Error while writing to temp file (%s)",
                    strerror(errno));
-               /*NOTREACHED*/
+               return -1;
        }
 
        /*
@@ -183,14 +193,14 @@ pipe2file(int fd, void *startbuf, size_t nbytes)
         * can still access the phantom inode.
         */
        if ((fd = dup2(tfd, fd)) == -1) {
-               error("Couldn't dup destcriptor for temp file(%s)\n",
+               file_error(ms, "Couldn't dup destcriptor for temp file (%s)",
                    strerror(errno));
-               /*NOTREACHED*/
+               return -1;
        }
        (void)close(tfd);
        if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) {
-               error("Couldn't seek on temp file (%s)\n", strerror(errno));
-               /*NOTREACHED*/
+               file_badseek(ms);
+               return -1;
        }
        return fd;
 }
@@ -202,8 +212,9 @@ pipe2file(int fd, void *startbuf, size_t nbytes)
 #define FNAME          (1 << 3)
 #define FCOMMENT       (1 << 4)
 
-static int
-uncompressgzipped(const unsigned char *old, unsigned char **newch, int n)
+private size_t
+uncompressgzipped(struct magic_set *ms, const unsigned char *old,
+    unsigned char **newch, size_t n)
 {
        unsigned char flg = old[3];
        int data_start = 10;
@@ -229,7 +240,8 @@ uncompressgzipped(const unsigned char *old, unsigned char **newch, int n)
                return 0;
        }
        
-       z.next_in = (Bytef *)(old + data_start);
+       /* XXX: const castaway, via strchr */
+       z.next_in = (Bytef *)strchr(old + data_start, old[data_start]);
        z.avail_in = n - data_start;
        z.next_out = *newch;
        z.avail_out = HOWMANY;
@@ -239,13 +251,13 @@ uncompressgzipped(const unsigned char *old, unsigned char **newch, int n)
 
        rc = inflateInit2(&z, -15);
        if (rc != Z_OK) {
-               (void) fprintf(stderr,"%s: zlib: %s\n", progname, z.msg);
+               file_error(ms, "zlib: %s", z.msg);
                return 0;
        }
 
        rc = inflate(&z, Z_SYNC_FLUSH);
        if (rc != Z_OK && rc != Z_STREAM_END) {
-               fprintf(stderr,"%s: zlib: %s\n", progname, z.msg);
+               file_error(ms, "zlib: %s", z.msg);
                return 0;
        }
 
@@ -259,9 +271,9 @@ uncompressgzipped(const unsigned char *old, unsigned char **newch, int n)
 }
 #endif
 
-static int
-uncompressbuf(int method, const unsigned char *old, unsigned char **newch,
-             int n)
+private size_t
+uncompressbuf(struct magic_set *ms, int method, const unsigned char *old,
+    unsigned char **newch, size_t n)
 {
        int fdin[2], fdout[2];
 
@@ -270,12 +282,12 @@ uncompressbuf(int method, const unsigned char *old, unsigned char **newch,
         
 #ifdef HAVE_LIBZ
        if (method == 2)
-               return uncompressgzipped(old,newch,n);
+               return uncompressgzipped(ms, old, newch, n);
 #endif
 
        if (pipe(fdin) == -1 || pipe(fdout) == -1) {
-               error("cannot create pipe (%s).\n", strerror(errno));   
-               /*NOTREACHED*/
+               file_error(ms, "Cannot create pipe (%s)", strerror(errno));     
+               return -1;
        }
        switch (fork()) {
        case 0: /* child */
@@ -296,8 +308,8 @@ uncompressbuf(int method, const unsigned char *old, unsigned char **newch,
                exit(1);
                /*NOTREACHED*/
        case -1:
-               error("could not fork (%s).\n", strerror(errno));
-               /*NOTREACHED*/
+               file_error(ms, "Could not fork (%s)", strerror(errno));
+               return -1;
 
        default: /* parent */
                (void) close(fdin[0]);
index 2ccd8cab980975e25ec347d594694e3f67b76b0f..c47f29db6bad2f66ac621cee7fb02a2b6e1115db 100644 (file)
  * 4. This notice may not be removed or altered.
  */
 
+#include "magic.h"
 #include "file.h"
+
+#include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
+#include <sys/types.h>
 #include <sys/param.h> /* for MAXPATHLEN */
+#include <sys/stat.h>
 #include <fcntl.h>     /* for open() */
 #ifdef RESTORE_TIME
 # if (__COHERENT__ >= 0x420)
@@ -58,7 +63,7 @@
 #include "patchlevel.h"
 
 #ifndef        lint
-FILE_RCSID("@(#)$Id: file.c,v 1.69 2003/02/27 20:47:46 christos Exp $")
+FILE_RCSID("@(#)$Id: file.c,v 1.70 2003/03/23 04:06:05 christos Exp $")
 #endif /* lint */
 
 
@@ -69,7 +74,7 @@ FILE_RCSID("@(#)$Id: file.c,v 1.69 2003/02/27 20:47:46 christos Exp $")
 #endif
 
 #ifdef __EMX__
-static char *apptypeName = NULL;
+private char *apptypeName = NULL;
 int os2_apptype (const char *fn, char *buf, int nb);
 #endif /* __EMX__ */
 
@@ -81,57 +86,50 @@ int os2_apptype (const char *fn, char *buf, int nb);
 #define        MAXPATHLEN      512
 #endif
 
-int                    /* Global command-line options          */
-       debug = 0,      /* debugging                            */
-       lflag = 0,      /* follow Symlinks (BSD only)           */
+private int            /* Global command-line options          */
        bflag = 0,      /* brief output format                  */
-       zflag = 0,      /* follow (uncompress) compressed files */
-       sflag = 0,      /* read block special files             */
-       iflag = 0,
        nopad = 0,      /* Don't pad output                     */
        nobuffer = 0,   /* Do not buffer stdout                 */
        kflag = 0;      /* Keep going after the first match     */
 
-int                    /* Misc globals                         */
-       nmagic = 0;     /* number of valid magic[]s             */
-
-struct  magic *magic;  /* array of magic entries               */
-
-const char *magicfile = 0;     /* where the magic is           */
-const char *default_magicfile = MAGIC;
+private const char *magicfile = 0;     /* where the magic is   */
+private const char *default_magicfile = MAGIC;
+private char separator = ':';  /* Default field separator      */
 
-char separator = ':';  /* Default field separator              */
+private char *progname;                /* used throughout              */
 
-char *progname;                /* used throughout                      */
-int lineno;            /* line number in the magic file        */
+private struct magic_set *magic;
 
-
-static void    unwrap(char *fn);
-static void    usage(void);
-#ifdef HAVE_GETOPT_LONG
-static void    help(void);
+private void unwrap(char *);
+private void usage(void);
+#ifdef HAVE_GETOPT_H
+private void help(void);
 #endif
 #if 0
-static int     byteconv4(int, int, int);
-static short   byteconv2(int, int, int);
+private int byteconv4(int, int, int);
+private short byteconv2(int, int, int);
 #endif
 
 int main(int, char *[]);
+private void process(const char *, int);
+private void load(const char *, int);
+
 
 /*
  * main - parse arguments and handle options
  */
 int
-main(int argc, char **argv)
+main(int argc, char *argv[])
 {
        int c;
-       int action = 0, didsomefiles = 0, errflg = 0, ret = 0, app = 0;
+       int action = 0, didsomefiles = 0, errflg = 0;
+       int flags = 0;
        char *mime, *home, *usermagic;
        struct stat sb;
 #define OPTSTRING      "bcdf:F:ikm:nNsvzCL"
 #ifdef HAVE_GETOPT_LONG
        int longindex;
-       static struct option long_options[] =
+       private struct option long_options[] =
        {
                {"version", 0, 0, 'v'},
                {"help", 0, 0, 0},
@@ -207,15 +205,12 @@ main(int argc, char **argv)
                        action = COMPILE;
                        break;
                case 'd':
-                       ++debug;
+                       flags |= MAGIC_DEBUG;
                        break;
                case 'f':
-                       if (!app) {
-                               ret = apprentice(magicfile, action);
-                               if (action)
-                                       exit(ret);
-                               app = 1;
-                       }
+                       if(action)
+                               usage();
+                       load(magicfile, flags);
                        unwrap(optarg);
                        ++didsomefiles;
                        break;
@@ -223,7 +218,7 @@ main(int argc, char **argv)
                        separator = *optarg;
                        break;
                case 'i':
-                       iflag++;
+                       flags |= MAGIC_MIME;
                        if ((mime = malloc(strlen(magicfile) + 6)) != NULL) {
                                (void)strcpy(mime, magicfile);
                                (void)strcat(mime, ".mime");
@@ -243,7 +238,7 @@ main(int argc, char **argv)
                        ++nopad;
                        break;
                case 's':
-                       sflag++;
+                       flags |= MAGIC_DEVICES;
                        break;
                case 'v':
                        (void) fprintf(stdout, "%s-%d.%d\n", progname,
@@ -252,11 +247,11 @@ main(int argc, char **argv)
                                       magicfile);
                        return 1;
                case 'z':
-                       zflag++;
+                       flags |= MAGIC_COMPRESS;
                        break;
 #ifdef S_IFLNK
                case 'L':
-                       ++lflag;
+                       flags |= MAGIC_SYMLINK;
                        break;
 #endif
                case '?':
@@ -269,11 +264,20 @@ main(int argc, char **argv)
                usage();
        }
 
-       if (!app) {
-               ret = apprentice(magicfile, action);
-               if (action)
-                       exit(ret);
-               app = 1;
+       switch(action) {
+       case CHECK:
+       case COMPILE:
+               magic = magic_open(flags);
+               if (magic == NULL) {
+                       (void)fprintf(stderr, "%s: %s\n", progname,
+                           strerror(errno));
+                       return 1;
+               }
+               return action == CHECK ? magic_check(magic, magicfile) :
+                   magic_compile(magic, magicfile);
+       default:
+               load(magicfile, flags);
+               break;
        }
 
        if (optind == argc) {
@@ -296,10 +300,27 @@ main(int argc, char **argv)
 }
 
 
+private void
+load(const char *m, int flags)
+{
+       if (magic)
+               return;
+       magic = magic_open(flags);
+       if (magic == NULL) {
+               (void)fprintf(stderr, "%s: %s\n", progname, strerror(errno));
+               exit(1);
+       }
+       if (magic_load(magic, magicfile) == -1) {
+               (void)fprintf(stderr, "%s: %s\n",
+                   progname, magic_error(magic));
+               exit(1);
+       }
+}
+
 /*
  * unwrap -- read a file of filenames, do each one.
  */
-static void
+private void
 unwrap(char *fn)
 {
        char buf[MAXPATHLEN];
@@ -311,8 +332,9 @@ unwrap(char *fn)
                wid = 1;
        } else {
                if ((f = fopen(fn, "r")) == NULL) {
-                       error("Cannot open `%s' (%s).\n", fn, strerror(errno));
-                       /*NOTREACHED*/
+                       (void)fprintf(stderr, "%s: Cannot open `%s' (%s).\n",
+                           progname, fn, strerror(errno));
+                       exit(1);
                }
 
                while (fgets(buf, MAXPATHLEN, f) != NULL) {
@@ -334,6 +356,22 @@ unwrap(char *fn)
        (void) fclose(f);
 }
 
+private void
+process(const char *inname, int wid)
+{
+       const char *type;
+
+       if (wid > 0 && !bflag)
+               (void) printf("%s%c%*s ", inname, separator,
+                   (int) (nopad ? 0 : (wid - strlen(inname))), "");
+
+       type = magic_file(magic, inname);
+       if (type == NULL)
+               printf("ERROR: %s\n", magic_error(magic));
+       else
+               printf("%s\n", type);
+}
+
 
 #if 0
 /*
@@ -343,7 +381,7 @@ unwrap(char *fn)
  *     same            whether to perform byte swapping
  *     big_endian      whether we are a big endian host
  */
-static int
+private int
 byteconv4(int from, int same, int big_endian)
 {
        if (same)
@@ -370,7 +408,7 @@ byteconv4(int from, int same, int big_endian)
  * byteconv2
  * Same as byteconv4, but for shorts
  */
-static short
+private short
 byteconv2(int from, int same, int big_endian)
 {
        if (same)
@@ -392,156 +430,19 @@ byteconv2(int from, int same, int big_endian)
 }
 #endif
 
-/*
- * process - process input file
- */
-void
-process(const char *inname, int wid)
-{
-       int     fd = 0;
-       static  const char stdname[] = "standard input";
-       unsigned char   buf[HOWMANY+1]; /* one extra for terminating '\0' */
-       struct stat     sb;
-       int nbytes = 0; /* number of bytes read from a datafile */
-       char match = '\0';
-
-       if (strcmp("-", inname) == 0) {
-               if (fstat(0, &sb)<0) {
-                       error("cannot fstat `%s' (%s).\n", stdname,
-                             strerror(errno));
-                       /*NOTREACHED*/
-               }
-               inname = stdname;
-       }
-
-       if (wid > 0 && !bflag)
-            (void) printf("%s%c%*s", inname, separator,
-                          (int) (nopad ? 0 : 1 + (wid - strlen(inname))), "");
-
-       if (inname != stdname) {
-               /*
-                * first try judging the file based on its filesystem status
-                */
-               if (fsmagic(inname, &sb) != 0) {
-                       putchar('\n');
-                       return;
-               }
-
-               if ((fd = open(inname, O_RDONLY)) < 0) {
-                       /* We can't open it, but we were able to stat it. */
-                       if (sb.st_mode & 0002) ckfputs("writable, ", stdout);
-                       if (sb.st_mode & 0111) ckfputs("executable, ", stdout);
-                       ckfprintf(stdout, "can't read `%s' (%s).\n",
-                           inname, strerror(errno));
-                       return;
-               }
-       }
-
-
-       /*
-        * try looking at the first HOWMANY bytes
-        */
-       if ((nbytes = read(fd, (char *)buf, HOWMANY)) == -1) {
-               error("read failed (%s).\n", strerror(errno));
-               /*NOTREACHED*/
-       }
-
-       if (nbytes == 0)
-               ckfputs(iflag ? "application/x-empty" : "empty", stdout);
-       else {
-               buf[nbytes++] = '\0';   /* null-terminate it */
-               match = tryit(inname, buf, nbytes, zflag);
-       }
-
-#ifdef BUILTIN_ELF
-       if (match == 's' && nbytes > 5) {
-               /*
-                * We matched something in the file, so this *might*
-                * be an ELF file, and the file is at least 5 bytes long,
-                * so if it's an ELF file it has at least one byte
-                * past the ELF magic number - try extracting information
-                * from the ELF headers that can't easily be extracted
-                * with rules in the magic file.
-                */
-               tryelf(fd, buf, nbytes);
-       }
-#endif
-
-       if (inname != stdname) {
-#ifdef RESTORE_TIME
-               /*
-                * Try to restore access, modification times if read it.
-                * This is really *bad* because it will modify the status
-                * time of the file... And of course this will affect
-                * backup programs
-                */
-# ifdef USE_UTIMES
-               struct timeval  utsbuf[2];
-               utsbuf[0].tv_sec = sb.st_atime;
-               utsbuf[1].tv_sec = sb.st_mtime;
-
-               (void) utimes(inname, utsbuf); /* don't care if loses */
-# else
-               struct utimbuf  utbuf;
-
-               utbuf.actime = sb.st_atime;
-               utbuf.modtime = sb.st_mtime;
-               (void) utime(inname, &utbuf); /* don't care if loses */
-# endif
-#endif
-               (void) close(fd);
-       }
-       (void) putchar('\n');
-}
-
-
-int
-tryit(const char *fn, unsigned char *buf, int nb, int zfl)
-{
-
-       /*
-        * The main work is done here!
-        * We have the file name and/or the data buffer to be identified. 
-        */
-
-#ifdef __EMX__
-       /*
-        * Ok, here's the right place to add a call to some os-specific
-        * routine, e.g.
-        */
-       if (os2_apptype(fn, buf, nb) == 1)
-              return 'o';
-#endif
-       /* try compression stuff */
-       if (zfl && zmagic(fn, buf, nb))
-               return 'z';
-
-       /* try tests in /etc/magic (or surrogate magic file) */
-       if (softmagic(buf, nb))
-               return 's';
-
-       /* try known keywords, check whether it is ASCII */
-       if (ascmagic(buf, nb))
-               return 'a';
-
-       /* abandon hope, all ye who remain here */
-       ckfputs(iflag ? "application/octet-stream" : "data", stdout);
-               return '\0';
-}
-
-static void
+private void
 usage(void)
 {
        (void)fprintf(stderr, USAGE, progname);
        (void)fprintf(stderr, "Usage: %s -C [-m magic]\n", progname);
-#ifdef HAVE_GETOPT_LONG
+#ifdef HAVE_GETOPT_H
        (void)fputs("Try `file --help' for more information.\n", stderr);
 #endif
        exit(1);
 }
 
-#ifdef HAVE_GETOPT_LONG
-static void
+#ifdef HAVE_GETOPT_H
+private void
 help(void)
 {
        puts(
@@ -556,10 +457,12 @@ help(void)
 "                               conjunction with -m to debug a new magic file\n"
 "                               before installing it\n"
 "  -f, --files-from FILE      read the filenames to be examined from FILE\n"
+"  -F, --separator char       use char as separator instead of `:'\n"
 "  -i, --mime                 output mime type strings\n"
 "  -k, --keep-going           don't stop at the first match\n"
 "  -L, --dereference          causes symlinks to be followed\n"
 "  -n, --no-buffer            do not buffer output\n"
+"  -N, --no-pad               do not pad output\n"
 "  -s, --special-files        treat special (block/char devices) files as\n"
 "                             ordinary ones\n"
 "      --help                 display this help and exit\n"
index 874beb9eb30d4d528dd5c6bc7806e3a267427495..d1662d035149a0f0b9620eb101e2fb53f016a256 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * file.h - definitions for file(1) program
- * @(#)$Id: file.h,v 1.45 2003/02/08 18:33:53 christos Exp $
+ * @(#)$Id: file.h,v 1.46 2003/03/23 04:06:05 christos Exp $
  *
  * Copyright (c) Ian F. Darwin, 1987.
  * Written by Ian F. Darwin.
 #include <config.h>
 #endif
 
+#include <stdio.h>     /* Include that here, to make sure __P gets defined */
 #include <errno.h>
-#include <stdio.h>
 #ifdef HAVE_STDINT_H
 #include <stdint.h>
-#elif defined(HAVE_INTTYPES_H)
+#endif
+#ifdef HAVE_INTTYPES_H
 #include <inttypes.h>
 #endif
 /* Do this here and now, because struct stat gets re-defined on solaris */
 #include <sys/stat.h>
 
+
+#define private static
+#ifndef protected
+#define protected
+#endif
+#define public
+
 #ifndef HOWMANY
 # define HOWMANY 65536         /* how much of the file to look at */
 #endif
@@ -131,48 +139,50 @@ struct magic {
 /* list of magic entries */
 struct mlist {
        struct magic *magic;            /* array of magic entries */
-       uint32_t nmagic;                /* number of entries in array */
+       uint32_t nmagic;                        /* number of entries in array */
+       int mapped;  /* allocation type: 0 => apprentice_file
+                     *                  1 => apprentice_map + malloc
+                     *                  2 => apprentice_map + mmap */
        struct mlist *next, *prev;
 };
 
-extern int   apprentice(const char *, int);
-extern int   ascmagic(unsigned char *, int);
-extern void  error(const char *, ...);
-extern void  ckfputs(const char *, FILE *);
+struct magic_set {
+    struct mlist *mlist;
+    struct cont {
+       size_t len;
+       int32_t *off;
+    } c;
+    struct out {
+       char *buf;
+       char *ptr;
+       size_t len;
+       size_t size;
+    } o;
+    int flags;
+    int haderr;
+};
+
 struct stat;
-extern int   fsmagic(const char *, struct stat *);
-extern char *fmttime(long, int);
-extern int   is_compress(const unsigned char *, int *);
-extern int   is_tar(unsigned char *, int);
-extern void  magwarn(const char *, ...);
-extern void  mdump(struct magic *);
-extern void  process(const char *, int);
-extern void  showstr(FILE *, const char *, int);
-extern int   softmagic(unsigned char *, int);
-extern int   tryit(const char *, unsigned char *, int, int);
-extern int   zmagic(const char *, unsigned char *, int);
-extern void  ckfprintf(FILE *, const char *, ...);
-extern uint32_t signextend(struct magic *, unsigned int32);
-extern void tryelf(int, unsigned char *, int);
-extern int pipe2file(int, void *, size_t);
-
-
-extern char *progname;         /* the program name                     */
-extern const char *magicfile;  /* name of the magic file               */
-extern int lineno;             /* current line number in magic file    */
-
-extern struct mlist mlist;     /* list of arrays of magic entries      */
-
-extern int debug;              /* enable debugging?                    */
-extern int zflag;              /* process compressed files?            */
-extern int lflag;              /* follow symbolic links?               */
-extern int sflag;              /* read/analyze block special files?    */
-extern int iflag;              /* Output types as mime-types           */
-
-#ifdef NEED_GETOPT
-extern int optind;             /* From getopt(3)                       */
-extern char *optarg;
-#endif
+protected char *file_fmttime(long, int);
+protected int file_buf(struct magic_set *, const void *buf, size_t);
+protected int file_fsmagic(struct magic_set *, const char *, struct stat *);
+protected int file_pipe2file(struct magic_set *, int, const void *, size_t);
+protected int file_printf(struct magic_set *, const char *, ...);
+protected int file_reset(struct magic_set *);
+protected int file_tryelf(struct magic_set *, int, const unsigned char *, size_t);
+protected int file_zmagic(struct magic_set *, const unsigned char *, size_t);
+protected int file_ascmagic(struct magic_set *, const unsigned char *, size_t);
+protected int file_is_tar(const unsigned char *, size_t);
+protected int file_softmagic(struct magic_set *, const unsigned char *, size_t);
+protected struct mlist *file_apprentice(struct magic_set *, const char *, int);
+protected uint32_t file_signextend(struct magic_set *, struct magic *, uint32_t);
+protected void file_badread(struct magic_set *);
+protected void file_badseek(struct magic_set *);
+protected void file_oomem(struct magic_set *);
+protected void file_error(struct magic_set *, const char *, ...);
+protected void file_magwarn(const char *, ...);
+protected void file_mdump(struct magic *);
+protected void file_showstr(FILE *, const char *, int);
 
 #ifndef HAVE_STRERROR
 extern int sys_nerr;
@@ -193,5 +203,6 @@ extern char *sys_errlist[];
 static const char *rcsid(const char *p) { \
        return rcsid(p = id); \
 }
+#else
 
 #endif /* __file_h__ */
index fc6a29b24daf7ff5c1baf1d2aa0e93cae17f1ca6..63c43e820054a88c3f92ed834b92c62710e2240d 100644 (file)
  */
 
 #include "file.h"
+#include "magic.h"
 #include <string.h>
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
 #include <stdlib.h>
+#include <sys/stat.h>
 /* Since major is a function on SVR4, we can't use `ifndef major'.  */
 #ifdef MAJOR_IN_MKDEV
 # include <sys/mkdev.h>
 #undef HAVE_MAJOR
 
 #ifndef        lint
-FILE_RCSID("@(#)$Id: fsmagic.c,v 1.36 2002/07/03 19:00:41 christos Exp $")
+FILE_RCSID("@(#)$Id: fsmagic.c,v 1.37 2003/03/23 04:06:05 christos Exp $")
 #endif /* lint */
 
-int
-fsmagic(const char *fn, struct stat *sb)
+protected int
+file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb)
 {
        int ret = 0;
 
@@ -64,41 +66,49 @@ fsmagic(const char *fn, struct stat *sb)
         * On 4.2BSD and similar systems, use lstat() to identify symlinks.
         */
 #ifdef S_IFLNK
-       if (!lflag)
+       if ((ms->flags & MAGIC_SYMLINK) != 0)
                ret = lstat(fn, sb);
        else
 #endif
        ret = stat(fn, sb);     /* don't merge into if; see "ret =" above */
 
        if (ret) {
-               ckfprintf(stdout,
-                       /* Yes, I do mean stdout. */
-                       /* No \n, caller will provide. */
-                       "can't stat `%s' (%s).", fn, strerror(errno));
+               if (file_printf(ms, "can't stat `%s' (%s)",
+                   fn, strerror(errno)) == -1)
+                       return -1;
                return 1;
        }
 
-       if (iflag) {
+       if ((ms->flags & MAGIC_MIME) != 0) {
                if ((sb->st_mode & S_IFMT) != S_IFREG) {
-                       ckfputs("application/x-not-regular-file", stdout);
+                       if (file_printf(ms, "application/x-not-regular-file")
+                           == -1)
+                               return -1;
                        return 1;
                }
        }
        else {
 #ifdef S_ISUID
-               if (sb->st_mode & S_ISUID) ckfputs("setuid ", stdout);
+               if (sb->st_mode & S_ISUID) 
+                       if (file_printf(ms, "setuid ") == -1)
+                               return -1;
 #endif
 #ifdef S_ISGID
-               if (sb->st_mode & S_ISGID) ckfputs("setgid ", stdout);
+               if (sb->st_mode & S_ISGID) 
+                       if (file_printf(ms, "setgid ") == -1)
+                               return -1;
 #endif
 #ifdef S_ISVTX
-               if (sb->st_mode & S_ISVTX) ckfputs("sticky ", stdout);
+               if (sb->st_mode & S_ISVTX) 
+                       if (file_printf(ms, "sticky ") == -1)
+                               return -1;
 #endif
        }
        
        switch (sb->st_mode & S_IFMT) {
        case S_IFDIR:
-               ckfputs("directory", stdout);
+               if (file_printf(ms, "directory") == -1)
+                       return -1;
                return 1;
 #ifdef S_IFCHR
        case S_IFCHR:
@@ -107,20 +117,22 @@ fsmagic(const char *fn, struct stat *sb)
                 * like ordinary files.  Otherwise, just report that they
                 * are block special files and go on to the next file.
                 */
-               if (sflag)
+               if ((ms->flags & MAGIC_DEVICES) != 0)
                        break;
 #ifdef HAVE_ST_RDEV
 # ifdef dv_unit
-               (void) printf("character special (%d/%d/%d)",
-                       major(sb->st_rdev),
-                       dv_unit(sb->st_rdev),
-                       dv_subunit(sb->st_rdev));
+               if (file_printf(ms, "character special (%d/%d/%d)",
+                   major(sb->st_rdev), dv_unit(sb->st_rdev),
+                   dv_subunit(sb->st_rdev)) == -1)
+                       return -1;
 # else
-               (void) printf("character special (%ld/%ld)",
-                       (long) major(sb->st_rdev), (long) minor(sb->st_rdev));
+               if (file_printf(ms, "character special (%ld/%ld)",
+                   (long) major(sb->st_rdev), (long) minor(sb->st_rdev)) == -1)
+                       return -1;
 # endif
 #else
-               (void) printf("character special");
+               if (file_printf(ms, "character special") == -1)
+                       return -1;
 #endif
                return 1;
 #endif
@@ -131,32 +143,36 @@ fsmagic(const char *fn, struct stat *sb)
                 * like ordinary files.  Otherwise, just report that they
                 * are block special files and go on to the next file.
                 */
-               if (sflag)
+               if ((ms->flags & MAGIC_DEVICES) != 0)
                        break;
 #ifdef HAVE_ST_RDEV
 # ifdef dv_unit
-               (void) printf("block special (%d/%d/%d)",
-                       major(sb->st_rdev),
-                       dv_unit(sb->st_rdev),
-                       dv_subunit(sb->st_rdev));
+               if (file_printf(ms, "block special (%d/%d/%d)",
+                   major(sb->st_rdev), dv_unit(sb->st_rdev),
+                   dv_subunit(sb->st_rdev)) == -1)
+                       return -1;
 # else
-               (void) printf("block special (%ld/%ld)",
-                       (long) major(sb->st_rdev), (long) minor(sb->st_rdev));
+               if (file_printf(ms, "block special (%ld/%ld)",
+                   (long)major(sb->st_rdev), (long)minor(sb->st_rdev)) == -1)
+                       return -1;
 # endif
 #else
-               (void) printf("block special");
+               if (file_printf(ms, "block special") == -1)
+                       return -1;
 #endif
                return 1;
 #endif
        /* TODO add code to handle V7 MUX and Blit MUX files */
 #ifdef S_IFIFO
        case S_IFIFO:
-               ckfputs("fifo (named pipe)", stdout);
+               if (file_printf(ms, "fifo (named pipe)") == -1)
+                       return -1;
                return 1;
 #endif
 #ifdef S_IFDOOR
        case S_IFDOOR:
-               ckfputs("door", stdout);
+               if (file_printf(ms, "door") == -1)
+                       return -1;
                return 1;
 #endif
 #ifdef S_IFLNK
@@ -167,8 +183,10 @@ fsmagic(const char *fn, struct stat *sb)
                        struct stat tstatbuf;
 
                        if ((nch = readlink(fn, buf, BUFSIZ-1)) <= 0) {
-                               ckfprintf(stdout, "unreadable symlink (%s).", 
-                                     strerror(errno));
+                               if (file_printf(ms,
+                                   "unreadable symlink `%s' (%s)", 
+                                   strerror(errno)) == -1)
+                                       return -1;
                                return 1;
                        }
                        buf[nch] = '\0';        /* readlink(2) forgets this */
@@ -176,8 +194,9 @@ fsmagic(const char *fn, struct stat *sb)
                        /* If broken symlink, say so and quit early. */
                        if (*buf == '/') {
                            if (stat(buf, &tstatbuf) < 0) {
-                               ckfprintf(stdout,
-                                       "broken symbolic link to %s", buf);
+                               if (file_printf(ms,
+                                   "broken symbolic link to `%s'", buf) == -1)
+                                       return -1;
                                return 1;
                            }
                        }
@@ -189,25 +208,31 @@ fsmagic(const char *fn, struct stat *sb)
                                tmp = buf; /* in current directory anyway */
                            }
                            else {
-                               strcpy (buf2, fn);  /* take directory part */
+                               strcpy(buf2, fn);  /* take directory part */
                                buf2[tmp-fn+1] = '\0';
-                               strcat (buf2, buf); /* plus (relative) symlink */
+                               strcat(buf2, buf); /* plus (relative) symlink */
                                tmp = buf2;
                            }
                            if (stat(tmp, &tstatbuf) < 0) {
-                               ckfprintf(stdout,
-                                       "broken symbolic link to %s", buf);
+                               if (file_printf(ms,
+                                   "broken symbolic link to `%s'",
+                                   buf) == -1)
+                                       return -1;
                                return 1;
                            }
                         }
 
                        /* Otherwise, handle it. */
-                       if (lflag) {
-                               process(buf, strlen(buf));
-                               return 1;
+                       if ((ms->flags & MAGIC_SYMLINK) != 0) {
+                               const char *p;
+                               ms->flags &= MAGIC_SYMLINK;
+                               p = magic_file(ms, buf);
+                               ms->flags |= MAGIC_SYMLINK;
+                               return p != NULL ? 1 : -1;
                        } else { /* just print what it points to */
-                               ckfputs("symbolic link to ", stdout);
-                               ckfputs(buf, stdout);
+                               if (file_printf(ms, "symbolic link to `%s'",
+                                   buf) == -1)
+                                       return -1;
                        }
                }
                return 1;
@@ -215,14 +240,16 @@ fsmagic(const char *fn, struct stat *sb)
 #ifdef S_IFSOCK
 #ifndef __COHERENT__
        case S_IFSOCK:
-               ckfputs("socket", stdout);
+               if (file_printf(ms, "socket") == -1)
+                       return -1;
                return 1;
 #endif
 #endif
        case S_IFREG:
                break;
        default:
-               error("invalid mode 0%o.\n", sb->st_mode);
+               file_error(ms, "invalid mode 0%o", sb->st_mode);
+               return -1;
                /*NOTREACHED*/
        }
 
@@ -238,8 +265,10 @@ fsmagic(const char *fn, struct stat *sb)
         * the fact that it is empty will be detected and reported correctly
         * when we read the file.)
         */
-       if (!sflag && sb->st_size == 0) {
-               ckfputs(iflag ? "application/x-empty" : "empty", stdout);
+       if ((ms->flags & MAGIC_DEVICES) == 0 && sb->st_size == 0) {
+               if (file_printf(ms, (ms->flags & MAGIC_MIME) ?
+                   "application/x-empty" : "empty") == -1)
+                       return -1;
                return 1;
        }
        return 0;
index de7a169184baab6f667e2529fa127be3acbcd424..e19b7f6ccecb5f8f338283332a6b05003f8f6fb4 100644 (file)
@@ -5,7 +5,7 @@
  * Public Domain version written 26 Aug 1985 John Gilmore (ihnp4!hoptoad!gnu).
  *
  * @(#)list.c 1.18 9/23/86 Public Domain - gnu
- * $Id: is_tar.c,v 1.17 2002/07/03 18:26:38 christos Exp $
+ * $Id: is_tar.c,v 1.18 2003/03/23 04:06:05 christos Exp $
  *
  * Comments changed and some code/comments reformatted
  * for file command by Ian Darwin.
 #include "tar.h"
 
 #ifndef lint
-FILE_RCSID("@(#)$Id: is_tar.c,v 1.17 2002/07/03 18:26:38 christos Exp $")
+FILE_RCSID("@(#)$Id: is_tar.c,v 1.18 2003/03/23 04:06:05 christos Exp $")
 #endif
 
 #define        isodigit(c)     ( ((c) >= '0') && ((c) <= '7') )
 
-static int from_oct(int, char *);      /* Decode octal number */
+private int from_oct(int, char *);     /* Decode octal number */
 
 /*
  * Return 
@@ -31,8 +31,8 @@ static int from_oct(int, char *);     /* Decode octal number */
  *     1 for old UNIX tar file,
  *     2 for Unix Std (POSIX) tar file.
  */
-int
-is_tar(unsigned char *buf, int nbytes)
+protected int
+file_is_tar(const unsigned char *buf, size_t nbytes)
 {
        union record *header = (union record *)buf;
        int     i;
@@ -74,7 +74,7 @@ is_tar(unsigned char *buf, int nbytes)
  *
  * Result is -1 if the field is invalid (all blank, or nonoctal).
  */
-static int
+private int
 from_oct(int digs, char *where)
 {
        int     value;
index ea4e85cc24dc51fbf4d0475a84039047164acb1d..6c5ea53d11c103f59836868614ea3473dbead74a 100644 (file)
@@ -10,7 +10,7 @@
  *
  * See LEGAL.NOTICE
  *
- * $Id: names.h,v 1.19 2002/05/16 15:01:41 christos Exp $
+ * $Id: names.h,v 1.20 2003/03/23 04:06:05 christos Exp $
  */
 
 /*
@@ -35,8 +35,8 @@
 #define        L_M4    13              /* M4 */
 
 static const struct {
-       char *human;
-       char *mime;
+       const char *human;
+       const char *mime;
 } types[] = {
        { "C program",                                  "text/x-c", },
        { "C++ program",                                "text/x-c++" },
index bec306747a30c39eb9ddf8ddd370230408bb0bb7..065c3c5f04c9afe9fc25a106b72b8debdb278be6 100644 (file)
@@ -1,30 +1,16 @@
 #define        FILE_VERSION_MAJOR      3
-#define        patchlevel              41
+#define        patchlevel              38
 
 /*
  * Patchlevel file for Ian Darwin's MAGIC command.
- * $Id: patchlevel.h,v 1.41 2003/02/27 20:53:45 christos Exp $
+ * $Id: patchlevel.h,v 1.42 2003/03/23 04:06:05 christos Exp $
  *
  * $Log: patchlevel.h,v $
- * Revision 1.41  2003/02/27 20:53:45  christos
- * - fix memory allocation problem (Jeff Johnson)
- * - fix stack overflow corruption (David Endler)
- * - fixes from NetBSD source (Antti Kantee)
- * - magic fixes
- *
- * Revision 1.40  2003/02/08 18:33:53  christos
- * - detect inttypes.h too (Dave Love <d.love@dl.ac.uk>)
- * - eliminate unsigned char warnings (Petter Reinholdtsen <pere@hungry.com>)
- * - better elf PT_NOTE handling (Nalin Dahyabhai <nalin@redhat.com>)
- * - add options to format the output differently
- * - much more magic.
+ * Revision 1.42  2003/03/23 04:06:05  christos
+ * reorg
  *
- * Revision 1.39  2002/07/03 18:57:52  christos
- * - ansify/c99ize
- * - more magic
- * - better COMPILE_ONLY support.
- * - new magic files.
- * - fix solaris compilation problems.
+ * Revision 1.1.1.1  2003/02/07 18:50:31  mru
+ * Initial librarification.
  *
  * Revision 1.38  2002/05/16 18:45:56  christos
  * - pt_note elf additions from NetBSD
  * Fix a tiny null-pointer bug in previous fix for tar archive + uncompress.
  * 
  */
+
index 0b1a0e4c1b344b6daac49f6f953cd7bbff98ef61..bf4c42e2ef1ca39ebaba334543e59f851d6359d6 100644 (file)
@@ -26,6 +26,8 @@
  */
 
 #include "file.h"
+#include <stdio.h>
+#include <errno.h>
 #include <string.h>
 #include <stdarg.h>
 #include <stdlib.h>
 #include <time.h>
 
 #ifndef lint
-FILE_RCSID("@(#)$Id: print.c,v 1.39 2002/07/09 15:46:23 christos Exp $")
+FILE_RCSID("@(#)$Id: print.c,v 1.40 2003/03/23 04:06:05 christos Exp $")
 #endif  /* lint */
 
 #define SZOF(a)        (sizeof(a) / sizeof(a[0]))
 
 #ifndef COMPILE_ONLY
-void
-mdump(struct magic *m)
+protected void
+file_mdump(struct magic *m)
 {
-       static const char *typ[] = { "invalid", "byte", "short", "invalid",
+       private const char *typ[] = { "invalid", "byte", "short", "invalid",
                                     "long", "string", "date", "beshort",
                                     "belong", "bedate", "leshort", "lelong",
                                     "ledate", "pstring", "ldate", "beldate",
                                     "leldate", "regex" };
-       static const char optyp[] = { '@', '&', '|', '^', '+', '-', 
+       private const char optyp[] = { '@', '&', '|', '^', '+', '-', 
                                      '*', '/', '%' };
        (void) fputc('[', stderr);
        (void) fprintf(stderr, ">>>>>>>> %d" + 8 - (m->cont_level & 7),
@@ -105,17 +107,19 @@ mdump(struct magic *m)
                case STRING:
                case PSTRING:
                case REGEX:
-                       showstr(stderr, m->value.s, -1);
+                       file_showstr(stderr, m->value.s, -1);
                        break;
                case DATE:
                case LEDATE:
                case BEDATE:
-                       (void)fprintf(stderr, "%s,", fmttime(m->value.l, 1));
+                       (void)fprintf(stderr, "%s,",
+                           file_fmttime(m->value.l, 1));
                        break;
                case LDATE:
                case LELDATE:
                case BELDATE:
-                       (void)fprintf(stderr, "%s,", fmttime(m->value.l, 0));
+                       (void)fprintf(stderr, "%s,",
+                           file_fmttime(m->value.l, 0));
                        break;
                default:
                        (void) fputs("*bad*", stderr);
@@ -126,72 +130,23 @@ mdump(struct magic *m)
 }
 #endif
 
-/*
- * ckfputs - fputs, but with error checking
- * ckfprintf - fprintf, but with error checking
- */
-void
-ckfputs(const char *str, FILE *fil)
-{
-       if (fputs(str,fil) == EOF)
-               error("write failed.\n");
-}
-
 /*VARARGS*/
-void
-ckfprintf(FILE *f, const char *fmt, ...)
+protected void
+file_magwarn(const char *f, ...)
 {
        va_list va;
-
-       va_start(va, fmt);
-       (void) vfprintf(f, fmt, va);
-       if (ferror(f))
-               error("write failed.\n");
-       va_end(va);
-}
-
-/*
- * error - print best error message possible and exit
- */
-/*VARARGS*/
-void
-error(const char *f, ...)
-{
-       va_list va;
-
        va_start(va, f);
-       /* cuz we use stdout for most, stderr here */
-       (void) fflush(stdout); 
-
-       if (progname != NULL) 
-               (void) fprintf(stderr, "%s: ", progname);
-       (void) vfprintf(stderr, f, va);
-       va_end(va);
-       exit(1);
-}
-
-/*VARARGS*/
-void
-magwarn(const char *f, ...)
-{
-       va_list va;
 
-       va_start(va, f);
        /* cuz we use stdout for most, stderr here */
        (void) fflush(stdout); 
 
-       if (progname != NULL) 
-               (void) fprintf(stderr, "%s: %s, %d: ", 
-                              progname, magicfile, lineno);
        (void) vfprintf(stderr, f, va);
        va_end(va);
        fputc('\n', stderr);
 }
 
-
-#ifndef COMPILE_ONLY
-char *
-fmttime(long v, int local)
+protected char *
+file_fmttime(long v, int local)
 {
        char *pp, *rt;
        time_t t = (time_t)v;
@@ -201,9 +156,9 @@ fmttime(long v, int local)
                pp = ctime(&t);
        } else {
 #ifndef HAVE_DAYLIGHT
-               static int daylight = 0;
+               private int daylight = 0;
 #ifdef HAVE_TM_ISDST
-               static time_t now = (time_t)0;
+               private time_t now = (time_t)0;
 
                if (now == (time_t)0) {
                        struct tm *tm1;
@@ -223,4 +178,3 @@ fmttime(long v, int local)
                *rt = '\0';
        return pp;
 }
-#endif
index 67dff14c7c7d09790f929890b73a2b01e966aadf..12eeee711bb07c99eda31688a9a06c1b1af75588 100644 (file)
 #include "readelf.h"
 
 #ifndef lint
-FILE_RCSID("@(#)$Id: readelf.c,v 1.28 2003/03/18 19:20:24 christos Exp $")
+FILE_RCSID("@(#)$Id: readelf.c,v 1.29 2003/03/23 04:06:05 christos Exp $")
 #endif
 
 #ifdef ELFCORE
-static void dophn_core(int, int, int, off_t, int, size_t);
+private int dophn_core(struct magic_set *, int, int, int, off_t, int, size_t);
 #endif
-static void dophn_exec(int, int, int, off_t, int, size_t);
-static void doshn(int, int, int, off_t, int, size_t);
-static size_t donote(unsigned char *, size_t, size_t, int, int, int);
+private int dophn_exec(struct magic_set *, int, int, int, off_t, int, size_t);
+private int doshn(struct magic_set *, int, int, int, off_t, int, size_t);
+private size_t donote(struct magic_set *, unsigned char *, size_t, size_t, int,
+    int, int);
 
 #define        ELF_ALIGN(a)    ((((a) + align - 1) / align) * align)
 
-static uint16_t getu16(int, uint16_t);
-static uint32_t getu32(int, uint32_t);
-static uint64_t getu64(int, uint64_t);
+private uint16_t getu16(int, uint16_t);
+private uint32_t getu32(int, uint32_t);
+private uint64_t getu64(int, uint64_t);
 
-static uint16_t
+private uint16_t
 getu16(int swap, uint16_t value)
 {
        union {
@@ -46,7 +47,7 @@ getu16(int swap, uint16_t value)
                return value;
 }
 
-static uint32_t
+private uint32_t
 getu32(int swap, uint32_t value)
 {
        union {
@@ -67,7 +68,7 @@ getu32(int swap, uint32_t value)
                return value;
 }
 
-static uint64_t
+private uint64_t
 getu64(int swap, uint64_t value)
 {
        union {
@@ -174,36 +175,38 @@ size_t    prpsoffsets64[] = {
 #define        OS_STYLE_FREEBSD        1
 #define        OS_STYLE_NETBSD         2
 
-static const char *os_style_names[] = {
+private const char *os_style_names[] = {
        "SVR4",
        "FreeBSD",
        "NetBSD",
 };
 
-static void
-dophn_core(int class, int swap, int fd, off_t off, int num, size_t size)
+private int
+dophn_core(struct magic_set *ms, int class, int swap, int fd, off_t off,
+    int num, size_t size)
 {
        Elf32_Phdr ph32;
-       Elf32_Nhdr *nh32 = NULL;
        Elf64_Phdr ph64;
-       Elf64_Nhdr *nh64 = NULL;
-       size_t offset, noffset, reloffset;
-       unsigned char c;
-       int i, j;
+       size_t offset;
        char nbuf[BUFSIZ];
        int bufsize;
-       int os_style = -1;
 
-       if (size != ph_size)
-               error("corrupted program header size.\n");
+       if (size != ph_size) {
+               file_error(ms, "Corrupted program header size");
+               return -1;
+       }
        /*
         * Loop through all the program headers.
         */
        for ( ; num; num--) {
-               if (lseek(fd, off, SEEK_SET) == -1)
-                       error("lseek failed (%s).\n", strerror(errno));
-               if (read(fd, ph_addr, ph_size) == -1)
-                       error("read failed (%s).\n", strerror(errno));
+               if (lseek(fd, off, SEEK_SET) == (off_t)-1) {
+                       file_badseek(ms);
+                       return -1;
+               }
+               if (read(fd, ph_addr, ph_size) == -1) {
+                       file_badread(ms);
+                       return -1;
+               }
                off += size;
                if (ph_type != PT_NOTE)
                        continue;
@@ -212,24 +215,31 @@ dophn_core(int class, int swap, int fd, off_t off, int num, size_t size)
                 * This is a PT_NOTE section; loop through all the notes
                 * in the section.
                 */
-               if (lseek(fd, (off_t) ph_offset, SEEK_SET) == -1)
-                       error("lseek failed (%s).\n", strerror(errno));
+               if (lseek(fd, (off_t) ph_offset, SEEK_SET) == (off_t)-1) {
+                       file_badseek(ms);
+                       return -1;
+               }
                bufsize = read(fd, nbuf, BUFSIZ);
-               if (bufsize == -1)
-                       error(": " "read failed (%s).\n", strerror(errno));
+               if (bufsize == -1) {
+                       file_badread(ms);
+                       return -1;
+               }
                offset = 0;
                for (;;) {
                        if (offset >= bufsize)
                                break;
-                       offset = donote(nbuf, offset, bufsize, class, swap, 4);
+                       offset = donote(ms, nbuf, offset, bufsize, class, swap,
+                           4);
+
                }
        }
+       return 0;
 }
 #endif
 
-static size_t
-donote(unsigned char *nbuf, size_t offset, size_t size, int class, int swap,
-       int align)
+private size_t
+donote(struct magic_set *ms, unsigned char *nbuf, size_t offset, size_t size,
+    int class, int swap, int align)
 {
        Elf32_Nhdr *nh32 = NULL;
        Elf64_Nhdr *nh64 = NULL;
@@ -269,22 +279,28 @@ donote(unsigned char *nbuf, size_t offset, size_t size, int class, int swap,
            nh_type == NT_GNU_VERSION && nh_descsz == 16) {
                uint32_t *desc = (uint32_t *)&nbuf[doff];
 
-               printf(", for GNU/");
+               if (file_printf(ms, ", for GNU/") == -1)
+                       return -1;
                switch (getu32(swap, desc[0])) {
                case GNU_OS_LINUX:
-                       printf("Linux");
+                       if (file_printf(ms, "Linux") == -1)
+                               return -1;
                        break;
                case GNU_OS_HURD:
-                       printf("Hurd");
+                       if (file_printf(ms, "Hurd") == -1)
+                               return -1;
                        break;
                case GNU_OS_SOLARIS:
-                       printf("Solaris");
+                       if (file_printf(ms, "Solaris") == -1)
+                               return -1;
                        break;
                default:
-                       printf("<unknown>");
+                       if (file_printf(ms, "<unknown>") == -1)
+                               return -1;
                }
-               printf(" %d.%d.%d", getu32(swap, desc[1]),
-                   getu32(swap, desc[2]), getu32(swap, desc[3]));
+               if (file_printf(ms, " %d.%d.%d", getu32(swap, desc[1]),
+                   getu32(swap, desc[2]), getu32(swap, desc[3])) == -1)
+                       return -1;
                return size;
        }
 
@@ -292,7 +308,8 @@ donote(unsigned char *nbuf, size_t offset, size_t size, int class, int swap,
            nh_type == NT_NETBSD_VERSION && nh_descsz == 4) {
                uint32_t desc = getu32(swap, *(uint32_t *)&nbuf[doff]);
 
-               printf(", for NetBSD");
+               if (file_printf(ms, ", for NetBSD") == -1)
+                       return -1;
                /*
                 * The version number used to be stuck as 199905, and was thus
                 * basically content-free.  Newer versions of NetBSD have fixed
@@ -311,15 +328,20 @@ donote(unsigned char *nbuf, size_t offset, size_t size, int class, int swap,
                        u_int ver_min = (desc / 1000000) % 100;
                        u_int ver_maj = desc / 100000000;
 
-                       printf(" %u.%u", ver_maj, ver_min);
+                       if (file_printf(ms, " %u.%u", ver_maj, ver_min) == -1)
+                               return -1;
                        if (ver_rel == 0 && ver_patch != 0) {
-                               printf(".%u", ver_patch);
+                               if (file_printf(ms, ".%u", ver_patch) == -1)
+                                       return -1;
                        } else if (ver_rel != 0 && ver_rel <= 26) {
-                               printf("%c", 'A' + ver_rel - 1);
+                               if (file_printf(ms, "%c", 'A' + ver_rel - 1) == -1)
+                                       return -1;
                        } else if (ver_rel != 0 && ver_rel <= 52) {
-                               printf("Z%c", 'A' + ver_rel - 1);
+                               if (file_printf(ms, "Z%c", 'A' + ver_rel - 1) == -1)
+                                       return -1;
                        } else if (ver_rel != 0) {
-                               printf("<unknown>");
+                               if (file_printf(ms, "<unknown>") == -1)
+                                       return -1;
                        }
                }
                return size;
@@ -329,22 +351,26 @@ donote(unsigned char *nbuf, size_t offset, size_t size, int class, int swap,
            nh_type == NT_FREEBSD_VERSION && nh_descsz == 4) {
                uint32_t desc = getu32(swap,
                    *(uint32_t *)&nbuf[doff]);
-               printf(", for FreeBSD");
+               if (file_printf(ms, ", for FreeBSD") == -1)
+                       return -1;
                /*
                 * Contents is __FreeBSD_version, whose relation to OS versions
                 * is defined by a huge table in the Porters' Handbook. Happily,
                 * the first three digits are the version number, at least in
                 * versions of FreeBSD that use this note.
                 */
-               printf(" %d.%d", desc / 100000, desc / 10000 % 10);
+               if (file_printf(ms, " %d.%d", desc / 100000, desc / 10000 % 10) == -1)
+                       return -1;
                if (desc / 1000 % 10 > 0)
-                       printf(".%d", desc / 1000 % 10);
+                       if (file_printf(ms, ".%d", desc / 1000 % 10) == -1)
+                               return -1;
                return size;
        }
 
        if (nh_namesz == 8 && strcmp(&nbuf[noff], "OpenBSD") == 0 &&
            nh_type == NT_OPENBSD_VERSION && nh_descsz == 4) {
-               printf(", for OpenBSD");
+               if (file_printf(ms, ", for OpenBSD") == -1)
+                       return -1;
                /* Content of note is always 0 */
                return size;
        }
@@ -378,7 +404,8 @@ donote(unsigned char *nbuf, size_t offset, size_t size, int class, int swap,
 
 #ifdef ELFCORE
        if (os_style != -1)
-               printf(", %s-style", os_style_names[os_style]);
+               if (file_printf(ms, ", %s-style", os_style_names[os_style]) == -1)
+                       return -1;
 
        if (os_style == OS_STYLE_NETBSD && nh_type == NT_NETBSD_CORE_PROCINFO) {
                uint32_t signo;
@@ -387,7 +414,8 @@ donote(unsigned char *nbuf, size_t offset, size_t size, int class, int swap,
                 * offset 0x7c, and is up to 32-bytes,
                 * including the terminating NUL.
                 */
-               printf(", from '%.31s'", &nbuf[doff + 0x7c]);
+               if (file_printf(ms, ", from '%.31s'", &nbuf[doff + 0x7c]) == -1)
+                       return -1;
                
                /*
                 * Extract the signal number.  It is at
@@ -395,7 +423,8 @@ donote(unsigned char *nbuf, size_t offset, size_t size, int class, int swap,
                 */
                memcpy(&signo, &nbuf[doff + 0x08],
                    sizeof(signo));
-               printf(" (signal %u)", getu32(swap, signo));
+               if (file_printf(ms, " (signal %u)", getu32(swap, signo)) == -1)
+                       return -1;
                return size;
        } else if (os_style != OS_STYLE_NETBSD && nh_type == NT_PRPSINFO) {
                int i, j;
@@ -459,8 +488,9 @@ donote(unsigned char *nbuf, size_t offset, size_t size, int class, int swap,
                        /*
                         * Well, that worked.
                         */
-                       printf(", from '%.16s'",
-                           &nbuf[doff + prpsoffsets(i)]);
+                       if (file_printf(ms, ", from '%.16s'",
+                           &nbuf[doff + prpsoffsets(i)]) == -1)
+                               return -1;
                        return size;
 
                tryanother:
@@ -472,27 +502,37 @@ donote(unsigned char *nbuf, size_t offset, size_t size, int class, int swap,
        return offset;
 }
 
-static void
-doshn(int class, int swap, int fd, off_t off, int num, size_t size)
+private int
+doshn(struct magic_set *ms, int class, int swap, int fd, off_t off, int num,
+    size_t size)
 {
        Elf32_Shdr sh32;
        Elf64_Shdr sh64;
 
-       if (size != sh_size)
-               error("corrupted section header size.\n");
+       if (size != sh_size) {
+               file_error(ms, "Corrupted section header size");
+               return -1;
+       }
 
-       if (lseek(fd, off, SEEK_SET) == -1)
-               error("lseek failed (%s).\n", strerror(errno));
+       if (lseek(fd, off, SEEK_SET) == (off_t)-1) {
+               file_badseek(ms);
+               return -1;
+       }
 
        for ( ; num; num--) {
-               if (read(fd, sh_addr, sh_size) == -1)
-                       error("read failed (%s).\n", strerror(errno));
+               if (read(fd, sh_addr, sh_size) == -1) {
+                       file_badread(ms);
+                       return -1;
+               }
                if (shs_type == SHT_SYMTAB /* || shs_type == SHT_DYNSYM */) {
-                       (void) printf (", not stripped");
-                       return;
+                       if (file_printf(ms, ", not stripped") == -1)
+                               return -1;
+                       return 0;
                }
        }
-       (void) printf (", stripped");
+       if (file_printf(ms, ", stripped") == -1)
+               return -1;
+       return 0;
 }
 
 /*
@@ -500,28 +540,37 @@ doshn(int class, int swap, int fd, off_t off, int num, size_t size)
  * for a PT_INTERP section; if one is found, it's dynamically linked,
  * otherwise it's statically linked.
  */
-static void
-dophn_exec(int class, int swap, int fd, off_t off, int num, size_t size)
+private int
+dophn_exec(struct magic_set *ms, int class, int swap, int fd, off_t off,
+    int num, size_t size)
 {
        Elf32_Phdr ph32;
        Elf64_Phdr ph64;
-       char *linking_style = "statically";
-       char *shared_libraries = "";
+       const char *linking_style = "statically";
+       const char *shared_libraries = "";
        char nbuf[BUFSIZ];
        int bufsize;
        size_t offset;
        off_t savedoffset;
 
-       if (size != ph_size)
-               error("corrupted program header size.\n");
-       if (lseek(fd, off, SEEK_SET) == -1)
-               error("lseek failed (%s).\n", strerror(errno));
+       if (size != ph_size) {
+               file_error(ms, "Corrupted program header size");
+               return -1;
+       }
+       if (lseek(fd, off, SEEK_SET) == (off_t)-1) {
+               file_badseek(ms);
+               return -1;
+       }
 
        for ( ; num; num--) {
-               if (read(fd, ph_addr, ph_size) == -1)
-                       error("read failed (%s).\n", strerror(errno));
-               if ((savedoffset = lseek(fd, 0, SEEK_CUR)) == -1)
-                       error("lseek failed (%s).\n", strerror(errno));
+               if (read(fd, ph_addr, ph_size) == -1) {
+                       file_badread(ms);
+                       return -1;
+               }
+               if ((savedoffset = lseek(fd, 0, SEEK_CUR)) == (off_t)-1) {
+                       file_badseek(ms);
+                       return -1;
+               }
 
                switch (ph_type) {
                case PT_DYNAMIC:
@@ -535,30 +584,41 @@ dophn_exec(int class, int swap, int fd, off_t off, int num, size_t size)
                         * This is a PT_NOTE section; loop through all the notes
                         * in the section.
                         */
-                       if (lseek(fd, (off_t) ph_offset, SEEK_SET) == -1)
-                               error("lseek failed (%s).\n", strerror(errno));
+                       if (lseek(fd, (off_t) ph_offset, SEEK_SET)
+                           == (off_t)-1) {
+                               file_badseek(ms);
+                               return -1;
+                       }
                        bufsize = read(fd, nbuf, sizeof(nbuf));
-                       if (bufsize == -1)
-                               error(": " "read failed (%s).\n",
-                                   strerror(errno));
+                       if (bufsize == -1) {
+                               file_badread(ms);
+                               return -1;
+                       }
                        offset = 0;
                        for (;;) {
                                if (offset >= bufsize)
                                        break;
-                               offset = donote(nbuf, offset, bufsize,
+                               offset = donote(ms, nbuf, offset, bufsize,
                                    class, swap, ph_align);
                        }
-                       if ((lseek(fd, savedoffset + offset, SEEK_SET)) == -1)
-                               error("lseek failed (%s).\n", strerror(errno));
+                       if (lseek(fd, savedoffset + offset, SEEK_SET)
+                           == (off_t)-1) {
+                               file_badseek(ms);
+                               return -1;
+                       }
                        break;
                }
        }
-       printf(", %s linked%s", linking_style, shared_libraries);
+       if (file_printf(ms, ", %s linked%s", linking_style, shared_libraries)
+           == -1)
+           return -1;
+       return 0;
 }
 
 
-void
-tryelf(int fd, unsigned char *buf, int nbytes)
+protected int
+file_tryelf(struct magic_set *ms, int fd, const unsigned char *buf,
+    size_t nbytes)
 {
        union {
                int32_t l;
@@ -571,7 +631,7 @@ tryelf(int fd, unsigned char *buf, int nbytes)
         * If we can't seek, it must be a pipe, socket or fifo.
         */
        if((lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) && (errno == ESPIPE))
-               fd = pipe2file(fd, buf, nbytes);
+               fd = file_pipe2file(ms, fd, buf, nbytes);
 
        /*
         * ELF executables have multiple section headers in arbitrary
@@ -582,7 +642,7 @@ tryelf(int fd, unsigned char *buf, int nbytes)
        if (buf[EI_MAG0] != ELFMAG0
            || (buf[EI_MAG1] != ELFMAG1 && buf[EI_MAG1] != OLFMAG1)
            || buf[EI_MAG2] != ELFMAG2 || buf[EI_MAG3] != ELFMAG3)
-           return;
+           return 0;
 
 
        class = buf[4];
@@ -590,88 +650,88 @@ tryelf(int fd, unsigned char *buf, int nbytes)
        if (class == ELFCLASS32) {
                Elf32_Ehdr elfhdr;
                if (nbytes <= sizeof (Elf32_Ehdr))
-                       return;
+                       return 0;
 
 
                u.l = 1;
                (void) memcpy(&elfhdr, buf, sizeof elfhdr);
                swap = (u.c[sizeof(int32_t) - 1] + 1) != elfhdr.e_ident[5];
 
-               if (getu16(swap, elfhdr.e_type) == ET_CORE) 
+               if (getu16(swap, elfhdr.e_type) == ET_CORE) {
 #ifdef ELFCORE
-                       dophn_core(class, swap,
-                                  fd,
-                                  getu32(swap, elfhdr.e_phoff),
-                                  getu16(swap, elfhdr.e_phnum), 
-                                  getu16(swap, elfhdr.e_phentsize));
+                       if (dophn_core(ms, class, swap, fd,
+                           getu32(swap, elfhdr.e_phoff),
+                           getu16(swap, elfhdr.e_phnum), 
+                           getu16(swap, elfhdr.e_phentsize)) == -1)
+                               return -1;
 #else
                        ;
 #endif
-               else {
+               else {
                        if (getu16(swap, elfhdr.e_type) == ET_EXEC) {
-                               dophn_exec(class, swap,
-                                          fd,
-                                          getu32(swap, elfhdr.e_phoff),
-                                          getu16(swap, elfhdr.e_phnum), 
-                                          getu16(swap, elfhdr.e_phentsize));
+                               if (dophn_exec(ms, class, swap,
+                                   fd, getu32(swap, elfhdr.e_phoff),
+                                   getu16(swap, elfhdr.e_phnum), 
+                                   getu16(swap, elfhdr.e_phentsize)) == -1)
+                                       return -1;
                        }
-                       doshn(class, swap,
-                             fd,
-                             getu32(swap, elfhdr.e_shoff),
-                             getu16(swap, elfhdr.e_shnum),
-                             getu16(swap, elfhdr.e_shentsize));
+                       if (doshn(ms, class, swap, fd,
+                           getu32(swap, elfhdr.e_shoff),
+                           getu16(swap, elfhdr.e_shnum),
+                           getu16(swap, elfhdr.e_shentsize)) == -1)
+                               return -1;
                }
-               return;
+               return 1;
        }
 
         if (class == ELFCLASS64) {
                Elf64_Ehdr elfhdr;
                if (nbytes <= sizeof (Elf64_Ehdr))
-                       return;
+                       return 0;
 
 
                u.l = 1;
                (void) memcpy(&elfhdr, buf, sizeof elfhdr);
                swap = (u.c[sizeof(int32_t) - 1] + 1) != elfhdr.e_ident[5];
 
-               if (getu16(swap, elfhdr.e_type) == ET_CORE) 
+               if (getu16(swap, elfhdr.e_type) == ET_CORE) {
 #ifdef ELFCORE
-                       dophn_core(class, swap,
-                                  fd,
+                       if (dophn_core(ms, class, swap, fd,
 #ifdef USE_ARRAY_FOR_64BIT_TYPES
-                                  getu32(swap, elfhdr.e_phoff[1]),
+                           getu32(swap, elfhdr.e_phoff[1]),
 #else
-                                  getu64(swap, elfhdr.e_phoff),
+                           getu64(swap, elfhdr.e_phoff),
 #endif
-                                  getu16(swap, elfhdr.e_phnum), 
-                                  getu16(swap, elfhdr.e_phentsize));
+                           getu16(swap, elfhdr.e_phnum), 
+                           getu16(swap, elfhdr.e_phentsize)) == -1)
+                               return -1;
 #else
                        ;
 #endif
-               else
-               {
+               } else {
                        if (getu16(swap, elfhdr.e_type) == ET_EXEC) {
-                               dophn_exec(class, swap,
-                                          fd,
+                               if (dophn_exec(ms, class, swap, fd,
 #ifdef USE_ARRAY_FOR_64BIT_TYPES
-                                          getu32(swap, elfhdr.e_phoff[1]),
+                                   getu32(swap, elfhdr.e_phoff[1]),
 #else
-                                          getu64(swap, elfhdr.e_phoff),
+                                   getu64(swap, elfhdr.e_phoff),
 #endif
-                                          getu16(swap, elfhdr.e_phnum), 
-                                          getu16(swap, elfhdr.e_phentsize));
+                                   getu16(swap, elfhdr.e_phnum), 
+                                   getu16(swap, elfhdr.e_phentsize)) == -1)
+                                       return -1;
                        }
-                       doshn(class, swap,
-                             fd,
+                       if (doshn(ms, class, swap, fd,
 #ifdef USE_ARRAY_FOR_64BIT_TYPES
-                             getu32(swap, elfhdr.e_shoff[1]),
+                           getu32(swap, elfhdr.e_shoff[1]),
 #else
-                             getu64(swap, elfhdr.e_shoff),
+                           getu64(swap, elfhdr.e_shoff),
 #endif
-                             getu16(swap, elfhdr.e_shnum),
-                             getu16(swap, elfhdr.e_shentsize));
+                           getu16(swap, elfhdr.e_shnum),
+                           getu16(swap, elfhdr.e_shentsize)) == -1)
+                               return -1;
                }
-               return;
+               return 1;
        }
+       return 0;
 }
 #endif
index f7494de6b61d466a37805e22986c08d8abfbfafc..8d80a5887f41feb972fd45c8d8a5d5dfd9440604 100644 (file)
@@ -1,8 +1,6 @@
-/*     $NetBSD: readelf.h,v 1.9 2002/05/18 07:00:47 pooka Exp $        */
-
 /*
  * readelf.h 
- * @(#)Id: readelf.h,v 1.9 2002/05/16 18:45:56 christos Exp 
+ * @(#)Id: readelf.h,v 1.9 2002/05/16 18:45:56 christos Exp
  *
  * Provide elf data structures for non-elf machines, allowing file
  * non-elf hosts to determine if an elf binary is stripped.
index d1ef94dd415c942460c2af10108fa33bf0ed15ea..c1c9ca353d74d4c96387d190511a2756d76f6e59 100644 (file)
@@ -26,6 +26,7 @@
  */
 
 #include "file.h"
+#include "magic.h"
 #include <string.h>
 #include <ctype.h>
 #include <stdlib.h>
 
 
 #ifndef        lint
-FILE_RCSID("@(#)$Id: softmagic.c,v 1.54 2003/02/25 13:04:32 christos Exp $")
+FILE_RCSID("@(#)$Id: softmagic.c,v 1.55 2003/03/23 04:06:05 christos Exp $")
 #endif /* lint */
 
-static int match(struct magic *, uint32_t, unsigned char *, int);
-static int mget(union VALUETYPE *, unsigned char *, struct magic *, int);
-static int mcheck(union VALUETYPE *, struct magic *);
-static int32_t mprint(union VALUETYPE *, struct magic *);
-static void mdebug(int32_t, char *, int);
-static int mconvert(union VALUETYPE *, struct magic *);
-
-extern int kflag;
+private int match(struct magic_set *, struct magic *, uint32_t,
+    const unsigned char *, size_t);
+private int mget(struct magic_set *, union VALUETYPE *, const unsigned char *,
+    struct magic *, size_t);
+private int mcheck(struct magic_set *, union VALUETYPE *, struct magic *);
+private int32_t mprint(struct magic_set *, union VALUETYPE *, struct magic *);
+private void mdebug(int32_t, const char *, size_t);
+private int mconvert(struct magic_set *, union VALUETYPE *, struct magic *);
+private int check_mem(struct magic_set *, int);
 
 /*
  * softmagic - lookup one file in database 
@@ -52,13 +54,12 @@ extern int kflag;
  * Passed the name and FILE * of one file to be typed.
  */
 /*ARGSUSED1*/          /* nbytes passed for regularity, maybe need later */
-int
-softmagic(unsigned char *buf, int nbytes)
+protected int
+file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes)
 {
        struct mlist *ml;
-
-       for (ml = mlist.next; ml != &mlist; ml = ml->next)
-               if (match(ml->magic, ml->nmagic, buf, nbytes))
+       for (ml = ms->mlist->next; ml != ms->mlist; ml = ml->next)
+               if (match(ms, ml->magic, ml->nmagic, buf, nbytes))
                        return 1;
 
        return 0;
@@ -91,44 +92,52 @@ softmagic(unsigned char *buf, int nbytes)
  *     If a continuation matches, we bump the current continuation level
  *     so that higher-level continuations are processed.
  */
-static int
-match(struct magic *magic, uint32_t nmagic, unsigned char *s, int nbytes)
+private int
+match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
+    const unsigned char *s, size_t nbytes)
 {
        int magindex = 0;
        int cont_level = 0;
        int need_separator = 0;
        union VALUETYPE p;
-       static int32_t *tmpoff = NULL;
-       static size_t tmplen = 0;
        int32_t oldoff = 0;
        int returnval = 0; /* if a match is found it is set to 1*/
        int firstline = 1; /* a flag to print X\n  X\n- X */
 
-       if (tmpoff == NULL)
-               if ((tmpoff = (int32_t *) malloc(
-                   (tmplen = 20) * sizeof(*tmpoff))) == NULL)
-                       error("out of memory\n");
+       if (check_mem(ms, cont_level) == -1)
+               return -1;
 
        for (magindex = 0; magindex < nmagic; magindex++) {
                /* if main entry matches, print it... */
-               if (!mget(&p, s, &magic[magindex], nbytes) ||
-                   !mcheck(&p, &magic[magindex])) {
-                           /* 
-                            * main entry didn't match,
-                            * flush its continuations
-                            */
-                           while (magindex < nmagic &&
-                                  magic[magindex + 1].cont_level != 0)
-                                  magindex++;
-                           continue;
+               int flush = !mget(ms, &p, s, &magic[magindex], nbytes);
+               switch (mcheck(ms, &p, &magic[magindex])) {
+               case -1:
+                       return -1;
+               case 0:
+                       flush++;
+               default:
+                       break;
+               }
+               if (flush) {
+                       /* 
+                        * main entry didn't match,
+                        * flush its continuations
+                        */
+                       while (magindex < nmagic &&
+                              magic[magindex + 1].cont_level != 0)
+                              magindex++;
+                       continue;
                }
 
-               if (! firstline) { /* we found another match */
+               if (!firstline) { /* we found another match */
                        /* put a newline and '-' to do some simple formatting*/
-                       printf("\n- ");
+                       if (file_printf(ms, "\n- ") == -1)
+                               return -1;
                }
 
-               tmpoff[cont_level] = mprint(&p, &magic[magindex]);
+               if ((ms->c.off[cont_level] = mprint(ms, &p, &magic[magindex]))
+                   == -1)
+                       return -1;
                /*
                 * If we printed something, we'll need to print
                 * a blank before we print something else.
@@ -136,75 +145,94 @@ match(struct magic *magic, uint32_t nmagic, unsigned char *s, int nbytes)
                if (magic[magindex].desc[0])
                        need_separator = 1;
                /* and any continuations that match */
-               if (++cont_level >= tmplen)
-                       if ((tmpoff = (int32_t *) realloc(tmpoff,
-                           (tmplen += 20) * sizeof(*tmpoff))) == NULL)
-                               error("out of memory\n");
+               if (check_mem(ms, ++cont_level) == -1)
+                       return -1;
+
                while (magic[magindex+1].cont_level != 0 && 
                       ++magindex < nmagic) {
-                       if (cont_level >= magic[magindex].cont_level) {
-                               if (cont_level > magic[magindex].cont_level) {
-                                       /*
-                                        * We're at the end of the level
-                                        * "cont_level" continuations.
-                                        */
-                                       cont_level = magic[magindex].cont_level;
-                               }
-                               if (magic[magindex].flag & OFFADD) {
-                                       oldoff=magic[magindex].offset;
-                                       magic[magindex].offset +=
-                                           tmpoff[cont_level-1];
+                       if (cont_level < magic[magindex].cont_level)
+                               continue;
+                       if (cont_level > magic[magindex].cont_level) {
+                               /*
+                                * We're at the end of the level
+                                * "cont_level" continuations.
+                                */
+                               cont_level = magic[magindex].cont_level;
+                       }
+                       if (magic[magindex].flag & OFFADD) {
+                               oldoff=magic[magindex].offset;
+                               magic[magindex].offset += ms->c.off[cont_level-1];
+                       }
+                       if (!mget(ms, &p, s, &magic[magindex], nbytes))
+                               goto done;
+                               
+                       switch (mcheck(ms, &p, &magic[magindex])) {
+                       case -1:
+                               return -1;
+                       case 0:
+                               break;
+                       default:
+                               /*
+                                * This continuation matched.
+                                * Print its message, with
+                                * a blank before it if
+                                * the previous item printed
+                                * and this item isn't empty.
+                                */
+                               /* space if previous printed */
+                               if (need_separator
+                                   && (magic[magindex].nospflag == 0)
+                                  && (magic[magindex].desc[0] != '\0')) {
+                                       if (file_printf(ms, " ") == -1)
+                                               return -1;
+                                       need_separator = 0;
                                }
-                               if (mget(&p, s, &magic[magindex], nbytes) &&
-                                   mcheck(&p, &magic[magindex])) {
-                                       /*
-                                        * This continuation matched.
-                                        * Print its message, with
-                                        * a blank before it if
-                                        * the previous item printed
-                                        * and this item isn't empty.
-                                        */
-                                       /* space if previous printed */
-                                       if (need_separator
-                                          && (magic[magindex].nospflag == 0)
-                                          && (magic[magindex].desc[0] != '\0')
-                                          ) {
-                                               (void) putchar(' ');
-                                               need_separator = 0;
-                                       }
-                                       tmpoff[cont_level] =
-                                           mprint(&p, &magic[magindex]);
-                                       if (magic[magindex].desc[0])
-                                               need_separator = 1;
+                               if ((ms->c.off[cont_level] = mprint(ms, &p,
+                                   &magic[magindex])) == -1)
+                                       return -1;
+                               if (magic[magindex].desc[0])
+                                       need_separator = 1;
 
-                                       /*
-                                        * If we see any continuations
-                                        * at a higher level,
-                                        * process them.
-                                        */
-                                       if (++cont_level >= tmplen)
-                                               if ((tmpoff = 
-                                                   (int32_t *) realloc(tmpoff,
-                                                   (tmplen += 20) 
-                                                   * sizeof(*tmpoff))) == NULL)
-                                                       error("out of memory\n");
-                               }
-                               if (magic[magindex].flag & OFFADD) {
-                                        magic[magindex].offset = oldoff;
-                               }
+                               /*
+                                * If we see any continuations
+                                * at a higher level,
+                                * process them.
+                                */
+                               if (check_mem(ms, ++cont_level) == -1)
+                                       return -1;
+                       }
+done:
+                       if (magic[magindex].flag & OFFADD) {
+                                magic[magindex].offset = oldoff;
                        }
                }
                firstline = 0;
                returnval = 1;
-               if (!kflag) {
+               if ((ms->flags & MAGIC_CONTINUE) == 0) {
                        return 1; /* don't keep searching */
                }                       
        }
        return returnval;  /* This is hit if -k is set or there is no match */
 }
 
-static int32_t
-mprint(union VALUETYPE *p, struct magic *m)
+private int
+check_mem(struct magic_set *ms, int level)
+{
+       size_t len;
+
+       if (level < ms->c.len)
+               return 0;
+
+       len = (ms->c.len += 20) * sizeof(*ms->c.off);
+       ms->c.off = (ms->c.off == NULL) ? malloc(len) : realloc(ms->c.off, len);
+       if (ms->c.off != NULL)
+               return 0;
+       file_oomem(ms);
+       return -1;
+}
+
+private int32_t
+mprint(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
 {
        uint32_t v;
        int32_t t=0 ;
@@ -212,31 +240,35 @@ mprint(union VALUETYPE *p, struct magic *m)
 
        switch (m->type) {
        case BYTE:
-               v = signextend(m, p->b);
-               (void) printf(m->desc, (unsigned char) v);
+               v = file_signextend(ms, m, p->b);
+               if (file_printf(ms, m->desc, (unsigned char) v) == -1)
+                       return -1;
                t = m->offset + sizeof(char);
                break;
 
        case SHORT:
        case BESHORT:
        case LESHORT:
-               v = signextend(m, p->h);
-               (void) printf(m->desc, (unsigned short) v);
+               v = file_signextend(ms, m, p->h);
+               if (file_printf(ms, m->desc, (unsigned short) v) == -1)
+                       return -1;
                t = m->offset + sizeof(short);
                break;
 
        case LONG:
        case BELONG:
        case LELONG:
-               v = signextend(m, p->l);
-               (void) printf(m->desc, (uint32_t) v);
+               v = file_signextend(ms, m, p->l);
+               if (file_printf(ms, m->desc, (uint32_t) v) == -1)
+                       return -1;
                t = m->offset + sizeof(int32_t);
                break;
 
        case STRING:
        case PSTRING:
                if (m->reln == '=') {
-                       (void) printf(m->desc, m->value.s);
+                       if (file_printf(ms, m->desc, m->value.s) == -1)
+                               return -1;
                        t = m->offset + strlen(m->value.s);
                }
                else {
@@ -245,7 +277,8 @@ mprint(union VALUETYPE *p, struct magic *m)
                                if (cp)
                                        *cp = '\0';
                        }
-                       (void) printf(m->desc, p->s);
+                       if (file_printf(ms, m->desc, p->s) == -1)
+                               return -1;
                        t = m->offset + strlen(p->s);
                }
                break;
@@ -253,24 +286,27 @@ mprint(union VALUETYPE *p, struct magic *m)
        case DATE:
        case BEDATE:
        case LEDATE:
-               (void) printf(m->desc, fmttime(p->l, 1));
+               if (file_printf(ms, m->desc, file_fmttime(p->l, 1)) == -1)
+                       return -1;
                t = m->offset + sizeof(time_t);
                break;
 
        case LDATE:
        case BELDATE:
        case LELDATE:
-               (void) printf(m->desc, fmttime(p->l, 0));
+               if (file_printf(ms, m->desc, file_fmttime(p->l, 0)) == -1)
+                       return -1;
                t = m->offset + sizeof(time_t);
                break;
        case REGEX:
-               (void) printf(m->desc, p->s);
+               if (file_printf(ms, m->desc, p->s) == -1)
+                       return -1;
                t = m->offset + strlen(p->s);
                break;
 
        default:
-               error("invalid m->type (%d) in mprint().\n", m->type);
-               /*NOTREACHED*/
+               file_error(ms, "invalid m->type (%d) in mprint()", m->type);
+               return -1;
        }
        return(t);
 }
@@ -280,8 +316,8 @@ mprint(union VALUETYPE *p, struct magic *m)
  * While we're here, let's apply the mask operation
  * (unless you have a better idea)
  */
-static int
-mconvert(union VALUETYPE *p, struct magic *m)
+private int
+mconvert(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
 {
        switch (m->type) {
        case BYTE:
@@ -541,38 +577,43 @@ mconvert(union VALUETYPE *p, struct magic *m)
        case REGEX:
                return 1;
        default:
-               error("invalid type %d in mconvert().\n", m->type);
+               file_error(ms, "invalid type %d in mconvert()", m->type);
                return 0;
        }
 }
 
 
-static void
-mdebug(int32_t offset, char *str, int len)
+private void
+mdebug(int32_t offset, const char *str, size_t len)
 {
        (void) fprintf(stderr, "mget @%d: ", offset);
-       showstr(stderr, (char *) str, len);
+       file_showstr(stderr, str, len);
        (void) fputc('\n', stderr);
        (void) fputc('\n', stderr);
 }
 
-static int
-mget(union VALUETYPE *p, unsigned char *s, struct magic *m, int nbytes)
+private int
+mget(struct magic_set *ms, union VALUETYPE *p, const unsigned char *s,
+    struct magic *m, size_t nbytes)
 {
        int32_t offset = m->offset;
 
        if (m->type == REGEX) {
-             /*
-              * offset is interpreted as last line to search,
-              * (starting at 1), not as bytes-from start-of-file
-              */
-             unsigned char *last = NULL;
-             p->buf = (char *)s;
-             for (; offset && (s = (unsigned char *)strchr(s, '\n')) != NULL;
-                 offset--, s++)
-                   last = s;
-             if (last != NULL)
-               *last = '\0';
+               /*
+                * offset is interpreted as last line to search,
+                * (starting at 1), not as bytes-from start-of-file
+                */
+               unsigned char *b, *last = NULL;
+               if ((b = p->buf = strdup(s)) == NULL) {
+                       file_oomem(ms);
+                       return -1;
+               }
+
+               for (; offset && (b = (unsigned char *)strchr(b, '\n')) != NULL;
+                   offset--, s++)
+                       last = b;
+               if (last != NULL)
+                       *last = '\0';
        } else if (offset + sizeof(union VALUETYPE) <= nbytes)
                memcpy(p, s + offset, sizeof(union VALUETYPE));
        else {
@@ -586,9 +627,9 @@ mget(union VALUETYPE *p, unsigned char *s, struct magic *m, int nbytes)
                        memcpy(p, s + offset, have);
        }
 
-       if (debug) {
+       if ((ms->flags & MAGIC_DEBUG) != 0) {
                mdebug(offset, (char *) p, sizeof(union VALUETYPE));
-               mdump(m);
+               file_mdump(m);
        }
 
        if (m->flag & INDIR) {
@@ -920,25 +961,24 @@ mget(union VALUETYPE *p, unsigned char *s, struct magic *m, int nbytes)
 
                memcpy(p, s + offset, sizeof(union VALUETYPE));
 
-               if (debug) {
+               if ((ms->flags & MAGIC_DEBUG) != 0) {
                        mdebug(offset, (char *) p, sizeof(union VALUETYPE));
-                       mdump(m);
+                       file_mdump(m);
                }
        }
-       if (!mconvert(p, m))
+       if (!mconvert(ms, p, m))
          return 0;
        return 1;
 }
 
-static int
-mcheck(union VALUETYPE *p, struct magic *m)
+private int
+mcheck(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
 {
        uint32_t l = m->value.l;
        uint32_t v;
        int matched;
 
        if ( (m->value.s[0] == 'x') && (m->value.s[1] == '\0') ) {
-               fprintf(stderr, "BOINK");
                return 1;
        }
 
@@ -1021,38 +1061,41 @@ mcheck(union VALUETYPE *p, struct magic *m)
 
                rc = regcomp(&rx, m->value.s, REG_EXTENDED|REG_NOSUB);
                if (rc) {
+                       free(p->buf);
                        regerror(rc, &rx, errmsg, sizeof(errmsg));
-                       error("regex error %d, (%s)\n", rc, errmsg);
+                       file_error(ms, "regex error %d, (%s)", rc, errmsg);
+                       return -1;
                } else {
                        rc = regexec(&rx, p->buf, 0, 0, 0);
+                       free(p->buf);
                        return !rc;
                }
        }
        default:
-               error("invalid type %d in mcheck().\n", m->type);
-               return 0;/*NOTREACHED*/
+               file_error(ms, "invalid type %d in mcheck()", m->type);
+               return -1;
        }
 
        if(m->type != STRING && m->type != PSTRING)
-               v = signextend(m, v);
+               v = file_signextend(ms, m, v);
 
        switch (m->reln) {
        case 'x':
-               if (debug)
+               if ((ms->flags & MAGIC_DEBUG) != 0)
                        (void) fprintf(stderr, "%u == *any* = 1\n", v);
                matched = 1;
                break;
 
        case '!':
                matched = v != l;
-               if (debug)
+               if ((ms->flags & MAGIC_DEBUG) != 0)
                        (void) fprintf(stderr, "%u != %u = %d\n",
                                       v, l, matched);
                break;
 
        case '=':
                matched = v == l;
-               if (debug)
+               if ((ms->flags & MAGIC_DEBUG) != 0)
                        (void) fprintf(stderr, "%u == %u = %d\n",
                                       v, l, matched);
                break;
@@ -1060,13 +1103,13 @@ mcheck(union VALUETYPE *p, struct magic *m)
        case '>':
                if (m->flag & UNSIGNED) {
                        matched = v > l;
-                       if (debug)
+                       if ((ms->flags & MAGIC_DEBUG) != 0)
                                (void) fprintf(stderr, "%u > %u = %d\n",
                                               v, l, matched);
                }
                else {
                        matched = (int32_t) v > (int32_t) l;
-                       if (debug)
+                       if ((ms->flags & MAGIC_DEBUG) != 0)
                                (void) fprintf(stderr, "%d > %d = %d\n",
                                               v, l, matched);
                }
@@ -1075,13 +1118,13 @@ mcheck(union VALUETYPE *p, struct magic *m)
        case '<':
                if (m->flag & UNSIGNED) {
                        matched = v < l;
-                       if (debug)
+                       if ((ms->flags & MAGIC_DEBUG) != 0)
                                (void) fprintf(stderr, "%u < %u = %d\n",
                                               v, l, matched);
                }
                else {
                        matched = (int32_t) v < (int32_t) l;
-                       if (debug)
+                       if ((ms->flags & MAGIC_DEBUG) != 0)
                                (void) fprintf(stderr, "%d < %d = %d\n",
                                               v, l, matched);
                }
@@ -1089,22 +1132,22 @@ mcheck(union VALUETYPE *p, struct magic *m)
 
        case '&':
                matched = (v & l) == l;
-               if (debug)
+               if ((ms->flags & MAGIC_DEBUG) != 0)
                        (void) fprintf(stderr, "((%x & %x) == %x) = %d\n",
                                       v, l, l, matched);
                break;
 
        case '^':
                matched = (v & l) != l;
-               if (debug)
+               if ((ms->flags & MAGIC_DEBUG) != 0)
                        (void) fprintf(stderr, "((%x & %x) != %x) = %d\n",
                                       v, l, l, matched);
                break;
 
        default:
                matched = 0;
-               error("mcheck: can't happen: invalid relation %d.\n", m->reln);
-               break;/*NOTREACHED*/
+               file_error(ms, "can't happen: invalid relation `%c'", m->reln);
+               return -1;
        }
 
        return matched;