* Copyright (C) 1996-2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2002 Martin Pool <mbp@samba.org>
- * Copyright (C) 2003-2008 Wayne Davison
+ * Copyright (C) 2003-2009 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 delete_before;
extern int delete_during;
extern int delete_after;
+extern int delete_missing_args;
extern int msgdone_cnt;
extern int ignore_errors;
extern int remove_source_files;
static int deldelay_size = 0, deldelay_cnt = 0;
static char *deldelay_buf = NULL;
static int deldelay_fd = -1;
-static int lull_mod;
+static int loopchk_limit;
static int dir_tweaking;
static int symlink_timeset_failed_flags;
static int need_retouch_dir_times;
f_name(fp, NULL));
continue;
}
- if (flist_find(cur_flist, fp) < 0) {
+ /* Here we want to match regardless of file type. Replacement
+ * of a file with one of another type is handled separately by
+ * a delete_item call with a DEL_MAKE_ROOM flag. */
+ if (flist_find_ignore_dirness(cur_flist, fp) < 0) {
int flags = DEL_RECURSE;
if (!(fp->mode & S_IWUSR) && !am_root && (uid_t)F_OWNER(fp) == our_uid)
flags |= DEL_NO_UID_WRITE;
if (iflags & ITEM_XNAME_FOLLOWS)
write_vstring(sock_f_out, xname, strlen(xname));
#ifdef SUPPORT_XATTRS
- if (preserve_xattrs && !dry_run
+ if (preserve_xattrs && do_xfers
&& iflags & (ITEM_REPORT_XATTR|ITEM_TRANSFER)) {
send_xattr_request(NULL, file,
iflags & ITEM_REPORT_XATTR ? sock_f_out : -1);
else if (len <= BLOCK_SIZE * BLOCK_SIZE)
blength = BLOCK_SIZE;
else {
+ int32 max_blength = protocol_version < 30 ? OLD_MAX_BLOCK_SIZE : MAX_BLOCK_SIZE;
int32 c;
int cnt;
for (c = 1, l = len, cnt = 0; l >>= 2; c <<= 1, cnt++) {}
- if (cnt >= 31 || c >= MAX_BLOCK_SIZE)
- blength = MAX_BLOCK_SIZE;
+ if (c < 0 || c >= max_blength)
+ blength = max_blength;
else {
blength = 0;
do {
}
switch (type) {
case TYPE_DIR:
- break;
case TYPE_SPECIAL:
+ break;
case TYPE_DEVICE:
devp = F_RDEV_P(file);
if (sxp->st.st_rdev != MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp)))
f_name(f, NULL), F_SYMLINK(f));
} else
#endif
- {
+ if (delete_missing_args && !f->mode) {
+ rprintf(FINFO, "%-*s %s\n",
+ /*colwidth*/11 + 31, "*missing",
+ f_name(f, NULL));
+ } else {
rprintf(FINFO, "%s %11.0f %s %s\n",
permbuf, len, timestring(f->modtime),
f_name(f, NULL));
stat_errno = errno;
}
+ if (delete_missing_args && file->mode == 0) {
+ if (statret == 0)
+ delete_item(fname, sx.st.st_mode, del_opts);
+ return;
+ }
+
if (ignore_non_existing > 0 && statret == -1 && stat_errno == ENOENT) {
if (is_dir) {
if (is_dir < 0)
if (j == -2) {
itemizing = 0;
code = FNONE;
+ statret = 1;
} else if (j >= 0)
statret = 1;
}
goto cleanup;
}
}
+#ifdef SUPPORT_XATTRS
+ if (preserve_xattrs && statret == 1)
+ copy_xattrs(fnamecmpbuf, fname);
+#endif
if (set_file_attrs(fname, file, real_ret ? NULL : &real_sx, NULL, 0)
&& verbose && code != FNONE && f_out != -1)
rprintf(code, "%s/\n", fname);
if ((am_root && preserve_devices && IS_DEVICE(file->mode))
|| (preserve_specials && IS_SPECIAL(file->mode))) {
- uint32 *devp = F_RDEV_P(file);
- dev_t rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp));
+ dev_t rdev;
+ if (IS_DEVICE(file->mode)) {
+ uint32 *devp = F_RDEV_P(file);
+ rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp));
+ } else
+ rdev = 0;
if (statret == 0) {
int del_for_flag;
if (IS_DEVICE(file->mode)) {
}
if (statret == 0
&& BITS_EQUAL(sx.st.st_mode, file->mode, _S_IFMT)
- && sx.st.st_rdev == rdev) {
+ && (IS_SPECIAL(sx.st.st_mode) || sx.st.st_rdev == rdev)) {
/* The device or special file is identical. */
set_file_attrs(fname, file, &sx, NULL, maybe_ATTRS_REPORT);
if (itemizing)
if (read_batch)
goto cleanup;
- if (statret != 0 || whole_file || sx.st.st_size <= 0)
+ if (statret != 0 || whole_file)
write_sum_head(f_out, NULL);
- else {
+ 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,
"WARNING: file is too large for checksum sending: %s\n",
&& cmp_time(st.st_mtime, file->modtime) != 0)
set_modtime(fname, file->modtime, file->mode);
}
- if (allowed_lull && !(counter % lull_mod))
- maybe_send_keepalive();
- else if (!(counter & 0xFF))
- maybe_flush_socket(0);
+ if (counter >= loopchk_limit) {
+ if (allowed_lull)
+ maybe_send_keepalive();
+ else
+ maybe_flush_socket(0);
+ counter = 0;
+ }
}
}
while (1) {
#ifdef SUPPORT_HARD_LINKS
if (preserve_hard_links && (ndx = get_hlink_num()) != -1) {
- flist = flist_for_ndx(ndx);
- assert(flist != NULL);
+ flist = flist_for_ndx(ndx, "check_for_finished_files.1");
file = flist->files[ndx - flist->ndx_start];
assert(file->flags & FLAG_HLINKED);
finish_hard_link(file, f_name(file, fbuf), ndx, NULL, itemizing, code, -1);
ignore_times++;
flist = cur_flist;
- cur_flist = flist_for_ndx(ndx);
+ cur_flist = flist_for_ndx(ndx, "check_for_finished_files.2");
file = cur_flist->files[ndx - cur_flist->ndx_start];
if (solo_file)
if (first_flist->in_progress || first_flist->to_redo)
break;
- if (!read_batch) {
- write_ndx(sock_f_out, NDX_DONE);
+ write_ndx(sock_f_out, NDX_DONE);
+ if (!read_batch)
maybe_flush_socket(1);
- }
if (delete_during == 2 || !dir_tweaking) {
/* Skip directory touch-up. */
void generate_files(int f_out, const char *local_name)
{
- int i, ndx;
+ int i, ndx, next_loopchk = 0;
char fbuf[MAXPATHLEN];
int itemizing;
enum logcode code;
solo_file = local_name;
dir_tweaking = !(list_only || solo_file || dry_run);
need_retouch_dir_times = preserve_times > 1;
- lull_mod = allowed_lull * 5;
+ loopchk_limit = allowed_lull ? allowed_lull * 5 : 200;
symlink_timeset_failed_flags = ITEM_REPORT_TIME
| (protocol_version >= 30 || !am_server ? ITEM_REPORT_TIMEFAIL : 0);
implied_dirs_are_missing = relative_paths && !implied_dirs && protocol_version < 30;
if (inc_recurse && cur_flist->parent_ndx >= 0) {
struct file_struct *fp = dir_flist->files[cur_flist->parent_ndx];
- f_name(fp, fbuf);
+ if (solo_file)
+ strlcpy(fbuf, solo_file, sizeof fbuf);
+ else
+ f_name(fp, fbuf);
ndx = cur_flist->ndx_start - 1;
recv_generator(fbuf, fp, ndx, itemizing, code, f_out);
if (delete_during && dry_run < 2 && !list_only
check_for_finished_files(itemizing, code, 0);
- if (allowed_lull && !(i % lull_mod))
- maybe_send_keepalive();
- else if (!(i & 0xFF))
- maybe_flush_socket(0);
+ if (i + cur_flist->ndx_start >= next_loopchk) {
+ if (allowed_lull)
+ maybe_send_keepalive();
+ else
+ maybe_flush_socket(0);
+ next_loopchk += loopchk_limit;
+ }
}
if (!inc_recurse) {
touch_up_dirs(dir_flist, -1);
if (max_delete >= 0 && deletion_count > max_delete) {
- rprintf(FINFO,
+ rprintf(FWARNING,
"Deletions stopped due to --max-delete limit (%d skipped)\n",
deletion_count - max_delete);
io_error |= IOERR_DEL_LIMIT;