-#if SUPPORT_HARD_LINKS
- int i;
-
- if (!hlink_list) return;
-
- for (i=1;i<hlink_count;i++) {
- if (S_ISREG(hlink_list[i].mode) &&
- S_ISREG(hlink_list[i-1].mode) &&
- hlink_list[i].basename && hlink_list[i-1].basename &&
- hlink_list[i].dev == hlink_list[i-1].dev &&
- hlink_list[i].inode == hlink_list[i-1].inode) {
- hard_link_one(i);
- }
+ if (do_link(oldname, fname) < 0) {
+ enum logcode code;
+ if (terse) {
+ if (!verbose)
+ return -1;
+ code = FINFO;
+ } else
+ code = FERROR;
+ rsyserr(code, errno, "link %s => %s failed",
+ full_fname(fname), oldname);
+ return 0;
+ }
+
+ file->flags |= FLAG_HLINK_DONE;
+
+ return 1;
+}
+
+void finish_hard_link(struct file_struct *file, const char *fname,
+ STRUCT_STAT *stp, int itemizing, enum logcode code,
+ int alt_dest)
+{
+ STRUCT_STAT st, prev_st;
+ char alt_name[MAXPATHLEN], *prev_name;
+ const char *our_name;
+ int prev_statret, ndx, prev_ndx = F_HL_PREV(file);
+
+ if (stp == NULL && prev_ndx >= 0) {
+ if (link_stat(fname, &st, 0) < 0) {
+ rsyserr(FERROR, errno, "stat %s failed",
+ full_fname(fname));
+ return;
+ }
+ stp = &st;
+ }
+
+ /* FIRST combined with DONE means we were the first to get done. */
+ file->flags |= FLAG_HLINK_FIRST | FLAG_HLINK_DONE;
+ F_HL_PREV(file) = alt_dest;
+ if (alt_dest >= 0 && dry_run) {
+ pathjoin(alt_name, MAXPATHLEN, basis_dir[alt_dest],
+ f_name(file, NULL));
+ our_name = alt_name;
+ } else
+ our_name = fname;
+
+ while ((ndx = prev_ndx) >= 0) {
+ file = FPTR(ndx);
+ file->flags = (file->flags & ~FLAG_HLINK_FIRST) | FLAG_HLINK_DONE;
+ prev_ndx = F_HL_PREV(file);
+ prev_name = f_name(file, NULL);
+ prev_statret = link_stat(prev_name, &prev_st, 0);
+ if (maybe_hard_link(file, ndx, prev_name, prev_statret, &prev_st,
+ our_name, stp, fname, itemizing, code) < 0)
+ continue;
+ if (remove_source_files == 1 && do_xfers)
+ send_msg_int(MSG_SUCCESS, ndx);