diff options
-rw-r--r-- | lib/replace/poll.c | 133 | ||||
-rw-r--r-- | lib/replace/replace.h | 5 | ||||
-rw-r--r-- | lib/replace/system/config.m4 | 4 | ||||
-rw-r--r-- | lib/replace/system/select.h | 36 | ||||
-rw-r--r-- | lib/replace/wscript | 4 | ||||
-rw-r--r-- | source3/configure.in | 2 |
6 files changed, 183 insertions, 1 deletions
diff --git a/lib/replace/poll.c b/lib/replace/poll.c new file mode 100644 index 0000000000..e41548dd39 --- /dev/null +++ b/lib/replace/poll.c @@ -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; +} diff --git a/lib/replace/replace.h b/lib/replace/replace.h index 60aa3d4e2c..c081f23c26 100644 --- a/lib/replace/replace.h +++ b/lib/replace/replace.h @@ -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 */ diff --git a/lib/replace/system/config.m4 b/lib/replace/system/config.m4 index 04364bc3a1..b7cdf1414a 100644 --- a/lib/replace/system/config.m4 +++ b/lib/replace/system/config.m4 @@ -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 diff --git a/lib/replace/system/select.h b/lib/replace/system/select.h index da18de0cfc..11c5390d90 100644 --- a/lib/replace/system/select.h +++ b/lib/replace/system/select.h @@ -38,4 +38,40 @@ #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 diff --git a/lib/replace/wscript b/lib/replace/wscript index b1aad69fb7..d0bbe96159 100644 --- a/lib/replace/wscript +++ b/lib/replace/wscript @@ -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' diff --git a/source3/configure.in b/source3/configure.in index 31ba9f68ce..b4794f28a2 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -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) |