diff options
-rw-r--r-- | content/fetchers/file.c | 2 | ||||
-rw-r--r-- | utils/utils.c | 35 | ||||
-rw-r--r-- | utils/utils.h | 14 |
3 files changed, 50 insertions, 1 deletions
diff --git a/content/fetchers/file.c b/content/fetchers/file.c index 4fe1c9867..c574c2160 100644 --- a/content/fetchers/file.c +++ b/content/fetchers/file.c @@ -508,7 +508,7 @@ static void fetch_file_process_dir(struct fetch_file_context *ctx, int i; /* directory entry index */ int n; /* number of directory entries */ - n = scandir(ctx->path, &listing, 0, alphasort); + n = scandir(ctx->path, &listing, 0, dir_sort_alpha); if (n < 0) { fetch_file_process_error(ctx, fetch_file_errno_to_http_code(errno)); diff --git a/utils/utils.c b/utils/utils.c index 7155ef78d..ac9f5af7a 100644 --- a/utils/utils.c +++ b/utils/utils.c @@ -340,6 +340,41 @@ char *strndup(const char *s, size_t n) #endif +/* Exported interface, documented in utils.c */ +int dir_sort_alpha(const struct dirent **d1, const struct dirent **d2) +{ + const char *s1 = (*d1)->d_name; + const char *s2 = (*d2)->d_name; + + while (*s1 != '\0' && *s2 != '\0') { + if ((*s1 >= '0' && *s1 <= '9') && + (*s2 >= '0' && *s2 <= '9')) { + int n1 = 0, n2 = 0; + while (*s1 >= '0' && *s1 <= '9') { + n1 = n1 * 10 + (*s1) - '0'; + s1++; + } + while (*s2 >= '0' && *s2 <= '9') { + n2 = n2 * 10 + (*s2) - '0'; + s2++; + } + if (n1 != n2) { + return n1 - n2; + } + if (*s1 == '\0' || *s2 == '\0') + break; + } + if (tolower(*s1) != tolower(*s2)) + break; + + s1++; + s2++; + } + + return tolower(*s1) - tolower(*s2); +} + + #ifndef HAVE_SCANDIR int alphasort(const struct dirent **d1, const struct dirent **d2) { diff --git a/utils/utils.h b/utils/utils.h index 8172d2d26..a1ff683d3 100644 --- a/utils/utils.h +++ b/utils/utils.h @@ -29,6 +29,8 @@ #include <regex.h> #include <assert.h> +struct dirent; + #ifndef NOF_ELEMENTS #define NOF_ELEMENTS(array) (sizeof(array)/sizeof(*(array))) #endif @@ -157,6 +159,18 @@ char *human_friendly_bytesize(unsigned long bytesize); const char *rfc1123_date(time_t t); unsigned int wallclock(void); + +/** + * Comparison function for sorting directories. + * + * Correctly orders non zero-padded numerical parts. + * ie. produces "file1, file2, file10" rather than "file1, file10, file2". + * + * d1 first directory entry + * d2 second directory entry + */ +int dir_sort_alpha(const struct dirent **d1, const struct dirent **d2); + /** * Return a hex digit for the given numerical value. * |