diff options
author | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2012-10-15 21:20:06 +0000 |
---|---|---|
committer | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2012-10-15 21:20:06 +0000 |
commit | eafb8cff86203eabbce33f10fc7d19a470fd5f1b (patch) | |
tree | e6f809ac306db49535d534ca5c0cc22c8dbb49c2 /usr.bin/ftp | |
parent | 40c9234ba53149b667a454da14175962636d3ec3 (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.c | 121 | ||||
-rw-r--r-- | usr.bin/ftp/ftp.1 | 21 |
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 |