Some "use chroot" improvements.
[rsync.git] / sender.c
index abd79bd2d6d5feb499c666516e34acb4e30950ff..3d4f052e9bdbeaf7e41a39315907bddcbe69ed15 100644 (file)
--- a/sender.c
+++ b/sender.c
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1996 Andrew Tridgell
  * Copyright (C) 1996 Paul Mackerras
- * Copyright (C) 2003-2020 Wayne Davison
+ * Copyright (C) 2003-2022 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
@@ -25,6 +25,7 @@
 extern int do_xfers;
 extern int am_server;
 extern int am_daemon;
+extern int local_server;
 extern int inc_recurse;
 extern int log_before_transfer;
 extern int stdout_format_has_i;
@@ -35,7 +36,9 @@ extern int append_mode;
 extern int copy_links;
 extern int io_error;
 extern int flist_eof;
+extern int whole_file;
 extern int allowed_lull;
+extern int copy_devices;
 extern int preserve_xattrs;
 extern int protocol_version;
 extern int remove_source_files;
@@ -49,6 +52,7 @@ extern int file_old_total;
 extern BOOL want_progress_now;
 extern struct stats stats;
 extern struct file_list *cur_flist, *first_flist, *dir_flist;
+extern char num_dev_ino_buf[4 + 8 + 8];
 
 BOOL extra_flist_sending_enabled;
 
@@ -65,13 +69,10 @@ BOOL extra_flist_sending_enabled;
  **/
 static struct sum_struct *receive_sums(int f)
 {
-       struct sum_struct *s;
-       int32 i;
+       struct sum_struct *s = new(struct sum_struct);
        int lull_mod = protocol_version >= 31 ? 0 : allowed_lull * 5;
        OFF_T offset = 0;
-
-       if (!(s = new(struct sum_struct)))
-               out_of_memory("receive_sums");
+       int32 i;
 
        read_sum_head(f, s);
 
@@ -92,8 +93,7 @@ static struct sum_struct *receive_sums(int f)
        if (s->count == 0)
                return(s);
 
-       if (!(s->sums = new_array(struct sum_buf, s->count)))
-               out_of_memory("receive_sums");
+       s->sums = new_array(struct sum_buf, s->count);
 
        for (i = 0; i < s->count; i++) {
                s->sums[i].sum1 = read_int(f);
@@ -146,6 +146,13 @@ void successful_send(int ndx)
                goto failed;
        }
 
+       if (local_server
+        && (int64)st.st_dev == IVAL64(num_dev_ino_buf, 4)
+        && (int64)st.st_ino == IVAL64(num_dev_ino_buf, 4 + 8)) {
+               rprintf(FERROR_XFER, "ERROR: Skipping sender remove of destination file: %s\n", fname);
+               return;
+       }
+
        if (st.st_size != F_LENGTH(file) || st.st_mtime != file->modtime
 #ifdef ST_MTIME_NSEC
         || (NSEC_BUMP(file) && (uint32)st.ST_MTIME_NSEC != F_MOD_NSEC(file))
@@ -208,6 +215,9 @@ void send_files(int f_in, int f_out)
        if (DEBUG_GTE(SEND, 1))
                rprintf(FINFO, "send_files starting\n");
 
+       if (whole_file < 0)
+               whole_file = 0;
+
        progress_init();
 
        while (1) {
@@ -366,6 +376,25 @@ void send_files(int f_in, int f_out)
                        exit_cleanup(RERR_FILEIO);
                }
 
+               if (IS_DEVICE(st.st_mode)) {
+                       if (!copy_devices) {
+                               rprintf(FERROR, "attempt to copy device contents without --copy-devices\n");
+                               exit_cleanup(RERR_PROTOCOL);
+                       }
+                       if (st.st_size == 0)
+                               st.st_size = get_device_size(fd, fname);
+               }
+
+               if (append_mode > 0 && st.st_size < F_LENGTH(file)) {
+                       rprintf(FWARNING, "skipped diminished file: %s\n",
+                               full_fname(fname));
+                       free_sums(s);
+                       close(fd);
+                       if (protocol_version >= 30)
+                               send_msg_int(MSG_NO_SEND, ndx);
+                       continue;
+               }
+
                if (st.st_size) {
                        int32 read_size = MAX(s->blength * 3, MAX_MAP_SIZE);
                        mbuf = map_file(fd, st.st_size, read_size, s->blength);