#endif
#ifndef lint
-FILE_RCSID("@(#)$Id: apprentice.c,v 1.75 2004/03/22 18:48:56 christos Exp $")
+FILE_RCSID("@(#)$Id: apprentice.c,v 1.76 2004/05/12 14:53:01 christos Exp $")
#endif /* lint */
#define EATAB {while (isascii((unsigned char) *l) && \
const char *);
private int apprentice_compile(struct magic_set *, struct magic **, uint32_t *,
const char *);
+private int check_format(struct magic *);
private size_t maxmagic = 0;
private size_t magicsize = sizeof(struct magic);
while ((m->desc[i++] = *l++) != '\0' && i < MAXDESC)
/* NULLBODY */;
+ if (ms->flags & MAGIC_CHECK) {
+ if (!check_format(m))
+ return -1;
+ }
#ifndef COMPILE_ONLY
if (action == FILE_CHECK) {
file_mdump(m);
return 0;
}
+/*
+ * Check that the optional printf format in description matches
+ * the type of the magic.
+ */
+private int
+check_format(struct magic *m)
+{
+ static const char *formats[] = { FILE_FORMAT_STRING };
+ static const char *names[] = { FILE_FORMAT_NAME };
+ char *ptr;
+
+ for (ptr = m->desc; *ptr; ptr++)
+ if (*ptr == '%')
+ break;
+ if (*ptr == '\0') {
+ /* No format string; ok */
+ return 1;
+ }
+ if (m->type >= sizeof(formats)/sizeof(formats[0])) {
+ file_magwarn("Internal error inconsistency between m->type"
+ " and format strings");
+ return 0;
+ }
+ if (formats[m->type] == NULL) {
+ file_magwarn("No format string for `%s' with description `%s'",
+ m->desc, names[m->type]);
+ return 0;
+ }
+ for (; *ptr; ptr++) {
+ if (*ptr == 'l' || *ptr == 'h') {
+ /* XXX: we should really fix this one day */
+ continue;
+ }
+ if (islower((unsigned char)*ptr) || *ptr == 'X')
+ break;
+ }
+ if (*ptr == '\0') {
+ /* Missing format string; bad */
+ file_magwarn("Invalid format `%s' for type `%s'",
+ m->desc, names[m->type]);
+ return 0;
+ }
+ if (strchr(formats[m->type], *ptr) == NULL) {
+ file_magwarn("Printf format `%c' is not valid for type `%s'"
+ " in description `%s'",
+ *ptr, names[m->type], m->desc);
+ return 0;
+ }
+ return 1;
+}
+
/*
* Read a numeric value from a pointer, into the value union of a magic
* pointer, according to the magic type. Update the string pointer to point
*/
/*
* file.h - definitions for file(1) program
- * @(#)$Id: file.h,v 1.60 2004/03/22 19:12:15 christos Exp $
+ * @(#)$Id: file.h,v 1.61 2004/05/12 14:53:01 christos Exp $
*/
#ifndef __file_h__
#define FILE_BELDATE 15
#define FILE_LELDATE 16
#define FILE_REGEX 17
+
+#define FILE_FORMAT_NAME \
+/* 0 */ "invalid 0", \
+/* 1 */ "byte", \
+/* 2 */ "short", \
+/* 3 */ "invalid 3", \
+/* 4 */ "long", \
+/* 5 */ "string", \
+/* 6 */ "date", \
+/* 7 */ "beshort", \
+/* 8 */ "belong", \
+/* 9 */ "bedate" \
+/* 10 */ "leshort", \
+/* 11 */ "lelong", \
+/* 12 */ "ledate", \
+/* 13 */ "pstring", \
+/* 14 */ "ldate", \
+/* 15 */ "beldate", \
+/* 16 */ "leldate", \
+/* 17 */ "regex",
+
+#define FILE_FMT_NUM "cduxXi"
+#define FILE_FMT_STR "s"
+
+#define FILE_FORMAT_STRING \
+/* 0 */ NULL, \
+/* 1 */ FILE_FMT_NUM, \
+/* 2 */ FILE_FMT_NUM, \
+/* 3 */ NULL, \
+/* 4 */ FILE_FMT_NUM, \
+/* 5 */ FILE_FMT_STR, \
+/* 6 */ FILE_FMT_STR, \
+/* 7 */ FILE_FMT_NUM, \
+/* 8 */ FILE_FMT_NUM, \
+/* 9 */ FILE_FMT_STR, \
+/* 10 */ FILE_FMT_NUM, \
+/* 11 */ FILE_FMT_NUM, \
+/* 12 */ FILE_FMT_STR, \
+/* 13 */ FILE_FMT_STR, \
+/* 14 */ FILE_FMT_STR, \
+/* 15 */ FILE_FMT_STR, \
+/* 16 */ FILE_FMT_STR, \
+/* 17 */ FILE_FMT_STR,
+
/* Word 3 */
uint8_t in_op; /* operator for indirection */
uint8_t mask_op; /* operator for mask */