X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/adc2476fa213797d849ae80fa8b5fcd9eba5dc4f..b3bf9b9df95137a3a43248be9599d919b04877af:/options.c diff --git a/options.c b/options.c index e0a84017..221ddcb5 100644 --- a/options.c +++ b/options.c @@ -3,7 +3,7 @@ * * Copyright (C) 1998-2001 Andrew Tridgell * Copyright (C) 2000, 2001, 2002 Martin Pool - * Copyright (C) 2002-2008 Wayne Davison + * Copyright (C) 2002-2009 Wayne Davison * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,7 +20,7 @@ */ #include "rsync.h" -#include "ifuncs.h" +#include "itypes.h" #include #include "zlib/zlib.h" @@ -167,6 +167,8 @@ char *rsync_path = RSYNC_PATH; char *backup_dir = NULL; char backup_dir_buf[MAXPATHLEN]; char *sockopts = NULL; +char *usermap = NULL; +char *groupmap = NULL; int rsync_port = 0; int compare_dest = 0; int copy_dest = 0; @@ -204,7 +206,7 @@ static const char *debug_verbosity[] = { /*2*/ "bind,cmd,connect,del,deltasum,dup,filter,flist,iconv", /*3*/ "acl,backup,deltasum2,del2,exit,filter2,flist2,fuzzy,genr,own,recv,send,time", /*4*/ "cmd2,deltasum3,del3,exit2,flist3,iconv2,own2,proto,time2", - /*5*/ "chdir,deltasum4,flist4,fuzzy2,hlink", + /*5*/ "chdir,deltasum4,flist4,fuzzy2,hash,hlink", }; #define MAX_VERBOSITY ((int)(sizeof debug_verbosity / sizeof debug_verbosity[0]) - 1) @@ -273,6 +275,7 @@ static struct output_struct debug_words[COUNT_DEBUG+1] = { DEBUG_WORD(FLIST, W_SND|W_REC, "Debug file-list operations (levels 1-4)"), DEBUG_WORD(FUZZY, W_REC, "Debug fuzzy scoring (levels 1-2)"), DEBUG_WORD(GENR, W_REC, "Debug generator functions"), + DEBUG_WORD(HASH, W_SND|W_REC, "Debug hashtable code"), DEBUG_WORD(HLINK, W_SND|W_REC, "Debug hard-link actions"), DEBUG_WORD(ICONV, W_CLI|W_SRV, "Debug iconv character conversions (levels 1-2)"), DEBUG_WORD(OWN, W_REC, "Debug ownership changes in users & groups (levels 1-2)"), @@ -295,6 +298,7 @@ static int refused_delete, refused_archive_part, refused_compress; static int refused_partial, refused_progress, refused_delete_before; static int refused_delete_during; static int refused_inplace, refused_no_iconv; +static BOOL usermap_via_chown, groupmap_via_chown; static char *max_size_arg, *min_size_arg; static char tmp_partialdir[] = ".~tmp~"; @@ -564,7 +568,8 @@ static void print_rsync_version(enum logcode f) STRUCT_STAT *dumstat; #if SUBPROTOCOL_VERSION != 0 - asprintf(&subprotocol, ".PR%d", SUBPROTOCOL_VERSION); + if (asprintf(&subprotocol, ".PR%d", SUBPROTOCOL_VERSION) < 0) + out_of_memory("print_rsync_version"); #endif #ifdef HAVE_SOCKETPAIR got_socketpair = ""; @@ -596,7 +601,7 @@ static void print_rsync_version(enum logcode f) rprintf(f, "%s version %s protocol version %d%s\n", RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION, subprotocol); - rprintf(f, "Copyright (C) 1996-2008 by Andrew Tridgell, Wayne Davison, and others.\n"); + rprintf(f, "Copyright (C) 1996-2009 by Andrew Tridgell, Wayne Davison, and others.\n"); rprintf(f, "Web site: http://rsync.samba.org/\n"); rprintf(f, "Capabilities:\n"); rprintf(f, " %d-bit files, %d-bit inums, %d-bit timestamps, %d-bit long ints,\n", @@ -723,6 +728,9 @@ void usage(enum logcode F) rprintf(F," --delay-updates put all updated files into place at transfer's end\n"); rprintf(F," -m, --prune-empty-dirs prune empty directory chains from the file-list\n"); rprintf(F," --numeric-ids don't map uid/gid values by user/group name\n"); + rprintf(F," --usermap=STRING custom username mapping\n"); + rprintf(F," --groupmap=STRING custom groupname mapping\n"); + rprintf(F," --chown=USER:GROUP simple username/groupname mapping\n"); rprintf(F," --timeout=SECONDS set I/O timeout in seconds\n"); rprintf(F," --contimeout=SECONDS set daemon connection timeout in seconds\n"); rprintf(F," -I, --ignore-times don't skip files that match in size and mod-time\n"); @@ -787,6 +795,7 @@ enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM, OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW, OPT_MIN_SIZE, OPT_CHMOD, OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_ONLY_WRITE_BATCH, OPT_MAX_SIZE, OPT_NO_D, OPT_APPEND, OPT_NO_ICONV, OPT_INFO, OPT_DEBUG, + OPT_USERMAP, OPT_GROUPMAP, OPT_CHOWN, OPT_SERVER, OPT_REFUSED_BASE = 9000}; static struct poptOption long_options[] = { @@ -967,6 +976,9 @@ static struct poptOption long_options[] = { {"no-s", 0, POPT_ARG_VAL, &protect_args, 0, 0, 0}, {"numeric-ids", 0, POPT_ARG_VAL, &numeric_ids, 1, 0, 0 }, {"no-numeric-ids", 0, POPT_ARG_VAL, &numeric_ids, 0, 0, 0 }, + {"usermap", 0, POPT_ARG_STRING, 0, OPT_USERMAP, 0, 0 }, + {"groupmap", 0, POPT_ARG_STRING, 0, OPT_GROUPMAP, 0, 0 }, + {"chown", 0, POPT_ARG_STRING, 0, OPT_CHOWN, 0, 0 }, {"timeout", 0, POPT_ARG_INT, &io_timeout, 0, 0, 0 }, {"no-timeout", 0, POPT_ARG_VAL, &io_timeout, 0, 0, 0 }, {"contimeout", 0, POPT_ARG_INT, &connect_timeout, 0, 0, 0 }, @@ -1623,6 +1635,76 @@ int parse_arguments(int *argc_p, const char ***argv_p) parse_output_words(debug_words, debug_levels, arg, USER_PRIORITY); break; + case OPT_USERMAP: + if (usermap) { + if (usermap_via_chown) { + snprintf(err_buf, sizeof err_buf, + "--usermap conflicts with prior --chown.\n"); + return 0; + } + snprintf(err_buf, sizeof err_buf, + "You can only specify --usermap once.\n"); + return 0; + } + usermap = (char *)poptGetOptArg(pc); + usermap_via_chown = False; + break; + + case OPT_GROUPMAP: + if (groupmap) { + if (groupmap_via_chown) { + snprintf(err_buf, sizeof err_buf, + "--groupmap conflicts with prior --chown.\n"); + return 0; + } + snprintf(err_buf, sizeof err_buf, + "You can only specify --groupmap once.\n"); + return 0; + } + groupmap = (char *)poptGetOptArg(pc); + groupmap_via_chown = False; + break; + + case OPT_CHOWN: { + const char *chown = poptGetOptArg(pc); + int len; + if ((arg = strchr(chown, ':')) != NULL) + len = arg++ - chown; + else + len = strlen(chown); + if (len) { + if (usermap) { + if (!usermap_via_chown) { + snprintf(err_buf, sizeof err_buf, + "--chown conflicts with prior --usermap.\n"); + return 0; + } + snprintf(err_buf, sizeof err_buf, + "You can only specify a user-affecting --chown once.\n"); + return 0; + } + if (asprintf(&usermap, "*:%.*s", len, chown) < 0) + out_of_memory("parse_arguments"); + usermap_via_chown = True; + } + if (arg && *arg) { + if (groupmap) { + if (!groupmap_via_chown) { + snprintf(err_buf, sizeof err_buf, + "--chown conflicts with prior --groupmap.\n"); + return 0; + } + snprintf(err_buf, sizeof err_buf, + "You can only specify a group-affecting --chown once.\n"); + return 0; + } + if (asprintf(&groupmap, "*:%s", arg) < 0) + out_of_memory("parse_arguments"); + groupmap_via_chown = True; + } + break; + } + case OPT_HELP: usage(FINFO); exit_cleanup(0); @@ -2267,7 +2349,8 @@ void server_options(char **args, int *argc_p) argstr[x] = '\0'; - args[ac++] = argstr; + if (x > 1) + args[ac++] = argstr; #ifdef ICONV_OPTION if (iconv_opt) { @@ -2432,6 +2515,18 @@ void server_options(char **args, int *argc_p) args[ac++] = "--use-qsort"; if (am_sender) { + if (usermap) { + if (asprintf(&arg, "--usermap=%s", usermap) < 0) + goto oom; + args[ac++] = arg; + } + + if (groupmap) { + if (asprintf(&arg, "--groupmap=%s", groupmap) < 0) + goto oom; + args[ac++] = arg; + } + if (ignore_existing) args[ac++] = "--ignore-existing";