pkgsrc-Bugs archive

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

Re: pkg/43013: Clarification of URL handling for pkg_add/pkgin



The following reply was made to PR pkg/43013; it has been noted by GNATS.

From: Joerg Sonnenberger <joerg%britannica.bec.de@localhost>
To: gnats-bugs%NetBSD.org@localhost
Cc: brook%nmsu.edu@localhost
Subject: Re: pkg/43013: Clarification of URL handling for pkg_add/pkgin
Date: Fri, 19 Mar 2010 19:08:07 +0100

 --bp/iNruPH9dso1Pn
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 
 Attached is a patch to correctly implement the desired RFC1738 behavior
 for FTP.
 
 Joerg
 
 --bp/iNruPH9dso1Pn
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: attachment; filename="ftp-urls.diff"
 
 Index: common.c
 ===================================================================
 RCS file: 
/home/joerg/repo/netbsd/src/external/bsd/fetch/dist/libfetch/common.c,v
 retrieving revision 1.1.1.8
 diff -u -p -r1.1.1.8 common.c
 --- common.c   30 Jan 2010 21:26:09 -0000      1.1.1.8
 +++ common.c   19 Mar 2010 14:25:55 -0000
 @@ -231,6 +231,7 @@ fetch_reopen(int sd)
        /* 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 @@ fetch_close(conn_t *conn)
        ret = close(conn->sd);
        if (conn->cache_url)
                fetchFreeURL(conn->cache_url);
 +      free(conn->ftp_home);
        free(conn->buf);
        free(conn);
        return (ret);
 Index: common.h
 ===================================================================
 RCS file: 
/home/joerg/repo/netbsd/src/external/bsd/fetch/dist/libfetch/common.h,v
 retrieving revision 1.1.1.6
 diff -u -p -r1.1.1.6 common.h
 --- common.h   30 Jan 2010 21:26:09 -0000      1.1.1.6
 +++ common.h   19 Mar 2010 14:24:51 -0000
 @@ -73,6 +73,8 @@ struct fetchconn {
  #  endif
  #endif
  
 +      char            *ftp_home;
 +
        struct url      *cache_url;
        int             cache_af;
        int             (*cache_close)(conn_t *);
 Index: ftp.c
 ===================================================================
 RCS file: /home/joerg/repo/netbsd/src/external/bsd/fetch/dist/libfetch/ftp.c,v
 retrieving revision 1.1.1.10
 diff -u -p -r1.1.1.10 ftp.c
 --- ftp.c      30 Jan 2010 21:26:13 -0000      1.1.1.10
 +++ ftp.c      19 Mar 2010 15:56:05 -0000
 @@ -252,7 +252,7 @@ ftp_filename(const char *file, int *len,
   * 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 @@ ftp_pwd(conn_t *conn, char *pwd, size_t 
        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 @@ ftp_pwd(conn_t *conn, char *pwd, size_t 
                else
                        *dst++ = *src;
        }
 -      if (!pwdlen)
 -              return (FTP_PROTOCOL_ERROR);
        *dst = '\0';
 +      if (**pwd != '/') {
 +              free(*pwd);
 +              *pwd = NULL;
 +              return (FTP_PROTOCOL_ERROR);
 +      }
        return (FTP_OK);
  }
  
 @@ -285,69 +291,108 @@ ftp_pwd(conn_t *conn, char *pwd, size_t 
   * 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)
 +              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 = file + i; beg < end && *beg == '/'; ++beg, ++i)
 +      for (beg = dst + i; beg < end && *beg == '/'; ++beg, ++i)
                /* nothing */ ;
  
        /* If there is no trailing dir, we're already there. */
 -      if (beg >= end)
 +      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)
 +      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 = file + i; beg < end; beg = file + i + 1) {
 +      for (beg = dst + i; beg < end; beg = dst + i + 1) {
                while (*beg == '/')
                        ++beg, ++i;
 -              for (++i; file + i < end && file[i] != '/'; ++i)
 +              for (++i; dst + i < end && dst[i] != '/'; ++i)
                        /* nothing */ ;
 -              e = ftp_cmd(conn, "CWD %.*s\r\n", file + i - beg, beg);
 +              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);
                }
        }
 +      free(dst);
        return (0);
  }
  
 
 --bp/iNruPH9dso1Pn--
 


Home | Main Index | Thread Index | Old Index