GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/file/magic-test.c Lines: 0 724 0.0 %
Date: 2016-12-06 Branches: 0 657 0.0 %

Line Branch Exec Source
1
/* $OpenBSD: magic-test.c,v 1.23 2016/05/01 11:26:19 nicm Exp $ */
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
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
122
static int
123
magic_one_eq(char a, char b, int cflag)
124
{
125
	if (a == b)
126
		return (1);
127
	if (cflag && islower((u_char)b) && tolower((u_char)a) == (u_char)b)
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,
226
    const char *s, size_t slen)
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
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
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;
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;
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);
353
	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BESHORT))
354
		value = be16toh(value);
355
	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LESHORT))
356
		value = le16toh(value);
357
358
	if (ml->type_operator == '&')
359
		value &= (int16_t)ml->type_operand;
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;
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);
389
	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BELONG))
390
		value = be32toh(value);
391
	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LELONG))
392
		value = le32toh(value);
393
394
	if (ml->type_operator == '&')
395
		value &= (int32_t)ml->type_operand;
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;
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);
425
	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BEQUAD))
426
		value = be64toh(value);
427
	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LEQUAD))
428
		value = le64toh(value);
429
430
	if (ml->type_operator == '&')
431
		value &= (int64_t)ml->type_operand;
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;
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;
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;
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)
494
		value = be16toh(value);
495
	if (ml->type == MAGIC_TYPE_ULESHORT)
496
		value = le16toh(value);
497
498
	if (ml->type_operator == '&')
499
		value &= (uint16_t)ml->type_operand;
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;
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)
530
		value = be32toh(value);
531
	if (ml->type == MAGIC_TYPE_ULELONG)
532
		value = le32toh(value);
533
534
	if (ml->type_operator == '&')
535
		value &= (uint32_t)ml->type_operand;
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;
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)
566
		value = be64toh(value);
567
	if (ml->type == MAGIC_TYPE_ULEQUAD)
568
		value = le64toh(value);
569
570
	if (ml->type_operator == '&')
571
		value &= (uint64_t)ml->type_operand;
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;
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;
597
	float		value;
598
	int		result;
599
600
	if (magic_copy_from(ms, -1, &value0, sizeof value0) != 0)
601
		return (0);
602
	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BEFLOAT))
603
		value0 = be32toh(value0);
604
	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LEFLOAT))
605
		value0 = le32toh(value0);
606
	memcpy(&value, &value0, sizeof value);
607
608
	if (ml->type_operator != ' ')
609
		return (-1);
610
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
	}
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;
624
	int		result;
625
626
	if (magic_copy_from(ms, -1, &value0, sizeof value0) != 0)
627
		return (0);
628
	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BEDOUBLE))
629
		value0 = be64toh(value0);
630
	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LEDOUBLE))
631
		value0 = le64toh(value0);
632
	memcpy(&value, &value0, sizeof value);
633
634
	if (ml->type_operator != ' ')
635
		return (-1);
636
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
	}
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':
660
			case 'W':
661
				Bflag = 1;
662
				break;
663
			case 'b':
664
			case 'w':
665
				bflag = 1;
666
				break;
667
			case 'c':
668
				cflag = 1;
669
				break;
670
			case 't':
671
				break;
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 '=':
696
		slen = ml->test_string_size; /* only print what was found */
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
{
715
	const char	*s, *cp;
716
	size_t		 slen;
717
	int		 result;
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
	}
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 + 1 > 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);
766
		if (result && ml->test_operator == '=')
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);
782
	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BEDATE) ||
783
	    ml->type == magic_reverse_type(ms, MAGIC_TYPE_BELDATE))
784
		value = be32toh(value);
785
	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LEDATE) ||
786
	    ml->type == magic_reverse_type(ms, MAGIC_TYPE_LELDATE))
787
		value = le32toh(value);
788
789
	if (ml->type_operator == '&')
790
		value &= (int32_t)ml->type_operand;
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;
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:
808
			asctime_r(gmtime(&t), s);
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);
828
	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BEQDATE) ||
829
	    ml->type == magic_reverse_type(ms, MAGIC_TYPE_BEQLDATE))
