ASF Bugzilla – Attachment 27195 Details for
Bug 51409
Sorting options accepted by ls, but ignored
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
An improved patch
patch-ls-sort (text/plain), 8.50 KB, created by
Mikhail T.
on 2011-06-22 16:49:08 UTC
(
hide
)
Description:
An improved patch
Filename:
MIME Type:
Creator:
Mikhail T.
Created:
2011-06-22 16:49:08 UTC
Size:
8.50 KB
patch
obsolete
>--- modules/ftp/ftp_commands.c 2009-09-21 15:09:19.000000000 -0400 >+++ modules/ftp/ftp_commands.c 2011-06-22 03:00:31.000000000 -0400 >@@ -24,6 +24,8 @@ > #include "mod_ftp.h" > #include "ftp_internal.h" >-#include "apr_version.h" >-#include "apr_network_io.h" >+#include <apr_version.h> >+#include <apr_getopt.h> >+#include <apr_network_io.h> >+#include <apr_strings.h> > #include "http_vhost.h" > >@@ -665,22 +667,66 @@ static int common_list(request_rec *r, c > apr_status_t rv; > apr_size_t nbytes; >- char *varg = apr_pstrdup(r->pool, arg); > const char *test, *sl; > int res; > int decend = 0; >+ apr_getopt_t *options; >+ char **argv, option; >+ const char *optval; >+ char * const *p; >+ int argc; >+ /* Sort by name ascending by default */ >+ int reverse = 0; >+ enum ftp_sort sortby = SORT_BY_NAME; /* Why not SORT_NONE? */ >+ >+ /* TODO: improve error reporting with detailed status explanation */ >+ if ((res = apr_tokenize_to_argv(arg, &argv, r->pool))) { >+ ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r, >+ "Attempt to tokenize string `%s' failed", arg); >+ return res; >+ } >+ for (p = argv, argc = 0; *p; p++) >+ argc++; > >- while (*varg == '-') >- { >- if (ftp_parse2(r->pool, varg, &word, &varg, FTP_KEEP_WHITESPACE)) { >- varg = word; >- break; >- } >- /* More Cowbell! TODO: expand the accepted dash patterns */ >- if (ap_strchr(word, 'l')) { >+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Split `%s' into %d word%s", >+ arg, argc, argc == 1 ? "" : "s"); >+ >+ /* >+ * apr_getopt ignores argv[0] thinking, it is the program's name, >+ * but we want it to start with it, so we shift argv and argc by one: >+ */ >+ if ((res = apr_getopt_init(&options, r->pool, argc + 1, (const char **)argv - 1))) { >+ ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r, >+ "apr_getopt_init failed"); >+ return res; >+ } >+ >+ /* Disable apr_getopt's own error-reporting: */ >+ options->errfn = NULL; >+ >+ while (apr_getopt(options, "Slrtcu", &option, &optval) != APR_EOF) { >+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Checking option `%c'", option); >+ switch(option) { >+ case 'l': > dashl = 1; >- } >- /* -- 'end of dash-opts' by convention allows patterns like '-*' */ >- if (ap_strchr(word + 1, '-')) { >- break; >+ continue; >+ case 'r': >+ reverse = 1; >+ continue; >+ case 't': >+ sortby = SORT_BY_MTIME; >+ continue; >+ case 'c': >+ sortby = SORT_BY_CTIME; >+ continue; >+ case 'u': >+ sortby = SORT_BY_ATIME; >+ continue; >+ case 'S': >+ sortby = SORT_BY_SIZE; >+ continue; >+ default: >+ /* TODO: communicate this back to the client too */ >+ ap_log_rerror(APLOG_MARK, APLOG_WARNING | APLOG_NOERRNO, 0, r, >+ "Ignoring unrecognized listing option `%c'", option); > } > } >@@ -696,5 +748,9 @@ static int common_list(request_rec *r, c > } > >- arg = varg; >+ arg = argv[options->ind - 1] ? argv[options->ind - 1] : ""; >+ >+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "%s-listing `%s', " >+ "sorting by %d (%sscending)", is_list ? "Long" : "Short", >+ arg ? arg : "nill!", (int)sortby, reverse ? "de" : "a"); > > if (is_list && (ap_strchr_c(arg, '*') != NULL)) >@@ -768,5 +824,5 @@ static int common_list(request_rec *r, c > > /* Construct the sorted array of directory contents */ >- if ((direntry = ftp_direntry_get(r, pattern)) == NULL) { >+ if ((direntry = ftp_direntry_get(r, pattern, sortby, reverse)) == NULL) { > fc->response_notes = apr_psprintf(r->pool, FTP_MSG_NOSUCHFILE, > ftp_escape_control_text(arg, r->pool)); >--- modules/ftp/ftp_internal.h 2009-09-17 14:06:43.000000000 -0400 >+++ modules/ftp/ftp_internal.h 2011-06-22 02:59:53.000000000 -0400 >@@ -160,4 +160,13 @@ typedef enum { > } ftp_loginlimit_t; > >+enum ftp_sort { >+ SORT_BY_NAME, >+ SORT_BY_MTIME, >+ SORT_BY_ATIME, >+ SORT_BY_CTIME, >+ SORT_BY_SIZE, >+ SORT_NONE >+}; >+ > /* Directory entry structure. Used for directory listings */ > typedef struct ftp_direntry >@@ -170,4 +179,5 @@ typedef struct ftp_direntry > apr_off_t size; > apr_off_t csize; >+ apr_time_t atime, mtime, ctime; > apr_int32_t nlink; > struct ftp_direntry *child; /* For descending */ >@@ -254,5 +264,6 @@ int ftp_limitlogin_loggedout(conn_rec *c > int ftp_eprt_decode(apr_int32_t *family, char **addr, apr_port_t *port, > char *arg); >-struct ftp_direntry *ftp_direntry_get(request_rec *r, const char *pattern); >+struct ftp_direntry *ftp_direntry_get(request_rec *r, const char *pattern, >+ enum ftp_sort sortby, int reverse); > > void ftp_set_authorization(request_rec *r); >--- modules/ftp/ftp_util.c 2009-09-17 17:36:36.000000000 -0400 >+++ modules/ftp/ftp_util.c 2011-06-22 03:05:05.000000000 -0400 >@@ -210,4 +210,7 @@ static struct ftp_direntry *ftp_direntry > dirent->size = rr->finfo.size; > dirent->csize = rr->finfo.csize; >+ dirent->ctime = rr->finfo.ctime; >+ dirent->atime = rr->finfo.atime; >+ dirent->mtime = rr->finfo.mtime; > dirent->modestring = apr_pstrdup(r->pool, > ftp_modestring_get( >@@ -267,6 +270,6 @@ static struct ftp_direntry *ftp_direntry > * be greater than d2. > */ >-static int ftp_dsortf(struct ftp_direntry ** d1, >- struct ftp_direntry ** d2) >+static int ftp_dsortf(const struct ftp_direntry ** d1, >+ const struct ftp_direntry ** d2) > { > /* Simple sort based on filename */ >@@ -274,4 +277,32 @@ static int ftp_dsortf(struct ftp_direntr > } > >+static int ftp_dsortf_desc(const struct ftp_direntry ** d1, >+ const struct ftp_direntry ** d2) >+{ >+ /* Simple sort based on filename, descending */ >+ return strcmp((*d2)->name, (*d1)->name); >+} >+ >+#define FTP_DSORT_NUM(field) \ >+static int ftp_dsort_##field(const struct ftp_direntry ** d1, \ >+ const struct ftp_direntry ** d2) \ >+{ \ >+ if ((*d1)->field == (*d2)->field) \ >+ return 0; \ >+ return (*d1)->field < (*d2)->field ? 1 : -1; \ >+} \ >+static int ftp_dsort_desc_##field(const struct ftp_direntry ** d1, \ >+ const struct ftp_direntry ** d2) \ >+{ \ >+ if ((*d1)->field == (*d2)->field) \ >+ return 0; \ >+ return (*d1)->field > (*d2)->field ? 1 : -1; \ >+} >+ >+FTP_DSORT_NUM(mtime) >+FTP_DSORT_NUM(ctime) >+FTP_DSORT_NUM(atime) >+FTP_DSORT_NUM(size) >+ > /* ftp_direntry_get: Return an array of ftp_direntry structures based > * on the uri stored in the request rec. An extra >@@ -283,5 +310,6 @@ static int ftp_dsortf(struct ftp_direntr > * Returns: The sorted array of directory entries on success, NULL otherwise > */ >-struct ftp_direntry *ftp_direntry_get(request_rec *r, const char *pattern) >+struct ftp_direntry *ftp_direntry_get(request_rec *r, const char *pattern, >+ enum ftp_sort sortby, int reverse) > { > struct ftp_direntry *p, *head, *current, **a; >@@ -293,4 +321,14 @@ struct ftp_direntry *ftp_direntry_get(re > const char *path, *search; > >+ int (*compar[])(const struct ftp_direntry **, >+ const struct ftp_direntry **) = { >+ /* The order here must match the enum ftp_sort! */ >+ ftp_dsortf, ftp_dsortf_desc, >+ ftp_dsort_mtime, ftp_dsort_desc_mtime, >+ ftp_dsort_atime, ftp_dsort_desc_atime, >+ ftp_dsort_ctime, ftp_dsort_desc_ctime, >+ ftp_dsort_size, ftp_dsort_desc_size >+ }; >+ > /* > * The actual search pattern, used to determine if we should recurse into >@@ -374,5 +412,5 @@ struct ftp_direntry *ftp_direntry_get(re > const char *newpattern = apr_pstrcat(r->pool, fname, > "/*", NULL); >- p->child = ftp_direntry_get(r, newpattern); >+ p->child = ftp_direntry_get(r, newpattern, sortby, reverse); > } > else { >@@ -396,6 +434,9 @@ struct ftp_direntry *ftp_direntry_get(re > } > num = i; >- qsort((void *) a, num, sizeof(struct ftp_direntry *), >- (int (*) (const void *, const void *)) ftp_dsortf); >+ if (sortby != SORT_NONE) { >+ qsort((void *) a, num, sizeof(struct ftp_direntry *), >+ (int (*)(const void *, >+ const void *))compar[sortby * 2 + reverse]); >+ } > > /* Re-construct the list from the sorted list */
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 51409
:
27192
| 27195