00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "file.h"
00033 #include "magic.h"
00034 #include <stdlib.h>
00035 #ifdef HAVE_UNISTD_H
00036 #include <unistd.h>
00037 #endif
00038 #include <string.h>
00039 #include <assert.h>
00040 #include <ctype.h>
00041 #include <fcntl.h>
00042 #include <sys/stat.h>
00043 #include <sys/param.h>
00044 #ifdef QUICK
00045 #include <sys/mman.h>
00046 #endif
00047
00048 #ifndef lint
00049 FILE_RCSID("@(#)$File: apprentice.c,v 1.104 2007/01/19 19:54:39 christos Exp $")
00050 #endif
00051
00052 #define EATAB {while (isascii((unsigned char) *l) && \
00053 isspace((unsigned char) *l)) ++l;}
00054 #define LOWCASE(l) (isupper((unsigned char) (l)) ? \
00055 tolower((unsigned char) (l)) : (l))
00056
00057
00058
00059
00060 #if defined(__osf__) && defined(__DECC)
00061 #ifdef MAP_FAILED
00062 #undef MAP_FAILED
00063 #endif
00064 #endif
00065
00066 #ifndef MAP_FAILED
00067 #define MAP_FAILED (void *) -1
00068 #endif
00069
00070 #ifndef MAP_FILE
00071 #define MAP_FILE 0
00072 #endif
00073
00074 #ifndef MAXPATHLEN
00075 #define MAXPATHLEN 1024
00076 #endif
00077
00078 struct magic_entry {
00079 struct magic *mp;
00080 uint32_t cont_count;
00081 uint32_t max_count;
00082 };
00083
00084
00085 int file_formats[FILE_NAMES_SIZE];
00086
00087 const size_t file_nformats = FILE_NAMES_SIZE;
00088
00089 const char *file_names[FILE_NAMES_SIZE];
00090
00091 const size_t file_nnames = FILE_NAMES_SIZE;
00092
00093
00094 private size_t maxmagic = 0;
00095
00096 private size_t magicsize = sizeof(struct magic);
00097
00098 private int getvalue(struct magic_set *ms, struct magic *m, const char **p,
00099 int action)
00100
00101 ;
00102 private int hextoint(int c)
00103 ;
00104
00105 private const char * getstr(struct magic_set *ms, const char *s, char *p,
00106 int plen, int *slen, int action)
00107
00108 ;
00109 private int parse(struct magic_set *ms, struct magic_entry **mentryp,
00110 uint32_t *nmentryp, const char *line, size_t lineno, int action)
00111
00112 ;
00113 private void eatsize(const char **p)
00114 ;
00115 private int apprentice_1(struct magic_set *ms, const char *fn, int action,
00116 struct mlist *mlist)
00117
00118 ;
00119 private size_t apprentice_magic_strength(const struct magic *m)
00120
00121 ;
00122 private int apprentice_sort(const void *a, const void *b)
00123
00124 ;
00125 private int apprentice_file(struct magic_set *ms, struct magic **magicp,
00126 uint32_t *nmagicp, const char *fn, int action)
00127
00128 ;
00129 private void byteswap(struct magic *magic, uint32_t nmagic)
00130 ;
00131 private void bs1(struct magic *m)
00132 ;
00133 private uint16_t swap2(uint16_t sv)
00134 ;
00135 private uint32_t swap4(uint32_t sv)
00136 ;
00137 private uint64_t swap8(uint64_t sv)
00138 ;
00139 private char * mkdbname(const char *fn, char *buf, size_t bufsiz, int strip)
00140 ;
00141 private int apprentice_map(struct magic_set *ms, struct magic **magicp,
00142 uint32_t *nmagicp, const char *fn)
00143
00144 ;
00145 private int apprentice_compile(struct magic_set *ms, struct magic **magicp,
00146 uint32_t *nmagicp, const char *fn)
00147
00148 ;
00149 private int check_format_type(const char *ptr, int type)
00150 ;
00151 private int check_format(struct magic_set *ms, struct magic *m)
00152 ;
00153
00154 #ifdef COMPILE_ONLY
00155
00156 int main(int, char *[]);
00157
00158 int
00159 main(int argc, char *argv[])
00160 {
00161 int ret;
00162 struct magic_set *ms;
00163 char *progname;
00164
00165 if ((progname = strrchr(argv[0], '/')) != NULL)
00166 progname++;
00167 else
00168 progname = argv[0];
00169
00170 if (argc != 2) {
00171 (void)fprintf(stderr, "Usage: %s file\n", progname);
00172 return 1;
00173 }
00174
00175 if ((ms = magic_open(MAGIC_CHECK)) == NULL) {
00176 (void)fprintf(stderr, "%s: %s\n", progname, strerror(errno));
00177 return 1;
00178 }
00179 ret = magic_compile(ms, argv[1]) == -1 ? 1 : 0;
00180 if (ret == 1)
00181 (void)fprintf(stderr, "%s: %s\n", progname, magic_error(ms));
00182 magic_close(ms);
00183 return ret;
00184 }
00185 #endif
00186
00187
00188 static const struct type_tbl_s {
00189
00190 const char *name;
00191 const size_t len;
00192 const int type;
00193 const int format;
00194 } type_tbl[] = {
00195 # define XX(s) s, (sizeof(s) - 1)
00196 # define XX_NULL NULL, 0
00197 { XX("byte"), FILE_BYTE, FILE_FMT_NUM },
00198 { XX("short"), FILE_SHORT, FILE_FMT_NUM },
00199 { XX("default"), FILE_DEFAULT, FILE_FMT_STR },
00200 { XX("long"), FILE_LONG, FILE_FMT_NUM },
00201 { XX("string"), FILE_STRING, FILE_FMT_STR },
00202 { XX("date"), FILE_DATE, FILE_FMT_STR },
00203 { XX("beshort"), FILE_BESHORT, FILE_FMT_NUM },
00204 { XX("belong"), FILE_BELONG, FILE_FMT_NUM },
00205 { XX("bedate"), FILE_BEDATE, FILE_FMT_STR },
00206 { XX("leshort"), FILE_LESHORT, FILE_FMT_NUM },
00207 { XX("lelong"), FILE_LELONG, FILE_FMT_NUM },
00208 { XX("ledate"), FILE_LEDATE, FILE_FMT_STR },
00209 { XX("pstring"), FILE_PSTRING, FILE_FMT_STR },
00210 { XX("ldate"), FILE_LDATE, FILE_FMT_STR },
00211 { XX("beldate"), FILE_BELDATE, FILE_FMT_STR },
00212 { XX("leldate"), FILE_LELDATE, FILE_FMT_STR },
00213 { XX("regex"), FILE_REGEX, FILE_FMT_STR },
00214 { XX("bestring16"), FILE_BESTRING16, FILE_FMT_STR },
00215 { XX("lestring16"), FILE_LESTRING16, FILE_FMT_STR },
00216 { XX("search"), FILE_SEARCH, FILE_FMT_STR },
00217 { XX("medate"), FILE_MEDATE, FILE_FMT_STR },
00218 { XX("meldate"), FILE_MELDATE, FILE_FMT_STR },
00219 { XX("melong"), FILE_MELONG, FILE_FMT_NUM },
00220 { XX("quad"), FILE_QUAD, FILE_FMT_QUAD },
00221 { XX("lequad"), FILE_LEQUAD, FILE_FMT_QUAD },
00222 { XX("bequad"), FILE_BEQUAD, FILE_FMT_QUAD },
00223 { XX("qdate"), FILE_QDATE, FILE_FMT_STR },
00224 { XX("leqdate"), FILE_LEQDATE, FILE_FMT_STR },
00225 { XX("beqdate"), FILE_BEQDATE, FILE_FMT_STR },
00226 { XX("qldate"), FILE_QLDATE, FILE_FMT_STR },
00227 { XX("leqldate"), FILE_LEQLDATE, FILE_FMT_STR },
00228 { XX("beqldate"), FILE_BEQLDATE, FILE_FMT_STR },
00229 { XX_NULL, FILE_INVALID, FILE_FMT_NONE },
00230 # undef XX
00231 # undef XX_NULL
00232 };
00233
00234 private int
00235 get_type(const char *l, const char **t)
00236
00237 {
00238 const struct type_tbl_s *p;
00239
00240 for (p = type_tbl; p->name; p++) {
00241 if (strncmp(l, p->name, p->len) == 0) {
00242 if (t)
00243 *t = l + p->len;
00244 break;
00245 }
00246 }
00247 return p->type;
00248 }
00249
00250 private void
00251 init_file_tables(void)
00252
00253
00254 {
00255 static int done = 0;
00256 const struct type_tbl_s *p;
00257
00258 if (done)
00259 return;
00260 done++;
00261
00262
00263 for (p = type_tbl; p->name; p++) {
00264 assert(p->type < FILE_NAMES_SIZE);
00265 file_names[p->type] = p->name;
00266 file_formats[p->type] = p->format;
00267 }
00268
00269 }
00270
00271
00272
00273
00274 private int
00275 apprentice_1(struct magic_set *ms, const char *fn, int action,
00276 struct mlist *mlist)
00277 {
00278 struct magic *magic = NULL;
00279 uint32_t nmagic = 0;
00280 struct mlist *ml;
00281 int rv = -1;
00282 int mapped;
00283
00284 if (magicsize != FILE_MAGICSIZE) {
00285 file_error(ms, 0, "magic element size %lu != %lu",
00286 (unsigned long)sizeof(*magic),
00287 (unsigned long)FILE_MAGICSIZE);
00288 return -1;
00289 }
00290
00291 if (action == FILE_COMPILE) {
00292 rv = apprentice_file(ms, &magic, &nmagic, fn, action);
00293 if (rv != 0)
00294 return -1;
00295 rv = apprentice_compile(ms, &magic, &nmagic, fn);
00296 free(magic);
00297 return rv;
00298 }
00299 #ifndef COMPILE_ONLY
00300 if ((rv = apprentice_map(ms, &magic, &nmagic, fn)) == -1) {
00301 if (ms->flags & MAGIC_CHECK)
00302 file_magwarn(ms, "using regular magic file `%s'", fn);
00303 rv = apprentice_file(ms, &magic, &nmagic, fn, action);
00304 if (rv != 0)
00305 return -1;
00306 mapped = 0;
00307 }
00308
00309 mapped = rv;
00310
00311 if (magic == NULL || nmagic == 0) {
00312 file_delmagic(magic, mapped, nmagic);
00313 return -1;
00314 }
00315
00316 if ((ml = malloc(sizeof(*ml))) == NULL) {
00317 file_delmagic(magic, mapped, nmagic);
00318 file_oomem(ms, sizeof(*ml));
00319 return -1;
00320 }
00321
00322 ml->magic = magic;
00323 ml->nmagic = nmagic;
00324 ml->mapped = mapped;
00325
00326 mlist->prev->next = ml;
00327 ml->prev = mlist->prev;
00328 ml->next = mlist;
00329 mlist->prev = ml;
00330
00331 return 0;
00332 #endif
00333 }
00334
00335 protected void
00336 file_delmagic(struct magic *p, int type, size_t entries)
00337 {
00338 if (p == NULL)
00339 return;
00340 switch (type) {
00341 case 2:
00342 p--;
00343 (void)munmap((void *)p, sizeof(*p) * (entries + 1));
00344 break;
00345 case 1:
00346 p--;
00347
00348 case 0:
00349 free(p);
00350 break;
00351 default:
00352 abort();
00353 }
00354 }
00355
00356
00357
00358 protected struct mlist *
00359 file_apprentice(struct magic_set *ms, const char *fn, int action)
00360 {
00361 char *p, *mfn, *afn = NULL;
00362 int file_err, errs = -1;
00363 struct mlist *mlist;
00364 static const char mime[] = ".mime";
00365
00366 init_file_tables();
00367
00368 if (fn == NULL)
00369 fn = getenv("MAGIC");
00370 if (fn == NULL)
00371 fn = MAGIC;
00372
00373 if ((fn = mfn = strdup(fn)) == NULL) {
00374 file_oomem(ms, strlen(fn));
00375 return NULL;
00376 }
00377
00378 if ((mlist = malloc(sizeof(*mlist))) == NULL) {
00379 free(mfn);
00380 file_oomem(ms, sizeof(*mlist));
00381 return NULL;
00382 }
00383 mlist->next = mlist->prev = mlist;
00384
00385 while (fn) {
00386 p = strchr(fn, PATHSEP);
00387 if (p)
00388 *p++ = '\0';
00389 if (*fn == '\0')
00390 break;
00391 if (ms->flags & MAGIC_MIME) {
00392 size_t len = strlen(fn) + sizeof(mime);
00393 if ((afn = malloc(len)) == NULL) {
00394 free(mfn);
00395 free(mlist);
00396 file_oomem(ms, len);
00397 return NULL;
00398 }
00399 (void)strcpy(afn, fn);
00400 (void)strcat(afn, mime);
00401 fn = afn;
00402 }
00403 file_err = apprentice_1(ms, fn, action, mlist);
00404 if (file_err > errs)
00405 errs = file_err;
00406 if (afn) {
00407 free(afn);
00408 afn = NULL;
00409 }
00410 fn = p;
00411 }
00412 if (errs == -1) {
00413 free(mfn);
00414 free(mlist);
00415 mlist = NULL;
00416 file_error(ms, 0, "could not find any magic files!");
00417 return NULL;
00418 }
00419 free(mfn);
00420 return mlist;
00421 }
00422
00423
00424
00425
00426 private size_t
00427 apprentice_magic_strength(const struct magic *m)
00428 {
00429 #define MULT 10
00430 size_t val = 2 * MULT;
00431
00432 switch (m->type) {
00433 case FILE_DEFAULT:
00434 return 0;
00435
00436 case FILE_BYTE:
00437 val += 1 * MULT;
00438 break;
00439
00440 case FILE_SHORT:
00441 case FILE_LESHORT:
00442 case FILE_BESHORT:
00443 val += 2 * MULT;
00444 break;
00445
00446 case FILE_LONG:
00447 case FILE_LELONG:
00448 case FILE_BELONG:
00449 case FILE_MELONG:
00450 val += 4 * MULT;
00451 break;
00452
00453 case FILE_PSTRING:
00454 case FILE_STRING:
00455 val += m->vallen * MULT;
00456 break;
00457
00458 case FILE_BESTRING16:
00459 case FILE_LESTRING16:
00460 val += m->vallen * MULT / 2;
00461 break;
00462
00463 case FILE_SEARCH:
00464 case FILE_REGEX:
00465 val += m->vallen;
00466 break;
00467
00468 case FILE_DATE:
00469 case FILE_LEDATE:
00470 case FILE_BEDATE:
00471 case FILE_MEDATE:
00472 case FILE_LDATE:
00473 case FILE_LELDATE:
00474 case FILE_BELDATE:
00475 case FILE_MELDATE:
00476 val += 4 * MULT;
00477 break;
00478
00479 case FILE_QUAD:
00480 case FILE_BEQUAD:
00481 case FILE_LEQUAD:
00482 case FILE_QDATE:
00483 case FILE_LEQDATE:
00484 case FILE_BEQDATE:
00485 case FILE_QLDATE:
00486 case FILE_LEQLDATE:
00487 case FILE_BEQLDATE:
00488 val += 8 * MULT;
00489 break;
00490
00491 default:
00492 val = 0;
00493 (void)fprintf(stderr, "Bad type %d\n", m->type);
00494 abort();
00495 }
00496
00497 switch (m->reln) {
00498 case 'x':
00499 val = 0;
00500 break;
00501
00502 case '!':
00503 case '=':
00504 val += MULT;
00505 break;
00506
00507 case '>':
00508 case '<':
00509 val -= 2 * MULT;
00510 break;
00511
00512 case '^':
00513 case '&':
00514 val -= MULT;
00515 break;
00516
00517 default:
00518 (void)fprintf(stderr, "Bad relation %c\n", m->reln);
00519 abort();
00520 }
00521
00522 if (val == 0)
00523 val = 1;
00524
00525 return val;
00526 }
00527
00528
00529
00530
00531 private int
00532 apprentice_sort(const void *a, const void *b)
00533 {
00534 const struct magic_entry *ma = a;
00535 const struct magic_entry *mb = b;
00536 size_t sa = apprentice_magic_strength(ma->mp);
00537 size_t sb = apprentice_magic_strength(mb->mp);
00538 if (sa == sb)
00539 return 0;
00540 else if (sa > sb)
00541 return -1;
00542 else
00543 return 1;
00544 }
00545
00546
00547
00548
00549
00550 private int
00551 apprentice_file(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
00552 const char *fn, int action)
00553 {
00554 private const char hdr[] =
00555 "cont\toffset\ttype\topcode\tmask\tvalue\tdesc";
00556 FILE *f;
00557 char line[BUFSIZ+1];
00558 int errs = 0;
00559 struct magic_entry *marray;
00560 uint32_t marraycount, i, mentrycount = 0;
00561 size_t lineno = 0;
00562
00563 ms->flags |= MAGIC_CHECK;
00564
00565 f = fopen(ms->file = fn, "r");
00566 if (f == NULL) {
00567 if (errno != ENOENT)
00568 file_error(ms, errno, "cannot read magic file `%s'",
00569 fn);
00570 return -1;
00571 }
00572
00573 maxmagic = MAXMAGIS;
00574 if ((marray = calloc(maxmagic, sizeof(*marray))) == NULL) {
00575 (void)fclose(f);
00576 file_oomem(ms, maxmagic * sizeof(*marray));
00577 return -1;
00578 }
00579 marraycount = 0;
00580
00581
00582 if (action == FILE_CHECK)
00583 (void)fprintf(stderr, "%s\n", hdr);
00584
00585
00586 for (ms->line = 1; fgets(line, BUFSIZ, f) != NULL; ms->line++) {
00587 size_t len;
00588 len = strlen(line);
00589 if (len == 0)
00590 continue;
00591 if (line[len - 1] == '\n') {
00592 lineno++;
00593 line[len - 1] = '\0';
00594 }
00595 if (line[0] == '\0')
00596 continue;
00597 if (line[0] == '#')
00598 continue;
00599 if (parse(ms, &marray, &marraycount, line, lineno, action) != 0)
00600 errs++;
00601 }
00602
00603 (void)fclose(f);
00604 if (errs)
00605 goto out;
00606
00607 #ifndef NOORDER
00608 qsort(marray, marraycount, sizeof(*marray), apprentice_sort);
00609
00610
00611
00612 for (i = 0; i < marraycount; i++) {
00613 if (marray[i].mp->cont_level == 0 &&
00614 marray[i].mp->type == FILE_DEFAULT) {
00615 while (++i < marraycount)
00616 if (marray[i].mp->cont_level == 0)
00617 break;
00618 if (i != marraycount) {
00619 ms->line = marray[i].mp->lineno;
00620 file_magwarn(ms,
00621 "level 0 \"default\" did not sort last");
00622 }
00623 break;
00624 }
00625 }
00626 #endif
00627
00628 for (i = 0; i < marraycount; i++)
00629 mentrycount += marray[i].cont_count;
00630
00631 if ((*magicp = malloc(sizeof(**magicp) * mentrycount)) == NULL) {
00632 file_oomem(ms, sizeof(**magicp) * mentrycount);
00633 errs++;
00634 goto out;
00635 }
00636
00637 mentrycount = 0;
00638 for (i = 0; i < marraycount; i++) {
00639 (void)memcpy(*magicp + mentrycount, marray[i].mp,
00640 marray[i].cont_count * sizeof(**magicp));
00641 mentrycount += marray[i].cont_count;
00642 }
00643 out:
00644 for (i = 0; i < marraycount; i++)
00645 free(marray[i].mp);
00646 free(marray);
00647 if (errs) {
00648 *magicp = NULL;
00649 *nmagicp = 0;
00650 return errs;
00651 } else {
00652 *nmagicp = mentrycount;
00653 return 0;
00654 }
00655
00656 }
00657
00658
00659
00660
00661 protected uint64_t
00662 file_signextend(struct magic_set *ms, struct magic *m, uint64_t v)
00663 {
00664 if (!(m->flag & UNSIGNED)) {
00665 switch(m->type) {
00666
00667
00668
00669
00670
00671 case FILE_BYTE:
00672 v = (char) v;
00673 break;
00674 case FILE_SHORT:
00675 case FILE_BESHORT:
00676 case FILE_LESHORT:
00677 v = (short) v;
00678 break;
00679 case FILE_DATE:
00680 case FILE_BEDATE:
00681 case FILE_LEDATE:
00682 case FILE_MEDATE:
00683 case FILE_LDATE:
00684 case FILE_BELDATE:
00685 case FILE_LELDATE:
00686 case FILE_MELDATE:
00687 case FILE_LONG:
00688 case FILE_BELONG:
00689 case FILE_LELONG:
00690 case FILE_MELONG:
00691 v = (int32_t) v;
00692 break;
00693 case FILE_QUAD:
00694 case FILE_BEQUAD:
00695 case FILE_LEQUAD:
00696 case FILE_QDATE:
00697 case FILE_QLDATE:
00698 case FILE_BEQDATE:
00699 case FILE_BEQLDATE:
00700 case FILE_LEQDATE:
00701 case FILE_LEQLDATE:
00702 v = (int64_t) v;
00703 break;
00704 case FILE_STRING:
00705 case FILE_PSTRING:
00706 case FILE_BESTRING16:
00707 case FILE_LESTRING16:
00708 case FILE_REGEX:
00709 case FILE_SEARCH:
00710 case FILE_DEFAULT:
00711 break;
00712 default:
00713 if (ms->flags & MAGIC_CHECK)
00714 file_magwarn(ms, "cannot happen: m->type=%d\n",
00715 m->type);
00716 return ~0U;
00717 }
00718 }
00719 return v;
00720 }
00721
00722 private int
00723 string_modifier_check(struct magic_set *ms, struct magic const *m)
00724
00725
00726 {
00727 if ((ms->flags & MAGIC_CHECK) == 0)
00728 return 0;
00729
00730 switch (m->type) {
00731 case FILE_BESTRING16:
00732 case FILE_LESTRING16:
00733 if (m->str_flags != 0) {
00734 file_magwarn(ms, "no modifiers allowed for 16-bit strings\n");
00735 return -1;
00736 }
00737 break;
00738 case FILE_STRING:
00739 case FILE_PSTRING:
00740 if ((m->str_flags & REGEX_OFFSET_START) != 0) {
00741 file_magwarn(ms, "'/%c' only allowed on regex and search\n",
00742 CHAR_REGEX_OFFSET_START);
00743 return -1;
00744 }
00745 break;
00746 case FILE_SEARCH:
00747 break;
00748 case FILE_REGEX:
00749 if ((m->str_flags & STRING_COMPACT_BLANK) != 0) {
00750 file_magwarn(ms, "'/%c' not allowed on regex\n",
00751 CHAR_COMPACT_BLANK);
00752 return -1;
00753 }
00754 if ((m->str_flags & STRING_COMPACT_OPTIONAL_BLANK) != 0) {
00755 file_magwarn(ms, "'/%c' not allowed on regex\n",
00756 CHAR_COMPACT_OPTIONAL_BLANK);
00757 return -1;
00758 }
00759 break;
00760 default:
00761 file_magwarn(ms, "coding error: m->type=%d\n",
00762 m->type);
00763 return -1;
00764 }
00765 return 0;
00766 }
00767
00768 private int
00769 get_op(char c)
00770
00771 {
00772 switch (c) {
00773 case '&':
00774 return FILE_OPAND;
00775 case '|':
00776 return FILE_OPOR;
00777 case '^':
00778 return FILE_OPXOR;
00779 case '+':
00780 return FILE_OPADD;
00781 case '-':
00782 return FILE_OPMINUS;
00783 case '*':
00784 return FILE_OPMULTIPLY;
00785 case '/':
00786 return FILE_OPDIVIDE;
00787 case '%':
00788 return FILE_OPMODULO;
00789 default:
00790 return -1;
00791 }
00792 }
00793
00794 #ifdef ENABLE_CONDITIONALS
00795 private int
00796 get_cond(const char *l, const char **t)
00797
00798 {
00799
00800 static struct cond_tbl_s {
00801
00802 const char *name;
00803 const size_t len;
00804 const int cond;
00805 } cond_tbl[] = {
00806 { "if", 2, COND_IF },
00807 { "elif", 4, COND_ELIF },
00808 { "else", 4, COND_ELSE },
00809 { NULL, 0, COND_NONE },
00810 };
00811 struct cond_tbl_s *p;
00812
00813 for (p = cond_tbl; p->name; p++) {
00814 if (strncmp(l, p->name, p->len) == 0 &&
00815 isspace((unsigned char)l[p->len])) {
00816 if (t)
00817 *t = l + p->len;
00818 break;
00819 }
00820 }
00821 return p->cond;
00822 }
00823
00824 private int
00825 check_cond(struct magic_set *ms, int cond, uint32_t cont_level)
00826
00827
00828 {
00829 int last_cond;
00830 last_cond = ms->c.li[cont_level].last_cond;
00831
00832 switch (cond) {
00833 case COND_IF:
00834 if (last_cond != COND_NONE && last_cond != COND_ELIF) {
00835 if (ms->flags & MAGIC_CHECK)
00836 file_magwarn(ms, "syntax error: `if'");
00837 return -1;
00838 }
00839 last_cond = COND_IF;
00840 break;
00841
00842 case COND_ELIF:
00843 if (last_cond != COND_IF && last_cond != COND_ELIF) {
00844 if (ms->flags & MAGIC_CHECK)
00845 file_magwarn(ms, "syntax error: `elif'");
00846 return -1;
00847 }
00848 last_cond = COND_ELIF;
00849 break;
00850
00851 case COND_ELSE:
00852 if (last_cond != COND_IF && last_cond != COND_ELIF) {
00853 if (ms->flags & MAGIC_CHECK)
00854 file_magwarn(ms, "syntax error: `else'");
00855 return -1;
00856 }
00857 last_cond = COND_NONE;
00858 break;
00859
00860 case COND_NONE:
00861 last_cond = COND_NONE;
00862 break;
00863 }
00864
00865 ms->c.li[cont_level].last_cond = last_cond;
00866 return 0;
00867 }
00868 #endif
00869
00870
00871
00872
00873 private int
00874 parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp,
00875 const char *line, size_t lineno, int action)
00876 {
00877 #ifdef ENABLE_CONDITIONALS
00878 static uint32_t last_cont_level = 0;
00879 #endif
00880 size_t i;
00881 struct magic_entry *me;
00882 struct magic *m;
00883 const char *l = line;
00884 char *t;
00885 int op;
00886 uint32_t cont_level;
00887
00888 cont_level = 0;
00889
00890 while (*l == '>') {
00891 ++l;
00892 cont_level++;
00893 }
00894 #ifdef ENABLE_CONDITIONALS
00895 if (cont_level == 0 || cont_level > last_cont_level)
00896 if (file_check_mem(ms, cont_level) == -1)
00897 return -1;
00898 last_cont_level = cont_level;
00899 #endif
00900
00901 #define ALLOC_CHUNK (size_t)10
00902 #define ALLOC_INCR (size_t)200
00903
00904 if (cont_level != 0) {
00905 if (*nmentryp == 0) {
00906 file_error(ms, 0, "No current entry for continuation");
00907 return -1;
00908 }
00909 me = &(*mentryp)[*nmentryp - 1];
00910 if (me->cont_count == me->max_count) {
00911 struct magic *nm;
00912 size_t cnt = me->max_count + ALLOC_CHUNK;
00913 if ((nm = realloc(me->mp, sizeof(*nm) * cnt)) == NULL) {
00914 file_oomem(ms, sizeof(*nm) * cnt);
00915 return -1;
00916 }
00917 me->mp = m = nm;
00918 me->max_count = cnt;
00919 }
00920 m = &me->mp[me->cont_count++];
00921 (void)memset(m, 0, sizeof(*m));
00922 m->cont_level = cont_level;
00923 } else {
00924 if (*nmentryp == maxmagic) {
00925 struct magic_entry *mp;
00926
00927 maxmagic += ALLOC_INCR;
00928 if ((mp = realloc(*mentryp, sizeof(*mp) * maxmagic)) ==
00929 NULL) {
00930 file_oomem(ms, sizeof(*mp) * maxmagic);
00931 return -1;
00932 }
00933 (void)memset(&mp[*nmentryp], 0, sizeof(*mp) *
00934 ALLOC_INCR);
00935 *mentryp = mp;
00936 }
00937 me = &(*mentryp)[*nmentryp];
00938 if (me->mp == NULL) {
00939 if ((m = malloc(sizeof(*m) * ALLOC_CHUNK)) == NULL) {
00940 file_oomem(ms, sizeof(*m) * ALLOC_CHUNK);
00941 return -1;
00942 }
00943 me->mp = m;
00944 me->max_count = ALLOC_CHUNK;
00945 } else
00946 m = me->mp;
00947 (void)memset(m, 0, sizeof(*m));
00948 m->cont_level = 0;
00949 me->cont_count = 1;
00950 }
00951 m->lineno = lineno;
00952
00953 if (*l == '&') {
00954 ++l;
00955 m->flag |= OFFADD;
00956 }
00957 if (*l == '(') {
00958 ++l;
00959 m->flag |= INDIR;
00960 if (m->flag & OFFADD)
00961 m->flag = (m->flag & ~OFFADD) | INDIROFFADD;
00962
00963 if (*l == '&') {
00964 ++l;
00965 m->flag |= OFFADD;
00966 }
00967 }
00968
00969 if (m->cont_level == 0 && (m->flag & (OFFADD | INDIROFFADD)))
00970 if (ms->flags & MAGIC_CHECK)
00971 file_magwarn(ms, "relative offset at level 0");
00972
00973
00974 m->offset = (uint32_t)strtoul(l, &t, 0);
00975 if (l == t)
00976 if (ms->flags & MAGIC_CHECK)
00977 file_magwarn(ms, "offset `%s' invalid", l);
00978 l = t;
00979
00980 if (m->flag & INDIR) {
00981 m->in_type = FILE_LONG;
00982 m->in_offset = 0;
00983
00984
00985
00986 if (*l == '.') {
00987 l++;
00988 switch (*l) {
00989 case 'l':
00990 m->in_type = FILE_LELONG;
00991 break;
00992 case 'L':
00993 m->in_type = FILE_BELONG;
00994 break;
00995 case 'm':
00996 m->in_type = FILE_MELONG;
00997 break;
00998 case 'h':
00999 case 's':
01000 m->in_type = FILE_LESHORT;
01001 break;
01002 case 'H':
01003 case 'S':
01004 m->in_type = FILE_BESHORT;
01005 break;
01006 case 'c':
01007 case 'b':
01008 case 'C':
01009 case 'B':
01010 m->in_type = FILE_BYTE;
01011 break;
01012 default:
01013 if (ms->flags & MAGIC_CHECK)
01014