Unsnarl missing_below/dry_run logic.
[rsync/rsync.git] / flist.c
diff --git a/flist.c b/flist.c
index a87a378..8eaebd1 100644 (file)
--- a/flist.c
+++ b/flist.c
@@ -4,7 +4,7 @@
  * Copyright (C) 1996 Andrew Tridgell
  * Copyright (C) 1996 Paul Mackerras
  * Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
- * Copyright (C) 2002-2007 Wayne Davison
+ * Copyright (C) 2002-2008 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
@@ -232,10 +232,20 @@ int link_stat(const char *path, STRUCT_STAT *stp, int follow_dirlinks)
 #endif
 }
 
+static inline int is_daemon_excluded(const char *fname, int is_dir)
+{
+       if (server_filter_list.head
+        && check_filter(&server_filter_list, fname, is_dir) < 0) {
+               errno = ENOENT;
+               return 1;
+       }
+       return 0;
+}
+
 /* This function is used to check if a file should be included/excluded
  * from the list of files based on its name and type etc.  The value of
  * filter_level is set to either SERVER_FILTERS or ALL_FILTERS. */
-static int is_excluded(char *fname, int is_dir, int filter_level)
+static int is_excluded(const char *fname, int is_dir, int filter_level)
 {
 #if 0 /* This currently never happens, so avoid a useless compare. */
        if (filter_level == NO_FILTERS)
@@ -252,8 +262,7 @@ static int is_excluded(char *fname, int is_dir, int filter_level)
                                return 0;
                }
        }
-       if (server_filter_list.head
-           && check_filter(&server_filter_list, fname, is_dir) < 0)
+       if (is_daemon_excluded(fname, is_dir))
                return 1;
        if (filter_level != ALL_FILTERS)
                return 0;
@@ -819,9 +828,9 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
 #endif
 
 #ifdef SUPPORT_ACLS
-       /* We need one or two index int32s when we're preserving ACLs. */
-       if (preserve_acls)
-               extra_len += (S_ISDIR(mode) ? 2 : 1) * EXTRA_LEN;
+       /* Directories need an extra int32 for the default ACL. */
+       if (preserve_acls && S_ISDIR(mode))
+               extra_len += EXTRA_LEN;
 #endif
 
        if (always_checksum && S_ISREG(mode))
@@ -854,7 +863,6 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
        bp += FILE_STRUCT_LEN;
 
        memcpy(bp, basename, basename_len);
-       bp += basename_len + linkname_len; /* skip space for symlink too */
 
 #ifdef SUPPORT_HARD_LINKS
        if (xflags & XMIT_HLINKED)
@@ -919,7 +927,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
 
 #ifdef SUPPORT_LINKS
        if (linkname_len) {
-               bp = (char*)file->basename + basename_len;
+               bp += basename_len;
                if (first_hlink_ndx >= flist->ndx_start) {
                        struct file_struct *first = flist->files[first_hlink_ndx - flist->ndx_start];
                        memcpy(bp, F_SYMLINK(first), linkname_len);
@@ -1123,8 +1131,14 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
                        pool = dir_flist->file_pool;
                } else
                        pool = flist->file_pool;
-       } else
+       } else {
+#ifdef SUPPORT_ACLS
+               /* Directories need an extra int32 for the default ACL. */
+               if (preserve_acls && S_ISDIR(st.st_mode))
+                       extra_len += EXTRA_LEN;
+#endif
                pool = NULL;
+       }
 
        if (verbose > 2) {
                rprintf(FINFO, "[%s] make_file(%s,*,%d)\n",
@@ -1172,7 +1186,6 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
        bp += FILE_STRUCT_LEN;
 
        memcpy(bp, basename, basename_len);
-       bp += basename_len + linkname_len; /* skip space for symlink too */
 
 #ifdef SUPPORT_HARD_LINKS
        if (preserve_hard_links && flist && flist->prev) {
@@ -1210,16 +1223,17 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
                file->dirname = lastdir;
 
 #ifdef SUPPORT_LINKS
-       if (linkname_len) {
-               bp = (char*)file->basename + basename_len;
-               memcpy(bp, linkname, linkname_len);
-       }
+       if (linkname_len)
+               memcpy(bp + basename_len, linkname, linkname_len);
 #endif
 
        if (always_checksum && am_sender && S_ISREG(st.st_mode))
                file_checksum(thisname, tmp_sum, st.st_size);
 
-       F_PATHNAME(file) = pathname;
+       if (am_sender)
+               F_PATHNAME(file) = pathname;
+       else if (!pool)
+               F_DEPTH(file) = extra_len / EXTRA_LEN;
 
        /* This code is only used by the receiver when it is building
         * a list of files for a delete pass. */
@@ -1255,12 +1269,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
 /* Only called for temporary file_struct entries created by make_file(). */
 void unmake_file(struct file_struct *file)
 {
-       int extra_cnt = file_extra_cnt + LEN64_BUMP(file);
-#if EXTRA_ROUNDING > 0
-       if (extra_cnt & EXTRA_ROUNDING)
-               extra_cnt = (extra_cnt | EXTRA_ROUNDING) + 1;
-#endif
-       free(REQ_EXTRA(file, extra_cnt));
+       free(REQ_EXTRA(file, F_DEPTH(file)));
 }
 
 static struct file_struct *send_file_name(int f, struct file_list *flist,
@@ -1939,7 +1948,8 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
                if (fn != fbuf)
                        memmove(fbuf, fn, len + 1);
 
-               if (link_stat(fbuf, &st, copy_dirlinks || name_type != NORMAL_NAME) != 0) {
+               if (link_stat(fbuf, &st, copy_dirlinks || name_type != NORMAL_NAME) != 0
+                || is_daemon_excluded(fbuf, S_ISDIR(st.st_mode) != 0)) {
                        io_error |= IOERR_GENERAL;
                        rsyserr(FERROR_XFER, errno, "link_stat %s failed",
                                full_fname(fbuf));