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

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.3 ! misho       6:  * Copyright (C) 2002-2015 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: 
1.1.1.3 ! misho      35: #define NOT_SPECIFIED (-42)
        !            36: 
1.1       misho      37: int make_backups = 0;
                     38: 
                     39: /**
                     40:  * If 1, send the whole file as literal data rather than trying to
                     41:  * create an incremental diff.
                     42:  *
                     43:  * If -1, then look at whether we're local or remote and go by that.
                     44:  *
                     45:  * @sa disable_deltas_p()
                     46:  **/
                     47: int whole_file = -1;
                     48: 
                     49: int append_mode = 0;
                     50: int keep_dirlinks = 0;
                     51: int copy_dirlinks = 0;
                     52: int copy_links = 0;
                     53: int preserve_links = 0;
                     54: int preserve_hard_links = 0;
                     55: int preserve_acls = 0;
                     56: int preserve_xattrs = 0;
                     57: int preserve_perms = 0;
                     58: int preserve_executability = 0;
                     59: int preserve_devices = 0;
                     60: int preserve_specials = 0;
                     61: int preserve_uid = 0;
                     62: int preserve_gid = 0;
                     63: int preserve_times = 0;
                     64: int update_only = 0;
                     65: int cvs_exclude = 0;
                     66: int dry_run = 0;
                     67: int do_xfers = 1;
                     68: int ignore_times = 0;
                     69: int delete_mode = 0;
                     70: int delete_during = 0;
                     71: int delete_before = 0;
                     72: int delete_after = 0;
                     73: int delete_excluded = 0;
                     74: int remove_source_files = 0;
                     75: int one_file_system = 0;
                     76: int protocol_version = PROTOCOL_VERSION;
                     77: int sparse_files = 0;
1.1.1.2   misho      78: int preallocate_files = 0;
1.1       misho      79: int do_compression = 0;
1.1.1.3 ! misho      80: int def_compress_level = NOT_SPECIFIED;
1.1       misho      81: int am_root = 0; /* 0 = normal, 1 = root, 2 = --super, -1 = --fake-super */
                     82: int am_server = 0;
                     83: int am_sender = 0;
                     84: int am_starting_up = 1;
                     85: int relative_paths = -1;
                     86: int implied_dirs = 1;
1.1.1.2   misho      87: int missing_args = 0; /* 0 = FERROR_XFER, 1 = ignore, 2 = delete */
1.1       misho      88: int numeric_ids = 0;
1.1.1.2   misho      89: int msgs2stderr = 0;
1.1       misho      90: int allow_8bit_chars = 0;
                     91: int force_delete = 0;
                     92: int io_timeout = 0;
                     93: int prune_empty_dirs = 0;
                     94: int use_qsort = 0;
                     95: char *files_from = NULL;
                     96: int filesfrom_fd = -1;
                     97: char *filesfrom_host = NULL;
                     98: int eol_nulls = 0;
1.1.1.2   misho      99: int protect_args = -1;
                    100: int human_readable = 1;
1.1       misho     101: int recurse = 0;
                    102: int allow_inc_recurse = 1;
                    103: int xfer_dirs = -1;
                    104: int am_daemon = 0;
                    105: int connect_timeout = 0;
                    106: int keep_partial = 0;
                    107: int safe_symlinks = 0;
                    108: int copy_unsafe_links = 0;
1.1.1.2   misho     109: int munge_symlinks = 0;
1.1       misho     110: int size_only = 0;
                    111: int daemon_bwlimit = 0;
                    112: int bwlimit = 0;
                    113: int fuzzy_basis = 0;
                    114: size_t bwlimit_writemax = 0;
                    115: int ignore_existing = 0;
                    116: int ignore_non_existing = 0;
                    117: int need_messages_from_generator = 0;
                    118: int max_delete = INT_MIN;
1.1.1.2   misho     119: OFF_T max_size = -1;
                    120: OFF_T min_size = -1;
1.1       misho     121: int ignore_errors = 0;
                    122: int modify_window = 0;
                    123: int blocking_io = -1;
                    124: int checksum_seed = 0;
                    125: int inplace = 0;
                    126: int delay_updates = 0;
                    127: long block_size = 0; /* "long" because popt can't set an int32. */
                    128: char *skip_compress = NULL;
1.1.1.2   misho     129: item_list dparam_list = EMPTY_ITEM_LIST;
1.1       misho     130: 
                    131: /** Network address family. **/
                    132: int default_af_hint
                    133: #ifdef INET6
                    134:        = 0;            /* Any protocol */
                    135: #else
                    136:        = AF_INET;      /* Must use IPv4 */
                    137: # ifdef AF_INET6
                    138: #  undef AF_INET6
                    139: # endif
                    140: # define AF_INET6 AF_INET /* make -6 option a no-op */
                    141: #endif
                    142: 
                    143: /** Do not go into the background when run as --daemon.  Good
                    144:  * for debugging and required for running as a service on W32,
                    145:  * or under Unix process-monitors. **/
                    146: int no_detach
                    147: #if defined _WIN32 || defined __WIN32__
                    148:        = 1;
                    149: #else
                    150:        = 0;
                    151: #endif
                    152: 
                    153: int write_batch = 0;
                    154: int read_batch = 0;
                    155: int backup_dir_len = 0;
                    156: int backup_suffix_len;
                    157: unsigned int backup_dir_remainder;
                    158: 
                    159: char *backup_suffix = NULL;
                    160: char *tmpdir = NULL;
                    161: char *partial_dir = NULL;
                    162: char *basis_dir[MAX_BASIS_DIRS+1];
                    163: char *config_file = NULL;
                    164: char *shell_cmd = NULL;
                    165: char *logfile_name = NULL;
                    166: char *logfile_format = NULL;
                    167: char *stdout_format = NULL;
                    168: char *password_file = NULL;
                    169: char *rsync_path = RSYNC_PATH;
                    170: char *backup_dir = NULL;
                    171: char backup_dir_buf[MAXPATHLEN];
                    172: char *sockopts = NULL;
1.1.1.2   misho     173: char *usermap = NULL;
                    174: char *groupmap = NULL;
1.1       misho     175: int rsync_port = 0;
                    176: int compare_dest = 0;
                    177: int copy_dest = 0;
                    178: int link_dest = 0;
                    179: int basis_dir_cnt = 0;
                    180: char *dest_option = NULL;
                    181: 
1.1.1.2   misho     182: static int remote_option_alloc = 0;
                    183: int remote_option_cnt = 0;
                    184: const char **remote_options = NULL;
                    185: 
1.1       misho     186: int quiet = 0;
                    187: int output_motd = 1;
                    188: int log_before_transfer = 0;
                    189: int stdout_format_has_i = 0;
                    190: int stdout_format_has_o_or_i = 0;
                    191: int logfile_format_has_i = 0;
                    192: int logfile_format_has_o_or_i = 0;
                    193: int always_checksum = 0;
                    194: int list_only = 0;
                    195: 
                    196: #define MAX_BATCH_NAME_LEN 256 /* Must be less than MAXPATHLEN-13 */
                    197: char *batch_name = NULL;
                    198: 
                    199: int need_unsorted_flist = 0;
                    200: #ifdef ICONV_OPTION
                    201: char *iconv_opt = ICONV_OPTION;
                    202: #endif
                    203: 
                    204: struct chmod_mode_struct *chmod_modes = NULL;
                    205: 
1.1.1.2   misho     206: static const char *debug_verbosity[] = {
                    207:        /*0*/ NULL,
                    208:        /*1*/ NULL,
                    209:        /*2*/ "BIND,CMD,CONNECT,DEL,DELTASUM,DUP,FILTER,FLIST,ICONV",
                    210:        /*3*/ "ACL,BACKUP,CONNECT2,DELTASUM2,DEL2,EXIT,FILTER2,FLIST2,FUZZY,GENR,OWN,RECV,SEND,TIME",
                    211:        /*4*/ "CMD2,DELTASUM3,DEL3,EXIT2,FLIST3,ICONV2,OWN2,PROTO,TIME2",
                    212:        /*5*/ "CHDIR,DELTASUM4,FLIST4,FUZZY2,HASH,HLINK",
                    213: };
                    214: 
                    215: #define MAX_VERBOSITY ((int)(sizeof debug_verbosity / sizeof debug_verbosity[0]) - 1)
                    216: 
                    217: static const char *info_verbosity[1+MAX_VERBOSITY] = {
                    218:        /*0*/ NULL,
                    219:        /*1*/ "COPY,DEL,FLIST,MISC,NAME,STATS,SYMSAFE",
                    220:        /*2*/ "BACKUP,MISC2,MOUNT,NAME2,REMOVE,SKIP",
                    221: };
                    222: 
                    223: #define MAX_OUT_LEVEL 4 /* The largest N allowed for any flagN word. */
                    224: 
                    225: short info_levels[COUNT_INFO], debug_levels[COUNT_DEBUG];
                    226: 
                    227: #define DEFAULT_PRIORITY 0     /* Default/implied/--verbose set values. */
                    228: #define HELP_PRIORITY 1                /* The help output uses this level. */
                    229: #define USER_PRIORITY 2                /* User-specified via --info or --debug */
                    230: #define LIMIT_PRIORITY 3       /* Overriding priority when limiting values. */
                    231: 
                    232: #define W_CLI (1<<0)   /* client side */
                    233: #define W_SRV (1<<1)   /* server side */
                    234: #define W_SND (1<<2)   /* sending side */
                    235: #define W_REC (1<<3)   /* receiving side */
                    236: 
                    237: struct output_struct {
                    238:        char *name;     /* The name of the info/debug flag. */
                    239:        char *help;     /* The description of the info/debug flag. */
                    240:        uchar namelen;  /* The length of the name string. */
                    241:        uchar flag;     /* The flag's value, for consistency check. */
                    242:        uchar where;    /* Bits indicating where the flag is used. */
                    243:        uchar priority; /* See *_PRIORITY defines. */
                    244: };
                    245: 
                    246: #define INFO_WORD(flag, where, help) { #flag, help, sizeof #flag - 1, INFO_##flag, where, 0 }
                    247: 
                    248: static struct output_struct info_words[COUNT_INFO+1] = {
                    249:        INFO_WORD(BACKUP, W_REC, "Mention files backed up"),
                    250:        INFO_WORD(COPY, W_REC, "Mention files copied locally on the receiving side"),
                    251:        INFO_WORD(DEL, W_REC, "Mention deletions on the receiving side"),
                    252:        INFO_WORD(FLIST, W_CLI, "Mention file-list receiving/sending (levels 1-2)"),
                    253:        INFO_WORD(MISC, W_SND|W_REC, "Mention miscellaneous information (levels 1-2)"),
                    254:        INFO_WORD(MOUNT, W_SND|W_REC, "Mention mounts that were found or skipped"),
                    255:        INFO_WORD(NAME, W_SND|W_REC, "Mention 1) updated file/dir names, 2) unchanged names"),
                    256:        INFO_WORD(PROGRESS, W_CLI, "Mention 1) per-file progress or 2) total transfer progress"),
                    257:        INFO_WORD(REMOVE, W_SND, "Mention files removed on the sending side"),
                    258:        INFO_WORD(SKIP, W_REC, "Mention files that are skipped due to options used"),
                    259:        INFO_WORD(STATS, W_CLI|W_SRV, "Mention statistics at end of run (levels 1-3)"),
                    260:        INFO_WORD(SYMSAFE, W_SND|W_REC, "Mention symlinks that are unsafe"),
                    261:        { NULL, "--info", 0, 0, 0, 0 }
                    262: };
                    263: 
                    264: #define DEBUG_WORD(flag, where, help) { #flag, help, sizeof #flag - 1, DEBUG_##flag, where, 0 }
                    265: 
                    266: static struct output_struct debug_words[COUNT_DEBUG+1] = {
                    267:        DEBUG_WORD(ACL, W_SND|W_REC, "Debug extra ACL info"),
                    268:        DEBUG_WORD(BACKUP, W_REC, "Debug backup actions (levels 1-2)"),
                    269:        DEBUG_WORD(BIND, W_CLI, "Debug socket bind actions"),
                    270:        DEBUG_WORD(CHDIR, W_CLI|W_SRV, "Debug when the current directory changes"),
                    271:        DEBUG_WORD(CONNECT, W_CLI, "Debug connection events (levels 1-2)"),
                    272:        DEBUG_WORD(CMD, W_CLI, "Debug commands+options that are issued (levels 1-2)"),
                    273:        DEBUG_WORD(DEL, W_REC, "Debug delete actions (levels 1-3)"),
                    274:        DEBUG_WORD(DELTASUM, W_SND|W_REC, "Debug delta-transfer checksumming (levels 1-4)"),
                    275:        DEBUG_WORD(DUP, W_REC, "Debug weeding of duplicate names"),
                    276:        DEBUG_WORD(EXIT, W_CLI|W_SRV, "Debug exit events (levels 1-3)"),
                    277:        DEBUG_WORD(FILTER, W_SND|W_REC, "Debug filter actions (levels 1-2)"),
                    278:        DEBUG_WORD(FLIST, W_SND|W_REC, "Debug file-list operations (levels 1-4)"),
                    279:        DEBUG_WORD(FUZZY, W_REC, "Debug fuzzy scoring (levels 1-2)"),
                    280:        DEBUG_WORD(GENR, W_REC, "Debug generator functions"),
                    281:        DEBUG_WORD(HASH, W_SND|W_REC, "Debug hashtable code"),
                    282:        DEBUG_WORD(HLINK, W_SND|W_REC, "Debug hard-link actions (levels 1-3)"),
                    283:        DEBUG_WORD(ICONV, W_CLI|W_SRV, "Debug iconv character conversions (levels 1-2)"),
                    284:        DEBUG_WORD(IO, W_CLI|W_SRV, "Debug I/O routines (levels 1-4)"),
                    285:        DEBUG_WORD(OWN, W_REC, "Debug ownership changes in users & groups (levels 1-2)"),
                    286:        DEBUG_WORD(PROTO, W_CLI|W_SRV, "Debug protocol information"),
                    287:        DEBUG_WORD(RECV, W_REC, "Debug receiver functions"),
                    288:        DEBUG_WORD(SEND, W_SND, "Debug sender functions"),
                    289:        DEBUG_WORD(TIME, W_REC, "Debug setting of modified times (levels 1-2)"),
                    290:        { NULL, "--debug", 0, 0, 0, 0 }
                    291: };
                    292: 
                    293: static int verbose = 0;
                    294: static int do_stats = 0;
                    295: static int do_progress = 0;
1.1       misho     296: static int daemon_opt;   /* sets am_daemon after option error-reporting */
                    297: static int omit_dir_times = 0;
