Changed most instances of "remote_version" to "protocol_version", and
[rsync/rsync.git] / main.c
diff --git a/main.c b/main.c
index 95e25b3..25cd106 100644 (file)
--- a/main.c
+++ b/main.c
 time_t starttime = 0;
 
 extern struct stats stats;
+extern char *files_from;
+extern int filesfrom_fd;
+extern char *remote_filesfrom_file;
 extern int am_server;
 extern int am_sender;
 extern int am_daemon;
 extern int verbose;
+extern int protocol_version;
 
 /* there's probably never more than at most 2 outstanding child processes,
  * but set it higher just in case.
@@ -79,10 +83,9 @@ static void report(int f)
 {
        time_t t = time(NULL);
        extern int do_stats;
-       extern int remote_version;
        int send_stats;
 
-       if (do_stats) {
+       if (do_stats && verbose > 1) {
                /* These come out from every process */
                show_malloc_stats();
                show_flist_stats();
@@ -93,7 +96,7 @@ static void report(int f)
                if (f == -1 || !am_sender) return;
        }
 
-       send_stats = verbose || (remote_version >= 20);
+       send_stats = verbose || protocol_version >= 20;
        if (am_server) {
                if (am_sender && send_stats) {
                        int64 w;
@@ -139,12 +142,12 @@ static void report(int f)
                rprintf(FINFO,"File list size: %d\n", stats.flist_size);
                rprintf(FINFO,"Total bytes written: %.0f\n",
                        (double)stats.total_written);
-               rprintf(FINFO,"Total bytes read: %.0f\n\n",
+               rprintf(FINFO,"Total bytes read: %.0f\n",
                        (double)stats.total_read);
        }
 
        if (verbose || do_stats) {
-               rprintf(FINFO,"wrote %.0f bytes  read %.0f bytes  %.2f bytes/sec\n",
+               rprintf(FINFO,"\nwrote %.0f bytes  read %.0f bytes  %.2f bytes/sec\n",
                        (double)stats.total_written,
                        (double)stats.total_read,
                        (stats.total_written+stats.total_read)/(0.5 + (t-starttime)));
@@ -282,6 +285,7 @@ oom:
 static char *get_local_name(struct file_list *flist,char *name)
 {
        STRUCT_STAT st;
+       int e;
        extern int orig_umask;
 
        if (verbose > 2)
@@ -307,7 +311,7 @@ static char *get_local_name(struct file_list *flist,char *name)
                return name;
        }
 
-       if (flist->count <= 1)
+       if (flist->count <= 1 && ((e = strlen(name)) <= 1 || name[e-1] != '/'))
                return name;
 
        if (do_mkdir(name,0777 & ~orig_umask) != 0) {
@@ -338,7 +342,6 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
        char *dir = argv[0];
        extern int relative_paths;
        extern int recurse;
-       extern int remote_version;
 
        if (verbose > 2)
                rprintf(FINFO,"server_sender starting pid=%d\n",(int)getpid());
@@ -372,7 +375,7 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
        send_files(flist,f_out,f_in);
        io_flush();
        report(f_out);
-       if (remote_version >= 24) {
+       if (protocol_version >= 24) {
                /* final goodbye message */
                read_int(f_in);
        }
@@ -391,7 +394,6 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
        extern int delete_after;
        extern int recurse;
        extern int delete_mode;
-       extern int remote_version;
 
        if (preserve_hard_links)
                init_hard_links(flist);
@@ -452,7 +454,7 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
 
        read_int(recv_pipe[0]);
        close(recv_pipe[0]);
-       if (remote_version >= 24) {
+       if (protocol_version >= 24) {
                /* send a final goodbye message */
                write_int(f_out, -1);
        }
@@ -501,6 +503,15 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
        if (delete_mode && !delete_excluded)
                recv_exclude_list(f_in);
 
+       if (filesfrom_fd >= 0) {
+               /* We're receiving the file info from the sender, so we need
+                * the IO routines to automatically write out the names onto
+                * our f_out socket as we read the list info from the sender.
+                * This avoids both deadlock and extra delays/buffers. */
+               io_set_filesfrom_fds(filesfrom_fd, f_out);
+               filesfrom_fd = -1;
+       }
+
        if (read_batch)
                flist = batch_flist;
        else
@@ -533,7 +544,6 @@ int child_main(int argc, char *argv[])
 void start_server(int f_in, int f_out, int argc, char *argv[])
 {
        extern int cvs_exclude;
-       extern int remote_version;
        extern int read_batch;
 
        setup_protocol(f_out, f_in);
@@ -541,7 +551,7 @@ void start_server(int f_in, int f_out, int argc, char *argv[])
        set_nonblocking(f_in);
        set_nonblocking(f_out);
 
-       if (remote_version >= 23)
+       if (protocol_version >= 23)
                io_start_multiplex_out(f_out);
 
        if (am_sender) {
@@ -567,7 +577,6 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
        struct file_list *flist = NULL;
        int status = 0, status2 = 0;
        char *local_name = NULL;
-       extern int remote_version;
        extern pid_t cleanup_child_pid;
        extern int write_batch;
        extern int read_batch;
@@ -582,7 +591,7 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
 
        setup_protocol(f_out,f_in);
 
-       if (remote_version >= 23)
+       if (protocol_version >= 23)
                io_start_multiplex_in(f_in);
 
        if (am_sender) {
@@ -593,13 +602,15 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
                        add_cvs_excludes();
                if (delete_mode && !delete_excluded)
                        send_exclude_list(f_out);
+               if (remote_filesfrom_file)
+                       filesfrom_fd = f_in;
                if (!read_batch) /*  dw -- don't write to pipe */
                        flist = send_file_list(f_out,argc,argv);
                if (verbose > 3)
                        rprintf(FINFO,"file list sent\n");
 
                send_files(flist,f_out,f_in);
-               if (remote_version >= 24) {
+               if (protocol_version >= 24) {
                        /* final goodbye message */
                        read_int(f_in);
                }
@@ -621,6 +632,11 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
        if (!write_batch)
                send_exclude_list(f_out);
 
+       if (filesfrom_fd >= 0) {
+               io_set_filesfrom_fds(filesfrom_fd, f_out);
+               filesfrom_fd = -1;
+       }
+
        flist = recv_file_list(f_in);
        if (!flist || flist->count == 0) {
                rprintf(FINFO, "client: nothing to do: "
@@ -643,22 +659,6 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
        return MAX(status, status2);
 }
 
-static char *find_colon(char *s)
-{
-       char *p, *p2;
-
-       p = strchr(s,':');
-       if (!p) return NULL;
-
-       /* now check to see if there is a / in the string before the : - if there is then
-          discard the colon on the assumption that the : is part of a filename */
-       p2 = strchr(s,'/');
-       if (p2 && p2 < p) return NULL;
-
-       return p;
-}
-
-
 static int copy_argv (char *argv[])
 {
        int i;
@@ -727,6 +727,13 @@ static int start_client(int argc, char *argv[])
        if (!read_batch) {
                p = find_colon(argv[0]);
                if (p) {
+                       if (remote_filesfrom_file
+                        && remote_filesfrom_file != files_from + 1
+                        && strncmp(files_from, argv[0], p-argv[0]+1) != 0) {
+                               rprintf(FERROR,
+                                       "--files-from hostname is not transfer hostname\n");
+                               exit_cleanup(RERR_SYNTAX);
+                       }
                        if (p[1] == ':') { /* double colon */
                                *p = 0;
                                if (!shell_cmd) {
@@ -772,8 +779,20 @@ static int start_client(int argc, char *argv[])
                        }
 
                        p = find_colon(argv[argc-1]);
+                       if (p && remote_filesfrom_file
+                        && remote_filesfrom_file != files_from + 1
+                        && strncmp(files_from, argv[argc-1], p-argv[argc-1]+1) != 0) {
+                               rprintf(FERROR,
+                                       "--files-from hostname is not transfer hostname\n");
+                               exit_cleanup(RERR_SYNTAX);
+                       }
                        if (!p) {
                                local_server = 1;
+                               if (remote_filesfrom_file) {
+                                       rprintf(FERROR,
+                                               "--files-from is remote but transfer is local\n");
+                                       exit_cleanup(RERR_SYNTAX);
+                               }
                        } else if (p[1] == ':') { /* double colon */
                                *p = 0;
                                if (!shell_cmd) {
@@ -854,17 +873,20 @@ static int start_client(int argc, char *argv[])
 }
 
 
-static RETSIGTYPE sigusr1_handler(int UNUSED(val)) {
+static RETSIGTYPE sigusr1_handler(UNUSED(int val))
+{
        exit_cleanup(RERR_SIGNAL);
 }
 
-static RETSIGTYPE sigusr2_handler(int UNUSED(val)) {
+static RETSIGTYPE sigusr2_handler(UNUSED(int val))
+{
        extern int log_got_error;
        if (log_got_error) _exit(RERR_PARTIAL);
        _exit(0);
 }
 
-static RETSIGTYPE sigchld_handler(int UNUSED(val)) {
+static RETSIGTYPE sigchld_handler(UNUSED(int val))
+{
 #ifdef WNOHANG
        int cnt, status;
        pid_t pid;
@@ -922,7 +944,7 @@ const char *get_panic_action(void)
  * should just look at the environment variable, but I'm a bit leery
  * of a signal sending us into a busy loop.
  **/
-static RETSIGTYPE rsync_panic_handler(int UNUSED(whatsig))
+static RETSIGTYPE rsync_panic_handler(UNUSED(int whatsig))
 {
        char cmd_buf[300];
        int ret;
@@ -1033,6 +1055,5 @@ int main(int argc,char *argv[])
        else
                exit_cleanup(ret);
 
-       exit(ret);
-       /* NOTREACHED */
+       return ret;
 }