summaryrefslogtreecommitdiffstats
path: root/qacp.c
diff options
context:
space:
mode:
authorNate Straz <nstraz@redhat.com>2005-09-13 19:47:14 +0000
committerNathan Straz <nstraz@redhat.com>2008-09-23 09:37:44 -0400
commitdc0208b08c7df7c0e559b021bdffcebdb2dc221e (patch)
tree63c15c2651515f369792ea30141c6286e8de450f /qacp.c
parent988f9b104087022ecf08ed881aa723fcb33a46b6 (diff)
downloadqarsh-dc0208b08c7df7c0e559b021bdffcebdb2dc221e.tar.gz
qarsh-dc0208b08c7df7c0e559b021bdffcebdb2dc221e.tar.xz
qarsh-dc0208b08c7df7c0e559b021bdffcebdb2dc221e.zip
Merge qarsh revisions 1727:1738 from sistina-test branch djansa-qarsh.
Diffstat (limited to 'qacp.c')
-rw-r--r--qacp.c331
1 files changed, 271 insertions, 60 deletions
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:<rmtpath> [[user@]host:<rmtpath> ...] <localpath> ");
}
-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++;
}
}