Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/external/bsd/fetch/dist/libfetch libfetch-2.31:



details:   https://anonhg.NetBSD.org/src/rev/d678a1fbf04a
branches:  trunk
changeset: 753376:d678a1fbf04a
user:      joerg <joerg%NetBSD.org@localhost>
date:      Wed Mar 24 20:51:41 2010 +0000

description:
libfetch-2.31:

PR 43013 by Brook Milligan: fetch(3) violates RFC 1738 for ftp:// URLs
if the home directory is not the root directory.

Remember the current directory the first time a CWD / CDUP has to be
issued. Use the document as full URL if the URL started with two /
(quoted or not), otherwise append it to the initial directory.

diffstat:

 external/bsd/fetch/dist/libfetch/common.c |    4 +-
 external/bsd/fetch/dist/libfetch/common.h |    4 +-
 external/bsd/fetch/dist/libfetch/ftp.c    |  136 ++++++++++++++++++++---------
 3 files changed, 97 insertions(+), 47 deletions(-)

diffs (238 lines):

diff -r 546ae5e3861c -r d678a1fbf04a external/bsd/fetch/dist/libfetch/common.c
--- a/external/bsd/fetch/dist/libfetch/common.c Wed Mar 24 19:33:51 2010 +0000
+++ b/external/bsd/fetch/dist/libfetch/common.c Wed Mar 24 20:51:41 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: common.c,v 1.1.1.8 2010/01/30 21:26:09 joerg Exp $     */
+/*     $NetBSD: common.c,v 1.1.1.9 2010/03/24 20:51:41 joerg Exp $     */
 /*-
  * Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav
  * Copyright (c) 2008, 2010 Joerg Sonnenberger <joerg%NetBSD.org@localhost>
@@ -231,6 +231,7 @@
        /* allocate and fill connection structure */
        if ((conn = calloc(1, sizeof(*conn))) == NULL)
                return (NULL);
+       conn->ftp_home = NULL;
        conn->cache_url = NULL;
        conn->next_buf = NULL;
        conn->next_len = 0;
@@ -711,6 +712,7 @@
        ret = close(conn->sd);
        if (conn->cache_url)
                fetchFreeURL(conn->cache_url);
+       free(conn->ftp_home);
        free(conn->buf);
        free(conn);
        return (ret);
diff -r 546ae5e3861c -r d678a1fbf04a external/bsd/fetch/dist/libfetch/common.h
--- a/external/bsd/fetch/dist/libfetch/common.h Wed Mar 24 19:33:51 2010 +0000
+++ b/external/bsd/fetch/dist/libfetch/common.h Wed Mar 24 20:51:41 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: common.h,v 1.1.1.6 2010/01/30 21:26:09 joerg Exp $     */
+/*     $NetBSD: common.h,v 1.1.1.7 2010/03/24 20:51:42 joerg Exp $     */
 /*-
  * Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav
  * All rights reserved.
@@ -73,6 +73,8 @@
 #  endif
 #endif
 
+       char            *ftp_home;
+
        struct url      *cache_url;
        int             cache_af;
        int             (*cache_close)(conn_t *);
diff -r 546ae5e3861c -r d678a1fbf04a external/bsd/fetch/dist/libfetch/ftp.c
--- a/external/bsd/fetch/dist/libfetch/ftp.c    Wed Mar 24 19:33:51 2010 +0000
+++ b/external/bsd/fetch/dist/libfetch/ftp.c    Wed Mar 24 20:51:41 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ftp.c,v 1.1.1.10 2010/01/30 21:26:13 joerg Exp $       */
+/*     $NetBSD: ftp.c,v 1.1.1.11 2010/03/24 20:51:44 joerg Exp $       */
 /*-
  * Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav
  * Copyright (c) 2008, 2009, 2010 Joerg Sonnenberger <joerg%NetBSD.org@localhost>
@@ -252,7 +252,7 @@
  * command.
  */
 static int
