| 1 | From: David Bolen <db3l@fitlinxx.com> |
| 2 | To: Peter Tattam <peter@jazz-1.trumpet.com.au> |
| 3 | Cc: rsync@lists.samba.org |
| 4 | Subject: RE: mixed case file systems. |
| 5 | Date: Thu, 18 Apr 2002 23:04:06 -0400 |
| 6 | |
| 7 | Peter Tattam [peter@jazz-1.trumpet.com.au] writes: |
| 8 | |
| 9 | > I believe a suitable workaround would be to ignore case for file names |
| 10 | > when the rsync process is undertaken. Is this facility available or |
| 11 | > planned in the near future? |
| 12 | |
| 13 | I've attached a context diff for some changes I made to our local copy |
| 14 | a while back to add an "--ignore-case" option just for this purpose. |
| 15 | In our case it came up in the context of disting between NTFS and FAT |
| 16 | remote systems. I think we ended up not needing it, but it does make |
| 17 | rsync match filenames in a case insensitive manner, so it might at |
| 18 | least be worth trying to see if it resolves your issue. |
| 19 | |
| 20 | A few caveats - both ends have to support the option - I couldn't make |
| 21 | it backwards compatible because both ends exchange information about a |
| 22 | sorted file list that has to sort the same way on either side (which |
| 23 | very subtly bit me when I first did this). I also didn't bump the |
| 24 | protocol in this patch (wasn't quite sure it was appropriate just for an |
| 25 | incompatible command line option) since it was for local use. |
| 26 | |
| 27 | NOTE: patch updated for latest CVS source by Wayne Davison, but UNTESTED! |
| 28 | |
| 29 | -- David |
| 30 | |
| 31 | /-----------------------------------------------------------------------\ |
| 32 | \ David Bolen \ E-mail: db3l@fitlinxx.com / |
| 33 | | FitLinxx, Inc. \ Phone: (203) 708-5192 | |
| 34 | / 860 Canal Street, Stamford, CT 06902 \ Fax: (203) 316-5150 \ |
| 35 | \-----------------------------------------------------------------------/ |
| 36 | |
| 37 | - - - - - - - - - - - - - - - - - - - - - - - - - |
| 38 | |
| 39 | --- options.c 17 Apr 2004 17:07:23 -0000 1.147 |
| 40 | +++ options.c 29 Apr 2004 19:50:13 -0000 |
| 41 | @@ -89,6 +89,7 @@ int opt_ignore_existing = 0; |
| 42 | int max_delete = 0; |
| 43 | int ignore_errors = 0; |
| 44 | int modify_window = 0; |
| 45 | +int ignore_case = 0; |
| 46 | int blocking_io = -1; |
| 47 | int checksum_seed = 0; |
| 48 | unsigned int block_size = 0; |
| 49 | @@ -275,6 +276,7 @@ void usage(enum logcode F) |
| 50 | rprintf(F," --include-from=FILE don't exclude patterns listed in FILE\n"); |
| 51 | rprintf(F," --files-from=FILE read FILE for list of source-file names\n"); |
| 52 | rprintf(F," -0 --from0 all *-from file lists are delimited by nulls\n"); |
| 53 | + rprintf(F," --ignore-case ignore case when comparing filenames\n"); |
| 54 | rprintf(F," --version print version number\n"); |
| 55 | rprintf(F," --daemon run as an rsync daemon\n"); |
| 56 | rprintf(F," --no-detach do not detach from the parent\n"); |
| 57 | @@ -329,6 +331,7 @@ static struct poptOption long_options[] |
| 58 | {"include", 0, POPT_ARG_STRING, 0, OPT_INCLUDE, 0, 0 }, |
| 59 | {"exclude-from", 0, POPT_ARG_STRING, 0, OPT_EXCLUDE_FROM, 0, 0 }, |
| 60 | {"include-from", 0, POPT_ARG_STRING, 0, OPT_INCLUDE_FROM, 0, 0 }, |
| 61 | + {"ignore-case", 0, POPT_ARG_NONE, &ignore_case, 0, 0, 0 }, |
| 62 | {"safe-links", 0, POPT_ARG_NONE, &safe_symlinks, 0, 0, 0 }, |
| 63 | {"help", 'h', POPT_ARG_NONE, 0, 'h', 0, 0 }, |
| 64 | {"backup", 'b', POPT_ARG_NONE, &make_backups, 0, 0, 0 }, |
| 65 | @@ -911,6 +914,9 @@ void server_options(char **args,int *arg |
| 66 | goto oom; |
| 67 | args[ac++] = arg; |
| 68 | } |
| 69 | + |
| 70 | + if (ignore_case) |
| 71 | + args[ac++] = "--ignore-case"; |
| 72 | |
| 73 | if (keep_partial) |
| 74 | args[ac++] = "--partial"; |
| 75 | --- util.c 27 Apr 2004 19:59:37 -0000 1.141 |
| 76 | +++ util.c 29 Apr 2004 19:50:13 -0000 |
| 77 | @@ -933,6 +933,19 @@ int u_strcmp(const char *cs1, const char |
| 78 | { |
| 79 | const uchar *s1 = (const uchar *)cs1; |
| 80 | const uchar *s2 = (const uchar *)cs2; |
| 81 | + extern int ignore_case; |
| 82 | + |
| 83 | + if (ignore_case) { |
| 84 | + while (*s1 && *s2) { |
| 85 | + uchar c1 = islower(*s1) ? toupper(*s1) : *s1; |
| 86 | + uchar c2 = islower(*s2) ? toupper(*s2) : *s2; |
| 87 | + if (c1 != c2) |
| 88 | + return (int)c1 - (int)c2; |
| 89 | + s1++; s2++; |
| 90 | + } |
| 91 | + |
| 92 | + return (int)*s1 - (int)*s2; |
| 93 | + } |
| 94 | |
| 95 | while (*s1 && *s2 && (*s1 == *s2)) { |
| 96 | s1++; s2++; |
| 97 | --- lib/wildmatch.c 14 Jul 2003 15:12:59 -0000 1.12 |
| 98 | +++ lib/wildmatch.c 29 Apr 2004 19:50:13 -0000 |
| 99 | @@ -76,8 +76,20 @@ static int domatch(const unsigned char * |
| 100 | ch = *++p; |
| 101 | /* FALLTHROUGH */ |
| 102 | default: |
| 103 | - if (*text != ch) |
| 104 | + if (*text != ch) { |
| 105 | + extern int ignore_case; |
| 106 | + if (ignore_case) { |
| 107 | + if (ISUPPER(*text)) { |
| 108 | + if (tolower(*text) == ch) |
| 109 | + continue; |
| 110 | + } |
| 111 | + else if (ISUPPER(ch)) { |
| 112 | + if (*text == tolower(ch)) |
| 113 | + continue; |
| 114 | + } |
| 115 | + } |
| 116 | return FALSE; |
| 117 | + } |
| 118 | continue; |
| 119 | case '?': |
| 120 | /* Match anything but '/'. */ |