+ if (statret != 0 && basis_dir[0] != NULL) {
+ int best_match = -1;
+ int match_level = 0;
+ int i = 0;
+ do {
+ pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
+ basis_dir[i], fname);
+ if (link_stat(fnamecmpbuf, &st, 0) < 0
+ || !S_ISREG(st.st_mode))
+ continue;
+ switch (match_level) {
+ case 0:
+ best_match = i;
+ match_level = 1;
+ /* FALL THROUGH */
+ case 1:
+ if (!unchanged_file(fnamecmpbuf, file, &st))
+ continue;
+ best_match = i;
+ match_level = 2;
+ if (copy_dest)
+ break;
+ /* FALL THROUGH */
+ case 2:
+ if (!unchanged_attrs(file, &st))
+ continue;
+ best_match = i;
+ match_level = 3;
+ break;
+ }
+ break;
+ } while (basis_dir[++i] != NULL);
+ if (match_level) {
+ statret = 0;
+ if (i != best_match) {
+ i = best_match;
+ pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
+ basis_dir[i], fname);
+ if (link_stat(fnamecmpbuf, &st, 0) < 0) {
+ match_level = 0;
+ statret = -1;
+ stat_errno = errno;
+ }
+ }
+#ifdef HAVE_LINK
+ if (link_dest && match_level == 3) {
+ if (hard_link_one(file, ndx, fname, -1, &st,
+ fnamecmpbuf, 1,
+ itemizing && verbose > 1,
+ code) == 0) {
+ if (preserve_hard_links
+ && file->link_u.links) {
+ hard_link_cluster(file, ndx,
+ itemizing,
+ code);
+ }
+ return;
+ }
+ match_level = 2;
+ }
+#endif
+ if (match_level == 2) {
+ /* Copy the file locally. */
+ if (copy_file(fnamecmpbuf, fname, file->mode) < 0) {
+ if (verbose) {
+ rsyserr(FINFO, errno,
+ "copy_file %s => %s",
+ full_fname(fnamecmpbuf),
+ safe_fname(fname));
+ }
+ match_level = 0;
+ statret = -1;
+ } else {
+ if (itemizing) {
+ itemize(file, ndx, 0, &st,
+ ITEM_LOCAL_CHANGE, 0,
+ NULL);
+ } else if (verbose && code) {
+ rprintf(code, "%s\n",
+ safe_fname(fname));
+ }
+ set_perms(fname, file, NULL,
+ maybe_PERMS_REPORT);
+ if (preserve_hard_links
+ && file->link_u.links) {
+ hard_link_cluster(file, ndx,
+ itemizing,
+ code);
+ }
+ return;
+ }
+ } else if (compare_dest || match_level == 1) {
+ fnamecmp = fnamecmpbuf;
+ fnamecmp_type = i;
+ }
+ }