X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/8eb6cf784bcec383e1f9cf9c1fee33f7ccfc8927..860236bf90087c88e886b6a7bffb83d6df51c1cc:/main.c diff --git a/main.c b/main.c index 3cc21b59..2b207be2 100644 --- a/main.c +++ b/main.c @@ -35,6 +35,7 @@ extern int blocking_io; extern int remove_sent_files; extern int daemon_over_rsh; extern int need_messages_from_generator; +extern int kluge_around_eof; extern int do_stats; extern int log_got_error; extern int module_id; @@ -57,8 +58,7 @@ extern int batch_gen_fd; extern int filesfrom_fd; extern pid_t cleanup_child_pid; extern struct stats stats; -extern char *files_from; -extern char *remote_filesfrom_file; +extern char *filesfrom_host; extern char *partial_dir; extern char *basis_dir[]; extern char *rsync_path; @@ -428,6 +428,29 @@ static char *get_local_name(struct file_list *flist,char *name) } +/* This is only called by the sender. */ +static void read_final_goodbye(int f_in, int f_out, int flist_count) +{ + int i; + + if (protocol_version < 29) + i = read_int(f_in); + else { + while ((i = read_int(f_in)) == flist_count + && read_shortint(f_in) == ITEM_IS_NEW) { + /* Forward the keep-alive (no-op) to the receiver. */ + write_int(f_out, flist_count); + write_shortint(f_out, ITEM_IS_NEW); + } + } + + if (i != -1) { + rprintf(FERROR, "Invalid packet from generator at end of run.\n"); + exit_cleanup(RERR_PROTOCOL); + } +} + + static void do_server_sender(int f_in, int f_out, int argc,char *argv[]) { int i; @@ -484,10 +507,8 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[]) send_files(flist,f_out,f_in); io_flush(FULL_FLUSH); report(f_out); - if (protocol_version >= 24) { - /* final goodbye message */ - read_int(f_in); - } + if (protocol_version >= 24) + read_final_goodbye(f_in, f_out, flist->count); io_flush(FULL_FLUSH); exit_cleanup(0); } @@ -543,9 +564,23 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name) send_msg(MSG_DONE, "", 0); io_flush(FULL_FLUSH); - /* finally we go to sleep until our parent kills us - * with a USR2 signal. We sleep for a short time as on - * some OSes a signal won't interrupt a sleep! */ + + /* Handle any keep-alive packets from the post-processing work + * that the generator does. */ + if (protocol_version >= 29) { + kluge_around_eof = -1; + + /* This should only get stopped via a USR2 signal. */ + while (read_int(f_in) == flist->count + && read_shortint(f_in) == ITEM_IS_NEW) {} + + rprintf(FERROR, "Invalid packet from server at end of run.\n"); + exit_cleanup(RERR_PROTOCOL); + } + + /* Finally, we go to sleep until our parent kills us with a + * USR2 signal. We sleep for a short time, as on some OSes + * a signal won't interrupt a sleep! */ while (1) msleep(20); } @@ -723,10 +758,10 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[]) if (am_sender) { keep_dirlinks = 0; /* Must be disabled on the sender. */ io_start_buffering_out(); - if (!remote_filesfrom_file) + if (!filesfrom_host) set_msg_fd_in(f_in); send_filter_list(f_out); - if (remote_filesfrom_file) + if (filesfrom_host) filesfrom_fd = f_in; if (write_batch) @@ -740,10 +775,8 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[]) io_flush(NORMAL_FLUSH); send_files(flist,f_out,f_in); io_flush(FULL_FLUSH); - if (protocol_version >= 24) { - /* final goodbye message */ - read_int(f_in); - } + if (protocol_version >= 24) + read_final_goodbye(f_in, f_out, flist->count); if (pid != -1) { if (verbose > 3) rprintf(FINFO,"client_run waiting on %d\n", (int) pid); @@ -832,49 +865,21 @@ static int start_client(int argc, char *argv[]) if ((rc = copy_argv(argv))) return rc; - /* rsync:// always uses rsync server over direct socket connection */ - if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0 - && !read_batch) { - char *host, *path; - - host = argv[0] + strlen(URL_PREFIX); - p = strchr(host,'/'); - if (p) { - *p = '\0'; - path = p+1; - } else - path = ""; - if (*host == '[' && (p = strchr(host, ']')) != NULL) { - host++; - *p++ = '\0'; - if (*p != ':') - p = NULL; - } else - p = strchr(host, ':'); - if (p) { - rsync_port = atoi(p+1); - *p = '\0'; - } - return start_socket_client(host, path, argc-1, argv+1); - } - if (!read_batch) { /* for read_batch, NO source is specified */ - p = find_colon(argv[0]); - if (p) { /* source is remote */ - if (remote_filesfrom_file - && remote_filesfrom_file != files_from + 1 - && strncmp(files_from, argv[0], p-argv[0]+1) != 0) { + shell_path = check_for_hostspec(argv[0], &shell_machine, &rsync_port); + if (shell_path) { /* source is remote */ + if (filesfrom_host && *filesfrom_host + && strcmp(filesfrom_host, shell_machine) != 0) { rprintf(FERROR, "--files-from hostname is not the same as the transfer hostname\n"); exit_cleanup(RERR_SYNTAX); } - if (p[1] == ':') { /* double colon */ - *p = 0; + if (rsync_port) { if (!shell_cmd) { - return start_socket_client(argv[0], p+2, + return start_socket_client(shell_machine, + shell_path, argc-1, argv+1); } - p++; daemon_over_rsh = 1; } @@ -884,60 +889,32 @@ static int start_client(int argc, char *argv[]) } am_sender = 0; - *p = 0; - shell_machine = argv[0]; - shell_path = p+1; argv++; - } else { /* source is local */ + } else { /* source is local, check dest arg */ am_sender = 1; - /* rsync:// destination uses rsync server over direct socket */ - if (strncasecmp(URL_PREFIX, argv[argc-1], strlen(URL_PREFIX)) == 0) { - char *host, *path; - - host = argv[argc-1] + strlen(URL_PREFIX); - p = strchr(host,'/'); - if (p) { - *p = '\0'; - path = p+1; - } else - path = ""; - if (*host == '[' && (p = strchr(host, ']')) != NULL) { - host++; - *p++ = '\0'; - if (*p != ':') - p = NULL; - } else - p = strchr(host, ':'); - if (p) { - rsync_port = atoi(p+1); - *p = '\0'; - } - return start_socket_client(host, path, argc-1, argv); - } - - p = find_colon(argv[argc-1]); /* look in dest arg */ - if (p && remote_filesfrom_file - && remote_filesfrom_file != files_from + 1 - && strncmp(files_from, argv[argc-1], p-argv[argc-1]+1) != 0) { + shell_path = check_for_hostspec(argv[argc-1], &shell_machine, &rsync_port); + if (shell_path && filesfrom_host && *filesfrom_host + && strcmp(filesfrom_host, shell_machine) != 0) { rprintf(FERROR, "--files-from hostname is not the same as the transfer hostname\n"); exit_cleanup(RERR_SYNTAX); } - if (!p) { /* no colon found, so src & dest are local */ + if (!shell_path) { /* no hostspec found, so src & dest are local */ local_server = 1; - if (remote_filesfrom_file) { + if (filesfrom_host) { rprintf(FERROR, "--files-from cannot be remote when the transfer is local\n"); exit_cleanup(RERR_SYNTAX); } - } else if (p[1] == ':') { /* double colon */ - *p = 0; + shell_machine = NULL; + shell_path = argv[argc-1]; + } else if (rsync_port) { if (!shell_cmd) { - return start_socket_client(argv[argc-1], p+2, + return start_socket_client(shell_machine, + shell_path, argc-1, argv); } - p++; daemon_over_rsh = 1; } @@ -945,21 +922,12 @@ static int start_client(int argc, char *argv[]) usage(FERROR); exit_cleanup(RERR_SYNTAX); } - - if (local_server) { - shell_machine = NULL; - shell_path = argv[argc-1]; - } else { - *p = 0; - shell_machine = argv[argc-1]; - shell_path = p+1; - } } argc--; } else { /* read_batch */ local_server = 1; shell_path = argv[argc-1]; - if (find_colon(shell_path)) { + if (check_for_hostspec(shell_path, &shell_machine, &rsync_port)) { rprintf(FERROR, "remote destination is not allowed with --read-batch\n"); exit_cleanup(RERR_SYNTAX); } @@ -1021,6 +989,7 @@ static RETSIGTYPE sigusr1_handler(UNUSED(int val)) static RETSIGTYPE sigusr2_handler(UNUSED(int val)) { + close_all(); if (log_got_error) _exit(RERR_PARTIAL); _exit(0); }