830
		value = be64toh(value);
831
	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LEQDATE) ||
832
	    ml->type == magic_reverse_type(ms, MAGIC_TYPE_LEQLDATE))
833
		value = le64toh(value);
834
835
	if (ml->type_operator == '&')
836
		value &= (int64_t)ml->type_operand;
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;
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:
854
			asctime_r(gmtime(&t), s);
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);
874
	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BEDATE) ||
875
	    ml->type == magic_reverse_type(ms, MAGIC_TYPE_BELDATE))
876
		value = be32toh(value);
877
	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LEDATE) ||
878
	    ml->type == magic_reverse_type(ms, MAGIC_TYPE_LELDATE))
879
		value = le32toh(value);
880
881
	if (ml->type_operator == '&')
882
		value &= (uint32_t)ml->type_operand;
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;
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)
922
		value = be64toh(value);
923
	if (ml->type == MAGIC_TYPE_ULEQDATE ||
924
	    ml->type == MAGIC_TYPE_ULEQLDATE)
925
		value = le64toh(value);
926
927
	if (ml->type_operator == '&')
928
		value &= (uint64_t)ml->type_operand;
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;
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);
1024
	if (result == !ml->test_not) {
1025
		if (ml->result != NULL) {
1026
			magic_add_string(ms, ml, ms->base + m.rm_so,
1027
			    m.rm_eo - m.rm_so);
1028
		}
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':
1062
				case 'W':
1063
					Bflag = 1;
1064
					break;
1065
				case 'b':
1066
				case 'w':
1067
					bflag = 1;
1068
					break;
1069
				case 'c':
1070
					cflag = 1;
1071
					break;
1072
				case 't':
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
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;
1135
	}
1136
	return (result);
1137
}
1138
1139
static int
1140
magic_test_type_default(struct magic_line *ml, struct magic_state *ms)
1141
{
1142
	if (!ms->matched && ml->result != NULL)
1143
		magic_add_result(ms, ml, "%s", "");
1144
	return (!ms->matched);
1145
}
1146
1147
static int
1148
magic_test_type_clear(struct magic_line *ml, struct magic_state *ms)
1149
{
1150
	if (ml->result != NULL)
1151
		magic_add_result(ms, ml, "%s", "");
1152
	return (1);
1153
}
1154
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
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,
1232
	magic_test_type_clear,
1233
	magic_test_type_name,
1234
	magic_test_type_use,
1235
};
1236
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
1264
static int
1265
magic_test_line(struct magic_line *ml, struct magic_state *ms)
1266
{
1267
	struct magic		*m = ml->root;
1268
	struct magic_line	*named;
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 == ' ')
1276
		wanted = ms->start + ml->offset;
1277
	else {
1278
		wanted = ml->indirect_offset;
1279
		if (ml->indirect_relative) {
1280
			if (wanted < 0 && (size_t)-wanted > ms->offset)
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);
1298
			wanted = le16toh(s);
1299
			break;
1300
		case 'S':
1301
			if (magic_copy_from(ms, next, &s, sizeof s) != 0)
1302
				return (0);
1303
			wanted = be16toh(s);
1304
			break;
1305
		case 'l':
1306
			if (magic_copy_from(ms, next, &l, sizeof l) != 0)
1307
				return (0);
1308
			wanted = le16toh(l);
1309
			break;
1310
		case 'L':
1311
			if (magic_copy_from(ms, next, &l, sizeof l) != 0)
1312
				return (0);
1313
			wanted = be16toh(l);
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) {
1331
		if (wanted < 0 && (size_t)-wanted > ms->offset)
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;
1338
	if (offset < 0 || (size_t)offset > ms->size)
1339
		return (0);
1340
	ms->offset = offset; /* test function may update */
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
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
	}
1374
1375
	magic_test_children(ml, ms, ms->start, ms->reverse);
1376
1377
	if (ml->type == MAGIC_TYPE_CLEAR)
1378
		ms->matched = 0;
1379
	else
1380
		ms->matched = 1;
1381
	return (ml->result != NULL);
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
}