Module Name:    src
Committed By:   riz
Date:           Sun Jun 13 05:59:11 UTC 2010

Modified Files:
        src/external/bsd/fetch/dist/libfetch [netbsd-4]: common.c common.h
            ftp.c
Removed Files:
        src/external/bsd/fetch/dist/libfetch [netbsd-4]: fetch.cat3

Log Message:
Pull up following revision(s) (requested by joerg in ticket #1390):

external/bsd/fetch/dist/libfetch/common.c: patch
external/bsd/fetch/dist/libfetch/common.h: patch
external/bsd/fetch/dist/libfetch/fetch.cat3: removed
external/bsd/fetch/dist/libfetch/ftp.c: patch

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.


To generate a diff of this commit:
cvs rdiff -u -r1.1.1.5.4.3 -r1.1.1.5.4.4 \
    src/external/bsd/fetch/dist/libfetch/common.c
cvs rdiff -u -r1.1.1.4.4.3 -r1.1.1.4.4.4 \
    src/external/bsd/fetch/dist/libfetch/common.h
cvs rdiff -u -r1.1.1.3.4.3 -r0 \
    src/external/bsd/fetch/dist/libfetch/fetch.cat3
cvs rdiff -u -r1.1.1.6.4.3 -r1.1.1.6.4.4 \
    src/external/bsd/fetch/dist/libfetch/ftp.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/external/bsd/fetch/dist/libfetch/common.c
diff -u src/external/bsd/fetch/dist/libfetch/common.c:1.1.1.5.4.3 src/external/bsd/fetch/dist/libfetch/common.c:1.1.1.5.4.4
--- src/external/bsd/fetch/dist/libfetch/common.c:1.1.1.5.4.3	Sat Jun 12 17:58:12 2010
+++ src/external/bsd/fetch/dist/libfetch/common.c	Sun Jun 13 05:59:10 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: common.c,v 1.1.1.5.4.3 2010/06/12 17:58:12 riz Exp $	*/
+/*	$NetBSD: common.c,v 1.1.1.5.4.4 2010/06/13 05:59:10 riz Exp $	*/
 /*-
  * Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav
  * Copyright (c) 2008, 2010 Joerg Sonnenberger <jo...@netbsd.org>
@@ -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);

Index: src/external/bsd/fetch/dist/libfetch/common.h
diff -u src/external/bsd/fetch/dist/libfetch/common.h:1.1.1.4.4.3 src/external/bsd/fetch/dist/libfetch/common.h:1.1.1.4.4.4
--- src/external/bsd/fetch/dist/libfetch/common.h:1.1.1.4.4.3	Sat Jun 12 17:58:12 2010
+++ src/external/bsd/fetch/dist/libfetch/common.h	Sun Jun 13 05:59:10 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: common.h,v 1.1.1.4.4.3 2010/06/12 17:58:12 riz Exp $	*/
+/*	$NetBSD: common.h,v 1.1.1.4.4.4 2010/06/13 05:59:10 riz 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 *);

Index: src/external/bsd/fetch/dist/libfetch/ftp.c
diff -u src/external/bsd/fetch/dist/libfetch/ftp.c:1.1.1.6.4.3 src/external/bsd/fetch/dist/libfetch/ftp.c:1.1.1.6.4.4
--- src/external/bsd/fetch/dist/libfetch/ftp.c:1.1.1.6.4.3	Sat Jun 12 17:58:13 2010
+++ src/external/bsd/fetch/dist/libfetch/ftp.c	Sun Jun 13 05:59:11 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: ftp.c,v 1.1.1.6.4.3 2010/06/12 17:58:13 riz Exp $	*/
+/*	$NetBSD: ftp.c,v 1.1.1.6.4.4 2010/06/13 05:59:11 riz Exp $	*/
 /*-
  * Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav
  * Copyright (c) 2008, 2009, 2010 Joerg Sonnenberger <jo...@netbsd.org>
@@ -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)
-		return (FTP_PROTOCOL_ERROR);
 	*dst = '\0';
+	if (**pwd != '/') {
+		free(*pwd);
+		*pwd = NULL;
+		return (FTP_PROTOCOL_ERROR);
+	}
 	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 = 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);
 }
 

Reply via email to