[openssh-commits] [openssh] 05/06: upstream commit

git+noreply at mindrot.org git+noreply at mindrot.org
Sat Jun 10 16:40:47 AEST 2017


This is an automated email from the git hooks/post-receive script.

djm pushed a commit to branch master
in repository openssh.

commit 72be5b2f8e7dc37235e8c4b8d0bc7b5ee1301505
Author: djm at openbsd.org <djm at openbsd.org>
Date:   Sat Jun 10 06:33:34 2017 +0000

    upstream commit
    
    implement sorting for globbed ls; bz#2649 ok dtucker@
    
    Upstream-ID: ed3110f351cc9703411bf847ba864041fb7216a8
---
 sftp.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 47 insertions(+), 3 deletions(-)

diff --git a/sftp.c b/sftp.c
index 9737bf50..001c6ed2 100644
--- a/sftp.c
+++ b/sftp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp.c,v 1.179 2017/05/02 08:54:19 djm Exp $ */
+/* $OpenBSD: sftp.c,v 1.180 2017/06/10 06:33:34 djm Exp $ */
 /*
  * Copyright (c) 2001-2004 Damien Miller <djm at openbsd.org>
  *
@@ -106,6 +106,7 @@ volatile sig_atomic_t interrupted = 0;
 
 /* I wish qsort() took a separate ctx for the comparison function...*/
 int sort_flag;
+glob_t *sort_glob;
 
 /* Context used for commandline completion */
 struct complete_ctx {
@@ -879,6 +880,28 @@ do_ls_dir(struct sftp_conn *conn, const char *path,
 	return (0);
 }
 
+static int
+sglob_comp(const void *aa, const void *bb)
+{
+	u_int a = *(const u_int *)aa;
+	u_int b = *(const u_int *)bb;
+	const char *ap = sort_glob->gl_pathv[a];
+	const char *bp = sort_glob->gl_pathv[b];
+	const struct stat *as = sort_glob->gl_statv[a];
+	const struct stat *bs = sort_glob->gl_statv[b];
+	int rmul = sort_flag & LS_REVERSE_SORT ? -1 : 1;
+
+#define NCMP(a,b) (a == b ? 0 : (a < b ? 1 : -1))
+	if (sort_flag & LS_NAME_SORT)
+		return (rmul * strcmp(ap, bp));
+	else if (sort_flag & LS_TIME_SORT)
+		return (rmul * timespeccmp(&as->st_mtim, &bs->st_mtim, <));
+	else if (sort_flag & LS_SIZE_SORT)
+		return (rmul * NCMP(as->st_size, bs->st_size));
+
+	fatal("Unknown ls sort type");
+}
+
 /* sftp ls.1 replacement which handles path globs */
 static int
 do_globbed_ls(struct sftp_conn *conn, const char *path,
@@ -888,7 +911,8 @@ do_globbed_ls(struct sftp_conn *conn, const char *path,
 	glob_t g;
 	int err, r;
 	struct winsize ws;
-	u_int i, c = 1, colspace = 0, columns = 1, m = 0, width = 80;
+	u_int i, j, nentries, *indices = NULL, c = 1;
+	u_int colspace = 0, columns = 1, m = 0, width = 80;
 
 	memset(&g, 0, sizeof(g));
 
@@ -933,7 +957,26 @@ do_globbed_ls(struct sftp_conn *conn, const char *path,
 		colspace = width / columns;
 	}
 
-	for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
+	/*
+	 * Sorting: rather than mess with the contents of glob_t, prepare
+	 * an array of indices into it and sort that. For the usual
+	 * unsorted case, the indices are just the identity 1=1, 2=2, etc.
+	 */
+	for (nentries = 0; g.gl_pathv[nentries] != NULL; nentries++)
+		;	/* count entries */
+	indices = calloc(nentries, sizeof(*indices));
+	for (i = 0; i < nentries; i++)
+		indices[i] = i;
+
+	if (lflag & SORT_FLAGS) {
+		sort_glob = &g;
+		sort_flag = lflag & (SORT_FLAGS|LS_REVERSE_SORT);
+		qsort(indices, nentries, sizeof(*indices), sglob_comp);
+		sort_glob = NULL;
+	}
+
+	for (j = 0; j < nentries && !interrupted; j++) {
+		i = indices[j];
 		fname = path_strip(g.gl_pathv[i], strip_path);
 		if (lflag & LS_LONG_VIEW) {
 			if (g.gl_statv[i] == NULL) {
@@ -961,6 +1004,7 @@ do_globbed_ls(struct sftp_conn *conn, const char *path,
  out:
 	if (g.gl_pathc)
 		globfree(&g);
+	free(indices);
 
 	return 0;
 }

-- 
To stop receiving notification emails like this one, please contact
djm at mindrot.org.


More information about the openssh-commits mailing list