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