Annotation of src/usr.bin/file/magic-test.c, Revision 1.27
1.27 ! nicm 1: /* $OpenBSD: magic-test.c,v 1.26 2018/06/14 19:51:11 nicm Exp $ */
1.1 nicm 2:
3: /*
4: * Copyright (c) 2015 Nicholas Marriott <nicm@openbsd.org>
5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15: * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16: * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18:
19: #include <sys/types.h>
20:
21: #include <ctype.h>
22: #include <errno.h>
23: #include <fcntl.h>
24: #include <limits.h>
25: #include <stdarg.h>
26: #include <stdio.h>
27: #include <stdint.h>
28: #include <stdlib.h>
29: #include <string.h>
1.24 guenther 30: #include <time.h>
1.1 nicm 31: #include <unistd.h>
32: #include <vis.h>
33:
34: #include "magic.h"
35: #include "xmalloc.h"
36:
1.22 nicm 37: static int magic_test_line(struct magic_line *, struct magic_state *);
38:
39: static struct magic_line *
40: magic_get_named(struct magic *m, const char *name)
41: {
42: struct magic_line ml;
43:
44: ml.name = name;
45: return (RB_FIND(magic_named_tree, &m->named, &ml));
46: }
47:
48: static enum magic_type
49: magic_reverse_type(struct magic_state *ms, enum magic_type type)
50: {
51: if (!ms->reverse)
52: return (type);
53: switch (type) {
54: case MAGIC_TYPE_BESHORT:
55: return (MAGIC_TYPE_LESHORT);
56: case MAGIC_TYPE_BELONG:
57: return (MAGIC_TYPE_LELONG);
58: case MAGIC_TYPE_BEQUAD:
59: return (MAGIC_TYPE_LEQUAD);
60: case MAGIC_TYPE_UBESHORT:
61: return (MAGIC_TYPE_ULESHORT);
62: case MAGIC_TYPE_UBELONG:
63: return (MAGIC_TYPE_ULELONG);
64: case MAGIC_TYPE_UBEQUAD:
65: return (MAGIC_TYPE_ULEQUAD);
66: case MAGIC_TYPE_BEFLOAT:
67: return (MAGIC_TYPE_LEFLOAT);
68: case MAGIC_TYPE_BEDOUBLE:
69: return (MAGIC_TYPE_LEDOUBLE);
70: case MAGIC_TYPE_BEDATE:
71: return (MAGIC_TYPE_LEDATE);
72: case MAGIC_TYPE_BEQDATE:
73: return (MAGIC_TYPE_LEQDATE);
74: case MAGIC_TYPE_BELDATE:
75: return (MAGIC_TYPE_LELDATE);
76: case MAGIC_TYPE_BEQLDATE:
77: return (MAGIC_TYPE_LEQLDATE);
78: case MAGIC_TYPE_UBEDATE:
79: return (MAGIC_TYPE_ULEDATE);
80: case MAGIC_TYPE_UBEQDATE:
81: return (MAGIC_TYPE_ULEQDATE);
82: case MAGIC_TYPE_UBELDATE:
83: return (MAGIC_TYPE_ULELDATE);
84: case MAGIC_TYPE_UBEQLDATE:
85: return (MAGIC_TYPE_ULEQLDATE);
86: case MAGIC_TYPE_LESHORT:
87: return (MAGIC_TYPE_BESHORT);
88: case MAGIC_TYPE_LELONG:
89: return (MAGIC_TYPE_LELONG);
90: case MAGIC_TYPE_LEQUAD:
91: return (MAGIC_TYPE_LEQUAD);
92: case MAGIC_TYPE_ULESHORT:
93: return (MAGIC_TYPE_UBESHORT);
94: case MAGIC_TYPE_ULELONG:
95: return (MAGIC_TYPE_UBELONG);
96: case MAGIC_TYPE_ULEQUAD:
97: return (MAGIC_TYPE_UBEQUAD);
98: case MAGIC_TYPE_LEFLOAT:
99: return (MAGIC_TYPE_BEFLOAT);
100: case MAGIC_TYPE_LEDOUBLE:
101: return (MAGIC_TYPE_BEDOUBLE);
102: case MAGIC_TYPE_LEDATE:
103: return (MAGIC_TYPE_BEDATE);
104: case MAGIC_TYPE_LEQDATE:
105: return (MAGIC_TYPE_BEQDATE);
106: case MAGIC_TYPE_LELDATE:
107: return (MAGIC_TYPE_BELDATE);
108: case MAGIC_TYPE_LEQLDATE:
109: return (MAGIC_TYPE_BEQLDATE);
110: case MAGIC_TYPE_ULEDATE:
111: return (MAGIC_TYPE_UBEDATE);
112: case MAGIC_TYPE_ULEQDATE:
113: return (MAGIC_TYPE_UBEQDATE);
114: case MAGIC_TYPE_ULELDATE:
115: return (MAGIC_TYPE_UBELDATE);
116: case MAGIC_TYPE_ULEQLDATE:
117: return (MAGIC_TYPE_UBEQLDATE);
118: default:
119: return (type);
120: }
121: }
122:
1.1 nicm 123: static int
124: magic_one_eq(char a, char b, int cflag)
125: {
126: if (a == b)
127: return (1);
1.4 nicm 128: if (cflag && islower((u_char)b) && tolower((u_char)a) == (u_char)b)
1.1 nicm 129: return (1);
130: return (0);
131: }
132:
133: static int
134: magic_test_eq(const char *ap, size_t asize, const char *bp, size_t bsize,
135: int cflag, int bflag, int Bflag)
136: {
137: size_t aoff, boff, aspaces, bspaces;
138:
139: aoff = boff = 0;
140: while (aoff != asize && boff != bsize) {
141: if (Bflag && isspace((u_char)ap[aoff])) {
142: aspaces = 0;
143: while (aoff != asize && isspace((u_char)ap[aoff])) {
144: aspaces++;
145: aoff++;
146: }
147: bspaces = 0;
148: while (boff != bsize && isspace((u_char)bp[boff])) {
149: bspaces++;
150: boff++;
151: }
152: if (bspaces >= aspaces)
153: continue;
154: return (1);
155: }
156: if (magic_one_eq(ap[aoff], bp[boff], cflag)) {
157: aoff++;
158: boff++;
159: continue;
160: }
161: if (bflag && isspace((u_char)bp[boff])) {
162: boff++;
163: continue;
164: }
165: if (ap[aoff] < bp[boff])
166: return (-1);
167: return (1);
168: }
169: return (0);
170: }
171:
172: static int
173: magic_copy_from(struct magic_state *ms, ssize_t offset, void *dst, size_t size)
174: {
175: if (offset < 0)
176: offset = ms->offset;
177: if (offset + size > ms->size)
178: return (-1);
179: memcpy(dst, ms->base + offset, size);
180: return (0);
181: }
182:
183: static void
184: magic_add_result(struct magic_state *ms, struct magic_line *ml,
185: const char *fmt, ...)
186: {
187: va_list ap;
188: int separate;
189: char *s, *tmp, *add;
190:
191: va_start(ap, fmt);
192: if (ml->stringify) {
193: if (vasprintf(&s, fmt, ap) == -1) {
194: va_end(ap);
195: return;
196: }
197: va_end(ap);
198: if (asprintf(&tmp, ml->result, s) == -1) {
199: free(s);
200: return;
201: }
202: free(s);
203: } else {
204: if (vasprintf(&tmp, ml->result, ap) == -1) {
205: va_end(ap);
206: return;
207: }
208: va_end(ap);
209: }
210:
211: separate = 1;
212: if (tmp[0] == '\\' && tmp[1] == 'b') {
213: separate = 0;
214: add = tmp + 2;
215: } else
216: add = tmp;
217:
218: if (separate && *ms->out != '\0')
219: strlcat(ms->out, " ", sizeof ms->out);
220: strlcat(ms->out, add, sizeof ms->out);
221:
222: free(tmp);
223: }
224:
225: static void
226: magic_add_string(struct magic_state *ms, struct magic_line *ml,
1.2 deraadt 227: const char *s, size_t slen)
1.1 nicm 228: {
229: char *out;
230: size_t outlen, offset;
231:
232: outlen = MAGIC_STRING_SIZE;
233: if (outlen > slen)
234: outlen = slen;
235: for (offset = 0; offset < outlen; offset++) {
236: if (s[offset] == '\0' || !isprint((u_char)s[offset])) {
237: outlen = offset;
238: break;
239: }
240: }
241: out = xreallocarray(NULL, 4, outlen + 1);
242: strvisx(out, s, outlen, VIS_TAB|VIS_NL|VIS_CSTYLE|VIS_OCTAL);
243: magic_add_result(ms, ml, "%s", out);
244: free(out);
245: }
246:
247: static int
248: magic_test_signed(struct magic_line *ml, int64_t value, int64_t wanted)
249: {
250: switch (ml->test_operator) {
251: case 'x':
252: return (1);
253: case '<':
254: return (value < wanted);
255: case '[':
256: return (value <= wanted);
257: case '>':
258: return (value > wanted);
259: case ']':
260: return (value >= wanted);
261: case '=':
262: return (value == wanted);
263: case '&':
264: return ((value & wanted) == wanted);
265: case '^':
266: return ((~value & wanted) == wanted);
267: }
268: return (-1);
269: }
270:
271: static int
272: magic_test_unsigned(struct magic_line *ml, uint64_t value, uint64_t wanted)
273: {
274: switch (ml->test_operator) {
275: case 'x':
276: return (1);
277: case '<':
278: return (value < wanted);
279: case '[':
280: return (value <= wanted);
281: case '>':
282: return (value > wanted);
283: case ']':
284: return (value >= wanted);
285: case '=':
286: return (value == wanted);
287: case '&':
288: return ((value & wanted) == wanted);
289: case '^':
290: return ((~value & wanted) == wanted);
291: }
292: return (-1);
293: }
294:
295: static int
1.7 nicm 296: magic_test_double(struct magic_line *ml, double value, double wanted)
297: {
298: switch (ml->test_operator) {
299: case 'x':
300: return (1);
301: case '=':
302: return (value == wanted);
303: }
304: return (-1);
305: }
306:
307: static int
1.1 nicm 308: magic_test_type_none(__unused struct magic_line *ml,
309: __unused struct magic_state *ms)
310: {
311: return (0);
312: }
313:
314: static int
315: magic_test_type_byte(struct magic_line *ml, struct magic_state *ms)
316: {
317: int8_t value;
318: int result;
319:
320: if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
321: return (0);
322:
323: if (ml->type_operator == '&')
324: value &= (int8_t)ml->type_operand;
1.8 nicm 325: else if (ml->type_operator == '-')
326: value -= (int8_t)ml->type_operand;
327: else if (ml->type_operator == '+')
328: value += (int8_t)ml->type_operand;
329: else if (ml->type_operator == '/')
330: value /= (int8_t)ml->type_operand;
331: else if (ml->type_operator == '%')
332: value %= (int8_t)ml->type_operand;
333: else if (ml->type_operator == '*')
334: value *= (int8_t)ml->type_operand;
1.1 nicm 335: else if (ml->type_operator != ' ')
336: return (-1);
337:
338: result = magic_test_signed(ml, value, (int8_t)ml->test_signed);
339: if (result == !ml->test_not && ml->result != NULL) {
340: magic_add_result(ms, ml, "%c", (int)value);
341: ms->offset += sizeof value;
342: }
343: return (result);
344: }
345:
346: static int
347: magic_test_type_short(struct magic_line *ml, struct magic_state *ms)
348: {
349: int16_t value;
350: int result;
351:
352: if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
353: return (0);
1.22 nicm 354: if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BESHORT))
1.3 brynet 355: value = be16toh(value);
1.22 nicm 356: if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LESHORT))
1.3 brynet 357: value = le16toh(value);
1.1 nicm 358:
359: if (ml->type_operator == '&')
360: value &= (int16_t)ml->type_operand;
1.8 nicm 361: else if (ml->type_operator == '-')
362: value -= (int16_t)ml->type_operand;
363: else if (ml->type_operator == '+')
364: value += (int16_t)ml->type_operand;
365: else if (ml->type_operator == '/')
366: value /= (int16_t)ml->type_operand;
367: else if (ml->type_operator == '%')
368: value %= (int16_t)ml->type_operand;
369: else if (ml->type_operator == '*')
370: value *= (int16_t)ml->type_operand;
1.1 nicm 371: else if (ml->type_operator != ' ')
372: return (-1);
373:
374: result = magic_test_signed(ml, value, (int16_t)ml->test_signed);
375: if (result == !ml->test_not && ml->result != NULL) {
376: magic_add_result(ms, ml, "%hd", (int)value);
377: ms->offset += sizeof value;
378: }
379: return (result);
380: }
381:
382: static int
383: magic_test_type_long(struct magic_line *ml, struct magic_state *ms)
384: {
385: int32_t value;
386: int result;
387:
388: if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
389: return (0);
1.22 nicm 390: if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BELONG))
1.3 brynet 391: value = be32toh(value);
1.22 nicm 392: if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LELONG))
1.3 brynet 393: value = le32toh(value);
1.1 nicm 394:
395: if (ml->type_operator == '&')
396: value &= (int32_t)ml->type_operand;
1.8 nicm 397: else if (ml->type_operator == '-')
398: value -= (int32_t)ml->type_operand;
399: else if (ml->type_operator == '+')
400: value += (int32_t)ml->type_operand;
401: else if (ml->type_operator == '/')
402: value /= (int32_t)ml->type_operand;
403: else if (ml->type_operator == '%')
404: value %= (int32_t)ml->type_operand;
405: else if (ml->type_operator == '*')
406: value *= (int32_t)ml->type_operand;
1.1 nicm 407: else if (ml->type_operator != ' ')
408: return (-1);
409:
410: result = magic_test_signed(ml, value, (int32_t)ml->test_signed);
411: if (result == !ml->test_not && ml->result != NULL) {
412: magic_add_result(ms, ml, "%d", (int)value);
413: ms->offset += sizeof value;
414: }
415: return (result);
416: }
417:
418: static int
419: magic_test_type_quad(struct magic_line *ml, struct magic_state *ms)
420: {
421: int64_t value;
422: int result;
423:
424: if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
425: return (0);
1.22 nicm 426: if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BEQUAD))
1.3 brynet 427: value = be64toh(value);
1.22 nicm 428: if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LEQUAD))
1.3 brynet 429: value = le64toh(value);
1.1 nicm 430:
431: if (ml->type_operator == '&')
432: value &= (int64_t)ml->type_operand;
1.8 nicm 433: else if (ml->type_operator == '-')
434: value -= (int64_t)ml->type_operand;
435: else if (ml->type_operator == '+')
436: value += (int64_t)ml->type_operand;
437: else if (ml->type_operator == '/')
438: value /= (int64_t)ml->type_operand;
439: else if (ml->type_operator == '%')
440: value %= (int64_t)ml->type_operand;
441: else if (ml->type_operator == '*')
442: value *= (int64_t)ml->type_operand;
1.1 nicm 443: else if (ml->type_operator != ' ')
444: return (-1);
445:
446: result = magic_test_signed(ml, value, (int64_t)ml->test_signed);
447: if (result == !ml->test_not && ml->result != NULL) {
448: magic_add_result(ms, ml, "%lld", (long long)value);
449: ms->offset += sizeof value;
450: }
451: return (result);
452: }
453:
454: static int
455: magic_test_type_ubyte(struct magic_line *ml, struct magic_state *ms)
456: {
457: uint8_t value;
458: int result;
459:
460: if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
461: return (0);
462:
463: if (ml->type_operator == '&')
464: value &= (uint8_t)ml->type_operand;
1.8 nicm 465: else if (ml->type_operator == '-')
466: value -= (uint8_t)ml->type_operand;
467: else if (ml->type_operator == '+')
468: value += (uint8_t)ml->type_operand;
469: else if (ml->type_operator == '/')
470: value /= (uint8_t)ml->type_operand;
471: else if (ml->type_operator == '%')
472: value %= (uint8_t)ml->type_operand;
473: else if (ml->type_operator == '*')
474: value *= (uint8_t)ml->type_operand;
1.1 nicm 475: else if (ml->type_operator != ' ')
476: return (-1);
477:
478: result = magic_test_unsigned(ml, value, (uint8_t)ml->test_unsigned);
479: if (result == !ml->test_not && ml->result != NULL) {
480: magic_add_result(ms, ml, "%c", (unsigned int)value);
481: ms->offset += sizeof value;
482: }
483: return (result);
484: }
485:
486: static int
487: magic_test_type_ushort(struct magic_line *ml, struct magic_state *ms)
488: {
489: uint16_t value;
490: int result;
491:
492: if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
493: return (0);
494: if (ml->type == MAGIC_TYPE_UBESHORT)
1.3 brynet 495: value = be16toh(value);
1.1 nicm 496: if (ml->type == MAGIC_TYPE_ULESHORT)
1.3 brynet 497: value = le16toh(value);
1.1 nicm 498:
499: if (ml->type_operator == '&')
500: value &= (uint16_t)ml->type_operand;
1.8 nicm 501: else if (ml->type_operator == '-')
502: value -= (uint16_t)ml->type_operand;
503: else if (ml->type_operator == '+')
504: value += (uint16_t)ml->type_operand;
505: else if (ml->type_operator == '/')
506: value /= (uint16_t)ml->type_operand;
507: else if (ml->type_operator == '%')
508: value %= (uint16_t)ml->type_operand;
509: else if (ml->type_operator == '*')
510: value *= (uint16_t)ml->type_operand;
1.1 nicm 511: else if (ml->type_operator != ' ')
512: return (-1);
513:
514: result = magic_test_unsigned(ml, value, (uint16_t)ml->test_unsigned);
515: if (result == !ml->test_not && ml->result != NULL) {
516: magic_add_result(ms, ml, "%hu", (unsigned int)value);
517: ms->offset += sizeof value;
518: }
519: return (result);
520: }
521:
522: static int
523: magic_test_type_ulong(struct magic_line *ml, struct magic_state *ms)
524: {
525: uint32_t value;
526: int result;
527:
528: if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
529: return (0);
530: if (ml->type == MAGIC_TYPE_UBELONG)
1.3 brynet 531: value = be32toh(value);
1.1 nicm 532: if (ml->type == MAGIC_TYPE_ULELONG)
1.3 brynet 533: value = le32toh(value);
1.1 nicm 534:
535: if (ml->type_operator == '&')
536: value &= (uint32_t)ml->type_operand;
1.8 nicm 537: else if (ml->type_operator == '-')
538: value -= (uint32_t)ml->type_operand;
539: else if (ml->type_operator == '+')
540: value += (uint32_t)ml->type_operand;
541: else if (ml->type_operator == '/')
542: value /= (uint32_t)ml->type_operand;
543: else if (ml->type_operator == '%')
544: value %= (uint32_t)ml->type_operand;
545: else if (ml->type_operator == '*')
546: value *= (uint32_t)ml->type_operand;
1.1 nicm 547: else if (ml->type_operator != ' ')
548: return (-1);
549:
550: result = magic_test_unsigned(ml, value, (uint32_t)ml->test_unsigned);
551: if (result == !ml->test_not && ml->result != NULL) {
552: magic_add_result(ms, ml, "%u", (unsigned int)value);
553: ms->offset += sizeof value;
554: }
555: return (result);
556: }
557:
558: static int
559: magic_test_type_uquad(struct magic_line *ml, struct magic_state *ms)
560: {
561: uint64_t value;
562: int result;
563:
564: if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
565: return (0);
566: if (ml->type == MAGIC_TYPE_UBEQUAD)
1.3 brynet 567: value = be64toh(value);
1.1 nicm 568: if (ml->type == MAGIC_TYPE_ULEQUAD)
1.3 brynet 569: value = le64toh(value);
1.1 nicm 570:
571: if (ml->type_operator == '&')
572: value &= (uint64_t)ml->type_operand;
1.8 nicm 573: else if (ml->type_operator == '-')
574: value -= (uint64_t)ml->type_operand;
575: else if (ml->type_operator == '+')
576: value += (uint64_t)ml->type_operand;
577: else if (ml->type_operator == '/')
578: value /= (uint64_t)ml->type_operand;
579: else if (ml->type_operator == '%')
580: value %= (uint64_t)ml->type_operand;
581: else if (ml->type_operator == '*')
582: value *= (uint64_t)ml->type_operand;
1.1 nicm 583: else if (ml->type_operator != ' ')
584: return (-1);
585:
586: result = magic_test_unsigned(ml, value, (uint64_t)ml->test_unsigned);
587: if (result == !ml->test_not && ml->result != NULL) {
588: magic_add_result(ms, ml, "%llu", (unsigned long long)value);
589: ms->offset += sizeof value;
590: }
591: return (result);
592: }
593:
594: static int
595: magic_test_type_float(struct magic_line *ml, struct magic_state *ms)
596: {
597: uint32_t value0;
1.16 nicm 598: float value;
1.7 nicm 599: int result;
1.1 nicm 600:
601: if (magic_copy_from(ms, -1, &value0, sizeof value0) != 0)
602: return (0);
1.22 nicm 603: if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BEFLOAT))
1.3 brynet 604: value0 = be32toh(value0);
1.22 nicm 605: if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LEFLOAT))
1.3 brynet 606: value0 = le32toh(value0);
1.1 nicm 607: memcpy(&value, &value0, sizeof value);
608:
609: if (ml->type_operator != ' ')
610: return (-1);
611:
1.7 nicm 612: result = magic_test_double(ml, value, (float)ml->test_double);
613: if (result == !ml->test_not && ml->result != NULL) {
614: magic_add_result(ms, ml, "%g", value);
615: ms->offset += sizeof value0;
616: }
1.1 nicm 617: return (1);
618: }
619:
620: static int
621: magic_test_type_double(struct magic_line *ml, struct magic_state *ms)
622: {
623: uint64_t value0;
624: double value;
1.7 nicm 625: int result;
1.1 nicm 626:
627: if (magic_copy_from(ms, -1, &value0, sizeof value0) != 0)
628: return (0);
1.22 nicm 629: if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BEDOUBLE))
1.3 brynet 630: value0 = be64toh(value0);
1.22 nicm 631: if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LEDOUBLE))
1.3 brynet 632: value0 = le64toh(value0);
1.1 nicm 633: memcpy(&value, &value0, sizeof value);
634:
635: if (ml->type_operator != ' ')
636: return (-1);
637:
1.7 nicm 638: result = magic_test_double(ml, value, (double)ml->test_double);
639: if (result == !ml->test_not && ml->result != NULL) {
640: magic_add_result(ms, ml, "%g", value);
641: ms->offset += sizeof value0;
642: }
1.1 nicm 643: return (1);
644: }
645:
646: static int
647: magic_test_type_string(struct magic_line *ml, struct magic_state *ms)
648: {
649: const char *s, *cp;
650: size_t slen;
651: int result, cflag = 0, bflag = 0, Bflag = 0;
652:
653: cp = &ml->type_string[(sizeof "string") - 1];
654: if (*cp != '\0') {
655: if (*cp != '/')
656: return (-1);
657: cp++;
658: for (; *cp != '\0'; cp++) {
659: switch (*cp) {
660: case 'B':
1.11 nicm 661: case 'W':
1.1 nicm 662: Bflag = 1;
663: break;
664: case 'b':
1.11 nicm 665: case 'w':
1.1 nicm 666: bflag = 1;
667: break;
668: case 'c':
669: cflag = 1;
670: break;
1.11 nicm 671: case 't':
672: break;
1.1 nicm 673: default:
674: return (-1);
675: }
676: }
677: }
678:
679: s = ms->base + ms->offset;
680: slen = ms->size - ms->offset;
681: if (slen < ml->test_string_size)
682: return (0);
683:
684: result = magic_test_eq(s, slen, ml->test_string, ml->test_string_size,
685: cflag, bflag, Bflag);
686: switch (ml->test_operator) {
687: case 'x':
688: result = 1;
689: break;
690: case '<':
691: result = result < 0;
692: break;
693: case '>':
694: result = result > 0;
695: break;
696: case '=':
1.10 nicm 697: slen = ml->test_string_size; /* only print what was found */
1.1 nicm 698: result = result == 0;
699: break;
700: default:
701: result = -1;
702: break;
703: }
704: if (result == !ml->test_not) {
705: if (ml->result != NULL)
706: magic_add_string(ms, ml, s, slen);
707: if (result && ml->test_operator == '=')
708: ms->offset = s - ms->base + ml->test_string_size;
709: }
710: return (result);
711: }
712:
713: static int
714: magic_test_type_pstring(struct magic_line *ml, struct magic_state *ms)
715: {
1.9 nicm 716: const char *s, *cp;
1.1 nicm 717: size_t slen;
718: int result;
1.9 nicm 719:
720: cp = &ml->type_string[(sizeof "pstring") - 1];
721: if (*cp != '\0') {
722: if (*cp != '/')
723: return (-1);
724: cp++;
725: for (; *cp != '\0'; cp++) {
726: switch (*cp) {
727: default:
728: return (-1);
729: }
730: }
731: }
1.1 nicm 732:
733: s = ms->base + ms->offset;
734: if (ms->size - ms->offset < 1)
735: return (-1);
736: slen = *(u_char *)s;
1.23 nicm 737: if (slen + 1 > ms->size - ms->offset)
1.1 nicm 738: return (-1);
739: s++;
740:
741: if (slen < ml->test_string_size)
742: result = -1;
743: else if (slen > ml->test_string_size)
744: result = 1;
745: else
746: result = memcmp(s, ml->test_string, ml->test_string_size);
747: switch (ml->test_operator) {
748: case 'x':
749: result = 1;
750: break;
751: case '<':
752: result = result < 0;
753: break;
754: case '>':
755: result = result > 0;
756: break;
757: case '=':
758: result = result == 0;
759: break;
760: default:
761: result = -1;
762: break;
763: }
764: if (result == !ml->test_not) {
765: if (ml->result != NULL)
766: magic_add_string(ms, ml, s, slen);
1.12 nicm 767: if (result && ml->test_operator == '=')
1.1 nicm 768: ms->offset += slen + 1;
769: }
770: return (result);
771: }
772:
773: static int
774: magic_test_type_date(struct magic_line *ml, struct magic_state *ms)
775: {
776: int32_t value;
777: int result;
778: time_t t;
779: char s[64];
780:
781: if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
782: return (0);
1.22 nicm 783: if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BEDATE) ||
784: ml->type == magic_reverse_type(ms, MAGIC_TYPE_BELDATE))
1.3 brynet 785: value = be32toh(value);
1.22 nicm 786: if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LEDATE) ||
787: ml->type == magic_reverse_type(ms, MAGIC_TYPE_LELDATE))
1.3 brynet 788: value = le32toh(value);
1.1 nicm 789:
790: if (ml->type_operator == '&')
791: value &= (int32_t)ml->type_operand;
1.13 nicm 792: else if (ml->type_operator == '-')
793: value -= (int32_t)ml->type_operand;
794: else if (ml->type_operator == '+')
795: value += (int32_t)ml->type_operand;
1.1 nicm 796: else if (ml->type_operator != ' ')
797: return (-1);
798:
799: result = magic_test_signed(ml, value, (int32_t)ml->test_signed);
800: if (result == !ml->test_not && ml->result != NULL) {
801: t = value;
802: switch (ml->type) {
803: case MAGIC_TYPE_LDATE:
804: case MAGIC_TYPE_LELDATE:
805: case MAGIC_TYPE_BELDATE:
806: ctime_r(&t, s);
807: break;
808: default:
1.6 nicm 809: asctime_r(gmtime(&t), s);
1.1 nicm 810: break;
811: }
812: s[strcspn(s, "\n")] = '\0';
813: magic_add_result(ms, ml, "%s", s);
814: ms->offset += sizeof value;
815: }
816: return (result);
817: }
818:
819: static int
820: magic_test_type_qdate(struct magic_line *ml, struct magic_state *ms)
821: {
822: int64_t value;
823: int result;
824: time_t t;
825: char s[64];
826:
827: if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
828: return (0);
1.22 nicm 829: if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BEQDATE) ||
830: ml->type == magic_reverse_type(ms, MAGIC_TYPE_BEQLDATE))
1.3 brynet 831: value = be64toh(value);
1.22 nicm 832: if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LEQDATE) ||
833: ml->type == magic_reverse_type(ms, MAGIC_TYPE_LEQLDATE))
1.3 brynet 834: value = le64toh(value);
1.1 nicm 835:
836: if (ml->type_operator == '&')
837: value &= (int64_t)ml->type_operand;
1.13 nicm 838: else if (ml->type_operator == '-')
839: value -= (int64_t)ml->type_operand;
840: else if (ml->type_operator == '+')
841: value += (int64_t)ml->type_operand;
1.1 nicm 842: else if (ml->type_operator != ' ')
843: return (-1);
844:
845: result = magic_test_signed(ml, value, (int64_t)ml->test_signed);
846: if (result == !ml->test_not && ml->result != NULL) {
847: t = value;
848: switch (ml->type) {
849: case MAGIC_TYPE_QLDATE:
850: case MAGIC_TYPE_LEQLDATE:
851: case MAGIC_TYPE_BEQLDATE:
852: ctime_r(&t, s);
853: break;
854: default:
1.6 nicm 855: asctime_r(gmtime(&t), s);
1.1 nicm 856: break;
857: }
858: s[strcspn(s, "\n")] = '\0';
859: magic_add_result(ms, ml, "%s", s);
860: ms->offset += sizeof value;
861: }
862: return (result);
863: }
864:
865: static int
866: magic_test_type_udate(struct magic_line *ml, struct magic_state *ms)
867: {
868: uint32_t value;
869: int result;
870: time_t t;
871: char s[64];
872:
873: if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
874: return (0);
1.22 nicm 875: if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BEDATE) ||
876: ml->type == magic_reverse_type(ms, MAGIC_TYPE_BELDATE))
1.3 brynet 877: value = be32toh(value);
1.22 nicm 878: if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LEDATE) ||
879: ml->type == magic_reverse_type(ms, MAGIC_TYPE_LELDATE))
1.3 brynet 880: value = le32toh(value);
1.1 nicm 881:
882: if (ml->type_operator == '&')
883: value &= (uint32_t)ml->type_operand;
1.13 nicm 884: else if (ml->type_operator == '-')
885: value -= (uint32_t)ml->type_operand;
886: else if (ml->type_operator == '+')
887: value += (uint32_t)ml->type_operand;
1.1 nicm 888: else if (ml->type_operator != ' ')
889: return (-1);
890:
891: result = magic_test_unsigned(ml, value, (uint32_t)ml->test_unsigned);
892: if (result == !ml->test_not && ml->result != NULL) {
893: t = value;
894: switch (ml->type) {
895: case MAGIC_TYPE_LDATE:
896: case MAGIC_TYPE_LELDATE:
897: case MAGIC_TYPE_BELDATE:
898: ctime_r(&t, s);
899: break;
900: default:
901: asctime_r(gmtime(&t), s);
902: break;
903: }
904: s[strcspn(s, "\n")] = '\0';
905: magic_add_result(ms, ml, "%s", s);
906: ms->offset += sizeof value;
907: }
908: return (result);
909: }
910:
911: static int
912: magic_test_type_uqdate(struct magic_line *ml, struct magic_state *ms)
913: {
914: uint64_t value;
915: int result;
916: time_t t;
917: char s[64];
918:
919: if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
920: return (0);
921: if (ml->type == MAGIC_TYPE_UBEQDATE ||
922: ml->type == MAGIC_TYPE_UBEQLDATE)
1.3 brynet 923: value = be64toh(value);
1.1 nicm 924: if (ml->type == MAGIC_TYPE_ULEQDATE ||
925: ml->type == MAGIC_TYPE_ULEQLDATE)
1.3 brynet 926: value = le64toh(value);
1.1 nicm 927:
928: if (ml->type_operator == '&')
929: value &= (uint64_t)ml->type_operand;
1.13 nicm 930: else if (ml->type_operator == '-')
931: value -= (uint64_t)ml->type_operand;
932: else if (ml->type_operator == '+')
933: value += (uint64_t)ml->type_operand;
1.1 nicm 934: else if (ml->type_operator != ' ')
935: return (-1);
936:
937: result = magic_test_unsigned(ml, value, (uint64_t)ml->test_unsigned);
938: if (result == !ml->test_not && ml->result != NULL) {
939: t = value;
940: switch (ml->type) {
941: case MAGIC_TYPE_UQLDATE:
942: case MAGIC_TYPE_ULEQLDATE:
943: case MAGIC_TYPE_UBEQLDATE:
944: ctime_r(&t, s);
945: break;
946: default:
947: asctime_r(gmtime(&t), s);
948: break;
949: }
950: s[strcspn(s, "\n")] = '\0';
951: magic_add_result(ms, ml, "%s", s);
952: ms->offset += sizeof value;
953: }
954: return (result);
955: }
956:
957: static int
958: magic_test_type_bestring16(__unused struct magic_line *ml,
959: __unused struct magic_state *ms)
960: {
961: return (-2);
962: }
963:
964: static int
965: magic_test_type_lestring16(__unused struct magic_line *ml,
966: __unused struct magic_state *ms)
967: {
968: return (-2);
969: }
970:
971: static int
972: magic_test_type_melong(__unused struct magic_line *ml,
973: __unused struct magic_state *ms)
974: {
975: return (-2);
976: }
977:
978: static int
979: magic_test_type_medate(__unused struct magic_line *ml,
980: __unused struct magic_state *ms)
981: {
982: return (-2);
983: }
984:
985: static int
986: magic_test_type_meldate(__unused struct magic_line *ml,
987: __unused struct magic_state *ms)
988: {
989: return (-2);
990: }
991:
992: static int
993: magic_test_type_regex(struct magic_line *ml, struct magic_state *ms)
994: {
995: const char *cp;
996: regex_t re;
997: regmatch_t m;
998: int result, flags = 0, sflag = 0;
999:
1000: cp = &ml->type_string[(sizeof "regex") - 1];
1001: if (*cp != '\0') {
1002: if (*cp != '/')
1003: return (-1);
1004: cp++;
1005: for (; *cp != '\0'; cp++) {
1006: switch (*cp) {
1007: case 's':
1008: sflag = 1;
1009: break;
1010: case 'c':
1011: flags |= REG_ICASE;
1012: break;
1013: default:
1014: return (-1);
1015: }
1016: }
1017: }
1018:
1.27 ! nicm 1019: if (regcomp(&re, ml->test_string, REG_EXTENDED|REG_NEWLINE|flags) != 0)
1.1 nicm 1020: return (-1);
1021: m.rm_so = ms->offset;
1022: m.rm_eo = ms->size;
1023:
1024: result = (regexec(&re, ms->base, 1, &m, REG_STARTEND) == 0);
1.12 nicm 1025: if (result == !ml->test_not) {
1.17 nicm 1026: if (ml->result != NULL) {
1027: magic_add_string(ms, ml, ms->base + m.rm_so,
1028: m.rm_eo - m.rm_so);
1029: }
1.1 nicm 1030: if (result) {
1031: if (sflag)
1032: ms->offset = m.rm_so;
1033: else
1034: ms->offset = m.rm_eo;
1035: }
1036: }
1037: regfree(&re);
1038: return (result);
1039: }
1040:
1041: static int
1042: magic_test_type_search(struct magic_line *ml, struct magic_state *ms)
1043: {
1044: const char *cp, *endptr, *start, *found;
1045: size_t size, end, i;
1046: uint64_t range;
1047: int result, n, cflag = 0, bflag = 0, Bflag = 0;
1048:
1049: cp = &ml->type_string[(sizeof "search") - 1];
1050: if (*cp != '\0') {
1051: if (*cp != '/')
1052: return (-1);
1053: cp++;
1054:
1055: endptr = magic_strtoull(cp, &range);
1056: if (endptr == NULL || (*endptr != '/' && *endptr != '\0'))
1057: return (-1);
1058:
1059: if (*endptr == '/') {
1060: for (cp = endptr + 1; *cp != '\0'; cp++) {
1061: switch (*cp) {
1062: case 'B':
1.11 nicm 1063: case 'W':
1.1 nicm 1064: Bflag = 1;
1065: break;
1066: case 'b':
1.11 nicm 1067: case 'w':
1.1 nicm 1068: bflag = 1;
1069: break;
1070: case 'c':
1071: cflag = 1;
1.11 nicm 1072: break;
1073: case 't':
1.1 nicm 1074: break;
1075: default:
1076: return (-1);
1077: }
1078: }
1079: }
1080: } else
1081: range = UINT64_MAX;
1082: if (range > (uint64_t)ms->size - ms->offset)
1083: range = ms->size - ms->offset;
1084: size = ml->test_string_size;
1085:
1086: /* Want to search every starting position from up to range + size. */
1087: end = range + size;
1088: if (end > ms->size - ms->offset) {
1089: if (size > ms->size - ms->offset)
1090: end = 0;
1091: else
1092: end = ms->size - ms->offset - size;
1093: }
1094:
1095: /*
1096: * < and > and the flags are only in /etc/magic with search/1 so don't
1097: * support them with anything else.
1098: */
1099: start = ms->base + ms->offset;
1100: if (end == 0)
1101: found = NULL;
1102: else if (ml->test_operator == 'x')
1103: found = start;
1104: else if (range == 1) {
1105: n = magic_test_eq(start, ms->size - ms->offset, ml->test_string,
1106: size, cflag, bflag, Bflag);
1107: if (n == -1 && ml->test_operator == '<')
1108: found = start;
1109: else if (n == 1 && ml->test_operator == '>')
1110: found = start;
1111: else if (n == 0 && ml->test_operator == '=')
1112: found = start;
1113: else
1114: found = NULL;
1115: } else {
1116: if (ml->test_operator != '=')
1117: return (-2);
1118: for (i = 0; i < end; i++) {
1119: n = magic_test_eq(start + i, ms->size - ms->offset - i,
1120: ml->test_string, size, cflag, bflag, Bflag);
1121: if (n == 0) {
1122: found = start + i;
1123: break;
1124: }
1125: }
1126: if (i == end)
1127: found = NULL;
1128: }
1129: result = (found != NULL);
1130:
1.12 nicm 1131: if (result == !ml->test_not) {
1132: if (ml->result != NULL)
1133: magic_add_string(ms, ml, found, ms->size - ms->offset);
1134: if (result && found != NULL && ml->test_operator == '=')
1135: ms->offset = (found + size) - ms->base;
1.1 nicm 1136: }
1137: return (result);
1138: }
1139:
1140: static int
1.21 nicm 1141: magic_test_type_default(struct magic_line *ml, struct magic_state *ms)
1.1 nicm 1142: {
1.20 nicm 1143: if (!ms->matched && ml->result != NULL)
1144: magic_add_result(ms, ml, "%s", "");
1.18 nicm 1145: return (!ms->matched);
1.1 nicm 1146: }
1147:
1.20 nicm 1148: static int
1.21 nicm 1149: magic_test_type_clear(struct magic_line *ml, struct magic_state *ms)
1.20 nicm 1150: {
1151: if (ml->result != NULL)
1152: magic_add_result(ms, ml, "%s", "");
1153: return (1);
1154: }
1155:
1.22 nicm 1156: static int
1157: magic_test_type_name(__unused struct magic_line *ml,
1158: __unused struct magic_state *ms)
1159: {
1160: return (-1);
1161: }
1162:
1163: static int
1164: magic_test_type_use(__unused struct magic_line *ml,
1165: __unused struct magic_state *ms)
1166: {
1167: return (1);
1168: }
1169:
1.1 nicm 1170: static int (*magic_test_functions[])(struct magic_line *,
1171: struct magic_state *) = {
1172: magic_test_type_none,
1173: magic_test_type_byte,
1174: magic_test_type_short,
1175: magic_test_type_long,
1176: magic_test_type_quad,
1177: magic_test_type_ubyte,
1178: magic_test_type_ushort,
1179: magic_test_type_ulong,
1180: magic_test_type_uquad,
1181: magic_test_type_float,
1182: magic_test_type_double,
1183: magic_test_type_string,
1184: magic_test_type_pstring,
1185: magic_test_type_date,
1186: magic_test_type_qdate,
1187: magic_test_type_date,
1188: magic_test_type_qdate,
1189: magic_test_type_udate,
1190: magic_test_type_uqdate,
1191: magic_test_type_udate,
1192: magic_test_type_qdate,
1193: magic_test_type_short,
1194: magic_test_type_long,
1195: magic_test_type_quad,
1196: magic_test_type_ushort,
1197: magic_test_type_ulong,
1198: magic_test_type_uquad,
1199: magic_test_type_float,
1200: magic_test_type_double,
1201: magic_test_type_date,
1202: magic_test_type_qdate,
1203: magic_test_type_date,
1204: magic_test_type_qdate,
1205: magic_test_type_udate,
1206: magic_test_type_uqdate,
1207: magic_test_type_udate,
1208: magic_test_type_uqdate,
1209: magic_test_type_bestring16,
1210: magic_test_type_short,
1211: magic_test_type_long,
1212: magic_test_type_quad,
1213: magic_test_type_ushort,
1214: magic_test_type_ulong,
1215: magic_test_type_uquad,
1216: magic_test_type_float,
1217: magic_test_type_double,
1218: magic_test_type_date,
1219: magic_test_type_qdate,
1220: magic_test_type_date,
1221: magic_test_type_qdate,
1222: magic_test_type_udate,
1223: magic_test_type_uqdate,
1224: magic_test_type_udate,
1225: magic_test_type_uqdate,
1226: magic_test_type_lestring16,
1227: magic_test_type_melong,
1228: magic_test_type_medate,
1229: magic_test_type_meldate,
1230: magic_test_type_regex,
1231: magic_test_type_search,
1232: magic_test_type_default,
1.20 nicm 1233: magic_test_type_clear,
1.22 nicm 1234: magic_test_type_name,
1235: magic_test_type_use,
1.1 nicm 1236: };
1237:
1.22 nicm 1238: static void
1239: magic_test_children(struct magic_line *ml, struct magic_state *ms, size_t start,
1240: int reverse)
1241: {
1242: struct magic_line *child;
1243: size_t saved_start, saved_offset;
1244: int saved_reverse;
1245:
1246: saved_start = ms->start;
1247: saved_reverse = ms->reverse;
1248: saved_offset = ms->offset;
1249:
1250: ms->matched = 0; /* no need to save, caller will set too */
1251:
1252: TAILQ_FOREACH(child, &ml->children, entry) {
1253: ms->start = start;
1254: ms->reverse = reverse;
1255: ms->offset = saved_offset;
1256:
1257: magic_test_line(child, ms);
1258: }
1259:
1260: ms->start = saved_start;
1261: ms->reverse = saved_reverse;
1262: ms->offset = saved_offset;
1263: }
1264:
1.1 nicm 1265: static int
1266: magic_test_line(struct magic_line *ml, struct magic_state *ms)
1267: {
1.22 nicm 1268: struct magic *m = ml->root;
1269: struct magic_line *named;
1.1 nicm 1270: int64_t offset, wanted, next;
1271: int result;
1272: uint8_t b;
1273: uint16_t s;
1274: uint32_t l;
1275:
1276: if (ml->indirect_type == ' ')
1.22 nicm 1277: wanted = ms->start + ml->offset;
1.1 nicm 1278: else {
1279: wanted = ml->indirect_offset;
1280: if (ml->indirect_relative) {
1.14 nicm 1281: if (wanted < 0 && (size_t)-wanted > ms->offset)
1.1 nicm 1282: return (0);
1283: if (wanted > 0 && ms->offset + wanted > ms->size)
1284: return (0);
1285: next = ms->offset + ml->indirect_offset;
1286: } else
1287: next = wanted;
1288:
1289: switch (ml->indirect_type) {
1290: case 'b':
1291: case 'B':
1292: if (magic_copy_from(ms, next, &b, sizeof b) != 0)
1293: return (0);
1294: wanted = b;
1295: break;
1296: case 's':
1297: if (magic_copy_from(ms, next, &s, sizeof s) != 0)
1298: return (0);
1.3 brynet 1299: wanted = le16toh(s);
1.1 nicm 1300: break;
1301: case 'S':
1302: if (magic_copy_from(ms, next, &s, sizeof s) != 0)
1303: return (0);
1.3 brynet 1304: wanted = be16toh(s);
1.1 nicm 1305: break;
1306: case 'l':
1307: if (magic_copy_from(ms, next, &l, sizeof l) != 0)
1308: return (0);
1.3 brynet 1309: wanted = le16toh(l);
1.1 nicm 1310: break;
1311: case 'L':
1312: if (magic_copy_from(ms, next, &l, sizeof l) != 0)
1313: return (0);
1.3 brynet 1314: wanted = be16toh(l);
1.1 nicm 1315: break;
1316: }
1317:
1318: switch (ml->indirect_operator) {
1319: case '+':
1320: wanted += ml->indirect_operand;
1321: break;
1322: case '-':
1323: wanted -= ml->indirect_operand;
1324: break;
1325: case '*':
1326: wanted *= ml->indirect_operand;
1327: break;
1328: }
1329: }
1330:
1331: if (ml->offset_relative) {
1.14 nicm 1332: if (wanted < 0 && (size_t)-wanted > ms->offset)
1.1 nicm 1333: return (0);
1334: if (wanted > 0 && ms->offset + wanted > ms->size)
1335: return (0);
1336: offset = ms->offset + wanted;
1337: } else
1338: offset = wanted;
1.14 nicm 1339: if (offset < 0 || (size_t)offset > ms->size)
1.1 nicm 1340: return (0);
1.22 nicm 1341: ms->offset = offset; /* test function may update */
1.1 nicm 1342:
1343: result = magic_test_functions[ml->type](ml, ms);
1344: if (result == -1) {
1345: magic_warn(ml, "test %s/%c failed", ml->type_string,
1346: ml->test_operator);
1347: return (0);
1348: }
1349: if (result == -2) {
1350: magic_warn(ml, "test %s/%c not implemented", ml->type_string,
1351: ml->test_operator);
1352: return (0);
1353: }
1354: if (result == ml->test_not)
1355: return (0);
1356: if (ml->mimetype != NULL)
1357: ms->mimetype = ml->mimetype;
1358:
1.22 nicm 1359: magic_warn(ml, "test %s/%c matched at offset %lld (now %zu): "
1360: "'%s'", ml->type_string, ml->test_operator, offset,
1361: ms->offset, ml->result == NULL ? "" : ml->result);
1362:
1363: if (ml->type == MAGIC_TYPE_USE) {
1364: if (*ml->name == '^')
1365: named = magic_get_named(m, ml->name + 1);
1366: else
1367: named = magic_get_named(m, ml->name);
1368: if (named == NULL) {
1369: magic_warn(ml, "no name found for use %s", ml->name);
1370: return (0);
1371: }
1372: magic_warn(ml, "use %s at offset %lld", ml->name, offset);
1373: magic_test_children(named, ms, offset, *ml->name == '^');
1374: }
1.1 nicm 1375:
1.22 nicm 1376: magic_test_children(ml, ms, ms->start, ms->reverse);
1.18 nicm 1377:
1.20 nicm 1378: if (ml->type == MAGIC_TYPE_CLEAR)
1379: ms->matched = 0;
1380: else
1381: ms->matched = 1;
1.5 nicm 1382: return (ml->result != NULL);
1.1 nicm 1383: }
1384:
1385: const char *
1386: magic_test(struct magic *m, const void *base, size_t size, int flags)
1387: {
1388: struct magic_line *ml;
1389: static struct magic_state ms;
1390:
1391: memset(&ms, 0, sizeof ms);
1392:
1393: ms.base = base;
1394: ms.size = size;
1395:
1396: ms.text = !!(flags & MAGIC_TEST_TEXT);
1397:
1398: RB_FOREACH(ml, magic_tree, &m->tree) {
1399: ms.offset = 0;
1400: if (ml->text == ms.text && magic_test_line(ml, &ms))
1401: break;
1402: }
1403:
1404: if (*ms.out != '\0') {
1405: if (flags & MAGIC_TEST_MIME) {
1.25 nicm 1406: if (ms.mimetype != NULL)
1.26 nicm 1407: return (ms.mimetype);
1.1 nicm 1408: return (NULL);
1409: }
1.26 nicm 1410: return (ms.out);
1.1 nicm 1411: }
1412: return (NULL);
1413: }