From e7a69008e6d8b0750e74bcec85ac1ee92703fa42 Mon Sep 17 00:00:00 2001 From: Wayne Davison Date: Mon, 19 Jul 2004 08:27:17 +0000 Subject: [PATCH] Do a better job of writing out the BATCH.sh file (i.e. quote special characters and spaces in args, omit all the source args, omit the include/exclude args if we can). --- batch.c | 82 +++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 25 deletions(-) diff --git a/batch.c b/batch.c index 8d3f7961..e84fe36f 100644 --- a/batch.c +++ b/batch.c @@ -9,11 +9,42 @@ #include extern char *batch_name; +extern int delete_mode; +extern int delete_excluded; -void write_batch_argvs_file(int argc, char *argv[]) +static void write_arg(int fd, char *arg) +{ + char *x, *s; + + if (*arg == '-' && (x = strchr(arg, '=')) != NULL) { + write(fd, arg, x - arg + 1); + arg += x - arg + 1; + } + + if (strpbrk(arg, " \"'&;|[]()$#!*?^\\") != NULL) { + write(fd, "'", 1); + for (s = arg; (x = strchr(s, '\'')) != NULL; s = x + 1) { + write(fd, s, x - s + 1); + write(fd, "'", 1); + } + write(fd, s, strlen(s)); + write(fd, "'", 1); + return; + } + + write(fd, arg, strlen(arg)); +} + +/* This routine tries to write out an equivalent --read-batch command + * given the user's --write-batch args. However, it doesn't really + * understand most of the options, so it uses some overly simple + * heuristics to munge the command line into something that will + * (hopefully) work. */ +void write_batch_shell_file(int argc, char *argv[], int file_arg_cnt) { int fd, i; - char filename[MAXPATHLEN]; + char *p, filename[MAXPATHLEN]; + int need_excludes = delete_mode && !delete_excluded; stringjoin(filename, sizeof filename, batch_name, ".sh", NULL); @@ -24,34 +55,35 @@ void write_batch_argvs_file(int argc, char *argv[]) exit_cleanup(1); } - /* Write argvs info to BATCH.rsync_argvs file */ - for (i = 0; i < argc; i++) { - if (i == argc - 2) /* Skip source directory on cmdline */ - continue; - if (strncmp(argv[i], "--files-from", 12) == 0) { - if (strchr(argv[i], '=') == NULL) + /* Write argvs info to BATCH.sh file */ + write_arg(fd, argv[0]); + for (i = 1; i < argc - file_arg_cnt; i++) { + p = argv[i]; + if (strncmp(p, "--files-from", 12) == 0 + || (!need_excludes && (strncmp(p, "--include", 9) == 0 + || strncmp(p, "--exclude", 9) == 0))) { + if (strchr(p, '=') == NULL) i++; continue; } - if (i != 0) - write(fd, " ", 1); - if (strncmp(argv[i], "--write-batch", 13) == 0) { - write(fd, "--read", 6); - write(fd, argv[i] + 7, strlen(argv[i] + 7)); - } else if (i == argc - 1) { - char *p = find_colon(argv[i]); - if (p) { - if (*++p == ':') - p++; - } else - p = argv[i]; - write(fd, "${1:-", 5); - write(fd, p, strlen(p)); - write(fd, "}", 1); + write(fd, " ", 1); + if (strncmp(p, "--write-batch", 13) == 0) { + write(fd, "--read-batch", 12); + if (p[13] == '=') { + write(fd, "=", 1); + write_arg(fd, p + 14); + } } else - write(fd, argv[i], strlen(argv[i])); + write_arg(fd, p); } - if (write(fd, "\n", 1) != 1 || close(fd) < 0) { + if ((p = find_colon(argv[argc - 1])) != NULL) { + if (*++p == ':') + p++; + } else + p = argv[argc - 1]; + write(fd, " ${1:-", 6); + write_arg(fd, p); + if (write(fd, "}\n", 2) != 2 || close(fd) < 0) { rsyserr(FERROR, errno, "Batch file %s write error", filename); exit_cleanup(1); } -- 2.34.1