4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
29 /* Copyright (c) 1987, 1988 Microsoft Corporation */
30 /* All Rights Reserved */
32 #pragma ident "%Z%%M% %I% %E% SMI"
41 #include <sys/types.h>
65 #define STRC 3 /* string compare */
68 #define NSET 6 /* True if bit is not set */
69 #define SUB 64 /* or'ed in, SUBstitution string, for example */
70 /* %ld, %s, %lo mask: with bit 6 on, used to locate */
80 * Structure of magic file entry
84 char e_level
; /* 0 or 1 */
85 off_t e_off
; /* in bytes */
86 uint32_t e_type
; /* BYTE, SHORT, STR, et al */
87 char e_opcode
; /* EQ, GT, LT, ANY, AND, NSET */
88 uint64_t e_mask
; /* if non-zero, mask value with this */
96 /* Non-localized string giving name of command. Defined in file.c */
97 extern const char *File
;
99 typedef struct entry Entry
;
101 static Entry
*mtab1
; /* 1st magic table, applied before default tests */
104 * 2nd magic table, includes default tests and magic entries
105 * to be applied after default position-sensitive tests
109 static Entry
*mend1
; /* one past last-allocated entry in mtab1 */
110 static Entry
*mend2
; /* one past last-allocated entry in mtab2 */
112 static Entry
*ep1
; /* current entry in mtab1 */
113 static Entry
*ep2
; /* current entry in mtab2 */
116 getstr(char *p
, char *file
)
123 newstr
= (char *)malloc((strlen(p
) + 1) * sizeof (char));
124 if (newstr
== NULL
) {
126 (void) fprintf(stderr
, gettext("%s: malloc failed: %s\n"),
127 File
, strerror(err
));
141 if (*p
== '0' && (*(p
+1) == 'x' || *(p
+1) == 'X')) {
148 val
= strtol(p
, &p
, base
);
149 if (val
> UCHAR_MAX
|| val
< 0 || errno
!= 0) {
150 (void) fprintf(stderr
, gettext("%s: %s: magic "
151 "table invalid string value\n"), File
,
157 /* escape the character */
193 * f_mkmtab - fills mtab array of magic table entries with
194 * values from the file magfile.
195 * May be called more than once if multiple magic
196 * files were specified.
197 * Stores entries sequentially in one of two magic
198 * tables: mtab1, if first = 1; mtab2 otherwise.
200 * If -c option is specified, cflg is non-zero, and
201 * f_mkmtab() reports on errors in the magic file.
203 * Two magic tables may need to be created. The first
204 * one (mtab1) contains magic entries to be checked before
205 * the programmatic default position-sensitive tests in
206 * def_position_tests().
207 * The second one (mtab2) should start with the default
208 * /etc/magic file entries and is to be checked after
209 * the programmatic default position-sensitive tests in
210 * def_position_tests(). The parameter "first" would
211 * be 1 for the former set of tables, 0 for the latter
212 * set of magic tables.
213 * No mtab2 should be created if file will not be
214 * applying default tests; in that case, all magic table
215 * entries should be in mtab1.
217 * f_mkmtab returns 0 on success, -1 on error. The calling
218 * program is not expected to proceed after f_mkmtab()
223 f_mkmtab(char *magfile
, int cflg
, int first
)
225 Entry
*mtab
; /* generic magic table pointer */
226 Entry
*ep
; /* current magic table entry */
227 Entry
*mend
; /* one past last-allocated entry of mtab */
244 /* mtab may have been allocated on a previous f_mkmtab call */
245 if (mtab
== (Entry
*)NULL
) {
246 if ((mtab
= calloc(sizeof (Entry
), NENT
)) == NULL
) {
248 (void) fprintf(stderr
, gettext("%s: malloc "
249 "failed: %s\n"), File
, strerror(err
));
258 if ((fp
= fopen(magfile
, "r")) == NULL
) {
260 (void) fprintf(stderr
, gettext("%s: %s: cannot open magic "
261 "file: %s\n"), File
, magfile
, err
? strerror(err
) : "");
264 while (fgets(buf
, BSZ
, fp
) != NULL
) {
271 * ensure we have one extra entry allocated
272 * to mark end of the table, after the while loop
274 if (ep
>= (mend
- 1)) {
275 oldsize
= mend
- mtab
;
276 tbsize
= (NENT
+ oldsize
) * sizeof (Entry
);
277 if ((mtab
= realloc(mtab
, tbsize
)) == NULL
) {
279 (void) fprintf(stderr
, gettext("%s: malloc "
280 "failed: %s\n"), File
, strerror(err
));
283 (void) memset(mtab
+ oldsize
, 0,
284 sizeof (Entry
) * NENT
);
285 mend
= &mtab
[tbsize
/ sizeof (Entry
)];
286 ep
= &mtab
[oldsize
-1];
291 if (*p
== '\n' || *p
== '#')
301 p2
= strchr(p
, '\t');
304 (void) fprintf(stderr
, gettext("%s: %s: format "
305 "error, no tab after %s on line %d\n"),
306 File
, magfile
, p
, lcnt
);
310 ep
->e_off
= strtol((const char *)p
, (char **)NULL
, 0);
315 p2
= strchr(p
, '\t');
318 (void) fprintf(stderr
, gettext("%s: %s: format "
319 "error, no tab after %s on line %d\n"),
320 File
, magfile
, p
, lcnt
);
327 ep
->e_mask
= strtoull((const char *)p3
, (char **)NULL
,
328 0); /* returns 0 or ULLONG_MAX on error */
334 if (*(p
+1) == NULL
) {
337 } else if (*(p
+2) == NULL
) { /* d? */
366 if (*(p
+1) == 'l') { /* llong */
382 if (*(p
+1) == NULL
) {
385 } else if (*(p
+2) == NULL
) { /* u? */
413 case 'b': /* ubyte */
416 case 's': /* ushort */
429 /* default, same as "u" */
436 /* retain (undocumented) default type */
440 if (ep
->e_type
== 0) {
441 ep
->e_type
= BYTE
; /* default */
447 p2
= strchr(p
, '\t');
450 (void) fprintf(stderr
, gettext("%s: %s: format "
451 "error, no tab after %s on line %d\n"),
452 File
, magfile
, p
, lcnt
);
456 if (ep
->e_type
!= STR
) {
482 default: /* EQ (i.e. 0) is default */
483 p
--; /* since global ep->e_opcode=0 */
486 if (ep
->e_opcode
!= ANY
) {
487 if (ep
->e_type
!= STR
) {
488 ep
->e_value
.num
= strtoull((const char *)p
,
490 } else if ((ep
->e_value
.str
=
491 getstr(p
, magfile
)) == NULL
) {
495 p2
+= strspn(p2
, "\t");
497 if ((ep
->e_str
= strdup(p2
)) == NULL
) {
499 (void) fprintf(stderr
, gettext("%s: malloc "
500 "failed: %s\n"), File
, strerror(err
));
503 if ((p
= strchr(ep
->e_str
, '\n')) != NULL
)
505 if (strchr(ep
->e_str
, '%') != NULL
)
509 } /* end while (fgets) */
511 ep
->e_off
= -1L; /* mark end of table */
521 if (fclose(fp
) != 0) {
523 (void) fprintf(stderr
, gettext("%s: fclose failed: %s\n"),
524 File
, strerror(err
));
531 * Check for Magic Table entries in the file.
533 * Since there may be two sets of magic tables, first = 1
534 * for the first magic table (mtab1) and 0 for the second magic
538 f_ckmtab(char *buf
, int bufsize
, int first
)
556 if (mtab
== (Entry
*)NULL
) {
557 return (0); /* no magic file tests in this table */
560 for (ep
= mtab
; ep
->e_off
!= -1L; ep
++) { /* -1 offset marks end of */
561 if (lev1
) { /* valid magic file entries */
562 if (ep
->e_level
!= 1)
564 } else if (ep
->e_level
== 1) {
567 if (ep
->e_off
> (off_t
)bufsize
)
570 switch (ep
->e_type
) {
573 if (strncmp(p
, ep
->e_value
.str
,
574 strlen(ep
->e_value
.str
)))
579 if (ep
->e_opcode
& SUB
)
580 (void) printf(ep
->e_str
,
583 (void) printf(ep
->e_str
);
587 * We've matched the string and printed the message;
588 * no STR processing occurs beyond this point.
594 u64_val
= (uint64_t)(uint8_t)(*p
);
599 (void) memcpy(&u16_val
, p
, sizeof (uint16_t));
600 u64_val
= (uint64_t)u16_val
;
605 (void) memcpy(&u32_val
, p
, sizeof (uint32_t));
606 u64_val
= (uint64_t)u32_val
;
611 (void) memcpy(&(u64_val
), p
, sizeof (uint64_t));
617 u64_val
&= ep
->e_mask
;
621 * Compare the values according to the size and sign
622 * of the type. For =, &, and ^ operators, the sign
623 * does not have any effect, so these are always compared
624 * unsigned. Only for < and > operators is the
626 * If the file value was masked, the compare should
629 switch (ep
->e_opcode
& ~SUB
) {
631 switch (ep
->e_type
) {
634 if ((uint8_t)u64_val
!=
635 (uint8_t)(ep
->e_value
.num
))
640 if ((uint16_t)u64_val
!=
641 (uint16_t)(ep
->e_value
.num
))
646 if ((uint32_t)u64_val
!=
647 (uint32_t)(ep
->e_value
.num
))
652 if (u64_val
!= ep
->e_value
.num
)
660 switch (ep
->e_type
) {
662 if (ep
->e_mask
== 0) {
663 if ((int8_t)u64_val
<=
664 (int8_t)(ep
->e_value
.num
))
670 if ((uint8_t)u64_val
<=
671 (uint8_t)(ep
->e_value
.num
))
675 if (ep
->e_mask
== 0) {
676 if ((int16_t)u64_val
<=
677 (int16_t)(ep
->e_value
.num
))
683 if ((uint16_t)u64_val
<=
684 (uint16_t)(ep
->e_value
.num
))
688 if (ep
->e_mask
== 0) {
689 if ((int32_t)u64_val
<=
690 (int32_t)(ep
->e_value
.num
))
696 if ((uint32_t)u64_val
<=
697 (uint32_t)(ep
->e_value
.num
))
701 if (ep
->e_mask
== 0) {
702 if ((int64_t)u64_val
<=
703 (int64_t)(ep
->e_value
.num
))
709 if (u64_val
<= ep
->e_value
.num
)
717 switch (ep
->e_type
) {
719 if (ep
->e_mask
== 0) {
720 if ((int8_t)u64_val
>=
721 (int8_t)(ep
->e_value
.num
))
727 if ((uint8_t)u64_val
>=
728 (uint8_t)(ep
->e_value
.num
))
732 if (ep
->e_mask
== 0) {
733 if ((int16_t)u64_val
>=
734 (int16_t)(ep
->e_value
.num
))
740 if ((uint16_t)u64_val
>=
741 (uint16_t)(ep
->e_value
.num
))
745 if (ep
->e_mask
== 0) {
746 if ((int32_t)u64_val
>=
747 (int32_t)(ep
->e_value
.num
))
753 if ((uint32_t)u64_val
>=
754 (uint32_t)(ep
->e_value
.num
))
758 if (ep
->e_mask
== 0) {
759 if ((int64_t)u64_val
>=
760 (int64_t)(ep
->e_value
.num
))
766 if (u64_val
>= ep
->e_value
.num
)
774 switch (ep
->e_type
) {
777 if (((uint8_t)u64_val
&
778 (uint8_t)(ep
->e_value
.num
)) ==
779 (uint8_t)(ep
->e_value
.num
))
784 if (((uint16_t)u64_val
&
785 (uint16_t)(ep
->e_value
.num
)) ==
786 (uint16_t)(ep
->e_value
.num
))
791 if (((uint32_t)u64_val
&
792 (uint32_t)(ep
->e_value
.num
)) ==
793 (uint32_t)(ep
->e_value
.num
))
798 if ((u64_val
& ep
->e_value
.num
) ==
807 switch (ep
->e_type
) {
810 if (((uint8_t)u64_val
&
811 (uint8_t)(ep
->e_value
.num
)) !=
812 (uint8_t)(ep
->e_value
.num
))
817 if (((uint16_t)u64_val
&
818 (uint16_t)(ep
->e_value
.num
)) !=
819 (uint16_t)(ep
->e_value
.num
))
824 if (((uint32_t)u64_val
&
825 (uint32_t)(ep
->e_value
.num
)) !=
826 (uint32_t)(ep
->e_value
.num
))
831 if ((u64_val
& ep
->e_value
.num
) !=
839 case ANY
: /* matches anything */
841 default: /* shouldn't occur; ignore it */
846 if (ep
->e_opcode
& SUB
) {
847 switch (ep
->e_type
) {
850 if (ep
->e_mask
== 0) {
851 (void) printf(ep
->e_str
,
858 (void) printf(ep
->e_str
, u64_val
);
862 if (ep
->e_mask
== 0) {
863 (void) printf(ep
->e_str
,
870 (void) printf(ep
->e_str
,
875 if (ep
->e_mask
== 0) {
876 (void) printf(ep
->e_str
,
883 (void) printf(ep
->e_str
,
888 if (ep
->e_mask
== 0) {
889 (void) printf(ep
->e_str
,
896 (void) printf(ep
->e_str
,
901 * Note: Currently can't get type
902 * STR here because we already
903 * did a 'continue' out of the
904 * loop earlier for case STR
909 (void) printf(ep
->e_str
);
912 result
= lev1
? (int)(1 + ep
- mtab
) : 0;
918 showstr(char *s
, int width
)
922 while ((c
= *s
++) != '\0')
923 if (c
>= 040 && c
< 0176) {
927 (void) putchar('\\');
966 (void) printf("%.3o", c
& 0377);
978 type_to_name(Entry
*ep
)
983 switch (ep
->e_type
) {
1011 /* more of an emergency measure .. */
1012 (void) sprintf(buf
, "%d", ep
->e_type
);
1016 (void) snprintf(buf
, sizeof (buf
), "%s&0x%llx", s
, ep
->e_mask
);
1027 switch (op
& ~SUB
) {
1063 * f_prtmtab - Prints out a header, then entries from both magic
1064 * tables, mtab1 and mtab2, if any exist.
1073 (void) printf("%-7s %-7s %-10s %-7s %-11s %s\n",
1074 "level", "off", "type", "opcode", "value", "string");
1075 for (mtab
= mtab1
, count
= 1; count
<= 2; count
++, mtab
= mtab2
) {
1076 if (mtab
== (Entry
*)NULL
) {
1079 for (ep
= mtab
; ep
->e_off
!= -1L; ep
++) {
1080 (void) printf("%-7d %-7ld %-10s %-7c ",
1082 ep
->e_off
, type_to_name(ep
),
1083 op_to_name(ep
->e_opcode
));
1084 if (ep
->e_type
== STR
) {
1085 showstr(ep
->e_value
.str
, 10);
1086 } else { /* numeric */
1087 (void) printf("%-#11llo", ep
->e_value
.num
);
1089 (void) printf(" %s", ep
->e_str
);
1090 if (ep
->e_opcode
& SUB
)
1091 (void) printf("\tsubst");
1092 (void) printf("\n");
1098 f_getmaxoffset(int first
)
1110 if (mtab
== (Entry
*)NULL
) {
1113 for (ep
= mtab
; ep
->e_off
!= -1L; ep
++) {
1115 switch (ep
->e_type
) {
1117 cur
+= strlen(ep
->e_value
.str
);
1121 cur
+= sizeof (uchar_t
);
1125 cur
+= sizeof (uint16_t);
1129 cur
+= sizeof (uint32_t);
1133 cur
+= sizeof (uint64_t);
1136 if (cur
<= INT_MAX
&& cur
> max
) {