From 29e765dd0b4ae7a3024390e739234284873e1acf Mon Sep 17 00:00:00 2001 From: Christos Zoulas Date: Mon, 4 Aug 2014 06:19:44 +0000 Subject: [PATCH] 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. --- ChangeLog | 4 ++ doc/libmagic.man | 19 ++++++- src/apprentice.c | 140 +++++++++++++++++++++++++++++++++++++++-------- src/file.h | 4 +- src/magic.c | 16 +++++- src/magic.h.in | 2 + 6 files changed, 157 insertions(+), 28 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6722e33a..c0e7273c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2014-08-04 9:18 Christos Zoulas + + * add magic_load_buffers from Brooks Davis + 2014-07-24 16:40 Christos Zoulas * add thumbs.db support diff --git a/doc/libmagic.man b/doc/libmagic.man index ee9cdb28..1c145638 100644 --- a/doc/libmagic.man +++ b/doc/libmagic.man @@ -1,4 +1,4 @@ -.\" $File: libmagic.man,v 1.28 2014/03/02 14:47:16 christos Exp $ +.\" $File: libmagic.man,v 1.29 2014/08/04 06:19:44 christos Exp $ .\" .\" Copyright (c) Christos Zoulas 2003. .\" All Rights Reserved. @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd January 6, 2012 +.Dd August 4, 2014 .Dt LIBMAGIC 3 .Os .Sh NAME @@ -71,6 +71,8 @@ .Ft int .Fn magic_load "magic_t cookie" "const char *filename" .Ft int +.Fn magic_load_buffers "magic_t cookie" "void **buffers" "size_t *sizes" "size_t nbuffers" +.Ft int .Fn magic_version "void" .Sh DESCRIPTION These functions @@ -253,6 +255,19 @@ adds to the database filename as appropriate. .Pp The +.Fn magic_load_buffers +function takes an array of size +.Fa nbuffers +of +.Fa buffers +with a respective size for each in the array of +.Fa sizes +loaded with the contents of the magic databases from the filesystem. +This function can be used in environment where the magic library does +not have direct access to the filesystem, but can access the magic +database via shared memory or other IPC means. +.Pp +The .Fn magic_version command returns the version number of this library which is compiled into the shared library using the constant 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) @@ -2693,6 +2751,28 @@ eatsize(const char **p) *p = l; } +/* + * 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; } /* diff --git a/src/file.h b/src/file.h index 67a25680..06c7abef 100644 --- a/src/file.h +++ b/src/file.h @@ -27,7 +27,7 @@ */ /* * file.h - definitions for file(1) program - * @(#)$File: file.h,v 1.152 2014/06/03 19:01:34 christos Exp $ + * @(#)$File: file.h,v 1.153 2014/08/04 06:19:44 christos Exp $ */ #ifndef __file_h__ @@ -442,6 +442,8 @@ protected int file_is_tar(struct magic_set *, const unsigned char *, size_t); protected int file_softmagic(struct magic_set *, const unsigned char *, size_t, size_t, int, int); protected int file_apprentice(struct magic_set *, const char *, int); +protected int buffer_apprentice(struct magic_set *, struct magic **, + size_t *, size_t); protected int file_magicfind(struct magic_set *, const char *, struct mlist *); protected uint64_t file_signextend(struct magic_set *, struct magic *, uint64_t); diff --git a/src/magic.c b/src/magic.c index e4bd12ba..371167f5 100644 --- a/src/magic.c +++ b/src/magic.c @@ -33,7 +33,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: magic.c,v 1.84 2014/05/14 23:15:42 christos Exp $") +FILE_RCSID("@(#)$File: magic.c,v 1.85 2014/08/04 06:19:44 christos Exp $") #endif /* lint */ #include "magic.h" @@ -257,6 +257,20 @@ magic_load(struct magic_set *ms, const char *magicfile) return file_apprentice(ms, magicfile, FILE_LOAD); } +#ifndef COMPILE_ONLY +/* + * Install a set of compiled magic buffers. + */ +public int +magic_load_buffers(struct magic_set *ms, void **bufs, size_t *sizes, + size_t nbufs) +{ + if (ms == NULL) + return -1; + return buffer_apprentice(ms, (struct magic **)bufs, sizes, nbufs); +} +#endif + public int magic_compile(struct magic_set *ms, const char *magicfile) { diff --git a/src/magic.h.in b/src/magic.h.in index 86fc41b7..4a357052 100644 --- a/src/magic.h.in +++ b/src/magic.h.in @@ -96,6 +96,8 @@ int magic_setflags(magic_t, int); int magic_version(void); int magic_load(magic_t, const char *); +int magic_load_buffers(struct magic_set *, void **, size_t *, size_t); + int magic_compile(magic_t, const char *); int magic_check(magic_t, const char *); int magic_list(magic_t, const char *); -- 2.49.0