X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/52d9a554d12c14d6964843a1c154ba8e78f78b09..b3bf9b9df95137a3a43248be9599d919b04877af:/compat.c diff --git a/compat.c b/compat.c index 888f94d9..6e000724 100644 --- a/compat.c +++ b/compat.c @@ -3,7 +3,7 @@ * * Copyright (C) Andrew Tridgell 1996 * Copyright (C) Paul Mackerras 1996 - * Copyright (C) 2004-2007 Wayne Davison + * Copyright (C) 2004-2009 Wayne Davison * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,7 +25,6 @@ int remote_protocol = 0; int file_extra_cnt = 0; /* count of file-list extras that everyone gets */ int inc_recurse = 0; -extern int verbose; extern int am_server; extern int am_sender; extern int local_server; @@ -48,25 +47,34 @@ extern int preserve_acls; extern int preserve_xattrs; extern int need_messages_from_generator; extern int delete_mode, delete_before, delete_during, delete_after; -extern char *shell_cmd; /* contains VER.SUB string if client is a pre-release */ +extern char *shell_cmd; extern char *partial_dir; extern char *dest_option; extern char *files_from; extern char *filesfrom_host; extern struct filter_list_struct filter_list; +extern int need_unsorted_flist; #ifdef ICONV_OPTION -extern char *iconv_opt; extern iconv_t ic_send, ic_recv; +extern char *iconv_opt; #endif /* These index values are for the file-list's extra-attribute array. */ -int uid_ndx, gid_ndx, acls_ndx, xattrs_ndx; -#ifdef ICONV_OPTION -int ic_ndx; +int uid_ndx, gid_ndx, acls_ndx, xattrs_ndx, unsort_ndx; +int receiver_symlink_times = 0; /* receiver can set the time on a symlink */ +int sender_symlink_iconv = 0; /* sender should convert symlink content */ + +#ifdef ICONV_OPTION int filesfrom_convert = 0; #endif +#define CF_INC_RECURSE (1<<0) +#define CF_SYMLINK_TIMES (1<<1) +#define CF_SYMLINK_ICONV (1<<2) + +static const char *client_info; + /* The server makes sure that if either side only supports a pre-release * version of a protocol, that both sides must speak a compatible version * of that protocol for it to be advertised as available. */ @@ -80,8 +88,9 @@ static void check_sub_protocol(void) int our_sub = 0; #endif - if (!shell_cmd || !(dot = strchr(shell_cmd, '.')) - || !(their_protocol = atoi(shell_cmd)) + /* client_info starts with VER.SUB string if client is a pre-release. */ + if (!(their_protocol = atoi(client_info)) + || !(dot = strchr(client_info, '.')) || !(their_sub = atoi(dot+1))) { #if SUBPROTOCOL_VERSION != 0 if (our_sub) @@ -104,6 +113,8 @@ static void check_sub_protocol(void) void set_allow_inc_recurse(void) { + client_info = shell_cmd ? shell_cmd : ""; + if (!recurse || use_qsort) allow_inc_recurse = 0; else if (!am_sender @@ -111,7 +122,7 @@ void set_allow_inc_recurse(void) || delay_updates || prune_empty_dirs)) allow_inc_recurse = 0; else if (am_server && !local_server - && (!shell_cmd || strchr(shell_cmd, 'i') == NULL)) + && (strchr(client_info, 'i') == NULL)) allow_inc_recurse = 0; } @@ -148,7 +159,7 @@ void setup_protocol(int f_out,int f_in) exit_cleanup(RERR_PROTOCOL); } - if (verbose > 3) { + if (DEBUG_GTE(PROTO, 1)) { rprintf(FINFO, "(%s) Protocol versions: remote=%d, negotiated=%d\n", am_server? "Server" : "Client", remote_protocol, protocol_version); } @@ -172,6 +183,8 @@ void setup_protocol(int f_out,int f_in) PROTOCOL_VERSION, am_server? "Server" : "Client"); exit_cleanup(RERR_PROTOCOL); } + if (read_batch) + check_batch_flags(); if (protocol_version < 30) { if (append_mode == 1) @@ -232,11 +245,34 @@ void setup_protocol(int f_out,int f_in) exit_cleanup(RERR_PROTOCOL); } } else if (protocol_version >= 30) { + int compat_flags; if (am_server) { - inc_recurse = allow_inc_recurse; - write_byte(f_out, inc_recurse); + compat_flags = allow_inc_recurse ? CF_INC_RECURSE : 0; +#if defined HAVE_LUTIMES && defined HAVE_UTIMES + compat_flags |= CF_SYMLINK_TIMES; +#endif +#ifdef ICONV_OPTION + compat_flags |= CF_SYMLINK_ICONV; +#endif + write_byte(f_out, compat_flags); } else - inc_recurse = read_byte(f_in); + compat_flags = read_byte(f_in); + /* The inc_recurse var MUST be set to 0 or 1. */ + inc_recurse = compat_flags & CF_INC_RECURSE ? 1 : 0; + if (am_sender) { + receiver_symlink_times = am_server + ? strchr(client_info, 'L') != NULL + : !!(compat_flags & CF_SYMLINK_TIMES); + } +#if defined HAVE_LUTIMES && defined HAVE_UTIMES + else + receiver_symlink_times = 1; +#endif +#ifdef ICONV_OPTION + sender_symlink_iconv = iconv_opt && (am_server + ? strchr(client_info, 's') != NULL + : !!(compat_flags & CF_SYMLINK_ICONV)); +#endif if (inc_recurse && !allow_inc_recurse) { /* This should only be able to happen in a batch. */ fprintf(stderr, @@ -245,12 +281,14 @@ void setup_protocol(int f_out,int f_in) exit_cleanup(RERR_SYNTAX); } need_messages_from_generator = 1; +#if defined HAVE_LUTIMES && defined HAVE_UTIMES + } else if (!am_sender) { + receiver_symlink_times = 1; +#endif } -#ifdef ICONV_OPTION - if (iconv_opt && (!am_sender || inc_recurse)) - ic_ndx = ++file_extra_cnt; -#endif + if (need_unsorted_flist && (!am_sender || inc_recurse)) + unsort_ndx = ++file_extra_cnt; if (partial_dir && *partial_dir != '/' && (!am_server || local_server)) { int flags = MATCHFLG_NO_PREFIXES | MATCHFLG_DIRECTORY;