From dc0208b08c7df7c0e559b021bdffcebdb2dc221e Mon Sep 17 00:00:00 2001 From: Nate Straz Date: Tue, 13 Sep 2005 19:47:14 +0000 Subject: Merge qarsh revisions 1727:1738 from sistina-test branch djansa-qarsh. --- qacp.c | 331 +++++++++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 271 insertions(+), 60 deletions(-) (limited to 'qacp.c') diff --git a/qacp.c b/qacp.c index aa3f22e..90185dd 100644 --- a/qacp.c +++ b/qacp.c @@ -45,29 +45,6 @@ usage() "qacp [user@]host: [[user@]host: ...] "); } -char * -copyargs(char **argv) -{ - int cc; - char **ap, *p; - char *args; - - cc = 0; - for (ap = argv; *ap; ++ap) - cc += strlen(*ap) + 1; - if (cc == 0) return NULL; - args = malloc(cc); - if (!args) { - perror("qacp: malloc failed in copyargs"); - exit(1); - } - for (p = args, ap = argv; *ap; ++ap) { - for (p = strcpy(p, *ap); *p; ++p); - if (ap[1]) - *p++ = ' '; - } - return args; -} void set_remote_user(char *user, char *group) @@ -89,6 +66,38 @@ set_remote_user(char *user, char *group) } } + +struct qp_rstat_pkt * +qacp_rstat(const char *rmtpath, int *rstaterrno) +{ + struct qa_packet *qp; + struct qp_rstat_pkt *rstatp; + + qp = make_qp_rstat(rmtpath, NULL); + send_packet(qacp_fd, qp); + qpfree(qp); + + qp = recv_packet(qacp_fd); + if (qp) { + if (qp->qp_type == QP_RSTAT) { + rstatp = malloc(sizeof *rstatp); + rstatp->qp_path = strdup(qp->qp_rstat.qp_path); + rstatp->qp_st_mode = qp->qp_rstat.qp_st_mode; + rstatp->qp_st_uid = qp->qp_rstat.qp_st_uid; + rstatp->qp_st_gid = qp->qp_rstat.qp_st_gid; + rstatp->qp_st_size = qp->qp_rstat.qp_st_size; + *rstaterrno = 0; + } else if (qp->qp_type == QP_RETURNCODE) { + rstatp = NULL; + *rstaterrno = qp->qp_returncode.qp_errno; + } + + qpfree(qp); + } + + return rstatp; +} + void qacp_sendonefile(const char *host, const char *srcfile, const char *destfile) { @@ -103,9 +112,6 @@ qacp_sendonefile(const char *host, const char *srcfile, const char *destfile) off_t offset = 0; struct stat sb; - /* Recall that the packet types are qarshd-centric, so if we want - * to send a file to the host running qarshd we have to tell - * qarshd to recv a file. */ if ((fd = open(srcfile, O_RDONLY)) <0) { fprintf(stderr, "Could not open %s: %s\n", srcfile, strerror(errno)); @@ -122,6 +128,10 @@ qacp_sendonefile(const char *host, const char *srcfile, const char *destfile) sd = bind_any(QARSH_MINPORT); port = getsockport(sd); + /* Recall that the packet types are qarshd-centric, so if we want + * to send a file to the host running qarshd we have to tell + * qarshd to recv a file. */ + qp = make_qp_recvfile(destfile, port, sb.st_size, sb.st_mode); qp->qp_seq = 1; send_packet(qacp_fd, qp); @@ -149,65 +159,264 @@ qacp_sendonefile(const char *host, const char *srcfile, const char *destfile) return; } + void qacp_recvonefile(const char *host, const char *srcfile, const char *destfile) { struct qa_packet *qp; + struct sockaddr_in daddr; + socklen_t dlen; + int sd; + int port; + int insd; + int outfd; + char buf[BUFSIZ]; + ssize_t nread; + ssize_t nwrote; + ssize_t nleft; + struct qp_rstat_pkt *rstatp; + int rstaterrno; + + rstatp = qacp_rstat(srcfile, &rstaterrno); + if (!rstatp) { + fprintf(stderr, "%s: %s\n", srcfile, strerror(rstaterrno)); + return; + } + + 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); + } + + fchmod(outfd, rstatp->qp_st_mode); + + sd = bind_any(QARSH_MINPORT); + port = getsockport(sd); /* Recall that the packet types are qarshd-centric, so if we want * to recv a file from the host running qarshd we have to tell * qarshd to send a file. */ - qp = make_qp_sendfile(srcfile, 88, 8888); + qp = make_qp_sendfile(srcfile, port); qp->qp_seq = 1; send_packet(qacp_fd, qp); qpfree(qp); + dlen = sizeof daddr; + insd = accept(sd, (struct sockaddr *) &daddr, &dlen); + + /* Read/write file */ + nleft = rstatp->qp_st_size; + while (nleft > 0) { + nread = read(insd, buf, BUFSIZ); + if (nread < 0) { + fprintf(stderr, "read() error: %s\n", strerror(errno)); + break; + } else if (nread == 0) { /* EOF */ + break; + } + + nwrote = write(outfd, buf, nread); + if (nwrote < 0) { + fprintf(stderr, "write() error: %s\n", strerror(errno)); + break; + } + + nleft -= nread; + } + + if (nleft != 0) { + unlink(destfile); + fprintf(stderr, "Short file transfer of %s, " + "%zd bytes lost, wanted %ld\n", srcfile, nleft, + rstatp->qp_st_size); + } + + close(sd); + close(insd); + close(outfd); + + /* 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); + exit(125); + } + return; } -struct qp_rstat_pkt * -qacp_rstat(const char *rmtpath, int *rstaterrno) +int +recvfiles(char **argv, int argc, int fileidx, short recursive, short quiet) { - struct qa_packet *qp; + char *cp; + char *rhost = NULL; + char *ruser = NULL; + char *rgrp = NULL; + struct passwd *pw; + int file; + char *rmtpath; + char *destpath; + int destisdir; + char *tmpstr; + char *ldnp; /* local path dirname */ + char *rbnp; /* remote path basename */ struct qp_rstat_pkt *rstatp; + struct stat sb; + int rstaterrno; - qp = make_qp_rstat(rmtpath, NULL); - send_packet(qacp_fd, qp); - qpfree(qp); + if (strchr(argv[argc-1], ':') != NULL) { + fprintf(stderr, "%s is not a valid local file string\n", + argv[argc-1]); + return -1; + } - qp = recv_packet(qacp_fd); - if (qp) { - if (qp->qp_type == QP_RSTAT) { - rstatp = malloc(sizeof *rstatp); - rstatp->qp_path = strdup(qp->qp_rstat.qp_path); - rstatp->qp_st_mode = qp->qp_rstat.qp_st_mode; - rstatp->qp_st_uid = qp->qp_rstat.qp_st_uid; - rstatp->qp_st_gid = qp->qp_rstat.qp_st_gid; - rstatp->qp_st_size = qp->qp_rstat.qp_st_size; - *rstaterrno = 0; - } else if (qp->qp_type == QP_RETURNCODE) { - rstatp = NULL; - *rstaterrno = qp->qp_returncode.qp_errno; + destpath = strdup(argv[argc-1]); + + /* Figure out if our destpath is just a dir. + * If so we need to set the flag to tack on the remote + * path basename onto our destpath + */ + + if (stat(destpath, &sb) < 0) { + /* stat couldn't file the file, check if the dirname exists, + * if so we need to reset our destpath to the local dirname + * if that directory exists. + */ + tmpstr = strdup(destpath); + ldnp = strdup(dirname(tmpstr)); + free(tmpstr); + if (stat(ldnp, &sb) < 0) { + fprintf(stderr, "%s: %s\n", ldnp, strerror(errno)); + return -1; } - qpfree(qp); - } + if (S_ISDIR(sb.st_mode)) { + /* No, we don't want to set destisdir, as our dest is really + * a full path, we striped off the filename above to check + * the rest of the path exists. + */ + destisdir = 0; + } else { + fprintf(stderr, "%s not a directory\n", ldnp); + return -1; + } + } else { + if (S_ISDIR(sb.st_mode)) { + destisdir = 1; + } else if (S_ISREG(sb.st_mode)) { + destisdir = 0; + } else { + fprintf(stderr, "%s not a file or directory\n", destpath); + return -1; + } + } + - return rstatp; -} + for (file = fileidx; file < (argc - 1); file++) { + + /* For each file in remote file list (fileidx to argc-2) */ + /* Rstat the file, if it is a dir, error */ + /* Otherwise copy it to local location */ + + if (strchr(argv[file], ':') == NULL) { + fprintf(stderr, "%s is not a valid remote host:file string\n", + argv[file]); + return -1; + } + + rhost = strdup(argv[file]); + cp = strchr(rhost, ':'); + *cp = '\0'; + + /* Grab any user/group info */ + if ((cp = strchr(rhost, '@'))) { + ruser = rhost; + rhost = cp+1; + *cp = '\0'; + } + + if (ruser && (cp = strchr(ruser, '.'))) { + rgrp = cp+1; + *cp = '\0'; + } + + if (!(pw = getpwuid(getuid()))) { + fprintf(stderr, "qacp: unknown user id.\n"); + return -1; + } + + if (ruser == NULL) { + ruser = strdup(pw->pw_name); + } + + qacp_fd = connect_to_host(rhost, QARSHD_CONTROL_PORT); + if (qacp_fd == -1) { + if (errno == 0) { + fprintf(stderr, "Could not connect to %s:%d, %d: %s\n", + rhost, QARSHD_CONTROL_PORT, h_errno, hstrerror(h_errno)); + } else { + fprintf(stderr, "Could not connect to %s:%d, %d: %s\n", + rhost, QARSHD_CONTROL_PORT, errno, strerror(errno)); + } + return -1; + } + + set_remote_user(ruser, rgrp); + + cp = strdup(argv[file]); + cp = strchr(argv[file], ':'); + cp++; + + rmtpath = strdup(cp); + + rstatp = qacp_rstat(rmtpath, &rstaterrno); + if (rstatp) { + if (S_ISREG(rstatp->qp_st_mode)) { + if (destisdir) { + cp = strdup(rmtpath); + rbnp = strdup(basename(cp)); + free(cp); + + cp = malloc(strlen(destpath) + strlen(rbnp) + 2); + strcpy(cp, destpath); + strcat(cp, "/"); + strcat(cp, rbnp); + + qacp_recvonefile(rhost, rmtpath, cp); + free(cp); + free(rbnp); + } else { + if (!quiet) { + printf("%s:%s -> %30.30s\n", + rhost, rmtpath, destpath); + } + qacp_recvonefile(rhost, rmtpath, destpath); + } + } + if (S_ISDIR(rstatp->qp_st_mode)) { + fprintf(stderr, "%s: Not a regular file\n", argv[file]); + return -1; + } + } else { + fprintf(stderr, "%s: %s\n", argv[file], strerror(rstaterrno)); + return -1; + } + + close(qacp_fd); + } -int -recvfiles(char **argv, int argc, short recursive, short quiet) -{ - puts("recvfiles() NA"); return 0; } int -sendfiles(char **argv, int argc, short recursive, short quiet) +sendfiles(char **argv, int argc, int fileidx, short recursive, short quiet) { char *cp; char *rhost = NULL; @@ -276,7 +485,7 @@ sendfiles(char **argv, int argc, short recursive, short quiet) rstatp = qacp_rstat(rmtpath, &rstaterrno); - for (file = optind; file < (argc - 1); file++) { + for (file = fileidx; file < (argc - 1); file++) { tmpstr = strdup(argv[file]); lbnp = strdup(basename(tmpstr)); free(tmpstr); @@ -318,7 +527,7 @@ sendfiles(char **argv, int argc, short recursive, short quiet) } if (!quiet) { - printf("%-40.40s -> %s:%s\n", argv[file], rhost, destpath); + printf("%-30.30s -> %s:%s\n", argv[file], rhost, destpath); } qacp_sendonefile(rhost, argv[file], destpath); @@ -342,6 +551,8 @@ main(int argc, char *argv[]) while ((c = getopt(argc, argv, "+rq")) != -1) { switch (c) { case 'r': + fprintf(stderr, "-r not supported\n"); + exit(2); recursive = 1; break; case 'q': @@ -355,7 +566,7 @@ main(int argc, char *argv[]) } } - if (argv[optind + 1] == NULL) { + if (argv[optind] == NULL) { usage(); exit(2); } @@ -363,11 +574,11 @@ main(int argc, char *argv[]) eflag = 0; /* If last arg has a ':' then we are sending files */ if (strchr(argv[argc-1], ':') != NULL) { - if (sendfiles(argv, argc, recursive, quiet) < 0) { + if (sendfiles(argv, argc, optind, recursive, quiet) < 0) { eflag++; } } else { - if (recvfiles(argv, argc, recursive, quiet) < 0) { + if (recvfiles(argv, argc, optind, recursive, quiet) < 0) { eflag++; } } -- cgit