Deleted Added
sdiff udiff text old ( 133359 ) new ( 139368 )
full compact
1/*
2 * Copyright (c) Ian F. Darwin 1986-1995.
3 * Software written by Ian F. Darwin and others;
4 * maintained 1995-present by Christos Zoulas and others.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice immediately at the beginning of the file, without modification,
11 * this list of conditions, and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)

--- 17 unchanged lines hidden (view full) ---

40#include <fcntl.h>
41#include <sys/stat.h>
42#include <sys/param.h>
43#ifdef QUICK
44#include <sys/mman.h>
45#endif
46
47#ifndef lint
48FILE_RCSID("@(#)$Id: apprentice.c,v 1.82 2004/11/24 18:56:04 christos Exp $")
49#endif /* lint */
50
51#define EATAB {while (isascii((unsigned char) *l) && \
52 isspace((unsigned char) *l)) ++l;}
53#define LOWCASE(l) (isupper((unsigned char) (l)) ? \
54 tolower((unsigned char) (l)) : (l))
55/*
56 * Work around a bug in headers on Digital Unix.

--- 12 unchanged lines hidden (view full) ---

69#ifndef MAP_FILE
70#define MAP_FILE 0
71#endif
72
73#ifndef MAXPATHLEN
74#define MAXPATHLEN 1024
75#endif
76
77#define IS_STRING(t) ((t) == FILE_STRING || (t) == FILE_PSTRING || \
78 (t) == FILE_BESTRING16 || (t) == FILE_LESTRING16)
79
80private int getvalue(struct magic_set *ms, struct magic *, char **);
81private int hextoint(int);
82private char *getstr(struct magic_set *, char *, char *, int, int *);
83private int parse(struct magic_set *, struct magic **, uint32_t *, char *, int);
84private void eatsize(char **);
85private int apprentice_1(struct magic_set *, const char *, int, struct mlist *);
86private int apprentice_file(struct magic_set *, struct magic **, uint32_t *,
87 const char *, int);
88private void byteswap(struct magic *, uint32_t);
89private void bs1(struct magic *);
90private uint16_t swap2(uint16_t);
91private uint32_t swap4(uint32_t);
92private char *mkdbname(const char *, char *, size_t, int);
93private int apprentice_map(struct magic_set *, struct magic **, uint32_t *,
94 const char *);
95private int apprentice_compile(struct magic_set *, struct magic **, uint32_t *,
96 const char *);
97private int check_format(struct magic_set *, struct magic *);
98
99private size_t maxmagic = 0;
100private size_t magicsize = sizeof(struct magic);
101
102#ifdef COMPILE_ONLY
103
104int main(int, char *[]);
105

--- 53 unchanged lines hidden (view full) ---

159 return -1;
160 rv = apprentice_compile(ms, &magic, &nmagic, fn);
161 free(magic);
162 return rv;
163 }
164#ifndef COMPILE_ONLY
165 if ((rv = apprentice_map(ms, &magic, &nmagic, fn)) == -1) {
166 if (ms->flags & MAGIC_CHECK)
167 file_magwarn(ms, "using regular magic file `%s'", fn);
168 rv = apprentice_file(ms, &magic, &nmagic, fn, action);
169 if (rv != 0)
170 return -1;
171 mapped = 0;
172 }
173
174 if (rv == -1)
175 return rv;

--- 114 unchanged lines hidden (view full) ---

290private int
291apprentice_file(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
292 const char *fn, int action)
293{
294 private const char hdr[] =
295 "cont\toffset\ttype\topcode\tmask\tvalue\tdesc";
296 FILE *f;
297 char line[BUFSIZ+1];
298 int errs = 0;
299
300 f = fopen(ms->file = fn, "r");
301 if (f == NULL) {
302 if (errno != ENOENT)
303 file_error(ms, errno, "cannot read magic file `%s'",
304 fn);
305 return -1;
306 }
307
308 maxmagic = MAXMAGIS;

--- 4 unchanged lines hidden (view full) ---

313 return -1;
314 }
315
316 /* print silly verbose header for USG compat. */
317 if (action == FILE_CHECK)
318 (void)fprintf(stderr, "%s\n", hdr);
319
320 /* parse it */
321 for (ms->line = 1; fgets(line, BUFSIZ, f) != NULL; ms->line++) {
322 size_t len;
323 if (line[0]=='#') /* comment, do not parse */
324 continue;
325 len = strlen(line);
326 if (len < 2) /* null line, garbage, etc */
327 continue;
328 line[len - 1] = '\0'; /* delete newline */
329 if (parse(ms, magicp, nmagicp, line, action) != 0)
330 errs = 1;
331 }
332
333 (void)fclose(f);
334 if (errs) {
335 free(*magicp);
336 *magicp = NULL;

--- 31 unchanged lines hidden (view full) ---

368 case FILE_LELDATE:
369 case FILE_LONG:
370 case FILE_BELONG:
371 case FILE_LELONG:
372 v = (int32_t) v;
373 break;
374 case FILE_STRING:
375 case FILE_PSTRING:
376 case FILE_BESTRING16:
377 case FILE_LESTRING16:
378 break;
379 case FILE_REGEX:
380 break;
381 default:
382 if (ms->flags & MAGIC_CHECK)
383 file_magwarn(ms, "cannot happen: m->type=%d\n",
384 m->type);
385 return ~0U;
386 }
387 return v;
388}
389
390/*
391 * parse one line from magic file, put into magic[index++] if valid

--- 39 unchanged lines hidden (view full) ---

431 ++l; /* step over */
432 m->flag |= OFFADD;
433 }
434
435 /* get offset, then skip over it */
436 m->offset = (uint32_t)strtoul(l, &t, 0);
437 if (l == t)
438 if (ms->flags & MAGIC_CHECK)
439 file_magwarn(ms, "offset `%s' invalid", l);
440 l = t;
441
442 if (m->flag & INDIR) {
443 m->in_type = FILE_LONG;
444 m->in_offset = 0;
445 /*
446 * read [.lbs][+-]nnnnn)
447 */

--- 17 unchanged lines hidden (view full) ---

465 case 'c':
466 case 'b':
467 case 'C':
468 case 'B':
469 m->in_type = FILE_BYTE;
470 break;
471 default:
472 if (ms->flags & MAGIC_CHECK)
473 file_magwarn(ms,
474 "indirect offset type `%c' invalid",
475 *l);
476 break;
477 }
478 l++;
479 }
480 if (*l == '~') {
481 m->in_op = FILE_OPINVERSE;
482 l++;

--- 33 unchanged lines hidden (view full) ---

516 break;
517 }
518 if (isdigit((unsigned char)*l))
519 m->in_offset = (uint32_t)strtoul(l, &t, 0);
520 else
521 t = l;
522 if (*t++ != ')')
523 if (ms->flags & MAGIC_CHECK)
524 file_magwarn(ms,
525 "missing ')' in indirect offset");
526 l = t;
527 }
528
529
530 while (isascii((unsigned char)*l) && isdigit((unsigned char)*l))
531 ++l;
532 EATAB;
533

