Tweaking the license text a bit more.
[rsync/rsync.git] / receiver.c
index 62d024c..9866648 100644 (file)
@@ -3,11 +3,11 @@
  *
  * Copyright (C) 1996-2000 Andrew Tridgell
  * Copyright (C) 1996 Paul Mackerras
- * 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"
 
 extern int verbose;
+extern int dry_run;
 extern int do_xfers;
 extern int am_server;
 extern int do_progress;
-extern int incremental;
+extern int inc_recurse;
 extern int log_before_transfer;
 extern int stdout_format_has_i;
 extern int logfile_format_has_i;
@@ -36,21 +36,25 @@ extern int write_batch;
 extern int batch_gen_fd;
 extern int protocol_version;
 extern int relative_paths;
+extern int preserve_hard_links;
 extern int preserve_perms;
+extern int preserve_xattrs;
 extern int basis_dir_cnt;
 extern int make_backups;
 extern int cleanup_got_literal;
+extern int remove_source_files;
 extern int append_mode;
 extern int sparse_files;
 extern int keep_partial;
 extern int checksum_seed;
 extern int inplace;
 extern int delay_updates;
+extern mode_t orig_umask;
 extern struct stats stats;
 extern char *tmpdir;
 extern char *partial_dir;
 extern char *basis_dir[];
-extern struct file_list *cur_flist, *first_flist;
+extern struct file_list *cur_flist, *first_flist, *dir_flist;
 extern struct filter_list_struct server_filter_list;
 
 static struct bitbag *delayed_bits = NULL;
@@ -121,13 +125,13 @@ int get_tmpname(char *fnametmp, char *fname)
 
 
 static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
-                       char *fname, int fd, OFF_T total_size)
+                       const char *fname, int fd, OFF_T total_size)
 {
-       static char file_sum1[MD4_SUM_LENGTH];
-       static char file_sum2[MD4_SUM_LENGTH];
+       static char file_sum1[MAX_DIGEST_LEN];
+       static char file_sum2[MAX_DIGEST_LEN];
        struct map_struct *mapbuf;
        struct sum_struct sum;
-       int32 len;
+       int32 len, sum_len;
        OFF_T offset = 0;
        OFF_T offset2;
        char *data;
@@ -255,15 +259,15 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
                exit_cleanup(RERR_FILEIO);
        }
 
-       sum_end(file_sum1);
+       sum_len = sum_end(file_sum1);
 
        if (mapbuf)
                unmap_file(mapbuf);
 
-       read_buf(f_in,file_sum2,MD4_SUM_LENGTH);
+       read_buf(f_in, file_sum2, sum_len);
        if (verbose > 2)
                rprintf(FINFO,"got file_sum\n");
-       if (fd != -1 && memcmp(file_sum1, file_sum2, MD4_SUM_LENGTH) != 0)
+       if (fd != -1 && memcmp(file_sum1, file_sum2, sum_len) != 0)
                return 0;
        return 1;
 }
@@ -316,10 +320,10 @@ static int get_next_gen_ndx(int fd, int next_gen_ndx, int desired_ndx)
                }
                next_gen_ndx = read_int(fd);
                if (next_gen_ndx == -1) {
-                       if (incremental)
-                               next_gen_ndx = first_flist->prev->count + first_flist->prev->ndx_start;
+                       if (inc_recurse)
+                               next_gen_ndx = first_flist->prev->used + first_flist->prev->ndx_start;
                        else
-                               next_gen_ndx = cur_flist->count;
+                               next_gen_ndx = cur_flist->used;
                }
        }
        return next_gen_ndx;
@@ -346,13 +350,17 @@ int recv_files(int f_in, char *local_name)
        int itemizing = am_server ? logfile_format_has_i : stdout_format_has_i;
        enum logcode log_code = log_before_transfer ? FLOG : FINFO;
        int max_phase = protocol_version >= 29 ? 2 : 1;
