Hi,

The patch below implements the following changes to ftp(1), beginning
with the least disruptive and ending with the most disruptive.

1) Change ftp->newer's behavior to match ftp->reget's behavior when
stat(2) on the local file fails: do the file transfer from offset 0
instead of from whatever offset is stored in the global variable
restart_point. 

2) Document ftp->newer's behavior of declining to do the transfer if the
modification time of the remote file cannot be determined.
Make ftp->newer emit an alert when this happens instead of being silent.
Document that ftp -C transfers files using the logic of ftp->reget
(unless I've misread the code, that's literally what happens in fetch.c)

3) Make the options -c and -n of ftp>mget for using reget or newer
exclusive instead of allowing ftp>mget -ncncncncccnc with the last
option winning.

4) Improve ftp>reget's behavior so that a local file is considered to
be a partially complete transfer only if its modification time is
determined to be more recent than the modification time of the remote
file. If so, the transfer is continued from the interruption point,
otherwise, the transfer is restarted from the beginning, overwriting
the local file.

5) Change ftp->reget's behavior to match ftp->newer's behaviour when the
modification time of the remote file cannot be determined: decline the
transfer (and alert!) instead of doing the transer anyway.

The actual diff implements these as follows.
1-5) a rewrite of the restartit conditional in getit() in small.c
3) Simple change to mget() in small.c
2-5) appropriate changes to ftp.1

Additionally, I enacted a few style improvements before the restartit
block in getit() in small.c: I removed some unnecessary braces,
eliminated a '!' from a boolean test, and changed a silly increment
of the 0-initialized variable loc to an explict assignment of 1.

--Vladimir Sotirov

Index: ftp.1
===================================================================
RCS file: /cvs/src/usr.bin/ftp/ftp.1,v
retrieving revision 1.101
diff -u -p -r1.101 ftp.1
--- ftp.1       5 Nov 2015 16:25:57 -0000       1.101
+++ ftp.1       24 Jun 2016 09:26:03 -0000
@@ -123,7 +123,9 @@ to bypass the normal login procedure and
 Continue a previously interrupted file transfer.
 .Nm
 will continue transferring from an offset equal to the length of
-.Ar file .
+.Ar file 
+using the logic of 
+.Ic reget .
 .Pp
 Resuming HTTP(S) transfers are only supported
 if the remote server supports the
@@ -628,7 +630,8 @@ on the remote machine.
 A synonym for
 .Ic mls .
 .It Xo Ic mget
-.Op Fl cnr
+.Op Fl r
+.Op Fl c | n
 .Op Fl d Ar depth
 .Ar remote-files
 .Xc
@@ -746,8 +749,9 @@ directories.
 A synonym for
 .Ic mput .
 .It Ic newer Ar remote-file Op Ar local-file
-Get the file only if the modification time of the remote file is more
-recent than the file on the current system.
+Get the file only if the modification time of the remote file can be 
+determined and is more
+recent than the modification time of the file on the current system.
 If the file does not
 exist on the current system, the remote file is considered
 .Ic newer .
@@ -1073,10 +1077,12 @@ The arguments specified are sent, verbat
 A synonym for
 .Ic get .
 .It Ic reget Ar remote-file Op Ar local-file
-Reget acts like get, except that if
+Reget acts like get, except that it transfers the
+.Ar remote-file
+only if its modification time can be determined, in which case if
 .Ar local-file
 exists and is
-smaller than
+smaller and more recent than 
 .Ar remote-file ,
 .Ar local-file
 is presumed to be
Index: small.c
===================================================================
RCS file: /cvs/src/usr.bin/ftp/small.c,v
retrieving revision 1.6
diff -u -p -r1.6 small.c
--- small.c     25 May 2016 15:36:01 -0000      1.6
+++ small.c     24 Jun 2016 09:26:03 -0000
@@ -215,7 +215,7 @@ getit(int argc, char *argv[], int restar
        if (argc == 2) {
                argc++;
                argv[2] = argv[1];
-               loc++;
+               loc = 1;
        }
 #ifndef SMALL
        if (argc < 2 && !another(&argc, &argv, "remote-file"))
@@ -238,16 +238,14 @@ usage:
        if (loc && mcase) {
                char *tp = argv[1], *tp2, tmpbuf[PATH_MAX];
 
-               while (*tp && !islower((unsigned char)*tp)) {
+               while (*tp && !islower((unsigned char)*tp))
                        tp++;
-               }
-               if (!*tp) {
+               if (*tp == '\0') {
                        tp = argv[2];
                        tp2 = tmpbuf;
                        while ((*tp2 = *tp) != '\0') {
-                               if (isupper((unsigned char)*tp2)) {
+                               if (isupper((unsigned char)*tp2))
                                        *tp2 = tolower((unsigned char)*tp2);
-                               }
                                tp++;
                                tp2++;
                        }
@@ -262,26 +260,29 @@ usage:
        if (restartit) {
                struct stat stbuf;
                int ret;
+               time_t mtime;
 
+               mtime = remotemodtime(argv[1], 0);
                ret = stat(argv[2], &stbuf);
-               if (restartit == 1) {
-                       restart_point = (ret < 0) ? 0 : stbuf.st_size;
-               } else {
-                       if (ret == 0) {
-                               time_t mtime;
-
-                               mtime = remotemodtime(argv[1], 0);
-                               if (mtime == -1)
-                                       goto freegetit;
-                               if (stbuf.st_mtime >= mtime) {
-                                       rval = 1;
-                                       fprintf(ttyout,
-                                               "Local file \"%s\" is newer "\
-                                               "than remote file \"%s\".\n",
-                                               argv[2], argv[1]);
-                                       goto freegetit;
-                               }
-                       }
+
+               if (mtime == -1) {
+                       rval = 1;
+                       fprintf(ttyout,
+                               "Modifcation time of remote file "
+                               "\"%s\" could not be determined.\n",
+                               argv[1]);
+                       goto freegetit;
+               } else if (ret == -1 || mtime > stbuf.st_mtime)
+                       restart_point = 0;
+               else if (restartit == 1)
+                       restart_point = stbuf.st_size;
+               else {
+                       rval = 1;
+                       fprintf(ttyout,
+                               "Local file \"%s\" is newer"
+                               "than remote file \"%s\".\n",
+                               argv[2], argv[1]);
+                       goto freegetit;
                }
        }
 #endif /* !SMALL */
@@ -345,6 +346,8 @@ mget(int argc, char *argv[])
        while ((ch = getopt(argc, argv, "cd:nr")) != -1) {
                switch(ch) {
                case 'c':
+                       if (restartit)
+                               goto usage;
                        restartit = 1;
                        break;
                case 'd':
@@ -357,6 +360,8 @@ mget(int argc, char *argv[])
                        }
                        break;
                case 'n':
+                       if (restartit)
+                               goto usage;
                        restartit = -1;
                        break;
                case 'r':
@@ -369,8 +374,8 @@ mget(int argc, char *argv[])
 
        if (argc - optind < 1 && !another(&argc, &argv, "remote-files")) {
 usage:
-               fprintf(ttyout, "usage: %s [-cnr] [-d depth] remote-files\n",
-                   argv[0]);
+               fprintf(ttyout, "usage: %s [-r] [-c | -n] [-d depth] 
remote-files\n",
+                       argv[0]);
                code = -1;
                return;
        }

Reply via email to