Added a remote-shell substitute for use in testing and for certain
[rsync/rsync.git] / main.c
diff --git a/main.c b/main.c
index 273513f..e9675f9 100644 (file)
--- a/main.c
+++ b/main.c
@@ -4,11 +4,11 @@
  * Copyright (C) 1996-2001 Andrew Tridgell <tridge@samba.org>
  * Copyright (C) 1996 Paul Mackerras
  * Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
- * Copyright (C) 2003, 2004, 2005, 2006 Wayne Davison
+ * Copyright (C) 2003-2007 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
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ * with this program; if not, visit the http://fsf.org website.
  */
 
 #include "rsync.h"
+#include "io.h"
 #if defined CONFIG_LOCALE && defined HAVE_LOCALE_H
 #include <locale.h>
 #endif
@@ -34,10 +34,9 @@ extern int am_server;
 extern int am_sender;
 extern int am_generator;
 extern int am_daemon;
-extern int incremental;
+extern int inc_recurse;
 extern int blocking_io;
 extern int remove_source_files;
-extern int daemon_over_rsh;
 extern int need_messages_from_generator;
 extern int kluge_around_eof;
 extern int do_stats;
@@ -71,10 +70,12 @@ extern char *shell_cmd;
 extern char *batch_name;
 extern char *password_file;
 extern char curr_dir[MAXPATHLEN];
+extern struct file_list *cur_flist;
 extern struct filter_list_struct server_filter_list;
 
 int local_server = 0;
 int new_root_dir = 0;
+int daemon_over_rsh = 0;
 mode_t orig_umask = 0;
 int batch_gen_fd = -1;
 
@@ -191,12 +192,12 @@ static void handle_stats(int f)
 
        if (am_server) {
                if (am_sender) {
-                       write_longint(f, total_read);
-                       write_longint(f, total_written);
-                       write_longint(f, stats.total_size);
+                       write_varlong30(f, total_read, 3);
+                       write_varlong30(f, total_written, 3);
+                       write_varlong30(f, stats.total_size, 3);
                        if (protocol_version >= 29) {
-                               write_longint(f, stats.flist_buildtime);
-                               write_longint(f, stats.flist_xfertime);
+                               write_varlong30(f, stats.flist_buildtime, 3);
+                               write_varlong30(f, stats.flist_xfertime, 3);
                        }
                }
                return;
@@ -209,22 +210,22 @@ static void handle_stats(int f)
        else if (!am_sender) {
                /* Read the first two in opposite order because the meaning of
                 * read/write swaps when switching from sender to receiver. */
-               total_written = read_longint(f);
-               total_read = read_longint(f);
-               stats.total_size = read_longint(f);
+               total_written = read_varlong30(f, 3);
+               total_read = read_varlong30(f, 3);
+               stats.total_size = read_varlong30(f, 3);
                if (protocol_version >= 29) {
-                       stats.flist_buildtime = read_longint(f);
-                       stats.flist_xfertime = read_longint(f);
+                       stats.flist_buildtime = read_varlong30(f, 3);
+                       stats.flist_xfertime = read_varlong30(f, 3);
                }
        } else if (write_batch) {
                /* The --read-batch process is going to be a client
                 * receiver, so we need to give it the stats. */
-               write_longint(batch_fd, total_read);
-               write_longint(batch_fd, total_written);
-               write_longint(batch_fd, stats.total_size);
+               write_varlong30(batch_fd, total_read, 3);
+               write_varlong30(batch_fd, total_written, 3);
+               write_varlong30(batch_fd, stats.total_size, 3);
                if (protocol_version >= 29) {
-                       write_longint(batch_fd, stats.flist_buildtime);
-                       write_longint(batch_fd, stats.flist_xfertime);
+                       write_varlong30(batch_fd, stats.flist_buildtime, 3);
+                       write_varlong30(batch_fd, stats.flist_xfertime, 3);
                }
        }
 }
@@ -609,7 +610,7 @@ static void fix_basis_dirs(void)
 }
 
 /* This is only called by the sender. */
-static void read_final_goodbye(int f_in, int f_out)
+static void read_final_goodbye(int f_in)
 {
        int i, iflags, xlen;
        uchar fnamecmp_type;
@@ -618,8 +619,8 @@ static void read_final_goodbye(int f_in, int f_out)
        if (protocol_version < 29)
                i = read_int(f_in);
        else {
-               i = read_ndx_and_attrs(f_in, f_out, &iflags,
-                                      &fnamecmp_type, xname, &xlen);
+               i = read_ndx_and_attrs(f_in, &iflags, &fnamecmp_type,
+                                      xname, &xlen);
        }
 
        if (i != NDX_DONE) {
@@ -669,7 +670,7 @@ static void do_server_sender(int f_in, int f_out, int argc, char *argv[])
        }
 
        flist = send_file_list(f_out,argc,argv);
-       if (!flist || flist->count == 0)
+       if (!flist || flist->used == 0)
                exit_cleanup(0);
 
        io_start_buffering_in(f_in);
@@ -678,7 +679,7 @@ static void do_server_sender(int f_in, int f_out, int argc, char *argv[])
        io_flush(FULL_FLUSH);
        handle_stats(f_out);
        if (protocol_version >= 24)
-               read_final_goodbye(f_in, f_out);
+               read_final_goodbye(f_in);
        io_flush(FULL_FLUSH);
        exit_cleanup(0);
 }