--- 8 unchanged lines hidden (view full) ---

542#define NLESHORT 7
543#define NLELONG 6
544#define NLEDATE 6
545#define NPSTRING 7
546#define NLDATE 5
547#define NBELDATE 7
548#define NLELDATE 7
549#define NREGEX 5
550#define NBESTRING16 10
551#define NLESTRING16 10
552
553 if (*l == 'u') {
554 ++l;
555 m->flag |= UNSIGNED;
556 }
557
558 /* get type, skip it */
559 if (strncmp(l, "char", NBYTE)==0) { /* HP/UX compat */

--- 41 unchanged lines hidden (view full) ---

601 } else if (strncmp(l, "beldate", NBELDATE)==0) {
602 m->type = FILE_BELDATE;
603 l += NBELDATE;
604 } else if (strncmp(l, "leldate", NLELDATE)==0) {
605 m->type = FILE_LELDATE;
606 l += NLELDATE;
607 } else if (strncmp(l, "regex", NREGEX)==0) {
608 m->type = FILE_REGEX;
609 l += NREGEX;
610 } else if (strncmp(l, "bestring16", NBESTRING16)==0) {
611 m->type = FILE_BESTRING16;
612 l += NBESTRING16;
613 } else if (strncmp(l, "lestring16", NLESTRING16)==0) {
614 m->type = FILE_LESTRING16;
615 l += NLESTRING16;
616 } else {
617 if (ms->flags & MAGIC_CHECK)
618 file_magwarn(ms, "type `%s' invalid", l);
619 return -1;
620 }
621 /* New-style anding: "0 byte&0x80 =0x80 dynamically linked" */
622 /* New and improved: ~ & | ^ + - * / % -- exciting, isn't it? */
623 if (*l == '~') {
624 if (!IS_STRING(m->type))
625 m->mask_op = FILE_OPINVERSE;
626 ++l;
627 }
628 if ((t = strchr(fops, *l)) != NULL) {
629 uint32_t op = (uint32_t)(t - fops);
630 if (op != FILE_OPDIVIDE || !IS_STRING(m->type)) {
631 ++l;
632 m->mask_op |= op;
633 val = (uint32_t)strtoul(l, &l, 0);
634 m->mask = file_signextend(ms, m, val);
635 eatsize(&l);
636 } else {
637 m->mask = 0L;
638 while (!isspace((unsigned char)*++l)) {

--- 5 unchanged lines hidden (view full) ---

644 m->mask |= STRING_COMPACT_BLANK;
645 break;
646 case CHAR_COMPACT_OPTIONAL_BLANK:
647 m->mask |=
648 STRING_COMPACT_OPTIONAL_BLANK;
649 break;
650 default:
651 if (ms->flags & MAGIC_CHECK)
652 file_magwarn(ms,
653 "string extension `%c' invalid",
654 *l);
655 return -1;
656 }
657 }
658 }
659 }
660 /*
661 * We used to set mask to all 1's here, instead let's just not do

--- 11 unchanged lines hidden (view full) ---

673 m->reln = *l;
674 ++l;
675 if (*l == '=') {
676 /* HP compat: ignore &= etc. */
677 ++l;
678 }
679 break;
680 case '!':
681 if (!IS_STRING(m->type)) {
682 m->reln = *l;
683 ++l;
684 break;
685 }
686 /*FALLTHROUGH*/
687 default:
688 if (*l == 'x' && isascii((unsigned char)l[1]) &&
689 isspace((unsigned char)l[1])) {

--- 27 unchanged lines hidden (view full) ---

717 ++l;
718 m->nospflag = 1;
719 } else
720 m->nospflag = 0;
721 while ((m->desc[i++] = *l++) != '\0' && i < MAXDESC)
722 /* NULLBODY */;
723
724 if (ms->flags & MAGIC_CHECK) {
725 if (!check_format(ms, m))
726 return -1;
727 }
728#ifndef COMPILE_ONLY
729 if (action == FILE_CHECK) {
730 file_mdump(m);
731 }
732#endif
733 ++(*nmagicp); /* make room for next */
734 return 0;
735}
736
737/*
738 * Check that the optional printf format in description matches
739 * the type of the magic.
740 */
741private int
742check_format(struct magic_set *ms, struct magic *m)
743{
744 static const char *formats[] = { FILE_FORMAT_STRING };
745 static const char *names[] = { FILE_FORMAT_NAME };
746 char *ptr;
747
748 for (ptr = m->desc; *ptr; ptr++)
749 if (*ptr == '%')
750 break;
751 if (*ptr == '\0') {
752 /* No format string; ok */
753 return 1;
754 }
755 if (m->type >= sizeof(formats)/sizeof(formats[0])) {
756 file_magwarn(ms, "Internal error inconsistency between m->type"
757 " and format strings");
758 return 0;
759 }
760 if (formats[m->type] == NULL) {
761 file_magwarn(ms, "No format string for `%s' with description "
762 "`%s'", m->desc, names[m->type]);
763 return 0;
764 }
765 for (; *ptr; ptr++) {
766 if (*ptr == 'l' || *ptr == 'h') {
767 /* XXX: we should really fix this one day */
768 continue;
769 }
770 if (islower((unsigned char)*ptr) || *ptr == 'X')
771 break;
772 }
773 if (*ptr == '\0') {
774 /* Missing format string; bad */
775 file_magwarn(ms, "Invalid format `%s' for type `%s'",
776 m->desc, names[m->type]);
777 return 0;
778 }
779 if (strchr(formats[m->type], *ptr) == NULL) {
780 file_magwarn(ms, "Printf format `%c' is not valid for type `%s'"
781 " in description `%s'",
782 *ptr, names[m->type], m->desc);
783 return 0;
784 }
785 return 1;
786}
787
788/*
789 * Read a numeric value from a pointer, into the value union of a magic
790 * pointer, according to the magic type. Update the string pointer to point
791 * just after the number read. Return 0 for success, non-zero for failure.
792 */
793private int
794getvalue(struct magic_set *ms, struct magic *m, char **p)
795{
796 int slen;
797
798 switch (m->type) {
799 case FILE_BESTRING16:
800 case FILE_LESTRING16:
801 case FILE_STRING:
802 case FILE_PSTRING:
803 case FILE_REGEX:
804 *p = getstr(ms, *p, m->value.s, sizeof(m->value.s), &slen);
805 if (*p == NULL) {
806 if (ms->flags & MAGIC_CHECK)
807 file_magwarn(ms, "cannot get string from `%s'",
808 m->value.s);
809 return -1;
810 }
811 m->vallen = slen;
812 return 0;
813 default:
814 if (m->reln != 'x') {
815 m->value.l = file_signextend(ms, m,

--- 215 unchanged lines hidden (view full) ---

1031 const char *fn)
1032{
1033 int fd;
1034 struct stat st;
1035 uint32_t *ptr;
1036 uint32_t version;
1037 int needsbyteswap;
1038 char buf[MAXPATHLEN];
1039 char *dbname = mkdbname(fn, buf, sizeof(buf), 0);
1040 void *mm = NULL;
1041
1042 if (dbname == NULL)
1043 return -1;
1044
1045 if ((fd = open(dbname, O_RDONLY)) == -1)
1046 return -1;
1047

--- 74 unchanged lines hidden (view full) ---

1122 * handle an mmaped file.
1123 */
1124private int
1125apprentice_compile(struct magic_set *ms, struct magic **magicp,
1126 uint32_t *nmagicp, const char *fn)
1127{
1128 int fd;
1129 char buf[MAXPATHLEN];
1130 char *dbname = mkdbname(fn, buf, sizeof(buf), 1);
1131
1132 if (dbname == NULL)
1133 return -1;
1134
1135 if ((fd = open(dbname, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) {
1136 file_error(ms, errno, "cannot open `%s'", dbname);
1137 return -1;
1138 }

--- 19 unchanged lines hidden (view full) ---

1158 return 0;
1159}
1160
1161private const char ext[] = ".mgc";
1162/*
1163 * make a dbname
1164 */
1165private char *
1166mkdbname(const char *fn, char *buf, size_t bufsiz, int strip)
1167{
1168 if (strip) {
1169 const char *p;
1170 if ((p = strrchr(fn, '/')) != NULL)
1171 fn = ++p;
1172 }
1173
1174 (void)snprintf(buf, bufsiz, "%s%s", fn, ext);
1175 return buf;
1176}
1177
1178/*
1179 * Byteswap an mmap'ed file if needed
1180 */
1181private void

--- 38 unchanged lines hidden (view full) ---

1220 * byteswap a single magic entry
1221 */
1222private void
1223bs1(struct magic *m)
1224{
1225 m->cont_level = swap2(m->cont_level);
1226 m->offset = swap4((uint32_t)m->offset);
1227 m->in_offset = swap4((uint32_t)m->in_offset);
1228 if (IS_STRING(m->type))
1229 m->value.l = swap4(m->value.l);
1230 m->mask = swap4(m->mask);
1231}