#include <string.h>
#include <errno.h>
#include <sys/types.h>
+#include <sys/ioctl.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#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
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
/*
* `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;
#ifdef QUICK
#include <sys/mman.h>
#endif
+#include <limits.h> /* for PIPE_BUF */
#if defined(HAVE_UTIMES)
# include <sys/time.h>
#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__
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
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);
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
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) {