@@ -695,8 +696,8 @@ static int do_recv(int f_in, int f_out, char *local_name)
        copy_links = copy_dirlinks = 0;
 
 #ifdef SUPPORT_HARD_LINKS
-       if (preserve_hard_links)
-               match_hard_links();
+       if (preserve_hard_links && !inc_recurse)
+               match_hard_links(cur_flist);
 #endif
 
        if (fd_pair(error_pipe) < 0) {
@@ -727,7 +728,8 @@ static int do_recv(int f_in, int f_out, char *local_name)
                io_flush(FULL_FLUSH);
                handle_stats(f_in);
 
-               send_msg(MSG_DONE, "", 0);
+               send_msg(MSG_DONE, "", 1, 0);
+               write_varlong(error_pipe[1], stats.total_read, 3);
                io_flush(FULL_FLUSH);
 
                /* Handle any keep-alive packets from the post-processing work
@@ -740,7 +742,7 @@ static int do_recv(int f_in, int f_out, char *local_name)
                        kluge_around_eof = -1;
 
                        /* This should only get stopped via a USR2 signal. */
-                       read_ndx_and_attrs(f_in, -1, &iflags, &fnamecmp_type,
+                       read_ndx_and_attrs(f_in, &iflags, &fnamecmp_type,
                                           xname, &xlen);
 
                        rprintf(FERROR, "Invalid packet at end of run [%s]\n",
@@ -843,7 +845,7 @@ static void do_server_recv(int f_in, int f_out, int argc, char *argv[])
                rprintf(FERROR,"server_recv: recv_file_list error\n");
                exit_cleanup(RERR_FILESELECT);
        }
-       if (incremental && file_total == 1)
+       if (inc_recurse && file_total == 1)
                recv_additional_file_list(f_in);
        verbose = save_verbose;
 
@@ -899,7 +901,7 @@ void start_server(int f_in, int f_out, int argc, char *argv[])
 
        io_set_sock_fds(f_in, f_out);
        setup_protocol(f_out, f_in);
-#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
+#ifdef ICONV_CONST
        setup_iconv();
 #endif
 
@@ -936,7 +938,7 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
 
        io_set_sock_fds(f_in, f_out);
        setup_protocol(f_out,f_in);
-#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
+#ifdef ICONV_CONST
        setup_iconv();
 #endif
 
@@ -977,7 +979,7 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
                io_flush(FULL_FLUSH);
                handle_stats(-1);
                if (protocol_version >= 24)
-                       read_final_goodbye(f_in, f_out);
+                       read_final_goodbye(f_in);
                if (pid != -1) {
                        if (verbose > 3)
                                rprintf(FINFO,"client_run waiting on %d\n", (int) pid);
@@ -1009,10 +1011,10 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
        if (write_batch && !am_server)
                start_write_batch(f_in);
        flist = recv_file_list(f_in);
-       if (incremental && file_total == 1)
+       if (inc_recurse && file_total == 1)
                recv_additional_file_list(f_in);
 
-       if (flist && flist->count > 0) {
+       if (flist && flist->used > 0) {
                local_name = get_local_name(flist, argv[0]);
 
                fix_basis_dirs();
@@ -1091,16 +1093,9 @@ static int start_client(int argc, char *argv[])
                                        "--files-from hostname is not the same as the transfer hostname\n");
                                exit_cleanup(RERR_SYNTAX);
                        }
-                       if (rsync_port) {
-                               if (!shell_cmd) {
-                                       return start_socket_client(shell_machine,
-                                                                  shell_path,
-                                                                  argc, argv);
-                               }
-                               daemon_over_rsh = 1;
-                       }
-
                        am_sender = 0;
+                       if (rsync_port)
+                               daemon_over_rsh = shell_cmd ? 1 : -1;
                } else { /* source is local, check dest arg */
                        am_sender = 1;
 
@@ -1127,14 +1122,8 @@ static int start_client(int argc, char *argv[])
                                }
                                shell_machine = NULL;
                                shell_path = p;
-                       } else if (rsync_port) {
-                               if (!shell_cmd) {
-                                       return start_socket_client(shell_machine,
-                                                                  shell_path,
-                                                                  argc, argv);
-                               }
-                               daemon_over_rsh = 1;
-                       }
+                       } else if (rsync_port)
+                               daemon_over_rsh = shell_cmd ? 1 : -1;
                }
        } else {  /* read_batch */
                local_server = 1;
@@ -1145,6 +1134,15 @@ static int start_client(int argc, char *argv[])
                }
        }
 
+       /* for remote source, only single dest arg can remain ... */
+       if (!am_sender && argc > 1) {
+               usage(FERROR);
+               exit_cleanup(RERR_SYNTAX);
+       }
+
+       if (daemon_over_rsh < 0)
+               return start_socket_client(shell_machine, shell_path, argc, argv);
+
        if (password_file && !daemon_over_rsh) {
                rprintf(FERROR, "The --password-file option may only be "
                                "used when accessing an rsync daemon.\n");
@@ -1168,12 +1166,6 @@ static int start_client(int argc, char *argv[])
                        shell_path ? shell_path : "");
        }
 
-       /* for remote source, only single dest arg can remain ... */
-       if (!am_sender && argc > 1) {
-               usage(FERROR);
-               exit_cleanup(RERR_SYNTAX);
-       }
-
        /* ... or no dest at all */
        if (!am_sender && argc == 0)
                list_only |= 1;