Annotation of embedaddon/rsync/patches/transliterate.diff, revision 1.1
1.1 ! misho 1: This patch adds an option --tr=BAD/GOOD to transliterate filenames. It
! 2: can be used to remove characters illegal on the destination filesystem.
! 3: Jeff Weber expressed interest in this:
! 4:
! 5: http://lists.samba.org/archive/rsync/2007-October/018996.html
! 6:
! 7: To use this patch, run these commands for a successful build:
! 8:
! 9: patch -p1 <patches/transliterate.diff
! 10: ./configure (optional if already run)
! 11: make
! 12:
! 13: based-on: e94bad1c156fc3910f24e2b3b71a81b0b0bdeb70
! 14: diff --git a/flist.c b/flist.c
! 15: --- a/flist.c
! 16: +++ b/flist.c
! 17: @@ -77,6 +77,7 @@ extern uid_t our_uid;
! 18: extern struct stats stats;
! 19: extern char *filesfrom_host;
! 20: extern char *usermap, *groupmap;
! 21: +extern char *tr_opt;
! 22:
! 23: extern char curr_dir[MAXPATHLEN];
! 24:
! 25: @@ -104,6 +105,8 @@ int file_old_total = 0; /* total of active items that will soon be gone */
! 26: int flist_eof = 0; /* all the file-lists are now known */
! 27: int xfer_flags_as_varint = 0;
! 28:
! 29: +char tr_substitutions[256];
! 30: +
! 31: #define NORMAL_NAME 0
! 32: #define SLASH_ENDING_NAME 1
! 33: #define DOTDIR_NAME 2
! 34: @@ -674,6 +677,23 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
! 35: stats.total_size += F_LENGTH(file);
! 36: }
! 37:
! 38: +static void transliterate(char *path, int len)
! 39: +{
! 40: + while (1) {
! 41: + /* Find position of any char in tr_opt in path, or the end of the path. */
! 42: + int span = strcspn(path, tr_opt);
! 43: + if ((len -= span) == 0)
! 44: + return;
! 45: + path += span;
! 46: + if ((*path = tr_substitutions[*(uchar*)path]) == '\0')
! 47: + memmove(path, path+1, len--); /* copies the trailing '\0' too. */
! 48: + else {
! 49: + path++;
! 50: + len--;
! 51: + }
! 52: + }
! 53: +}
! 54: +
! 55: static struct file_struct *recv_file_entry(int f, struct file_list *flist, int xflags)
! 56: {
! 57: static int64 modtime, atime;
! 58: @@ -744,9 +764,13 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
! 59: outbuf.len = 0;
! 60: }
! 61: thisname[outbuf.len] = '\0';
! 62: + basename_len = outbuf.len;
! 63: }
! 64: #endif
! 65:
! 66: + if (tr_opt)
! 67: + transliterate(thisname, basename_len);
! 68: +
! 69: if (*thisname
! 70: && (clean_fname(thisname, CFN_REFUSE_DOT_DOT_DIRS) < 0 || (!relative_paths && *thisname == '/'))) {
! 71: rprintf(FERROR, "ABORTING due to unsafe pathname from sender: %s\n", thisname);
! 72: @@ -2531,6 +2555,15 @@ struct file_list *recv_file_list(int f, int dir_ndx)
! 73: parse_name_map(usermap, True);
! 74: if (groupmap)
! 75: parse_name_map(groupmap, False);
! 76: + if (tr_opt) { /* Parse FROM/TO string and populate tr_substitutions[] */
! 77: + char *f, *t;
! 78: + if ((t = strchr(tr_opt, '/')) != NULL)
! 79: + *t++ = '\0';
! 80: + else
! 81: + t = "";
! 82: + for (f = tr_opt; *f; f++)
! 83: + tr_substitutions[*(uchar*)f] = *t ? *t++ : '\0';
! 84: + }
! 85: }
! 86:
! 87: start_read = stats.total_read;
! 88: diff --git a/options.c b/options.c
! 89: --- a/options.c
! 90: +++ b/options.c
! 91: @@ -201,6 +201,7 @@ int logfile_format_has_i = 0;
! 92: int logfile_format_has_o_or_i = 0;
! 93: int always_checksum = 0;
! 94: int list_only = 0;
! 95: +char *tr_opt = NULL;
! 96:
! 97: #define MAX_BATCH_NAME_LEN 256 /* Must be less than MAXPATHLEN-13 */
! 98: char *batch_name = NULL;
! 99: @@ -797,6 +798,7 @@ static struct poptOption long_options[] = {
! 100: {"temp-dir", 'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
! 101: {"iconv", 0, POPT_ARG_STRING, &iconv_opt, 0, 0, 0 },
! 102: {"no-iconv", 0, POPT_ARG_NONE, 0, OPT_NO_ICONV, 0, 0 },
! 103: + {"tr", 0, POPT_ARG_STRING, &tr_opt, 0, 0, 0 },
! 104: {"ipv4", '4', POPT_ARG_VAL, &default_af_hint, AF_INET, 0, 0 },
! 105: {"ipv6", '6', POPT_ARG_VAL, &default_af_hint, AF_INET6, 0, 0 },
! 106: {"8-bit-output", '8', POPT_ARG_VAL, &allow_8bit_chars, 1, 0, 0 },
! 107: @@ -2436,6 +2438,24 @@ int parse_arguments(int *argc_p, const char ***argv_p)
! 108: }
! 109: }
! 110:
! 111: + if (tr_opt) {
! 112: + if (*tr_opt == '/' && tr_opt[1]) {
! 113: + snprintf(err_buf, sizeof err_buf,
! 114: + "Do not start the --tr arg with a slash\n");
! 115: + return 0;
! 116: + }
! 117: + if (*tr_opt && *tr_opt != '/') {
! 118: + need_unsorted_flist = 1;
! 119: + arg = strchr(tr_opt, '/');
! 120: + if (arg && strchr(arg+1, '/')) {
! 121: + snprintf(err_buf, sizeof err_buf,
! 122: + "--tr cannot transliterate slashes\n");
! 123: + return 0;
! 124: + }
! 125: + } else
! 126: + tr_opt = NULL;
! 127: + }
! 128: +
! 129: am_starting_up = 0;
! 130:
! 131: return 1;
! 132: @@ -2887,6 +2907,12 @@ void server_options(char **args, int *argc_p)
! 133: if (relative_paths && !implied_dirs && (!am_sender || protocol_version >= 30))
! 134: args[ac++] = "--no-implied-dirs";
! 135:
! 136: + if (tr_opt) {
! 137: + if (asprintf(&arg, "--tr=%s", tr_opt) < 0)
! 138: + goto oom;
! 139: + args[ac++] = arg;
! 140: + }
! 141: +
! 142: if (write_devices && am_sender)
! 143: args[ac++] = "--write-devices";
! 144:
! 145: diff --git a/rsync.1.md b/rsync.1.md
! 146: --- a/rsync.1.md
! 147: +++ b/rsync.1.md
! 148: @@ -466,6 +466,7 @@ detailed description below for a complete description.
! 149: --read-batch=FILE read a batched update from FILE
! 150: --protocol=NUM force an older protocol version to be used
! 151: --iconv=CONVERT_SPEC request charset conversion of filenames
! 152: +--tr=BAD/GOOD transliterate filenames
! 153: --checksum-seed=NUM set block/file checksum seed (advanced)
! 154: --ipv4, -4 prefer IPv4
! 155: --ipv6, -6 prefer IPv6
! 156: @@ -3319,6 +3320,25 @@ your home directory (remove the '=' for that).
! 157: free to specify just the local charset for a daemon transfer (e.g.
! 158: `--iconv=utf8`).
! 159:
! 160: +0. `--tr=BAD/GOOD`
! 161: +
! 162: + Transliterates filenames on the receiver, after the iconv conversion (if
! 163: + any). This can be used to remove characters illegal on the destination
! 164: + filesystem. If you use this option, consider saving a "find . -ls" listing
! 165: + of the source in the destination to help you determine the original
! 166: + filenames in case of need.
! 167: +
! 168: + The argument consists of a string of characters to remove, optionally
! 169: + followed by a slash and a string of corresponding characters with which to
! 170: + replace them. The second string may be shorter, in which case any leftover
! 171: + characters in the first string are simply deleted. For example,
! 172: + `--tr=':\/!'` replaces colons with exclamation marks and deletes
! 173: + backslashes. Slashes cannot be transliterated because it would cause
! 174: + havoc.
! 175: +
! 176: + If the receiver is invoked over a remote shell, use `--protect-args` to
! 177: + stop the shell from interpreting any nasty characters in the argument.
! 178: +
! 179: 0. `--ipv4`, `-4` or `--ipv6`, `-6`
! 180:
! 181: Tells rsync to prefer IPv4/IPv6 when creating sockets or running ssh. This
! 182: diff -Nurp a/rsync.1 b/rsync.1
! 183: --- a/rsync.1
! 184: +++ b/rsync.1
! 185: @@ -542,6 +542,7 @@ detailed description below for a complet
! 186: --read-batch=FILE read a batched update from FILE
! 187: --protocol=NUM force an older protocol version to be used
! 188: --iconv=CONVERT_SPEC request charset conversion of filenames
! 189: +--tr=BAD/GOOD transliterate filenames
! 190: --checksum-seed=NUM set block/file checksum seed (advanced)
! 191: --ipv4, -4 prefer IPv4
! 192: --ipv6, -6 prefer IPv6
! 193: @@ -3372,6 +3373,23 @@ daemon uses the charset specified in its
! 194: regardless of the remote charset you actually pass. Thus, you may feel
! 195: free to specify just the local charset for a daemon transfer (e.g.
! 196: \fB\-\-iconv=utf8\fP).
! 197: +.IP "\fB\-\-tr=BAD/GOOD\fP"
! 198: +Transliterates filenames on the receiver, after the iconv conversion (if
! 199: +any). This can be used to remove characters illegal on the destination
! 200: +filesystem. If you use this option, consider saving a "find . \-ls" listing
! 201: +of the source in the destination to help you determine the original
! 202: +filenames in case of need.
! 203: +.IP
! 204: +The argument consists of a string of characters to remove, optionally
! 205: +followed by a slash and a string of corresponding characters with which to
! 206: +replace them. The second string may be shorter, in which case any leftover
! 207: +characters in the first string are simply deleted. For example,
! 208: +\fB\-\-tr=':\\/!'\fP replaces colons with exclamation marks and deletes
! 209: +backslashes. Slashes cannot be transliterated because it would cause
! 210: +havoc.
! 211: +.IP
! 212: +If the receiver is invoked over a remote shell, use \fB\-\-protect-args\fP to
! 213: +stop the shell from interpreting any nasty characters in the argument.
! 214: .IP "\fB\-\-ipv4\fP, \fB\-4\fP or \fB\-\-ipv6\fP, \fB\-6\fP"
! 215: Tells rsync to prefer IPv4/IPv6 when creating sockets or running ssh. This
! 216: affects sockets that rsync has direct control over, such as the outgoing
! 217: diff -Nurp a/rsync.1.html b/rsync.1.html
! 218: --- a/rsync.1.html
! 219: +++ b/rsync.1.html
! 220: @@ -457,6 +457,7 @@ detailed description below for a complet
! 221: --read-batch=FILE read a batched update from FILE
! 222: --protocol=NUM force an older protocol version to be used
! 223: --iconv=CONVERT_SPEC request charset conversion of filenames
! 224: +--tr=BAD/GOOD transliterate filenames
! 225: --checksum-seed=NUM set block/file checksum seed (advanced)
! 226: --ipv4, -4 prefer IPv4
! 227: --ipv6, -6 prefer IPv6
! 228: @@ -3129,6 +3130,23 @@ free to specify just the local charset f
! 229: <code>--iconv=utf8</code>).</p>
! 230: </dd>
! 231:
! 232: +<dt><code>--tr=BAD/GOOD</code></dt><dd>
! 233: +<p>Transliterates filenames on the receiver, after the iconv conversion (if
! 234: +any). This can be used to remove characters illegal on the destination
! 235: +filesystem. If you use this option, consider saving a "find . -⁠ls" listing
! 236: +of the source in the destination to help you determine the original
! 237: +filenames in case of need.</p>
! 238: +<p>The argument consists of a string of characters to remove, optionally
! 239: +followed by a slash and a string of corresponding characters with which to
! 240: +replace them. The second string may be shorter, in which case any leftover
! 241: +characters in the first string are simply deleted. For example,
! 242: +<code>--tr=':\/!'</code> replaces colons with exclamation marks and deletes
! 243: +backslashes. Slashes cannot be transliterated because it would cause
! 244: +havoc.</p>
! 245: +<p>If the receiver is invoked over a remote shell, use <code>--protect-args</code> to
! 246: +stop the shell from interpreting any nasty characters in the argument.</p>
! 247: +</dd>
! 248: +
! 249: <dt><code>--ipv4</code>, <code>-4</code> or <code>--ipv6</code>, <code>-6</code></dt><dd>
! 250: <p>Tells rsync to prefer IPv4/IPv6 when creating sockets or running ssh. This
! 251: affects sockets that rsync has direct control over, such as the outgoing
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>