diff options
Diffstat (limited to 'contrib/file/apprentice.c')
-rw-r--r-- | contrib/file/apprentice.c | 547 |
1 files changed, 429 insertions, 118 deletions
diff --git a/contrib/file/apprentice.c b/contrib/file/apprentice.c index 974fae95e2dd..d5a5bec5129f 100644 --- a/contrib/file/apprentice.c +++ b/contrib/file/apprentice.c @@ -46,7 +46,7 @@ #endif #ifndef lint -FILE_RCSID("@(#)$Id: apprentice.c,v 1.100 2006/12/11 21:48:49 christos Exp $") +FILE_RCSID("@(#)$File: apprentice.c,v 1.105 2007/05/16 20:51:40 christos Exp $") #endif /* lint */ #define EATAB {while (isascii((unsigned char) *l) && \ @@ -75,27 +75,21 @@ FILE_RCSID("@(#)$Id: apprentice.c,v 1.100 2006/12/11 21:48:49 christos Exp $") #define MAXPATHLEN 1024 #endif -#define IS_PLAINSTRING(t) ((t) == FILE_STRING || (t) == FILE_PSTRING || \ - (t) == FILE_BESTRING16 || (t) == FILE_LESTRING16) - -#define IS_STRING(t) (IS_PLAINSTRING(t) || (t) == FILE_REGEX || \ - (t) == FILE_SEARCH) - struct magic_entry { struct magic *mp; uint32_t cont_count; uint32_t max_count; }; -const int file_formats[] = { FILE_FORMAT_STRING }; -const size_t file_nformats = sizeof(file_formats) / sizeof(file_formats[0]); -const char *file_names[] = { FILE_FORMAT_NAME }; -const size_t file_nnames = sizeof(file_names) / sizeof(file_names[0]); +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 **); +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 *, int); private int parse(struct magic_set *, struct magic_entry **, uint32_t *, const char *, size_t, int); private void eatsize(const char **); @@ -154,6 +148,82 @@ main(int argc, char *argv[]) } #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 int +get_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 void +init_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. @@ -241,7 +311,6 @@ file_delmagic(struct magic *p, int type, size_t entries) } } - /* const char *fn: list of magic files */ protected struct mlist * file_apprentice(struct magic_set *ms, const char *fn, int action) @@ -251,15 +320,18 @@ file_apprentice(struct magic_set *ms, const char *fn, int action) struct mlist *mlist; static const char mime[] = ".mime"; + init_file_tables(); + if (fn == NULL) fn = getenv("MAGIC"); if (fn == NULL) fn = MAGIC; - if ((fn = mfn = strdup(fn)) == NULL) { + if ((mfn = strdup(fn)) == NULL) { file_oomem(ms, strlen(fn)); return NULL; } + fn = mfn; if ((mlist = malloc(sizeof(*mlist))) == NULL) { free(mfn); @@ -316,6 +388,9 @@ apprentice_magic_strength(const struct magic *m) 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; @@ -401,6 +476,10 @@ apprentice_magic_strength(const struct magic *m) (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; } @@ -485,6 +564,23 @@ apprentice_file(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp, #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++) @@ -523,7 +619,7 @@ out: protected uint64_t file_signextend(struct magic_set *ms, struct magic *m, uint64_t v) { - if (!(m->flag & UNSIGNED)) + if (!(m->flag & UNSIGNED)) { switch(m->type) { /* * Do not remove the casts below. They are @@ -569,6 +665,7 @@ file_signextend(struct magic_set *ms, struct magic *m, uint64_t v) case FILE_LESTRING16: case FILE_REGEX: case FILE_SEARCH: + case FILE_DEFAULT: break; default: if (ms->flags & MAGIC_CHECK) @@ -576,9 +673,150 @@ file_signextend(struct magic_set *ms, struct magic *m, uint64_t v) m->type); return ~0U; } + } return v; } +private int +string_modifier_check(struct magic_set *ms, struct magic const *m) +{ + if ((ms->flags & MAGIC_CHECK) == 0) + return 0; + + switch (m->type) { + case FILE_BESTRING16: + case FILE_LESTRING16: + if (m->str_flags != 0) { + file_magwarn(ms, "no modifiers allowed for 16-bit strings\n"); + return -1; + } + break; + case FILE_STRING: + case FILE_PSTRING: + if ((m->str_flags & REGEX_OFFSET_START) != 0) { + file_magwarn(ms, "'/%c' only allowed on regex and search\n", + CHAR_REGEX_OFFSET_START); + return -1; + } + break; + case FILE_SEARCH: + break; + case FILE_REGEX: + if ((m->str_flags & STRING_COMPACT_BLANK) != 0) { + file_magwarn(ms, "'/%c' not allowed on regex\n", + CHAR_COMPACT_BLANK); + return -1; + } + if ((m->str_flags & STRING_COMPACT_OPTIONAL_BLANK) != 0) { + file_magwarn(ms, "'/%c' not allowed on regex\n", + CHAR_COMPACT_OPTIONAL_BLANK); + return -1; + } + break; + default: + file_magwarn(ms, "coding error: m->type=%d\n", + m->type); + return -1; + } + return 0; +} + +private int +get_op(char c) +{ + switch (c) { + case '&': + return FILE_OPAND; + case '|': + return FILE_OPOR; + case '^': + return FILE_OPXOR; + case '+': + return FILE_OPADD; + case '-': + return FILE_OPMINUS; + case '*': + return FILE_OPMULTIPLY; + case '/': + return FILE_OPDIVIDE; + case '%': + return FILE_OPMODULO; + default: + return -1; + } +} + +#ifdef ENABLE_CONDITIONALS +private int +get_cond(const char *l, const char **t) +{ + static struct cond_tbl_s { + const char *name; + const size_t len; + const int cond; + } cond_tbl[] = { + { "if", 2, COND_IF }, + { "elif", 4, COND_ELIF }, + { "else", 4, COND_ELSE }, + { NULL, 0, COND_NONE }, + }; + struct cond_tbl_s *p; + + for (p = cond_tbl; p->name; p++) { + if (strncmp(l, p->name, p->len) == 0 && + isspace((unsigned char)l[p->len])) { + if (t) + *t = l + p->len; + break; + } + } + return p->cond; +} + +private int +check_cond(struct magic_set *ms, int cond, uint32_t cont_level) +{ + int last_cond; + last_cond = ms->c.li[cont_level].last_cond; + + switch (cond) { + case COND_IF: + if (last_cond != COND_NONE && last_cond != COND_ELIF) { + if (ms->flags & MAGIC_CHECK) + file_magwarn(ms, "syntax error: `if'"); + return -1; + } + last_cond = COND_IF; + break; + + case COND_ELIF: + if (last_cond != COND_IF && last_cond != COND_ELIF) { + if (ms->flags & MAGIC_CHECK) + file_magwarn(ms, "syntax error: `elif'"); + return -1; + } + last_cond = COND_ELIF; + break; + + case COND_ELSE: + if (last_cond != COND_IF && last_cond != COND_ELIF) { + if (ms->flags & MAGIC_CHECK) + file_magwarn(ms, "syntax error: `else'"); + return -1; + } + last_cond = COND_NONE; + break; + + case COND_NONE: + last_cond = COND_NONE; + break; + } + + ms->c.li[cont_level].last_cond = last_cond; + return 0; +} +#endif /* ENABLE_CONDITIONALS */ + /* * parse one line from magic file, put into magic[index++] if valid */ @@ -586,13 +824,15 @@ private int parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp, const char *line, size_t lineno, int action) { +#ifdef ENABLE_CONDITIONALS + static uint32_t last_cont_level = 0; +#endif size_t i; struct magic_entry *me; struct magic *m; const char *l = line; char *t; - private const char *fops = FILE_OPS; - uint64_t val; + int op; uint32_t cont_level; cont_level = 0; @@ -601,6 +841,12 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp, ++l; /* step over */ cont_level++; } +#ifdef ENABLE_CONDITIONALS + if (cont_level == 0 || cont_level > last_cont_level) + if (file_check_mem(ms, cont_level) == -1) + return -1; + last_cont_level = cont_level; +#endif #define ALLOC_CHUNK (size_t)10 #define ALLOC_INCR (size_t)200 @@ -622,7 +868,7 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp, me->max_count = cnt; } m = &me->mp[me->cont_count++]; - memset(m, 0, sizeof(*m)); + (void)memset(m, 0, sizeof(*m)); m->cont_level = cont_level; } else { if (*nmentryp == maxmagic) { @@ -648,26 +894,31 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp, me->max_count = ALLOC_CHUNK; } else m = me->mp; - memset(m, 0, sizeof(*m)); + (void)memset(m, 0, sizeof(*m)); m->cont_level = 0; me->cont_count = 1; } m->lineno = lineno; - if (m->cont_level != 0 && *l == '&') { + if (*l == '&') { /* m->cont_level == 0 checked below. */ ++l; /* step over */ m->flag |= OFFADD; } - if (m->cont_level != 0 && *l == '(') { + if (*l == '(') { ++l; /* step over */ m->flag |= INDIR; if (m->flag & OFFADD) m->flag = (m->flag & ~OFFADD) | INDIROFFADD; + + if (*l == '&') { /* m->cont_level == 0 checked below */ + ++l; /* step over */ + m->flag |= OFFADD; + } } - if (m->cont_level != 0 && *l == '&') { - ++l; /* step over */ - m->flag |= OFFADD; - } + /* Indirect offsets are not valid at level 0. */ + if (m->cont_level == 0 && (m->flag & (OFFADD | INDIROFFADD))) + if (ms->flags & MAGIC_CHECK) + file_magwarn(ms, "relative offset at level 0"); /* get offset, then skip over it */ m->offset = (uint32_t)strtoul(l, &t, 0); @@ -717,43 +968,15 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp, } l++; } + + m->in_op = 0; if (*l == '~') { m->in_op |= FILE_OPINVERSE; l++; } - switch (*l) { - case '&': - m->in_op |= FILE_OPAND; - l++; - break; - case '|': - m->in_op |= FILE_OPOR; - l++; - break; - case '^': - m->in_op |= FILE_OPXOR; - l++; - break; - case '+': - m->in_op |= FILE_OPADD; - l++; - break; - case '-': - m->in_op |= FILE_OPMINUS; - l++; - break; - case '*': - m->in_op |= FILE_OPMULTIPLY; - l++; - break; - case '/': - m->in_op |= FILE_OPDIVIDE; - l++; - break; - case '%': - m->in_op |= FILE_OPMODULO; + if ((op = get_op(*l)) != -1) { + m->in_op |= op; l++; - break; } if (*l == '(') { m->in_op |= FILE_OPINDIRECT; @@ -761,6 +984,10 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp, } if (isdigit((unsigned char)*l) || *l == '-') { m->in_offset = (int32_t)strtol(l, &t, 0); + if (l == t) + if (ms->flags & MAGIC_CHECK) + file_magwarn(ms, + "in_offset `%s' invalid", l); l = t; } if (*l++ != ')' || @@ -769,61 +996,85 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp, file_magwarn(ms, "missing ')' in indirect offset"); } + EATAB; +#ifdef ENABLE_CONDITIONALS + m->cond = get_cond(l, &l); + if (check_cond(ms, m->cond, cont_level) == -1) + return -1; - while (isascii((unsigned char)*l) && isdigit((unsigned char)*l)) - ++l; EATAB; +#endif if (*l == 'u') { ++l; m->flag |= UNSIGNED; } - /* get type, skip it */ - for (i = 0; i < file_nnames; i++) { - size_t len = strlen(file_names[i]); - if (strncmp(l, file_names[i], len) == 0) { - m->type = i; - l+= len; - break; - } - } - if (i == file_nnames) { + m->type = get_type(l, &l); + if (m->type == FILE_INVALID) { if (ms->flags & MAGIC_CHECK) file_magwarn(ms, "type `%s' invalid", l); return -1; } + /* New-style anding: "0 byte&0x80 =0x80 dynamically linked" */ /* New and improved: ~ & | ^ + - * / % -- exciting, isn't it? */ + + m->mask_op = 0; if (*l == '~') { if (!IS_STRING(m->type)) m->mask_op |= FILE_OPINVERSE; + else if (ms->flags & MAGIC_CHECK) + file_magwarn(ms, "'~' invalid for string types"); ++l; } - if ((t = strchr(fops, *l)) != NULL) { - uint32_t op = (uint32_t)(t - fops); - if (op != FILE_OPDIVIDE || !IS_PLAINSTRING(m->type)) { + m->str_count = 0; + m->str_flags = 0; + m->num_mask = 0; + if ((op = get_op(*l)) != -1) { + if (!IS_STRING(m->type)) { + uint64_t val; ++l; m->mask_op |= op; val = (uint64_t)strtoull(l, &t, 0); l = t; - m->mask = file_signextend(ms, m, val); + m->num_mask = file_signextend(ms, m, val); eatsize(&l); - } else { - m->mask = 0L; + } + else if (op == FILE_OPDIVIDE) { + int have_count = 0; while (!isspace((unsigned char)*++l)) { switch (*l) { - case CHAR_IGNORE_LOWERCASE: - m->mask |= STRING_IGNORE_LOWERCASE; + /* for portability avoid "case '0' ... '9':" */ + case '0': case '1': case '2': + case '3': case '4': case '5': + case '6': case '7': case '8': + case '9': { + if (have_count && ms->flags & MAGIC_CHECK) + file_magwarn(ms, + "multiple counts"); + have_count = 1; + m->str_count = strtoul(l, &t, 0); + l = t - 1; break; + } case CHAR_COMPACT_BLANK: - m->mask |= STRING_COMPACT_BLANK; + m->str_flags |= STRING_COMPACT_BLANK; break; case CHAR_COMPACT_OPTIONAL_BLANK: - m->mask |= + m->str_flags |= STRING_COMPACT_OPTIONAL_BLANK; break; + case CHAR_IGNORE_LOWERCASE: + m->str_flags |= STRING_IGNORE_LOWERCASE; + break; + case CHAR_IGNORE_UPPERCASE: + m->str_flags |= STRING_IGNORE_UPPERCASE; + break; + case CHAR_REGEX_OFFSET_START: + m->str_flags |= REGEX_OFFSET_START; + break; default: if (ms->flags & MAGIC_CHECK) file_magwarn(ms, @@ -831,8 +1082,17 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp, *l); return -1; } + /* allow multiple '/' for readability */ + if (l[1] == '/' && !isspace((unsigned char)l[2])) + l++; } - ++l; + if (string_modifier_check(ms, m) == -1) + return -1; + } + else { + if (ms->flags & MAGIC_CHECK) + file_magwarn(ms, "invalid string op: %c", *t); + return -1; } } /* @@ -860,19 +1120,20 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp, ++l; break; default: + m->reln = '='; /* the default relation */ if (*l == 'x' && ((isascii((unsigned char)l[1]) && isspace((unsigned char)l[1])) || !l[1])) { m->reln = *l; ++l; - goto GetDesc; /* Bill The Cat */ } - m->reln = '='; break; } - EATAB; - - if (getvalue(ms, m, &l)) + /* + * Grab the value part, except for an 'x' reln. + */ + if (m->reln != 'x' && getvalue(ms, m, &l, action)) return -1; + /* * TODO finish this macro and start using it! * #define offsetcheck {if (offset > HOWMANY-1) @@ -880,9 +1141,8 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp, */ /* - * now get last part - the description + * Now get last part - the description */ -GetDesc: EATAB; if (l[0] == '\b') { ++l; @@ -1078,7 +1338,7 @@ check_format(struct magic_set *ms, struct magic *m) * just after the number read. Return 0 for success, non-zero for failure. */ private int -getvalue(struct magic_set *ms, struct magic *m, const char **p) +getvalue(struct magic_set *ms, struct magic *m, const char **p, int action) { int slen; @@ -1089,7 +1349,7 @@ getvalue(struct magic_set *ms, struct magic *m, const char **p) case FILE_PSTRING: case FILE_REGEX: case FILE_SEARCH: - *p = getstr(ms, *p, m->value.s, sizeof(m->value.s), &slen); + *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'", @@ -1117,7 +1377,7 @@ getvalue(struct magic_set *ms, struct magic *m, const char **p) * Return updated scan pointer as function result. */ private const char * -getstr(struct magic_set *ms, const char *s, char *p, int plen, int *slen) +getstr(struct magic_set *ms, const char *s, char *p, int plen, int *slen, int action) { const char *origs = s; char *origp = p; @@ -1132,16 +1392,66 @@ getstr(struct magic_set *ms, const char *s, char *p, int plen, int *slen) file_error(ms, 0, "string too long: `%s'", origs); return NULL; } - if(c == '\\') { + 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; @@ -1150,18 +1460,10 @@ getstr(struct magic_set *ms, const char *s, char *p, int plen, int *slen) *p++ = '\r'; break; - case 'b': - *p++ = '\b'; - break; - case 't': *p++ = '\t'; break; - case 'f': - *p++ = '\f'; - break; - case 'v': *p++ = '\v'; break; @@ -1177,11 +1479,11 @@ getstr(struct magic_set *ms, const char *s, char *p, int plen, int *slen) case '7': val = c - '0'; c = *s++; /* try for 2 */ - if(c >= '0' && c <= '7') { - val = (val<<3) | (c - '0'); + 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'); + if (c >= '0' && c <= '7') + val = (val << 3) | (c-'0'); else --s; } @@ -1224,9 +1526,9 @@ hextoint(int c) return -1; if (isdigit((unsigned char) c)) return c - '0'; - if ((c >= 'a')&&(c <= 'f')) + if ((c >= 'a') && (c <= 'f')) return c + 10 - 'a'; - if (( c>= 'A')&&(c <= 'F')) + if (( c>= 'A') && (c <= 'F')) return c + 10 - 'A'; return -1; } @@ -1250,12 +1552,23 @@ file_showstr(FILE *fp, const char *s, size_t len) if (len-- == 0) break; } - if(c >= 040 && c <= 0176) /* TODO isprint && !iscntrl */ + 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; @@ -1264,18 +1577,10 @@ file_showstr(FILE *fp, const char *s, size_t len) (void) fputc('r', fp); break; - case '\b': - (void) fputc('b', fp); - break; - case '\t': (void) fputc('t', fp); break; - case '\f': - (void) fputc('f', fp); - break; - case '\v': (void) fputc('v', fp); break; @@ -1536,7 +1841,13 @@ bs1(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); - if (!IS_STRING(m->type)) + 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->mask = swap8(m->mask); + m->num_mask = swap8(m->num_mask); + } } |