diff options
author | Christos Zoulas <christos@zoulas.com> | 2014-08-04 06:19:44 +0000 |
---|---|---|
committer | Christos Zoulas <christos@zoulas.com> | 2014-08-04 06:19:44 +0000 |
commit | 29e765dd0b4ae7a3024390e739234284873e1acf (patch) | |
tree | 5e53d2304e45ab09e402106b4201d2228f224d87 /src/apprentice.c | |
parent | 02c79ae3c71c2ec8e665ce36f266f157c06122fc (diff) | |
download | file-git-29e765dd0b4ae7a3024390e739234284873e1acf.tar.gz |
PR/367: Brooks Davis: Add magic_load_buffers to provide a means to load the
magic database on environments that have no direct access to the filesystem.
Diffstat (limited to 'src/apprentice.c')
-rw-r--r-- | src/apprentice.c | 140 |
1 files changed, 116 insertions, 24 deletions
diff --git a/src/apprentice.c b/src/apprentice.c index 715c26ec..cdb830c8 100644 --- a/src/apprentice.c +++ b/src/apprentice.c @@ -32,7 +32,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: apprentice.c,v 1.212 2014/06/26 12:53:36 christos Exp $") +FILE_RCSID("@(#)$File: apprentice.c,v 1.213 2014/08/04 06:19:44 christos Exp $") #endif /* lint */ #include "magic.h" @@ -86,6 +86,10 @@ FILE_RCSID("@(#)$File: apprentice.c,v 1.212 2014/06/26 12:53:36 christos Exp $") #define ALLOC_CHUNK (size_t)10 #define ALLOC_INCR (size_t)200 +#define MAP_TYPE_MMAP 0 +#define MAP_TYPE_MALLOC 1 +#define MAP_TYPE_USER 2 + struct magic_entry { struct magic *mp; uint32_t cont_count; @@ -101,6 +105,7 @@ struct magic_entry_set { struct magic_map { void *p; size_t len; + int type; struct magic *magic[MAGIC_SETS]; uint32_t nmagic[MAGIC_SETS]; }; @@ -131,7 +136,10 @@ private uint16_t swap2(uint16_t); private uint32_t swap4(uint32_t); private uint64_t swap8(uint64_t); private char *mkdbname(struct magic_set *, const char *, int); +private struct magic_map *apprentice_buf(struct magic_set *, struct magic *, + size_t); private struct magic_map *apprentice_map(struct magic_set *, const char *); +private int check_buffer(struct magic_set *, struct magic_map *, const char *); private void apprentice_unmap(struct magic_map *); private int apprentice_compile(struct magic_set *, struct magic_map *, const char *); @@ -518,9 +526,9 @@ apprentice_unmap(struct magic_map *map) { if (map == NULL) return; - if (map->p != NULL) { + if (map->p != NULL && map->type != MAP_TYPE_USER) { #ifdef QUICK - if (map->len) + if (map->type == MAP_TYPE_MMAP) (void)munmap(map->p, map->len); else #endif @@ -562,6 +570,56 @@ mlist_free(struct mlist *mlist) free(ml); } +#ifndef COMPILE_ONLY +/* void **bufs: an array of compiled magic files */ +protected int +buffer_apprentice(struct magic_set *ms, struct magic **bufs, + size_t *sizes, size_t nbufs) +{ + size_t i; + struct mlist *ml; + struct magic_map *map; + + if (nbufs == 0) + return -1; + + if (ms->mlist[0] != NULL) + file_reset(ms); + + init_file_tables(); + + for (i = 0; i < MAGIC_SETS; i++) { + mlist_free(ms->mlist[i]); + if ((ms->mlist[i] = mlist_alloc()) == NULL) { + file_oomem(ms, sizeof(*ms->mlist[i])); + if (i != 0) { + --i; + do + mlist_free(ms->mlist[i]); + while (i != 0); + } + return -1; + } + } + + for (i = 0; i < nbufs; i++) { + map = apprentice_buf(ms, bufs[i], sizes[i]); + if (map == NULL) + return -1; + + for (i = 0; i < MAGIC_SETS; i++) { + if (add_mlist(ms->mlist[i], map, i) == -1) { + file_oomem(ms, sizeof(*ml)); + apprentice_unmap(map); + return -1; + } + } + } + + return 0; +} +#endif + /* const char *fn: list of magic files and directories */ protected int file_apprentice(struct magic_set *ms, const char *fn, int action) @@ -2694,6 +2752,28 @@ eatsize(const char **p) } /* + * handle a buffer containging a compiled file. + */ +private struct magic_map * +apprentice_buf(struct magic_set *ms, struct magic *buf, size_t len) +{ + struct magic_map *map; + + if ((map = CAST(struct magic_map *, calloc(1, sizeof(*map)))) == NULL) { + file_oomem(ms, sizeof(*map)); + return NULL; + } + map->len = len; + map->p = buf; + map->type = MAP_TYPE_USER; + if (check_buffer(ms, map, "buffer") != 0) { + apprentice_unmap(map); + return NULL; + } + return map; +} + +/* * handle a compiled file. */ @@ -2702,12 +2782,8 @@ apprentice_map(struct magic_set *ms, const char *fn) { int fd; struct stat st; - uint32_t *ptr; - uint32_t version, entries, nentries; - int needsbyteswap; char *dbname = NULL; struct magic_map *map; - size_t i; fd = -1; if ((map = CAST(struct magic_map *, calloc(1, sizeof(*map)))) == NULL) { @@ -2739,6 +2815,7 @@ apprentice_map(struct magic_set *ms, const char *fn) file_error(ms, errno, "cannot map `%s'", dbname); goto error; } + map->type = MAP_TYPE_MMAP; #else if ((map->p = CAST(void *, malloc(map->len))) == NULL) { file_oomem(ms, map->len); @@ -2748,16 +2825,39 @@ apprentice_map(struct magic_set *ms, const char *fn) file_badread(ms); goto error; } - map->len = 0; + map->type = MAP_TYPE_MALLOC; #define RET 1 #endif (void)close(fd); fd = -1; + + if (check_buffer(ms, map, dbname) != 0) + goto error; + + free(dbname); + return map; + +error: + if (fd != -1) + (void)close(fd); + apprentice_unmap(map); + free(dbname); + return NULL; +} + +private int +check_buffer(struct magic_set *ms, struct magic_map *map, const char *dbname) +{ + uint32_t *ptr; + uint32_t entries, nentries; + uint32_t version; + int i, needsbyteswap; + ptr = CAST(uint32_t *, map->p); if (*ptr != MAGICNO) { if (swap4(*ptr) != MAGICNO) { file_error(ms, 0, "bad magic in `%s'", dbname); - goto error; + return -1; } needsbyteswap = 1; } else @@ -2770,15 +2870,15 @@ apprentice_map(struct magic_set *ms, const char *fn) file_error(ms, 0, "File %s supports only version %d magic " "files. `%s' is version %d", VERSION, VERSIONNO, dbname, version); - goto error; + return -1; } - entries = (uint32_t)(st.st_size / sizeof(struct magic)); - if ((off_t)(entries * sizeof(struct magic)) != st.st_size) { + entries = (uint32_t)(map->len / sizeof(struct magic)); + if ((entries * sizeof(struct magic)) != map->len) { file_error(ms, 0, "Size of `%s' %" INT64_T_FORMAT "u is not " "a multiple of %" SIZE_T_FORMAT "u", - dbname, (unsigned long long)st.st_size, + dbname, (unsigned long long)map->len, sizeof(struct magic)); - goto error; + return -1; } map->magic[0] = CAST(struct magic *, map->p) + 1; nentries = 0; @@ -2794,20 +2894,12 @@ apprentice_map(struct magic_set *ms, const char *fn) if (entries != nentries + 1) { file_error(ms, 0, "Inconsistent entries in `%s' %u != %u", dbname, entries, nentries + 1); - goto error; + return -1; } if (needsbyteswap) for (i = 0; i < MAGIC_SETS; i++) byteswap(map->magic[i], map->nmagic[i]); - free(dbname); - return map; - -error: - if (fd != -1) - (void)close(fd); - apprentice_unmap(map); - free(dbname); - return NULL; + return -1; } /* |