*/
#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) && \
#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;
}
magicfile = argv[1];
- exit(apprentice(magicfile, COMPILE));
+ exit(apprentice(magicfile, COMPILE, MAGIC_CHECK));
}
#endif /* COMPILE_ONLY */
/*
* 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;
/*
* 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) {
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;
/*
* 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;
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)
/* 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) {
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++;
else
t = l;
if (*t++ != ')')
- magwarn("missing ')' in indirect offset");
+ if (ms->flags & MAGIC_CHECK)
+ file_magwarn("missing ')' in indirect offset");
l = t;
}
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" */
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;
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;
}
}
}
EATAB;
- if (getvalue(m, &l))
+ if (getvalue(ms, m, &l))
return -1;
/*
* TODO finish this macro and start using it!
#ifndef COMPILE_ONLY
if (action == CHECK) {
- mdump(m);
+ file_mdump(m);
}
#endif
++(*nmagicp); /* make room for next */
* 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;
* 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;
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++) {
/* Single hex char to int; -1 if not a hex char. */
-static int
+private int
hextoint(int c)
{
if (!isascii((unsigned char) 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;
/*
* eatsize(): Eat the size spec from a number [eg. 10UL]
*/
-static void
+private void
eatsize(char **p)
{
char *l = *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)
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
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;
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;
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;
}
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;
/*
* swap a short
*/
-static uint16_t
+private uint16_t
swap2(uint16_t sv)
{
uint16_t rv;
/*
* swap an int
*/
-static uint32_t
+private uint32_t
swap4(uint32_t sv)
{
uint32_t rv;
/*
* 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);
* 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>
#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;
#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;
* 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;
}
i = 0;
while (i < ulen) {
- int end;
+ size_t end;
/*
* skip past any leading space
* 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;
}
}
- 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,
*/
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;
#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 */
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;
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;
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;
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;
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;
* 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,
'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
* 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,
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;
* 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];
{ "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;
/*
* `safe' read for sockets and pipes.
*/
-static int
+private int
sread(int fd, void *buf, size_t n)
{
int rv;
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;
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)
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;
}
/*
* 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;
}
#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;
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;
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;
}
}
#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];
#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 */
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]);
* 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)
#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 */
#endif
#ifdef __EMX__
-static char *apptypeName = NULL;
+private char *apptypeName = NULL;
int os2_apptype (const char *fn, char *buf, int nb);
#endif /* __EMX__ */
#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},
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;
separator = *optarg;
break;
case 'i':
- iflag++;
+ flags |= MAGIC_MIME;
if ((mime = malloc(strlen(magicfile) + 6)) != NULL) {
(void)strcpy(mime, magicfile);
(void)strcat(mime, ".mime");
++nopad;
break;
case 's':
- sflag++;
+ flags |= MAGIC_DEVICES;
break;
case 'v':
(void) fprintf(stdout, "%s-%d.%d\n", progname,
magicfile);
return 1;
case 'z':
- zflag++;
+ flags |= MAGIC_COMPRESS;
break;
#ifdef S_IFLNK
case 'L':
- ++lflag;
+ flags |= MAGIC_SYMLINK;
break;
#endif
case '?':
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) {
}
+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];
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) {
(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
/*
* 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)
* byteconv2
* Same as byteconv4, but for shorts
*/
-static short
+private short
byteconv2(int from, int same, int big_endian)
{
if (same)
}
#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(
" 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"
/*
* 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
/* 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;
static const char *rcsid(const char *p) { \
return rcsid(p = id); \
}
+#else
#endif /* __file_h__ */
*/
#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;
* 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:
* 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
* 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
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 */
/* 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;
}
}
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;
#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*/
}
* 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;
* 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
* 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;
*
* Result is -1 if the field is invalid (all blank, or nonoctal).
*/
-static int
+private int
from_oct(int digs, char *where)
{
int value;
*
* 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 $
*/
/*
#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++" },
#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.
*
*/
+
*/
#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),
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);
}
#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;
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;
*rt = '\0';
return pp;
}
-#endif
#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 {
return value;
}
-static uint32_t
+private uint32_t
getu32(int swap, uint32_t value)
{
union {
return value;
}
-static uint64_t
+private uint64_t
getu64(int swap, uint64_t value)
{
union {
#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;
* 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;
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;
}
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
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;
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;
}
#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;
* 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
*/
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;
/*
* 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:
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;
}
/*
* 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:
* 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;
* 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
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];
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
-/* $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.
*/
#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
* 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;
* 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.
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 ;
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 {
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;
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);
}
* 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:
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 {
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) {
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;
}
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;
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);
}
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);
}
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;