[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