Annotation of embedaddon/php/ext/fileinfo/libmagic/softmagic.c, revision 1.1.1.2
1.1 misho 1: /*
2: * Copyright (c) Ian F. Darwin 1986-1995.
3: * Software written by Ian F. Darwin and others;
4: * maintained 1995-present by Christos Zoulas and others.
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: * 1. Redistributions of source code must retain the above copyright
10: * notice immediately at the beginning of the file, without modification,
11: * this list of conditions, and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20: * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26: * SUCH DAMAGE.
27: */
28: /*
29: * softmagic - interpret variable magic from MAGIC
30: */
31:
32: #include "file.h"
33:
34: #ifndef lint
1.1.1.2 ! misho 35: FILE_RCSID("@(#)$File: softmagic.c,v 1.147 2011/11/05 15:44:22 rrt Exp $")
1.1 misho 36: #endif /* lint */
37:
38: #include "magic.h"
39: #include <string.h>
40: #include <ctype.h>
41: #include <stdlib.h>
42: #include <time.h>
43:
44: #ifndef PREG_OFFSET_CAPTURE
45: # define PREG_OFFSET_CAPTURE (1<<8)
46: #endif
47:
48:
49:
50: private int match(struct magic_set *, struct magic *, uint32_t,
1.1.1.2 ! misho 51: const unsigned char *, size_t, int, int);
1.1 misho 52: private int mget(struct magic_set *, const unsigned char *,
1.1.1.2 ! misho 53: struct magic *, size_t, unsigned int, int);
1.1 misho 54: private int magiccheck(struct magic_set *, struct magic *);
55: private int32_t mprint(struct magic_set *, struct magic *);
56: private int32_t moffset(struct magic_set *, struct magic *);
57: private void mdebug(uint32_t, const char *, size_t);
58: private int mcopy(struct magic_set *, union VALUETYPE *, int, int,
59: const unsigned char *, uint32_t, size_t, size_t);
60: private int mconvert(struct magic_set *, struct magic *);
61: private int print_sep(struct magic_set *, int);
62: private int handle_annotation(struct magic_set *, struct magic *);
63: private void cvt_8(union VALUETYPE *, const struct magic *);
64: private void cvt_16(union VALUETYPE *, const struct magic *);
65: private void cvt_32(union VALUETYPE *, const struct magic *);
66: private void cvt_64(union VALUETYPE *, const struct magic *);
67:
68: /*
69: * softmagic - lookup one file in parsed, in-memory copy of database
70: * Passed the name and FILE * of one file to be typed.
71: */
72: /*ARGSUSED1*/ /* nbytes passed for regularity, maybe need later */
73: protected int
1.1.1.2 ! misho 74: file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes,
! 75: int mode, int text)
1.1 misho 76: {
77: struct mlist *ml;
78: int rv;
79: for (ml = ms->mlist->next; ml != ms->mlist; ml = ml->next)
1.1.1.2 ! misho 80: if ((rv = match(ms, ml->magic, ml->nmagic, buf, nbytes, mode,
! 81: text)) != 0)
1.1 misho 82: return rv;
83:
84: return 0;
85: }
86:
87: /*
88: * Go through the whole list, stopping if you find a match. Process all
89: * the continuations of that match before returning.
90: *
91: * We support multi-level continuations:
92: *
93: * At any time when processing a successful top-level match, there is a
94: * current continuation level; it represents the level of the last
95: * successfully matched continuation.
96: *
97: * Continuations above that level are skipped as, if we see one, it
98: * means that the continuation that controls them - i.e, the
99: * lower-level continuation preceding them - failed to match.
100: *
101: * Continuations below that level are processed as, if we see one,
102: * it means we've finished processing or skipping higher-level
103: * continuations under the control of a successful or unsuccessful
104: * lower-level continuation, and are now seeing the next lower-level
105: * continuation and should process it. The current continuation
106: * level reverts to the level of the one we're seeing.
107: *
108: * Continuations at the current level are processed as, if we see
109: * one, there's no lower-level continuation that may have failed.
110: *
111: * If a continuation matches, we bump the current continuation level
112: * so that higher-level continuations are processed.
113: */
114: private int
115: match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
1.1.1.2 ! misho 116: const unsigned char *s, size_t nbytes, int mode, int text)
1.1 misho 117: {
118: uint32_t magindex = 0;
119: unsigned int cont_level = 0;
120: int need_separator = 0;
121: int returnval = 0, e; /* if a match is found it is set to 1*/
122: int firstline = 1; /* a flag to print X\n X\n- X */
123: int printed_something = 0;
124: int print = (ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0;
125:
126: if (file_check_mem(ms, cont_level) == -1)
127: return -1;
128:
129: for (magindex = 0; magindex < nmagic; magindex++) {
130: int flush = 0;
131: struct magic *m = &magic[magindex];
132:
1.1.1.2 ! misho 133: if ((IS_LIBMAGIC_STRING(m->type) &&
! 134: ((text && (m->str_flags & (STRING_BINTEST | STRING_TEXTTEST)) == STRING_BINTEST) ||
! 135: (!text && (m->str_flags & (STRING_TEXTTEST | STRING_BINTEST)) == STRING_TEXTTEST))) ||
! 136: (m->flag & mode) != mode) {
1.1 misho 137: /* Skip sub-tests */
138: while (magindex < nmagic - 1 && magic[magindex + 1].cont_level != 0) {
139: magindex++;
140: }
141: continue; /* Skip to next top-level test*/
142: }
143:
144: ms->offset = m->offset;
145: ms->line = m->lineno;
146:
147: /* if main entry matches, print it... */
1.1.1.2 ! misho 148: switch (mget(ms, s, m, nbytes, cont_level, text)) {
1.1 misho 149: case -1:
150: return -1;
151: case 0:
152: flush = m->reln != '!';
153: break;
154: default:
155: if (m->type == FILE_INDIRECT)
156: returnval = 1;
1.1.1.2 ! misho 157:
1.1 misho 158: switch (magiccheck(ms, m)) {
159: case -1:
160: return -1;
161: case 0:
162: flush++;
163: break;
164: default:
165: flush = 0;
166: break;
167: }
168: break;
169: }
170: if (flush) {
171: /*
172: * main entry didn't match,
173: * flush its continuations
174: */
175: while (magindex < nmagic - 1 && magic[magindex + 1].cont_level != 0) {
176: magindex++;
177: }
178: continue;
179: }
180:
1.1.1.2 ! misho 181: if ((e = handle_annotation(ms, m)) != 0)
! 182: return e;
1.1 misho 183: /*
184: * If we are going to print something, we'll need to print
185: * a blank before we print something else.
186: */
187: if (*m->desc) {
188: need_separator = 1;
189: printed_something = 1;
190: if (print_sep(ms, firstline) == -1)
191: return -1;
192: }
193:
194:
195: if (print && mprint(ms, m) == -1)
196: return -1;
197:
198: ms->c.li[cont_level].off = moffset(ms, m);
199:
200: /* and any continuations that match */
201: if (file_check_mem(ms, ++cont_level) == -1)
202: return -1;
203:
204: while (magindex < nmagic - 1 && magic[magindex + 1].cont_level != 0) {
205: magindex++;
206: m = &magic[magindex];
207: ms->line = m->lineno; /* for messages */
208:
209: if (cont_level < m->cont_level)
210: continue;
211: if (cont_level > m->cont_level) {
212: /*
213: * We're at the end of the level
214: * "cont_level" continuations.
215: */
216: cont_level = m->cont_level;
217: }
218: ms->offset = m->offset;
219: if (m->flag & OFFADD) {
220: ms->offset += ms->c.li[cont_level - 1].off;
221: }
222:
223: #ifdef ENABLE_CONDITIONALS
224: if (m->cond == COND_ELSE ||
225: m->cond == COND_ELIF) {
226: if (ms->c.li[cont_level].last_match == 1)
227: continue;
228: }
229: #endif
1.1.1.2 ! misho 230: switch (mget(ms, s, m, nbytes, cont_level, text)) {
1.1 misho 231: case -1:
232: return -1;
233: case 0:
234: if (m->reln != '!')
235: continue;
236: flush = 1;
237: break;
238: default:
239: if (m->type == FILE_INDIRECT)
240: returnval = 1;
241: flush = 0;
242: break;
243: }
244:
245: switch (flush ? 1 : magiccheck(ms, m)) {
246: case -1:
247: return -1;
248: case 0:
249: #ifdef ENABLE_CONDITIONALS
250: ms->c.li[cont_level].last_match = 0;
251: #endif
252: break;
253: default:
254: #ifdef ENABLE_CONDITIONALS
255: ms->c.li[cont_level].last_match = 1;
256: #endif
257: if (m->type != FILE_DEFAULT)
258: ms->c.li[cont_level].got_match = 1;
259: else if (ms->c.li[cont_level].got_match) {
260: ms->c.li[cont_level].got_match = 0;
261: break;
262: }
1.1.1.2 ! misho 263: if ((e = handle_annotation(ms, m)) != 0)
! 264: return e;
1.1 misho 265: /*
266: * If we are going to print something,
267: * make sure that we have a separator first.
268: */
269: if (*m->desc) {
270: if (!printed_something) {
271: printed_something = 1;
272: if (print_sep(ms, firstline)
273: == -1)
274: return -1;
275: }
276: }
277: /*
278: * This continuation matched. Print
279: * its message, with a blank before it
280: * if the previous item printed and
281: * this item isn't empty.
282: */
283: /* space if previous printed */
284: if (need_separator
285: && ((m->flag & NOSPACE) == 0)
286: && *m->desc) {
287: if (print &&
288: file_printf(ms, " ") == -1)
289: return -1;
290: need_separator = 0;
291: }
292: if (print && mprint(ms, m) == -1)
293: return -1;
294:
295: ms->c.li[cont_level].off = moffset(ms, m);
296:
297: if (*m->desc)
298: need_separator = 1;
299:
300: /*
301: * If we see any continuations
302: * at a higher level,
303: * process them.
304: */
305: if (file_check_mem(ms, ++cont_level) == -1)
306: return -1;
307: break;
308: }
309: }
310: if (printed_something) {
311: firstline = 0;
312: if (print)
313: returnval = 1;
314: }
315: if ((ms->flags & MAGIC_CONTINUE) == 0 && printed_something) {
316: return returnval; /* don't keep searching */
317: }
318: }
319: return returnval; /* This is hit if -k is set or there is no match */
320: }
321:
322: private int
323: check_fmt(struct magic_set *ms, struct magic *m)
324: {
325: pcre *pce;
326: int re_options;
327: pcre_extra *re_extra;
328: TSRMLS_FETCH();
329:
330: if (strchr(m->desc, '%') == NULL) {
331: return 0;
332: }
333:
334: if ((pce = pcre_get_compiled_regex("~%[-0-9.]*s~", &re_extra, &re_options TSRMLS_CC)) == NULL) {
335: return -1;
336: } else {
337: return !pcre_exec(pce, re_extra, m->desc, strlen(m->desc), 0, re_options, NULL, 0);
338: }
339: }
340:
341: private int32_t
342: mprint(struct magic_set *ms, struct magic *m)
343: {
344: uint64_t v;
345: float vf;
346: double vd;
347: int64_t t = 0;
348: char buf[128];
349: union VALUETYPE *p = &ms->ms_value;
350:
351: switch (m->type) {
352: case FILE_BYTE:
353: v = file_signextend(ms, m, (uint64_t)p->b);
354: switch (check_fmt(ms, m)) {
355: case -1:
356: return -1;
357: case 1:
358: (void)snprintf(buf, sizeof(buf), "%c",
359: (unsigned char)v);
360: if (file_printf(ms, m->desc, buf) == -1)
361: return -1;
362: break;
363: default:
364: if (file_printf(ms, m->desc, (unsigned char) v) == -1)
365: return -1;
366: break;
367: }
368: t = ms->offset + sizeof(char);
369: break;
370:
371: case FILE_SHORT:
372: case FILE_BESHORT:
373: case FILE_LESHORT:
374: v = file_signextend(ms, m, (uint64_t)p->h);
375: switch (check_fmt(ms, m)) {
376: case -1:
377: return -1;
378: case 1:
379: (void)snprintf(buf, sizeof(buf), "%hu",
380: (unsigned short)v);
381: if (file_printf(ms, m->desc, buf) == -1)
382: return -1;
383: break;
384: default:
385: if (
386: file_printf(ms, m->desc, (unsigned short) v) == -1)
387: return -1;
388: break;
389: }
390: t = ms->offset + sizeof(short);
391: break;
392:
393: case FILE_LONG:
394: case FILE_BELONG:
395: case FILE_LELONG:
396: case FILE_MELONG:
397: v = file_signextend(ms, m, (uint64_t)p->l);
398: switch (check_fmt(ms, m)) {
399: case -1:
400: return -1;
401: case 1:
402: (void)snprintf(buf, sizeof(buf), "%u", (uint32_t)v);
403: if (file_printf(ms, m->desc, buf) == -1)
404: return -1;
405: break;
406: default:
407: if (file_printf(ms, m->desc, (uint32_t) v) == -1)
408: return -1;
409: break;
410: }
411: t = ms->offset + sizeof(int32_t);
412: break;
413:
414: case FILE_QUAD:
415: case FILE_BEQUAD:
416: case FILE_LEQUAD:
417: v = file_signextend(ms, m, p->q);
418: if (file_printf(ms, m->desc, (uint64_t) v) == -1)
419: return -1;
420: t = ms->offset + sizeof(int64_t);
421: break;
422:
423: case FILE_STRING:
424: case FILE_PSTRING:
425: case FILE_BESTRING16:
426: case FILE_LESTRING16:
427: if (m->reln == '=' || m->reln == '!') {
428: if (file_printf(ms, m->desc, m->value.s) == -1)
429: return -1;
430: t = ms->offset + m->vallen;
431: }
432: else {
433: if (*m->value.s == '\0')
434: p->s[strcspn(p->s, "\n")] = '\0';
435: if (file_printf(ms, m->desc, p->s) == -1)
436: return -1;
437: t = ms->offset + strlen(p->s);
438: if (m->type == FILE_PSTRING)
1.1.1.2 ! misho 439: t += file_pstring_length_size(m);
1.1 misho 440: }
441: break;
442:
443: case FILE_DATE:
444: case FILE_BEDATE:
445: case FILE_LEDATE:
446: case FILE_MEDATE:
447: if (file_printf(ms, m->desc, file_fmttime(p->l, 1)) == -1)
448: return -1;
449: t = ms->offset + sizeof(time_t);
450: break;
451:
452: case FILE_LDATE:
453: case FILE_BELDATE:
454: case FILE_LELDATE:
455: case FILE_MELDATE:
456: if (file_printf(ms, m->desc, file_fmttime(p->l, 0)) == -1)
457: return -1;
458: t = ms->offset + sizeof(time_t);
459: break;
460:
461: case FILE_QDATE:
462: case FILE_BEQDATE:
463: case FILE_LEQDATE:
464: if (file_printf(ms, m->desc, file_fmttime((uint32_t)p->q,
465: 1)) == -1)
466: return -1;
467: t = ms->offset + sizeof(uint64_t);
468: break;
469:
470: case FILE_QLDATE:
471: case FILE_BEQLDATE:
472: case FILE_LEQLDATE:
473: if (file_printf(ms, m->desc, file_fmttime((uint32_t)p->q,
474: 0)) == -1)
475: return -1;
476: t = ms->offset + sizeof(uint64_t);
477: break;
478:
479: case FILE_FLOAT:
480: case FILE_BEFLOAT:
481: case FILE_LEFLOAT:
482: vf = p->f;
483: switch (check_fmt(ms, m)) {
484: case -1:
485: return -1;
486: case 1:
487: (void)snprintf(buf, sizeof(buf), "%g", vf);
488: if (file_printf(ms, m->desc, buf) == -1)
489: return -1;
490: break;
491: default:
492: if (file_printf(ms, m->desc, vf) == -1)
493: return -1;
494: break;
495: }
496: t = ms->offset + sizeof(float);
497: break;
498:
499: case FILE_DOUBLE:
500: case FILE_BEDOUBLE:
501: case FILE_LEDOUBLE:
502: vd = p->d;
503: switch (check_fmt(ms, m)) {
504: case -1:
505: return -1;
506: case 1:
507: (void)snprintf(buf, sizeof(buf), "%g", vd);
508: if (file_printf(ms, m->desc, buf) == -1)
509: return -1;
510: break;
511: default:
512: if (file_printf(ms, m->desc, vd) == -1)
513: return -1;
514: break;
515: }
516: t = ms->offset + sizeof(double);
517: break;
518:
519: case FILE_REGEX: {
520: char *cp;
521: int rval;
522:
523: cp = estrndup((const char *)ms->search.s, ms->search.rm_len);
524:
525: rval = file_printf(ms, m->desc, cp);
526: efree(cp);
527:
528: if (rval == -1)
529: return -1;
530:
531: if ((m->str_flags & REGEX_OFFSET_START))
532: t = ms->search.offset;
533: else
534: t = ms->search.offset + ms->search.rm_len;
535: break;
536: }
537:
538: case FILE_SEARCH:
539: if (file_printf(ms, m->desc, m->value.s) == -1)
540: return -1;
541: if ((m->str_flags & REGEX_OFFSET_START))
542: t = ms->search.offset;
543: else
544: t = ms->search.offset + m->vallen;
545: break;
546:
547: case FILE_DEFAULT:
548: if (file_printf(ms, m->desc, m->value.s) == -1)
549: return -1;
550: t = ms->offset;
551: break;
552:
553: case FILE_INDIRECT:
554: t = ms->offset;
555: break;
556:
557: default:
558: file_magerror(ms, "invalid m->type (%d) in mprint()", m->type);
559: return -1;
560: }
561: return (int32_t)t;
562: }
563:
564: private int32_t
565: moffset(struct magic_set *ms, struct magic *m)
566: {
567: switch (m->type) {
568: case FILE_BYTE:
1.1.1.2 ! misho 569: return CAST(int32_t, (ms->offset + sizeof(char)));
1.1 misho 570:
571: case FILE_SHORT:
572: case FILE_BESHORT:
573: case FILE_LESHORT:
1.1.1.2 ! misho 574: return CAST(int32_t, (ms->offset + sizeof(short)));
1.1 misho 575:
576: case FILE_LONG:
577: case FILE_BELONG:
578: case FILE_LELONG:
579: case FILE_MELONG:
1.1.1.2 ! misho 580: return CAST(int32_t, (ms->offset + sizeof(int32_t)));
1.1 misho 581:
582: case FILE_QUAD:
583: case FILE_BEQUAD:
584: case FILE_LEQUAD:
1.1.1.2 ! misho 585: return CAST(int32_t, (ms->offset + sizeof(int64_t)));
1.1 misho 586:
587: case FILE_STRING:
588: case FILE_PSTRING:
589: case FILE_BESTRING16:
590: case FILE_LESTRING16:
591: if (m->reln == '=' || m->reln == '!')
592: return ms->offset + m->vallen;
593: else {
594: union VALUETYPE *p = &ms->ms_value;
595: uint32_t t;
596:
597: if (*m->value.s == '\0')
598: p->s[strcspn(p->s, "\n")] = '\0';
1.1.1.2 ! misho 599: t = CAST(uint32_t, (ms->offset + strlen(p->s)));
1.1 misho 600: if (m->type == FILE_PSTRING)
1.1.1.2 ! misho 601: t += file_pstring_length_size(m);
1.1 misho 602: return t;
603: }
604:
605: case FILE_DATE:
606: case FILE_BEDATE:
607: case FILE_LEDATE:
608: case FILE_MEDATE:
1.1.1.2 ! misho 609: return CAST(int32_t, (ms->offset + sizeof(time_t)));
1.1 misho 610:
611: case FILE_LDATE:
612: case FILE_BELDATE:
613: case FILE_LELDATE:
614: case FILE_MELDATE:
1.1.1.2 ! misho 615: return CAST(int32_t, (ms->offset + sizeof(time_t)));
1.1 misho 616:
617: case FILE_QDATE:
618: case FILE_BEQDATE:
619: case FILE_LEQDATE:
1.1.1.2 ! misho 620: return CAST(int32_t, (ms->offset + sizeof(uint64_t)));
1.1 misho 621:
622: case FILE_QLDATE:
623: case FILE_BEQLDATE:
624: case FILE_LEQLDATE:
1.1.1.2 ! misho 625: return CAST(int32_t, (ms->offset + sizeof(uint64_t)));
1.1 misho 626:
627: case FILE_FLOAT:
628: case FILE_BEFLOAT:
629: case FILE_LEFLOAT:
1.1.1.2 ! misho 630: return CAST(int32_t, (ms->offset + sizeof(float)));
1.1 misho 631:
632: case FILE_DOUBLE:
633: case FILE_BEDOUBLE:
634: case FILE_LEDOUBLE:
1.1.1.2 ! misho 635: return CAST(int32_t, (ms->offset + sizeof(double)));
1.1 misho 636:
637: case FILE_REGEX:
638: if ((m->str_flags & REGEX_OFFSET_START) != 0)
1.1.1.2 ! misho 639: return CAST(int32_t, ms->search.offset);
1.1 misho 640: else
1.1.1.2 ! misho 641: return CAST(int32_t, (ms->search.offset +
! 642: ms->search.rm_len));
1.1 misho 643:
644: case FILE_SEARCH:
645: if ((m->str_flags & REGEX_OFFSET_START) != 0)
1.1.1.2 ! misho 646: return CAST(int32_t, ms->search.offset);
1.1 misho 647: else
1.1.1.2 ! misho 648: return CAST(int32_t, (ms->search.offset + m->vallen));
1.1 misho 649:
650: case FILE_DEFAULT:
651: return ms->offset;
652:
653: case FILE_INDIRECT:
654: return ms->offset;
655:
656: default:
657: return 0;
658: }
659: }
660:
661: #define DO_CVT(fld, cast) \
662: if (m->num_mask) \
663: switch (m->mask_op & FILE_OPS_MASK) { \
664: case FILE_OPAND: \
665: p->fld &= cast m->num_mask; \
666: break; \
667: case FILE_OPOR: \
668: p->fld |= cast m->num_mask; \
669: break; \
670: case FILE_OPXOR: \
671: p->fld ^= cast m->num_mask; \
672: break; \
673: case FILE_OPADD: \
674: p->fld += cast m->num_mask; \
675: break; \
676: case FILE_OPMINUS: \
677: p->fld -= cast m->num_mask; \
678: break; \
679: case FILE_OPMULTIPLY: \
680: p->fld *= cast m->num_mask; \
681: break; \
682: case FILE_OPDIVIDE: \
683: p->fld /= cast m->num_mask; \
684: break; \
685: case FILE_OPMODULO: \
686: p->fld %= cast m->num_mask; \
687: break; \
688: } \
689: if (m->mask_op & FILE_OPINVERSE) \
690: p->fld = ~p->fld \
691:
692: private void
693: cvt_8(union VALUETYPE *p, const struct magic *m)
694: {
695: DO_CVT(b, (uint8_t));
696: }
697:
698: private void
699: cvt_16(union VALUETYPE *p, const struct magic *m)
700: {
701: DO_CVT(h, (uint16_t));
702: }
703:
704: private void
705: cvt_32(union VALUETYPE *p, const struct magic *m)
706: {
707: DO_CVT(l, (uint32_t));
708: }
709:
710: private void
711: cvt_64(union VALUETYPE *p, const struct magic *m)
712: {
713: DO_CVT(q, (uint64_t));
714: }
715:
716: #define DO_CVT2(fld, cast) \
717: if (m->num_mask) \
718: switch (m->mask_op & FILE_OPS_MASK) { \
719: case FILE_OPADD: \
720: p->fld += cast (int64_t)m->num_mask; \
721: break; \
722: case FILE_OPMINUS: \
723: p->fld -= cast (int64_t)m->num_mask; \
724: break; \
725: case FILE_OPMULTIPLY: \
726: p->fld *= cast (int64_t)m->num_mask; \
727: break; \
728: case FILE_OPDIVIDE: \
729: p->fld /= cast (int64_t)m->num_mask; \
730: break; \
731: } \
732:
733: private void
734: cvt_float(union VALUETYPE *p, const struct magic *m)
735: {
736: DO_CVT2(f, (float));
737: }
738:
739: private void
740: cvt_double(union VALUETYPE *p, const struct magic *m)
741: {
742: DO_CVT2(d, (double));
743: }
744:
745: /*
746: * Convert the byte order of the data we are looking at
747: * While we're here, let's apply the mask operation
748: * (unless you have a better idea)
749: */
750: private int
751: mconvert(struct magic_set *ms, struct magic *m)
752: {
753: union VALUETYPE *p = &ms->ms_value;
754:
755: switch (m->type) {
756: case FILE_BYTE:
757: cvt_8(p, m);
758: return 1;
759: case FILE_SHORT:
760: cvt_16(p, m);
761: return 1;
762: case FILE_LONG:
763: case FILE_DATE:
764: case FILE_LDATE:
765: cvt_32(p, m);
766: return 1;
767: case FILE_QUAD:
768: case FILE_QDATE:
769: case FILE_QLDATE:
770: cvt_64(p, m);
771: return 1;
772: case FILE_STRING:
773: case FILE_BESTRING16:
774: case FILE_LESTRING16: {
775: /* Null terminate and eat *trailing* return */
776: p->s[sizeof(p->s) - 1] = '\0';
777: return 1;
778: }
779: case FILE_PSTRING: {
1.1.1.2 ! misho 780: char *ptr1 = p->s, *ptr2 = ptr1 + file_pstring_length_size(m);
! 781: size_t len = file_pstring_get_length(m, ptr1);
1.1 misho 782: if (len >= sizeof(p->s))
783: len = sizeof(p->s) - 1;
784: while (len--)
785: *ptr1++ = *ptr2++;
786: *ptr1 = '\0';
787: return 1;
788: }
789: case FILE_BESHORT:
790: p->h = (short)((p->hs[0]<<8)|(p->hs[1]));
791: cvt_16(p, m);
792: return 1;
793: case FILE_BELONG:
794: case FILE_BEDATE:
795: case FILE_BELDATE:
796: p->l = (int32_t)
797: ((p->hl[0]<<24)|(p->hl[1]<<16)|(p->hl[2]<<8)|(p->hl[3]));
798: cvt_32(p, m);
799: return 1;
800: case FILE_BEQUAD:
801: case FILE_BEQDATE:
802: case FILE_BEQLDATE:
803: p->q = (uint64_t)
804: (((uint64_t)p->hq[0]<<56)|((uint64_t)p->hq[1]<<48)|
805: ((uint64_t)p->hq[2]<<40)|((uint64_t)p->hq[3]<<32)|
806: ((uint64_t)p->hq[4]<<24)|((uint64_t)p->hq[5]<<16)|
807: ((uint64_t)p->hq[6]<<8)|((uint64_t)p->hq[7]));
808: cvt_64(p, m);
809: return 1;
810: case FILE_LESHORT:
811: p->h = (short)((p->hs[1]<<8)|(p->hs[0]));
812: cvt_16(p, m);
813: return 1;
814: case FILE_LELONG:
815: case FILE_LEDATE:
816: case FILE_LELDATE:
817: p->l = (int32_t)
818: ((p->hl[3]<<24)|(p->hl[2]<<16)|(p->hl[1]<<8)|(p->hl[0]));
819: cvt_32(p, m);
820: return 1;
821: case FILE_LEQUAD:
822: case FILE_LEQDATE:
823: case FILE_LEQLDATE:
824: p->q = (uint64_t)
825: (((uint64_t)p->hq[7]<<56)|((uint64_t)p->hq[6]<<48)|
826: ((uint64_t)p->hq[5]<<40)|((uint64_t)p->hq[4]<<32)|
827: ((uint64_t)p->hq[3]<<24)|((uint64_t)p->hq[2]<<16)|
828: ((uint64_t)p->hq[1]<<8)|((uint64_t)p->hq[0]));
829: cvt_64(p, m);
830: return 1;
831: case FILE_MELONG:
832: case FILE_MEDATE:
833: case FILE_MELDATE:
834: p->l = (int32_t)
835: ((p->hl[1]<<24)|(p->hl[0]<<16)|(p->hl[3]<<8)|(p->hl[2]));
836: cvt_32(p, m);
837: return 1;
838: case FILE_FLOAT:
839: cvt_float(p, m);
840: return 1;
841: case FILE_BEFLOAT:
842: p->l = ((uint32_t)p->hl[0]<<24)|((uint32_t)p->hl[1]<<16)|
843: ((uint32_t)p->hl[2]<<8) |((uint32_t)p->hl[3]);
844: cvt_float(p, m);
845: return 1;
846: case FILE_LEFLOAT:
847: p->l = ((uint32_t)p->hl[3]<<24)|((uint32_t)p->hl[2]<<16)|
848: ((uint32_t)p->hl[1]<<8) |((uint32_t)p->hl[0]);
849: cvt_float(p, m);
850: return 1;
851: case FILE_DOUBLE:
852: cvt_double(p, m);
853: return 1;
854: case FILE_BEDOUBLE:
855: p->q = ((uint64_t)p->hq[0]<<56)|((uint64_t)p->hq[1]<<48)|
856: ((uint64_t)p->hq[2]<<40)|((uint64_t)p->hq[3]<<32)|
857: ((uint64_t)p->hq[4]<<24)|((uint64_t)p->hq[5]<<16)|
858: ((uint64_t)p->hq[6]<<8) |((uint64_t)p->hq[7]);
859: cvt_double(p, m);
860: return 1;
861: case FILE_LEDOUBLE:
862: p->q = ((uint64_t)p->hq[7]<<56)|((uint64_t)p->hq[6]<<48)|
863: ((uint64_t)p->hq[5]<<40)|((uint64_t)p->hq[4]<<32)|
864: ((uint64_t)p->hq[3]<<24)|((uint64_t)p->hq[2]<<16)|
865: ((uint64_t)p->hq[1]<<8) |((uint64_t)p->hq[0]);
866: cvt_double(p, m);
867: return 1;
868: case FILE_REGEX:
869: case FILE_SEARCH:
870: case FILE_DEFAULT:
871: return 1;
872: default:
873: file_magerror(ms, "invalid type %d in mconvert()", m->type);
874: return 0;
875: }
876: }
877:
878:
879: private void
880: mdebug(uint32_t offset, const char *str, size_t len)
881: {
882: (void) fprintf(stderr, "mget @%d: ", offset);
883: file_showstr(stderr, str, len);
884: (void) fputc('\n', stderr);
885: (void) fputc('\n', stderr);
886: }
887:
888: private int
889: mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
890: const unsigned char *s, uint32_t offset, size_t nbytes, size_t linecnt)
891: {
892: /*
893: * Note: FILE_SEARCH and FILE_REGEX do not actually copy
894: * anything, but setup pointers into the source
895: */
896: if (indir == 0) {
897: switch (type) {
898: case FILE_SEARCH:
1.1.1.2 ! misho 899: ms->search.s = RCAST(const char *, s) + offset;
1.1 misho 900: ms->search.s_len = nbytes - offset;
901: ms->search.offset = offset;
902: return 0;
903:
904: case FILE_REGEX: {
905: const char *b;
906: const char *c;
907: const char *last; /* end of search region */
908: const char *buf; /* start of search region */
909: const char *end;
910: size_t lines;
911:
912: if (s == NULL) {
913: ms->search.s_len = 0;
914: ms->search.s = NULL;
915: return 0;
916: }
1.1.1.2 ! misho 917: buf = RCAST(const char *, s) + offset;
! 918: end = last = RCAST(const char *, s) + nbytes;
1.1 misho 919: /* mget() guarantees buf <= last */
1.1.1.2 ! misho 920: for (lines = linecnt, b = buf; lines && b < end &&
! 921: ((b = CAST(const char *,
! 922: memchr(c = b, '\n', CAST(size_t, (end - b)))))
! 923: || (b = CAST(const char *,
! 924: memchr(c, '\r', CAST(size_t, (end - c))))));
1.1 misho 925: lines--, b++) {
926: last = b;
927: if (b[0] == '\r' && b[1] == '\n')
928: b++;
929: }
930: if (lines)
1.1.1.2 ! misho 931: last = RCAST(const char *, s) + nbytes;
1.1 misho 932:
933: ms->search.s = buf;
934: ms->search.s_len = last - buf;
935: ms->search.offset = offset;
936: ms->search.rm_len = 0;
937: return 0;
938: }
939: case FILE_BESTRING16:
940: case FILE_LESTRING16: {
941: const unsigned char *src = s + offset;
942: const unsigned char *esrc = s + nbytes;
943: char *dst = p->s;
944: char *edst = &p->s[sizeof(p->s) - 1];
945:
946: if (type == FILE_BESTRING16)
947: src++;
948:
949: /* check for pointer overflow */
950: if (src < s) {
951: file_magerror(ms, "invalid offset %u in mcopy()",
952: offset);
953: return -1;
954: }
955: for (/*EMPTY*/; src < esrc; src += 2, dst++) {
956: if (dst < edst)
957: *dst = *src;
958: else
959: break;
960: if (*dst == '\0') {
961: if (type == FILE_BESTRING16 ?
962: *(src - 1) != '\0' :
963: *(src + 1) != '\0')
964: *dst = ' ';
965: }
966: }
967: *edst = '\0';
968: return 0;
969: }
970: case FILE_STRING: /* XXX - these two should not need */
971: case FILE_PSTRING: /* to copy anything, but do anyway. */
972: default:
973: break;
974: }
975: }
976:
977: if (offset >= nbytes) {
978: (void)memset(p, '\0', sizeof(*p));
979: return 0;
980: }
981: if (nbytes - offset < sizeof(*p))
982: nbytes = nbytes - offset;
983: else
984: nbytes = sizeof(*p);
985:
986: (void)memcpy(p, s + offset, nbytes);
987:
988: /*
989: * the usefulness of padding with zeroes eludes me, it
990: * might even cause problems
991: */
992: if (nbytes < sizeof(*p))
993: (void)memset(((char *)(void *)p) + nbytes, '\0',
994: sizeof(*p) - nbytes);
995: return 0;
996: }
997:
998: private int
999: mget(struct magic_set *ms, const unsigned char *s,
1.1.1.2 ! misho 1000: struct magic *m, size_t nbytes, unsigned int cont_level, int text)
1.1 misho 1001: {
1002: uint32_t offset = ms->offset;
1003: uint32_t count = m->str_range;
1004: union VALUETYPE *p = &ms->ms_value;
1005:
1006: if (mcopy(ms, p, m->type, m->flag & INDIR, s, offset, nbytes, count) == -1)
1007: return -1;
1008:
1009: if ((ms->flags & MAGIC_DEBUG) != 0) {
1010: mdebug(offset, (char *)(void *)p, sizeof(union VALUETYPE));
1011: }
1012:
1013: if (m->flag & INDIR) {
1014: int off = m->in_offset;
1015: if (m->in_op & FILE_OPINDIRECT) {
1016: const union VALUETYPE *q =
1017: ((const void *)(s + offset + off));
1018: switch (m->in_type) {
1019: case FILE_BYTE:
1020: off = q->b;
1021: break;
1022: case FILE_SHORT:
1023: off = q->h;
1024: break;
1025: case FILE_BESHORT:
1026: off = (short)((q->hs[0]<<8)|(q->hs[1]));
1027: break;
1028: case FILE_LESHORT:
1029: off = (short)((q->hs[1]<<8)|(q->hs[0]));
1030: break;
1031: case FILE_LONG:
1032: off = q->l;
1033: break;
1034: case FILE_BELONG:
1035: case FILE_BEID3:
1036: off = (int32_t)((q->hl[0]<<24)|(q->hl[1]<<16)|
1037: (q->hl[2]<<8)|(q->hl[3]));
1038: break;
1039: case FILE_LEID3:
1040: case FILE_LELONG:
1041: off = (int32_t)((q->hl[3]<<24)|(q->hl[2]<<16)|
1042: (q->hl[1]<<8)|(q->hl[0]));
1043: break;
1044: case FILE_MELONG:
1045: off = (int32_t)((q->hl[1]<<24)|(q->hl[0]<<16)|
1046: (q->hl[3]<<8)|(q->hl[2]));
1047: break;
1048: }
1049: }
1050: switch (m->in_type) {
1051: case FILE_BYTE:
1052: if (nbytes < (offset + 1))
1053: return 0;
1054: if (off) {
1055: switch (m->in_op & FILE_OPS_MASK) {
1056: case FILE_OPAND:
1057: offset = p->b & off;
1058: break;
1059: case FILE_OPOR:
1060: offset = p->b | off;
1061: break;
1062: case FILE_OPXOR:
1063: offset = p->b ^ off;
1064: break;
1065: case FILE_OPADD:
1066: offset = p->b + off;
1067: break;
1068: case FILE_OPMINUS:
1069: offset = p->b - off;
1070: break;
1071: case FILE_OPMULTIPLY:
1072: offset = p->b * off;
1073: break;
1074: case FILE_OPDIVIDE:
1075: offset = p->b / off;
1076: break;
1077: case FILE_OPMODULO:
1078: offset = p->b % off;
1079: break;
1080: }
1081: } else
1082: offset = p->b;
1083: if (m->in_op & FILE_OPINVERSE)
1084: offset = ~offset;
1085: break;
1086: case FILE_BESHORT:
1087: if (nbytes < (offset + 2))
1088: return 0;
1089: if (off) {
1090: switch (m->in_op & FILE_OPS_MASK) {
1091: case FILE_OPAND:
1092: offset = (short)((p->hs[0]<<8)|
1093: (p->hs[1])) &
1094: off;
1095: break;
1096: case FILE_OPOR:
1097: offset = (short)((p->hs[0]<<8)|
1098: (p->hs[1])) |
1099: off;
1100: break;
1101: case FILE_OPXOR:
1102: offset = (short)((p->hs[0]<<8)|
1103: (p->hs[1])) ^
1104: off;
1105: break;
1106: case FILE_OPADD:
1107: offset = (short)((p->hs[0]<<8)|
1108: (p->hs[1])) +
1109: off;
1110: break;
1111: case FILE_OPMINUS:
1112: offset = (short)((p->hs[0]<<8)|
1113: (p->hs[1])) -
1114: off;
1115: break;
1116: case FILE_OPMULTIPLY:
1117: offset = (short)((p->hs[0]<<8)|
1118: (p->hs[1])) *
1119: off;
1120: break;
1121: case FILE_OPDIVIDE:
1122: offset = (short)((p->hs[0]<<8)|
1123: (p->hs[1])) /
1124: off;
1125: break;
1126: case FILE_OPMODULO:
1127: offset = (short)((p->hs[0]<<8)|
1128: (p->hs[1])) %
1129: off;
1130: break;
1131: }
1132: } else
1133: offset = (short)((p->hs[0]<<8)|
1134: (p->hs[1]));
1135: if (m->in_op & FILE_OPINVERSE)
1136: offset = ~offset;
1137: break;
1138: case FILE_LESHORT:
1139: if (nbytes < (offset + 2))
1140: return 0;
1141: if (off) {
1142: switch (m->in_op & FILE_OPS_MASK) {
1143: case FILE_OPAND:
1144: offset = (short)((p->hs[1]<<8)|
1145: (p->hs[0])) &
1146: off;
1147: break;
1148: case FILE_OPOR:
1149: offset = (short)((p->hs[1]<<8)|
1150: (p->hs[0])) |
1151: off;
1152: break;
1153: case FILE_OPXOR:
1154: offset = (short)((p->hs[1]<<8)|
1155: (p->hs[0])) ^
1156: off;
1157: break;
1158: case FILE_OPADD:
1159: offset = (short)((p->hs[1]<<8)|
1160: (p->hs[0])) +
1161: off;
1162: break;
1163: case FILE_OPMINUS:
1164: offset = (short)((p->hs[1]<<8)|
1165: (p->hs[0])) -
1166: off;
1167: break;
1168: case FILE_OPMULTIPLY:
1169: offset = (short)((p->hs[1]<<8)|
1170: (p->hs[0])) *
1171: off;
1172: break;
1173: case FILE_OPDIVIDE:
1174: offset = (short)((p->hs[1]<<8)|
1175: (p->hs[0])) /
1176: off;
1177: break;
1178: case FILE_OPMODULO:
1179: offset = (short)((p->hs[1]<<8)|
1180: (p->hs[0])) %
1181: off;
1182: break;
1183: }
1184: } else
1185: offset = (short)((p->hs[1]<<8)|
1186: (p->hs[0]));
1187: if (m->in_op & FILE_OPINVERSE)
1188: offset = ~offset;
1189: break;
1190: case FILE_SHORT:
1191: if (nbytes < (offset + 2))
1192: return 0;
1193: if (off) {
1194: switch (m->in_op & FILE_OPS_MASK) {
1195: case FILE_OPAND:
1196: offset = p->h & off;
1197: break;
1198: case FILE_OPOR:
1199: offset = p->h | off;
1200: break;
1201: case FILE_OPXOR:
1202: offset = p->h ^ off;
1203: break;
1204: case FILE_OPADD:
1205: offset = p->h + off;
1206: break;
1207: case FILE_OPMINUS:
1208: offset = p->h - off;
1209: break;
1210: case FILE_OPMULTIPLY:
1211: offset = p->h * off;
1212: break;
1213: case FILE_OPDIVIDE:
1214: offset = p->h / off;
1215: break;
1216: case FILE_OPMODULO:
1217: offset = p->h % off;
1218: break;
1219: }
1220: }
1221: else
1222: offset = p->h;
1223: if (m->in_op & FILE_OPINVERSE)
1224: offset = ~offset;
1225: break;
1226: case FILE_BELONG:
1227: case FILE_BEID3:
1228: if (nbytes < (offset + 4))
1229: return 0;
1230: if (off) {
1231: switch (m->in_op & FILE_OPS_MASK) {
1232: case FILE_OPAND:
1233: offset = (int32_t)((p->hl[0]<<24)|
1234: (p->hl[1]<<16)|
1235: (p->hl[2]<<8)|
1236: (p->hl[3])) &
1237: off;
1238: break;
1239: case FILE_OPOR:
1240: offset = (int32_t)((p->hl[0]<<24)|
1241: (p->hl[1]<<16)|
1242: (p->hl[2]<<8)|
1243: (p->hl[3])) |
1244: off;
1245: break;
1246: case FILE_OPXOR:
1247: offset = (int32_t)((p->hl[0]<<24)|
1248: (p->hl[1]<<16)|
1249: (p->hl[2]<<8)|
1250: (p->hl[3])) ^
1251: off;
1252: break;
1253: case FILE_OPADD:
1254: offset = (int32_t)((p->hl[0]<<24)|
1255: (p->hl[1]<<16)|
1256: (p->hl[2]<<8)|
1257: (p->hl[3])) +
1258: off;
1259: break;
1260: case FILE_OPMINUS:
1261: offset = (int32_t)((p->hl[0]<<24)|
1262: (p->hl[1]<<16)|
1263: (p->hl[2]<<8)|
1264: (p->hl[3])) -
1265: off;
1266: break;
1267: case FILE_OPMULTIPLY:
1268: offset = (int32_t)((p->hl[0]<<24)|
1269: (p->hl[1]<<16)|
1270: (p->hl[2]<<8)|
1271: (p->hl[3])) *
1272: off;
1273: break;
1274: case FILE_OPDIVIDE:
1275: offset = (int32_t)((p->hl[0]<<24)|
1276: (p->hl[1]<<16)|
1277: (p->hl[2]<<8)|
1278: (p->hl[3])) /
1279: off;
1280: break;
1281: case FILE_OPMODULO:
1282: offset = (int32_t)((p->hl[0]<<24)|
1283: (p->hl[1]<<16)|
1284: (p->hl[2]<<8)|
1285: (p->hl[3])) %
1286: off;
1287: break;
1288: }
1289: } else
1290: offset = (int32_t)((p->hl[0]<<24)|
1291: (p->hl[1]<<16)|
1292: (p->hl[2]<<8)|
1293: (p->hl[3]));
1294: if (m->in_op & FILE_OPINVERSE)
1295: offset = ~offset;
1296: break;
1297: case FILE_LELONG:
1298: case FILE_LEID3:
1299: if (nbytes < (offset + 4))
1300: return 0;
1301: if (off) {
1302: switch (m->in_op & FILE_OPS_MASK) {
1303: case FILE_OPAND:
1304: offset = (int32_t)((p->hl[3]<<24)|
1305: (p->hl[2]<<16)|
1306: (p->hl[1]<<8)|
1307: (p->hl[0])) &
1308: off;
1309: break;
1310: case FILE_OPOR:
1311: offset = (int32_t)((p->hl[3]<<24)|
1312: (p->hl[2]<<16)|
1313: (p->hl[1]<<8)|
1314: (p->hl[0])) |
1315: off;
1316: break;
1317: case FILE_OPXOR:
1318: offset = (int32_t)((p->hl[3]<<24)|
1319: (p->hl[2]<<16)|
1320: (p->hl[1]<<8)|
1321: (p->hl[0])) ^
1322: off;
1323: break;
1324: case FILE_OPADD:
1325: offset = (int32_t)((p->hl[3]<<24)|
1326: (p->hl[2]<<16)|
1327: (p->hl[1]<<8)|
1328: (p->hl[0])) +
1329: off;
1330: break;
1331: case FILE_OPMINUS:
1332: offset = (int32_t)((p->hl[3]<<24)|
1333: (p->hl[2]<<16)|
1334: (p->hl[1]<<8)|
1335: (p->hl[0])) -
1336: off;
1337: break;
1338: case FILE_OPMULTIPLY:
1339: offset = (int32_t)((p->hl[3]<<24)|
1340: (p->hl[2]<<16)|
1341: (p->hl[1]<<8)|
1342: (p->hl[0])) *
1343: off;
1344: break;
1345: case FILE_OPDIVIDE:
1346: offset = (int32_t)((p->hl[3]<<24)|
1347: (p->hl[2]<<16)|
1348: (p->hl[1]<<8)|
1349: (p->hl[0])) /
1350: off;
1351: break;
1352: case FILE_OPMODULO:
1353: offset = (int32_t)((p->hl[3]<<24)|
1354: (p->hl[2]<<16)|
1355: (p->hl[1]<<8)|
1356: (p->hl[0])) %
1357: off;
1358: break;
1359: }
1360: } else
1361: offset = (int32_t)((p->hl[3]<<24)|
1362: (p->hl[2]<<16)|
1363: (p->hl[1]<<8)|
1364: (p->hl[0]));
1365: if (m->in_op & FILE_OPINVERSE)
1366: offset = ~offset;
1367: break;
1368: case FILE_MELONG:
1369: if (nbytes < (offset + 4))
1370: return 0;
1371: if (off) {
1372: switch (m->in_op & FILE_OPS_MASK) {
1373: case FILE_OPAND:
1374: offset = (int32_t)((p->hl[1]<<24)|
1375: (p->hl[0]<<16)|
1376: (p->hl[3]<<8)|
1377: (p->hl[2])) &
1378: off;
1379: break;
1380: case FILE_OPOR:
1381: offset = (int32_t)((p->hl[1]<<24)|
1382: (p->hl[0]<<16)|
1383: (p->hl[3]<<8)|
1384: (p->hl[2])) |
1385: off;
1386: break;
1387: case FILE_OPXOR:
1388: offset = (int32_t)((p->hl[1]<<24)|
1389: (p->hl[0]<<16)|
1390: (p->hl[3]<<8)|
1391: (p->hl[2])) ^
1392: off;
1393: break;
1394: case FILE_OPADD:
1395: offset = (int32_t)((p->hl[1]<<24)|
1396: (p->hl[0]<<16)|
1397: (p->hl[3]<<8)|
1398: (p->hl[2])) +
1399: off;
1400: break;
1401: case FILE_OPMINUS:
1402: offset = (int32_t)((p->hl[1]<<24)|
1403: (p->hl[0]<<16)|
1404: (p->hl[3]<<8)|
1405: (p->hl[2])) -
1406: off;
1407: break;
1408: case FILE_OPMULTIPLY:
1409: offset = (int32_t)((p->hl[1]<<24)|
1410: (p->hl[0]<<16)|
1411: (p->hl[3]<<8)|
1412: (p->hl[2])) *
1413: off;
1414: break;
1415: case FILE_OPDIVIDE:
1416: offset = (int32_t)((p->hl[1]<<24)|
1417: (p->hl[0]<<16)|
1418: (p->hl[3]<<8)|
1419: (p->hl[2])) /
1420: off;
1421: break;
1422: case FILE_OPMODULO:
1423: offset = (int32_t)((p->hl[1]<<24)|
1424: (p->hl[0]<<16)|
1425: (p->hl[3]<<8)|
1426: (p->hl[2])) %
1427: off;
1428: break;
1429: }
1430: } else
1431: offset = (int32_t)((p->hl[1]<<24)|
1432: (p->hl[0]<<16)|
1433: (p->hl[3]<<8)|
1434: (p->hl[2]));
1435: if (m->in_op & FILE_OPINVERSE)
1436: offset = ~offset;
1437: break;
1438: case FILE_LONG:
1439: if (nbytes < (offset + 4))
1440: return 0;
1441: if (off) {
1442: switch (m->in_op & FILE_OPS_MASK) {
1443: case FILE_OPAND:
1444: offset = p->l & off;
1445: break;
1446: case FILE_OPOR:
1447: offset = p->l | off;
1448: break;
1449: case FILE_OPXOR:
1450: offset = p->l ^ off;
1451: break;
1452: case FILE_OPADD:
1453: offset = p->l + off;
1454: break;
1455: case FILE_OPMINUS:
1456: offset = p->l - off;
1457: break;
1458: case FILE_OPMULTIPLY:
1459: offset = p->l * off;
1460: break;
1461: case FILE_OPDIVIDE:
1462: offset = p->l / off;
1463: break;
1464: case FILE_OPMODULO:
1465: offset = p->l % off;
1466: break;
1467: }
1468: } else
1469: offset = p->l;
1470: if (m->in_op & FILE_OPINVERSE)
1471: offset = ~offset;
1472: break;
1473: }
1474:
1475: switch (m->in_type) {
1476: case FILE_LEID3:
1477: case FILE_BEID3:
1478: offset = ((((offset >> 0) & 0x7f) << 0) |
1479: (((offset >> 8) & 0x7f) << 7) |
1480: (((offset >> 16) & 0x7f) << 14) |
1481: (((offset >> 24) & 0x7f) << 21)) + 10;
1482: break;
1483: default:
1484: break;
1485: }
1486:
1487: if (m->flag & INDIROFFADD) {
1488: offset += ms->c.li[cont_level-1].off;
1489: }
1490: if (mcopy(ms, p, m->type, 0, s, offset, nbytes, count) == -1)
1491: return -1;
1492: ms->offset = offset;
1493:
1494: if ((ms->flags & MAGIC_DEBUG) != 0) {
1495: mdebug(offset, (char *)(void *)p,
1496: sizeof(union VALUETYPE));
1497: }
1498: }
1499:
1500: /* Verify we have enough data to match magic type */
1501: switch (m->type) {
1502: case FILE_BYTE:
1503: if (nbytes < (offset + 1)) /* should alway be true */
1504: return 0;
1505: break;
1506:
1507: case FILE_SHORT:
1508: case FILE_BESHORT:
1509: case FILE_LESHORT:
1510: if (nbytes < (offset + 2))
1511: return 0;
1512: break;
1513:
1514: case FILE_LONG:
1515: case FILE_BELONG:
1516: case FILE_LELONG:
1517: case FILE_MELONG:
1518: case FILE_DATE:
1519: case FILE_BEDATE:
1520: case FILE_LEDATE:
1521: case FILE_MEDATE:
1522: case FILE_LDATE:
1523: case FILE_BELDATE:
1524: case FILE_LELDATE:
1525: case FILE_MELDATE:
1526: case FILE_FLOAT:
1527: case FILE_BEFLOAT:
1528: case FILE_LEFLOAT:
1529: if (nbytes < (offset + 4))
1530: return 0;
1531: break;
1532:
1533: case FILE_DOUBLE:
1534: case FILE_BEDOUBLE:
1535: case FILE_LEDOUBLE:
1536: if (nbytes < (offset + 8))
1537: return 0;
1538: break;
1539:
1540: case FILE_STRING:
1541: case FILE_PSTRING:
1542: case FILE_SEARCH:
1543: if (nbytes < (offset + m->vallen))
1544: return 0;
1545: break;
1546:
1547: case FILE_REGEX:
1548: if (nbytes < offset)
1549: return 0;
1550: break;
1551:
1552: case FILE_INDIRECT:
1553: if ((ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0 &&
1.1.1.2 ! misho 1554: file_printf(ms, "%s", m->desc) == -1)
1.1 misho 1555: return -1;
1556: if (nbytes < offset)
1557: return 0;
1558: return file_softmagic(ms, s + offset, nbytes - offset,
1.1.1.2 ! misho 1559: BINTEST, text);
1.1 misho 1560:
1561: case FILE_DEFAULT: /* nothing to check */
1562: default:
1563: break;
1564: }
1565: if (!mconvert(ms, m))
1566: return 0;
1567: return 1;
1568: }
1569:
1570: private uint64_t
1571: file_strncmp(const char *s1, const char *s2, size_t len, uint32_t flags)
1572: {
1573: /*
1574: * Convert the source args to unsigned here so that (1) the
1575: * compare will be unsigned as it is in strncmp() and (2) so
1576: * the ctype functions will work correctly without extra
1577: * casting.
1578: */
1579: const unsigned char *a = (const unsigned char *)s1;
1580: const unsigned char *b = (const unsigned char *)s2;
1581: uint64_t v;
1582:
1583: /*
1584: * What we want here is v = strncmp(s1, s2, len),
1585: * but ignoring any nulls.
1586: */
1587: v = 0;
1588: if (0L == flags) { /* normal string: do it fast */
1589: while (len-- > 0)
1590: if ((v = *b++ - *a++) != '\0')
1591: break;
1592: }
1593: else { /* combine the others */
1594: while (len-- > 0) {
1595: if ((flags & STRING_IGNORE_LOWERCASE) &&
1596: islower(*a)) {
1597: if ((v = tolower(*b++) - *a++) != '\0')
1598: break;
1599: }
1600: else if ((flags & STRING_IGNORE_UPPERCASE) &&
1601: isupper(*a)) {
1602: if ((v = toupper(*b++) - *a++) != '\0')
1603: break;
1604: }
1.1.1.2 ! misho 1605: else if ((flags & STRING_COMPACT_WHITESPACE) &&
1.1 misho 1606: isspace(*a)) {
1607: a++;
1608: if (isspace(*b++)) {
1.1.1.2 ! misho 1609: if (!isspace(*a))
! 1610: while (isspace(*b))
! 1611: b++;
1.1 misho 1612: }
1613: else {
1614: v = 1;
1615: break;
1616: }
1617: }
1.1.1.2 ! misho 1618: else if ((flags & STRING_COMPACT_OPTIONAL_WHITESPACE) &&
1.1 misho 1619: isspace(*a)) {
1620: a++;
1621: while (isspace(*b))
1622: b++;
1623: }
1624: else {
1625: if ((v = *b++ - *a++) != '\0')
1626: break;
1627: }
1628: }
1629: }
1630: return v;
1631: }
1632:
1633: private uint64_t
1634: file_strncmp16(const char *a, const char *b, size_t len, uint32_t flags)
1635: {
1636: /*
1637: * XXX - The 16-bit string compare probably needs to be done
1638: * differently, especially if the flags are to be supported.
1639: * At the moment, I am unsure.
1640: */
1641: flags = 0;
1642: return file_strncmp(a, b, len, flags);
1643: }
1644:
1.1.1.2 ! misho 1645: public void
1.1 misho 1646: convert_libmagic_pattern(zval *pattern, int options)
1647: {
1648: int i, j=0;
1649: char *t;
1650:
1651: t = (char *) safe_emalloc(Z_STRLEN_P(pattern), 2, 5);
1652:
1653: t[j++] = '~';
1654:
1655: for (i=0; i<Z_STRLEN_P(pattern); i++, j++) {
1656: switch (Z_STRVAL_P(pattern)[i]) {
1657: case '?':
1658: t[j] = '.';
1659: break;
1660: case '*':
1661: t[j++] = '.';
1662: t[j] = '*';
1663: break;
1664: case '.':
1665: t[j++] = '\\';
1666: t[j] = '.';
1667: break;
1668: case '\\':
1669: t[j++] = '\\';
1670: t[j] = '\\';
1671: break;
1672: case '(':
1673: t[j++] = '\\';
1674: t[j] = '(';
1675: break;
1676: case ')':
1677: t[j++] = '\\';
1678: t[j] = ')';
1679: break;
1680: case '~':
1681: t[j++] = '\\';
1682: t[j] = '~';
1683: break;
1684: default:
1685: t[j] = Z_STRVAL_P(pattern)[i];
1686: break;
1687: }
1688: }
1689: t[j++] = '~';
1690:
1691: if (options & PCRE_CASELESS)
1.1.1.2 ! misho 1692: t[j++] = 'i';
1.1 misho 1693:
1694: if (options & PCRE_MULTILINE)
1.1.1.2 ! misho 1695: t[j++] = 'm';
1.1 misho 1696:
1.1.1.2 ! misho 1697: t[j]='\0';
1.1 misho 1698:
1699: Z_STRVAL_P(pattern) = t;
1700: Z_STRLEN_P(pattern) = j;
1701:
1702: }
1703:
1704: private int
1705: magiccheck(struct magic_set *ms, struct magic *m)
1706: {
1707: uint64_t l = m->value.q;
1708: uint64_t v;
1709: float fl, fv;
1710: double dl, dv;
1711: int matched;
1712: union VALUETYPE *p = &ms->ms_value;
1713:
1714: switch (m->type) {
1715: case FILE_BYTE:
1716: v = p->b;
1717: break;
1718:
1719: case FILE_SHORT:
1720: case FILE_BESHORT:
1721: case FILE_LESHORT:
1722: v = p->h;
1723: break;
1724:
1725: case FILE_LONG:
1726: case FILE_BELONG:
1727: case FILE_LELONG:
1728: case FILE_MELONG:
1729: case FILE_DATE:
1730: case FILE_BEDATE:
1731: case FILE_LEDATE:
1732: case FILE_MEDATE:
1733: case FILE_LDATE:
1734: case FILE_BELDATE:
1735: case FILE_LELDATE:
1736: case FILE_MELDATE:
1737: v = p->l;
1738: break;
1739:
1740: case FILE_QUAD:
1741: case FILE_LEQUAD:
1742: case FILE_BEQUAD:
1743: case FILE_QDATE:
1744: case FILE_BEQDATE:
1745: case FILE_LEQDATE:
1746: case FILE_QLDATE:
1747: case FILE_BEQLDATE:
1748: case FILE_LEQLDATE:
1749: v = p->q;
1750: break;
1751:
1752: case FILE_FLOAT:
1753: case FILE_BEFLOAT:
1754: case FILE_LEFLOAT:
1755: fl = m->value.f;
1756: fv = p->f;
1757: switch (m->reln) {
1758: case 'x':
1759: matched = 1;
1760: break;
1761:
1762: case '!':
1763: matched = fv != fl;
1764: break;
1765:
1766: case '=':
1767: matched = fv == fl;
1768: break;
1769:
1770: case '>':
1771: matched = fv > fl;
1772: break;
1773:
1774: case '<':
1775: matched = fv < fl;
1776: break;
1777:
1778: default:
1779: matched = 0;
1780: file_magerror(ms, "cannot happen with float: invalid relation `%c'",
1781: m->reln);
1782: return -1;
1783: }
1784: return matched;
1785:
1786: case FILE_DOUBLE:
1787: case FILE_BEDOUBLE:
1788: case FILE_LEDOUBLE:
1789: dl = m->value.d;
1790: dv = p->d;
1791: switch (m->reln) {
1792: case 'x':
1793: matched = 1;
1794: break;
1795:
1796: case '!':
1797: matched = dv != dl;
1798: break;
1799:
1800: case '=':
1801: matched = dv == dl;
1802: break;
1803:
1804: case '>':
1805: matched = dv > dl;
1806: break;
1807:
1808: case '<':
1809: matched = dv < dl;
1810: break;
1811:
1812: default:
1813: matched = 0;
1814: file_magerror(ms, "cannot happen with double: invalid relation `%c'", m->reln);
1815: return -1;
1816: }
1817: return matched;
1818:
1819: case FILE_DEFAULT:
1820: l = 0;
1821: v = 0;
1822: break;
1823:
1824: case FILE_STRING:
1825: case FILE_PSTRING:
1826: l = 0;
1827: v = file_strncmp(m->value.s, p->s, (size_t)m->vallen, m->str_flags);
1828: break;
1829:
1830: case FILE_BESTRING16:
1831: case FILE_LESTRING16:
1832: l = 0;
1833: v = file_strncmp16(m->value.s, p->s, (size_t)m->vallen, m->str_flags);
1834: break;
1835:
1836: case FILE_SEARCH: { /* search ms->search.s for the string m->value.s */
1837: size_t slen;
1838: size_t idx;
1839:
1840: if (ms->search.s == NULL)
1841: return 0;
1842:
1843: slen = MIN(m->vallen, sizeof(m->value.s));
1844: l = 0;
1845: v = 0;
1846:
1847: for (idx = 0; m->str_range == 0 || idx < m->str_range; idx++) {
1848: if (slen + idx > ms->search.s_len)
1849: break;
1850:
1851: v = file_strncmp(m->value.s, ms->search.s + idx, slen, m->str_flags);
1852: if (v == 0) { /* found match */
1853: ms->search.offset += idx;
1854: break;
1855: }
1856: }
1857: break;
1858: }
1859: case FILE_REGEX: {
1860: zval *pattern;
1861: int options = 0;
1862: pcre_cache_entry *pce;
1863: TSRMLS_FETCH();
1864:
1865: MAKE_STD_ZVAL(pattern);
1866: ZVAL_STRINGL(pattern, (char *)m->value.s, m->vallen, 0);
1867:
1868: options |= PCRE_MULTILINE;
1869:
1870: if (m->str_flags & STRING_IGNORE_CASE) {
1871: options |= PCRE_CASELESS;
1872: }
1873:
1874: convert_libmagic_pattern(pattern, options);
1875:
1.1.1.2 ! misho 1876: l = 0;
1.1 misho 1877: #if (PHP_MAJOR_VERSION < 6)
1878: if ((pce = pcre_get_compiled_regex_cache(Z_STRVAL_P(pattern), Z_STRLEN_P(pattern) TSRMLS_CC)) == NULL) {
1879: #else
1880: if ((pce = pcre_get_compiled_regex_cache(IS_STRING, Z_STRVAL_P(pattern), Z_STRLEN_P(pattern) TSRMLS_CC)) == NULL) {
1881: #endif
1882: zval_dtor(pattern);
1883: FREE_ZVAL(pattern);
1884: return -1;
1885: } else {
1886: /* pce now contains the compiled regex */
1887: zval *retval;
1888: zval *subpats;
1889: char *haystack;
1890:
1891: MAKE_STD_ZVAL(retval);
1892: ALLOC_INIT_ZVAL(subpats);
1893:
1894: /* Cut the search len from haystack, equals to REG_STARTEND */
1895: haystack = estrndup(ms->search.s, ms->search.s_len);
1896:
1897: /* match v = 0, no match v = 1 */
1898: #if (PHP_MAJOR_VERSION < 6)
1899: php_pcre_match_impl(pce, haystack, ms->search.s_len, retval, subpats, 1, 1, PREG_OFFSET_CAPTURE, 0 TSRMLS_CC);
1900: #else
1901: php_pcre_match_impl(pce, IS_STRING, haystack, ms->search.s_len, retval, subpats, 1, 1, PREG_OFFSET_CAPTURE, 0 TSRMLS_CC);
1902: #endif
1903: /* Free haystack */
1904: efree(haystack);
1905:
1906: if (Z_LVAL_P(retval) < 0) {
1907: zval_ptr_dtor(&subpats);
1908: FREE_ZVAL(retval);
1909: zval_dtor(pattern);
1910: FREE_ZVAL(pattern);
1911: return -1;
1912: } else if ((Z_LVAL_P(retval) > 0) && (Z_TYPE_P(subpats) == IS_ARRAY)) {
1913:
1914: /* Need to fetch global match which equals pmatch[0] */
1915: HashTable *ht = Z_ARRVAL_P(subpats);
1916: HashPosition outer_pos;
1917: zval *pattern_match = NULL, *pattern_offset = NULL;
1918:
1919: zend_hash_internal_pointer_reset_ex(ht, &outer_pos);
1920:
1921: if (zend_hash_has_more_elements_ex(ht, &outer_pos) == SUCCESS &&
1922: zend_hash_move_forward_ex(ht, &outer_pos)) {
1923:
1924: zval **ppzval;
1925:
1926: /* The first element (should be) is the global match
1927: Need to move to the inner array to get the global match */
1928:
1929: if (zend_hash_get_current_data_ex(ht, (void**)&ppzval, &outer_pos) != FAILURE) {
1930:
1931: HashTable *inner_ht;
1932: HashPosition inner_pos;
1933: zval **match, **offset;
1934: zval tmpcopy = **ppzval, matchcopy, offsetcopy;
1935:
1936: zval_copy_ctor(&tmpcopy);
1937: INIT_PZVAL(&tmpcopy);
1938:
1939: inner_ht = Z_ARRVAL(tmpcopy);
1940:
1941: /* If everything goes according to the master plan
1942: tmpcopy now contains two elements:
1943: 0 = the match
1944: 1 = starting position of the match */
1945: zend_hash_internal_pointer_reset_ex(inner_ht, &inner_pos);
1946:
1947: if (zend_hash_has_more_elements_ex(inner_ht, &inner_pos) == SUCCESS &&
1948: zend_hash_move_forward_ex(inner_ht, &inner_pos)) {
1949:
1950: if (zend_hash_get_current_data_ex(inner_ht, (void**)&match, &inner_pos) != FAILURE) {
1951:
1952: matchcopy = **match;
1953: zval_copy_ctor(&matchcopy);
1954: INIT_PZVAL(&matchcopy);
1955: convert_to_string(&matchcopy);
1956:
1957: MAKE_STD_ZVAL(pattern_match);
1958: Z_STRVAL_P(pattern_match) = (char *)Z_STRVAL(matchcopy);
1959: Z_STRLEN_P(pattern_match) = Z_STRLEN(matchcopy);
1960: Z_TYPE_P(pattern_match) = IS_STRING;
1961:
1962: zval_dtor(&matchcopy);
1963: }
1964: }
1965:
1966: if (zend_hash_has_more_elements_ex(inner_ht, &inner_pos) == SUCCESS &&
1967: zend_hash_move_forward_ex(inner_ht, &inner_pos)) {
1968:
1969: if (zend_hash_get_current_data_ex(inner_ht, (void**)&offset, &inner_pos) != FAILURE) {
1970:
1971: offsetcopy = **offset;
1972: zval_copy_ctor(&offsetcopy);
1973: INIT_PZVAL(&offsetcopy);
1974: convert_to_long(&offsetcopy);
1975:
1976: MAKE_STD_ZVAL(pattern_offset);
1977: Z_LVAL_P(pattern_offset) = Z_LVAL(offsetcopy);
1978: Z_TYPE_P(pattern_offset) = IS_LONG;
1979:
1980: zval_dtor(&offsetcopy);
1981: }
1982: }
1983: zval_dtor(&tmpcopy);
1984: }
1985:
1986: if ((pattern_match != NULL) && (pattern_offset != NULL)) {
1987: ms->search.s += (int)Z_LVAL_P(pattern_offset); /* this is where the match starts */
1988: ms->search.offset += (size_t)Z_LVAL_P(pattern_offset); /* this is where the match starts as size_t */
1989: ms->search.rm_len = Z_STRLEN_P(pattern_match) /* This is the length of the matched pattern */;
1990: v = 0;
1991:
1992: efree(pattern_match);
1993: efree(pattern_offset);
1994:
1995: } else {
1996: zval_ptr_dtor(&subpats);
1997: FREE_ZVAL(retval);
1998: zval_dtor(pattern);
1999: FREE_ZVAL(pattern);
2000: return -1;
2001: }
2002: }
2003:
2004:
2005: } else {
2006: v = 1;
2007: }
2008: zval_ptr_dtor(&subpats);
2009: FREE_ZVAL(retval);
2010: }
2011: zval_dtor(pattern);
2012: FREE_ZVAL(pattern);
2013: break;
2014: }
2015: case FILE_INDIRECT:
2016: return 1;
2017: default:
2018: file_magerror(ms, "invalid type %d in magiccheck()", m->type);
2019: return -1;
2020: }
2021:
2022: v = file_signextend(ms, m, v);
2023:
2024: switch (m->reln) {
2025: case 'x':
2026: if ((ms->flags & MAGIC_DEBUG) != 0)
1.1.1.2 ! misho 2027: (void) fprintf(stderr, "%" INT64_T_FORMAT
! 2028: "u == *any* = 1\n", (unsigned long long)v);
1.1 misho 2029: matched = 1;
2030: break;
2031:
2032: case '!':
2033: matched = v != l;
2034: if ((ms->flags & MAGIC_DEBUG) != 0)
1.1.1.2 ! misho 2035: (void) fprintf(stderr, "%" INT64_T_FORMAT "u != %"
! 2036: INT64_T_FORMAT "u = %d\n", (unsigned long long)v,
! 2037: (unsigned long long)l, matched);
1.1 misho 2038: break;
2039:
2040: case '=':
2041: matched = v == l;
2042: if ((ms->flags & MAGIC_DEBUG) != 0)
1.1.1.2 ! misho 2043: (void) fprintf(stderr, "%" INT64_T_FORMAT "u == %"
! 2044: INT64_T_FORMAT "u = %d\n", (unsigned long long)v,
! 2045: (unsigned long long)l, matched);
1.1 misho 2046: break;
2047:
2048: case '>':
2049: if (m->flag & UNSIGNED) {
2050: matched = v > l;
2051: if ((ms->flags & MAGIC_DEBUG) != 0)
1.1.1.2 ! misho 2052: (void) fprintf(stderr, "%" INT64_T_FORMAT
! 2053: "u > %" INT64_T_FORMAT "u = %d\n",
! 2054: (unsigned long long)v,
! 2055: (unsigned long long)l, matched);
1.1 misho 2056: }
2057: else {
2058: matched = (int64_t) v > (int64_t) l;
2059: if ((ms->flags & MAGIC_DEBUG) != 0)
1.1.1.2 ! misho 2060: (void) fprintf(stderr, "%" INT64_T_FORMAT
! 2061: "d > %" INT64_T_FORMAT "d = %d\n",
! 2062: (long long)v, (long long)l, matched);
1.1 misho 2063: }
2064: break;
2065:
2066: case '<':
2067: if (m->flag & UNSIGNED) {
2068: matched = v < l;
2069: if ((ms->flags & MAGIC_DEBUG) != 0)
1.1.1.2 ! misho 2070: (void) fprintf(stderr, "%" INT64_T_FORMAT
! 2071: "u < %" INT64_T_FORMAT "u = %d\n",
! 2072: (unsigned long long)v,
! 2073: (unsigned long long)l, matched);
1.1 misho 2074: }
2075: else {
2076: matched = (int64_t) v < (int64_t) l;
2077: if ((ms->flags & MAGIC_DEBUG) != 0)
1.1.1.2 ! misho 2078: (void) fprintf(stderr, "%" INT64_T_FORMAT
! 2079: "d < %" INT64_T_FORMAT "d = %d\n",
! 2080: (long long)v, (long long)l, matched);
1.1 misho 2081: }
2082: break;
2083:
2084: case '&':
2085: matched = (v & l) == l;
2086: if ((ms->flags & MAGIC_DEBUG) != 0)
1.1.1.2 ! misho 2087: (void) fprintf(stderr, "((%" INT64_T_FORMAT "x & %"
! 2088: INT64_T_FORMAT "x) == %" INT64_T_FORMAT
! 2089: "x) = %d\n", (unsigned long long)v,
! 2090: (unsigned long long)l, (unsigned long long)l,
! 2091: matched);
1.1 misho 2092: break;
2093:
2094: case '^':
2095: matched = (v & l) != l;
2096: if ((ms->flags & MAGIC_DEBUG) != 0)
1.1.1.2 ! misho 2097: (void) fprintf(stderr, "((%" INT64_T_FORMAT "x & %"
! 2098: INT64_T_FORMAT "x) != %" INT64_T_FORMAT
! 2099: "x) = %d\n", (unsigned long long)v,
! 2100: (unsigned long long)l, (unsigned long long)l,
! 2101: matched);
1.1 misho 2102: break;
2103:
2104: default:
2105: matched = 0;
2106: file_magerror(ms, "cannot happen: invalid relation `%c'",
2107: m->reln);
2108: return -1;
2109: }
2110:
2111: return matched;
2112: }
2113:
2114: private int
2115: handle_annotation(struct magic_set *ms, struct magic *m)
2116: {
2117: if (ms->flags & MAGIC_APPLE) {
2118: if (file_printf(ms, "%.8s", m->apple) == -1)
2119: return -1;
2120: return 1;
2121: }
2122: if ((ms->flags & MAGIC_MIME_TYPE) && m->mimetype[0]) {
2123: if (file_printf(ms, "%s", m->mimetype) == -1)
2124: return -1;
2125: return 1;
2126: }
2127: return 0;
2128: }
2129:
2130: private int
2131: print_sep(struct magic_set *ms, int firstline)
2132: {
2133: if (ms->flags & MAGIC_MIME)
2134: return 0;
2135: if (firstline)
2136: return 0;
2137: /*
2138: * we found another match
2139: * put a newline and '-' to do some simple formatting
2140: */
2141: return file_printf(ms, "\n- ");
2142: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>