libreplace: poll based on select
authorVolker Lendecke <vl@samba.org>
Wed, 9 Feb 2011 18:22:25 +0000 (19:22 +0100)
committerVolker Lendecke <vlendec@samba.org>
Mon, 28 Feb 2011 15:40:19 +0000 (16:40 +0100)
lib/replace/poll.c [new file with mode: 0644]
lib/replace/replace.h
lib/replace/system/config.m4
lib/replace/system/select.h
lib/replace/wscript
source3/configure.in

diff --git a/lib/replace/poll.c b/lib/replace/poll.c
new file mode 100644 (file)
index 0000000..e41548d
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+   Unix SMB/CIFS implementation.
+   poll.c - poll wrapper
+
+   This file is based on code from libssh (LGPLv2.1+ at the time it
+   was downloaded), thus the following copyrights:
+
+   Copyright (c) 2009-2010 by Andreas Schneider <mail@cynapses.org>
+   Copyright (c) 2003-2009 by Aris Adamantiadis
+   Copyright (c) 2009 Aleksandar Kanchev
+   Copyright (C) Volker Lendecke 2011
+
+     ** NOTE! The following LGPL license applies to the replace
+     ** library. This does NOT imply that all of Samba is released
+     ** under the LGPL
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 3 of the License, or (at your option) any later version.
+
+   This library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "replace.h"
+#include "system/select.h"
+
+
+int rep_poll(struct pollfd *fds, nfds_t nfds, int timeout)
+{
+       fd_set rfds, wfds, efds;
+       struct timeval tv, *ptv;
+       int max_fd;
+       int rc;
+       nfds_t i;
+
+       if (fds == NULL) {
+               errno = EFAULT;
+               return -1;
+       }
+
+       FD_ZERO(&rfds);
+       FD_ZERO(&wfds);
+       FD_ZERO(&efds);
+
+       rc = 0;
+       max_fd = 0;
+
+       /* compute fd_sets and find largest descriptor */
+       for (i = 0; i < nfds; i++) {
+               if ((fds[i].fd < 0) || (fds[i].fd >= FD_SETSIZE)) {
+                       fds[i].revents = POLLNVAL;
+                       continue;
+               }
+
+               if (fds[i].events & (POLLIN | POLLRDNORM)) {
+                       FD_SET(fds[i].fd, &rfds);
+               }
+               if (fds[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND)) {
+                       FD_SET(fds[i].fd, &wfds);
+               }
+               if (fds[i].events & (POLLPRI | POLLRDBAND)) {
+                       FD_SET(fds[i].fd, &efds);
+               }
+               if (fds[i].fd > max_fd &&
+                   (fds[i].events & (POLLIN | POLLOUT | POLLPRI |
+                                     POLLRDNORM | POLLRDBAND |
+                                     POLLWRNORM | POLLWRBAND))) {
+                       max_fd = fds[i].fd;
+               }
+       }
+
+       if (timeout < 0) {
+               ptv = NULL;
+       } else {
+               ptv = &tv;
+               if (timeout == 0) {
+                       tv.tv_sec = 0;
+                       tv.tv_usec = 0;
+               } else {
+                       tv.tv_sec = timeout / 1000;
+                       tv.tv_usec = (timeout % 1000) * 1000;
+               }
+       }
+
+       rc = select(max_fd + 1, &rfds, &wfds, &efds, ptv);
+       if (rc < 0) {
+               return -1;
+       }
+
+       for (rc = 0, i = 0; i < nfds; i++) {
+               if ((fds[i].fd < 0) || (fds[i].fd >= FD_SETSIZE)) {
+                       continue;
+               }
+
+               fds[i].revents = 0;
+
+               if (FD_ISSET(fds[i].fd, &rfds)) {
+                       int err = errno;
+                       int available = 0;
+                       int ret;
+
+                       /* support for POLLHUP */
+                       ret = ioctl(fds[i].fd, FIONREAD, &available);
+                       if ((ret == -1) || (available == 0)) {
+                               fds[i].revents |= POLLHUP;
+                       } else {
+                               fds[i].revents |= fds[i].events
+                                       & (POLLIN | POLLRDNORM);
+                       }
+
+                       errno = err;
+               }
+               if (FD_ISSET(fds[i].fd, &wfds)) {
+                       fds[i].revents |= fds[i].events
+                               & (POLLOUT | POLLWRNORM | POLLWRBAND);
+               }
+               if (FD_ISSET(fds[i].fd, &efds)) {
+                       fds[i].revents |= fds[i].events
+                               & (POLLPRI | POLLRDBAND);
+               }
+               if (fds[i].revents & ~POLLHUP) {
+                       rc++;
+               }
+       }
+       return rc;
+}
index 60aa3d4e2c498fbb231fa1fc6e8de932ee18b7d0..c081f23c266ca49e30d92996ae6db594ba7b3d10 100644 (file)
@@ -797,4 +797,9 @@ int fdatasync(int );
 #endif
 #endif
 
+#ifndef HAVE_POLL
+#define poll rep_poll
+/* prototype is in "system/network.h" */
+#endif
+
 #endif /* _LIBREPLACE_REPLACE_H */
