summaryrefslogtreecommitdiff
path: root/usr.bin/ftp
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2012-10-15 21:20:06 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2012-10-15 21:20:06 +0000
commiteafb8cff86203eabbce33f10fc7d19a470fd5f1b (patch)
treee6f809ac306db49535d534ca5c0cc22c8dbb49c2 /usr.bin/ftp
parent40c9234ba53149b667a454da14175962636d3ec3 (diff)
Add support for recursive ftp upload. The mput command of the ftp
client got the -r switch and -d depth option. From Jan Klemkow <j.klemkow AT wemelug DOT de> OK haesbaert@
Diffstat (limited to 'usr.bin/ftp')
-rw-r--r--usr.bin/ftp/cmds.c121
-rw-r--r--usr.bin/ftp/ftp.121
2 files changed, 116 insertions, 26 deletions
diff --git a/usr.bin/ftp/cmds.c b/usr.bin/ftp/cmds.c
index ec6e99357b2..5b424182bf8 100644
--- a/usr.bin/ftp/cmds.c
+++ b/usr.bin/ftp/cmds.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmds.c,v 1.70 2009/05/05 19:35:30 martynas Exp $ */
+/* $OpenBSD: cmds.c,v 1.71 2012/10/15 21:20:05 bluhm Exp $ */
/* $NetBSD: cmds.c,v 1.27 1997/08/18 10:20:15 lukem Exp $ */
/*
@@ -231,15 +231,32 @@ mput(int argc, char *argv[])
extern int optind, optreset;
int ch, i, restartit = 0;
sig_t oldintr;
- char *cmd, *tp;
+ char *cmd, *tp, *xargv[] = { argv[0], NULL, NULL };
+ const char *errstr;
+ static int depth = 0, max_depth = 0;
optind = optreset = 1;
- while ((ch = getopt(argc, argv, "c")) != -1) {
+ if (depth)
+ depth++;
+
+ while ((ch = getopt(argc, argv, "cd:r")) != -1) {
switch(ch) {
case 'c':
restartit = 1;
break;
+ case 'd':
+ max_depth = strtonum(optarg, 0, INT_MAX, &errstr);
+ if (errstr != NULL) {
+ fprintf(ttyout, "bad depth value, %s: %s\n",
+ errstr, optarg);
+ code = -1;
+ return;
+ }
+ break;
+ case 'r':
+ depth = 1;
+ break;
default:
goto usage;
}
@@ -247,7 +264,8 @@ mput(int argc, char *argv[])
if (argc - optind < 1 && !another(&argc, &argv, "local-files")) {
usage:
- fprintf(ttyout, "usage: %s [-c] local-files\n", argv[0]);
+ fprintf(ttyout, "usage: %s [-cr] [-d depth] local-files\n",
+ argv[0]);
code = -1;
return;
}
@@ -318,11 +336,13 @@ usage:
mflag = 0;
return;
}
+
for (i = 1; i < argc; i++) {
char **cpp;
glob_t gl;
int flags;
+ /* Copy files without word expansion */
if (!doglob) {
if (mflag && confirm(argv[0], argv[i])) {
tp = (ntflag) ? dotrans(argv[i]) : argv[i];
@@ -348,6 +368,7 @@ usage:
continue;
}
+ /* expanding file names */
memset(&gl, 0, sizeof(gl));
flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
if (glob(argv[i], flags, NULL, &gl) || gl.gl_pathc == 0) {
@@ -355,33 +376,89 @@ usage:
globfree(&gl);
continue;
}
+
+ /* traverse all expanded file names */
for (cpp = gl.gl_pathv; cpp && *cpp != NULL; cpp++) {
- if (mflag && confirm(argv[0], *cpp)) {
- tp = (ntflag) ? dotrans(*cpp) : *cpp;
- tp = (mapflag) ? domap(tp) : tp;
- if (restartit == 1) {
- off_t ret;
+ struct stat filestat;
- if (curtype != type)
- changetype(type, 0);
- ret = remotesize(tp, 0);
- restart_point = (ret < 0) ? 0 : ret;
+ if (!mflag)
+ continue;
+ if (stat(*cpp, &filestat) != 0) {
+ warn("local: %s", *cpp);
+ continue;
+ }
+ if (S_ISDIR(filestat.st_mode) && depth == max_depth)
+ continue;
+ if (!confirm(argv[0], *cpp))
+ continue;
+
+ /*
+ * If file is a directory then create a new one
+ * at the remote machine.
+ */
+ if (S_ISDIR(filestat.st_mode)) {
+ xargv[1] = *cpp;
+ makedir(2, xargv);
+ cd(2, xargv);
+ if (dirchange != 1) {
+ warnx("remote: %s", *cpp);
+ continue;
}
- cmd = restartit ? "APPE" : ((sunique) ?
- "STOU" : "STOR");
- sendrequest(cmd, *cpp, tp,
- *cpp != tp || !interactive);
- restart_point = 0;
- if (!mflag && fromatty) {
- if (confirm(argv[0], NULL))
- mflag = 1;
+
+ if (chdir(*cpp) != 0) {
+ warn("local: %s", *cpp);
+ goto out;
}
+
+ /* Copy the whole directory recursively. */
+ xargv[1] = "*";
+ mput(2, xargv);
+
+ if (chdir("..") != 0) {
+ mflag = 0;
+ warn("local: %s", *cpp);
+ goto out;
+ }
+
+ out:
+ xargv[1] = "..";
+ cd(2, xargv);
+ if (dirchange != 1) {
+ warnx("remote: %s", *cpp);
+ mflag = 0;
+ }
+ continue;
+ }
+
+ tp = (ntflag) ? dotrans(*cpp) : *cpp;
+ tp = (mapflag) ? domap(tp) : tp;
+ if (restartit == 1) {
+ off_t ret;
+
+ if (curtype != type)
+ changetype(type, 0);
+ ret = remotesize(tp, 0);
+ restart_point = (ret < 0) ? 0 : ret;
+ }
+ cmd = restartit ? "APPE" : ((sunique) ?
+ "STOU" : "STOR");
+ sendrequest(cmd, *cpp, tp,
+ *cpp != tp || !interactive);
+ restart_point = 0;
+ if (!mflag && fromatty) {
+ if (confirm(argv[0], NULL))
+ mflag = 1;
}
}
globfree(&gl);
}
+
(void)signal(SIGINT, oldintr);
- mflag = 0;
+
+ if (depth)
+ depth--;
+ if (depth == 0 || mflag == 0)
+ depth = max_depth = mflag = 0;
}
void
diff --git a/usr.bin/ftp/ftp.1 b/usr.bin/ftp/ftp.1
index abce0bd3e3c..3f147c34293 100644
--- a/usr.bin/ftp/ftp.1
+++ b/usr.bin/ftp/ftp.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: ftp.1,v 1.84 2012/08/26 02:16:02 lteo Exp $
+.\" $OpenBSD: ftp.1,v 1.85 2012/10/15 21:20:05 bluhm Exp $
.\" $NetBSD: ftp.1,v 1.22 1997/08/18 10:20:22 lukem Exp $
.\"
.\" Copyright (c) 1985, 1989, 1990, 1993
@@ -30,7 +30,7 @@
.\"
.\" @(#)ftp.1 8.3 (Berkeley) 10/9/94
.\"
-.Dd $Mdocdate: August 26 2012 $
+.Dd $Mdocdate: October 15 2012 $
.Dt FTP 1
.Os
.Sh NAME
@@ -655,7 +655,8 @@ on the remote machine.
A synonym for
.Ic page .
.It Xo Ic mput
-.Op Fl c
+.Op Fl cr
+.Op Fl d Ar depth
.Ar local-files
.Xc
Expand wild cards in the list of local files given as arguments
@@ -674,9 +675,21 @@ settings.
If the
.Fl c
flag is specified then
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl c
+Use
.Ic reput
-is used instead of
+instead of
.Ic put .
+.It Fl d Ar depth
+Specify the maximum recursion level
+.Ar depth .
+The default is 0, which means unlimited.
+.It Fl r
+Recursively descend the directory tree, transferring all files and
+directories.
+.El
.It Xo Ic msend
.Op Fl c
.Ar local-files