Add conditional support for excluding types of files from xattr ops.
[rsync/rsync.git] / flist.c
diff --git a/flist.c b/flist.c
index 09b4fc5..7208efa 100644 (file)
--- a/flist.c
+++ b/flist.c
@@ -79,8 +79,8 @@ extern char curr_dir[MAXPATHLEN];
 
 extern struct chmod_mode_struct *chmod_modes;
 
-extern struct filter_list_struct filter_list;
-extern struct filter_list_struct daemon_filter_list;
+extern filter_rule_list filter_list;
+extern filter_rule_list daemon_filter_list;
 
 #ifdef ICONV_OPTION
 extern int filesfrom_convert;
@@ -442,8 +442,7 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
        else
                mode = file->mode;
 
-       if ((preserve_devices && IS_DEVICE(mode))
-        || (preserve_specials && IS_SPECIAL(mode))) {
+       if (preserve_devices && IS_DEVICE(mode)) {
                if (protocol_version < 28) {
                        if (tmp_rdev == rdev)
                                xflags |= XMIT_SAME_RDEV_pre28;
@@ -458,6 +457,17 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
                        if (protocol_version < 30 && (uint32)minor(rdev) <= 0xFFu)
                                xflags |= XMIT_RDEV_MINOR_8_pre30;
                }
+       } else if (preserve_specials && IS_SPECIAL(mode) && protocol_version < 31) {
+               /* Special files don't need an rdev number, so just make
+                * the historical transmission of the value efficient. */
+               if (protocol_version < 28)
+                       xflags |= XMIT_SAME_RDEV_pre28;
+               else {
+                       rdev = MAKEDEV(major(rdev), 0);
+                       xflags |= XMIT_SAME_RDEV_MAJOR;
+                       if (protocol_version < 30)
+                               xflags |= XMIT_RDEV_MINOR_8_pre30;
+               }
        } else if (protocol_version < 28)
                rdev = MAKEDEV(0, 0);
        if (!preserve_uid || ((uid_t)F_OWNER(file) == uid && *lastname))
@@ -593,7 +603,7 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
                }
        }
        if ((preserve_devices && IS_DEVICE(mode))
-        || (preserve_specials && IS_SPECIAL(mode))) {
+        || (preserve_specials && IS_SPECIAL(mode) && protocol_version < 31)) {
                if (protocol_version < 28) {
                        if (!(xflags & XMIT_SAME_RDEV_pre28))
                                write_int(f, (int)rdev);
@@ -762,8 +772,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
                                uid = F_OWNER(first);
                        if (preserve_gid)
                                gid = F_GROUP(first);
-                       if ((preserve_devices && IS_DEVICE(mode))
-                        || (preserve_specials && IS_SPECIAL(mode))) {
+                       if (preserve_devices && IS_DEVICE(mode)) {
                                uint32 *devp = F_RDEV_P(first);
                                rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp));
                                extra_len += DEV_EXTRA_CNT * EXTRA_LEN;
@@ -822,7 +831,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
        }
 
        if ((preserve_devices && IS_DEVICE(mode))
-        || (preserve_specials && IS_SPECIAL(mode))) {
+        || (preserve_specials && IS_SPECIAL(mode) && protocol_version < 31)) {
                if (protocol_version < 28) {
                        if (!(xflags & XMIT_SAME_RDEV_pre28))
                                rdev = (dev_t)read_int(f);
@@ -838,7 +847,8 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
                                rdev_minor = read_int(f);
                        rdev = MAKEDEV(rdev_major, rdev_minor);
                }
-               extra_len += DEV_EXTRA_CNT * EXTRA_LEN;
+               if (IS_DEVICE(mode))
+                       extra_len += DEV_EXTRA_CNT * EXTRA_LEN;
                file_length = 0;
        } else if (protocol_version < 28)
                rdev = MAKEDEV(0, 0);
@@ -979,8 +989,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
                }
        }
 
-       if ((preserve_devices && IS_DEVICE(mode))
-        || (preserve_specials && IS_SPECIAL(mode))) {
+       if (preserve_devices && IS_DEVICE(mode)) {
                uint32 *devp = F_RDEV_P(file);
                DEV_MAJOR(devp) = major(rdev);
                DEV_MINOR(devp) = minor(rdev);
@@ -1307,10 +1316,11 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
 #endif
 
 #ifdef HAVE_STRUCT_STAT_ST_RDEV
-       if (IS_DEVICE(st.st_mode) || IS_SPECIAL(st.st_mode)) {
+       if (IS_DEVICE(st.st_mode)) {
                tmp_rdev = st.st_rdev;
                st.st_size = 0;
-       }
+       } else if (IS_SPECIAL(st.st_mode))
+               st.st_size = 0;
 #endif
 
        file->flags = flags;
@@ -1466,6 +1476,7 @@ static struct file_struct *send_file_name(int f, struct file_list *flist,
 #endif
 #ifdef SUPPORT_XATTRS
                if (preserve_xattrs) {
+                       sx.st.st_mode = file->mode;
                        if (get_xattr(fname, &sx) < 0) {
                                io_error |= IOERR_GENERAL;
                                return NULL;
@@ -1733,7 +1744,7 @@ static void send_implied_dirs(int f, struct file_list *flist, char *fname,
        item_list *relname_list;
        relnamecache **rnpp;
        int len, need_new_dir, depth = 0;
-       struct filter_list_struct save_filter_list = filter_list;
+       filter_rule_list save_filter_list = filter_list;
 
        flags = (flags | FLAG_IMPLIED_DIR) & ~(FLAG_TOP_DIR | FLAG_CONTENT_DIR);
        filter_list.head = filter_list.tail = NULL; /* Don't filter implied dirs. */
@@ -3106,7 +3117,7 @@ struct file_list *get_dirlist(char *dirname, int dlen, int ignore_filter_rules)
 
        recurse = 0;
        xfer_dirs = 1;
-       send_directory(ignore_filter_rules ? -2 : -1, dirlist, dirname, dlen, 0);
+       send_directory(ignore_filter_rules ? -2 : -1, dirlist, dirname, dlen, FLAG_CONTENT_DIR);
        xfer_dirs = save_xfer_dirs;
        recurse = save_recurse;
        if (INFO_GTE(PROGRESS, 1))