diff options
author | Nathan Straz <nstraz@redhat.com> | 2013-09-26 11:36:39 -0400 |
---|---|---|
committer | Nathan Straz <nstraz@redhat.com> | 2013-10-02 14:11:33 -0400 |
commit | 1aa4bac6bceb8bd1ce0914134d91f59ed46d4a90 (patch) | |
tree | 746bacc6bf192326469bc96bd7eda79a39cb907a /qacp.c | |
parent | 49ef7d04e217579b2b0f9be70396cc4230523476 (diff) | |
download | qarsh-1aa4bac6bceb8bd1ce0914134d91f59ed46d4a90.tar.gz qarsh-1aa4bac6bceb8bd1ce0914134d91f59ed46d4a90.tar.xz qarsh-1aa4bac6bceb8bd1ce0914134d91f59ed46d4a90.zip |
Rewrite send file to handle all packets
This change breaks the qacp protocol!
Before there was a chance we would exit before receiving and checking
all packets from qarshd. Now we look at all packets and check them.
Use data allow packets and larger buffers.
Handle errors on the write end.
Diffstat (limited to 'qacp.c')
-rw-r--r-- | qacp.c | 114 |
1 files changed, 70 insertions, 44 deletions
@@ -148,6 +148,11 @@ qacp_sendonefile(const char *host, const char *srcfile, const char *destfile) struct stat sb; const int bufsize = QARSH_MAX_PACKET_SIZE/2; char buf[bufsize]; + fd_set rfds, wfds; + int nfd; + struct timeval timeout; + int dallow; + int complete; if ((fd = open(srcfile, O_RDONLY)) <0) { @@ -174,59 +179,80 @@ qacp_sendonefile(const char *host, const char *srcfile, const char *destfile) send_packet(qacp_fd, qp); qpfree(qp); - /* Await our return code from qarshd */ - qp = recv_packet(qacp_fd); - if (qp && qp->qp_type == QP_RETURNCODE) { - if (qp->qp_returncode.qp_rc != 0) { - fprintf(stderr, "Remote side failed: %s\n", - qp->qp_returncode.qp_strerror); - qpfree(qp); - goto sendone_error; - } - qpfree(qp); - } else { - fprintf(stderr, "Did not receive response to recvfile\n"); - goto sendone_failure; - } - offset = 0; - do { - nbytes = read(fd, buf, bufsize); - if (nbytes < 0) { - fprintf(stderr, "read() error: %s\n", strerror(errno)); - qp = make_qp_returncode(-1, errno, strerror(errno)); - } else { - qp = make_qp_data(0, offset, nbytes, buf); + dallow = 0; + complete = 0; + for (;;) { + FD_ZERO(&rfds); + FD_SET(qacp_fd, &rfds); + FD_ZERO(&wfds); + if (!complete && dallow > 0) FD_SET(qacp_fd, &wfds); + timeout.tv_sec = 10; + timeout.tv_usec = 0; + + nfd = select(qacp_fd+1, &rfds, &wfds, NULL, &timeout); + if (nfd < 0) { + if (errno == EINTR) { + continue; + } else { + fprintf(stderr, "select errno %d, %s\n", errno, strerror(errno)); + } + } else if (nfd > 0) { + if (nfd && FD_ISSET(qacp_fd, &rfds)) { + qp = recv_packet(qacp_fd); + if (qp == NULL) { + fprintf(stderr, "No packet\n"); + break; + } + if (qp->qp_type == QP_DALLOW) { + if (qp->qp_dallow.qp_count > 0) { + dallow += qp->qp_dallow.qp_count; + } else { + dallow = 0; + } + } else if (qp->qp_type == QP_RETURNCODE) { + if (qp->qp_returncode.qp_rc == 0) { /* success */ + break; + } else if (qp->qp_returncode.qp_rc == -1) { + fprintf(stderr, "Transfer failed: %s\n", + qp->qp_returncode.qp_strerror); + exit(125); + } + } else { + fprintf(stderr, "Received unexpected packet\n"); + dump_qp(qp); + break; + } + qpfree(qp); + } + if (nfd && FD_ISSET(qacp_fd, &wfds)) { + /* Create a data packet to send */ + nbytes = read(fd, buf, dallow); + if (nbytes < 0) { + fprintf(stderr, "read() error: %s\n", + strerror(errno)); + qp = make_qp_returncode(-1, errno, strerror(errno)); + } else { + qp = make_qp_data(0, offset, nbytes, buf); + if (nbytes == 0) { /* Transfer is complete */ + complete = 1; + } else { + offset += nbytes; + dallow -= nbytes; + } + } + send_packet(qacp_fd, qp); + qpfree(qp); + } } - send_packet(qacp_fd, qp); - offset += nbytes; - qpfree(qp); - } while (nbytes > 0); -sendone_failure: - - close(fd); - - /* Await our return code from qarshd */ - qp = recv_packet(qacp_fd); - if (qp && qp->qp_type == QP_RETURNCODE - && qp->qp_returncode.qp_rc == -1) { - fprintf(stderr, "Remote side failed, %s\n", - qp->qp_returncode.qp_strerror); - close(qacp_fd); - qpfree(qp); - exit(125); } - - qpfree(qp); + close(fd); if (!quiet) { printf("%-30.30s -> %s:%s\n", srcfile, host, destfile); } return; -sendone_error: - close(qacp_fd); - exit(125); } |