1.1.1.2   misho     298: static int omit_link_times = 0;
1.1       misho     299: static int F_option_cnt = 0;
                    300: static int modify_window_set;
                    301: static int itemize_changes = 0;
                    302: static int refused_delete, refused_archive_part, refused_compress;
                    303: static int refused_partial, refused_progress, refused_delete_before;
                    304: static int refused_delete_during;
                    305: static int refused_inplace, refused_no_iconv;
1.1.1.2   misho     306: static BOOL usermap_via_chown, groupmap_via_chown;
                    307: #ifdef HAVE_SETVBUF
                    308: static char *outbuf_mode;
                    309: #endif
                    310: static char *bwlimit_arg, *max_size_arg, *min_size_arg;
1.1       misho     311: static char tmp_partialdir[] = ".~tmp~";
                    312: 
                    313: /** Local address to bind.  As a character string because it's
                    314:  * interpreted by the IPv6 layer: should be a numeric IP4 or IP6
                    315:  * address, or a hostname. **/
                    316: char *bind_address;
                    317: 
1.1.1.2   misho     318: static void output_item_help(struct output_struct *words);
                    319: 
                    320: /* This constructs a string that represents all the options set for either
                    321:  * the --info or --debug setting, skipping any implied options (by -v, etc.).
                    322:  * This is used both when conveying the user's options to the server, and
                    323:  * when the help output wants to tell the user what options are implied. */
                    324: static char *make_output_option(struct output_struct *words, short *levels, uchar where)
                    325: {
                    326:        char *str = words == info_words ? "--info=" : "--debug=";
                    327:        int j, counts[MAX_OUT_LEVEL+1], pos, skipped = 0, len = 0, max = 0, lev = 0;
                    328:        int word_count = words == info_words ? COUNT_INFO : COUNT_DEBUG;
                    329:        char *buf;
                    330: 
                    331:        memset(counts, 0, sizeof counts);
                    332: 
                    333:        for (j = 0; words[j].name; j++) {
                    334:                if (words[j].flag != j) {
                    335:                        rprintf(FERROR, "rsync: internal error on %s%s: %d != %d\n",
                    336:                                words == info_words ? "INFO_" : "DEBUG_",
                    337:                                words[j].name, words[j].flag, j);
                    338:                        exit_cleanup(RERR_UNSUPPORTED);
                    339:                }
                    340:                if (!(words[j].where & where))
                    341:                        continue;
                    342:                if (words[j].priority == DEFAULT_PRIORITY) {
                    343:                        /* Implied items don't need to be mentioned. */
                    344:                        skipped++;
                    345:                        continue;
                    346:                }
                    347:                len += len ? 1 : strlen(str);
                    348:                len += strlen(words[j].name);
                    349:                len += levels[j] == 1 ? 0 : 1;
                    350: 
                    351:                if (words[j].priority == HELP_PRIORITY)
                    352:                        continue; /* no abbreviating for help */
                    353: 
                    354:                assert(levels[j] <= MAX_OUT_LEVEL);
                    355:                if (++counts[levels[j]] > max) {
                    356:                        /* Determine which level has the most items. */
                    357:                        lev = levels[j];
                    358:                        max = counts[lev];
                    359:                }
                    360:        }
                    361: 
                    362:        /* Sanity check the COUNT_* define against the length of the table. */
                    363:        if (j != word_count) {
                    364:                rprintf(FERROR, "rsync: internal error: %s is wrong! (%d != %d)\n",
                    365:                        words == info_words ? "COUNT_INFO" : "COUNT_DEBUG",
                    366:                        j, word_count);
                    367:                exit_cleanup(RERR_UNSUPPORTED);
                    368:        }
                    369: 
                    370:        if (!len)
                    371:                return NULL;
                    372: 
                    373:        len++;
                    374:        if (!(buf = new_array(char, len)))
                    375:                out_of_memory("make_output_option");
                    376:        pos = 0;
                    377: 
                    378:        if (skipped || max < 5)
                    379:                lev = -1;
                    380:        else {
                    381:                if (lev == 0)
                    382:                        pos += snprintf(buf, len, "%sNONE", str);
                    383:                else if (lev == 1)
                    384:                        pos += snprintf(buf, len, "%sALL", str);
                    385:                else
                    386:                        pos += snprintf(buf, len, "%sALL%d", str, lev);
                    387:        }
                    388: 
                    389:        for (j = 0; words[j].name && pos < len; j++) {
                    390:                if (words[j].priority == DEFAULT_PRIORITY || levels[j] == lev || !(words[j].where & where))
                    391:                        continue;
                    392:                if (pos)
                    393:                        buf[pos++] = ',';
                    394:                else
                    395:                        pos += strlcpy(buf+pos, str, len-pos);
                    396:                if (pos < len)
                    397:                        pos += strlcpy(buf+pos, words[j].name, len-pos);
                    398:                /* Level 1 is implied by the name alone. */
                    399:                if (levels[j] != 1 && pos < len)
                    400:                        buf[pos++] = '0' + levels[j];
                    401:        }
                    402: 
                    403:        buf[pos] = '\0';
                    404: 
                    405:        return buf;
                    406: }
                    407: 
                    408: static void parse_output_words(struct output_struct *words, short *levels,
                    409:                               const char *str, uchar priority)
                    410: {
                    411:        const char *s;
                    412:        int j, len, lev;
                    413: 
1.1.1.3 ! misho     414:        for ( ; str; str = s) {
1.1.1.2   misho     415:                if ((s = strchr(str, ',')) != NULL)
                    416:                        len = s++ - str;
                    417:                else
                    418:                        len = strlen(str);
1.1.1.3 ! misho     419:                if (!len)
        !           420:                        continue;
        !           421:                if (!isDigit(str)) {
        !           422:                        while (len && isDigit(str+len-1))
        !           423:                                len--;
        !           424:                }
1.1.1.2   misho     425:                lev = isDigit(str+len) ? atoi(str+len) : 1;
                    426:                if (lev > MAX_OUT_LEVEL)
                    427:                        lev = MAX_OUT_LEVEL;
                    428:                if (len == 4 && strncasecmp(str, "help", 4) == 0) {
                    429:                        output_item_help(words);
                    430:                        exit_cleanup(0);
                    431:                }
                    432:                if (len == 4 && strncasecmp(str, "none", 4) == 0)
                    433:                        len = lev = 0;
                    434:                else if (len == 3 && strncasecmp(str, "all", 3) == 0)
                    435:                        len = 0;
                    436:                for (j = 0; words[j].name; j++) {
                    437:                        if (!len
                    438:                         || (len == words[j].namelen && strncasecmp(str, words[j].name, len) == 0)) {
                    439:                                if (priority >= words[j].priority) {
                    440:                                        words[j].priority = priority;
                    441:                                        levels[j] = lev;
                    442:                                }
                    443:                                if (len)
                    444:                                        break;
                    445:                        }
                    446:                }
                    447:                if (len && !words[j].name) {
                    448:                        rprintf(FERROR, "Unknown %s item: \"%.*s\"\n",
                    449:                                words[j].help, len, str);
                    450:                        exit_cleanup(RERR_SYNTAX);
                    451:                }
                    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.3 ! misho     614:        rprintf(f, "Copyright (C) 1996-2015 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 },
1.1.1.3 ! misho     968:   {"old-compress",     0,  POPT_ARG_VAL,    &do_compression, 1, 0, 0 },
        !           969:   {"new-compress",     0,  POPT_ARG_VAL,    &do_compression, 2, 0, 0 },
1.1       misho     970:   {"no-compress",      0,  POPT_ARG_VAL,    &do_compression, 0, 0, 0 },
                    971:   {"no-z",             0,  POPT_ARG_VAL,    &do_compression, 0, 0, 0 },
                    972:   {"skip-compress",    0,  POPT_ARG_STRING, &skip_compress, 0, 0, 0 },
1.1.1.3 ! misho     973:   {"compress-level",   0,  POPT_ARG_INT,    &def_compress_level, 0, 0, 0 },
1.1       misho     974:   {0,                 'P', POPT_ARG_NONE,   0, 'P', 0, 0 },
                    975:   {"progress",         0,  POPT_ARG_VAL,    &do_progress, 1, 0, 0 },
                    976:   {"no-progress",      0,  POPT_ARG_VAL,    &do_progress, 0, 0, 0 },
                    977:   {"partial",          0,  POPT_ARG_VAL,    &keep_partial, 1, 0, 0 },
                    978:   {"no-partial",       0,  POPT_ARG_VAL,    &keep_partial, 0, 0, 0 },
                    979:   {"partial-dir",      0,  POPT_ARG_STRING, &partial_dir, 0, 0, 0 },
                    980:   {"delay-updates",    0,  POPT_ARG_VAL,    &delay_updates, 1, 0, 0 },
                    981:   {"no-delay-updates", 0,  POPT_ARG_VAL,    &delay_updates, 0, 0, 0 },
                    982:   {"prune-empty-dirs",'m', POPT_ARG_VAL,    &prune_empty_dirs, 1, 0, 0 },
                    983:   {"no-prune-empty-dirs",0,POPT_ARG_VAL,    &prune_empty_dirs, 0, 0, 0 },
                    984:   {"no-m",             0,  POPT_ARG_VAL,    &prune_empty_dirs, 0, 0, 0 },
                    985:   {"log-file",         0,  POPT_ARG_STRING, &logfile_name, 0, 0, 0 },
                    986:   {"log-file-format",  0,  POPT_ARG_STRING, &logfile_format, 0, 0, 0 },
                    987:   {"out-format",       0,  POPT_ARG_STRING, &stdout_format, 0, 0, 0 },
                    988:   {"log-format",       0,  POPT_ARG_STRING, &stdout_format, 0, 0, 0 }, /* DEPRECATED */
                    989:   {"itemize-changes", 'i', POPT_ARG_NONE,   0, 'i', 0, 0 },
                    990:   {"no-itemize-changes",0, POPT_ARG_VAL,    &itemize_changes, 0, 0, 0 },
                    991:   {"no-i",             0,  POPT_ARG_VAL,    &itemize_changes, 0, 0, 0 },
1.1.1.2   misho     992:   {"bwlimit",          0,  POPT_ARG_STRING, &bwlimit_arg, OPT_BWLIMIT, 0, 0 },
1.1       misho     993:   {"no-bwlimit",       0,  POPT_ARG_VAL,    &bwlimit, 0, 0, 0 },
                    994:   {"backup",          'b', POPT_ARG_VAL,    &make_backups, 1, 0, 0 },
                    995:   {"no-backup",        0,  POPT_ARG_VAL,    &make_backups, 0, 0, 0 },
                    996:   {"backup-dir",       0,  POPT_ARG_STRING, &backup_dir, 0, 0, 0 },
                    997:   {"suffix",           0,  POPT_ARG_STRING, &backup_suffix, 0, 0, 0 },
                    998:   {"list-only",        0,  POPT_ARG_VAL,    &list_only, 2, 0, 0 },
                    999:   {"read-batch",       0,  POPT_ARG_STRING, &batch_name, OPT_READ_BATCH, 0, 0 },
                   1000:   {"write-batch",      0,  POPT_ARG_STRING, &batch_name, OPT_WRITE_BATCH, 0, 0 },
                   1001:   {"only-write-batch", 0,  POPT_ARG_STRING, &batch_name, OPT_ONLY_WRITE_BATCH, 0, 0 },
                   1002:   {"files-from",       0,  POPT_ARG_STRING, &files_from, 0, 0, 0 },
                   1003:   {"from0",           '0', POPT_ARG_VAL,    &eol_nulls, 1, 0, 0},
                   1004:   {"no-from0",         0,  POPT_ARG_VAL,    &eol_nulls, 0, 0, 0},
                   1005:   {"protect-args",    's', POPT_ARG_VAL,    &protect_args, 1, 0, 0},
                   1006:   {"no-protect-args",  0,  POPT_ARG_VAL,    &protect_args, 0, 0, 0},
                   1007:   {"no-s",             0,  POPT_ARG_VAL,    &protect_args, 0, 0, 0},
                   1008:   {"numeric-ids",      0,  POPT_ARG_VAL,    &numeric_ids, 1, 0, 0 },
                   1009:   {"no-numeric-ids",   0,  POPT_ARG_VAL,    &numeric_ids, 0, 0, 0 },
1.1.1.2   misho    1010:   {"usermap",          0,  POPT_ARG_STRING, 0, OPT_USERMAP, 0, 0 },
                   1011:   {"groupmap",         0,  POPT_ARG_STRING, 0, OPT_GROUPMAP, 0, 0 },
                   1012:   {"chown",            0,  POPT_ARG_STRING, 0, OPT_CHOWN, 0, 0 },
1.1       misho    1013:   {"timeout",          0,  POPT_ARG_INT,    &io_timeout, 0, 0, 0 },
                   1014:   {"no-timeout",       0,  POPT_ARG_VAL,    &io_timeout, 0, 0, 0 },
                   1015:   {"contimeout",       0,  POPT_ARG_INT,    &connect_timeout, 0, 0, 0 },
                   1016:   {"no-contimeout",    0,  POPT_ARG_VAL,    &connect_timeout, 0, 0, 0 },
                   1017:   {"rsh",             'e', POPT_ARG_STRING, &shell_cmd, 0, 0, 0 },
                   1018:   {"rsync-path",       0,  POPT_ARG_STRING, &rsync_path, 0, 0, 0 },
                   1019:   {"temp-dir",        'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
                   1020: #ifdef ICONV_OPTION
                   1021:   {"iconv",            0,  POPT_ARG_STRING, &iconv_opt, 0, 0, 0 },
                   1022:   {"no-iconv",         0,  POPT_ARG_NONE,   0, OPT_NO_ICONV, 0, 0 },
                   1023: #endif
                   1024:   {"ipv4",            '4', POPT_ARG_VAL,    &default_af_hint, AF_INET, 0, 0 },
                   1025:   {"ipv6",            '6', POPT_ARG_VAL,    &default_af_hint, AF_INET6, 0, 0 },
                   1026:   {"8-bit-output",    '8', POPT_ARG_VAL,    &allow_8bit_chars, 1, 0, 0 },
                   1027:   {"no-8-bit-output",  0,  POPT_ARG_VAL,    &allow_8bit_chars, 0, 0, 0 },
                   1028:   {"no-8",             0,  POPT_ARG_VAL,    &allow_8bit_chars, 0, 0, 0 },
                   1029:   {"qsort",            0,  POPT_ARG_NONE,   &use_qsort, 0, 0, 0 },
                   1030:   {"address",          0,  POPT_ARG_STRING, &bind_address, 0, 0, 0 },
                   1031:   {"port",             0,  POPT_ARG_INT,    &rsync_port, 0, 0, 0 },
                   1032:   {"sockopts",         0,  POPT_ARG_STRING, &sockopts, 0, 0, 0 },
                   1033:   {"password-file",    0,  POPT_ARG_STRING, &password_file, 0, 0, 0 },
                   1034:   {"blocking-io",      0,  POPT_ARG_VAL,    &blocking_io, 1, 0, 0 },
                   1035:   {"no-blocking-io",   0,  POPT_ARG_VAL,    &blocking_io, 0, 0, 0 },
1.1.1.2   misho    1036: #ifdef HAVE_SETVBUF
                   1037:   {"outbuf",           0,  POPT_ARG_STRING, &outbuf_mode, 0, 0, 0 },
                   1038: #endif
                   1039:   {"remote-option",   'M', POPT_ARG_STRING, 0, 'M', 0, 0 },
1.1       misho    1040:   {"protocol",         0,  POPT_ARG_INT,    &protocol_version, 0, 0, 0 },
                   1041:   {"checksum-seed",    0,  POPT_ARG_INT,    &checksum_seed, 0, 0, 0 },
                   1042:   {"server",           0,  POPT_ARG_NONE,   0, OPT_SERVER, 0, 0 },
                   1043:   {"sender",           0,  POPT_ARG_NONE,   0, OPT_SENDER, 0, 0 },
                   1044:   /* All the following options switch us into daemon-mode option-parsing. */
                   1045:   {"config",           0,  POPT_ARG_STRING, 0, OPT_DAEMON, 0, 0 },
                   1046:   {"daemon",           0,  POPT_ARG_NONE,   0, OPT_DAEMON, 0, 0 },
1.1.1.2   misho    1047:   {"dparam",           0,  POPT_ARG_STRING, 0, OPT_DAEMON, 0, 0 },
1.1       misho    1048:   {"detach",           0,  POPT_ARG_NONE,   0, OPT_DAEMON, 0, 0 },
                   1049:   {"no-detach",        0,  POPT_ARG_NONE,   0, OPT_DAEMON, 0, 0 },
                   1050:   {0,0,0,0, 0, 0, 0}
                   1051: };
                   1052: 
                   1053: static void daemon_usage(enum logcode F)
                   1054: {
                   1055:   print_rsync_version(F);
                   1056: 
                   1057:   rprintf(F,"\n");
                   1058:   rprintf(F,"Usage: rsync --daemon [OPTION]...\n");
                   1059:   rprintf(F,"     --address=ADDRESS       bind to the specified address\n");
1.1.1.2   misho    1060:   rprintf(F,"     --bwlimit=RATE          limit socket I/O bandwidth\n");
1.1       misho    1061:   rprintf(F,"     --config=FILE           specify alternate rsyncd.conf file\n");
1.1.1.2   misho    1062:   rprintf(F," -M, --dparam=OVERRIDE       override global daemon config parameter\n");
1.1       misho    1063:   rprintf(F,"     --no-detach             do not detach from the parent\n");
                   1064:   rprintf(F,"     --port=PORT             listen on alternate port number\n");
                   1065:   rprintf(F,"     --log-file=FILE         override the \"log file\" setting\n");
                   1066:   rprintf(F,"     --log-file-format=FMT   override the \"log format\" setting\n");
                   1067:   rprintf(F,"     --sockopts=OPTIONS      specify custom TCP options\n");
                   1068:   rprintf(F," -v, --verbose               increase verbosity\n");
                   1069:   rprintf(F," -4, --ipv4                  prefer IPv4\n");
                   1070:   rprintf(F," -6, --ipv6                  prefer IPv6\n");
                   1071:   rprintf(F,"     --help                  show this help screen\n");
                   1072: 
                   1073:   rprintf(F,"\n");
                   1074:   rprintf(F,"If you were not trying to invoke rsync as a daemon, avoid using any of the\n");
                   1075:   rprintf(F,"daemon-specific rsync options.  See also the rsyncd.conf(5) man page.\n");
                   1076: }
                   1077: 
                   1078: static struct poptOption long_daemon_options[] = {
                   1079:   /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
                   1080:   {"address",          0,  POPT_ARG_STRING, &bind_address, 0, 0, 0 },
                   1081:   {"bwlimit",          0,  POPT_ARG_INT,    &daemon_bwlimit, 0, 0, 0 },
                   1082:   {"config",           0,  POPT_ARG_STRING, &config_file, 0, 0, 0 },
                   1083:   {"daemon",           0,  POPT_ARG_NONE,   &daemon_opt, 0, 0, 0 },
1.1.1.2   misho    1084:   {"dparam",          'M', POPT_ARG_STRING, 0, 'M', 0, 0 },
1.1       misho    1085:   {"ipv4",            '4', POPT_ARG_VAL,    &default_af_hint, AF_INET, 0, 0 },
                   1086:   {"ipv6",            '6', POPT_ARG_VAL,    &default_af_hint, AF_INET6, 0, 0 },
                   1087:   {"detach",           0,  POPT_ARG_VAL,    &no_detach, 0, 0, 0 },
                   1088:   {"no-detach",        0,  POPT_ARG_VAL,    &no_detach, 1, 0, 0 },
                   1089:   {"log-file",         0,  POPT_ARG_STRING, &logfile_name, 0, 0, 0 },
                   1090:   {"log-file-format",  0,  POPT_ARG_STRING, &logfile_format, 0, 0, 0 },
                   1091:   {"port",             0,  POPT_ARG_INT,    &rsync_port, 0, 0, 0 },
                   1092:   {"sockopts",         0,  POPT_ARG_STRING, &sockopts, 0, 0, 0 },
                   1093:   {"protocol",         0,  POPT_ARG_INT,    &protocol_version, 0, 0, 0 },
                   1094:   {"server",           0,  POPT_ARG_NONE,   &am_server, 0, 0, 0 },
                   1095:   {"temp-dir",        'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
                   1096:   {"verbose",         'v', POPT_ARG_NONE,   0, 'v', 0, 0 },
                   1097:   {"no-verbose",       0,  POPT_ARG_VAL,    &verbose, 0, 0, 0 },
                   1098:   {"no-v",             0,  POPT_ARG_VAL,    &verbose, 0, 0, 0 },
                   1099:   {"help",            'h', POPT_ARG_NONE,   0, 'h', 0, 0 },
                   1100:   {0,0,0,0, 0, 0, 0}
                   1101: };
                   1102: 
                   1103: 
                   1104: static char err_buf[200];
                   1105: 
                   1106: 
                   1107: /**
                   1108:  * Store the option error message, if any, so that we can log the
                   1109:  * connection attempt (which requires parsing the options), and then
                   1110:  * show the error later on.
                   1111:  **/
                   1112: void option_error(void)
                   1113: {
                   1114:        if (!err_buf[0]) {
                   1115:                strlcpy(err_buf, "Error parsing options: option may "
                   1116:                        "be supported on client but not on server?\n",
                   1117:                        sizeof err_buf);
                   1118:        }
                   1119: 
                   1120:        rprintf(FERROR, RSYNC_NAME ": %s", err_buf);
                   1121:        msleep(20);
                   1122: }
                   1123: 
                   1124: 
                   1125: /**
                   1126:  * Tweak the option table to disable all options that the rsyncd.conf
                   1127:  * file has told us to refuse.
                   1128:  **/
                   1129: static void set_refuse_options(char *bp)
                   1130: {
                   1131:        struct poptOption *op;
                   1132:        char *cp, shortname[2];
                   1133:        int is_wild, found_match;
                   1134: 
                   1135:        shortname[1] = '\0';
                   1136: 
                   1137:        while (1) {
                   1138:                while (*bp == ' ') bp++;
                   1139:                if (!*bp)
                   1140:                        break;
                   1141:                if ((cp = strchr(bp, ' ')) != NULL)
                   1142:                        *cp= '\0';
                   1143:                is_wild = strpbrk(bp, "*?[") != NULL;
                   1144:                found_match = 0;
                   1145:                for (op = long_options; ; op++) {
                   1146:                        *shortname = op->shortName;
                   1147:                        if (!op->longName && !*shortname)
                   1148:                                break;
                   1149:                        if ((op->longName && wildmatch(bp, op->longName))
                   1150:                            || (*shortname && wildmatch(bp, shortname))) {
                   1151:                                if (op->argInfo == POPT_ARG_VAL)
                   1152:                                        op->argInfo = POPT_ARG_NONE;
                   1153:                                op->val = (op - long_options) + OPT_REFUSED_BASE;
                   1154:                                found_match = 1;
                   1155:                                /* These flags are set to let us easily check
                   1156:                                 * an implied option later in the code. */
                   1157:                                switch (*shortname) {
                   1158:                                case 'r': case 'd': case 'l': case 'p':
                   1159:                                case 't': case 'g': case 'o': case 'D':
                   1160:                                        refused_archive_part = op->val;
                   1161:                                        break;
                   1162:                                case 'z':
                   1163:                                        refused_compress = op->val;
                   1164:                                        break;
                   1165:                                case '\0':
                   1166:                                        if (wildmatch("delete", op->longName))
                   1167:                                                refused_delete = op->val;
                   1168:                                        else if (wildmatch("delete-before", op->longName))
                   1169:                                                refused_delete_before = op->val;
                   1170:                                        else if (wildmatch("delete-during", op->longName))
                   1171:                                                refused_delete_during = op->val;
                   1172:                                        else if (wildmatch("partial", op->longName))
                   1173:                                                refused_partial = op->val;
                   1174:                                        else if (wildmatch("progress", op->longName))
                   1175:                                                refused_progress = op->val;
                   1176:                                        else if (wildmatch("inplace", op->longName))
                   1177:                                                refused_inplace = op->val;
                   1178:                                        else if (wildmatch("no-iconv", op->longName))
                   1179:                                                refused_no_iconv = op->val;
                   1180:                                        break;
                   1181:                                }
                   1182:                                if (!is_wild)
                   1183:                                        break;
                   1184:                        }
                   1185:                }
                   1186:                if (!found_match) {
                   1187:                        rprintf(FLOG, "No match for refuse-options string \"%s\"\n",
                   1188:                                bp);
                   1189:                }
                   1190:                if (!cp)
                   1191:                        break;
                   1192:                *cp = ' ';
                   1193:                bp = cp + 1;
                   1194:        }
                   1195: }
                   1196: 
                   1197: 
                   1198: static int count_args(const char **argv)
                   1199: {
                   1200:        int i = 0;
                   1201: 
                   1202:        if (argv) {
                   1203:                while (argv[i] != NULL)
                   1204:                        i++;
                   1205:        }
                   1206: 
                   1207:        return i;
                   1208: }
                   1209: 
                   1210: 
                   1211: static OFF_T parse_size_arg(char **size_arg, char def_suf)
                   1212: {
                   1213:        int reps, mult, make_compatible = 0;
                   1214:        const char *arg;
                   1215:        OFF_T size = 1;
                   1216: 
                   1217:        for (arg = *size_arg; isDigit(arg); arg++) {}
                   1218:        if (*arg == '.')
                   1219:                for (arg++; isDigit(arg); arg++) {}
                   1220:        switch (*arg && *arg != '+' && *arg != '-' ? *arg++ : def_suf) {
                   1221:        case 'b': case 'B':
                   1222:                reps = 0;
                   1223:                break;
                   1224:        case 'k': case 'K':
                   1225:                reps = 1;
                   1226:                break;
                   1227:        case 'm': case 'M':
                   1228:                reps = 2;
                   1229:                break;
                   1230:        case 'g': case 'G':
                   1231:                reps = 3;
                   1232:                break;
                   1233:        default:
                   1234:                return -1;
                   1235:        }
                   1236:        if (*arg == 'b' || *arg == 'B')
                   1237:                mult = 1000, make_compatible = 1, arg++;
                   1238:        else if (!*arg || *arg == '+' || *arg == '-')
                   1239:                mult = 1024;
                   1240:        else if (strncasecmp(arg, "ib", 2) == 0)
                   1241:                mult = 1024, arg += 2;
                   1242:        else
                   1243:                return -1;
                   1244:        while (reps--)
                   1245:                size *= mult;
                   1246:        size *= atof(*size_arg);
                   1247:        if ((*arg == '+' || *arg == '-') && arg[1] == '1')
                   1248:                size += atoi(arg), make_compatible = 1, arg += 2;
                   1249:        if (*arg)
                   1250:                return -1;
1.1.1.2   misho    1251:        if (size > 0 && make_compatible && def_suf == 'b') {
1.1       misho    1252:                /* We convert this manually because we may need %lld precision,
                   1253:                 * and that's not a portable sprintf() escape. */
                   1254:                char buf[128], *s = buf + sizeof buf - 1;
                   1255:                OFF_T num = size;
                   1256:                *s = '\0';
                   1257:                while (num) {
                   1258:                        *--s = (char)(num % 10) + '0';
                   1259:                        num /= 10;
                   1260:                }
                   1261:                if (!(*size_arg = strdup(s)))
                   1262:                        out_of_memory("parse_size_arg");
                   1263:        }
                   1264:        return size;
                   1265: }
                   1266: 
                   1267: 
                   1268: static void create_refuse_error(int which)
                   1269: {
                   1270:        /* The "which" value is the index + OPT_REFUSED_BASE. */
                   1271:        struct poptOption *op = &long_options[which - OPT_REFUSED_BASE];
                   1272:        int n = snprintf(err_buf, sizeof err_buf,
                   1273:                         "The server is configured to refuse --%s\n",
                   1274:                         op->longName) - 1;
                   1275:        if (op->shortName) {
                   1276:                snprintf(err_buf + n, sizeof err_buf - n,
                   1277:                         " (-%c)\n", op->shortName);
                   1278:        }
                   1279: }
                   1280: 
                   1281: 
                   1282: /**
                   1283:  * Process command line arguments.  Called on both local and remote.
                   1284:  *
                   1285:  * @retval 1 if all options are OK; with globals set to appropriate
                   1286:  * values
                   1287:  *
                   1288:  * @retval 0 on error, with err_buf containing an explanation
                   1289:  **/
                   1290: int parse_arguments(int *argc_p, const char ***argv_p)
                   1291: {
                   1292:        static poptContext pc;
                   1293:        char *ref = lp_refuse_options(module_id);
                   1294:        const char *arg, **argv = *argv_p;
                   1295:        int argc = *argc_p;
                   1296:        int opt;
                   1297: 
                   1298:        if (ref && *ref)
                   1299:                set_refuse_options(ref);
                   1300:        if (am_daemon) {
                   1301:                set_refuse_options("log-file*");
                   1302: #ifdef ICONV_OPTION
                   1303:                if (!*lp_charset(module_id))
                   1304:                        set_refuse_options("iconv");
                   1305: #endif
                   1306:        }
                   1307: 
                   1308: #ifdef ICONV_OPTION
1.1.1.2   misho    1309:        if (!am_daemon && protect_args <= 0 && (arg = getenv("RSYNC_ICONV")) != NULL && *arg)
1.1       misho    1310:                iconv_opt = strdup(arg);
                   1311: #endif
                   1312: 
                   1313:        /* TODO: Call poptReadDefaultConfig; handle errors. */
                   1314: 
                   1315:        /* The context leaks in case of an error, but if there's a
                   1316:         * problem we always exit anyhow. */
                   1317:        if (pc)
                   1318:                poptFreeContext(pc);
                   1319:        pc = poptGetContext(RSYNC_NAME, argc, argv, long_options, 0);
                   1320:        if (!am_server)
                   1321:                poptReadDefaultConfig(pc, 0);
                   1322: 
                   1323:        while ((opt = poptGetNextOpt(pc)) != -1) {
                   1324:                /* most options are handled automatically by popt;
                   1325:                 * only special cases are returned and listed here. */
                   1326: 
                   1327:                switch (opt) {
                   1328:                case OPT_VERSION:
                   1329:                        print_rsync_version(FINFO);
                   1330:                        exit_cleanup(0);
                   1331: 
                   1332:                case OPT_SERVER:
                   1333:                        if (!am_server) {
                   1334:                                /* Disable popt aliases on the server side and
                   1335:                                 * then start parsing the options again. */
                   1336:                                poptFreeContext(pc);
                   1337:                                pc = poptGetContext(RSYNC_NAME, argc, argv,
                   1338:                                                    long_options, 0);
                   1339:                                am_server = 1;
                   1340:                        }
                   1341: #ifdef ICONV_OPTION
                   1342:                        iconv_opt = NULL;
                   1343: #endif
                   1344:                        break;
                   1345: 
                   1346:                case OPT_SENDER:
                   1347:                        if (!am_server) {
                   1348:                                usage(FERROR);
                   1349:                                exit_cleanup(RERR_SYNTAX);
                   1350:                        }
                   1351:                        am_sender = 1;
                   1352:                        break;
                   1353: 
                   1354:                case OPT_DAEMON:
                   1355:                        if (am_daemon) {
                   1356:                                strlcpy(err_buf,
                   1357:                                        "Attempt to hack rsync thwarted!\n",
                   1358:                                        sizeof err_buf);
                   1359:                                return 0;
                   1360:                        }
                   1361: #ifdef ICONV_OPTION
                   1362:                        iconv_opt = NULL;
                   1363: #endif
1.1.1.2   misho    1364:                        protect_args = 0;
1.1       misho    1365:                        poptFreeContext(pc);
                   1366:                        pc = poptGetContext(RSYNC_NAME, argc, argv,
                   1367:                                            long_daemon_options, 0);
                   1368:                        while ((opt = poptGetNextOpt(pc)) != -1) {
1.1.1.2   misho    1369:                                char **cpp;
1.1       misho    1370:                                switch (opt) {
                   1371:                                case 'h':
                   1372:                                        daemon_usage(FINFO);
                   1373:                                        exit_cleanup(0);
                   1374: 
1.1.1.2   misho    1375:                                case 'M':
                   1376:                                        arg = poptGetOptArg(pc);
                   1377:                                        if (!strchr(arg, '=')) {
                   1378:                                                rprintf(FERROR,
                   1379:                                                    "--dparam value is missing an '=': %s\n",
                   1380:                                                    arg);
                   1381:                                                goto daemon_error;
                   1382:                                        }
                   1383:                                        cpp = EXPAND_ITEM_LIST(&dparam_list, char *, 4);
                   1384:                                        *cpp = strdup(arg);
                   1385:                                        break;
                   1386: 
1.1       misho    1387:                                case 'v':
                   1388:                                        verbose++;
                   1389:                                        break;
                   1390: 
                   1391:                                default:
                   1392:                                        rprintf(FERROR,
                   1393:                                            "rsync: %s: %s (in daemon mode)\n",
                   1394:                                            poptBadOption(pc, POPT_BADOPTION_NOALIAS),
                   1395:                                            poptStrerror(opt));
                   1396:                                        goto daemon_error;
                   1397:                                }
                   1398:                        }
                   1399: 
1.1.1.2   misho    1400:                        if (dparam_list.count && !set_dparams(1))
                   1401:                                exit_cleanup(RERR_SYNTAX);
                   1402: 
1.1       misho    1403:                        if (tmpdir && strlen(tmpdir) >= MAXPATHLEN - 10) {
                   1404:                                snprintf(err_buf, sizeof err_buf,
                   1405:                                         "the --temp-dir path is WAY too long.\n");
                   1406:                                return 0;
                   1407:                        }
                   1408: 
                   1409:                        if (!daemon_opt) {
                   1410:                                rprintf(FERROR, "Daemon option(s) used without --daemon.\n");
                   1411:                            daemon_error:
                   1412:                                rprintf(FERROR,
                   1413:                                    "(Type \"rsync --daemon --help\" for assistance with daemon mode.)\n");
                   1414:                                exit_cleanup(RERR_SYNTAX);
                   1415:                        }
                   1416: 
                   1417:                        *argv_p = argv = poptGetArgs(pc);
                   1418:                        *argc_p = argc = count_args(argv);
                   1419:                        am_starting_up = 0;
                   1420:                        daemon_opt = 0;
                   1421:                        am_daemon = 1;
                   1422:                        return 1;
                   1423: 
                   1424:                case OPT_MODIFY_WINDOW:
                   1425:                        /* The value has already been set by popt, but
                   1426:                         * we need to remember that we're using a
                   1427:                         * non-default setting. */
                   1428:                        modify_window_set = 1;
                   1429:                        break;
                   1430: 
                   1431:                case OPT_FILTER:
1.1.1.2   misho    1432:                        parse_filter_str(&filter_list, poptGetOptArg(pc),
                   1433:                                        rule_template(0), 0);
1.1       misho    1434:                        break;
                   1435: 
                   1436:                case OPT_EXCLUDE:
1.1.1.2   misho    1437:                        parse_filter_str(&filter_list, poptGetOptArg(pc),
                   1438:                                        rule_template(0), XFLG_OLD_PREFIXES);
1.1       misho    1439:                        break;
                   1440: 
                   1441:                case OPT_INCLUDE:
1.1.1.2   misho    1442:                        parse_filter_str(&filter_list, poptGetOptArg(pc),
                   1443:                                        rule_template(FILTRULE_INCLUDE), XFLG_OLD_PREFIXES);
1.1       misho    1444:                        break;
                   1445: 
                   1446:                case OPT_EXCLUDE_FROM:
                   1447:                case OPT_INCLUDE_FROM:
                   1448:                        arg = poptGetOptArg(pc);
                   1449:                        if (sanitize_paths)
                   1450:                                arg = sanitize_path(NULL, arg, NULL, 0, SP_DEFAULT);
                   1451:                        if (daemon_filter_list.head) {
                   1452:                                int rej;
1.1.1.2   misho    1453:                                char *cp = strdup(arg);
1.1       misho    1454:                                if (!cp)
                   1455:                                        out_of_memory("parse_arguments");
                   1456:                                if (!*cp)
1.1.1.2   misho    1457:                                        rej = 1;
                   1458:                                else {
                   1459:                                        char *dir = cp + (*cp == '/' ? module_dirlen : 0);
                   1460:                                        clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
                   1461:                                        rej = check_filter(&daemon_filter_list, FLOG, dir, 0) < 0;
                   1462:                                }
1.1       misho    1463:                                free(cp);
                   1464:                                if (rej)
                   1465:                                        goto options_rejected;
                   1466:                        }
                   1467:                        parse_filter_file(&filter_list, arg,
1.1.1.2   misho    1468:                                rule_template(opt == OPT_INCLUDE_FROM ? FILTRULE_INCLUDE : 0),
1.1       misho    1469:                                XFLG_FATAL_ERRORS | XFLG_OLD_PREFIXES);
                   1470:                        break;
                   1471: 
                   1472:                case 'a':
                   1473:                        if (refused_archive_part) {
                   1474:                                create_refuse_error(refused_archive_part);
                   1475:                                return 0;
                   1476:                        }
                   1477:                        if (!recurse) /* preserve recurse == 2 */
                   1478:                                recurse = 1;
                   1479: #ifdef SUPPORT_LINKS
                   1480:                        preserve_links = 1;
                   1481: #endif
                   1482:                        preserve_perms = 1;
                   1483:                        preserve_times = 1;
                   1484:                        preserve_gid = 1;
                   1485:                        preserve_uid = 1;
                   1486:                        preserve_devices = 1;
                   1487:                        preserve_specials = 1;
                   1488:                        break;
                   1489: 
                   1490:                case 'D':
                   1491:                        preserve_devices = preserve_specials = 1;
                   1492:                        break;
                   1493: 
                   1494:                case OPT_NO_D:
                   1495:                        preserve_devices = preserve_specials = 0;
                   1496:                        break;
                   1497: 
                   1498:                case 'h':
                   1499:                        human_readable++;
                   1500:                        break;
                   1501: 
                   1502:                case 'H':
                   1503:                        preserve_hard_links++;
                   1504:                        break;
                   1505: 
                   1506:                case 'i':
                   1507:                        itemize_changes++;
                   1508:                        break;
                   1509: 
                   1510:                case 'v':
                   1511:                        verbose++;
                   1512:                        break;
                   1513: 
1.1.1.2   misho    1514:                case 'y':
                   1515:                        fuzzy_basis++;
                   1516:                        break;
                   1517: 
1.1       misho    1518:                case 'q':
                   1519:                        quiet++;
                   1520:                        break;
                   1521: 
                   1522:                case 'x':
                   1523:                        one_file_system++;
                   1524:                        break;
                   1525: 
                   1526:                case 'F':
                   1527:                        switch (++F_option_cnt) {
                   1528:                        case 1:
1.1.1.2   misho    1529:                                parse_filter_str(&filter_list,": /.rsync-filter",rule_template(0),0);
1.1       misho    1530:                                break;
                   1531:                        case 2:
1.1.1.2   misho    1532:                                parse_filter_str(&filter_list,"- .rsync-filter",rule_template(0),0);
1.1       misho    1533:                                break;
                   1534:                        }
                   1535:                        break;
                   1536: 
                   1537:                case 'P':
                   1538:                        if (refused_partial || refused_progress) {
                   1539:                                create_refuse_error(refused_partial
                   1540:                                    ? refused_partial : refused_progress);
                   1541:                                return 0;
                   1542:                        }
                   1543:                        do_progress = 1;
                   1544:                        keep_partial = 1;
                   1545:                        break;
                   1546: 
                   1547:                case 'z':
1.1.1.3 ! misho    1548:                        do_compression++;
1.1       misho    1549:                        break;
                   1550: 
1.1.1.2   misho    1551:                case 'M':
                   1552:                        arg = poptGetOptArg(pc);
                   1553:                        if (*arg != '-') {
                   1554:                                snprintf(err_buf, sizeof err_buf,
                   1555:                                        "Remote option must start with a dash: %s\n", arg);
                   1556:                                return 0;
                   1557:                        }
                   1558:                        if (remote_option_cnt+2 >= remote_option_alloc) {
                   1559:                                remote_option_alloc += 16;
                   1560:                                remote_options = realloc_array(remote_options,
                   1561:                                                        const char *, remote_option_alloc);
                   1562:                                if (!remote_options)
                   1563:                                        out_of_memory("parse_arguments");
                   1564:                                if (!remote_option_cnt)
                   1565:                                        remote_options[0] = "ARG0";
                   1566:                        }
                   1567:                        remote_options[++remote_option_cnt] = arg;
                   1568:                        remote_options[remote_option_cnt+1] = NULL;
                   1569:                        break;
                   1570: 
1.1       misho    1571:                case OPT_WRITE_BATCH:
                   1572:                        /* batch_name is already set */
                   1573:                        write_batch = 1;
                   1574:                        break;
                   1575: 
                   1576:                case OPT_ONLY_WRITE_BATCH:
                   1577:                        /* batch_name is already set */
                   1578:                        write_batch = -1;
                   1579:                        break;
                   1580: 
                   1581:                case OPT_READ_BATCH:
                   1582:                        /* batch_name is already set */
                   1583:                        read_batch = 1;
                   1584:                        break;
                   1585: 
                   1586:                case OPT_NO_ICONV:
                   1587: #ifdef ICONV_OPTION
                   1588:                        iconv_opt = NULL;
                   1589: #endif
                   1590:                        break;
                   1591: 
                   1592:                case OPT_MAX_SIZE:
1.1.1.2   misho    1593:                        if ((max_size = parse_size_arg(&max_size_arg, 'b')) < 0) {
1.1       misho    1594:                                snprintf(err_buf, sizeof err_buf,
                   1595:                                        "--max-size value is invalid: %s\n",
                   1596:                                        max_size_arg);
                   1597:                                return 0;
                   1598:                        }
                   1599:                        break;
                   1600: 
                   1601:                case OPT_MIN_SIZE:
1.1.1.2   misho    1602:                        if ((min_size = parse_size_arg(&min_size_arg, 'b')) < 0) {
1.1       misho    1603:                                snprintf(err_buf, sizeof err_buf,
                   1604:                                        "--min-size value is invalid: %s\n",
                   1605:                                        min_size_arg);
                   1606:                                return 0;
                   1607:                        }
                   1608:                        break;
                   1609: 
1.1.1.2   misho    1610:                case OPT_BWLIMIT:
                   1611:                        {
                   1612:                                OFF_T limit = parse_size_arg(&bwlimit_arg, 'K');
                   1613:                                if (limit < 0) {
                   1614:                                        snprintf(err_buf, sizeof err_buf,
                   1615:                                                "--bwlimit value is invalid: %s\n", bwlimit_arg);
                   1616:                                        return 0;
                   1617:                                }
                   1618:                                bwlimit = (limit + 512) / 1024;
                   1619:                                if (limit && !bwlimit) {
                   1620:                                        snprintf(err_buf, sizeof err_buf,
                   1621:                                                "--bwlimit value is too small: %s\n", bwlimit_arg);
                   1622:                                        return 0;
                   1623:                                }
                   1624:                        }
                   1625:                        break;
                   1626: 
1.1       misho    1627:                case OPT_APPEND:
                   1628:                        if (am_server)
                   1629:                                append_mode++;
                   1630:                        else
                   1631:                                append_mode = 1;
                   1632:                        break;
                   1633: 
                   1634:                case OPT_LINK_DEST:
                   1635: #ifdef SUPPORT_HARD_LINKS
                   1636:                        link_dest = 1;
                   1637:                        dest_option = "--link-dest";
                   1638:                        goto set_dest_dir;
                   1639: #else
                   1640:                        snprintf(err_buf, sizeof err_buf,
                   1641:                                 "hard links are not supported on this %s\n",
                   1642:                                 am_server ? "server" : "client");
                   1643:                        return 0;
                   1644: #endif
                   1645: 
                   1646:                case OPT_COPY_DEST:
                   1647:                        copy_dest = 1;
                   1648:                        dest_option = "--copy-dest";
                   1649:                        goto set_dest_dir;
                   1650: 
                   1651:                case OPT_COMPARE_DEST:
                   1652:                        compare_dest = 1;
                   1653:                        dest_option = "--compare-dest";
                   1654:                set_dest_dir:
                   1655:                        if (basis_dir_cnt >= MAX_BASIS_DIRS) {
                   1656:                                snprintf(err_buf, sizeof err_buf,
                   1657:                                        "ERROR: at most %d %s args may be specified\n",
                   1658:                                        MAX_BASIS_DIRS, dest_option);
                   1659:                                return 0;
                   1660:                        }
                   1661:                        /* We defer sanitizing this arg until we know what
                   1662:                         * our destination directory is going to be. */
                   1663:                        basis_dir[basis_dir_cnt++] = (char *)poptGetOptArg(pc);
                   1664:                        break;
                   1665: 
                   1666:                case OPT_CHMOD:
                   1667:                        arg = poptGetOptArg(pc);
                   1668:                        if (!parse_chmod(arg, &chmod_modes)) {
                   1669:                                snprintf(err_buf, sizeof err_buf,
                   1670:                                    "Invalid argument passed to --chmod (%s)\n",
                   1671:                                    arg);
                   1672:                                return 0;
                   1673:                        }
                   1674:                        break;
                   1675: 
1.1.1.2   misho    1676:                case OPT_INFO:
                   1677:                        arg = poptGetOptArg(pc);
                   1678:                        parse_output_words(info_words, info_levels, arg, USER_PRIORITY);
                   1679:                        break;
                   1680: 
                   1681:                case OPT_DEBUG:
                   1682:                        arg = poptGetOptArg(pc);
                   1683:                        parse_output_words(debug_words, debug_levels, arg, USER_PRIORITY);
                   1684:                        break;
                   1685: 
                   1686:                case OPT_USERMAP:
                   1687:                        if (usermap) {
                   1688:                                if (usermap_via_chown) {
                   1689:                                        snprintf(err_buf, sizeof err_buf,
                   1690:                                            "--usermap conflicts with prior --chown.\n");
                   1691:                                        return 0;
                   1692:                                }
                   1693:                                snprintf(err_buf, sizeof err_buf,
                   1694:                                    "You can only specify --usermap once.\n");
                   1695:                                return 0;
                   1696:                        }
                   1697:                        usermap = (char *)poptGetOptArg(pc);
                   1698:                        usermap_via_chown = False;
                   1699:                        break;
                   1700: 
                   1701:                case OPT_GROUPMAP:
                   1702:                        if (groupmap) {
                   1703:                                if (groupmap_via_chown) {
                   1704:                                        snprintf(err_buf, sizeof err_buf,
                   1705:                                            "--groupmap conflicts with prior --chown.\n");
                   1706:                                        return 0;
                   1707:                                }
                   1708:                                snprintf(err_buf, sizeof err_buf,
                   1709:                                    "You can only specify --groupmap once.\n");
                   1710:                                return 0;
                   1711:                        }
                   1712:                        groupmap = (char *)poptGetOptArg(pc);
                   1713:                        groupmap_via_chown = False;
                   1714:                        break;
                   1715: 
                   1716:                case OPT_CHOWN: {
                   1717:                        const char *chown = poptGetOptArg(pc);
                   1718:                        int len;
                   1719:                        if ((arg = strchr(chown, ':')) != NULL)
                   1720:                                len = arg++ - chown;
                   1721:                        else
                   1722:                                len = strlen(chown);
                   1723:                        if (len) {
                   1724:                                if (usermap) {
                   1725:                                        if (!usermap_via_chown) {
                   1726:                                                snprintf(err_buf, sizeof err_buf,
                   1727:                                                    "--chown conflicts with prior --usermap.\n");
                   1728:                                                return 0;
                   1729:                                        }
                   1730:                                        snprintf(err_buf, sizeof err_buf,
                   1731:                                            "You can only specify a user-affecting --chown once.\n");
                   1732:                                        return 0;
                   1733:                                }
                   1734:                                if (asprintf(&usermap, "*:%.*s", len, chown) < 0)
                   1735:                                        out_of_memory("parse_arguments");
                   1736:                                usermap_via_chown = True;
                   1737:                        }
                   1738:                        if (arg && *arg) {
                   1739:                                if (groupmap) {
                   1740:                                        if (!groupmap_via_chown) {
                   1741:                                                snprintf(err_buf, sizeof err_buf,
                   1742:                                                    "--chown conflicts with prior --groupmap.\n");
                   1743:                                                return 0;
                   1744:                                        }
                   1745:                                        snprintf(err_buf, sizeof err_buf,
                   1746:                                            "You can only specify a group-affecting --chown once.\n");
                   1747:                                        return 0;
                   1748:                                }
                   1749:                                if (asprintf(&groupmap, "*:%s", arg) < 0)
                   1750:                                        out_of_memory("parse_arguments");
                   1751:                                groupmap_via_chown = True;
                   1752:                        }
                   1753:                        break;
                   1754:                }
                   1755: 
1.1       misho    1756:                case OPT_HELP:
                   1757:                        usage(FINFO);
                   1758:                        exit_cleanup(0);
                   1759: 
                   1760:                case 'A':
                   1761: #ifdef SUPPORT_ACLS
                   1762:                        preserve_acls = 1;
                   1763:                        preserve_perms = 1;
                   1764:                        break;
                   1765: #else
                   1766:                        /* FIXME: this should probably be ignored with a
                   1767:                         * warning and then countermeasures taken to
                   1768:                         * restrict group and other access in the presence
                   1769:                         * of any more restrictive ACLs, but this is safe
                   1770:                         * for now */
                   1771:                        snprintf(err_buf,sizeof(err_buf),
                   1772:                                  "ACLs are not supported on this %s\n",
                   1773:                                 am_server ? "server" : "client");
                   1774:                        return 0;
                   1775: #endif
                   1776: 
                   1777:                case 'X':
                   1778: #ifdef SUPPORT_XATTRS
                   1779:                        preserve_xattrs++;
                   1780:                        break;
                   1781: #else
                   1782:                        snprintf(err_buf,sizeof(err_buf),
                   1783:                                 "extended attributes are not supported on this %s\n",
                   1784:                                 am_server ? "server" : "client");
                   1785:                        return 0;
                   1786: #endif
                   1787: 
                   1788:                default:
                   1789:                        /* A large opt value means that set_refuse_options()
                   1790:                         * turned this option off. */
                   1791:                        if (opt >= OPT_REFUSED_BASE) {
                   1792:                                create_refuse_error(opt);
                   1793:                                return 0;
                   1794:                        }
                   1795:                        snprintf(err_buf, sizeof err_buf, "%s%s: %s\n",
                   1796:                                 am_server ? "on remote machine: " : "",
                   1797:                                 poptBadOption(pc, POPT_BADOPTION_NOALIAS),
                   1798:                                 poptStrerror(opt));
                   1799:                        return 0;
                   1800:                }
                   1801:        }
                   1802: 
1.1.1.2   misho    1803:        if (protect_args < 0) {
                   1804:                if (am_server)
                   1805:                        protect_args = 0;
                   1806:                else if ((arg = getenv("RSYNC_PROTECT_ARGS")) != NULL && *arg)
                   1807:                        protect_args = atoi(arg) ? 1 : 0;
                   1808:                else {
                   1809: #ifdef RSYNC_USE_PROTECTED_ARGS
                   1810:                        protect_args = 1;
                   1811: #else
                   1812:                        protect_args = 0;
                   1813: #endif
                   1814:                }
                   1815:        }
                   1816: 
                   1817:        if (human_readable > 1 && argc == 2 && !am_server) {
1.1       misho    1818:                /* Allow the old meaning of 'h' (--help) on its own. */
                   1819:                usage(FINFO);
                   1820:                exit_cleanup(0);
                   1821:        }
                   1822: 
1.1.1.3 ! misho    1823:        if (do_compression || def_compress_level != NOT_SPECIFIED) {
        !          1824:                if (def_compress_level == NOT_SPECIFIED)
        !          1825:                        def_compress_level = Z_DEFAULT_COMPRESSION;
        !          1826:                else if (def_compress_level < Z_DEFAULT_COMPRESSION || def_compress_level > Z_BEST_COMPRESSION) {
        !          1827:                        snprintf(err_buf, sizeof err_buf, "--compress-level value is invalid: %d\n",
        !          1828:                                 def_compress_level);
        !          1829:                        return 0;
        !          1830:                } else if (def_compress_level == Z_NO_COMPRESSION)
        !          1831:                        do_compression = 0;
        !          1832:                else if (!do_compression)
        !          1833:                        do_compression = 1;
        !          1834:                if (do_compression && refused_compress) {
        !          1835:                        create_refuse_error(refused_compress);
        !          1836:                        return 0;
        !          1837:                }
        !          1838: #ifdef EXTERNAL_ZLIB
        !          1839:                if (do_compression == 1) {
        !          1840:                        snprintf(err_buf, sizeof err_buf,
        !          1841:                                "This rsync lacks old-style --compress due to its external zlib.  Try -zz.\n");
        !          1842:                        if (am_server)
        !          1843:                                return 0;
        !          1844:                        fprintf(stderr, "%s" "Continuing without compression.\n\n", err_buf);
        !          1845:                        do_compression = 0;
        !          1846:                }
        !          1847: #endif
        !          1848:        }
        !          1849: 
1.1.1.2   misho    1850: #ifdef HAVE_SETVBUF
                   1851:        if (outbuf_mode && !am_server) {
                   1852:                int mode = *(uchar *)outbuf_mode;
                   1853:                if (islower(mode))
                   1854:                        mode = toupper(mode);
                   1855:                fflush(stdout); /* Just in case... */
                   1856:                switch (mode) {
                   1857:                case 'N': /* None */
                   1858:                case 'U': /* Unbuffered */
                   1859:                        mode = _IONBF;
                   1860:                        break;
                   1861:                case 'L': /* Line */
                   1862:                        mode = _IOLBF;
                   1863:                        break;
                   1864:                case 'B': /* Block */
                   1865:                case 'F': /* Full */
                   1866:                        mode = _IOFBF;
                   1867:                        break;
                   1868:                default:
                   1869:                        snprintf(err_buf, sizeof err_buf,
                   1870:                                "Invalid --outbuf setting -- specify N, L, or B.\n");
                   1871:                        return 0;
                   1872:                }
                   1873:                setvbuf(stdout, (char *)NULL, mode, 0);
                   1874:        }
                   1875: 
                   1876:        if (msgs2stderr) {
                   1877:                /* Make stderr line buffered for better sharing of the stream. */
                   1878:                fflush(stderr); /* Just in case... */
                   1879:                setvbuf(stderr, (char *)NULL, _IOLBF, 0);
                   1880:        }
                   1881: #endif
                   1882: 
                   1883:        set_output_verbosity(verbose, DEFAULT_PRIORITY);
                   1884: 
                   1885:        if (do_stats) {
                   1886:                parse_output_words(info_words, info_levels,
                   1887:                        verbose > 1 ? "stats3" : "stats2", DEFAULT_PRIORITY);
                   1888:        }
                   1889: 
1.1       misho    1890: #ifdef ICONV_OPTION
                   1891:        if (iconv_opt && protect_args != 2) {
                   1892:                if (!am_server && strcmp(iconv_opt, "-") == 0)
                   1893:                        iconv_opt = NULL;
                   1894:                else
                   1895:                        need_unsorted_flist = 1;
                   1896:        }
                   1897:        if (refused_no_iconv && !iconv_opt) {
                   1898:                create_refuse_error(refused_no_iconv);
                   1899:                return 0;
                   1900:        }
                   1901: #endif
                   1902: 
1.1.1.2   misho    1903:        if (fuzzy_basis > 1)
                   1904:                fuzzy_basis = basis_dir_cnt + 1;
                   1905: 
1.1       misho    1906:        if (protect_args == 1 && am_server)
                   1907:                return 1;
                   1908: 
                   1909:        *argv_p = argv = poptGetArgs(pc);
                   1910:        *argc_p = argc = count_args(argv);
                   1911: 
                   1912: #ifndef SUPPORT_LINKS
                   1913:        if (preserve_links && !am_sender) {
                   1914:                snprintf(err_buf, sizeof err_buf,
                   1915:                         "symlinks are not supported on this %s\n",
                   1916:                         am_server ? "server" : "client");
                   1917:                return 0;
                   1918:        }
                   1919: #endif
                   1920: 
                   1921: #ifndef SUPPORT_HARD_LINKS
                   1922:        if (preserve_hard_links) {
                   1923:                snprintf(err_buf, sizeof err_buf,
                   1924:                         "hard links are not supported on this %s\n",
                   1925:                         am_server ? "server" : "client");
                   1926:                return 0;
                   1927:        }
                   1928: #endif
                   1929: 
                   1930: #ifdef SUPPORT_XATTRS
                   1931:        if (am_root < 0 && preserve_xattrs > 1) {
                   1932:                snprintf(err_buf, sizeof err_buf,
                   1933:                         "--fake-super conflicts with -XX\n");
                   1934:                return 0;
                   1935:        }
                   1936: #else
                   1937:        if (am_root < 0) {
                   1938:                snprintf(err_buf, sizeof err_buf,
                   1939:                         "--fake-super requires an rsync with extended attributes enabled\n");
                   1940:                return 0;
                   1941:        }
                   1942: #endif
                   1943: 
1.1.1.2   misho    1944:        if (block_size > MAX_BLOCK_SIZE) {
                   1945:                snprintf(err_buf, sizeof err_buf,
                   1946:                         "--block-size=%lu is too large (max: %u)\n", block_size, MAX_BLOCK_SIZE);
                   1947:                return 0;
                   1948:        }
                   1949: 
1.1       misho    1950:        if (write_batch && read_batch) {
                   1951:                snprintf(err_buf, sizeof err_buf,
                   1952:                        "--write-batch and --read-batch can not be used together\n");
                   1953:                return 0;
                   1954:        }
                   1955:        if (write_batch > 0 || read_batch) {
                   1956:                if (am_server) {
                   1957:                        rprintf(FINFO,
                   1958:                                "ignoring --%s-batch option sent to server\n",
                   1959:                                write_batch ? "write" : "read");
                   1960:                        /* We don't actually exit_cleanup(), so that we can
                   1961:                         * still service older version clients that still send
                   1962:                         * batch args to server. */
                   1963:                        read_batch = write_batch = 0;
                   1964:                        batch_name = NULL;
                   1965:                } else if (dry_run)
                   1966:                        write_batch = 0;
                   1967:        } else if (write_batch < 0 && dry_run)
                   1968:                write_batch = 0;
                   1969:        if (read_batch && files_from) {
                   1970:                snprintf(err_buf, sizeof err_buf,
                   1971:                        "--read-batch cannot be used with --files-from\n");
                   1972:                return 0;
                   1973:        }
                   1974:        if (read_batch && remove_source_files) {
                   1975:                snprintf(err_buf, sizeof err_buf,
                   1976:                        "--read-batch cannot be used with --remove-%s-files\n",
                   1977:                        remove_source_files == 1 ? "source" : "sent");
                   1978:                return 0;
                   1979:        }
                   1980:        if (batch_name && strlen(batch_name) > MAX_BATCH_NAME_LEN) {
                   1981:                snprintf(err_buf, sizeof err_buf,
                   1982:                        "the batch-file name must be %d characters or less.\n",
                   1983:                        MAX_BATCH_NAME_LEN);
                   1984:                return 0;
                   1985:        }
                   1986: 
                   1987:        if (tmpdir && strlen(tmpdir) >= MAXPATHLEN - 10) {
                   1988:                snprintf(err_buf, sizeof err_buf,
                   1989:                         "the --temp-dir path is WAY too long.\n");
                   1990:                return 0;
                   1991:        }
                   1992: 
                   1993:        if (max_delete < 0 && max_delete != INT_MIN) {
                   1994:                /* Negative numbers are treated as "no deletions". */
                   1995:                max_delete = 0;
                   1996:        }
                   1997: 
                   1998:        if (compare_dest + copy_dest + link_dest > 1) {
                   1999:                snprintf(err_buf, sizeof err_buf,
                   2000:                        "You may not mix --compare-dest, --copy-dest, and --link-dest.\n");
                   2001:                return 0;
                   2002:        }
                   2003: 
                   2004:        if (files_from) {
                   2005:                if (recurse == 1) /* preserve recurse == 2 */
                   2006:                        recurse = 0;
                   2007:                if (xfer_dirs < 0)
                   2008:                        xfer_dirs = 1;
                   2009:        }
                   2010: 
                   2011:        if (argc < 2 && !read_batch && !am_server)
                   2012:                list_only |= 1;
                   2013: 
                   2014:        if (xfer_dirs >= 4) {
1.1.1.2   misho    2015:                parse_filter_str(&filter_list, "- /*/*", rule_template(0), 0);
1.1       misho    2016:                recurse = xfer_dirs = 1;
                   2017:        } else if (recurse)
                   2018:                xfer_dirs = 1;
                   2019:        else if (xfer_dirs < 0)
                   2020:                xfer_dirs = list_only ? 1 : 0;
                   2021: 
                   2022:        if (relative_paths < 0)
                   2023:                relative_paths = files_from? 1 : 0;
                   2024:        if (!relative_paths)
                   2025:                implied_dirs = 0;
                   2026: 
                   2027:        if (delete_before + !!delete_during + delete_after > 1) {
                   2028:                snprintf(err_buf, sizeof err_buf,
                   2029:                        "You may not combine multiple --delete-WHEN options.\n");
                   2030:                return 0;
                   2031:        }
                   2032:        if (delete_before || delete_during || delete_after)
                   2033:                delete_mode = 1;
                   2034:        else if (delete_mode || delete_excluded) {
                   2035:                /* Only choose now between before & during if one is refused. */
                   2036:                if (refused_delete_before) {
                   2037:                        if (!refused_delete_during)
                   2038:                                delete_during = 1;
                   2039:                        else {
                   2040:                                create_refuse_error(refused_delete_before);
                   2041:                                return 0;
                   2042:                        }
                   2043:                } else if (refused_delete_during)
                   2044:                        delete_before = 1;
                   2045:                delete_mode = 1;
                   2046:        }
                   2047:        if (!xfer_dirs && delete_mode) {
                   2048:                snprintf(err_buf, sizeof err_buf,
                   2049:                        "--delete does not work without --recursive (-r) or --dirs (-d).\n");
                   2050:                return 0;
                   2051:        }
                   2052: 
1.1.1.2   misho    2053:        if (missing_args == 3) /* simplify if both options were specified */
                   2054:                missing_args = 2;
                   2055:        if (refused_delete && (delete_mode || missing_args == 2)) {
1.1       misho    2056:                create_refuse_error(refused_delete);
                   2057:                return 0;
                   2058:        }
                   2059: 
                   2060:        if (remove_source_files) {
                   2061:                /* We only want to infer this refusal of --remove-source-files
                   2062:                 * via the refusal of "delete", not any of the "delete-FOO"
                   2063:                 * options. */
                   2064:                if (refused_delete && am_sender) {
                   2065:                        create_refuse_error(refused_delete);
                   2066:                        return 0;
                   2067:                }
                   2068:                need_messages_from_generator = 1;
                   2069:        }
                   2070: 
1.1.1.2   misho    2071:        if (munge_symlinks && !am_daemon) {
                   2072:                STRUCT_STAT st;
                   2073:                char prefix[SYMLINK_PREFIX_LEN]; /* NOT +1 ! */
                   2074:                strlcpy(prefix, SYMLINK_PREFIX, sizeof prefix); /* trim the trailing slash */
                   2075:                if (do_stat(prefix, &st) == 0 && S_ISDIR(st.st_mode)) {
                   2076:                        rprintf(FERROR, "Symlink munging is unsafe when a %s directory exists.\n",
                   2077:                                prefix);
                   2078:                        exit_cleanup(RERR_UNSUPPORTED);
                   2079:                }
                   2080:        }
                   2081: 
1.1       misho    2082:        if (sanitize_paths) {
                   2083:                int i;
                   2084:                for (i = argc; i-- > 0; )
                   2085:                        argv[i] = sanitize_path(NULL, argv[i], "", 0, SP_KEEP_DOT_DIRS);
                   2086:                if (tmpdir)
                   2087:                        tmpdir = sanitize_path(NULL, tmpdir, NULL, 0, SP_DEFAULT);
                   2088:                if (backup_dir)
                   2089:                        backup_dir = sanitize_path(NULL, backup_dir, NULL, 0, SP_DEFAULT);
                   2090:        }
                   2091:        if (daemon_filter_list.head && !am_sender) {
1.1.1.2   misho    2092:                filter_rule_list *elp = &daemon_filter_list;
1.1       misho    2093:                if (tmpdir) {
                   2094:                        char *dir;
                   2095:                        if (!*tmpdir)
                   2096:                                goto options_rejected;
                   2097:                        dir = tmpdir + (*tmpdir == '/' ? module_dirlen : 0);
                   2098:                        clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
                   2099:                        if (check_filter(elp, FLOG, dir, 1) < 0)
                   2100:                                goto options_rejected;
                   2101:                }
                   2102:                if (backup_dir) {
                   2103:                        char *dir;
                   2104:                        if (!*backup_dir)
                   2105:                                goto options_rejected;
                   2106:                        dir = backup_dir + (*backup_dir == '/' ? module_dirlen : 0);
                   2107:                        clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
                   2108:                        if (check_filter(elp, FLOG, dir, 1) < 0)
                   2109:                                goto options_rejected;
                   2110:                }
                   2111:        }
                   2112: 
                   2113:        if (!backup_suffix)
                   2114:                backup_suffix = backup_dir ? "" : BACKUP_SUFFIX;
                   2115:        backup_suffix_len = strlen(backup_suffix);
                   2116:        if (strchr(backup_suffix, '/') != NULL) {
                   2117:                snprintf(err_buf, sizeof err_buf,
                   2118:                        "--suffix cannot contain slashes: %s\n",
                   2119:                        backup_suffix);
                   2120:                return 0;
                   2121:        }
                   2122:        if (backup_dir) {
1.1.1.2   misho    2123:                size_t len;
                   2124:                while (*backup_dir == '.' && backup_dir[1] == '/')
                   2125:                        backup_dir += 2;
                   2126:                if (*backup_dir == '.' && backup_dir[1] == '\0')
                   2127:                        backup_dir++;
                   2128:                len = strlcpy(backup_dir_buf, backup_dir, sizeof backup_dir_buf);
1.1       misho    2129:                if (len > sizeof backup_dir_buf - 128) {
                   2130:                        snprintf(err_buf, sizeof err_buf,
                   2131:                                "the --backup-dir path is WAY too long.\n");
                   2132:                        return 0;
                   2133:                }
                   2134:                backup_dir_len = (int)len;
1.1.1.2   misho    2135:                if (!backup_dir_len) {
                   2136:                        backup_dir_len = -1;
                   2137:                        backup_dir = NULL;
                   2138:                } else if (backup_dir_buf[backup_dir_len - 1] != '/') {
1.1       misho    2139:                        backup_dir_buf[backup_dir_len++] = '/';
                   2140:                        backup_dir_buf[backup_dir_len] = '\0';
                   2141:                }
                   2142:                backup_dir_remainder = sizeof backup_dir_buf - backup_dir_len;
1.1.1.2   misho    2143:        }
                   2144:        if (backup_dir) {
                   2145:                /* No need for a suffix or a protect rule. */
1.1       misho    2146:        } else if (!backup_suffix_len && (!am_server || !am_sender)) {
                   2147:                snprintf(err_buf, sizeof err_buf,
1.1.1.2   misho    2148:                        "--suffix cannot be empty %s\n", backup_dir_len < 0
                   2149:                        ? "when --backup-dir is the same as the dest dir"
                   2150:                        : "without a --backup-dir");
1.1       misho    2151:                return 0;
                   2152:        } else if (make_backups && delete_mode && !delete_excluded && !am_server) {
                   2153:                snprintf(backup_dir_buf, sizeof backup_dir_buf,
                   2154:                        "P *%s", backup_suffix);
1.1.1.2   misho    2155:                parse_filter_str(&filter_list, backup_dir_buf, rule_template(0), 0);
1.1       misho    2156:        }
                   2157: 
                   2158:        if (preserve_times) {
                   2159:                preserve_times = PRESERVE_FILE_TIMES;
                   2160:                if (!omit_dir_times)
                   2161:                        preserve_times |= PRESERVE_DIR_TIMES;
                   2162: #ifdef CAN_SET_SYMLINK_TIMES
1.1.1.2   misho    2163:                if (!omit_link_times)
                   2164:                        preserve_times |= PRESERVE_LINK_TIMES;
1.1       misho    2165: #endif
                   2166:        }
                   2167: 
                   2168:        if (make_backups && !backup_dir) {
                   2169:                omit_dir_times = 0; /* Implied, so avoid -O to sender. */
                   2170:                preserve_times &= ~PRESERVE_DIR_TIMES;
                   2171:        }
                   2172: 
                   2173:        if (stdout_format) {
                   2174:                if (am_server && log_format_has(stdout_format, 'I'))
                   2175:                        stdout_format_has_i = 2;
                   2176:                else if (log_format_has(stdout_format, 'i'))
                   2177:                        stdout_format_has_i = itemize_changes | 1;
                   2178:                if (!log_format_has(stdout_format, 'b')
1.1.1.2   misho    2179:                 && !log_format_has(stdout_format, 'c')
                   2180:                 && !log_format_has(stdout_format, 'C'))
1.1       misho    2181:                        log_before_transfer = !am_server;
                   2182:        } else if (itemize_changes) {
                   2183:                stdout_format = "%i %n%L";
                   2184:                stdout_format_has_i = itemize_changes;
                   2185:                log_before_transfer = !am_server;
                   2186:        }
                   2187: 
1.1.1.2   misho    2188:        if (do_progress && !am_server) {
                   2189:                if (!log_before_transfer && INFO_EQ(NAME, 0))
                   2190:                        parse_output_words(info_words, info_levels, "name", DEFAULT_PRIORITY);
                   2191:                parse_output_words(info_words, info_levels, "flist2,progress", DEFAULT_PRIORITY);
                   2192:        }
1.1       misho    2193: 
                   2194:        if (dry_run)
                   2195:                do_xfers = 0;
                   2196: 
                   2197:        set_io_timeout(io_timeout);
                   2198: 
1.1.1.2   misho    2199:        if (INFO_GTE(NAME, 1) && !stdout_format) {
1.1       misho    2200:                stdout_format = "%n%L";
                   2201:                log_before_transfer = !am_server;
                   2202:        }
                   2203:        if (stdout_format_has_i || log_format_has(stdout_format, 'o'))
                   2204:                stdout_format_has_o_or_i = 1;
                   2205: 
                   2206:        if (logfile_name && !am_daemon) {
                   2207:                if (!logfile_format) {
                   2208:                        logfile_format = "%i %n%L";
                   2209:                        logfile_format_has_i = logfile_format_has_o_or_i = 1;
                   2210:                } else {
                   2211:                        if (log_format_has(logfile_format, 'i'))
                   2212:                                logfile_format_has_i = 1;
                   2213:                        if (logfile_format_has_i || log_format_has(logfile_format, 'o'))
                   2214:                                logfile_format_has_o_or_i = 1;
                   2215:                }
                   2216:                log_init(0);
                   2217:        } else if (!am_daemon)
                   2218:                logfile_format = NULL;
                   2219: 
                   2220:        if (daemon_bwlimit && (!bwlimit || bwlimit > daemon_bwlimit))
                   2221:                bwlimit = daemon_bwlimit;
                   2222:        if (bwlimit) {
                   2223:                bwlimit_writemax = (size_t)bwlimit * 128;
                   2224:                if (bwlimit_writemax < 512)
                   2225:                        bwlimit_writemax = 512;
                   2226:        }
                   2227: 
                   2228:        if (sparse_files && inplace) {
                   2229:                /* Note: we don't check for this below, because --append is
                   2230:                 * OK with --sparse (as long as redos are handled right). */
                   2231:                snprintf(err_buf, sizeof err_buf,
                   2232:                         "--sparse cannot be used with --inplace\n");
                   2233:                return 0;
                   2234:        }
                   2235: 
                   2236:        if (append_mode) {
                   2237:                if (whole_file > 0) {
                   2238:                        snprintf(err_buf, sizeof err_buf,
                   2239:                                 "--append cannot be used with --whole-file\n");
                   2240:                        return 0;
                   2241:                }
                   2242:                if (refused_inplace) {
                   2243:                        create_refuse_error(refused_inplace);
                   2244:                        return 0;
                   2245:                }
                   2246:                inplace = 1;
                   2247:        }
                   2248: 
                   2249:        if (delay_updates && !partial_dir)
                   2250:                partial_dir = tmp_partialdir;
                   2251: 
                   2252:        if (inplace) {
                   2253: #ifdef HAVE_FTRUNCATE
                   2254:                if (partial_dir) {
                   2255:                        snprintf(err_buf, sizeof err_buf,
                   2256:                                 "--%s cannot be used with --%s\n",
                   2257:                                 append_mode ? "append" : "inplace",
                   2258:                                 delay_updates ? "delay-updates" : "partial-dir");
                   2259:                        return 0;
                   2260:                }
                   2261:                /* --inplace implies --partial for refusal purposes, but we
                   2262:                 * clear the keep_partial flag for internal logic purposes. */
                   2263:                if (refused_partial) {
                   2264:                        create_refuse_error(refused_partial);
                   2265:                        return 0;
                   2266:                }
                   2267:                keep_partial = 0;
                   2268: #else
                   2269:                snprintf(err_buf, sizeof err_buf,
                   2270:                         "--%s is not supported on this %s\n",
                   2271:                         append_mode ? "append" : "inplace",
                   2272:                         am_server ? "server" : "client");
                   2273:                return 0;
                   2274: #endif
                   2275:        } else {
                   2276:                if (keep_partial && !partial_dir && !am_server) {
                   2277:                        if ((arg = getenv("RSYNC_PARTIAL_DIR")) != NULL && *arg)
                   2278:                                partial_dir = strdup(arg);
                   2279:                }
                   2280:                if (partial_dir) {
                   2281:                        if (*partial_dir)
                   2282:                                clean_fname(partial_dir, CFN_COLLAPSE_DOT_DOT_DIRS);
                   2283:                        if (!*partial_dir || strcmp(partial_dir, ".") == 0)
                   2284:                                partial_dir = NULL;
                   2285:                        if (!partial_dir && refused_partial) {
                   2286:                                create_refuse_error(refused_partial);
                   2287:                                return 0;
                   2288:                        }
                   2289:                        keep_partial = 1;
                   2290:                }
                   2291:        }
                   2292: 
                   2293:        if (files_from) {
                   2294:                char *h, *p;
                   2295:                int q;
1.1.1.2   misho    2296:                if (argc > 2 || (!am_daemon && !am_server && argc == 1)) {
1.1       misho    2297:                        usage(FERROR);
                   2298:                        exit_cleanup(RERR_SYNTAX);
                   2299:                }
                   2300:                if (strcmp(files_from, "-") == 0) {
                   2301:                        filesfrom_fd = 0;
                   2302:                        if (am_server)
                   2303:                                filesfrom_host = ""; /* reading from socket */
                   2304:                } else if ((p = check_for_hostspec(files_from, &h, &q)) != 0) {
                   2305:                        if (am_server) {
                   2306:                                snprintf(err_buf, sizeof err_buf,
                   2307:                                        "The --files-from sent to the server cannot specify a host.\n");
                   2308:                                return 0;
                   2309:                        }
                   2310:                        files_from = p;
                   2311:                        filesfrom_host = h;
                   2312:                        if (strcmp(files_from, "-") == 0) {
                   2313:                                snprintf(err_buf, sizeof err_buf,
                   2314:                                        "Invalid --files-from remote filename\n");
                   2315:                                return 0;
                   2316:                        }
                   2317:                } else {
                   2318:                        if (sanitize_paths)
                   2319:                                files_from = sanitize_path(NULL, files_from, NULL, 0, SP_DEFAULT);
                   2320:                        if (daemon_filter_list.head) {
                   2321:                                char *dir;
                   2322:                                if (!*files_from)
                   2323:                                        goto options_rejected;
                   2324:                                dir = files_from + (*files_from == '/' ? module_dirlen : 0);
                   2325:                                clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
                   2326:                                if (check_filter(&daemon_filter_list, FLOG, dir, 0) < 0)
                   2327:                                        goto options_rejected;
                   2328:                        }
                   2329:                        filesfrom_fd = open(files_from, O_RDONLY|O_BINARY);
                   2330:                        if (filesfrom_fd < 0) {
                   2331:                                snprintf(err_buf, sizeof err_buf,
                   2332:                                        "failed to open files-from file %s: %s\n",
                   2333:                                        files_from, strerror(errno));
                   2334:                                return 0;
                   2335:                        }
                   2336:                }
                   2337:        }
                   2338: 
                   2339:        am_starting_up = 0;
                   2340: 
                   2341:        return 1;
                   2342: 
                   2343:   options_rejected:
                   2344:        snprintf(err_buf, sizeof err_buf,
                   2345:                "Your options have been rejected by the server.\n");
                   2346:        return 0;
                   2347: }
                   2348: 
                   2349: 
                   2350: /**
                   2351:  * Construct a filtered list of options to pass through from the
                   2352:  * client to the server.
                   2353:  *
                   2354:  * This involves setting options that will tell the server how to
                   2355:  * behave, and also filtering out options that are processed only
                   2356:  * locally.
                   2357:  **/
                   2358: void server_options(char **args, int *argc_p)
                   2359: {
                   2360:        static char argstr[64];
                   2361:        int ac = *argc_p;
1.1.1.2   misho    2362:        uchar where;
1.1       misho    2363:        char *arg;
                   2364:        int i, x;
                   2365: 
                   2366:        /* This should always remain first on the server's command-line. */
                   2367:        args[ac++] = "--server";
                   2368: 
                   2369:        if (daemon_over_rsh > 0) {
                   2370:                args[ac++] = "--daemon";
                   2371:                *argc_p = ac;
                   2372:                /* if we're passing --daemon, we're done */
                   2373:                return;
                   2374:        }
                   2375: 
                   2376:        if (!am_sender)
                   2377:                args[ac++] = "--sender";
                   2378: 
                   2379:        x = 1;
                   2380:        argstr[0] = '-';
                   2381: 
                   2382:        if (protect_args)
                   2383:                argstr[x++] = 's';
                   2384: 
                   2385:        for (i = 0; i < verbose; i++)
                   2386:                argstr[x++] = 'v';
                   2387: 
                   2388:        /* the -q option is intentionally left out */
                   2389:        if (make_backups)
                   2390:                argstr[x++] = 'b';
                   2391:        if (update_only)
                   2392:                argstr[x++] = 'u';
                   2393:        if (!do_xfers) /* Note: NOT "dry_run"! */
                   2394:                argstr[x++] = 'n';
                   2395:        if (preserve_links)
                   2396:                argstr[x++] = 'l';
                   2397:        if ((xfer_dirs >= 2 && xfer_dirs < 4)
                   2398:         || (xfer_dirs && !recurse && (list_only || (delete_mode && am_sender))))
                   2399:                argstr[x++] = 'd';
                   2400:        if (am_sender) {
                   2401:                if (keep_dirlinks)
                   2402:                        argstr[x++] = 'K';
                   2403:                if (prune_empty_dirs)
                   2404:                        argstr[x++] = 'm';
                   2405:                if (omit_dir_times)
                   2406:                        argstr[x++] = 'O';
1.1.1.2   misho    2407:                if (omit_link_times)
                   2408:                        argstr[x++] = 'J';
                   2409:                if (fuzzy_basis) {
                   2410:                        argstr[x++] = 'y';
                   2411:                        if (fuzzy_basis > 1)
                   2412:                                argstr[x++] = 'y';
                   2413:                }
1.1       misho    2414:        } else {
                   2415:                if (copy_links)
                   2416:                        argstr[x++] = 'L';
                   2417:                if (copy_dirlinks)
                   2418:                        argstr[x++] = 'k';
                   2419:        }
                   2420: 
                   2421:        if (whole_file > 0)
                   2422:                argstr[x++] = 'W';
                   2423:        /* We don't need to send --no-whole-file, because it's the
                   2424:         * default for remote transfers, and in any case old versions
                   2425:         * of rsync will not understand it. */
                   2426: 
                   2427:        if (preserve_hard_links) {
                   2428:                argstr[x++] = 'H';
                   2429:                if (preserve_hard_links > 1)
                   2430:                        argstr[x++] = 'H';
                   2431:        }
                   2432:        if (preserve_uid)
                   2433:                argstr[x++] = 'o';
                   2434:        if (preserve_gid)
                   2435:                argstr[x++] = 'g';
                   2436:        if (preserve_devices) /* ignore preserve_specials here */
                   2437:                argstr[x++] = 'D';
                   2438:        if (preserve_times)
                   2439:                argstr[x++] = 't';
                   2440:        if (preserve_perms)
                   2441:                argstr[x++] = 'p';
                   2442:        else if (preserve_executability && am_sender)
                   2443:                argstr[x++] = 'E';
                   2444: #ifdef SUPPORT_ACLS
                   2445:        if (preserve_acls)
                   2446:                argstr[x++] = 'A';
                   2447: #endif
                   2448: #ifdef SUPPORT_XATTRS
                   2449:        if (preserve_xattrs) {
                   2450:                argstr[x++] = 'X';
                   2451:                if (preserve_xattrs > 1)
                   2452:                        argstr[x++] = 'X';
                   2453:        }
                   2454: #endif
                   2455:        if (recurse)
                   2456:                argstr[x++] = 'r';
                   2457:        if (always_checksum)
                   2458:                argstr[x++] = 'c';
                   2459:        if (cvs_exclude)
                   2460:                argstr[x++] = 'C';
                   2461:        if (ignore_times)
                   2462:                argstr[x++] = 'I';
                   2463:        if (relative_paths)
                   2464:                argstr[x++] = 'R';
                   2465:        if (one_file_system) {
                   2466:                argstr[x++] = 'x';
                   2467:                if (one_file_system > 1)
                   2468:                        argstr[x++] = 'x';
                   2469:        }
                   2470:        if (sparse_files)
                   2471:                argstr[x++] = 'S';
1.1.1.3 ! misho    2472:        if (do_compression == 1)
1.1       misho    2473:                argstr[x++] = 'z';
                   2474: 
                   2475:        set_allow_inc_recurse();
                   2476: 
1.1.1.3 ! misho    2477:        /* We don't really know the actual protocol_version at this point,
        !          2478:         * but checking the pre-negotiated value allows the user to use a
        !          2479:         * --protocol=29 override to avoid the use of this -eFLAGS opt. */
1.1       misho    2480:        if (protocol_version >= 30) {
1.1.1.3 ! misho    2481:                /* Use "eFlags" alias so that cull_options doesn't think that these are no-arg option letters. */
        !          2482: #define eFlags argstr
1.1       misho    2483:                /* We make use of the -e option to let the server know about
                   2484:                 * any pre-release protocol version && some behavior flags. */
1.1.1.3 ! misho    2485:                eFlags[x++] = 'e';
1.1       misho    2486: #if SUBPROTOCOL_VERSION != 0
                   2487:                if (protocol_version == PROTOCOL_VERSION) {
                   2488:                        x += snprintf(argstr+x, sizeof argstr - x,
                   2489:                                      "%d.%d",
                   2490:                                      PROTOCOL_VERSION, SUBPROTOCOL_VERSION);
                   2491:                } else
                   2492: #endif
1.1.1.3 ! misho    2493:                        eFlags[x++] = '.';
1.1       misho    2494:                if (allow_inc_recurse)
1.1.1.3 ! misho    2495:                        eFlags[x++] = 'i';
1.1       misho    2496: #ifdef CAN_SET_SYMLINK_TIMES
1.1.1.3 ! misho    2497:                eFlags[x++] = 'L'; /* symlink time-setting support */
1.1       misho    2498: #endif
                   2499: #ifdef ICONV_OPTION
1.1.1.3 ! misho    2500:                eFlags[x++] = 's'; /* symlink iconv translation support */
1.1       misho    2501: #endif
1.1.1.3 ! misho    2502:                eFlags[x++] = 'f'; /* flist I/O-error safety support */
        !          2503:                eFlags[x++] = 'x'; /* xattr hardlink optimization not desired */
        !          2504:                eFlags[x++] = 'C'; /* support checksum seed order fix */
        !          2505: #undef eFlags
1.1       misho    2506:        }
                   2507: 
                   2508:        if (x >= (int)sizeof argstr) { /* Not possible... */
                   2509:                rprintf(FERROR, "argstr overflow in server_options().\n");
                   2510:                exit_cleanup(RERR_MALLOC);
                   2511:        }
                   2512: 
                   2513:        argstr[x] = '\0';
                   2514: 
                   2515:        if (x > 1)
                   2516:                args[ac++] = argstr;
                   2517: 
                   2518: #ifdef ICONV_OPTION
                   2519:        if (iconv_opt) {
                   2520:                char *set = strchr(iconv_opt, ',');
                   2521:                if (set)
                   2522:                        set++;
                   2523:                else
                   2524:                        set = iconv_opt;
                   2525:                if (asprintf(&arg, "--iconv=%s", set) < 0)
                   2526:                        goto oom;
                   2527:                args[ac++] = arg;
                   2528:        }
                   2529: #endif
                   2530: 
                   2531:        if (protect_args && !local_server) /* unprotected args stop here */
                   2532:                args[ac++] = NULL;
                   2533: 
                   2534:        if (list_only > 1)
                   2535:                args[ac++] = "--list-only";
                   2536: 
                   2537:        /* This makes sure that the remote rsync can handle deleting with -d
                   2538:         * sans -r because the --no-r option was added at the same time. */
                   2539:        if (xfer_dirs && !recurse && delete_mode && am_sender)
                   2540:                args[ac++] = "--no-r";
                   2541: 
                   2542:        if (do_compression && def_compress_level != Z_DEFAULT_COMPRESSION) {
                   2543:                if (asprintf(&arg, "--compress-level=%d", def_compress_level) < 0)
                   2544:                        goto oom;
                   2545:                args[ac++] = arg;
                   2546:        }
                   2547: 
                   2548:        if (preserve_devices) {
                   2549:                /* Note: sending "--devices" would not be backward-compatible. */
                   2550:                if (!preserve_specials)
                   2551:                        args[ac++] = "--no-specials"; /* -D is already set. */
                   2552:        } else if (preserve_specials)
                   2553:                args[ac++] = "--specials";
                   2554: 
                   2555:        /* The server side doesn't use our log-format, but in certain
                   2556:         * circumstances they need to know a little about the option. */
                   2557:        if (stdout_format && am_sender) {
                   2558:                /* Use --log-format, not --out-format, for compatibility. */
                   2559:                if (stdout_format_has_i > 1)
                   2560:                        args[ac++] = "--log-format=%i%I";
                   2561:                else if (stdout_format_has_i)
                   2562:                        args[ac++] = "--log-format=%i";
                   2563:                else if (stdout_format_has_o_or_i)
                   2564:                        args[ac++] = "--log-format=%o";
                   2565:                else if (!verbose)
                   2566:                        args[ac++] = "--log-format=X";
                   2567:        }
                   2568: 
                   2569:        if (block_size) {
                   2570:                if (asprintf(&arg, "-B%lu", block_size) < 0)
                   2571:                        goto oom;
                   2572:                args[ac++] = arg;
                   2573:        }
                   2574: 
                   2575:        if (io_timeout) {
                   2576:                if (asprintf(&arg, "--timeout=%d", io_timeout) < 0)
                   2577:                        goto oom;
                   2578:                args[ac++] = arg;
                   2579:        }
                   2580: 
                   2581:        if (bwlimit) {
                   2582:                if (asprintf(&arg, "--bwlimit=%d", bwlimit) < 0)
                   2583:                        goto oom;
                   2584:                args[ac++] = arg;
                   2585:        }
                   2586: 
                   2587:        if (backup_dir) {
                   2588:                args[ac++] = "--backup-dir";
                   2589:                args[ac++] = backup_dir;
                   2590:        }
                   2591: 
                   2592:        /* Only send --suffix if it specifies a non-default value. */
                   2593:        if (strcmp(backup_suffix, backup_dir ? "" : BACKUP_SUFFIX) != 0) {
                   2594:                /* We use the following syntax to avoid weirdness with '~'. */
                   2595:                if (asprintf(&arg, "--suffix=%s", backup_suffix) < 0)
                   2596:                        goto oom;
                   2597:                args[ac++] = arg;
                   2598:        }
                   2599: 
                   2600:        if (am_sender) {
                   2601:                if (max_delete > 0) {
                   2602:                        if (asprintf(&arg, "--max-delete=%d", max_delete) < 0)
                   2603:                                goto oom;
                   2604:                        args[ac++] = arg;
                   2605:                } else if (max_delete == 0)
                   2606:                        args[ac++] = "--max-delete=-1";
1.1.1.2   misho    2607:                if (min_size >= 0) {
1.1       misho    2608:                        args[ac++] = "--min-size";
                   2609:                        args[ac++] = min_size_arg;
                   2610:                }
1.1.1.2   misho    2611:                if (max_size >= 0) {
1.1       misho    2612:                        args[ac++] = "--max-size";
                   2613:                        args[ac++] = max_size_arg;
                   2614:                }
                   2615:                if (delete_before)
                   2616:                        args[ac++] = "--delete-before";
                   2617:                else if (delete_during == 2)
                   2618:                        args[ac++] = "--delete-delay";
                   2619:                else if (delete_during)
                   2620:                        args[ac++] = "--delete-during";
                   2621:                else if (delete_after)
                   2622:                        args[ac++] = "--delete-after";
                   2623:                else if (delete_mode && !delete_excluded)
                   2624:                        args[ac++] = "--delete";
                   2625:                if (delete_excluded)
                   2626:                        args[ac++] = "--delete-excluded";
                   2627:                if (force_delete)
                   2628:                        args[ac++] = "--force";
                   2629:                if (write_batch < 0)
                   2630:                        args[ac++] = "--only-write-batch=X";
                   2631:                if (am_root > 1)
                   2632:                        args[ac++] = "--super";
                   2633:                if (size_only)
                   2634:                        args[ac++] = "--size-only";
1.1.1.2   misho    2635:                if (do_stats)
                   2636:                        args[ac++] = "--stats";
1.1       misho    2637:        } else {
                   2638:                if (skip_compress) {
                   2639:                        if (asprintf(&arg, "--skip-compress=%s", skip_compress) < 0)
                   2640:                                goto oom;
                   2641:                        args[ac++] = arg;
                   2642:                }
                   2643:        }
                   2644: 
1.1.1.2   misho    2645:        /* --delete-missing-args needs the cooperation of both sides, but
                   2646:         * the sender can handle --ignore-missing-args by itself. */
                   2647:        if (missing_args == 2)
                   2648:                args[ac++] = "--delete-missing-args";
                   2649:        else if (missing_args == 1 && !am_sender)
                   2650:                args[ac++] = "--ignore-missing-args";
                   2651: 
1.1       misho    2652:        if (modify_window_set) {
                   2653:                if (asprintf(&arg, "--modify-window=%d", modify_window) < 0)
                   2654:                        goto oom;
                   2655:                args[ac++] = arg;
                   2656:        }
                   2657: 
                   2658:        if (checksum_seed) {
                   2659:                if (asprintf(&arg, "--checksum-seed=%d", checksum_seed) < 0)
                   2660:                        goto oom;
                   2661:                args[ac++] = arg;
                   2662:        }
                   2663: 
                   2664:        if (partial_dir && am_sender) {
                   2665:                if (partial_dir != tmp_partialdir) {
                   2666:                        args[ac++] = "--partial-dir";
                   2667:                        args[ac++] = partial_dir;
                   2668:                }
                   2669:                if (delay_updates)
                   2670:                        args[ac++] = "--delay-updates";
                   2671:        } else if (keep_partial && am_sender)
                   2672:                args[ac++] = "--partial";
                   2673: 
                   2674:        if (ignore_errors)
                   2675:                args[ac++] = "--ignore-errors";
                   2676: 
                   2677:        if (copy_unsafe_links)
                   2678:                args[ac++] = "--copy-unsafe-links";
                   2679: 
                   2680:        if (safe_symlinks)
                   2681:                args[ac++] = "--safe-links";
                   2682: 
                   2683:        if (numeric_ids)
                   2684:                args[ac++] = "--numeric-ids";
                   2685: 
                   2686:        if (use_qsort)
                   2687:                args[ac++] = "--use-qsort";
                   2688: 
                   2689:        if (am_sender) {
1.1.1.2   misho    2690:                if (usermap) {
                   2691:                        if (asprintf(&arg, "--usermap=%s", usermap) < 0)
                   2692:                                goto oom;
                   2693:                        args[ac++] = arg;
                   2694:                }
                   2695: 
                   2696:                if (groupmap) {
                   2697:                        if (asprintf(&arg, "--groupmap=%s", groupmap) < 0)
                   2698:                                goto oom;
                   2699:                        args[ac++] = arg;
                   2700:                }
                   2701: 
1.1       misho    2702:                if (ignore_existing)
                   2703:                        args[ac++] = "--ignore-existing";
                   2704: 
                   2705:                /* Backward compatibility: send --existing, not --ignore-non-existing. */
                   2706:                if (ignore_non_existing)
                   2707:                        args[ac++] = "--existing";
                   2708: 
                   2709:                if (tmpdir) {
                   2710:                        args[ac++] = "--temp-dir";
                   2711:                        args[ac++] = tmpdir;
                   2712:                }
                   2713: 
                   2714:                if (basis_dir[0]) {
                   2715:                        /* the server only needs this option if it is not the sender,
                   2716:                         *   and it may be an older version that doesn't know this
                   2717:                         *   option, so don't send it if client is the sender.
                   2718:                         */
                   2719:                        for (i = 0; i < basis_dir_cnt; i++) {
                   2720:                                args[ac++] = dest_option;
                   2721:                                args[ac++] = basis_dir[i];
                   2722:                        }
                   2723:                }
                   2724:        }
                   2725: 
1.1.1.2   misho    2726:        /* What flags do we need to send to the other side? */
                   2727:        where = (am_server ? W_CLI : W_SRV) | (am_sender ? W_REC : W_SND);
                   2728:        arg = make_output_option(info_words, info_levels, where);
                   2729:        if (arg)
                   2730:                args[ac++] = arg;
                   2731: 
                   2732:        arg = make_output_option(debug_words, debug_levels, where);
                   2733:        if (arg)
                   2734:                args[ac++] = arg;
                   2735: 
1.1       misho    2736:        if (append_mode) {
                   2737:                if (append_mode > 1)
                   2738:                        args[ac++] = "--append";
                   2739:                args[ac++] = "--append";
                   2740:        } else if (inplace)
                   2741:                args[ac++] = "--inplace";
                   2742: 
                   2743:        if (files_from && (!am_sender || filesfrom_host)) {
                   2744:                if (filesfrom_host) {
                   2745:                        args[ac++] = "--files-from";
                   2746:                        args[ac++] = files_from;
                   2747:                        if (eol_nulls)
                   2748:                                args[ac++] = "--from0";
                   2749:                } else {
                   2750:                        args[ac++] = "--files-from=-";
                   2751:                        args[ac++] = "--from0";
                   2752:                }
                   2753:                if (!relative_paths)
                   2754:                        args[ac++] = "--no-relative";
                   2755:        }
                   2756:        /* It's OK that this checks the upper-bound of the protocol_version. */
                   2757:        if (relative_paths && !implied_dirs && (!am_sender || protocol_version >= 30))
                   2758:                args[ac++] = "--no-implied-dirs";
                   2759: 
                   2760:        if (remove_source_files == 1)
                   2761:                args[ac++] = "--remove-source-files";
                   2762:        else if (remove_source_files)
                   2763:                args[ac++] = "--remove-sent-files";
                   2764: 
1.1.1.2   misho    2765:        if (preallocate_files && am_sender)
                   2766:                args[ac++] = "--preallocate";
                   2767: 
1.1       misho    2768:        if (ac > MAX_SERVER_ARGS) { /* Not possible... */
                   2769:                rprintf(FERROR, "argc overflow in server_options().\n");
                   2770:                exit_cleanup(RERR_MALLOC);
                   2771:        }
1.1.1.3 ! misho    2772: 
        !          2773:        if (do_compression > 1)
        !          2774:                args[ac++] = "--new-compress";
1.1       misho    2775: 
1.1.1.2   misho    2776:        if (remote_option_cnt) {
                   2777:                int j;
                   2778:                if (ac + remote_option_cnt > MAX_SERVER_ARGS) {
                   2779:                        rprintf(FERROR, "too many remote options specified.\n");
                   2780:                        exit_cleanup(RERR_SYNTAX);
                   2781:                }
                   2782:                for (j = 1; j <= remote_option_cnt; j++)
                   2783:                        args[ac++] = (char*)remote_options[j];
                   2784:        }
                   2785: 
1.1       misho    2786:        *argc_p = ac;
                   2787:        return;
                   2788: 
                   2789:     oom:
                   2790:        out_of_memory("server_options");
                   2791: }
                   2792: 
                   2793: /* If str points to a valid hostspec, return allocated memory containing the
                   2794:  * [USER@]HOST part of the string, and set the path_start_ptr to the part of
                   2795:  * the string after the host part.  Otherwise, return NULL.  If port_ptr is
                   2796:  * non-NULL, we must be parsing an rsync:// URL hostname, and we will set
                   2797:  * *port_ptr if a port number is found.  Note that IPv6 IPs will have their
                   2798:  * (required for parsing) [ and ] chars elided from the returned string. */
                   2799: static char *parse_hostspec(char *str, char **path_start_ptr, int *port_ptr)
                   2800: {
                   2801:        char *s, *host_start = str;
                   2802:        int hostlen = 0, userlen = 0;
                   2803:        char *ret;
                   2804: 
                   2805:        for (s = str; ; s++) {
                   2806:                if (!*s) {
                   2807:                        /* It is only OK if we run out of string with rsync:// */
                   2808:                        if (!port_ptr)
                   2809:                                return NULL;
                   2810:                        if (!hostlen)
                   2811:                                hostlen = s - host_start;
                   2812:                        break;
                   2813:                }
                   2814:                if (*s == ':' || *s == '/') {
                   2815:                        if (!hostlen)
                   2816:                                hostlen = s - host_start;
                   2817:                        if (*s++ == '/') {
                   2818:                                if (!port_ptr)
                   2819:                                        return NULL;
                   2820:                        } else if (port_ptr) {
                   2821:                                *port_ptr = atoi(s);
                   2822:                                while (isDigit(s)) s++;
                   2823:                                if (*s && *s++ != '/')
                   2824:                                        return NULL;
                   2825:                        }
                   2826:                        break;
                   2827:                }
                   2828:                if (*s == '@') {
                   2829:                        userlen = s - str + 1;
                   2830:                        host_start = s + 1;
                   2831:                } else if (*s == '[') {
                   2832:                        if (s != host_start++)
                   2833:                                return NULL;
                   2834:                        while (*s && *s != ']' && *s != '/') s++; /*SHARED ITERATOR*/
                   2835:                        hostlen = s - host_start;
                   2836:                        if (*s != ']' || (s[1] && s[1] != '/' && s[1] != ':') || !hostlen)
                   2837:                                return NULL;
                   2838:                }
                   2839:        }
                   2840: 
                   2841:        *path_start_ptr = s;
                   2842:        ret = new_array(char, userlen + hostlen + 1);
                   2843:        if (userlen)
                   2844:                strlcpy(ret, str, userlen + 1);
                   2845:        strlcpy(ret + userlen, host_start, hostlen + 1);
                   2846:        return ret;
                   2847: }
                   2848: 
                   2849: /* Look for a HOST specfication of the form "HOST:PATH", "HOST::PATH", or
                   2850:  * "rsync://HOST:PORT/PATH".  If found, *host_ptr will be set to some allocated
                   2851:  * memory with the HOST.  If a daemon-accessing spec was specified, the value
                   2852:  * of *port_ptr will contain a non-0 port number, otherwise it will be set to
                   2853:  * 0.  The return value is a pointer to the PATH.  Note that the HOST spec can
                   2854:  * be an IPv6 literal address enclosed in '[' and ']' (such as "[::1]" or
                   2855:  * "[::ffff:127.0.0.1]") which is returned without the '[' and ']'. */
                   2856: char *check_for_hostspec(char *s, char **host_ptr, int *port_ptr)
                   2857: {
                   2858:        char *path;
                   2859: 
                   2860:        if (port_ptr && strncasecmp(URL_PREFIX, s, strlen(URL_PREFIX)) == 0) {
                   2861:                *host_ptr = parse_hostspec(s + strlen(URL_PREFIX), &path, port_ptr);
                   2862:                if (*host_ptr) {
                   2863:                        if (!*port_ptr)
                   2864:                                *port_ptr = RSYNC_PORT;
                   2865:                        return path;
                   2866:                }
                   2867:        }
                   2868: 
                   2869:        *host_ptr = parse_hostspec(s, &path, NULL);
                   2870:        if (!*host_ptr)
                   2871:                return NULL;
                   2872: 
                   2873:        if (*path == ':') {
                   2874:                if (port_ptr && !*port_ptr)
                   2875:                        *port_ptr = RSYNC_PORT;
                   2876:                return path + 1;
                   2877:        }
                   2878:        if (port_ptr)
                   2879:                *port_ptr = 0;
                   2880: 
                   2881:        return path;
                   2882: }

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