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 <string.h>
00035 #include <ctype.h>
00036 #include <stdlib.h>
00037 #include <time.h>
00038
00039
00040 #ifndef lint
00041 FILE_RCSID("@(#)$File: softmagic.c,v 1.99 2007/05/08 14:44:18 christos Exp $")
00042 #endif
00043
00044 private int match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
00045 const unsigned char *s, size_t nbytes)
00046
00047 ;
00048 private int mget(struct magic_set *ms, const unsigned char *s,
00049 struct magic *m, size_t nbytes, unsigned int cont_level)
00050
00051 ;
00052 private int magiccheck(struct magic_set *ms, struct magic *m)
00053
00054 ;
00055 private int32_t mprint(struct magic_set *ms, struct magic *m)
00056
00057 ;
00058 private void mdebug(uint32_t offset, const char *str, size_t len)
00059
00060 ;
00061 private int mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
00062 const unsigned char *s, uint32_t offset, size_t nbytes, size_t linecnt)
00063 ;
00064 private int mconvert(struct magic_set *ms, struct magic *m)
00065 ;
00066 private int print_sep(struct magic_set *ms, int firstline)
00067 ;
00068 private void cvt_8(union VALUETYPE *p, const struct magic *m)
00069 ;
00070 private void cvt_16(union VALUETYPE *p, const struct magic *m)
00071 ;
00072 private void cvt_32(union VALUETYPE *p, const struct magic *m)
00073 ;
00074 private void cvt_64(union VALUETYPE *p, const struct magic *m)
00075 ;
00076
00077
00078
00079
00080
00081
00082 protected int
00083 file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes)
00084 {
00085 struct mlist *ml;
00086 int rv;
00087 for (ml = ms->mlist->next; ml != ms->mlist; ml = ml->next)
00088 if ((rv = match(ms, ml->magic, ml->nmagic, buf, nbytes)) != 0)
00089 return rv;
00090
00091 return 0;
00092 }
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121 private int
00122 match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
00123 const unsigned char *s, size_t nbytes)
00124 {
00125 uint32_t magindex = 0;
00126 unsigned int cont_level = 0;
00127 int need_separator = 0;
00128 int returnval = 0;
00129 int firstline = 1;
00130 int printed_something = 0;
00131
00132 if (file_check_mem(ms, cont_level) == -1)
00133 return -1;
00134
00135 for (magindex = 0; magindex < nmagic; magindex++) {
00136 int flush;
00137
00138 ms->offset = magic[magindex].offset;
00139 ms->line = magic[magindex].lineno;
00140
00141
00142 flush = !mget(ms, s, &magic[magindex], nbytes, cont_level);
00143 if (flush) {
00144 if (magic[magindex].reln == '!')
00145 flush = 0;
00146 } else {
00147 switch (magiccheck(ms, &magic[magindex])) {
00148 case -1:
00149 return -1;
00150 case 0:
00151 flush++;
00152 break;
00153 default:
00154 break;
00155 }
00156 }
00157 if (flush) {
00158
00159
00160
00161
00162 while (magindex < nmagic - 1 &&
00163 magic[magindex + 1].cont_level != 0)
00164 magindex++;
00165 continue;
00166 }
00167
00168
00169
00170
00171
00172 if (magic[magindex].desc[0]) {
00173 need_separator = 1;
00174 printed_something = 1;
00175 if (print_sep(ms, firstline) == -1)
00176 return -1;
00177 }
00178
00179 if ((ms->c.li[cont_level].off = mprint(ms, &magic[magindex]))
00180 == -1)
00181 return -1;
00182
00183
00184 if (file_check_mem(ms, ++cont_level) == -1)
00185 return -1;
00186
00187 while (magic[magindex+1].cont_level != 0 &&
00188 ++magindex < nmagic) {
00189 ms->line = magic[magindex].lineno;
00190
00191 if (cont_level < magic[magindex].cont_level)
00192 continue;
00193 if (cont_level > magic[magindex].cont_level) {
00194
00195
00196
00197
00198 cont_level = magic[magindex].cont_level;
00199 }
00200 ms->offset = magic[magindex].offset;
00201 if (magic[magindex].flag & OFFADD) {
00202 ms->offset +=
00203 ms->c.li[cont_level - 1].off;
00204 }
00205
00206 #ifdef ENABLE_CONDITIONALS
00207 if (magic[magindex].cond == COND_ELSE ||
00208 magic[magindex].cond == COND_ELIF) {
00209 if (ms->c.li[cont_level].last_match == 1)
00210 continue;
00211 }
00212 #endif
00213 flush = !mget(ms, s, &magic[magindex], nbytes,
00214 cont_level);
00215 if (flush && magic[magindex].reln != '!')
00216 continue;
00217
00218 switch (flush ? 1 : magiccheck(ms, &magic[magindex])) {
00219 case -1:
00220 return -1;
00221 case 0:
00222 #ifdef ENABLE_CONDITIONALS
00223 ms->c.li[cont_level].last_match = 0;
00224 #endif
00225 break;
00226 default:
00227 #ifdef ENABLE_CONDITIONALS
00228 ms->c.li[cont_level].last_match = 1;
00229 #endif
00230 if (magic[magindex].type != FILE_DEFAULT)
00231 ms->c.li[cont_level].got_match = 1;
00232 else if (ms->c.li[cont_level].got_match) {
00233 ms->c.li[cont_level].got_match = 0;
00234 break;
00235 }
00236
00237
00238
00239
00240 if (magic[magindex].desc[0]) {
00241 printed_something = 1;
00242 if (print_sep(ms, firstline) == -1)
00243 return -1;
00244 }
00245
00246
00247
00248
00249
00250
00251
00252 if (need_separator
00253 && (magic[magindex].nospflag == 0)
00254 && (magic[magindex].desc[0] != '\0')) {
00255 if (file_printf(ms, " ") == -1)
00256 return -1;
00257 need_separator = 0;
00258 }
00259 if ((ms->c.li[cont_level].off = mprint(ms, &magic[magindex])) == -1)
00260 return -1;
00261 if (magic[magindex].desc[0])
00262 need_separator = 1;
00263
00264
00265
00266
00267
00268
00269 if (file_check_mem(ms, ++cont_level) == -1)
00270 return -1;
00271 break;
00272 }
00273 }
00274 firstline = 0;
00275 if (printed_something)
00276 returnval = 1;
00277 if ((ms->flags & MAGIC_CONTINUE) == 0 && printed_something) {
00278 return 1;
00279 }
00280 }
00281 return returnval;
00282 }
00283
00284 private int
00285 check_fmt(struct magic_set *ms, struct magic *m)
00286
00287 {
00288 regex_t rx;
00289 int rc;
00290
00291 if (strchr(m->desc, '%') == NULL)
00292 return 0;
00293
00294 rc = regcomp(&rx, "%[-0-9\\.]*s", REG_EXTENDED|REG_NOSUB);
00295 if (rc) {
00296 char errmsg[512];
00297 (void)regerror(rc, &rx, errmsg, sizeof(errmsg));
00298 file_magerror(ms, "regex error %d, (%s)", rc, errmsg);
00299 return -1;
00300 } else {
00301 rc = regexec(&rx, m->desc, 0, 0, 0);
00302 regfree(&rx);
00303 return !rc;
00304 }
00305 }
00306
00307 #ifndef HAVE_STRNDUP
00308 char * strndup(const char *, size_t);
00309
00310 char *
00311 strndup(const char *str, size_t n)
00312 {
00313 size_t len;
00314 char *copy;
00315
00316 len = strlen(str);
00317 if (len > n)
00318 len = n;
00319 if (!(copy = malloc(len + 1)))
00320 return (NULL);
00321 (void) memcpy(copy, str, len + 1);
00322 copy[len] = '\0';
00323 return (copy);
00324 }
00325 #endif
00326
00327 private int32_t
00328 mprint(struct magic_set *ms, struct magic *m)
00329 {
00330 uint64_t v;
00331 int64_t t = 0;
00332 char buf[512];
00333 union VALUETYPE *p = &ms->ms_value;
00334
00335 switch (m->type) {
00336 case FILE_BYTE:
00337 v = file_signextend(ms, m, (uint64_t)p->b);
00338 switch (check_fmt(ms, m)) {
00339 case -1:
00340 return -1;
00341 case 1:
00342 if (snprintf(buf, sizeof(buf), "%c",
00343 (unsigned char)v) < 0)
00344 return -1;
00345 if (file_printf(ms, m->desc, buf) == -1)
00346 return -1;
00347 break;
00348 default:
00349 if (file_printf(ms, m->desc, (unsigned char) v) == -1)
00350 return -1;
00351 break;
00352 }
00353 t = ms->offset + sizeof(char);
00354 break;
00355
00356 case FILE_SHORT:
00357 case FILE_BESHORT:
00358 case FILE_LESHORT:
00359 v = file_signextend(ms, m, (uint64_t)p->h);
00360 switch (check_fmt(ms, m)) {
00361 case -1:
00362 return -1;
00363 case 1:
00364 if (snprintf(buf, sizeof(buf), "%hu",
00365 (unsigned short)v) < 0)
00366 return -1;
00367 if (file_printf(ms, m->desc, buf) == -1)
00368 return -1;
00369 break;
00370 default:
00371 if (file_printf(ms, m->desc, (unsigned short) v) == -1)
00372 return -1;
00373 break;
00374 }
00375 t = ms->offset + sizeof(short);
00376 break;
00377
00378 case FILE_LONG:
00379 case FILE_BELONG:
00380 case FILE_LELONG:
00381 case FILE_MELONG:
00382 v = file_signextend(ms, m, (uint64_t)p->l);
00383 switch (check_fmt(ms, m)) {
00384 case -1:
00385 return -1;
00386 case 1:
00387 if (snprintf(buf, sizeof(buf), "%u", (uint32_t)v) < 0)
00388 return -1;
00389 if (file_printf(ms, m->desc, buf) == -1)
00390 return -1;
00391 break;
00392 default:
00393 if (file_printf(ms, m->desc, (uint32_t) v) == -1)
00394 return -1;
00395 break;
00396 }
00397 t = ms->offset + sizeof(int32_t);
00398 break;
00399
00400 case FILE_QUAD:
00401 case FILE_BEQUAD:
00402 case FILE_LEQUAD:
00403 v = file_signextend(ms, m, p->q);
00404 if (file_printf(ms, m->desc, (uint64_t) v) == -1)
00405 return -1;
00406 t = ms->offset + sizeof(int64_t);
00407 break;
00408
00409 case FILE_STRING:
00410 case FILE_PSTRING:
00411 case FILE_BESTRING16:
00412 case FILE_LESTRING16:
00413 if (m->reln == '=' || m->reln == '!') {
00414 if (file_printf(ms, m->desc, m->value.s) == -1)
00415 return -1;
00416 t = ms->offset + m->vallen;
00417 }
00418 else {
00419 if (*m->value.s == '\0') {
00420 char *cp = strchr(p->s,'\n');
00421 if (cp)
00422 *cp = '\0';
00423 }
00424 if (file_printf(ms, m->desc, p->s) == -1)
00425 return -1;
00426 t = ms->offset + strlen(p->s);
00427 }
00428 break;
00429
00430 case FILE_DATE:
00431 case FILE_BEDATE:
00432 case FILE_LEDATE:
00433 case FILE_MEDATE:
00434 if (file_printf(ms, m->desc, file_fmttime(p->l, 1)) == -1)
00435 return -1;
00436 t = ms->offset + sizeof(time_t);
00437 break;
00438
00439 case FILE_LDATE:
00440 case FILE_BELDATE:
00441 case FILE_LELDATE:
00442 case FILE_MELDATE:
00443 if (file_printf(ms, m->desc, file_fmttime(p->l, 0)) == -1)
00444 return -1;
00445 t = ms->offset + sizeof(time_t);
00446 break;
00447
00448 case FILE_QDATE:
00449 case FILE_BEQDATE:
00450 case FILE_LEQDATE:
00451 if (file_printf(ms, m->desc, file_fmttime((uint32_t)p->q, 1))
00452 == -1)
00453 return -1;
00454 t = ms->offset + sizeof(uint64_t);
00455 break;
00456
00457 case FILE_QLDATE:
00458 case FILE_BEQLDATE:
00459 case FILE_LEQLDATE:
00460 if (file_printf(ms, m->desc, file_fmttime((uint32_t)p->q, 0))
00461 == -1)
00462 return -1;
00463 t = ms->offset + sizeof(uint64_t);
00464 break;
00465
00466 case FILE_REGEX: {
00467 char *cp;
00468 int rval;
00469
00470 cp = strndup((const char *)ms->search.s, ms->search.rm_len);
00471 if (cp == NULL) {
00472 file_oomem(ms, ms->search.rm_len);
00473 return -1;
00474 }
00475 rval = file_printf(ms, m->desc, cp);
00476 free(cp);
00477
00478 if (rval == -1)
00479 return -1;
00480
00481 if ((m->str_flags & REGEX_OFFSET_START))
00482 t = ms->search.offset;
00483 else
00484 t = ms->search.offset + ms->search.rm_len;
00485 break;
00486 }
00487
00488 case FILE_SEARCH:
00489 if (file_printf(ms, m->desc, m->value.s) == -1)
00490 return -1;
00491 if ((m->str_flags & REGEX_OFFSET_START))
00492 t = ms->search.offset;
00493 else
00494 t = ms->search.offset + m->vallen;
00495 break;
00496
00497 case FILE_DEFAULT:
00498 if (file_printf(ms, m->desc, m->value.s) == -1)
00499 return -1;
00500 t = ms->offset;
00501 break;
00502
00503 default:
00504 file_magerror(ms, "invalid m->type (%d) in mprint()", m->type);
00505 return -1;
00506 }
00507 return(t);
00508 }
00509
00510
00511 #define DO_CVT(fld, cast) \
00512 if (m->num_mask) \
00513 switch (m->mask_op & FILE_OPS_MASK) { \
00514 case FILE_OPAND: \
00515 p->fld &= cast m->num_mask; \
00516 break; \
00517 case FILE_OPOR: \
00518 p->fld |= cast m->num_mask; \
00519 break; \
00520 case FILE_OPXOR: \
00521 p->fld ^= cast m->num_mask; \
00522 break; \
00523 case FILE_OPADD: \
00524 p->fld += cast m->num_mask; \
00525 break; \
00526 case FILE_OPMINUS: \
00527 p->fld -= cast m->num_mask; \
00528 break; \
00529 case FILE_OPMULTIPLY: \
00530 p->fld *= cast m->num_mask; \
00531 break; \
00532 case FILE_OPDIVIDE: \
00533 p->fld /= cast m->num_mask; \
00534 break; \
00535 case FILE_OPMODULO: \
00536 p->fld %= cast m->num_mask; \
00537 break; \
00538 } \
00539 if (m->mask_op & FILE_OPINVERSE) \
00540 p->fld = ~p->fld \
00541
00542 private void
00543 cvt_8(union VALUETYPE *p, const struct magic *m)
00544 {
00545 DO_CVT(b, (uint8_t));
00546 }
00547
00548 private void
00549 cvt_16(union VALUETYPE *p, const struct magic *m)
00550 {
00551 DO_CVT(h, (uint16_t));
00552 }
00553
00554 private void
00555 cvt_32(union VALUETYPE *p, const struct magic *m)
00556 {
00557 DO_CVT(l, (uint32_t));
00558 }
00559
00560 private void
00561 cvt_64(union VALUETYPE *p, const struct magic *m)
00562 {
00563 DO_CVT(q, (uint64_t));
00564 }
00565
00566
00567
00568
00569
00570
00571 private int
00572 mconvert(struct magic_set *ms, struct magic *m)
00573 {
00574 union VALUETYPE *p = &ms->ms_value;
00575
00576 switch (m->type) {
00577 case FILE_BYTE:
00578 cvt_8(p, m);
00579 return 1;
00580 case FILE_SHORT:
00581 cvt_16(p, m);
00582 return 1;
00583 case FILE_LONG:
00584 case FILE_DATE:
00585 case FILE_LDATE:
00586 cvt_32(p, m);
00587 return 1;
00588 case FILE_QUAD:
00589 case FILE_QDATE:
00590 case FILE_QLDATE:
00591 cvt_64(p, m);
00592 return 1;
00593 case FILE_STRING:
00594 case FILE_BESTRING16:
00595 case FILE_LESTRING16: {
00596 size_t len;
00597
00598
00599 p->s[sizeof(p->s) - 1] = '\0';
00600 len = strlen(p->s);
00601 if (len-- && p->s[len] == '\n')
00602 p->s[len] = '\0';
00603 return 1;
00604 }
00605 case FILE_PSTRING: {
00606 char *ptr1 = p->s, *ptr2 = ptr1 + 1;
00607 size_t len = *p->s;
00608 if (len >= sizeof(p->s))
00609 len = sizeof(p->s) - 1;
00610 while (len--)
00611 *ptr1++ = *ptr2++;
00612 *ptr1 = '\0';
00613 len = strlen(p->s);
00614 if (len-- && p->s[len] == '\n')
00615 p->s[len] = '\0';
00616 return 1;
00617 }
00618 case FILE_BESHORT:
00619 p->h = (short)((p->hs[0]<<8)|(p->hs[1]));
00620 cvt_16(p, m);
00621 return 1;
00622 case FILE_BELONG:
00623 case FILE_BEDATE:
00624 case FILE_BELDATE:
00625 p->l = (int32_t)
00626 ((p->hl[0]<<24)|(p->hl[1]<<16)|(p->hl[2]<<8)|(p->hl[3]));
00627 cvt_32(p, m);
00628 return 1;
00629 case FILE_BEQUAD:
00630 case FILE_BEQDATE:
00631 case FILE_BEQLDATE:
00632 p->q = (int64_t)
00633 (((int64_t)p->hq[0]<<56)|((int64_t)p->hq[1]<<48)|
00634 ((int64_t)p->hq[2]<<40)|((int64_t)p->hq[3]<<32)|
00635 (p->hq[4]<<24)|(p->hq[5]<<16)|(p->hq[6]<<8)|(p->hq[7]));
00636 cvt_64(p, m);
00637 return 1;
00638 case FILE_LESHORT:
00639 p->h = (short)((p->hs[1]<<8)|(p->hs[0]));
00640 cvt_16(p, m);
00641 return 1;
00642 case FILE_LELONG:
00643 case FILE_LEDATE:
00644 case FILE_LELDATE:
00645 p->l = (int32_t)
00646 ((p->hl[3]<<24)|(p->hl[2]<<16)|(p->hl[1]<<8)|(p->hl[0]));
00647 cvt_32(p, m);
00648 return 1;
00649 case FILE_LEQUAD:
00650 case FILE_LEQDATE:
00651 case FILE_LEQLDATE:
00652 p->q = (int64_t)
00653 (((int64_t)p->hq[7]<<56)|((int64_t)p->hq[6]<<48)|
00654 ((int64_t)p->hq[5]<<40)|((int64_t)p->hq[4]<<32)|
00655 (p->hq[3]<<24)|(p->hq[2]<<16)|(p->hq[1]<<8)|(p->hq[0]));
00656 cvt_64(p, m);
00657 return 1;
00658 case FILE_MELONG:
00659 case FILE_MEDATE:
00660 case FILE_MELDATE:
00661 p->l = (int32_t)
00662 ((p->hl[1]<<24)|(p->hl[0]<<16)|(p->hl[3]<<8)|(p->hl[2]));
00663 cvt_32(p, m);
00664 return 1;
00665 case FILE_REGEX:
00666 case FILE_SEARCH:
00667 case FILE_DEFAULT:
00668 return 1;
00669 default:
00670 file_magerror(ms, "invalid type %d in mconvert()", m->type);
00671 return 0;
00672 }
00673 }
00674
00675
00676 private void
00677 mdebug(uint32_t offset, const char *str, size_t len)
00678 {
00679 (void) fprintf(stderr, "mget @%d: ", offset);
00680 file_showstr(stderr, str, len);
00681 (void) fputc('\n', stderr);
00682 (void) fputc('\n', stderr);
00683 }
00684
00685 private int
00686 mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
00687 const unsigned char *s, uint32_t offset, size_t nbytes, size_t linecnt)
00688 {
00689
00690
00691
00692
00693 if (indir == 0) {
00694 switch (type) {
00695 case FILE_SEARCH:
00696 ms->search.s = (const char *)s + offset;
00697 ms->search.s_len = nbytes - offset;
00698 return 0;
00699
00700 case FILE_REGEX: {
00701
00702
00703
00704
00705 const char *b;
00706 const char *c;
00707 const char *last;
00708 const char *buf;
00709 size_t lines;
00710
00711 if (s == NULL) {
00712 ms->search.s_len = 0;
00713 ms->search.s = NULL;
00714 return 0;
00715 }
00716 buf = (const char *)s + offset;
00717 last = (const char *)s + nbytes;
00718
00719 for (lines = linecnt, b = buf;
00720 lines && ((b = strchr(c = b, '\n')) || (b = strchr(c, '\r')));
00721 lines--, b++) {
00722 last = b;
00723 if (b[0] == '\r' && b[1] == '\n')
00724 b++;
00725 }
00726 if (lines)
00727 last = (const char *)s + nbytes;
00728
00729 ms->search.s = buf;
00730 ms->search.s_len = last - buf;
00731 ms->search.offset = offset;
00732 ms->search.rm_len = 0;
00733 return 0;
00734 }
00735 case FILE_BESTRING16:
00736 case FILE_LESTRING16: {
00737 const unsigned char *src = s + offset;
00738 const unsigned char *esrc = s + nbytes;
00739 char *dst = p->s;
00740 char *edst = &p->s[sizeof(p->s) - 1];
00741
00742 if (type == FILE_BESTRING16)
00743 src++;
00744
00745
00746 if (src < s) {
00747 file_magerror(ms, "invalid offset %zu in mcopy()",
00748 offset);
00749 return -1;
00750 }
00751 for (; src < esrc; src++, dst++) {
00752 if (dst < edst)
00753 *dst = *src++;
00754 else
00755 break;
00756 if (*dst == '\0')
00757 *dst = ' ';
00758 }
00759 *edst = '\0';
00760 return 0;
00761 }
00762 case FILE_STRING:
00763 case FILE_PSTRING:
00764 default:
00765 break;
00766 }
00767 }
00768
00769 if (offset >= nbytes) {
00770 (void)memset(p, '\0', sizeof(*p));
00771 return 0;
00772 }
00773 if (nbytes - offset < sizeof(*p))
00774 nbytes = nbytes - offset;
00775 else
00776 nbytes = sizeof(*p);
00777
00778 (void)memcpy(p, s + offset, nbytes);
00779
00780
00781
00782
00783
00784 if (nbytes < sizeof(*p))
00785 (void)memset(((char *)(void *)p) + nbytes, '\0',
00786 sizeof(*p) - nbytes);
00787 return 0;
00788 }
00789
00790 private int
00791 mget(struct magic_set *ms, const unsigned char *s,
00792 struct magic *m, size_t nbytes, unsigned int cont_level)
00793 {
00794 uint32_t offset = ms->offset;
00795 uint32_t count = m->str_count;
00796 union VALUETYPE *p = &ms->ms_value;
00797
00798 if (mcopy(ms, p, m->type, m->flag & INDIR, s, offset, nbytes, count) == -1)
00799 return -1;
00800
00801 if ((ms->flags & MAGIC_DEBUG) != 0) {
00802 mdebug(offset, (char *)(void *)p, sizeof(union VALUETYPE));
00803 file_mdump(m);
00804 }
00805
00806 if (m->flag & INDIR) {
00807 int off = m->in_offset;
00808 if (m->in_op & FILE_OPINDIRECT) {
00809 const union VALUETYPE *q =
00810 ((const void *)(s + offset + off));
00811 switch (m->in_type) {
00812 case FILE_BYTE:
00813 off = q->b;
00814 break;
00815 case FILE_SHORT:
00816 off = q->h;
00817 break;
00818 case FILE_BESHORT:
00819 off = (short)((q->hs[0]<<8)|(q->hs[1]));
00820 break;
00821 case FILE_LESHORT:
00822 off = (short)((q->hs[1]<<8)|(q->hs[0]));
00823 break;
00824 case FILE_LONG:
00825 off = q->l;
00826 break;
00827 case FILE_BELONG:
00828 off = (int32_t)((q->hl[0]<<24)|(q->hl[1]<<16)|
00829 (q->hl[2]<<8)|(q->hl[3]));
00830 break;
00831 case FILE_LELONG:
00832 off = (int32_t)((q->hl[3]<<24)|(q->hl[2]<<16)|
00833 (q->hl[1]<<8)|(q->hl[0]));
00834 break;
00835 case FILE_MELONG:
00836 off = (int32_t)((q->hl[1]<<24)|(q->hl[0]<<16)|
00837 (q->hl[3]<<8)|(q->hl[2]));
00838 break;
00839 }
00840 }
00841 switch (m->in_type) {
00842 case FILE_BYTE:
00843 if (nbytes < (offset + 1))
00844 return 0;
00845 if (off) {
00846 switch (m->in_op & FILE_OPS_MASK) {
00847 case FILE_OPAND:
00848 offset = p->b & off;
00849 break;
00850 case FILE_OPOR:
00851 offset = p->b | off;
00852 break;
00853 case FILE_OPXOR:
00854 offset = p->b ^ off;
00855 break;
00856 case FILE_OPADD:
00857 offset = p->b + off;
00858 break;
00859 case FILE_OPMINUS:
00860 offset = p->b - off;
00861 break;
00862 case FILE_OPMULTIPLY:
00863 offset = p->b * off;
00864 break;
00865 case FILE_OPDIVIDE:
00866 offset = p->b / off;
00867 break;
00868 case FILE_OPMODULO:
00869 offset = p->b % off;
00870 break;
00871 }
00872 } else
00873 offset = p->b;
00874 if (m->in_op & FILE_OPINVERSE)
00875 offset = ~offset;
00876 break;
00877 case FILE_BESHORT:
00878 if (nbytes < (offset + 2))
00879 return 0;
00880 if (off) {
00881 switch (m->in_op & FILE_OPS_MASK) {
00882 case FILE_OPAND:
00883 offset = (short)((p->hs[0]<<8)|
00884 (p->hs[1])) &
00885 off;
00886 break;
00887 case FILE_OPOR:
00888 offset = (short)((p->hs[0]<<8)|
00889 (p->hs[1])) |
00890 off;
00891 break;
00892 case FILE_OPXOR:
00893 offset = (short)((p->hs[0]<<8)|
00894 (p->hs[1])) ^
00895 off;
00896 break;
00897 case FILE_OPADD:
00898 offset = (short)((p->hs[0]<<8)|
00899 (p->hs[1])) +
00900 off;
00901 break;
00902 case FILE_OPMINUS:
00903 offset = (short)((p->hs[0]<<8)|
00904 (p->hs[1])) -
00905 off;
00906 break;
00907 case FILE_OPMULTIPLY:
00908 offset = (short)((p->hs[0]<<8)|
00909 (p->hs[1])) *
00910 off;
00911 break;
00912 case FILE_OPDIVIDE:
00913 offset = (short)((p->hs[0]<<8)|
00914 (p->hs[1])) /
00915 off;
00916 break;
00917 case FILE_OPMODULO:
00918 offset = (short)((p->hs[0]<<8)|
00919 (p->hs[1])) %
00920 off;
00921 break;
00922 }
00923 } else
00924 offset = (short)((p->hs[0]<<8)|
00925 (p->hs[1]));
00926 if (m->in_op & FILE_OPINVERSE)
00927 offset = ~offset;
00928 break;
00929 case FILE_LESHORT:
00930 if (nbytes < (offset + 2))
00931 return 0;
00932 if (off) {
00933 switch (m->in_op & FILE_OPS_MASK) {
00934 case FILE_OPAND:
00935 offset = (short)((p->hs[1]<<8)|
00936 (p->hs[0])) &
00937 off;
00938 break;
00939 case FILE_OPOR:
00940 offset = (short)((p->hs[1]<<8)|
00941 (p->hs[0])) |
00942 off;
00943 break;
00944 case FILE_OPXOR:
00945 offset = (short)((p->hs[1]<<8)|
00946 (p->hs[0])) ^
00947 off;
00948 break;
00949 case FILE_OPADD:
00950 offset = (short)((p->hs[1]<<8)|
00951 (p->hs[0])) +
00952 off;
00953 break;
00954 case FILE_OPMINUS:
00955 offset = (short)((p->hs[1]<<8)|
00956 (p->hs[0])) -
00957 off;
00958 break;
00959 case FILE_OPMULTIPLY:
00960 offset = (short)((p->hs[1]<<8)|
00961 (p->hs[0])) *
00962 off;
00963 break;
00964 case FILE_OPDIVIDE:
00965 offset = (short)((p->hs[1]<<8)|
00966 (p->hs[0])) /
00967 off;
00968 break;
00969 case FILE_OPMODULO:
00970 offset = (short)((p->hs[1]<<8)|
00971 (p->hs[0])) %
00972 off;
00973 break;
00974 }
00975 } else
00976 offset = (short)((p->hs[1]<<8)|
00977 (p->hs[0]));
00978 if (m->in_op & FILE_OPINVERSE)
00979 offset = ~offset;
00980 break;
00981 case FILE_SHORT:
00982 if (nbytes < (offset + 2))
00983 return 0;
00984 if (off) {
00985 switch (m->in_op & FILE_OPS_MASK) {
00986 case FILE_OPAND:
00987 offset = p->h & off;
00988 break;
00989 case FILE_OPOR:
00990 offset = p->h | off;
00991 break;
00992 case FILE_OPXOR:
00993 offset = p->h ^ off;
00994 break;
00995 case FILE_OPADD:
00996 offset = p->h + off;
00997 break;
00998 case FILE_OPMINUS:
00999 offset = p->h - off;
01000 break;
01001 case FILE_OPMULTIPLY:
01002 offset = p->h * off;
01003 break;
01004 case FILE_OPDIVIDE:
01005 offset = p->h / off;
01006 break;
01007 case FILE_OPMODULO:
01008 offset = p->h % off;
01009 break;
01010 }
01011 }
01012 else
01013 offset = p->h;
01014 if (m->in_op & FILE_OPINVERSE)
01015 offset = ~offset;
01016 break;
01017 case FILE_BELONG:
01018 if (nbytes < (offset + 4))
01019 return 0;
01020 if (off) {
01021 switch (m->in_op & FILE_OPS_MASK) {
01022 case FILE_OPAND:
01023 offset = (int32_t)((p->hl[0]<<24)|
01024 (p->hl[1]<<16)|
01025 (p->hl[2]<<8)|
01026 (p->hl[3])) &
01027 off;
01028 break;
01029 case FILE_OPOR:
01030 offset = (int32_t)((p->hl[0]<<24)|
01031 (p->hl[1]<<16)|
01032 (p->hl[2]<<8)|
01033 (p->hl[3])) |
01034 off;
01035 break;
01036 case FILE_OPXOR:
01037 offset = (int32_t)((p->hl[0]<<24)|
01038 (p->hl[1]<<16)|
01039 (p->hl[2]<<8)|
01040 (p->hl[3])) ^
01041 off;
01042 break;
01043 case FILE_OPADD:
01044 offset = (int32_t)((p->hl[0]<<24)|
01045 (p->hl[1]<<16)|
01046 (p->hl[2]<<8)|
01047 (p->hl[3])) +
01048 off;
01049 break;
01050 case FILE_OPMINUS:
01051 offset = (int32_t)((p->hl[0]<<24)|
01052 (p->hl[1]<<16)|
01053 (p->hl[2]<<8)|
01054 (p->hl[3])) -
01055 off;
01056 break;
01057 case FILE_OPMULTIPLY:
01058 offset = (int32_t)((p->hl[0]<<24)|
01059 (p->hl[1]<<16)|
01060 (p->hl[2]<<8)|
01061 (p->hl[3])) *
01062 off;
01063 break;
01064 case FILE_OPDIVIDE:
01065 offset = (int32_t)((p->hl[0]<<24)|
01066 (p->hl[1]<<16)|
01067 (p->hl[2]<<8)|
01068 (p->hl[3])) /
01069 off;
01070 break;
01071 case FILE_OPMODULO:
01072 offset = (int32_t)((p->hl[0]<<24)|
01073 (p->hl[1]<<16)|
01074 (p->hl[2]<<8)|
01075 (p->hl[3])) %
01076 off;
01077 break;
01078 }
01079 } else
01080 offset = (int32_t)((p->hl[0]<<24)|
01081 (p->hl[1]<<16)|
01082 (p->hl[2]<<8)|
01083 (p->hl[3]));
01084 if (m->in_op & FILE_OPINVERSE)
01085 offset = ~offset;
01086 break;
01087 case FILE_LELONG:
01088 if (nbytes < (offset + 4))
01089 return 0;
01090 if (off) {
01091 switch (m->in_op & FILE_OPS_MASK) {
01092 case FILE_OPAND:
01093 offset = (int32_t)((p->hl[3]<<24)|
01094 (p->hl[2]<<16)|
01095 (p->hl[1]<<8)|
01096 (p->hl[0])) &
01097 off;
01098 break;
01099 case FILE_OPOR:
01100 offset = (int32_t)((p->hl[3]<<24)|
01101 (p->hl[2]<<16)|
01102 (p->hl[1]<<8)|
01103 (p->hl[0])) |
01104 off;
01105 break;
01106 case FILE_OPXOR:
01107 offset = (int32_t)((p->hl[3]<<24)|
01108 (p->hl[2]<<16)|
01109 (p->hl[1]<<8)|
01110 (p->hl[0])) ^
01111 off;
01112 break;
01113 case FILE_OPADD:
01114 offset = (int32_t)((p->hl[3]<<24)|
01115 (p->hl[2]<<16)|
01116 (p->hl[1]<<8)|
01117 (p->hl[0])) +
01118 off;
01119 break;
01120 case FILE_OPMINUS:
01121 offset = (int32_t)((p->hl[3]<<24)|
01122 (p->hl[2]<<16)|
01123 (p->hl[1]<<8)|
01124 (p->hl[0])) -
01125 off;
01126 break;
01127 case FILE_OPMULTIPLY:
01128 offset = (int32_t)((p->hl[3]<<24)|
01129 (p->hl[2]<<16)|
01130 (p->hl[1]<<8)|
01131 (p->hl[0])) *
01132 off;
01133 break;
01134 case FILE_OPDIVIDE:
01135 offset = (int32_t)((p->hl[3]<<24)|
01136 (p->hl[2]<<16)|
01137 (p->hl[1]<<8)|
01138 (p->hl[0])) /
01139 off;
01140 break;
01141 case FILE_OPMODULO:
01142 offset = (int32_t)((p->hl[3]<<24)|
01143 (p->hl[2]<<16)|
01144 (p->hl[1]<<8)|
01145 (p->hl[0])) %
01146 off;
01147 break;
01148 }
01149 } else
01150 offset = (int32_t)((p->hl[3]<<24)|
01151 (p->hl[2]<<16)|
01152 (p->hl[1]<<8)|
01153 (p->hl[0]));
01154 if (m->in_op & FILE_OPINVERSE)
01155 offset = ~offset;
01156 break;
01157 case FILE_MELONG:
01158 if (nbytes < (offset + 4))
01159 return 0;
01160 if (off) {
01161 switch (m->in_op & FILE_OPS_MASK) {
01162 case FILE_OPAND:
01163 offset = (int32_t)((p->hl[1]<<24)|
01164 (p->hl[0]<<16)|
01165 (p->hl[3]<<8)|
01166 (p->hl[2])) &
01167 off;
01168 break;
01169 case FILE_OPOR:
01170 offset = (int32_t)((p->hl[1]<<24)|
01171 (p->hl[0]<<16)|
01172 (p->hl[3]<<8)|
01173 (p->hl[2])) |
01174 off;
01175 break;
01176 case FILE_OPXOR:
01177 offset = (int32_t)((p->hl[1]<<24)|
01178 (p->hl[0]<<16)|
01179 (p->hl[3]<<8)|
01180 (p->hl[2])) ^
01181 off;
01182 break;
01183 case FILE_OPADD:
01184 offset = (int32_t)((p->hl[1]<<24)|
01185 (p->hl[0]<<16)|
01186 (p->hl[3]<<8)|
01187 (p->hl[2])) +
01188 off;
01189 break;
01190 case FILE_OPMINUS:
01191 offset = (int32_t)((p->hl[1]<<24)|
01192 (p->hl[0]<<16)|
01193 (p->hl[3]<<8)|
01194 (p->hl[2])) -
01195 off;
01196 break;
01197 case FILE_OPMULTIPLY:
01198 offset = (int32_t)((p->hl[1]<<24)|
01199 (p->hl[0]<<16)|
01200 (p->hl[3]<<8)|
01201 (p->hl[2])) *
01202 off;
01203 break;
01204 case FILE_OPDIVIDE:
01205 offset = (int32_t)((p->hl[1]<<24)|
01206 (p->hl[0]<<16)|
01207 (p->hl[3]<<8)|
01208 (p->hl[2])) /
01209 off;
01210 break;
01211 case FILE_OPMODULO:
01212 offset = (int32_t)((p->hl[1]<<24)|
01213 (p->hl[0]<<16)|
01214 (p->hl[3]<<8)|
01215 (p->hl[2])) %
01216 off;
01217 break;
01218 }
01219 } else
01220 offset = (int32_t)((p->hl[1]<<24)|
01221 (p->hl[0]<<16)|
01222 (p->hl[3]<<8)|
01223 (p->hl[2]));
01224 if (m->in_op & FILE_OPINVERSE)
01225 offset = ~offset;
01226 break;
01227 case FILE_LONG:
01228 if (nbytes < (offset + 4))
01229 return 0;
01230 if (off) {
01231 switch (m->in_op & FILE_OPS_MASK) {
01232 case FILE_OPAND:
01233 offset = p->l & off;
01234 break;
01235 case FILE_OPOR:
01236 offset = p->l | off;
01237 break;
01238 case FILE_OPXOR:
01239 offset = p->l ^ off;
01240 break;
01241 case FILE_OPADD:
01242 offset = p->l + off;
01243 break;
01244 case FILE_OPMINUS:
01245 offset = p->l - off;
01246 break;
01247 case FILE_OPMULTIPLY:
01248 offset = p->l * off;
01249 break;
01250 case FILE_OPDIVIDE:
01251 offset = p->l / off;
01252 break;
01253 case FILE_OPMODULO:
01254 offset = p->l % off;
01255 break;
01256
01257
01258
01259
01260
01261
01262
01263 }
01264 } else
01265 offset = p->l;
01266 if (m->in_op & FILE_OPINVERSE)
01267 offset = ~offset;
01268 break;
01269 }
01270
01271 if (m->flag & INDIROFFADD)
01272 offset += ms->c.li[cont_level-1].off;
01273 if (mcopy(ms, p, m->type, 0, s, offset, nbytes, count) == -1)
01274 return -1;
01275 ms->offset = offset;
01276
01277 if ((ms->flags & MAGIC_DEBUG) != 0) {
01278 mdebug(offset, (char *)(void *)p,
01279 sizeof(union VALUETYPE));
01280 file_mdump(m);
01281 }
01282 }
01283
01284
01285 switch (m->type) {
01286 case FILE_BYTE:
01287 if (nbytes < (offset + 1))
01288 return 0;
01289 break;
01290
01291 case FILE_SHORT:
01292 case FILE_BESHORT:
01293 case FILE_LESHORT:
01294 if (nbytes < (offset + 2))
01295 return 0;
01296 break;
01297
01298 case FILE_LONG:
01299 case FILE_BELONG:
01300 case FILE_LELONG:
01301 case FILE_MELONG:
01302 case FILE_DATE:
01303 case FILE_BEDATE:
01304 case FILE_LEDATE:
01305 case FILE_MEDATE:
01306 case FILE_LDATE:
01307 case FILE_BELDATE:
01308 case FILE_LELDATE:
01309 case FILE_MELDATE:
01310 if (nbytes < (offset + 4))
01311 return 0;
01312 break;
01313
01314 case FILE_STRING:
01315 case FILE_PSTRING:
01316 case FILE_SEARCH:
01317 if (nbytes < (offset + m->vallen))
01318 return 0;
01319 break;
01320
01321 case FILE_REGEX:
01322 if (nbytes < offset)
01323 return 0;
01324 break;
01325
01326 case FILE_DEFAULT:
01327 default:
01328 break;
01329 }
01330 if (!mconvert(ms, m))
01331 return 0;
01332 return 1;
01333 }
01334
01335 private uint64_t
01336 file_strncmp(const char *s1, const char *s2, size_t len, uint32_t flags)
01337
01338 {
01339
01340
01341
01342
01343
01344
01345 const unsigned char *a = (const unsigned char *)s1;
01346 const unsigned char *b = (const unsigned char *)s2;
01347 uint64_t v;
01348
01349
01350
01351
01352
01353
01354
01355 v = 0;
01356 if (0L == flags) {
01357 while (len-- > 0)
01358 if ((v = *b++ - *a++) != '\0')
01359 break;
01360 }
01361 else {
01362 while (len-- > 0) {
01363 if ((flags & STRING_IGNORE_LOWERCASE) &&
01364 islower(*a)) {
01365 if ((v = tolower(*b++) - *a++) != '\0')
01366 break;
01367 }
01368 else if ((flags & STRING_IGNORE_UPPERCASE) &&
01369 isupper(*a)) {
01370 if ((v = toupper(*b++) - *a++) != '\0')
01371 break;
01372 }
01373 else if ((flags & STRING_COMPACT_BLANK) &&
01374 isspace(*a)) {
01375 a++;
01376 if (isspace(*b++)) {
01377 while (isspace(*b))
01378 b++;
01379 }
01380 else {
01381 v = 1;
01382 break;
01383 }
01384 }
01385 else if ((flags & STRING_COMPACT_OPTIONAL_BLANK) &&
01386 isspace(*a)) {
01387 a++;
01388 while (isspace(*b))
01389 b++;
01390 }
01391 else {
01392 if ((v = *b++ - *a++) != '\0')
01393 break;
01394 }
01395 }
01396 }
01397 return v;
01398 }
01399
01400 private uint64_t
01401 file_strncmp16(const char *a, const char *b, size_t len, uint32_t flags)
01402
01403 {
01404
01405
01406
01407
01408
01409 flags = 0;
01410 return file_strncmp(a, b, len, flags);
01411 }
01412
01413 private int
01414 magiccheck(struct magic_set *ms, struct magic *m)
01415 {
01416 uint64_t l = m->value.q;
01417 uint64_t v;
01418 int matched;
01419 union VALUETYPE *p = &ms->ms_value;
01420
01421 switch (m->type) {
01422 case FILE_BYTE:
01423 v = p->b;
01424 break;
01425
01426 case FILE_SHORT:
01427 case FILE_BESHORT:
01428 case FILE_LESHORT:
01429 v = p->h;
01430 break;
01431
01432 case FILE_LONG:
01433 case FILE_BELONG:
01434 case FILE_LELONG:
01435 case FILE_MELONG:
01436 case FILE_DATE:
01437 case FILE_BEDATE:
01438 case FILE_LEDATE:
01439 case FILE_MEDATE:
01440 case FILE_LDATE:
01441 case FILE_BELDATE:
01442 case FILE_LELDATE:
01443 case FILE_MELDATE:
01444 v = p->l;
01445 break;
01446
01447 case FILE_QUAD:
01448 case FILE_LEQUAD:
01449 case FILE_BEQUAD:
01450 case FILE_QDATE:
01451 case FILE_BEQDATE:
01452 case FILE_LEQDATE:
01453 case FILE_QLDATE:
01454 case FILE_BEQLDATE:
01455 case FILE_LEQLDATE:
01456 v = p->q;
01457 break;
01458
01459 case FILE_DEFAULT:
01460 l = 0;
01461 v = 0;
01462 break;
01463
01464 case FILE_STRING:
01465 case FILE_PSTRING:
01466 l = 0;
01467 v = file_strncmp(m->value.s, p->s, (size_t)m->vallen, m->str_flags);
01468 break;
01469
01470 case FILE_BESTRING16:
01471 case FILE_LESTRING16:
01472 l = 0;
01473 v = file_strncmp16(m->value.s, p->s, (size_t)m->vallen, m->str_flags);
01474 break;
01475
01476 case FILE_SEARCH: {
01477 size_t slen;
01478 size_t idx;
01479
01480 if (ms->search.s == NULL)
01481 return 0;
01482
01483 slen = MIN(m->vallen, sizeof(m->value.s));
01484 l = 0;
01485 v = 0;
01486 ms->search.offset = m->offset;
01487
01488 for (idx = 0; m->str_count == 0 || idx < m->str_count; idx++) {
01489 if (slen + idx > ms->search.s_len)
01490 break;
01491
01492 v = file_strncmp(m->value.s, ms->search.s + idx, slen, m->str_flags);
01493 if (v == 0) {
01494 ms->search.offset = m->offset + idx;
01495 break;
01496 }
01497 }
01498 break;
01499 }
01500 case FILE_REGEX: {
01501 int rc;
01502 regex_t rx;
01503 char errmsg[512];
01504
01505 if (ms->search.s == NULL)
01506 return 0;
01507
01508 l = 0;
01509 rc = regcomp(&rx, m->value.s,
01510 REG_EXTENDED|REG_NEWLINE|
01511 ((m->str_flags & STRING_IGNORE_CASE) ? REG_ICASE : 0));
01512 if (rc) {
01513 (void) regerror(rc, &rx, errmsg, sizeof(errmsg));
01514 file_magerror(ms, "regex error %d, (%s)",
01515 rc, errmsg);
01516 v = (uint64_t)-1;
01517 }
01518 else {
01519 regmatch_t pmatch[1];
01520 #ifndef REG_STARTEND
01521 #define REG_STARTEND 0
01522 size_t l = ms->search.s_len - 1;
01523 char c = ms->search.s[l];
01524 ((char *)(intptr_t)ms->search.s)[l] = '\0';
01525 #else
01526 pmatch[0].rm_so = 0;
01527 pmatch[0].rm_eo = ms->search.s_len;
01528 #endif
01529 rc = regexec(&rx, (const char *)ms->search.s,
01530 1, pmatch, REG_STARTEND);
01531 #if REG_STARTEND == 0
01532 ((char *)(intptr_t)ms->search.s)[l] = c;
01533 #endif
01534 switch (rc) {
01535 case 0:
01536 ms->search.s += (int)pmatch[0].rm_so;
01537 ms->search.offset += (size_t)pmatch[0].rm_so;
01538 ms->search.rm_len =
01539 (size_t)(pmatch[0].rm_eo - pmatch[0].rm_so);
01540 v = 0;
01541 break;
01542
01543 case REG_NOMATCH:
01544 v = 1;
01545 break;
01546
01547 default:
01548 (void)regerror(rc, &rx, errmsg, sizeof(errmsg));
01549 file_magerror(ms, "regexec error %d, (%s)",
01550 rc, errmsg);
01551 v = (uint64_t)-1;
01552 break;
01553 }
01554 regfree(&rx);
01555 }
01556 if (v == (uint64_t)-1)
01557 return -1;
01558 break;
01559 }
01560 default:
01561 file_magerror(ms, "invalid type %d in magiccheck()", m->type);
01562 return -1;
01563 }
01564
01565 v = file_signextend(ms, m, v);
01566
01567 switch (m->reln) {
01568 case 'x':
01569 if ((ms->flags & MAGIC_DEBUG) != 0)
01570 (void) fprintf(stderr, "%llu == *any* = 1\n",
01571 (unsigned long long)v);
01572 matched = 1;
01573 break;
01574
01575 case '!':
01576 matched = v != l;
01577 if ((ms->flags & MAGIC_DEBUG) != 0)
01578 (void) fprintf(stderr, "%llu != %llu = %d\n",
01579 (unsigned long long)v, (unsigned long long)l,
01580 matched);
01581 break;
01582
01583 case '=':
01584 matched = v == l;
01585 if ((ms->flags & MAGIC_DEBUG) != 0)
01586 (void) fprintf(stderr, "%llu == %llu = %d\n",
01587 (unsigned long long)v, (unsigned long long)l,
01588 matched);
01589 break;
01590
01591 case '>':
01592 if (m->flag & UNSIGNED) {
01593 matched = v > l;
01594 if ((ms->flags & MAGIC_DEBUG) != 0)
01595 (void) fprintf(stderr, "%llu > %llu = %d\n",
01596 (unsigned long long)v,
01597 (unsigned long long)l, matched);
01598 }
01599 else {
01600 matched = (int64_t) v > (int64_t) l;
01601 if ((ms->flags & MAGIC_DEBUG) != 0)
01602 (void) fprintf(stderr, "%lld > %lld = %d\n",
01603 (long long)v, (long long)l, matched);
01604 }
01605 break;
01606
01607 case '<':
01608 if (m->flag & UNSIGNED) {
01609 matched = v < l;
01610 if ((ms->flags & MAGIC_DEBUG) != 0)
01611 (void) fprintf(stderr, "%llu < %llu = %d\n",
01612 (unsigned long long)v,
01613 (unsigned long long)l, matched);
01614 }
01615 else {
01616 matched = (int64_t) v < (int64_t) l;
01617 if ((ms->flags & MAGIC_DEBUG) != 0)
01618 (void) fprintf(stderr, "%lld < %lld = %d\n",
01619 (long long)v, (long long)l, matched);
01620 }
01621 break;
01622
01623 case '&':
01624 matched = (v & l) == l;
01625 if ((ms->flags & MAGIC_DEBUG) != 0)
01626 (void) fprintf(stderr, "((%llx & %llx) == %llx) = %d\n",
01627 (unsigned long long)v, (unsigned long long)l,
01628 (unsigned long long)l, matched);
01629 break;
01630
01631 case '^':
01632 matched = (v & l) != l;
01633 if ((ms->flags & MAGIC_DEBUG) != 0)
01634 (void) fprintf(stderr, "((%llx & %llx) != %llx) = %d\n",
01635 (unsigned long long)v, (unsigned long long)l,
01636 (unsigned long long)l, matched);
01637 break;
01638
01639 default:
01640 matched = 0;
01641 file_magerror(ms, "cannot happen: invalid relation `%c'",
01642 m->reln);
01643 return -1;
01644 }
01645
01646 return matched;
01647 }
01648
01649 private int
01650 print_sep(struct magic_set *ms, int firstline)
01651 {
01652 if (firstline)
01653 return 0;
01654
01655
01656
01657
01658 return file_printf(ms, "\n- ");
01659 }