upstream commit
implement sorting for globbed ls; bz#2649 ok dtucker@ Upstream-ID: ed3110f351cc9703411bf847ba864041fb7216a8
This commit is contained in:
parent
5b2f34a74a
commit
72be5b2f8e
50
sftp.c
50
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@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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue