diff options
Diffstat (limited to 'contrib/file/funcs.c')
-rw-r--r-- | contrib/file/funcs.c | 161 |
1 files changed, 116 insertions, 45 deletions
diff --git a/contrib/file/funcs.c b/contrib/file/funcs.c index af98605..af10688 100644 --- a/contrib/file/funcs.c +++ b/contrib/file/funcs.c @@ -1,7 +1,7 @@ /* * Copyright (c) Christos Zoulas 2003. * All Rights Reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -11,7 +11,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -25,6 +25,11 @@ * SUCH DAMAGE. */ #include "file.h" + +#ifndef lint +FILE_RCSID("@(#)$File: funcs.c,v 1.51 2008/11/07 18:57:28 christos Exp $") +#endif /* lint */ + #include "magic.h" #include <stdarg.h> #include <stdlib.h> @@ -40,10 +45,6 @@ #include <limits.h> #endif -#ifndef lint -FILE_RCSID("@(#)$File: funcs.c,v 1.44 2008/07/16 18:00:57 christos Exp $") -#endif /* lint */ - #ifndef SIZE_MAX #define SIZE_MAX ((size_t)~0) #endif @@ -97,17 +98,17 @@ file_error_core(struct magic_set *ms, int error, const char *f, va_list va, uint32_t lineno) { /* Only the first error is ok */ - if (ms->haderr) + if (ms->event_flags & EVENT_HAD_ERR) return; if (lineno != 0) { free(ms->o.buf); ms->o.buf = NULL; file_printf(ms, "line %u: ", lineno); } - file_vprintf(ms, f, va); + file_vprintf(ms, f, va); if (error > 0) file_printf(ms, " (%s)", strerror(error)); - ms->haderr++; + ms->event_flags |= EVENT_HAD_ERR; ms->error = error; } @@ -157,9 +158,16 @@ protected int file_buffer(struct magic_set *ms, int fd, const char *inname, const void *buf, size_t nb) { - int m; + int m = 0, rv = 0, looks_text = 0; int mime = ms->flags & MAGIC_MIME; const unsigned char *ubuf = CAST(const unsigned char *, buf); + unichar *u8buf = NULL; + size_t ulen; + const char *code = NULL; + const char *code_mime = "binary"; + const char *type = NULL; + + if (nb == 0) { if ((!mime || (mime & MAGIC_MIME_TYPE)) && @@ -175,6 +183,11 @@ file_buffer(struct magic_set *ms, int fd, const char *inname, const void *buf, return 1; } + if ((ms->flags & MAGIC_NO_CHECK_ENCODING) == 0) { + looks_text = file_encoding(ms, ubuf, nb, &u8buf, &ulen, + &code, &code_mime, &type); + } + #ifdef __EMX__ if ((ms->flags & MAGIC_NO_CHECK_APPTYPE) == 0 && inname) { switch (file_os2_apptype(ms, inname, buf, nb)) { @@ -189,41 +202,96 @@ file_buffer(struct magic_set *ms, int fd, const char *inname, const void *buf, #endif /* try compression stuff */ - if ((ms->flags & MAGIC_NO_CHECK_COMPRESS) != 0 || - (m = file_zmagic(ms, fd, inname, ubuf, nb)) == 0) { - /* Check if we have a tar file */ - if ((ms->flags & MAGIC_NO_CHECK_TAR) != 0 || - (m = file_is_tar(ms, ubuf, nb)) == 0) { - /* try tests in /etc/magic (or surrogate magic file) */ - if ((ms->flags & MAGIC_NO_CHECK_SOFT) != 0 || - (m = file_softmagic(ms, ubuf, nb, BINTEST)) == 0) { - /* try known keywords, check whether it is ASCII */ - if ((ms->flags & MAGIC_NO_CHECK_ASCII) != 0 || - (m = file_ascmagic(ms, ubuf, 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; - } + if ((ms->flags & MAGIC_NO_CHECK_COMPRESS) == 0) + if ((m = file_zmagic(ms, fd, inname, ubuf, nb)) != 0) { + if ((ms->flags & MAGIC_DEBUG) != 0) + (void)fprintf(stderr, "zmagic %d\n", m); + goto done; } - } - } + + /* Check if we have a tar file */ + if ((ms->flags & MAGIC_NO_CHECK_TAR) == 0) + if ((m = file_is_tar(ms, ubuf, nb)) != 0) { + if ((ms->flags & MAGIC_DEBUG) != 0) + (void)fprintf(stderr, "tar %d\n", m); + goto done; + } + + /* Check if we have a CDF file */ + if ((ms->flags & MAGIC_NO_CHECK_CDF) == 0) + if ((m = file_trycdf(ms, fd, ubuf, nb)) != 0) { + if ((ms->flags & MAGIC_DEBUG) != 0) + (void)fprintf(stderr, "cdf %d\n", m); + goto done; + } + + /* try soft magic tests */ + if ((ms->flags & MAGIC_NO_CHECK_SOFT) == 0) + if ((m = file_softmagic(ms, ubuf, nb, BINTEST)) != 0) { + if ((ms->flags & MAGIC_DEBUG) != 0) + (void)fprintf(stderr, "softmagic %d\n", 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, ubuf, nb); - } + 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. + */ + if ((m = file_tryelf(ms, fd, ubuf, nb)) != 0) + if ((ms->flags & MAGIC_DEBUG) != 0) + (void)fprintf(stderr, + "elf %d\n", m); + } #endif + goto done; + } + + /* try text properties (and possibly text tokens) */ + if ((ms->flags & MAGIC_NO_CHECK_TEXT) == 0) { + + if ((m = file_ascmagic(ms, ubuf, nb)) != 0) { + if ((ms->flags & MAGIC_DEBUG) != 0) + (void)fprintf(stderr, "ascmagic %d\n", m); + goto done; + } + + /* try to discover text encoding */ + if ((ms->flags & MAGIC_NO_CHECK_ENCODING) == 0) { + if (looks_text == 0) + if ((m = file_ascmagic_with_encoding( ms, ubuf, + nb, u8buf, ulen, code, type)) != 0) { + if ((ms->flags & MAGIC_DEBUG) != 0) + (void)fprintf(stderr, + "ascmagic/enc %d\n", m); + goto done; + } + } + } + + /* give up */ + m = 1; + if ((!mime || (mime & MAGIC_MIME_TYPE)) && + file_printf(ms, mime ? "application/octet-stream" : "data") == -1) { + rv = -1; + } + done: + if ((ms->flags & MAGIC_MIME_ENCODING) != 0) { + if (ms->flags & MAGIC_MIME_TYPE) + if (file_printf(ms, "; charset=") == -1) + rv = -1; + if (file_printf(ms, "%s", code_mime) == -1) + rv = -1; + } + if (u8buf) + free(u8buf); + if (rv) + return rv; + return m; } #endif @@ -236,7 +304,7 @@ file_reset(struct magic_set *ms) return -1; } ms->o.buf = NULL; - ms->haderr = 0; + ms->event_flags &= ~EVENT_HAD_ERR; ms->error = -1; return 0; } @@ -255,12 +323,15 @@ file_getbuffer(struct magic_set *ms) char *pbuf, *op, *np; size_t psize, len; - if (ms->haderr) + if (ms->event_flags & EVENT_HAD_ERR) return NULL; if (ms->flags & MAGIC_RAW) return ms->o.buf; + if (ms->o.buf == NULL) + return NULL; + /* * 4 is for octal representation, + 1 is for NUL */ len = strlen(ms->o.buf); if (len > (SIZE_MAX - 1) / 4) { @@ -315,7 +386,7 @@ file_getbuffer(struct magic_set *ms) for (np = ms->o.pbuf, op = ms->o.buf; *op; op++) { if (isprint((unsigned char)*op)) { - *np++ = *op; + *np++ = *op; } else { OCTALIFY(np, op); } |