Annotation of embedaddon/rsync/main.c, revision 1.1.1.3
1.1 misho 1: /*
2: * The startup routines, including main(), for rsync.
3: *
4: * Copyright (C) 1996-2001 Andrew Tridgell <tridge@samba.org>
5: * Copyright (C) 1996 Paul Mackerras
6: * Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
1.1.1.3 ! misho 7: * Copyright (C) 2003-2015 Wayne Davison
1.1 misho 8: *
9: * This program is free software; you can redistribute it and/or modify
10: * it under the terms of the GNU General Public License as published by
11: * the Free Software Foundation; either version 3 of the License, or
12: * (at your option) any later version.
13: *
14: * This program is distributed in the hope that it will be useful,
15: * but WITHOUT ANY WARRANTY; without even the implied warranty of
16: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17: * GNU General Public License for more details.
18: *
19: * You should have received a copy of the GNU General Public License along
20: * with this program; if not, visit the http://fsf.org website.
21: */
22:
23: #include "rsync.h"
1.1.1.2 misho 24: #include "inums.h"
1.1 misho 25: #include "io.h"
26: #if defined CONFIG_LOCALE && defined HAVE_LOCALE_H
27: #include <locale.h>
28: #endif
29:
1.1.1.2 misho 30: extern int force_change;
1.1 misho 31: extern int dry_run;
32: extern int list_only;
1.1.1.2 misho 33: extern int io_timeout;
1.1 misho 34: extern int am_root;
35: extern int am_server;
36: extern int am_sender;
37: extern int am_daemon;
38: extern int inc_recurse;
39: extern int blocking_io;
1.1.1.2 misho 40: extern int always_checksum;
1.1 misho 41: extern int remove_source_files;
1.1.1.2 misho 42: extern int output_needs_newline;
1.1 misho 43: extern int need_messages_from_generator;
44: extern int kluge_around_eof;
45: extern int got_xfer_error;
1.1.1.2 misho 46: extern int msgs2stderr;
1.1 misho 47: extern int module_id;
1.1.1.2 misho 48: extern int read_only;
1.1 misho 49: extern int copy_links;
50: extern int copy_dirlinks;
51: extern int copy_unsafe_links;
52: extern int keep_dirlinks;
53: extern int preserve_hard_links;
54: extern int protocol_version;
55: extern int file_total;
56: extern int recurse;
57: extern int xfer_dirs;
58: extern int protect_args;
59: extern int relative_paths;
60: extern int sanitize_paths;
61: extern int curr_dir_depth;
62: extern int curr_dir_len;
63: extern int module_id;
64: extern int rsync_port;
65: extern int whole_file;
66: extern int read_batch;
67: extern int write_batch;
68: extern int batch_fd;
1.1.1.2 misho 69: extern int sock_f_in;
70: extern int sock_f_out;
1.1 misho 71: extern int filesfrom_fd;
72: extern int connect_timeout;
1.1.1.2 misho 73: extern int send_msgs_to_gen;
1.1 misho 74: extern dev_t filesystem_dev;
75: extern pid_t cleanup_child_pid;
1.1.1.2 misho 76: extern size_t bwlimit_writemax;
1.1 misho 77: extern unsigned int module_dirlen;
1.1.1.2 misho 78: extern BOOL flist_receiving_enabled;
79: extern BOOL shutting_down;
1.1.1.3 ! misho 80: extern BOOL want_progress_now;
! 81: extern int backup_dir_len;
1.1.1.2 misho 82: extern int basis_dir_cnt;
1.1 misho 83: extern struct stats stats;
1.1.1.2 misho 84: extern char *stdout_format;
85: extern char *logfile_format;
1.1 misho 86: extern char *filesfrom_host;
87: extern char *partial_dir;
88: extern char *dest_option;
89: extern char *rsync_path;
90: extern char *shell_cmd;
91: extern char *batch_name;
92: extern char *password_file;
1.1.1.2 misho 93: extern char *backup_dir;
1.1 misho 94: extern char curr_dir[MAXPATHLEN];
1.1.1.2 misho 95: extern char backup_dir_buf[MAXPATHLEN];
96: extern char *basis_dir[MAX_BASIS_DIRS+1];
1.1 misho 97: extern struct file_list *first_flist;
1.1.1.2 misho 98: extern filter_rule_list daemon_filter_list;
1.1 misho 99:
100: uid_t our_uid;
1.1.1.2 misho 101: gid_t our_gid;
1.1 misho 102: int am_receiver = 0; /* Only set to 1 after the receiver/generator fork. */
103: int am_generator = 0; /* Only set to 1 after the receiver/generator fork. */
104: int local_server = 0;
105: int daemon_over_rsh = 0;
106: mode_t orig_umask = 0;
107: int batch_gen_fd = -1;
1.1.1.2 misho 108: int sender_keeps_checksum = 0;
1.1 misho 109:
110: /* There's probably never more than at most 2 outstanding child processes,
111: * but set it higher, just in case. */
112: #define MAXCHILDPROCS 7
113:
114: #ifdef HAVE_SIGACTION
115: # ifdef HAVE_SIGPROCMASK
116: # define SIGACTMASK(n,h) SIGACTION(n,h), sigaddset(&sigmask,(n))
117: # else
118: # define SIGACTMASK(n,h) SIGACTION(n,h)
119: # endif
120: static struct sigaction sigact;
121: #endif
122:
123: struct pid_status {
124: pid_t pid;
125: int status;
126: } pid_stat_table[MAXCHILDPROCS];
127:
128: static time_t starttime, endtime;
129: static int64 total_read, total_written;
130:
131: static void show_malloc_stats(void);
132:
133: /* Works like waitpid(), but if we already harvested the child pid in our
134: * remember_children(), we succeed instead of returning an error. */
135: pid_t wait_process(pid_t pid, int *status_ptr, int flags)
136: {
137: pid_t waited_pid;
1.1.1.2 misho 138:
1.1 misho 139: do {
140: waited_pid = waitpid(pid, status_ptr, flags);
141: } while (waited_pid == -1 && errno == EINTR);
142:
143: if (waited_pid == -1 && errno == ECHILD) {
144: /* Status of requested child no longer available: check to
145: * see if it was processed by remember_children(). */
146: int cnt;
147: for (cnt = 0; cnt < MAXCHILDPROCS; cnt++) {
148: if (pid == pid_stat_table[cnt].pid) {
149: *status_ptr = pid_stat_table[cnt].status;
150: pid_stat_table[cnt].pid = 0;
151: return pid;
152: }
153: }
154: }
155:
156: return waited_pid;
157: }
158:
159: /* Wait for a process to exit, calling io_flush while waiting. */
160: static void wait_process_with_flush(pid_t pid, int *exit_code_ptr)
161: {
162: pid_t waited_pid;
163: int status;
164:
165: while ((waited_pid = wait_process(pid, &status, WNOHANG)) == 0) {
166: msleep(20);
167: io_flush(FULL_FLUSH);
168: }
169:
170: /* TODO: If the child exited on a signal, then log an
171: * appropriate error message. Perhaps we should also accept a
172: * message describing the purpose of the child. Also indicate
173: * this to the caller so that they know something went wrong. */
174: if (waited_pid < 0) {
175: rsyserr(FERROR, errno, "waitpid");
176: *exit_code_ptr = RERR_WAITCHILD;
177: } else if (!WIFEXITED(status)) {
178: #ifdef WCOREDUMP
179: if (WCOREDUMP(status))
180: *exit_code_ptr = RERR_CRASHED;
181: else
182: #endif
183: if (WIFSIGNALED(status))
184: *exit_code_ptr = RERR_TERMINATED;
185: else
186: *exit_code_ptr = RERR_WAITCHILD;
187: } else
188: *exit_code_ptr = WEXITSTATUS(status);
189: }
190:
1.1.1.2 misho 191: void write_del_stats(int f)
192: {
193: if (read_batch)
194: write_int(f, NDX_DEL_STATS);
195: else
196: write_ndx(f, NDX_DEL_STATS);
197: write_varint(f, stats.deleted_files - stats.deleted_dirs
198: - stats.deleted_symlinks - stats.deleted_devices
199: - stats.deleted_specials);
200: write_varint(f, stats.deleted_dirs);
201: write_varint(f, stats.deleted_symlinks);
202: write_varint(f, stats.deleted_devices);
203: write_varint(f, stats.deleted_specials);
204: }
205:
206: void read_del_stats(int f)
207: {
208: stats.deleted_files = read_varint(f);
209: stats.deleted_files += stats.deleted_dirs = read_varint(f);
210: stats.deleted_files += stats.deleted_symlinks = read_varint(f);
211: stats.deleted_files += stats.deleted_devices = read_varint(f);
212: stats.deleted_files += stats.deleted_specials = read_varint(f);
213: }
214:
1.1 misho 215: /* This function gets called from all 3 processes. We want the client side
216: * to actually output the text, but the sender is the only process that has
217: * all the stats we need. So, if we're a client sender, we do the report.
218: * If we're a server sender, we write the stats on the supplied fd. If
219: * we're the client receiver we read the stats from the supplied fd and do
220: * the report. All processes might also generate a set of debug stats, if
221: * the verbose level is high enough (this is the only thing that the
222: * generator process and the server receiver ever do here). */
223: static void handle_stats(int f)
224: {
225: endtime = time(NULL);
226:
227: /* Cache two stats because the read/write code can change it. */
228: total_read = stats.total_read;
229: total_written = stats.total_written;
230:
1.1.1.2 misho 231: if (INFO_GTE(STATS, 3)) {
1.1 misho 232: /* These come out from every process */
233: show_malloc_stats();
234: show_flist_stats();
235: }
236:
237: if (am_generator)
238: return;
239:
240: if (am_daemon) {
241: if (f == -1 || !am_sender)
242: return;
243: }
244:
245: if (am_server) {
246: if (am_sender) {
247: write_varlong30(f, total_read, 3);
248: write_varlong30(f, total_written, 3);
249: write_varlong30(f, stats.total_size, 3);
250: if (protocol_version >= 29) {
251: write_varlong30(f, stats.flist_buildtime, 3);
252: write_varlong30(f, stats.flist_xfertime, 3);
253: }
254: }
255: return;
256: }
257:
258: /* this is the client */
259:
260: if (f < 0 && !am_sender) /* e.g. when we got an empty file list. */
261: ;
262: else if (!am_sender) {
263: /* Read the first two in opposite order because the meaning of
264: * read/write swaps when switching from sender to receiver. */
265: total_written = read_varlong30(f, 3);
266: total_read = read_varlong30(f, 3);
267: stats.total_size = read_varlong30(f, 3);
268: if (protocol_version >= 29) {
269: stats.flist_buildtime = read_varlong30(f, 3);
270: stats.flist_xfertime = read_varlong30(f, 3);
271: }
272: } else if (write_batch) {
273: /* The --read-batch process is going to be a client
274: * receiver, so we need to give it the stats. */
275: write_varlong30(batch_fd, total_read, 3);
276: write_varlong30(batch_fd, total_written, 3);
277: write_varlong30(batch_fd, stats.total_size, 3);
278: if (protocol_version >= 29) {
279: write_varlong30(batch_fd, stats.flist_buildtime, 3);
280: write_varlong30(batch_fd, stats.flist_xfertime, 3);
281: }
282: }
283: }
284:
1.1.1.2 misho 285: static void output_itemized_counts(const char *prefix, int *counts)
286: {
287: static char *labels[] = { "reg", "dir", "link", "dev", "special" };
288: char buf[1024], *pre = " (";
289: int j, len = 0;
290: int total = counts[0];
291: if (total) {
292: counts[0] -= counts[1] + counts[2] + counts[3] + counts[4];
293: for (j = 0; j < 5; j++) {
294: if (counts[j]) {
295: len += snprintf(buf+len, sizeof buf - len - 2,
296: "%s%s: %s",
297: pre, labels[j], comma_num(counts[j]));
298: pre = ", ";
299: }
300: }
301: buf[len++] = ')';
302: }
303: buf[len] = '\0';
304: rprintf(FINFO, "%s: %s%s\n", prefix, comma_num(total), buf);
305: }
306:
1.1 misho 307: static void output_summary(void)
308: {
1.1.1.2 misho 309: if (INFO_GTE(STATS, 2)) {
1.1 misho 310: rprintf(FCLIENT, "\n");
1.1.1.2 misho 311: output_itemized_counts("Number of files", &stats.num_files);
312: if (protocol_version >= 29)
313: output_itemized_counts("Number of created files", &stats.created_files);
314: if (protocol_version >= 31)
315: output_itemized_counts("Number of deleted files", &stats.deleted_files);
316: rprintf(FINFO,"Number of regular files transferred: %s\n",
317: comma_num(stats.xferred_files));
1.1 misho 318: rprintf(FINFO,"Total file size: %s bytes\n",
319: human_num(stats.total_size));
320: rprintf(FINFO,"Total transferred file size: %s bytes\n",
321: human_num(stats.total_transferred_size));
322: rprintf(FINFO,"Literal data: %s bytes\n",
323: human_num(stats.literal_data));
324: rprintf(FINFO,"Matched data: %s bytes\n",
325: human_num(stats.matched_data));
326: rprintf(FINFO,"File list size: %s\n",
327: human_num(stats.flist_size));
328: if (stats.flist_buildtime) {
329: rprintf(FINFO,
1.1.1.2 misho 330: "File list generation time: %s seconds\n",
331: comma_dnum((double)stats.flist_buildtime / 1000, 3));
1.1 misho 332: rprintf(FINFO,
1.1.1.2 misho 333: "File list transfer time: %s seconds\n",
334: comma_dnum((double)stats.flist_xfertime / 1000, 3));
1.1 misho 335: }
336: rprintf(FINFO,"Total bytes sent: %s\n",
337: human_num(total_written));
338: rprintf(FINFO,"Total bytes received: %s\n",
339: human_num(total_read));
340: }
341:
1.1.1.2 misho 342: if (INFO_GTE(STATS, 1)) {
1.1 misho 343: rprintf(FCLIENT, "\n");
344: rprintf(FINFO,
345: "sent %s bytes received %s bytes %s bytes/sec\n",
346: human_num(total_written), human_num(total_read),
347: human_dnum((total_written + total_read)/(0.5 + (endtime - starttime)), 2));
1.1.1.2 misho 348: rprintf(FINFO, "total size is %s speedup is %s%s\n",
1.1 misho 349: human_num(stats.total_size),
1.1.1.2 misho 350: comma_dnum((double)stats.total_size / (total_written+total_read), 2),
1.1 misho 351: write_batch < 0 ? " (BATCH ONLY)" : dry_run ? " (DRY RUN)" : "");
352: }
353:
354: fflush(stdout);
355: fflush(stderr);
356: }
357:
358:
359: /**
360: * If our C library can get malloc statistics, then show them to FINFO
361: **/
362: static void show_malloc_stats(void)
363: {
364: #ifdef HAVE_MALLINFO
365: struct mallinfo mi;
366:
367: mi = mallinfo();
368:
369: rprintf(FCLIENT, "\n");
370: rprintf(FINFO, RSYNC_NAME "[%d] (%s%s%s) heap statistics:\n",
1.1.1.2 misho 371: (int)getpid(), am_server ? "server " : "",
1.1 misho 372: am_daemon ? "daemon " : "", who_am_i());
373: rprintf(FINFO, " arena: %10ld (bytes from sbrk)\n",
374: (long)mi.arena);
375: rprintf(FINFO, " ordblks: %10ld (chunks not in use)\n",
376: (long)mi.ordblks);
377: rprintf(FINFO, " smblks: %10ld\n",
378: (long)mi.smblks);
379: rprintf(FINFO, " hblks: %10ld (chunks from mmap)\n",
380: (long)mi.hblks);
381: rprintf(FINFO, " hblkhd: %10ld (bytes from mmap)\n",
382: (long)mi.hblkhd);
383: rprintf(FINFO, " allmem: %10ld (bytes from sbrk + mmap)\n",
384: (long)mi.arena + mi.hblkhd);
385: rprintf(FINFO, " usmblks: %10ld\n",
386: (long)mi.usmblks);
387: rprintf(FINFO, " fsmblks: %10ld\n",
388: (long)mi.fsmblks);
389: rprintf(FINFO, " uordblks: %10ld (bytes used)\n",
390: (long)mi.uordblks);
391: rprintf(FINFO, " fordblks: %10ld (bytes free)\n",
392: (long)mi.fordblks);
393: rprintf(FINFO, " keepcost: %10ld (bytes in releasable chunk)\n",
394: (long)mi.keepcost);
395: #endif /* HAVE_MALLINFO */
396: }
397:
398:
399: /* Start the remote shell. cmd may be NULL to use the default. */
400: static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, int remote_argc,
401: int *f_in_p, int *f_out_p)
402: {
403: int i, argc = 0;
1.1.1.2 misho 404: char *args[MAX_ARGS], *need_to_free = NULL;
1.1 misho 405: pid_t pid;
406: int dash_l_set = 0;
407:
408: if (!read_batch && !local_server) {
409: char *t, *f, in_quote = '\0';
410: char *rsh_env = getenv(RSYNC_RSH_ENV);
411: if (!cmd)
412: cmd = rsh_env;
413: if (!cmd)
414: cmd = RSYNC_RSH;
1.1.1.2 misho 415: cmd = need_to_free = strdup(cmd);
1.1 misho 416: if (!cmd)
417: goto oom;
418:
419: for (t = f = cmd; *f; f++) {
420: if (*f == ' ')
421: continue;
422: /* Comparison leaves rooms for server_options(). */
423: if (argc >= MAX_ARGS - MAX_SERVER_ARGS)
424: goto arg_overflow;
425: args[argc++] = t;
426: while (*f != ' ' || in_quote) {
427: if (!*f) {
428: if (in_quote) {
429: rprintf(FERROR,
430: "Missing trailing-%c in remote-shell command.\n",
431: in_quote);
432: exit_cleanup(RERR_SYNTAX);
433: }
434: f--;
435: break;
436: }
437: if (*f == '\'' || *f == '"') {
438: if (!in_quote) {
439: in_quote = *f++;
440: continue;
441: }
442: if (*f == in_quote && *++f != in_quote) {
443: in_quote = '\0';
444: continue;
445: }
446: }
447: *t++ = *f++;
448: }
449: *t++ = '\0';
450: }
451:
452: /* check to see if we've already been given '-l user' in
453: * the remote-shell command */
454: for (i = 0; i < argc-1; i++) {
455: if (!strcmp(args[i], "-l") && args[i+1][0] != '-')
456: dash_l_set = 1;
457: }
458:
459: #ifdef HAVE_REMSH
460: /* remsh (on HPUX) takes the arguments the other way around */
461: args[argc++] = machine;
462: if (user && !(daemon_over_rsh && dash_l_set)) {
463: args[argc++] = "-l";
464: args[argc++] = user;
465: }
466: #else
467: if (user && !(daemon_over_rsh && dash_l_set)) {
468: args[argc++] = "-l";
469: args[argc++] = user;
470: }
471: args[argc++] = machine;
472: #endif
473:
474: args[argc++] = rsync_path;
475:
476: if (blocking_io < 0) {
477: char *cp;
478: if ((cp = strrchr(cmd, '/')) != NULL)
479: cp++;
480: else
481: cp = cmd;
482: if (strcmp(cp, "rsh") == 0 || strcmp(cp, "remsh") == 0)
483: blocking_io = 1;
484: }
485:
486: server_options(args,&argc);
487:
488: if (argc >= MAX_ARGS - 2)
489: goto arg_overflow;
490: }
491:
492: args[argc++] = ".";
493:
494: if (!daemon_over_rsh) {
495: while (remote_argc > 0) {
496: if (argc >= MAX_ARGS - 1) {
497: arg_overflow:
498: rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
499: exit_cleanup(RERR_SYNTAX);
500: }
501: if (**remote_argv == '-') {
502: if (asprintf(args + argc++, "./%s", *remote_argv++) < 0)
503: out_of_memory("do_cmd");
504: } else
505: args[argc++] = *remote_argv++;
506: remote_argc--;
507: }
508: }
509:
510: args[argc] = NULL;
511:
1.1.1.2 misho 512: if (DEBUG_GTE(CMD, 2)) {
1.1 misho 513: for (i = 0; i < argc; i++)
514: rprintf(FCLIENT, "cmd[%d]=%s ", i, args[i]);
515: rprintf(FCLIENT, "\n");
516: }
517:
518: if (read_batch) {
519: int from_gen_pipe[2];
520: set_allow_inc_recurse();
521: if (fd_pair(from_gen_pipe) < 0) {
522: rsyserr(FERROR, errno, "pipe");
523: exit_cleanup(RERR_IPC);
524: }
525: batch_gen_fd = from_gen_pipe[0];
526: *f_out_p = from_gen_pipe[1];
527: *f_in_p = batch_fd;
528: pid = (pid_t)-1; /* no child pid */
529: #ifdef ICONV_CONST
530: setup_iconv();
531: #endif
532: } else if (local_server) {
533: /* If the user didn't request --[no-]whole-file, force
534: * it on, but only if we're not batch processing. */
535: if (whole_file < 0 && !write_batch)
536: whole_file = 1;
537: set_allow_inc_recurse();
538: pid = local_child(argc, args, f_in_p, f_out_p, child_main);
539: #ifdef ICONV_CONST
540: setup_iconv();
541: #endif
542: } else {
543: pid = piped_child(args, f_in_p, f_out_p);
544: #ifdef ICONV_CONST
545: setup_iconv();
546: #endif
547: if (protect_args && !daemon_over_rsh)
548: send_protected_args(*f_out_p, args);
549: }
550:
1.1.1.2 misho 551: if (need_to_free)
552: free(need_to_free);
553:
1.1 misho 554: return pid;
555:
556: oom:
557: out_of_memory("do_cmd");
558: return 0; /* not reached */
559: }
560:
561: /* The receiving side operates in one of two modes:
562: *
563: * 1. it receives any number of files into a destination directory,
564: * placing them according to their names in the file-list.
565: *
566: * 2. it receives a single file and saves it using the name in the
567: * destination path instead of its file-list name. This requires a
568: * "local name" for writing out the destination file.
569: *
570: * So, our task is to figure out what mode/local-name we need.
571: * For mode 1, we change into the destination directory and return NULL.
572: * For mode 2, we change into the directory containing the destination
573: * file (if we aren't already there) and return the local-name. */
574: static char *get_local_name(struct file_list *flist, char *dest_path)
575: {
576: STRUCT_STAT st;
577: int statret;
578: char *cp;
579:
1.1.1.2 misho 580: if (DEBUG_GTE(RECV, 1)) {
1.1 misho 581: rprintf(FINFO, "get_local_name count=%d %s\n",
582: file_total, NS(dest_path));
583: }
584:
585: if (!dest_path || list_only)
586: return NULL;
587:
588: /* Treat an empty string as a copy into the current directory. */
589: if (!*dest_path)
590: dest_path = ".";
591:
592: if (daemon_filter_list.head) {
593: char *slash = strrchr(dest_path, '/');
594: if (slash && (slash[1] == '\0' || (slash[1] == '.' && slash[2] == '\0')))
595: *slash = '\0';
596: else
597: slash = NULL;
598: if ((*dest_path != '.' || dest_path[1] != '\0')
599: && (check_filter(&daemon_filter_list, FLOG, dest_path, 0) < 0
600: || check_filter(&daemon_filter_list, FLOG, dest_path, 1) < 0)) {
601: rprintf(FERROR, "ERROR: daemon has excluded destination \"%s\"\n",
602: dest_path);
603: exit_cleanup(RERR_FILESELECT);
604: }
605: if (slash)
606: *slash = '/';
607: }
608:
609: /* See what currently exists at the destination. */
610: if ((statret = do_stat(dest_path, &st)) == 0) {
611: /* If the destination is a dir, enter it and use mode 1. */
612: if (S_ISDIR(st.st_mode)) {
613: if (!change_dir(dest_path, CD_NORMAL)) {
614: rsyserr(FERROR, errno, "change_dir#1 %s failed",
615: full_fname(dest_path));
616: exit_cleanup(RERR_FILESELECT);
617: }
618: filesystem_dev = st.st_dev; /* ensures --force works right w/-x */
619: return NULL;
620: }
621: if (file_total > 1) {
622: rprintf(FERROR,
623: "ERROR: destination must be a directory when"
624: " copying more than 1 file\n");
625: exit_cleanup(RERR_FILESELECT);
626: }
627: if (file_total == 1 && S_ISDIR(flist->files[0]->mode)) {
628: rprintf(FERROR,
629: "ERROR: cannot overwrite non-directory"
630: " with a directory\n");
631: exit_cleanup(RERR_FILESELECT);
632: }
633: } else if (errno != ENOENT) {
634: /* If we don't know what's at the destination, fail. */
635: rsyserr(FERROR, errno, "ERROR: cannot stat destination %s",
636: full_fname(dest_path));
637: exit_cleanup(RERR_FILESELECT);
638: }
639:
640: cp = strrchr(dest_path, '/');
641:
642: /* If we need a destination directory because the transfer is not
643: * of a single non-directory or the user has requested one via a
644: * destination path ending in a slash, create one and use mode 1. */
645: if (file_total > 1 || (cp && !cp[1])) {
646: /* Lop off the final slash (if any). */
647: if (cp && !cp[1])
648: *cp = '\0';
649:
650: if (statret == 0) {
651: rprintf(FERROR,
652: "ERROR: destination path is not a directory\n");
653: exit_cleanup(RERR_SYNTAX);
654: }
655:
1.1.1.2 misho 656: if (do_mkdir(dest_path, ACCESSPERMS) != 0) {
1.1 misho 657: rsyserr(FERROR, errno, "mkdir %s failed",
658: full_fname(dest_path));
659: exit_cleanup(RERR_FILEIO);
660: }
661:
662: if (flist->high >= flist->low
663: && strcmp(flist->files[flist->low]->basename, ".") == 0)
664: flist->files[0]->flags |= FLAG_DIR_CREATED;
665:
1.1.1.2 misho 666: if (INFO_GTE(NAME, 1))
1.1 misho 667: rprintf(FINFO, "created directory %s\n", dest_path);
668:
669: if (dry_run) {
670: /* Indicate that dest dir doesn't really exist. */
671: dry_run++;
672: }
673:
674: if (!change_dir(dest_path, dry_run > 1 ? CD_SKIP_CHDIR : CD_NORMAL)) {
675: rsyserr(FERROR, errno, "change_dir#2 %s failed",
676: full_fname(dest_path));
677: exit_cleanup(RERR_FILESELECT);
678: }
679:
680: return NULL;
681: }
682:
683: /* Otherwise, we are writing a single file, possibly on top of an
684: * existing non-directory. Change to the item's parent directory
685: * (if it has a path component), return the basename of the
686: * destination file as the local name, and use mode 2. */
687: if (!cp)
688: return dest_path;
689:
690: if (cp == dest_path)
691: dest_path = "/";
692:
693: *cp = '\0';
694: if (!change_dir(dest_path, CD_NORMAL)) {
695: rsyserr(FERROR, errno, "change_dir#3 %s failed",
696: full_fname(dest_path));
697: exit_cleanup(RERR_FILESELECT);
698: }
699: *cp = '/';
700:
701: return cp + 1;
702: }
703:
704: /* This function checks on our alternate-basis directories. If we're in
705: * dry-run mode and the destination dir does not yet exist, we'll try to
706: * tweak any dest-relative paths to make them work for a dry-run (the
707: * destination dir must be in curr_dir[] when this function is called).
708: * We also warn about any arg that is non-existent or not a directory. */
709: static void check_alt_basis_dirs(void)
710: {
711: STRUCT_STAT st;
1.1.1.2 misho 712: char *slash = strrchr(curr_dir, '/');
713: int j;
1.1 misho 714:
1.1.1.2 misho 715: for (j = 0; j < basis_dir_cnt; j++) {
716: char *bdir = basis_dir[j];
717: int bd_len = strlen(bdir);
718: if (bd_len > 1 && bdir[bd_len-1] == '/')
719: bdir[--bd_len] = '\0';
720: if (dry_run > 1 && *bdir != '/') {
721: int len = curr_dir_len + 1 + bd_len + 1;
1.1 misho 722: char *new = new_array(char, len);
723: if (!new)
724: out_of_memory("check_alt_basis_dirs");
1.1.1.2 misho 725: if (slash && strncmp(bdir, "../", 3) == 0) {
1.1 misho 726: /* We want to remove only one leading "../" prefix for
727: * the directory we couldn't create in dry-run mode:
728: * this ensures that any other ".." references get
729: * evaluated the same as they would for a live copy. */
730: *slash = '\0';
1.1.1.2 misho 731: pathjoin(new, len, curr_dir, bdir + 3);
1.1 misho 732: *slash = '/';
733: } else
1.1.1.2 misho 734: pathjoin(new, len, curr_dir, bdir);
735: basis_dir[j] = bdir = new;
1.1 misho 736: }
1.1.1.2 misho 737: if (do_stat(bdir, &st) < 0)
738: rprintf(FWARNING, "%s arg does not exist: %s\n", dest_option, bdir);
739: else if (!S_ISDIR(st.st_mode))
740: rprintf(FWARNING, "%s arg is not a dir: %s\n", dest_option, bdir);
1.1 misho 741: }
742: }
743:
744: /* This is only called by the sender. */
1.1.1.2 misho 745: static void read_final_goodbye(int f_in, int f_out)
1.1 misho 746: {
747: int i, iflags, xlen;
748: uchar fnamecmp_type;
749: char xname[MAXPATHLEN];
750:
1.1.1.2 misho 751: shutting_down = True;
752:
1.1 misho 753: if (protocol_version < 29)
754: i = read_int(f_in);
755: else {
1.1.1.2 misho 756: i = read_ndx_and_attrs(f_in, f_out, &iflags, &fnamecmp_type, xname, &xlen);
757: if (protocol_version >= 31 && i == NDX_DONE) {
758: if (am_sender)
759: write_ndx(f_out, NDX_DONE);
760: else {
761: if (batch_gen_fd >= 0) {
762: while (read_int(batch_gen_fd) != NDX_DEL_STATS) {}
763: read_del_stats(batch_gen_fd);
764: }
765: write_int(f_out, NDX_DONE);
766: }
767: i = read_ndx_and_attrs(f_in, f_out, &iflags, &fnamecmp_type, xname, &xlen);
768: }
1.1 misho 769: }
770:
771: if (i != NDX_DONE) {
772: rprintf(FERROR, "Invalid packet at end of run (%d) [%s]\n",
773: i, who_am_i());
774: exit_cleanup(RERR_PROTOCOL);
775: }
776: }
777:
778: static void do_server_sender(int f_in, int f_out, int argc, char *argv[])
779: {
780: struct file_list *flist;
781: char *dir = argv[0];
782:
1.1.1.2 misho 783: if (DEBUG_GTE(SEND, 1))
784: rprintf(FINFO, "server_sender starting pid=%d\n", (int)getpid());
1.1 misho 785:
786: if (am_daemon && lp_write_only(module_id)) {
787: rprintf(FERROR, "ERROR: module is write only\n");
788: exit_cleanup(RERR_SYNTAX);
789: return;
790: }
1.1.1.2 misho 791: if (am_daemon && read_only && remove_source_files) {
1.1 misho 792: rprintf(FERROR,
793: "ERROR: --remove-%s-files cannot be used with a read-only module\n",
794: remove_source_files == 1 ? "source" : "sent");
795: exit_cleanup(RERR_SYNTAX);
796: return;
797: }
798:
799: if (!relative_paths) {
800: if (!change_dir(dir, CD_NORMAL)) {
801: rsyserr(FERROR, errno, "change_dir#3 %s failed",
802: full_fname(dir));
803: exit_cleanup(RERR_FILESELECT);
804: }
805: }
806: argc--;
807: argv++;
808:
809: if (argc == 0 && (recurse || xfer_dirs || list_only)) {
810: argc = 1;
811: argv--;
812: argv[0] = ".";
813: }
814:
815: flist = send_file_list(f_out,argc,argv);
1.1.1.2 misho 816: if (!flist || flist->used == 0) {
817: /* Make sure input buffering is off so we can't hang in noop_io_until_death(). */
818: io_end_buffering_in(0);
819: /* TODO: we should really exit in a more controlled manner. */
1.1 misho 820: exit_cleanup(0);
1.1.1.2 misho 821: }
1.1 misho 822:
823: io_start_buffering_in(f_in);
824:
825: send_files(f_in, f_out);
826: io_flush(FULL_FLUSH);
827: handle_stats(f_out);
828: if (protocol_version >= 24)
1.1.1.2 misho 829: read_final_goodbye(f_in, f_out);
1.1 misho 830: io_flush(FULL_FLUSH);
831: exit_cleanup(0);
832: }
833:
834:
835: static int do_recv(int f_in, int f_out, char *local_name)
836: {
837: int pid;
838: int exit_code = 0;
839: int error_pipe[2];
840:
841: /* The receiving side mustn't obey this, or an existing symlink that
842: * points to an identical file won't be replaced by the referent. */
843: copy_links = copy_dirlinks = copy_unsafe_links = 0;
844:
845: #ifdef SUPPORT_HARD_LINKS
846: if (preserve_hard_links && !inc_recurse)
847: match_hard_links(first_flist);
848: #endif
849:
850: if (fd_pair(error_pipe) < 0) {
851: rsyserr(FERROR, errno, "pipe failed in do_recv");
852: exit_cleanup(RERR_IPC);
853: }
854:
1.1.1.2 misho 855: if (backup_dir) {
1.1.1.3 ! misho 856: STRUCT_STAT st;
! 857: int ret;
! 858: if (backup_dir_len > 1)
! 859: backup_dir_buf[backup_dir_len-1] = '\0';
! 860: ret = do_stat(backup_dir_buf, &st);
! 861: if (ret != 0 || !S_ISDIR(st.st_mode)) {
! 862: if (ret == 0) {
! 863: rprintf(FERROR, "The backup-dir is not a directory: %s\n", backup_dir_buf);
! 864: exit_cleanup(RERR_SYNTAX);
! 865: }
! 866: if (errno != ENOENT) {
! 867: rprintf(FERROR, "Failed to stat %s: %s\n", backup_dir_buf, strerror(errno));
! 868: exit_cleanup(RERR_FILEIO);
! 869: }
! 870: rprintf(FINFO, "(new) backup_dir is %s\n", backup_dir_buf);
! 871: } else if (INFO_GTE(BACKUP, 1))
1.1.1.2 misho 872: rprintf(FINFO, "backup_dir is %s\n", backup_dir_buf);
1.1.1.3 ! misho 873: if (backup_dir_len > 1)
! 874: backup_dir_buf[backup_dir_len-1] = '/';
1.1.1.2 misho 875: }
876:
877: io_flush(FULL_FLUSH);
1.1 misho 878:
879: if ((pid = do_fork()) == -1) {
880: rsyserr(FERROR, errno, "fork failed in do_recv");
881: exit_cleanup(RERR_IPC);
882: }
883:
884: if (pid == 0) {
885: am_receiver = 1;
1.1.1.2 misho 886: send_msgs_to_gen = am_server;
1.1 misho 887:
888: close(error_pipe[0]);
1.1.1.2 misho 889:
890: /* We can't let two processes write to the socket at one time. */
891: io_end_multiplex_out(MPLX_SWITCHING);
1.1 misho 892: if (f_in != f_out)
893: close(f_out);
1.1.1.2 misho 894: sock_f_out = -1;
895: f_out = error_pipe[1];
1.1 misho 896:
1.1.1.2 misho 897: bwlimit_writemax = 0; /* receiver doesn't need to do this */
1.1 misho 898:
1.1.1.2 misho 899: if (read_batch)
900: io_start_buffering_in(f_in);
901: io_start_multiplex_out(f_out);
1.1 misho 902:
1.1.1.2 misho 903: recv_files(f_in, f_out, local_name);
1.1 misho 904: io_flush(FULL_FLUSH);
905: handle_stats(f_in);
906:
1.1.1.2 misho 907: if (output_needs_newline) {
908: fputc('\n', stdout);
909: output_needs_newline = 0;
910: }
911:
912: write_int(f_out, NDX_DONE);
913: send_msg(MSG_STATS, (char*)&stats.total_read, sizeof stats.total_read, 0);
1.1 misho 914: io_flush(FULL_FLUSH);
915:
916: /* Handle any keep-alive packets from the post-processing work
917: * that the generator does. */
918: if (protocol_version >= 29) {
919: kluge_around_eof = -1;
920:
921: /* This should only get stopped via a USR2 signal. */
1.1.1.2 misho 922: read_final_goodbye(f_in, f_out);
1.1 misho 923:
924: rprintf(FERROR, "Invalid packet at end of run [%s]\n",
925: who_am_i());
926: exit_cleanup(RERR_PROTOCOL);
927: }
928:
929: /* Finally, we go to sleep until our parent kills us with a
930: * USR2 signal. We sleep for a short time, as on some OSes
931: * a signal won't interrupt a sleep! */
932: while (1)
933: msleep(20);
934: }
935:
936: am_generator = 1;
1.1.1.2 misho 937: flist_receiving_enabled = True;
1.1 misho 938:
1.1.1.2 misho 939: io_end_multiplex_in(MPLX_SWITCHING);
1.1 misho 940: if (write_batch && !am_server)
941: stop_write_batch();
942:
943: close(error_pipe[1]);
944: if (f_in != f_out)
945: close(f_in);
1.1.1.2 misho 946: sock_f_in = -1;
947: f_in = error_pipe[0];
1.1 misho 948:
949: io_start_buffering_out(f_out);
1.1.1.2 misho 950: io_start_multiplex_in(f_in);
1.1 misho 951:
952: #ifdef SUPPORT_HARD_LINKS
953: if (preserve_hard_links && inc_recurse) {
954: struct file_list *flist;
955: for (flist = first_flist; flist; flist = flist->next)
956: match_hard_links(flist);
957: }
958: #endif
959:
960: generate_files(f_out, local_name);
961:
962: handle_stats(-1);
963: io_flush(FULL_FLUSH);
1.1.1.2 misho 964: shutting_down = True;
1.1 misho 965: if (protocol_version >= 24) {
966: /* send a final goodbye message */
967: write_ndx(f_out, NDX_DONE);
968: }
969: io_flush(FULL_FLUSH);
970:
971: kill(pid, SIGUSR2);
972: wait_process_with_flush(pid, &exit_code);
973: return exit_code;
974: }
975:
976: static void do_server_recv(int f_in, int f_out, int argc, char *argv[])
977: {
978: int exit_code;
979: struct file_list *flist;
980: char *local_name = NULL;
1.1.1.2 misho 981: int negated_levels;
1.1 misho 982:
1.1.1.2 misho 983: if (filesfrom_fd >= 0 && !msgs2stderr && protocol_version < 31) {
1.1 misho 984: /* We can't mix messages with files-from data on the socket,
1.1.1.2 misho 985: * so temporarily turn off info/debug messages. */
986: negate_output_levels();
987: negated_levels = 1;
988: } else
989: negated_levels = 0;
1.1 misho 990:
1.1.1.2 misho 991: if (DEBUG_GTE(RECV, 1))
992: rprintf(FINFO, "server_recv(%d) starting pid=%d\n", argc, (int)getpid());
1.1 misho 993:
1.1.1.2 misho 994: if (am_daemon && read_only) {
1.1 misho 995: rprintf(FERROR,"ERROR: module is read only\n");
996: exit_cleanup(RERR_SYNTAX);
997: return;
998: }
999:
1000: if (argc > 0) {
1001: char *dir = argv[0];
1002: argc--;
1003: argv++;
1004: if (!am_daemon && !change_dir(dir, CD_NORMAL)) {
1005: rsyserr(FERROR, errno, "change_dir#4 %s failed",
1006: full_fname(dir));
1007: exit_cleanup(RERR_FILESELECT);
1008: }
1009: }
1010:
1011: if (protocol_version >= 30)
1.1.1.2 misho 1012: io_start_multiplex_in(f_in);
1.1 misho 1013: else
1014: io_start_buffering_in(f_in);
1015: recv_filter_list(f_in);
1016:
1017: if (filesfrom_fd >= 0) {
1018: /* We need to send the files-from names to the sender at the
1019: * same time that we receive the file-list from them, so we
1020: * need the IO routines to automatically write out the names
1021: * onto our f_out socket as we read the file-list. This
1022: * avoids both deadlock and extra delays/buffers. */
1.1.1.2 misho 1023: start_filesfrom_forwarding(filesfrom_fd);
1.1 misho 1024: filesfrom_fd = -1;
1025: }
1026:
1.1.1.3 ! misho 1027: flist = recv_file_list(f_in, -1);
1.1 misho 1028: if (!flist) {
1029: rprintf(FERROR,"server_recv: recv_file_list error\n");
1030: exit_cleanup(RERR_FILESELECT);
1031: }
1.1.1.3 ! misho 1032:
1.1 misho 1033: if (inc_recurse && file_total == 1)
1034: recv_additional_file_list(f_in);
1.1.1.2 misho 1035:
1036: if (negated_levels)
1037: negate_output_levels();
1.1 misho 1038:
1039: if (argc > 0)
1040: local_name = get_local_name(flist,argv[0]);
1041:
1042: /* Now that we know what our destination directory turned out to be,
1043: * we can sanitize the --link-/copy-/compare-dest args correctly. */
1044: if (sanitize_paths) {
1045: char **dir_p;
1046: for (dir_p = basis_dir; *dir_p; dir_p++)
1047: *dir_p = sanitize_path(NULL, *dir_p, NULL, curr_dir_depth, SP_DEFAULT);
1048: if (partial_dir)
1049: partial_dir = sanitize_path(NULL, partial_dir, NULL, curr_dir_depth, SP_DEFAULT);
1050: }
1051: check_alt_basis_dirs();
1052:
1053: if (daemon_filter_list.head) {
1054: char **dir_p;
1.1.1.2 misho 1055: filter_rule_list *elp = &daemon_filter_list;
1.1 misho 1056:
1057: for (dir_p = basis_dir; *dir_p; dir_p++) {
1058: char *dir = *dir_p;
1059: if (*dir == '/')
1060: dir += module_dirlen;
1061: if (check_filter(elp, FLOG, dir, 1) < 0)
1062: goto options_rejected;
1063: }
1064: if (partial_dir && *partial_dir == '/'
1065: && check_filter(elp, FLOG, partial_dir + module_dirlen, 1) < 0) {
1066: options_rejected:
1067: rprintf(FERROR,
1068: "Your options have been rejected by the server.\n");
1069: exit_cleanup(RERR_SYNTAX);
1070: }
1071: }
1072:
1073: exit_code = do_recv(f_in, f_out, local_name);
1074: exit_cleanup(exit_code);
1075: }
1076:
1077:
1078: int child_main(int argc, char *argv[])
1079: {
1080: start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
1081: return 0;
1082: }
1083:
1084:
1085: void start_server(int f_in, int f_out, int argc, char *argv[])
1086: {
1087: set_nonblocking(f_in);
1088: set_nonblocking(f_out);
1089:
1090: io_set_sock_fds(f_in, f_out);
1091: setup_protocol(f_out, f_in);
1092:
1093: if (protocol_version >= 23)
1.1.1.2 misho 1094: io_start_multiplex_out(f_out);
1095: if (am_daemon && io_timeout && protocol_version >= 31)
1096: send_msg_int(MSG_IO_TIMEOUT, io_timeout);
1.1 misho 1097:
1098: if (am_sender) {
1099: keep_dirlinks = 0; /* Must be disabled on the sender. */
1100: if (need_messages_from_generator)
1.1.1.2 misho 1101: io_start_multiplex_in(f_in);
1102: else
1103: io_start_buffering_in(f_in);
1.1 misho 1104: recv_filter_list(f_in);
1105: do_server_sender(f_in, f_out, argc, argv);
1106: } else
1107: do_server_recv(f_in, f_out, argc, argv);
1108: exit_cleanup(0);
1109: }
1110:
1.1.1.2 misho 1111: /* This is called once the connection has been negotiated. It is used
1112: * for rsyncd, remote-shell, and local connections. */
1.1 misho 1113: int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
1114: {
1115: struct file_list *flist = NULL;
1116: int exit_code = 0, exit_code2 = 0;
1117: char *local_name = NULL;
1118:
1119: cleanup_child_pid = pid;
1120: if (!read_batch) {
1121: set_nonblocking(f_in);
1122: set_nonblocking(f_out);
1123: }
1124:
1125: io_set_sock_fds(f_in, f_out);
1126: setup_protocol(f_out,f_in);
1127:
1128: /* We set our stderr file handle to blocking because ssh might have
1129: * set it to non-blocking. This can be particularly troublesome if
1130: * stderr is a clone of stdout, because ssh would have set our stdout
1131: * to non-blocking at the same time (which can easily cause us to lose
1132: * output from our print statements). This kluge shouldn't cause ssh
1133: * any problems for how we use it. Note also that we delayed setting
1134: * this until after the above protocol setup so that we know for sure
1135: * that ssh is done twiddling its file descriptors. */
1136: set_blocking(STDERR_FILENO);
1137:
1138: if (am_sender) {
1139: keep_dirlinks = 0; /* Must be disabled on the sender. */
1.1.1.2 misho 1140:
1141: if (always_checksum
1142: && (log_format_has(stdout_format, 'C')
1143: || log_format_has(logfile_format, 'C')))
1144: sender_keeps_checksum = 1;
1145:
1.1 misho 1146: if (protocol_version >= 30)
1.1.1.2 misho 1147: io_start_multiplex_out(f_out);
1.1 misho 1148: else
1149: io_start_buffering_out(f_out);
1.1.1.2 misho 1150: if (protocol_version >= 31 || (!filesfrom_host && protocol_version >= 23))
1151: io_start_multiplex_in(f_in);
1152: else
1153: io_start_buffering_in(f_in);
1.1 misho 1154: send_filter_list(f_out);
1155: if (filesfrom_host)
1156: filesfrom_fd = f_in;
1157:
1158: if (write_batch && !am_server)
1159: start_write_batch(f_out);
1160: flist = send_file_list(f_out, argc, argv);
1.1.1.2 misho 1161: if (DEBUG_GTE(FLIST, 3))
1.1 misho 1162: rprintf(FINFO,"file list sent\n");
1163:
1.1.1.2 misho 1164: if (protocol_version < 31 && filesfrom_host && protocol_version >= 23)
1165: io_start_multiplex_in(f_in);
1.1 misho 1166:
1167: io_flush(NORMAL_FLUSH);
1168: send_files(f_in, f_out);
1169: io_flush(FULL_FLUSH);
1170: handle_stats(-1);
1171: if (protocol_version >= 24)
1.1.1.2 misho 1172: read_final_goodbye(f_in, f_out);
1.1 misho 1173: if (pid != -1) {
1.1.1.2 misho 1174: if (DEBUG_GTE(EXIT, 2))
1.1 misho 1175: rprintf(FINFO,"client_run waiting on %d\n", (int) pid);
1176: io_flush(FULL_FLUSH);
1177: wait_process_with_flush(pid, &exit_code);
1178: }
1179: output_summary();
1180: io_flush(FULL_FLUSH);
1181: exit_cleanup(exit_code);
1182: }
1183:
1184: if (!read_batch) {
1185: if (protocol_version >= 23)
1.1.1.2 misho 1186: io_start_multiplex_in(f_in);
1.1 misho 1187: if (need_messages_from_generator)
1.1.1.2 misho 1188: io_start_multiplex_out(f_out);
1189: else
1190: io_start_buffering_out(f_out);
1.1 misho 1191: }
1192:
1193: send_filter_list(read_batch ? -1 : f_out);
1194:
1195: if (filesfrom_fd >= 0) {
1.1.1.2 misho 1196: start_filesfrom_forwarding(filesfrom_fd);
1.1 misho 1197: filesfrom_fd = -1;
1198: }
1199:
1200: if (write_batch && !am_server)
1201: start_write_batch(f_in);
1.1.1.3 ! misho 1202: flist = recv_file_list(f_in, -1);
1.1 misho 1203: if (inc_recurse && file_total == 1)
1204: recv_additional_file_list(f_in);
1205:
1206: if (flist && flist->used > 0) {
1207: local_name = get_local_name(flist, argv[0]);
1208:
1209: check_alt_basis_dirs();
1210:
1211: exit_code2 = do_recv(f_in, f_out, local_name);
1212: } else {
1213: handle_stats(-1);
1214: output_summary();
1215: }
1216:
1217: if (pid != -1) {
1.1.1.2 misho 1218: if (DEBUG_GTE(RECV, 1))
1.1 misho 1219: rprintf(FINFO,"client_run2 waiting on %d\n", (int) pid);
1220: io_flush(FULL_FLUSH);
1221: wait_process_with_flush(pid, &exit_code);
1222: }
1223:
1224: return MAX(exit_code, exit_code2);
1225: }
1226:
1227: static int copy_argv(char *argv[])
1228: {
1229: int i;
1230:
1231: for (i = 0; argv[i]; i++) {
1232: if (!(argv[i] = strdup(argv[i]))) {
1233: rprintf (FERROR, "out of memory at %s(%d)\n",
1234: __FILE__, __LINE__);
1235: return RERR_MALLOC;
1236: }
1237: }
1238:
1239: return 0;
1240: }
1241:
1242:
1.1.1.2 misho 1243: /* Start a client for either type of remote connection. Work out
1.1 misho 1244: * whether the arguments request a remote shell or rsyncd connection,
1245: * and call the appropriate connection function, then run_client.
1246: *
1247: * Calls either start_socket_client (for sockets) or do_cmd and
1.1.1.2 misho 1248: * client_run (for ssh). */
1.1 misho 1249: static int start_client(int argc, char *argv[])
1250: {
1251: char *p, *shell_machine = NULL, *shell_user = NULL;
1252: char **remote_argv;
1253: int remote_argc;
1254: int f_in, f_out;
1255: int ret;
1256: pid_t pid;
1257:
1258: /* Don't clobber argv[] so that ps(1) can still show the right
1259: * command line. */
1260: if ((ret = copy_argv(argv)) != 0)
1261: return ret;
1262:
1263: if (!read_batch) { /* for read_batch, NO source is specified */
1264: char *path = check_for_hostspec(argv[0], &shell_machine, &rsync_port);
1265: if (path) { /* source is remote */
1266: char *dummy_host;
1267: int dummy_port = 0;
1268: *argv = path;
1269: remote_argv = argv;
1270: remote_argc = argc;
1271: argv += argc - 1;
1272: if (argc == 1 || **argv == ':')
1273: argc = 0; /* no dest arg */
1274: else if (check_for_hostspec(*argv, &dummy_host, &dummy_port)) {
1275: rprintf(FERROR,
1276: "The source and destination cannot both be remote.\n");
1277: exit_cleanup(RERR_SYNTAX);
1278: } else {
1279: remote_argc--; /* don't count dest */
1280: argc = 1;
1281: }
1282: if (filesfrom_host && *filesfrom_host
1283: && strcmp(filesfrom_host, shell_machine) != 0) {
1284: rprintf(FERROR,
1285: "--files-from hostname is not the same as the transfer hostname\n");
1286: exit_cleanup(RERR_SYNTAX);
1287: }
1288: am_sender = 0;
1289: if (rsync_port)
1290: daemon_over_rsh = shell_cmd ? 1 : -1;
1291: } else { /* source is local, check dest arg */
1292: am_sender = 1;
1293:
1294: if (argc > 1) {
1295: p = argv[--argc];
1296: remote_argv = argv + argc;
1297: } else {
1298: static char *dotarg[1] = { "." };
1299: p = dotarg[0];
1300: remote_argv = dotarg;
1301: }
1302: remote_argc = 1;
1303:
1304: path = check_for_hostspec(p, &shell_machine, &rsync_port);
1305: if (path && filesfrom_host && *filesfrom_host
1306: && strcmp(filesfrom_host, shell_machine) != 0) {
1307: rprintf(FERROR,
1308: "--files-from hostname is not the same as the transfer hostname\n");
1309: exit_cleanup(RERR_SYNTAX);
1310: }
1311: if (!path) { /* no hostspec found, so src & dest are local */
1312: local_server = 1;
1313: if (filesfrom_host) {
1314: rprintf(FERROR,
1315: "--files-from cannot be remote when the transfer is local\n");
1316: exit_cleanup(RERR_SYNTAX);
1317: }
1318: shell_machine = NULL;
1319: } else { /* hostspec was found, so dest is remote */
1320: argv[argc] = path;
1321: if (rsync_port)
1322: daemon_over_rsh = shell_cmd ? 1 : -1;
1323: }
1324: }
1325: } else { /* read_batch */
1326: local_server = 1;
1327: if (check_for_hostspec(argv[argc-1], &shell_machine, &rsync_port)) {
1328: rprintf(FERROR, "remote destination is not allowed with --read-batch\n");
1329: exit_cleanup(RERR_SYNTAX);
1330: }
1331: remote_argv = argv += argc - 1;
1332: remote_argc = argc = 1;
1333: }
1334:
1.1.1.2 misho 1335: if (!rsync_port && remote_argc && !**remote_argv) /* Turn an empty arg into a dot dir. */
1336: *remote_argv = ".";
1337:
1.1 misho 1338: if (am_sender) {
1339: char *dummy_host;
1340: int dummy_port = rsync_port;
1341: int i;
1342: /* For local source, extra source args must not have hostspec. */
1343: for (i = 1; i < argc; i++) {
1344: if (check_for_hostspec(argv[i], &dummy_host, &dummy_port)) {
1345: rprintf(FERROR, "Unexpected remote arg: %s\n", argv[i]);
1346: exit_cleanup(RERR_SYNTAX);
1347: }
1348: }
1349: } else {
1350: char *dummy_host;
1351: int dummy_port = rsync_port;
1352: int i;
1353: /* For remote source, any extra source args must have either
1354: * the same hostname or an empty hostname. */
1355: for (i = 1; i < remote_argc; i++) {
1356: char *arg = check_for_hostspec(remote_argv[i], &dummy_host, &dummy_port);
1357: if (!arg) {
1358: rprintf(FERROR, "Unexpected local arg: %s\n", remote_argv[i]);
1359: rprintf(FERROR, "If arg is a remote file/dir, prefix it with a colon (:).\n");
1360: exit_cleanup(RERR_SYNTAX);
1361: }
1362: if (*dummy_host && strcmp(dummy_host, shell_machine) != 0) {
1363: rprintf(FERROR, "All source args must come from the same machine.\n");
1364: exit_cleanup(RERR_SYNTAX);
1365: }
1366: if (rsync_port != dummy_port) {
1367: if (!rsync_port || !dummy_port)
1368: rprintf(FERROR, "All source args must use the same hostspec format.\n");
1369: else
1370: rprintf(FERROR, "All source args must use the same port number.\n");
1371: exit_cleanup(RERR_SYNTAX);
1372: }
1.1.1.2 misho 1373: if (!rsync_port && !*arg) /* Turn an empty arg into a dot dir. */
1374: arg = ".";
1.1 misho 1375: remote_argv[i] = arg;
1376: }
1377: }
1378:
1379: if (daemon_over_rsh < 0)
1380: return start_socket_client(shell_machine, remote_argc, remote_argv, argc, argv);
1381:
1382: if (password_file && !daemon_over_rsh) {
1383: rprintf(FERROR, "The --password-file option may only be "
1384: "used when accessing an rsync daemon.\n");
1385: exit_cleanup(RERR_SYNTAX);
1386: }
1387:
1388: if (connect_timeout) {
1389: rprintf(FERROR, "The --contimeout option may only be "
1390: "used when connecting to an rsync daemon.\n");
1391: exit_cleanup(RERR_SYNTAX);
1392: }
1393:
1394: if (shell_machine) {
1395: p = strrchr(shell_machine,'@');
1396: if (p) {
1397: *p = 0;
1398: shell_user = shell_machine;
1399: shell_machine = p+1;
1400: }
1401: }
1402:
1.1.1.2 misho 1403: if (DEBUG_GTE(CMD, 2)) {
1.1 misho 1404: rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
1405: NS(shell_cmd), NS(shell_machine), NS(shell_user),
1.1.1.2 misho 1406: NS(remote_argv[0]));
1.1 misho 1407: }
1408:
1409: pid = do_cmd(shell_cmd, shell_machine, shell_user, remote_argv, remote_argc,
1410: &f_in, &f_out);
1411:
1412: /* if we're running an rsync server on the remote host over a
1413: * remote shell command, we need to do the RSYNCD protocol first */
1414: if (daemon_over_rsh) {
1415: int tmpret;
1416: tmpret = start_inband_exchange(f_in, f_out, shell_user, remote_argc, remote_argv);
1417: if (tmpret < 0)
1418: return tmpret;
1419: }
1420:
1421: ret = client_run(f_in, f_out, pid, argc, argv);
1422:
1423: fflush(stdout);
1424: fflush(stderr);
1425:
1426: return ret;
1427: }
1428:
1429:
1.1.1.3 ! misho 1430: static void sigusr1_handler(UNUSED(int val))
1.1 misho 1431: {
1432: exit_cleanup(RERR_SIGNAL1);
1433: }
1434:
1.1.1.3 ! misho 1435: static void sigusr2_handler(UNUSED(int val))
1.1 misho 1436: {
1437: if (!am_server)
1438: output_summary();
1439: close_all();
1440: if (got_xfer_error)
1441: _exit(RERR_PARTIAL);
1442: _exit(0);
1443: }
1444:
1.1.1.3 ! misho 1445: #ifdef SIGINFO
! 1446: static void siginfo_handler(UNUSED(int val))
! 1447: {
! 1448:
! 1449: if (!am_server)
! 1450: want_progress_now = True;
! 1451: }
! 1452: #endif
! 1453:
! 1454: void remember_children(UNUSED(int val))
1.1 misho 1455: {
1456: #ifdef WNOHANG
1457: int cnt, status;
1458: pid_t pid;
1459: /* An empty waitpid() loop was put here by Tridge and we could never
1460: * get him to explain why he put it in, so rather than taking it
1461: * out we're instead saving the child exit statuses for later use.
1462: * The waitpid() loop presumably eliminates all possibility of leaving
1463: * zombie children, maybe that's why he did it. */
1464: while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
1465: /* save the child's exit status */
1466: for (cnt = 0; cnt < MAXCHILDPROCS; cnt++) {
1467: if (pid_stat_table[cnt].pid == 0) {
1468: pid_stat_table[cnt].pid = pid;
1469: pid_stat_table[cnt].status = status;
1470: break;
1471: }
1472: }
1473: }
1474: #endif
1475: #ifndef HAVE_SIGACTION
1476: signal(SIGCHLD, remember_children);
1477: #endif
1478: }
1479:
1480:
1481: /**
1482: * This routine catches signals and tries to send them to gdb.
1483: *
1484: * Because it's called from inside a signal handler it ought not to
1485: * use too many library routines.
1486: *
1487: * @todo Perhaps use "screen -X" instead/as well, to help people
1488: * debugging without easy access to X. Perhaps use an environment
1489: * variable, or just call a script?
1490: *
1491: * @todo The /proc/ magic probably only works on Linux (and
1492: * Solaris?) Can we be more portable?
1493: **/
1494: #ifdef MAINTAINER_MODE
1495: const char *get_panic_action(void)
1496: {
1497: const char *cmd_fmt = getenv("RSYNC_PANIC_ACTION");
1498:
1499: if (cmd_fmt)
1500: return cmd_fmt;
1501: else
1502: return "xterm -display :0 -T Panic -n Panic "
1503: "-e gdb /proc/%d/exe %d";
1504: }
1505:
1506:
1507: /**
1508: * Handle a fatal signal by launching a debugger, controlled by $RSYNC_PANIC_ACTION.
1509: *
1510: * This signal handler is only installed if we were configured with
1511: * --enable-maintainer-mode. Perhaps it should always be on and we
1512: * should just look at the environment variable, but I'm a bit leery
1513: * of a signal sending us into a busy loop.
1514: **/
1.1.1.3 ! misho 1515: static void rsync_panic_handler(UNUSED(int whatsig))
1.1 misho 1516: {
1517: char cmd_buf[300];
1.1.1.2 misho 1518: int ret, pid_int = getpid();
1.1 misho 1519:
1.1.1.2 misho 1520: snprintf(cmd_buf, sizeof cmd_buf, get_panic_action(), pid_int, pid_int);
1.1 misho 1521:
1522: /* Unless we failed to execute gdb, we allow the process to
1523: * continue. I'm not sure if that's right. */
1524: ret = system(cmd_buf);
1525: if (ret)
1526: _exit(ret);
1527: }
1528: #endif
1529:
1530:
1531: int main(int argc,char *argv[])
1532: {
1533: int ret;
1534: int orig_argc = argc;
1535: char **orig_argv = argv;
1536: #ifdef HAVE_SIGACTION
1537: # ifdef HAVE_SIGPROCMASK
1538: sigset_t sigmask;
1539:
1540: sigemptyset(&sigmask);
1541: # endif
1542: sigact.sa_flags = SA_NOCLDSTOP;
1543: #endif
1544: SIGACTMASK(SIGUSR1, sigusr1_handler);
1545: SIGACTMASK(SIGUSR2, sigusr2_handler);
1546: SIGACTMASK(SIGCHLD, remember_children);
1547: #ifdef MAINTAINER_MODE
1548: SIGACTMASK(SIGSEGV, rsync_panic_handler);
1549: SIGACTMASK(SIGFPE, rsync_panic_handler);
1550: SIGACTMASK(SIGABRT, rsync_panic_handler);
1551: SIGACTMASK(SIGBUS, rsync_panic_handler);
1.1.1.3 ! misho 1552: #endif
! 1553: #ifdef SIGINFO
! 1554: SIGACTMASK(SIGINFO, siginfo_handler);
1.1 misho 1555: #endif
1556:
1557: starttime = time(NULL);
1558: our_uid = MY_UID();
1.1.1.2 misho 1559: our_gid = MY_GID();
1.1 misho 1560: am_root = our_uid == 0;
1561:
1562: memset(&stats, 0, sizeof(stats));
1563:
1564: if (argc < 2) {
1565: usage(FERROR);
1566: exit_cleanup(RERR_SYNTAX);
1567: }
1568:
1.1.1.2 misho 1569: /* Get the umask for use in permission calculations. We no longer set
1570: * it to zero; that is ugly and pointless now that all the callers that
1571: * relied on it have been reeducated to work with default ACLs. */
1572: umask(orig_umask = umask(0));
1.1 misho 1573:
1574: #if defined CONFIG_LOCALE && defined HAVE_SETLOCALE
1575: setlocale(LC_CTYPE, "");
1576: #endif
1577:
1578: if (!parse_arguments(&argc, (const char ***) &argv)) {
1579: /* FIXME: We ought to call the same error-handling
1580: * code here, rather than relying on getopt. */
1581: option_error();
1582: exit_cleanup(RERR_SYNTAX);
1583: }
1584:
1585: SIGACTMASK(SIGINT, sig_int);
1586: SIGACTMASK(SIGHUP, sig_int);
1587: SIGACTMASK(SIGTERM, sig_int);
1588: #if defined HAVE_SIGACTION && HAVE_SIGPROCMASK
1589: sigprocmask(SIG_UNBLOCK, &sigmask, NULL);
1590: #endif
1591:
1592: /* Ignore SIGPIPE; we consistently check error codes and will
1593: * see the EPIPE. */
1594: SIGACTION(SIGPIPE, SIG_IGN);
1595: #ifdef SIGXFSZ
1596: SIGACTION(SIGXFSZ, SIG_IGN);
1597: #endif
1598:
1599: /* Initialize change_dir() here because on some old systems getcwd
1600: * (implemented by forking "pwd" and reading its output) doesn't
1601: * work when there are other child processes. Also, on all systems
1602: * that implement getcwd that way "pwd" can't be found after chroot. */
1603: change_dir(NULL, CD_NORMAL);
1604:
1605: init_flist();
1606:
1607: if ((write_batch || read_batch) && !am_server) {
1608: if (write_batch)
1609: write_batch_shell_file(orig_argc, orig_argv, argc);
1610:
1611: if (read_batch && strcmp(batch_name, "-") == 0)
1612: batch_fd = STDIN_FILENO;
1613: else {
1614: batch_fd = do_open(batch_name,
1615: write_batch ? O_WRONLY | O_CREAT | O_TRUNC
1616: : O_RDONLY, S_IRUSR | S_IWUSR);
1617: }
1618: if (batch_fd < 0) {
1619: rsyserr(FERROR, errno, "Batch file %s open error",
1620: full_fname(batch_name));
1621: exit_cleanup(RERR_FILEIO);
1622: }
1623: if (read_batch)
1624: read_stream_flags(batch_fd);
1625: else
1626: write_stream_flags(batch_fd);
1627: }
1628: if (write_batch < 0)
1629: dry_run = 1;
1630:
1631: if (am_server) {
1632: #ifdef ICONV_CONST
1633: setup_iconv();
1634: #endif
1635: } else if (am_daemon)
1636: return daemon_main();
1637:
1638: if (am_server && protect_args) {
1639: char buf[MAXPATHLEN];
1640: protect_args = 2;
1641: read_args(STDIN_FILENO, NULL, buf, sizeof buf, 1, &argv, &argc, NULL);
1642: if (!parse_arguments(&argc, (const char ***) &argv)) {
1643: option_error();
1644: exit_cleanup(RERR_SYNTAX);
1645: }
1646: }
1647:
1648: if (argc < 1) {
1649: usage(FERROR);
1650: exit_cleanup(RERR_SYNTAX);
1651: }
1652:
1653: if (am_server) {
1654: set_nonblocking(STDIN_FILENO);
1655: set_nonblocking(STDOUT_FILENO);
1656: if (am_daemon)
1657: return start_daemon(STDIN_FILENO, STDOUT_FILENO);
1658: start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
1659: }
1660:
1661: ret = start_client(argc, argv);
1662: if (ret == -1)
1663: exit_cleanup(RERR_STARTCLIENT);
1664: else
1665: exit_cleanup(ret);
1666:
1667: return ret;
1668: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>