summaryrefslogtreecommitdiff
path: root/src/magic.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/magic.c')
-rw-r--r--src/magic.c140
1 files changed, 122 insertions, 18 deletions
diff --git a/src/magic.c b/src/magic.c
index bc382e8..d16f8c6 100644
--- a/src/magic.c
+++ b/src/magic.c
@@ -33,7 +33,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: magic.c,v 1.78 2013/01/07 18:20:19 christos Exp $")
+FILE_RCSID("@(#)$File: magic.c,v 1.91 2014/12/16 23:18:40 christos Exp $")
#endif /* lint */
#include "magic.h"
@@ -126,8 +126,10 @@ out:
free(hmagicpath);
return MAGIC;
#else
- char *hmagicp = hmagicpath;
+ char *hmagicp;
char *tmppath = NULL;
+ LPTSTR dllpath;
+ hmagicpath = NULL;
#define APPENDPATH() \
do { \
@@ -172,7 +174,7 @@ out:
}
/* Third, try to get magic file relative to dll location */
- LPTSTR dllpath = malloc(sizeof(*dllpath) * (MAX_PATH + 1));
+ dllpath = malloc(sizeof(*dllpath) * (MAX_PATH + 1));
dllpath[MAX_PATH] = 0; /* just in case long path gets truncated and not null terminated */
if (GetModuleFileNameA(NULL, dllpath, MAX_PATH)){
PathRemoveFileSpecA(dllpath);
@@ -220,13 +222,15 @@ magic_open(int flags)
private int
unreadable_info(struct magic_set *ms, mode_t md, const char *file)
{
- /* We cannot open it, but we were able to stat it. */
- if (access(file, W_OK) == 0)
- if (file_printf(ms, "writable, ") == -1)
- return -1;
- if (access(file, X_OK) == 0)
- if (file_printf(ms, "executable, ") == -1)
- return -1;
+ if (file) {
+ /* We cannot open it, but we were able to stat it. */
+ if (access(file, W_OK) == 0)
+ if (file_printf(ms, "writable, ") == -1)
+ return -1;
+ if (access(file, X_OK) == 0)
+ if (file_printf(ms, "executable, ") == -1)
+ return -1;
+ }
if (S_ISREG(md))
if (file_printf(ms, "regular file, ") == -1)
return -1;
@@ -254,6 +258,20 @@ magic_load(struct magic_set *ms, const char *magicfile)
return file_apprentice(ms, magicfile, FILE_LOAD);
}
+#ifndef COMPILE_ONLY
+/*
+ * Install a set of compiled magic buffers.
+ */
+public int
+magic_load_buffers(struct magic_set *ms, void **bufs, size_t *sizes,
+ size_t nbufs)
+{
+ if (ms == NULL)
+ return -1;
+ return buffer_apprentice(ms, (struct magic **)bufs, sizes, nbufs);
+}
+#endif
+
public int
magic_compile(struct magic_set *ms, const char *magicfile)
{
@@ -282,7 +300,7 @@ private void
close_and_restore(const struct magic_set *ms, const char *name, int fd,
const struct stat *sb)
{
- if (fd == STDIN_FILENO)
+ if (fd == STDIN_FILENO || name == NULL)
return;
(void) close(fd);
@@ -343,6 +361,10 @@ file_or_fd(struct magic_set *ms, const char *inname, int fd)
struct stat sb;
ssize_t nbytes = 0; /* number of bytes read from a datafile */
int ispipe = 0;
+ off_t pos = (off_t)-1;
+
+ if (file_reset(ms) == -1)
+ goto out;
/*
* one extra for terminating '\0', and
@@ -352,9 +374,6 @@ file_or_fd(struct magic_set *ms, const char *inname, int fd)
if ((buf = CAST(unsigned char *, malloc(HOWMANY + SLOP))) == NULL)
return NULL;
- if (file_reset(ms) == -1)
- goto done;
-
switch (file_fsmagic(ms, inname, &sb)) {
case -1: /* error */
goto done;
@@ -365,13 +384,22 @@ file_or_fd(struct magic_set *ms, const char *inname, int fd)
goto done;
}
+#ifdef WIN32
+ /* Place stdin in binary mode, so EOF (Ctrl+Z) doesn't stop early. */
+ if (fd == STDIN_FILENO)
+ _setmode(STDIN_FILENO, O_BINARY);
+#endif
+
if (inname == NULL) {
if (fstat(fd, &sb) == 0 && S_ISFIFO(sb.st_mode))
ispipe = 1;
+ else
+ pos = lseek(fd, (off_t)0, SEEK_CUR);
} else {
int flags = O_RDONLY|O_BINARY;
+ int okstat = stat(inname, &sb) == 0;
- if (stat(inname, &sb) == 0 && S_ISFIFO(sb.st_mode)) {
+ if (okstat && S_ISFIFO(sb.st_mode)) {
#ifdef O_NONBLOCK
flags |= O_NONBLOCK;
#endif
@@ -380,7 +408,20 @@ file_or_fd(struct magic_set *ms, const char *inname, int fd)
errno = 0;
if ((fd = open(inname, flags)) < 0) {
- if (unreadable_info(ms, sb.st_mode, inname) == -1)
+#ifdef WIN32
+ /*
+ * Can't stat, can't open. It may have been opened in
+ * fsmagic, so if the user doesn't have read permission,
+ * allow it to say so; otherwise an error was probably
+ * displayed in fsmagic.
+ */
+ if (!okstat && errno == EACCES) {
+ sb.st_mode = S_IFBLK;
+ okstat = 1;
+ }
+#endif
+ if (okstat &&
+ unreadable_info(ms, sb.st_mode, inname) == -1)
goto done;
rv = 0;
goto done;
@@ -414,8 +455,18 @@ file_or_fd(struct magic_set *ms, const char *inname, int fd)
}
} else {
- if ((nbytes = read(fd, (char *)buf, HOWMANY)) == -1) {
- file_error(ms, errno, "cannot read `%s'", inname);
+ /* Windows refuses to read from a big console buffer. */
+ size_t howmany =
+#if defined(WIN32) && HOWMANY > 8 * 1024
+ _isatty(fd) ? 8 * 1024 :
+#endif
+ HOWMANY;
+ if ((nbytes = read(fd, (char *)buf, howmany)) == -1) {
+ if (inname == NULL && fd != STDIN_FILENO)
+ file_error(ms, errno, "cannot read fd %d", fd);
+ else
+ file_error(ms, errno, "cannot read `%s'",
+ inname == NULL ? "/dev/stdin" : inname);
goto done;
}
}
@@ -426,7 +477,10 @@ file_or_fd(struct magic_set *ms, const char *inname, int fd)
rv = 0;
done:
free(buf);
+ if (pos != (off_t)-1)
+ (void)lseek(fd, pos, SEEK_SET);
close_and_restore(ms, inname, fd, &sb);
+out:
return rv == 0 ? file_getbuffer(ms) : NULL;
}
@@ -483,3 +537,53 @@ magic_version(void)
{
return MAGIC_VERSION;
}
+
+public int
+magic_setparam(struct magic_set *ms, int param, const void *val)
+{
+ switch (param) {
+ case MAGIC_PARAM_INDIR_MAX:
+ ms->indir_max = *(const size_t *)val;
+ return 0;
+ case MAGIC_PARAM_NAME_MAX:
+ ms->name_max = *(const size_t *)val;
+ return 0;
+ case MAGIC_PARAM_ELF_PHNUM_MAX:
+ ms->elf_phnum_max = *(const size_t *)val;
+ return 0;
+ case MAGIC_PARAM_ELF_SHNUM_MAX:
+ ms->elf_shnum_max = *(const size_t *)val;
+ return 0;
+ case MAGIC_PARAM_ELF_NOTES_MAX:
+ ms->elf_notes_max = *(const size_t *)val;
+ return 0;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+}
+
+public int
+magic_getparam(struct magic_set *ms, int param, void *val)
+{
+ switch (param) {
+ case MAGIC_PARAM_INDIR_MAX:
+ *(size_t *)val = ms->indir_max;
+ return 0;
+ case MAGIC_PARAM_NAME_MAX:
+ *(size_t *)val = ms->name_max;
+ return 0;
+ case MAGIC_PARAM_ELF_PHNUM_MAX:
+ *(size_t *)val = ms->elf_phnum_max;
+ return 0;
+ case MAGIC_PARAM_ELF_SHNUM_MAX:
+ *(size_t *)val = ms->elf_shnum_max;
+ return 0;
+ case MAGIC_PARAM_ELF_NOTES_MAX:
+ *(size_t *)val = ms->elf_notes_max;
+ return 0;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+}