?? softmagic.c
字號:
/* * 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. *//* * softmagic - interpret variable magic from MAGIC */#include "file.h"#include "magic.h"#include <string.h>#include <ctype.h>#include <stdlib.h>#include <time.h>#ifndef lintFILE_RCSID("@(#)$File: softmagic.c,v 1.99 2007/05/08 14:44:18 christos Exp $")#endif /* lint */private int match(struct magic_set *, struct magic *, uint32_t, const unsigned char *, size_t);private int mget(struct magic_set *, const unsigned char *, struct magic *, size_t, unsigned int);private int magiccheck(struct magic_set *, struct magic *);private int32_t mprint(struct magic_set *, struct magic *);private void mdebug(uint32_t, const char *, size_t);private int mcopy(struct magic_set *, union VALUETYPE *, int, int, const unsigned char *, uint32_t, size_t, size_t);private int mconvert(struct magic_set *, struct magic *);private int print_sep(struct magic_set *, int);private void cvt_8(union VALUETYPE *, const struct magic *);private void cvt_16(union VALUETYPE *, const struct magic *);private void cvt_32(union VALUETYPE *, const struct magic *);private void cvt_64(union VALUETYPE *, const struct magic *);/* * softmagic - lookup one file in parsed, in-memory copy of database * Passed the name and FILE * of one file to be typed. *//*ARGSUSED1*/ /* nbytes passed for regularity, maybe need later */protected intfile_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes){ struct mlist *ml; int rv; for (ml = ms->mlist->next; ml != ms->mlist; ml = ml->next) if ((rv = match(ms, ml->magic, ml->nmagic, buf, nbytes)) != 0) return rv; return 0;}/* * Go through the whole list, stopping if you find a match. Process all * the continuations of that match before returning. * * We support multi-level continuations: * * At any time when processing a successful top-level match, there is a * current continuation level; it represents the level of the last * successfully matched continuation. * * Continuations above that level are skipped as, if we see one, it * means that the continuation that controls them - i.e, the * lower-level continuation preceding them - failed to match. * * Continuations below that level are processed as, if we see one, * it means we've finished processing or skipping higher-level * continuations under the control of a successful or unsuccessful * lower-level continuation, and are now seeing the next lower-level * continuation and should process it. The current continuation * level reverts to the level of the one we're seeing. * * Continuations at the current level are processed as, if we see * one, there's no lower-level continuation that may have failed. * * If a continuation matches, we bump the current continuation level * so that higher-level continuations are processed. */private intmatch(struct magic_set *ms, struct magic *magic, uint32_t nmagic, const unsigned char *s, size_t nbytes){ uint32_t magindex = 0; unsigned int cont_level = 0; int need_separator = 0; int returnval = 0; /* if a match is found it is set to 1*/ int firstline = 1; /* a flag to print X\n X\n- X */ int printed_something = 0; if (file_check_mem(ms, cont_level) == -1) return -1; for (magindex = 0; magindex < nmagic; magindex++) { int flush; ms->offset = magic[magindex].offset; ms->line = magic[magindex].lineno; /* if main entry matches, print it... */ flush = !mget(ms, s, &magic[magindex], nbytes, cont_level); if (flush) { if (magic[magindex].reln == '!') flush = 0; } else { switch (magiccheck(ms, &magic[magindex])) { case -1: return -1; case 0: flush++; break; default: break; } } if (flush) { /* * main entry didn't match, * flush its continuations */ while (magindex < nmagic - 1 && magic[magindex + 1].cont_level != 0) magindex++; continue; } /* * If we are going to print something, we'll need to print * a blank before we print something else. */ if (magic[magindex].desc[0]) { need_separator = 1; printed_something = 1; if (print_sep(ms, firstline) == -1) return -1; } if ((ms->c.li[cont_level].off = mprint(ms, &magic[magindex])) == -1) return -1; /* and any continuations that match */ if (file_check_mem(ms, ++cont_level) == -1) return -1; while (magic[magindex+1].cont_level != 0 && ++magindex < nmagic) { ms->line = magic[magindex].lineno; /* for messages */ if (cont_level < magic[magindex].cont_level) continue; if (cont_level > magic[magindex].cont_level) { /* * We're at the end of the level * "cont_level" continuations. */ cont_level = magic[magindex].cont_level; } ms->offset = magic[magindex].offset; if (magic[magindex].flag & OFFADD) { ms->offset += ms->c.li[cont_level - 1].off; }#ifdef ENABLE_CONDITIONALS if (magic[magindex].cond == COND_ELSE || magic[magindex].cond == COND_ELIF) { if (ms->c.li[cont_level].last_match == 1) continue; }#endif flush = !mget(ms, s, &magic[magindex], nbytes, cont_level); if (flush && magic[magindex].reln != '!') continue; switch (flush ? 1 : magiccheck(ms, &magic[magindex])) { case -1: return -1; case 0:#ifdef ENABLE_CONDITIONALS ms->c.li[cont_level].last_match = 0;#endif break; default:#ifdef ENABLE_CONDITIONALS ms->c.li[cont_level].last_match = 1;#endif if (magic[magindex].type != FILE_DEFAULT) ms->c.li[cont_level].got_match = 1; else if (ms->c.li[cont_level].got_match) { ms->c.li[cont_level].got_match = 0; break; } /* * If we are going to print something, * make sure that we have a separator first. */ if (magic[magindex].desc[0]) { printed_something = 1; if (print_sep(ms, firstline) == -1) return -1; } /* * This continuation matched. Print * its message, with a blank before it * if the previous item printed and * this item isn't empty. */ /* space if previous printed */ if (need_separator && (magic[magindex].nospflag == 0) && (magic[magindex].desc[0] != '\0')) { if (file_printf(ms, " ") == -1) return -1; need_separator = 0; } if ((ms->c.li[cont_level].off = mprint(ms, &magic[magindex])) == -1) return -1; if (magic[magindex].desc[0]) need_separator = 1; /* * If we see any continuations * at a higher level, * process them. */ if (file_check_mem(ms, ++cont_level) == -1) return -1; break; } } firstline = 0; if (printed_something) returnval = 1; if ((ms->flags & MAGIC_CONTINUE) == 0 && printed_something) { return 1; /* don't keep searching */ } } return returnval; /* This is hit if -k is set or there is no match */}private intcheck_fmt(struct magic_set *ms, struct magic *m){ regex_t rx; int rc; if (strchr(m->desc, '%') == NULL) return 0; rc = regcomp(&rx, "%[-0-9\\.]*s", REG_EXTENDED|REG_NOSUB); if (rc) { char errmsg[512]; (void)regerror(rc, &rx, errmsg, sizeof(errmsg)); file_magerror(ms, "regex error %d, (%s)", rc, errmsg); return -1; } else { rc = regexec(&rx, m->desc, 0, 0, 0); regfree(&rx); return !rc; }}#ifndef HAVE_STRNDUPchar * strndup(const char *, size_t);char *strndup(const char *str, size_t n){ size_t len; char *copy; len = strlen(str); if (len > n) len = n; if (!(copy = malloc(len + 1))) return (NULL); (void) memcpy(copy, str, len + 1); copy[len] = '\0'; return (copy);}#endif /* HAVE_STRNDUP */private int32_tmprint(struct magic_set *ms, struct magic *m){ uint64_t v; int64_t t = 0; char buf[512]; union VALUETYPE *p = &ms->ms_value; switch (m->type) { case FILE_BYTE: v = file_signextend(ms, m, (uint64_t)p->b); switch (check_fmt(ms, m)) { case -1: return -1; case 1: if (snprintf(buf, sizeof(buf), "%c", (unsigned char)v) < 0) return -1; if (file_printf(ms, m->desc, buf) == -1) return -1; break; default: if (file_printf(ms, m->desc, (unsigned char) v) == -1) return -1; break; } t = ms->offset + sizeof(char); break; case FILE_SHORT: case FILE_BESHORT: case FILE_LESHORT: v = file_signextend(ms, m, (uint64_t)p->h); switch (check_fmt(ms, m)) { case -1: return -1; case 1: if (snprintf(buf, sizeof(buf), "%hu", (unsigned short)v) < 0) return -1; if (file_printf(ms, m->desc, buf) == -1) return -1; break; default: if (file_printf(ms, m->desc, (unsigned short) v) == -1) return -1; break; } t = ms->offset + sizeof(short); break; case FILE_LONG: case FILE_BELONG: case FILE_LELONG: case FILE_MELONG: v = file_signextend(ms, m, (uint64_t)p->l); switch (check_fmt(ms, m)) { case -1: return -1; case 1: if (snprintf(buf, sizeof(buf), "%u", (uint32_t)v) < 0) return -1; if (file_printf(ms, m->desc, buf) == -1) return -1; break; default: if (file_printf(ms, m->desc, (uint32_t) v) == -1) return -1; break; } t = ms->offset + sizeof(int32_t); break; case FILE_QUAD: case FILE_BEQUAD: case FILE_LEQUAD: v = file_signextend(ms, m, p->q); if (file_printf(ms, m->desc, (uint64_t) v) == -1) return -1; t = ms->offset + sizeof(int64_t); break; case FILE_STRING: case FILE_PSTRING: case FILE_BESTRING16: case FILE_LESTRING16: if (m->reln == '=' || m->reln == '!') { if (file_printf(ms, m->desc, m->value.s) == -1) return -1; t = ms->offset + m->vallen; } else { if (*m->value.s == '\0') { char *cp = strchr(p->s,'\n'); if (cp) *cp = '\0'; } if (file_printf(ms, m->desc, p->s) == -1) return -1; t = ms->offset + strlen(p->s); } break; case FILE_DATE: case FILE_BEDATE: case FILE_LEDATE: case FILE_MEDATE: if (file_printf(ms, m->desc, file_fmttime(p->l, 1)) == -1) return -1; t = ms->offset + sizeof(time_t); break; case FILE_LDATE: case FILE_BELDATE: case FILE_LELDATE: case FILE_MELDATE: if (file_printf(ms, m->desc, file_fmttime(p->l, 0)) == -1) return -1; t = ms->offset + sizeof(time_t); break; case FILE_QDATE: case FILE_BEQDATE: case FILE_LEQDATE: if (file_printf(ms, m->desc, file_fmttime((uint32_t)p->q, 1)) == -1) return -1; t = ms->offset + sizeof(uint64_t); break; case FILE_QLDATE: case FILE_BEQLDATE: case FILE_LEQLDATE: if (file_printf(ms, m->desc, file_fmttime((uint32_t)p->q, 0)) == -1) return -1; t = ms->offset + sizeof(uint64_t); break; case FILE_REGEX: { char *cp; int rval; cp = strndup((const char *)ms->search.s, ms->search.rm_len); if (cp == NULL) { file_oomem(ms, ms->search.rm_len); return -1; } rval = file_printf(ms, m->desc, cp); free(cp); if (rval == -1) return -1; if ((m->str_flags & REGEX_OFFSET_START)) t = ms->search.offset; else t = ms->search.offset + ms->search.rm_len; break; } case FILE_SEARCH: if (file_printf(ms, m->desc, m->value.s) == -1) return -1; if ((m->str_flags & REGEX_OFFSET_START)) t = ms->search.offset; else t = ms->search.offset + m->vallen; break; case FILE_DEFAULT: if (file_printf(ms, m->desc, m->value.s) == -1) return -1; t = ms->offset; break; default: file_magerror(ms, "invalid m->type (%d) in mprint()", m->type); return -1; } return(t);}#define DO_CVT(fld, cast) \ if (m->num_mask) \ switch (m->mask_op & FILE_OPS_MASK) { \ case FILE_OPAND: \ p->fld &= cast m->num_mask; \ break; \ case FILE_OPOR: \ p->fld |= cast m->num_mask; \ break; \ case FILE_OPXOR: \ p->fld ^= cast m->num_mask; \ break; \ case FILE_OPADD: \ p->fld += cast m->num_mask; \ break; \ case FILE_OPMINUS: \ p->fld -= cast m->num_mask; \ break; \ case FILE_OPMULTIPLY: \ p->fld *= cast m->num_mask; \ break; \ case FILE_OPDIVIDE: \ p->fld /= cast m->num_mask; \ break; \ case FILE_OPMODULO: \ p->fld %= cast m->num_mask; \ break; \ } \ if (m->mask_op & FILE_OPINVERSE) \ p->fld = ~p->fld \private voidcvt_8(union VALUETYPE *p, const struct magic *m){ DO_CVT(b, (uint8_t));}private voidcvt_16(union VALUETYPE *p, const struct magic *m){ DO_CVT(h, (uint16_t));}private voidcvt_32(union VALUETYPE *p, const struct magic *m){ DO_CVT(l, (uint32_t));}private voidcvt_64(union VALUETYPE *p, const struct magic *m){ DO_CVT(q, (uint64_t));}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -