Diff for /embedaddon/rsync/main.c between versions 1.1 and 1.1.1.2

version 1.1, 2012/02/17 15:09:30 version 1.1.1.2, 2013/10/14 07:51:14
Line 4 Line 4
  * Copyright (C) 1996-2001 Andrew Tridgell <tridge@samba.org>   * Copyright (C) 1996-2001 Andrew Tridgell <tridge@samba.org>
  * Copyright (C) 1996 Paul Mackerras   * Copyright (C) 1996 Paul Mackerras
  * Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>   * Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
 * Copyright (C) 2003-2009 Wayne Davison * Copyright (C) 2003-2013 Wayne Davison
  *   *
  * This program is free software; you can redistribute it and/or modify   * 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   * it under the terms of the GNU General Public License as published by
Line 21 Line 21
  */   */
   
 #include "rsync.h"  #include "rsync.h"
#include "ifuncs.h"#include "inums.h"
 #include "io.h"  #include "io.h"
 #if defined CONFIG_LOCALE && defined HAVE_LOCALE_H  #if defined CONFIG_LOCALE && defined HAVE_LOCALE_H
 #include <locale.h>  #include <locale.h>
 #endif  #endif
   
extern int verbose;extern int force_change;
 extern int dry_run;  extern int dry_run;
 extern int list_only;  extern int list_only;
   extern int io_timeout;
 extern int am_root;  extern int am_root;
 extern int am_server;  extern int am_server;
 extern int am_sender;  extern int am_sender;
 extern int am_daemon;  extern int am_daemon;
 extern int inc_recurse;  extern int inc_recurse;
 extern int blocking_io;  extern int blocking_io;
   extern int always_checksum;
 extern int remove_source_files;  extern int remove_source_files;
   extern int output_needs_newline;
 extern int need_messages_from_generator;  extern int need_messages_from_generator;
 extern int kluge_around_eof;  extern int kluge_around_eof;
 extern int do_stats;  
 extern int got_xfer_error;  extern int got_xfer_error;
   extern int msgs2stderr;
 extern int module_id;  extern int module_id;
   extern int read_only;
 extern int copy_links;  extern int copy_links;
 extern int copy_dirlinks;  extern int copy_dirlinks;
 extern int copy_unsafe_links;  extern int copy_unsafe_links;
Line 62  extern int whole_file; Line 66  extern int whole_file;
 extern int read_batch;  extern int read_batch;
 extern int write_batch;  extern int write_batch;
 extern int batch_fd;  extern int batch_fd;
   extern int sock_f_in;
   extern int sock_f_out;
 extern int filesfrom_fd;  extern int filesfrom_fd;
 extern int connect_timeout;  extern int connect_timeout;
   extern int send_msgs_to_gen;
 extern dev_t filesystem_dev;  extern dev_t filesystem_dev;
 extern pid_t cleanup_child_pid;  extern pid_t cleanup_child_pid;
   extern size_t bwlimit_writemax;
 extern unsigned int module_dirlen;  extern unsigned int module_dirlen;
   extern BOOL flist_receiving_enabled;
   extern BOOL shutting_down;
   extern int basis_dir_cnt;
 extern struct stats stats;  extern struct stats stats;
   extern char *stdout_format;
   extern char *logfile_format;
 extern char *filesfrom_host;  extern char *filesfrom_host;
 extern char *partial_dir;  extern char *partial_dir;
 extern char *dest_option;  extern char *dest_option;
 extern char *basis_dir[MAX_BASIS_DIRS+1];  
 extern char *rsync_path;  extern char *rsync_path;
 extern char *shell_cmd;  extern char *shell_cmd;
 extern char *batch_name;  extern char *batch_name;
 extern char *password_file;  extern char *password_file;
   extern char *backup_dir;
 extern char curr_dir[MAXPATHLEN];  extern char curr_dir[MAXPATHLEN];
   extern char backup_dir_buf[MAXPATHLEN];
   extern char *basis_dir[MAX_BASIS_DIRS+1];
 extern struct file_list *first_flist;  extern struct file_list *first_flist;
extern struct filter_list_struct daemon_filter_list;extern filter_rule_list daemon_filter_list;
   
 uid_t our_uid;  uid_t our_uid;
   gid_t our_gid;
 int am_receiver = 0;  /* Only set to 1 after the receiver/generator fork. */  int am_receiver = 0;  /* Only set to 1 after the receiver/generator fork. */
 int am_generator = 0; /* Only set to 1 after the receiver/generator fork. */  int am_generator = 0; /* Only set to 1 after the receiver/generator fork. */
 int local_server = 0;  int local_server = 0;
 int daemon_over_rsh = 0;  int daemon_over_rsh = 0;
 mode_t orig_umask = 0;  mode_t orig_umask = 0;
 int batch_gen_fd = -1;  int batch_gen_fd = -1;
   int sender_keeps_checksum = 0;
   
 /* There's probably never more than at most 2 outstanding child processes,  /* There's probably never more than at most 2 outstanding child processes,
  * but set it higher, just in case. */   * but set it higher, just in case. */
Line 116  static void show_malloc_stats(void); Line 133  static void show_malloc_stats(void);
 pid_t wait_process(pid_t pid, int *status_ptr, int flags)  pid_t wait_process(pid_t pid, int *status_ptr, int flags)
 {  {
         pid_t waited_pid;          pid_t waited_pid;
        
         do {          do {
                 waited_pid = waitpid(pid, status_ptr, flags);                  waited_pid = waitpid(pid, status_ptr, flags);
         } while (waited_pid == -1 && errno == EINTR);          } while (waited_pid == -1 && errno == EINTR);
Line 169  static void wait_process_with_flush(pid_t pid, int *ex Line 186  static void wait_process_with_flush(pid_t pid, int *ex
                 *exit_code_ptr = WEXITSTATUS(status);                  *exit_code_ptr = WEXITSTATUS(status);
 }  }
   
   void write_del_stats(int f)
   {
           if (read_batch)
                   write_int(f, NDX_DEL_STATS);
           else
                   write_ndx(f, NDX_DEL_STATS);
           write_varint(f, stats.deleted_files - stats.deleted_dirs
                         - stats.deleted_symlinks - stats.deleted_devices
                         - stats.deleted_specials);
           write_varint(f, stats.deleted_dirs);
           write_varint(f, stats.deleted_symlinks);
           write_varint(f, stats.deleted_devices);
           write_varint(f, stats.deleted_specials);
   }
   
   void read_del_stats(int f)
   {
           stats.deleted_files = read_varint(f);
           stats.deleted_files += stats.deleted_dirs = read_varint(f);
           stats.deleted_files += stats.deleted_symlinks = read_varint(f);
           stats.deleted_files += stats.deleted_devices = read_varint(f);
           stats.deleted_files += stats.deleted_specials = read_varint(f);
   }
   
 /* This function gets called from all 3 processes.  We want the client side  /* This function gets called from all 3 processes.  We want the client side
  * to actually output the text, but the sender is the only process that has   * to actually output the text, but the sender is the only process that has
  * all the stats we need.  So, if we're a client sender, we do the report.   * all the stats we need.  So, if we're a client sender, we do the report.
Line 185  static void handle_stats(int f) Line 226  static void handle_stats(int f)
         total_read = stats.total_read;          total_read = stats.total_read;
         total_written = stats.total_written;          total_written = stats.total_written;
   
        if (do_stats && verbose > 1) {        if (INFO_GTE(STATS, 3)) {
                 /* These come out from every process */                  /* These come out from every process */
                 show_malloc_stats();                  show_malloc_stats();
                 show_flist_stats();                  show_flist_stats();
Line 239  static void handle_stats(int f) Line 280  static void handle_stats(int f)
         }          }
 }  }
   
   static void output_itemized_counts(const char *prefix, int *counts)
   {
           static char *labels[] = { "reg", "dir", "link", "dev", "special" };
           char buf[1024], *pre = " (";
           int j, len = 0;
           int total = counts[0];
           if (total) {
                   counts[0] -= counts[1] + counts[2] + counts[3] + counts[4];
                   for (j = 0; j < 5; j++) {
                           if (counts[j]) {
                                   len += snprintf(buf+len, sizeof buf - len - 2,
                                           "%s%s: %s",
                                           pre, labels[j], comma_num(counts[j]));
                                   pre = ", ";
                           }
                   }
                   buf[len++] = ')';
           }
           buf[len] = '\0';
           rprintf(FINFO, "%s: %s%s\n", prefix, comma_num(total), buf);
   }
   
 static void output_summary(void)  static void output_summary(void)
 {  {
        if (do_stats) {        if (INFO_GTE(STATS, 2)) {
                 rprintf(FCLIENT, "\n");                  rprintf(FCLIENT, "\n");
                rprintf(FINFO,"Number of files: %d\n", stats.num_files);                output_itemized_counts("Number of files", &stats.num_files);
                rprintf(FINFO,"Number of files transferred: %d\n",                if (protocol_version >= 29)
                        stats.num_transferred_files);                        output_itemized_counts("Number of created files", &stats.created_files);
                 if (protocol_version >= 31)
                         output_itemized_counts("Number of deleted files", &stats.deleted_files);
                 rprintf(FINFO,"Number of regular files transferred: %s\n",
                         comma_num(stats.xferred_files));
                 rprintf(FINFO,"Total file size: %s bytes\n",                  rprintf(FINFO,"Total file size: %s bytes\n",
                         human_num(stats.total_size));                          human_num(stats.total_size));
                 rprintf(FINFO,"Total transferred file size: %s bytes\n",                  rprintf(FINFO,"Total transferred file size: %s bytes\n",
Line 258  static void output_summary(void) Line 325  static void output_summary(void)
                         human_num(stats.flist_size));                          human_num(stats.flist_size));
                 if (stats.flist_buildtime) {                  if (stats.flist_buildtime) {
                         rprintf(FINFO,                          rprintf(FINFO,
                                "File list generation time: %.3f seconds\n",                                "File list generation time: %s seconds\n",
                                (double)stats.flist_buildtime / 1000);                                comma_dnum((double)stats.flist_buildtime / 1000, 3));
                         rprintf(FINFO,                          rprintf(FINFO,
                                "File list transfer time: %.3f seconds\n",                                "File list transfer time: %s seconds\n",
                                (double)stats.flist_xfertime / 1000);                                comma_dnum((double)stats.flist_xfertime / 1000, 3));
                 }                  }
                 rprintf(FINFO,"Total bytes sent: %s\n",                  rprintf(FINFO,"Total bytes sent: %s\n",
                         human_num(total_written));                          human_num(total_written));
Line 270  static void output_summary(void) Line 337  static void output_summary(void)
                         human_num(total_read));                          human_num(total_read));
         }          }
   
        if (verbose || do_stats) {        if (INFO_GTE(STATS, 1)) {
                 rprintf(FCLIENT, "\n");                  rprintf(FCLIENT, "\n");
                 rprintf(FINFO,                  rprintf(FINFO,
                         "sent %s bytes  received %s bytes  %s bytes/sec\n",                          "sent %s bytes  received %s bytes  %s bytes/sec\n",
                         human_num(total_written), human_num(total_read),                          human_num(total_written), human_num(total_read),
                         human_dnum((total_written + total_read)/(0.5 + (endtime - starttime)), 2));                          human_dnum((total_written + total_read)/(0.5 + (endtime - starttime)), 2));
                rprintf(FINFO, "total size is %s  speedup is %.2f%s\n",                rprintf(FINFO, "total size is %s  speedup is %s%s\n",
                         human_num(stats.total_size),                          human_num(stats.total_size),
                        (double)stats.total_size / (total_written+total_read),                        comma_dnum((double)stats.total_size / (total_written+total_read), 2),
                         write_batch < 0 ? " (BATCH ONLY)" : dry_run ? " (DRY RUN)" : "");                          write_batch < 0 ? " (BATCH ONLY)" : dry_run ? " (DRY RUN)" : "");
         }          }
   
