* Copyright (C) 1996-2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2002 Martin Pool <mbp@samba.org>
- * Copyright (C) 2003-2020 Wayne Davison
+ * Copyright (C) 2003-2023 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 relative_paths;
extern int implied_dirs;
extern int keep_dirlinks;
+extern int write_devices;
extern int preserve_acls;
extern int preserve_xattrs;
extern int preserve_links;
extern int preserve_devices;
-extern int write_devices;
extern int preserve_specials;
extern int preserve_hard_links;
extern int preserve_executability;
extern int preserve_perms;
-extern int preserve_times;
+extern int preserve_mtimes;
+extern int omit_dir_times;
+extern int omit_link_times;
extern int delete_mode;
extern int delete_before;
extern int delete_during;
static int read_delay_line(char *buf, int *flags_p)
{
static int read_pos = 0;
- int j, len, mode;
+ unsigned int mode;
+ int j, len;
char *bp, *past_space;
while (1) {
* MAXPATHLEN buffer with the name of the directory in it (the functions we
* call will append names onto the end, but the old dir value will be restored
* on exit). */
-static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
+static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t fs_dev)
{
static int already_warned = 0;
static struct hashtable *dev_tbl;
if (!dev_tbl)
dev_tbl = hashtable_create(16, HT_KEY64);
if (file->flags & FLAG_TOP_DIR) {
- hashtable_find(dev_tbl, *fs_dev+1, "");
- filesystem_dev = *fs_dev;
- } else if (filesystem_dev != *fs_dev) {
- if (!hashtable_find(dev_tbl, *fs_dev+1, NULL))
+ hashtable_find(dev_tbl, fs_dev+1, "");
+ filesystem_dev = fs_dev;
+ } else if (filesystem_dev != fs_dev) {
+ if (!hashtable_find(dev_tbl, fs_dev+1, NULL))
return;
- filesystem_dev = *fs_dev; /* it's a prior top-dir dev */
+ filesystem_dev = fs_dev; /* it's a prior top-dir dev */
}
}
|| !S_ISDIR(st.st_mode))
continue;
- delete_in_dir(fbuf, file, &st.st_dev);
+ delete_in_dir(fbuf, file, st.st_dev);
}
- delete_in_dir(NULL, NULL, &dev_zero);
+ delete_in_dir(NULL, NULL, dev_zero);
if (INFO_GTE(FLIST, 2) && !am_server)
rprintf(FINFO, " \r");
#ifdef SUPPORT_CRTIMES
if (!differs && crtimes_ndx) {
if (sxp->crtime == 0)
- sxp->crtime = get_create_time(fname);
+ sxp->crtime = get_create_time(fname, &sxp->st);
differs = !same_time(sxp->crtime, 0, F_CRTIME(file), 0);
}
#endif
{
if (S_ISLNK(file->mode)) {
#ifdef CAN_SET_SYMLINK_TIMES
- if (preserve_times & PRESERVE_LINK_TIMES && any_time_differs(sxp, file, fname))
+ if (preserve_mtimes && !omit_link_times && any_time_differs(sxp, file, fname))
return 0;
#endif
#ifdef CAN_CHMOD_SYMLINK
return 0;
#endif
} else {
- if (preserve_times && any_time_differs(sxp, file, fname))
+ if (preserve_mtimes && any_time_differs(sxp, file, fname))
return 0;
if (perms_differ(file, sxp))
return 0;
const char *xname)
{
if (statret >= 0) { /* A from-dest-dir statret can == 1! */
- int keep_time = !preserve_times ? 0
- : S_ISDIR(file->mode) ? preserve_times & PRESERVE_DIR_TIMES
- : S_ISLNK(file->mode) ? preserve_times & PRESERVE_LINK_TIMES
+ int keep_time = !preserve_mtimes ? 0
+ : S_ISDIR(file->mode) ? !omit_dir_times
+ : S_ISLNK(file->mode) ? !omit_link_times
: 1;
if (S_ISREG(file->mode) && F_LENGTH(file) != sxp->st.st_size)
#ifdef SUPPORT_CRTIMES
if (crtimes_ndx) {
if (sxp->crtime == 0)
- sxp->crtime = get_create_time(fnamecmp);
+ sxp->crtime = get_create_time(fnamecmp, &sxp->st);
if (!same_time(sxp->crtime, 0, F_CRTIME(file), 0))
iflags |= ITEM_REPORT_CRTIME;
}
#endif
-#if !defined HAVE_LCHMOD && !defined HAVE_SETATTRLIST
+#ifndef CAN_CHMOD_SYMLINK
if (S_ISLNK(file->mode)) {
;
} else
for (i = 0; i < sum.count; i++) {
int32 n1 = (int32)MIN(len, (OFF_T)sum.blength);
char *map = map_ptr(mapbuf, offset, n1);
- char sum2[SUM_LENGTH];
+ char sum2[MAX_DIGEST_LEN];
uint32 sum1;
len -= n1;
len = strlen(name);
suf = find_filename_suffix(name, len, &suf_len);
- dist = fuzzy_distance(name, len, fname, fname_len);
- /* Add some extra weight to how well the suffixes match. */
- dist += fuzzy_distance(suf, suf_len, fname_suf, fname_suf_len) * 10;
+ dist = fuzzy_distance(name, len, fname, fname_len, lowest_dist);
+ /* Add some extra weight to how well the suffixes match unless we've already disqualified
+ * this file based on a heuristic. */
+ if (dist < 0xFFFF0000U) {
+ dist += fuzzy_distance(suf, suf_len, fname_suf, fname_suf_len, 0xFFFF0000U) * 10;
+ }
if (DEBUG_GTE(FUZZY, 2)) {
rprintf(FINFO, "fuzzy distance for %s = %d.%05d\n",
f_name(fp, NULL), (int)(dist>>16), (int)(dist&0xFFFF));
return;
}
}
- sx.crtime = 0;
if (dry_run > 1 || (dry_missing_dir && is_below(file, dry_missing_dir))) {
int i;
const char *suf = "";
if (INFO_GTE(SKIP, 2)) {
if (ftype != stype)
- suf = " (type differs)";
- else if (quick_check_ok(ftype, fname, file, &sx.st))
- suf = " (uptodate)";
+ suf = " (type change)";
+ else if (!quick_check_ok(ftype, fname, file, &sx.st))
+ suf = always_checksum ? " (sum change)" : " (file change)";
+ else if (!unchanged_attrs(fname, file, &sx))
+ suf = " (attr change)";
else
- suf = " (differs)";
+ suf = " (uptodate)";
}
rprintf(FINFO, "%s exists%s\n", fname, suf);
}
} else
added_perms = 0;
if (is_dir < 0) {
- if (!(preserve_times & PRESERVE_DIR_TIMES))
+ if (!preserve_mtimes || omit_dir_times)
goto cleanup;
/* In inc_recurse mode we want to make sure any missing
* directories get created while we're still processing
else if (delete_during && f_out != -1 && !phase
&& !(file->flags & FLAG_MISSING_DIR)) {
if (file->flags & FLAG_CONTENT_DIR)
- delete_in_dir(fname, file, &real_sx.st.st_dev);
+ delete_in_dir(fname, file, real_sx.st.st_dev);
else
change_local_filter_dir(fname, strlen(fname), F_DEPTH(file));
}
}
if (ftype != FT_REG) {
- if (solo_file)
- fname = f_name(file, NULL);
- rprintf(FINFO, "skipping non-regular file \"%s\"\n", fname);
+ if (INFO_GTE(NONREG, 1)) {
+ if (solo_file)
+ fname = f_name(file, NULL);
+ rprintf(FINFO, "skipping non-regular file \"%s\"\n", fname);
+ }
goto cleanup;
}
goto cleanup;
}
+ if (write_devices && IS_DEVICE(sx.st.st_mode) && sx.st.st_size == 0) {
+ /* This early open into fd skips the regular open below. */
+ if ((fd = do_open(fnamecmp, O_RDONLY, 0)) >= 0)
+ real_sx.st.st_size = sx.st.st_size = get_device_size(fd, fnamecmp);
+ }
+
if (fnamecmp_type <= FNAMECMP_BASIS_DIR_HIGH)
;
else if (fnamecmp_type >= FNAMECMP_FUZZY)
goto cleanup;
return_with_success:
if (!dry_run)
- send_msg_int(MSG_SUCCESS, ndx);
+ send_msg_success(fname, ndx);
goto cleanup;
}
}
/* open the file */
- if ((fd = do_open(fnamecmp, O_RDONLY, 0)) < 0) {
+ if (fd < 0 && (fd = do_open(fnamecmp, O_RDONLY, 0)) < 0) {
rsyserr(FERROR, errno, "failed to open %s, continuing",
full_fname(fnamecmp));
pretend_missing:
if (inplace && make_backups > 0 && fnamecmp_type == FNAMECMP_FNAME) {
if (!(backupptr = get_backup_name(fname))) {
- close(fd);
goto cleanup;
}
if (!(back_file = make_file(fname, NULL, NULL, 0, NO_FILTERS))) {
- close(fd);
goto pretend_missing;
}
if (robust_unlink(backupptr) && errno != ENOENT) {
full_fname(backupptr));
unmake_file(back_file);
back_file = NULL;
- close(fd);
goto cleanup;
}
if ((f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0) {
rsyserr(FERROR_XFER, errno, "open %s", full_fname(backupptr));
unmake_file(back_file);
back_file = NULL;
- close(fd);
goto cleanup;
}
fnamecmp_type = FNAMECMP_BACKUP;
write_sum_head(f_out, NULL);
else if (sx.st.st_size <= 0) {
write_sum_head(f_out, NULL);
- close(fd);
} else {
if (generate_and_send_sums(fd, sx.st.st_size, f_out, f_copy) < 0) {
rprintf(FWARNING,
fnamecmp);
write_sum_head(f_out, NULL);
}
- close(fd);
}
cleanup:
+ if (fd >= 0)
+ close(fd);
if (back_file) {
int save_preserve_xattrs = preserve_xattrs;
if (f_copy >= 0)
}
solo_file = local_name;
dir_tweaking = !(list_only || solo_file || dry_run);
- need_retouch_dir_times = preserve_times & PRESERVE_DIR_TIMES;
+ need_retouch_dir_times = preserve_mtimes && !omit_dir_times;
loopchk_limit = allowed_lull ? allowed_lull * 5 : 200;
symlink_timeset_failed_flags = ITEM_REPORT_TIME
| (protocol_version >= 30 || !am_server ? ITEM_REPORT_TIMEFAIL : 0);
dirdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp));
} else
dirdev = MAKEDEV(0, 0);
- delete_in_dir(fbuf, fp, &dirdev);
+ delete_in_dir(fbuf, fp, dirdev);
} else
change_local_filter_dir(fbuf, strlen(fbuf), F_DEPTH(fp));
}
} while ((cur_flist = cur_flist->next) != NULL);
if (delete_during)
- delete_in_dir(NULL, NULL, &dev_zero);
+ delete_in_dir(NULL, NULL, dev_zero);
phase++;
if (DEBUG_GTE(GENR, 1))
rprintf(FINFO, "generate_files phase=%d\n", phase);