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