Annotation of embedaddon/rsync/options.c, revision 1.1.1.2

1.1       misho       1: /*
                      2:  * Command-line (and received via daemon-socket) option parsing.
                      3:  *
                      4:  * Copyright (C) 1998-2001 Andrew Tridgell <tridge@samba.org>
                      5:  * Copyright (C) 2000, 2001, 2002 Martin Pool <mbp@samba.org>
1.1.1.2 ! misho       6:  * Copyright (C) 2002-2013 Wayne Davison
1.1       misho       7:  *
                      8:  * This program is free software; you can redistribute it and/or modify
                      9:  * it under the terms of the GNU General Public License as published by
                     10:  * the Free Software Foundation; either version 3 of the License, or
                     11:  * (at your option) any later version.
                     12:  *
                     13:  * This program is distributed in the hope that it will be useful,
                     14:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     15:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     16:  * GNU General Public License for more details.
                     17:  *
                     18:  * You should have received a copy of the GNU General Public License along
                     19:  * with this program; if not, visit the http://fsf.org website.
                     20:  */
                     21: 
                     22: #include "rsync.h"
1.1.1.2 ! misho      23: #include "itypes.h"
1.1       misho      24: #include <popt.h>
1.1.1.2 ! misho      25: #include <zlib.h>
1.1       misho      26: 
                     27: extern int module_id;
                     28: extern int local_server;
                     29: extern int sanitize_paths;
                     30: extern int daemon_over_rsh;
                     31: extern unsigned int module_dirlen;
1.1.1.2 ! misho      32: extern filter_rule_list filter_list;
        !            33: extern filter_rule_list daemon_filter_list;
1.1       misho      34: 
                     35: int make_backups = 0;
                     36: 
                     37: /**
                     38:  * If 1, send the whole file as literal data rather than trying to
                     39:  * create an incremental diff.
                     40:  *
                     41:  * If -1, then look at whether we're local or remote and go by that.
                     42:  *
                     43:  * @sa disable_deltas_p()
                     44:  **/
                     45: int whole_file = -1;
                     46: 
                     47: int append_mode = 0;
                     48: int keep_dirlinks = 0;
                     49: int copy_dirlinks = 0;
                     50: int copy_links = 0;
                     51: int preserve_links = 0;
                     52: int preserve_hard_links = 0;
                     53: int preserve_acls = 0;
                     54: int preserve_xattrs = 0;
                     55: int preserve_perms = 0;
                     56: int preserve_executability = 0;
                     57: int preserve_devices = 0;
                     58: int preserve_specials = 0;
                     59: int preserve_uid = 0;
                     60: int preserve_gid = 0;
                     61: int preserve_times = 0;
                     62: int update_only = 0;
                     63: int cvs_exclude = 0;
                     64: int dry_run = 0;
                     65: int do_xfers = 1;
                     66: int ignore_times = 0;
                     67: int delete_mode = 0;
                     68: int delete_during = 0;
                     69: int delete_before = 0;
                     70: int delete_after = 0;
                     71: int delete_excluded = 0;
                     72: int remove_source_files = 0;
                     73: int one_file_system = 0;
                     74: int protocol_version = PROTOCOL_VERSION;
                     75: int sparse_files = 0;
1.1.1.2 ! misho      76: int preallocate_files = 0;
1.1       misho      77: int do_compression = 0;
                     78: int def_compress_level = Z_DEFAULT_COMPRESSION;
                     79: int am_root = 0; /* 0 = normal, 1 = root, 2 = --super, -1 = --fake-super */
                     80: int am_server = 0;
                     81: int am_sender = 0;
                     82: int am_starting_up = 1;
                     83: int relative_paths = -1;
                     84: int implied_dirs = 1;
1.1.1.2 ! misho      85: int missing_args = 0; /* 0 = FERROR_XFER, 1 = ignore, 2 = delete */
1.1       misho      86: int numeric_ids = 0;
1.1.1.2 ! misho      87: int msgs2stderr = 0;
1.1       misho      88: int allow_8bit_chars = 0;
                     89: int force_delete = 0;
                     90: int io_timeout = 0;
                     91: int prune_empty_dirs = 0;
                     92: int use_qsort = 0;
                     93: char *files_from = NULL;
                     94: int filesfrom_fd = -1;
                     95: char *filesfrom_host = NULL;
                     96: int eol_nulls = 0;
1.1.1.2 ! misho      97: int protect_args = -1;
        !            98: int human_readable = 1;
1.1       misho      99: int recurse = 0;
                    100: int allow_inc_recurse = 1;
                    101: int xfer_dirs = -1;
                    102: int am_daemon = 0;
                    103: int connect_timeout = 0;
                    104: int keep_partial = 0;
                    105: int safe_symlinks = 0;
                    106: int copy_unsafe_links = 0;
1.1.1.2 ! misho     107: int munge_symlinks = 0;
1.1       misho     108: int size_only = 0;
                    109: int daemon_bwlimit = 0;
                    110: int bwlimit = 0;
                    111: int fuzzy_basis = 0;
                    112: size_t bwlimit_writemax = 0;
                    113: int ignore_existing = 0;
                    114: int ignore_non_existing = 0;
                    115: int need_messages_from_generator = 0;
                    116: int max_delete = INT_MIN;
1.1.1.2 ! misho     117: OFF_T max_size = -1;
        !           118: OFF_T min_size = -1;
1.1       misho     119: int ignore_errors = 0;
                    120: int modify_window = 0;
                    121: int blocking_io = -1;
                    122: int checksum_seed = 0;
                    123: int inplace = 0;
                    124: int delay_updates = 0;
                    125: long block_size = 0; /* "long" because popt can't set an int32. */
                    126: char *skip_compress = NULL;
1.1.1.2 ! misho     127: item_list dparam_list = EMPTY_ITEM_LIST;
1.1       misho     128: 
                    129: /** Network address family. **/
                    130: int default_af_hint
                    131: #ifdef INET6
                    132:        = 0;            /* Any protocol */
                    133: #else
                    134:        = AF_INET;      /* Must use IPv4 */
                    135: # ifdef AF_INET6
                    136: #  undef AF_INET6
                    137: # endif
                    138: # define AF_INET6 AF_INET /* make -6 option a no-op */
                    139: #endif
                    140: 
                    141: /** Do not go into the background when run as --daemon.  Good
                    142:  * for debugging and required for running as a service on W32,
                    143:  * or under Unix process-monitors. **/
                    144: int no_detach
                    145: #if defined _WIN32 || defined __WIN32__
                    146:        = 1;
                    147: #else
                    148:        = 0;
                    149: #endif
                    150: 
                    151: int write_batch = 0;
                    152: int read_batch = 0;
                    153: int backup_dir_len = 0;
                    154: int backup_suffix_len;
                    155: unsigned int backup_dir_remainder;
                    156: 
                    157: char *backup_suffix = NULL;
                    158: char *tmpdir = NULL;
                    159: char *partial_dir = NULL;
                    160: char *basis_dir[MAX_BASIS_DIRS+1];
                    161: char *config_file = NULL;
                    162: char *shell_cmd = NULL;
                    163: char *logfile_name = NULL;
                    164: char *logfile_format = NULL;
                    165: char *stdout_format = NULL;
                    166: char *password_file = NULL;
                    167: char *rsync_path = RSYNC_PATH;
                    168: char *backup_dir = NULL;
                    169: char backup_dir_buf[MAXPATHLEN];
                    170: char *sockopts = NULL;
1.1.1.2 ! misho     171: char *usermap = NULL;
        !           172: char *groupmap = NULL;
1.1       misho     173: int rsync_port = 0;
                    174: int compare_dest = 0;
                    175: int copy_dest = 0;
                    176: int link_dest = 0;
                    177: int basis_dir_cnt = 0;
                    178: char *dest_option = NULL;
                    179: 
1.1.1.2 ! misho     180: static int remote_option_alloc = 0;
        !           181: int remote_option_cnt = 0;
        !           182: const char **remote_options = NULL;
        !           183: 
1.1       misho     184: int quiet = 0;
                    185: int output_motd = 1;
                    186: int log_before_transfer = 0;
                    187: int stdout_format_has_i = 0;
                    188: int stdout_format_has_o_or_i = 0;
                    189: int logfile_format_has_i = 0;
                    190: int logfile_format_has_o_or_i = 0;
                    191: int always_checksum = 0;
                    192: int list_only = 0;
                    193: 
                    194: #define MAX_BATCH_NAME_LEN 256 /* Must be less than MAXPATHLEN-13 */
                    195: char *batch_name = NULL;
                    196: 
                    197: int need_unsorted_flist = 0;
                    198: #ifdef ICONV_OPTION
                    199: char *iconv_opt = ICONV_OPTION;
                    200: #endif
                    201: 
                    202: struct chmod_mode_struct *chmod_modes = NULL;
                    203: 
1.1.1.2 ! misho     204: static const char *debug_verbosity[] = {
        !           205:        /*0*/ NULL,
        !           206:        /*1*/ NULL,
        !           207:        /*2*/ "BIND,CMD,CONNECT,DEL,DELTASUM,DUP,FILTER,FLIST,ICONV",
        !           208:        /*3*/ "ACL,BACKUP,CONNECT2,DELTASUM2,DEL2,EXIT,FILTER2,FLIST2,FUZZY,GENR,OWN,RECV,SEND,TIME",
        !           209:        /*4*/ "CMD2,DELTASUM3,DEL3,EXIT2,FLIST3,ICONV2,OWN2,PROTO,TIME2",
        !           210:        /*5*/ "CHDIR,DELTASUM4,FLIST4,FUZZY2,HASH,HLINK",
        !           211: };
        !           212: 
        !           213: #define MAX_VERBOSITY ((int)(sizeof debug_verbosity / sizeof debug_verbosity[0]) - 1)
        !           214: 
        !           215: static const char *info_verbosity[1+MAX_VERBOSITY] = {
        !           216:        /*0*/ NULL,
        !           217:        /*1*/ "COPY,DEL,FLIST,MISC,NAME,STATS,SYMSAFE",
        !           218:        /*2*/ "BACKUP,MISC2,MOUNT,NAME2,REMOVE,SKIP",
        !           219: };
        !           220: 
        !           221: #define MAX_OUT_LEVEL 4 /* The largest N allowed for any flagN word. */
        !           222: 
        !           223: short info_levels[COUNT_INFO], debug_levels[COUNT_DEBUG];
        !           224: 
        !           225: #define DEFAULT_PRIORITY 0     /* Default/implied/--verbose set values. */
        !           226: #define HELP_PRIORITY 1                /* The help output uses this level. */
        !           227: #define USER_PRIORITY 2                /* User-specified via --info or --debug */
        !           228: #define LIMIT_PRIORITY 3       /* Overriding priority when limiting values. */
        !           229: 
        !           230: #define W_CLI (1<<0)   /* client side */
        !           231: #define W_SRV (1<<1)   /* server side */
        !           232: #define W_SND (1<<2)   /* sending side */
        !           233: #define W_REC (1<<3)   /* receiving side */
        !           234: 
        !           235: struct output_struct {
        !           236:        char *name;     /* The name of the info/debug flag. */
        !           237:        char *help;     /* The description of the info/debug flag. */
        !           238:        uchar namelen;  /* The length of the name string. */
        !           239:        uchar flag;     /* The flag's value, for consistency check. */
        !           240:        uchar where;    /* Bits indicating where the flag is used. */
        !           241:        uchar priority; /* See *_PRIORITY defines. */
        !           242: };
        !           243: 
        !           244: #define INFO_WORD(flag, where, help) { #flag, help, sizeof #flag - 1, INFO_##flag, where, 0 }
        !           245: 
        !           246: static struct output_struct info_words[COUNT_INFO+1] = {
        !           247:        INFO_WORD(BACKUP, W_REC, "Mention files backed up"),
        !           248:        INFO_WORD(COPY, W_REC, "Mention files copied locally on the receiving side"),
        !           249:        INFO_WORD(DEL, W_REC, "Mention deletions on the receiving side"),
        !           250:        INFO_WORD(FLIST, W_CLI, "Mention file-list receiving/sending (levels 1-2)"),
        !           251:        INFO_WORD(MISC, W_SND|W_REC, "Mention miscellaneous information (levels 1-2)"),
        !           252:        INFO_WORD(MOUNT, W_SND|W_REC, "Mention mounts that were found or skipped"),
        !           253:        INFO_WORD(NAME, W_SND|W_REC, "Mention 1) updated file/dir names, 2) unchanged names"),
        !           254:        INFO_WORD(PROGRESS, W_CLI, "Mention 1) per-file progress or 2) total transfer progress"),
        !           255:        INFO_WORD(REMOVE, W_SND, "Mention files removed on the sending side"),
        !           256:        INFO_WORD(SKIP, W_REC, "Mention files that are skipped due to options used"),
        !           257:        INFO_WORD(STATS, W_CLI|W_SRV, "Mention statistics at end of run (levels 1-3)"),
        !           258:        INFO_WORD(SYMSAFE, W_SND|W_REC, "Mention symlinks that are unsafe"),
        !           259:        { NULL, "--info", 0, 0, 0, 0 }
        !           260: };
        !           261: 
        !           262: #define DEBUG_WORD(flag, where, help) { #flag, help, sizeof #flag - 1, DEBUG_##flag, where, 0 }
        !           263: 
        !           264: static struct output_struct debug_words[COUNT_DEBUG+1] = {
        !           265:        DEBUG_WORD(ACL, W_SND|W_REC, "Debug extra ACL info"),
        !           266:        DEBUG_WORD(BACKUP, W_REC, "Debug backup actions (levels 1-2)"),
        !           267:        DEBUG_WORD(BIND, W_CLI, "Debug socket bind actions"),
        !           268:        DEBUG_WORD(CHDIR, W_CLI|W_SRV, "Debug when the current directory changes"),
        !           269:        DEBUG_WORD(CONNECT, W_CLI, "Debug connection events (levels 1-2)"),
        !           270:        DEBUG_WORD(CMD, W_CLI, "Debug commands+options that are issued (levels 1-2)"),
        !           271:        DEBUG_WORD(DEL, W_REC, "Debug delete actions (levels 1-3)"),
        !           272:        DEBUG_WORD(DELTASUM, W_SND|W_REC, "Debug delta-transfer checksumming (levels 1-4)"),
        !           273:        DEBUG_WORD(DUP, W_REC, "Debug weeding of duplicate names"),
        !           274:        DEBUG_WORD(EXIT, W_CLI|W_SRV, "Debug exit events (levels 1-3)"),
        !           275:        DEBUG_WORD(FILTER, W_SND|W_REC, "Debug filter actions (levels 1-2)"),
        !           276:        DEBUG_WORD(FLIST, W_SND|W_REC, "Debug file-list operations (levels 1-4)"),
        !           277:        DEBUG_WORD(FUZZY, W_REC, "Debug fuzzy scoring (levels 1-2)"),
        !           278:        DEBUG_WORD(GENR, W_REC, "Debug generator functions"),
        !           279:        DEBUG_WORD(HASH, W_SND|W_REC, "Debug hashtable code"),
        !           280:        DEBUG_WORD(HLINK, W_SND|W_REC, "Debug hard-link actions (levels 1-3)"),
        !           281:        DEBUG_WORD(ICONV, W_CLI|W_SRV, "Debug iconv character conversions (levels 1-2)"),
        !           282:        DEBUG_WORD(IO, W_CLI|W_SRV, "Debug I/O routines (levels 1-4)"),
        !           283:        DEBUG_WORD(OWN, W_REC, "Debug ownership changes in users & groups (levels 1-2)"),
        !           284:        DEBUG_WORD(PROTO, W_CLI|W_SRV, "Debug protocol information"),
        !           285:        DEBUG_WORD(RECV, W_REC, "Debug receiver functions"),
        !           286:        DEBUG_WORD(SEND, W_SND, "Debug sender functions"),
        !           287:        DEBUG_WORD(TIME, W_REC, "Debug setting of modified times (levels 1-2)"),
        !           288:        { NULL, "--debug", 0, 0, 0, 0 }
        !           289: };
        !           290: 
        !           291: static int verbose = 0;
        !           292: static int do_stats = 0;
        !           293: static int do_progress = 0;
1.1       misho     294: static int daemon_opt;   /* sets am_daemon after option error-reporting */
                    295: static int omit_dir_times = 0;
1.1.1.2 ! misho     296: static int omit_link_times = 0;
1.1       misho     297: static int F_option_cnt = 0;
                    298: static int modify_window_set;
                    299: static int itemize_changes = 0;
                    300: static int refused_delete, refused_archive_part, refused_compress;
                    301: static int refused_partial, refused_progress, refused_delete_before;
                    302: static int refused_delete_during;
                    303: static int refused_inplace, refused_no_iconv;
1.1.1.2 ! misho     304: static BOOL usermap_via_chown, groupmap_via_chown;
        !           305: #ifdef HAVE_SETVBUF
        !           306: static char *outbuf_mode;
        !           307: #endif
        !           308: static char *bwlimit_arg, *max_size_arg, *min_size_arg;
1.1       misho     309: static char tmp_partialdir[] = ".~tmp~";
                    310: 
                    311: /** Local address to bind.  As a character string because it's
                    312:  * interpreted by the IPv6 layer: should be a numeric IP4 or IP6
                    313:  * address, or a hostname. **/
                    314: char *bind_address;
                    315: 
