static int winbind_write_sock(void *buffer, int count, int recursing, int need_priv) { int fd, result, nwritten; /* Open connection to winbind daemon */ restart: fd = winbind_open_pipe_sock(recursing, need_priv); if (fd == -1) { errno = ENOENT; return -1; } /* Write data to socket */ nwritten = 0; while(nwritten < count) { struct pollfd pfd; int ret; /* Catch pipe close on other end by checking if a read() call would not block by calling poll(). */ pfd.fd = fd; pfd.events = POLLIN|POLLOUT|POLLHUP; ret = poll(&pfd, 1, -1); if (ret == -1) { winbind_close_sock(); return -1; /* poll error */ } /* Write should be OK if fd not available for reading */ if ((ret == 1) && (pfd.revents & (POLLIN|POLLHUP|POLLERR))) { /* Pipe has closed on remote end */ winbind_close_sock(); goto restart; } /* Do the write */ result = write(fd, (char *)buffer + nwritten, count - nwritten); if ((result == -1) || (result == 0)) { /* Write failed */ winbind_close_sock(); return -1; } nwritten += result; } return nwritten; }
static int winbind_read_sock(void *buffer, int count) { int fd; int nread = 0; int total_time = 0; fd = winbind_open_pipe_sock(false, false); if (fd == -1) { return -1; } /* Read data from socket */ while(nread < count) { struct pollfd pfd; int ret; /* Catch pipe close on other end by checking if a read() call would not block by calling poll(). */ pfd.fd = fd; pfd.events = POLLIN|POLLHUP; /* Wait for 5 seconds for a reply. May need to parameterise this... */ ret = poll(&pfd, 1, 5000); if (ret == -1) { winbind_close_sock(); return -1; /* poll error */ } if (ret == 0) { /* Not ready for read yet... */ if (total_time >= 30) { /* Timeout */ winbind_close_sock(); return -1; } total_time += 5; continue; } if ((ret == 1) && (pfd.revents & (POLLIN|POLLHUP|POLLERR))) { /* Do the Read */ int result = read(fd, (char *)buffer + nread, count - nread); if ((result == -1) || (result == 0)) { /* Read failed. I think the only useful thing we can do here is just return -1 and fail since the transaction has failed half way through. */ winbind_close_sock(); return -1; } nread += result; } } return nread; }
int write_sock(void *buffer, int count, int recursing) { int result, nwritten; /* Open connection to winbind daemon */ restart: if (winbind_open_pipe_sock(recursing) == -1) { return -1; } /* Write data to socket */ nwritten = 0; while(nwritten < count) { struct timeval tv; fd_set r_fds; /* Catch pipe close on other end by checking if a read() call would not block by calling select(). */ FD_ZERO(&r_fds); FD_SET(winbindd_fd, &r_fds); ZERO_STRUCT(tv); if (select(winbindd_fd + 1, &r_fds, NULL, NULL, &tv) == -1) { close_sock(); return -1; /* Select error */ } /* Write should be OK if fd not available for reading */ if (!FD_ISSET(winbindd_fd, &r_fds)) { /* Do the write */ result = write(winbindd_fd, (char *)buffer + nwritten, count - nwritten); if ((result == -1) || (result == 0)) { /* Write failed */ close_sock(); return -1; } nwritten += result; } else { /* Pipe has closed on remote end */ close_sock(); goto restart; } } return nwritten; }