From f0e088d682de0015abdfacae91576ef7836fd2d8 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Tue, 29 Aug 2006 20:32:07 +0000 Subject: [PATCH] * 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. --- ChangeLog | 5 +++ MODULES.html.sh | 1 + lib/ChangeLog | 4 +++ lib/isapipe.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/isapipe.h | 1 + m4/ChangeLog | 4 +++ m4/isapipe.m4 | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++ modules/isapipe | 27 ++++++++++++++++ 8 files changed, 229 insertions(+) create mode 100644 lib/isapipe.c create mode 100644 lib/isapipe.h create mode 100644 m4/isapipe.m4 create mode 100644 modules/isapipe diff --git a/ChangeLog b/ChangeLog index b093af4a7..d995f06c7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2006-08-29 Paul Eggert + + * modules/isapipe: New file. + * MODULES.html.sh (File descriptor based Input/Output): Add isapipe. + 2006-08-29 Jim Meyering * modules/configmake (Makefile.am): Make configmake.h depend on diff --git a/MODULES.html.sh b/MODULES.html.sh index 116dccf58..fe2c8b120 100755 --- a/MODULES.html.sh +++ b/MODULES.html.sh @@ -1928,6 +1928,7 @@ func_all_modules () func_module full-read func_module full-write func_module binary-io + func_module isapipe func_end_table element="File stream based Input/Output" diff --git a/lib/ChangeLog b/lib/ChangeLog index d11d6b8f4..6f7d25cc2 100644 --- a/lib/ChangeLog +++ b/lib/ChangeLog @@ -1,3 +1,7 @@ +2006-08-29 Paul Eggert + + * isapipe.c, isapipe.h: New files. + 2006-08-29 Eric Blake * error.c (error_at_line, print_errno_message): Match libc, after diff --git a/lib/isapipe.c b/lib/isapipe.c new file mode 100644 index 000000000..02c11715d --- /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 + +#include "isapipe.h" + +#include +#include +#include +#include +#include + +#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))); +} diff --git a/lib/isapipe.h b/lib/isapipe.h new file mode 100644 index 000000000..187527ac8 --- /dev/null +++ b/lib/isapipe.h @@ -0,0 +1 @@ +int isapipe (int); diff --git a/m4/ChangeLog b/m4/ChangeLog index ede511e6e..3a265cd10 100644 --- a/m4/ChangeLog +++ b/m4/ChangeLog @@ -1,3 +1,7 @@ +2006-08-29 Paul Eggert + + * isapipe.m4: New file. + 2006-08-28 Paul Eggert * fcntl_h.m4: New file. diff --git a/m4/isapipe.m4 b/m4/isapipe.m4 new file mode 100644 index 000000000..04e693435 --- /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 + #include + #include + #include + #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 +]) diff --git a/modules/isapipe b/modules/isapipe new file mode 100644 index 000000000..602f2a3c9 --- /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 -- 2.11.0