Added get_xattr_acl(), set_xattr_acl(), and del_def_xattr_acl().
[rsync/rsync.git] / flist.c
diff --git a/flist.c b/flist.c
index a51413a..60ce2ba 100644 (file)
--- a/flist.c
+++ b/flist.c
@@ -1041,26 +1041,26 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
                        rprintf(FINFO, "skipping directory %s\n", thisname);
                        return NULL;
                }
-       } else
-               flags &= ~FLAG_XFER_DIR;
-
-       /* -x only affects directories because we need to avoid recursing
-        * into a mount-point directory, not to avoid copying a symlinked
-        * file if -L (or similar) was specified. */
-       if (one_file_system && S_ISDIR(st.st_mode)) {
-               if (flags & FLAG_TOP_DIR)
-                       filesystem_dev = st.st_dev;
-               else if (st.st_dev != filesystem_dev) {
-                       if (one_file_system > 1) {
-                               if (verbose > 2) {
-                                       rprintf(FINFO, "skipping mount-point dir %s\n",
-                                               thisname);
+               /* -x only affects dirs because we need to avoid recursing
+                * into a mount-point directory, not to avoid copying a
+                * symlinked file if -L (or similar) was specified. */
+               if (one_file_system && flags & FLAG_XFER_DIR) {
+                       if (flags & FLAG_TOP_DIR)
+                               filesystem_dev = st.st_dev;
+                       else if (st.st_dev != filesystem_dev) {
+                               if (one_file_system > 1) {
+                                       if (verbose > 1) {
+                                               rprintf(FINFO,
+                                                   "[%s] skipping mount-point dir %s\n",
+                                                   who_am_i(), thisname);
+                                       }
+                                       return NULL;
                                }
-                               return NULL;
+                               flags |= FLAG_MOUNT_DIR;
                        }
-                       flags |= FLAG_MOUNT_DIR;
                }
-       }
+       } else
+               flags &= ~FLAG_XFER_DIR;
 
        if (is_excluded(thisname, S_ISDIR(st.st_mode) != 0, filter_level)) {
                if (ignore_perishable)
@@ -1235,7 +1235,7 @@ static struct file_struct *send_file_name(int f, struct file_list *flist,
 {
        struct file_struct *file;
 #if defined SUPPORT_ACLS || defined SUPPORT_XATTRS
-       statx sx;
+       stat_x sx;
 #endif
 
        file = make_file(fname, flist, stp, flags, filter_level);
@@ -1399,9 +1399,6 @@ static void add_dirs_to_tree(int parent_ndx, struct file_list *from_flist,
                dir_flist->files[dir_flist->used++] = file;
                dir_cnt--;
 
-               if (file->flags & FLAG_MOUNT_DIR)
-                       continue;
-
                if (dp)
                        DIR_NEXT_SIBLING(dp) = dir_flist->used - 1;
                else if (parent_dp)
@@ -1579,7 +1576,7 @@ static void send1extra(int f, struct file_struct *file, struct file_list *flist)
 
        change_local_filter_dir(fbuf, dlen, send_dir_depth);
 
-       if (file->flags & FLAG_XFER_DIR)
+       if (BITS_SETnUNSET(file->flags, FLAG_XFER_DIR, FLAG_MOUNT_DIR))
                send_directory(f, flist, fbuf, dlen, flags);
 
        if (!relative_paths)
@@ -1608,7 +1605,7 @@ static void send1extra(int f, struct file_struct *file, struct file_list *flist)
 
                if (is_dot_dir) {
                        STRUCT_STAT st;
-                       if (link_stat(fbuf, &st, copy_dirlinks) != 0) {
+                       if (link_stat(fbuf, &st, 1) != 0) {
                                io_error |= IOERR_GENERAL;
                                rsyserr(FERROR, errno, "link_stat %s failed",
                                        full_fname(fbuf));
@@ -1631,6 +1628,7 @@ void send_extra_file_list(int f, int at_least)
 {
        struct file_list *flist;
        int64 start_write;
+       uint16 prev_flags;
        int future_cnt, save_io_error = io_error;
 
        if (flist_eof)
@@ -1662,6 +1660,7 @@ void send_extra_file_list(int f, int at_least)
                flist->parent_ndx = dir_ndx;
 
                send1extra(f, file, flist);
+               prev_flags = file->flags;
                dp = F_DIR_NODE_P(file);
 
                /* If there are any duplicate directory names that follow, we
@@ -1671,8 +1670,11 @@ void send_extra_file_list(int f, int at_least)
                    && dir_flist->sorted[dir_ndx]->flags & FLAG_DUPLICATE) {
                        send_dir_ndx = dir_ndx;
                        file = dir_flist->sorted[dir_ndx];
-                       if (F_PATHNAME(file) != pathname)
-                               send1extra(f, file, flist);
+                       /* Try to avoid some duplicate scanning of identical dirs. */
+                       if (F_PATHNAME(file) == pathname && prev_flags & FLAG_XFER_DIR)
+                               file->flags &= ~FLAG_XFER_DIR;
+                       send1extra(f, file, flist);
+                       prev_flags = file->flags;
                        dp = F_DIR_NODE_P(file);
                }
 
@@ -1900,7 +1902,7 @@ 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) != 0) {
+               if (link_stat(fbuf, &st, copy_dirlinks || is_dot_dir) != 0) {
                        io_error |= IOERR_GENERAL;
                        rsyserr(FERROR, errno, "link_stat %s failed",
                                full_fname(fbuf));
@@ -2387,6 +2389,8 @@ static void clean_flist(struct file_list *flist, int strip_root)
                                else {
                                        if (am_sender)
                                                file->flags |= FLAG_DUPLICATE;
+                                       else    /* Make sure we don't lose vital flags. */
+                                               fp->flags |= file->flags & (FLAG_TOP_DIR|FLAG_XFER_DIR);
                                        keep = j, drop = i;
                                }
                        } else
@@ -2398,11 +2402,6 @@ static void clean_flist(struct file_list *flist, int strip_root)
                                            "removing duplicate name %s from file list (%d)\n",
                                            f_name(file, fbuf), drop + flist->ndx_start);
                                }
-                               /* Make sure we don't lose track of a user-specified
-                                * top directory. */
-                               flist->sorted[keep]->flags |= flist->sorted[drop]->flags
-                                                          & (FLAG_TOP_DIR|FLAG_XFER_DIR);
-
                                clear_file(flist->sorted[drop]);
                        }