diff options
Diffstat (limited to 'contrib/file/apprentice.c')
-rw-r--r-- | contrib/file/apprentice.c | 117 |
1 files changed, 90 insertions, 27 deletions
diff --git a/contrib/file/apprentice.c b/contrib/file/apprentice.c index 714c86c..ba7f783 100644 --- a/contrib/file/apprentice.c +++ b/contrib/file/apprentice.c @@ -30,6 +30,11 @@ */ #include "file.h" + +#ifndef lint +FILE_RCSID("@(#)$File: apprentice.c,v 1.147 2009/02/03 20:27:51 christos Exp $") +#endif /* lint */ + #include "magic.h" #include "patchlevel.h" #include <stdlib.h> @@ -40,18 +45,11 @@ #include <assert.h> #include <ctype.h> #include <fcntl.h> -#include <sys/stat.h> -#include <sys/param.h> #ifdef QUICK #include <sys/mman.h> #endif -#include <sys/types.h> #include <dirent.h> -#ifndef lint -FILE_RCSID("@(#)$File: apprentice.c,v 1.140 2008/07/20 04:02:15 christos Exp $") -#endif /* lint */ - #define EATAB {while (isascii((unsigned char) *l) && \ isspace((unsigned char) *l)) ++l;} #define LOWCASE(l) (isupper((unsigned char) (l)) ? \ @@ -106,7 +104,7 @@ private void bs1(struct magic *); private uint16_t swap2(uint16_t); private uint32_t swap4(uint32_t); private uint64_t swap8(uint64_t); -private void mkdbname(const char *, char **, int); +private char *mkdbname(struct magic_set *, const char *, int); private int apprentice_map(struct magic_set *, struct magic **, uint32_t *, const char *); private int apprentice_compile(struct magic_set *, struct magic **, uint32_t *, @@ -115,8 +113,8 @@ private int check_format_type(const char *, int); private int check_format(struct magic_set *, struct magic *); private int get_op(char); private int parse_mime(struct magic_set *, struct magic_entry *, const char *); -private int parse_strength(struct magic_set *, struct magic_entry *, - const char *); +private int parse_strength(struct magic_set *, struct magic_entry *, const char *); +private int parse_apple(struct magic_set *, struct magic_entry *, const char *); private size_t maxmagic = 0; @@ -131,6 +129,7 @@ private struct { } bang[] = { #define DECLARE_FIELD(name) { # name, sizeof(# name) - 1, parse_ ## name } DECLARE_FIELD(mime), + DECLARE_FIELD(apple), DECLARE_FIELD(strength), #undef DECLARE_FIELD { NULL, 0, NULL } @@ -215,6 +214,9 @@ static const struct type_tbl_s { { XX("double"), FILE_DOUBLE, FILE_FMT_DOUBLE }, { XX("bedouble"), FILE_BEDOUBLE, FILE_FMT_DOUBLE }, { XX("ledouble"), FILE_LEDOUBLE, FILE_FMT_DOUBLE }, + { XX("leid3"), FILE_LEID3, FILE_FMT_NUM }, + { XX("beid3"), FILE_BEID3, FILE_FMT_NUM }, + { XX("indirect"), FILE_INDIRECT, FILE_FMT_NONE }, { XX_NULL, FILE_INVALID, FILE_FMT_NONE }, # undef XX # undef XX_NULL @@ -590,7 +592,8 @@ set_test_type(struct magic *mstart, struct magic *m) case FILE_SEARCH: #ifndef COMPILE_ONLY /* binary test if pattern is not text */ - if (file_looks_utf8(m->value.us, m->vallen, NULL, NULL) <= 0) + if (file_looks_utf8(m->value.us, (size_t)m->vallen, NULL, + NULL) <= 0) mstart->flag |= BINTEST; #endif break; @@ -706,6 +709,8 @@ apprentice_load(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp, (void)fprintf(stderr, "%s\n", usg_hdr); /* load directory or file */ + /* FIXME: Read file names and sort them to prevent + non-determinism. See Debian bug #488562. */ if (stat(fn, &st) == 0 && S_ISDIR(st.st_mode)) { dir = opendir(fn); if (dir) { @@ -870,6 +875,7 @@ file_signextend(struct magic_set *ms, struct magic *m, uint64_t v) case FILE_REGEX: case FILE_SEARCH: case FILE_DEFAULT: + case FILE_INDIRECT: break; default: if (ms->flags & MAGIC_CHECK) @@ -1186,6 +1192,12 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp, case 'G': m->in_type = FILE_BEDOUBLE; break; + case 'i': + m->in_type = FILE_LEID3; + break; + case 'I': + m->in_type = FILE_BEID3; + break; default: if (ms->flags & MAGIC_CHECK) file_magwarn(ms, @@ -1475,6 +1487,38 @@ out: } /* + * Parse an Apple CREATOR/TYPE annotation from magic file and put it into magic[index - 1] + */ +private int +parse_apple(struct magic_set *ms, struct magic_entry *me, const char *line) +{ + size_t i; + const char *l = line; + struct magic *m = &me->mp[me->cont_count == 0 ? 0 : me->cont_count - 1]; + + if (m->apple[0] != '\0') { + file_magwarn(ms, "Current entry already has a APPLE type `%.8s'," + " new type `%s'", m->mimetype, l); + return -1; + } + + EATAB; + for (i = 0; *l && ((isascii((unsigned char)*l) && isalnum((unsigned char)*l)) + || strchr("-+/.", *l)) && i < sizeof(m->apple); m->apple[i++] = *l++) + continue; + if (i == sizeof(m->apple) && *l) { + if (ms->flags & MAGIC_CHECK) + file_magwarn(ms, "APPLE type `%s' truncated %zu", + line, i); + } + + if (i > 0) + return 0; + else + return -1; +} + +/* * parse a MIME annotation line from magic file, put into magic[index - 1] * if valid */ @@ -1492,10 +1536,8 @@ parse_mime(struct magic_set *ms, struct magic_entry *me, const char *line) } EATAB; - for (i = 0; - *l && ((isascii((unsigned char)*l) && isalnum((unsigned char)*l)) - || strchr("-+/.", *l)) && i < sizeof(m->mimetype); - m->mimetype[i++] = *l++) + for (i = 0; *l && ((isascii((unsigned char)*l) && isalnum((unsigned char)*l)) + || strchr("-+/.", *l)) && i < sizeof(m->mimetype); m->mimetype[i++] = *l++) continue; if (i == sizeof(m->mimetype)) { m->desc[sizeof(m->mimetype) - 1] = '\0'; @@ -2016,7 +2058,7 @@ apprentice_map(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp, char *dbname = NULL; void *mm = NULL; - mkdbname(fn, &dbname, 0); + dbname = mkdbname(ms, fn, 0); if (dbname == NULL) goto error2; @@ -2113,7 +2155,7 @@ apprentice_compile(struct magic_set *ms, struct magic **magicp, char *dbname; int rv = -1; - mkdbname(fn, &dbname, 1); + dbname = mkdbname(ms, fn, 1); if (dbname == NULL) goto out; @@ -2151,24 +2193,45 @@ private const char ext[] = ".mgc"; /* * make a dbname */ -private void -mkdbname(const char *fn, char **buf, int strip) +private char * +mkdbname(struct magic_set *ms, const char *fn, int strip) { - const char *p; + const char *p, *q; + char *buf; + if (strip) { if ((p = strrchr(fn, '/')) != NULL) fn = ++p; } - if ((p = strstr(fn, ext)) != NULL && p[sizeof(ext) - 1] == '\0') - *buf = strdup(fn); - else - (void)asprintf(buf, "%s%s", fn, ext); + for (q = fn; *q; q++) + continue; + /* Look for .mgc */ + for (p = ext + sizeof(ext) - 1; p >= ext && q >= fn; p--, q--) + if (*p != *q) + break; - if (buf && *buf && strlen(*buf) > MAXPATHLEN) { - free(*buf); - *buf = NULL; + /* Did not find .mgc, restore q */ + if (p >= ext) + while (*q) + q++; + + q++; + /* Compatibility with old code that looked in .mime */ + if (ms->flags & MAGIC_MIME) { + asprintf(&buf, "%.*s.mime%s", (int)(q - fn), fn, ext); + if (access(buf, R_OK) != -1) { + ms->flags &= MAGIC_MIME_TYPE; + return buf; + } + free(buf); } + asprintf(&buf, "%.*s%s", (int)(q - fn), fn, ext); + + /* Compatibility with old code that looked in .mime */ + if (strstr(p, ".mime") != NULL) + ms->flags &= MAGIC_MIME_TYPE; + return buf; } /* |