+       int dflt_perms = (ACCESSPERMS & ~orig_umask);
+#ifdef SUPPORT_ACLS
+       const char *parent_dirname = "";
+#endif
        int ndx, recv_ok;
 
        if (verbose > 2)
-               rprintf(FINFO, "recv_files(%d) starting\n", cur_flist->count);
+               rprintf(FINFO, "recv_files(%d) starting\n", cur_flist->used);
 
        if (delay_updates)
-               delayed_bits = bitbag_create(cur_flist->count + 1);
+               delayed_bits = bitbag_create(cur_flist->used + 1);
 
        updating_basis = inplace;
 
@@ -360,18 +368,18 @@ int recv_files(int f_in, char *local_name)
                cleanup_disable();
 
                /* This call also sets cur_flist. */
-               ndx = read_ndx_and_attrs(f_in, -1, &iflags,
-                                        &fnamecmp_type, xname, &xlen);
+               ndx = read_ndx_and_attrs(f_in, &iflags, &fnamecmp_type,
+                                        xname, &xlen);
                if (ndx == NDX_DONE) {
-                       if (incremental && first_flist) {
+                       if (inc_recurse && first_flist) {
                                flist_free(first_flist);
                                if (first_flist)
                                        continue;
                        }
                        if (read_batch && cur_flist) {
-                               int high = incremental
-                                   ? first_flist->prev->count + first_flist->prev->ndx_start
-                                   : cur_flist->count;
+                               int high = inc_recurse
+                                   ? first_flist->prev->used + first_flist->prev->ndx_start
+                                   : cur_flist->used;
                                get_next_gen_ndx(batch_gen_fd, next_gen_ndx, high);
                                next_gen_ndx = -1;
                        }
@@ -381,18 +389,30 @@ int recv_files(int f_in, char *local_name)
                                rprintf(FINFO, "recv_files phase=%d\n", phase);
                        if (phase == 2 && delay_updates)
                                handle_delayed_updates(local_name);
-                       send_msg(MSG_DONE, "", 0);
+                       send_msg(MSG_DONE, "", 0, 0);
                        continue;
                }
 
-               file = cur_flist->files[ndx - cur_flist->ndx_start];
+               if (ndx - cur_flist->ndx_start >= 0)
+                       file = cur_flist->files[ndx - cur_flist->ndx_start];
+               else
+                       file = dir_flist->files[cur_flist->parent_ndx];
                fname = local_name ? local_name : f_name(file, fbuf);
 
                if (verbose > 2)
                        rprintf(FINFO, "recv_files(%s)\n", fname);
 
+#ifdef SUPPORT_XATTRS
+               if (iflags & ITEM_REPORT_XATTR && !dry_run)
+                       recv_xattr_request(file, f_in);
+#endif
+
                if (!(iflags & ITEM_TRANSFER)) {
                        maybe_log_item(file, iflags, itemizing, xname);
+#ifdef SUPPORT_XATTRS
+                       if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && !dry_run)
+                               set_file_attrs(fname, file, NULL, fname, 0);
+#endif
                        continue;
                }
                if (phase == 2) {
@@ -453,6 +473,8 @@ int recv_files(int f_in, char *local_name)
                                        "(Skipping batched update for \"%s\")\n",
                                        fname);
                                discard_receive_data(f_in, F_LENGTH(file));
+                               if (inc_recurse)
+                                       send_msg_int(MSG_NO_SEND, ndx);
                                continue;
                        }
                        next_gen_ndx = -1;
@@ -536,6 +558,8 @@ int recv_files(int f_in, char *local_name)
                                full_fname(fnamecmp));
                        discard_receive_data(f_in, F_LENGTH(file));
                        close(fd1);
+                       if (inc_recurse)
+                               send_msg_int(MSG_NO_SEND, ndx);
                        continue;
                }
 
@@ -549,6 +573,8 @@ int recv_files(int f_in, char *local_name)
                                full_fname(fnamecmp));
                        discard_receive_data(f_in, F_LENGTH(file));
                        close(fd1);
+                       if (inc_recurse)
+                               send_msg_int(MSG_NO_SEND, ndx);
                        continue;
                }
 
@@ -561,7 +587,16 @@ int recv_files(int f_in, char *local_name)
                 * mode based on the local permissions and some heuristics. */
                if (!preserve_perms) {
                        int exists = fd1 != -1;
-                       file->mode = dest_mode(file->mode, st.st_mode, exists);
+#ifdef SUPPORT_ACLS
+                       const char *dn = file->dirname ? file->dirname : ".";
+                       if (parent_dirname != dn
+                        && strcmp(parent_dirname, dn) != 0) {
+                               dflt_perms = default_perms_for_dir(dn);
+                               parent_dirname = dn;
+                       }
+#endif
+                       file->mode = dest_mode(file->mode, st.st_mode,
+                                              dflt_perms, exists);
                }
 
                /* We now check to see if we are writing the file "inplace" */
@@ -573,6 +608,8 @@ int recv_files(int f_in, char *local_name)
                                discard_receive_data(f_in, F_LENGTH(file));
                                if (fd1 != -1)
                                        close(fd1);
+                               if (inc_recurse)
+                                       send_msg_int(MSG_NO_SEND, ndx);
                                continue;
                        }
                } else {
@@ -580,6 +617,8 @@ int recv_files(int f_in, char *local_name)
                                discard_receive_data(f_in, F_LENGTH(file));
                                if (fd1 != -1)
                                        close(fd1);
+                               if (inc_recurse)
+                                       send_msg_int(MSG_NO_SEND, ndx);
                                continue;
                        }
 
@@ -606,6 +645,8 @@ int recv_files(int f_in, char *local_name)
                                discard_receive_data(f_in, F_LENGTH(file));
                                if (fd1 != -1)
                                        close(fd1);
+                               if (inc_recurse)
+                                       send_msg_int(MSG_NO_SEND, ndx);
                                continue;
                        }
 
@@ -640,15 +681,15 @@ int recv_files(int f_in, char *local_name)
                                temp_copy_name = NULL;
                        else
                                temp_copy_name = partialptr;
-                       finish_transfer(fname, fnametmp, temp_copy_name,
-                                       file, recv_ok, 1);
+                       finish_transfer(fname, fnametmp, fnamecmp,
+                                       temp_copy_name, file, recv_ok, 1);
                        if (fnamecmp == partialptr) {
                                do_unlink(partialptr);
                                handle_partial_dir(partialptr, PDIR_DELETE);
                        }
                } else if (keep_partial && partialptr
                    && handle_partial_dir(partialptr, PDIR_CREATE)) {
-                       finish_transfer(partialptr, fnametmp, NULL,
+                       finish_transfer(partialptr, fnametmp, fnamecmp, NULL,
                                        file, recv_ok, !partial_dir);
                        if (delay_updates && recv_ok) {
                                bitbag_set_bit(delayed_bits, ndx);
@@ -662,7 +703,7 @@ int recv_files(int f_in, char *local_name)
                cleanup_disable();
 
                if (recv_ok > 0) {
-                       if (remove_source_files || incremental
+                       if (remove_source_files || inc_recurse
                         || (preserve_hard_links && F_IS_HLINKED(file)))
                                send_msg_int(MSG_SUCCESS, ndx);
                } else if (!recv_ok) {
@@ -689,7 +730,7 @@ int recv_files(int f_in, char *local_name)
                        if (!redoing) {
                                send_msg_int(MSG_REDO, ndx);
                                file->flags |= FLAG_FILE_SENT;
-                       } else if (incremental)
+                       } else if (inc_recurse)
                                send_msg_int(MSG_NO_SEND, ndx);
                }
        }