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 #include "system.h"
00029 #include "file.h"
00030 #include "debug.h"
00031
00032 FILE_RCSID("@(#)Id: apprentice.c,v 1.49 2002/07/03 19:00:41 christos Exp ")
00033
00034
00035
00036 #define EATAB {while (isascii((unsigned char) *l) && \
00037 isspace((unsigned char) *l)) ++l;}
00038 #define LOWCASE(l) (isupper((unsigned char) (l)) ? \
00039 tolower((unsigned char) (l)) : (l))
00040
00041
00042
00043
00044 #if defined(__osf__) && defined(__DECC)
00045 #ifdef MAP_FAILED
00046 #undef MAP_FAILED
00047 #endif
00048 #endif
00049
00050 #ifndef MAP_FAILED
00051 #define MAP_FAILED (void *) -1
00052 #endif
00053
00054 #ifndef MAP_FILE
00055 #define MAP_FILE 0
00056 #endif
00057
00058
00059 #ifdef __EMX__
00060 static char PATHSEP=';';
00061 #else
00062 static char PATHSEP=':';
00063 #endif
00064
00065
00066 static int maxmagic = 0;
00067
00068 #ifndef MAGIC
00069 # define MAGIC "/etc/magic"
00070 #endif
00071
00072
00073 const char *default_magicfile = MAGIC;
00074
00075
00076
00077
00078 uint32_t
00079 signextend(struct magic *m, uint32_t v)
00080 {
00081 if (!(m->flag & UNSIGNED))
00082 switch(m->type) {
00083
00084
00085
00086
00087
00088 case BYTE:
00089 v = (char) v;
00090 break;
00091 case SHORT:
00092 case BESHORT:
00093 case LESHORT:
00094 v = (short) v;
00095 break;
00096 case DATE:
00097 case BEDATE:
00098 case LEDATE:
00099 case LDATE:
00100 case BELDATE:
00101 case LELDATE:
00102 case LONG:
00103 case BELONG:
00104 case LELONG:
00105 v = (int32_t) v;
00106 break;
00107 case STRING:
00108 case PSTRING:
00109 break;
00110 case REGEX:
00111 break;
00112 default:
00113 magwarn("can't happen: m->type=%d\n", m->type);
00114 return -1;
00115 }
00116 return v;
00117 }
00118
00119
00120
00121
00122
00123 static void
00124 eatsize( char **p)
00125
00126 {
00127 char *l = *p;
00128
00129 if (LOWCASE(*l) == 'u')
00130 l++;
00131
00132 switch (LOWCASE(*l)) {
00133 case 'l':
00134 case 's':
00135 case 'h':
00136 case 'b':
00137 case 'c':
00138 l++;
00139
00140 default:
00141 break;
00142 }
00143
00144 *p = l;
00145 }
00146
00147
00148
00149 static int
00150 hextoint(int c)
00151
00152 {
00153 if (!isascii((unsigned char) c))
00154 return -1;
00155 if (isdigit((unsigned char) c))
00156 return c - '0';
00157 if ((c >= 'a')&&(c <= 'f'))
00158 return c + 10 - 'a';
00159 if (( c>= 'A')&&(c <= 'F'))
00160 return c + 10 - 'A';
00161 return -1;
00162 }
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172 static char *
00173 getstr( char *s, char *p, int plen, int *slen)
00174
00175
00176 {
00177 char *origs = s, *origp = p;
00178 char *pmax = p + plen - 1;
00179 int c;
00180 int val;
00181
00182 while ((c = *s++) != '\0') {
00183 if (isspace((unsigned char) c))
00184 break;
00185 if (p >= pmax) {
00186 fprintf(stderr, "String too long: %s\n", origs);
00187 break;
00188 }
00189 if(c == '\\') {
00190 switch(c = *s++) {
00191
00192 case '\0':
00193 goto out;
00194
00195 default:
00196 *p++ = (char) c;
00197 break;
00198
00199 case 'n':
00200 *p++ = '\n';
00201 break;
00202
00203 case 'r':
00204 *p++ = '\r';
00205 break;
00206
00207 case 'b':
00208 *p++ = '\b';
00209 break;
00210
00211 case 't':
00212 *p++ = '\t';
00213 break;
00214
00215 case 'f':
00216 *p++ = '\f';
00217 break;
00218
00219 case 'v':
00220 *p++ = '\v';
00221 break;
00222
00223
00224 case '0':
00225 case '1':
00226 case '2':
00227 case '3':
00228 case '4':
00229 case '5':
00230 case '6':
00231 case '7':
00232 val = c - '0';
00233 c = *s++;
00234 if(c >= '0' && c <= '7') {
00235 val = (val<<3) | (c - '0');
00236 c = *s++;
00237 if(c >= '0' && c <= '7')
00238 val = (val<<3) | (c-'0');
00239 else
00240 --s;
00241 }
00242 else
00243 --s;
00244 *p++ = (char)val;
00245 break;
00246
00247
00248 case 'x':
00249 val = 'x';
00250 c = hextoint(*s++);
00251 if (c >= 0) {
00252 val = c;
00253 c = hextoint(*s++);
00254 if (c >= 0)
00255 val = (val << 4) + c;
00256 else
00257 --s;
00258 } else
00259 --s;
00260 *p++ = (char)val;
00261 break;
00262 }
00263 } else
00264 *p++ = (char)c;
00265 }
00266 out:
00267 *p = '\0';
00268 *slen = p - origp;
00269 return s;
00270 }
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280 static int
00281 getvalue(struct magic *m, char **p)
00282
00283
00284 {
00285 int slen;
00286
00287 if (m->type == STRING || m->type == PSTRING || m->type == REGEX) {
00288 *p = getstr(*p, m->value.s, sizeof(m->value.s), &slen);
00289 m->vallen = slen;
00290 } else
00291 if (m->reln != 'x') {
00292 m->value.l = signextend(m, strtoul(*p, p, 0));
00293 eatsize(p);
00294 }
00295 return 0;
00296 }
00297
00298
00299
00300
00301
00302
00303 static int
00304 parse( struct magic **magicp, uint32_t *nmagicp,
00305 char *l, int action)
00306
00307
00308 {
00309 int i = 0;
00310 struct magic *m;
00311 char *t;
00312
00313 #define ALLOC_INCR 200
00314 if (*nmagicp + 1 >= maxmagic){
00315 maxmagic += ALLOC_INCR;
00316
00317 *magicp = xrealloc(*magicp, sizeof(**magicp) * maxmagic);
00318
00319 m = &(*magicp)[*nmagicp];
00320 memset(m, 0, sizeof(**magicp) * ALLOC_INCR);
00321 } else
00322 m = &(*magicp)[*nmagicp];
00323 m->flag = 0;
00324 m->cont_level = 0;
00325
00326 while (*l == '>') {
00327 ++l;
00328 m->cont_level++;
00329 }
00330
00331 if (m->cont_level != 0 && *l == '(') {
00332 ++l;
00333 m->flag |= INDIR;
00334 }
00335 if (m->cont_level != 0 && *l == '&') {
00336 ++l;
00337 m->flag |= OFFADD;
00338 }
00339
00340
00341 m->offset = (int) strtoul(l,&t,0);
00342 if (l == t)
00343 magwarn("offset %s invalid", l);
00344 l = t;
00345
00346 if (m->flag & INDIR) {
00347 m->in_type = LONG;
00348 m->in_offset = 0;
00349
00350
00351
00352 if (*l == '.') {
00353 l++;
00354 switch (*l) {
00355 case 'l':
00356 m->in_type = LELONG;
00357 break;
00358 case 'L':
00359 m->in_type = BELONG;
00360 break;
00361 case 'h':
00362 case 's':
00363 m->in_type = LESHORT;
00364 break;
00365 case 'H':
00366 case 'S':
00367 m->in_type = BESHORT;
00368 break;
00369 case 'c':
00370 case 'b':
00371 case 'C':
00372 case 'B':
00373 m->in_type = BYTE;
00374 break;
00375 default:
00376 magwarn("indirect offset type %c invalid", *l);
00377 break;
00378 }
00379 l++;
00380 }
00381 if (*l == '~') {
00382 m->in_op = OPINVERSE;
00383 l++;
00384 }
00385 switch (*l) {
00386 case '&':
00387 m->in_op |= OPAND;
00388 l++;
00389 break;
00390 case '|':
00391 m->in_op |= OPOR;
00392 l++;
00393 break;
00394 case '^':
00395 m->in_op |= OPXOR;
00396 l++;
00397 break;
00398 case '+':
00399 m->in_op |= OPADD;
00400 l++;
00401 break;
00402 case '-':
00403 m->in_op |= OPMINUS;
00404 l++;
00405 break;
00406 case '*':
00407 m->in_op |= OPMULTIPLY;
00408 l++;
00409 break;
00410 case '/':
00411 m->in_op |= OPDIVIDE;
00412 l++;
00413 break;
00414 case '%':
00415 m->in_op |= OPMODULO;
00416 l++;
00417 break;
00418 }
00419 if (isdigit((unsigned char)*l))
00420 m->in_offset = strtoul(l, &t, 0);
00421 else
00422 t = l;
00423 if (*t++ != ')')
00424 magwarn("missing ')' in indirect offset");
00425 l = t;
00426 }
00427
00428
00429 while (isascii((unsigned char)*l) && isdigit((unsigned char)*l))
00430 ++l;
00431 EATAB;
00432
00433 #define NBYTE 4
00434 #define NSHORT 5
00435 #define NLONG 4
00436 #define NSTRING 6
00437 #define NDATE 4
00438 #define NBESHORT 7
00439 #define NBELONG 6
00440 #define NBEDATE 6
00441 #define NLESHORT 7
00442 #define NLELONG 6
00443 #define NLEDATE 6
00444 #define NPSTRING 7
00445 #define NLDATE 5
00446 #define NBELDATE 7
00447 #define NLELDATE 7
00448 #define NREGEX 5
00449
00450 if (*l == 'u') {
00451 ++l;
00452 m->flag |= UNSIGNED;
00453 }
00454
00455
00456 if (strncmp(l, "char", NBYTE)==0) {
00457 m->type = BYTE;
00458 l += NBYTE;
00459 } else if (strncmp(l, "byte", NBYTE)==0) {
00460 m->type = BYTE;
00461 l += NBYTE;
00462 } else if (strncmp(l, "short", NSHORT)==0) {
00463 m->type = SHORT;
00464 l += NSHORT;
00465 } else if (strncmp(l, "long", NLONG)==0) {
00466 m->type = LONG;
00467 l += NLONG;
00468 } else if (strncmp(l, "string", NSTRING)==0) {
00469 m->type = STRING;
00470 l += NSTRING;
00471 } else if (strncmp(l, "date", NDATE)==0) {
00472 m->type = DATE;
00473 l += NDATE;
00474 } else if (strncmp(l, "beshort", NBESHORT)==0) {
00475 m->type = BESHORT;
00476 l += NBESHORT;
00477 } else if (strncmp(l, "belong", NBELONG)==0) {
00478 m->type = BELONG;
00479 l += NBELONG;
00480 } else if (strncmp(l, "bedate", NBEDATE)==0) {
00481 m->type = BEDATE;
00482 l += NBEDATE;
00483 } else if (strncmp(l, "leshort", NLESHORT)==0) {
00484 m->type = LESHORT;
00485 l += NLESHORT;
00486 } else if (strncmp(l, "lelong", NLELONG)==0) {
00487 m->type = LELONG;
00488 l += NLELONG;
00489 } else if (strncmp(l, "ledate", NLEDATE)==0) {
00490 m->type = LEDATE;
00491 l += NLEDATE;
00492 } else if (strncmp(l, "pstring", NPSTRING)==0) {
00493 m->type = PSTRING;
00494 l += NPSTRING;
00495 } else if (strncmp(l, "ldate", NLDATE)==0) {
00496 m->type = LDATE;
00497 l += NLDATE;
00498 } else if (strncmp(l, "beldate", NBELDATE)==0) {
00499 m->type = BELDATE;
00500 l += NBELDATE;
00501 } else if (strncmp(l, "leldate", NLELDATE)==0) {
00502 m->type = LELDATE;
00503 l += NLELDATE;
00504 } else if (strncmp(l, "regex", NREGEX)==0) {
00505 m->type = REGEX;
00506 l += sizeof("regex");
00507 } else {
00508 magwarn("type %s invalid", l);
00509 return -1;
00510 }
00511
00512
00513 if (*l == '~') {
00514 if (STRING != m->type && PSTRING != m->type)
00515 m->mask_op = OPINVERSE;
00516 ++l;
00517 }
00518 switch (*l) {
00519 case '&':
00520 m->mask_op |= OPAND;
00521 ++l;
00522 m->mask = signextend(m, strtoul(l, &l, 0));
00523 eatsize(&l);
00524 break;
00525 case '|':
00526 m->mask_op |= OPOR;
00527 ++l;
00528 m->mask = signextend(m, strtoul(l, &l, 0));
00529 eatsize(&l);
00530 break;
00531 case '^':
00532 m->mask_op |= OPXOR;
00533 ++l;
00534 m->mask = signextend(m, strtoul(l, &l, 0));
00535 eatsize(&l);
00536 break;
00537 case '+':
00538 m->mask_op |= OPADD;
00539 ++l;
00540 m->mask = signextend(m, strtoul(l, &l, 0));
00541 eatsize(&l);
00542 break;
00543 case '-':
00544 m->mask_op |= OPMINUS;
00545 ++l;
00546 m->mask = signextend(m, strtoul(l, &l, 0));
00547 eatsize(&l);
00548 break;
00549 case '*':
00550 m->mask_op |= OPMULTIPLY;
00551 ++l;
00552 m->mask = signextend(m, strtoul(l, &l, 0));
00553 eatsize(&l);
00554 break;
00555 case '%':
00556 m->mask_op |= OPMODULO;
00557 ++l;
00558 m->mask = signextend(m, strtoul(l, &l, 0));
00559 eatsize(&l);
00560 break;
00561 case '/':
00562 if (STRING != m->type && PSTRING != m->type) {
00563 m->mask_op |= OPDIVIDE;
00564 ++l;
00565 m->mask = signextend(m, strtoul(l, &l, 0));
00566 eatsize(&l);
00567 } else {
00568 m->mask = 0L;
00569 while (!isspace(*++l)) {
00570 switch (*l) {
00571 case CHAR_IGNORE_LOWERCASE:
00572 m->mask |= STRING_IGNORE_LOWERCASE;
00573 break;
00574 case CHAR_COMPACT_BLANK:
00575 m->mask |= STRING_COMPACT_BLANK;
00576 break;
00577 case CHAR_COMPACT_OPTIONAL_BLANK:
00578 m->mask |=
00579 STRING_COMPACT_OPTIONAL_BLANK;
00580 break;
00581 default:
00582 magwarn("string extension %c invalid",
00583 *l);
00584 return -1;
00585 }
00586 }
00587 }
00588 break;
00589 }
00590
00591
00592 EATAB;
00593
00594 switch (*l) {
00595 case '>':
00596 case '<':
00597
00598 case '&':
00599 case '^':
00600 case '=':
00601 m->reln = *l;
00602 ++l;
00603 if (*l == '=') {
00604
00605 ++l;
00606 }
00607 break;
00608 case '!':
00609 if (m->type != STRING && m->type != PSTRING) {
00610 m->reln = *l;
00611 ++l;
00612 break;
00613 }
00614
00615 default:
00616 if (*l == 'x' && isascii((unsigned char)l[1]) &&
00617 isspace((unsigned char)l[1])) {
00618 m->reln = *l;
00619 ++l;
00620 goto GetDesc;
00621 }
00622 m->reln = '=';
00623 break;
00624 }
00625 EATAB;
00626
00627 if (getvalue(m, &l))
00628 return -1;
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638 GetDesc:
00639 EATAB;
00640 if (l[0] == '\b') {
00641 ++l;
00642 m->nospflag = 1;
00643 } else if ((l[0] == '\\') && (l[1] == 'b')) {
00644 ++l;
00645 ++l;
00646 m->nospflag = 1;
00647 } else
00648 m->nospflag = 0;
00649 while ((m->desc[i++] = *l++) != '\0' && i<MAXDESC)
00650 {};
00651
00652 #ifndef COMPILE_ONLY
00653 if (action == CHECK) {
00654 mdump(m);
00655 }
00656 #endif
00657 ++(*nmagicp);
00658 return 0;
00659 }
00660
00661
00662
00663
00664
00665 void
00666 showstr(FILE *fp, const char *s, int len)
00667 {
00668 char c;
00669
00670 for (;;) {
00671 c = *s++;
00672 if (len == -1) {
00673 if (c == '\0')
00674 break;
00675 }
00676 else {
00677 if (len-- == 0)
00678 break;
00679 }
00680 if(c >= 040 && c <= 0176)
00681 (void) fputc(c, fp);
00682 else {
00683 (void) fputc('\\', fp);
00684 switch (c) {
00685
00686 case '\n':
00687 (void) fputc('n', fp);
00688 break;
00689
00690 case '\r':
00691 (void) fputc('r', fp);
00692 break;
00693
00694 case '\b':
00695 (void) fputc('b', fp);
00696 break;
00697
00698 case '\t':
00699 (void) fputc('t', fp);
00700 break;
00701
00702 case '\f':
00703 (void) fputc('f', fp);
00704 break;
00705
00706 case '\v':
00707 (void) fputc('v', fp);
00708 break;
00709
00710 default:
00711 (void) fprintf(fp, "%.3o", c & 0377);
00712 break;
00713 }
00714 }
00715 }
00716 }
00717
00718
00719
00720
00721
00722 static uint16_t
00723 swap2(uint16_t sv)
00724
00725 {
00726 uint16_t rv;
00727 uint8_t *s = (uint8_t *) &sv;
00728 uint8_t *d = (uint8_t *) &rv;
00729 d[0] = s[1];
00730 d[1] = s[0];
00731 return rv;
00732 }
00733
00734
00735
00736
00737
00738
00739 static uint32_t
00740 swap4(uint32_t sv)
00741
00742 {
00743 uint32_t rv;
00744 uint8_t *s = (uint8_t *) &sv;
00745 uint8_t *d = (uint8_t *) &rv;
00746 d[0] = s[3];
00747 d[1] = s[2];
00748 d[2] = s[1];
00749 d[3] = s[0];
00750 return rv;
00751 }
00752
00753
00754
00755
00756
00757 static
00758 void bs1(struct magic *m)
00759
00760 {
00761 m->cont_level = swap2(m->cont_level);
00762 m->offset = swap4(m->offset);
00763 m->in_offset = swap4(m->in_offset);
00764 if (m->type != STRING)
00765 m->value.l = swap4(m->value.l);
00766 m->mask = swap4(m->mask);
00767 }
00768
00769
00770
00771
00772
00773 static void
00774 byteswap( struct magic *m, uint32_t nmagic)
00775
00776 {
00777 uint32_t i;
00778 if (m != NULL)
00779 for (i = 0; i < nmagic; i++)
00780 bs1(&m[i]);
00781 }
00782
00783
00784
00785
00786
00787 static char *
00788 mkdbname(const char *fn)
00789
00790 {
00791 static const char ext[] = ".mgc";
00792
00793 static char *buf = NULL;
00794
00795 buf = xrealloc(buf, strlen(fn) + sizeof(ext) + 1);
00796 (void)strcpy(buf, fn);
00797 (void)strcat(buf, ext);
00798 return buf;
00799 }
00800
00801
00802
00803
00804
00805
00806 static int
00807 apprentice_file(fmagic fm, struct magic **magicp,
00808 uint32_t *nmagicp, const char *fn, int action)
00809
00810
00811 {
00812
00813 static const char hdr[] =
00814 "cont\toffset\ttype\topcode\tmask\tvalue\tdesc";
00815 FILE *f;
00816 char line[BUFSIZ+1];
00817 int errs = 0;
00818
00819 f = fopen(fn, "r");
00820 if (f == NULL) {
00821 if (errno != ENOENT)
00822 (void) fprintf(stderr,
00823 "%s: can't read magic file %s (%s)\n",
00824 __progname, fn, strerror(errno));
00825 return -1;
00826 }
00827
00828 maxmagic = MAXMAGIS;
00829 *magicp = (struct magic *) xcalloc(sizeof(**magicp), maxmagic);
00830
00831
00832 if (action == CHECK)
00833 (void) printf("%s\n", hdr);
00834
00835 for (fm->lineno = 1; fgets(line, BUFSIZ, f) != NULL; fm->lineno++) {
00836 if (line[0]=='#')
00837 continue;
00838 if (strlen(line) <= (unsigned)1)
00839 continue;
00840 line[strlen(line)-1] = '\0';
00841 if (parse(magicp, nmagicp, line, action) != 0)
00842 errs = 1;
00843 }
00844
00845 (void) fclose(f);
00846 if (errs) {
00847 free(*magicp);
00848 *magicp = NULL;
00849 *nmagicp = 0;
00850 }
00851 return errs;
00852 }
00853
00854
00855
00856
00857
00858
00859 static int
00860 apprentice_compile( const fmagic fm,
00861 struct magic **magicp, uint32_t *nmagicp,
00862 const char *fn, int action)
00863
00864
00865 {
00866 int fd;
00867 char *dbname = mkdbname(fn);
00868
00869 static const uint32_t ar[] = {
00870 MAGICNO, VERSIONNO
00871 };
00872
00873 if (dbname == NULL)
00874 return -1;
00875
00876 if ((fd = open(dbname, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) {
00877 (void)fprintf(stderr, "%s: Cannot open `%s' (%s)\n",
00878 __progname, dbname, strerror(errno));
00879 return -1;
00880 }
00881
00882 if (write(fd, ar, sizeof(ar)) != sizeof(ar)) {
00883 (void)fprintf(stderr, "%s: error writing `%s' (%s)\n",
00884 __progname, dbname, strerror(errno));
00885 return -1;
00886 }
00887
00888 if (lseek(fd, sizeof(**magicp), SEEK_SET) != sizeof(**magicp)) {
00889 (void)fprintf(stderr, "%s: error seeking `%s' (%s)\n",
00890 __progname, dbname, strerror(errno));
00891 return -1;
00892 }
00893
00894 if (write(fd, *magicp, sizeof(**magicp) * *nmagicp)
00895 != sizeof(**magicp) * *nmagicp) {
00896 (void)fprintf(stderr, "%s: error writing `%s' (%s)\n",
00897 __progname, dbname, strerror(errno));
00898 return -1;
00899 }
00900
00901 (void)close(fd);
00902 return 0;
00903 }
00904
00905
00906
00907
00908
00909
00910 static int
00911 apprentice_map( const fmagic fm,
00912 struct magic **magicp, uint32_t *nmagicp,
00913 const char *fn, int action)
00914
00915
00916 {
00917 int fd;
00918 struct stat st;
00919 uint32_t *ptr;
00920 uint32_t version;
00921 int needsbyteswap;
00922 char *dbname = mkdbname(fn);
00923 void *mm = NULL;
00924
00925 if (dbname == NULL)
00926 return -1;
00927
00928 if ((fd = open(dbname, O_RDONLY)) == -1)
00929 return -1;
00930
00931 if (fstat(fd, &st) == -1) {
00932 (void)fprintf(stderr, "%s: Cannot stat `%s' (%s)\n",
00933 __progname, dbname, strerror(errno));
00934 goto errxit;
00935 }
00936
00937 #ifdef HAVE_MMAP
00938 if ((mm = mmap(0, (size_t)st.st_size, PROT_READ|PROT_WRITE,
00939 MAP_PRIVATE|MAP_FILE, fd, (off_t)0)) == MAP_FAILED) {
00940 (void)fprintf(stderr, "%s: Cannot map `%s' (%s)\n",
00941 __progname, dbname, strerror(errno));
00942 goto errxit;
00943 }
00944 #else
00945 mm = xmalloc((size_t)st.st_size);
00946 if (read(fd, mm, (size_t)st.st_size) != (size_t)st.st_size) {
00947 (void) fprintf(stderr, "%s: Read failed (%s).\n", __progname,
00948 strerror(errno));
00949 goto errxit;
00950 }
00951 #endif
00952 *magicp = mm;
00953 (void)close(fd);
00954 fd = -1;
00955 ptr = (uint32_t *) *magicp;
00956 if (ptr == NULL)
00957 goto errxit;
00958 if (*ptr != MAGICNO) {
00959 if (swap4(*ptr) != MAGICNO) {
00960 (void)fprintf(stderr, "%s: Bad magic in `%s'\n",
00961 __progname, dbname);
00962 goto errxit;
00963 }
00964 needsbyteswap = 1;
00965 } else
00966 needsbyteswap = 0;
00967 if (needsbyteswap)
00968 version = swap4(ptr[1]);
00969 else
00970 version = ptr[1];
00971 if (version != VERSIONNO) {
00972 (void)fprintf(stderr,
00973 "%s: version mismatch (%d != %d) in `%s'\n",
00974 __progname, version, VERSIONNO, dbname);
00975 goto errxit;
00976 }
00977 *nmagicp = (st.st_size / sizeof(**magicp)) - 1;
00978 (*magicp)++;
00979 if (needsbyteswap)
00980 byteswap(*magicp, *nmagicp);
00981 return 0;
00982
00983 errxit:
00984 if (fd != -1)
00985 (void)close(fd);
00986
00987 if (mm != NULL) {
00988 #ifdef HAVE_MMAP
00989 (void)munmap(mm, (size_t)st.st_size);
00990 #else
00991 free(mm);
00992 #endif
00993 } else {
00994 *magicp = NULL;
00995 *nmagicp = 0;
00996 }
00997
00998 return -1;
00999 }
01000
01001
01002
01003
01004
01005 static int
01006 apprentice_1(fmagic fm, const char *fn, int action)
01007
01008
01009 {
01010
01011 struct magic *magic = NULL;
01012 uint32_t nmagic = 0;
01013
01014 struct mlist *ml;
01015 int rv = -1;
01016
01017 if (action == COMPILE) {
01018 rv = apprentice_file(fm, &magic, &nmagic, fn, action);
01019 if (rv)
01020 return rv;
01021 return apprentice_compile(fm, &magic, &nmagic, fn, action);
01022 }
01023 #ifndef COMPILE_ONLY
01024 if ((rv = apprentice_map(fm, &magic, &nmagic, fn, action)) != 0)
01025 (void)fprintf(stderr, "%s: Using regular magic file `%s'\n",
01026 __progname, fn);
01027
01028 if (rv != 0)
01029 rv = apprentice_file(fm, &magic, &nmagic, fn, action);
01030
01031 if (rv != 0)
01032 return rv;
01033
01034 if (magic == NULL || nmagic == 0)
01035 return rv;
01036
01037 ml = xmalloc(sizeof(*ml));
01038
01039 ml->magic = magic;
01040 ml->nmagic = nmagic;
01041
01042 fm->mlist->prev->next = ml;
01043 ml->prev = fm->mlist->prev;
01044
01045 ml->next = fm->mlist;
01046
01047
01048 fm->mlist->prev = ml;
01049
01050
01051
01052 return rv;
01053
01054 #endif
01055 }
01056
01057
01058 int
01059 fmagicSetup(fmagic fm, const char *fn, int action)
01060 {
01061 char *p, *mfn;
01062 int file_err, errs = -1;
01063
01064 if (fm->mlist == NULL) {
01065 static struct mlist mlist;
01066
01067 mlist.next = &mlist;
01068 mlist.prev = &mlist;
01069 fm->mlist = &mlist;
01070
01071 }
01072
01073 mfn = xstrdup(fn);
01074 fn = mfn;
01075
01076
01077 while (fn != NULL) {
01078 p = strchr(fn, PATHSEP);
01079 if (p != NULL)
01080 *p++ = '\0';
01081 file_err = apprentice_1(fm, fn, action);
01082 if (file_err > errs)
01083 errs = file_err;
01084 fn = p;
01085 }
01086
01087 if (errs == -1)
01088 (void) fprintf(stderr, "%s: couldn't find any magic files!\n",
01089 __progname);
01090 if (action == CHECK && errs)
01091 exit(EXIT_FAILURE);
01092
01093 free(mfn);
01094
01095 return errs;
01096
01097 }
01098
01099 #ifdef COMPILE_ONLY
01100 int
01101 main(int argc, char *argv[])
01102
01103 {
01104 static struct fmagic_s myfmagic;
01105 fmagic fm = &myfmagic;
01106 int ret;
01107
01108 setprogname(argv[0]);
01109
01110 if (argc != 2) {
01111 (void)fprintf(stderr, "usage: %s file\n", __progname);
01112 exit(1);
01113 }
01114 fm->magicfile = argv[1];
01115
01116 exit(apprentice(fm, fm->magicfile, COMPILE));
01117 }
01118 #endif