index 04364bc3a1d66715df246380e01353ecbe7a3f85..b7cdf1414a2f0a9fb6f30d0924f0b3037cec0682 100644 (file)
@@ -6,6 +6,10 @@ AC_CHECK_HEADERS(sys/acl.h acl/libacl.h sys/file.h)
 # select
 AC_CHECK_HEADERS(sys/select.h)
 
+# poll
+AC_CHECK_HEADERS(poll.h)
+AC_CHECK_FUNCS(poll,[],[LIBREPLACEOBJ="${LIBREPLACEOBJ} $libreplacedir/poll.o"])
+
 # time
 AC_CHECK_HEADERS(sys/time.h utime.h)
 AC_HEADER_TIME
index da18de0cfc750ccc3863c25c791ee063447021ab..11c5390d90138ad0106af2feab6e56713cb71497 100644 (file)
 #define SELECT_CAST
 #endif
 
+#ifdef HAVE_POLL
+
+#include <poll.h>
+
+#else
+
+/* Type used for the number of file descriptors.  */
+typedef unsigned long int nfds_t;
+
+/* Data structure describing a polling request.  */
+struct pollfd
+{
+       int fd;            /* File descriptor to poll.  */
+       short int events;  /* Types of events poller cares about.  */
+       short int revents; /* Types of events that actually occurred.  */
+};
+
+/* Event types that can be polled for.  These bits may be set in `events'
+   to indicate the interesting event types; they will appear in `revents'
+   to indicate the status of the file descriptor.  */
+#define POLLIN         0x001           /* There is data to read.  */
+#define POLLPRI                0x002           /* There is urgent data to read.  */
+#define POLLOUT                0x004           /* Writing now will not block.  */
+#define POLLRDNORM     0x040           /* Normal data may be read.  */
+#define POLLRDBAND     0x080           /* Priority data may be read.  */
+#define POLLWRNORM     0x100           /* Writing now will not block.  */
+#define POLLWRBAND     0x200           /* Priority data may be written.  */
+#define POLLERR                0x008           /* Error condition.  */
+#define POLLHUP                0x010           /* Hung up.  */
+#define POLLNVAL       0x020           /* Invalid polling request.  */
+
+/* define is in "replace.h" */
+int rep_poll(struct pollfd *fds, nfds_t nfds, int timeout);
+
+#endif
+
 #endif
index b1aad69fb76288bc7970b8015974072c4a415846..d0bbe9615975b7191a9c3edab7cf7f9a760adaff 100644 (file)
@@ -254,6 +254,9 @@ def configure(conf):
     if conf.CONFIG_SET('HAVE_EPOLL_CREATE') and conf.CONFIG_SET('HAVE_SYS_EPOLL_H'):
         conf.DEFINE('HAVE_EPOLL', 1)
 
+    conf.CHECK_HEADERS('poll.h')
+    conf.CHECK_FUNCS('poll')
+
     if not conf.CHECK_CODE('''#define LIBREPLACE_CONFIGURE_TEST_STRPTIME
                            #include "test/strptime.c"''',
                            define='HAVE_STRPTIME',
@@ -411,6 +414,7 @@ def build(bld):
     if bld.CONFIG_SET('REPLACE_GETPASS'):        REPLACE_SOURCE += ' getpass.c'
     if not bld.CONFIG_SET('HAVE_CRYPT'):         REPLACE_SOURCE += ' crypt.c'
     if not bld.CONFIG_SET('HAVE_DLOPEN'):        REPLACE_SOURCE += ' dlfcn.c'
+    if not bld.CONFIG_SET('HAVE_POLL'):          REPLACE_SOURCE += ' poll.c'
 
     if not bld.CONFIG_SET('HAVE_SOCKETPAIR'):    REPLACE_SOURCE += ' socketpair.c'
     if not bld.CONFIG_SET('HAVE_CONNECT'):       REPLACE_SOURCE += ' socket.c'
index 31ba9f68ceaf8eee3573034e0fff65d926e9172f..b4794f28a2fa7b22cc8e264b0c711a749d245020 100644 (file)
@@ -1093,7 +1093,7 @@ AC_CHECK_FUNCS(getrlimit fsync setpgid)
 AC_CHECK_FUNCS(fdatasync,,[AC_CHECK_LIB_EXT(rt, LIBS, fdatasync)])
 AC_CHECK_FUNCS(setsid glob strpbrk crypt16 getauthuid)
 AC_CHECK_FUNCS(sigprocmask sigblock sigaction sigset innetgr setnetgrent getnetgrent endnetgrent)
-AC_CHECK_FUNCS(initgroups select poll rdchk getgrnam getgrent pathconf)
+AC_CHECK_FUNCS(initgroups select rdchk getgrnam getgrent pathconf)
 AC_CHECK_FUNCS(setpriv setgidx setuidx setgroups sysconf stat64 fstat64)
 AC_CHECK_FUNCS(lstat64 fopen64 atexit grantpt lseek64 ftruncate64 posix_fallocate posix_fallocate64)
 AC_CHECK_FUNCS(fallocate fallocate64)