[Midnightbsd-cvs] src: contrib/file: Merge changes.

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Tue Dec 9 13:35:13 EST 2008


Log Message:
-----------
Merge changes.

Modified Files:
--------------
    src/contrib/file:
        file.h (r1.2 -> r1.3)
        funcs.c (r1.2 -> r1.3)
        magic.c (r1.2 -> r1.3)

-------------- next part --------------
Index: magic.c
===================================================================
RCS file: /home/cvs/src/contrib/file/magic.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/file/magic.c -L contrib/file/magic.c -u -r1.2 -r1.3
--- contrib/file/magic.c
+++ contrib/file/magic.c
@@ -35,10 +35,10 @@
 #include <sys/types.h>
 #include <sys/param.h>	/* for MAXPATHLEN */
 #include <sys/stat.h>
-#include <fcntl.h>	/* for open() */
 #ifdef QUICK
 #include <sys/mman.h>
 #endif
+#include <limits.h>	/* for PIPE_BUF */
 
 #if defined(HAVE_UTIMES)
 # include <sys/time.h>
@@ -63,7 +63,7 @@
 #include "patchlevel.h"
 
 #ifndef	lint
-FILE_RCSID("@(#)$Id: magic.c,v 1.24 2004/09/27 15:28:37 christos Exp $")
+FILE_RCSID("@(#)$File: magic.c,v 1.45 2007/12/27 16:35:59 christos Exp $")
 #endif	/* lint */
 
 #ifdef __EMX__
@@ -75,13 +75,21 @@
 private void free_mlist(struct mlist *);
 private void close_and_restore(const struct magic_set *, const char *, int,
     const struct stat *);
