Changed "statx" to "stat_x" to try to work around a build problem on AIX.
[rsync/rsync.git] / generator.c
index 3e21d82..e6e5003 100644 (file)
@@ -515,7 +515,7 @@ static void do_delete_pass(void)
                rprintf(FINFO, "                    \r");
 }
 
-int unchanged_attrs(const char *fname, struct file_struct *file, statx *sxp)
+int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp)
 {
        if (preserve_perms && !BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS))
                return 0;
@@ -547,7 +547,7 @@ int unchanged_attrs(const char *fname, struct file_struct *file, statx *sxp)
 }
 
 void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statret,
-            statx *sxp, int32 iflags, uchar fnamecmp_type,
+            stat_x *sxp, int32 iflags, uchar fnamecmp_type,
             const char *xname)
 {
        if (statret >= 0) { /* A from-dest-dir statret can == 1! */
@@ -829,7 +829,7 @@ static int find_fuzzy(struct file_struct *file, struct file_list *dirlist)
  * handling the file, -1 if no dest-linking occurred, or a non-negative
  * value if we found an alternate basis file. */
 static int try_dests_reg(struct file_struct *file, char *fname, int ndx,
-                        char *cmpbuf, statx *sxp, int itemizing,
+                        char *cmpbuf, stat_x *sxp, int itemizing,
                         enum logcode code)
 {
        int best_match = -1;
@@ -899,7 +899,7 @@ static int try_dests_reg(struct file_struct *file, char *fname, int ndx,
 #ifdef SUPPORT_HARD_LINKS
          try_a_copy: /* Copy the file locally. */
 #endif
-               if (copy_file(cmpbuf, fname, file->mode) < 0) {
+               if (copy_file(cmpbuf, fname, file->mode, 0) < 0) {
                        if (verbose) {
                                rsyserr(FINFO, errno, "copy_file %s => %s",
                                        full_fname(cmpbuf), fname);
@@ -934,7 +934,7 @@ static int try_dests_reg(struct file_struct *file, char *fname, int ndx,
  * handling the file, or -1 if no dest-linking occurred, or a non-negative
  * value if we found an alternate basis file. */
 static int try_dests_non(struct file_struct *file, char *fname, int ndx,
-                        char *cmpbuf, statx *sxp, int itemizing,
+                        char *cmpbuf, stat_x *sxp, int itemizing,
                         enum logcode code)
 {
        char lnk[MAXPATHLEN];
@@ -1072,6 +1072,35 @@ static int try_dests_non(struct file_struct *file, char *fname, int ndx,
        return j;
 }
 
+static void list_file_entry(struct file_struct *f)
+{
+       char permbuf[PERMSTRING_SIZE];
+       double len;
+
+       if (!F_IS_ACTIVE(f)) {
+               /* this can happen if duplicate names were removed */
+               return;
+       }
+
+       permstring(permbuf, f->mode);
+       len = F_LENGTH(f);
+
+       /* TODO: indicate '+' if the entry has an ACL. */
+
+#ifdef SUPPORT_LINKS
+       if (preserve_links && S_ISLNK(f->mode)) {
+               rprintf(FINFO, "%s %11.0f %s %s -> %s\n",
+                       permbuf, len, timestring(f->modtime),
+                       f_name(f, NULL), F_SYMLINK(f));
+       } else
+#endif
+       {
+               rprintf(FINFO, "%s %11.0f %s %s\n",
+                       permbuf, len, timestring(f->modtime),
+                       f_name(f, NULL));
+       }
+}
+
 static int phase = 0;
 static int dflt_perms;
 
@@ -1095,7 +1124,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
        static int need_fuzzy_dirlist = 0;
        struct file_struct *fuzzy_file = NULL;
        int fd = -1, f_copy = -1;
-       statx sx, real_sx;
+       stat_x sx, real_sx;
        STRUCT_STAT partial_st;
        struct file_struct *back_file = NULL;
        int statret, real_ret, stat_errno;
@@ -1105,12 +1134,18 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
        int implied_dirs_are_missing = relative_paths && !implied_dirs && !inc_recurse;
        int del_opts = delete_mode || force_delete ? DEL_RECURSE : 0;
 
-       if (list_only)
-               return;
-
        if (verbose > 2)
                rprintf(FINFO, "recv_generator(%s,%d)\n", fname, ndx);
 
+       if (list_only) {
+               if (S_ISDIR(file->mode)
+                && ((!implied_dirs && !(file->flags & FLAG_XFER_DIR))
+                 || (inc_recurse && ndx != cur_flist->ndx_start - 1)))
+                       return;
+               list_file_entry(file);
+               return;
+       }
+
        if (server_filter_list.head) {
                if (excluded_below >= 0) {
                        if (F_DEPTH(file) > excluded_below
@@ -1163,7 +1198,8 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
        } else {
                const char *dn = file->dirname ? file->dirname : ".";
                if (parent_dirname != dn && strcmp(parent_dirname, dn) != 0) {
-                       if (implied_dirs_are_missing && do_stat(dn, &sx.st) < 0
+                       if (relative_paths && !implied_dirs
+                        && do_stat(dn, &sx.st) < 0
                         && create_directory_path(fname) < 0) {
                                rsyserr(FERROR, errno,
                                        "recv_generator: mkdir %s failed",
@@ -1630,8 +1666,23 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                statret = 0;
        }
 
-       if (!do_xfers || read_batch || whole_file)
+       if (!do_xfers)
+               goto notify_others;
+
+       if (read_batch || whole_file) {
+               if (inplace && make_backups > 0 && fnamecmp_type == FNAMECMP_FNAME) {
+                       if (!(backupptr = get_backup_name(fname)))
+                               goto cleanup;
+                       if (!(back_file = make_file(fname, NULL, NULL, 0, NO_FILTERS)))
+                               goto pretend_missing;
+                       if (copy_file(fname, backupptr, back_file->mode, 1) < 0) {
+                               unmake_file(back_file);
+                               back_file = NULL;
+                               goto cleanup;
+                       }
+               }
                goto notify_others;
+       }
 
        if (fuzzy_dirlist) {
                int j = flist_find(fuzzy_dirlist, file);
@@ -1640,9 +1691,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
        }
 
        /* open the file */
-       fd = do_open(fnamecmp, O_RDONLY, 0);
-
-       if (fd == -1) {
+       if ((fd = do_open(fnamecmp, O_RDONLY, 0)) < 0) {
                rsyserr(FERROR, errno, "failed to open %s, continuing",
                        full_fname(fnamecmp));
          pretend_missing:
@@ -1670,14 +1719,17 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                        rsyserr(FERROR, errno, "unlink %s",
                                full_fname(backupptr));
                        unmake_file(back_file);
+                       back_file = NULL;
                        close(fd);
                        goto cleanup;
                }
-               if ((f_copy = do_open(backupptr,
-                   O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0) {
+               if ((f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0
+                && (errno != ENOENT || make_bak_dir(backupptr) < 0
+                 || (f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0)) {
                        rsyserr(FERROR, errno, "open %s",
                                full_fname(backupptr));
                        unmake_file(back_file);
+                       back_file = NULL;
                        close(fd);
                        goto cleanup;
                }
@@ -1732,15 +1784,17 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
        if (read_batch)
                goto cleanup;
 
-       if (statret != 0 || whole_file) {
+       if (statret != 0 || whole_file)
                write_sum_head(f_out, NULL);
-               goto cleanup;
+       else {
+               generate_and_send_sums(fd, sx.st.st_size, f_out, f_copy);
+               close(fd);
        }
 
-       generate_and_send_sums(fd, sx.st.st_size, f_out, f_copy);
-
-       if (f_copy >= 0) {
-               close(f_copy);
+  cleanup:
+       if (back_file) {
+               if (f_copy >= 0)
+                       close(f_copy);
                set_file_attrs(backupptr, back_file, NULL, NULL, 0);
                if (verbose > 1) {
                        rprintf(FINFO, "backed up %s to %s\n",
@@ -1749,9 +1803,6 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                unmake_file(back_file);
        }
 
-       close(fd);
-
-  cleanup:
 #ifdef SUPPORT_ACLS
        if (preserve_acls)
                free_acl(&sx);