diff options
Diffstat (limited to 'src/magic.c')
-rw-r--r-- | src/magic.c | 140 |
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; + } +} |