]> granicus.if.org Git - file/commitdiff
FIFO handling.
authorChristos Zoulas <christos@zoulas.com>
Thu, 8 Jun 2006 20:52:08 +0000 (20:52 +0000)
committerChristos Zoulas <christos@zoulas.com>
Thu, 8 Jun 2006 20:52:08 +0000 (20:52 +0000)
src/compress.c
src/magic.c

index a33c7e9331dcbc5baa8d36988527334dce40c94a..1f82d423e6597ffd3ad2ed469683098ada3bb61b 100644 (file)
@@ -42,6 +42,7 @@
 #include <string.h>
 #include <errno.h>
 #include <sys/types.h>
+#include <sys/ioctl.h>
 #ifdef HAVE_SYS_WAIT_H
 #include <sys/wait.h>
 #endif
@@ -50,7 +51,7 @@
 #endif
 
 #ifndef lint
-FILE_RCSID("@(#)$Id: compress.c,v 1.42 2005/03/06 05:58:22 christos Exp $")
+FILE_RCSID("@(#)$Id: compress.c,v 1.43 2006/06/08 20:52:08 christos Exp $")
 #endif
 
 
@@ -78,7 +79,6 @@ private int ncompr = sizeof(compr) / sizeof(compr[0]);
 
 
 private ssize_t swrite(int, const void *, size_t);
-private ssize_t sread(int, void *, size_t);
 private size_t uncompressbuf(struct magic_set *, int, size_t,
     const unsigned char *, unsigned char **, size_t);
 #ifdef HAVE_LIBZ
@@ -152,14 +152,53 @@ swrite(int fd, const void *buf, size_t n)
 /*
  * `safe' read for sockets and pipes.
  */
-private ssize_t
+protected ssize_t
 sread(int fd, void *buf, size_t n)
 {
        int rv;
+#ifdef FIONREAD
+       int t;
+#endif
        size_t rn = n;
 
+       if (fd == STDIN_FILENO)
+               goto nocheck;
+
+#ifdef FIONREAD
+       if ((ioctl(fd, FIONREAD, &t) < 0) || (t == 0)) {
+#ifdef FD_ZERO
+               for (;;) {
+                       fd_set check;
+                       struct timeval tout = {0, 100 * 1000};
+
+                       FD_ZERO(&check);
+                       FD_SET(fd, &check);
+
+                       /*
+                        * Avoid soft deadlock: do not read if there
+                        * is nothing to read from sockets and pipes.
+                        */
+                       if (select(fd + 1, &check, NULL, NULL, &tout) <= 0) {
+                               if (errno == EINTR || errno == EAGAIN)
+                                       continue;
+                               return 0;
+                       }
+               }
+
+#endif
+
+               (void)ioctl(fd, FIONREAD, &t);
+       }
+
+       if (t > 0 && (size_t)t < n) {
+               n = t;
+               rn = n;
+       }
+#endif
+
+nocheck:
        do
-               switch (rv = read(fd, buf, n)) {
+               switch ((rv = read(fd, buf, n))) {
                case -1:
                        if (errno == EINTR)
                                continue;
index 30996159b6b19484d2687e9b8234f6402540fc82..a01dd2552e232b55b429ead8d28505934f0128f0 100644 (file)
@@ -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.33 2006/06/01 18:52:18 ian Exp $")
+FILE_RCSID("@(#)$Id: magic.c,v 1.34 2006/06/08 20:52:08 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
@@ -243,39 +263,66 @@ magic_file(struct magic_set *ms, const char *inname)
                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],
+                   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) {