1.1.1.2 ! misho     316: static void output_item_help(struct output_struct *words);
        !           317: 
        !           318: /* This constructs a string that represents all the options set for either
        !           319:  * the --info or --debug setting, skipping any implied options (by -v, etc.).
        !           320:  * This is used both when conveying the user's options to the server, and
        !           321:  * when the help output wants to tell the user what options are implied. */
        !           322: static char *make_output_option(struct output_struct *words, short *levels, uchar where)
        !           323: {
        !           324:        char *str = words == info_words ? "--info=" : "--debug=";
        !           325:        int j, counts[MAX_OUT_LEVEL+1], pos, skipped = 0, len = 0, max = 0, lev = 0;
        !           326:        int word_count = words == info_words ? COUNT_INFO : COUNT_DEBUG;
        !           327:        char *buf;
        !           328: 
        !           329:        memset(counts, 0, sizeof counts);
        !           330: 
        !           331:        for (j = 0; words[j].name; j++) {
        !           332:                if (words[j].flag != j) {
        !           333:                        rprintf(FERROR, "rsync: internal error on %s%s: %d != %d\n",
        !           334:                                words == info_words ? "INFO_" : "DEBUG_",
        !           335:                                words[j].name, words[j].flag, j);
        !           336:                        exit_cleanup(RERR_UNSUPPORTED);
        !           337:                }
        !           338:                if (!(words[j].where & where))
        !           339:                        continue;
        !           340:                if (words[j].priority == DEFAULT_PRIORITY) {
        !           341:                        /* Implied items don't need to be mentioned. */
        !           342:                        skipped++;
        !           343:                        continue;
        !           344:                }
        !           345:                len += len ? 1 : strlen(str);
        !           346:                len += strlen(words[j].name);
        !           347:                len += levels[j] == 1 ? 0 : 1;
        !           348: 
        !           349:                if (words[j].priority == HELP_PRIORITY)
        !           350:                        continue; /* no abbreviating for help */
        !           351: 
        !           352:                assert(levels[j] <= MAX_OUT_LEVEL);
        !           353:                if (++counts[levels[j]] > max) {
        !           354:                        /* Determine which level has the most items. */
        !           355:                        lev = levels[j];
        !           356:                        max = counts[lev];
        !           357:                }
        !           358:        }
        !           359: 
        !           360:        /* Sanity check the COUNT_* define against the length of the table. */
        !           361:        if (j != word_count) {
        !           362:                rprintf(FERROR, "rsync: internal error: %s is wrong! (%d != %d)\n",
        !           363:                        words == info_words ? "COUNT_INFO" : "COUNT_DEBUG",
        !           364:                        j, word_count);
        !           365:                exit_cleanup(RERR_UNSUPPORTED);
        !           366:        }
        !           367: 
        !           368:        if (!len)
        !           369:                return NULL;
        !           370: 
        !           371:        len++;
        !           372:        if (!(buf = new_array(char, len)))
        !           373:                out_of_memory("make_output_option");
        !           374:        pos = 0;
        !           375: 
        !           376:        if (skipped || max < 5)
        !           377:                lev = -1;
        !           378:        else {
        !           379:                if (lev == 0)
        !           380:                        pos += snprintf(buf, len, "%sNONE", str);
        !           381:                else if (lev == 1)
        !           382:                        pos += snprintf(buf, len, "%sALL", str);
        !           383:                else
        !           384:                        pos += snprintf(buf, len, "%sALL%d", str, lev);
        !           385:        }
        !           386: 
        !           387:        for (j = 0; words[j].name && pos < len; j++) {
        !           388:                if (words[j].priority == DEFAULT_PRIORITY || levels[j] == lev || !(words[j].where & where))
        !           389:                        continue;
        !           390:                if (pos)
        !           391:                        buf[pos++] = ',';
        !           392:                else
        !           393:                        pos += strlcpy(buf+pos, str, len-pos);
        !           394:                if (pos < len)
        !           395:                        pos += strlcpy(buf+pos, words[j].name, len-pos);
        !           396:                /* Level 1 is implied by the name alone. */
        !           397:                if (levels[j] != 1 && pos < len)
        !           398:                        buf[pos++] = '0' + levels[j];
        !           399:        }
        !           400: 
        !           401:        buf[pos] = '\0';
        !           402: 
        !           403:        return buf;
        !           404: }
        !           405: 
        !           406: static void parse_output_words(struct output_struct *words, short *levels,
        !           407:                               const char *str, uchar priority)
        !           408: {
        !           409:        const char *s;
        !           410:        int j, len, lev;
        !           411: 
        !           412:        if (!str)
        !           413:                return;
        !           414: 
        !           415:        while (*str) {
        !           416:                if ((s = strchr(str, ',')) != NULL)
        !           417:                        len = s++ - str;
        !           418:                else
        !           419:                        len = strlen(str);
        !           420:                while (len && isDigit(str+len-1))
        !           421:                        len--;
        !           422:                lev = isDigit(str+len) ? atoi(str+len) : 1;
        !           423:                if (lev > MAX_OUT_LEVEL)
        !           424:                        lev = MAX_OUT_LEVEL;
        !           425:                if (len == 4 && strncasecmp(str, "help", 4) == 0) {
        !           426:                        output_item_help(words);
        !           427:                        exit_cleanup(0);
        !           428:                }
        !           429:                if (len == 4 && strncasecmp(str, "none", 4) == 0)
        !           430:                        len = lev = 0;
        !           431:                else if (len == 3 && strncasecmp(str, "all", 3) == 0)
        !           432:                        len = 0;
        !           433:                for (j = 0; words[j].name; j++) {
        !           434:                        if (!len
        !           435:                         || (len == words[j].namelen && strncasecmp(str, words[j].name, len) == 0)) {
        !           436:                                if (priority >= words[j].priority) {
        !           437:                                        words[j].priority = priority;
        !           438:                                        levels[j] = lev;
        !           439:                                }
        !           440:                                if (len)
        !           441:                                        break;
        !           442:                        }
        !           443:                }
        !           444:                if (len && !words[j].name) {
        !           445:                        rprintf(FERROR, "Unknown %s item: \"%.*s\"\n",
        !           446:                                words[j].help, len, str);
        !           447:                        exit_cleanup(RERR_SYNTAX);
        !           448:                }
        !           449:                if (!s)
        !           450:                        break;
        !           451:                str = s;
        !           452:        }
        !           453: }
        !           454: 
        !           455: /* Tell the user what all the info or debug flags mean. */
        !           456: static void output_item_help(struct output_struct *words)
        !           457: {
        !           458:        short *levels = words == info_words ? info_levels : debug_levels;
        !           459:        const char **verbosity = words == info_words ? info_verbosity : debug_verbosity;
        !           460:        char buf[128], *opt, *fmt = "%-10s %s\n";
        !           461:        int j;
        !           462: 
        !           463:        reset_output_levels();
        !           464: 
        !           465:        rprintf(FINFO, "Use OPT or OPT1 for level 1 output, OPT2 for level 2, etc.; OPT0 silences.\n");
        !           466:        rprintf(FINFO, "\n");
        !           467:        for (j = 0; words[j].name; j++)
        !           468:                rprintf(FINFO, fmt, words[j].name, words[j].help);
        !           469:        rprintf(FINFO, "\n");
        !           470: 
        !           471:        snprintf(buf, sizeof buf, "Set all %s options (e.g. all%d)",
        !           472:                 words[j].help, MAX_OUT_LEVEL);
        !           473:        rprintf(FINFO, fmt, "ALL", buf);
        !           474: 
        !           475:        snprintf(buf, sizeof buf, "Silence all %s options (same as all0)",
        !           476:                 words[j].help);
        !           477:        rprintf(FINFO, fmt, "NONE", buf);
        !           478: 
        !           479:        rprintf(FINFO, fmt, "HELP", "Output this help message");
        !           480:        rprintf(FINFO, "\n");
        !           481:        rprintf(FINFO, "Options added for each increase in verbose level:\n");
        !           482: 
        !           483:        for (j = 1; j <= MAX_VERBOSITY; j++) {
        !           484:                parse_output_words(words, levels, verbosity[j], HELP_PRIORITY);
        !           485:                opt = make_output_option(words, levels, W_CLI|W_SRV|W_SND|W_REC);
        !           486:                if (opt) {
        !           487:                        rprintf(FINFO, "%d) %s\n", j, strchr(opt, '=')+1);
        !           488:                        free(opt);
        !           489:                }
        !           490:                reset_output_levels();
        !           491:        }
        !           492: }
        !           493: 
        !           494: /* The --verbose option now sets info+debug flags. */
        !           495: static void set_output_verbosity(int level, uchar priority)
        !           496: {
        !           497:        int j;
        !           498: 
        !           499:        if (level > MAX_VERBOSITY)
        !           500:                level = MAX_VERBOSITY;
        !           501: 
        !           502:        for (j = 1; j <= level; j++) {
        !           503:                parse_output_words(info_words, info_levels, info_verbosity[j], priority);
        !           504:                parse_output_words(debug_words, debug_levels, debug_verbosity[j], priority);
        !           505:        }
        !           506: }
        !           507: 
        !           508: /* Limit the info+debug flag levels given a verbose-option level limit. */
        !           509: void limit_output_verbosity(int level)
        !           510: {
        !           511:        short info_limits[COUNT_INFO], debug_limits[COUNT_DEBUG];
        !           512:        int j;
        !           513: 
        !           514:        if (level > MAX_VERBOSITY)
        !           515:                return;
        !           516: 
        !           517:        memset(info_limits, 0, sizeof info_limits);
        !           518:        memset(debug_limits, 0, sizeof debug_limits);
        !           519: 
        !           520:        /* Compute the level limits in the above arrays. */
        !           521:        for (j = 1; j <= level; j++) {
        !           522:                parse_output_words(info_words, info_limits, info_verbosity[j], LIMIT_PRIORITY);
        !           523:                parse_output_words(debug_words, debug_limits, debug_verbosity[j], LIMIT_PRIORITY);
        !           524:        }
        !           525: 
        !           526:        for (j = 0; j < COUNT_INFO; j++) {
        !           527:                if (info_levels[j] > info_limits[j])
        !           528:                        info_levels[j] = info_limits[j];
        !           529:        }
        !           530: 
        !           531:        for (j = 0; j < COUNT_DEBUG; j++) {
        !           532:                if (debug_levels[j] > debug_limits[j])
        !           533:                        debug_levels[j] = debug_limits[j];
        !           534:        }
        !           535: }
        !           536: 
        !           537: void reset_output_levels(void)
        !           538: {
        !           539:        int j;
        !           540: 
        !           541:        memset(info_levels, 0, sizeof info_levels);
        !           542:        memset(debug_levels, 0, sizeof debug_levels);
        !           543: 
        !           544:        for (j = 0; j < COUNT_INFO; j++)
        !           545:                info_words[j].priority = DEFAULT_PRIORITY;
        !           546: 
        !           547:        for (j = 0; j < COUNT_DEBUG; j++)
        !           548:                debug_words[j].priority = DEFAULT_PRIORITY;
        !           549: }
        !           550: 
        !           551: void negate_output_levels(void)
        !           552: {
        !           553:        int j;
        !           554: 
        !           555:        for (j = 0; j < COUNT_INFO; j++)
        !           556:                info_levels[j] *= -1;
        !           557: 
        !           558:        for (j = 0; j < COUNT_DEBUG; j++)
        !           559:                debug_levels[j] *= -1;
        !           560: }
1.1       misho     561: 
                    562: static void print_rsync_version(enum logcode f)
                    563: {
                    564:        char *subprotocol = "";
                    565:        char const *got_socketpair = "no ";
                    566:        char const *have_inplace = "no ";
                    567:        char const *hardlinks = "no ";
1.1.1.2 ! misho     568:        char const *prealloc = "no ";
1.1       misho     569:        char const *symtimes = "no ";
                    570:        char const *acls = "no ";
                    571:        char const *xattrs = "no ";
                    572:        char const *links = "no ";
                    573:        char const *iconv = "no ";
                    574:        char const *ipv6 = "no ";
                    575:        STRUCT_STAT *dumstat;
                    576: 
                    577: #if SUBPROTOCOL_VERSION != 0
                    578:        if (asprintf(&subprotocol, ".PR%d", SUBPROTOCOL_VERSION) < 0)
                    579:                out_of_memory("print_rsync_version");
                    580: #endif
                    581: #ifdef HAVE_SOCKETPAIR
                    582:        got_socketpair = "";
                    583: #endif
                    584: #ifdef HAVE_FTRUNCATE
                    585:        have_inplace = "";
                    586: #endif
                    587: #ifdef SUPPORT_HARD_LINKS
                    588:        hardlinks = "";
                    589: #endif
1.1.1.2 ! misho     590: #ifdef SUPPORT_PREALLOCATION
        !           591:        prealloc = "";
        !           592: #endif
1.1       misho     593: #ifdef SUPPORT_ACLS
                    594:        acls = "";
                    595: #endif
                    596: #ifdef SUPPORT_XATTRS
                    597:        xattrs = "";
                    598: #endif
                    599: #ifdef SUPPORT_LINKS
                    600:        links = "";
                    601: #endif
                    602: #ifdef INET6
                    603:        ipv6 = "";
                    604: #endif
                    605: #ifdef ICONV_OPTION
                    606:        iconv = "";
                    607: #endif
                    608: #ifdef CAN_SET_SYMLINK_TIMES
                    609:        symtimes = "";
                    610: #endif
                    611: 
                    612:        rprintf(f, "%s  version %s  protocol version %d%s\n",
                    613:                RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION, subprotocol);
1.1.1.2 ! misho     614:        rprintf(f, "Copyright (C) 1996-2013 by Andrew Tridgell, Wayne Davison, and others.\n");
1.1       misho     615:        rprintf(f, "Web site: http://rsync.samba.org/\n");
                    616:        rprintf(f, "Capabilities:\n");
                    617:        rprintf(f, "    %d-bit files, %d-bit inums, %d-bit timestamps, %d-bit long ints,\n",
                    618:                (int)(sizeof (OFF_T) * 8),
                    619:                (int)(sizeof dumstat->st_ino * 8), /* Don't check ino_t! */
                    620:                (int)(sizeof (time_t) * 8),
                    621:                (int)(sizeof (int64) * 8));
                    622:        rprintf(f, "    %ssocketpairs, %shardlinks, %ssymlinks, %sIPv6, batchfiles, %sinplace,\n",
                    623:                got_socketpair, hardlinks, links, ipv6, have_inplace);
1.1.1.2 ! misho     624:        rprintf(f, "    %sappend, %sACLs, %sxattrs, %siconv, %ssymtimes, %sprealloc\n",
        !           625:                have_inplace, acls, xattrs, iconv, symtimes, prealloc);
1.1       misho     626: 
                    627: #ifdef MAINTAINER_MODE
                    628:        rprintf(f, "Panic Action: \"%s\"\n", get_panic_action());
                    629: #endif
                    630: 
                    631: #if SIZEOF_INT64 < 8
                    632:        rprintf(f, "WARNING: no 64-bit integers on this platform!\n");
                    633: #endif
                    634:        if (sizeof (int64) != SIZEOF_INT64) {
                    635:                rprintf(f,
                    636:                        "WARNING: size mismatch in SIZEOF_INT64 define (%d != %d)\n",
                    637:                        (int) SIZEOF_INT64, (int) sizeof (int64));
                    638:        }
                    639: 
                    640:        rprintf(f,"\n");
                    641:        rprintf(f,"rsync comes with ABSOLUTELY NO WARRANTY.  This is free software, and you\n");
                    642:        rprintf(f,"are welcome to redistribute it under certain conditions.  See the GNU\n");
                    643:        rprintf(f,"General Public Licence for details.\n");
                    644: }
                    645: 
                    646: 
                    647: void usage(enum logcode F)
                    648: {
                    649:   print_rsync_version(F);
                    650: 
                    651:   rprintf(F,"\n");
                    652:   rprintf(F,"rsync is a file transfer program capable of efficient remote update\n");
                    653:   rprintf(F,"via a fast differencing algorithm.\n");
                    654: 
                    655:   rprintf(F,"\n");
                    656:   rprintf(F,"Usage: rsync [OPTION]... SRC [SRC]... DEST\n");
                    657:   rprintf(F,"  or   rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST\n");
                    658:   rprintf(F,"  or   rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST\n");
                    659:   rprintf(F,"  or   rsync [OPTION]... SRC [SRC]... rsync://[USER@]HOST[:PORT]/DEST\n");
                    660:   rprintf(F,"  or   rsync [OPTION]... [USER@]HOST:SRC [DEST]\n");
                    661:   rprintf(F,"  or   rsync [OPTION]... [USER@]HOST::SRC [DEST]\n");
                    662:   rprintf(F,"  or   rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC [DEST]\n");
                    663:   rprintf(F,"The ':' usages connect via remote shell, while '::' & 'rsync://' usages connect\n");
                    664:   rprintf(F,"to an rsync daemon, and require SRC or DEST to start with a module name.\n");
                    665:   rprintf(F,"\n");
                    666:   rprintf(F,"Options\n");
                    667:   rprintf(F," -v, --verbose               increase verbosity\n");
1.1.1.2 ! misho     668:   rprintf(F,"     --info=FLAGS            fine-grained informational verbosity\n");
        !           669:   rprintf(F,"     --debug=FLAGS           fine-grained debug verbosity\n");
        !           670:   rprintf(F,"     --msgs2stderr           special output handling for debugging\n");
1.1       misho     671:   rprintf(F," -q, --quiet                 suppress non-error messages\n");
                    672:   rprintf(F,"     --no-motd               suppress daemon-mode MOTD (see manpage caveat)\n");
                    673:   rprintf(F," -c, --checksum              skip based on checksum, not mod-time & size\n");
                    674:   rprintf(F," -a, --archive               archive mode; equals -rlptgoD (no -H,-A,-X)\n");
                    675:   rprintf(F,"     --no-OPTION             turn off an implied OPTION (e.g. --no-D)\n");
                    676:   rprintf(F," -r, --recursive             recurse into directories\n");
                    677:   rprintf(F," -R, --relative              use relative path names\n");
                    678:   rprintf(F,"     --no-implied-dirs       don't send implied dirs with --relative\n");
                    679:   rprintf(F," -b, --backup                make backups (see --suffix & --backup-dir)\n");
                    680:   rprintf(F,"     --backup-dir=DIR        make backups into hierarchy based in DIR\n");
                    681:   rprintf(F,"     --suffix=SUFFIX         set backup suffix (default %s w/o --backup-dir)\n",BACKUP_SUFFIX);
                    682:   rprintf(F," -u, --update                skip files that are newer on the receiver\n");
                    683:   rprintf(F,"     --inplace               update destination files in-place (SEE MAN PAGE)\n");
                    684:   rprintf(F,"     --append                append data onto shorter files\n");
                    685:   rprintf(F,"     --append-verify         like --append, but with old data in file checksum\n");
                    686:   rprintf(F," -d, --dirs                  transfer directories without recursing\n");
                    687:   rprintf(F," -l, --links                 copy symlinks as symlinks\n");
                    688:   rprintf(F," -L, --copy-links            transform symlink into referent file/dir\n");
                    689:   rprintf(F,"     --copy-unsafe-links     only \"unsafe\" symlinks are transformed\n");
                    690:   rprintf(F,"     --safe-links            ignore symlinks that point outside the source tree\n");
1.1.1.2 ! misho     691:   rprintf(F,"     --munge-links           munge symlinks to make them safer (but unusable)\n");
1.1       misho     692:   rprintf(F," -k, --copy-dirlinks         transform symlink to a dir into referent dir\n");
                    693:   rprintf(F," -K, --keep-dirlinks         treat symlinked dir on receiver as dir\n");
                    694:   rprintf(F," -H, --hard-links            preserve hard links\n");
                    695:   rprintf(F," -p, --perms                 preserve permissions\n");
                    696:   rprintf(F," -E, --executability         preserve the file's executability\n");
                    697:   rprintf(F,"     --chmod=CHMOD           affect file and/or directory permissions\n");
                    698: #ifdef SUPPORT_ACLS
                    699:   rprintf(F," -A, --acls                  preserve ACLs (implies --perms)\n");
                    700: #endif
                    701: #ifdef SUPPORT_XATTRS
                    702:   rprintf(F," -X, --xattrs                preserve extended attributes\n");
                    703: #endif
                    704:   rprintf(F," -o, --owner                 preserve owner (super-user only)\n");
                    705:   rprintf(F," -g, --group                 preserve group\n");
                    706:   rprintf(F,"     --devices               preserve device files (super-user only)\n");
                    707:   rprintf(F,"     --specials              preserve special files\n");
                    708:   rprintf(F," -D                          same as --devices --specials\n");
                    709:   rprintf(F," -t, --times                 preserve modification times\n");
                    710:   rprintf(F," -O, --omit-dir-times        omit directories from --times\n");
1.1.1.2 ! misho     711:   rprintf(F," -J, --omit-link-times       omit symlinks from --times\n");
1.1       misho     712:   rprintf(F,"     --super                 receiver attempts super-user activities\n");
                    713: #ifdef SUPPORT_XATTRS
                    714:   rprintf(F,"     --fake-super            store/recover privileged attrs using xattrs\n");
                    715: #endif
                    716:   rprintf(F," -S, --sparse                handle sparse files efficiently\n");
1.1.1.2 ! misho     717: #ifdef SUPPORT_PREALLOCATION
        !           718:   rprintf(F,"     --preallocate           allocate dest files before writing them\n");
        !           719: #else
        !           720:   rprintf(F,"     --preallocate           pre-allocate dest files on remote receiver\n");
        !           721: #endif
1.1       misho     722:   rprintf(F," -n, --dry-run               perform a trial run with no changes made\n");
                    723:   rprintf(F," -W, --whole-file            copy files whole (without delta-xfer algorithm)\n");
                    724:   rprintf(F," -x, --one-file-system       don't cross filesystem boundaries\n");
                    725:   rprintf(F," -B, --block-size=SIZE       force a fixed checksum block-size\n");
                    726:   rprintf(F," -e, --rsh=COMMAND           specify the remote shell to use\n");
                    727:   rprintf(F,"     --rsync-path=PROGRAM    specify the rsync to run on the remote machine\n");
                    728:   rprintf(F,"     --existing              skip creating new files on receiver\n");
                    729:   rprintf(F,"     --ignore-existing       skip updating files that already exist on receiver\n");
                    730:   rprintf(F,"     --remove-source-files   sender removes synchronized files (non-dirs)\n");
                    731:   rprintf(F,"     --del                   an alias for --delete-during\n");
                    732:   rprintf(F,"     --delete                delete extraneous files from destination dirs\n");
                    733:   rprintf(F,"     --delete-before         receiver deletes before transfer, not during\n");
                    734:   rprintf(F,"     --delete-during         receiver deletes during the transfer\n");
                    735:   rprintf(F,"     --delete-delay          find deletions during, delete after\n");
                    736:   rprintf(F,"     --delete-after          receiver deletes after transfer, not during\n");
                    737:   rprintf(F,"     --delete-excluded       also delete excluded files from destination dirs\n");
1.1.1.2 ! misho     738:   rprintf(F,"     --ignore-missing-args   ignore missing source args without error\n");
        !           739:   rprintf(F,"     --delete-missing-args   delete missing source args from destination\n");
1.1       misho     740:   rprintf(F,"     --ignore-errors         delete even if there are I/O errors\n");
                    741:   rprintf(F,"     --force                 force deletion of directories even if not empty\n");
                    742:   rprintf(F,"     --max-delete=NUM        don't delete more than NUM files\n");
                    743:   rprintf(F,"     --max-size=SIZE         don't transfer any file larger than SIZE\n");
                    744:   rprintf(F,"     --min-size=SIZE         don't transfer any file smaller than SIZE\n");
                    745:   rprintf(F,"     --partial               keep partially transferred files\n");
                    746:   rprintf(F,"     --partial-dir=DIR       put a partially transferred file into DIR\n");
                    747:   rprintf(F,"     --delay-updates         put all updated files into place at transfer's end\n");
                    748:   rprintf(F," -m, --prune-empty-dirs      prune empty directory chains from the file-list\n");
                    749:   rprintf(F,"     --numeric-ids           don't map uid/gid values by user/group name\n");
1.1.1.2 ! misho     750:   rprintf(F,"     --usermap=STRING        custom username mapping\n");
        !           751:   rprintf(F,"     --groupmap=STRING       custom groupname mapping\n");
        !           752:   rprintf(F,"     --chown=USER:GROUP      simple username/groupname mapping\n");
1.1       misho     753:   rprintf(F,"     --timeout=SECONDS       set I/O timeout in seconds\n");
                    754:   rprintf(F,"     --contimeout=SECONDS    set daemon connection timeout in seconds\n");
                    755:   rprintf(F," -I, --ignore-times          don't skip files that match in size and mod-time\n");
1.1.1.2 ! misho     756:   rprintf(F," -M, --remote-option=OPTION  send OPTION to the remote side only\n");
1.1       misho     757:   rprintf(F,"     --size-only             skip files that match in size\n");
                    758:   rprintf(F,"     --modify-window=NUM     compare mod-times with reduced accuracy\n");
                    759:   rprintf(F," -T, --temp-dir=DIR          create temporary files in directory DIR\n");
                    760:   rprintf(F," -y, --fuzzy                 find similar file for basis if no dest file\n");
                    761:   rprintf(F,"     --compare-dest=DIR      also compare destination files relative to DIR\n");
                    762:   rprintf(F,"     --copy-dest=DIR         ... and include copies of unchanged files\n");
                    763:   rprintf(F,"     --link-dest=DIR         hardlink to files in DIR when unchanged\n");
                    764:   rprintf(F," -z, --compress              compress file data during the transfer\n");
                    765:   rprintf(F,"     --compress-level=NUM    explicitly set compression level\n");
                    766:   rprintf(F,"     --skip-compress=LIST    skip compressing files with a suffix in LIST\n");
                    767:   rprintf(F," -C, --cvs-exclude           auto-ignore files the same way CVS does\n");
                    768:   rprintf(F," -f, --filter=RULE           add a file-filtering RULE\n");
                    769:   rprintf(F," -F                          same as --filter='dir-merge /.rsync-filter'\n");
                    770:   rprintf(F,"                             repeated: --filter='- .rsync-filter'\n");
                    771:   rprintf(F,"     --exclude=PATTERN       exclude files matching PATTERN\n");
                    772:   rprintf(F,"     --exclude-from=FILE     read exclude patterns from FILE\n");
                    773:   rprintf(F,"     --include=PATTERN       don't exclude files matching PATTERN\n");
                    774:   rprintf(F,"     --include-from=FILE     read include patterns from FILE\n");
                    775:   rprintf(F,"     --files-from=FILE       read list of source-file names from FILE\n");
                    776:   rprintf(F," -0, --from0                 all *-from/filter files are delimited by 0s\n");
                    777:   rprintf(F," -s, --protect-args          no space-splitting; only wildcard special-chars\n");
                    778:   rprintf(F,"     --address=ADDRESS       bind address for outgoing socket to daemon\n");
                    779:   rprintf(F,"     --port=PORT             specify double-colon alternate port number\n");
                    780:   rprintf(F,"     --sockopts=OPTIONS      specify custom TCP options\n");
                    781:   rprintf(F,"     --blocking-io           use blocking I/O for the remote shell\n");
                    782:   rprintf(F,"     --stats                 give some file-transfer stats\n");
                    783:   rprintf(F," -8, --8-bit-output          leave high-bit chars unescaped in output\n");
                    784:   rprintf(F," -h, --human-readable        output numbers in a human-readable format\n");
                    785:   rprintf(F,"     --progress              show progress during transfer\n");
                    786:   rprintf(F," -P                          same as --partial --progress\n");
                    787:   rprintf(F," -i, --itemize-changes       output a change-summary for all updates\n");
                    788:   rprintf(F,"     --out-format=FORMAT     output updates using the specified FORMAT\n");
                    789:   rprintf(F,"     --log-file=FILE         log what we're doing to the specified FILE\n");
                    790:   rprintf(F,"     --log-file-format=FMT   log updates using the specified FMT\n");
                    791:   rprintf(F,"     --password-file=FILE    read daemon-access password from FILE\n");
                    792:   rprintf(F,"     --list-only             list the files instead of copying them\n");
1.1.1.2 ! misho     793:   rprintf(F,"     --bwlimit=RATE          limit socket I/O bandwidth\n");
        !           794: #ifdef HAVE_SETVBUF
        !           795:   rprintf(F,"     --outbuf=N|L|B          set output buffering to None, Line, or Block\n");
        !           796: #endif
1.1       misho     797:   rprintf(F,"     --write-batch=FILE      write a batched update to FILE\n");
                    798:   rprintf(F,"     --only-write-batch=FILE like --write-batch but w/o updating destination\n");
                    799:   rprintf(F,"     --read-batch=FILE       read a batched update from FILE\n");
                    800:   rprintf(F,"     --protocol=NUM          force an older protocol version to be used\n");
                    801: #ifdef ICONV_OPTION
                    802:   rprintf(F,"     --iconv=CONVERT_SPEC    request charset conversion of filenames\n");
                    803: #endif
1.1.1.2 ! misho     804:   rprintf(F,"     --checksum-seed=NUM     set block/file checksum seed (advanced)\n");
1.1       misho     805:   rprintf(F," -4, --ipv4                  prefer IPv4\n");
                    806:   rprintf(F," -6, --ipv6                  prefer IPv6\n");
                    807:   rprintf(F,"     --version               print version number\n");
                    808:   rprintf(F,"(-h) --help                  show this help (-h is --help only if used alone)\n");
                    809: 
                    810:   rprintf(F,"\n");
                    811:   rprintf(F,"Use \"rsync --daemon --help\" to see the daemon-mode command-line options.\n");
                    812:   rprintf(F,"Please see the rsync(1) and rsyncd.conf(5) man pages for full documentation.\n");
                    813:   rprintf(F,"See http://rsync.samba.org/ for updates, bug reports, and answers\n");
                    814: }
                    815: 
                    816: enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
                    817:       OPT_FILTER, OPT_COMPARE_DEST, OPT_COPY_DEST, OPT_LINK_DEST, OPT_HELP,
                    818:       OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW, OPT_MIN_SIZE, OPT_CHMOD,
                    819:       OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_ONLY_WRITE_BATCH, OPT_MAX_SIZE,
