- fgsch@cvs.openbsd.org 2004/12/10 03:10:42
     [sftp.c]
     - fix globbed ls for paths the same lenght as the globbed path when
       we have a unique matching.
     - fix globbed ls in case of a directory when we have a unique matching.
     - as a side effect, if the path does not exist error (used to silently
       ignore).
     - don't do extra do_lstat() if we only have one matching file.
     djm@ ok
diff --git a/sftp.c b/sftp.c
index 2c7b546..9e29cb0 100644
--- a/sftp.c
+++ b/sftp.c
@@ -16,7 +16,7 @@
 
 #include "includes.h"
 
-RCSID("$OpenBSD: sftp.c,v 1.59 2004/11/29 07:41:24 djm Exp $");
+RCSID("$OpenBSD: sftp.c,v 1.60 2004/12/10 03:10:42 fgsch Exp $");
 
 #ifdef USE_LIBEDIT
 #include <histedit.h>
@@ -746,12 +746,14 @@
 {
 	glob_t g;
 	int i, c = 1, colspace = 0, columns = 1;
-	Attrib *a;
+	Attrib *a = NULL;
 
 	memset(&g, 0, sizeof(g));
 
 	if (remote_glob(conn, path, GLOB_MARK|GLOB_NOCHECK|GLOB_BRACE,
-	    NULL, &g)) {
+	    NULL, &g) || (g.gl_pathc && !g.gl_matchc)) {
+		if (g.gl_pathc)
+			globfree(&g);
 		error("Can't ls: \"%s\" not found", path);
 		return (-1);
 	}
@@ -760,19 +762,21 @@
 		goto out;
 
 	/*
-	 * If the glob returns a single match, which is the same as the
-	 * input glob, and it is a directory, then just list its contents
+	 * If the glob returns a single match and it is a directory,
+	 * then just list its contents.
 	 */
-	if (g.gl_pathc == 1 &&
-	    strncmp(path, g.gl_pathv[0], strlen(g.gl_pathv[0]) - 1) == 0) {
-		if ((a = do_lstat(conn, path, 1)) == NULL) {
+	if (g.gl_matchc == 1) {
+		if ((a = do_lstat(conn, g.gl_pathv[0], 1)) == NULL) {
 			globfree(&g);
 			return (-1);
 		}
 		if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
 		    S_ISDIR(a->perm)) {
+			int err;
+
+			err = do_ls_dir(conn, g.gl_pathv[0], strip_path, lflag);
 			globfree(&g);
-			return (do_ls_dir(conn, path, strip_path, lflag));
+			return (err);
 		}
 	}
 
@@ -792,7 +796,7 @@
 		colspace = width / columns;
 	}
 
-	for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
+	for (i = 0; g.gl_pathv[i] && !interrupted; i++, a = NULL) {
 		char *fname;
 
 		fname = path_strip(g.gl_pathv[i], strip_path);
@@ -809,7 +813,8 @@
 			 * that the server returns as well as the filenames.
 			 */
 			memset(&sb, 0, sizeof(sb));
-			a = do_lstat(conn, g.gl_pathv[i], 1);
+			if (a == NULL)
+				a = do_lstat(conn, g.gl_pathv[i], 1);
 			if (a != NULL)
 				attrib_to_stat(a, &sb);
 			lname = ls_file(fname, &sb, 1);