#include "rounding.h"
#include "io.h"
-extern int verbose;
extern int am_root;
extern int am_server;
extern int am_daemon;
extern int am_sender;
extern int am_generator;
extern int inc_recurse;
-extern int do_progress;
extern int always_checksum;
extern int module_id;
extern int ignore_errors;
extern int sanitize_paths;
extern int munge_symlinks;
extern int need_unsorted_flist;
+extern int output_needs_newline;
+extern int sender_keeps_checksum;
extern int unsort_ndx;
extern struct stats stats;
extern char *filesfrom_host;
void init_flist(void)
{
- if (verbose > 4) {
+ if (DEBUG_GTE(FLIST, 4)) {
rprintf(FINFO, "FILE_STRUCT_LEN=%d, EXTRA_LEN=%d\n",
(int)FILE_STRUCT_LEN, (int)EXTRA_LEN);
}
static int show_filelist_p(void)
{
- return verbose && xfer_dirs && !am_server && !inc_recurse;
+ return INFO_GTE(FLIST, 1) && xfer_dirs && !am_server && !inc_recurse;
}
static void start_filelist_progress(char *kind)
{
rprintf(FCLIENT, "%s ... ", kind);
- if (verbose > 1 || do_progress)
- rprintf(FCLIENT, "\n");
+ output_needs_newline = 1;
rflush(FINFO);
}
static void maybe_emit_filelist_progress(int count)
{
- if (do_progress && show_filelist_p() && (count % 100) == 0)
+ if (INFO_GTE(FLIST, 2) && show_filelist_p() && (count % 100) == 0)
emit_filelist_progress(count);
}
static void finish_filelist_progress(const struct file_list *flist)
{
- if (do_progress) {
+ if (INFO_GTE(FLIST, 2)) {
/* This overwrites the progress line */
rprintf(FINFO, "%d file%sto consider\n",
flist->used, flist->used == 1 ? " " : "s ");
- } else
+ } else {
+ output_needs_newline = 0;
rprintf(FINFO, "done\n");
+ }
}
void show_flist_stats(void)
return -1;
linkbuf[llen] = '\0';
if (copy_unsafe_links && unsafe_symlink(linkbuf, path)) {
- if (verbose > 1) {
+ if (INFO_GTE(SYMSAFE, 1)) {
rprintf(FINFO,"copying unsafe symlink \"%s\" -> \"%s\"\n",
path, linkbuf);
}
new_ptr = realloc_array(flist->files, struct file_struct *,
flist->malloced);
- if (verbose >= 2 && flist->malloced != FLIST_START) {
- rprintf(FCLIENT, "[%s] expand file_list pointer array to %.0f bytes, did%s move\n",
+ if (DEBUG_GTE(FLIST, 1) && flist->malloced != FLIST_START) {
+ rprintf(FCLIENT, "[%s] expand file_list pointer array to %s bytes, did%s move\n",
who_am_i(),
- (double)sizeof flist->files[0] * flist->malloced,
+ big_num(sizeof flist->files[0] * flist->malloced, 0),
(new_ptr == flist->files) ? " not" : "");
}
static gid_t gid;
static const char *user_name, *group_name;
static char lastname[MAXPATHLEN];
+#ifdef SUPPORT_HARD_LINKS
int first_hlink_ndx = -1;
+#endif
int l1, l2;
int xflags;
np->data = (void*)(long)(first_ndx + ndx + 1);
xflags |= XMIT_HLINK_FIRST;
}
+ if (DEBUG_GTE(HLINK, 1)) {
+ if (first_hlink_ndx >= 0) {
+ rprintf(FINFO, "[%s] #%d hard-links #%d (%sabbrev)\n",
+ who_am_i(), first_ndx + ndx, first_hlink_ndx,
+ first_hlink_ndx >= first_ndx ? "" : "un");
+ } else if (DEBUG_GTE(HLINK, 3)) {
+ rprintf(FINFO, "[%s] dev:inode for #%d is %s:%s\n",
+ who_am_i(), first_ndx + ndx,
+ big_num(tmp_dev, 0), big_num(tmp_ino, 0));
+ }
+ }
} else {
if (tmp_dev == dev) {
if (protocol_version >= 28)
write_byte(f, l2);
write_buf(f, fname + l1, l2);
+#ifdef SUPPORT_HARD_LINKS
if (first_hlink_ndx >= 0) {
write_varint(f, first_hlink_ndx);
if (first_hlink_ndx >= first_ndx)
goto the_end;
}
+#endif
write_varlong30(f, F_LENGTH(file), 3);
if (!(xflags & XMIT_SAME_TIME)) {
write_buf(f, sum, checksum_len);
}
+#ifdef SUPPORT_HARD_LINKS
the_end:
+#endif
strlcpy(lastname, fname, MAXPATHLEN);
if (S_ISREG(mode) || S_ISLNK(mode))
int alloc_len, basename_len, linkname_len;
int extra_len = file_extra_cnt * EXTRA_LEN;
int first_hlink_ndx = -1;
- OFF_T file_length;
+ int64 file_length;
const char *basename;
struct file_struct *file;
alloc_pool_t *pool;
first_hlink_ndx, flist->ndx_start + flist->used);
exit_cleanup(RERR_PROTOCOL);
}
+ if (DEBUG_GTE(HLINK, 1)) {
+ rprintf(FINFO, "[%s] #%d hard-links #%d (%sabbrev)\n",
+ who_am_i(), flist->used+flist->ndx_start, first_hlink_ndx,
+ first_hlink_ndx >= flist->ndx_start ? "" : "un");
+ }
if (first_hlink_ndx >= flist->ndx_start) {
struct file_struct *first = flist->files[first_hlink_ndx - flist->ndx_start];
file_length = F_LENGTH(first);
if (always_checksum && S_ISREG(mode))
extra_len += SUM_EXTRA_CNT * EXTRA_LEN;
+#if SIZEOF_INT64 >= 8
if (file_length > 0xFFFFFFFFu && S_ISREG(mode))
extra_len += EXTRA_LEN;
+#endif
+ if (file_length < 0) {
+ rprintf(FERROR, "Offset underflow: file-length is negative\n");
+ exit_cleanup(RERR_UNSUPPORTED);
+ }
if (inc_recurse && S_ISDIR(mode)) {
if (one_file_system) {
#endif
file->modtime = (time_t)modtime;
file->len32 = (uint32)file_length;
+#if SIZEOF_INT64 >= 8
if (file_length > 0xFFFFFFFFu && S_ISREG(mode)) {
+#if SIZEOF_CAPITAL_OFF_T < 8
+ rprintf(FERROR, "Offset overflow: attempted 64-bit file-length\n");
+ exit_cleanup(RERR_UNSUPPORTED);
+#else
file->flags |= FLAG_LENGTH64;
OPT_EXTRA(file, 0)->unum = (uint32)(file_length >> 32);
+#endif
}
+#endif
file->mode = mode;
if (preserve_uid)
F_OWNER(file) = uid;
* and performing extensive checks against global options.
*
* Returns a pointer to the new file struct, or NULL if there was an error
- * or this file should be excluded. */
+ * or this file should be excluded.
+ *
+ * Note: Any error (here or in send_file_name) that results in the omission of
+ * an existent source file from the file list should set
+ * "io_error |= IOERR_GENERAL" to avoid deletion of the file from the
+ * destination if --delete is on. */
struct file_struct *make_file(const char *fname, struct file_list *flist,
STRUCT_STAT *stp, int flags, int filter_level)
{
const char *basename;
alloc_pool_t *pool;
STRUCT_STAT st;
- int excl_ret;
char *bp;
if (strlcpy(thisname, fname, sizeof thisname) >= sizeof thisname) {
+ io_error |= IOERR_GENERAL;
rprintf(FINFO, "skipping overly long name: %s\n", fname);
return NULL;
}
return NULL;
}
- /* backup.c calls us with filter_level set to NO_FILTERS. */
if (filter_level == NO_FILTERS)
goto skip_filters;
if (one_file_system && st.st_dev != filesystem_dev
&& BITS_SETnUNSET(flags, FLAG_CONTENT_DIR, FLAG_TOP_DIR)) {
if (one_file_system > 1) {
- if (verbose > 1) {
+ if (INFO_GTE(MOUNT, 1)) {
rprintf(FINFO,
"[%s] skipping mount-point dir %s\n",
who_am_i(), thisname);
} else
flags &= ~FLAG_CONTENT_DIR;
- if (S_ISDIR(st.st_mode)) {
- if (flags & FLAG_DOTDIR_NAME) {
- /* A "." fname (or "/." fname in relative mode) is
- * never excluded. No other trailing-dotdir names
- * are possible. */
- excl_ret = 0;
- } else
- excl_ret = is_excluded(thisname, 1, filter_level);
- } else
- excl_ret = is_excluded(thisname, 0, filter_level);
- if (excl_ret) {
+ if (is_excluded(thisname, S_ISDIR(st.st_mode) != 0, filter_level)) {
if (ignore_perishable)
non_perishable_cnt++;
return NULL;
pool = NULL;
}
- if (verbose > 2) {
+ if (DEBUG_GTE(FLIST, 2)) {
rprintf(FINFO, "[%s] make_file(%s,*,%d)\n",
who_am_i(), thisname, filter_level);
}
linkname_len = 0;
#endif
+#if SIZEOF_CAPITAL_OFF_T >= 8
if (st.st_size > 0xFFFFFFFFu && S_ISREG(st.st_mode))
extra_len += EXTRA_LEN;
+#endif
+
+ if (always_checksum && am_sender && S_ISREG(st.st_mode)) {
+ file_checksum(thisname, tmp_sum, st.st_size);
+ if (sender_keeps_checksum)
+ extra_len += SUM_EXTRA_CNT * EXTRA_LEN;
+ }
#if EXTRA_ROUNDING > 0
if (extra_len & (EXTRA_ROUNDING * EXTRA_LEN))
file->flags = flags;
file->modtime = st.st_mtime;
file->len32 = (uint32)st.st_size;
+#if SIZEOF_CAPITAL_OFF_T >= 8
if (st.st_size > 0xFFFFFFFFu && S_ISREG(st.st_mode)) {
file->flags |= FLAG_LENGTH64;
OPT_EXTRA(file, 0)->unum = (uint32)(st.st_size >> 32);
}
+#endif
file->mode = st.st_mode;
if (uid_ndx) /* Check uid_ndx instead of preserve_uid for del support */
F_OWNER(file) = st.st_uid;
memcpy(bp + basename_len, linkname, linkname_len);
#endif
- if (always_checksum && am_sender && S_ISREG(st.st_mode))
- file_checksum(thisname, tmp_sum, st.st_size);
-
if (am_sender)
F_PATHNAME(file) = pathname;
else if (!pool)
return NULL;
}
+ if (sender_keeps_checksum && S_ISREG(st.st_mode))
+ memcpy(F_SUM(file), tmp_sum, checksum_len);
+
if (unsort_ndx)
F_NDX(file) = dir_count;
if (preserve_acls && !S_ISLNK(file->mode)) {
sx.st.st_mode = file->mode;
sx.acc_acl = sx.def_acl = NULL;
- if (get_acl(fname, &sx) < 0)
+ if (get_acl(fname, &sx) < 0) {
+ io_error |= IOERR_GENERAL;
return NULL;
+ }
}
#endif
#ifdef SUPPORT_XATTRS
if (preserve_xattrs) {
sx.xattr = NULL;
- if (get_xattr(fname, &sx) < 0)
+ if (get_xattr(fname, &sx) < 0) {
+ io_error |= IOERR_GENERAL;
return NULL;
+ }
}
#endif
file_total += flist->used;
stats.flist_size += stats.total_written - start_write;
stats.num_files += flist->used;
- if (verbose > 3)
+ if (DEBUG_GTE(FLIST, 3))
output_flist(flist);
if (DIR_FIRST_CHILD(dp) >= 0) {
int64 start_write;
int use_ff_fd = 0;
int disable_buffering;
- int arg_flags, flags = recurse ? FLAG_CONTENT_DIR : 0;
+ int flags = recurse ? FLAG_CONTENT_DIR : 0;
int reading_remotely = filesfrom_host != NULL;
int rl_flags = (reading_remotely ? 0 : RL_DUMP_COMMENTS)
#ifdef ICONV_OPTION
rprintf(FLOG, "building file list\n");
if (show_filelist_p())
start_filelist_progress("building file list");
- else if (inc_recurse && verbose && !am_server)
+ else if (inc_recurse && INFO_GTE(FLIST, 1) && !am_server)
rprintf(FCLIENT, "sending incremental file list\n");
start_write = stats.total_written;
continue;
}
+ /* A dot-dir should not be excluded! */
+ if (name_type != DOTDIR_NAME
+ && is_excluded(fbuf, S_ISDIR(st.st_mode) != 0, ALL_FILTERS))
+ continue;
+
if (S_ISDIR(st.st_mode) && !xfer_dirs) {
rprintf(FINFO, "skipping directory %s\n", fbuf);
continue;
}
if (inc_recurse && relative_paths && *fbuf) {
- if ((p = strchr(fbuf+1, '/')) != NULL
- && !is_excluded(fbuf, S_ISDIR(st.st_mode) != 0, ALL_FILTERS)) {
+ if ((p = strchr(fbuf+1, '/')) != NULL) {
if (p - fbuf == 1 && *fbuf == '.') {
if ((fn = strchr(p+1, '/')) != NULL)
p = fn;
if (fn == p)
continue;
}
- } else if (implied_dirs && (p=strrchr(fbuf,'/')) && p != fbuf
- && !is_excluded(fbuf, S_ISDIR(st.st_mode) != 0, ALL_FILTERS)) {
+ } else if (implied_dirs && (p=strrchr(fbuf,'/')) && p != fbuf) {
/* Send the implied directories at the start of the
* source spec, so we get their permissions right. */
send_implied_dirs(f, flist, fbuf, fbuf, p, flags, 0);
if (one_file_system)
filesystem_dev = st.st_dev;
- arg_flags = name_type == DOTDIR_NAME ? FLAG_DOTDIR_NAME : 0;
-
if (recurse || (xfer_dirs && name_type != NORMAL_NAME)) {
struct file_struct *file;
- arg_flags |= FLAG_TOP_DIR | FLAG_CONTENT_DIR;
file = send_file_name(f, flist, fbuf, &st,
- arg_flags | flags, ALL_FILTERS);
+ FLAG_TOP_DIR | FLAG_CONTENT_DIR | flags,
+ NO_FILTERS);
if (!file)
continue;
if (inc_recurse) {
} else
send_if_directory(f, flist, file, fbuf, len, flags);
} else
- send_file_name(f, flist, fbuf, &st, arg_flags | flags, ALL_FILTERS);
+ send_file_name(f, flist, fbuf, &st, flags, NO_FILTERS);
}
gettimeofday(&end_tv, NULL);
stats.flist_size = stats.total_written - start_write;
stats.num_files = flist->used;
- if (verbose > 3)
+ if (DEBUG_GTE(FLIST, 3))
output_flist(flist);
- if (verbose > 2)
+ if (DEBUG_GTE(FLIST, 2))
rprintf(FINFO, "send_file_list done\n");
if (inc_recurse) {
send_dir_depth = 1;
add_dirs_to_tree(-1, flist, dir_count);
- if (!file_total || strcmp(flist->sorted[0]->basename, ".") != 0)
+ if (!file_total || strcmp(flist->sorted[0]->basename, ".") != 0)
flist->parent_ndx = -1;
flist_done_allocating(flist);
if (send_dir_ndx < 0) {
int dstart, flags;
int64 start_read;
- if (!first_flist)
+ if (!first_flist) {
+ if (show_filelist_p())
+ start_filelist_progress("receiving file list");
+ else if (inc_recurse && INFO_GTE(FLIST, 1) && !am_server)
+ rprintf(FCLIENT, "receiving incremental file list\n");
rprintf(FLOG, "receiving file list\n");
- if (show_filelist_p())
- start_filelist_progress("receiving file list");
- else if (inc_recurse && verbose && !am_server && !first_flist)
- rprintf(FCLIENT, "receiving incremental file list\n");
+ }
start_read = stats.total_read;
maybe_emit_filelist_progress(flist->used);
- if (verbose > 2) {
+ if (DEBUG_GTE(FLIST, 2)) {
rprintf(FINFO, "recv_file_name(%s)\n",
f_name(file, NULL));
}
}
file_total += flist->used;
- if (verbose > 2)
+ if (DEBUG_GTE(FLIST, 2))
rprintf(FINFO, "received %d names\n", flist->used);
if (show_filelist_p())
else
io_error |= read_int(f);
} else if (inc_recurse && flist->ndx_start == 1) {
- if (!file_total || strcmp(flist->sorted[0]->basename, ".") != 0)
+ if (!file_total || strcmp(flist->sorted[0]->basename, ".") != 0)
flist->parent_ndx = -1;
}
- if (verbose > 3)
+ if (DEBUG_GTE(FLIST, 3))
output_flist(flist);
- if (verbose > 2)
+ if (DEBUG_GTE(FLIST, 2))
rprintf(FINFO, "recv_file_list done\n");
stats.flist_size += stats.total_read - start_read;
NDX_FLIST_OFFSET - dir_flist->used + 1);
exit_cleanup(RERR_PROTOCOL);
}
- if (verbose > 3) {
+ if (DEBUG_GTE(FLIST, 3)) {
rprintf(FINFO, "[%s] receiving flist for dir %d\n",
who_am_i(), ndx);
}
if (flags & FLIST_TEMP) {
if (!(flist->file_pool = pool_create(SMALL_EXTENT, 0,
- out_of_memory, POOL_INTERN)))
+ out_of_memory,
+ POOL_INTERN)))
out_of_memory(msg);
} else {
/* This is a doubly linked list with prev looping back to
* the end of the list, but the last next pointer is NULL. */
if (!first_flist) {
flist->file_pool = pool_create(NORMAL_EXTENT, 0,
- out_of_memory, POOL_INTERN);
+ out_of_memory,
+ POOL_INTERN);
if (!flist->file_pool)
out_of_memory(msg);
keep = j, drop = i;
if (!am_sender) {
- if (verbose > 1) {
+ if (DEBUG_GTE(DUP, 1)) {
rprintf(FINFO,
"removing duplicate name %s from file list (%d)\n",
f_name(file, fbuf), drop + flist->ndx_start);
} else
root = dir = slash = name = trail = "";
rprintf(FINFO,
- "[%s] i=%d %s %s%s%s%s mode=0%o len=%.0f%s%s flags=%x\n",
+ "[%s] i=%d %s %s%s%s%s mode=0%o len=%s%s%s flags=%x\n",
who, i + flist->ndx_start,
root, dir, slash, name, trail,
- (int)file->mode, (double)F_LENGTH(file),
+ (int)file->mode, big_num(F_LENGTH(file), 0),
uidbuf, gidbuf, file->flags);
}
}
send_directory(ignore_filter_rules ? -2 : -1, dirlist, dirname, dlen, 0);
xfer_dirs = save_xfer_dirs;
recurse = save_recurse;
- if (do_progress)
+ if (INFO_GTE(PROGRESS, 1))
flist_count_offset += dirlist->used;
prune_empty_dirs = 0;
flist_sort_and_clean(dirlist, 0);
prune_empty_dirs = save_prune_empty_dirs;
- if (verbose > 3)
+ if (DEBUG_GTE(FLIST, 3))
output_flist(dirlist);
return dirlist;