1.1.1.2 ! misho     820:       OPT_NO_D, OPT_APPEND, OPT_NO_ICONV, OPT_INFO, OPT_DEBUG,
        !           821:       OPT_USERMAP, OPT_GROUPMAP, OPT_CHOWN, OPT_BWLIMIT,
1.1       misho     822:       OPT_SERVER, OPT_REFUSED_BASE = 9000};
                    823: 
                    824: static struct poptOption long_options[] = {
                    825:   /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
                    826:   {"help",             0,  POPT_ARG_NONE,   0, OPT_HELP, 0, 0 },
                    827:   {"version",          0,  POPT_ARG_NONE,   0, OPT_VERSION, 0, 0},
                    828:   {"verbose",         'v', POPT_ARG_NONE,   0, 'v', 0, 0 },
                    829:   {"no-verbose",       0,  POPT_ARG_VAL,    &verbose, 0, 0, 0 },
                    830:   {"no-v",             0,  POPT_ARG_VAL,    &verbose, 0, 0, 0 },
1.1.1.2 ! misho     831:   {"info",             0,  POPT_ARG_STRING, 0, OPT_INFO, 0, 0 },
        !           832:   {"debug",            0,  POPT_ARG_STRING, 0, OPT_DEBUG, 0, 0 },
        !           833:   {"msgs2stderr",      0,  POPT_ARG_NONE,   &msgs2stderr, 0, 0, 0 },
1.1       misho     834:   {"quiet",           'q', POPT_ARG_NONE,   0, 'q', 0, 0 },
                    835:   {"motd",             0,  POPT_ARG_VAL,    &output_motd, 1, 0, 0 },
                    836:   {"no-motd",          0,  POPT_ARG_VAL,    &output_motd, 0, 0, 0 },
                    837:   {"stats",            0,  POPT_ARG_NONE,   &do_stats, 0, 0, 0 },
                    838:   {"human-readable",  'h', POPT_ARG_NONE,   0, 'h', 0, 0},
                    839:   {"no-human-readable",0,  POPT_ARG_VAL,    &human_readable, 0, 0, 0},
                    840:   {"no-h",             0,  POPT_ARG_VAL,    &human_readable, 0, 0, 0},
                    841:   {"dry-run",         'n', POPT_ARG_NONE,   &dry_run, 0, 0, 0 },
                    842:   {"archive",         'a', POPT_ARG_NONE,   0, 'a', 0, 0 },
                    843:   {"recursive",       'r', POPT_ARG_VAL,    &recurse, 2, 0, 0 },
                    844:   {"no-recursive",     0,  POPT_ARG_VAL,    &recurse, 0, 0, 0 },
                    845:   {"no-r",             0,  POPT_ARG_VAL,    &recurse, 0, 0, 0 },
                    846:   {"inc-recursive",    0,  POPT_ARG_VAL,    &allow_inc_recurse, 1, 0, 0 },
                    847:   {"no-inc-recursive", 0,  POPT_ARG_VAL,    &allow_inc_recurse, 0, 0, 0 },
                    848:   {"i-r",              0,  POPT_ARG_VAL,    &allow_inc_recurse, 1, 0, 0 },
                    849:   {"no-i-r",           0,  POPT_ARG_VAL,    &allow_inc_recurse, 0, 0, 0 },
                    850:   {"dirs",            'd', POPT_ARG_VAL,    &xfer_dirs, 2, 0, 0 },
                    851:   {"no-dirs",          0,  POPT_ARG_VAL,    &xfer_dirs, 0, 0, 0 },
                    852:   {"no-d",             0,  POPT_ARG_VAL,    &xfer_dirs, 0, 0, 0 },
                    853:   {"old-dirs",         0,  POPT_ARG_VAL,    &xfer_dirs, 4, 0, 0 },
                    854:   {"old-d",            0,  POPT_ARG_VAL,    &xfer_dirs, 4, 0, 0 },
                    855:   {"perms",           'p', POPT_ARG_VAL,    &preserve_perms, 1, 0, 0 },
                    856:   {"no-perms",         0,  POPT_ARG_VAL,    &preserve_perms, 0, 0, 0 },
                    857:   {"no-p",             0,  POPT_ARG_VAL,    &preserve_perms, 0, 0, 0 },
                    858:   {"executability",   'E', POPT_ARG_NONE,   &preserve_executability, 0, 0, 0 },
                    859:   {"acls",            'A', POPT_ARG_NONE,   0, 'A', 0, 0 },
                    860:   {"no-acls",          0,  POPT_ARG_VAL,    &preserve_acls, 0, 0, 0 },
                    861:   {"no-A",             0,  POPT_ARG_VAL,    &preserve_acls, 0, 0, 0 },
                    862:   {"xattrs",          'X', POPT_ARG_NONE,   0, 'X', 0, 0 },
                    863:   {"no-xattrs",        0,  POPT_ARG_VAL,    &preserve_xattrs, 0, 0, 0 },
                    864:   {"no-X",             0,  POPT_ARG_VAL,    &preserve_xattrs, 0, 0, 0 },
                    865:   {"times",           't', POPT_ARG_VAL,    &preserve_times, 1, 0, 0 },
                    866:   {"no-times",         0,  POPT_ARG_VAL,    &preserve_times, 0, 0, 0 },
                    867:   {"no-t",             0,  POPT_ARG_VAL,    &preserve_times, 0, 0, 0 },
                    868:   {"omit-dir-times",  'O', POPT_ARG_VAL,    &omit_dir_times, 1, 0, 0 },
                    869:   {"no-omit-dir-times",0,  POPT_ARG_VAL,    &omit_dir_times, 0, 0, 0 },
                    870:   {"no-O",             0,  POPT_ARG_VAL,    &omit_dir_times, 0, 0, 0 },
1.1.1.2 ! misho     871:   {"omit-link-times", 'J', POPT_ARG_VAL,    &omit_link_times, 1, 0, 0 },
        !           872:   {"no-omit-link-times",0, POPT_ARG_VAL,    &omit_link_times, 0, 0, 0 },
        !           873:   {"no-J",             0,  POPT_ARG_VAL,    &omit_link_times, 0, 0, 0 },
1.1       misho     874:   {"modify-window",    0,  POPT_ARG_INT,    &modify_window, OPT_MODIFY_WINDOW, 0, 0 },
                    875:   {"super",            0,  POPT_ARG_VAL,    &am_root, 2, 0, 0 },
                    876:   {"no-super",         0,  POPT_ARG_VAL,    &am_root, 0, 0, 0 },
                    877:   {"fake-super",       0,  POPT_ARG_VAL,    &am_root, -1, 0, 0 },
                    878:   {"owner",           'o', POPT_ARG_VAL,    &preserve_uid, 1, 0, 0 },
                    879:   {"no-owner",         0,  POPT_ARG_VAL,    &preserve_uid, 0, 0, 0 },
                    880:   {"no-o",             0,  POPT_ARG_VAL,    &preserve_uid, 0, 0, 0 },
                    881:   {"group",           'g', POPT_ARG_VAL,    &preserve_gid, 1, 0, 0 },
                    882:   {"no-group",         0,  POPT_ARG_VAL,    &preserve_gid, 0, 0, 0 },
                    883:   {"no-g",             0,  POPT_ARG_VAL,    &preserve_gid, 0, 0, 0 },
                    884:   {0,                 'D', POPT_ARG_NONE,   0, 'D', 0, 0 },
                    885:   {"no-D",             0,  POPT_ARG_NONE,   0, OPT_NO_D, 0, 0 },
                    886:   {"devices",          0,  POPT_ARG_VAL,    &preserve_devices, 1, 0, 0 },
                    887:   {"no-devices",       0,  POPT_ARG_VAL,    &preserve_devices, 0, 0, 0 },
                    888:   {"specials",         0,  POPT_ARG_VAL,    &preserve_specials, 1, 0, 0 },
                    889:   {"no-specials",      0,  POPT_ARG_VAL,    &preserve_specials, 0, 0, 0 },
                    890:   {"links",           'l', POPT_ARG_VAL,    &preserve_links, 1, 0, 0 },
                    891:   {"no-links",         0,  POPT_ARG_VAL,    &preserve_links, 0, 0, 0 },
                    892:   {"no-l",             0,  POPT_ARG_VAL,    &preserve_links, 0, 0, 0 },
                    893:   {"copy-links",      'L', POPT_ARG_NONE,   &copy_links, 0, 0, 0 },
                    894:   {"copy-unsafe-links",0,  POPT_ARG_NONE,   &copy_unsafe_links, 0, 0, 0 },
                    895:   {"safe-links",       0,  POPT_ARG_NONE,   &safe_symlinks, 0, 0, 0 },
1.1.1.2 ! misho     896:   {"munge-links",      0,  POPT_ARG_VAL,    &munge_symlinks, 1, 0, 0 },
        !           897:   {"no-munge-links",   0,  POPT_ARG_VAL,    &munge_symlinks, 0, 0, 0 },
1.1       misho     898:   {"copy-dirlinks",   'k', POPT_ARG_NONE,   &copy_dirlinks, 0, 0, 0 },
                    899:   {"keep-dirlinks",   'K', POPT_ARG_NONE,   &keep_dirlinks, 0, 0, 0 },
                    900:   {"hard-links",      'H', POPT_ARG_NONE,   0, 'H', 0, 0 },
                    901:   {"no-hard-links",    0,  POPT_ARG_VAL,    &preserve_hard_links, 0, 0, 0 },
                    902:   {"no-H",             0,  POPT_ARG_VAL,    &preserve_hard_links, 0, 0, 0 },
                    903:   {"relative",        'R', POPT_ARG_VAL,    &relative_paths, 1, 0, 0 },
                    904:   {"no-relative",      0,  POPT_ARG_VAL,    &relative_paths, 0, 0, 0 },
                    905:   {"no-R",             0,  POPT_ARG_VAL,    &relative_paths, 0, 0, 0 },
                    906:   {"implied-dirs",     0,  POPT_ARG_VAL,    &implied_dirs, 1, 0, 0 },
                    907:   {"no-implied-dirs",  0,  POPT_ARG_VAL,    &implied_dirs, 0, 0, 0 },
                    908:   {"i-d",              0,  POPT_ARG_VAL,    &implied_dirs, 1, 0, 0 },
                    909:   {"no-i-d",           0,  POPT_ARG_VAL,    &implied_dirs, 0, 0, 0 },
                    910:   {"chmod",            0,  POPT_ARG_STRING, 0, OPT_CHMOD, 0, 0 },
                    911:   {"ignore-times",    'I', POPT_ARG_NONE,   &ignore_times, 0, 0, 0 },
                    912:   {"size-only",        0,  POPT_ARG_NONE,   &size_only, 0, 0, 0 },
                    913:   {"one-file-system", 'x', POPT_ARG_NONE,   0, 'x', 0, 0 },
                    914:   {"no-one-file-system",0, POPT_ARG_VAL,    &one_file_system, 0, 0, 0 },
                    915:   {"no-x",             0,  POPT_ARG_VAL,    &one_file_system, 0, 0, 0 },
                    916:   {"update",          'u', POPT_ARG_NONE,   &update_only, 0, 0, 0 },
                    917:   {"existing",         0,  POPT_ARG_NONE,   &ignore_non_existing, 0, 0, 0 },
                    918:   {"ignore-non-existing",0,POPT_ARG_NONE,   &ignore_non_existing, 0, 0, 0 },
                    919:   {"ignore-existing",  0,  POPT_ARG_NONE,   &ignore_existing, 0, 0, 0 },
                    920:   {"max-size",         0,  POPT_ARG_STRING, &max_size_arg, OPT_MAX_SIZE, 0, 0 },
                    921:   {"min-size",         0,  POPT_ARG_STRING, &min_size_arg, OPT_MIN_SIZE, 0, 0 },
                    922:   {"sparse",          'S', POPT_ARG_VAL,    &sparse_files, 1, 0, 0 },
                    923:   {"no-sparse",        0,  POPT_ARG_VAL,    &sparse_files, 0, 0, 0 },
                    924:   {"no-S",             0,  POPT_ARG_VAL,    &sparse_files, 0, 0, 0 },
1.1.1.2 ! misho     925:   {"preallocate",      0,  POPT_ARG_NONE,   &preallocate_files, 0, 0, 0},
1.1       misho     926:   {"inplace",          0,  POPT_ARG_VAL,    &inplace, 1, 0, 0 },
                    927:   {"no-inplace",       0,  POPT_ARG_VAL,    &inplace, 0, 0, 0 },
                    928:   {"append",           0,  POPT_ARG_NONE,   0, OPT_APPEND, 0, 0 },
                    929:   {"append-verify",    0,  POPT_ARG_VAL,    &append_mode, 2, 0, 0 },
                    930:   {"no-append",        0,  POPT_ARG_VAL,    &append_mode, 0, 0, 0 },
                    931:   {"del",              0,  POPT_ARG_NONE,   &delete_during, 0, 0, 0 },
                    932:   {"delete",           0,  POPT_ARG_NONE,   &delete_mode, 0, 0, 0 },
                    933:   {"delete-before",    0,  POPT_ARG_NONE,   &delete_before, 0, 0, 0 },
                    934:   {"delete-during",    0,  POPT_ARG_VAL,    &delete_during, 1, 0, 0 },
                    935:   {"delete-delay",     0,  POPT_ARG_VAL,    &delete_during, 2, 0, 0 },
                    936:   {"delete-after",     0,  POPT_ARG_NONE,   &delete_after, 0, 0, 0 },
                    937:   {"delete-excluded",  0,  POPT_ARG_NONE,   &delete_excluded, 0, 0, 0 },
1.1.1.2 ! misho     938:   {"delete-missing-args",0,POPT_BIT_SET,    &missing_args, 2, 0, 0 },
        !           939:   {"ignore-missing-args",0,POPT_BIT_SET,    &missing_args, 1, 0, 0 },
1.1       misho     940:   {"remove-sent-files",0,  POPT_ARG_VAL,    &remove_source_files, 2, 0, 0 }, /* deprecated */
                    941:   {"remove-source-files",0,POPT_ARG_VAL,    &remove_source_files, 1, 0, 0 },
                    942:   {"force",            0,  POPT_ARG_VAL,    &force_delete, 1, 0, 0 },
                    943:   {"no-force",         0,  POPT_ARG_VAL,    &force_delete, 0, 0, 0 },
                    944:   {"ignore-errors",    0,  POPT_ARG_VAL,    &ignore_errors, 1, 0, 0 },
                    945:   {"no-ignore-errors", 0,  POPT_ARG_VAL,    &ignore_errors, 0, 0, 0 },
                    946:   {"max-delete",       0,  POPT_ARG_INT,    &max_delete, 0, 0, 0 },
                    947:   {0,                 'F', POPT_ARG_NONE,   0, 'F', 0, 0 },
                    948:   {"filter",          'f', POPT_ARG_STRING, 0, OPT_FILTER, 0, 0 },
                    949:   {"exclude",          0,  POPT_ARG_STRING, 0, OPT_EXCLUDE, 0, 0 },
                    950:   {"include",          0,  POPT_ARG_STRING, 0, OPT_INCLUDE, 0, 0 },
                    951:   {"exclude-from",     0,  POPT_ARG_STRING, 0, OPT_EXCLUDE_FROM, 0, 0 },
                    952:   {"include-from",     0,  POPT_ARG_STRING, 0, OPT_INCLUDE_FROM, 0, 0 },
                    953:   {"cvs-exclude",     'C', POPT_ARG_NONE,   &cvs_exclude, 0, 0, 0 },
                    954:   {"whole-file",      'W', POPT_ARG_VAL,    &whole_file, 1, 0, 0 },
                    955:   {"no-whole-file",    0,  POPT_ARG_VAL,    &whole_file, 0, 0, 0 },
                    956:   {"no-W",             0,  POPT_ARG_VAL,    &whole_file, 0, 0, 0 },
                    957:   {"checksum",        'c', POPT_ARG_VAL,    &always_checksum, 1, 0, 0 },
                    958:   {"no-checksum",      0,  POPT_ARG_VAL,    &always_checksum, 0, 0, 0 },
                    959:   {"no-c",             0,  POPT_ARG_VAL,    &always_checksum, 0, 0, 0 },
                    960:   {"block-size",      'B', POPT_ARG_LONG,   &block_size, 0, 0, 0 },
                    961:   {"compare-dest",     0,  POPT_ARG_STRING, 0, OPT_COMPARE_DEST, 0, 0 },
                    962:   {"copy-dest",        0,  POPT_ARG_STRING, 0, OPT_COPY_DEST, 0, 0 },
                    963:   {"link-dest",        0,  POPT_ARG_STRING, 0, OPT_LINK_DEST, 0, 0 },
1.1.1.2 ! misho     964:   {"fuzzy",           'y', POPT_ARG_NONE,   0, 'y', 0, 0 },
1.1       misho     965:   {"no-fuzzy",         0,  POPT_ARG_VAL,    &fuzzy_basis, 0, 0, 0 },
                    966:   {"no-y",             0,  POPT_ARG_VAL,    &fuzzy_basis, 0, 0, 0 },
                    967:   {"compress",        'z', POPT_ARG_NONE,   0, 'z', 0, 0 },
                    968:   {"no-compress",      0,  POPT_ARG_VAL,    &do_compression, 0, 0, 0 },
                    969:   {"no-z",             0,  POPT_ARG_VAL,    &do_compression, 0, 0, 0 },
                    970:   {"skip-compress",    0,  POPT_ARG_STRING, &skip_compress, 0, 0, 0 },
                    971:   {"compress-level",   0,  POPT_ARG_INT,    &def_compress_level, 'z', 0, 0 },
                    972:   {0,                 'P', POPT_ARG_NONE,   0, 'P', 0, 0 },
                    973:   {"progress",         0,  POPT_ARG_VAL,    &do_progress, 1, 0, 0 },
                    974:   {"no-progress",      0,  POPT_ARG_VAL,    &do_progress, 0, 0, 0 },
                    975:   {"partial",          0,  POPT_ARG_VAL,    &keep_partial, 1, 0, 0 },
                    976:   {"no-partial",       0,  POPT_ARG_VAL,    &keep_partial, 0, 0, 0 },
                    977:   {"partial-dir",      0,  POPT_ARG_STRING, &partial_dir, 0, 0, 0 },
                    978:   {"delay-updates",    0,  POPT_ARG_VAL,    &delay_updates, 1, 0, 0 },
                    979:   {"no-delay-updates", 0,  POPT_ARG_VAL,    &delay_updates, 0, 0, 0 },
                    980:   {"prune-empty-dirs",'m', POPT_ARG_VAL,    &prune_empty_dirs, 1, 0, 0 },
                    981:   {"no-prune-empty-dirs",0,POPT_ARG_VAL,    &prune_empty_dirs, 0, 0, 0 },
                    982:   {"no-m",             0,  POPT_ARG_VAL,    &prune_empty_dirs, 0, 0, 0 },
                    983:   {"log-file",         0,  POPT_ARG_STRING, &logfile_name, 0, 0, 0 },
                    984:   {"log-file-format",  0,  POPT_ARG_STRING, &logfile_format, 0, 0, 0 },
                    985:   {"out-format",       0,  POPT_ARG_STRING, &stdout_format, 0, 0, 0 },
                    986:   {"log-format",       0,  POPT_ARG_STRING, &stdout_format, 0, 0, 0 }, /* DEPRECATED */
                    987:   {"itemize-changes", 'i', POPT_ARG_NONE,   0, 'i', 0, 0 },
                    988:   {"no-itemize-changes",0, POPT_ARG_VAL,    &itemize_changes, 0, 0, 0 },
                    989:   {"no-i",             0,  POPT_ARG_VAL,    &itemize_changes, 0, 0, 0 },
1.1.1.2 ! misho     990:   {"bwlimit",          0,  POPT_ARG_STRING, &bwlimit_arg, OPT_BWLIMIT, 0, 0 },
1.1       misho     991:   {"no-bwlimit",       0,  POPT_ARG_VAL,    &bwlimit, 0, 0, 0 },
                    992:   {"backup",          'b', POPT_ARG_VAL,    &make_backups, 1, 0, 0 },
                    993:   {"no-backup",        0,  POPT_ARG_VAL,    &make_backups, 0, 0, 0 },
                    994:   {"backup-dir",       0,  POPT_ARG_STRING, &backup_dir, 0, 0, 0 },
                    995:   {"suffix",           0,  POPT_ARG_STRING, &backup_suffix, 0, 0, 0 },
                    996:   {"list-only",        0,  POPT_ARG_VAL,    &list_only, 2, 0, 0 },
                    997:   {"read-batch",       0,  POPT_ARG_STRING, &batch_name, OPT_READ_BATCH, 0, 0 },
                    998:   {"write-batch",      0,  POPT_ARG_STRING, &batch_name, OPT_WRITE_BATCH, 0, 0 },
                    999:   {"only-write-batch", 0,  POPT_ARG_STRING, &batch_name, OPT_ONLY_WRITE_BATCH, 0, 0 },
                   1000:   {"files-from",       0,  POPT_ARG_STRING, &files_from, 0, 0, 0 },
                   1001:   {"from0",           '0', POPT_ARG_VAL,    &eol_nulls, 1, 0, 0},
                   1002:   {"no-from0",         0,  POPT_ARG_VAL,    &eol_nulls, 0, 0, 0},
                   1003:   {"protect-args",    's', POPT_ARG_VAL,    &protect_args, 1, 0, 0},
                   1004:   {"no-protect-args",  0,  POPT_ARG_VAL,    &protect_args, 0, 0, 0},
                   1005:   {"no-s",             0,  POPT_ARG_VAL,    &protect_args, 0, 0, 0},
                   1006:   {"numeric-ids",      0,  POPT_ARG_VAL,    &numeric_ids, 1, 0, 0 },
                   1007:   {"no-numeric-ids",   0,  POPT_ARG_VAL,    &numeric_ids, 0, 0, 0 },
1.1.1.2 ! misho    1008:   {"usermap",          0,  POPT_ARG_STRING, 0, OPT_USERMAP, 0, 0 },
        !          1009:   {"groupmap",         0,  POPT_ARG_STRING, 0, OPT_GROUPMAP, 0, 0 },
        !          1010:   {"chown",            0,  POPT_ARG_STRING, 0, OPT_CHOWN, 0, 0 },
1.1       misho    1011:   {"timeout",          0,  POPT_ARG_INT,    &io_timeout, 0, 0, 0 },
                   1012:   {"no-timeout",       0,  POPT_ARG_VAL,    &io_timeout, 0, 0, 0 },
                   1013:   {"contimeout",       0,  POPT_ARG_INT,    &connect_timeout, 0, 0, 0 },
                   1014:   {"no-contimeout",    0,  POPT_ARG_VAL,    &connect_timeout, 0, 0, 0 },
                   1015:   {"rsh",             'e', POPT_ARG_STRING, &shell_cmd, 0, 0, 0 },
                   1016:   {"rsync-path",       0,  POPT_ARG_STRING, &rsync_path, 0, 0, 0 },
                   1017:   {"temp-dir",        'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
                   1018: #ifdef ICONV_OPTION
                   1019:   {"iconv",            0,  POPT_ARG_STRING, &iconv_opt, 0, 0, 0 },
                   1020:   {"no-iconv",         0,  POPT_ARG_NONE,   0, OPT_NO_ICONV, 0, 0 },
                   1021: #endif
                   1022:   {"ipv4",            '4', POPT_ARG_VAL,    &default_af_hint, AF_INET, 0, 0 },
                   1023:   {"ipv6",            '6', POPT_ARG_VAL,    &default_af_hint, AF_INET6, 0, 0 },
                   1024:   {"8-bit-output",    '8', POPT_ARG_VAL,    &allow_8bit_chars, 1, 0, 0 },
                   1025:   {"no-8-bit-output",  0,  POPT_ARG_VAL,    &allow_8bit_chars, 0, 0, 0 },
                   1026:   {"no-8",             0,  POPT_ARG_VAL,    &allow_8bit_chars, 0, 0, 0 },
                   1027:   {"qsort",            0,  POPT_ARG_NONE,   &use_qsort, 0, 0, 0 },
                   1028:   {"address",          0,  POPT_ARG_STRING, &bind_address, 0, 0, 0 },
                   1029:   {"port",             0,  POPT_ARG_INT,    &rsync_port, 0, 0, 0 },
                   1030:   {"sockopts",         0,  POPT_ARG_STRING, &sockopts, 0, 0, 0 },
                   1031:   {"password-file",    0,  POPT_ARG_STRING, &password_file, 0, 0, 0 },
                   1032:   {"blocking-io",      0,  POPT_ARG_VAL,    &blocking_io, 1, 0, 0 },
                   1033:   {"no-blocking-io",   0,  POPT_ARG_VAL,    &blocking_io, 0, 0, 0 },
1.1.1.2 ! misho    1034: #ifdef HAVE_SETVBUF
        !          1035:   {"outbuf",           0,  POPT_ARG_STRING, &outbuf_mode, 0, 0, 0 },
        !          1036: #endif
        !          1037:   {"remote-option",   'M', POPT_ARG_STRING, 0, 'M', 0, 0 },
1.1       misho    1038:   {"protocol",         0,  POPT_ARG_INT,    &protocol_version, 0, 0, 0 },
                   1039:   {"checksum-seed",    0,  POPT_ARG_INT,    &checksum_seed, 0, 0, 0 },
                   1040:   {"server",           0,  POPT_ARG_NONE,   0, OPT_SERVER, 0, 0 },
                   1041:   {"sender",           0,  POPT_ARG_NONE,   0, OPT_SENDER, 0, 0 },
                   1042:   /* All the following options switch us into daemon-mode option-parsing. */
                   1043:   {"config",           0,  POPT_ARG_STRING, 0, OPT_DAEMON, 0, 0 },
                   1044:   {"daemon",           0,  POPT_ARG_NONE,   0, OPT_DAEMON, 0, 0 },
1.1.1.2 ! misho    1045:   {"dparam",           0,  POPT_ARG_STRING, 0, OPT_DAEMON, 0, 0 },
1.1       misho    1046:   {"detach",           0,  POPT_ARG_NONE,   0, OPT_DAEMON, 0, 0 },
                   1047:   {"no-detach",        0,  POPT_ARG_NONE,   0, OPT_DAEMON, 0, 0 },
                   1048:   {0,0,0,0, 0, 0, 0}
                   1049: };
                   1050: 
                   1051: static void daemon_usage(enum logcode F)
                   1052: {
                   1053:   print_rsync_version(F);
                   1054: 
                   1055:   rprintf(F,"\n");
                   1056:   rprintf(F,"Usage: rsync --daemon [OPTION]...\n");
                   1057:   rprintf(F,"     --address=ADDRESS       bind to the specified address\n");
1.1.1.2 ! misho    1058:   rprintf(F,"     --bwlimit=RATE          limit socket I/O bandwidth\n");
1.1       misho    1059:   rprintf(F,"     --config=FILE           specify alternate rsyncd.conf file\n");
1.1.1.2 ! misho    1060:   rprintf(F," -M, --dparam=OVERRIDE       override global daemon config parameter\n");
1.1       misho    1061:   rprintf(F,"     --no-detach             do not detach from the parent\n");
                   1062:   rprintf(F,"     --port=PORT             listen on alternate port number\n");
                   1063:   rprintf(F,"     --log-file=FILE         override the \"log file\" setting\n");
                   1064:   rprintf(F,"     --log-file-format=FMT   override the \"log format\" setting\n");
                   1065:   rprintf(F,"     --sockopts=OPTIONS      specify custom TCP options\n");
                   1066:   rprintf(F," -v, --verbose               increase verbosity\n");
                   1067:   rprintf(F," -4, --ipv4                  prefer IPv4\n");
                   1068:   rprintf(F," -6, --ipv6                  prefer IPv6\n");
                   1069:   rprintf(F,"     --help                  show this help screen\n");
                   1070: 
                   1071:   rprintf(F,"\n");
                   1072:   rprintf(F,"If you were not trying to invoke rsync as a daemon, avoid using any of the\n");
                   1073:   rprintf(F,"daemon-specific rsync options.  See also the rsyncd.conf(5) man page.\n");
                   1074: }
                   1075: 
                   1076: static struct poptOption long_daemon_options[] = {
                   1077:   /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
                   1078:   {"address",          0,  POPT_ARG_STRING, &bind_address, 0, 0, 0 },
                   1079:   {"bwlimit",          0,  POPT_ARG_INT,    &daemon_bwlimit, 0, 0, 0 },
                   1080:   {"config",           0,  POPT_ARG_STRING, &config_file, 0, 0, 0 },
                   1081:   {"daemon",           0,  POPT_ARG_NONE,   &daemon_opt, 0, 0, 0 },
1.1.1.2 ! misho    1082:   {"dparam",          'M', POPT_ARG_STRING, 0, 'M', 0, 0 },
1.1       misho    1083:   {"ipv4",            '4', POPT_ARG_VAL,    &default_af_hint, AF_INET, 0, 0 },
                   1084:   {"ipv6",            '6', POPT_ARG_VAL,    &default_af_hint, AF_INET6, 0, 0 },
                   1085:   {"detach",           0,  POPT_ARG_VAL,    &no_detach, 0, 0, 0 },
                   1086:   {"no-detach",        0,  POPT_ARG_VAL,    &no_detach, 1, 0, 0 },
                   1087:   {"log-file",         0,  POPT_ARG_STRING, &logfile_name, 0, 0, 0 },
                   1088:   {"log-file-format",  0,  POPT_ARG_STRING, &logfile_format, 0, 0, 0 },
                   1089:   {"port",             0,  POPT_ARG_INT,    &rsync_port, 0, 0, 0 },
                   1090:   {"sockopts",         0,  POPT_ARG_STRING, &sockopts, 0, 0, 0 },
                   1091:   {"protocol",         0,  POPT_ARG_INT,    &protocol_version, 0, 0, 0 },
                   1092:   {"server",           0,  POPT_ARG_NONE,   &am_server, 0, 0, 0 },
                   1093:   {"temp-dir",        'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
                   1094:   {"verbose",         'v', POPT_ARG_NONE,   0, 'v', 0, 0 },
                   1095:   {"no-verbose",       0,  POPT_ARG_VAL,    &verbose, 0, 0, 0 },
                   1096:   {"no-v",             0,  POPT_ARG_VAL,    &verbose, 0, 0, 0 },
                   1097:   {"help",            'h', POPT_ARG_NONE,   0, 'h', 0, 0 },
                   1098:   {0,0,0,0, 0, 0, 0}
                   1099: };
                   1100: 
                   1101: 
                   1102: static char err_buf[200];
                   1103: 
                   1104: 
                   1105: /**
                   1106:  * Store the option error message, if any, so that we can log the
                   1107:  * connection attempt (which requires parsing the options), and then
                   1108:  * show the error later on.
                   1109:  **/
                   1110: void option_error(void)
                   1111: {
                   1112:        if (!err_buf[0]) {
                   1113:                strlcpy(err_buf, "Error parsing options: option may "
                   1114:                        "be supported on client but not on server?\n",
                   1115:                        sizeof err_buf);
                   1116:        }
                   1117: 
                   1118:        rprintf(FERROR, RSYNC_NAME ": %s", err_buf);
                   1119:        msleep(20);
                   1120: }
                   1121: 
                   1122: 
                   1123: /**
                   1124:  * Tweak the option table to disable all options that the rsyncd.conf
                   1125:  * file has told us to refuse.
                   1126:  **/
                   1127: static void set_refuse_options(char *bp)
                   1128: {
                   1129:        struct poptOption *op;
                   1130:        char *cp, shortname[2];
                   1131:        int is_wild, found_match;
                   1132: 
                   1133:        shortname[1] = '\0';
                   1134: 
                   1135:        while (1) {
                   1136:                while (*bp == ' ') bp++;
                   1137:                if (!*bp)
                   1138:                        break;
                   1139:                if ((cp = strchr(bp, ' ')) != NULL)
                   1140:                        *cp= '\0';
                   1141:                is_wild = strpbrk(bp, "*?[") != NULL;
                   1142:                found_match = 0;
                   1143:                for (op = long_options; ; op++) {
                   1144:                        *shortname = op->shortName;
                   1145:                        if (!op->longName && !*shortname)
                   1146:                                break;
                   1147:                        if ((op->longName && wildmatch(bp, op->longName))
                   1148:                            || (*shortname && wildmatch(bp, shortname))) {
                   1149:                                if (op->argInfo == POPT_ARG_VAL)
                   1150:                                        op->argInfo = POPT_ARG_NONE;
                   1151:                                op->val = (op - long_options) + OPT_REFUSED_BASE;
                   1152:                                found_match = 1;
                   1153:                                /* These flags are set to let us easily check
                   1154:                                 * an implied option later in the code. */
                   1155:                                switch (*shortname) {
                   1156:                                case 'r': case 'd': case 'l': case 'p':
                   1157:                                case 't': case 'g': case 'o': case 'D':
                   1158:                                        refused_archive_part = op->val;
                   1159:                                        break;
                   1160:                                case 'z':
                   1161:                                        refused_compress = op->val;
                   1162:                                        break;
                   1163:                                case '\0':
                   1164:                                        if (wildmatch("delete", op->longName))
                   1165:                                                refused_delete = op->val;
                   1166:                                        else if (wildmatch("delete-before", op->longName))
                   1167:                                                refused_delete_before = op->val;
                   1168:                                        else if (wildmatch("delete-during", op->longName))
                   1169:                                                refused_delete_during = op->val;
                   1170:                                        else if (wildmatch("partial", op->longName))
                   1171:                                                refused_partial = op->val;
                   1172:                                        else if (wildmatch("progress", op->longName))
                   1173:                                                refused_progress = op->val;
                   1174:                                        else if (wildmatch("inplace", op->longName))
                   1175:                                                refused_inplace = op->val;
                   1176:                                        else if (wildmatch("no-iconv", op->longName))
                   1177:                                                refused_no_iconv = op->val;
                   1178:                                        break;
                   1179:                                }
                   1180:                                if (!is_wild)
                   1181:                                        break;
                   1182:                        }
                   1183:                }
                   1184:                if (!found_match) {
                   1185:                        rprintf(FLOG, "No match for refuse-options string \"%s\"\n",
                   1186:                                bp);
                   1187:                }
                   1188:                if (!cp)
                   1189:                        break;
                   1190:                *cp = ' ';
                   1191:                bp = cp + 1;
                   1192:        }
                   1193: }
                   1194: 
                   1195: 
                   1196: static int count_args(const char **argv)
                   1197: {
                   1198:        int i = 0;
                   1199: 
                   1200:        if (argv) {
                   1201:                while (argv[i] != NULL)
                   1202:                        i++;
                   1203:        }
                   1204: 
                   1205:        return i;
                   1206: }
                   1207: 
                   1208: 
                   1209: static OFF_T parse_size_arg(char **size_arg, char def_suf)
                   1210: {
                   1211:        int reps, mult, make_compatible = 0;
                   1212:        const char *arg;
                   1213:        OFF_T size = 1;
                   1214: 
                   1215:        for (arg = *size_arg; isDigit(arg); arg++) {}
                   1216:        if (*arg == '.')
                   1217:                for (arg++; isDigit(arg); arg++) {}
                   1218:        switch (*arg && *arg != '+' && *arg != '-' ? *arg++ : def_suf) {
                   1219:        case 'b': case 'B':
                   1220:                reps = 0;
                   1221:                break;
                   1222:        case 'k': case 'K':
                   1223:                reps = 1;
                   1224:                break;
                   1225:        case 'm': case 'M':
                   1226:                reps = 2;
                   1227:                break;
                   1228:        case 'g': case 'G':
                   1229:                reps = 3;
                   1230:                break;
                   1231:        default:
                   1232:                return -1;
                   1233:        }
                   1234:        if (*arg == 'b' || *arg == 'B')
                   1235:                mult = 1000, make_compatible = 1, arg++;
                   1236:        else if (!*arg || *arg == '+' || *arg == '-')
                   1237:                mult = 1024;
                   1238:        else if (strncasecmp(arg, "ib", 2) == 0)
                   1239:                mult = 1024, arg += 2;
                   1240:        else
                   1241:                return -1;
                   1242:        while (reps--)
                   1243:                size *= mult;
                   1244:        size *= atof(*size_arg);
                   1245:        if ((*arg == '+' || *arg == '-') && arg[1] == '1')
                   1246:                size += atoi(arg), make_compatible = 1, arg += 2;
                   1247:        if (*arg)
                   1248:                return -1;
1.1.1.2 ! misho    1249:        if (size > 0 && make_compatible && def_suf == 'b') {
1.1       misho    1250:                /* We convert this manually because we may need %lld precision,
                   1251:                 * and that's not a portable sprintf() escape. */
                   1252:                char buf[128], *s = buf + sizeof buf - 1;
                   1253:                OFF_T num = size;
                   1254:                *s = '\0';
                   1255:                while (num) {
                   1256:                        *--s = (char)(num % 10) + '0';
                   1257:                        num /= 10;
                   1258:                }
                   1259:                if (!(*size_arg = strdup(s)))
                   1260:                        out_of_memory("parse_size_arg");
                   1261:        }
                   1262:        return size;
                   1263: }
                   1264: 
                   1265: 
                   1266: static void create_refuse_error(int which)
                   1267: {
                   1268:        /* The "which" value is the index + OPT_REFUSED_BASE. */
                   1269:        struct poptOption *op = &long_options[which - OPT_REFUSED_BASE];
                   1270:        int n = snprintf(err_buf, sizeof err_buf,
                   1271:                         "The server is configured to refuse --%s\n",
                   1272:                         op->longName) - 1;
                   1273:        if (op->shortName) {
                   1274:                snprintf(err_buf + n, sizeof err_buf - n,
                   1275:                         " (-%c)\n", op->shortName);
                   1276:        }
                   1277: }
                   1278: 
                   1279: 
                   1280: /**
                   1281:  * Process command line arguments.  Called on both local and remote.
                   1282:  *
                   1283:  * @retval 1 if all options are OK; with globals set to appropriate
                   1284:  * values
                   1285:  *
                   1286:  * @retval 0 on error, with err_buf containing an explanation
                   1287:  **/
                   1288: int parse_arguments(int *argc_p, const char ***argv_p)
                   1289: {
                   1290:        static poptContext pc;
                   1291:        char *ref = lp_refuse_options(module_id);
                   1292:        const char *arg, **argv = *argv_p;
                   1293:        int argc = *argc_p;
                   1294:        int opt;
                   1295: 
                   1296:        if (ref && *ref)
                   1297:                set_refuse_options(ref);
                   1298:        if (am_daemon) {
                   1299:                set_refuse_options("log-file*");
                   1300: #ifdef ICONV_OPTION
                   1301:                if (!*lp_charset(module_id))
                   1302:                        set_refuse_options("iconv");
                   1303: #endif
                   1304:        }
                   1305: 
                   1306: #ifdef ICONV_OPTION
1.1.1.2 ! misho    1307:        if (!am_daemon && protect_args <= 0 && (arg = getenv("RSYNC_ICONV")) != NULL && *arg)
1.1       misho    1308:                iconv_opt = strdup(arg);
                   1309: #endif
                   1310: 
                   1311:        /* TODO: Call poptReadDefaultConfig; handle errors. */
                   1312: 
                   1313:        /* The context leaks in case of an error, but if there's a
                   1314:         * problem we always exit anyhow. */
                   1315:        if (pc)
                   1316:                poptFreeContext(pc);
                   1317:        pc = poptGetContext(RSYNC_NAME, argc, argv, long_options, 0);
                   1318:        if (!am_server)
                   1319:                poptReadDefaultConfig(pc, 0);
                   1320: 
                   1321:        while ((opt = poptGetNextOpt(pc)) != -1) {
                   1322:                /* most options are handled automatically by popt;
                   1323:                 * only special cases are returned and listed here. */
                   1324: 
                   1325:                switch (opt) {
                   1326:                case OPT_VERSION:
                   1327:                        print_rsync_version(FINFO);
                   1328:                        exit_cleanup(0);
                   1329: 
                   1330:                case OPT_SERVER:
                   1331:                        if (!am_server) {
                   1332:                                /* Disable popt aliases on the server side and
                   1333:                                 * then start parsing the options again. */
                   1334:                                poptFreeContext(pc);
                   1335:                                pc = poptGetContext(RSYNC_NAME, argc, argv,
                   1336:                                                    long_options, 0);
                   1337:                                am_server = 1;
                   1338:                        }
                   1339: #ifdef ICONV_OPTION
                   1340:                        iconv_opt = NULL;
                   1341: #endif
                   1342:                        break;
                   1343: 
                   1344:                case OPT_SENDER:
                   1345:                        if (!am_server) {
                   1346:                                usage(FERROR);
                   1347:                                exit_cleanup(RERR_SYNTAX);
                   1348:                        }
                   1349:                        am_sender = 1;
                   1350:                        break;
                   1351: 
                   1352:                case OPT_DAEMON:
                   1353:                        if (am_daemon) {
                   1354:                                strlcpy(err_buf,
                   1355:                                        "Attempt to hack rsync thwarted!\n",
                   1356:                                        sizeof err_buf);
                   1357:                                return 0;
                   1358:                        }
                   1359: #ifdef ICONV_OPTION
                   1360:                        iconv_opt = NULL;
                   1361: #endif
1.1.1.2 ! misho    1362:                        protect_args = 0;
1.1       misho    1363:                        poptFreeContext(pc);
                   1364:                        pc = poptGetContext(RSYNC_NAME, argc, argv,
                   1365:                                            long_daemon_options, 0);
                   1366:                        while ((opt = poptGetNextOpt(pc)) != -1) {
1.1.1.2 ! misho    1367:                                char **cpp;
1.1       misho    1368:                                switch (opt) {
                   1369:                                case 'h':
                   1370:                                        daemon_usage(FINFO);
                   1371:                                        exit_cleanup(0);
                   1372: 
1.1.1.2 ! misho    1373:                                case 'M':
        !          1374:                                        arg = poptGetOptArg(pc);
        !          1375:                                        if (!strchr(arg, '=')) {
        !          1376:                                                rprintf(FERROR,
        !          1377:                                                    "--dparam value is missing an '=': %s\n",
        !          1378:                                                    arg);
        !          1379:                                                goto daemon_error;
        !          1380:                                        }
        !          1381:                                        cpp = EXPAND_ITEM_LIST(&dparam_list, char *, 4);
        !          1382:                                        *cpp = strdup(arg);
        !          1383:                                        break;
        !          1384: 
1.1       misho    1385:                                case 'v':
                   1386:                                        verbose++;
                   1387:                                        break;
                   1388: 
                   1389:                                default:
                   1390:                                        rprintf(FERROR,
                   1391:                                            "rsync: %s: %s (in daemon mode)\n",
                   1392:                                            poptBadOption(pc, POPT_BADOPTION_NOALIAS),
                   1393:                                            poptStrerror(opt));
                   1394:                                        goto daemon_error;
                   1395:                                }
                   1396:                        }
                   1397: 
1.1.1.2 ! misho    1398:                        if (dparam_list.count && !set_dparams(1))
        !          1399:                                exit_cleanup(RERR_SYNTAX);
        !          1400: 
1.1       misho    1401:                        if (tmpdir && strlen(tmpdir) >= MAXPATHLEN - 10) {
                   1402:                                snprintf(err_buf, sizeof err_buf,
                   1403:                                         "the --temp-dir path is WAY too long.\n");
                   1404:                                return 0;
                   1405:                        }
                   1406: 
                   1407:                        if (!daemon_opt) {
                   1408:                                rprintf(FERROR, "Daemon option(s) used without --daemon.\n");
                   1409:                            daemon_error:
                   1410:                                rprintf(FERROR,
                   1411:                                    "(Type \"rsync --daemon --help\" for assistance with daemon mode.)\n");
                   1412:                                exit_cleanup(RERR_SYNTAX);
                   1413:                        }
                   1414: 
                   1415:                        *argv_p = argv = poptGetArgs(pc);
                   1416:                        *argc_p = argc = count_args(argv);
                   1417:                        am_starting_up = 0;
                   1418:                        daemon_opt = 0;
                   1419:                        am_daemon = 1;
                   1420:                        return 1;
                   1421: 
                   1422:                case OPT_MODIFY_WINDOW:
                   1423:                        /* The value has already been set by popt, but
                   1424:                         * we need to remember that we're using a
                   1425:                         * non-default setting. */
                   1426:                        modify_window_set = 1;
                   1427:                        break;
                   1428: 
                   1429:                case OPT_FILTER:
1.1.1.2 ! misho    1430:                        parse_filter_str(&filter_list, poptGetOptArg(pc),
        !          1431:                                        rule_template(0), 0);
1.1       misho    1432:                        break;
                   1433: 
                   1434:                case OPT_EXCLUDE:
1.1.1.2 ! misho    1435:                        parse_filter_str(&filter_list, poptGetOptArg(pc),
        !          1436:                                        rule_template(0), XFLG_OLD_PREFIXES);
1.1       misho    1437:                        break;
                   1438: 
                   1439:                case OPT_INCLUDE:
1.1.1.2 ! misho    1440:                        parse_filter_str(&filter_list, poptGetOptArg(pc),
        !          1441:                                        rule_template(FILTRULE_INCLUDE), XFLG_OLD_PREFIXES);
1.1       misho    1442:                        break;
                   1443: 
                   1444:                case OPT_EXCLUDE_FROM:
                   1445:                case OPT_INCLUDE_FROM:
                   1446:                        arg = poptGetOptArg(pc);
                   1447:                        if (sanitize_paths)
                   1448:                                arg = sanitize_path(NULL, arg, NULL, 0, SP_DEFAULT);
                   1449:                        if (daemon_filter_list.head) {
                   1450:                                int rej;
1.1.1.2 ! misho    1451:                                char *cp = strdup(arg);
1.1       misho    1452:                                if (!cp)
                   1453:                                        out_of_memory("parse_arguments");
                   1454:                                if (!*cp)
1.1.1.2 ! misho    1455:                                        rej = 1;
        !          1456:                                else {
        !          1457:                                        char *dir = cp + (*cp == '/' ? module_dirlen : 0);
        !          1458:                                        clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
        !          1459:                                        rej = check_filter(&daemon_filter_list, FLOG, dir, 0) < 0;
        !          1460:                                }
1.1       misho    1461:                                free(cp);
                   1462:                                if (rej)
                   1463:                                        goto options_rejected;
                   1464:                        }
                   1465:                        parse_filter_file(&filter_list, arg,
1.1.1.2 ! misho    1466:                                rule_template(opt == OPT_INCLUDE_FROM ? FILTRULE_INCLUDE : 0),
1.1       misho    1467:                                XFLG_FATAL_ERRORS | XFLG_OLD_PREFIXES);
                   1468:                        break;
                   1469: 
                   1470:                case 'a':
                   1471:                        if (refused_archive_part) {
                   1472:                                create_refuse_error(refused_archive_part);
                   1473:                                return 0;
                   1474:                        }
                   1475:                        if (!recurse) /* preserve recurse == 2 */
                   1476:                                recurse = 1;
                   1477: #ifdef SUPPORT_LINKS
                   1478:                        preserve_links = 1;
                   1479: #endif
                   1480:                        preserve_perms = 1;
                   1481:                        preserve_times = 1;
                   1482:                        preserve_gid = 1;
                   1483:                        preserve_uid = 1;
                   1484:                        preserve_devices = 1;
                   1485:                        preserve_specials = 1;
                   1486:                        break;
                   1487: 
                   1488:                case 'D':
                   1489:                        preserve_devices = preserve_specials = 1;
                   1490:                        break;
                   1491: 
                   1492:                case OPT_NO_D:
                   1493:                        preserve_devices = preserve_specials = 0;
                   1494:                        break;
                   1495: 
                   1496:                case 'h':
                   1497:                        human_readable++;
                   1498:                        break;
                   1499: 
                   1500:                case 'H':
                   1501:                        preserve_hard_links++;
                   1502:                        break;
                   1503: 
                   1504:                case 'i':
                   1505:                        itemize_changes++;
                   1506:                        break;
                   1507: 
                   1508:                case 'v':
                   1509:                        verbose++;
                   1510:                        break;
                   1511: 
1.1.1.2 ! misho    1512:                case 'y':
        !          1513:                        fuzzy_basis++;
        !          1514:                        break;
        !          1515: 
1.1       misho    1516:                case 'q':
                   1517:                        quiet++;
                   1518:                        break;
                   1519: 
                   1520:                case 'x':
                   1521:                        one_file_system++;
                   1522:                        break;
                   1523: 
                   1524:                case 'F':
                   1525:                        switch (++F_option_cnt) {
                   1526:                        case 1:
1.1.1.2 ! misho    1527:                                parse_filter_str(&filter_list,": /.rsync-filter",rule_template(0),0);
1.1       misho    1528:                                break;
                   1529:                        case 2:
1.1.1.2 ! misho    1530:                                parse_filter_str(&filter_list,"- .rsync-filter",rule_template(0),0);
1.1       misho    1531:                                break;
                   1532:                        }
                   1533:                        break;
                   1534: 
                   1535:                case 'P':
                   1536:                        if (refused_partial || refused_progress) {
                   1537:                                create_refuse_error(refused_partial
                   1538:                                    ? refused_partial : refused_progress);
                   1539:                                return 0;
                   1540:                        }
                   1541:                        do_progress = 1;
                   1542:                        keep_partial = 1;
                   1543:                        break;
                   1544: 
                   1545:                case 'z':
                   1546:                        if (def_compress_level < Z_DEFAULT_COMPRESSION
                   1547:                         || def_compress_level > Z_BEST_COMPRESSION) {
                   1548:                                snprintf(err_buf, sizeof err_buf,
                   1549:                                        "--compress-level value is invalid: %d\n",
                   1550:                                        def_compress_level);
                   1551:                                return 0;
                   1552:                        }
                   1553:                        do_compression = def_compress_level != Z_NO_COMPRESSION;
                   1554:                        if (do_compression && refused_compress) {
                   1555:                                create_refuse_error(refused_compress);
                   1556:                                return 0;
                   1557:                        }
                   1558:                        break;
                   1559: 
1.1.1.2 ! misho    1560:                case 'M':
        !          1561:                        arg = poptGetOptArg(pc);
        !          1562:                        if (*arg != '-') {
        !          1563:                                snprintf(err_buf, sizeof err_buf,
        !          1564:                                        "Remote option must start with a dash: %s\n", arg);
        !          1565:                                return 0;
        !          1566:                        }
        !          1567:                        if (remote_option_cnt+2 >= remote_option_alloc) {
        !          1568:                                remote_option_alloc += 16;
        !          1569:                                remote_options = realloc_array(remote_options,
        !          1570:                                                        const char *, remote_option_alloc);
        !          1571:                                if (!remote_options)
        !          1572:                                        out_of_memory("parse_arguments");
        !          1573:                                if (!remote_option_cnt)
        !          1574:                                        remote_options[0] = "ARG0";
        !          1575:                        }
        !          1576:                        remote_options[++remote_option_cnt] = arg;
        !          1577:                        remote_options[remote_option_cnt+1] = NULL;
        !          1578:                        break;
        !          1579: 
1.1       misho    1580:                case OPT_WRITE_BATCH:
                   1581:                        /* batch_name is already set */
                   1582:                        write_batch = 1;
                   1583:                        break;
                   1584: 
                   1585:                case OPT_ONLY_WRITE_BATCH:
                   1586:                        /* batch_name is already set */
                   1587:                        write_batch = -1;
                   1588:                        break;
                   1589: 
                   1590:                case OPT_READ_BATCH:
                   1591:                        /* batch_name is already set */
                   1592:                        read_batch = 1;
                   1593:                        break;
                   1594: 
                   1595:                case OPT_NO_ICONV:
                   1596: #ifdef ICONV_OPTION
                   1597:                        iconv_opt = NULL;
                   1598: #endif
                   1599:                        break;
                   1600: 
                   1601:                case OPT_MAX_SIZE:
1.1.1.2 ! misho    1602:                        if ((max_size = parse_size_arg(&max_size_arg, 'b')) < 0) {
1.1       misho    1603:                                snprintf(err_buf, sizeof err_buf,
                   1604:                                        "--max-size value is invalid: %s\n",
                   1605:                                        max_size_arg);
                   1606:                                return 0;
                   1607:                        }
                   1608:                        break;
                   1609: 
                   1610:                case OPT_MIN_SIZE:
1.1.1.2 ! misho    1611:                        if ((min_size = parse_size_arg(&min_size_arg, 'b')) < 0) {
1.1       misho    1612:                                snprintf(err_buf, sizeof err_buf,
                   1613:                                        "--min-size value is invalid: %s\n",
                   1614:                                        min_size_arg);
                   1615:                                return 0;
                   1616:                        }
                   1617:                        break;
                   1618: 
1.1.1.2 ! misho    1619:                case OPT_BWLIMIT:
        !          1620:                        {
        !          1621:                                OFF_T limit = parse_size_arg(&bwlimit_arg, 'K');
        !          1622:                                if (limit < 0) {
        !          1623:                                        snprintf(err_buf, sizeof err_buf,
        !          1624:                                                "--bwlimit value is invalid: %s\n", bwlimit_arg);
        !          1625:                                        return 0;
        !          1626:                                }
        !          1627:                                bwlimit = (limit + 512) / 1024;
        !          1628:                                if (limit && !bwlimit) {
        !          1629:                                        snprintf(err_buf, sizeof err_buf,
        !          1630:                                                "--bwlimit value is too small: %s\n", bwlimit_arg);
        !          1631:                                        return 0;
        !          1632:                                }
        !          1633:                        }
        !          1634:                        break;
        !          1635: 
1.1       misho    1636:                case OPT_APPEND:
                   1637:                        if (am_server)
                   1638:                                append_mode++;
                   1639:                        else
                   1640:                                append_mode = 1;
                   1641:                        break;
                   1642: 
                   1643:                case OPT_LINK_DEST:
                   1644: #ifdef SUPPORT_HARD_LINKS
                   1645:                        link_dest = 1;
                   1646:                        dest_option = "--link-dest";
                   1647:                        goto set_dest_dir;
                   1648: #else
                   1649:                        snprintf(err_buf, sizeof err_buf,
                   1650:                                 "hard links are not supported on this %s\n",
                   1651:                                 am_server ? "server" : "client");
                   1652:                        return 0;
                   1653: #endif
                   1654: 
                   1655:                case OPT_COPY_DEST:
                   1656:                        copy_dest = 1;
                   1657:                        dest_option = "--copy-dest";
                   1658:                        goto set_dest_dir;
                   1659: 
                   1660:                case OPT_COMPARE_DEST:
                   1661:                        compare_dest = 1;
                   1662:                        dest_option = "--compare-dest";
                   1663:                set_dest_dir:
                   1664:                        if (basis_dir_cnt >= MAX_BASIS_DIRS) {
                   1665:                                snprintf(err_buf, sizeof err_buf,
                   1666:                                        "ERROR: at most %d %s args may be specified\n",
                   1667:                                        MAX_BASIS_DIRS, dest_option);
                   1668:                                return 0;
                   1669:                        }
                   1670:                        /* We defer sanitizing this arg until we know what
                   1671:                         * our destination directory is going to be. */
                   1672:                        basis_dir[basis_dir_cnt++] = (char *)poptGetOptArg(pc);
                   1673:                        break;
                   1674: 
                   1675:                case OPT_CHMOD:
                   1676:                        arg = poptGetOptArg(pc);
                   1677:                        if (!parse_chmod(arg, &chmod_modes)) {
                   1678:                                snprintf(err_buf, sizeof err_buf,
                   1679:                                    "Invalid argument passed to --chmod (%s)\n",
                   1680:                                    arg);
                   1681:                                return 0;
                   1682:                        }
                   1683:                        break;
                   1684: 
1.1.1.2 ! misho    1685:                case OPT_INFO:
        !          1686:                        arg = poptGetOptArg(pc);
        !          1687:                        parse_output_words(info_words, info_levels, arg, USER_PRIORITY);
        !          1688:                        break;
        !          1689: 
        !          1690:                case OPT_DEBUG:
        !          1691:                        arg = poptGetOptArg(pc);
        !          1692:                        parse_output_words(debug_words, debug_levels, arg, USER_PRIORITY);
        !          1693:                        break;
        !          1694: 
        !          1695:                case OPT_USERMAP:
        !          1696:                        if (usermap) {
        !          1697:                                if (usermap_via_chown) {
        !          1698:                                        snprintf(err_buf, sizeof err_buf,
        !          1699:                                            "--usermap conflicts with prior --chown.\n");
        !          1700:                                        return 0;
        !          1701:                                }
        !          1702:                                snprintf(err_buf, sizeof err_buf,
        !          1703:                                    "You can only specify --usermap once.\n");
        !          1704:                                return 0;
        !          1705:                        }
        !          1706:                        usermap = (char *)poptGetOptArg(pc);
        !          1707:                        usermap_via_chown = False;
        !          1708:                        break;
        !          1709: 
        !          1710:                case OPT_GROUPMAP:
        !          1711:                        if (groupmap) {
        !          1712:                                if (groupmap_via_chown) {
        !          1713:                                        snprintf(err_buf, sizeof err_buf,
        !          1714:                                            "--groupmap conflicts with prior --chown.\n");
        !          1715:                                        return 0;
        !          1716:                                }
        !          1717:                                snprintf(err_buf, sizeof err_buf,
        !          1718:                                    "You can only specify --groupmap once.\n");
        !          1719:                                return 0;
        !          1720:                        }
        !          1721:                        groupmap = (char *)poptGetOptArg(pc);
        !          1722:                        groupmap_via_chown = False;
        !          1723:                        break;
        !          1724: 
        !          1725:                case OPT_CHOWN: {
        !          1726:                        const char *chown = poptGetOptArg(pc);
        !          1727:                        int len;
        !          1728:                        if ((arg = strchr(chown, ':')) != NULL)
        !          1729:                                len = arg++ - chown;
        !          1730:                        else
        !          1731:                                len = strlen(chown);
        !          1732:                        if (len) {
        !          1733:                                if (usermap) {
        !          1734:                                        if (!usermap_via_chown) {
        !          1735:                                                snprintf(err_buf, sizeof err_buf,
        !          1736:                                                    "--chown conflicts with prior --usermap.\n");
        !          1737:                                                return 0;
        !          1738:                                        }
        !          1739:                                        snprintf(err_buf, sizeof err_buf,
        !          1740:                                            "You can only specify a user-affecting --chown once.\n");
        !          1741:                                        return 0;
        !          1742:                                }
        !          1743:                                if (asprintf(&usermap, "*:%.*s", len, chown) < 0)
        !          1744:                                        out_of_memory("parse_arguments");
        !          1745:                                usermap_via_chown = True;
        !          1746:                        }
        !          1747:                        if (arg && *arg) {
        !          1748:                                if (groupmap) {
        !          1749:                                        if (!groupmap_via_chown) {
        !          1750:                                                snprintf(err_buf, sizeof err_buf,
        !          1751:                                                    "--chown conflicts with prior --groupmap.\n");
        !          1752:                                                return 0;
        !          1753:                                        }
        !          1754:                                        snprintf(err_buf, sizeof err_buf,
        !          1755:                                            "You can only specify a group-affecting --chown once.\n");
        !          1756:                                        return 0;
        !          1757:                                }
        !          1758:                                if (asprintf(&groupmap, "*:%s", arg) < 0)
        !          1759:                                        out_of_memory("parse_arguments");
        !          1760:                                groupmap_via_chown = True;
        !          1761:                        }
        !          1762:                        break;
        !          1763:                }
        !          1764: 
1.1       misho    1765:                case OPT_HELP:
                   1766:                        usage(FINFO);
                   1767:                        exit_cleanup(0);
                   1768: 
                   1769:                case 'A':
                   1770: #ifdef SUPPORT_ACLS
                   1771:                        preserve_acls = 1;
                   1772:                        preserve_perms = 1;
                   1773:                        break;
                   1774: #else
                   1775:                        /* FIXME: this should probably be ignored with a
                   1776:                         * warning and then countermeasures taken to
                   1777:                         * restrict group and other access in the presence
                   1778:                         * of any more restrictive ACLs, but this is safe
                   1779:                         * for now */
                   1780:                        snprintf(err_buf,sizeof(err_buf),
                   1781:                                  "ACLs are not supported on this %s\n",
                   1782:                                 am_server ? "server" : "client");
                   1783:                        return 0;
                   1784: #endif
                   1785: 
                   1786:                case 'X':
                   1787: #ifdef SUPPORT_XATTRS
                   1788:                        preserve_xattrs++;
                   1789:                        break;
                   1790: #else
                   1791:                        snprintf(err_buf,sizeof(err_buf),
                   1792:                                 "extended attributes are not supported on this %s\n",
                   1793:                                 am_server ? "server" : "client");
                   1794:                        return 0;
                   1795: #endif
                   1796: 
                   1797:                default:
                   1798:                        /* A large opt value means that set_refuse_options()
                   1799:                         * turned this option off. */
                   1800:                        if (opt >= OPT_REFUSED_BASE) {
                   1801:                                create_refuse_error(opt);
                   1802:                                return 0;
                   1803:                        }
                   1804:                        snprintf(err_buf, sizeof err_buf, "%s%s: %s\n",
                   1805:                                 am_server ? "on remote machine: " : "",
                   1806:                                 poptBadOption(pc, POPT_BADOPTION_NOALIAS),
                   1807:                                 poptStrerror(opt));
                   1808:                        return 0;
                   1809:                }
                   1810:        }
                   1811: 
1.1.1.2 ! misho    1812:        if (protect_args < 0) {
        !          1813:                if (am_server)
        !          1814:                        protect_args = 0;
        !          1815:                else if ((arg = getenv("RSYNC_PROTECT_ARGS")) != NULL && *arg)
        !          1816:                        protect_args = atoi(arg) ? 1 : 0;
        !          1817:                else {
        !          1818: #ifdef RSYNC_USE_PROTECTED_ARGS
        !          1819:                        protect_args = 1;
        !          1820: #else
        !          1821:                        protect_args = 0;
        !          1822: #endif
        !          1823:                }
        !          1824:        }
        !          1825: 
        !          1826:        if (human_readable > 1 && argc == 2 && !am_server) {
1.1       misho    1827:                /* Allow the old meaning of 'h' (--help) on its own. */
                   1828:                usage(FINFO);
                   1829:                exit_cleanup(0);
                   1830:        }
                   1831: 
1.1.1.2 ! misho    1832: #ifdef HAVE_SETVBUF
        !          1833:        if (outbuf_mode && !am_server) {
        !          1834:                int mode = *(uchar *)outbuf_mode;
        !          1835:                if (islower(mode))
        !          1836:                        mode = toupper(mode);
        !          1837:                fflush(stdout); /* Just in case... */
        !          1838:                switch (mode) {
        !          1839:                case 'N': /* None */
        !          1840:                case 'U': /* Unbuffered */
        !          1841:                        mode = _IONBF;
        !          1842:                        break;
        !          1843:                case 'L': /* Line */
        !          1844:                        mode = _IOLBF;
        !          1845:                        break;
        !          1846:                case 'B': /* Block */
        !          1847:                case 'F': /* Full */
        !          1848:                        mode = _IOFBF;
        !          1849:                        break;
        !          1850:                default:
        !          1851:                        snprintf(err_buf, sizeof err_buf,
        !          1852:                                "Invalid --outbuf setting -- specify N, L, or B.\n");
        !          1853:                        return 0;
        !          1854:                }
        !          1855:                setvbuf(stdout, (char *)NULL, mode, 0);
        !          1856:        }
        !          1857: 
        !          1858:        if (msgs2stderr) {
        !          1859:                /* Make stderr line buffered for better sharing of the stream. */
        !          1860:                fflush(stderr); /* Just in case... */
        !          1861:                setvbuf(stderr, (char *)NULL, _IOLBF, 0);
        !          1862:        }
        !          1863: #endif
        !          1864: 
        !          1865:        set_output_verbosity(verbose, DEFAULT_PRIORITY);
        !          1866: 
        !          1867:        if (do_stats) {
        !          1868:                parse_output_words(info_words, info_levels,
        !          1869:                        verbose > 1 ? "stats3" : "stats2", DEFAULT_PRIORITY);
        !          1870:        }
        !          1871: 
1.1       misho    1872: #ifdef ICONV_OPTION
                   1873:        if (iconv_opt && protect_args != 2) {
                   1874:                if (!am_server && strcmp(iconv_opt, "-") == 0)
                   1875:                        iconv_opt = NULL;
                   1876:                else
                   1877:                        need_unsorted_flist = 1;
                   1878:        }
                   1879:        if (refused_no_iconv && !iconv_opt) {
                   1880:                create_refuse_error(refused_no_iconv);
                   1881:                return 0;
                   1882:        }
                   1883: #endif
                   1884: 
1.1.1.2 ! misho    1885:        if (fuzzy_basis > 1)
        !          1886:                fuzzy_basis = basis_dir_cnt + 1;
        !          1887: 
1.1       misho    1888:        if (protect_args == 1 && am_server)
                   1889:                return 1;
                   1890: 
                   1891:        *argv_p = argv = poptGetArgs(pc);
                   1892:        *argc_p = argc = count_args(argv);
                   1893: 
                   1894: #ifndef SUPPORT_LINKS
                   1895:        if (preserve_links && !am_sender) {
                   1896:                snprintf(err_buf, sizeof err_buf,
                   1897:                         "symlinks are not supported on this %s\n",
                   1898:                         am_server ? "server" : "client");
                   1899:                return 0;
                   1900:        }
                   1901: #endif
                   1902: 
                   1903: #ifndef SUPPORT_HARD_LINKS
                   1904:        if (preserve_hard_links) {
                   1905:                snprintf(err_buf, sizeof err_buf,
                   1906:                         "hard links are not supported on this %s\n",
                   1907:                         am_server ? "server" : "client");
                   1908:                return 0;
                   1909:        }
                   1910: #endif
                   1911: 
                   1912: #ifdef SUPPORT_XATTRS
                   1913:        if (am_root < 0 && preserve_xattrs > 1) {
                   1914:                snprintf(err_buf, sizeof err_buf,
                   1915:                         "--fake-super conflicts with -XX\n");
                   1916:                return 0;
                   1917:        }
                   1918: #else
                   1919:        if (am_root < 0) {
                   1920:                snprintf(err_buf, sizeof err_buf,
                   1921:                         "--fake-super requires an rsync with extended attributes enabled\n");
                   1922:                return 0;
                   1923:        }
                   1924: #endif
                   1925: 
1.1.1.2 ! misho    1926:        if (block_size > MAX_BLOCK_SIZE) {
        !          1927:                snprintf(err_buf, sizeof err_buf,
        !          1928:                         "--block-size=%lu is too large (max: %u)\n", block_size, MAX_BLOCK_SIZE);
        !          1929:                return 0;
        !          1930:        }
        !          1931: 
1.1       misho    1932:        if (write_batch && read_batch) {
                   1933:                snprintf(err_buf, sizeof err_buf,
                   1934:                        "--write-batch and --read-batch can not be used together\n");
                   1935:                return 0;
                   1936:        }
                   1937:        if (write_batch > 0 || read_batch) {
                   1938:                if (am_server) {
                   1939:                        rprintf(FINFO,
                   1940:                                "ignoring --%s-batch option sent to server\n",
                   1941:                                write_batch ? "write" : "read");
                   1942:                        /* We don't actually exit_cleanup(), so that we can
                   1943:                         * still service older version clients that still send
                   1944:                         * batch args to server. */
                   1945:                        read_batch = write_batch = 0;
                   1946:                        batch_name = NULL;
                   1947:                } else if (dry_run)
                   1948:                        write_batch = 0;
                   1949:        } else if (write_batch < 0 && dry_run)
                   1950:                write_batch = 0;
                   1951:        if (read_batch && files_from) {
                   1952:                snprintf(err_buf, sizeof err_buf,
                   1953:                        "--read-batch cannot be used with --files-from\n");
                   1954:                return 0;
                   1955:        }
                   1956:        if (read_batch && remove_source_files) {
                   1957:                snprintf(err_buf, sizeof err_buf,
                   1958:                        "--read-batch cannot be used with --remove-%s-files\n",
                   1959:                        remove_source_files == 1 ? "source" : "sent");
                   1960:                return 0;
                   1961:        }
                   1962:        if (batch_name && strlen(batch_name) > MAX_BATCH_NAME_LEN) {
                   1963:                snprintf(err_buf, sizeof err_buf,
                   1964:                        "the batch-file name must be %d characters or less.\n",
                   1965:                        MAX_BATCH_NAME_LEN);
                   1966:                return 0;
                   1967:        }
                   1968: 
                   1969:        if (tmpdir && strlen(tmpdir) >= MAXPATHLEN - 10) {
                   1970:                snprintf(err_buf, sizeof err_buf,
                   1971:                         "the --temp-dir path is WAY too long.\n");
                   1972:                return 0;
                   1973:        }
                   1974: 
                   1975:        if (max_delete < 0 && max_delete != INT_MIN) {
                   1976:                /* Negative numbers are treated as "no deletions". */
                   1977:                max_delete = 0;
                   1978:        }
                   1979: 
                   1980:        if (compare_dest + copy_dest + link_dest > 1) {
                   1981:                snprintf(err_buf, sizeof err_buf,
                   1982:                        "You may not mix --compare-dest, --copy-dest, and --link-dest.\n");
                   1983:                return 0;
                   1984:        }
                   1985: 
                   1986:        if (files_from) {
                   1987:                if (recurse == 1) /* preserve recurse == 2 */
                   1988:                        recurse = 0;
                   1989:                if (xfer_dirs < 0)
                   1990:                        xfer_dirs = 1;
                   1991:        }
                   1992: 
                   1993:        if (argc < 2 && !read_batch && !am_server)
                   1994:                list_only |= 1;
                   1995: 
                   1996:        if (xfer_dirs >= 4) {
1.1.1.2 ! misho    1997:                parse_filter_str(&filter_list, "- /*/*", rule_template(0), 0);
1.1       misho    1998:                recurse = xfer_dirs = 1;
                   1999:        } else if (recurse)
                   2000:                xfer_dirs = 1;
                   2001:        else if (xfer_dirs < 0)
                   2002:                xfer_dirs = list_only ? 1 : 0;
                   2003: 
                   2004:        if (relative_paths < 0)
                   2005:                relative_paths = files_from? 1 : 0;
                   2006:        if (!relative_paths)
                   2007:                implied_dirs = 0;
                   2008: 
                   2009:        if (delete_before + !!delete_during + delete_after > 1) {
                   2010:                snprintf(err_buf, sizeof err_buf,
                   2011:                        "You may not combine multiple --delete-WHEN options.\n");
                   2012:                return 0;
                   2013:        }
                   2014:        if (delete_before || delete_during || delete_after)
                   2015:                delete_mode = 1;
                   2016:        else if (delete_mode || delete_excluded) {
                   2017:                /* Only choose now between before & during if one is refused. */
                   2018:                if (refused_delete_before) {
                   2019:                        if (!refused_delete_during)
                   2020:                                delete_during = 1;
                   2021:                        else {
                   2022:                                create_refuse_error(refused_delete_before);
                   2023:                                return 0;
                   2024:                        }
                   2025:                } else if (refused_delete_during)
                   2026:                        delete_before = 1;
                   2027:                delete_mode = 1;
                   2028:        }
                   2029:        if (!xfer_dirs && delete_mode) {
                   2030:                snprintf(err_buf, sizeof err_buf,
                   2031:                        "--delete does not work without --recursive (-r) or --dirs (-d).\n");
                   2032:                return 0;
                   2033:        }
                   2034: 
1.1.1.2 ! misho    2035:        if (missing_args == 3) /* simplify if both options were specified */
        !          2036:                missing_args = 2;
        !          2037:        if (refused_delete && (delete_mode || missing_args == 2)) {
1.1       misho    2038:                create_refuse_error(refused_delete);
                   2039:                return 0;
                   2040:        }
                   2041: 
                   2042:        if (remove_source_files) {
                   2043:                /* We only want to infer this refusal of --remove-source-files
                   2044:                 * via the refusal of "delete", not any of the "delete-FOO"
                   2045:                 * options. */
                   2046:                if (refused_delete && am_sender) {
                   2047:                        create_refuse_error(refused_delete);
                   2048:                        return 0;
                   2049:                }
                   2050:                need_messages_from_generator = 1;
                   2051:        }
                   2052: 
1.1.1.2 ! misho    2053:        if (munge_symlinks && !am_daemon) {
        !          2054:                STRUCT_STAT st;
        !          2055:                char prefix[SYMLINK_PREFIX_LEN]; /* NOT +1 ! */
        !          2056:                strlcpy(prefix, SYMLINK_PREFIX, sizeof prefix); /* trim the trailing slash */
        !          2057:                if (do_stat(prefix, &st) == 0 && S_ISDIR(st.st_mode)) {
        !          2058:                        rprintf(FERROR, "Symlink munging is unsafe when a %s directory exists.\n",
        !          2059:                                prefix);
        !          2060:                        exit_cleanup(RERR_UNSUPPORTED);
        !          2061:                }
        !          2062:        }
        !          2063: 
1.1       misho    2064:        if (sanitize_paths) {
                   2065:                int i;
                   2066:                for (i = argc; i-- > 0; )
                   2067:                        argv[i] = sanitize_path(NULL, argv[i], "", 0, SP_KEEP_DOT_DIRS);
                   2068:                if (tmpdir)
                   2069:                        tmpdir = sanitize_path(NULL, tmpdir, NULL, 0, SP_DEFAULT);
                   2070:                if (backup_dir)
                   2071:                        backup_dir = sanitize_path(NULL, backup_dir, NULL, 0, SP_DEFAULT);
                   2072:        }
                   2073:        if (daemon_filter_list.head && !am_sender) {
1.1.1.2 ! misho    2074:                filter_rule_list *elp = &daemon_filter_list;
1.1       misho    2075:                if (tmpdir) {
                   2076:                        char *dir;
                   2077:                        if (!*tmpdir)
                   2078:                                goto options_rejected;
                   2079:                        dir = tmpdir + (*tmpdir == '/' ? module_dirlen : 0);
                   2080:                        clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
                   2081:                        if (check_filter(elp, FLOG, dir, 1) < 0)
                   2082:                                goto options_rejected;
                   2083:                }
                   2084:                if (backup_dir) {
                   2085:                        char *dir;
                   2086:                        if (!*backup_dir)
                   2087:                                goto options_rejected;
                   2088:                        dir = backup_dir + (*backup_dir == '/' ? module_dirlen : 0);
                   2089:                        clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
                   2090:                        if (check_filter(elp, FLOG, dir, 1) < 0)
                   2091:                                goto options_rejected;
                   2092:                }
                   2093:        }
                   2094: 
                   2095:        if (!backup_suffix)
                   2096:                backup_suffix = backup_dir ? "" : BACKUP_SUFFIX;
                   2097:        backup_suffix_len = strlen(backup_suffix);
                   2098:        if (strchr(backup_suffix, '/') != NULL) {
                   2099:                snprintf(err_buf, sizeof err_buf,
                   2100:                        "--suffix cannot contain slashes: %s\n",
                   2101:                        backup_suffix);
                   2102:                return 0;
                   2103:        }
                   2104:        if (backup_dir) {
1.1.1.2 ! misho    2105:                size_t len;
        !          2106:                while (*backup_dir == '.' && backup_dir[1] == '/')
        !          2107:                        backup_dir += 2;
        !          2108:                if (*backup_dir == '.' && backup_dir[1] == '\0')
        !          2109:                        backup_dir++;
        !          2110:                len = strlcpy(backup_dir_buf, backup_dir, sizeof backup_dir_buf);
1.1       misho    2111:                if (len > sizeof backup_dir_buf - 128) {
                   2112:                        snprintf(err_buf, sizeof err_buf,
                   2113:                                "the --backup-dir path is WAY too long.\n");
                   2114:                        return 0;
                   2115:                }
                   2116:                backup_dir_len = (int)len;
1.1.1.2 ! misho    2117:                if (!backup_dir_len) {
        !          2118:                        backup_dir_len = -1;
        !          2119:                        backup_dir = NULL;
        !          2120:                } else if (backup_dir_buf[backup_dir_len - 1] != '/') {
1.1       misho    2121:                        backup_dir_buf[backup_dir_len++] = '/';
                   2122:                        backup_dir_buf[backup_dir_len] = '\0';
                   2123:                }
                   2124:                backup_dir_remainder = sizeof backup_dir_buf - backup_dir_len;
1.1.1.2 ! misho    2125:        }
        !          2126:        if (backup_dir) {
        !          2127:                /* No need for a suffix or a protect rule. */
1.1       misho    2128:        } else if (!backup_suffix_len && (!am_server || !am_sender)) {
                   2129:                snprintf(err_buf, sizeof err_buf,
1.1.1.2 ! misho    2130:                        "--suffix cannot be empty %s\n", backup_dir_len < 0
        !          2131:                        ? "when --backup-dir is the same as the dest dir"
        !          2132:                        : "without a --backup-dir");
1.1       misho    2133:                return 0;
                   2134:        } else if (make_backups && delete_mode && !delete_excluded && !am_server) {
                   2135:                snprintf(backup_dir_buf, sizeof backup_dir_buf,
                   2136:                        "P *%s", backup_suffix);
1.1.1.2 ! misho    2137:                parse_filter_str(&filter_list, backup_dir_buf, rule_template(0), 0);
1.1       misho    2138:        }
                   2139: 
                   2140:        if (preserve_times) {
                   2141:                preserve_times = PRESERVE_FILE_TIMES;
                   2142:                if (!omit_dir_times)
                   2143:                        preserve_times |= PRESERVE_DIR_TIMES;
                   2144: #ifdef CAN_SET_SYMLINK_TIMES
1.1.1.2 ! misho    2145:                if (!omit_link_times)
        !          2146:                        preserve_times |= PRESERVE_LINK_TIMES;
1.1       misho    2147: #endif
                   2148:        }
                   2149: 
                   2150:        if (make_backups && !backup_dir) {
                   2151:                omit_dir_times = 0; /* Implied, so avoid -O to sender. */
                   2152:                preserve_times &= ~PRESERVE_DIR_TIMES;
                   2153:        }
                   2154: 
                   2155:        if (stdout_format) {
                   2156:                if (am_server && log_format_has(stdout_format, 'I'))
                   2157:                        stdout_format_has_i = 2;
                   2158:                else if (log_format_has(stdout_format, 'i'))
                   2159:                        stdout_format_has_i = itemize_changes | 1;
                   2160:                if (!log_format_has(stdout_format, 'b')
1.1.1.2 ! misho    2161:                 && !log_format_has(stdout_format, 'c')
        !          2162:                 && !log_format_has(stdout_format, 'C'))
1.1       misho    2163:                        log_before_transfer = !am_server;
                   2164:        } else if (itemize_changes) {
                   2165:                stdout_format = "%i %n%L";
                   2166:                stdout_format_has_i = itemize_changes;
                   2167:                log_before_transfer = !am_server;
                   2168:        }
                   2169: 
1.1.1.2 ! misho    2170:        if (do_progress && !am_server) {
        !          2171:                if (!log_before_transfer && INFO_EQ(NAME, 0))
        !          2172:                        parse_output_words(info_words, info_levels, "name", DEFAULT_PRIORITY);
        !          2173:                parse_output_words(info_words, info_levels, "flist2,progress", DEFAULT_PRIORITY);
        !          2174:        }
1.1       misho    2175: 
                   2176:        if (dry_run)
                   2177:                do_xfers = 0;
                   2178: 
                   2179:        set_io_timeout(io_timeout);
                   2180: 
1.1.1.2 ! misho    2181:        if (INFO_GTE(NAME, 1) && !stdout_format) {
1.1       misho    2182:                stdout_format = "%n%L";
                   2183:                log_before_transfer = !am_server;
                   2184:        }
                   2185:        if (stdout_format_has_i || log_format_has(stdout_format, 'o'))
                   2186:                stdout_format_has_o_or_i = 1;
                   2187: 
                   2188:        if (logfile_name && !am_daemon) {
                   2189:                if (!logfile_format) {
                   2190:                        logfile_format = "%i %n%L";
                   2191:                        logfile_format_has_i = logfile_format_has_o_or_i = 1;
                   2192:                } else {
                   2193:                        if (log_format_has(logfile_format, 'i'))
                   2194:                                logfile_format_has_i = 1;
                   2195:                        if (logfile_format_has_i || log_format_has(logfile_format, 'o'))
                   2196:                                logfile_format_has_o_or_i = 1;
                   2197:                }
                   2198:                log_init(0);
                   2199:        } else if (!am_daemon)
                   2200:                logfile_format = NULL;
                   2201: 
                   2202:        if (daemon_bwlimit && (!bwlimit || bwlimit > daemon_bwlimit))
                   2203:                bwlimit = daemon_bwlimit;
                   2204:        if (bwlimit) {
                   2205:                bwlimit_writemax = (size_t)bwlimit * 128;
                   2206:                if (bwlimit_writemax < 512)
                   2207:                        bwlimit_writemax = 512;
                   2208:        }
                   2209: 
                   2210:        if (sparse_files && inplace) {
                   2211:                /* Note: we don't check for this below, because --append is
                   2212:                 * OK with --sparse (as long as redos are handled right). */
                   2213:                snprintf(err_buf, sizeof err_buf,
                   2214:                         "--sparse cannot be used with --inplace\n");
                   2215:                return 0;
                   2216:        }
                   2217: 
                   2218:        if (append_mode) {
                   2219:                if (whole_file > 0) {
                   2220:                        snprintf(err_buf, sizeof err_buf,
                   2221:                                 "--append cannot be used with --whole-file\n");
                   2222:                        return 0;
                   2223:                }
                   2224:                if (refused_inplace) {
                   2225:                        create_refuse_error(refused_inplace);
                   2226:                        return 0;
                   2227:                }
                   2228:                inplace = 1;
                   2229:        }
                   2230: 
                   2231:        if (delay_updates && !partial_dir)
                   2232:                partial_dir = tmp_partialdir;
                   2233: 
                   2234:        if (inplace) {
                   2235: #ifdef HAVE_FTRUNCATE
                   2236:                if (partial_dir) {
                   2237:                        snprintf(err_buf, sizeof err_buf,
                   2238:                                 "--%s cannot be used with --%s\n",
                   2239:                                 append_mode ? "append" : "inplace",
                   2240:                                 delay_updates ? "delay-updates" : "partial-dir");
                   2241:                        return 0;
                   2242:                }
                   2243:                /* --inplace implies --partial for refusal purposes, but we
                   2244:                 * clear the keep_partial flag for internal logic purposes. */
                   2245:                if (refused_partial) {
                   2246:                        create_refuse_error(refused_partial);
                   2247:                        return 0;
                   2248:                }
                   2249:                keep_partial = 0;
                   2250: #else
                   2251:                snprintf(err_buf, sizeof err_buf,
                   2252:                         "--%s is not supported on this %s\n",
                   2253:                         append_mode ? "append" : "inplace",
                   2254:                         am_server ? "server" : "client");
                   2255:                return 0;
                   2256: #endif
                   2257:        } else {
                   2258:                if (keep_partial && !partial_dir && !am_server) {
                   2259:                        if ((arg = getenv("RSYNC_PARTIAL_DIR")) != NULL && *arg)
                   2260:                                partial_dir = strdup(arg);
                   2261:                }
                   2262:                if (partial_dir) {
                   2263:                        if (*partial_dir)
                   2264:                                clean_fname(partial_dir, CFN_COLLAPSE_DOT_DOT_DIRS);
                   2265:                        if (!*partial_dir || strcmp(partial_dir, ".") == 0)
                   2266:                                partial_dir = NULL;
                   2267:                        if (!partial_dir && refused_partial) {
                   2268:                                create_refuse_error(refused_partial);
                   2269:                                return 0;
                   2270:                        }
                   2271:                        keep_partial = 1;
                   2272:                }
                   2273:        }
                   2274: 
                   2275:        if (files_from) {
                   2276:                char *h, *p;
                   2277:                int q;
1.1.1.2 ! misho    2278:                if (argc > 2 || (!am_daemon && !am_server && argc == 1)) {
1.1       misho    2279:                        usage(FERROR);
                   2280:                        exit_cleanup(RERR_SYNTAX);
                   2281:                }
                   2282:                if (strcmp(files_from, "-") == 0) {
                   2283:                        filesfrom_fd = 0;
                   2284:                        if (am_server)
                   2285:                                filesfrom_host = ""; /* reading from socket */
                   2286:                } else if ((p = check_for_hostspec(files_from, &h, &q)) != 0) {
                   2287:                        if (am_server) {
                   2288:                                snprintf(err_buf, sizeof err_buf,
                   2289:                                        "The --files-from sent to the server cannot specify a host.\n");
                   2290:                                return 0;
                   2291:                        }
                   2292:                        files_from = p;
                   2293:                        filesfrom_host = h;
                   2294:                        if (strcmp(files_from, "-") == 0) {
                   2295:                                snprintf(err_buf, sizeof err_buf,
                   2296:                                        "Invalid --files-from remote filename\n");
                   2297:                                return 0;
                   2298:                        }
                   2299:                } else {
                   2300:                        if (sanitize_paths)
                   2301:                                files_from = sanitize_path(NULL, files_from, NULL, 0, SP_DEFAULT);
                   2302:                        if (daemon_filter_list.head) {
                   2303:                                char *dir;
                   2304:                                if (!*files_from)
                   2305:                                        goto options_rejected;
                   2306:                                dir = files_from + (*files_from == '/' ? module_dirlen : 0);
                   2307:                                clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
                   2308:                                if (check_filter(&daemon_filter_list, FLOG, dir, 0) < 0)
                   2309:                                        goto options_rejected;
                   2310:                        }
                   2311:                        filesfrom_fd = open(files_from, O_RDONLY|O_BINARY);
                   2312:                        if (filesfrom_fd < 0) {
                   2313:                                snprintf(err_buf, sizeof err_buf,
                   2314:                                        "failed to open files-from file %s: %s\n",
                   2315:                                        files_from, strerror(errno));
                   2316:                                return 0;
                   2317:                        }
                   2318:                }
                   2319:        }
                   2320: 
                   2321:        am_starting_up = 0;
                   2322: 
                   2323:        return 1;
                   2324: 
                   2325:   options_rejected:
                   2326:        snprintf(err_buf, sizeof err_buf,
                   2327:                "Your options have been rejected by the server.\n");
                   2328:        return 0;
                   2329: }
                   2330: 
                   2331: 
                   2332: /**
                   2333:  * Construct a filtered list of options to pass through from the
                   2334:  * client to the server.
                   2335:  *
                   2336:  * This involves setting options that will tell the server how to
                   2337:  * behave, and also filtering out options that are processed only
                   2338:  * locally.
                   2339:  **/
                   2340: void server_options(char **args, int *argc_p)
                   2341: {
                   2342:        static char argstr[64];
                   2343:        int ac = *argc_p;
1.1.1.2 ! misho    2344:        uchar where;
1.1       misho    2345:        char *arg;
                   2346:        int i, x;
                   2347: 
                   2348:        /* This should always remain first on the server's command-line. */
                   2349:        args[ac++] = "--server";
                   2350: 
                   2351:        if (daemon_over_rsh > 0) {
                   2352:                args[ac++] = "--daemon";
                   2353:                *argc_p = ac;
                   2354:                /* if we're passing --daemon, we're done */
                   2355:                return;
                   2356:        }
                   2357: 
                   2358:        if (!am_sender)
                   2359:                args[ac++] = "--sender";
                   2360: 
                   2361:        x = 1;
                   2362:        argstr[0] = '-';
                   2363: 
                   2364:        if (protect_args)
                   2365:                argstr[x++] = 's';
                   2366: 
                   2367:        for (i = 0; i < verbose; i++)
                   2368:                argstr[x++] = 'v';
                   2369: 
                   2370:        /* the -q option is intentionally left out */
                   2371:        if (make_backups)
                   2372:                argstr[x++] = 'b';
                   2373:        if (update_only)
                   2374:                argstr[x++] = 'u';
                   2375:        if (!do_xfers) /* Note: NOT "dry_run"! */
                   2376:                argstr[x++] = 'n';
                   2377:        if (preserve_links)
                   2378:                argstr[x++] = 'l';
                   2379:        if ((xfer_dirs >= 2 && xfer_dirs < 4)
                   2380:         || (xfer_dirs && !recurse && (list_only || (delete_mode && am_sender))))
                   2381:                argstr[x++] = 'd';
                   2382:        if (am_sender) {
                   2383:                if (keep_dirlinks)
                   2384:                        argstr[x++] = 'K';
                   2385:                if (prune_empty_dirs)
                   2386:                        argstr[x++] = 'm';
                   2387:                if (omit_dir_times)
                   2388:                        argstr[x++] = 'O';
1.1.1.2 ! misho    2389:                if (omit_link_times)
        !          2390:                        argstr[x++] = 'J';
        !          2391:                if (fuzzy_basis) {
        !          2392:                        argstr[x++] = 'y';
        !          2393:                        if (fuzzy_basis > 1)
        !          2394:                                argstr[x++] = 'y';
        !          2395:                }
1.1       misho    2396:        } else {
                   2397:                if (copy_links)
                   2398:                        argstr[x++] = 'L';
                   2399:                if (copy_dirlinks)
                   2400:                        argstr[x++] = 'k';
                   2401:        }
                   2402: 
                   2403:        if (whole_file > 0)
                   2404:                argstr[x++] = 'W';
                   2405:        /* We don't need to send --no-whole-file, because it's the
                   2406:         * default for remote transfers, and in any case old versions
                   2407:         * of rsync will not understand it. */
                   2408: 
                   2409:        if (preserve_hard_links) {
                   2410:                argstr[x++] = 'H';
                   2411:                if (preserve_hard_links > 1)
                   2412:                        argstr[x++] = 'H';
                   2413:        }
                   2414:        if (preserve_uid)
                   2415:                argstr[x++] = 'o';
                   2416:        if (preserve_gid)
                   2417:                argstr[x++] = 'g';
                   2418:        if (preserve_devices) /* ignore preserve_specials here */
                   2419:                argstr[x++] = 'D';
                   2420:        if (preserve_times)
                   2421:                argstr[x++] = 't';
                   2422:        if (preserve_perms)
                   2423:                argstr[x++] = 'p';
                   2424:        else if (preserve_executability && am_sender)
                   2425:                argstr[x++] = 'E';
                   2426: #ifdef SUPPORT_ACLS
                   2427:        if (preserve_acls)
                   2428:                argstr[x++] = 'A';
                   2429: #endif
                   2430: #ifdef SUPPORT_XATTRS
                   2431:        if (preserve_xattrs) {
                   2432:                argstr[x++] = 'X';
                   2433:                if (preserve_xattrs > 1)
                   2434:                        argstr[x++] = 'X';
                   2435:        }
                   2436: #endif
                   2437:        if (recurse)
                   2438:                argstr[x++] = 'r';
                   2439:        if (always_checksum)
                   2440:                argstr[x++] = 'c';
                   2441:        if (cvs_exclude)
                   2442:                argstr[x++] = 'C';
                   2443:        if (ignore_times)
                   2444:                argstr[x++] = 'I';
                   2445:        if (relative_paths)
                   2446:                argstr[x++] = 'R';
                   2447:        if (one_file_system) {
                   2448:                argstr[x++] = 'x';
                   2449:                if (one_file_system > 1)
                   2450:                        argstr[x++] = 'x';
                   2451:        }
                   2452:        if (sparse_files)
                   2453:                argstr[x++] = 'S';
                   2454:        if (do_compression)
                   2455:                argstr[x++] = 'z';
                   2456: 
                   2457:        set_allow_inc_recurse();
                   2458: 
                   2459:        /* Checking the pre-negotiated value allows --protocol=29 override. */
                   2460:        if (protocol_version >= 30) {
                   2461:                /* We make use of the -e option to let the server know about
                   2462:                 * any pre-release protocol version && some behavior flags. */
                   2463:                argstr[x++] = 'e';
                   2464: #if SUBPROTOCOL_VERSION != 0
                   2465:                if (protocol_version == PROTOCOL_VERSION) {
                   2466:                        x += snprintf(argstr+x, sizeof argstr - x,
                   2467:                                      "%d.%d",
                   2468:                                      PROTOCOL_VERSION, SUBPROTOCOL_VERSION);
                   2469:                } else
                   2470: #endif
                   2471:                        argstr[x++] = '.';
                   2472:                if (allow_inc_recurse)
                   2473:                        argstr[x++] = 'i';
                   2474: #ifdef CAN_SET_SYMLINK_TIMES
                   2475:                argstr[x++] = 'L';
                   2476: #endif
                   2477: #ifdef ICONV_OPTION
                   2478:                argstr[x++] = 's';
                   2479: #endif
                   2480:        }
                   2481: 
                   2482:        if (x >= (int)sizeof argstr) { /* Not possible... */
                   2483:                rprintf(FERROR, "argstr overflow in server_options().\n");
                   2484:                exit_cleanup(RERR_MALLOC);
                   2485:        }
                   2486: 
                   2487:        argstr[x] = '\0';
                   2488: 
                   2489:        if (x > 1)
                   2490:                args[ac++] = argstr;
                   2491: 
                   2492: #ifdef ICONV_OPTION
                   2493:        if (iconv_opt) {
                   2494:                char *set = strchr(iconv_opt, ',');
                   2495:                if (set)
                   2496:                        set++;
                   2497:                else
                   2498:                        set = iconv_opt;
                   2499:                if (asprintf(&arg, "--iconv=%s", set) < 0)
                   2500:                        goto oom;
                   2501:                args[ac++] = arg;
                   2502:        }
                   2503: #endif
                   2504: 
                   2505:        if (protect_args && !local_server) /* unprotected args stop here */
                   2506:                args[ac++] = NULL;
                   2507: 
                   2508:        if (list_only > 1)
                   2509:                args[ac++] = "--list-only";
                   2510: 
                   2511:        /* This makes sure that the remote rsync can handle deleting with -d
                   2512:         * sans -r because the --no-r option was added at the same time. */
                   2513:        if (xfer_dirs && !recurse && delete_mode && am_sender)
                   2514:                args[ac++] = "--no-r";
                   2515: 
                   2516:        if (do_compression && def_compress_level != Z_DEFAULT_COMPRESSION) {
                   2517:                if (asprintf(&arg, "--compress-level=%d", def_compress_level) < 0)
                   2518:                        goto oom;
                   2519:                args[ac++] = arg;
                   2520:        }
                   2521: 
                   2522:        if (preserve_devices) {
                   2523:                /* Note: sending "--devices" would not be backward-compatible. */
                   2524:                if (!preserve_specials)
                   2525:                        args[ac++] = "--no-specials"; /* -D is already set. */
                   2526:        } else if (preserve_specials)
                   2527:                args[ac++] = "--specials";
                   2528: 
                   2529:        /* The server side doesn't use our log-format, but in certain
                   2530:         * circumstances they need to know a little about the option. */
                   2531:        if (stdout_format && am_sender) {
                   2532:                /* Use --log-format, not --out-format, for compatibility. */
                   2533:                if (stdout_format_has_i > 1)
                   2534:                        args[ac++] = "--log-format=%i%I";
                   2535:                else if (stdout_format_has_i)
                   2536:                        args[ac++] = "--log-format=%i";
                   2537:                else if (stdout_format_has_o_or_i)
                   2538:                        args[ac++] = "--log-format=%o";
                   2539:                else if (!verbose)
                   2540:                        args[ac++] = "--log-format=X";
                   2541:        }
                   2542: 
                   2543:        if (block_size) {
                   2544:                if (asprintf(&arg, "-B%lu", block_size) < 0)
                   2545:                        goto oom;
                   2546:                args[ac++] = arg;
                   2547:        }
                   2548: 
                   2549:        if (io_timeout) {
                   2550:                if (asprintf(&arg, "--timeout=%d", io_timeout) < 0)
                   2551:                        goto oom;
                   2552:                args[ac++] = arg;
                   2553:        }
                   2554: 
                   2555:        if (bwlimit) {
                   2556:                if (asprintf(&arg, "--bwlimit=%d", bwlimit) < 0)
                   2557:                        goto oom;
                   2558:                args[ac++] = arg;
                   2559:        }
                   2560: 
                   2561:        if (backup_dir) {
                   2562:                args[ac++] = "--backup-dir";
                   2563:                args[ac++] = backup_dir;
                   2564:        }
                   2565: 
                   2566:        /* Only send --suffix if it specifies a non-default value. */
                   2567:        if (strcmp(backup_suffix, backup_dir ? "" : BACKUP_SUFFIX) != 0) {
                   2568:                /* We use the following syntax to avoid weirdness with '~'. */
                   2569:                if (asprintf(&arg, "--suffix=%s", backup_suffix) < 0)
                   2570:                        goto oom;
                   2571:                args[ac++] = arg;
                   2572:        }
                   2573: 
                   2574:        if (am_sender) {
                   2575:                if (max_delete > 0) {
                   2576:                        if (asprintf(&arg, "--max-delete=%d", max_delete) < 0)
                   2577:                                goto oom;
                   2578:                        args[ac++] = arg;
                   2579:                } else if (max_delete == 0)
                   2580:                        args[ac++] = "--max-delete=-1";
1.1.1.2 ! misho    2581:                if (min_size >= 0) {
1.1       misho    2582:                        args[ac++] = "--min-size";
                   2583:                        args[ac++] = min_size_arg;
                   2584:                }
1.1.1.2 ! misho    2585:                if (max_size >= 0) {
1.1       misho    2586:                        args[ac++] = "--max-size";
                   2587:                        args[ac++] = max_size_arg;
                   2588:                }
                   2589:                if (delete_before)
                   2590:                        args[ac++] = "--delete-before";
                   2591:                else if (delete_during == 2)
                   2592:                        args[ac++] = "--delete-delay";
                   2593:                else if (delete_during)
                   2594:                        args[ac++] = "--delete-during";
                   2595:                else if (delete_after)
                   2596:                        args[ac++] = "--delete-after";
                   2597:                else if (delete_mode && !delete_excluded)
                   2598:                        args[ac++] = "--delete";
                   2599:                if (delete_excluded)
                   2600:                        args[ac++] = "--delete-excluded";
                   2601:                if (force_delete)
                   2602:                        args[ac++] = "--force";
                   2603:                if (write_batch < 0)
                   2604:                        args[ac++] = "--only-write-batch=X";
                   2605:                if (am_root > 1)
                   2606:                        args[ac++] = "--super";
                   2607:                if (size_only)
                   2608:                        args[ac++] = "--size-only";
1.1.1.2 ! misho    2609:                if (do_stats)
        !          2610:                        args[ac++] = "--stats";
1.1       misho    2611:        } else {
                   2612:                if (skip_compress) {
                   2613:                        if (asprintf(&arg, "--skip-compress=%s", skip_compress) < 0)
                   2614:                                goto oom;
                   2615:                        args[ac++] = arg;
                   2616:                }
                   2617:        }
                   2618: 
1.1.1.2 ! misho    2619:        /* --delete-missing-args needs the cooperation of both sides, but
        !          2620:         * the sender can handle --ignore-missing-args by itself. */
        !          2621:        if (missing_args == 2)
        !          2622:                args[ac++] = "--delete-missing-args";
        !          2623:        else if (missing_args == 1 && !am_sender)
        !          2624:                args[ac++] = "--ignore-missing-args";
        !          2625: 
1.1       misho    2626:        if (modify_window_set) {
                   2627:                if (asprintf(&arg, "--modify-window=%d", modify_window) < 0)
                   2628:                        goto oom;
                   2629:                args[ac++] = arg;
                   2630:        }
                   2631: 
                   2632:        if (checksum_seed) {
                   2633:                if (asprintf(&arg, "--checksum-seed=%d", checksum_seed) < 0)
                   2634:                        goto oom;
                   2635:                args[ac++] = arg;
                   2636:        }
                   2637: 
                   2638:        if (partial_dir && am_sender) {
                   2639:                if (partial_dir != tmp_partialdir) {
                   2640:                        args[ac++] = "--partial-dir";
                   2641:                        args[ac++] = partial_dir;
                   2642:                }
                   2643:                if (delay_updates)
                   2644:                        args[ac++] = "--delay-updates";
                   2645:        } else if (keep_partial && am_sender)
                   2646:                args[ac++] = "--partial";
                   2647: 
                   2648:        if (ignore_errors)
                   2649:                args[ac++] = "--ignore-errors";
                   2650: 
                   2651:        if (copy_unsafe_links)
                   2652:                args[ac++] = "--copy-unsafe-links";
                   2653: 
                   2654:        if (safe_symlinks)
                   2655:                args[ac++] = "--safe-links";
                   2656: 
                   2657:        if (numeric_ids)
                   2658:                args[ac++] = "--numeric-ids";
                   2659: 
                   2660:        if (use_qsort)
                   2661:                args[ac++] = "--use-qsort";
                   2662: 
                   2663:        if (am_sender) {
1.1.1.2 ! misho    2664:                if (usermap) {
        !          2665:                        if (asprintf(&arg, "--usermap=%s", usermap) < 0)
        !          2666:                                goto oom;
        !          2667:                        args[ac++] = arg;
        !          2668:                }
        !          2669: 
        !          2670:                if (groupmap) {
        !          2671:                        if (asprintf(&arg, "--groupmap=%s", groupmap) < 0)
        !          2672:                                goto oom;
        !          2673:                        args[ac++] = arg;
        !          2674:                }
        !          2675: 
1.1       misho    2676:                if (ignore_existing)
                   2677:                        args[ac++] = "--ignore-existing";
                   2678: 
                   2679:                /* Backward compatibility: send --existing, not --ignore-non-existing. */
                   2680:                if (ignore_non_existing)
                   2681:                        args[ac++] = "--existing";
                   2682: 
                   2683:                if (tmpdir) {
                   2684:                        args[ac++] = "--temp-dir";
                   2685:                        args[ac++] = tmpdir;
                   2686:                }
                   2687: 
                   2688:                if (basis_dir[0]) {
                   2689:                        /* the server only needs this option if it is not the sender,
                   2690:                         *   and it may be an older version that doesn't know this
                   2691:                         *   option, so don't send it if client is the sender.
                   2692:                         */
                   2693:                        for (i = 0; i < basis_dir_cnt; i++) {
                   2694:                                args[ac++] = dest_option;
                   2695:                                args[ac++] = basis_dir[i];
                   2696:                        }
                   2697:                }
                   2698:        }
                   2699: 
1.1.1.2 ! misho    2700:        /* What flags do we need to send to the other side? */
        !          2701:        where = (am_server ? W_CLI : W_SRV) | (am_sender ? W_REC : W_SND);
        !          2702:        arg = make_output_option(info_words, info_levels, where);
        !          2703:        if (arg)
        !          2704:                args[ac++] = arg;
        !          2705: 
        !          2706:        arg = make_output_option(debug_words, debug_levels, where);
        !          2707:        if (arg)
        !          2708:                args[ac++] = arg;
        !          2709: 
1.1       misho    2710:        if (append_mode) {
                   2711:                if (append_mode > 1)
                   2712:                        args[ac++] = "--append";
                   2713:                args[ac++] = "--append";
                   2714:        } else if (inplace)
                   2715:                args[ac++] = "--inplace";
                   2716: 
                   2717:        if (files_from && (!am_sender || filesfrom_host)) {
                   2718:                if (filesfrom_host) {
                   2719:                        args[ac++] = "--files-from";
                   2720:                        args[ac++] = files_from;
                   2721:                        if (eol_nulls)
                   2722:                                args[ac++] = "--from0";
                   2723:                } else {
                   2724:                        args[ac++] = "--files-from=-";
                   2725:                        args[ac++] = "--from0";
                   2726:                }
                   2727:                if (!relative_paths)
                   2728:                        args[ac++] = "--no-relative";
                   2729:        }
                   2730:        /* It's OK that this checks the upper-bound of the protocol_version. */
                   2731:        if (relative_paths && !implied_dirs && (!am_sender || protocol_version >= 30))
                   2732:                args[ac++] = "--no-implied-dirs";
                   2733: 
                   2734:        if (remove_source_files == 1)
                   2735:                args[ac++] = "--remove-source-files";
                   2736:        else if (remove_source_files)
                   2737:                args[ac++] = "--remove-sent-files";
                   2738: 
1.1.1.2 ! misho    2739:        if (preallocate_files && am_sender)
        !          2740:                args[ac++] = "--preallocate";
        !          2741: 
1.1       misho    2742:        if (ac > MAX_SERVER_ARGS) { /* Not possible... */
                   2743:                rprintf(FERROR, "argc overflow in server_options().\n");
                   2744:                exit_cleanup(RERR_MALLOC);
                   2745:        }
                   2746: 
1.1.1.2 ! misho    2747:        if (remote_option_cnt) {
        !          2748:                int j;
        !          2749:                if (ac + remote_option_cnt > MAX_SERVER_ARGS) {
        !          2750:                        rprintf(FERROR, "too many remote options specified.\n");
        !          2751:                        exit_cleanup(RERR_SYNTAX);
        !          2752:                }
        !          2753:                for (j = 1; j <= remote_option_cnt; j++)
        !          2754:                        args[ac++] = (char*)remote_options[j];
        !          2755:        }
        !          2756: 
1.1       misho    2757:        *argc_p = ac;
                   2758:        return;
                   2759: 
                   2760:     oom:
                   2761:        out_of_memory("server_options");
                   2762: }
                   2763: 
                   2764: /* If str points to a valid hostspec, return allocated memory containing the
                   2765:  * [USER@]HOST part of the string, and set the path_start_ptr to the part of
                   2766:  * the string after the host part.  Otherwise, return NULL.  If port_ptr is
                   2767:  * non-NULL, we must be parsing an rsync:// URL hostname, and we will set
                   2768:  * *port_ptr if a port number is found.  Note that IPv6 IPs will have their
                   2769:  * (required for parsing) [ and ] chars elided from the returned string. */
                   2770: static char *parse_hostspec(char *str, char **path_start_ptr, int *port_ptr)
                   2771: {
                   2772:        char *s, *host_start = str;
                   2773:        int hostlen = 0, userlen = 0;
                   2774:        char *ret;
                   2775: 
                   2776:        for (s = str; ; s++) {
                   2777:                if (!*s) {
                   2778:                        /* It is only OK if we run out of string with rsync:// */
                   2779:                        if (!port_ptr)
                   2780:                                return NULL;
                   2781:                        if (!hostlen)
                   2782:                                hostlen = s - host_start;
                   2783:                        break;
                   2784:                }
                   2785:                if (*s == ':' || *s == '/') {
                   2786:                        if (!hostlen)
                   2787:                                hostlen = s - host_start;
                   2788:                        if (*s++ == '/') {
                   2789:                                if (!port_ptr)
                   2790:                                        return NULL;
                   2791:                        } else if (port_ptr) {
                   2792:                                *port_ptr = atoi(s);
                   2793:                                while (isDigit(s)) s++;
                   2794:                                if (*s && *s++ != '/')
                   2795:                                        return NULL;
                   2796:                        }
                   2797:                        break;
                   2798:                }
                   2799:                if (*s == '@') {
                   2800:                        userlen = s - str + 1;
                   2801:                        host_start = s + 1;
                   2802:                } else if (*s == '[') {
                   2803:                        if (s != host_start++)
                   2804:                                return NULL;
                   2805:                        while (*s && *s != ']' && *s != '/') s++; /*SHARED ITERATOR*/
                   2806:                        hostlen = s - host_start;
                   2807:                        if (*s != ']' || (s[1] && s[1] != '/' && s[1] != ':') || !hostlen)
                   2808:                                return NULL;
                   2809:                }
                   2810:        }
                   2811: 
                   2812:        *path_start_ptr = s;
                   2813:        ret = new_array(char, userlen + hostlen + 1);
                   2814:        if (userlen)
                   2815:                strlcpy(ret, str, userlen + 1);
                   2816:        strlcpy(ret + userlen, host_start, hostlen + 1);
                   2817:        return ret;
                   2818: }
                   2819: 
                   2820: /* Look for a HOST specfication of the form "HOST:PATH", "HOST::PATH", or
                   2821:  * "rsync://HOST:PORT/PATH".  If found, *host_ptr will be set to some allocated
                   2822:  * memory with the HOST.  If a daemon-accessing spec was specified, the value
                   2823:  * of *port_ptr will contain a non-0 port number, otherwise it will be set to
                   2824:  * 0.  The return value is a pointer to the PATH.  Note that the HOST spec can
                   2825:  * be an IPv6 literal address enclosed in '[' and ']' (such as "[::1]" or
                   2826:  * "[::ffff:127.0.0.1]") which is returned without the '[' and ']'. */
                   2827: char *check_for_hostspec(char *s, char **host_ptr, int *port_ptr)
                   2828: {
                   2829:        char *path;
                   2830: 
                   2831:        if (port_ptr && strncasecmp(URL_PREFIX, s, strlen(URL_PREFIX)) == 0) {
                   2832:                *host_ptr = parse_hostspec(s + strlen(URL_PREFIX), &path, port_ptr);
                   2833:                if (*host_ptr) {
                   2834:                        if (!*port_ptr)
                   2835:                                *port_ptr = RSYNC_PORT;
                   2836:                        return path;
                   2837:                }
                   2838:        }
                   2839: 
                   2840:        *host_ptr = parse_hostspec(s, &path, NULL);
                   2841:        if (!*host_ptr)
                   2842:                return NULL;
                   2843: 
                   2844:        if (*path == ':') {
                   2845:                if (port_ptr && !*port_ptr)
                   2846:                        *port_ptr = RSYNC_PORT;
                   2847:                return path + 1;
                   2848:        }
                   2849:        if (port_ptr)
                   2850:                *port_ptr = 0;
                   2851: 
                   2852:        return path;
                   2853: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>