summaryrefslogtreecommitdiffstats
path: root/sftp.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2010-10-07 12:39:17 +0200
committerDamien Miller <djm@mindrot.org>2010-10-07 12:39:17 +0200
commita6e121aaa0ab61965db2dcfe8e2ba5d719fbe1e6 (patch)
tree4583d2a94482493f21537611187bd119f496807c /sftp.c
parent - matthew@cvs.openbsd.org 2010/09/24 13:33:00 (diff)
downloadopenssh-a6e121aaa0ab61965db2dcfe8e2ba5d719fbe1e6.tar.xz
openssh-a6e121aaa0ab61965db2dcfe8e2ba5d719fbe1e6.zip
- djm@cvs.openbsd.org 2010/09/25 09:30:16
[sftp.c configure.ac openbsd-compat/glob.c openbsd-compat/glob.h] make use of new glob(3) GLOB_KEEPSTAT extension to save extra server rountrips to fetch per-file stat(2) information. NB. update openbsd-compat/ glob(3) implementation from OpenBSD libc to match.
Diffstat (limited to '')
-rw-r--r--sftp.c56
1 files changed, 19 insertions, 37 deletions
diff --git a/sftp.c b/sftp.c
index f6cadd113..46bee1982 100644
--- a/sftp.c
+++ b/sftp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp.c,v 1.127 2010/09/23 13:34:43 jmc Exp $ */
+/* $OpenBSD: sftp.c,v 1.128 2010/09/25 09:30:16 djm Exp $ */
/*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
*
@@ -761,15 +761,18 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
glob_t g;
u_int i, c = 1, colspace = 0, columns = 1;
Attrib *a = NULL;
+ int err;
+ char *fname, *lname;
memset(&g, 0, sizeof(g));
- if (remote_glob(conn, path, GLOB_MARK|GLOB_NOCHECK|GLOB_BRACE,
- NULL, &g) || (g.gl_pathc && !g.gl_matchc)) {
+ if (remote_glob(conn, path,
+ GLOB_MARK|GLOB_NOCHECK|GLOB_BRACE|GLOB_KEEPSTAT, NULL, &g) ||
+ (g.gl_pathc && !g.gl_matchc)) {
if (g.gl_pathc)
globfree(&g);
error("Can't ls: \"%s\" not found", path);
- return (-1);
+ return -1;
}
if (interrupted)
@@ -779,19 +782,11 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
* If the glob returns a single match and it is a directory,
* then just list its contents.
*/
- 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 (err);
- }
+ if (g.gl_matchc == 1 && g.gl_statv[0] != NULL &&
+ S_ISDIR(g.gl_statv[0]->st_mode)) {
+ err = do_ls_dir(conn, g.gl_pathv[0], strip_path, lflag);
+ globfree(&g);
+ return err;
}
if (!(lflag & LS_SHORT_VIEW)) {
@@ -811,27 +806,14 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
}
for (i = 0; g.gl_pathv[i] && !interrupted; i++, a = NULL) {
- char *fname;
-
fname = path_strip(g.gl_pathv[i], strip_path);
-
if (lflag & LS_LONG_VIEW) {
- char *lname;
- struct stat sb;
-
- /*
- * XXX: this is slow - 1 roundtrip per path
- * A solution to this is to fork glob() and
- * build a sftp specific version which keeps the
- * attribs (which currently get thrown away)
- * that the server returns as well as the filenames.
- */
- memset(&sb, 0, sizeof(sb));
- 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, (lflag & LS_SI_UNITS));
+ if (g.gl_statv[i] == NULL) {
+ error("no stat information for %s", fname);
+ continue;
+ }
+ lname = ls_file(fname, g.gl_statv[i], 1,
+ (lflag & LS_SI_UNITS));
printf("%s\n", lname);
xfree(lname);
} else {
@@ -852,7 +834,7 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
if (g.gl_pathc)
globfree(&g);
- return (0);
+ return 0;
}
static int