changeset 7233:ec85aace506a

* modules/isapipe: New file. * MODULES.html.sh (File descriptor based Input/Output): Add isapipe. * lib/isapipe.c, lib/isapipe.h, m4/isapipe.m4: New files.
author Paul Eggert <eggert@cs.ucla.edu>
date Tue, 29 Aug 2006 20:32:07 +0000
parents b307709e3a05
children cb0b761d8477
files ChangeLog MODULES.html.sh lib/ChangeLog lib/isapipe.c lib/isapipe.h m4/ChangeLog m4/isapipe.m4 modules/isapipe
diffstat 8 files changed, 229 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2006-08-29  Paul Eggert  <eggert@cs.ucla.edu>
+
+	* modules/isapipe: New file.
+	* MODULES.html.sh (File descriptor based Input/Output): Add isapipe.
+
 2006-08-29  Jim Meyering  <jim@meyering.net>
 
 	* modules/configmake (Makefile.am): Make configmake.h depend on
--- a/MODULES.html.sh
+++ b/MODULES.html.sh
@@ -1928,6 +1928,7 @@
   func_module full-read
   func_module full-write
   func_module binary-io
+  func_module isapipe
   func_end_table
 
   element="File stream based Input/Output"
--- a/lib/ChangeLog
+++ b/lib/ChangeLog
@@ -1,3 +1,7 @@
+2006-08-29  Paul Eggert  <eggert@cs.ucla.edu>
+
+	* isapipe.c, isapipe.h: New files.
+
 2006-08-29  Eric Blake  <ebb9@byu.net>
 
 	* error.c (error_at_line, print_errno_message): Match libc, after
new file mode 100644
--- /dev/null
+++ b/lib/isapipe.c
@@ -0,0 +1,98 @@
+/* Test whether a file descriptor is a pipe.
+
+   Copyright (C) 2006 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by Paul Eggert.  */
+
+#include <config.h>
+
+#include "isapipe.h"
+
+#include <errno.h>
+#include <stdbool.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "stat-macros.h"
+
+/* Whether pipes are FIFOs; -1 if not known.  */
+#ifndef HAVE_FIFO_PIPES
+# define HAVE_FIFO_PIPES (-1)
+#endif
+
+/* The maximum link count for pipes; (nlink_t) -1 if not known.  */
+#ifndef PIPE_LINK_COUNT_MAX
+# define PIPE_LINK_COUNT_MAX ((nlink_t) (-1))
+#endif
+
+/* Return 1 if FD is a pipe, 0 if not, -1 (setting errno) on error.
+
+   Test fairly strictly whether FD is a pipe.  lseek and checking for
+   ESPIPE does not suffice, since many non-pipe files cause lseek to
+   fail with errno == ESPIPE.  */
+
+int
+isapipe (int fd)
+{
+  nlink_t pipe_link_count_max = PIPE_LINK_COUNT_MAX;
+  bool check_for_fifo = (HAVE_FIFO_PIPES == 1);
+  struct stat st;
+  int fstat_result = fstat (fd, &st);
+
+  if (fstat_result != 0)
+    return fstat_result;
+
+  /* We want something that succeeds only for pipes, but on
+     POSIX-conforming hosts S_ISFIFO succeeds for both FIFOs and pipes
+     and we know of no portable, reliable way to distinguish them in
+     general.  However, in practice pipes always have a link count <=
+     PIPE_LINK_COUNT_MAX (unless someone attaches them to the file
+     system name space using fattach, in which case they're not really
+     pipes any more), so test for that as well.
+
+     On Darwin 7.7, pipes are sockets, so check for those instead.  */
+
+  if (! ((HAVE_FIFO_PIPES == 0 || HAVE_FIFO_PIPES == 1)
+	 && PIPE_LINK_COUNT_MAX != (nlink_t) -1)
+      && (S_ISFIFO (st.st_mode) | S_ISSOCK (st.st_mode)))
+    {
+      int fd[2];
+      int pipe_result = pipe (fd);
+      if (pipe_result != 0)
+	return pipe_result;
+      else
+	{
+	  struct stat pipe_st;
+	  int fstat_pipe_result = fstat (fd[0], &pipe_st);
+	  int fstat_pipe_errno = errno;
+	  close (fd[0]);
+	  close (fd[1]);
+	  if (fstat_pipe_result != 0)
+	    {
+	      errno = fstat_pipe_errno;
+	      return fstat_pipe_result;
+	    }
+	  check_for_fifo = (S_ISFIFO (pipe_st.st_mode) != 0);
+	  pipe_link_count_max = pipe_st.st_nlink;
+	}
+    }
+
+  return
+    (st.st_nlink <= pipe_link_count_max
+     && (check_for_fifo ? S_ISFIFO (st.st_mode) : S_ISSOCK (st.st_mode)));
+}
new file mode 100644
--- /dev/null
+++ b/lib/isapipe.h
@@ -0,0 +1,1 @@
+int isapipe (int);
--- a/m4/ChangeLog
+++ b/m4/ChangeLog
@@ -1,3 +1,7 @@
+2006-08-29  Paul Eggert  <eggert@cs.ucla.edu>
+
+	* isapipe.m4: New file.
+
 2006-08-28  Paul Eggert  <eggert@cs.ucla.edu>
 
 	* fcntl_h.m4: New file.
