compat.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. /*
  2. * Compatibility routines for older rsync protocol versions.
  3. *
  4. * Copyright (C) Andrew Tridgell 1996
  5. * Copyright (C) Paul Mackerras 1996
  6. * Copyright (C) 2004-2009 Wayne Davison
  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. #include "rsync.h"
  22. int remote_protocol = 0;
  23. int file_extra_cnt = 0; /* count of file-list extras that everyone gets */
  24. int inc_recurse = 0;
  25. int compat_flags = 0;
  26. int use_safe_inc_flist = 0;
  27. extern int verbose;
  28. extern int am_server;
  29. extern int am_sender;
  30. extern int local_server;
  31. extern int inplace;
  32. extern int recurse;
  33. extern int use_qsort;
  34. extern int allow_inc_recurse;
  35. extern int append_mode;
  36. extern int fuzzy_basis;
  37. extern int read_batch;
  38. extern int delay_updates;
  39. extern int checksum_seed;
  40. extern int basis_dir_cnt;
  41. extern int prune_empty_dirs;
  42. extern int protocol_version;
  43. extern int protect_args;
  44. extern int preserve_uid;
  45. extern int preserve_gid;
  46. extern int preserve_acls;
  47. extern int preserve_xattrs;
  48. extern int need_messages_from_generator;
  49. extern int delete_mode, delete_before, delete_during, delete_after;
  50. extern char *shell_cmd;
  51. extern char *partial_dir;
  52. extern char *dest_option;
  53. extern char *files_from;
  54. extern char *filesfrom_host;
  55. extern struct filter_list_struct filter_list;
  56. extern int need_unsorted_flist;
  57. #ifdef ICONV_OPTION
  58. extern iconv_t ic_send, ic_recv;
  59. extern char *iconv_opt;
  60. #endif
  61. /* These index values are for the file-list's extra-attribute array. */
  62. int uid_ndx, gid_ndx, acls_ndx, xattrs_ndx, unsort_ndx;
  63. int receiver_symlink_times = 0; /* receiver can set the time on a symlink */
  64. int sender_symlink_iconv = 0; /* sender should convert symlink content */
  65. #ifdef ICONV_OPTION
  66. int filesfrom_convert = 0;
  67. #endif
  68. #define CF_INC_RECURSE (1<<0)
  69. #define CF_SYMLINK_TIMES (1<<1)
  70. #define CF_SYMLINK_ICONV (1<<2)
  71. #define CF_SAFE_FLIST (1<<3)
  72. static const char *client_info;
  73. /* The server makes sure that if either side only supports a pre-release
  74. * version of a protocol, that both sides must speak a compatible version
  75. * of that protocol for it to be advertised as available. */
  76. static void check_sub_protocol(void)
  77. {
  78. char *dot;
  79. int their_protocol, their_sub;
  80. #if SUBPROTOCOL_VERSION != 0
  81. int our_sub = protocol_version < PROTOCOL_VERSION ? 0 : SUBPROTOCOL_VERSION;
  82. #else
  83. int our_sub = 0;
  84. #endif
  85. /* client_info starts with VER.SUB string if client is a pre-release. */
  86. if (!(their_protocol = atoi(client_info))
  87. || !(dot = strchr(client_info, '.'))
  88. || !(their_sub = atoi(dot+1))) {
  89. #if SUBPROTOCOL_VERSION != 0
  90. if (our_sub)
  91. protocol_version--;
  92. #endif
  93. return;
  94. }
  95. if (their_protocol < protocol_version) {
  96. if (their_sub)
  97. protocol_version = their_protocol - 1;
  98. return;
  99. }
  100. if (their_protocol > protocol_version)
  101. their_sub = 0; /* 0 == final version of older protocol */
  102. if (their_sub != our_sub)
  103. protocol_version--;
  104. }
  105. void set_allow_inc_recurse(void)
  106. {
  107. client_info = shell_cmd ? shell_cmd : "";
  108. if (!recurse || use_qsort)
  109. allow_inc_recurse = 0;
  110. else if (!am_sender
  111. && (delete_before || delete_after
  112. || delay_updates || prune_empty_dirs))
  113. allow_inc_recurse = 0;
  114. else if (am_server && !local_server
  115. && (strchr(client_info, 'i') == NULL))
  116. allow_inc_recurse = 0;
  117. }
  118. void setup_protocol(int f_out,int f_in)
  119. {
  120. if (am_sender)
  121. file_extra_cnt += PTR_EXTRA_CNT;
  122. else
  123. file_extra_cnt++;
  124. if (preserve_uid)
  125. uid_ndx = ++file_extra_cnt;
  126. if (preserve_gid)
  127. gid_ndx = ++file_extra_cnt;
  128. if (preserve_acls && !am_sender)
  129. acls_ndx = ++file_extra_cnt;
  130. if (preserve_xattrs)
  131. xattrs_ndx = ++file_extra_cnt;
  132. if (am_server)
  133. set_allow_inc_recurse();
  134. if (remote_protocol == 0) {
  135. if (am_server && !local_server)
  136. check_sub_protocol();
  137. if (!read_batch)
  138. write_int(f_out, protocol_version);
  139. remote_protocol = read_int(f_in);
  140. if (protocol_version > remote_protocol)
  141. protocol_version = remote_protocol;
  142. }
  143. if (read_batch && remote_protocol > protocol_version) {
  144. rprintf(FERROR, "The protocol version in the batch file is too new (%d > %d).\n",
  145. remote_protocol, protocol_version);
  146. exit_cleanup(RERR_PROTOCOL);
  147. }
  148. if (verbose > 3) {
  149. rprintf(FINFO, "(%s) Protocol versions: remote=%d, negotiated=%d\n",
  150. am_server? "Server" : "Client", remote_protocol, protocol_version);
  151. }
  152. if (remote_protocol < MIN_PROTOCOL_VERSION
  153. || remote_protocol > MAX_PROTOCOL_VERSION) {
  154. rprintf(FERROR,"protocol version mismatch -- is your shell clean?\n");
  155. rprintf(FERROR,"(see the rsync man page for an explanation)\n");
  156. exit_cleanup(RERR_PROTOCOL);
  157. }
  158. if (remote_protocol < OLD_PROTOCOL_VERSION) {
  159. rprintf(FINFO,"%s is very old version of rsync, upgrade recommended.\n",
  160. am_server? "Client" : "Server");
  161. }
  162. if (protocol_version < MIN_PROTOCOL_VERSION) {
  163. rprintf(FERROR, "--protocol must be at least %d on the %s.\n",
  164. MIN_PROTOCOL_VERSION, am_server? "Server" : "Client");
  165. exit_cleanup(RERR_PROTOCOL);
  166. }
  167. if (protocol_version > PROTOCOL_VERSION) {
  168. rprintf(FERROR, "--protocol must be no more than %d on the %s.\n",
  169. PROTOCOL_VERSION, am_server? "Server" : "Client");
  170. exit_cleanup(RERR_PROTOCOL);
  171. }
  172. if (read_batch)
  173. check_batch_flags();
  174. if (protocol_version < 30) {
  175. if (append_mode == 1)
  176. append_mode = 2;
  177. if (preserve_acls && !local_server) {
  178. rprintf(FERROR,
  179. "--acls requires protocol 30 or higher"
  180. " (negotiated %d).\n",
  181. protocol_version);
  182. exit_cleanup(RERR_PROTOCOL);
  183. }
  184. if (preserve_xattrs && !local_server) {
  185. rprintf(FERROR,
  186. "--xattrs requires protocol 30 or higher"
  187. " (negotiated %d).\n",
  188. protocol_version);
  189. exit_cleanup(RERR_PROTOCOL);
  190. }
  191. }
  192. if (delete_mode && !(delete_before+delete_during+delete_after)) {
  193. if (protocol_version < 30)
  194. delete_before = 1;
  195. else
  196. delete_during = 1;
  197. }
  198. if (protocol_version < 29) {
  199. if (fuzzy_basis) {
  200. rprintf(FERROR,
  201. "--fuzzy requires protocol 29 or higher"
  202. " (negotiated %d).\n",
  203. protocol_version);
  204. exit_cleanup(RERR_PROTOCOL);
  205. }
  206. if (basis_dir_cnt && inplace) {
  207. rprintf(FERROR,
  208. "%s with --inplace requires protocol 29 or higher"
  209. " (negotiated %d).\n",
  210. dest_option, protocol_version);
  211. exit_cleanup(RERR_PROTOCOL);
  212. }
  213. if (basis_dir_cnt > 1) {
  214. rprintf(FERROR,
  215. "Using more than one %s option requires protocol"
  216. " 29 or higher (negotiated %d).\n",
  217. dest_option, protocol_version);
  218. exit_cleanup(RERR_PROTOCOL);
  219. }
  220. if (prune_empty_dirs) {
  221. rprintf(FERROR,
  222. "--prune-empty-dirs requires protocol 29 or higher"
  223. " (negotiated %d).\n",
  224. protocol_version);
  225. exit_cleanup(RERR_PROTOCOL);
  226. }
  227. } else if (protocol_version >= 30) {
  228. if (am_server) {
  229. compat_flags = allow_inc_recurse ? CF_INC_RECURSE : 0;
  230. #ifdef CAN_SET_SYMLINK_TIMES
  231. compat_flags |= CF_SYMLINK_TIMES;
  232. #endif
  233. #ifdef ICONV_OPTION
  234. compat_flags |= CF_SYMLINK_ICONV;
  235. #endif
  236. if (local_server || strchr(client_info, 'f') != NULL)
  237. compat_flags |= CF_SAFE_FLIST;
  238. write_byte(f_out, compat_flags);
  239. } else
  240. compat_flags = read_byte(f_in);
  241. /* The inc_recurse var MUST be set to 0 or 1. */
  242. inc_recurse = compat_flags & CF_INC_RECURSE ? 1 : 0;
  243. if (am_sender) {
  244. receiver_symlink_times = am_server
  245. ? strchr(client_info, 'L') != NULL
  246. : !!(compat_flags & CF_SYMLINK_TIMES);
  247. }
  248. #ifdef CAN_SET_SYMLINK_TIMES
  249. else
  250. receiver_symlink_times = 1;
  251. #endif
  252. #ifdef ICONV_OPTION
  253. sender_symlink_iconv = iconv_opt && (am_server
  254. ? local_server || strchr(client_info, 's') != NULL
  255. : !!(compat_flags & CF_SYMLINK_ICONV));
  256. #endif
  257. if (inc_recurse && !allow_inc_recurse) {
  258. /* This should only be able to happen in a batch. */
  259. fprintf(stderr,
  260. "Incompatible options specified for inc-recursive %s.\n",
  261. read_batch ? "batch file" : "connection");
  262. exit_cleanup(RERR_SYNTAX);
  263. }
  264. use_safe_inc_flist = !!(compat_flags & CF_SAFE_FLIST);
  265. need_messages_from_generator = 1;
  266. #ifdef CAN_SET_SYMLINK_TIMES
  267. } else if (!am_sender) {
  268. receiver_symlink_times = 1;
  269. #endif
  270. }
  271. if (need_unsorted_flist && (!am_sender || inc_recurse))
  272. unsort_ndx = ++file_extra_cnt;
  273. if (partial_dir && *partial_dir != '/' && (!am_server || local_server)) {
  274. int flags = MATCHFLG_NO_PREFIXES | MATCHFLG_DIRECTORY;
  275. if (!am_sender || protocol_version >= 30)
  276. flags |= MATCHFLG_PERISHABLE;
  277. parse_rule(&filter_list, partial_dir, flags, 0);
  278. }
  279. #ifdef ICONV_OPTION
  280. if (protect_args && files_from) {
  281. if (am_sender)
  282. filesfrom_convert = filesfrom_host && ic_send != (iconv_t)-1;
  283. else
  284. filesfrom_convert = !filesfrom_host && ic_recv != (iconv_t)-1;
  285. }
  286. #endif
  287. if (am_server) {
  288. if (!checksum_seed)
  289. checksum_seed = time(NULL);
  290. write_int(f_out, checksum_seed);
  291. } else {
  292. checksum_seed = read_int(f_in);
  293. }
  294. }