|
Lines 86-91
volatile sig_atomic_t interrupted = 0;
Link Here
|
| 86 |
|
86 |
|
| 87 |
/* I wish qsort() took a separate ctx for the comparison function...*/ |
87 |
/* I wish qsort() took a separate ctx for the comparison function...*/ |
| 88 |
int sort_flag; |
88 |
int sort_flag; |
|
|
89 |
glob_t *sort_glob; |
| 89 |
|
90 |
|
| 90 |
/* Context used for commandline completion */ |
91 |
/* Context used for commandline completion */ |
| 91 |
struct complete_ctx { |
92 |
struct complete_ctx { |
|
Lines 857-862
do_ls_dir(struct sftp_conn *conn, const char *path,
Link Here
|
| 857 |
return (0); |
858 |
return (0); |
| 858 |
} |
859 |
} |
| 859 |
|
860 |
|
|
|
861 |
static int |
| 862 |
sglob_comp(const void *aa, const void *bb) |
| 863 |
{ |
| 864 |
u_int a = *(const u_int *)aa; |
| 865 |
u_int b = *(const u_int *)bb; |
| 866 |
const char *ap = sort_glob->gl_pathv[a]; |
| 867 |
const char *bp = sort_glob->gl_pathv[b]; |
| 868 |
const struct stat *as = sort_glob->gl_statv[a]; |
| 869 |
const struct stat *bs = sort_glob->gl_statv[b]; |
| 870 |
int rmul = sort_flag & LS_REVERSE_SORT ? -1 : 1; |
| 871 |
|
| 872 |
#define NCMP(a,b) (a == b ? 0 : (a < b ? 1 : -1)) |
| 873 |
if (sort_flag & LS_NAME_SORT) |
| 874 |
return (rmul * strcmp(ap, bp)); |
| 875 |
else if (sort_flag & LS_TIME_SORT) |
| 876 |
return (rmul * timespeccmp(&as->st_mtim, &bs->st_mtim, <)); |
| 877 |
else if (sort_flag & LS_SIZE_SORT) |
| 878 |
return (rmul * NCMP(as->st_size, bs->st_size)); |
| 879 |
|
| 880 |
fatal("Unknown ls sort type"); |
| 881 |
} |
| 882 |
|
| 860 |
/* sftp ls.1 replacement which handles path globs */ |
883 |
/* sftp ls.1 replacement which handles path globs */ |
| 861 |
static int |
884 |
static int |
| 862 |
do_globbed_ls(struct sftp_conn *conn, const char *path, |
885 |
do_globbed_ls(struct sftp_conn *conn, const char *path, |
|
Lines 866-872
do_globbed_ls(struct sftp_conn *conn, const char *path,
Link Here
|
| 866 |
glob_t g; |
889 |
glob_t g; |
| 867 |
int err, r; |
890 |
int err, r; |
| 868 |
struct winsize ws; |
891 |
struct winsize ws; |
| 869 |
u_int i, c = 1, colspace = 0, columns = 1, m = 0, width = 80; |
892 |
u_int i, j, nentries, *indices = NULL, c = 1; |
|
|
893 |
u_int colspace = 0, columns = 1, m = 0, width = 80; |
| 870 |
|
894 |
|
| 871 |
memset(&g, 0, sizeof(g)); |
895 |
memset(&g, 0, sizeof(g)); |
| 872 |
|
896 |
|
|
Lines 911-917
do_globbed_ls(struct sftp_conn *conn, const char *path,
Link Here
|
| 911 |
colspace = width / columns; |
935 |
colspace = width / columns; |
| 912 |
} |
936 |
} |
| 913 |
|
937 |
|
| 914 |
for (i = 0; g.gl_pathv[i] && !interrupted; i++) { |
938 |
/* |
|
|
939 |
* Sorting: rather than mess with the contents of glob_t, prepare |
| 940 |
* an array of indices into it and sort that. For the usual |
| 941 |
* unsorted case, the indices are just the identity 1=1, 2=2, etc. |
| 942 |
*/ |
| 943 |
for (nentries = 0; g.gl_pathv[nentries] != NULL; nentries++) |
| 944 |
; /* count entries */ |
| 945 |
indices = calloc(nentries, sizeof(*indices)); |
| 946 |
for (i = 0; i < nentries; i++) |
| 947 |
indices[i] = i; |
| 948 |
|
| 949 |
if (lflag & SORT_FLAGS) { |
| 950 |
sort_glob = &g; |
| 951 |
sort_flag = lflag & (SORT_FLAGS|LS_REVERSE_SORT); |
| 952 |
qsort(indices, nentries, sizeof(*indices), sglob_comp); |
| 953 |
sort_glob = NULL; |
| 954 |
} |
| 955 |
|
| 956 |
for (j = 0; j < nentries && !interrupted; j++) { |
| 957 |
i = indices[j]; |
| 915 |
fname = path_strip(g.gl_pathv[i], strip_path); |
958 |
fname = path_strip(g.gl_pathv[i], strip_path); |
| 916 |
if (lflag & LS_LONG_VIEW) { |
959 |
if (lflag & LS_LONG_VIEW) { |
| 917 |
if (g.gl_statv[i] == NULL) { |
960 |
if (g.gl_statv[i] == NULL) { |
|
Lines 939-944
do_globbed_ls(struct sftp_conn *conn, const char *path,
Link Here
|
| 939 |
out: |
982 |
out: |
| 940 |
if (g.gl_pathc) |
983 |
if (g.gl_pathc) |
| 941 |
globfree(&g); |
984 |
globfree(&g); |
|
|
985 |
free(indices); |
| 942 |
|
986 |
|
| 943 |
return 0; |
987 |
return 0; |
| 944 |
} |
988 |
} |