From: Christos Zoulas Date: Thu, 8 Jun 2006 20:52:08 +0000 (+0000) Subject: FIFO handling. X-Git-Tag: FILE5_05~739 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ef49aed8e477a7561e8a5193cf317ca26a582ee4;p=file FIFO handling. --- diff --git a/src/compress.c b/src/compress.c index a33c7e93..1f82d423 100644 --- a/src/compress.c +++ b/src/compress.c @@ -42,6 +42,7 @@ #include #include #include +#include #ifdef HAVE_SYS_WAIT_H #include #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; diff --git a/src/magic.c b/src/magic.c index 30996159..a01dd255 100644 --- a/src/magic.c +++ b/src/magic.c @@ -38,6 +38,7 @@ #ifdef QUICK #include #endif +#include /* for PIPE_BUF */ #if defined(HAVE_UTIMES) # include @@ -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) {