libfetch ftp patch for less latency



To speed up pkg_add and other ftp command channel performance over slow
links, change this:

PWD
<<< 257 "/"
CWD pub
<<< 250 Directory successfully changed.
CWD FreeBSD
<<< 250 Directory successfully changed.
CWD ports
<<< 250 Directory successfully changed.
CWD amd64
<<< 250 Directory successfully changed.
CWD packages-6-stable
<<< 250 Directory successfully changed.
CWD Latest
<<< 250 Directory successfully changed.
MODE S

Into this:

PWD
<<< 257 "/"
CWD pub/FreeBSD/ports/amd64/packages-6-stable/Latest
<<< 250 Directory successfully changed.

All ftp servers I've ever seen support a full path when changing down
dirs. This might be a DOS ftp server thing however. In any case, if
there is an error to the all-in-one CWD, the code reverts back to legacy
behavior of multiple CWDs.

--
Nate
===================================================================
RCS file: /home/ncvs/src/lib/libfetch/ftp.c,v
--- ftp.c 22 Jul 2006 06:01:58 -0000 1.91.2.1
+++ ftp.c 28 Mar 2007 20:42:58 -0000
@@ -267,6 +267,7 @@
char pwd[PATH_MAX];
int e, i, len;

+ /* If no slashes in name, no need to change dirs. */
if ((end = strrchr(file, '/')) == NULL)
return (0);
if ((e = _ftp_cmd(conn, "PWD")) != FTP_WORKING_DIRECTORY ||
@@ -276,7 +277,8 @@
}
for (;;) {
len = strlen(pwd);
- /* look for a common prefix */
+
+ /* Look for a common prefix between PWD and dir to fetch. */
for (i = 0; i <= len && i <= end - file; ++i)
if (pwd[i] != file[i])
break;
@@ -284,6 +286,7 @@
DEBUG(fprintf(stderr, "have: [%.*s|%s]\n", i, pwd, pwd + i));
DEBUG(fprintf(stderr, "want: [%.*s|%s]\n", i, file, file + i));
#endif
+ /* Keep going up a dir until we have a matching prefix. */
if (pwd[i] == '\0' && (file[i - 1] == '/' || file[i] == '/'))
break;
if ((e = _ftp_cmd(conn, "CDUP")) != FTP_FILE_ACTION_OK ||
@@ -293,6 +296,21 @@
return (-1);
}
}
+
+ /* Skip leading slashes, even "////". */
+ for (beg = file + i; beg < end && *beg == '/'; ++beg, ++i)
+ /* nothing */ ;
+
+ /* If there is no trailing dir, we're already there. */
+ if (beg >= end)
+ return (0);
+
+ /* Change to the directory all in one chunk (e.g., foo/bar/baz). */
+ e = _ftp_cmd(conn, "CWD %.*s", (int)(end - beg), beg);
+ if (e == FTP_FILE_ACTION_OK)
+ return (0);
+
+ /* That didn't work so go back to legacy behavior (multiple CWDs). */
for (beg = file + i; beg < end; beg = file + i + 1) {
while (*beg == '/')
++beg, ++i;
_______________________________________________
freebsd-current@xxxxxxxxxxx mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to "freebsd-current-unsubscribe@xxxxxxxxxxx"