⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 apprentice.c

📁 sleuthit-2.09 一个磁盘的工具集
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) Ian F. Darwin 1986-1995. * Software written by Ian F. Darwin and others; * maintained 1995-present by Christos Zoulas and others. *  * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice immediately at the beginning of the file, without modification, *    this list of conditions, and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. *   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. *//* * apprentice - make one pass through /etc/magic, learning its secrets. */#include "file.h"#include "magic.h"#include <stdlib.h>#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include <string.h>#include <assert.h>#include <ctype.h>#include <fcntl.h>#include <sys/stat.h>#include <sys/param.h>#ifdef QUICK#include <sys/mman.h>#endif#ifndef	lintFILE_RCSID("@(#)$File: apprentice.c,v 1.105 2007/05/16 20:51:40 christos Exp $")#endif	/* lint */#define	EATAB {while (isascii((unsigned char) *l) && \		      isspace((unsigned char) *l))  ++l;}#define LOWCASE(l) (isupper((unsigned char) (l)) ? \			tolower((unsigned char) (l)) : (l))/* * Work around a bug in headers on Digital Unix. * At least confirmed for: OSF1 V4.0 878 */#if defined(__osf__) && defined(__DECC)#ifdef MAP_FAILED#undef MAP_FAILED#endif#endif#ifndef MAP_FAILED#define MAP_FAILED (void *) -1#endif#ifndef MAP_FILE#define MAP_FILE 0#endif#ifndef MAXPATHLEN#define MAXPATHLEN	1024#endifstruct magic_entry {	struct magic *mp;		uint32_t cont_count;	uint32_t max_count;};int file_formats[FILE_NAMES_SIZE];const size_t file_nformats = FILE_NAMES_SIZE;const char *file_names[FILE_NAMES_SIZE];const size_t file_nnames = FILE_NAMES_SIZE;private int getvalue(struct magic_set *ms, struct magic *, const char **, int);private int hextoint(int);private const char *getstr(struct magic_set *, const char *, char *, int,    int *, int);private int parse(struct magic_set *, struct magic_entry **, uint32_t *,    const char *, size_t, int);private void eatsize(const char **);private int apprentice_1(struct magic_set *, const char *, int, struct mlist *);private size_t apprentice_magic_strength(const struct magic *);private int apprentice_sort(const void *, const void *);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 uint64_t swap8(uint64_t);private char *mkdbname(const char *, char *, size_t, 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 *,    const char *);private int check_format_type(const char *, int);private int check_format(struct magic_set *, struct magic *);private size_t maxmagic = 0;private size_t magicsize = sizeof(struct magic);#ifdef COMPILE_ONLYint main(int, char *[]);intmain(int argc, char *argv[]){	int ret;	struct magic_set *ms;	char *progname;	if ((progname = strrchr(argv[0], '/')) != NULL)		progname++;	else		progname = argv[0];	if (argc != 2) {		(void)fprintf(stderr, "Usage: %s file\n", progname);		return 1;	}	if ((ms = magic_open(MAGIC_CHECK)) == NULL) {		(void)fprintf(stderr, "%s: %s\n", progname, strerror(errno));		return 1;	}	ret = magic_compile(ms, argv[1]) == -1 ? 1 : 0;	if (ret == 1)		(void)fprintf(stderr, "%s: %s\n", progname, magic_error(ms));	magic_close(ms);	return ret;}#endif /* COMPILE_ONLY */static const struct type_tbl_s {	const char *name;	const size_t len;	const int type;	const int format;} type_tbl[] = {# define XX(s)		s, (sizeof(s) - 1)# define XX_NULL	NULL, 0	{ XX("byte"),		FILE_BYTE,		FILE_FMT_NUM },	{ XX("short"),		FILE_SHORT,		FILE_FMT_NUM },	{ XX("default"),	FILE_DEFAULT,		FILE_FMT_STR },	{ XX("long"),		FILE_LONG,		FILE_FMT_NUM },	{ XX("string"),		FILE_STRING,		FILE_FMT_STR },	{ XX("date"),		FILE_DATE,		FILE_FMT_STR },	{ XX("beshort"),	FILE_BESHORT,		FILE_FMT_NUM },	{ XX("belong"),		FILE_BELONG,		FILE_FMT_NUM },	{ XX("bedate"),		FILE_BEDATE,		FILE_FMT_STR },	{ XX("leshort"),	FILE_LESHORT,		FILE_FMT_NUM },	{ XX("lelong"),		FILE_LELONG,		FILE_FMT_NUM },	{ XX("ledate"),		FILE_LEDATE,		FILE_FMT_STR },	{ XX("pstring"),	FILE_PSTRING,		FILE_FMT_STR },	{ XX("ldate"),		FILE_LDATE,		FILE_FMT_STR },	{ XX("beldate"),	FILE_BELDATE,		FILE_FMT_STR },	{ XX("leldate"),	FILE_LELDATE,		FILE_FMT_STR },	{ XX("regex"),		FILE_REGEX,		FILE_FMT_STR },	{ XX("bestring16"),	FILE_BESTRING16,	FILE_FMT_STR },	{ XX("lestring16"),	FILE_LESTRING16,	FILE_FMT_STR },	{ XX("search"),		FILE_SEARCH,		FILE_FMT_STR },	{ XX("medate"),		FILE_MEDATE,		FILE_FMT_STR },	{ XX("meldate"),	FILE_MELDATE,		FILE_FMT_STR },	{ XX("melong"),		FILE_MELONG,		FILE_FMT_NUM },	{ XX("quad"),		FILE_QUAD,		FILE_FMT_QUAD },	{ XX("lequad"),		FILE_LEQUAD,		FILE_FMT_QUAD },	{ XX("bequad"),		FILE_BEQUAD,		FILE_FMT_QUAD },	{ XX("qdate"),		FILE_QDATE,		FILE_FMT_STR },	{ XX("leqdate"),	FILE_LEQDATE,		FILE_FMT_STR },	{ XX("beqdate"),	FILE_BEQDATE,		FILE_FMT_STR },	{ XX("qldate"),		FILE_QLDATE,		FILE_FMT_STR },	{ XX("leqldate"),	FILE_LEQLDATE,		FILE_FMT_STR },	{ XX("beqldate"),	FILE_BEQLDATE,		FILE_FMT_STR },	{ XX_NULL,		FILE_INVALID,		FILE_FMT_NONE },# undef XX# undef XX_NULL};private intget_type(const char *l, const char **t){	const struct type_tbl_s *p;	for (p = type_tbl; p->name; p++) {		if (strncmp(l, p->name, p->len) == 0) {			if (t)				*t = l + p->len;			break;		}	}	return p->type;}private voidinit_file_tables(void){	static int done = 0;	const struct type_tbl_s *p;	if (done)		return;	done++;	for (p = type_tbl; p->name; p++) {		assert(p->type < FILE_NAMES_SIZE);		file_names[p->type] = p->name;		file_formats[p->type] = p->format;	}}/* * Handle one file. */private intapprentice_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 (magicsize != FILE_MAGICSIZE) {		file_error(ms, 0, "magic element size %lu != %lu",		    (unsigned long)sizeof(*magic),		    (unsigned long)FILE_MAGICSIZE);		return -1;	}	if (action == FILE_COMPILE) {		rv = apprentice_file(ms, &magic, &nmagic, fn, action);		if (rv != 0)			return -1;		rv = apprentice_compile(ms, &magic, &nmagic, fn);		free(magic);		return rv;	}#ifndef COMPILE_ONLY	if ((rv = apprentice_map(ms, &magic, &nmagic, fn)) == -1) {		if (ms->flags & MAGIC_CHECK)			file_magwarn(ms, "using regular magic file `%s'", fn);		rv = apprentice_file(ms, &magic, &nmagic, fn, action);		if (rv != 0)			return -1;		mapped = 0;	}	mapped = rv;	     	if (magic == NULL || nmagic == 0) {		file_delmagic(magic, mapped, nmagic);		return -1;	}	if ((ml = malloc(sizeof(*ml))) == NULL) {		file_delmagic(magic, mapped, nmagic);		file_oomem(ms, sizeof(*ml));		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;	return 0;#endif /* COMPILE_ONLY */}protected voidfile_delmagic(struct magic *p, int type, size_t entries){	if (p == NULL)		return;	switch (type) {	case 2:		p--;		(void)munmap((void *)p, sizeof(*p) * (entries + 1));		break;	case 1:		p--;		/*FALLTHROUGH*/	case 0:		free(p);		break;	default:		abort();	}}/* const char *fn: list of magic files */protected struct mlist *file_apprentice(struct magic_set *ms, const char *fn, int action){	char *p, *mfn, *afn = NULL;	int file_err, errs = -1;	struct mlist *mlist;	static const char mime[] = ".mime";	init_file_tables();	if (fn == NULL)		fn = getenv("MAGIC");	if (fn == NULL)		fn = MAGIC;	if ((mfn = strdup(fn)) == NULL) {		file_oomem(ms, strlen(fn));		return NULL;	}	fn = mfn;	if ((mlist = malloc(sizeof(*mlist))) == NULL) {		free(mfn);		file_oomem(ms, sizeof(*mlist));		return NULL;	}	mlist->next = mlist->prev = mlist;	while (fn) {		p = strchr(fn, PATHSEP);		if (p)			*p++ = '\0';		if (*fn == '\0')			break;		if (ms->flags & MAGIC_MIME) {			size_t len = strlen(fn) + sizeof(mime);			if ((afn = malloc(len)) == NULL) {				free(mfn);				free(mlist);				file_oomem(ms, len);				return NULL;			}			(void)strcpy(afn, fn);			(void)strcat(afn, mime);			fn = afn;		}		file_err = apprentice_1(ms, fn, action, mlist);		if (file_err > errs)			errs = file_err;		if (afn) {			free(afn);			afn = NULL;		}		fn = p;	}	if (errs == -1) {		free(mfn);		free(mlist);		mlist = NULL;		file_error(ms, 0, "could not find any magic files!");		return NULL;	}	free(mfn);	return mlist;}/* * Get weight of this magic entry, for sorting purposes. */private size_tapprentice_magic_strength(const struct magic *m){#define MULT 10	size_t val = 2 * MULT;	/* baseline strength */	switch (m->type) {	case FILE_DEFAULT:	/* make sure this sorts last */		return 0;	case FILE_BYTE:		val += 1 * MULT;		break;	case FILE_SHORT:	case FILE_LESHORT:	case FILE_BESHORT:		val += 2 * MULT;		break;	case FILE_LONG:	case FILE_LELONG:	case FILE_BELONG:	case FILE_MELONG:		val += 4 * MULT;		break;	case FILE_PSTRING:	case FILE_STRING:		val += m->vallen * MULT;		break;	case FILE_BESTRING16:	case FILE_LESTRING16:		val += m->vallen * MULT / 2;		break;	case FILE_SEARCH:	case FILE_REGEX:		val += m->vallen;		break;	case FILE_DATE:	case FILE_LEDATE:	case FILE_BEDATE:	case FILE_MEDATE:	case FILE_LDATE:	case FILE_LELDATE:	case FILE_BELDATE:	case FILE_MELDATE:		val += 4 * MULT;		break;	case FILE_QUAD:	case FILE_BEQUAD:	case FILE_LEQUAD:	case FILE_QDATE:	case FILE_LEQDATE:	case FILE_BEQDATE:	case FILE_QLDATE:	case FILE_LEQLDATE:	case FILE_BEQLDATE:		val += 8 * MULT;		break;	default:		val = 0;		(void)fprintf(stderr, "Bad type %d\n", m->type);		abort();	}	switch (m->reln) {	case 'x':	/* matches anything penalize */		val = 0;		break;	case '!':	case '=':	/* Exact match, prefer */		val += MULT;		break;	case '>':	case '<':	/* comparison match reduce strength */		val -= 2 * MULT;		break;	case '^':	case '&':	/* masking bits, we could count them too */		val -= MULT;		break;	default:		(void)fprintf(stderr, "Bad relation %c\n", m->reln);		abort();	}	if (val == 0)	/* ensure we only return 0 for FILE_DEFAULT */		val = 1;	return val;}/*   * Sort callback for sorting entries by "strength" (basically length) */private intapprentice_sort(const void *a, const void *b){	const struct magic_entry *ma = a;	const struct magic_entry *mb = b;	size_t sa = apprentice_magic_strength(ma->mp);	size_t sb = apprentice_magic_strength(mb->mp);	if (sa == sb)		return 0;	else if (sa > sb)		return -1;	else		return 1;}/* * parse from a file * const char *fn: name of magic file */private intapprentice_file(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,    const char *fn, int action){	private const char hdr[] =		"cont\toffset\ttype\topcode\tmask\tvalue\tdesc";	FILE *f;	char line[BUFSIZ+1];	int errs = 0;	struct magic_entry *marray;	uint32_t marraycount, i, mentrycount = 0;	size_t lineno = 0;	ms->flags |= MAGIC_CHECK;	/* Enable checks for parsed files */	f = fopen(ms->file = fn, "r");	if (f == NULL) {		if (errno != ENOENT)			file_error(ms, errno, "cannot read magic file `%s'",			    fn);		return -1;	}        maxmagic = MAXMAGIS;	if ((marray = calloc(maxmagic, sizeof(*marray))) == NULL) {		(void)fclose(f);		file_oomem(ms, maxmagic * sizeof(*marray));		return -1;	}	marraycount = 0;	/* print silly verbose header for USG compat. */	if (action == FILE_CHECK)		(void)fprintf(stderr, "%s\n", hdr);	/* read and parse this file */	for (ms->line = 1; fgets(line, BUFSIZ, f) != NULL; ms->line++) {		size_t len;		len = strlen(line);		if (len == 0) /* null line, garbage, etc */			continue;		if (line[len - 1] == '\n') {			lineno++;			line[len - 1] = '\0'; /* delete newline */		}		if (line[0] == '\0')	/* empty, do not parse */			continue;		if (line[0] == '#')	/* comment, do not parse */			continue;		if (parse(ms, &marray, &marraycount, line, lineno, action) != 0)			errs++;	}	(void)fclose(f);	if (errs)		goto out;#ifndef NOORDER	qsort(marray, marraycount, sizeof(*marray), apprentice_sort);	/*	 * Make sure that any level 0 "default" line is last (if one exists).	 */	for (i = 0; i < marraycount; i++) {		if (marray[i].mp->cont_level == 0 &&		    marray[i].mp->type == FILE_DEFAULT) {			while (++i < marraycount)				if (marray[i].mp->cont_level == 0)					break;			if (i != marraycount) {				ms->line = marray[i].mp->lineno; /* XXX - Ugh! */				file_magwarn(ms,				    "level 0 \"default\" did not sort last");			}			break;					    		}	}#endif	for (i = 0; i < marraycount; i++)		mentrycount += marray[i].cont_count;	if ((*magicp = malloc(sizeof(**magicp) * mentrycount)) == NULL) {		file_oomem(ms, sizeof(**magicp) * mentrycount);		errs++;		goto out;	}	mentrycount = 0;	for (i = 0; i < marraycount; i++) {		(void)memcpy(*magicp + mentrycount, marray[i].mp,		    marray[i].cont_count * sizeof(**magicp));		mentrycount += marray[i].cont_count;	}out:	for (i = 0; i < marraycount; i++)		free(marray[i].mp);	free(marray);	if (errs) {		*magicp = NULL;		*nmagicp = 0;		return errs;	} else {		*nmagicp = mentrycount;		return 0;	}}/* * extend the sign bit if the comparison is to be signed */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -