From c31ae564014c08378563171f22421de08ba83bc2 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Tue, 26 Aug 2014 18:42:51 +0200 Subject: [PATCH] Add a flag to use numeric sort Add an option --numeric-sort (-N) to compare filepaths according to string numerical value. Without this option, the files are transferred in that order: file1 file10 file11 file100 file101 file19 file2 file20 With the option enabled: file1 file2 file10 file11 file19 file20 file100 file101 --- flist.c | 38 +++++++++++++++++++++++++++++++++++++- options.c | 2 ++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/flist.c b/flist.c index c24672e..b5b17d6 100644 --- a/flist.c +++ b/flist.c @@ -38,6 +38,7 @@ extern int ignore_errors; extern int numeric_ids; extern int recurse; extern int use_qsort; +extern int numeric_sort; extern int xfer_dirs; extern int filesfrom_fd; extern int one_file_system; @@ -3011,6 +3012,11 @@ enum fnc_type { t_PATH, t_ITEM }; static int found_prefix; +static inline must_numcompare(const char c1, const char c2) +{ + return numeric_sort && isdigit(c1) && isdigit(c2); +} + /* Compare the names of two file_struct entities, similar to how strcmp() * would do if it were operating on the joined strings. * @@ -3030,6 +3036,7 @@ int f_name_cmp(const struct file_struct *f1, const struct file_struct *f2) { int dif; const uchar *c1, *c2; + int dcmp; /* digits compare result */ enum fnc_state state1, state2; enum fnc_type type1, type2; enum fnc_type t_path = protocol_version >= 29 ? t_PATH : t_ITEM; @@ -3140,7 +3147,36 @@ int f_name_cmp(const struct file_struct *f1, const struct file_struct *f2) if (type1 != type2) return type1 == t_PATH ? 1 : -1; } - } while ((dif = (int)*c1++ - (int)*c2++) == 0); + if (must_numcompare(*c1, *c2)) { + dcmp = 0; + do { + if (!dcmp) { + if (*c1 < *c2) + dcmp = -1; + else if (*c1 > *c2) + dcmp = 1; + } + c1++; + c2++; + } while (isdigit(*c1) && isdigit(*c2)); + + if (isdigit(*c1)) + /* more digits in f1 */ + return 1; + + if (isdigit(*c2)) + /* more digits in f2 */ + return -1; + + if (dcmp) + /* same number of digits, but different numbers */ + return dcmp; + + } else { + c1++; + c2++; + } + } while (must_numcompare(*c1, *c2) || (dif = (int)*c1 - (int)*c2) == 0); return dif; } diff --git a/options.c b/options.c index 62dfe4f..86681ab 100644 --- a/options.c +++ b/options.c @@ -92,6 +92,7 @@ int force_delete = 0; int io_timeout = 0; int prune_empty_dirs = 0; int use_qsort = 0; +int numeric_sort = 0; char *files_from = NULL; int filesfrom_fd = -1; char *filesfrom_host = NULL; @@ -1029,6 +1030,7 @@ static struct poptOption long_options[] = { {"no-8-bit-output", 0, POPT_ARG_VAL, &allow_8bit_chars, 0, 0, 0 }, {"no-8", 0, POPT_ARG_VAL, &allow_8bit_chars, 0, 0, 0 }, {"qsort", 0, POPT_ARG_NONE, &use_qsort, 0, 0, 0 }, + {"numeric-sort", 'N', POPT_ARG_NONE, &numeric_sort, 0, 0, 0 }, {"address", 0, POPT_ARG_STRING, &bind_address, 0, 0, 0 }, {"port", 0, POPT_ARG_INT, &rsync_port, 0, 0, 0 }, {"sockopts", 0, POPT_ARG_STRING, &sockopts, 0, 0, 0 }, -- 1.9.1