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