+private int info_from_stat(struct magic_set *, mode_t);
+#ifndef COMPILE_ONLY
+private const char *file_or_fd(struct magic_set *, const char *, int);
+#endif
+
+#ifndef	STDIN_FILENO
+#define	STDIN_FILENO	0
+#endif
 
 public struct magic_set *
 magic_open(int flags)
 {
 	struct magic_set *ms;
 
-	if ((ms = malloc(sizeof(struct magic_set))) == NULL)
+	if ((ms = calloc((size_t)1, sizeof(struct magic_set))) == NULL)
 		return NULL;
 
 	if (magic_setflags(ms, flags) == -1) {
@@ -97,13 +105,15 @@
 	if (ms->o.pbuf == NULL)
 		goto free2;
 
-	ms->c.off = malloc((ms->c.len = 10) * sizeof(*ms->c.off));
-	if (ms->c.off == NULL)
+	ms->c.li = malloc((ms->c.len = 10) * sizeof(*ms->c.li));
+	if (ms->c.li == NULL)
 		goto free3;
 	
 	ms->haderr = 0;
 	ms->error = -1;
 	ms->mlist = NULL;
+	ms->file = "unknown";
+	ms->line = 0;
 	return ms;
 free3:
 	free(ms->o.pbuf);
@@ -132,14 +142,31 @@
 	free(ml);
 }
 
+private int
+info_from_stat(struct magic_set *ms, mode_t md)
+{
+	/* We cannot open it, but we were able to stat it. */
+	if (md & 0222)
+		if (file_printf(ms, "writable, ") == -1)
+			return -1;
+	if (md & 0111)
+		if (file_printf(ms, "executable, ") == -1)
+			return -1;
+	if (S_ISREG(md))
+		if (file_printf(ms, "regular file, ") == -1)
+			return -1;
+	if (file_printf(ms, "no read permission") == -1)
+		return -1;
+	return 0;
+}
+
 public void
-magic_close(ms)
-    struct magic_set *ms;
+magic_close(struct magic_set *ms)
 {
 	free_mlist(ms->mlist);
 	free(ms->o.pbuf);
 	free(ms->o.buf);
-	free(ms->c.off);
+	free(ms->c.li);
 	free(ms);
 }
 
@@ -178,8 +205,11 @@
 close_and_restore(const struct magic_set *ms, const char *name, int fd,
     const struct stat *sb)
 {
+	if (fd == STDIN_FILENO)
+		return;
 	(void) close(fd);
-	if (fd != STDIN_FILENO && (ms->flags & MAGIC_PRESERVE_ATIME) != 0) {
+
+	if ((ms->flags & MAGIC_PRESERVE_ATIME) != 0) {
 		/*
 		 * Try to restore access, modification times if read it.
 		 * This is really *bad* because it will modify the status
@@ -188,6 +218,7 @@
 		 */
 #ifdef HAVE_UTIMES
 		struct timeval  utsbuf[2];
+		memset(utsbuf, 0, sizeof(struct timeval) * 2);
 		utsbuf[0].tv_sec = sb->st_atime;
 		utsbuf[1].tv_sec = sb->st_mtime;
 
@@ -195,6 +226,7 @@
 #elif defined(HAVE_UTIME_H) || defined(HAVE_SYS_UTIME_H)
 		struct utimbuf  utbuf;
 
+		memset(&utbuf, 0, sizeof(struct utimbuf));
 		utbuf.actime = sb->st_atime;
 		utbuf.modtime = sb->st_mtime;
 		(void) utime(name, &utbuf); /* don't care if loses */
@@ -203,101 +235,124 @@
 }
 
 #ifndef COMPILE_ONLY
+
+/*
+ * find type of descriptor
+ */
+public const char *
+magic_descriptor(struct magic_set *ms, int fd)
+{
+	return file_or_fd(ms, NULL, fd);
+}
+
 /*
  * find type of named file
  */
 public const char *
 magic_file(struct magic_set *ms, const char *inname)
 {
-	int	fd = 0;
-	unsigned char buf[HOWMANY+1];	/* one extra for terminating '\0' */
+	return file_or_fd(ms, inname, STDIN_FILENO);
+}
+
+private const char *
+file_or_fd(struct magic_set *ms, const char *inname, int fd)
+{
+	int	rv = -1;
+	unsigned char *buf;
 	struct stat	sb;
 	ssize_t nbytes = 0;	/* number of bytes read from a datafile */
+	int	ispipe = 0;
 
-	if (file_reset(ms) == -1)
+	/*
+	 * one extra for terminating '\0', and
+	 * some overlapping space for matches near EOF
+	 */
+#define SLOP (1 + sizeof(union VALUETYPE))
+	if ((buf = malloc(HOWMANY + SLOP)) == NULL)
 		return NULL;
 
+	if (file_reset(ms) == -1)
+		goto done;
+
 	switch (file_fsmagic(ms, inname, &sb)) {
-	case -1:
-		return NULL;
-	case 0:
+	case -1:		/* error */
+		goto done;
+	case 0:			/* nothing found */
 		break;
-	default:
-		return file_getbuffer(ms);
+	default:		/* matched it and printed type */
+		rv = 0;
+		goto done;
 	}
 
-#ifndef	STDIN_FILENO
-#define	STDIN_FILENO	0
+	if (inname == NULL) {
+		if (fstat(fd, &sb) == 0 && S_ISFIFO(sb.st_mode))
+			ispipe = 1;
+	} else {
+		int flags = O_RDONLY|O_BINARY;
+
+		if (stat(inname, &sb) == 0 && S_ISFIFO(sb.st_mode)) {
+			flags |= O_NONBLOCK;
+			ispipe = 1;
+		}
+
+		errno = 0;
+		if ((fd = open(inname, flags)) < 0) {
+#ifdef __CYGWIN__
+			char *tmp = alloca(strlen(inname) + 5);
+			(void)strcat(strcpy(tmp, inname), ".exe");
+			if ((fd = open(tmp, flags)) < 0) {
+#endif
+				if (info_from_stat(ms, sb.st_mode) == -1)
+					goto done;
+				rv = 0;
+				goto done;
+#ifdef __CYGWIN__
+			}
+#endif
+		}
+#ifdef O_NONBLOCK
+		if ((flags = fcntl(fd, F_GETFL)) != -1) {
+			flags &= ~O_NONBLOCK;
+			(void)fcntl(fd, F_SETFL, flags);
+		}
 #endif
-	if (inname == NULL)
-		fd = STDIN_FILENO;
-	else if ((fd = open(inname, O_RDONLY)) < 0) {
-		/* We cannot open it, but we were able to stat it. */
-		if (sb.st_mode & 0222)
-			if (file_printf(ms, "writable, ") == -1)
-				return NULL;
-		if (sb.st_mode & 0111)
-			if (file_printf(ms, "executable, ") == -1)
-				return NULL;
-		if (S_ISREG(sb.st_mode))
-			if (file_printf(ms, "regular file, ") == -1)
-				return NULL;
-		if (file_printf(ms, "no read permission") == -1)
-			return NULL;
-		return file_getbuffer(ms);
 	}
 
 	/*
 	 * try looking at the first HOWMANY bytes
 	 */
-	if ((nbytes = read(fd, (char *)buf, HOWMANY)) == -1) {
-		file_error(ms, errno, "cannot read `%s'", inname);
-		goto done;
-	}
+	if (ispipe) {
+		ssize_t r = 0;
 
-	if (nbytes == 0) {
-		if (file_printf(ms, (ms->flags & MAGIC_MIME) ?
-		    "application/x-empty" : "empty") == -1)
-			goto done;
-		goto gotit;
-	} else if (nbytes == 1) {
-		if (file_printf(ms, "very short file (no magic)") == -1)
-			goto done;
-		goto gotit;
-	} else {
-		buf[nbytes] = '\0';	/* null-terminate it */
-#ifdef __EMX__
-		switch (file_os2_apptype(ms, inname, buf, nbytes)) {
-		case -1:
+		while ((r = sread(fd, (void *)&buf[nbytes],
+		    (size_t)(HOWMANY - nbytes), 1)) > 0) {
+			nbytes += r;
+			if (r < PIPE_BUF) break;
+		}
+
+		if (nbytes == 0) {
+			/* We can not read it, but we were able to stat it. */
+			if (info_from_stat(ms, sb.st_mode) == -1)
+				goto done;
+			rv = 0;
 			goto done;
-		case 0:
-			break;
-		default:
-			goto gotit;
 		}
-#endif
-		if (file_buffer(ms, buf, (size_t)nbytes) == -1)
+
+	} else {
+		if ((nbytes = read(fd, (char *)buf, HOWMANY)) == -1) {
+			file_error(ms, errno, "cannot read `%s'", inname);
 			goto done;
-#ifdef BUILTIN_ELF
-		if (nbytes > 5) {
-			/*
-			 * We matched something in the file, so this *might*
-			 * be an ELF file, and the file is at least 5 bytes
-			 * long, so if it's an ELF file it has at least one
-			 * byte past the ELF magic number - try extracting
-			 * information from the ELF headers that cannot easily
-			 * be extracted with rules in the magic file.
-			 */
-			file_tryelf(ms, fd, buf, (size_t)nbytes);
 		}
-#endif
 	}
-gotit:
-	close_and_restore(ms, inname, fd, &sb);
-	return file_getbuffer(ms);
+
+	(void)memset(buf + nbytes, 0, SLOP); /* NUL terminate */
+	if (file_buffer(ms, fd, inname, buf, (size_t)nbytes) == -1)
+		goto done;
+	rv = 0;
 done:
+	free(buf);
 	close_and_restore(ms, inname, fd, &sb);
-	return NULL;
+	return rv == 0 ? file_getbuffer(ms) : NULL;
 }
 
 
@@ -310,7 +365,7 @@
 	 * The main work is done here!
 	 * We have the file name and/or the data buffer to be identified. 
 	 */
-	if (file_buffer(ms, buf, nb) == -1) {
+	if (file_buffer(ms, -1, NULL, buf, nb) == -1) {
 		return NULL;
 	}
 	return file_getbuffer(ms);
Index: funcs.c
===================================================================
RCS file: /home/cvs/src/contrib/file/funcs.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/file/funcs.c -L contrib/file/funcs.c -u -r1.2 -r1.3
--- contrib/file/funcs.c
+++ contrib/file/funcs.c
@@ -26,15 +26,35 @@
  */
 #include "file.h"
 #include "magic.h"
-#include <limits.h>
 #include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
+#if defined(HAVE_WCHAR_H)
+#include <wchar.h>
+#endif
+#if defined(HAVE_WCTYPE_H)
+#include <wctype.h>
+#endif
+#if defined(HAVE_LIMITS_H)
+#include <limits.h>
+#endif
+#ifndef SIZE_T_MAX
+#ifdef __LP64__
+#define SIZE_T_MAX (size_t)0xffffffffffffffffU
+#else
+#define SIZE_T_MAX (size_t)0xffffffffU
+#endif
+#endif
 
 #ifndef	lint
-FILE_RCSID("@(#)$Id: funcs.c,v 1.13 2004/09/11 19:15:57 christos Exp $")
+FILE_RCSID("@(#)$File: funcs.c,v 1.35 2007/12/27 16:35:59 christos Exp $")
 #endif	/* lint */
+
+#ifndef HAVE_VSNPRINTF
+int vsnprintf(char *, size_t, const char *, va_list);
+#endif
+
 /*
  * Like printf, only we print to a buffer and advance it.
  */
@@ -42,18 +62,22 @@
 file_printf(struct magic_set *ms, const char *fmt, ...)
 {
 	va_list ap;
-	size_t len, size;
+	size_t size;
+	ssize_t len;
 	char *buf;
 
 	va_start(ap, fmt);
 
-	if ((len = vsnprintf(ms->o.ptr, ms->o.left, fmt, ap)) >= ms->o.left) {
-		long diff;  /* XXX: really ptrdiff_t */
+	len = vsnprintf(ms->o.ptr, ms->o.left, fmt, ap);
+	if (len == -1)
+		goto out;
+	if (len >= (ssize_t)ms->o.left) {
+		long diff;	/* XXX: really ptrdiff_t */
 
 		va_end(ap);
 		size = (ms->o.size - ms->o.left) + len + 1024;
 		if ((buf = realloc(ms->o.buf, size)) == NULL) {
-			file_oomem(ms);
+			file_oomem(ms, size);
 			return -1;
 		}
 		diff = ms->o.ptr - ms->o.buf;
@@ -64,29 +88,38 @@
 
 		va_start(ap, fmt);
 		len = vsnprintf(ms->o.ptr, ms->o.left, fmt, ap);
+		if (len == -1)
+			goto out;
 	}
+	va_end(ap);
 	ms->o.ptr += len;
 	ms->o.left -= len;
-	va_end(ap);
 	return 0;
+out:
+	file_error(ms, errno, "vsnprintf failed");
+	return -1;
 }
 
 /*
  * error - print best error message possible
  */
 /*VARARGS*/
-protected void
-file_error(struct magic_set *ms, int error, const char *f, ...)
+private void
+file_error_core(struct magic_set *ms, int error, const char *f, va_list va,
+    uint32_t lineno)
 {
-	va_list va;
+	size_t len;
 	/* Only the first error is ok */
 	if (ms->haderr)
 		return;
-	va_start(va, f);
-	(void)vsnprintf(ms->o.buf, ms->o.size, f, va);
-	va_end(va);
+	len = 0;
+	if (lineno != 0) {
+		(void)snprintf(ms->o.buf, ms->o.size, "line %u: ", lineno);
+		len = strlen(ms->o.buf);
+	}
+	(void)vsnprintf(ms->o.buf + len, ms->o.size - len, f, va);
 	if (error > 0) {
-		size_t len = strlen(ms->o.buf);
+		len = strlen(ms->o.buf);
 		(void)snprintf(ms->o.buf + len, ms->o.size - len, " (%s)",
 		    strerror(error));
 	}
@@ -94,11 +127,33 @@
 	ms->error = error;
 }
 
+/*VARARGS*/
+protected void
+file_error(struct magic_set *ms, int error, const char *f, ...)
+{
+	va_list va;
+	va_start(va, f);
+	file_error_core(ms, error, f, va, 0);
+	va_end(va);
+}
 
+/*
+ * Print an error with magic line number.
+ */
+/*VARARGS*/
 protected void
-file_oomem(struct magic_set *ms)
+file_magerror(struct magic_set *ms, const char *f, ...)
 {
-	file_error(ms, errno, "cannot allocate memory");
+	va_list va;
+	va_start(va, f);
+	file_error_core(ms, 0, f, va, ms->line);
+	va_end(va);
+}
+
+protected void
+file_oomem(struct magic_set *ms, size_t len)
+{
+	file_error(ms, errno, "cannot allocate %zu bytes", len);
 }
 
 protected void
@@ -115,27 +170,76 @@
 
 #ifndef COMPILE_ONLY
 protected int
-file_buffer(struct magic_set *ms, const void *buf, size_t nb)
+file_buffer(struct magic_set *ms, int fd, const char *inname, const void *buf,
+    size_t nb)
 {
-    int m;
-    /* try compression stuff */
-    if ((m = file_zmagic(ms, buf, nb)) == 0) {
-	/* Check if we have a tar file */
-	if ((m = file_is_tar(ms, buf, nb)) == 0) {
-	    /* try tests in /etc/magic (or surrogate magic file) */
-	    if ((m = file_softmagic(ms, buf, nb)) == 0) {
-		/* try known keywords, check whether it is ASCII */
-		if ((m = file_ascmagic(ms, buf, nb)) == 0) {
-		    /* abandon hope, all ye who remain here */
-		    if (file_printf(ms, ms->flags & MAGIC_MIME ?
-			"application/octet-stream" : "data") == -1)
-			    return -1;
-		    m = 1;
+	int m;
+	int mime = ms->flags & MAGIC_MIME;
+
+	if (nb == 0) {
+		if ((!mime || (mime & MAGIC_MIME_TYPE)) &&
+		    file_printf(ms, mime ? "application/x-empty" :
+		    "empty") == -1)
+			return -1;
+		return 1;
+	} else if (nb == 1) {
+		if ((!mime || (mime & MAGIC_MIME_TYPE)) &&
+		    file_printf(ms, mime ?  "application/octet-stream" :
+		    "very short file (no magic)") == -1)
+			return -1;
+		return 1;
+	}
+
+#ifdef __EMX__
+	if ((ms->flags & MAGIC_NO_CHECK_APPTYPE) == 0 && inname) {
+		switch (file_os2_apptype(ms, inname, buf, nb)) {
+		case -1:
+			return -1;
+		case 0:
+			break;
+		default:
+			return 1;
+		}
+	}
+#endif
+
+	/* try compression stuff */
+	if ((ms->flags & MAGIC_NO_CHECK_COMPRESS) != 0 ||
+	    (m = file_zmagic(ms, fd, inname, buf, nb)) == 0) {
+	    /* Check if we have a tar file */
+	    if ((ms->flags & MAGIC_NO_CHECK_TAR) != 0 ||
+		(m = file_is_tar(ms, buf, nb)) == 0) {
+		/* try tests in /etc/magic (or surrogate magic file) */
+		if ((ms->flags & MAGIC_NO_CHECK_SOFT) != 0 ||
+		    (m = file_softmagic(ms, buf, nb)) == 0) {
+		    /* try known keywords, check whether it is ASCII */
+		    if ((ms->flags & MAGIC_NO_CHECK_ASCII) != 0 ||
+			(m = file_ascmagic(ms, buf, nb)) == 0) {
+			/* abandon hope, all ye who remain here */
+			if ((!mime || (mime & MAGIC_MIME_TYPE)) &&
+			    file_printf(ms, mime ?  "application/octet-stream" :
+				"data") == -1)
+				return -1;
+			m = 1;
+		    }
 		}
 	    }
 	}
-    }
-    return m;
+#ifdef BUILTIN_ELF
+	if ((ms->flags & MAGIC_NO_CHECK_ELF) == 0 && m == 1 &&
+	    nb > 5 && fd != -1) {
+		/*
+		 * We matched something in the file, so this *might*
+		 * be an ELF file, and the file is at least 5 bytes
+		 * long, so if it's an ELF file it has at least one
+		 * byte past the ELF magic number - try extracting
+		 * information from the ELF headers that cannot easily
+		 * be extracted with rules in the magic file.
+		 */
+		(void)file_tryelf(ms, fd, buf, nb);
+	}
+#endif
+	return m;
 }
 #endif
 
@@ -147,11 +251,20 @@
 		return -1;
 	}
 	ms->o.ptr = ms->o.buf;
+	ms->o.left = ms->o.size;
 	ms->haderr = 0;
 	ms->error = -1;
 	return 0;
 }
 
+#define OCTALIFY(n, o)	\
+	/*LINTED*/ \
+	(void)(*(n)++ = '\\', \
+	*(n)++ = (((uint32_t)*(o) >> 6) & 3) + '0', \
+	*(n)++ = (((uint32_t)*(o) >> 3) & 7) + '0', \
+	*(n)++ = (((uint32_t)*(o) >> 0) & 7) + '0', \
+	(o)++)
+
 protected const char *
 file_getbuffer(struct magic_set *ms)
 {
@@ -165,31 +278,114 @@
 		return ms->o.buf;
 
 	len = ms->o.size - ms->o.left;
+	/* * 4 is for octal representation, + 1 is for NUL */
 	if (len > (SIZE_T_MAX - 1) / 4) {
-		file_oomem(ms);
+		file_oomem(ms, len);
 		return NULL;
 	}
-	/* * 4 is for octal representation, + 1 is for NUL */
 	psize = len * 4 + 1;
 	if (ms->o.psize < psize) {
 		if ((pbuf = realloc(ms->o.pbuf, psize)) == NULL) {
-			file_oomem(ms);
+			file_oomem(ms, psize);
 			return NULL;
 		}
 		ms->o.psize = psize;
 		ms->o.pbuf = pbuf;
 	}
 
+#if defined(HAVE_WCHAR_H) && defined(HAVE_MBRTOWC) && defined(HAVE_WCWIDTH)
+	{
+		mbstate_t state;
+		wchar_t nextchar;
+		int mb_conv = 1;
+		size_t bytesconsumed;
+		char *eop;
+		(void)memset(&state, 0, sizeof(mbstate_t));
+
+		np = ms->o.pbuf;
+		op = ms->o.buf;
+		eop = op + strlen(ms->o.buf);
+
+		while (op < eop) {
+			bytesconsumed = mbrtowc(&nextchar, op,
+			    (size_t)(eop - op), &state);
+			if (bytesconsumed == (size_t)(-1) ||
+			    bytesconsumed == (size_t)(-2)) {
+				mb_conv = 0;
+				break;
+			}
+
+			if (iswprint(nextchar)) {
+				(void)memcpy(np, op, bytesconsumed);
+				op += bytesconsumed;
+				np += bytesconsumed;
+			} else {
+				while (bytesconsumed-- > 0)
+					OCTALIFY(np, op);
+			}
+		}
+		*np = '\0';
+
+		/* Parsing succeeded as a multi-byte sequence */
+		if (mb_conv != 0)
+			return ms->o.pbuf;
+	}
+#endif
+
 	for (np = ms->o.pbuf, op = ms->o.buf; *op; op++) {
 		if (isprint((unsigned char)*op)) {
 			*np++ = *op;	
 		} else {
-			*np++ = '\\';
-			*np++ = ((*op >> 6) & 3) + '0';
-			*np++ = ((*op >> 3) & 7) + '0';
-			*np++ = ((*op >> 0) & 7) + '0';
+			OCTALIFY(np, op);
 		}
 	}
 	*np = '\0';
 	return ms->o.pbuf;
 }
+
+protected int
+file_check_mem(struct magic_set *ms, unsigned int level)
+{
+	size_t len;
+
+	if (level >= ms->c.len) {
+		len = (ms->c.len += 20) * sizeof(*ms->c.li);
+		ms->c.li = (ms->c.li == NULL) ? malloc(len) :
+		    realloc(ms->c.li, len);
+		if (ms->c.li == NULL) {
+			file_oomem(ms, len);
+			return -1;
+		}
+	}
+	ms->c.li[level].got_match = 0;
+#ifdef ENABLE_CONDITIONALS
+	ms->c.li[level].last_match = 0;
+	ms->c.li[level].last_cond = COND_NONE;
+#endif /* ENABLE_CONDITIONALS */
+	return 0;
+}
+/*
+ * Yes these wrappers suffer from buffer overflows, but if your OS does not
+ * have the real functions, maybe you should consider replacing your OS?
+ */
+#ifndef HAVE_VSNPRINTF
+int
+vsnprintf(char *buf, size_t len, const char *fmt, va_list ap)
+{
+	return vsprintf(buf, fmt, ap);
+}
+#endif
+
+#ifndef HAVE_SNPRINTF
+/*ARGSUSED*/
+int
+snprintf(char *buf, size_t len, const char *fmt, ...)
+{
+	int rv;
+	va_list ap;
+	va_start(ap, fmt);
+	rv = vsprintf(buf, fmt, ap);
+	va_end(ap);
+	return rv;
+}
+#endif
Index: file.h
===================================================================
RCS file: /home/cvs/src/contrib/file/file.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/file/file.h -L contrib/file/file.h -u -r1.2 -r1.3
--- contrib/file/file.h
+++ contrib/file/file.h
@@ -27,7 +27,7 @@
  */
 /*
  * file.h - definitions for file(1) program
- * @(#)$Id: file.h,v 1.64 2004/11/20 23:50:12 christos Exp $
+ * @(#)$File: file.h,v 1.92 2007/11/08 00:31:37 christos Exp $
  */
 
 #ifndef __file_h__
@@ -39,15 +39,20 @@
 
 #include <stdio.h>	/* Include that here, to make sure __P gets defined */
 #include <errno.h>
+#include <fcntl.h>	/* For open and flags */
 #ifdef HAVE_STDINT_H
 #include <stdint.h>
 #endif
 #ifdef HAVE_INTTYPES_H
 #include <inttypes.h>
 #endif
+#include <regex.h>
+#include <sys/types.h>
 /* Do this here and now, because struct stat gets re-defined on solaris */
 #include <sys/stat.h>
 
+#define ENABLE_CONDITIONALS
+
 #ifndef MAGIC
 #define MAGIC "/etc/magic"
 #endif
@@ -64,15 +69,29 @@
 #endif
 #define public
 
+#ifndef __GNUC_PREREQ__
+#ifdef __GNUC__
+#define	__GNUC_PREREQ__(x, y)						\
+	((__GNUC__ == (x) && __GNUC_MINOR__ >= (y)) ||			\
+	 (__GNUC__ > (x)))
+#else
+#define	__GNUC_PREREQ__(x, y)	0
+#endif
+#endif
+
+#ifndef MIN
+#define	MIN(a,b)	(((a) < (b)) ? (a) : (b))
+#endif
+
 #ifndef HOWMANY
-# define HOWMANY 65536		/* how much of the file to look at */
+# define HOWMANY (256 * 1024)	/* how much of the file to look at */
 #endif
-#define MAXMAGIS 4096		/* max entries in /etc/magic */
+#define MAXMAGIS 8192		/* max entries in /etc/magic */
 #define MAXDESC	64		/* max leng of text description */
 #define MAXstring 32		/* max leng of "string" types */
 
 #define MAGICNO		0xF11E041C
-#define VERSIONNO	2
+#define VERSIONNO	4
 #define FILE_MAGICSIZE	(32 * 4)
 
 #define	FILE_LOAD	0
@@ -84,16 +103,20 @@
 	uint16_t cont_level;	/* level of ">" */
 	uint8_t nospflag;	/* supress space character */
 	uint8_t flag;
-#define INDIR	1		/* if '>(...)' appears,  */
-#define	UNSIGNED 2		/* comparison is unsigned */
-#define OFFADD	4		/* if '>&' appears,  */
+#define INDIR		1	/* if '(...)' appears */
+#define OFFADD		2	/* if '>&' or '>...(&' appears */
+#define INDIROFFADD	4	/* if '>&(' appears */
+#define	UNSIGNED	8	/* comparison is unsigned */
+
 	/* Word 2 */
 	uint8_t reln;		/* relation (0=eq, '>'=gt, etc) */
 	uint8_t vallen;		/* length of string value, if any */
 	uint8_t type;		/* int, short, long or string. */
 	uint8_t in_type;	/* type of indirrection */
+#define 			FILE_INVALID	0
 #define 			FILE_BYTE	1
 #define				FILE_SHORT	2
+#define				FILE_DEFAULT	3
 #define				FILE_LONG	4
 #define				FILE_STRING	5
 #define				FILE_DATE	6
@@ -110,59 +133,54 @@
 #define				FILE_REGEX	17
 #define				FILE_BESTRING16	18
 #define				FILE_LESTRING16	19
-
-#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",		\
-/* 18 */			"bestring16",		\
-/* 19 */			"lestring16",
-
-#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,		\
-/* 18 */			FILE_FMT_STR,		\
-/* 19 */			FILE_FMT_STR,
+#define				FILE_SEARCH	20
+#define				FILE_MEDATE	21
+#define				FILE_MELDATE	22
+#define				FILE_MELONG	23
+#define				FILE_QUAD	24
+#define				FILE_LEQUAD	25
+#define				FILE_BEQUAD	26
+#define				FILE_QDATE	27
+#define				FILE_LEQDATE	28
+#define				FILE_BEQDATE	29
+#define				FILE_QLDATE	30
+#define				FILE_LEQLDATE	31
+#define				FILE_BEQLDATE	32
+#define				FILE_FLOAT	33
+#define				FILE_BEFLOAT	34
+#define				FILE_LEFLOAT	35
+#define				FILE_DOUBLE	36
+#define				FILE_BEDOUBLE	37
+#define				FILE_LEDOUBLE	38
+#define				FILE_NAMES_SIZE	39/* size of array to contain all names */
+
+#define IS_STRING(t) \
+	((t) == FILE_STRING || \
+	 (t) == FILE_PSTRING || \
+	 (t) == FILE_BESTRING16 || \
+	 (t) == FILE_LESTRING16 || \
+	 (t) == FILE_REGEX || \
+	 (t) == FILE_SEARCH || \
+	 (t) == FILE_DEFAULT)
+
+#define FILE_FMT_NONE 0
+#define FILE_FMT_NUM  1 /* "cduxXi" */
+#define FILE_FMT_STR  2 /* "s" */
+#define FILE_FMT_QUAD 3 /* "ll" */
+#define FILE_FMT_FLOAT 4 /* "eEfFgG" */
+#define FILE_FMT_DOUBLE 5 /* "eEfFgG" */
 
 	/* Word 3 */
 	uint8_t in_op;		/* operator for indirection */
 	uint8_t mask_op;	/* operator for mask */
+#ifdef ENABLE_CONDITIONALS
+	uint8_t cond;		/* conditional type */
+	uint8_t dummy1;	
+#else
 	uint8_t dummy1;	
 	uint8_t dummy2;	
+#endif
+
 #define				FILE_OPS	"&|^+-*/%"
 #define				FILE_OPAND	0
 #define				FILE_OPOR	1
@@ -172,38 +190,67 @@
 #define				FILE_OPMULTIPLY	5
 #define				FILE_OPDIVIDE	6
 #define				FILE_OPMODULO	7
-#define				FILE_OPINVERSE	0x80
+#define				FILE_OPS_MASK	0x07 /* mask for above ops */
+#define				FILE_UNUSED_1	0x08
+#define				FILE_UNUSED_2	0x10
+#define				FILE_UNUSED_3	0x20
+#define				FILE_OPINVERSE	0x40
+#define				FILE_OPINDIRECT	0x80
+
+#ifdef ENABLE_CONDITIONALS
+#define				COND_NONE	0
+#define				COND_IF		1
+#define				COND_ELIF	2
+#define				COND_ELSE	3
+#endif /* ENABLE_CONDITIONALS */
+
 	/* Word 4 */
 	uint32_t offset;	/* offset to magic number */
 	/* Word 5 */
-	uint32_t in_offset;	/* offset from indirection */
+	int32_t in_offset;	/* offset from indirection */
 	/* Word 6 */
-	uint32_t mask;	/* mask before comparison with value */
-	/* Word 7 */
-	uint32_t dummy3;
-	/* Word 8 */
-	uint32_t dummp4;
+	uint32_t lineno;	/* line number in magic file */
+	/* Word 7,8 */
+	union {
+		uint64_t _mask;	/* for use with numeric and date types */
+		struct {
+			uint32_t _count;	/* repeat/line count */
+			uint32_t _flags;	/* modifier flags */
+		} _s;		/* for use with string types */
+	} _u;
+#define num_mask _u._mask
+#define str_count _u._s._count
+#define str_flags _u._s._flags
+
 	/* Words 9-16 */
 	union VALUETYPE {
 		uint8_t b;
 		uint16_t h;
 		uint32_t l;
-		char s[MAXstring];
-		char *buf;
+		uint64_t q;
 		uint8_t hs[2];	/* 2 bytes of a fixed-endian "short" */
 		uint8_t hl[4];	/* 4 bytes of a fixed-endian "long" */
+		uint8_t hq[8];	/* 8 bytes of a fixed-endian "quad" */
+		char s[MAXstring];	/* the search string or regex pattern */
+		float f;
+		double d;
 	} value;		/* either number or string */
 	/* Words 17..31 */
 	char desc[MAXDESC];	/* description */
 };
 
 #define BIT(A)   (1 << (A))
-#define STRING_IGNORE_LOWERCASE		BIT(0)
-#define STRING_COMPACT_BLANK		BIT(1)
-#define STRING_COMPACT_OPTIONAL_BLANK	BIT(2)
-#define CHAR_IGNORE_LOWERCASE		'c'
+#define STRING_COMPACT_BLANK		BIT(0)
+#define STRING_COMPACT_OPTIONAL_BLANK	BIT(1)
+#define STRING_IGNORE_LOWERCASE		BIT(2)
+#define STRING_IGNORE_UPPERCASE		BIT(3)
+#define REGEX_OFFSET_START		BIT(4)
 #define CHAR_COMPACT_BLANK		'B'
 #define CHAR_COMPACT_OPTIONAL_BLANK	'b'
+#define CHAR_IGNORE_LOWERCASE		'c'
+#define CHAR_IGNORE_UPPERCASE		'C'
+#define CHAR_REGEX_OFFSET_START		's'
+#define STRING_IGNORE_CASE		(STRING_IGNORE_LOWERCASE|STRING_IGNORE_UPPERCASE)
 
 
 /* list of magic entries */
@@ -217,52 +264,82 @@
 };
 
 struct magic_set {
-    struct mlist *mlist;
-    struct cont {
-	size_t len;
-	int32_t *off;
-    } c;
-    struct out {
-	/* Accumulation buffer */
-	char *buf;
-	char *ptr;
-	size_t left;
-	size_t size;
-	/* Printable buffer */
-	char *pbuf;
-	size_t psize;
-    } o;
-    int error;
-    int flags;
-    int haderr;
-    const char *file;
-    size_t line;
+	struct mlist *mlist;
+	struct cont {
+		size_t len;
+		struct level_info {
+			int32_t off;
+			int got_match;
+#ifdef ENABLE_CONDITIONALS
+			int last_match;
+			int last_cond;	/* used for error checking by parse() */
+#endif
+		} *li;
+	} c;
+	struct out {
+		/* Accumulation buffer */
+		char *buf;
+		char *ptr;
+		size_t left;
+		size_t size;
+		/* Printable buffer */
+		char *pbuf;
+		size_t psize;
+	} o;
+	uint32_t offset;
+	int error;
+	int flags;
+	int haderr;
+	const char *file;
+	size_t line;			/* current magic line number */
+
+	/* data for searches */
+	struct {
+		const char *s;		/* start of search in original source */
+		size_t s_len;		/* length of search region */
+		size_t offset;		/* starting offset in source: XXX - should this be off_t? */
+		size_t rm_len;		/* match length */
+	} search;
+
+	union VALUETYPE ms_value;	/* either number or string */
 };
 
 struct stat;
-protected char *file_fmttime(uint32_t, int);
-protected int file_buffer(struct magic_set *, const void *, size_t);
+protected const char *file_fmttime(uint32_t, int);
+protected int file_buffer(struct magic_set *, int, const char *, const void *,
+    size_t);
 protected int file_fsmagic(struct magic_set *, const char *, struct stat *);
 protected int file_pipe2file(struct magic_set *, int, const void *, size_t);
 protected int file_printf(struct magic_set *, const char *, ...);
 protected int file_reset(struct magic_set *);
-protected int file_tryelf(struct magic_set *, int, const unsigned char *, size_t);
-protected int file_zmagic(struct magic_set *, const unsigned char *, size_t);
+protected int file_tryelf(struct magic_set *, int, const unsigned char *,
+    size_t);
+protected int file_zmagic(struct magic_set *, int, const char *,
+    const unsigned char *, size_t);
 protected int file_ascmagic(struct magic_set *, const unsigned char *, size_t);
 protected int file_is_tar(struct magic_set *, const unsigned char *, size_t);
 protected int file_softmagic(struct magic_set *, const unsigned char *, size_t);
 protected struct mlist *file_apprentice(struct magic_set *, const char *, int);
-protected uint32_t file_signextend(struct magic_set *, struct magic *, uint32_t);
+protected uint64_t file_signextend(struct magic_set *, struct magic *,
+    uint64_t);
 protected void file_delmagic(struct magic *, int type, size_t entries);
 protected void file_badread(struct magic_set *);
 protected void file_badseek(struct magic_set *);
-protected void file_oomem(struct magic_set *);
+protected void file_oomem(struct magic_set *, size_t);
 protected void file_error(struct magic_set *, int, const char *, ...);
+protected void file_magerror(struct magic_set *, const char *, ...);
 protected void file_magwarn(struct magic_set *, const char *, ...);
 protected void file_mdump(struct magic *);
 protected void file_showstr(FILE *, const char *, size_t);
 protected size_t file_mbswidth(const char *);
 protected const char *file_getbuffer(struct magic_set *);
+protected ssize_t sread(int, void *, size_t, int);
+protected int file_check_mem(struct magic_set *, unsigned int);
+
+#ifndef COMPILE_ONLY
+extern const char *file_names[];
+extern const size_t file_nnames;
+#endif
 
 #ifndef HAVE_STRERROR
 extern int sys_nerr;
@@ -275,14 +352,21 @@
 #define strtoul(a, b, c)	strtol(a, b, c)
 #endif
 
+#ifndef HAVE_SNPRINTF
+int snprintf(char *, size_t, const char *, ...);
+#endif
+
 #if defined(HAVE_MMAP) && defined(HAVE_SYS_MMAN_H) && !defined(QUICK)
 #define QUICK
 #endif
 
+#ifndef O_BINARY
+#define O_BINARY	0
+#endif
+
 #define FILE_RCSID(id) \
 static const char *rcsid(const char *p) { \
 	return rcsid(p = id); \
 }
-#else
 
 #endif /* __file_h__ */


More information about the Midnightbsd-cvs mailing list