summaryrefslogtreecommitdiffstats
path: root/contrib/file/magic.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/file/magic.c')
-rw-r--r--contrib/file/magic.c103
1 files changed, 75 insertions, 28 deletions
diff --git a/contrib/file/magic.c b/contrib/file/magic.c
index 03d0291..3f24075 100644
--- a/contrib/file/magic.c
+++ b/contrib/file/magic.c
@@ -38,6 +38,7 @@
#ifdef QUICK
#include <sys/mman.h>
#endif
+#include <limits.h> /* for PIPE_BUF */
#if defined(HAVE_UTIMES)
# include <sys/time.h>
@@ -62,7 +63,7 @@
#include "patchlevel.h"
#ifndef lint
-FILE_RCSID("@(#)$Id: magic.c,v 1.32 2005/10/17 15:31:10 christos Exp $")
+FILE_RCSID("@(#)$Id: magic.c,v 1.35 2006/10/31 19:37:17 christos Exp $")
#endif /* lint */
#ifdef __EMX__
@@ -74,6 +75,7 @@ protected int file_os2_apptype(struct magic_set *ms, const char *fn,
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 STDIN_FILENO
#define STDIN_FILENO 0
@@ -136,9 +138,26 @@ free_mlist(struct mlist *mlist)
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);
@@ -221,6 +240,7 @@ magic_file(struct magic_set *ms, const char *inname)
unsigned char *buf;
struct stat sb;
ssize_t nbytes = 0; /* number of bytes read from a datafile */
+ int ispipe = 0;
/*
* one extra for terminating '\0', and
@@ -234,48 +254,75 @@ magic_file(struct magic_set *ms, const char *inname)
goto done;
switch (file_fsmagic(ms, inname, &sb)) {
- case -1:
+ case -1: /* error */
goto done;
- case 0:
+ case 0: /* nothing found */
break;
- default:
+ default: /* matched it and printed type */
rv = 0;
goto done;
}
- if (inname == NULL)
+ if (inname == NULL) {
fd = STDIN_FILENO;
- else if ((fd = open(inname, O_RDONLY|O_BINARY)) < 0) {
+ 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, O_RDONLY|O_BINARY)) < 0) {
+ char *tmp = alloca(strlen(inname) + 5);
+ (void)strcat(strcpy(tmp, inname), ".exe");
+ if ((fd = open(tmp, flags)) < 0) {
#endif
- /* We cannot open it, but we were able to stat it. */
- if (sb.st_mode & 0222)
- if (file_printf(ms, "writable, ") == -1)
- goto done;
- if (sb.st_mode & 0111)
- if (file_printf(ms, "executable, ") == -1)
- goto done;
- if (S_ISREG(sb.st_mode))
- if (file_printf(ms, "regular file, ") == -1)
- goto done;
- if (file_printf(ms, "no read permission") == -1)
+ if (info_from_stat(ms, sb.st_mode) == -1)
+ goto done;
+ rv = 0;
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
}
/*
* 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;
+
+ while ((r = sread(fd, (void *)&buf[nbytes],
+ (size_t)(HOWMANY - nbytes))) > 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;
+ }
+
+ } else {
+ if ((nbytes = read(fd, (char *)buf, HOWMANY)) == -1) {
+ file_error(ms, errno, "cannot read `%s'", inname);
+ goto done;
+ }
}
if (nbytes == 0) {
OpenPOWER on IntegriCloud