Line 299  static void show_malloc_stats(void) Line 366  static void show_malloc_stats(void)
   
         rprintf(FCLIENT, "\n");          rprintf(FCLIENT, "\n");
         rprintf(FINFO, RSYNC_NAME "[%d] (%s%s%s) heap statistics:\n",          rprintf(FINFO, RSYNC_NAME "[%d] (%s%s%s) heap statistics:\n",
                getpid(), am_server ? "server " : "",                (int)getpid(), am_server ? "server " : "",
                 am_daemon ? "daemon " : "", who_am_i());                  am_daemon ? "daemon " : "", who_am_i());
         rprintf(FINFO, "  arena:     %10ld   (bytes from sbrk)\n",          rprintf(FINFO, "  arena:     %10ld   (bytes from sbrk)\n",
                 (long)mi.arena);                  (long)mi.arena);
Line 332  static pid_t do_cmd(char *cmd, char *machine, char *us Line 399  static pid_t do_cmd(char *cmd, char *machine, char *us
                     int *f_in_p, int *f_out_p)                      int *f_in_p, int *f_out_p)
 {  {
         int i, argc = 0;          int i, argc = 0;
        char *args[MAX_ARGS];        char *args[MAX_ARGS], *need_to_free = NULL;
         pid_t pid;          pid_t pid;
         int dash_l_set = 0;          int dash_l_set = 0;
   
Line 343  static pid_t do_cmd(char *cmd, char *machine, char *us Line 410  static pid_t do_cmd(char *cmd, char *machine, char *us
                         cmd = rsh_env;                          cmd = rsh_env;
                 if (!cmd)                  if (!cmd)
                         cmd = RSYNC_RSH;                          cmd = RSYNC_RSH;
                cmd = strdup(cmd); /* MEMORY LEAK */                cmd = need_to_free = strdup(cmd);
                 if (!cmd)                  if (!cmd)
                         goto oom;                          goto oom;
   
Line 440  static pid_t do_cmd(char *cmd, char *machine, char *us Line 507  static pid_t do_cmd(char *cmd, char *machine, char *us
   
         args[argc] = NULL;          args[argc] = NULL;
   
        if (verbose > 3) {        if (DEBUG_GTE(CMD, 2)) {
                 for (i = 0; i < argc; i++)                  for (i = 0; i < argc; i++)
                         rprintf(FCLIENT, "cmd[%d]=%s ", i, args[i]);                          rprintf(FCLIENT, "cmd[%d]=%s ", i, args[i]);
                 rprintf(FCLIENT, "\n");                  rprintf(FCLIENT, "\n");
Line 479  static pid_t do_cmd(char *cmd, char *machine, char *us Line 546  static pid_t do_cmd(char *cmd, char *machine, char *us
                         send_protected_args(*f_out_p, args);                          send_protected_args(*f_out_p, args);
         }          }
   
           if (need_to_free)
                   free(need_to_free);
   
         return pid;          return pid;
   
   oom:    oom:
Line 505  static char *get_local_name(struct file_list *flist, c Line 575  static char *get_local_name(struct file_list *flist, c
         int statret;          int statret;
         char *cp;          char *cp;
   
        if (verbose > 2) {        if (DEBUG_GTE(RECV, 1)) {
                 rprintf(FINFO, "get_local_name count=%d %s\n",                  rprintf(FINFO, "get_local_name count=%d %s\n",
                         file_total, NS(dest_path));                          file_total, NS(dest_path));
         }          }
Line 581  static char *get_local_name(struct file_list *flist, c Line 651  static char *get_local_name(struct file_list *flist, c
                         exit_cleanup(RERR_SYNTAX);                          exit_cleanup(RERR_SYNTAX);
                 }                  }
   
                if (mkdir_defmode(dest_path) != 0) {                if (do_mkdir(dest_path, ACCESSPERMS) != 0) {
                         rsyserr(FERROR, errno, "mkdir %s failed",                          rsyserr(FERROR, errno, "mkdir %s failed",
                                 full_fname(dest_path));                                  full_fname(dest_path));
                         exit_cleanup(RERR_FILEIO);                          exit_cleanup(RERR_FILEIO);
Line 591  static char *get_local_name(struct file_list *flist, c Line 661  static char *get_local_name(struct file_list *flist, c
                  && strcmp(flist->files[flist->low]->basename, ".") == 0)                   && strcmp(flist->files[flist->low]->basename, ".") == 0)
                         flist->files[0]->flags |= FLAG_DIR_CREATED;                          flist->files[0]->flags |= FLAG_DIR_CREATED;
   
                if (verbose)                if (INFO_GTE(NAME, 1))
                         rprintf(FINFO, "created directory %s\n", dest_path);                          rprintf(FINFO, "created directory %s\n", dest_path);
   
                 if (dry_run) {                  if (dry_run) {
Line 637  static char *get_local_name(struct file_list *flist, c Line 707  static char *get_local_name(struct file_list *flist, c
 static void check_alt_basis_dirs(void)  static void check_alt_basis_dirs(void)
 {  {
         STRUCT_STAT st;          STRUCT_STAT st;
        char **dir_p, *slash = strrchr(curr_dir, '/');        char *slash = strrchr(curr_dir, '/');
         int j;
   
        for (dir_p = basis_dir; *dir_p; dir_p++) {        for (j = 0; j < basis_dir_cnt; j++) {
                if (dry_run > 1 && **dir_p != '/') {                char *bdir = basis_dir[j];
                        int len = curr_dir_len + 1 + strlen(*dir_p) + 1;                int bd_len = strlen(bdir);
                 if (bd_len > 1 && bdir[bd_len-1] == '/')
                         bdir[--bd_len] = '\0';
                 if (dry_run > 1 && *bdir != '/') {
                         int len = curr_dir_len + 1 + bd_len + 1;
                         char *new = new_array(char, len);                          char *new = new_array(char, len);
                         if (!new)                          if (!new)
                                 out_of_memory("check_alt_basis_dirs");                                  out_of_memory("check_alt_basis_dirs");
                        if (slash && strncmp(*dir_p, "../", 3) == 0) {                        if (slash && strncmp(bdir, "../", 3) == 0) {
                             /* We want to remove only one leading "../" prefix for                              /* We want to remove only one leading "../" prefix for
                              * the directory we couldn't create in dry-run mode:                               * the directory we couldn't create in dry-run mode:
                              * this ensures that any other ".." references get                               * this ensures that any other ".." references get
                              * evaluated the same as they would for a live copy. */                               * evaluated the same as they would for a live copy. */
                             *slash = '\0';                              *slash = '\0';
                            pathjoin(new, len, curr_dir, *dir_p + 3);                            pathjoin(new, len, curr_dir, bdir + 3);
                             *slash = '/';                              *slash = '/';
                         } else                          } else
                            pathjoin(new, len, curr_dir, *dir_p);                            pathjoin(new, len, curr_dir, bdir);
                        *dir_p = new;                        basis_dir[j] = bdir = new;
                 }                  }
                if (do_stat(*dir_p, &st) < 0) {                if (do_stat(bdir, &st) < 0)
                        rprintf(FWARNING, "%s arg does not exist: %s\n",                        rprintf(FWARNING, "%s arg does not exist: %s\n", dest_option, bdir);
                                dest_option, *dir_p);                else if (!S_ISDIR(st.st_mode))
                } else if (!S_ISDIR(st.st_mode)) {                        rprintf(FWARNING, "%s arg is not a dir: %s\n", dest_option, bdir);
                        rprintf(FWARNING, "%s arg is not a dir: %s\n", 
                                dest_option, *dir_p); 
                } 
         }          }
 }  }
   
 /* This is only called by the sender. */  /* This is only called by the sender. */
static void read_final_goodbye(int f_in)static void read_final_goodbye(int f_in, int f_out)
 {  {
         int i, iflags, xlen;          int i, iflags, xlen;
         uchar fnamecmp_type;          uchar fnamecmp_type;
         char xname[MAXPATHLEN];          char xname[MAXPATHLEN];
   
           shutting_down = True;
   
         if (protocol_version < 29)          if (protocol_version < 29)
                 i = read_int(f_in);                  i = read_int(f_in);
         else {          else {
                i = read_ndx_and_attrs(f_in, &iflags, &fnamecmp_type,                i = read_ndx_and_attrs(f_in, f_out, &iflags, &fnamecmp_type, xname, &xlen);
                                       xname, &xlen);                if (protocol_version >= 31 && i == NDX_DONE) {
                         if (am_sender)
                                 write_ndx(f_out, NDX_DONE);
                         else {
                                 if (batch_gen_fd >= 0) {
                                         while (read_int(batch_gen_fd) != NDX_DEL_STATS) {}
                                         read_del_stats(batch_gen_fd);
                                 }
                                 write_int(f_out, NDX_DONE);
                         }
                         i = read_ndx_and_attrs(f_in, f_out, &iflags, &fnamecmp_type, xname, &xlen);
                 }
         }          }
   
         if (i != NDX_DONE) {          if (i != NDX_DONE) {
Line 693  static void do_server_sender(int f_in, int f_out, int  Line 778  static void do_server_sender(int f_in, int f_out, int 
         struct file_list *flist;          struct file_list *flist;
         char *dir = argv[0];          char *dir = argv[0];
   
        if (verbose > 2) {        if (DEBUG_GTE(SEND, 1))
                rprintf(FINFO, "server_sender starting pid=%ld\n",                rprintf(FINFO, "server_sender starting pid=%d\n", (int)getpid());
                        (long)getpid()); 
        } 
   
         if (am_daemon && lp_write_only(module_id)) {          if (am_daemon && lp_write_only(module_id)) {
                 rprintf(FERROR, "ERROR: module is write only\n");                  rprintf(FERROR, "ERROR: module is write only\n");
                 exit_cleanup(RERR_SYNTAX);                  exit_cleanup(RERR_SYNTAX);
                 return;                  return;
         }          }
        if (am_daemon && lp_read_only(module_id) && remove_source_files) {        if (am_daemon && read_only && remove_source_files) {
                 rprintf(FERROR,                  rprintf(FERROR,
                     "ERROR: --remove-%s-files cannot be used with a read-only module\n",                      "ERROR: --remove-%s-files cannot be used with a read-only module\n",
                     remove_source_files == 1 ? "source" : "sent");                      remove_source_files == 1 ? "source" : "sent");
Line 728  static void do_server_sender(int f_in, int f_out, int  Line 811  static void do_server_sender(int f_in, int f_out, int 
         }          }
   
         flist = send_file_list(f_out,argc,argv);          flist = send_file_list(f_out,argc,argv);
        if (!flist || flist->used == 0)        if (!flist || flist->used == 0) {
                 /* Make sure input buffering is off so we can't hang in noop_io_until_death(). */
                 io_end_buffering_in(0);
                 /* TODO:  we should really exit in a more controlled manner. */
                 exit_cleanup(0);                  exit_cleanup(0);
           }
   
         io_start_buffering_in(f_in);          io_start_buffering_in(f_in);
   
Line 737  static void do_server_sender(int f_in, int f_out, int  Line 824  static void do_server_sender(int f_in, int f_out, int 
         io_flush(FULL_FLUSH);          io_flush(FULL_FLUSH);
         handle_stats(f_out);          handle_stats(f_out);
         if (protocol_version >= 24)          if (protocol_version >= 24)
                read_final_goodbye(f_in);                read_final_goodbye(f_in, f_out);
         io_flush(FULL_FLUSH);          io_flush(FULL_FLUSH);
         exit_cleanup(0);          exit_cleanup(0);
 }  }
Line 763  static int do_recv(int f_in, int f_out, char *local_na Line 850  static int do_recv(int f_in, int f_out, char *local_na
                 exit_cleanup(RERR_IPC);                  exit_cleanup(RERR_IPC);
         }          }
   
        io_flush(NORMAL_FLUSH);        if (backup_dir) {
                 int ret = make_path(backup_dir_buf, MKP_DROP_NAME); /* drops trailing slash */
                 if (ret < 0)
                         exit_cleanup(RERR_SYNTAX);
                 if (ret)
                         rprintf(FINFO, "Created backup_dir %s\n", backup_dir_buf);
                 else if (INFO_GTE(BACKUP, 1))
                         rprintf(FINFO, "backup_dir is %s\n", backup_dir_buf);
         }
   
           io_flush(FULL_FLUSH);
   
         if ((pid = do_fork()) == -1) {          if ((pid = do_fork()) == -1) {
                 rsyserr(FERROR, errno, "fork failed in do_recv");                  rsyserr(FERROR, errno, "fork failed in do_recv");
                 exit_cleanup(RERR_IPC);                  exit_cleanup(RERR_IPC);
Line 772  static int do_recv(int f_in, int f_out, char *local_na Line 869  static int do_recv(int f_in, int f_out, char *local_na
   
         if (pid == 0) {          if (pid == 0) {
                 am_receiver = 1;                  am_receiver = 1;
                   send_msgs_to_gen = am_server;
   
                 close(error_pipe[0]);                  close(error_pipe[0]);
   
                   /* We can't let two processes write to the socket at one time. */
                   io_end_multiplex_out(MPLX_SWITCHING);
                 if (f_in != f_out)                  if (f_in != f_out)
                         close(f_out);                          close(f_out);
                   sock_f_out = -1;
                   f_out = error_pipe[1];
   
                /* we can't let two processes write to the socket at one time */                bwlimit_writemax = 0; /* receiver doesn't need to do this */
                io_end_multiplex_out(); 
   
                /* set place to send errors */                if (read_batch)
                set_msg_fd_out(error_pipe[1]);                        io_start_buffering_in(f_in);
                io_start_buffering_out(error_pipe[1]);                io_start_multiplex_out(f_out);
   
                recv_files(f_in, local_name);                recv_files(f_in, f_out, local_name);
                 io_flush(FULL_FLUSH);                  io_flush(FULL_FLUSH);
                 handle_stats(f_in);                  handle_stats(f_in);
   
                send_msg(MSG_DONE, "", 1, 0);                if (output_needs_newline) {
                write_varlong(error_pipe[1], stats.total_read, 3);                        fputc('\n', stdout);
                         output_needs_newline = 0;
                 }
 
                 write_int(f_out, NDX_DONE);
                 send_msg(MSG_STATS, (char*)&stats.total_read, sizeof stats.total_read, 0);
                 io_flush(FULL_FLUSH);                  io_flush(FULL_FLUSH);
   
                 /* Handle any keep-alive packets from the post-processing work                  /* Handle any keep-alive packets from the post-processing work
                  * that the generator does. */                   * that the generator does. */
                 if (protocol_version >= 29) {                  if (protocol_version >= 29) {
                         int iflags, xlen;  
                         uchar fnamecmp_type;  
                         char xname[MAXPATHLEN];  
   
                         kluge_around_eof = -1;                          kluge_around_eof = -1;
   
                         /* This should only get stopped via a USR2 signal. */                          /* This should only get stopped via a USR2 signal. */
                        read_ndx_and_attrs(f_in, &iflags, &fnamecmp_type,                        read_final_goodbye(f_in, f_out);
                                           xname, &xlen); 
   
                         rprintf(FERROR, "Invalid packet at end of run [%s]\n",                          rprintf(FERROR, "Invalid packet at end of run [%s]\n",
                                 who_am_i());                                  who_am_i());
Line 818  static int do_recv(int f_in, int f_out, char *local_na Line 920  static int do_recv(int f_in, int f_out, char *local_na
         }          }
   
         am_generator = 1;          am_generator = 1;
           flist_receiving_enabled = True;
   
        io_end_multiplex_in();        io_end_multiplex_in(MPLX_SWITCHING);
         if (write_batch && !am_server)          if (write_batch && !am_server)
                 stop_write_batch();                  stop_write_batch();
   
         close(error_pipe[1]);          close(error_pipe[1]);
         if (f_in != f_out)          if (f_in != f_out)
                 close(f_in);                  close(f_in);
           sock_f_in = -1;
           f_in = error_pipe[0];
   
         io_start_buffering_out(f_out);          io_start_buffering_out(f_out);
           io_start_multiplex_in(f_in);
   
         set_msg_fd_in(error_pipe[0]);  
         io_start_buffering_in(error_pipe[0]);  
   
 #ifdef SUPPORT_HARD_LINKS  #ifdef SUPPORT_HARD_LINKS
         if (preserve_hard_links && inc_recurse) {          if (preserve_hard_links && inc_recurse) {
                 struct file_list *flist;                  struct file_list *flist;
Line 844  static int do_recv(int f_in, int f_out, char *local_na Line 947  static int do_recv(int f_in, int f_out, char *local_na
   
         handle_stats(-1);          handle_stats(-1);
         io_flush(FULL_FLUSH);          io_flush(FULL_FLUSH);
           shutting_down = True;
         if (protocol_version >= 24) {          if (protocol_version >= 24) {
                 /* send a final goodbye message */                  /* send a final goodbye message */
                 write_ndx(f_out, NDX_DONE);                  write_ndx(f_out, NDX_DONE);
         }          }
         io_flush(FULL_FLUSH);          io_flush(FULL_FLUSH);
   
         set_msg_fd_in(-1);  
         kill(pid, SIGUSR2);          kill(pid, SIGUSR2);
         wait_process_with_flush(pid, &exit_code);          wait_process_with_flush(pid, &exit_code);
         return exit_code;          return exit_code;
Line 861  static void do_server_recv(int f_in, int f_out, int ar Line 964  static void do_server_recv(int f_in, int f_out, int ar
         int exit_code;          int exit_code;
         struct file_list *flist;          struct file_list *flist;
         char *local_name = NULL;          char *local_name = NULL;
        int save_verbose = verbose;        int negated_levels;
   
        if (filesfrom_fd >= 0) {        if (filesfrom_fd >= 0 && !msgs2stderr && protocol_version < 31) {
                 /* We can't mix messages with files-from data on the socket,                  /* We can't mix messages with files-from data on the socket,
                 * so temporarily turn off verbose messages. */                 * so temporarily turn off info/debug messages. */
                verbose = 0;                negate_output_levels();
        }                negated_levels = 1;
         } else
                 negated_levels = 0;
   
        if (verbose > 2) {        if (DEBUG_GTE(RECV, 1))
                rprintf(FINFO, "server_recv(%d) starting pid=%ld\n",                rprintf(FINFO, "server_recv(%d) starting pid=%d\n", argc, (int)getpid());
                        argc, (long)getpid()); 
        } 
   
        if (am_daemon && lp_read_only(module_id)) {        if (am_daemon && read_only) {
                 rprintf(FERROR,"ERROR: module is read only\n");                  rprintf(FERROR,"ERROR: module is read only\n");
                 exit_cleanup(RERR_SYNTAX);                  exit_cleanup(RERR_SYNTAX);
                 return;                  return;
Line 892  static void do_server_recv(int f_in, int f_out, int ar Line 995  static void do_server_recv(int f_in, int f_out, int ar
         }          }
   
         if (protocol_version >= 30)          if (protocol_version >= 30)
                io_start_multiplex_in();                io_start_multiplex_in(f_in);
         else          else
                 io_start_buffering_in(f_in);                  io_start_buffering_in(f_in);
         recv_filter_list(f_in);          recv_filter_list(f_in);
Line 903  static void do_server_recv(int f_in, int f_out, int ar Line 1006  static void do_server_recv(int f_in, int f_out, int ar
                  * need the IO routines to automatically write out the names                   * need the IO routines to automatically write out the names
                  * onto our f_out socket as we read the file-list.  This                   * onto our f_out socket as we read the file-list.  This
                  * avoids both deadlock and extra delays/buffers. */                   * avoids both deadlock and extra delays/buffers. */
                io_set_filesfrom_fds(filesfrom_fd, f_out);                start_filesfrom_forwarding(filesfrom_fd);
                 filesfrom_fd = -1;                  filesfrom_fd = -1;
         }          }
   
Line 914  static void do_server_recv(int f_in, int f_out, int ar Line 1017  static void do_server_recv(int f_in, int f_out, int ar
         }          }
         if (inc_recurse && file_total == 1)          if (inc_recurse && file_total == 1)
                 recv_additional_file_list(f_in);                  recv_additional_file_list(f_in);
         verbose = save_verbose;  
   
           if (negated_levels)
                   negate_output_levels();
   
         if (argc > 0)          if (argc > 0)
                 local_name = get_local_name(flist,argv[0]);                  local_name = get_local_name(flist,argv[0]);
   
Line 932  static void do_server_recv(int f_in, int f_out, int ar Line 1037  static void do_server_recv(int f_in, int f_out, int ar
   
         if (daemon_filter_list.head) {          if (daemon_filter_list.head) {
                 char **dir_p;                  char **dir_p;
                struct filter_list_struct *elp = &daemon_filter_list;                filter_rule_list *elp = &daemon_filter_list;
   
                 for (dir_p = basis_dir; *dir_p; dir_p++) {                  for (dir_p = basis_dir; *dir_p; dir_p++) {
                         char *dir = *dir_p;                          char *dir = *dir_p;
Line 971  void start_server(int f_in, int f_out, int argc, char  Line 1076  void start_server(int f_in, int f_out, int argc, char 
         setup_protocol(f_out, f_in);          setup_protocol(f_out, f_in);
   
         if (protocol_version >= 23)          if (protocol_version >= 23)
                io_start_multiplex_out();                io_start_multiplex_out(f_out);
         if (am_daemon && io_timeout && protocol_version >= 31)
                 send_msg_int(MSG_IO_TIMEOUT, io_timeout);
   
         if (am_sender) {          if (am_sender) {
                 keep_dirlinks = 0; /* Must be disabled on the sender. */                  keep_dirlinks = 0; /* Must be disabled on the sender. */
                 if (need_messages_from_generator)                  if (need_messages_from_generator)
                        io_start_multiplex_in();                        io_start_multiplex_in(f_in);
                 else
                         io_start_buffering_in(f_in);
                 recv_filter_list(f_in);                  recv_filter_list(f_in);
                 do_server_sender(f_in, f_out, argc, argv);                  do_server_sender(f_in, f_out, argc, argv);
         } else          } else
Line 984  void start_server(int f_in, int f_out, int argc, char  Line 1093  void start_server(int f_in, int f_out, int argc, char 
         exit_cleanup(0);          exit_cleanup(0);
 }  }
   
/* This is called once the connection has been negotiated.  It is used
/* * for rsyncd, remote-shell, and local connections. */
 * This is called once the connection has been negotiated.  It is used 
 * for rsyncd, remote-shell, and local connections. 
 */ 
 int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])  int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
 {  {
         struct file_list *flist = NULL;          struct file_list *flist = NULL;
Line 1016  int client_run(int f_in, int f_out, pid_t pid, int arg Line 1122  int client_run(int f_in, int f_out, pid_t pid, int arg
   
         if (am_sender) {          if (am_sender) {
                 keep_dirlinks = 0; /* Must be disabled on the sender. */                  keep_dirlinks = 0; /* Must be disabled on the sender. */
   
                   if (always_checksum
                    && (log_format_has(stdout_format, 'C')
                     || log_format_has(logfile_format, 'C')))
                           sender_keeps_checksum = 1;
   
                 if (protocol_version >= 30)                  if (protocol_version >= 30)
                        io_start_multiplex_out();                        io_start_multiplex_out(f_out);
                 else                  else
                         io_start_buffering_out(f_out);                          io_start_buffering_out(f_out);
                if (!filesfrom_host)                if (protocol_version >= 31 || (!filesfrom_host && protocol_version >= 23))
                        set_msg_fd_in(f_in);                        io_start_multiplex_in(f_in);
                 else
                         io_start_buffering_in(f_in);
                 send_filter_list(f_out);                  send_filter_list(f_out);
                 if (filesfrom_host)                  if (filesfrom_host)
                         filesfrom_fd = f_in;                          filesfrom_fd = f_in;
Line 1029  int client_run(int f_in, int f_out, pid_t pid, int arg Line 1143  int client_run(int f_in, int f_out, pid_t pid, int arg
                 if (write_batch && !am_server)                  if (write_batch && !am_server)
                         start_write_batch(f_out);                          start_write_batch(f_out);
                 flist = send_file_list(f_out, argc, argv);                  flist = send_file_list(f_out, argc, argv);
                if (verbose > 3)                if (DEBUG_GTE(FLIST, 3))
                         rprintf(FINFO,"file list sent\n");                          rprintf(FINFO,"file list sent\n");
   
                if (protocol_version >= 23)                if (protocol_version < 31 && filesfrom_host && protocol_version >= 23)
                        io_start_multiplex_in();                        io_start_multiplex_in(f_in);
   
                 io_flush(NORMAL_FLUSH);                  io_flush(NORMAL_FLUSH);
                 send_files(f_in, f_out);                  send_files(f_in, f_out);
                 io_flush(FULL_FLUSH);                  io_flush(FULL_FLUSH);
                 handle_stats(-1);                  handle_stats(-1);
                 if (protocol_version >= 24)                  if (protocol_version >= 24)
                        read_final_goodbye(f_in);                        read_final_goodbye(f_in, f_out);
                 if (pid != -1) {                  if (pid != -1) {
                        if (verbose > 3)                        if (DEBUG_GTE(EXIT, 2))
                                 rprintf(FINFO,"client_run waiting on %d\n", (int) pid);                                  rprintf(FINFO,"client_run waiting on %d\n", (int) pid);
                         io_flush(FULL_FLUSH);                          io_flush(FULL_FLUSH);
                         wait_process_with_flush(pid, &exit_code);                          wait_process_with_flush(pid, &exit_code);
Line 1054  int client_run(int f_in, int f_out, pid_t pid, int arg Line 1168  int client_run(int f_in, int f_out, pid_t pid, int arg
   
         if (!read_batch) {          if (!read_batch) {
                 if (protocol_version >= 23)                  if (protocol_version >= 23)
                        io_start_multiplex_in();                        io_start_multiplex_in(f_in);
                 if (need_messages_from_generator)                  if (need_messages_from_generator)
                        io_start_multiplex_out();                        io_start_multiplex_out(f_out);
                 else
                         io_start_buffering_out(f_out);
         }          }
   
         send_filter_list(read_batch ? -1 : f_out);          send_filter_list(read_batch ? -1 : f_out);
   
         if (filesfrom_fd >= 0) {          if (filesfrom_fd >= 0) {
                io_set_filesfrom_fds(filesfrom_fd, f_out);                start_filesfrom_forwarding(filesfrom_fd);
                 filesfrom_fd = -1;                  filesfrom_fd = -1;
         }          }
   
Line 1084  int client_run(int f_in, int f_out, pid_t pid, int arg Line 1200  int client_run(int f_in, int f_out, pid_t pid, int arg
         }          }
   
         if (pid != -1) {          if (pid != -1) {
                if (verbose > 3)                if (DEBUG_GTE(RECV, 1))
                         rprintf(FINFO,"client_run2 waiting on %d\n", (int) pid);                          rprintf(FINFO,"client_run2 waiting on %d\n", (int) pid);
                 io_flush(FULL_FLUSH);                  io_flush(FULL_FLUSH);
                 wait_process_with_flush(pid, &exit_code);                  wait_process_with_flush(pid, &exit_code);
Line 1109  static int copy_argv(char *argv[]) Line 1225  static int copy_argv(char *argv[])
 }  }
   
   
/**/* Start a client for either type of remote connection.  Work out
 * Start a client for either type of remote connection.  Work out 
  * whether the arguments request a remote shell or rsyncd connection,   * whether the arguments request a remote shell or rsyncd connection,
  * and call the appropriate connection function, then run_client.   * and call the appropriate connection function, then run_client.
  *   *
  * Calls either start_socket_client (for sockets) or do_cmd and   * Calls either start_socket_client (for sockets) or do_cmd and
 * client_run (for ssh). * client_run (for ssh). */
 **/ 
 static int start_client(int argc, char *argv[])  static int start_client(int argc, char *argv[])
 {  {
         char *p, *shell_machine = NULL, *shell_user = NULL;          char *p, *shell_machine = NULL, *shell_user = NULL;
Line 1203  static int start_client(int argc, char *argv[]) Line 1317  static int start_client(int argc, char *argv[])
                 remote_argc = argc = 1;                  remote_argc = argc = 1;
         }          }
   
           if (!rsync_port && remote_argc && !**remote_argv) /* Turn an empty arg into a dot dir. */
                   *remote_argv = ".";
   
         if (am_sender) {          if (am_sender) {
                 char *dummy_host;                  char *dummy_host;
                 int dummy_port = rsync_port;                  int dummy_port = rsync_port;
Line 1238  static int start_client(int argc, char *argv[]) Line 1355  static int start_client(int argc, char *argv[])
                                         rprintf(FERROR, "All source args must use the same port number.\n");                                          rprintf(FERROR, "All source args must use the same port number.\n");
                                 exit_cleanup(RERR_SYNTAX);                                  exit_cleanup(RERR_SYNTAX);
                         }                          }
                           if (!rsync_port && !*arg) /* Turn an empty arg into a dot dir. */
                                   arg = ".";
                         remote_argv[i] = arg;                          remote_argv[i] = arg;
                 }                  }
         }          }
Line 1266  static int start_client(int argc, char *argv[]) Line 1385  static int start_client(int argc, char *argv[])
                 }                  }
         }          }
   
        if (verbose > 3) {        if (DEBUG_GTE(CMD, 2)) {
                 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",                  rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
                         NS(shell_cmd), NS(shell_machine), NS(shell_user),                          NS(shell_cmd), NS(shell_machine), NS(shell_user),
                        remote_argv ? NS(remote_argv[0]) : "");                        NS(remote_argv[0]));
         }          }
   
         pid = do_cmd(shell_cmd, shell_machine, shell_user, remote_argv, remote_argc,          pid = do_cmd(shell_cmd, shell_machine, shell_user, remote_argv, remote_argc,
Line 1372  const char *get_panic_action(void) Line 1491  const char *get_panic_action(void)
 static RETSIGTYPE rsync_panic_handler(UNUSED(int whatsig))  static RETSIGTYPE rsync_panic_handler(UNUSED(int whatsig))
 {  {
         char cmd_buf[300];          char cmd_buf[300];
        int ret;        int ret, pid_int = getpid();
   
        snprintf(cmd_buf, sizeof cmd_buf, get_panic_action(),        snprintf(cmd_buf, sizeof cmd_buf, get_panic_action(), pid_int, pid_int);
                 getpid(), getpid()); 
   
         /* Unless we failed to execute gdb, we allow the process to          /* Unless we failed to execute gdb, we allow the process to
          * continue.  I'm not sure if that's right. */           * continue.  I'm not sure if that's right. */
Line 1411  int main(int argc,char *argv[]) Line 1529  int main(int argc,char *argv[])
   
         starttime = time(NULL);          starttime = time(NULL);
         our_uid = MY_UID();          our_uid = MY_UID();
           our_gid = MY_GID();
         am_root = our_uid == 0;          am_root = our_uid == 0;
   
         memset(&stats, 0, sizeof(stats));          memset(&stats, 0, sizeof(stats));
Line 1420  int main(int argc,char *argv[]) Line 1539  int main(int argc,char *argv[])
                 exit_cleanup(RERR_SYNTAX);                  exit_cleanup(RERR_SYNTAX);
         }          }
   
        /* we set a 0 umask so that correct file permissions can be        /* Get the umask for use in permission calculations.  We no longer set
         * carried across */         * it to zero; that is ugly and pointless now that all the callers that
        orig_umask = umask(0);         * relied on it have been reeducated to work with default ACLs. */
         umask(orig_umask = umask(0));
   
 #if defined CONFIG_LOCALE && defined HAVE_SETLOCALE  #if defined CONFIG_LOCALE && defined HAVE_SETLOCALE
         setlocale(LC_CTYPE, "");          setlocale(LC_CTYPE, "");

Removed from v.1.1  
changed lines
  Added in v.1.1.1.2


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>