* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2002 Martin Pool <mbp@samba.org>
- * Copyright (C) 2004-2009 Wayne Davison
+ * Copyright (C) 2004-2022 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
extern int am_sender;
extern int inc_recurse;
extern int do_xfers;
-extern int link_dest;
+extern int alt_dest_type;
extern int preserve_acls;
extern int preserve_xattrs;
extern int protocol_version;
* we can avoid the pool of dev+inode data. For incremental recursion mode,
* the receiver will use a ndx hash to remember old pathnames. */
+static void *data_when_new = "";
+
static struct hashtable *dev_tbl;
static struct hashtable *prior_hlinks;
void init_hard_links(void)
{
if (am_sender || protocol_version < 30)
- dev_tbl = hashtable_create(16, SIZEOF_INT64 == 8);
+ dev_tbl = hashtable_create(16, HT_KEY64);
else if (inc_recurse)
- prior_hlinks = hashtable_create(1024, 0);
+ prior_hlinks = hashtable_create(1024, HT_KEY32);
}
struct ht_int64_node *idev_find(int64 dev, int64 ino)
{
static struct ht_int64_node *dev_node = NULL;
- struct hashtable *tbl;
- if (!dev_node || dev_node->key != dev) {
+ /* Note that some OSes have a dev == 0, so increment to avoid storing a 0. */
+ if (!dev_node || dev_node->key != dev+1) {
/* We keep a separate hash table of inodes for every device. */
- dev_node = hashtable_find(dev_tbl, dev, 1);
- if (!(tbl = dev_node->data)) {
- tbl = dev_node->data = hashtable_create(512, SIZEOF_INT64 == 8);
+ dev_node = hashtable_find(dev_tbl, dev+1, data_when_new);
+ if (dev_node->data == data_when_new) {
+ dev_node->data = hashtable_create(512, HT_KEY64);
if (DEBUG_GTE(HLINK, 3)) {
- rprintf(FINFO,
- "[%s] created hashtable for dev %s\n",
- who_am_i(), big_num(dev));
+ rprintf(FINFO, "[%s] created hashtable for dev %s\n",
+ who_am_i(), big_num(dev));
}
}
- } else
- tbl = dev_node->data;
+ }
- return hashtable_find(tbl, ino, 1);
+ return hashtable_find(dev_node->data, ino, (void*)-1L);
}
void idev_destroy(void)
struct ht_int32_node *node = NULL;
int32 gnum, gnum_next;
- qsort(ndx_list, ndx_count, sizeof ndx_list[0],
- (int (*)()) hlink_compare_gnum);
+ qsort(ndx_list, ndx_count, sizeof ndx_list[0], (int (*)()) hlink_compare_gnum);
for (from = 0; from < ndx_count; from++) {
file = hlink_flist->sorted[ndx_list[from]];
gnum = F_HL_GNUM(file);
if (inc_recurse) {
- node = hashtable_find(prior_hlinks, gnum, 1);
- if (!node->data) {
- if (!(node->data = new_array0(char, 5)))
- out_of_memory("match_gnums");
+ node = hashtable_find(prior_hlinks, gnum, data_when_new);
+ if (node->data == data_when_new) {
+ node->data = new_array0(char, 5);
assert(gnum >= hlink_flist->ndx_start);
file->flags |= FLAG_HLINK_FIRST;
prev = -1;
int i, ndx_count = 0;
int32 *ndx_list;
- if (!(ndx_list = new_array(int32, flist->used)))
- out_of_memory("match_hard_links");
+ ndx_list = new_array(int32, flist->used);
for (i = 0; i < flist->used; i++) {
if (F_IS_HLINKED(flist->sorted[i]))
}
}
- if (atomic_create(file, fname, oldname, MAKEDEV(0, 0), sxp, statret == 0 ? DEL_FOR_FILE : 0)) {
+ if (atomic_create(file, fname, NULL, oldname, MAKEDEV(0, 0), sxp, statret == 0 ? DEL_FOR_FILE : 0)) {
if (itemizing) {
itemize(fname, file, ndx, statret, sxp,
ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS, 0,
}
if (inc_recurse
- && (node = hashtable_find(prior_hlinks, gnum, 0)) != NULL) {
+ && (node = hashtable_find(prior_hlinks, gnum, NULL)) != NULL) {
assert(node->data != NULL);
if (CVAL(node->data, 0) != 0) {
*prev_ndx_p = -1;
pathjoin(cmpbuf, MAXPATHLEN, basis_dir[j], fname);
if (link_stat(cmpbuf, &alt_sx.st, 0) < 0)
continue;
- if (link_dest) {
+ if (alt_dest_type == LINK_DEST) {
if (prev_st.st_dev != alt_sx.st.st_dev
|| prev_st.st_ino != alt_sx.st.st_ino)
continue;
}
break;
}
- if (!unchanged_file(cmpbuf, file, &alt_sx.st))
+ if (!quick_check_ok(FT_REG, cmpbuf, file, &alt_sx.st))
continue;
statret = 1;
if (unchanged_attrs(cmpbuf, file, &alt_sx))
}
}
#endif
- } else {
-#ifdef SUPPORT_ACLS
- if (preserve_acls)
- free_acl(&alt_sx);
-#endif
-#ifdef SUPPORT_XATTRS
- if (preserve_xattrs)
- free_xattr(&alt_sx);
-#endif
- }
+ } else
+ free_stat_x(&alt_sx);
}
if (maybe_hard_link(file, ndx, fname, statret, sxp, prev_name, &prev_st,
return -1;
if (remove_source_files == 1 && do_xfers)
- send_msg_int(MSG_SUCCESS, ndx);
+ send_msg_success(fname, ndx);
return 1;
}
int prev_statret, ndx, prev_ndx = F_HL_PREV(file);
if (stp == NULL && prev_ndx >= 0) {
- if (link_stat(fname, &st, 0) < 0) {
+ if (link_stat(fname, &st, 0) < 0 && !dry_run) {
rsyserr(FERROR_XFER, errno, "stat %s failed",
full_fname(fname));
return;
val = maybe_hard_link(file, ndx, prev_name, prev_statret, &prev_sx,
our_name, stp, fname, itemizing, code);
flist->in_progress--;
-#ifdef SUPPORT_ACLS
- if (preserve_acls)
- free_acl(&prev_sx);
-#endif
-#ifdef SUPPORT_XATTRS
- if (preserve_xattrs)
- free_xattr(&prev_sx);
-#endif
+ free_stat_x(&prev_sx);
if (val < 0)
continue;
if (remove_source_files == 1 && do_xfers)
- send_msg_int(MSG_SUCCESS, ndx);
+ send_msg_success(fname, ndx);
}
if (inc_recurse) {
int gnum = F_HL_GNUM(file);
- struct ht_int32_node *node = hashtable_find(prior_hlinks, gnum, 0);
- assert(node != NULL && node->data != NULL);
- assert(CVAL(node->data, 0) == 0);
+ struct ht_int32_node *node = hashtable_find(prior_hlinks, gnum, NULL);
+ if (node == NULL) {
+ rprintf(FERROR, "Unable to find a hlink node for %d (%s)\n", gnum, f_name(file, prev_name));
+ exit_cleanup(RERR_MESSAGEIO);
+ }
+ if (node->data == NULL) {
+ rprintf(FERROR, "Hlink node data for %d is NULL (%s)\n", gnum, f_name(file, prev_name));
+ exit_cleanup(RERR_MESSAGEIO);
+ }
+ if (CVAL(node->data, 0) != 0) {
+ rprintf(FERROR, "Hlink node data for %d already has path=%s (%s)\n",
+ gnum, (char*)node->data, f_name(file, prev_name));
+ exit_cleanup(RERR_MESSAGEIO);
+ }
free(node->data);
- if (!(node->data = strdup(our_name)))
- out_of_memory("finish_hard_link");
+ node->data = strdup(our_name);
}
}