X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/486f8cd1abb053fbe2dc4cbabe3db6f326019ea3..1874f7e2e176dc7a3c2f05687a28bcbfe5964b06:/options.c diff --git a/options.c b/options.c index 4a9b28f2..57c4446e 100644 --- a/options.c +++ b/options.c @@ -72,7 +72,7 @@ int protocol_version = PROTOCOL_VERSION; int sparse_files = 0; int do_compression = 0; int def_compress_level = Z_DEFAULT_COMPRESSION; -int am_root = 0; +int am_root = 0; /* 0 = normal, 1 = root, 2 = --super, -1 = --fake-super */ int am_server = 0; int am_sender = 0; int am_generator = 0; @@ -177,6 +177,11 @@ int list_only = 0; #define MAX_BATCH_NAME_LEN 256 /* Must be less than MAXPATHLEN-13 */ char *batch_name = NULL; +#ifdef ICONV_OPTION +int need_unsorted_flist = 0; +char *iconv_opt = ICONV_OPTION; +#endif + struct chmod_mode_struct *chmod_modes = NULL; static int daemon_opt; /* sets am_daemon after option error-reporting */ @@ -198,28 +203,29 @@ char *bind_address; static void print_rsync_version(enum logcode f) { - char buf[32]; + char *subprotocol = ""; char const *got_socketpair = "no "; char const *have_inplace = "no "; char const *hardlinks = "no "; char const *acls = "no "; char const *xattrs = "no "; char const *links = "no "; + char const *iconv = "no "; char const *ipv6 = "no "; STRUCT_STAT *dumstat; +#if SUBPROTOCOL_VERSION != 0 + asprintf(&subprotocol, ".PR%d", SUBPROTOCOL_VERSION); +#endif #ifdef HAVE_SOCKETPAIR got_socketpair = ""; #endif - #ifdef HAVE_FTRUNCATE have_inplace = ""; #endif - #ifdef SUPPORT_HARD_LINKS hardlinks = ""; #endif - #ifdef SUPPORT_ACLS acls = ""; #endif @@ -229,17 +235,15 @@ static void print_rsync_version(enum logcode f) #ifdef SUPPORT_LINKS links = ""; #endif - #ifdef INET6 ipv6 = ""; #endif +#ifdef ICONV_OPTION + iconv = ""; +#endif - if (SUBPROTOCOL_VERSION) - snprintf(buf, sizeof buf, ".PR%d", SUBPROTOCOL_VERSION); - else - *buf = '\0'; rprintf(f, "%s version %s protocol version %d%s\n", - RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION, buf); + RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION, subprotocol); rprintf(f, "Copyright (C) 1996-2007 by Andrew Tridgell, Wayne Davison, and others.\n"); rprintf(f, "Web site: http://rsync.samba.org/\n"); rprintf(f, "Capabilities:\n"); @@ -250,8 +254,8 @@ static void print_rsync_version(enum logcode f) (int)(sizeof (int64) * 8)); rprintf(f, " %ssocketpairs, %shardlinks, %ssymlinks, %sIPv6, batchfiles, %sinplace,\n", got_socketpair, hardlinks, links, ipv6, have_inplace); - rprintf(f, " %sappend, %sACLs, %sxattrs\n", - have_inplace, acls, xattrs); + rprintf(f, " %sappend, %sACLs, %sxattrs, %siconv\n", + have_inplace, acls, xattrs, iconv); #ifdef MAINTAINER_MODE rprintf(f, "Panic Action: \"%s\"\n", get_panic_action()); @@ -333,6 +337,9 @@ void usage(enum logcode F) rprintf(F," -t, --times preserve times\n"); rprintf(F," -O, --omit-dir-times omit directories when preserving times\n"); rprintf(F," --super receiver attempts super-user activities\n"); +#ifdef SUPPORT_XATTRS + rprintf(F," --fake-super store/recover privileged attrs using xattrs\n"); +#endif rprintf(F," -S, --sparse handle sparse files efficiently\n"); rprintf(F," -n, --dry-run show what would have been transferred\n"); rprintf(F," -W, --whole-file copy files whole (without rsync algorithm)\n"); @@ -401,6 +408,9 @@ void usage(enum logcode F) rprintf(F," --only-write-batch=FILE like --write-batch but w/o updating destination\n"); rprintf(F," --read-batch=FILE read a batched update from FILE\n"); rprintf(F," --protocol=NUM force an older protocol version to be used\n"); +#ifdef ICONV_OPTION + rprintf(F," --iconv=CONVERT_SPEC request charset conversion of filesnames\n"); +#endif #ifdef INET6 rprintf(F," -4, --ipv4 prefer IPv4\n"); rprintf(F," -6, --ipv6 prefer IPv6\n"); @@ -462,6 +472,7 @@ static struct poptOption long_options[] = { {"modify-window", 0, POPT_ARG_INT, &modify_window, OPT_MODIFY_WINDOW, 0, 0 }, {"super", 0, POPT_ARG_VAL, &am_root, 2, 0, 0 }, {"no-super", 0, POPT_ARG_VAL, &am_root, 0, 0, 0 }, + {"fake-super", 0, POPT_ARG_VAL, &am_root, -1, 0, 0 }, {"owner", 'o', POPT_ARG_VAL, &preserve_uid, 1, 0, 0 }, {"no-owner", 0, POPT_ARG_VAL, &preserve_uid, 0, 0, 0 }, {"no-o", 0, POPT_ARG_VAL, &preserve_uid, 0, 0, 0 }, @@ -561,6 +572,9 @@ static struct poptOption long_options[] = { {"rsh", 'e', POPT_ARG_STRING, &shell_cmd, 0, 0, 0 }, {"rsync-path", 0, POPT_ARG_STRING, &rsync_path, 0, 0, 0 }, {"temp-dir", 'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 }, +#ifdef ICONV_OPTION + {"iconv", 0, POPT_ARG_STRING, &iconv_opt, 0, 0, 0 }, +#endif #ifdef INET6 {"ipv4", '4', POPT_ARG_VAL, &default_af_hint, AF_INET, 0, 0 }, {"ipv6", '6', POPT_ARG_VAL, &default_af_hint, AF_INET6, 0, 0 }, @@ -833,6 +847,11 @@ int parse_arguments(int *argc, const char ***argv, int frommain) if (am_daemon) set_refuse_options("log-file*"); +#ifdef ICONV_OPTION + if (!am_daemon && (arg = getenv("RSYNC_ICONV")) != NULL && *arg) + iconv_opt = strdup(arg); +#endif + /* TODO: Call poptReadDefaultConfig; handle errors. */ /* The context leaks in case of an error, but if there's a @@ -858,6 +877,9 @@ int parse_arguments(int *argc, const char ***argv, int frommain) long_options, 0); am_server = 1; } +#ifdef ICONV_OPTION + iconv_opt = NULL; +#endif break; case OPT_SENDER: @@ -875,6 +897,9 @@ int parse_arguments(int *argc, const char ***argv, int frommain) sizeof err_buf); return 0; } +#ifdef ICONV_OPTION + iconv_opt = NULL; +#endif poptFreeContext(pc); pc = poptGetContext(RSYNC_NAME, *argc, *argv, long_daemon_options, 0); @@ -1176,6 +1201,15 @@ int parse_arguments(int *argc, const char ***argv, int frommain) exit_cleanup(0); } +#ifdef ICONV_OPTION + if (iconv_opt) { + if (!am_server && strcmp(iconv_opt, "-") == 0) + iconv_opt = NULL; + else + need_unsorted_flist = 1; + } +#endif + #ifndef SUPPORT_LINKS if (preserve_links && !am_sender) { snprintf(err_buf, sizeof err_buf, @@ -1194,6 +1228,14 @@ int parse_arguments(int *argc, const char ***argv, int frommain) } #endif +#ifndef SUPPORT_XATTRS + if (am_root < 0) { + snprintf(err_buf, sizeof err_buf, + "--fake-super requires an rsync with extended attributes enabled\n"); + return 0; + } +#endif + if (write_batch && read_batch) { snprintf(err_buf, sizeof err_buf, "--write-batch and --read-batch can not be used together\n"); @@ -1648,14 +1690,16 @@ void server_options(char **args,int *argc) if (list_only == 1 && !recurse) argstr[x++] = 'r'; - argstr[x] = '\0'; - +#if SUBPROTOCOL_VERSION != 0 /* If we're speaking a pre-release version of a protocol, we tell * the server about this by (ab)using the -e option. */ - if (SUBPROTOCOL_VERSION && protocol_version == PROTOCOL_VERSION) { + if (protocol_version == PROTOCOL_VERSION) { x += snprintf(argstr+x, sizeof argstr - x, "e%d.%d", PROTOCOL_VERSION, SUBPROTOCOL_VERSION); } +#endif + + argstr[x] = '\0'; if (x != 1) args[ac++] = argstr; @@ -1695,6 +1739,19 @@ void server_options(char **args,int *argc) args[ac++] = "--log-format=X"; } +#ifdef ICONV_OPTION + if (iconv_opt) { + char *set = strchr(iconv_opt, ','); + if (set) + set++; + else + set = iconv_opt; + if (asprintf(&arg, "--iconv=%s", set) < 0) + goto oom; + args[ac++] = arg; + } +#endif + if (block_size) { if (asprintf(&arg, "-B%lu", block_size) < 0) goto oom; @@ -1799,35 +1856,37 @@ void server_options(char **args,int *argc) if (numeric_ids) args[ac++] = "--numeric-ids"; - if (ignore_existing && am_sender) - args[ac++] = "--ignore-existing"; + if (am_sender) { + if (ignore_existing) + args[ac++] = "--ignore-existing"; + + /* Backward compatibility: send --existing, not --ignore-non-existing. */ + if (ignore_non_existing) + args[ac++] = "--existing"; - /* Backward compatibility: send --existing, not --ignore-non-existing. */ - if (ignore_non_existing && am_sender) - args[ac++] = "--existing"; + if (tmpdir) { + args[ac++] = "--temp-dir"; + args[ac++] = tmpdir; + } + + if (basis_dir[0]) { + /* the server only needs this option if it is not the sender, + * and it may be an older version that doesn't know this + * option, so don't send it if client is the sender. + */ + int i; + for (i = 0; i < basis_dir_cnt; i++) { + args[ac++] = dest_option; + args[ac++] = basis_dir[i]; + } + } + } if (append_mode) args[ac++] = "--append"; else if (inplace) args[ac++] = "--inplace"; - if (tmpdir && am_sender) { - args[ac++] = "--temp-dir"; - args[ac++] = tmpdir; - } - - if (basis_dir[0] && am_sender) { - /* the server only needs this option if it is not the sender, - * and it may be an older version that doesn't know this - * option, so don't send it if client is the sender. - */ - int i; - for (i = 0; i < basis_dir_cnt; i++) { - args[ac++] = dest_option; - args[ac++] = basis_dir[i]; - } - } - if (files_from && (!am_sender || filesfrom_host)) { if (filesfrom_host) { args[ac++] = "--files-from";