xref: /dflybsd-src/contrib/file/src/softmagic.c (revision 739f0ef867128a933e021db3d831e906fcafd825)
1327e51cbSPeter Avalos /*
2327e51cbSPeter Avalos  * Copyright (c) Ian F. Darwin 1986-1995.
3327e51cbSPeter Avalos  * Software written by Ian F. Darwin and others;
4327e51cbSPeter Avalos  * maintained 1995-present by Christos Zoulas and others.
5327e51cbSPeter Avalos  *
6327e51cbSPeter Avalos  * Redistribution and use in source and binary forms, with or without
7327e51cbSPeter Avalos  * modification, are permitted provided that the following conditions
8327e51cbSPeter Avalos  * are met:
9327e51cbSPeter Avalos  * 1. Redistributions of source code must retain the above copyright
10327e51cbSPeter Avalos  *    notice immediately at the beginning of the file, without modification,
11327e51cbSPeter Avalos  *    this list of conditions, and the following disclaimer.
12327e51cbSPeter Avalos  * 2. Redistributions in binary form must reproduce the above copyright
13327e51cbSPeter Avalos  *    notice, this list of conditions and the following disclaimer in the
14327e51cbSPeter Avalos  *    documentation and/or other materials provided with the distribution.
15327e51cbSPeter Avalos  *
16327e51cbSPeter Avalos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17327e51cbSPeter Avalos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18327e51cbSPeter Avalos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19327e51cbSPeter Avalos  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20327e51cbSPeter Avalos  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21327e51cbSPeter Avalos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22327e51cbSPeter Avalos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23327e51cbSPeter Avalos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24327e51cbSPeter Avalos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25327e51cbSPeter Avalos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26327e51cbSPeter Avalos  * SUCH DAMAGE.
27327e51cbSPeter Avalos  */
28327e51cbSPeter Avalos /*
29327e51cbSPeter Avalos  * softmagic - interpret variable magic from MAGIC
30327e51cbSPeter Avalos  */
31327e51cbSPeter Avalos 
32327e51cbSPeter Avalos #include "file.h"
3379343712SPeter Avalos 
3479343712SPeter Avalos #ifndef	lint
35*3b9cdfa3SAntonio Huete Jimenez FILE_RCSID("@(#)$File: softmagic.c,v 1.328 2022/09/13 18:46:07 christos Exp $")
3679343712SPeter Avalos #endif	/* lint */
3779343712SPeter Avalos 
38327e51cbSPeter Avalos #include "magic.h"
39e8af9738SPeter Avalos #include <assert.h>
40327e51cbSPeter Avalos #include <string.h>
41327e51cbSPeter Avalos #include <ctype.h>
42327e51cbSPeter Avalos #include <stdlib.h>
43327e51cbSPeter Avalos #include <time.h>
44c30bd091SSascha Wildner #include "der.h"
45327e51cbSPeter Avalos 
46*3b9cdfa3SAntonio Huete Jimenez private int match(struct magic_set *, struct magic *, file_regex_t **, size_t,
47e88a9a20SSascha Wildner     const struct buffer *, size_t, int, int, int, uint16_t *,
48e88a9a20SSascha Wildner     uint16_t *, int *, int *, int *, int *);
49e88a9a20SSascha Wildner private int mget(struct magic_set *, struct magic *, const struct buffer *,
50e88a9a20SSascha Wildner     const unsigned char *, size_t,
51e88a9a20SSascha Wildner     size_t, unsigned int, int, int, int, uint16_t *,
52e88a9a20SSascha Wildner     uint16_t *, int *, int *, int *, int *);
53e88a9a20SSascha Wildner private int msetoffset(struct magic_set *, struct magic *, struct buffer *,
54e88a9a20SSascha Wildner     const struct buffer *, size_t, unsigned int);
55*3b9cdfa3SAntonio Huete Jimenez private int magiccheck(struct magic_set *, struct magic *, file_regex_t **);
56*3b9cdfa3SAntonio Huete Jimenez private int mprint(struct magic_set *, struct magic *);
57e88a9a20SSascha Wildner private int moffset(struct magic_set *, struct magic *, const struct buffer *,
58e88a9a20SSascha Wildner     int32_t *);
59327e51cbSPeter Avalos private void mdebug(uint32_t, const char *, size_t);
60327e51cbSPeter Avalos private int mcopy(struct magic_set *, union VALUETYPE *, int, int,
6182c5fa3eSPeter Avalos     const unsigned char *, uint32_t, size_t, struct magic *);
62e8af9738SPeter Avalos private int mconvert(struct magic_set *, struct magic *, int);
63327e51cbSPeter Avalos private int print_sep(struct magic_set *, int);
64c30bd091SSascha Wildner private int handle_annotation(struct magic_set *, struct magic *, int);
65c30bd091SSascha Wildner private int cvt_8(union VALUETYPE *, const struct magic *);
66c30bd091SSascha Wildner private int cvt_16(union VALUETYPE *, const struct magic *);
67c30bd091SSascha Wildner private int cvt_32(union VALUETYPE *, const struct magic *);
68c30bd091SSascha Wildner private int cvt_64(union VALUETYPE *, const struct magic *);
69327e51cbSPeter Avalos 
70e88a9a20SSascha Wildner #define OFFSET_OOB(n, o, i)	((n) < CAST(uint32_t, (o)) || (i) > ((n) - (o)))
71e88a9a20SSascha Wildner #define BE64(p) ( \
72e88a9a20SSascha Wildner     (CAST(uint64_t, (p)->hq[0])<<56)| \
73e88a9a20SSascha Wildner     (CAST(uint64_t, (p)->hq[1])<<48)| \
74e88a9a20SSascha Wildner     (CAST(uint64_t, (p)->hq[2])<<40)| \
75e88a9a20SSascha Wildner     (CAST(uint64_t, (p)->hq[3])<<32)| \
76e88a9a20SSascha Wildner     (CAST(uint64_t, (p)->hq[4])<<24)| \
77e88a9a20SSascha Wildner     (CAST(uint64_t, (p)->hq[5])<<16)| \
78e88a9a20SSascha Wildner     (CAST(uint64_t, (p)->hq[6])<<8)| \
79e88a9a20SSascha Wildner     (CAST(uint64_t, (p)->hq[7])))
80e88a9a20SSascha Wildner #define LE64(p) ( \
81e88a9a20SSascha Wildner     (CAST(uint64_t, (p)->hq[7])<<56)| \
82e88a9a20SSascha Wildner     (CAST(uint64_t, (p)->hq[6])<<48)| \
83e88a9a20SSascha Wildner     (CAST(uint64_t, (p)->hq[5])<<40)| \
84e88a9a20SSascha Wildner     (CAST(uint64_t, (p)->hq[4])<<32)| \
85e88a9a20SSascha Wildner     (CAST(uint64_t, (p)->hq[3])<<24)| \
86e88a9a20SSascha Wildner     (CAST(uint64_t, (p)->hq[2])<<16)| \
87e88a9a20SSascha Wildner     (CAST(uint64_t, (p)->hq[1])<<8)| \
88e88a9a20SSascha Wildner     (CAST(uint64_t, (p)->hq[0])))
89e88a9a20SSascha Wildner #define LE32(p) ( \
90e88a9a20SSascha Wildner     (CAST(uint32_t, (p)->hl[3])<<24)| \
91e88a9a20SSascha Wildner     (CAST(uint32_t, (p)->hl[2])<<16)| \
92e88a9a20SSascha Wildner     (CAST(uint32_t, (p)->hl[1])<<8)| \
93e88a9a20SSascha Wildner     (CAST(uint32_t, (p)->hl[0])))
94e88a9a20SSascha Wildner #define BE32(p) ( \
95e88a9a20SSascha Wildner     (CAST(uint32_t, (p)->hl[0])<<24)| \
96e88a9a20SSascha Wildner     (CAST(uint32_t, (p)->hl[1])<<16)| \
97e88a9a20SSascha Wildner     (CAST(uint32_t, (p)->hl[2])<<8)| \
98e88a9a20SSascha Wildner     (CAST(uint32_t, (p)->hl[3])))
99e88a9a20SSascha Wildner #define ME32(p) ( \
100e88a9a20SSascha Wildner     (CAST(uint32_t, (p)->hl[1])<<24)| \
101e88a9a20SSascha Wildner     (CAST(uint32_t, (p)->hl[0])<<16)| \
102e88a9a20SSascha Wildner     (CAST(uint32_t, (p)->hl[3])<<8)| \
103e88a9a20SSascha Wildner     (CAST(uint32_t, (p)->hl[2])))
104e88a9a20SSascha Wildner 
105e88a9a20SSascha Wildner #define BE16(p) ((CAST(uint16_t, (p)->hs[0])<<8)|(CAST(uint16_t, (p)->hs[1])))
106e88a9a20SSascha Wildner #define LE16(p) ((CAST(uint16_t, (p)->hs[1])<<8)|(CAST(uint16_t, (p)->hs[0])))
107e88a9a20SSascha Wildner #define SEXT(s,v,p) ((s) ? \
108e88a9a20SSascha Wildner 	CAST(intmax_t, CAST(int##v##_t, p)) : \
109e88a9a20SSascha Wildner 	CAST(intmax_t, CAST(uint##v##_t, p)))
11082c5fa3eSPeter Avalos 
111327e51cbSPeter Avalos /*
112327e51cbSPeter Avalos  * softmagic - lookup one file in parsed, in-memory copy of database
113327e51cbSPeter Avalos  * Passed the name and FILE * of one file to be typed.
114327e51cbSPeter Avalos  */
115327e51cbSPeter Avalos /*ARGSUSED1*/		/* nbytes passed for regularity, maybe need later */
116327e51cbSPeter Avalos protected int
file_softmagic(struct magic_set * ms,const struct buffer * b,uint16_t * indir_count,uint16_t * name_count,int mode,int text)117e88a9a20SSascha Wildner file_softmagic(struct magic_set *ms, const struct buffer *b,
118c30bd091SSascha Wildner     uint16_t *indir_count, uint16_t *name_count, int mode, int text)
119327e51cbSPeter Avalos {
120327e51cbSPeter Avalos 	struct mlist *ml;
121*3b9cdfa3SAntonio Huete Jimenez 	int rv = 0, printed_something = 0, need_separator = 0;
122c30bd091SSascha Wildner 	uint16_t nc, ic;
12382c5fa3eSPeter Avalos 
12482c5fa3eSPeter Avalos 	if (name_count == NULL) {
12582c5fa3eSPeter Avalos 		nc = 0;
12682c5fa3eSPeter Avalos 		name_count = &nc;
12782c5fa3eSPeter Avalos 	}
128c30bd091SSascha Wildner 	if (indir_count == NULL) {
129c30bd091SSascha Wildner 		ic = 0;
130c30bd091SSascha Wildner 		indir_count = &ic;
131c30bd091SSascha Wildner 	}
13282c5fa3eSPeter Avalos 
133*3b9cdfa3SAntonio Huete Jimenez 	for (ml = ms->mlist[0]->next; ml != ms->mlist[0]; ml = ml->next) {
134*3b9cdfa3SAntonio Huete Jimenez 		int ret = match(ms, ml->magic, ml->magic_rxcomp, ml->nmagic, b,
135*3b9cdfa3SAntonio Huete Jimenez 		    0, mode, text, 0, indir_count, name_count,
136*3b9cdfa3SAntonio Huete Jimenez 		    &printed_something, &need_separator, NULL, NULL);
137*3b9cdfa3SAntonio Huete Jimenez 		switch (ret) {
138*3b9cdfa3SAntonio Huete Jimenez 		case -1:
139*3b9cdfa3SAntonio Huete Jimenez 			return ret;
140*3b9cdfa3SAntonio Huete Jimenez 		case 0:
141*3b9cdfa3SAntonio Huete Jimenez 			continue;
142*3b9cdfa3SAntonio Huete Jimenez 		default:
143*3b9cdfa3SAntonio Huete Jimenez 			if ((ms->flags & MAGIC_CONTINUE) == 0)
144*3b9cdfa3SAntonio Huete Jimenez 				return ret;
145*3b9cdfa3SAntonio Huete Jimenez 			rv = ret;
146*3b9cdfa3SAntonio Huete Jimenez 			break;
147*3b9cdfa3SAntonio Huete Jimenez 		}
148*3b9cdfa3SAntonio Huete Jimenez 	}
149327e51cbSPeter Avalos 
150*3b9cdfa3SAntonio Huete Jimenez 	return rv;
151327e51cbSPeter Avalos }
152327e51cbSPeter Avalos 
15382c5fa3eSPeter Avalos #define FILE_FMTDEBUG
15482c5fa3eSPeter Avalos #ifdef FILE_FMTDEBUG
15582c5fa3eSPeter Avalos #define F(a, b, c) file_fmtcheck((a), (b), (c), __FILE__, __LINE__)
15682c5fa3eSPeter Avalos 
15782c5fa3eSPeter Avalos private const char * __attribute__((__format_arg__(3)))
file_fmtcheck(struct magic_set * ms,const char * desc,const char * def,const char * file,size_t line)158e88a9a20SSascha Wildner file_fmtcheck(struct magic_set *ms, const char *desc, const char *def,
15982c5fa3eSPeter Avalos 	const char *file, size_t line)
16082c5fa3eSPeter Avalos {
161e88a9a20SSascha Wildner 	const char *ptr;
162e88a9a20SSascha Wildner 
163e88a9a20SSascha Wildner 	if (strchr(desc, '%') == NULL)
164e88a9a20SSascha Wildner 		return desc;
165e88a9a20SSascha Wildner 
166e88a9a20SSascha Wildner 	ptr = fmtcheck(desc, def);
16782c5fa3eSPeter Avalos 	if (ptr == def)
16882c5fa3eSPeter Avalos 		file_magerror(ms,
16982c5fa3eSPeter Avalos 		    "%s, %" SIZE_T_FORMAT "u: format `%s' does not match"
170e88a9a20SSascha Wildner 		    " with `%s'", file, line, desc, def);
17182c5fa3eSPeter Avalos 	return ptr;
17282c5fa3eSPeter Avalos }
17382c5fa3eSPeter Avalos #else
174e88a9a20SSascha Wildner #define F(a, b, c) fmtcheck((b), (c))
17582c5fa3eSPeter Avalos #endif
17682c5fa3eSPeter Avalos 
177327e51cbSPeter Avalos /*
178327e51cbSPeter Avalos  * Go through the whole list, stopping if you find a match.  Process all
179327e51cbSPeter Avalos  * the continuations of that match before returning.
180327e51cbSPeter Avalos  *
181327e51cbSPeter Avalos  * We support multi-level continuations:
182327e51cbSPeter Avalos  *
183327e51cbSPeter Avalos  *	At any time when processing a successful top-level match, there is a
184327e51cbSPeter Avalos  *	current continuation level; it represents the level of the last
185327e51cbSPeter Avalos  *	successfully matched continuation.
186327e51cbSPeter Avalos  *
187327e51cbSPeter Avalos  *	Continuations above that level are skipped as, if we see one, it
188327e51cbSPeter Avalos  *	means that the continuation that controls them - i.e, the
189327e51cbSPeter Avalos  *	lower-level continuation preceding them - failed to match.
190327e51cbSPeter Avalos  *
191327e51cbSPeter Avalos  *	Continuations below that level are processed as, if we see one,
192327e51cbSPeter Avalos  *	it means we've finished processing or skipping higher-level
193327e51cbSPeter Avalos  *	continuations under the control of a successful or unsuccessful
194327e51cbSPeter Avalos  *	lower-level continuation, and are now seeing the next lower-level
195327e51cbSPeter Avalos  *	continuation and should process it.  The current continuation
196327e51cbSPeter Avalos  *	level reverts to the level of the one we're seeing.
197327e51cbSPeter Avalos  *
198327e51cbSPeter Avalos  *	Continuations at the current level are processed as, if we see
199327e51cbSPeter Avalos  *	one, there's no lower-level continuation that may have failed.
200327e51cbSPeter Avalos  *
201327e51cbSPeter Avalos  *	If a continuation matches, we bump the current continuation level
202327e51cbSPeter Avalos  *	so that higher-level continuations are processed.
203327e51cbSPeter Avalos  */
204327e51cbSPeter Avalos private int
match(struct magic_set * ms,struct magic * magic,file_regex_t ** magic_rxcomp,size_t nmagic,const struct buffer * b,size_t offset,int mode,int text,int flip,uint16_t * indir_count,uint16_t * name_count,int * printed_something,int * need_separator,int * returnval,int * found_match)205*3b9cdfa3SAntonio Huete Jimenez match(struct magic_set *ms, struct magic *magic, file_regex_t **magic_rxcomp,
206*3b9cdfa3SAntonio Huete Jimenez     size_t nmagic, const struct buffer *b, size_t offset, int mode, int text,
207c30bd091SSascha Wildner     int flip, uint16_t *indir_count, uint16_t *name_count,
208e88a9a20SSascha Wildner     int *printed_something, int *need_separator, int *returnval,
209e88a9a20SSascha Wildner     int *found_match)
210327e51cbSPeter Avalos {
211327e51cbSPeter Avalos 	uint32_t magindex = 0;
212327e51cbSPeter Avalos 	unsigned int cont_level = 0;
213e88a9a20SSascha Wildner 	int found_matchv = 0; /* if a match is found it is set to 1*/
214e88a9a20SSascha Wildner 	int returnvalv = 0, e;
215*3b9cdfa3SAntonio Huete Jimenez 	/* a flag to print X\n  X\n- X */
216*3b9cdfa3SAntonio Huete Jimenez 	int firstline = !(*printed_something || *need_separator);
217e88a9a20SSascha Wildner 	struct buffer bb;
218c30bd091SSascha Wildner 	int print = (ms->flags & MAGIC_NODESC) == 0;
219327e51cbSPeter Avalos 
220e88a9a20SSascha Wildner 	/*
221e88a9a20SSascha Wildner 	 * returnval can be 0 if a match is found, but there was no
222e88a9a20SSascha Wildner 	 * annotation to be printed.
223e88a9a20SSascha Wildner 	 */
224e8af9738SPeter Avalos 	if (returnval == NULL)
225e8af9738SPeter Avalos 		returnval = &returnvalv;
226e88a9a20SSascha Wildner 	if (found_match == NULL)
227e88a9a20SSascha Wildner 		found_match = &found_matchv;
228e8af9738SPeter Avalos 
229327e51cbSPeter Avalos 	if (file_check_mem(ms, cont_level) == -1)
230327e51cbSPeter Avalos 		return -1;
231327e51cbSPeter Avalos 
232327e51cbSPeter Avalos 	for (magindex = 0; magindex < nmagic; magindex++) {
23379343712SPeter Avalos 		int flush = 0;
23479343712SPeter Avalos 		struct magic *m = &magic[magindex];
235*3b9cdfa3SAntonio Huete Jimenez 		file_regex_t **m_rxcomp = &magic_rxcomp[magindex];
236327e51cbSPeter Avalos 
237e8af9738SPeter Avalos 		if (m->type != FILE_NAME)
2389f86ab30SPeter Avalos 		if ((IS_STRING(m->type) &&
239e8af9738SPeter Avalos #define FLT (STRING_BINTEST | STRING_TEXTTEST)
240e8af9738SPeter Avalos 		     ((text && (m->str_flags & FLT) == STRING_BINTEST) ||
241e8af9738SPeter Avalos 		      (!text && (m->str_flags & FLT) == STRING_TEXTTEST))) ||
2429f86ab30SPeter Avalos 		    (m->flag & mode) != mode) {
243c30bd091SSascha Wildner flush:
24479343712SPeter Avalos 			/* Skip sub-tests */
245c30bd091SSascha Wildner 			while (magindex < nmagic - 1 &&
246c30bd091SSascha Wildner 			    magic[magindex + 1].cont_level != 0)
247c30bd091SSascha Wildner 				magindex++;
248c30bd091SSascha Wildner 			cont_level = 0;
24979343712SPeter Avalos 			continue; /* Skip to next top-level test*/
25079343712SPeter Avalos 		}
25179343712SPeter Avalos 
252e88a9a20SSascha Wildner 		if (msetoffset(ms, m, &bb, b, offset, cont_level) == -1)
253e88a9a20SSascha Wildner 			goto flush;
25479343712SPeter Avalos 		ms->line = m->lineno;
255327e51cbSPeter Avalos 
256327e51cbSPeter Avalos 		/* if main entry matches, print it... */
257e88a9a20SSascha Wildner 		switch (mget(ms, m, b, CAST(const unsigned char *, bb.fbuf),
258e88a9a20SSascha Wildner 		    bb.flen, offset, cont_level,
259e88a9a20SSascha Wildner 		    mode, text, flip, indir_count, name_count,
260e88a9a20SSascha Wildner 		    printed_something, need_separator, returnval, found_match))
261e88a9a20SSascha Wildner 		{
26279343712SPeter Avalos 		case -1:
26379343712SPeter Avalos 			return -1;
26479343712SPeter Avalos 		case 0:
26579343712SPeter Avalos 			flush = m->reln != '!';
26679343712SPeter Avalos 			break;
26779343712SPeter Avalos 		default:
268e88a9a20SSascha Wildner 			if (m->type == FILE_INDIRECT) {
269e88a9a20SSascha Wildner 				*found_match = 1;
270e8af9738SPeter Avalos 				*returnval = 1;
271e88a9a20SSascha Wildner 			}
27279343712SPeter Avalos 
273*3b9cdfa3SAntonio Huete Jimenez 			switch (magiccheck(ms, m, m_rxcomp)) {
274327e51cbSPeter Avalos 			case -1:
275327e51cbSPeter Avalos 				return -1;
276327e51cbSPeter Avalos 			case 0:
277327e51cbSPeter Avalos 				flush++;
278327e51cbSPeter Avalos 				break;
279327e51cbSPeter Avalos 			default:
28079343712SPeter Avalos 				flush = 0;
281327e51cbSPeter Avalos 				break;
282327e51cbSPeter Avalos 			}
28379343712SPeter Avalos 			break;
284327e51cbSPeter Avalos 		}
285327e51cbSPeter Avalos 		if (flush) {
286327e51cbSPeter Avalos 			/*
287327e51cbSPeter Avalos 			 * main entry didn't match,
288327e51cbSPeter Avalos 			 * flush its continuations
289327e51cbSPeter Avalos 			 */
290c30bd091SSascha Wildner 			goto flush;
291327e51cbSPeter Avalos 		}
292327e51cbSPeter Avalos 
293e88a9a20SSascha Wildner 		if ((e = handle_annotation(ms, m, firstline)) != 0)
294e88a9a20SSascha Wildner 		{
295970935fdSSascha Wildner 			*found_match = 1;
296e8af9738SPeter Avalos 			*need_separator = 1;
297e8af9738SPeter Avalos 			*printed_something = 1;
298e8af9738SPeter Avalos 			*returnval = 1;
299e4d4ce0cSPeter Avalos 			return e;
300e8af9738SPeter Avalos 		}
301c30bd091SSascha Wildner 
302327e51cbSPeter Avalos 		/*
303327e51cbSPeter Avalos 		 * If we are going to print something, we'll need to print
304327e51cbSPeter Avalos 		 * a blank before we print something else.
305327e51cbSPeter Avalos 		 */
306970935fdSSascha Wildner 		if (*m->desc) {
307970935fdSSascha Wildner 			*found_match = 1;
308970935fdSSascha Wildner 			if (print) {
309614728caSSascha Wildner 				*returnval = 1;
310e8af9738SPeter Avalos 				*need_separator = 1;
311e8af9738SPeter Avalos 				*printed_something = 1;
312327e51cbSPeter Avalos 				if (print_sep(ms, firstline) == -1)
313327e51cbSPeter Avalos 					return -1;
314e88a9a20SSascha Wildner 				if (mprint(ms, m) == -1)
315e88a9a20SSascha Wildner 					return -1;
316327e51cbSPeter Avalos 			}
317970935fdSSascha Wildner 		}
318327e51cbSPeter Avalos 
319e88a9a20SSascha Wildner 		switch (moffset(ms, m, &bb, &ms->c.li[cont_level].off)) {
320c30bd091SSascha Wildner 		case -1:
321c30bd091SSascha Wildner 		case 0:
322c30bd091SSascha Wildner 			goto flush;
323c30bd091SSascha Wildner 		default:
324c30bd091SSascha Wildner 			break;
325c30bd091SSascha Wildner 		}
32679343712SPeter Avalos 
327327e51cbSPeter Avalos 		/* and any continuations that match */
328327e51cbSPeter Avalos 		if (file_check_mem(ms, ++cont_level) == -1)
329327e51cbSPeter Avalos 			return -1;
330327e51cbSPeter Avalos 
33182c5fa3eSPeter Avalos 		while (magindex + 1 < nmagic &&
33282c5fa3eSPeter Avalos 		    magic[magindex + 1].cont_level != 0) {
33382c5fa3eSPeter Avalos 			m = &magic[++magindex];
334*3b9cdfa3SAntonio Huete Jimenez 			m_rxcomp = &magic_rxcomp[magindex];
33579343712SPeter Avalos 			ms->line = m->lineno; /* for messages */
336327e51cbSPeter Avalos 
33779343712SPeter Avalos 			if (cont_level < m->cont_level)
338327e51cbSPeter Avalos 				continue;
33979343712SPeter Avalos 			if (cont_level > m->cont_level) {
340327e51cbSPeter Avalos 				/*
341327e51cbSPeter Avalos 				 * We're at the end of the level
342327e51cbSPeter Avalos 				 * "cont_level" continuations.
343327e51cbSPeter Avalos 				 */
34479343712SPeter Avalos 				cont_level = m->cont_level;
345327e51cbSPeter Avalos 			}
346e88a9a20SSascha Wildner 			if (msetoffset(ms, m, &bb, b, offset, cont_level) == -1)
347e88a9a20SSascha Wildner 				goto flush;
34879343712SPeter Avalos 			if (m->flag & OFFADD) {
349c990e5baSDaniel Fojt 				if (cont_level == 0) {
350c990e5baSDaniel Fojt 					if ((ms->flags & MAGIC_DEBUG) != 0)
351c990e5baSDaniel Fojt 						fprintf(stderr,
352c990e5baSDaniel Fojt 						    "direct *zero*"
353c990e5baSDaniel Fojt 						    " cont_level\n");
354c990e5baSDaniel Fojt 					return 0;
355c990e5baSDaniel Fojt 				}
356327e51cbSPeter Avalos 				ms->offset +=
357327e51cbSPeter Avalos 				    ms->c.li[cont_level - 1].off;
358327e51cbSPeter Avalos 			}
359327e51cbSPeter Avalos 
360327e51cbSPeter Avalos #ifdef ENABLE_CONDITIONALS
36179343712SPeter Avalos 			if (m->cond == COND_ELSE ||
36279343712SPeter Avalos 			    m->cond == COND_ELIF) {
363327e51cbSPeter Avalos 				if (ms->c.li[cont_level].last_match == 1)
364327e51cbSPeter Avalos 					continue;
365327e51cbSPeter Avalos 			}
366327e51cbSPeter Avalos #endif
367e88a9a20SSascha Wildner 			switch (mget(ms, m, b, CAST(const unsigned char *,
368e88a9a20SSascha Wildner 			    bb.fbuf), bb.flen, offset,
369e88a9a20SSascha Wildner 			    cont_level, mode, text, flip, indir_count,
370e88a9a20SSascha Wildner 			    name_count, printed_something, need_separator,
371e88a9a20SSascha Wildner 			    returnval, found_match)) {
37279343712SPeter Avalos 			case -1:
37379343712SPeter Avalos 				return -1;
37479343712SPeter Avalos 			case 0:
37579343712SPeter Avalos 				if (m->reln != '!')
376327e51cbSPeter Avalos 					continue;
37779343712SPeter Avalos 				flush = 1;
37879343712SPeter Avalos 				break;
37979343712SPeter Avalos 			default:
380e88a9a20SSascha Wildner 				if (m->type == FILE_INDIRECT) {
381e88a9a20SSascha Wildner 					*found_match = 1;
382e8af9738SPeter Avalos 					*returnval = 1;
383e88a9a20SSascha Wildner 				}
38479343712SPeter Avalos 				flush = 0;
38579343712SPeter Avalos 				break;
38679343712SPeter Avalos 			}
387327e51cbSPeter Avalos 
388*3b9cdfa3SAntonio Huete Jimenez 			switch (flush ? 1 : magiccheck(ms, m, m_rxcomp)) {
389327e51cbSPeter Avalos 			case -1:
390327e51cbSPeter Avalos 				return -1;
391327e51cbSPeter Avalos 			case 0:
392327e51cbSPeter Avalos #ifdef ENABLE_CONDITIONALS
393327e51cbSPeter Avalos 				ms->c.li[cont_level].last_match = 0;
394327e51cbSPeter Avalos #endif
395327e51cbSPeter Avalos 				break;
396327e51cbSPeter Avalos 			default:
397327e51cbSPeter Avalos #ifdef ENABLE_CONDITIONALS
398327e51cbSPeter Avalos 				ms->c.li[cont_level].last_match = 1;
399327e51cbSPeter Avalos #endif
400e8af9738SPeter Avalos 				if (m->type == FILE_CLEAR)
401327e51cbSPeter Avalos 					ms->c.li[cont_level].got_match = 0;
402e8af9738SPeter Avalos 				else if (ms->c.li[cont_level].got_match) {
403e8af9738SPeter Avalos 					if (m->type == FILE_DEFAULT)
404327e51cbSPeter Avalos 						break;
405e8af9738SPeter Avalos 				} else
406e8af9738SPeter Avalos 					ms->c.li[cont_level].got_match = 1;
407c30bd091SSascha Wildner 
408e88a9a20SSascha Wildner 				if ((e = handle_annotation(ms, m, firstline))
409e88a9a20SSascha Wildner 				    != 0) {
410970935fdSSascha Wildner 					*found_match = 1;
411e8af9738SPeter Avalos 					*need_separator = 1;
412e8af9738SPeter Avalos 					*printed_something = 1;
413e8af9738SPeter Avalos 					*returnval = 1;
414e4d4ce0cSPeter Avalos 					return e;
415e8af9738SPeter Avalos 				}
416970935fdSSascha Wildner 				if (*m->desc) {
417970935fdSSascha Wildner 					*found_match = 1;
418970935fdSSascha Wildner 				}
419e88a9a20SSascha Wildner 				if (print && *m->desc) {
420614728caSSascha Wildner 					*returnval = 1;
421327e51cbSPeter Avalos 					/*
422327e51cbSPeter Avalos 					 * This continuation matched.  Print
423327e51cbSPeter Avalos 					 * its message, with a blank before it
424327e51cbSPeter Avalos 					 * if the previous item printed and
425327e51cbSPeter Avalos 					 * this item isn't empty.
426327e51cbSPeter Avalos 					 */
427e88a9a20SSascha Wildner 					/*
428e88a9a20SSascha Wildner 					 * If we are going to print something,
429e88a9a20SSascha Wildner 					 * make sure that we have a separator
430e88a9a20SSascha Wildner 					 * first.
431e88a9a20SSascha Wildner 					 */
432e88a9a20SSascha Wildner 					if (!*printed_something) {
433e88a9a20SSascha Wildner 						*printed_something = 1;
434e88a9a20SSascha Wildner 						if (print_sep(ms, firstline)
435e88a9a20SSascha Wildner 						    == -1)
436e88a9a20SSascha Wildner 							return -1;
437e88a9a20SSascha Wildner 					}
438327e51cbSPeter Avalos 					/* space if previous printed */
439e8af9738SPeter Avalos 					if (*need_separator
440e88a9a20SSascha Wildner 					    && (m->flag & NOSPACE) == 0) {
441e88a9a20SSascha Wildner 						if (file_printf(ms, " ") == -1)
442327e51cbSPeter Avalos 							return -1;
443327e51cbSPeter Avalos 					}
444e88a9a20SSascha Wildner 					if (mprint(ms, m) == -1)
445327e51cbSPeter Avalos 						return -1;
446e88a9a20SSascha Wildner 					*need_separator = 1;
447e88a9a20SSascha Wildner 				}
44879343712SPeter Avalos 
449e88a9a20SSascha Wildner 				switch (moffset(ms, m, &bb,
450c30bd091SSascha Wildner 				    &ms->c.li[cont_level].off)) {
451c30bd091SSascha Wildner 				case -1:
452c30bd091SSascha Wildner 				case 0:
453c30bd091SSascha Wildner 					cont_level--;
454c30bd091SSascha Wildner 					break;
455c30bd091SSascha Wildner 				default:
456c30bd091SSascha Wildner 					break;
457c30bd091SSascha Wildner 				}
45879343712SPeter Avalos 
459327e51cbSPeter Avalos 				/*
460327e51cbSPeter Avalos 				 * If we see any continuations
461327e51cbSPeter Avalos 				 * at a higher level,
462327e51cbSPeter Avalos 				 * process them.
463327e51cbSPeter Avalos 				 */
464327e51cbSPeter Avalos 				if (file_check_mem(ms, ++cont_level) == -1)
465327e51cbSPeter Avalos 					return -1;
466327e51cbSPeter Avalos 				break;
467327e51cbSPeter Avalos 			}
468327e51cbSPeter Avalos 		}
469e8af9738SPeter Avalos 		if (*printed_something) {
470327e51cbSPeter Avalos 			firstline = 0;
471327e51cbSPeter Avalos 		}
472e88a9a20SSascha Wildner 		if (*found_match) {
473e88a9a20SSascha Wildner 			if ((ms->flags & MAGIC_CONTINUE) == 0)
474614728caSSascha Wildner 				return *returnval;
475e88a9a20SSascha Wildner 			// So that we print a separator
476e88a9a20SSascha Wildner 			*printed_something = 0;
477e88a9a20SSascha Wildner 			firstline = 0;
478327e51cbSPeter Avalos 		}
479c30bd091SSascha Wildner 		cont_level = 0;
480327e51cbSPeter Avalos 	}
481614728caSSascha Wildner 	return *returnval;
482327e51cbSPeter Avalos }
483327e51cbSPeter Avalos 
484327e51cbSPeter Avalos private int
check_fmt(struct magic_set * ms,const char * fmt)485e88a9a20SSascha Wildner check_fmt(struct magic_set *ms, const char *fmt)
486327e51cbSPeter Avalos {
48782c5fa3eSPeter Avalos 	file_regex_t rx;
488e8af9738SPeter Avalos 	int rc, rv = -1;
489*3b9cdfa3SAntonio Huete Jimenez         const char* pat = "%[-0-9\\.]*s";
490327e51cbSPeter Avalos 
491e88a9a20SSascha Wildner 	if (strchr(fmt, '%') == NULL)
492327e51cbSPeter Avalos 		return 0;
493327e51cbSPeter Avalos 
494*3b9cdfa3SAntonio Huete Jimenez 	rc = file_regcomp(ms, &rx, pat, REG_EXTENDED|REG_NOSUB);
495*3b9cdfa3SAntonio Huete Jimenez 	if (rc == 0) {
496*3b9cdfa3SAntonio Huete Jimenez 		rc = file_regexec(ms, &rx, fmt, 0, 0, 0);
497e8af9738SPeter Avalos 		rv = !rc;
498327e51cbSPeter Avalos 	}
49982c5fa3eSPeter Avalos 	file_regfree(&rx);
500e8af9738SPeter Avalos 	return rv;
501327e51cbSPeter Avalos }
502327e51cbSPeter Avalos 
503970935fdSSascha Wildner #if !defined(HAVE_STRNDUP) || defined(__aiws__) || defined(_AIX)
504970935fdSSascha Wildner # if defined(__aiws__) || defined(_AIX)
505e88a9a20SSascha Wildner #  define strndup aix_strndup	/* aix is broken */
506e88a9a20SSascha Wildner # endif
507327e51cbSPeter Avalos char *strndup(const char *, size_t);
508327e51cbSPeter Avalos 
509327e51cbSPeter Avalos char *
strndup(const char * str,size_t n)510327e51cbSPeter Avalos strndup(const char *str, size_t n)
511327e51cbSPeter Avalos {
512327e51cbSPeter Avalos 	size_t len;
513327e51cbSPeter Avalos 	char *copy;
514327e51cbSPeter Avalos 
51579343712SPeter Avalos 	for (len = 0; len < n && str[len]; len++)
51679343712SPeter Avalos 		continue;
517*3b9cdfa3SAntonio Huete Jimenez 	if ((copy = CAST(char *, malloc(len + 1))) == NULL)
51879343712SPeter Avalos 		return NULL;
51979343712SPeter Avalos 	(void)memcpy(copy, str, len);
520327e51cbSPeter Avalos 	copy[len] = '\0';
52179343712SPeter Avalos 	return copy;
522327e51cbSPeter Avalos }
523327e51cbSPeter Avalos #endif /* HAVE_STRNDUP */
524327e51cbSPeter Avalos 
525e88a9a20SSascha Wildner static int
varexpand(struct magic_set * ms,char * buf,size_t len,const char * str)526e88a9a20SSascha Wildner varexpand(struct magic_set *ms, char *buf, size_t len, const char *str)
527e88a9a20SSascha Wildner {
528e88a9a20SSascha Wildner 	const char *ptr, *sptr, *e, *t, *ee, *et;
529e88a9a20SSascha Wildner 	size_t l;
530e88a9a20SSascha Wildner 
531e88a9a20SSascha Wildner 	for (sptr = str; (ptr = strstr(sptr, "${")) != NULL;) {
532e88a9a20SSascha Wildner 		l = CAST(size_t, ptr - sptr);
533e88a9a20SSascha Wildner 		if (l >= len)
534e88a9a20SSascha Wildner 			return -1;
535e88a9a20SSascha Wildner 		memcpy(buf, sptr, l);
536e88a9a20SSascha Wildner 		buf += l;
537e88a9a20SSascha Wildner 		len -= l;
538e88a9a20SSascha Wildner 		ptr += 2;
539e88a9a20SSascha Wildner 		if (!*ptr || ptr[1] != '?')
540e88a9a20SSascha Wildner 			return -1;
541e88a9a20SSascha Wildner 		for (et = t = ptr + 2; *et && *et != ':'; et++)
542e88a9a20SSascha Wildner 			continue;
543e88a9a20SSascha Wildner 		if (*et != ':')
544e88a9a20SSascha Wildner 			return -1;
545e88a9a20SSascha Wildner 		for (ee = e = et + 1; *ee && *ee != '}'; ee++)
546e88a9a20SSascha Wildner 			continue;
547e88a9a20SSascha Wildner 		if (*ee != '}')
548e88a9a20SSascha Wildner 			return -1;
549e88a9a20SSascha Wildner 		switch (*ptr) {
550e88a9a20SSascha Wildner 		case 'x':
551e88a9a20SSascha Wildner 			if (ms->mode & 0111) {
552e88a9a20SSascha Wildner 				ptr = t;
553e88a9a20SSascha Wildner 				l = et - t;
554e88a9a20SSascha Wildner 			} else {
555e88a9a20SSascha Wildner 				ptr = e;
556e88a9a20SSascha Wildner 				l = ee - e;
557e88a9a20SSascha Wildner 			}
558e88a9a20SSascha Wildner 			break;
559e88a9a20SSascha Wildner 		default:
560e88a9a20SSascha Wildner 			return -1;
561e88a9a20SSascha Wildner 		}
562e88a9a20SSascha Wildner 		if (l >= len)
563e88a9a20SSascha Wildner 			return -1;
564e88a9a20SSascha Wildner 		memcpy(buf, ptr, l);
565e88a9a20SSascha Wildner 		buf += l;
566e88a9a20SSascha Wildner 		len -= l;
567e88a9a20SSascha Wildner 		sptr = ee + 1;
568e88a9a20SSascha Wildner 	}
569e88a9a20SSascha Wildner 
570e88a9a20SSascha Wildner 	l = strlen(sptr);
571e88a9a20SSascha Wildner 	if (l >= len)
572e88a9a20SSascha Wildner 		return -1;
573e88a9a20SSascha Wildner 
574e88a9a20SSascha Wildner 	memcpy(buf, sptr, l);
575e88a9a20SSascha Wildner 	buf[l] = '\0';
576e88a9a20SSascha Wildner 	return 0;
577e88a9a20SSascha Wildner }
578e88a9a20SSascha Wildner 
579e88a9a20SSascha Wildner 
580*3b9cdfa3SAntonio Huete Jimenez private int
mprint(struct magic_set * ms,struct magic * m)581327e51cbSPeter Avalos mprint(struct magic_set *ms, struct magic *m)
582327e51cbSPeter Avalos {
583327e51cbSPeter Avalos 	uint64_t v;
584327e51cbSPeter Avalos 	float vf;
585327e51cbSPeter Avalos 	double vd;
586e88a9a20SSascha Wildner  	char buf[128], tbuf[26], sbuf[512], ebuf[512];
587e88a9a20SSascha Wildner 	const char *desc;
588327e51cbSPeter Avalos 	union VALUETYPE *p = &ms->ms_value;
589327e51cbSPeter Avalos 
590e88a9a20SSascha Wildner 	if (varexpand(ms, ebuf, sizeof(ebuf), m->desc) == -1)
591e88a9a20SSascha Wildner 		desc = m->desc;
592e88a9a20SSascha Wildner 	else
593e88a9a20SSascha Wildner 		desc = ebuf;
594e88a9a20SSascha Wildner 
595970935fdSSascha Wildner #define	PRINTER(value, format, stype, utype)	\
596970935fdSSascha Wildner 	v = file_signextend(ms, m, CAST(uint64_t, value)); \
597970935fdSSascha Wildner 	switch (check_fmt(ms, desc)) { \
598970935fdSSascha Wildner 	case -1: \
599970935fdSSascha Wildner 		return -1; \
600970935fdSSascha Wildner 	case 1: \
601970935fdSSascha Wildner 		if (m->flag & UNSIGNED) { \
602970935fdSSascha Wildner 			(void)snprintf(buf, sizeof(buf), "%" format "u", \
603970935fdSSascha Wildner 			    CAST(utype, v)); \
604970935fdSSascha Wildner 		} else { \
605970935fdSSascha Wildner 			(void)snprintf(buf, sizeof(buf), "%" format "d", \
606970935fdSSascha Wildner 			    CAST(stype, v)); \
607970935fdSSascha Wildner 		} \
608970935fdSSascha Wildner 		if (file_printf(ms, F(ms, desc, "%s"), buf) == -1) \
609970935fdSSascha Wildner 			return -1; \
610970935fdSSascha Wildner 		break; \
611970935fdSSascha Wildner 	default: \
612970935fdSSascha Wildner 		if (m->flag & UNSIGNED) { \
613970935fdSSascha Wildner 		       if (file_printf(ms, F(ms, desc, "%" format "u"), \
614970935fdSSascha Wildner 			   CAST(utype, v)) == -1) \
615970935fdSSascha Wildner 			   return -1; \
616970935fdSSascha Wildner 		} else { \
617970935fdSSascha Wildner 		       if (file_printf(ms, F(ms, desc, "%" format "d"), \
618970935fdSSascha Wildner 			   CAST(stype, v)) == -1) \
619970935fdSSascha Wildner 			   return -1; \
620970935fdSSascha Wildner 		} \
621970935fdSSascha Wildner 		break; \
622970935fdSSascha Wildner 	} \
623970935fdSSascha Wildner 	break
624970935fdSSascha Wildner 
625327e51cbSPeter Avalos   	switch (m->type) {
626327e51cbSPeter Avalos   	case FILE_BYTE:
627970935fdSSascha Wildner 		PRINTER(p->b, "", int8_t, uint8_t);
628327e51cbSPeter Avalos 
629327e51cbSPeter Avalos   	case FILE_SHORT:
630327e51cbSPeter Avalos   	case FILE_BESHORT:
631327e51cbSPeter Avalos   	case FILE_LESHORT:
632970935fdSSascha Wildner 		PRINTER(p->h, "", int16_t, uint16_t);
633327e51cbSPeter Avalos 
634327e51cbSPeter Avalos   	case FILE_LONG:
635327e51cbSPeter Avalos   	case FILE_BELONG:
636327e51cbSPeter Avalos   	case FILE_LELONG:
637327e51cbSPeter Avalos   	case FILE_MELONG:
638970935fdSSascha Wildner 		PRINTER(p->l, "", int32_t, uint32_t);
639327e51cbSPeter Avalos 
640327e51cbSPeter Avalos   	case FILE_QUAD:
641327e51cbSPeter Avalos   	case FILE_BEQUAD:
642327e51cbSPeter Avalos   	case FILE_LEQUAD:
643c990e5baSDaniel Fojt 	case FILE_OFFSET:
644970935fdSSascha Wildner 		PRINTER(p->q, INT64_T_FORMAT, long long, unsigned long long);
645327e51cbSPeter Avalos 
646327e51cbSPeter Avalos   	case FILE_STRING:
647327e51cbSPeter Avalos   	case FILE_PSTRING:
648327e51cbSPeter Avalos   	case FILE_BESTRING16:
649327e51cbSPeter Avalos   	case FILE_LESTRING16:
650327e51cbSPeter Avalos 		if (m->reln == '=' || m->reln == '!') {
651e88a9a20SSascha Wildner 			if (file_printf(ms, F(ms, desc, "%s"),
652614728caSSascha Wildner 			    file_printable(ms, sbuf, sizeof(sbuf), m->value.s,
653e88a9a20SSascha Wildner 			    sizeof(m->value.s))) == -1)
654327e51cbSPeter Avalos 				return -1;
655327e51cbSPeter Avalos 		}
656327e51cbSPeter Avalos 		else {
657e8af9738SPeter Avalos 			char *str = p->s;
658e8af9738SPeter Avalos 
659e8af9738SPeter Avalos 			/* compute t before we mangle the string? */
660e8af9738SPeter Avalos 
661327e51cbSPeter Avalos 			if (*m->value.s == '\0')
662c30bd091SSascha Wildner 				str[strcspn(str, "\r\n")] = '\0';
663e8af9738SPeter Avalos 
664970935fdSSascha Wildner 			if (m->str_flags & STRING_TRIM)
665970935fdSSascha Wildner 				str = file_strtrim(str);
666e8af9738SPeter Avalos 
667e88a9a20SSascha Wildner 			if (file_printf(ms, F(ms, desc, "%s"),
668614728caSSascha Wildner 			    file_printable(ms, sbuf, sizeof(sbuf), str,
669e88a9a20SSascha Wildner 				sizeof(p->s) - (str - p->s))) == -1)
670327e51cbSPeter Avalos 				return -1;
671e8af9738SPeter Avalos 
672c990e5baSDaniel Fojt 			if (m->type == FILE_PSTRING) {
673c990e5baSDaniel Fojt 				size_t l = file_pstring_length_size(ms, m);
674c990e5baSDaniel Fojt 				if (l == FILE_BADSIZE)
675c990e5baSDaniel Fojt 					return -1;
676c990e5baSDaniel Fojt 			}
677327e51cbSPeter Avalos 		}
678327e51cbSPeter Avalos 		break;
679327e51cbSPeter Avalos 
680327e51cbSPeter Avalos 	case FILE_DATE:
681327e51cbSPeter Avalos 	case FILE_BEDATE:
682327e51cbSPeter Avalos 	case FILE_LEDATE:
683327e51cbSPeter Avalos 	case FILE_MEDATE:
684e88a9a20SSascha Wildner 		if (file_printf(ms, F(ms, desc, "%s"),
685*3b9cdfa3SAntonio Huete Jimenez 		    file_fmtdatetime(tbuf, sizeof(tbuf), p->l, 0)) == -1)
686327e51cbSPeter Avalos 			return -1;
687327e51cbSPeter Avalos 		break;
688327e51cbSPeter Avalos 
689327e51cbSPeter Avalos 	case FILE_LDATE:
690327e51cbSPeter Avalos 	case FILE_BELDATE:
691327e51cbSPeter Avalos 	case FILE_LELDATE:
692327e51cbSPeter Avalos 	case FILE_MELDATE:
693e88a9a20SSascha Wildner 		if (file_printf(ms, F(ms, desc, "%s"),
694*3b9cdfa3SAntonio Huete Jimenez 		    file_fmtdatetime(tbuf, sizeof(tbuf), p->l, FILE_T_LOCAL))
695*3b9cdfa3SAntonio Huete Jimenez 			== -1)
696327e51cbSPeter Avalos 			return -1;
697327e51cbSPeter Avalos 		break;
698327e51cbSPeter Avalos 
699327e51cbSPeter Avalos 	case FILE_QDATE:
700327e51cbSPeter Avalos 	case FILE_BEQDATE:
701327e51cbSPeter Avalos 	case FILE_LEQDATE:
702e88a9a20SSascha Wildner 		if (file_printf(ms, F(ms, desc, "%s"),
703*3b9cdfa3SAntonio Huete Jimenez 		    file_fmtdatetime(tbuf, sizeof(tbuf), p->q, 0)) == -1)
704327e51cbSPeter Avalos 			return -1;
705327e51cbSPeter Avalos 		break;
706327e51cbSPeter Avalos 
707327e51cbSPeter Avalos 	case FILE_QLDATE:
708327e51cbSPeter Avalos 	case FILE_BEQLDATE:
709327e51cbSPeter Avalos 	case FILE_LEQLDATE:
710e88a9a20SSascha Wildner 		if (file_printf(ms, F(ms, desc, "%s"),
711*3b9cdfa3SAntonio Huete Jimenez 		    file_fmtdatetime(tbuf, sizeof(tbuf), p->q, FILE_T_LOCAL)) == -1)
712e8af9738SPeter Avalos 			return -1;
713e8af9738SPeter Avalos 		break;
714e8af9738SPeter Avalos 
715e8af9738SPeter Avalos 	case FILE_QWDATE:
716e8af9738SPeter Avalos 	case FILE_BEQWDATE:
717e8af9738SPeter Avalos 	case FILE_LEQWDATE:
718e88a9a20SSascha Wildner 		if (file_printf(ms, F(ms, desc, "%s"),
719*3b9cdfa3SAntonio Huete Jimenez 		    file_fmtdatetime(tbuf, sizeof(tbuf), p->q, FILE_T_WINDOWS))
720c990e5baSDaniel Fojt 		    == -1)
721327e51cbSPeter Avalos 			return -1;
722327e51cbSPeter Avalos 		break;
723327e51cbSPeter Avalos 
724327e51cbSPeter Avalos 	case FILE_FLOAT:
725327e51cbSPeter Avalos 	case FILE_BEFLOAT:
726327e51cbSPeter Avalos 	case FILE_LEFLOAT:
727327e51cbSPeter Avalos 		vf = p->f;
728e88a9a20SSascha Wildner 		switch (check_fmt(ms, desc)) {
729327e51cbSPeter Avalos 		case -1:
730327e51cbSPeter Avalos 			return -1;
731327e51cbSPeter Avalos 		case 1:
73279343712SPeter Avalos 			(void)snprintf(buf, sizeof(buf), "%g", vf);
733e88a9a20SSascha Wildner 			if (file_printf(ms, F(ms, desc, "%s"), buf) == -1)
734327e51cbSPeter Avalos 				return -1;
735327e51cbSPeter Avalos 			break;
736327e51cbSPeter Avalos 		default:
737e88a9a20SSascha Wildner 			if (file_printf(ms, F(ms, desc, "%g"), vf) == -1)
738327e51cbSPeter Avalos 				return -1;
739327e51cbSPeter Avalos 			break;
740327e51cbSPeter Avalos 		}
741327e51cbSPeter Avalos   		break;
742327e51cbSPeter Avalos 
743327e51cbSPeter Avalos 	case FILE_DOUBLE:
744327e51cbSPeter Avalos 	case FILE_BEDOUBLE:
745327e51cbSPeter Avalos 	case FILE_LEDOUBLE:
746327e51cbSPeter Avalos 		vd = p->d;
747e88a9a20SSascha Wildner 		switch (check_fmt(ms, desc)) {
748327e51cbSPeter Avalos 		case -1:
749327e51cbSPeter Avalos 			return -1;
750327e51cbSPeter Avalos 		case 1:
75179343712SPeter Avalos 			(void)snprintf(buf, sizeof(buf), "%g", vd);
752e88a9a20SSascha Wildner 			if (file_printf(ms, F(ms, desc, "%s"), buf) == -1)
753327e51cbSPeter Avalos 				return -1;
754327e51cbSPeter Avalos 			break;
755327e51cbSPeter Avalos 		default:
756e88a9a20SSascha Wildner 			if (file_printf(ms, F(ms, desc, "%g"), vd) == -1)
757327e51cbSPeter Avalos 				return -1;
758327e51cbSPeter Avalos 			break;
759327e51cbSPeter Avalos 		}
760327e51cbSPeter Avalos   		break;
761327e51cbSPeter Avalos 
762c30bd091SSascha Wildner 	case FILE_SEARCH:
763327e51cbSPeter Avalos 	case FILE_REGEX: {
764970935fdSSascha Wildner 		char *cp, *scp;
765327e51cbSPeter Avalos 		int rval;
766327e51cbSPeter Avalos 
767e88a9a20SSascha Wildner 		cp = strndup(RCAST(const char *, ms->search.s),
768e88a9a20SSascha Wildner 		    ms->search.rm_len);
769327e51cbSPeter Avalos 		if (cp == NULL) {
770327e51cbSPeter Avalos 			file_oomem(ms, ms->search.rm_len);
771327e51cbSPeter Avalos 			return -1;
772327e51cbSPeter Avalos 		}
773970935fdSSascha Wildner 		scp = (m->str_flags & STRING_TRIM) ? file_strtrim(cp) : cp;
774970935fdSSascha Wildner 
775614728caSSascha Wildner 		rval = file_printf(ms, F(ms, desc, "%s"), file_printable(ms,
776614728caSSascha Wildner 		    sbuf, sizeof(sbuf), scp, ms->search.rm_len));
777327e51cbSPeter Avalos 		free(cp);
778327e51cbSPeter Avalos 
779327e51cbSPeter Avalos 		if (rval == -1)
780327e51cbSPeter Avalos 			return -1;
781327e51cbSPeter Avalos 		break;
782327e51cbSPeter Avalos 	}
783327e51cbSPeter Avalos 
784327e51cbSPeter Avalos 	case FILE_DEFAULT:
785e8af9738SPeter Avalos 	case FILE_CLEAR:
786e8af9738SPeter Avalos 	  	if (file_printf(ms, "%s", m->desc) == -1)
787327e51cbSPeter Avalos 			return -1;
788327e51cbSPeter Avalos 		break;
789327e51cbSPeter Avalos 
79079343712SPeter Avalos 	case FILE_INDIRECT:
791e8af9738SPeter Avalos 	case FILE_USE:
792e8af9738SPeter Avalos 	case FILE_NAME:
79379343712SPeter Avalos 		break;
794c30bd091SSascha Wildner 	case FILE_DER:
795e88a9a20SSascha Wildner 		if (file_printf(ms, F(ms, desc, "%s"),
796614728caSSascha Wildner 		    file_printable(ms, sbuf, sizeof(sbuf), ms->ms_value.s,
797e88a9a20SSascha Wildner 			sizeof(ms->ms_value.s))) == -1)
798c30bd091SSascha Wildner 			return -1;
799c30bd091SSascha Wildner 		break;
800c990e5baSDaniel Fojt 	case FILE_GUID:
801c990e5baSDaniel Fojt 		(void) file_print_guid(buf, sizeof(buf), ms->ms_value.guid);
802c990e5baSDaniel Fojt 		if (file_printf(ms, F(ms, desc, "%s"), buf) == -1)
803c990e5baSDaniel Fojt 			return -1;
804*3b9cdfa3SAntonio Huete Jimenez 		break;
805*3b9cdfa3SAntonio Huete Jimenez 	case FILE_MSDOSDATE:
806*3b9cdfa3SAntonio Huete Jimenez 	case FILE_BEMSDOSDATE:
807*3b9cdfa3SAntonio Huete Jimenez 	case FILE_LEMSDOSDATE:
808*3b9cdfa3SAntonio Huete Jimenez 		if (file_printf(ms, F(ms, desc, "%s"),
809*3b9cdfa3SAntonio Huete Jimenez 		    file_fmtdate(tbuf, sizeof(tbuf), p->h)) == -1)
810*3b9cdfa3SAntonio Huete Jimenez 			return -1;
811*3b9cdfa3SAntonio Huete Jimenez 		break;
812*3b9cdfa3SAntonio Huete Jimenez 	case FILE_MSDOSTIME:
813*3b9cdfa3SAntonio Huete Jimenez 	case FILE_BEMSDOSTIME:
814*3b9cdfa3SAntonio Huete Jimenez 	case FILE_LEMSDOSTIME:
815*3b9cdfa3SAntonio Huete Jimenez 		if (file_printf(ms, F(ms, desc, "%s"),
816*3b9cdfa3SAntonio Huete Jimenez 		    file_fmttime(tbuf, sizeof(tbuf), p->h)) == -1)
817*3b9cdfa3SAntonio Huete Jimenez 			return -1;
818*3b9cdfa3SAntonio Huete Jimenez 		break;
819*3b9cdfa3SAntonio Huete Jimenez 	case FILE_OCTAL:
820*3b9cdfa3SAntonio Huete Jimenez 		file_fmtnum(buf, sizeof(buf), m->value.s, 8);
821*3b9cdfa3SAntonio Huete Jimenez 		if (file_printf(ms, F(ms, desc, "%s"), buf) == -1)
822*3b9cdfa3SAntonio Huete Jimenez 			return -1;
823c990e5baSDaniel Fojt 		break;
824327e51cbSPeter Avalos 	default:
825327e51cbSPeter Avalos 		file_magerror(ms, "invalid m->type (%d) in mprint()", m->type);
826327e51cbSPeter Avalos 		return -1;
827327e51cbSPeter Avalos 	}
828*3b9cdfa3SAntonio Huete Jimenez 	return 0;
829327e51cbSPeter Avalos }
830327e51cbSPeter Avalos 
831c30bd091SSascha Wildner private int
moffset(struct magic_set * ms,struct magic * m,const struct buffer * b,int32_t * op)832e88a9a20SSascha Wildner moffset(struct magic_set *ms, struct magic *m, const struct buffer *b,
833e88a9a20SSascha Wildner     int32_t *op)
83479343712SPeter Avalos {
835e88a9a20SSascha Wildner 	size_t nbytes = b->flen;
836c30bd091SSascha Wildner 	int32_t o;
837c30bd091SSascha Wildner 
83879343712SPeter Avalos   	switch (m->type) {
83979343712SPeter Avalos   	case FILE_BYTE:
840c30bd091SSascha Wildner 		o = CAST(int32_t, (ms->offset + sizeof(char)));
841c30bd091SSascha Wildner 		break;
84279343712SPeter Avalos 
84379343712SPeter Avalos   	case FILE_SHORT:
84479343712SPeter Avalos   	case FILE_BESHORT:
84579343712SPeter Avalos   	case FILE_LESHORT:
846*3b9cdfa3SAntonio Huete Jimenez 	case FILE_MSDOSDATE:
847*3b9cdfa3SAntonio Huete Jimenez 	case FILE_LEMSDOSDATE:
848*3b9cdfa3SAntonio Huete Jimenez 	case FILE_BEMSDOSDATE:
849*3b9cdfa3SAntonio Huete Jimenez 	case FILE_MSDOSTIME:
850*3b9cdfa3SAntonio Huete Jimenez 	case FILE_LEMSDOSTIME:
851*3b9cdfa3SAntonio Huete Jimenez 	case FILE_BEMSDOSTIME:
852c30bd091SSascha Wildner 		o = CAST(int32_t, (ms->offset + sizeof(short)));
853c30bd091SSascha Wildner 		break;
85479343712SPeter Avalos 
85579343712SPeter Avalos   	case FILE_LONG:
85679343712SPeter Avalos   	case FILE_BELONG:
85779343712SPeter Avalos   	case FILE_LELONG:
85879343712SPeter Avalos   	case FILE_MELONG:
859c30bd091SSascha Wildner 		o = CAST(int32_t, (ms->offset + sizeof(int32_t)));
860c30bd091SSascha Wildner 		break;
86179343712SPeter Avalos 
86279343712SPeter Avalos   	case FILE_QUAD:
86379343712SPeter Avalos   	case FILE_BEQUAD:
86479343712SPeter Avalos   	case FILE_LEQUAD:
865c30bd091SSascha Wildner 		o = CAST(int32_t, (ms->offset + sizeof(int64_t)));
866c30bd091SSascha Wildner 		break;
86779343712SPeter Avalos 
86879343712SPeter Avalos   	case FILE_STRING:
86979343712SPeter Avalos   	case FILE_PSTRING:
87079343712SPeter Avalos   	case FILE_BESTRING16:
87179343712SPeter Avalos   	case FILE_LESTRING16:
872*3b9cdfa3SAntonio Huete Jimenez 	case FILE_OCTAL:
873c30bd091SSascha Wildner 		if (m->reln == '=' || m->reln == '!') {
874c30bd091SSascha Wildner 			o = ms->offset + m->vallen;
875c30bd091SSascha Wildner 		} else {
87679343712SPeter Avalos 			union VALUETYPE *p = &ms->ms_value;
87779343712SPeter Avalos 
87879343712SPeter Avalos 			if (*m->value.s == '\0')
879c30bd091SSascha Wildner 				p->s[strcspn(p->s, "\r\n")] = '\0';
880c30bd091SSascha Wildner 			o = CAST(uint32_t, (ms->offset + strlen(p->s)));
881c990e5baSDaniel Fojt 			if (m->type == FILE_PSTRING) {
882c990e5baSDaniel Fojt 				size_t l = file_pstring_length_size(ms, m);
883c990e5baSDaniel Fojt 				if (l == FILE_BADSIZE)
884c990e5baSDaniel Fojt 					return -1;
885c990e5baSDaniel Fojt 				o += CAST(uint32_t, l);
886c990e5baSDaniel Fojt 			}
88779343712SPeter Avalos 		}
888c30bd091SSascha Wildner 		break;
88979343712SPeter Avalos 
89079343712SPeter Avalos 	case FILE_DATE:
89179343712SPeter Avalos 	case FILE_BEDATE:
89279343712SPeter Avalos 	case FILE_LEDATE:
89379343712SPeter Avalos 	case FILE_MEDATE:
894c30bd091SSascha Wildner 		o = CAST(int32_t, (ms->offset + sizeof(uint32_t)));
895c30bd091SSascha Wildner 		break;
89679343712SPeter Avalos 
89779343712SPeter Avalos 	case FILE_LDATE:
89879343712SPeter Avalos 	case FILE_BELDATE:
89979343712SPeter Avalos 	case FILE_LELDATE:
90079343712SPeter Avalos 	case FILE_MELDATE:
901c30bd091SSascha Wildner 		o = CAST(int32_t, (ms->offset + sizeof(uint32_t)));
902c30bd091SSascha Wildner 		break;
90379343712SPeter Avalos 
90479343712SPeter Avalos 	case FILE_QDATE:
90579343712SPeter Avalos 	case FILE_BEQDATE:
90679343712SPeter Avalos 	case FILE_LEQDATE:
907c30bd091SSascha Wildner 		o = CAST(int32_t, (ms->offset + sizeof(uint64_t)));
908c30bd091SSascha Wildner 		break;
90979343712SPeter Avalos 
91079343712SPeter Avalos 	case FILE_QLDATE:
91179343712SPeter Avalos 	case FILE_BEQLDATE:
91279343712SPeter Avalos 	case FILE_LEQLDATE:
913c30bd091SSascha Wildner 		o = CAST(int32_t, (ms->offset + sizeof(uint64_t)));
914c30bd091SSascha Wildner 		break;
91579343712SPeter Avalos 
91679343712SPeter Avalos   	case FILE_FLOAT:
91779343712SPeter Avalos   	case FILE_BEFLOAT:
91879343712SPeter Avalos   	case FILE_LEFLOAT:
919c30bd091SSascha Wildner 		o = CAST(int32_t, (ms->offset + sizeof(float)));
920c30bd091SSascha Wildner 		break;
92179343712SPeter Avalos 
92279343712SPeter Avalos   	case FILE_DOUBLE:
92379343712SPeter Avalos   	case FILE_BEDOUBLE:
92479343712SPeter Avalos   	case FILE_LEDOUBLE:
925c30bd091SSascha Wildner 		o = CAST(int32_t, (ms->offset + sizeof(double)));
926c30bd091SSascha Wildner 		break;
92779343712SPeter Avalos 
92879343712SPeter Avalos 	case FILE_REGEX:
92979343712SPeter Avalos 		if ((m->str_flags & REGEX_OFFSET_START) != 0)
930c30bd091SSascha Wildner 			o = CAST(int32_t, ms->search.offset);
93179343712SPeter Avalos 		else
932c30bd091SSascha Wildner 			o = CAST(int32_t,
933c30bd091SSascha Wildner 			    (ms->search.offset + ms->search.rm_len));
934c30bd091SSascha Wildner 		break;
93579343712SPeter Avalos 
93679343712SPeter Avalos 	case FILE_SEARCH:
93779343712SPeter Avalos 		if ((m->str_flags & REGEX_OFFSET_START) != 0)
938c30bd091SSascha Wildner 			o = CAST(int32_t, ms->search.offset);
93979343712SPeter Avalos 		else
940c30bd091SSascha Wildner 			o = CAST(int32_t, (ms->search.offset + m->vallen));
941c30bd091SSascha Wildner 		break;
94279343712SPeter Avalos 
943e8af9738SPeter Avalos 	case FILE_CLEAR:
94479343712SPeter Avalos 	case FILE_DEFAULT:
94579343712SPeter Avalos 	case FILE_INDIRECT:
946c990e5baSDaniel Fojt 	case FILE_OFFSET:
947970935fdSSascha Wildner 	case FILE_USE:
948c30bd091SSascha Wildner 		o = ms->offset;
949c30bd091SSascha Wildner 		break;
95079343712SPeter Avalos 
951c30bd091SSascha Wildner 	case FILE_DER:
952c30bd091SSascha Wildner 		o = der_offs(ms, m, nbytes);
953e88a9a20SSascha Wildner 		if (o == -1 || CAST(size_t, o) > nbytes) {
954c30bd091SSascha Wildner 			if ((ms->flags & MAGIC_DEBUG) != 0) {
955c30bd091SSascha Wildner 				(void)fprintf(stderr,
956e88a9a20SSascha Wildner 				    "Bad DER offset %d nbytes=%"
957e88a9a20SSascha Wildner 				    SIZE_T_FORMAT "u", o, nbytes);
958c30bd091SSascha Wildner 			}
959c30bd091SSascha Wildner 			*op = 0;
96079343712SPeter Avalos 			return 0;
96179343712SPeter Avalos 		}
962c30bd091SSascha Wildner 		break;
963c990e5baSDaniel Fojt 
964c990e5baSDaniel Fojt 	case FILE_GUID:
965c990e5baSDaniel Fojt 		o = CAST(int32_t, (ms->offset + 2 * sizeof(uint64_t)));
966c990e5baSDaniel Fojt 		break;
967c30bd091SSascha Wildner 
968c30bd091SSascha Wildner 	default:
969c30bd091SSascha Wildner 		o = 0;
970c30bd091SSascha Wildner 		break;
971c30bd091SSascha Wildner 	}
972c30bd091SSascha Wildner 
973e88a9a20SSascha Wildner 	if (CAST(size_t, o) > nbytes) {
974c30bd091SSascha Wildner #if 0
975e88a9a20SSascha Wildner 		file_error(ms, 0, "Offset out of range %" SIZE_T_FORMAT
976e88a9a20SSascha Wildner 		    "u > %" SIZE_T_FORMAT "u", (size_t)o, nbytes);
977c30bd091SSascha Wildner #endif
978c30bd091SSascha Wildner 		return -1;
979c30bd091SSascha Wildner 	}
980c30bd091SSascha Wildner 	*op = o;
981c30bd091SSascha Wildner 	return 1;
982c30bd091SSascha Wildner }
983c30bd091SSascha Wildner 
984c30bd091SSascha Wildner private uint32_t
cvt_id3(struct magic_set * ms,uint32_t v)985c30bd091SSascha Wildner cvt_id3(struct magic_set *ms, uint32_t v)
986c30bd091SSascha Wildner {
987c30bd091SSascha Wildner 	v = ((((v >>  0) & 0x7f) <<  0) |
988c30bd091SSascha Wildner 	     (((v >>  8) & 0x7f) <<  7) |
989c30bd091SSascha Wildner 	     (((v >> 16) & 0x7f) << 14) |
990c30bd091SSascha Wildner 	     (((v >> 24) & 0x7f) << 21));
991c30bd091SSascha Wildner 	if ((ms->flags & MAGIC_DEBUG) != 0)
992c30bd091SSascha Wildner 		fprintf(stderr, "id3 offs=%u\n", v);
993c30bd091SSascha Wildner 	return v;
99479343712SPeter Avalos }
995327e51cbSPeter Avalos 
996e8af9738SPeter Avalos private int
cvt_flip(int type,int flip)997e8af9738SPeter Avalos cvt_flip(int type, int flip)
998e8af9738SPeter Avalos {
999e8af9738SPeter Avalos 	if (flip == 0)
1000e8af9738SPeter Avalos 		return type;
1001e8af9738SPeter Avalos 	switch (type) {
1002e8af9738SPeter Avalos 	case FILE_BESHORT:
1003e8af9738SPeter Avalos 		return FILE_LESHORT;
1004e8af9738SPeter Avalos 	case FILE_BELONG:
1005e8af9738SPeter Avalos 		return FILE_LELONG;
1006e8af9738SPeter Avalos 	case FILE_BEDATE:
1007e8af9738SPeter Avalos 		return FILE_LEDATE;
1008e8af9738SPeter Avalos 	case FILE_BELDATE:
1009e8af9738SPeter Avalos 		return FILE_LELDATE;
1010e8af9738SPeter Avalos 	case FILE_BEQUAD:
1011e8af9738SPeter Avalos 		return FILE_LEQUAD;
1012e8af9738SPeter Avalos 	case FILE_BEQDATE:
1013e8af9738SPeter Avalos 		return FILE_LEQDATE;
1014e8af9738SPeter Avalos 	case FILE_BEQLDATE:
1015e8af9738SPeter Avalos 		return FILE_LEQLDATE;
1016e8af9738SPeter Avalos 	case FILE_BEQWDATE:
1017e8af9738SPeter Avalos 		return FILE_LEQWDATE;
1018e8af9738SPeter Avalos 	case FILE_LESHORT:
1019e8af9738SPeter Avalos 		return FILE_BESHORT;
1020e8af9738SPeter Avalos 	case FILE_LELONG:
1021e8af9738SPeter Avalos 		return FILE_BELONG;
1022e8af9738SPeter Avalos 	case FILE_LEDATE:
1023e8af9738SPeter Avalos 		return FILE_BEDATE;
1024e8af9738SPeter Avalos 	case FILE_LELDATE:
1025e8af9738SPeter Avalos 		return FILE_BELDATE;
1026e8af9738SPeter Avalos 	case FILE_LEQUAD:
1027e8af9738SPeter Avalos 		return FILE_BEQUAD;
1028e8af9738SPeter Avalos 	case FILE_LEQDATE:
1029e8af9738SPeter Avalos 		return FILE_BEQDATE;
1030e8af9738SPeter Avalos 	case FILE_LEQLDATE:
1031e8af9738SPeter Avalos 		return FILE_BEQLDATE;
1032e8af9738SPeter Avalos 	case FILE_LEQWDATE:
1033e8af9738SPeter Avalos 		return FILE_BEQWDATE;
1034e8af9738SPeter Avalos 	case FILE_BEFLOAT:
1035e8af9738SPeter Avalos 		return FILE_LEFLOAT;
1036e8af9738SPeter Avalos 	case FILE_LEFLOAT:
1037e8af9738SPeter Avalos 		return FILE_BEFLOAT;
1038e8af9738SPeter Avalos 	case FILE_BEDOUBLE:
1039e8af9738SPeter Avalos 		return FILE_LEDOUBLE;
1040e8af9738SPeter Avalos 	case FILE_LEDOUBLE:
1041e8af9738SPeter Avalos 		return FILE_BEDOUBLE;
1042e8af9738SPeter Avalos 	default:
1043e8af9738SPeter Avalos 		return type;
1044e8af9738SPeter Avalos 	}
1045e8af9738SPeter Avalos }
1046e88a9a20SSascha Wildner #define DO_CVT(fld, type) \
1047327e51cbSPeter Avalos 	if (m->num_mask) \
1048327e51cbSPeter Avalos 		switch (m->mask_op & FILE_OPS_MASK) { \
1049327e51cbSPeter Avalos 		case FILE_OPAND: \
1050e88a9a20SSascha Wildner 			p->fld &= CAST(type, m->num_mask); \
1051327e51cbSPeter Avalos 			break; \
1052327e51cbSPeter Avalos 		case FILE_OPOR: \
1053e88a9a20SSascha Wildner 			p->fld |= CAST(type, m->num_mask); \
1054327e51cbSPeter Avalos 			break; \
1055327e51cbSPeter Avalos 		case FILE_OPXOR: \
1056e88a9a20SSascha Wildner 			p->fld ^= CAST(type, m->num_mask); \
1057327e51cbSPeter Avalos 			break; \
1058327e51cbSPeter Avalos 		case FILE_OPADD: \
1059e88a9a20SSascha Wildner 			p->fld += CAST(type, m->num_mask); \
1060327e51cbSPeter Avalos 			break; \
1061327e51cbSPeter Avalos 		case FILE_OPMINUS: \
1062e88a9a20SSascha Wildner 			p->fld -= CAST(type, m->num_mask); \
1063327e51cbSPeter Avalos 			break; \
1064327e51cbSPeter Avalos 		case FILE_OPMULTIPLY: \
1065e88a9a20SSascha Wildner 			p->fld *= CAST(type, m->num_mask); \
1066327e51cbSPeter Avalos 			break; \
1067327e51cbSPeter Avalos 		case FILE_OPDIVIDE: \
1068e88a9a20SSascha Wildner 			if (CAST(type, m->num_mask) == 0) \
1069c30bd091SSascha Wildner 				return -1; \
1070e88a9a20SSascha Wildner 			p->fld /= CAST(type, m->num_mask); \
1071327e51cbSPeter Avalos 			break; \
1072327e51cbSPeter Avalos 		case FILE_OPMODULO: \
1073e88a9a20SSascha Wildner 			if (CAST(type, m->num_mask) == 0) \
1074c30bd091SSascha Wildner 				return -1; \
1075e88a9a20SSascha Wildner 			p->fld %= CAST(type, m->num_mask); \
1076327e51cbSPeter Avalos 			break; \
1077327e51cbSPeter Avalos 		} \
1078327e51cbSPeter Avalos 	if (m->mask_op & FILE_OPINVERSE) \
1079327e51cbSPeter Avalos 		p->fld = ~p->fld \
1080327e51cbSPeter Avalos 
1081c30bd091SSascha Wildner private int
cvt_8(union VALUETYPE * p,const struct magic * m)1082327e51cbSPeter Avalos cvt_8(union VALUETYPE *p, const struct magic *m)
1083327e51cbSPeter Avalos {
1084e88a9a20SSascha Wildner 	DO_CVT(b, uint8_t);
1085c30bd091SSascha Wildner 	return 0;
1086327e51cbSPeter Avalos }
1087327e51cbSPeter Avalos 
1088c30bd091SSascha Wildner private int
cvt_16(union VALUETYPE * p,const struct magic * m)1089327e51cbSPeter Avalos cvt_16(union VALUETYPE *p, const struct magic *m)
1090327e51cbSPeter Avalos {
1091e88a9a20SSascha Wildner 	DO_CVT(h, uint16_t);
1092c30bd091SSascha Wildner 	return 0;
1093327e51cbSPeter Avalos }
1094327e51cbSPeter Avalos 
1095c30bd091SSascha Wildner private int
cvt_32(union VALUETYPE * p,const struct magic * m)1096327e51cbSPeter Avalos cvt_32(union VALUETYPE *p, const struct magic *m)
1097327e51cbSPeter Avalos {
1098e88a9a20SSascha Wildner 	DO_CVT(l, uint32_t);
1099c30bd091SSascha Wildner 	return 0;
1100327e51cbSPeter Avalos }
1101327e51cbSPeter Avalos 
1102c30bd091SSascha Wildner private int
cvt_64(union VALUETYPE * p,const struct magic * m)1103327e51cbSPeter Avalos cvt_64(union VALUETYPE *p, const struct magic *m)
1104327e51cbSPeter Avalos {
1105e88a9a20SSascha Wildner 	DO_CVT(q, uint64_t);
1106c30bd091SSascha Wildner 	return 0;
1107327e51cbSPeter Avalos }
1108327e51cbSPeter Avalos 
1109e88a9a20SSascha Wildner #define DO_CVT2(fld, type) \
1110327e51cbSPeter Avalos 	if (m->num_mask) \
1111327e51cbSPeter Avalos 		switch (m->mask_op & FILE_OPS_MASK) { \
1112327e51cbSPeter Avalos 		case FILE_OPADD: \
1113e88a9a20SSascha Wildner 			p->fld += CAST(type, m->num_mask); \
1114327e51cbSPeter Avalos 			break; \
1115327e51cbSPeter Avalos 		case FILE_OPMINUS: \
1116e88a9a20SSascha Wildner 			p->fld -= CAST(type, m->num_mask); \
1117327e51cbSPeter Avalos 			break; \
1118327e51cbSPeter Avalos 		case FILE_OPMULTIPLY: \
1119e88a9a20SSascha Wildner 			p->fld *= CAST(type, m->num_mask); \
1120327e51cbSPeter Avalos 			break; \
1121327e51cbSPeter Avalos 		case FILE_OPDIVIDE: \
1122e88a9a20SSascha Wildner 			if (CAST(type, m->num_mask) == 0) \
1123c30bd091SSascha Wildner 				return -1; \
1124e88a9a20SSascha Wildner 			p->fld /= CAST(type, m->num_mask); \
1125327e51cbSPeter Avalos 			break; \
1126327e51cbSPeter Avalos 		} \
1127327e51cbSPeter Avalos 
1128c30bd091SSascha Wildner private int
cvt_float(union VALUETYPE * p,const struct magic * m)1129327e51cbSPeter Avalos cvt_float(union VALUETYPE *p, const struct magic *m)
1130327e51cbSPeter Avalos {
1131e88a9a20SSascha Wildner 	DO_CVT2(f, float);
1132c30bd091SSascha Wildner 	return 0;
1133327e51cbSPeter Avalos }
1134327e51cbSPeter Avalos 
1135c30bd091SSascha Wildner private int
cvt_double(union VALUETYPE * p,const struct magic * m)1136327e51cbSPeter Avalos cvt_double(union VALUETYPE *p, const struct magic *m)
1137327e51cbSPeter Avalos {
1138e88a9a20SSascha Wildner 	DO_CVT2(d, double);
1139c30bd091SSascha Wildner 	return 0;
1140327e51cbSPeter Avalos }
1141327e51cbSPeter Avalos 
1142327e51cbSPeter Avalos /*
1143327e51cbSPeter Avalos  * Convert the byte order of the data we are looking at
1144327e51cbSPeter Avalos  * While we're here, let's apply the mask operation
1145327e51cbSPeter Avalos  * (unless you have a better idea)
1146327e51cbSPeter Avalos  */
1147327e51cbSPeter Avalos private int
mconvert(struct magic_set * ms,struct magic * m,int flip)1148e8af9738SPeter Avalos mconvert(struct magic_set *ms, struct magic *m, int flip)
1149327e51cbSPeter Avalos {
1150327e51cbSPeter Avalos 	union VALUETYPE *p = &ms->ms_value;
1151327e51cbSPeter Avalos 
1152c30bd091SSascha Wildner 	switch (cvt_flip(m->type, flip)) {
1153327e51cbSPeter Avalos 	case FILE_BYTE:
1154c30bd091SSascha Wildner 		if (cvt_8(p, m) == -1)
1155c30bd091SSascha Wildner 			goto out;
1156327e51cbSPeter Avalos 		return 1;
1157327e51cbSPeter Avalos 	case FILE_SHORT:
1158*3b9cdfa3SAntonio Huete Jimenez 	case FILE_MSDOSDATE:
1159*3b9cdfa3SAntonio Huete Jimenez 	case FILE_LEMSDOSDATE:
1160*3b9cdfa3SAntonio Huete Jimenez 	case FILE_BEMSDOSDATE:
1161*3b9cdfa3SAntonio Huete Jimenez 	case FILE_MSDOSTIME:
1162*3b9cdfa3SAntonio Huete Jimenez 	case FILE_LEMSDOSTIME:
1163*3b9cdfa3SAntonio Huete Jimenez 	case FILE_BEMSDOSTIME:
1164c30bd091SSascha Wildner 		if (cvt_16(p, m) == -1)
1165c30bd091SSascha Wildner 			goto out;
1166327e51cbSPeter Avalos 		return 1;
1167327e51cbSPeter Avalos 	case FILE_LONG:
1168327e51cbSPeter Avalos 	case FILE_DATE:
1169327e51cbSPeter Avalos 	case FILE_LDATE:
1170c30bd091SSascha Wildner 		if (cvt_32(p, m) == -1)
1171c30bd091SSascha Wildner 			goto out;
1172327e51cbSPeter Avalos 		return 1;
1173327e51cbSPeter Avalos 	case FILE_QUAD:
1174327e51cbSPeter Avalos 	case FILE_QDATE:
1175327e51cbSPeter Avalos 	case FILE_QLDATE:
1176e8af9738SPeter Avalos 	case FILE_QWDATE:
1177c990e5baSDaniel Fojt 	case FILE_OFFSET:
1178c30bd091SSascha Wildner 		if (cvt_64(p, m) == -1)
1179c30bd091SSascha Wildner 			goto out;
1180327e51cbSPeter Avalos 		return 1;
1181327e51cbSPeter Avalos 	case FILE_STRING:
1182327e51cbSPeter Avalos 	case FILE_BESTRING16:
1183*3b9cdfa3SAntonio Huete Jimenez 	case FILE_LESTRING16:
1184*3b9cdfa3SAntonio Huete Jimenez 	case FILE_OCTAL: {
1185327e51cbSPeter Avalos 		/* Null terminate and eat *trailing* return */
1186327e51cbSPeter Avalos 		p->s[sizeof(p->s) - 1] = '\0';
1187327e51cbSPeter Avalos 		return 1;
1188327e51cbSPeter Avalos 	}
1189327e51cbSPeter Avalos 	case FILE_PSTRING: {
1190c990e5baSDaniel Fojt 		char *ptr1, *ptr2;
1191c990e5baSDaniel Fojt 		size_t len, sz = file_pstring_length_size(ms, m);
1192c990e5baSDaniel Fojt 		if (sz == FILE_BADSIZE)
1193c990e5baSDaniel Fojt 			return 0;
1194c990e5baSDaniel Fojt 		ptr1 = p->s;
1195c990e5baSDaniel Fojt 		ptr2 = ptr1 + sz;
1196c990e5baSDaniel Fojt 		len = file_pstring_get_length(ms, m, ptr1);
1197c990e5baSDaniel Fojt 		if (len == FILE_BADSIZE)
1198c990e5baSDaniel Fojt 			return 0;
119982c5fa3eSPeter Avalos 		sz = sizeof(p->s) - sz; /* maximum length of string */
120082c5fa3eSPeter Avalos 		if (len >= sz) {
120182c5fa3eSPeter Avalos 			/*
120282c5fa3eSPeter Avalos 			 * The size of the pascal string length (sz)
120382c5fa3eSPeter Avalos 			 * is 1, 2, or 4. We need at least 1 byte for NUL
120482c5fa3eSPeter Avalos 			 * termination, but we've already truncated the
120582c5fa3eSPeter Avalos 			 * string by p->s, so we need to deduct sz.
120682c5fa3eSPeter Avalos 			 * Because we can use one of the bytes of the length
120782c5fa3eSPeter Avalos 			 * after we shifted as NUL termination.
120882c5fa3eSPeter Avalos 			 */
120982c5fa3eSPeter Avalos 			len = sz;
121082c5fa3eSPeter Avalos 		}
1211327e51cbSPeter Avalos 		while (len--)
1212327e51cbSPeter Avalos 			*ptr1++ = *ptr2++;
1213327e51cbSPeter Avalos 		*ptr1 = '\0';
1214327e51cbSPeter Avalos 		return 1;
1215327e51cbSPeter Avalos 	}
1216327e51cbSPeter Avalos 	case FILE_BESHORT:
1217e88a9a20SSascha Wildner 		p->h = CAST(short, BE16(p));
1218c30bd091SSascha Wildner 		if (cvt_16(p, m) == -1)
1219c30bd091SSascha Wildner 			goto out;
1220327e51cbSPeter Avalos 		return 1;
1221327e51cbSPeter Avalos 	case FILE_BELONG:
1222327e51cbSPeter Avalos 	case FILE_BEDATE:
1223327e51cbSPeter Avalos 	case FILE_BELDATE:
1224e88a9a20SSascha Wildner 		p->l = CAST(int32_t, BE32(p));
1225c30bd091SSascha Wildner 		if (cvt_32(p, m) == -1)
1226c30bd091SSascha Wildner 			goto out;
1227327e51cbSPeter Avalos 		return 1;
1228327e51cbSPeter Avalos 	case FILE_BEQUAD:
1229327e51cbSPeter Avalos 	case FILE_BEQDATE:
1230327e51cbSPeter Avalos 	case FILE_BEQLDATE:
1231e8af9738SPeter Avalos 	case FILE_BEQWDATE:
1232e88a9a20SSascha Wildner 		p->q = CAST(uint64_t, BE64(p));
1233c30bd091SSascha Wildner 		if (cvt_64(p, m) == -1)
1234c30bd091SSascha Wildner 			goto out;
1235327e51cbSPeter Avalos 		return 1;
1236327e51cbSPeter Avalos 	case FILE_LESHORT:
1237e88a9a20SSascha Wildner 		p->h = CAST(short, LE16(p));
1238c30bd091SSascha Wildner 		if (cvt_16(p, m) == -1)
1239c30bd091SSascha Wildner 			goto out;
1240327e51cbSPeter Avalos 		return 1;
1241327e51cbSPeter Avalos 	case FILE_LELONG:
1242327e51cbSPeter Avalos 	case FILE_LEDATE:
1243327e51cbSPeter Avalos 	case FILE_LELDATE:
1244e88a9a20SSascha Wildner 		p->l = CAST(int32_t, LE32(p));
1245c30bd091SSascha Wildner 		if (cvt_32(p, m) == -1)
1246c30bd091SSascha Wildner 			goto out;
1247327e51cbSPeter Avalos 		return 1;
1248327e51cbSPeter Avalos 	case FILE_LEQUAD:
1249327e51cbSPeter Avalos 	case FILE_LEQDATE:
1250327e51cbSPeter Avalos 	case FILE_LEQLDATE:
1251e8af9738SPeter Avalos 	case FILE_LEQWDATE:
1252e88a9a20SSascha Wildner 		p->q = CAST(uint64_t, LE64(p));
1253c30bd091SSascha Wildner 		if (cvt_64(p, m) == -1)
1254c30bd091SSascha Wildner 			goto out;
1255327e51cbSPeter Avalos 		return 1;
1256327e51cbSPeter Avalos 	case FILE_MELONG:
1257327e51cbSPeter Avalos 	case FILE_MEDATE:
1258327e51cbSPeter Avalos 	case FILE_MELDATE:
1259e88a9a20SSascha Wildner 		p->l = CAST(int32_t, ME32(p));
1260c30bd091SSascha Wildner 		if (cvt_32(p, m) == -1)
1261c30bd091SSascha Wildner 			goto out;
1262327e51cbSPeter Avalos 		return 1;
1263327e51cbSPeter Avalos 	case FILE_FLOAT:
1264c30bd091SSascha Wildner 		if (cvt_float(p, m) == -1)
1265c30bd091SSascha Wildner 			goto out;
1266327e51cbSPeter Avalos 		return 1;
1267327e51cbSPeter Avalos 	case FILE_BEFLOAT:
1268c30bd091SSascha Wildner 		p->l = BE32(p);
1269c30bd091SSascha Wildner 		if (cvt_float(p, m) == -1)
1270c30bd091SSascha Wildner 			goto out;
1271327e51cbSPeter Avalos 		return 1;
1272327e51cbSPeter Avalos 	case FILE_LEFLOAT:
1273c30bd091SSascha Wildner 		p->l = LE32(p);
1274c30bd091SSascha Wildner 		if (cvt_float(p, m) == -1)
1275c30bd091SSascha Wildner 			goto out;
1276327e51cbSPeter Avalos 		return 1;
1277327e51cbSPeter Avalos 	case FILE_DOUBLE:
1278c30bd091SSascha Wildner 		if (cvt_double(p, m) == -1)
1279c30bd091SSascha Wildner 			goto out;
1280327e51cbSPeter Avalos 		return 1;
1281327e51cbSPeter Avalos 	case FILE_BEDOUBLE:
1282c30bd091SSascha Wildner 		p->q = BE64(p);
1283c30bd091SSascha Wildner 		if (cvt_double(p, m) == -1)
1284c30bd091SSascha Wildner 			goto out;
1285327e51cbSPeter Avalos 		return 1;
1286327e51cbSPeter Avalos 	case FILE_LEDOUBLE:
1287c30bd091SSascha Wildner 		p->q = LE64(p);
1288c30bd091SSascha Wildner 		if (cvt_double(p, m) == -1)
1289c30bd091SSascha Wildner 			goto out;
1290327e51cbSPeter Avalos 		return 1;
1291327e51cbSPeter Avalos 	case FILE_REGEX:
1292327e51cbSPeter Avalos 	case FILE_SEARCH:
1293327e51cbSPeter Avalos 	case FILE_DEFAULT:
1294e8af9738SPeter Avalos 	case FILE_CLEAR:
1295e8af9738SPeter Avalos 	case FILE_NAME:
1296e8af9738SPeter Avalos 	case FILE_USE:
1297c30bd091SSascha Wildner 	case FILE_DER:
1298c990e5baSDaniel Fojt 	case FILE_GUID:
1299327e51cbSPeter Avalos 		return 1;
1300327e51cbSPeter Avalos 	default:
1301327e51cbSPeter Avalos 		file_magerror(ms, "invalid type %d in mconvert()", m->type);
1302327e51cbSPeter Avalos 		return 0;
1303327e51cbSPeter Avalos 	}
1304c30bd091SSascha Wildner out:
1305c30bd091SSascha Wildner 	file_magerror(ms, "zerodivide in mconvert()");
1306c30bd091SSascha Wildner 	return 0;
1307327e51cbSPeter Avalos }
1308327e51cbSPeter Avalos 
1309327e51cbSPeter Avalos 
1310327e51cbSPeter Avalos private void
mdebug(uint32_t offset,const char * str,size_t len)1311327e51cbSPeter Avalos mdebug(uint32_t offset, const char *str, size_t len)
1312327e51cbSPeter Avalos {
131382c5fa3eSPeter Avalos 	(void) fprintf(stderr, "mget/%" SIZE_T_FORMAT "u @%d: ", len, offset);
1314327e51cbSPeter Avalos 	file_showstr(stderr, str, len);
1315327e51cbSPeter Avalos 	(void) fputc('\n', stderr);
1316327e51cbSPeter Avalos 	(void) fputc('\n', stderr);
1317327e51cbSPeter Avalos }
1318327e51cbSPeter Avalos 
1319327e51cbSPeter Avalos private int
mcopy(struct magic_set * ms,union VALUETYPE * p,int type,int indir,const unsigned char * s,uint32_t offset,size_t nbytes,struct magic * m)1320327e51cbSPeter Avalos mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
132182c5fa3eSPeter Avalos     const unsigned char *s, uint32_t offset, size_t nbytes, struct magic *m)
1322327e51cbSPeter Avalos {
1323327e51cbSPeter Avalos 	/*
1324327e51cbSPeter Avalos 	 * Note: FILE_SEARCH and FILE_REGEX do not actually copy
1325327e51cbSPeter Avalos 	 * anything, but setup pointers into the source
1326327e51cbSPeter Avalos 	 */
1327327e51cbSPeter Avalos 	if (indir == 0) {
1328327e51cbSPeter Avalos 		switch (type) {
1329c30bd091SSascha Wildner 		case FILE_DER:
1330327e51cbSPeter Avalos 		case FILE_SEARCH:
1331c30bd091SSascha Wildner 			if (offset > nbytes)
1332c30bd091SSascha Wildner 				offset = CAST(uint32_t, nbytes);
1333a96e001bSPeter Avalos 			ms->search.s = RCAST(const char *, s) + offset;
1334327e51cbSPeter Avalos 			ms->search.s_len = nbytes - offset;
133579343712SPeter Avalos 			ms->search.offset = offset;
1336327e51cbSPeter Avalos 			return 0;
1337327e51cbSPeter Avalos 
1338327e51cbSPeter Avalos 		case FILE_REGEX: {
1339327e51cbSPeter Avalos 			const char *b;
1340327e51cbSPeter Avalos 			const char *c;
1341327e51cbSPeter Avalos 			const char *last;	/* end of search region */
1342327e51cbSPeter Avalos 			const char *buf;	/* start of search region */
134379343712SPeter Avalos 			const char *end;
134482c5fa3eSPeter Avalos 			size_t lines, linecnt, bytecnt;
1345327e51cbSPeter Avalos 
1346c30bd091SSascha Wildner 			if (s == NULL || nbytes < offset) {
1347327e51cbSPeter Avalos 				ms->search.s_len = 0;
1348327e51cbSPeter Avalos 				ms->search.s = NULL;
1349327e51cbSPeter Avalos 				return 0;
1350327e51cbSPeter Avalos 			}
135182c5fa3eSPeter Avalos 
135282c5fa3eSPeter Avalos 			if (m->str_flags & REGEX_LINE_COUNT) {
135382c5fa3eSPeter Avalos 				linecnt = m->str_range;
135482c5fa3eSPeter Avalos 				bytecnt = linecnt * 80;
135582c5fa3eSPeter Avalos 			} else {
135682c5fa3eSPeter Avalos 				linecnt = 0;
135782c5fa3eSPeter Avalos 				bytecnt = m->str_range;
135882c5fa3eSPeter Avalos 			}
135982c5fa3eSPeter Avalos 
1360c30bd091SSascha Wildner 			if (bytecnt == 0 || bytecnt > nbytes - offset)
1361c30bd091SSascha Wildner 				bytecnt = nbytes - offset;
1362c30bd091SSascha Wildner 			if (bytecnt > ms->regex_max)
1363c30bd091SSascha Wildner 				bytecnt = ms->regex_max;
136482c5fa3eSPeter Avalos 
1365a96e001bSPeter Avalos 			buf = RCAST(const char *, s) + offset;
1366c30bd091SSascha Wildner 			end = last = RCAST(const char *, s) + bytecnt + offset;
1367327e51cbSPeter Avalos 			/* mget() guarantees buf <= last */
1368e4d4ce0cSPeter Avalos 			for (lines = linecnt, b = buf; lines && b < end &&
1369f72f8299SJan Lentfer 			     ((b = CAST(const char *,
1370f72f8299SJan Lentfer 				 memchr(c = b, '\n', CAST(size_t, (end - b)))))
1371f72f8299SJan Lentfer 			     || (b = CAST(const char *,
1372f72f8299SJan Lentfer 				 memchr(c, '\r', CAST(size_t, (end - c))))));
1373327e51cbSPeter Avalos 			     lines--, b++) {
1374c30bd091SSascha Wildner 				if (b < end - 1 && b[0] == '\r' && b[1] == '\n')
1375327e51cbSPeter Avalos 					b++;
1376e88a9a20SSascha Wildner 				if (b < end - 1 && b[0] == '\n')
1377e88a9a20SSascha Wildner 					b++;
1378e88a9a20SSascha Wildner 				last = b;
1379327e51cbSPeter Avalos 			}
1380327e51cbSPeter Avalos 			if (lines)
1381e88a9a20SSascha Wildner 				last = end;
1382327e51cbSPeter Avalos 
1383327e51cbSPeter Avalos 			ms->search.s = buf;
1384327e51cbSPeter Avalos 			ms->search.s_len = last - buf;
1385327e51cbSPeter Avalos 			ms->search.offset = offset;
1386327e51cbSPeter Avalos 			ms->search.rm_len = 0;
1387327e51cbSPeter Avalos 			return 0;
1388327e51cbSPeter Avalos 		}
1389327e51cbSPeter Avalos 		case FILE_BESTRING16:
1390327e51cbSPeter Avalos 		case FILE_LESTRING16: {
1391327e51cbSPeter Avalos 			const unsigned char *src = s + offset;
1392327e51cbSPeter Avalos 			const unsigned char *esrc = s + nbytes;
1393327e51cbSPeter Avalos 			char *dst = p->s;
1394327e51cbSPeter Avalos 			char *edst = &p->s[sizeof(p->s) - 1];
1395327e51cbSPeter Avalos 
1396327e51cbSPeter Avalos 			if (type == FILE_BESTRING16)
1397327e51cbSPeter Avalos 				src++;
1398327e51cbSPeter Avalos 
1399e8af9738SPeter Avalos 			/* check that offset is within range */
1400e8af9738SPeter Avalos 			if (offset >= nbytes)
1401e8af9738SPeter Avalos 				break;
1402327e51cbSPeter Avalos 			for (/*EMPTY*/; src < esrc; src += 2, dst++) {
1403327e51cbSPeter Avalos 				if (dst < edst)
1404327e51cbSPeter Avalos 					*dst = *src;
1405327e51cbSPeter Avalos 				else
1406327e51cbSPeter Avalos 					break;
1407327e51cbSPeter Avalos 				if (*dst == '\0') {
1408327e51cbSPeter Avalos 					if (type == FILE_BESTRING16 ?
1409327e51cbSPeter Avalos 					    *(src - 1) != '\0' :
1410c30bd091SSascha Wildner 					    ((src + 1 < esrc) &&
1411c30bd091SSascha Wildner 					    *(src + 1) != '\0'))
1412327e51cbSPeter Avalos 						*dst = ' ';
1413327e51cbSPeter Avalos 				}
1414327e51cbSPeter Avalos 			}
1415327e51cbSPeter Avalos 			*edst = '\0';
1416327e51cbSPeter Avalos 			return 0;
1417327e51cbSPeter Avalos 		}
1418327e51cbSPeter Avalos 		case FILE_STRING:	/* XXX - these two should not need */
1419327e51cbSPeter Avalos 		case FILE_PSTRING:	/* to copy anything, but do anyway. */
1420327e51cbSPeter Avalos 		default:
1421327e51cbSPeter Avalos 			break;
1422327e51cbSPeter Avalos 		}
1423327e51cbSPeter Avalos 	}
1424327e51cbSPeter Avalos 
1425c990e5baSDaniel Fojt 	if (type == FILE_OFFSET) {
1426c990e5baSDaniel Fojt 		(void)memset(p, '\0', sizeof(*p));
1427c990e5baSDaniel Fojt 		p->q = offset;
1428c990e5baSDaniel Fojt 		return 0;
1429c990e5baSDaniel Fojt 	}
1430c990e5baSDaniel Fojt 
1431327e51cbSPeter Avalos 	if (offset >= nbytes) {
1432327e51cbSPeter Avalos 		(void)memset(p, '\0', sizeof(*p));
1433327e51cbSPeter Avalos 		return 0;
1434327e51cbSPeter Avalos 	}
1435327e51cbSPeter Avalos 	if (nbytes - offset < sizeof(*p))
1436327e51cbSPeter Avalos 		nbytes = nbytes - offset;
1437327e51cbSPeter Avalos 	else
1438327e51cbSPeter Avalos 		nbytes = sizeof(*p);
1439327e51cbSPeter Avalos 
1440327e51cbSPeter Avalos 	(void)memcpy(p, s + offset, nbytes);
1441327e51cbSPeter Avalos 
1442327e51cbSPeter Avalos 	/*
1443327e51cbSPeter Avalos 	 * the usefulness of padding with zeroes eludes me, it
1444327e51cbSPeter Avalos 	 * might even cause problems
1445327e51cbSPeter Avalos 	 */
1446327e51cbSPeter Avalos 	if (nbytes < sizeof(*p))
1447e88a9a20SSascha Wildner 		(void)memset(RCAST(char *, RCAST(void *, p)) + nbytes, '\0',
1448327e51cbSPeter Avalos 		    sizeof(*p) - nbytes);
1449327e51cbSPeter Avalos 	return 0;
1450327e51cbSPeter Avalos }
1451327e51cbSPeter Avalos 
1452c30bd091SSascha Wildner private uint32_t
do_ops(struct magic * m,intmax_t lhs,intmax_t off)1453c30bd091SSascha Wildner do_ops(struct magic *m, intmax_t lhs, intmax_t off)
1454c30bd091SSascha Wildner {
145563725360SSascha Wildner 	intmax_t offset = 0;
1456c30bd091SSascha Wildner 	if (off) {
1457c30bd091SSascha Wildner 		switch (m->in_op & FILE_OPS_MASK) {
1458c30bd091SSascha Wildner 		case FILE_OPAND:
1459c30bd091SSascha Wildner 			offset = lhs & off;
1460c30bd091SSascha Wildner 			break;
1461c30bd091SSascha Wildner 		case FILE_OPOR:
1462c30bd091SSascha Wildner 			offset = lhs | off;
1463c30bd091SSascha Wildner 			break;
1464c30bd091SSascha Wildner 		case FILE_OPXOR:
1465c30bd091SSascha Wildner 			offset = lhs ^ off;
1466c30bd091SSascha Wildner 			break;
1467c30bd091SSascha Wildner 		case FILE_OPADD:
1468c30bd091SSascha Wildner 			offset = lhs + off;
1469c30bd091SSascha Wildner 			break;
1470c30bd091SSascha Wildner 		case FILE_OPMINUS:
1471c30bd091SSascha Wildner 			offset = lhs - off;
1472c30bd091SSascha Wildner 			break;
1473c30bd091SSascha Wildner 		case FILE_OPMULTIPLY:
1474c30bd091SSascha Wildner 			offset = lhs * off;
1475c30bd091SSascha Wildner 			break;
1476c30bd091SSascha Wildner 		case FILE_OPDIVIDE:
1477c30bd091SSascha Wildner 			offset = lhs / off;
1478c30bd091SSascha Wildner 			break;
1479c30bd091SSascha Wildner 		case FILE_OPMODULO:
1480c30bd091SSascha Wildner 			offset = lhs % off;
1481c30bd091SSascha Wildner 			break;
1482c30bd091SSascha Wildner 		}
1483c30bd091SSascha Wildner 	} else
1484c30bd091SSascha Wildner 		offset = lhs;
1485c30bd091SSascha Wildner 	if (m->in_op & FILE_OPINVERSE)
1486c30bd091SSascha Wildner 		offset = ~offset;
1487c30bd091SSascha Wildner 
1488e88a9a20SSascha Wildner 	return CAST(uint32_t, offset);
1489c30bd091SSascha Wildner }
1490c30bd091SSascha Wildner 
1491327e51cbSPeter Avalos private int
msetoffset(struct magic_set * ms,struct magic * m,struct buffer * bb,const struct buffer * b,size_t o,unsigned int cont_level)1492e88a9a20SSascha Wildner msetoffset(struct magic_set *ms, struct magic *m, struct buffer *bb,
1493e88a9a20SSascha Wildner     const struct buffer *b, size_t o, unsigned int cont_level)
1494e88a9a20SSascha Wildner {
1495c990e5baSDaniel Fojt 	int32_t offset;
1496c990e5baSDaniel Fojt 	if (m->flag & OFFNEGATIVE) {
1497c990e5baSDaniel Fojt 		offset = -m->offset;
1498e88a9a20SSascha Wildner 		if (cont_level > 0) {
1499e88a9a20SSascha Wildner 			if (m->flag & (OFFADD|INDIROFFADD))
1500e88a9a20SSascha Wildner 				goto normal;
1501e88a9a20SSascha Wildner #if 0
1502e88a9a20SSascha Wildner 			file_error(ms, 0, "negative offset %d at continuation"
1503e88a9a20SSascha Wildner 			    "level %u", m->offset, cont_level);
1504e88a9a20SSascha Wildner 			return -1;
1505e88a9a20SSascha Wildner #endif
1506e88a9a20SSascha Wildner 		}
1507e88a9a20SSascha Wildner 		if (buffer_fill(b) == -1)
1508e88a9a20SSascha Wildner 			return -1;
1509e88a9a20SSascha Wildner 		if (o != 0) {
1510e88a9a20SSascha Wildner 			// Not yet!
1511e88a9a20SSascha Wildner 			file_magerror(ms, "non zero offset %" SIZE_T_FORMAT
1512e88a9a20SSascha Wildner 			    "u at level %u", o, cont_level);
1513e88a9a20SSascha Wildner 			return -1;
1514e88a9a20SSascha Wildner 		}
1515c990e5baSDaniel Fojt 		if (CAST(size_t, m->offset) > b->elen)
1516e88a9a20SSascha Wildner 			return -1;
1517e88a9a20SSascha Wildner 		buffer_init(bb, -1, NULL, b->ebuf, b->elen);
1518c990e5baSDaniel Fojt 		ms->eoffset = ms->offset = CAST(int32_t, b->elen - m->offset);
1519e88a9a20SSascha Wildner 	} else {
1520c990e5baSDaniel Fojt 		offset = m->offset;
1521e88a9a20SSascha Wildner 		if (cont_level == 0) {
1522e88a9a20SSascha Wildner normal:
1523e88a9a20SSascha Wildner 			// XXX: Pass real fd, then who frees bb?
1524e88a9a20SSascha Wildner 			buffer_init(bb, -1, NULL, b->fbuf, b->flen);
1525c990e5baSDaniel Fojt 			ms->offset = offset;
1526e88a9a20SSascha Wildner 			ms->eoffset = 0;
1527e88a9a20SSascha Wildner 		} else {
1528c990e5baSDaniel Fojt 			ms->offset = ms->eoffset + offset;
1529e88a9a20SSascha Wildner 		}
1530e88a9a20SSascha Wildner 	}
1531e88a9a20SSascha Wildner 	if ((ms->flags & MAGIC_DEBUG) != 0) {
1532c990e5baSDaniel Fojt 		fprintf(stderr, "bb=[%p,%" SIZE_T_FORMAT "u,%"
1533c990e5baSDaniel Fojt 		    SIZE_T_FORMAT "u], %d [b=%p,%"
1534c990e5baSDaniel Fojt 		    SIZE_T_FORMAT "u,%" SIZE_T_FORMAT "u], [o=%#x, c=%d]\n",
1535c990e5baSDaniel Fojt 		    bb->fbuf, bb->flen, bb->elen, ms->offset, b->fbuf,
1536c990e5baSDaniel Fojt 		    b->flen, b->elen, offset, cont_level);
1537e88a9a20SSascha Wildner 	}
1538e88a9a20SSascha Wildner 	return 0;
1539e88a9a20SSascha Wildner }
1540e88a9a20SSascha Wildner 
1541e88a9a20SSascha Wildner private int
save_cont(struct magic_set * ms,struct cont * c)1542970935fdSSascha Wildner save_cont(struct magic_set *ms, struct cont *c)
1543970935fdSSascha Wildner {
1544970935fdSSascha Wildner 	size_t len;
1545970935fdSSascha Wildner 	*c = ms->c;
1546970935fdSSascha Wildner 	len = c->len * sizeof(*c->li);
1547970935fdSSascha Wildner 	ms->c.li = CAST(struct level_info *, malloc(len));
1548970935fdSSascha Wildner 	if (ms->c.li == NULL) {
1549970935fdSSascha Wildner 		ms->c = *c;
1550970935fdSSascha Wildner 		return -1;
1551970935fdSSascha Wildner 	}
1552970935fdSSascha Wildner 	memcpy(ms->c.li, c->li, len);
1553970935fdSSascha Wildner 	return 0;
1554970935fdSSascha Wildner }
1555970935fdSSascha Wildner 
1556970935fdSSascha Wildner private void
restore_cont(struct magic_set * ms,struct cont * c)1557970935fdSSascha Wildner restore_cont(struct magic_set *ms, struct cont *c)
1558970935fdSSascha Wildner {
1559970935fdSSascha Wildner 	free(ms->c.li);
1560970935fdSSascha Wildner 	ms->c = *c;
1561970935fdSSascha Wildner }
1562970935fdSSascha Wildner 
1563970935fdSSascha Wildner private int
mget(struct magic_set * ms,struct magic * m,const struct buffer * b,const unsigned char * s,size_t nbytes,size_t o,unsigned int cont_level,int mode,int text,int flip,uint16_t * indir_count,uint16_t * name_count,int * printed_something,int * need_separator,int * returnval,int * found_match)1564e88a9a20SSascha Wildner mget(struct magic_set *ms, struct magic *m, const struct buffer *b,
1565e88a9a20SSascha Wildner     const unsigned char *s, size_t nbytes, size_t o, unsigned int cont_level,
1566e88a9a20SSascha Wildner     int mode, int text, int flip, uint16_t *indir_count, uint16_t *name_count,
1567e88a9a20SSascha Wildner     int *printed_something, int *need_separator, int *returnval,
1568e88a9a20SSascha Wildner     int *found_match)
1569327e51cbSPeter Avalos {
1570970935fdSSascha Wildner 	uint32_t eoffset, offset = ms->offset;
1571e88a9a20SSascha Wildner 	struct buffer bb;
1572c30bd091SSascha Wildner 	intmax_t lhs;
157382c5fa3eSPeter Avalos 	file_pushbuf_t *pb;
1574970935fdSSascha Wildner 	int rv, oneed_separator, in_type, nfound_match;
157582c5fa3eSPeter Avalos 	char *rbuf;
1576327e51cbSPeter Avalos 	union VALUETYPE *p = &ms->ms_value;
1577614728caSSascha Wildner 	struct mlist ml, *mlp;
1578970935fdSSascha Wildner 	struct cont c;
1579327e51cbSPeter Avalos 
1580c30bd091SSascha Wildner 	if (*indir_count >= ms->indir_max) {
1581c30bd091SSascha Wildner 		file_error(ms, 0, "indirect count (%hu) exceeded",
1582c30bd091SSascha Wildner 		    *indir_count);
158382c5fa3eSPeter Avalos 		return -1;
158482c5fa3eSPeter Avalos 	}
158582c5fa3eSPeter Avalos 
158682c5fa3eSPeter Avalos 	if (*name_count >= ms->name_max) {
158782c5fa3eSPeter Avalos 		file_error(ms, 0, "name use count (%hu) exceeded",
158882c5fa3eSPeter Avalos 		    *name_count);
1589e8af9738SPeter Avalos 		return -1;
1590e8af9738SPeter Avalos 	}
1591e8af9738SPeter Avalos 
1592e88a9a20SSascha Wildner 
1593e88a9a20SSascha Wildner 
1594e88a9a20SSascha Wildner 	if (mcopy(ms, p, m->type, m->flag & INDIR, s,
1595e88a9a20SSascha Wildner 	    CAST(uint32_t, offset + o), CAST(uint32_t, nbytes), m) == -1)
1596327e51cbSPeter Avalos 		return -1;
1597327e51cbSPeter Avalos 
1598327e51cbSPeter Avalos 	if ((ms->flags & MAGIC_DEBUG) != 0) {
1599c30bd091SSascha Wildner 		fprintf(stderr, "mget(type=%d, flag=%#x, offset=%u, o=%"
160082c5fa3eSPeter Avalos 		    SIZE_T_FORMAT "u, " "nbytes=%" SIZE_T_FORMAT
160182c5fa3eSPeter Avalos 		    "u, il=%hu, nc=%hu)\n",
160282c5fa3eSPeter Avalos 		    m->type, m->flag, offset, o, nbytes,
1603c30bd091SSascha Wildner 		    *indir_count, *name_count);
1604e88a9a20SSascha Wildner 		mdebug(offset, RCAST(char *, RCAST(void *, p)),
1605e88a9a20SSascha Wildner 		    sizeof(union VALUETYPE));
160679343712SPeter Avalos #ifndef COMPILE_ONLY
1607327e51cbSPeter Avalos 		file_mdump(m);
160879343712SPeter Avalos #endif
1609327e51cbSPeter Avalos 	}
1610327e51cbSPeter Avalos 
1611327e51cbSPeter Avalos 	if (m->flag & INDIR) {
1612c30bd091SSascha Wildner 		intmax_t off = m->in_offset;
1613c30bd091SSascha Wildner 		const int sgn = m->in_op & FILE_OPSIGNED;
1614327e51cbSPeter Avalos 		if (m->in_op & FILE_OPINDIRECT) {
161579343712SPeter Avalos 			const union VALUETYPE *q = CAST(const union VALUETYPE *,
1616e88a9a20SSascha Wildner 			    RCAST(const void *, s + offset + off));
1617c990e5baSDaniel Fojt 			int op;
1618c990e5baSDaniel Fojt 			switch (op = cvt_flip(m->in_type, flip)) {
1619327e51cbSPeter Avalos 			case FILE_BYTE:
1620e88a9a20SSascha Wildner 				if (OFFSET_OOB(nbytes, offset + off, 1))
1621e88a9a20SSascha Wildner 					return 0;
1622c30bd091SSascha Wildner 				off = SEXT(sgn,8,q->b);
1623327e51cbSPeter Avalos 				break;
1624327e51cbSPeter Avalos 			case FILE_SHORT:
1625e88a9a20SSascha Wildner 				if (OFFSET_OOB(nbytes, offset + off, 2))
1626e88a9a20SSascha Wildner 					return 0;
1627c30bd091SSascha Wildner 				off = SEXT(sgn,16,q->h);
1628327e51cbSPeter Avalos 				break;
1629327e51cbSPeter Avalos 			case FILE_BESHORT:
1630e88a9a20SSascha Wildner 				if (OFFSET_OOB(nbytes, offset + off, 2))
1631e88a9a20SSascha Wildner 					return 0;
1632c30bd091SSascha Wildner 				off = SEXT(sgn,16,BE16(q));
1633327e51cbSPeter Avalos 				break;
1634327e51cbSPeter Avalos 			case FILE_LESHORT:
1635e88a9a20SSascha Wildner 				if (OFFSET_OOB(nbytes, offset + off, 2))
1636e88a9a20SSascha Wildner 					return 0;
1637c30bd091SSascha Wildner 				off = SEXT(sgn,16,LE16(q));
1638327e51cbSPeter Avalos 				break;
1639327e51cbSPeter Avalos 			case FILE_LONG:
1640e88a9a20SSascha Wildner 				if (OFFSET_OOB(nbytes, offset + off, 4))
1641e88a9a20SSascha Wildner 					return 0;
1642c30bd091SSascha Wildner 				off = SEXT(sgn,32,q->l);
1643327e51cbSPeter Avalos 				break;
1644327e51cbSPeter Avalos 			case FILE_BELONG:
164579343712SPeter Avalos 			case FILE_BEID3:
1646e88a9a20SSascha Wildner 				if (OFFSET_OOB(nbytes, offset + off, 4))
1647e88a9a20SSascha Wildner 					return 0;
1648c30bd091SSascha Wildner 				off = SEXT(sgn,32,BE32(q));
1649327e51cbSPeter Avalos 				break;
165079343712SPeter Avalos 			case FILE_LEID3:
1651327e51cbSPeter Avalos 			case FILE_LELONG:
1652e88a9a20SSascha Wildner 				if (OFFSET_OOB(nbytes, offset + off, 4))
1653e88a9a20SSascha Wildner 					return 0;
1654c30bd091SSascha Wildner 				off = SEXT(sgn,32,LE32(q));
1655327e51cbSPeter Avalos 				break;
1656327e51cbSPeter Avalos 			case FILE_MELONG:
1657e88a9a20SSascha Wildner 				if (OFFSET_OOB(nbytes, offset + off, 4))
1658e88a9a20SSascha Wildner 					return 0;
1659c30bd091SSascha Wildner 				off = SEXT(sgn,32,ME32(q));
1660327e51cbSPeter Avalos 				break;
1661e88a9a20SSascha Wildner 			case FILE_BEQUAD:
1662e88a9a20SSascha Wildner 				if (OFFSET_OOB(nbytes, offset + off, 8))
1663e88a9a20SSascha Wildner 					return 0;
1664e88a9a20SSascha Wildner 				off = SEXT(sgn,64,BE64(q));
1665e88a9a20SSascha Wildner 				break;
1666e88a9a20SSascha Wildner 			case FILE_LEQUAD:
1667e88a9a20SSascha Wildner 				if (OFFSET_OOB(nbytes, offset + off, 8))
1668e88a9a20SSascha Wildner 					return 0;
1669e88a9a20SSascha Wildner 				off = SEXT(sgn,64,LE64(q));
1670e88a9a20SSascha Wildner 				break;
1671*3b9cdfa3SAntonio Huete Jimenez 			case FILE_OCTAL:
1672*3b9cdfa3SAntonio Huete Jimenez 				if (OFFSET_OOB(nbytes, offset, m->vallen))
1673*3b9cdfa3SAntonio Huete Jimenez 					return 0;
1674*3b9cdfa3SAntonio Huete Jimenez 				off = SEXT(sgn,64,strtoull(p->s, NULL, 8));
1675*3b9cdfa3SAntonio Huete Jimenez 				break;
1676e88a9a20SSascha Wildner 			default:
1677c990e5baSDaniel Fojt 				if ((ms->flags & MAGIC_DEBUG) != 0)
1678c990e5baSDaniel Fojt 					fprintf(stderr, "bad op=%d\n", op);
1679c990e5baSDaniel Fojt 				return 0;
1680327e51cbSPeter Avalos 			}
1681e8af9738SPeter Avalos 			if ((ms->flags & MAGIC_DEBUG) != 0)
1682c30bd091SSascha Wildner 				fprintf(stderr, "indirect offs=%jd\n", off);
1683327e51cbSPeter Avalos 		}
1684e8af9738SPeter Avalos 		switch (in_type = cvt_flip(m->in_type, flip)) {
1685327e51cbSPeter Avalos 		case FILE_BYTE:
1686e8af9738SPeter Avalos 			if (OFFSET_OOB(nbytes, offset, 1))
1687327e51cbSPeter Avalos 				return 0;
1688c30bd091SSascha Wildner 			offset = do_ops(m, SEXT(sgn,8,p->b), off);
1689327e51cbSPeter Avalos 			break;
1690327e51cbSPeter Avalos 		case FILE_BESHORT:
1691e8af9738SPeter Avalos 			if (OFFSET_OOB(nbytes, offset, 2))
1692327e51cbSPeter Avalos 				return 0;
1693c30bd091SSascha Wildner 			offset = do_ops(m, SEXT(sgn,16,BE16(p)), off);
1694327e51cbSPeter Avalos 			break;
1695327e51cbSPeter Avalos 		case FILE_LESHORT:
1696e8af9738SPeter Avalos 			if (OFFSET_OOB(nbytes, offset, 2))
1697327e51cbSPeter Avalos 				return 0;
1698c30bd091SSascha Wildner 			offset = do_ops(m, SEXT(sgn,16,LE16(p)), off);
1699327e51cbSPeter Avalos 			break;
1700327e51cbSPeter Avalos 		case FILE_SHORT:
1701e8af9738SPeter Avalos 			if (OFFSET_OOB(nbytes, offset, 2))
1702327e51cbSPeter Avalos 				return 0;
1703c30bd091SSascha Wildner 			offset = do_ops(m, SEXT(sgn,16,p->h), off);
1704327e51cbSPeter Avalos 			break;
1705327e51cbSPeter Avalos 		case FILE_BELONG:
170679343712SPeter Avalos 		case FILE_BEID3:
1707e8af9738SPeter Avalos 			if (OFFSET_OOB(nbytes, offset, 4))
1708327e51cbSPeter Avalos 				return 0;
1709c30bd091SSascha Wildner 			lhs = BE32(p);
1710c30bd091SSascha Wildner 			if (in_type == FILE_BEID3)
1711e88a9a20SSascha Wildner 				lhs = cvt_id3(ms, CAST(uint32_t, lhs));
1712c30bd091SSascha Wildner 			offset = do_ops(m, SEXT(sgn,32,lhs), off);
1713327e51cbSPeter Avalos 			break;
1714327e51cbSPeter Avalos 		case FILE_LELONG:
171579343712SPeter Avalos 		case FILE_LEID3:
1716e8af9738SPeter Avalos 			if (OFFSET_OOB(nbytes, offset, 4))
1717327e51cbSPeter Avalos 				return 0;
1718c30bd091SSascha Wildner 			lhs = LE32(p);
1719c30bd091SSascha Wildner 			if (in_type == FILE_LEID3)
1720e88a9a20SSascha Wildner 				lhs = cvt_id3(ms, CAST(uint32_t, lhs));
1721c30bd091SSascha Wildner 			offset = do_ops(m, SEXT(sgn,32,lhs), off);
1722327e51cbSPeter Avalos 			break;
1723327e51cbSPeter Avalos 		case FILE_MELONG:
1724e8af9738SPeter Avalos 			if (OFFSET_OOB(nbytes, offset, 4))
1725327e51cbSPeter Avalos 				return 0;
1726c30bd091SSascha Wildner 			offset = do_ops(m, SEXT(sgn,32,ME32(p)), off);
1727327e51cbSPeter Avalos 			break;
1728327e51cbSPeter Avalos 		case FILE_LONG:
1729e8af9738SPeter Avalos 			if (OFFSET_OOB(nbytes, offset, 4))
1730327e51cbSPeter Avalos 				return 0;
1731c30bd091SSascha Wildner 			offset = do_ops(m, SEXT(sgn,32,p->l), off);
173279343712SPeter Avalos 			break;
1733e88a9a20SSascha Wildner 		case FILE_LEQUAD:
1734e88a9a20SSascha Wildner 			if (OFFSET_OOB(nbytes, offset, 8))
1735e88a9a20SSascha Wildner 				return 0;
1736e88a9a20SSascha Wildner 			offset = do_ops(m, SEXT(sgn,64,LE64(p)), off);
173779343712SPeter Avalos 			break;
1738e88a9a20SSascha Wildner 		case FILE_BEQUAD:
1739e88a9a20SSascha Wildner 			if (OFFSET_OOB(nbytes, offset, 8))
1740e88a9a20SSascha Wildner 				return 0;
1741e88a9a20SSascha Wildner 			offset = do_ops(m, SEXT(sgn,64,BE64(p)), off);
1742e88a9a20SSascha Wildner 			break;
1743*3b9cdfa3SAntonio Huete Jimenez 		case FILE_OCTAL:
1744*3b9cdfa3SAntonio Huete Jimenez 			if (OFFSET_OOB(nbytes, offset, m->vallen))
1745*3b9cdfa3SAntonio Huete Jimenez 				return 0;
1746*3b9cdfa3SAntonio Huete Jimenez 			offset = do_ops(m,
1747*3b9cdfa3SAntonio Huete Jimenez 			    SEXT(sgn,64,strtoull(p->s, NULL, 8)), off);
1748*3b9cdfa3SAntonio Huete Jimenez 			break;
1749e88a9a20SSascha Wildner 		default:
1750c990e5baSDaniel Fojt 			if ((ms->flags & MAGIC_DEBUG) != 0)
1751c990e5baSDaniel Fojt 				fprintf(stderr, "bad in_type=%d\n", in_type);
1752c990e5baSDaniel Fojt 			return 0;
175379343712SPeter Avalos 		}
175479343712SPeter Avalos 
175579343712SPeter Avalos 		if (m->flag & INDIROFFADD) {
1756c990e5baSDaniel Fojt 			if (cont_level == 0) {
1757c990e5baSDaniel Fojt 				if ((ms->flags & MAGIC_DEBUG) != 0)
1758c990e5baSDaniel Fojt 					fprintf(stderr,
1759c990e5baSDaniel Fojt 					    "indirect *zero* cont_level\n");
1760c990e5baSDaniel Fojt 				return 0;
1761c990e5baSDaniel Fojt 			}
1762327e51cbSPeter Avalos 			offset += ms->c.li[cont_level - 1].off;
1763e8af9738SPeter Avalos 			if (offset == 0) {
1764e8af9738SPeter Avalos 				if ((ms->flags & MAGIC_DEBUG) != 0)
1765e8af9738SPeter Avalos 					fprintf(stderr,
1766e8af9738SPeter Avalos 					    "indirect *zero* offset\n");
1767e8af9738SPeter Avalos 				return 0;
1768e8af9738SPeter Avalos 			}
1769e8af9738SPeter Avalos 			if ((ms->flags & MAGIC_DEBUG) != 0)
1770e8af9738SPeter Avalos 				fprintf(stderr, "indirect +offs=%u\n", offset);
177179343712SPeter Avalos 		}
177282c5fa3eSPeter Avalos 		if (mcopy(ms, p, m->type, 0, s, offset, nbytes, m) == -1)
1773327e51cbSPeter Avalos 			return -1;
1774327e51cbSPeter Avalos 		ms->offset = offset;
1775327e51cbSPeter Avalos 
1776327e51cbSPeter Avalos 		if ((ms->flags & MAGIC_DEBUG) != 0) {
1777e88a9a20SSascha Wildner 			mdebug(offset, RCAST(char *, RCAST(void *, p)),
1778327e51cbSPeter Avalos 			    sizeof(union VALUETYPE));
177979343712SPeter Avalos #ifndef COMPILE_ONLY
1780327e51cbSPeter Avalos 			file_mdump(m);
178179343712SPeter Avalos #endif
1782327e51cbSPeter Avalos 		}
1783327e51cbSPeter Avalos 	}
1784327e51cbSPeter Avalos 
1785327e51cbSPeter Avalos 	/* Verify we have enough data to match magic type */
1786327e51cbSPeter Avalos 	switch (m->type) {
1787327e51cbSPeter Avalos 	case FILE_BYTE:
1788e8af9738SPeter Avalos 		if (OFFSET_OOB(nbytes, offset, 1))
1789327e51cbSPeter Avalos 			return 0;
1790327e51cbSPeter Avalos 		break;
1791327e51cbSPeter Avalos 
1792327e51cbSPeter Avalos 	case FILE_SHORT:
1793327e51cbSPeter Avalos 	case FILE_BESHORT:
1794327e51cbSPeter Avalos 	case FILE_LESHORT:
1795e8af9738SPeter Avalos 		if (OFFSET_OOB(nbytes, offset, 2))
1796327e51cbSPeter Avalos 			return 0;
1797327e51cbSPeter Avalos 		break;
1798327e51cbSPeter Avalos 
1799327e51cbSPeter Avalos 	case FILE_LONG:
1800327e51cbSPeter Avalos 	case FILE_BELONG:
1801327e51cbSPeter Avalos 	case FILE_LELONG:
1802327e51cbSPeter Avalos 	case FILE_MELONG:
1803327e51cbSPeter Avalos 	case FILE_DATE:
1804327e51cbSPeter Avalos 	case FILE_BEDATE:
1805327e51cbSPeter Avalos 	case FILE_LEDATE:
1806327e51cbSPeter Avalos 	case FILE_MEDATE:
1807327e51cbSPeter Avalos 	case FILE_LDATE:
1808327e51cbSPeter Avalos 	case FILE_BELDATE:
1809327e51cbSPeter Avalos 	case FILE_LELDATE:
1810327e51cbSPeter Avalos 	case FILE_MELDATE:
1811327e51cbSPeter Avalos 	case FILE_FLOAT:
1812327e51cbSPeter Avalos 	case FILE_BEFLOAT:
1813327e51cbSPeter Avalos 	case FILE_LEFLOAT:
1814e8af9738SPeter Avalos 		if (OFFSET_OOB(nbytes, offset, 4))
1815327e51cbSPeter Avalos 			return 0;
1816327e51cbSPeter Avalos 		break;
1817327e51cbSPeter Avalos 
1818327e51cbSPeter Avalos 	case FILE_DOUBLE:
1819327e51cbSPeter Avalos 	case FILE_BEDOUBLE:
1820327e51cbSPeter Avalos 	case FILE_LEDOUBLE:
1821e8af9738SPeter Avalos 		if (OFFSET_OOB(nbytes, offset, 8))
1822327e51cbSPeter Avalos 			return 0;
1823327e51cbSPeter Avalos 		break;
1824327e51cbSPeter Avalos 
1825c990e5baSDaniel Fojt 	case FILE_GUID:
1826c990e5baSDaniel Fojt 		if (OFFSET_OOB(nbytes, offset, 16))
1827c990e5baSDaniel Fojt 			return 0;
1828c990e5baSDaniel Fojt 		break;
1829c990e5baSDaniel Fojt 
1830327e51cbSPeter Avalos 	case FILE_STRING:
1831327e51cbSPeter Avalos 	case FILE_PSTRING:
1832327e51cbSPeter Avalos 	case FILE_SEARCH:
1833*3b9cdfa3SAntonio Huete Jimenez 	case FILE_OCTAL:
1834e8af9738SPeter Avalos 		if (OFFSET_OOB(nbytes, offset, m->vallen))
1835327e51cbSPeter Avalos 			return 0;
1836327e51cbSPeter Avalos 		break;
1837327e51cbSPeter Avalos 
1838327e51cbSPeter Avalos 	case FILE_REGEX:
1839327e51cbSPeter Avalos 		if (nbytes < offset)
1840327e51cbSPeter Avalos 			return 0;
1841327e51cbSPeter Avalos 		break;
1842327e51cbSPeter Avalos 
184379343712SPeter Avalos 	case FILE_INDIRECT:
184482c5fa3eSPeter Avalos 		if (m->str_flags & INDIRECT_RELATIVE)
1845c30bd091SSascha Wildner 			offset += CAST(uint32_t, o);
1846e8af9738SPeter Avalos 		if (offset == 0)
1847e8af9738SPeter Avalos 			return 0;
184882c5fa3eSPeter Avalos 
184979343712SPeter Avalos 		if (nbytes < offset)
185079343712SPeter Avalos 			return 0;
185182c5fa3eSPeter Avalos 
185282c5fa3eSPeter Avalos 		if ((pb = file_push_buffer(ms)) == NULL)
185382c5fa3eSPeter Avalos 			return -1;
185482c5fa3eSPeter Avalos 
1855c30bd091SSascha Wildner 		(*indir_count)++;
1856e88a9a20SSascha Wildner 		bb = *b;
1857e88a9a20SSascha Wildner 		bb.fbuf = s + offset;
1858e88a9a20SSascha Wildner 		bb.flen = nbytes - offset;
1859*3b9cdfa3SAntonio Huete Jimenez 		rv = -1;
1860614728caSSascha Wildner 		for (mlp = ms->mlist[0]->next; mlp != ms->mlist[0];
1861614728caSSascha Wildner 		    mlp = mlp->next)
1862614728caSSascha Wildner 		{
1863*3b9cdfa3SAntonio Huete Jimenez 			if ((rv = match(ms, mlp->magic, mlp->magic_rxcomp,
1864*3b9cdfa3SAntonio Huete Jimenez 			    mlp->nmagic, &bb, 0, BINTEST, text, 0, indir_count,
1865*3b9cdfa3SAntonio Huete Jimenez 			    name_count, printed_something, need_separator,
1866*3b9cdfa3SAntonio Huete Jimenez 			    NULL, NULL)) != 0)
1867614728caSSascha Wildner 				break;
1868614728caSSascha Wildner 		}
186982c5fa3eSPeter Avalos 
1870e8af9738SPeter Avalos 		if ((ms->flags & MAGIC_DEBUG) != 0)
1871e8af9738SPeter Avalos 			fprintf(stderr, "indirect @offs=%u[%d]\n", offset, rv);
187282c5fa3eSPeter Avalos 
187382c5fa3eSPeter Avalos 		rbuf = file_pop_buffer(ms, pb);
187482c5fa3eSPeter Avalos 		if (rbuf == NULL && ms->event_flags & EVENT_HAD_ERR)
187582c5fa3eSPeter Avalos 			return -1;
187682c5fa3eSPeter Avalos 
1877e8af9738SPeter Avalos 		if (rv == 1) {
1878c30bd091SSascha Wildner 			if ((ms->flags & MAGIC_NODESC) == 0 &&
1879e88a9a20SSascha Wildner 			    file_printf(ms, F(ms, m->desc, "%u"), offset) == -1)
1880e88a9a20SSascha Wildner 			{
1881e8af9738SPeter Avalos 				free(rbuf);
1882e8af9738SPeter Avalos 				return -1;
1883e8af9738SPeter Avalos 			}
1884e8af9738SPeter Avalos 			if (file_printf(ms, "%s", rbuf) == -1) {
1885e8af9738SPeter Avalos 				free(rbuf);
1886e8af9738SPeter Avalos 				return -1;
1887e8af9738SPeter Avalos 			}
1888e8af9738SPeter Avalos 		}
1889e8af9738SPeter Avalos 		free(rbuf);
1890e8af9738SPeter Avalos 		return rv;
189179343712SPeter Avalos 
1892e8af9738SPeter Avalos 	case FILE_USE:
1893e8af9738SPeter Avalos 		if (nbytes < offset)
1894e8af9738SPeter Avalos 			return 0;
189582c5fa3eSPeter Avalos 		rbuf = m->value.s;
189682c5fa3eSPeter Avalos 		if (*rbuf == '^') {
189782c5fa3eSPeter Avalos 			rbuf++;
1898e8af9738SPeter Avalos 			flip = !flip;
1899e8af9738SPeter Avalos 		}
190082c5fa3eSPeter Avalos 		if (file_magicfind(ms, rbuf, &ml) == -1) {
190182c5fa3eSPeter Avalos 			file_error(ms, 0, "cannot find entry `%s'", rbuf);
1902e8af9738SPeter Avalos 			return -1;
1903e8af9738SPeter Avalos 		}
1904970935fdSSascha Wildner 		if (save_cont(ms, &c) == -1) {
1905970935fdSSascha Wildner 			file_error(ms, errno, "can't allocate continuation");
1906970935fdSSascha Wildner 			return -1;
1907970935fdSSascha Wildner 		}
1908970935fdSSascha Wildner 
1909e8af9738SPeter Avalos 		oneed_separator = *need_separator;
1910e8af9738SPeter Avalos 		if (m->flag & NOSPACE)
1911e8af9738SPeter Avalos 			*need_separator = 0;
1912970935fdSSascha Wildner 
1913970935fdSSascha Wildner 		nfound_match = 0;
1914970935fdSSascha Wildner 		(*name_count)++;
1915970935fdSSascha Wildner 		eoffset = ms->eoffset;
1916*3b9cdfa3SAntonio Huete Jimenez 		rv = match(ms, ml.magic, ml.magic_rxcomp, ml.nmagic, b,
1917*3b9cdfa3SAntonio Huete Jimenez 		    offset + o, mode, text, flip, indir_count, name_count,
1918970935fdSSascha Wildner 		    printed_something, need_separator, returnval,
1919970935fdSSascha Wildner 		    &nfound_match);
1920970935fdSSascha Wildner 		ms->ms_value.q = nfound_match;
1921e88a9a20SSascha Wildner 		(*name_count)--;
1922970935fdSSascha Wildner 		*found_match |= nfound_match;
1923970935fdSSascha Wildner 
1924970935fdSSascha Wildner 		restore_cont(ms, &c);
1925970935fdSSascha Wildner 
1926e8af9738SPeter Avalos 		if (rv != 1)
1927e8af9738SPeter Avalos 		    *need_separator = oneed_separator;
1928970935fdSSascha Wildner 		ms->offset = offset;
1929970935fdSSascha Wildner 		ms->eoffset = eoffset;
1930e88a9a20SSascha Wildner 		return rv;
1931e8af9738SPeter Avalos 
1932e8af9738SPeter Avalos 	case FILE_NAME:
1933c30bd091SSascha Wildner 		if (ms->flags & MAGIC_NODESC)
1934c30bd091SSascha Wildner 			return 1;
1935e8af9738SPeter Avalos 		if (file_printf(ms, "%s", m->desc) == -1)
1936e8af9738SPeter Avalos 			return -1;
1937e8af9738SPeter Avalos 		return 1;
1938c30bd091SSascha Wildner 	case FILE_DER:
1939327e51cbSPeter Avalos 	case FILE_DEFAULT:	/* nothing to check */
1940e8af9738SPeter Avalos 	case FILE_CLEAR:
1941327e51cbSPeter Avalos 	default:
1942327e51cbSPeter Avalos 		break;
1943327e51cbSPeter Avalos 	}
1944e8af9738SPeter Avalos 	if (!mconvert(ms, m, flip))
1945327e51cbSPeter Avalos 		return 0;
1946327e51cbSPeter Avalos 	return 1;
1947327e51cbSPeter Avalos }
1948327e51cbSPeter Avalos 
1949327e51cbSPeter Avalos private uint64_t
file_strncmp(const char * s1,const char * s2,size_t len,size_t maxlen,uint32_t flags)1950c990e5baSDaniel Fojt file_strncmp(const char *s1, const char *s2, size_t len, size_t maxlen,
1951c990e5baSDaniel Fojt     uint32_t flags)
1952327e51cbSPeter Avalos {
1953327e51cbSPeter Avalos 	/*
1954327e51cbSPeter Avalos 	 * Convert the source args to unsigned here so that (1) the
1955327e51cbSPeter Avalos 	 * compare will be unsigned as it is in strncmp() and (2) so
1956327e51cbSPeter Avalos 	 * the ctype functions will work correctly without extra
1957327e51cbSPeter Avalos 	 * casting.
1958327e51cbSPeter Avalos 	 */
1959e88a9a20SSascha Wildner 	const unsigned char *a = RCAST(const unsigned char *, s1);
1960e88a9a20SSascha Wildner 	const unsigned char *b = RCAST(const unsigned char *, s2);
1961c990e5baSDaniel Fojt 	uint32_t ws = flags & (STRING_COMPACT_WHITESPACE |
1962c990e5baSDaniel Fojt 	    STRING_COMPACT_OPTIONAL_WHITESPACE);
1963c990e5baSDaniel Fojt 	const unsigned char *eb = b + (ws ? maxlen : len);
1964327e51cbSPeter Avalos 	uint64_t v;
1965327e51cbSPeter Avalos 
1966327e51cbSPeter Avalos 	/*
196779343712SPeter Avalos 	 * What we want here is v = strncmp(s1, s2, len),
196879343712SPeter Avalos 	 * but ignoring any nulls.
1969327e51cbSPeter Avalos 	 */
1970327e51cbSPeter Avalos 	v = 0;
1971614728caSSascha Wildner 	len++;
1972327e51cbSPeter Avalos 	if (0L == flags) { /* normal string: do it fast */
1973614728caSSascha Wildner 		while (--len > 0)
1974327e51cbSPeter Avalos 			if ((v = *b++ - *a++) != '\0')
1975327e51cbSPeter Avalos 				break;
1976327e51cbSPeter Avalos 	}
1977327e51cbSPeter Avalos 	else { /* combine the others */
1978614728caSSascha Wildner 		while (--len > 0) {
1979c30bd091SSascha Wildner 			if (b >= eb) {
1980c30bd091SSascha Wildner 				v = 1;
1981c30bd091SSascha Wildner 				break;
1982c30bd091SSascha Wildner 			}
1983327e51cbSPeter Avalos 			if ((flags & STRING_IGNORE_LOWERCASE) &&
1984327e51cbSPeter Avalos 			    islower(*a)) {
1985327e51cbSPeter Avalos 				if ((v = tolower(*b++) - *a++) != '\0')
1986327e51cbSPeter Avalos 					break;
1987327e51cbSPeter Avalos 			}
1988327e51cbSPeter Avalos 			else if ((flags & STRING_IGNORE_UPPERCASE) &&
1989327e51cbSPeter Avalos 			    isupper(*a)) {
1990327e51cbSPeter Avalos 				if ((v = toupper(*b++) - *a++) != '\0')
1991327e51cbSPeter Avalos 					break;
1992327e51cbSPeter Avalos 			}
1993f72f8299SJan Lentfer 			else if ((flags & STRING_COMPACT_WHITESPACE) &&
1994327e51cbSPeter Avalos 			    isspace(*a)) {
1995327e51cbSPeter Avalos 				a++;
1996614728caSSascha Wildner 				if (isspace(*b)) {
1997614728caSSascha Wildner 					b++;
1998e4d4ce0cSPeter Avalos 					if (!isspace(*a))
1999c30bd091SSascha Wildner 						while (b < eb && isspace(*b))
2000327e51cbSPeter Avalos 							b++;
2001327e51cbSPeter Avalos 				}
2002327e51cbSPeter Avalos 				else {
2003327e51cbSPeter Avalos 					v = 1;
2004327e51cbSPeter Avalos 					break;
2005327e51cbSPeter Avalos 				}
2006327e51cbSPeter Avalos 			}
2007f72f8299SJan Lentfer 			else if ((flags & STRING_COMPACT_OPTIONAL_WHITESPACE) &&
2008327e51cbSPeter Avalos 			    isspace(*a)) {
2009327e51cbSPeter Avalos 				a++;
2010c30bd091SSascha Wildner 				while (b < eb && isspace(*b))
2011327e51cbSPeter Avalos 					b++;
2012327e51cbSPeter Avalos 			}
2013327e51cbSPeter Avalos 			else {
2014327e51cbSPeter Avalos 				if ((v = *b++ - *a++) != '\0')
2015327e51cbSPeter Avalos 					break;
2016327e51cbSPeter Avalos 			}
2017327e51cbSPeter Avalos 		}
2018614728caSSascha Wildner 		if (len == 0 && v == 0 && (flags & STRING_FULL_WORD)) {
2019614728caSSascha Wildner 			if (*b && !isspace(*b))
2020614728caSSascha Wildner 				v = 1;
2021614728caSSascha Wildner 		}
2022327e51cbSPeter Avalos 	}
2023327e51cbSPeter Avalos 	return v;
2024327e51cbSPeter Avalos }
2025327e51cbSPeter Avalos 
2026327e51cbSPeter Avalos private uint64_t
file_strncmp16(const char * a,const char * b,size_t len,size_t maxlen,uint32_t flags)2027c990e5baSDaniel Fojt file_strncmp16(const char *a, const char *b, size_t len, size_t maxlen,
2028c990e5baSDaniel Fojt     uint32_t flags)
2029327e51cbSPeter Avalos {
2030327e51cbSPeter Avalos 	/*
2031327e51cbSPeter Avalos 	 * XXX - The 16-bit string compare probably needs to be done
2032327e51cbSPeter Avalos 	 * differently, especially if the flags are to be supported.
2033327e51cbSPeter Avalos 	 * At the moment, I am unsure.
2034327e51cbSPeter Avalos 	 */
2035327e51cbSPeter Avalos 	flags = 0;
2036c990e5baSDaniel Fojt 	return file_strncmp(a, b, len, maxlen, flags);
2037327e51cbSPeter Avalos }
2038327e51cbSPeter Avalos 
2039*3b9cdfa3SAntonio Huete Jimenez private file_regex_t *
alloc_regex(struct magic_set * ms,struct magic * m)2040*3b9cdfa3SAntonio Huete Jimenez alloc_regex(struct magic_set *ms, struct magic *m)
2041*3b9cdfa3SAntonio Huete Jimenez {
2042*3b9cdfa3SAntonio Huete Jimenez 	int rc;
2043*3b9cdfa3SAntonio Huete Jimenez 	file_regex_t *rx = CAST(file_regex_t *, malloc(sizeof(*rx)));
2044*3b9cdfa3SAntonio Huete Jimenez 
2045*3b9cdfa3SAntonio Huete Jimenez 	if (rx == NULL) {
2046*3b9cdfa3SAntonio Huete Jimenez 		file_error(ms, errno, "can't allocate %" SIZE_T_FORMAT
2047*3b9cdfa3SAntonio Huete Jimenez 		    "u bytes", sizeof(*rx));
2048*3b9cdfa3SAntonio Huete Jimenez 		return NULL;
2049*3b9cdfa3SAntonio Huete Jimenez 	}
2050*3b9cdfa3SAntonio Huete Jimenez 
2051*3b9cdfa3SAntonio Huete Jimenez 	rc = file_regcomp(ms, rx, m->value.s, REG_EXTENDED | REG_NEWLINE |
2052*3b9cdfa3SAntonio Huete Jimenez 	    ((m->str_flags & STRING_IGNORE_CASE) ? REG_ICASE : 0));
2053*3b9cdfa3SAntonio Huete Jimenez 	if (rc == 0)
2054*3b9cdfa3SAntonio Huete Jimenez 		return rx;
2055*3b9cdfa3SAntonio Huete Jimenez 
2056*3b9cdfa3SAntonio Huete Jimenez 	free(rx);
2057*3b9cdfa3SAntonio Huete Jimenez 	return NULL;
2058*3b9cdfa3SAntonio Huete Jimenez }
2059*3b9cdfa3SAntonio Huete Jimenez 
2060327e51cbSPeter Avalos private int
magiccheck(struct magic_set * ms,struct magic * m,file_regex_t ** m_cache)2061*3b9cdfa3SAntonio Huete Jimenez magiccheck(struct magic_set *ms, struct magic *m, file_regex_t **m_cache)
2062327e51cbSPeter Avalos {
2063327e51cbSPeter Avalos 	uint64_t l = m->value.q;
2064327e51cbSPeter Avalos 	uint64_t v;
2065327e51cbSPeter Avalos 	float fl, fv;
2066327e51cbSPeter Avalos 	double dl, dv;
2067327e51cbSPeter Avalos 	int matched;
2068327e51cbSPeter Avalos 	union VALUETYPE *p = &ms->ms_value;
2069327e51cbSPeter Avalos 
2070327e51cbSPeter Avalos 	switch (m->type) {
2071327e51cbSPeter Avalos 	case FILE_BYTE:
2072327e51cbSPeter Avalos 		v = p->b;
2073327e51cbSPeter Avalos 		break;
2074327e51cbSPeter Avalos 
2075327e51cbSPeter Avalos 	case FILE_SHORT:
2076327e51cbSPeter Avalos 	case FILE_BESHORT:
2077327e51cbSPeter Avalos 	case FILE_LESHORT:
2078*3b9cdfa3SAntonio Huete Jimenez 	case FILE_MSDOSDATE:
2079*3b9cdfa3SAntonio Huete Jimenez 	case FILE_LEMSDOSDATE:
2080*3b9cdfa3SAntonio Huete Jimenez 	case FILE_BEMSDOSDATE:
2081*3b9cdfa3SAntonio Huete Jimenez 	case FILE_MSDOSTIME:
2082*3b9cdfa3SAntonio Huete Jimenez 	case FILE_LEMSDOSTIME:
2083*3b9cdfa3SAntonio Huete Jimenez 	case FILE_BEMSDOSTIME:
2084327e51cbSPeter Avalos 		v = p->h;
2085327e51cbSPeter Avalos 		break;
2086327e51cbSPeter Avalos 
2087327e51cbSPeter Avalos 	case FILE_LONG:
2088327e51cbSPeter Avalos 	case FILE_BELONG:
2089327e51cbSPeter Avalos 	case FILE_LELONG:
2090327e51cbSPeter Avalos 	case FILE_MELONG:
2091327e51cbSPeter Avalos 	case FILE_DATE:
2092327e51cbSPeter Avalos 	case FILE_BEDATE:
2093327e51cbSPeter Avalos 	case FILE_LEDATE:
2094327e51cbSPeter Avalos 	case FILE_MEDATE:
2095327e51cbSPeter Avalos 	case FILE_LDATE:
2096327e51cbSPeter Avalos 	case FILE_BELDATE:
2097327e51cbSPeter Avalos 	case FILE_LELDATE:
2098327e51cbSPeter Avalos 	case FILE_MELDATE:
2099327e51cbSPeter Avalos 		v = p->l;
2100327e51cbSPeter Avalos 		break;
2101327e51cbSPeter Avalos 
2102327e51cbSPeter Avalos 	case FILE_QUAD:
2103327e51cbSPeter Avalos 	case FILE_LEQUAD:
2104327e51cbSPeter Avalos 	case FILE_BEQUAD:
2105327e51cbSPeter Avalos 	case FILE_QDATE:
2106327e51cbSPeter Avalos 	case FILE_BEQDATE:
2107327e51cbSPeter Avalos 	case FILE_LEQDATE:
2108327e51cbSPeter Avalos 	case FILE_QLDATE:
2109327e51cbSPeter Avalos 	case FILE_BEQLDATE:
2110327e51cbSPeter Avalos 	case FILE_LEQLDATE:
2111e8af9738SPeter Avalos 	case FILE_QWDATE:
2112e8af9738SPeter Avalos 	case FILE_BEQWDATE:
2113e8af9738SPeter Avalos 	case FILE_LEQWDATE:
2114c990e5baSDaniel Fojt 	case FILE_OFFSET:
2115327e51cbSPeter Avalos 		v = p->q;
2116327e51cbSPeter Avalos 		break;
2117327e51cbSPeter Avalos 
2118327e51cbSPeter Avalos 	case FILE_FLOAT:
2119327e51cbSPeter Avalos 	case FILE_BEFLOAT:
2120327e51cbSPeter Avalos 	case FILE_LEFLOAT:
2121327e51cbSPeter Avalos 		fl = m->value.f;
2122327e51cbSPeter Avalos 		fv = p->f;
2123327e51cbSPeter Avalos 		switch (m->reln) {
2124327e51cbSPeter Avalos 		case 'x':
2125327e51cbSPeter Avalos 			matched = 1;
2126327e51cbSPeter Avalos 			break;
2127327e51cbSPeter Avalos 
2128327e51cbSPeter Avalos 		case '!':
2129327e51cbSPeter Avalos 			matched = fv != fl;
2130327e51cbSPeter Avalos 			break;
2131327e51cbSPeter Avalos 
2132327e51cbSPeter Avalos 		case '=':
2133327e51cbSPeter Avalos 			matched = fv == fl;
2134327e51cbSPeter Avalos 			break;
2135327e51cbSPeter Avalos 
2136327e51cbSPeter Avalos 		case '>':
2137327e51cbSPeter Avalos 			matched = fv > fl;
2138327e51cbSPeter Avalos 			break;
2139327e51cbSPeter Avalos 
2140327e51cbSPeter Avalos 		case '<':
2141327e51cbSPeter Avalos 			matched = fv < fl;
2142327e51cbSPeter Avalos 			break;
2143327e51cbSPeter Avalos 
2144327e51cbSPeter Avalos 		default:
2145*3b9cdfa3SAntonio Huete Jimenez 			file_magerror(ms, "cannot happen with float: "
2146*3b9cdfa3SAntonio Huete Jimenez 			    "invalid relation `%c'", m->reln);
2147327e51cbSPeter Avalos 			return -1;
2148327e51cbSPeter Avalos 		}
2149327e51cbSPeter Avalos 		return matched;
2150327e51cbSPeter Avalos 
2151327e51cbSPeter Avalos 	case FILE_DOUBLE:
2152327e51cbSPeter Avalos 	case FILE_BEDOUBLE:
2153327e51cbSPeter Avalos 	case FILE_LEDOUBLE:
2154327e51cbSPeter Avalos 		dl = m->value.d;
2155327e51cbSPeter Avalos 		dv = p->d;
2156327e51cbSPeter Avalos 		switch (m->reln) {
2157327e51cbSPeter Avalos 		case 'x':
2158327e51cbSPeter Avalos 			matched = 1;
2159327e51cbSPeter Avalos 			break;
2160327e51cbSPeter Avalos 
2161327e51cbSPeter Avalos 		case '!':
2162327e51cbSPeter Avalos 			matched = dv != dl;
2163327e51cbSPeter Avalos 			break;
2164327e51cbSPeter Avalos 
2165327e51cbSPeter Avalos 		case '=':
2166327e51cbSPeter Avalos 			matched = dv == dl;
2167327e51cbSPeter Avalos 			break;
2168327e51cbSPeter Avalos 
2169327e51cbSPeter Avalos 		case '>':
2170327e51cbSPeter Avalos 			matched = dv > dl;
2171327e51cbSPeter Avalos 			break;
2172327e51cbSPeter Avalos 
2173327e51cbSPeter Avalos 		case '<':
2174327e51cbSPeter Avalos 			matched = dv < dl;
2175327e51cbSPeter Avalos 			break;
2176327e51cbSPeter Avalos 
2177327e51cbSPeter Avalos 		default:
2178*3b9cdfa3SAntonio Huete Jimenez 			file_magerror(ms, "cannot happen with double: "
2179*3b9cdfa3SAntonio Huete Jimenez 			    "invalid relation `%c'", m->reln);
2180327e51cbSPeter Avalos 			return -1;
2181327e51cbSPeter Avalos 		}
2182327e51cbSPeter Avalos 		return matched;
2183327e51cbSPeter Avalos 
2184327e51cbSPeter Avalos 	case FILE_DEFAULT:
2185e8af9738SPeter Avalos 	case FILE_CLEAR:
2186327e51cbSPeter Avalos 		l = 0;
2187327e51cbSPeter Avalos 		v = 0;
2188327e51cbSPeter Avalos 		break;
2189327e51cbSPeter Avalos 
2190327e51cbSPeter Avalos 	case FILE_STRING:
2191327e51cbSPeter Avalos 	case FILE_PSTRING:
2192*3b9cdfa3SAntonio Huete Jimenez 	case FILE_OCTAL:
2193327e51cbSPeter Avalos 		l = 0;
2194e88a9a20SSascha Wildner 		v = file_strncmp(m->value.s, p->s, CAST(size_t, m->vallen),
2195c990e5baSDaniel Fojt 		    sizeof(p->s), m->str_flags);
2196327e51cbSPeter Avalos 		break;
2197327e51cbSPeter Avalos 
2198327e51cbSPeter Avalos 	case FILE_BESTRING16:
2199327e51cbSPeter Avalos 	case FILE_LESTRING16:
2200327e51cbSPeter Avalos 		l = 0;
2201e88a9a20SSascha Wildner 		v = file_strncmp16(m->value.s, p->s, CAST(size_t, m->vallen),
2202c990e5baSDaniel Fojt 		    sizeof(p->s), m->str_flags);
2203327e51cbSPeter Avalos 		break;
2204327e51cbSPeter Avalos 
2205327e51cbSPeter Avalos 	case FILE_SEARCH: { /* search ms->search.s for the string m->value.s */
2206327e51cbSPeter Avalos 		size_t slen;
2207327e51cbSPeter Avalos 		size_t idx;
2208327e51cbSPeter Avalos 
2209327e51cbSPeter Avalos 		if (ms->search.s == NULL)
2210327e51cbSPeter Avalos 			return 0;
2211327e51cbSPeter Avalos 
2212327e51cbSPeter Avalos 		slen = MIN(m->vallen, sizeof(m->value.s));
2213327e51cbSPeter Avalos 		l = 0;
2214327e51cbSPeter Avalos 		v = 0;
2215e88a9a20SSascha Wildner #ifdef HAVE_MEMMEM
2216e88a9a20SSascha Wildner 		if (slen > 0 && m->str_flags == 0) {
2217e88a9a20SSascha Wildner 			const char *found;
2218e88a9a20SSascha Wildner 			idx = m->str_range + slen;
2219e88a9a20SSascha Wildner 			if (m->str_range == 0 || ms->search.s_len < idx)
2220e88a9a20SSascha Wildner 				idx = ms->search.s_len;
2221e88a9a20SSascha Wildner 			found = CAST(const char *, memmem(ms->search.s, idx,
2222e88a9a20SSascha Wildner 			    m->value.s, slen));
2223614728caSSascha Wildner 			if (!found) {
2224614728caSSascha Wildner 				v = 1;
2225614728caSSascha Wildner 				break;
2226614728caSSascha Wildner 			}
2227e88a9a20SSascha Wildner 			idx = found - ms->search.s;
2228e88a9a20SSascha Wildner 			ms->search.offset += idx;
2229e88a9a20SSascha Wildner 			ms->search.rm_len = ms->search.s_len - idx;
2230e88a9a20SSascha Wildner 			break;
2231e88a9a20SSascha Wildner 		}
2232e88a9a20SSascha Wildner #endif
2233327e51cbSPeter Avalos 
223479343712SPeter Avalos 		for (idx = 0; m->str_range == 0 || idx < m->str_range; idx++) {
2235614728caSSascha Wildner 			if (slen + idx > ms->search.s_len) {
2236614728caSSascha Wildner 				v = 1;
2237614728caSSascha Wildner 				break;
2238614728caSSascha Wildner 			}
2239327e51cbSPeter Avalos 
224082c5fa3eSPeter Avalos 			v = file_strncmp(m->value.s, ms->search.s + idx, slen,
2241c990e5baSDaniel Fojt 			    ms->search.s_len - idx, m->str_flags);
2242327e51cbSPeter Avalos 			if (v == 0) {	/* found match */
224379343712SPeter Avalos 				ms->search.offset += idx;
2244c30bd091SSascha Wildner 				ms->search.rm_len = ms->search.s_len - idx;
2245327e51cbSPeter Avalos 				break;
2246327e51cbSPeter Avalos 			}
2247327e51cbSPeter Avalos 		}
2248327e51cbSPeter Avalos 		break;
2249327e51cbSPeter Avalos 	}
2250327e51cbSPeter Avalos 	case FILE_REGEX: {
2251327e51cbSPeter Avalos 		int rc;
2252*3b9cdfa3SAntonio Huete Jimenez 		file_regex_t *rx = *m_cache;
225382c5fa3eSPeter Avalos 		const char *search;
2254*3b9cdfa3SAntonio Huete Jimenez 		regmatch_t pmatch;
2255*3b9cdfa3SAntonio Huete Jimenez 		size_t slen = ms->search.s_len;
2256*3b9cdfa3SAntonio Huete Jimenez 		char *copy;
2257327e51cbSPeter Avalos 
2258327e51cbSPeter Avalos 		if (ms->search.s == NULL)
2259327e51cbSPeter Avalos 			return 0;
2260327e51cbSPeter Avalos 
2261*3b9cdfa3SAntonio Huete Jimenez 		if (rx == NULL) {
2262*3b9cdfa3SAntonio Huete Jimenez 			rx = *m_cache = alloc_regex(ms, m);
2263*3b9cdfa3SAntonio Huete Jimenez 			if (rx == NULL)
2264*3b9cdfa3SAntonio Huete Jimenez 				return -1;
2265*3b9cdfa3SAntonio Huete Jimenez 		}
2266327e51cbSPeter Avalos 		l = 0;
226782c5fa3eSPeter Avalos 		if (slen != 0) {
2268c30bd091SSascha Wildner 		    copy = CAST(char *, malloc(slen));
226982c5fa3eSPeter Avalos 		    if (copy == NULL)  {
227082c5fa3eSPeter Avalos 			file_error(ms, errno,
227182c5fa3eSPeter Avalos 			    "can't allocate %" SIZE_T_FORMAT "u bytes",
227282c5fa3eSPeter Avalos 			    slen);
227382c5fa3eSPeter Avalos 			return -1;
227482c5fa3eSPeter Avalos 		    }
227582c5fa3eSPeter Avalos 		    memcpy(copy, ms->search.s, slen);
227682c5fa3eSPeter Avalos 		    copy[--slen] = '\0';
227782c5fa3eSPeter Avalos 		    search = copy;
227882c5fa3eSPeter Avalos 		} else {
2279c30bd091SSascha Wildner 		    search = CCAST(char *, "");
228082c5fa3eSPeter Avalos 		    copy = NULL;
228182c5fa3eSPeter Avalos 		}
2282*3b9cdfa3SAntonio Huete Jimenez 		rc = file_regexec(ms, rx, RCAST(const char *, search),
2283c30bd091SSascha Wildner 		    1, &pmatch, 0);
228482c5fa3eSPeter Avalos 		free(copy);
2285327e51cbSPeter Avalos 		switch (rc) {
2286327e51cbSPeter Avalos 		case 0:
2287e88a9a20SSascha Wildner 			ms->search.s += CAST(int, pmatch.rm_so);
2288e88a9a20SSascha Wildner 			ms->search.offset += CAST(size_t, pmatch.rm_so);
2289e88a9a20SSascha Wildner 			ms->search.rm_len = CAST(size_t,
2290e88a9a20SSascha Wildner 			    pmatch.rm_eo - pmatch.rm_so);
2291327e51cbSPeter Avalos 			v = 0;
2292327e51cbSPeter Avalos 			break;
2293327e51cbSPeter Avalos 
2294327e51cbSPeter Avalos 		case REG_NOMATCH:
2295327e51cbSPeter Avalos 			v = 1;
2296327e51cbSPeter Avalos 			break;
2297327e51cbSPeter Avalos 
2298327e51cbSPeter Avalos 		default:
2299327e51cbSPeter Avalos 			return -1;
2300*3b9cdfa3SAntonio Huete Jimenez 		}
2301327e51cbSPeter Avalos 		break;
2302327e51cbSPeter Avalos 	}
2303e8af9738SPeter Avalos 	case FILE_USE:
2304970935fdSSascha Wildner 		return ms->ms_value.q != 0;
2305e8af9738SPeter Avalos 	case FILE_NAME:
2306970935fdSSascha Wildner 	case FILE_INDIRECT:
230779343712SPeter Avalos 		return 1;
2308c30bd091SSascha Wildner 	case FILE_DER:
2309c30bd091SSascha Wildner 		matched = der_cmp(ms, m);
2310c30bd091SSascha Wildner 		if (matched == -1) {
2311c30bd091SSascha Wildner 			if ((ms->flags & MAGIC_DEBUG) != 0) {
2312c30bd091SSascha Wildner 				(void) fprintf(stderr,
2313*3b9cdfa3SAntonio Huete Jimenez 				    "EOF comparing DER entries\n");
2314c30bd091SSascha Wildner 			}
2315c30bd091SSascha Wildner 			return 0;
2316c30bd091SSascha Wildner 		}
2317c30bd091SSascha Wildner 		return matched;
2318c990e5baSDaniel Fojt 	case FILE_GUID:
2319c990e5baSDaniel Fojt 		l = 0;
2320c990e5baSDaniel Fojt 		v = memcmp(m->value.guid, p->guid, sizeof(p->guid));
2321c990e5baSDaniel Fojt 		break;
2322327e51cbSPeter Avalos 	default:
2323327e51cbSPeter Avalos 		file_magerror(ms, "invalid type %d in magiccheck()", m->type);
2324327e51cbSPeter Avalos 		return -1;
2325327e51cbSPeter Avalos 	}
2326327e51cbSPeter Avalos 
2327327e51cbSPeter Avalos 	v = file_signextend(ms, m, v);
2328327e51cbSPeter Avalos 
2329327e51cbSPeter Avalos 	switch (m->reln) {
2330327e51cbSPeter Avalos 	case 'x':
2331327e51cbSPeter Avalos 		if ((ms->flags & MAGIC_DEBUG) != 0)
2332e4d4ce0cSPeter Avalos 			(void) fprintf(stderr, "%" INT64_T_FORMAT
2333e88a9a20SSascha Wildner 			    "u == *any* = 1\n", CAST(unsigned long long, v));
2334327e51cbSPeter Avalos 		matched = 1;
2335327e51cbSPeter Avalos 		break;
2336327e51cbSPeter Avalos 
2337327e51cbSPeter Avalos 	case '!':
2338327e51cbSPeter Avalos 		matched = v != l;
2339327e51cbSPeter Avalos 		if ((ms->flags & MAGIC_DEBUG) != 0)
2340e4d4ce0cSPeter Avalos 			(void) fprintf(stderr, "%" INT64_T_FORMAT "u != %"
2341e88a9a20SSascha Wildner 			    INT64_T_FORMAT "u = %d\n",
2342e88a9a20SSascha Wildner 			    CAST(unsigned long long, v),
2343e88a9a20SSascha Wildner 			    CAST(unsigned long long, l), matched);
2344327e51cbSPeter Avalos 		break;
2345327e51cbSPeter Avalos 
2346327e51cbSPeter Avalos 	case '=':
2347327e51cbSPeter Avalos 		matched = v == l;
2348327e51cbSPeter Avalos 		if ((ms->flags & MAGIC_DEBUG) != 0)
2349e4d4ce0cSPeter Avalos 			(void) fprintf(stderr, "%" INT64_T_FORMAT "u == %"
2350e88a9a20SSascha Wildner 			    INT64_T_FORMAT "u = %d\n",
2351e88a9a20SSascha Wildner 			    CAST(unsigned long long, v),
2352e88a9a20SSascha Wildner 			    CAST(unsigned long long, l), matched);
2353327e51cbSPeter Avalos 		break;
2354327e51cbSPeter Avalos 
2355327e51cbSPeter Avalos 	case '>':
2356327e51cbSPeter Avalos 		if (m->flag & UNSIGNED) {
2357327e51cbSPeter Avalos 			matched = v > l;
2358327e51cbSPeter Avalos 			if ((ms->flags & MAGIC_DEBUG) != 0)
2359e4d4ce0cSPeter Avalos 				(void) fprintf(stderr, "%" INT64_T_FORMAT
2360e4d4ce0cSPeter Avalos 				    "u > %" INT64_T_FORMAT "u = %d\n",
2361e88a9a20SSascha Wildner 				    CAST(unsigned long long, v),
2362e88a9a20SSascha Wildner 				    CAST(unsigned long long, l), matched);
2363327e51cbSPeter Avalos 		}
2364327e51cbSPeter Avalos 		else {
2365e88a9a20SSascha Wildner 			matched = CAST(int64_t, v) > CAST(int64_t, l);
2366327e51cbSPeter Avalos 			if ((ms->flags & MAGIC_DEBUG) != 0)
2367e4d4ce0cSPeter Avalos 				(void) fprintf(stderr, "%" INT64_T_FORMAT
2368e4d4ce0cSPeter Avalos 				    "d > %" INT64_T_FORMAT "d = %d\n",
2369e88a9a20SSascha Wildner 				    CAST(long long, v),
2370e88a9a20SSascha Wildner 				    CAST(long long, l), matched);
2371327e51cbSPeter Avalos 		}
2372327e51cbSPeter Avalos 		break;
2373327e51cbSPeter Avalos 
2374327e51cbSPeter Avalos 	case '<':
2375327e51cbSPeter Avalos 		if (m->flag & UNSIGNED) {
2376327e51cbSPeter Avalos 			matched = v < l;
2377327e51cbSPeter Avalos 			if ((ms->flags & MAGIC_DEBUG) != 0)
2378e4d4ce0cSPeter Avalos 				(void) fprintf(stderr, "%" INT64_T_FORMAT
2379e4d4ce0cSPeter Avalos 				    "u < %" INT64_T_FORMAT "u = %d\n",
2380e88a9a20SSascha Wildner 				    CAST(unsigned long long, v),
2381e88a9a20SSascha Wildner 				    CAST(unsigned long long, l), matched);
2382327e51cbSPeter Avalos 		}
2383327e51cbSPeter Avalos 		else {
2384e88a9a20SSascha Wildner 			matched = CAST(int64_t, v) < CAST(int64_t, l);
2385327e51cbSPeter Avalos 			if ((ms->flags & MAGIC_DEBUG) != 0)
2386e4d4ce0cSPeter Avalos 				(void) fprintf(stderr, "%" INT64_T_FORMAT
2387e4d4ce0cSPeter Avalos 				    "d < %" INT64_T_FORMAT "d = %d\n",
2388e88a9a20SSascha Wildner 				     CAST(long long, v),
2389e88a9a20SSascha Wildner 				     CAST(long long, l), matched);
2390327e51cbSPeter Avalos 		}
2391327e51cbSPeter Avalos 		break;
2392327e51cbSPeter Avalos 
2393327e51cbSPeter Avalos 	case '&':
2394327e51cbSPeter Avalos 		matched = (v & l) == l;
2395327e51cbSPeter Avalos 		if ((ms->flags & MAGIC_DEBUG) != 0)
2396e4d4ce0cSPeter Avalos 			(void) fprintf(stderr, "((%" INT64_T_FORMAT "x & %"
2397e4d4ce0cSPeter Avalos 			    INT64_T_FORMAT "x) == %" INT64_T_FORMAT
2398e88a9a20SSascha Wildner 			    "x) = %d\n", CAST(unsigned long long, v),
2399e88a9a20SSascha Wildner 			    CAST(unsigned long long, l),
2400e88a9a20SSascha Wildner 			    CAST(unsigned long long, l),
2401e4d4ce0cSPeter Avalos 			    matched);
2402327e51cbSPeter Avalos 		break;
2403327e51cbSPeter Avalos 
2404327e51cbSPeter Avalos 	case '^':
2405327e51cbSPeter Avalos 		matched = (v & l) != l;
2406327e51cbSPeter Avalos 		if ((ms->flags & MAGIC_DEBUG) != 0)
2407e4d4ce0cSPeter Avalos 			(void) fprintf(stderr, "((%" INT64_T_FORMAT "x & %"
2408e4d4ce0cSPeter Avalos 			    INT64_T_FORMAT "x) != %" INT64_T_FORMAT
2409e88a9a20SSascha Wildner 			    "x) = %d\n", CAST(unsigned long long, v),
2410e88a9a20SSascha Wildner 			    CAST(unsigned long long, l),
2411e88a9a20SSascha Wildner 			    CAST(unsigned long long, l), matched);
2412327e51cbSPeter Avalos 		break;
2413327e51cbSPeter Avalos 
2414327e51cbSPeter Avalos 	default:
2415327e51cbSPeter Avalos 		file_magerror(ms, "cannot happen: invalid relation `%c'",
2416327e51cbSPeter Avalos 		    m->reln);
2417327e51cbSPeter Avalos 		return -1;
2418327e51cbSPeter Avalos 	}
2419327e51cbSPeter Avalos 
2420327e51cbSPeter Avalos 	return matched;
2421327e51cbSPeter Avalos }
2422327e51cbSPeter Avalos 
2423327e51cbSPeter Avalos private int
handle_annotation(struct magic_set * ms,struct magic * m,int firstline)2424c30bd091SSascha Wildner handle_annotation(struct magic_set *ms, struct magic *m, int firstline)
242579343712SPeter Avalos {
2426c30bd091SSascha Wildner 	if ((ms->flags & MAGIC_APPLE) && m->apple[0]) {
2427e88a9a20SSascha Wildner 		if (print_sep(ms, firstline) == -1)
2428c30bd091SSascha Wildner 			return -1;
242979343712SPeter Avalos 		if (file_printf(ms, "%.8s", m->apple) == -1)
243079343712SPeter Avalos 			return -1;
243179343712SPeter Avalos 		return 1;
243279343712SPeter Avalos 	}
2433c30bd091SSascha Wildner 	if ((ms->flags & MAGIC_EXTENSION) && m->ext[0]) {
2434e88a9a20SSascha Wildner 		if (print_sep(ms, firstline) == -1)
2435c30bd091SSascha Wildner 			return -1;
2436c30bd091SSascha Wildner 		if (file_printf(ms, "%s", m->ext) == -1)
2437c30bd091SSascha Wildner 			return -1;
2438c30bd091SSascha Wildner 		return 1;
2439c30bd091SSascha Wildner 	}
244079343712SPeter Avalos 	if ((ms->flags & MAGIC_MIME_TYPE) && m->mimetype[0]) {
2441e88a9a20SSascha Wildner 		char buf[1024];
2442e88a9a20SSascha Wildner 		const char *p;
2443e88a9a20SSascha Wildner 		if (print_sep(ms, firstline) == -1)
2444c30bd091SSascha Wildner 			return -1;
2445e88a9a20SSascha Wildner 		if (varexpand(ms, buf, sizeof(buf), m->mimetype) == -1)
2446e88a9a20SSascha Wildner 			p = m->mimetype;
2447e88a9a20SSascha Wildner 		else
2448e88a9a20SSascha Wildner 			p = buf;
2449e88a9a20SSascha Wildner 		if (file_printf(ms, "%s", p) == -1)
245079343712SPeter Avalos 			return -1;
245179343712SPeter Avalos 		return 1;
245279343712SPeter Avalos 	}
245379343712SPeter Avalos 	return 0;
245479343712SPeter Avalos }
245579343712SPeter Avalos 
245679343712SPeter Avalos private int
print_sep(struct magic_set * ms,int firstline)2457327e51cbSPeter Avalos print_sep(struct magic_set *ms, int firstline)
2458327e51cbSPeter Avalos {
2459327e51cbSPeter Avalos 	if (firstline)
2460327e51cbSPeter Avalos 		return 0;
2461327e51cbSPeter Avalos 	/*
2462327e51cbSPeter Avalos 	 * we found another match
2463327e51cbSPeter Avalos 	 * put a newline and '-' to do some simple formatting
2464327e51cbSPeter Avalos 	 */
2465e88a9a20SSascha Wildner 	return file_separator(ms);
2466327e51cbSPeter Avalos }
2467