apprentice.c

来自「sleuthit-2.09 一个磁盘的工具集」· C语言 代码 · 共 1,854 行 · 第 1/3 页

C
1,854
字号
			case 'd':				return 0;			default:				return -1;			}		case 'i':		case 'c':		case 'd':		case 'u':		case 'x':		case 'X':			return 0;					default:			return -1;		}			case FILE_FMT_STR:		if (*ptr == '-')			ptr++;		while (isdigit((unsigned char )*ptr))			ptr++;		if (*ptr == '.') {			ptr++;			while (isdigit((unsigned char )*ptr))				ptr++;		}				switch (*ptr++) {		case 's':			return 0;		default:			return -1;		}			default:		/* internal error */		abort();	}	/*NOTREACHED*/	return -1;}	/* * Check that the optional printf format in description matches * the type of the magic. */private intcheck_format(struct magic_set *ms, struct magic *m){	char *ptr;	for (ptr = m->desc; *ptr; ptr++)		if (*ptr == '%')			break;	if (*ptr == '\0') {		/* No format string; ok */		return 1;	}	assert(file_nformats == file_nnames);	if (m->type >= file_nformats) {		file_error(ms, 0, "Internal error inconsistency between "		    "m->type and format strings");				return -1;	}	if (file_formats[m->type] == FILE_FMT_NONE) {		file_error(ms, 0, "No format string for `%s' with description "		    "`%s'", m->desc, file_names[m->type]);		return -1;	}	ptr++;	if (check_format_type(ptr, file_formats[m->type]) == -1) {		/*		 * TODO: this error message is unhelpful if the format		 * string is not one character long		 */		file_error(ms, 0, "Printf format `%c' is not valid for type "		    " `%s' in description `%s'", *ptr,		    file_names[m->type], m->desc);		return -1;	}		for (; *ptr; ptr++) {		if (*ptr == '%') {			file_error(ms, 0,			    "Too many format strings (should have at most one) "			    "for `%s' with description `%s'",			    file_names[m->type], m->desc);			return -1;		}	}	return 0;}/*  * Read a numeric value from a pointer, into the value union of a magic  * pointer, according to the magic type.  Update the string pointer to point  * just after the number read.  Return 0 for success, non-zero for failure. */private intgetvalue(struct magic_set *ms, struct magic *m, const char **p, int action){	int slen;	switch (m->type) {	case FILE_BESTRING16:	case FILE_LESTRING16:	case FILE_STRING:	case FILE_PSTRING:	case FILE_REGEX:	case FILE_SEARCH:		*p = getstr(ms, *p, m->value.s, sizeof(m->value.s), &slen, action);		if (*p == NULL) {			if (ms->flags & MAGIC_CHECK)				file_magwarn(ms, "cannot get string from `%s'",				    m->value.s);			return -1;		}		m->vallen = slen;		return 0;	default:		if (m->reln != 'x') {			char *ep;			m->value.q = file_signextend(ms, m,			    (uint64_t)strtoull(*p, &ep, 0));			*p = ep;			eatsize(p);		}		return 0;	}}/* * Convert a string containing C character escapes.  Stop at an unescaped * space or tab. * Copy the converted version to "p", returning its length in *slen. * Return updated scan pointer as function result. */private const char *getstr(struct magic_set *ms, const char *s, char *p, int plen, int *slen, int action){	const char *origs = s;	char 	*origp = p;	char	*pmax = p + plen - 1;	int	c;	int	val;	while ((c = *s++) != '\0') {		if (isspace((unsigned char) c))			break;		if (p >= pmax) {			file_error(ms, 0, "string too long: `%s'", origs);			return NULL;		}		if (c == '\\') {			switch(c = *s++) {			case '\0':				if (action == FILE_COMPILE)					file_magwarn(ms, "incomplete escape");				goto out;			case '\t':				if (action == FILE_COMPILE) {					file_magwarn(ms,					    "escaped tab found, use \\t instead");					action++;				}				/*FALLTHROUGH*/			default:				if (action == FILE_COMPILE) {					if (isprint((unsigned char)c))					    file_magwarn(ms,						"no need to escape `%c'", c);					else					    file_magwarn(ms,						"unknown escape sequence: \\%03o", c);				}				/*FALLTHROUGH*/			/* space, perhaps force people to use \040? */			case ' ':#if 0			/*			 * Other things people escape, but shouldn't need to,			 * so we disallow them			 */			case '\'':			case '"':			case '?':#endif			/* Relations */			case '>':			case '<':			case '&':			case '^':			case '=':			case '!':			/* and baskslash itself */			case '\\':				*p++ = (char) c;				break;			case 'a':				*p++ = '\a';				break;			case 'b':				*p++ = '\b';				break;			case 'f':				*p++ = '\f';				break;			case 'n':				*p++ = '\n';				break;			case 'r':				*p++ = '\r';				break;			case 't':				*p++ = '\t';				break;			case 'v':				*p++ = '\v';				break;			/* \ and up to 3 octal digits */			case '0':			case '1':			case '2':			case '3':			case '4':			case '5':			case '6':			case '7':				val = c - '0';				c = *s++;  /* try for 2 */				if (c >= '0' && c <= '7') {					val = (val << 3) | (c - '0');					c = *s++;  /* try for 3 */					if (c >= '0' && c <= '7')						val = (val << 3) | (c-'0');					else						--s;				}				else					--s;				*p++ = (char)val;				break;			/* \x and up to 2 hex digits */			case 'x':				val = 'x';	/* Default if no digits */				c = hextoint(*s++);	/* Get next char */				if (c >= 0) {					val = c;					c = hextoint(*s++);					if (c >= 0)						val = (val << 4) + c;					else						--s;				} else					--s;				*p++ = (char)val;				break;			}		} else			*p++ = (char)c;	}out:	*p = '\0';	*slen = p - origp;	return s;}/* Single hex char to int; -1 if not a hex char. */private inthextoint(int c){	if (!isascii((unsigned char) c))		return -1;	if (isdigit((unsigned char) c))		return c - '0';	if ((c >= 'a') && (c <= 'f'))		return c + 10 - 'a';	if (( c>= 'A') && (c <= 'F'))		return c + 10 - 'A';	return -1;}/* * Print a string containing C character escapes. */protected voidfile_showstr(FILE *fp, const char *s, size_t len){	char	c;	for (;;) {		c = *s++;		if (len == ~0U) {			if (c == '\0')				break;		}		else  {			if (len-- == 0)				break;		}		if (c >= 040 && c <= 0176)	/* TODO isprint && !iscntrl */			(void) fputc(c, fp);		else {			(void) fputc('\\', fp);			switch (c) {			case '\a':				(void) fputc('a', fp);				break;			case '\b':				(void) fputc('b', fp);				break;			case '\f':				(void) fputc('f', fp);				break;			case '\n':				(void) fputc('n', fp);				break;			case '\r':				(void) fputc('r', fp);				break;			case '\t':				(void) fputc('t', fp);				break;			case '\v':				(void) fputc('v', fp);				break;			default:				(void) fprintf(fp, "%.3o", c & 0377);				break;			}		}	}}/* * eatsize(): Eat the size spec from a number [eg. 10UL] */private voideatsize(const char **p){	const char *l = *p;	if (LOWCASE(*l) == 'u') 		l++;	switch (LOWCASE(*l)) {	case 'l':    /* long */	case 's':    /* short */	case 'h':    /* short */	case 'b':    /* char/byte */	case 'c':    /* char/byte */		l++;		/*FALLTHROUGH*/	default:		break;	}	*p = l;}/* * handle a compiled file. */private intapprentice_map(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,    const char *fn){	int fd;	struct stat st;	uint32_t *ptr;	uint32_t version;	int needsbyteswap;	char buf[MAXPATHLEN];	char *dbname = mkdbname(fn, buf, sizeof(buf), 0);	void *mm = NULL;	if (dbname == NULL)		return -1;	if ((fd = open(dbname, O_RDONLY|O_BINARY)) == -1)		return -1;	if (fstat(fd, &st) == -1) {		file_error(ms, errno, "cannot stat `%s'", dbname);		goto error;	}	if (st.st_size < 16) {		file_error(ms, 0, "file `%s' is too small", dbname);		goto error;	}#ifdef QUICK	if ((mm = mmap(0, (size_t)st.st_size, PROT_READ|PROT_WRITE,	    MAP_PRIVATE|MAP_FILE, fd, (off_t)0)) == MAP_FAILED) {		file_error(ms, errno, "cannot map `%s'", dbname);		goto error;	}#define RET	2#else	if ((mm = malloc((size_t)st.st_size)) == NULL) {		file_oomem(ms, (size_t)st.st_size);		goto error;	}	if (read(fd, mm, (size_t)st.st_size) != (size_t)st.st_size) {		file_badread(ms);		goto error;	}#define RET	1#endif	*magicp = mm;	(void)close(fd);	fd = -1;	ptr = (uint32_t *)(void *)*magicp;	if (*ptr != MAGICNO) {		if (swap4(*ptr) != MAGICNO) {			file_error(ms, 0, "bad magic in `%s'");			goto error;		}		needsbyteswap = 1;	} else		needsbyteswap = 0;	if (needsbyteswap)		version = swap4(ptr[1]);	else		version = ptr[1];	if (version != VERSIONNO) {		file_error(ms, 0, "version mismatch (%d != %d) in `%s'",		    version, VERSIONNO, dbname);		goto error;	}	*nmagicp = (uint32_t)(st.st_size / sizeof(struct magic)) - 1;	(*magicp)++;	if (needsbyteswap)		byteswap(*magicp, *nmagicp);	return RET;error:	if (fd != -1)		(void)close(fd);	if (mm) {#ifdef QUICK		(void)munmap((void *)mm, (size_t)st.st_size);#else		free(mm);#endif	} else {		*magicp = NULL;		*nmagicp = 0;	}	return -1;}private const uint32_t ar[] = {    MAGICNO, VERSIONNO};/* * handle an mmaped file. */private intapprentice_compile(struct magic_set *ms, struct magic **magicp,    uint32_t *nmagicp, const char *fn){	int fd;	char buf[MAXPATHLEN];	char *dbname = mkdbname(fn, buf, sizeof(buf), 1);	if (dbname == NULL) 		return -1;	if ((fd = open(dbname, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0644)) == -1) {		file_error(ms, errno, "cannot open `%s'", dbname);		return -1;	}	if (write(fd, ar, sizeof(ar)) != (ssize_t)sizeof(ar)) {		file_error(ms, errno, "error writing `%s'", dbname);		return -1;	}	if (lseek(fd, (off_t)sizeof(struct magic), SEEK_SET)	    != sizeof(struct magic)) {		file_error(ms, errno, "error seeking `%s'", dbname);		return -1;	}	if (write(fd, *magicp, (sizeof(struct magic) * *nmagicp)) 	    != (ssize_t)(sizeof(struct magic) * *nmagicp)) {		file_error(ms, errno, "error writing `%s'", dbname);		return -1;	}	(void)close(fd);	return 0;}private const char ext[] = ".mgc";/* * make a dbname */private char *mkdbname(const char *fn, char *buf, size_t bufsiz, int strip){	if (strip) {		const char *p;		if ((p = strrchr(fn, '/')) != NULL)			fn = ++p;	}	(void)snprintf(buf, bufsiz, "%s%s", fn, ext);	return buf;}/* * Byteswap an mmap'ed file if needed */private voidbyteswap(struct magic *magic, uint32_t nmagic){	uint32_t i;	for (i = 0; i < nmagic; i++)		bs1(&magic[i]);}/* * swap a short */private uint16_tswap2(uint16_t sv){	uint16_t rv;	uint8_t *s = (uint8_t *)(void *)&sv; 	uint8_t *d = (uint8_t *)(void *)&rv; 	d[0] = s[1];	d[1] = s[0];	return rv;}/* * swap an int */private uint32_tswap4(uint32_t sv){	uint32_t rv;	uint8_t *s = (uint8_t *)(void *)&sv; 	uint8_t *d = (uint8_t *)(void *)&rv; 	d[0] = s[3];	d[1] = s[2];	d[2] = s[1];	d[3] = s[0];	return rv;}/* * swap a quad */private uint64_tswap8(uint64_t sv){	uint32_t rv;	uint8_t *s = (uint8_t *)(void *)&sv; 	uint8_t *d = (uint8_t *)(void *)&rv; 	d[0] = s[3];	d[1] = s[2];	d[2] = s[1];	d[3] = s[0];	d[4] = s[7];	d[5] = s[6];	d[6] = s[5];	d[7] = s[4];	return rv;}/* * byteswap a single magic entry */private voidbs1(struct magic *m){	m->cont_level = swap2(m->cont_level);	m->offset = swap4((uint32_t)m->offset);	m->in_offset = swap4((uint32_t)m->in_offset);	m->lineno = swap4((uint32_t)m->lineno);	if (IS_STRING(m->type)) {		m->str_count = swap4(m->str_count);		m->str_flags = swap4(m->str_flags);	}	else {		m->value.q = swap8(m->value.q);		m->num_mask = swap8(m->num_mask);	}}

⌨️ 快捷键说明

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