+int hard_link_check(struct file_struct *file, int ndx, const char *fname,
+ int statret, STRUCT_STAT *stp, int itemizing,
+ enum logcode code, int skip)
+{
+ int head;
+ struct hlist *hl = F_HL_LIST(file);
+
+ if (skip && !(file->flags & FLAG_HLINK_LAST))
+ head = hlink_list[hl->hlindex] = hl->next;
+ else
+ head = hlink_list[hl->hlindex];
+ if (ndx != head) {
+ struct file_struct *head_file = FPTR(head);
+ struct hlist *hf_hl = F_HL_LIST(head_file);
+ if (!stdout_format_has_i && verbose > 1) {
+ rprintf(FINFO, "\"%s\" is a hard link\n",
+ f_name(file, NULL));
+ }
+ if (hf_hl->hlindex == FINISHED_LINK) {
+ STRUCT_STAT st2, st3;
+ char toname[MAXPATHLEN];
+ int ldu = hf_hl->dest_used;
+ if (ldu) {
+ pathjoin(toname, MAXPATHLEN, basis_dir[ldu-1],
+ f_name(head_file, NULL));
+ } else
+ f_name(head_file, toname);
+ if (link_stat(toname, &st2, 0) < 0) {
+ rsyserr(FERROR, errno, "stat %s failed",
+ full_fname(toname));
+ return -1;
+ }
+ if (statret < 0 && basis_dir[0] != NULL) {
+ char cmpbuf[MAXPATHLEN];
+ int j = 0;
+ do {
+ pathjoin(cmpbuf, MAXPATHLEN, basis_dir[j], fname);
+ if (link_stat(cmpbuf, &st3, 0) < 0)
+ continue;
+ if (link_dest) {
+ if (st2.st_dev != st3.st_dev
+ || st2.st_ino != st3.st_ino)
+ continue;
+ statret = 1;
+ stp = &st3;
+ if (verbose < 2 || !stdout_format_has_i) {
+ itemizing = 0;
+ code = FNONE;
+ }
+ break;
+ }
+ if (!unchanged_file(cmpbuf, file, &st3))
+ continue;
+ statret = 1;
+ stp = &st3;
+ if (unchanged_attrs(file, &st3))
+ break;
+ } while (basis_dir[++j] != NULL);
+ }
+ maybe_hard_link(file, ndx, fname, statret, stp,
+ toname, &st2, itemizing, code);
+ if (remove_source_files == 1 && do_xfers)
+ send_msg_int(MSG_SUCCESS, ndx);
+ hl->hlindex = FINISHED_LINK;
+ } else
+ hl->hlindex = SKIPPED_LINK;
+ return 1;
+ }
+ return 0;
+}