- while (total < size) {
- int n = MIN(size-total,bufsize);
- read_buf(fd_in,buf,n);
- if (write(fd_out,buf,n) != n)
- return total;
- total += n;
- }
- return total;
+
+/* write len bytes to fd, possibly reading from buffer_f_in if set
+ in order to unclog the pipe. don't return until all len
+ bytes have been written */
+static void writefd_unbuffered(int fd,char *buf,int len)
+{
+ int total = 0;
+ fd_set w_fds, r_fds;
+ int fd_count, count;
+ struct timeval tv;
+ int reading=0;
+ int blocked=0;
+
+ no_flush++;
+
+ while (total < len) {
+ FD_ZERO(&w_fds);
+ FD_ZERO(&r_fds);
+ FD_SET(fd,&w_fds);
+ fd_count = fd+1;
+
+ if (!no_flush_read) {
+ reading = (buffer_f_in != -1 &&
+ read_buffer_len < MAX_READ_BUFFER);
+ }
+
+ if (reading) {
+ FD_SET(buffer_f_in,&r_fds);
+ if (buffer_f_in > fd)
+ fd_count = buffer_f_in+1;
+ }
+
+ tv.tv_sec = io_timeout?io_timeout:SELECT_TIMEOUT;
+ tv.tv_usec = 0;
+
+ count = select(fd_count,
+ reading?&r_fds:NULL,
+ &w_fds,NULL,
+ &tv);
+
+ if (count <= 0) {
+ check_timeout();
+ continue;
+ }
+
+ if (reading && FD_ISSET(buffer_f_in, &r_fds)) {
+ read_check(buffer_f_in);
+ }
+
+ if (FD_ISSET(fd, &w_fds)) {
+ int n = (len-total)>>blocked;
+ int ret = write(fd,buf+total,n?n:1);
+
+ if (ret == -1 && errno == EINTR) {
+ continue;
+ }
+
+ if (ret == -1 &&
+ (errno == EAGAIN || errno == EWOULDBLOCK)) {
+ blocked++;
+ continue;
+ }
+
+ if (ret <= 0) {
+ rprintf(FERROR,"erroring writing %d bytes - exiting\n", len);
+ exit_cleanup(1);
+ }
+
+ blocked = 0;
+ total += ret;
+ stats.total_written += ret;
+
+ if (io_timeout)
+ last_io = time(NULL);
+ }
+ }
+
+ no_flush--;