-ftp_pwd(conn_t *conn, char *pwd, size_t pwdlen)
+ftp_pwd(conn_t *conn, char **pwd)
 {
        char *src, *dst, *end;
        int q;
@@ -264,7 +264,10 @@
        src = conn->buf + 4;
        if (src >= end || *src++ != '"')
                return (FTP_PROTOCOL_ERROR);
-       for (q = 0, dst = pwd; src < end && pwdlen--; ++src) {
+       *pwd = malloc(end - src + 1);
+       if (*pwd == NULL)
+               return (FTP_PROTOCOL_ERROR);
+       for (q = 0, dst = *pwd; src < end; ++src) {
                if (!q && *src == '"')
                        q = 1;
                else if (q && *src != '"')
@@ -274,9 +277,12 @@
                else
                        *dst++ = *src;
        }
-       if (!pwdlen)
+       *dst = '\0';
+       if (**pwd != '/') {
+               free(*pwd);
+               *pwd = NULL;
                return (FTP_PROTOCOL_ERROR);
-       *dst = '\0';
+       }
        return (FTP_OK);
 }
 
@@ -285,69 +291,109 @@
  * file.
  */
 static int
-ftp_cwd(conn_t *conn, const char *file, int subdir)
+ftp_cwd(conn_t *conn, const char *path, int subdir)
 {
        const char *beg, *end;
-       char pwd[PATH_MAX];
+       char *pwd, *dst;
        int e, i, len;
 
-       /* If no slashes in name, no need to change dirs. */
-       if (subdir)
-               end = file + strlen(file);
-       else if ((end = strrchr(file, '/')) == NULL)
-               return (0);
+       if (*path != '/') {
+               ftp_seterr(501);
+               return (-1);
+       }
+       ++path;
+
+       /* Simple case: still in the home directory and no directory change. */
+       if (conn->ftp_home == NULL && strchr(path, '/') == NULL &&
+           (!subdir || *path == '\0'))
+               return 0;
+
        if ((e = ftp_cmd(conn, "PWD\r\n")) != FTP_WORKING_DIRECTORY ||
-           (e = ftp_pwd(conn, pwd, sizeof(pwd))) != FTP_OK) {
+           (e = ftp_pwd(conn, &pwd)) != FTP_OK) {
                ftp_seterr(e);
                return (-1);
        }
+       if (conn->ftp_home == NULL && (conn->ftp_home = strdup(pwd)) == NULL) {
+               fetch_syserr();
+               free(pwd);
+               return (-1);
+       }
+       if (*path == '/') {
+               while (path[1] == '/')
+                       ++path;
+               dst = strdup(path);
+       } else if (strcmp(conn->ftp_home, "/") == 0) {
+               dst = strdup(path - 1);
+       } else {
+               asprintf(&dst, "%s/%s", conn->ftp_home, path);
+       }
+       if (dst == NULL) {
+               fetch_syserr();
+               free(pwd);
+               return (-1);
+       }
+
+       if (subdir)
+               end = dst + strlen(dst);
+       else
+               end = strrchr(dst, '/');
+
        for (;;) {
                len = strlen(pwd);
 
                /* 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])
+               for (i = 0; i <= len && i <= end - dst; ++i)
+                       if (pwd[i] != dst[i])
                                break;
                /* Keep going up a dir until we have a matching prefix. */
                if (strcmp(pwd, "/") == 0)
                        break;
-               if (pwd[i] == '\0' && (file[i - 1] == '/' || file[i] == '/'))
+               if (pwd[i] == '\0' && (dst[i - 1] == '/' || dst[i] == '/'))
                        break;
+               free(pwd);
                if ((e = ftp_cmd(conn, "CDUP\r\n")) != FTP_FILE_ACTION_OK ||
                    (e = ftp_cmd(conn, "PWD\r\n")) != FTP_WORKING_DIRECTORY ||
-                   (e = ftp_pwd(conn, pwd, sizeof(pwd))) != FTP_OK) {
+                   (e = ftp_pwd(conn, &pwd)) != FTP_OK) {
+                       ftp_seterr(e);
+                       free(dst);
+                       return (-1);
+               }
+       }
+       free(pwd);
+
+#ifdef FTP_COMBINE_CWDS
+       /* Skip leading slashes, even "////". */
+       for (beg = dst + i; beg < end && *beg == '/'; ++beg, ++i)
+               /* nothing */ ;
+
+       /* If there is no trailing dir, we're already there. */
+       if (beg >= end) {
+               free(dst);
+               return (0);
+       }
+
+       /* Change to the directory all in one chunk (e.g., foo/bar/baz). */
+       e = ftp_cmd(conn, "CWD %.*s\r\n", (int)(end - beg), beg);
+       if (e == FTP_FILE_ACTION_OK) {
+               free(dst);
+               return (0);
+       }
+#endif /* FTP_COMBINE_CWDS */
+
+       /* That didn't work so go back to legacy behavior (multiple CWDs). */
+       for (beg = dst + i; beg < end; beg = dst + i + 1) {
+               while (*beg == '/')
+                       ++beg, ++i;
+               for (++i; dst + i < end && dst[i] != '/'; ++i)
+                       /* nothing */ ;
+               e = ftp_cmd(conn, "CWD %.*s\r\n", dst + i - beg, beg);
+               if (e != FTP_FILE_ACTION_OK) {
+                       free(dst);
                        ftp_seterr(e);
                        return (-1);
                }
        }
-
-#ifdef FTP_COMBINE_CWDS
-       /* 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\r\n", (int)(end - beg), beg);
-       if (e == FTP_FILE_ACTION_OK)
-               return (0);
-#endif /* FTP_COMBINE_CWDS */
-
-       /* 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;
-               for (++i; file + i < end && file[i] != '/'; ++i)
-                       /* nothing */ ;
-               e = ftp_cmd(conn, "CWD %.*s\r\n", file + i - beg, beg);
-               if (e != FTP_FILE_ACTION_OK) {
-                       ftp_seterr(e);
-                       return (-1);
-               }
-       }
+       free(dst);
        return (0);
 }
 



Home | Main Index | Thread Index | Old Index