2 * Copyright (c) Ian F. Darwin 1986-1995.
3 * Software written by Ian F. Darwin and others;
4 * maintained 1995-present by Christos Zoulas and others.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice immediately at the beginning of the file, without modification,
11 * this list of conditions, and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * softmagic - interpret variable magic from MAGIC
35 FILE_RCSID("@(#)$File: softmagic.c,v 1.286 2019/05/17 02:24:59 christos Exp $")
46 private int match(struct magic_set
*, struct magic
*, uint32_t,
47 const struct buffer
*, size_t, int, int, int, uint16_t *,
48 uint16_t *, int *, int *, int *, int *);
49 private int mget(struct magic_set
*, struct magic
*, const struct buffer
*,
50 const unsigned char *, size_t,
51 size_t, unsigned int, int, int, int, uint16_t *,
52 uint16_t *, int *, int *, int *, int *);
53 private int msetoffset(struct magic_set
*, struct magic
*, struct buffer
*,
54 const struct buffer
*, size_t, unsigned int);
55 private int magiccheck(struct magic_set
*, struct magic
*);
56 private int32_t mprint(struct magic_set
*, struct magic
*);
57 private int moffset(struct magic_set
*, struct magic
*, const struct buffer
*,
59 private void mdebug(uint32_t, const char *, size_t);
60 private int mcopy(struct magic_set
*, union VALUETYPE
*, int, int,
61 const unsigned char *, uint32_t, size_t, struct magic
*);
62 private int mconvert(struct magic_set
*, struct magic
*, int);
63 private int print_sep(struct magic_set
*, int);
64 private int handle_annotation(struct magic_set
*, struct magic
*, int);
65 private int cvt_8(union VALUETYPE
*, const struct magic
*);
66 private int cvt_16(union VALUETYPE
*, const struct magic
*);
67 private int cvt_32(union VALUETYPE
*, const struct magic
*);
68 private int cvt_64(union VALUETYPE
*, const struct magic
*);
70 #define OFFSET_OOB(n, o, i) ((n) < CAST(uint32_t, (o)) || (i) > ((n) - (o)))
72 (CAST(uint64_t, (p)->hq[0])<<56)| \
73 (CAST(uint64_t, (p)->hq[1])<<48)| \
74 (CAST(uint64_t, (p)->hq[2])<<40)| \
75 (CAST(uint64_t, (p)->hq[3])<<32)| \
76 (CAST(uint64_t, (p)->hq[4])<<24)| \
77 (CAST(uint64_t, (p)->hq[5])<<16)| \
78 (CAST(uint64_t, (p)->hq[6])<<8)| \
79 (CAST(uint64_t, (p)->hq[7])))
81 (CAST(uint64_t, (p)->hq[7])<<56)| \
82 (CAST(uint64_t, (p)->hq[6])<<48)| \
83 (CAST(uint64_t, (p)->hq[5])<<40)| \
84 (CAST(uint64_t, (p)->hq[4])<<32)| \
85 (CAST(uint64_t, (p)->hq[3])<<24)| \
86 (CAST(uint64_t, (p)->hq[2])<<16)| \
87 (CAST(uint64_t, (p)->hq[1])<<8)| \
88 (CAST(uint64_t, (p)->hq[0])))
90 (CAST(uint32_t, (p)->hl[3])<<24)| \
91 (CAST(uint32_t, (p)->hl[2])<<16)| \
92 (CAST(uint32_t, (p)->hl[1])<<8)| \
93 (CAST(uint32_t, (p)->hl[0])))
95 (CAST(uint32_t, (p)->hl[0])<<24)| \
96 (CAST(uint32_t, (p)->hl[1])<<16)| \
97 (CAST(uint32_t, (p)->hl[2])<<8)| \
98 (CAST(uint32_t, (p)->hl[3])))
100 (CAST(uint32_t, (p)->hl[1])<<24)| \
101 (CAST(uint32_t, (p)->hl[0])<<16)| \
102 (CAST(uint32_t, (p)->hl[3])<<8)| \
103 (CAST(uint32_t, (p)->hl[2])))
105 #define BE16(p) ((CAST(uint16_t, (p)->hs[0])<<8)|(CAST(uint16_t, (p)->hs[1])))
106 #define LE16(p) ((CAST(uint16_t, (p)->hs[1])<<8)|(CAST(uint16_t, (p)->hs[0])))
107 #define SEXT(s,v,p) ((s) ? \
108 CAST(intmax_t, CAST(int##v##_t, p)) : \
109 CAST(intmax_t, CAST(uint##v##_t, p)))
112 * softmagic - lookup one file in parsed, in-memory copy of database
113 * Passed the name and FILE * of one file to be typed.
115 /*ARGSUSED1*/ /* nbytes passed for regularity, maybe need later */
117 file_softmagic(struct magic_set
*ms
, const struct buffer
*b
,
118 uint16_t *indir_count
, uint16_t *name_count
, int mode
, int text
)
121 int rv
, printed_something
= 0, need_separator
= 0;
124 if (name_count
== NULL
) {
128 if (indir_count
== NULL
) {
133 for (ml
= ms
->mlist
[0]->next
; ml
!= ms
->mlist
[0]; ml
= ml
->next
)
134 if ((rv
= match(ms
, ml
->magic
, ml
->nmagic
, b
, 0, mode
,
135 text
, 0, indir_count
, name_count
,
136 &printed_something
, &need_separator
, NULL
, NULL
)) != 0)
142 #define FILE_FMTDEBUG
144 #define F(a, b, c) file_fmtcheck((a), (b), (c), __FILE__, __LINE__)
146 private const char * __attribute__((__format_arg__(3)))
147 file_fmtcheck(struct magic_set
*ms
, const char *desc
, const char *def
,
148 const char *file
, size_t line
)
152 if (strchr(desc
, '%') == NULL
)
155 ptr
= fmtcheck(desc
, def
);
158 "%s, %" SIZE_T_FORMAT
"u: format `%s' does not match"
159 " with `%s'", file
, line
, desc
, def
);
163 #define F(a, b, c) fmtcheck((b), (c))
167 * Go through the whole list, stopping if you find a match. Process all
168 * the continuations of that match before returning.
170 * We support multi-level continuations:
172 * At any time when processing a successful top-level match, there is a
173 * current continuation level; it represents the level of the last
174 * successfully matched continuation.
176 * Continuations above that level are skipped as, if we see one, it
177 * means that the continuation that controls them - i.e, the
178 * lower-level continuation preceding them - failed to match.
180 * Continuations below that level are processed as, if we see one,
181 * it means we've finished processing or skipping higher-level
182 * continuations under the control of a successful or unsuccessful
183 * lower-level continuation, and are now seeing the next lower-level
184 * continuation and should process it. The current continuation
185 * level reverts to the level of the one we're seeing.
187 * Continuations at the current level are processed as, if we see
188 * one, there's no lower-level continuation that may have failed.
190 * If a continuation matches, we bump the current continuation level
191 * so that higher-level continuations are processed.
194 match(struct magic_set
*ms
, struct magic
*magic
, uint32_t nmagic
,
195 const struct buffer
*b
, size_t offset
, int mode
, int text
,
196 int flip
, uint16_t *indir_count
, uint16_t *name_count
,
197 int *printed_something
, int *need_separator
, int *returnval
,
200 uint32_t magindex
= 0;
201 unsigned int cont_level
= 0;
202 int found_matchv
= 0; /* if a match is found it is set to 1*/
203 int returnvalv
= 0, e
;
204 int firstline
= 1; /* a flag to print X\n X\n- X */
206 int print
= (ms
->flags
& MAGIC_NODESC
) == 0;
209 * returnval can be 0 if a match is found, but there was no
210 * annotation to be printed.
212 if (returnval
== NULL
)
213 returnval
= &returnvalv
;
214 if (found_match
== NULL
)
215 found_match
= &found_matchv
;
217 if (file_check_mem(ms
, cont_level
) == -1)
220 for (magindex
= 0; magindex
< nmagic
; magindex
++) {
222 struct magic
*m
= &magic
[magindex
];
224 if (m
->type
!= FILE_NAME
)
225 if ((IS_STRING(m
->type
) &&
226 #define FLT (STRING_BINTEST | STRING_TEXTTEST)
227 ((text
&& (m
->str_flags
& FLT
) == STRING_BINTEST
) ||
228 (!text
&& (m
->str_flags
& FLT
) == STRING_TEXTTEST
))) ||
229 (m
->flag
& mode
) != mode
) {
232 while (magindex
< nmagic
- 1 &&
233 magic
[magindex
+ 1].cont_level
!= 0)
236 continue; /* Skip to next top-level test*/
239 if (msetoffset(ms
, m
, &bb
, b
, offset
, cont_level
) == -1)
241 ms
->line
= m
->lineno
;
243 /* if main entry matches, print it... */
244 switch (mget(ms
, m
, b
, CAST(const unsigned char *, bb
.fbuf
),
245 bb
.flen
, offset
, cont_level
,
246 mode
, text
, flip
, indir_count
, name_count
,
247 printed_something
, need_separator
, returnval
, found_match
))
252 flush
= m
->reln
!= '!';
255 if (m
->type
== FILE_INDIRECT
) {
260 switch (magiccheck(ms
, m
)) {
274 * main entry didn't match,
275 * flush its continuations
283 if ((e
= handle_annotation(ms
, m
, firstline
)) != 0)
286 *printed_something
= 1;
292 * If we are going to print something, we'll need to print
293 * a blank before we print something else.
295 if (print
&& *m
->desc
) {
297 *printed_something
= 1;
299 if (print_sep(ms
, firstline
) == -1)
301 if (mprint(ms
, m
) == -1)
305 switch (moffset(ms
, m
, &bb
, &ms
->c
.li
[cont_level
].off
)) {
313 /* and any continuations that match */
314 if (file_check_mem(ms
, ++cont_level
) == -1)
317 while (magindex
+ 1 < nmagic
&&
318 magic
[magindex
+ 1].cont_level
!= 0) {
319 m
= &magic
[++magindex
];
320 ms
->line
= m
->lineno
; /* for messages */
322 if (cont_level
< m
->cont_level
)
324 if (cont_level
> m
->cont_level
) {
326 * We're at the end of the level
327 * "cont_level" continuations.
329 cont_level
= m
->cont_level
;
331 if (msetoffset(ms
, m
, &bb
, b
, offset
, cont_level
) == -1)
333 if (m
->flag
& OFFADD
) {
335 ms
->c
.li
[cont_level
- 1].off
;
338 #ifdef ENABLE_CONDITIONALS
339 if (m
->cond
== COND_ELSE
||
340 m
->cond
== COND_ELIF
) {
341 if (ms
->c
.li
[cont_level
].last_match
== 1)
345 switch (mget(ms
, m
, b
, CAST(const unsigned char *,
346 bb
.fbuf
), bb
.flen
, offset
,
347 cont_level
, mode
, text
, flip
, indir_count
,
348 name_count
, printed_something
, need_separator
,
349 returnval
, found_match
)) {
358 if (m
->type
== FILE_INDIRECT
) {
366 switch (flush
? 1 : magiccheck(ms
, m
)) {
370 #ifdef ENABLE_CONDITIONALS
371 ms
->c
.li
[cont_level
].last_match
= 0;
375 #ifdef ENABLE_CONDITIONALS
376 ms
->c
.li
[cont_level
].last_match
= 1;
378 if (m
->type
== FILE_CLEAR
)
379 ms
->c
.li
[cont_level
].got_match
= 0;
380 else if (ms
->c
.li
[cont_level
].got_match
) {
381 if (m
->type
== FILE_DEFAULT
)
384 ms
->c
.li
[cont_level
].got_match
= 1;
389 if ((e
= handle_annotation(ms
, m
, firstline
))
392 *printed_something
= 1;
396 if (print
&& *m
->desc
) {
398 * This continuation matched. Print
399 * its message, with a blank before it
400 * if the previous item printed and
401 * this item isn't empty.
404 * If we are going to print something,
405 * make sure that we have a separator
408 if (!*printed_something
) {
409 *printed_something
= 1;
410 if (print_sep(ms
, firstline
)
414 /* space if previous printed */
416 && (m
->flag
& NOSPACE
) == 0) {
417 if (file_printf(ms
, " ") == -1)
422 if (mprint(ms
, m
) == -1)
427 switch (moffset(ms
, m
, &bb
,
428 &ms
->c
.li
[cont_level
].off
)) {
439 * If we see any continuations
443 if (file_check_mem(ms
, ++cont_level
) == -1)
448 if (*printed_something
) {
452 if ((ms
->flags
& MAGIC_CONTINUE
) == 0)
453 return *returnval
; /* don't keep searching */
454 // So that we print a separator
455 *printed_something
= 0;
460 return *returnval
; /* This is hit if -k is set or there is no match */
464 check_fmt(struct magic_set
*ms
, const char *fmt
)
469 if (strchr(fmt
, '%') == NULL
)
472 rc
= file_regcomp(&rx
, "%[-0-9\\.]*s", REG_EXTENDED
|REG_NOSUB
);
474 file_regerror(&rx
, rc
, ms
);
476 rc
= file_regexec(&rx
, fmt
, 0, 0, 0);
483 #if !defined(HAVE_STRNDUP) || defined(__aiws__)
485 # define strndup aix_strndup /* aix is broken */
487 char *strndup(const char *, size_t);
490 strndup(const char *str
, size_t n
)
495 for (len
= 0; len
< n
&& str
[len
]; len
++)
497 if ((copy
= malloc(len
+ 1)) == NULL
)
499 (void)memcpy(copy
, str
, len
);
503 #endif /* HAVE_STRNDUP */
506 varexpand(struct magic_set
*ms
, char *buf
, size_t len
, const char *str
)
508 const char *ptr
, *sptr
, *e
, *t
, *ee
, *et
;
511 for (sptr
= str
; (ptr
= strstr(sptr
, "${")) != NULL
;) {
512 l
= CAST(size_t, ptr
- sptr
);
515 memcpy(buf
, sptr
, l
);
519 if (!*ptr
|| ptr
[1] != '?')
521 for (et
= t
= ptr
+ 2; *et
&& *et
!= ':'; et
++)
525 for (ee
= e
= et
+ 1; *ee
&& *ee
!= '}'; ee
++)
531 if (ms
->mode
& 0111) {
554 memcpy(buf
, sptr
, l
);
561 mprint(struct magic_set
*ms
, struct magic
*m
)
567 char buf
[128], tbuf
[26], sbuf
[512], ebuf
[512];
569 union VALUETYPE
*p
= &ms
->ms_value
;
571 if (varexpand(ms
, ebuf
, sizeof(ebuf
), m
->desc
) == -1)
578 v
= file_signextend(ms
, m
, CAST(uint64_t, p
->b
));
579 switch (check_fmt(ms
, desc
)) {
583 (void)snprintf(buf
, sizeof(buf
), "%d",
584 CAST(unsigned char, v
));
585 if (file_printf(ms
, F(ms
, desc
, "%s"), buf
) == -1)
589 if (file_printf(ms
, F(ms
, desc
, "%d"),
590 CAST(unsigned char, v
)) == -1)
594 t
= ms
->offset
+ sizeof(char);
600 v
= file_signextend(ms
, m
, CAST(uint64_t, p
->h
));
601 switch (check_fmt(ms
, desc
)) {
605 (void)snprintf(buf
, sizeof(buf
), "%u",
606 CAST(unsigned short, v
));
607 if (file_printf(ms
, F(ms
, desc
, "%s"), buf
) == -1)
611 if (file_printf(ms
, F(ms
, desc
, "%u"),
612 CAST(unsigned short, v
)) == -1)
616 t
= ms
->offset
+ sizeof(short);
623 v
= file_signextend(ms
, m
, CAST(uint64_t, p
->l
));
624 switch (check_fmt(ms
, desc
)) {
628 (void)snprintf(buf
, sizeof(buf
), "%u",
630 if (file_printf(ms
, F(ms
, desc
, "%s"), buf
) == -1)
634 if (file_printf(ms
, F(ms
, desc
, "%u"),
635 CAST(uint32_t, v
)) == -1)
639 t
= ms
->offset
+ sizeof(int32_t);
645 v
= file_signextend(ms
, m
, p
->q
);
646 switch (check_fmt(ms
, desc
)) {
650 (void)snprintf(buf
, sizeof(buf
), "%" INT64_T_FORMAT
"u",
651 CAST(unsigned long long, v
));
652 if (file_printf(ms
, F(ms
, desc
, "%s"), buf
) == -1)
656 if (file_printf(ms
, F(ms
, desc
, "%" INT64_T_FORMAT
"u"),
657 CAST(unsigned long long, v
)) == -1)
661 t
= ms
->offset
+ sizeof(int64_t);
666 case FILE_BESTRING16
:
667 case FILE_LESTRING16
:
668 if (m
->reln
== '=' || m
->reln
== '!') {
669 if (file_printf(ms
, F(ms
, desc
, "%s"),
670 file_printable(sbuf
, sizeof(sbuf
), m
->value
.s
,
671 sizeof(m
->value
.s
))) == -1)
673 t
= ms
->offset
+ m
->vallen
;
678 /* compute t before we mangle the string? */
679 t
= ms
->offset
+ strlen(str
);
681 if (*m
->value
.s
== '\0')
682 str
[strcspn(str
, "\r\n")] = '\0';
684 if (m
->str_flags
& STRING_TRIM
) {
686 while (isspace(CAST(unsigned char, *str
)))
692 while (isspace(CAST(unsigned char, *last
)))
697 if (file_printf(ms
, F(ms
, desc
, "%s"),
698 file_printable(sbuf
, sizeof(sbuf
), str
,
699 sizeof(p
->s
) - (str
- p
->s
))) == -1)
702 if (m
->type
== FILE_PSTRING
)
703 t
+= file_pstring_length_size(m
);
711 if (file_printf(ms
, F(ms
, desc
, "%s"),
712 file_fmttime(p
->l
, 0, tbuf
)) == -1)
714 t
= ms
->offset
+ sizeof(uint32_t);
721 if (file_printf(ms
, F(ms
, desc
, "%s"),
722 file_fmttime(p
->l
, FILE_T_LOCAL
, tbuf
)) == -1)
724 t
= ms
->offset
+ sizeof(uint32_t);
730 if (file_printf(ms
, F(ms
, desc
, "%s"),
731 file_fmttime(p
->q
, 0, tbuf
)) == -1)
733 t
= ms
->offset
+ sizeof(uint64_t);
739 if (file_printf(ms
, F(ms
, desc
, "%s"),
740 file_fmttime(p
->q
, FILE_T_LOCAL
, tbuf
)) == -1)
742 t
= ms
->offset
+ sizeof(uint64_t);
748 if (file_printf(ms
, F(ms
, desc
, "%s"),
749 file_fmttime(p
->q
, FILE_T_WINDOWS
, tbuf
)) == -1)
751 t
= ms
->offset
+ sizeof(uint64_t);
758 switch (check_fmt(ms
, desc
)) {
762 (void)snprintf(buf
, sizeof(buf
), "%g", vf
);
763 if (file_printf(ms
, F(ms
, desc
, "%s"), buf
) == -1)
767 if (file_printf(ms
, F(ms
, desc
, "%g"), vf
) == -1)
771 t
= ms
->offset
+ sizeof(float);
778 switch (check_fmt(ms
, desc
)) {
782 (void)snprintf(buf
, sizeof(buf
), "%g", vd
);
783 if (file_printf(ms
, F(ms
, desc
, "%s"), buf
) == -1)
787 if (file_printf(ms
, F(ms
, desc
, "%g"), vd
) == -1)
791 t
= ms
->offset
+ sizeof(double);
799 cp
= strndup(RCAST(const char *, ms
->search
.s
),
802 file_oomem(ms
, ms
->search
.rm_len
);
805 rval
= file_printf(ms
, F(ms
, desc
, "%s"),
806 file_printable(sbuf
, sizeof(sbuf
), cp
, ms
->search
.rm_len
));
812 if ((m
->str_flags
& REGEX_OFFSET_START
))
813 t
= ms
->search
.offset
;
815 t
= ms
->search
.offset
+ ms
->search
.rm_len
;
821 if (file_printf(ms
, "%s", m
->desc
) == -1)
832 if (file_printf(ms
, F(ms
, desc
, "%s"),
833 file_printable(sbuf
, sizeof(sbuf
), ms
->ms_value
.s
,
834 sizeof(ms
->ms_value
.s
))) == -1)
839 file_magerror(ms
, "invalid m->type (%d) in mprint()", m
->type
);
842 return CAST(int32_t, t
);
846 moffset(struct magic_set
*ms
, struct magic
*m
, const struct buffer
*b
,
849 size_t nbytes
= b
->flen
;
854 o
= CAST(int32_t, (ms
->offset
+ sizeof(char)));
860 o
= CAST(int32_t, (ms
->offset
+ sizeof(short)));
867 o
= CAST(int32_t, (ms
->offset
+ sizeof(int32_t)));
873 o
= CAST(int32_t, (ms
->offset
+ sizeof(int64_t)));
878 case FILE_BESTRING16
:
879 case FILE_LESTRING16
:
880 if (m
->reln
== '=' || m
->reln
== '!') {
881 o
= ms
->offset
+ m
->vallen
;
883 union VALUETYPE
*p
= &ms
->ms_value
;
885 if (*m
->value
.s
== '\0')
886 p
->s
[strcspn(p
->s
, "\r\n")] = '\0';
887 o
= CAST(uint32_t, (ms
->offset
+ strlen(p
->s
)));
888 if (m
->type
== FILE_PSTRING
)
890 file_pstring_length_size(m
));
898 o
= CAST(int32_t, (ms
->offset
+ sizeof(uint32_t)));
905 o
= CAST(int32_t, (ms
->offset
+ sizeof(uint32_t)));
911 o
= CAST(int32_t, (ms
->offset
+ sizeof(uint64_t)));
917 o
= CAST(int32_t, (ms
->offset
+ sizeof(uint64_t)));
923 o
= CAST(int32_t, (ms
->offset
+ sizeof(float)));
929 o
= CAST(int32_t, (ms
->offset
+ sizeof(double)));
933 if ((m
->str_flags
& REGEX_OFFSET_START
) != 0)
934 o
= CAST(int32_t, ms
->search
.offset
);
937 (ms
->search
.offset
+ ms
->search
.rm_len
));
941 if ((m
->str_flags
& REGEX_OFFSET_START
) != 0)
942 o
= CAST(int32_t, ms
->search
.offset
);
944 o
= CAST(int32_t, (ms
->search
.offset
+ m
->vallen
));
955 o
= der_offs(ms
, m
, nbytes
);
956 if (o
== -1 || CAST(size_t, o
) > nbytes
) {
957 if ((ms
->flags
& MAGIC_DEBUG
) != 0) {
958 (void)fprintf(stderr
,
959 "Bad DER offset %d nbytes=%"
960 SIZE_T_FORMAT
"u", o
, nbytes
);
973 if (CAST(size_t, o
) > nbytes
) {
975 file_error(ms
, 0, "Offset out of range %" SIZE_T_FORMAT
976 "u > %" SIZE_T_FORMAT
"u", (size_t)o
, nbytes
);
985 cvt_id3(struct magic_set
*ms
, uint32_t v
)
987 v
= ((((v
>> 0) & 0x7f) << 0) |
988 (((v
>> 8) & 0x7f) << 7) |
989 (((v
>> 16) & 0x7f) << 14) |
990 (((v
>> 24) & 0x7f) << 21));
991 if ((ms
->flags
& MAGIC_DEBUG
) != 0)
992 fprintf(stderr
, "id3 offs=%u\n", v
);
997 cvt_flip(int type
, int flip
)
1003 return FILE_LESHORT
;
1009 return FILE_LELDATE
;
1013 return FILE_LEQDATE
;
1015 return FILE_LEQLDATE
;
1017 return FILE_LEQWDATE
;
1019 return FILE_BESHORT
;
1025 return FILE_BELDATE
;
1029 return FILE_BEQDATE
;
1031 return FILE_BEQLDATE
;
1033 return FILE_BEQWDATE
;
1035 return FILE_LEFLOAT
;
1037 return FILE_BEFLOAT
;
1039 return FILE_LEDOUBLE
;
1041 return FILE_BEDOUBLE
;
1046 #define DO_CVT(fld, type) \
1048 switch (m->mask_op & FILE_OPS_MASK) { \
1050 p->fld &= CAST(type, m->num_mask); \
1053 p->fld |= CAST(type, m->num_mask); \
1056 p->fld ^= CAST(type, m->num_mask); \
1059 p->fld += CAST(type, m->num_mask); \
1061 case FILE_OPMINUS: \
1062 p->fld -= CAST(type, m->num_mask); \
1064 case FILE_OPMULTIPLY: \
1065 p->fld *= CAST(type, m->num_mask); \
1067 case FILE_OPDIVIDE: \
1068 if (CAST(type, m->num_mask) == 0) \
1070 p->fld /= CAST(type, m->num_mask); \
1072 case FILE_OPMODULO: \
1073 if (CAST(type, m->num_mask) == 0) \
1075 p->fld %= CAST(type, m->num_mask); \
1078 if (m->mask_op & FILE_OPINVERSE) \
1082 cvt_8(union VALUETYPE
*p
, const struct magic
*m
)
1089 cvt_16(union VALUETYPE
*p
, const struct magic
*m
)
1091 DO_CVT(h
, uint16_t);
1096 cvt_32(union VALUETYPE
*p
, const struct magic
*m
)
1098 DO_CVT(l
, uint32_t);
1103 cvt_64(union VALUETYPE
*p
, const struct magic
*m
)
1105 DO_CVT(q
, uint64_t);
1109 #define DO_CVT2(fld, type) \
1111 switch (m->mask_op & FILE_OPS_MASK) { \
1113 p->fld += CAST(type, m->num_mask); \
1115 case FILE_OPMINUS: \
1116 p->fld -= CAST(type, m->num_mask); \
1118 case FILE_OPMULTIPLY: \
1119 p->fld *= CAST(type, m->num_mask); \
1121 case FILE_OPDIVIDE: \
1122 if (CAST(type, m->num_mask) == 0) \
1124 p->fld /= CAST(type, m->num_mask); \
1129 cvt_float(union VALUETYPE
*p
, const struct magic
*m
)
1136 cvt_double(union VALUETYPE
*p
, const struct magic
*m
)
1143 * Convert the byte order of the data we are looking at
1144 * While we're here, let's apply the mask operation
1145 * (unless you have a better idea)
1148 mconvert(struct magic_set
*ms
, struct magic
*m
, int flip
)
1150 union VALUETYPE
*p
= &ms
->ms_value
;
1152 switch (cvt_flip(m
->type
, flip
)) {
1154 if (cvt_8(p
, m
) == -1)
1158 if (cvt_16(p
, m
) == -1)
1164 if (cvt_32(p
, m
) == -1)
1171 if (cvt_64(p
, m
) == -1)
1175 case FILE_BESTRING16
:
1176 case FILE_LESTRING16
: {
1177 /* Null terminate and eat *trailing* return */
1178 p
->s
[sizeof(p
->s
) - 1] = '\0';
1181 case FILE_PSTRING
: {
1182 size_t sz
= file_pstring_length_size(m
);
1183 char *ptr1
= p
->s
, *ptr2
= ptr1
+ sz
;
1184 size_t len
= file_pstring_get_length(m
, ptr1
);
1185 sz
= sizeof(p
->s
) - sz
; /* maximum length of string */
1188 * The size of the pascal string length (sz)
1189 * is 1, 2, or 4. We need at least 1 byte for NUL
1190 * termination, but we've already truncated the
1191 * string by p->s, so we need to deduct sz.
1192 * Because we can use one of the bytes of the length
1193 * after we shifted as NUL termination.
1203 p
->h
= CAST(short, BE16(p
));
1204 if (cvt_16(p
, m
) == -1)
1210 p
->l
= CAST(int32_t, BE32(p
));
1211 if (cvt_32(p
, m
) == -1)
1218 p
->q
= CAST(uint64_t, BE64(p
));
1219 if (cvt_64(p
, m
) == -1)
1223 p
->h
= CAST(short, LE16(p
));
1224 if (cvt_16(p
, m
) == -1)
1230 p
->l
= CAST(int32_t, LE32(p
));
1231 if (cvt_32(p
, m
) == -1)
1238 p
->q
= CAST(uint64_t, LE64(p
));
1239 if (cvt_64(p
, m
) == -1)
1245 p
->l
= CAST(int32_t, ME32(p
));
1246 if (cvt_32(p
, m
) == -1)
1250 if (cvt_float(p
, m
) == -1)
1255 if (cvt_float(p
, m
) == -1)
1260 if (cvt_float(p
, m
) == -1)
1264 if (cvt_double(p
, m
) == -1)
1269 if (cvt_double(p
, m
) == -1)
1274 if (cvt_double(p
, m
) == -1)
1286 file_magerror(ms
, "invalid type %d in mconvert()", m
->type
);
1290 file_magerror(ms
, "zerodivide in mconvert()");
1296 mdebug(uint32_t offset
, const char *str
, size_t len
)
1298 (void) fprintf(stderr
, "mget/%" SIZE_T_FORMAT
"u @%d: ", len
, offset
);
1299 file_showstr(stderr
, str
, len
);
1300 (void) fputc('\n', stderr
);
1301 (void) fputc('\n', stderr
);
1305 mcopy(struct magic_set
*ms
, union VALUETYPE
*p
, int type
, int indir
,
1306 const unsigned char *s
, uint32_t offset
, size_t nbytes
, struct magic
*m
)
1309 * Note: FILE_SEARCH and FILE_REGEX do not actually copy
1310 * anything, but setup pointers into the source
1316 if (offset
> nbytes
)
1317 offset
= CAST(uint32_t, nbytes
);
1318 ms
->search
.s
= RCAST(const char *, s
) + offset
;
1319 ms
->search
.s_len
= nbytes
- offset
;
1320 ms
->search
.offset
= offset
;
1326 const char *last
; /* end of search region */
1327 const char *buf
; /* start of search region */
1329 size_t lines
, linecnt
, bytecnt
;
1331 if (s
== NULL
|| nbytes
< offset
) {
1332 ms
->search
.s_len
= 0;
1333 ms
->search
.s
= NULL
;
1337 if (m
->str_flags
& REGEX_LINE_COUNT
) {
1338 linecnt
= m
->str_range
;
1339 bytecnt
= linecnt
* 80;
1342 bytecnt
= m
->str_range
;
1345 if (bytecnt
== 0 || bytecnt
> nbytes
- offset
)
1346 bytecnt
= nbytes
- offset
;
1347 if (bytecnt
> ms
->regex_max
)
1348 bytecnt
= ms
->regex_max
;
1350 buf
= RCAST(const char *, s
) + offset
;
1351 end
= last
= RCAST(const char *, s
) + bytecnt
+ offset
;
1352 /* mget() guarantees buf <= last */
1353 for (lines
= linecnt
, b
= buf
; lines
&& b
< end
&&
1354 ((b
= CAST(const char *,
1355 memchr(c
= b
, '\n', CAST(size_t, (end
- b
)))))
1356 || (b
= CAST(const char *,
1357 memchr(c
, '\r', CAST(size_t, (end
- c
))))));
1359 if (b
< end
- 1 && b
[0] == '\r' && b
[1] == '\n')
1361 if (b
< end
- 1 && b
[0] == '\n')
1369 ms
->search
.s_len
= last
- buf
;
1370 ms
->search
.offset
= offset
;
1371 ms
->search
.rm_len
= 0;
1374 case FILE_BESTRING16
:
1375 case FILE_LESTRING16
: {
1376 const unsigned char *src
= s
+ offset
;
1377 const unsigned char *esrc
= s
+ nbytes
;
1379 char *edst
= &p
->s
[sizeof(p
->s
) - 1];
1381 if (type
== FILE_BESTRING16
)
1384 /* check that offset is within range */
1385 if (offset
>= nbytes
)
1387 for (/*EMPTY*/; src
< esrc
; src
+= 2, dst
++) {
1393 if (type
== FILE_BESTRING16
?
1394 *(src
- 1) != '\0' :
1395 ((src
+ 1 < esrc
) &&
1396 *(src
+ 1) != '\0'))
1403 case FILE_STRING
: /* XXX - these two should not need */
1404 case FILE_PSTRING
: /* to copy anything, but do anyway. */
1410 if (offset
>= nbytes
) {
1411 (void)memset(p
, '\0', sizeof(*p
));
1414 if (nbytes
- offset
< sizeof(*p
))
1415 nbytes
= nbytes
- offset
;
1417 nbytes
= sizeof(*p
);
1419 (void)memcpy(p
, s
+ offset
, nbytes
);
1422 * the usefulness of padding with zeroes eludes me, it
1423 * might even cause problems
1425 if (nbytes
< sizeof(*p
))
1426 (void)memset(RCAST(char *, RCAST(void *, p
)) + nbytes
, '\0',
1427 sizeof(*p
) - nbytes
);
1432 do_ops(struct magic
*m
, intmax_t lhs
, intmax_t off
)
1436 switch (m
->in_op
& FILE_OPS_MASK
) {
1452 case FILE_OPMULTIPLY
:
1464 if (m
->in_op
& FILE_OPINVERSE
)
1467 return CAST(uint32_t, offset
);
1471 msetoffset(struct magic_set
*ms
, struct magic
*m
, struct buffer
*bb
,
1472 const struct buffer
*b
, size_t o
, unsigned int cont_level
)
1474 if (m
->offset
< 0) {
1475 if (cont_level
> 0) {
1476 if (m
->flag
& (OFFADD
|INDIROFFADD
))
1479 file_error(ms
, 0, "negative offset %d at continuation"
1480 "level %u", m
->offset
, cont_level
);
1484 if (buffer_fill(b
) == -1)
1488 file_magerror(ms
, "non zero offset %" SIZE_T_FORMAT
1489 "u at level %u", o
, cont_level
);
1492 if (CAST(size_t, -m
->offset
) > b
->elen
)
1494 buffer_init(bb
, -1, NULL
, b
->ebuf
, b
->elen
);
1495 ms
->eoffset
= ms
->offset
= CAST(int32_t, b
->elen
+ m
->offset
);
1497 if (cont_level
== 0) {
1499 // XXX: Pass real fd, then who frees bb?
1500 buffer_init(bb
, -1, NULL
, b
->fbuf
, b
->flen
);
1501 ms
->offset
= m
->offset
;
1504 ms
->offset
= ms
->eoffset
+ m
->offset
;
1507 if ((ms
->flags
& MAGIC_DEBUG
) != 0) {
1508 fprintf(stderr
, "bb=[%p,%" SIZE_T_FORMAT
"u], %d [b=%p,%"
1509 SIZE_T_FORMAT
"u], [o=%#x, c=%d]\n",
1510 bb
->fbuf
, bb
->flen
, ms
->offset
, b
->fbuf
, b
->flen
,
1511 m
->offset
, cont_level
);
1517 mget(struct magic_set
*ms
, struct magic
*m
, const struct buffer
*b
,
1518 const unsigned char *s
, size_t nbytes
, size_t o
, unsigned int cont_level
,
1519 int mode
, int text
, int flip
, uint16_t *indir_count
, uint16_t *name_count
,
1520 int *printed_something
, int *need_separator
, int *returnval
,
1523 uint32_t offset
= ms
->offset
;
1527 int rv
, oneed_separator
, in_type
;
1529 union VALUETYPE
*p
= &ms
->ms_value
;
1532 if (*indir_count
>= ms
->indir_max
) {
1533 file_error(ms
, 0, "indirect count (%hu) exceeded",
1538 if (*name_count
>= ms
->name_max
) {
1539 file_error(ms
, 0, "name use count (%hu) exceeded",
1546 if (mcopy(ms
, p
, m
->type
, m
->flag
& INDIR
, s
,
1547 CAST(uint32_t, offset
+ o
), CAST(uint32_t, nbytes
), m
) == -1)
1550 if ((ms
->flags
& MAGIC_DEBUG
) != 0) {
1551 fprintf(stderr
, "mget(type=%d, flag=%#x, offset=%u, o=%"
1552 SIZE_T_FORMAT
"u, " "nbytes=%" SIZE_T_FORMAT
1553 "u, il=%hu, nc=%hu)\n",
1554 m
->type
, m
->flag
, offset
, o
, nbytes
,
1555 *indir_count
, *name_count
);
1556 mdebug(offset
, RCAST(char *, RCAST(void *, p
)),
1557 sizeof(union VALUETYPE
));
1558 #ifndef COMPILE_ONLY
1563 if (m
->flag
& INDIR
) {
1564 intmax_t off
= m
->in_offset
;
1565 const int sgn
= m
->in_op
& FILE_OPSIGNED
;
1566 if (m
->in_op
& FILE_OPINDIRECT
) {
1567 const union VALUETYPE
*q
= CAST(const union VALUETYPE
*,
1568 RCAST(const void *, s
+ offset
+ off
));
1569 switch (cvt_flip(m
->in_type
, flip
)) {
1571 if (OFFSET_OOB(nbytes
, offset
+ off
, 1))
1573 off
= SEXT(sgn
,8,q
->b
);
1576 if (OFFSET_OOB(nbytes
, offset
+ off
, 2))
1578 off
= SEXT(sgn
,16,q
->h
);
1581 if (OFFSET_OOB(nbytes
, offset
+ off
, 2))
1583 off
= SEXT(sgn
,16,BE16(q
));
1586 if (OFFSET_OOB(nbytes
, offset
+ off
, 2))
1588 off
= SEXT(sgn
,16,LE16(q
));
1591 if (OFFSET_OOB(nbytes
, offset
+ off
, 4))
1593 off
= SEXT(sgn
,32,q
->l
);
1597 if (OFFSET_OOB(nbytes
, offset
+ off
, 4))
1599 off
= SEXT(sgn
,32,BE32(q
));
1603 if (OFFSET_OOB(nbytes
, offset
+ off
, 4))
1605 off
= SEXT(sgn
,32,LE32(q
));
1608 if (OFFSET_OOB(nbytes
, offset
+ off
, 4))
1610 off
= SEXT(sgn
,32,ME32(q
));
1613 if (OFFSET_OOB(nbytes
, offset
+ off
, 8))
1615 off
= SEXT(sgn
,64,BE64(q
));
1618 if (OFFSET_OOB(nbytes
, offset
+ off
, 8))
1620 off
= SEXT(sgn
,64,LE64(q
));
1625 if ((ms
->flags
& MAGIC_DEBUG
) != 0)
1626 fprintf(stderr
, "indirect offs=%jd\n", off
);
1628 switch (in_type
= cvt_flip(m
->in_type
, flip
)) {
1630 if (OFFSET_OOB(nbytes
, offset
, 1))
1632 offset
= do_ops(m
, SEXT(sgn
,8,p
->b
), off
);
1635 if (OFFSET_OOB(nbytes
, offset
, 2))
1637 offset
= do_ops(m
, SEXT(sgn
,16,BE16(p
)), off
);
1640 if (OFFSET_OOB(nbytes
, offset
, 2))
1642 offset
= do_ops(m
, SEXT(sgn
,16,LE16(p
)), off
);
1645 if (OFFSET_OOB(nbytes
, offset
, 2))
1647 offset
= do_ops(m
, SEXT(sgn
,16,p
->h
), off
);
1651 if (OFFSET_OOB(nbytes
, offset
, 4))
1654 if (in_type
== FILE_BEID3
)
1655 lhs
= cvt_id3(ms
, CAST(uint32_t, lhs
));
1656 offset
= do_ops(m
, SEXT(sgn
,32,lhs
), off
);
1660 if (OFFSET_OOB(nbytes
, offset
, 4))
1663 if (in_type
== FILE_LEID3
)
1664 lhs
= cvt_id3(ms
, CAST(uint32_t, lhs
));
1665 offset
= do_ops(m
, SEXT(sgn
,32,lhs
), off
);
1668 if (OFFSET_OOB(nbytes
, offset
, 4))
1670 offset
= do_ops(m
, SEXT(sgn
,32,ME32(p
)), off
);
1673 if (OFFSET_OOB(nbytes
, offset
, 4))
1675 offset
= do_ops(m
, SEXT(sgn
,32,p
->l
), off
);
1678 if (OFFSET_OOB(nbytes
, offset
, 8))
1680 offset
= do_ops(m
, SEXT(sgn
,64,LE64(p
)), off
);
1683 if (OFFSET_OOB(nbytes
, offset
, 8))
1685 offset
= do_ops(m
, SEXT(sgn
,64,BE64(p
)), off
);
1691 if (m
->flag
& INDIROFFADD
) {
1692 offset
+= ms
->c
.li
[cont_level
-1].off
;
1694 if ((ms
->flags
& MAGIC_DEBUG
) != 0)
1696 "indirect *zero* offset\n");
1699 if ((ms
->flags
& MAGIC_DEBUG
) != 0)
1700 fprintf(stderr
, "indirect +offs=%u\n", offset
);
1702 if (mcopy(ms
, p
, m
->type
, 0, s
, offset
, nbytes
, m
) == -1)
1704 ms
->offset
= offset
;
1706 if ((ms
->flags
& MAGIC_DEBUG
) != 0) {
1707 mdebug(offset
, RCAST(char *, RCAST(void *, p
)),
1708 sizeof(union VALUETYPE
));
1709 #ifndef COMPILE_ONLY
1715 /* Verify we have enough data to match magic type */
1718 if (OFFSET_OOB(nbytes
, offset
, 1))
1725 if (OFFSET_OOB(nbytes
, offset
, 2))
1744 if (OFFSET_OOB(nbytes
, offset
, 4))
1751 if (OFFSET_OOB(nbytes
, offset
, 8))
1758 if (OFFSET_OOB(nbytes
, offset
, m
->vallen
))
1763 if (nbytes
< offset
)
1768 if (m
->str_flags
& INDIRECT_RELATIVE
)
1769 offset
+= CAST(uint32_t, o
);
1773 if (nbytes
< offset
)
1776 if ((pb
= file_push_buffer(ms
)) == NULL
)
1781 bb
.fbuf
= s
+ offset
;
1782 bb
.flen
= nbytes
- offset
;
1783 rv
= file_softmagic(ms
, &bb
,
1784 indir_count
, name_count
, BINTEST
, text
);
1786 if ((ms
->flags
& MAGIC_DEBUG
) != 0)
1787 fprintf(stderr
, "indirect @offs=%u[%d]\n", offset
, rv
);
1789 rbuf
= file_pop_buffer(ms
, pb
);
1790 if (rbuf
== NULL
&& ms
->event_flags
& EVENT_HAD_ERR
)
1794 if ((ms
->flags
& MAGIC_NODESC
) == 0 &&
1795 file_printf(ms
, F(ms
, m
->desc
, "%u"), offset
) == -1)
1800 if (file_printf(ms
, "%s", rbuf
) == -1) {
1809 if (nbytes
< offset
)
1816 if (file_magicfind(ms
, rbuf
, &ml
) == -1) {
1817 file_error(ms
, 0, "cannot find entry `%s'", rbuf
);
1821 oneed_separator
= *need_separator
;
1822 if (m
->flag
& NOSPACE
)
1823 *need_separator
= 0;
1824 rv
= match(ms
, ml
.magic
, ml
.nmagic
, b
, offset
+ o
,
1825 mode
, text
, flip
, indir_count
, name_count
,
1826 printed_something
, need_separator
, returnval
, found_match
);
1829 *need_separator
= oneed_separator
;
1833 if (ms
->flags
& MAGIC_NODESC
)
1835 if (file_printf(ms
, "%s", m
->desc
) == -1)
1839 case FILE_DEFAULT
: /* nothing to check */
1844 if (!mconvert(ms
, m
, flip
))
1850 file_strncmp(const char *s1
, const char *s2
, size_t len
, uint32_t flags
)
1853 * Convert the source args to unsigned here so that (1) the
1854 * compare will be unsigned as it is in strncmp() and (2) so
1855 * the ctype functions will work correctly without extra
1858 const unsigned char *a
= RCAST(const unsigned char *, s1
);
1859 const unsigned char *b
= RCAST(const unsigned char *, s2
);
1860 const unsigned char *eb
= b
+ len
;
1864 * What we want here is v = strncmp(s1, s2, len),
1865 * but ignoring any nulls.
1868 if (0L == flags
) { /* normal string: do it fast */
1870 if ((v
= *b
++ - *a
++) != '\0')
1873 else { /* combine the others */
1879 if ((flags
& STRING_IGNORE_LOWERCASE
) &&
1881 if ((v
= tolower(*b
++) - *a
++) != '\0')
1884 else if ((flags
& STRING_IGNORE_UPPERCASE
) &&
1886 if ((v
= toupper(*b
++) - *a
++) != '\0')
1889 else if ((flags
& STRING_COMPACT_WHITESPACE
) &&
1892 if (isspace(*b
++)) {
1894 while (b
< eb
&& isspace(*b
))
1902 else if ((flags
& STRING_COMPACT_OPTIONAL_WHITESPACE
) &&
1905 while (b
< eb
&& isspace(*b
))
1909 if ((v
= *b
++ - *a
++) != '\0')
1918 file_strncmp16(const char *a
, const char *b
, size_t len
, uint32_t flags
)
1921 * XXX - The 16-bit string compare probably needs to be done
1922 * differently, especially if the flags are to be supported.
1923 * At the moment, I am unsure.
1926 return file_strncmp(a
, b
, len
, flags
);
1930 magiccheck(struct magic_set
*ms
, struct magic
*m
)
1932 uint64_t l
= m
->value
.q
;
1937 union VALUETYPE
*p
= &ms
->ms_value
;
2007 file_magerror(ms
, "cannot happen with float: invalid relation `%c'",
2040 file_magerror(ms
, "cannot happen with double: invalid relation `%c'", m
->reln
);
2054 v
= file_strncmp(m
->value
.s
, p
->s
, CAST(size_t, m
->vallen
),
2058 case FILE_BESTRING16
:
2059 case FILE_LESTRING16
:
2061 v
= file_strncmp16(m
->value
.s
, p
->s
, CAST(size_t, m
->vallen
),
2065 case FILE_SEARCH
: { /* search ms->search.s for the string m->value.s */
2069 if (ms
->search
.s
== NULL
)
2072 slen
= MIN(m
->vallen
, sizeof(m
->value
.s
));
2076 if (slen
> 0 && m
->str_flags
== 0) {
2078 idx
= m
->str_range
+ slen
;
2079 if (m
->str_range
== 0 || ms
->search
.s_len
< idx
)
2080 idx
= ms
->search
.s_len
;
2081 found
= CAST(const char *, memmem(ms
->search
.s
, idx
,
2085 idx
= found
- ms
->search
.s
;
2086 ms
->search
.offset
+= idx
;
2087 ms
->search
.rm_len
= ms
->search
.s_len
- idx
;
2092 for (idx
= 0; m
->str_range
== 0 || idx
< m
->str_range
; idx
++) {
2093 if (slen
+ idx
> ms
->search
.s_len
)
2096 v
= file_strncmp(m
->value
.s
, ms
->search
.s
+ idx
, slen
,
2098 if (v
== 0) { /* found match */
2099 ms
->search
.offset
+= idx
;
2100 ms
->search
.rm_len
= ms
->search
.s_len
- idx
;
2111 if (ms
->search
.s
== NULL
)
2115 rc
= file_regcomp(&rx
, m
->value
.s
,
2116 REG_EXTENDED
|REG_NEWLINE
|
2117 ((m
->str_flags
& STRING_IGNORE_CASE
) ? REG_ICASE
: 0));
2119 file_regerror(&rx
, rc
, ms
);
2120 v
= CAST(uint64_t, -1);
2123 size_t slen
= ms
->search
.s_len
;
2126 copy
= CAST(char *, malloc(slen
));
2129 file_error(ms
, errno
,
2130 "can't allocate %" SIZE_T_FORMAT
"u bytes",
2134 memcpy(copy
, ms
->search
.s
, slen
);
2135 copy
[--slen
] = '\0';
2138 search
= CCAST(char *, "");
2141 rc
= file_regexec(&rx
, RCAST(const char *, search
),
2146 ms
->search
.s
+= CAST(int, pmatch
.rm_so
);
2147 ms
->search
.offset
+= CAST(size_t, pmatch
.rm_so
);
2148 ms
->search
.rm_len
= CAST(size_t,
2149 pmatch
.rm_eo
- pmatch
.rm_so
);
2158 file_regerror(&rx
, rc
, ms
);
2159 v
= CAST(uint64_t, -1);
2164 if (v
== CAST(uint64_t, -1))
2173 matched
= der_cmp(ms
, m
);
2174 if (matched
== -1) {
2175 if ((ms
->flags
& MAGIC_DEBUG
) != 0) {
2176 (void) fprintf(stderr
,
2177 "EOF comparing DER entries");
2183 file_magerror(ms
, "invalid type %d in magiccheck()", m
->type
);
2187 v
= file_signextend(ms
, m
, v
);
2191 if ((ms
->flags
& MAGIC_DEBUG
) != 0)
2192 (void) fprintf(stderr
, "%" INT64_T_FORMAT
2193 "u == *any* = 1\n", CAST(unsigned long long, v
));
2199 if ((ms
->flags
& MAGIC_DEBUG
) != 0)
2200 (void) fprintf(stderr
, "%" INT64_T_FORMAT
"u != %"
2201 INT64_T_FORMAT
"u = %d\n",
2202 CAST(unsigned long long, v
),
2203 CAST(unsigned long long, l
), matched
);
2208 if ((ms
->flags
& MAGIC_DEBUG
) != 0)
2209 (void) fprintf(stderr
, "%" INT64_T_FORMAT
"u == %"
2210 INT64_T_FORMAT
"u = %d\n",
2211 CAST(unsigned long long, v
),
2212 CAST(unsigned long long, l
), matched
);
2216 if (m
->flag
& UNSIGNED
) {
2218 if ((ms
->flags
& MAGIC_DEBUG
) != 0)
2219 (void) fprintf(stderr
, "%" INT64_T_FORMAT
2220 "u > %" INT64_T_FORMAT
"u = %d\n",
2221 CAST(unsigned long long, v
),
2222 CAST(unsigned long long, l
), matched
);
2225 matched
= CAST(int64_t, v
) > CAST(int64_t, l
);
2226 if ((ms
->flags
& MAGIC_DEBUG
) != 0)
2227 (void) fprintf(stderr
, "%" INT64_T_FORMAT
2228 "d > %" INT64_T_FORMAT
"d = %d\n",
2230 CAST(long long, l
), matched
);
2235 if (m
->flag
& UNSIGNED
) {
2237 if ((ms
->flags
& MAGIC_DEBUG
) != 0)
2238 (void) fprintf(stderr
, "%" INT64_T_FORMAT
2239 "u < %" INT64_T_FORMAT
"u = %d\n",
2240 CAST(unsigned long long, v
),
2241 CAST(unsigned long long, l
), matched
);
2244 matched
= CAST(int64_t, v
) < CAST(int64_t, l
);
2245 if ((ms
->flags
& MAGIC_DEBUG
) != 0)
2246 (void) fprintf(stderr
, "%" INT64_T_FORMAT
2247 "d < %" INT64_T_FORMAT
"d = %d\n",
2249 CAST(long long, l
), matched
);
2254 matched
= (v
& l
) == l
;
2255 if ((ms
->flags
& MAGIC_DEBUG
) != 0)
2256 (void) fprintf(stderr
, "((%" INT64_T_FORMAT
"x & %"
2257 INT64_T_FORMAT
"x) == %" INT64_T_FORMAT
2258 "x) = %d\n", CAST(unsigned long long, v
),
2259 CAST(unsigned long long, l
),
2260 CAST(unsigned long long, l
),
2265 matched
= (v
& l
) != l
;
2266 if ((ms
->flags
& MAGIC_DEBUG
) != 0)
2267 (void) fprintf(stderr
, "((%" INT64_T_FORMAT
"x & %"
2268 INT64_T_FORMAT
"x) != %" INT64_T_FORMAT
2269 "x) = %d\n", CAST(unsigned long long, v
),
2270 CAST(unsigned long long, l
),
2271 CAST(unsigned long long, l
), matched
);
2275 file_magerror(ms
, "cannot happen: invalid relation `%c'",
2284 handle_annotation(struct magic_set
*ms
, struct magic
*m
, int firstline
)
2286 if ((ms
->flags
& MAGIC_APPLE
) && m
->apple
[0]) {
2287 if (print_sep(ms
, firstline
) == -1)
2289 if (file_printf(ms
, "%.8s", m
->apple
) == -1)
2293 if ((ms
->flags
& MAGIC_EXTENSION
) && m
->ext
[0]) {
2294 if (print_sep(ms
, firstline
) == -1)
2296 if (file_printf(ms
, "%s", m
->ext
) == -1)
2300 if ((ms
->flags
& MAGIC_MIME_TYPE
) && m
->mimetype
[0]) {
2303 if (print_sep(ms
, firstline
) == -1)
2305 if (varexpand(ms
, buf
, sizeof(buf
), m
->mimetype
) == -1)
2309 if (file_printf(ms
, "%s", p
) == -1)
2317 print_sep(struct magic_set
*ms
, int firstline
)
2322 * we found another match
2323 * put a newline and '-' to do some simple formatting
2325 return file_separator(ms
);