Fix --delete-missing-args when --relative is active.
[rsync.git] / flist.c
diff --git a/flist.c b/flist.c
index 4a5058399abbaa0c3115ff9ce9ee4e2aa1e4fa34..6ec3c39cffe1af0e6c381c218e86e3b042d85be6 100644 (file)
--- a/flist.c
+++ b/flist.c
@@ -52,12 +52,9 @@ extern int preserve_devices;
 extern int preserve_specials;
 extern int delete_during;
 extern int missing_args;
-extern int uid_ndx;
-extern int gid_ndx;
 extern int eol_nulls;
 extern int relative_paths;
 extern int implied_dirs;
-extern int file_extra_cnt;
 extern int ignore_perishable;
 extern int non_perishable_cnt;
 extern int prune_empty_dirs;
@@ -72,6 +69,7 @@ extern int sender_symlink_iconv;
 extern int output_needs_newline;
 extern int sender_keeps_checksum;
 extern int unsort_ndx;
+extern uid_t our_uid;
 extern struct stats stats;
 extern char *filesfrom_host;
 extern char *usermap, *groupmap;
@@ -88,14 +86,6 @@ extern int filesfrom_convert;
 extern iconv_t ic_send, ic_recv;
 #endif
 
-#ifdef HAVE_UTIMENSAT
-#ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
-#define ST_MTIME_NSEC st_mtim.tv_nsec
-#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
-#define ST_MTIME_NSEC st_mtimensec
-#endif
-#endif
-
 #define PTR_SIZE (sizeof (struct file_struct *))
 
 int io_error;
@@ -112,6 +102,7 @@ int flist_eof = 0; /* all the file-lists are now known */
 #define NORMAL_NAME 0
 #define SLASH_ENDING_NAME 1
 #define DOTDIR_NAME 2
+#define MISSING_NAME 3
 
 /* Starting from protocol version 26, we always use 64-bit ino_t and dev_t
  * internally, even if this platform does not allow files to have 64-bit inums.
@@ -1374,10 +1365,12 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
        }
 #endif
        file->mode = st.st_mode;
-       if (uid_ndx) /* Check uid_ndx instead of preserve_uid for del support */
+       if (preserve_uid)
                F_OWNER(file) = st.st_uid;
-       if (gid_ndx) /* Check gid_ndx instead of preserve_gid for del support */
+       if (preserve_gid)
                F_GROUP(file) = st.st_gid;
+       if (am_generator && st.st_uid == our_uid)
+               file->flags |= FLAG_OWNED_BY_US;
 
        if (basename != thisname)
                file->dirname = lastdir;
@@ -1734,11 +1727,12 @@ static void send_directory(int f, struct file_list *flist, char *fbuf, int len,
                remainder = 0;
 
        for (errno = 0, di = readdir(d); di; errno = 0, di = readdir(d)) {
+               unsigned name_len;
                char *dname = d_name(di);
                if (dname[0] == '.' && (dname[1] == '\0'
                    || (dname[1] == '.' && dname[2] == '\0')))
                        continue;
-               unsigned name_len = strlcpy(p, dname, remainder);
+               name_len = strlcpy(p, dname, remainder);
                if (name_len >= remainder) {
                        char save = fbuf[len];
                        fbuf[len] = '\0';
@@ -1940,7 +1934,9 @@ static void send1extra(int f, struct file_struct *file, struct file_list *flist)
 
                if (name_type != NORMAL_NAME) {
                        STRUCT_STAT st;
-                       if (link_stat(fbuf, &st, 1) != 0) {
+                       if (name_type == MISSING_NAME)
+                               memset(&st, 0, sizeof st);
+                       else if (link_stat(fbuf, &st, 1) != 0) {
                                interpret_stat_error(fbuf, True);
                                continue;
                        }
@@ -2197,12 +2193,8 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
                                fn = fbuf;
                        /* A leading ./ can be used in relative mode to affect
                         * the dest dir without its name being in the path. */
-                       if (*fn == '.' && fn[1] == '/' && !implied_dot_dir) {
-                               send_file_name(f, flist, ".", NULL,
-                                   (flags | FLAG_IMPLIED_DIR) & ~FLAG_CONTENT_DIR,
-                                   ALL_FILTERS);
-                               implied_dot_dir = 1;
-                       }
+                       if (*fn == '.' && fn[1] == '/' && fn[2] && !implied_dot_dir)
+                               implied_dot_dir = -1;
                        len = clean_fname(fn, CFN_KEEP_TRAILING_SLASH
                                            | CFN_DROP_TRAILING_DOT_DIR);
                        if (len == 1) {
@@ -2240,11 +2232,20 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
                dirlen = dir ? strlen(dir) : 0;
                if (dirlen != lastdir_len || memcmp(lastdir, dir, dirlen) != 0) {
                        if (!change_pathname(NULL, dir, -dirlen))
-                               continue;
+                               goto bad_path;
                        lastdir = pathname;
                        lastdir_len = pathname_len;
-               } else if (!change_pathname(NULL, lastdir, lastdir_len))
+               } else if (!change_pathname(NULL, lastdir, lastdir_len)) {
+                   bad_path:
+                       if (implied_dot_dir < 0)
+                               implied_dot_dir = 0;
                        continue;
+               }
+
+               if (implied_dot_dir < 0) {
+                       implied_dot_dir = 1;
+                       send_file_name(f, flist, ".", NULL, (flags | FLAG_IMPLIED_DIR) & ~FLAG_CONTENT_DIR, ALL_FILTERS);
+               }
 
                if (fn != fbuf)
                        memmove(fbuf, fn, len + 1);
@@ -2287,7 +2288,8 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
                                                p = fn;
                                } else
                                        fn = p;
-                               send_implied_dirs(f, flist, fbuf, fbuf, p, flags, name_type);
+                               send_implied_dirs(f, flist, fbuf, fbuf, p, flags,
+                                                 st.st_mode == 0 ? MISSING_NAME : name_type);
                                if (fn == p)
                                        continue;
                        }
@@ -3177,13 +3179,14 @@ char *f_name(const struct file_struct *f, char *fbuf)
  * of the dirname string, and also indicates that "dirname" is a MAXPATHLEN
  * buffer (the functions we call will append names onto the end, but the old
  * dir value will be restored on exit). */
-struct file_list *get_dirlist(char *dirname, int dlen, int ignore_filter_rules)
+struct file_list *get_dirlist(char *dirname, int dlen, int flags)
 {
        struct file_list *dirlist;
        char dirbuf[MAXPATHLEN];
        int save_recurse = recurse;
        int save_xfer_dirs = xfer_dirs;
        int save_prune_empty_dirs = prune_empty_dirs;
+       int senddir_fd = flags & GDL_IGNORE_FILTER_RULES ? -2 : -1;
 
        if (dlen < 0) {
                dlen = strlcpy(dirbuf, dirname, MAXPATHLEN);
@@ -3196,7 +3199,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, FLAG_CONTENT_DIR);
+       send_directory(senddir_fd, dirlist, dirname, dlen, FLAG_CONTENT_DIR);
        xfer_dirs = save_xfer_dirs;
        recurse = save_recurse;
        if (INFO_GTE(PROGRESS, 1))