From b1c21ed4dc79b4250d604570c7516e267a521792 Mon Sep 17 00:00:00 2001 From: Nathan Straz Date: Wed, 2 Oct 2013 11:22:22 -0400 Subject: Handle errors better in qacp Pass errors up from the transfer functions so we can keep track of errors and continue trying to transfer all files. Make output more consistent and all on stderr. --- qacp.c | 107 +++++++++++++++++++++++++++++++++++++------------------------ sockutil.c | 2 -- 2 files changed, 65 insertions(+), 44 deletions(-) diff --git a/qacp.c b/qacp.c index cf76652..b2f4535 100644 --- a/qacp.c +++ b/qacp.c @@ -134,7 +134,7 @@ free_rstat(struct qp_rstat_pkt *p) free(p); } -void +int qacp_sendonefile(const char *host, const char *srcfile, const char *destfile) { struct qa_packet *qp; @@ -149,22 +149,28 @@ qacp_sendonefile(const char *host, const char *srcfile, const char *destfile) int dallow; int complete; + if (!quiet) { + fprintf(stderr, "%s -> ", srcfile); + } if ((fd = open(srcfile, O_RDONLY)) <0) { fprintf(stderr, "Could not open %s: %s\n", srcfile, strerror(errno)); - close(qacp_fd); - exit(errno); + return -1; } if (fstat(fd, &sb) < 0) { fprintf(stderr, "Could not stat %s: %s\n", srcfile, strerror(errno)); - close(qacp_fd); - exit(errno); + return -1; } if (S_ISDIR(sb.st_mode)) { fprintf(stderr, "Skipping directory %s, recursive not supported, use rsync.\n", srcfile); - return; + return -1; + } + + if (!S_ISREG(sb.st_mode)) { + fprintf(stderr, "Skipping %s, not a regular file.\n", srcfile); + return -1; } /* Packet types are qarshd-centric, so if we want to send a file to the @@ -210,7 +216,7 @@ qacp_sendonefile(const char *host, const char *srcfile, const char *destfile) } else if (qp->qp_returncode.qp_rc == -1) { fprintf(stderr, "Transfer failed: %s\n", qp->qp_returncode.qp_strerror); - exit(125); + return -1; } } else { fprintf(stderr, "Received unexpected packet\n"); @@ -241,15 +247,15 @@ qacp_sendonefile(const char *host, const char *srcfile, const char *destfile) } close(fd); - if (!quiet) { - printf("%-30.30s -> %s:%s\n", srcfile, host, destfile); + if (!quiet && complete) { + fprintf(stderr, "%s:%s\n", host, destfile); } - return; + return 0; } -void +int qacp_recvonefile(const char *host, const char *srcfile, const char *destfile) { struct qa_packet *qp; @@ -261,17 +267,21 @@ qacp_recvonefile(const char *host, const char *srcfile, const char *destfile) fd_set rfds; int nfd; struct timeval timeout; + int fail = 0; + + if (!quiet) { + fprintf(stderr, "%s:%s -> ", host, srcfile); + } rstatp = qacp_rstat(srcfile, &rstaterrno); if (!rstatp) { fprintf(stderr, "%s: %s\n", srcfile, strerror(rstaterrno)); - return; + return 1; } if ((outfd = open(destfile, O_TRUNC|O_CREAT|O_WRONLY)) < 0) { fprintf(stderr, "Could not open %s: %s\n", destfile, strerror(errno)); - close(qacp_fd); - exit(errno); + return 1; } fchmod(outfd, rstatp->qp_st_mode); @@ -301,6 +311,8 @@ qacp_recvonefile(const char *host, const char *srcfile, const char *destfile) continue; } else { fprintf(stderr, "select errno %d, %s\n", errno, strerror(errno)); + fail = 1; + break; } } else if (nfd > 0) { if (nfd && FD_ISSET(qacp_fd, &rfds)) { @@ -326,20 +338,27 @@ qacp_recvonefile(const char *host, const char *srcfile, const char *destfile) nwrote += ret; } while (nwrote < qp->qp_data.qp_count); - rp = make_qp_data_allow(0, nwrote); - send_packet(qacp_fd, rp); - qpfree(rp); + if (nwrote == qp->qp_data.qp_count) { + rp = make_qp_data_allow(0, nwrote); + send_packet(qacp_fd, rp); + qpfree(rp); + } else { + fail = 1; + break; + } } 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); + fail = 1; + break; } } else { fprintf(stderr, "Received unexpected packet\n"); dump_qp(qp); + fail = 1; break; } qpfree(qp); @@ -348,11 +367,11 @@ qacp_recvonefile(const char *host, const char *srcfile, const char *destfile) } close(outfd); - if (!quiet) { - printf("%s:%s -> %30.30s\n", host, srcfile, destfile); + if (!quiet && !fail) { + fprintf(stderr, "%s\n", destfile); } - return; + return fail; } @@ -373,12 +392,7 @@ recvfiles(char **argv, int argc, int fileidx) struct qp_rstat_pkt *rstatp; struct stat sb; int rstaterrno; - - if (strchr(argv[argc-1], ':') != NULL) { - fprintf(stderr, "%s is not a valid local file string\n", - argv[argc-1]); - return -1; - } + int eflag = 0; destpath = strdup(argv[argc-1]); @@ -467,6 +481,15 @@ recvfiles(char **argv, int argc, int fileidx) ruser = pw->pw_name; } + + if (strchr(rmtpath, '*') + || strchr(rmtpath, '?') + || strchr(rmtpath, '[')) { + fprintf(stderr, "globs are not supported on remote paths\n"); + eflag |= 1; + continue; + } + qacp_fd = connect_to_host(rhost, QARSHD_CONTROL_PORT, &qarsh_ss_family); if (qacp_fd == -1) { if (errno == 0) { @@ -489,33 +512,30 @@ recvfiles(char **argv, int argc, int fileidx) cp = malloc(strlen(destpath) + strlen(rbnp) + 2); strcpy(cp, destpath); - strcat(cp, "/"); + if (cp[strlen(cp)-1] != '/') strcat(cp, "/"); strcat(cp, rbnp); - qacp_recvonefile(rhost, rmtpath, cp); + eflag |= qacp_recvonefile(rhost, rmtpath, cp); free(cp); } else { - qacp_recvonefile(rhost, rmtpath, destpath); + eflag |= qacp_recvonefile(rhost, rmtpath, destpath); } } if (S_ISDIR(rstatp->qp_st_mode)) { - fprintf(stderr, "%s: Not a regular file\n", argv[file]); - free(destpath); - free(rmtpath); - free_rstat(rstatp); - return -1; + fprintf(stderr, "%s:%s -> Not a regular file\n", rhost, rmtpath); + eflag |= 1; } free_rstat(rstatp); } else { - fprintf(stderr, "%s: %s\n", argv[file], strerror(rstaterrno)); - goto error_free_destpath; + fprintf(stderr, "%s:%s -> %s\n", rhost, rmtpath, strerror(rstaterrno)); + eflag |= 1; } close(qacp_fd); } /* for file */ free(destpath); - return 0; + return eflag ? -1 : 0; error_free_destpath: free(destpath); @@ -539,6 +559,7 @@ sendfiles(char **argv, int argc, int fileidx) char *rdnp; /* remote path dirname */ struct qp_rstat_pkt *rstatp; int rstaterrno; + int fail = 0; if ((rmtpath = strchr(argv[argc-1], ':')) == NULL) { @@ -598,7 +619,7 @@ sendfiles(char **argv, int argc, int fileidx) if (S_ISDIR(rstatp->qp_st_mode)) { destpath = malloc(strlen(rmtpath) + strlen(lbnp) + 2); strcpy(destpath, rmtpath); - strcat(destpath, "/"); + if (destpath[strlen(destpath)-1] != '/') strcat(destpath, "/"); strcat(destpath, lbnp); } @@ -631,7 +652,9 @@ sendfiles(char **argv, int argc, int fileidx) } } - qacp_sendonefile(rhost, argv[file], destpath); + if (qacp_sendonefile(rhost, argv[file], destpath) < 0) { + fail = 1; + } free(destpath); } @@ -641,7 +664,7 @@ sendfiles(char **argv, int argc, int fileidx) } close(qacp_fd); - return 0; + return fail ? -1 : 0; } @@ -660,7 +683,7 @@ main(int argc, char *argv[]) case 'h': default: usage(); - exit(1); + exit(2); } } diff --git a/sockutil.c b/sockutil.c index 87a718b..c180eb3 100644 --- a/sockutil.c +++ b/sockutil.c @@ -56,8 +56,6 @@ connect_to_host(char *hostname, int port, unsigned short *ss_family) snprintf(portstr, NI_MAXSERV, "%d", port); if ((err = getaddrinfo(hostname, portstr, &hints, &ail)) != 0) { - lprintf(LOG_ERR, "Could not resolve hostname %s: %s\n", - hostname, gai_strerror(err)); return -1; } -- cgit