summaryrefslogtreecommitdiff
path: root/src/apprentice.c
diff options
context:
space:
mode:
authorChristos Zoulas <christos@zoulas.com>2014-08-04 06:19:44 +0000
committerChristos Zoulas <christos@zoulas.com>2014-08-04 06:19:44 +0000
commit29e765dd0b4ae7a3024390e739234284873e1acf (patch)
tree5e53d2304e45ab09e402106b4201d2228f224d87 /src/apprentice.c
parent02c79ae3c71c2ec8e665ce36f266f157c06122fc (diff)
downloadfile-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.c140
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;
}
/*