| 473 | } |
| 474 | |
| 475 | void finish_hard_link(struct file_struct *file, const char *fname, int fin_ndx, |
| 476 | STRUCT_STAT *stp, int itemizing, enum logcode code, |
| 477 | int alt_dest) |
| 478 | { |
| 479 | stat_x prev_sx; |
| 480 | STRUCT_STAT st; |
| 481 | char prev_name[MAXPATHLEN], alt_name[MAXPATHLEN]; |
| 482 | const char *our_name; |
| 483 | struct file_list *flist; |
| 484 | int prev_statret, ndx, prev_ndx = F_HL_PREV(file); |
| 485 | |
| 486 | if (stp == NULL && prev_ndx >= 0) { |
| 487 | if (link_stat(fname, &st, 0) < 0 && !dry_run) { |
| 488 | rsyserr(FERROR_XFER, errno, "stat %s failed", |
| 489 | full_fname(fname)); |
| 490 | return; |
| 491 | } |
| 492 | stp = &st; |
| 493 | } |
| 494 | |
| 495 | /* FIRST combined with DONE means we were the first to get done. */ |
| 496 | file->flags |= FLAG_HLINK_FIRST | FLAG_HLINK_DONE; |
| 497 | F_HL_PREV(file) = alt_dest; |
| 498 | if (alt_dest >= 0 && dry_run) { |
| 499 | pathjoin(alt_name, MAXPATHLEN, basis_dir[alt_dest], |
| 500 | f_name(file, NULL)); |
| 501 | our_name = alt_name; |
| 502 | } else |
| 503 | our_name = fname; |
| 504 | |
| 505 | init_stat_x(&prev_sx); |
| 506 | |
| 507 | while ((ndx = prev_ndx) >= 0) { |
| 508 | int val; |
| 509 | flist = flist_for_ndx(ndx, "finish_hard_link"); |
| 510 | file = flist->files[ndx - flist->ndx_start]; |
| 511 | file->flags = (file->flags & ~FLAG_HLINK_FIRST) | FLAG_HLINK_DONE; |
| 512 | prev_ndx = F_HL_PREV(file); |
| 513 | F_HL_PREV(file) = fin_ndx; |
| 514 | prev_statret = link_stat(f_name(file, prev_name), &prev_sx.st, 0); |
| 515 | val = maybe_hard_link(file, ndx, prev_name, prev_statret, &prev_sx, |
| 516 | our_name, stp, fname, itemizing, code); |
| 517 | flist->in_progress--; |
| 518 | free_stat_x(&prev_sx); |
| 519 | if (val < 0) |
| 520 | continue; |
| 521 | if (remove_source_files == 1 && do_xfers) |
| 522 | send_msg_success(fname, ndx); |
| 523 | } |
| 524 | |
| 525 | if (inc_recurse) { |
| 526 | int gnum = F_HL_GNUM(file); |
| 527 | struct ht_int32_node *node = hashtable_find(prior_hlinks, gnum, NULL); |
| 528 | if (node == NULL) { |
| 529 | rprintf(FERROR, "Unable to find a hlink node for %d (%s)\n", gnum, f_name(file, prev_name)); |
| 530 | exit_cleanup(RERR_MESSAGEIO); |
| 531 | } |
| 532 | if (node->data == NULL) { |
no test coverage detected