new file mode 100644
--- /dev/null
+++ b/m4/isapipe.m4
@@ -0,0 +1,89 @@
+# Test whether a file descriptor is a pipe.
+
+dnl Copyright (C) 2006 Free Software Foundation, Inc.
+
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl Written by Paul Eggert.
+
+AC_DEFUN([gl_ISAPIPE],
+[
+  # OpenVMS has isapipe already, so check for it.
+  AC_REPLACE_FUNCS(isapipe)
+  if test $ac_cv_func_isapipe = no; then
+    gl_PREREQ_ISAPIPE
+  fi
+])
+
+# Prerequisites of lib/isapipe.c.
+AC_DEFUN([gl_PREREQ_ISAPIPE],
+[
+  AC_CACHE_CHECK([whether pipes are FIFOs (and for their link count)],
+    [gl_cv_pipes_are_fifos],
+    [AC_RUN_IFELSE(
+       [AC_LANG_SOURCE(
+	  [[#include <stdio.h>
+	    #include <sys/types.h>
+	    #include <sys/stat.h>
+	    #include <unistd.h>
+	    #ifndef S_ISFIFO
+	     #define S_ISFIFO(m) 0
+	    #endif
+	    #ifndef S_ISSOCK
+	     #define S_ISSOCK(m) 0
+	    #endif
+	    int
+	    main (int argc, char **argv)
+	    {
+	      int fd[2];
+	      struct stat st;
+	      if (pipe (fd) != 0 || fstat (fd[0], &st) != 0)
+		return 1;
+	      if (2 <= argc && argv[1][0] == '-')
+		{
+		  char const *yesno = (S_ISFIFO (st.st_mode) ? "yes" : "no");
+		  if (st.st_nlink <= 1)
+		    {
+		      long int i = st.st_nlink;
+		      if (i != st.st_nlink)
+			return 1;
+		      printf ("%s (%ld)\n", yesno, i);
+		    }
+		  else
+		    {
+		      unsigned long int i = st.st_nlink;
+		      if (i != st.st_nlink)
+			return 1;
+		      printf ("%s (%lu)\n", yesno, i);
+		    }
+		}
+	      else
+		{
+		  if (! S_ISFIFO (st.st_mode) && ! S_ISSOCK (st.st_mode))
+		    return 1;
+		}
+	      return 0;
+	    }]])],
+       [gl_cv_pipes_are_fifos=`./conftest$ac_exeext -`
+	test -z "$gl_cv_pipes_are_fifos" && gl_cv_pipes_are_fifos=no],
+       [gl_cv_pipes_are_fifos=unknown],
+       [gl_cv_pipes_are_fifos=cross-compiling])])
+
+  case $gl_cv_pipes_are_fifos in #(
+  'yes ('*')')
+    AC_DEFINE([HAVE_FIFO_PIPES], 1,
+      [Define to 1 if pipes are FIFOs, 0 if sockets.  Leave undefined
+       if not known.]);; #(
+  'no ('*')')
+    AC_DEFINE([HAVE_FIFO_PIPES], 0);;
+  esac
+
+  case $gl_cv_pipes_are_fifos in #(
+  *'('*')')
+    AC_DEFINE_UNQUOTED([PIPE_LINK_COUNT_MAX],
+      [`expr "$gl_cv_pipes_are_fifos" : '.*\((.*)\)'`],
+      [Define to the maximum link count that a true pipe can have.]);;
+  esac
+])
new file mode 100644
--- /dev/null
+++ b/modules/isapipe
@@ -0,0 +1,27 @@
+Description:
+Test whether a file descriptor is a pipe.
+
+Files:
+lib/isapipe.c
+lib/isapipe.h
+m4/isapipe.m4
+
+Depends-on:
+stat-macros
+stdbool
+unistd
+
+configure.ac:
+gl_ISAPIPE
+
+Makefile.am:
+EXTRA_DIST += isapipe.h
+
+Include:
+"isapipe.h"
+
+License:
+LGPL
+
+Maintainer:
+Paul Eggert, Jim Meyering