]>
git.saurik.com Git - apple/file_cmds.git/blob - file/softmagic.c
46838532388fff25fcf9948376cbd77537598c17
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
24 /* $OpenBSD: softmagic.c,v 1.3 1997/02/09 23:58:36 millert Exp $ */
27 * softmagic - interpret variable magic from /etc/magic
29 * Copyright (c) Ian F. Darwin, 1987.
30 * Written by Ian F. Darwin.
32 * This software is not subject to any license of the American Telephone
33 * and Telegraph Company or of the Regents of the University of California.
35 * Permission is granted to anyone to use this software for any purpose on
36 * any computer system, and to alter it and redistribute it freely, subject
37 * to the following restrictions:
39 * 1. The author is not responsible for the consequences of use of this
40 * software, no matter how awful, even if they arise from flaws in it.
42 * 2. The origin of this software must not be misrepresented, either by
43 * explicit claim or by omission. Since few users ever read sources,
44 * credits must appear in the documentation.
46 * 3. Altered versions must be plainly marked as such, and must not be
47 * misrepresented as being the original software. Since few users
48 * ever read sources, credits must appear in the documentation.
50 * 4. This notice may not be removed or altered.
57 #include <sys/types.h>
63 static char *moduleid
= "$OpenBSD: softmagic.c,v 1.3 1997/02/09 23:58:36 millert Exp $";
67 static int match
__P((unsigned char *, int));
68 static int mget
__P((union VALUETYPE
*,
69 unsigned char *, struct magic
*, int));
70 static int mcheck
__P((union VALUETYPE
*, struct magic
*));
71 static int32 mprint
__P((union VALUETYPE
*, struct magic
*));
72 static void mdebug
__P((int32
, char *, int));
73 static int mconvert
__P((union VALUETYPE
*, struct magic
*));
76 * softmagic - lookup one file in database
77 * (already read from /etc/magic by apprentice.c).
78 * Passed the name and FILE * of one file to be typed.
80 /*ARGSUSED1*/ /* nbytes passed for regularity, maybe need later */
82 softmagic(buf
, nbytes
)
86 if (match(buf
, nbytes
))
93 * Go through the whole list, stopping if you find a match. Process all
94 * the continuations of that match before returning.
96 * We support multi-level continuations:
98 * At any time when processing a successful top-level match, there is a
99 * current continuation level; it represents the level of the last
100 * successfully matched continuation.
102 * Continuations above that level are skipped as, if we see one, it
103 * means that the continuation that controls them - i.e, the
104 * lower-level continuation preceding them - failed to match.
106 * Continuations below that level are processed as, if we see one,
107 * it means we've finished processing or skipping higher-level
108 * continuations under the control of a successful or unsuccessful
109 * lower-level continuation, and are now seeing the next lower-level
110 * continuation and should process it. The current continuation
111 * level reverts to the level of the one we're seeing.
113 * Continuations at the current level are processed as, if we see
114 * one, there's no lower-level continuation that may have failed.
116 * If a continuation matches, we bump the current continuation level
117 * so that higher-level continuations are processed.
126 int need_separator
= 0;
128 static int32
*tmpoff
= NULL
;
129 static size_t tmplen
= 0;
133 if ((tmpoff
= (int32
*) malloc(tmplen
= 20)) == NULL
)
134 error("out of memory\n");
136 for (magindex
= 0; magindex
< nmagic
; magindex
++) {
137 /* if main entry matches, print it... */
138 if (!mget(&p
, s
, &magic
[magindex
], nbytes
) ||
139 !mcheck(&p
, &magic
[magindex
])) {
141 * main entry didn't match,
142 * flush its continuations
144 while (magindex
< nmagic
&&
145 magic
[magindex
+ 1].cont_level
!= 0)
150 tmpoff
[cont_level
] = mprint(&p
, &magic
[magindex
]);
152 * If we printed something, we'll need to print
153 * a blank before we print something else.
155 if (magic
[magindex
].desc
[0])
157 /* and any continuations that match */
158 if (++cont_level
>= tmplen
)
159 if ((tmpoff
= (int32
*) realloc(tmpoff
,
160 tmplen
+= 20)) == NULL
)
161 error("out of memory\n");
162 while (magic
[magindex
+1].cont_level
!= 0 &&
163 ++magindex
< nmagic
) {
164 if (cont_level
>= magic
[magindex
].cont_level
) {
165 if (cont_level
> magic
[magindex
].cont_level
) {
167 * We're at the end of the level
168 * "cont_level" continuations.
170 cont_level
= magic
[magindex
].cont_level
;
172 if (magic
[magindex
].flag
& ADD
) {
173 oldoff
=magic
[magindex
].offset
;
174 magic
[magindex
].offset
+= tmpoff
[cont_level
-1];
176 if (mget(&p
, s
, &magic
[magindex
], nbytes
) &&
177 mcheck(&p
, &magic
[magindex
])) {
179 * This continuation matched.
180 * Print its message, with
181 * a blank before it if
182 * the previous item printed
183 * and this item isn't empty.
185 /* space if previous printed */
187 && (magic
[magindex
].nospflag
== 0)
188 && (magic
[magindex
].desc
[0] != '\0')
193 tmpoff
[cont_level
] = mprint(&p
, &magic
[magindex
]);
194 if (magic
[magindex
].desc
[0])
198 * If we see any continuations
202 if (++cont_level
>= tmplen
)
204 (int32
*) realloc(tmpoff
,
205 tmplen
+= 20)) == NULL
)
206 error("out of memory\n");
208 if (magic
[magindex
].flag
& ADD
) {
209 magic
[magindex
].offset
= oldoff
;
213 return 1; /* all through */
215 return 0; /* no match at all */
231 v
= signextend(m
, v
) & m
->mask
;
232 (void) printf(m
->desc
, (unsigned char) v
);
233 t
= m
->offset
+ sizeof(char);
240 v
= signextend(m
, v
) & m
->mask
;
241 (void) printf(m
->desc
, (unsigned short) v
);
242 t
= m
->offset
+ sizeof(short);
249 v
= signextend(m
, v
) & m
->mask
;
250 (void) printf(m
->desc
, (uint32
) v
);
251 t
= m
->offset
+ sizeof(int32
);
255 if (m
->reln
== '=') {
256 (void) printf(m
->desc
, m
->value
.s
);
257 t
= m
->offset
+ strlen(m
->value
.s
);
260 if (*m
->value
.s
== '\0') {
261 char *cp
= strchr(p
->s
,'\n');
265 (void) printf(m
->desc
, p
->s
);
266 t
= m
->offset
+ strlen(p
->s
);
273 pp
= ctime((time_t*) &p
->l
);
274 if ((rt
= strchr(pp
, '\n')) != NULL
)
276 (void) printf(m
->desc
, pp
);
277 t
= m
->offset
+ sizeof(time_t);
281 error("invalid m->type (%d) in mprint().\n", m
->type
);
288 * Convert the byte order of the data we are looking at
305 /* Null terminate and eat the return */
306 p
->s
[sizeof(p
->s
) - 1] = '\0';
307 if ((ptr
= strchr(p
->s
, '\n')) != NULL
)
312 p
->h
= (short)((p
->hs
[0]<<8)|(p
->hs
[1]));
317 ((p
->hl
[0]<<24)|(p
->hl
[1]<<16)|(p
->hl
[2]<<8)|(p
->hl
[3]));
320 p
->h
= (short)((p
->hs
[1]<<8)|(p
->hs
[0]));
325 ((p
->hl
[3]<<24)|(p
->hl
[2]<<16)|(p
->hl
[1]<<8)|(p
->hl
[0]));
328 error("invalid type %d in mconvert().\n", m
->type
);
335 mdebug(offset
, str
, len
)
340 (void) fprintf(stderr
, "mget @%d: ", offset
);
341 showstr(stderr
, (char *) str
, len
);
342 (void) fputc('\n', stderr
);
343 (void) fputc('\n', stderr
);
347 mget(p
, s
, m
, nbytes
)
353 int32 offset
= m
->offset
;
355 if (offset
+ sizeof(union VALUETYPE
) <= nbytes
)
356 memcpy(p
, s
+ offset
, sizeof(union VALUETYPE
));
359 * the usefulness of padding with zeroes eludes me, it
360 * might even cause problems
362 int32 have
= nbytes
- offset
;
363 memset(p
, 0, sizeof(union VALUETYPE
));
365 memcpy(p
, s
+ offset
, have
);
370 mdebug(offset
, (char *) p
, sizeof(union VALUETYPE
));
377 if (m
->flag
& INDIR
) {
379 switch (m
->in
.type
) {
381 offset
= p
->b
+ m
->in
.offset
;
384 offset
= p
->h
+ m
->in
.offset
;
387 offset
= p
->l
+ m
->in
.offset
;
391 if (offset
+ sizeof(union VALUETYPE
) > nbytes
)
394 memcpy(p
, s
+ offset
, sizeof(union VALUETYPE
));
397 mdebug(offset
, (char *) p
, sizeof(union VALUETYPE
));
412 register uint32 l
= m
->value
.l
;
416 if ( (m
->value
.s
[0] == 'x') && (m
->value
.s
[1] == '\0') ) {
417 fprintf(stderr
, "BOINK");
444 /* What we want here is:
445 * v = strncmp(m->value.s, p->s, m->vallen);
446 * but ignoring any nulls. bcmp doesn't give -/+/0
447 * and isn't universally available anyway.
451 register unsigned char *a
= (unsigned char*)m
->value
.s
;
452 register unsigned char *b
= (unsigned char*)p
->s
;
453 register int len
= m
->vallen
;
456 if ((v
= *b
++ - *a
++) != '\0')
461 error("invalid type %d in mcheck().\n", m
->type
);
462 return 0;/*NOTREACHED*/
465 v
= signextend(m
, v
) & m
->mask
;
470 (void) fprintf(stderr
, "%u == *any* = 1\n", v
);
477 (void) fprintf(stderr
, "%u != %u = %d\n",
484 (void) fprintf(stderr
, "%u == %u = %d\n",
489 if (m
->flag
& UNSIGNED
) {
492 (void) fprintf(stderr
, "%u > %u = %d\n",
496 matched
= (int32
) v
> (int32
) l
;
498 (void) fprintf(stderr
, "%d > %d = %d\n",
504 if (m
->flag
& UNSIGNED
) {
507 (void) fprintf(stderr
, "%u < %u = %d\n",
511 matched
= (int32
) v
< (int32
) l
;
513 (void) fprintf(stderr
, "%d < %d = %d\n",
519 matched
= (v
& l
) == l
;
521 (void) fprintf(stderr
, "((%x & %x) == %x) = %d\n",
526 matched
= (v
& l
) != l
;
528 (void) fprintf(stderr
, "((%x & %x) != %x) = %d\n",
534 error("mcheck: can't happen: invalid relation %d.\n", m
->reln
);