version 1.1.1.3, 2016/11/01 09:54:32
|
version 1.1.1.4, 2021/03/17 00:32:36
|
Line 4
|
Line 4
|
* Copyright (C) 1996 Andrew Tridgell |
* Copyright (C) 1996 Andrew Tridgell |
* Copyright (C) 1996 Paul Mackerras |
* Copyright (C) 1996 Paul Mackerras |
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org> |
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org> |
* Copyright (C) 2002-2015 Wayne Davison | * Copyright (C) 2002-2020 Wayne Davison |
* |
* |
* This program is free software; you can redistribute it and/or modify |
* 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 |
* it under the terms of the GNU General Public License as published by |
Line 22
|
Line 22
|
|
|
#include "rsync.h" |
#include "rsync.h" |
#include "ifuncs.h" |
#include "ifuncs.h" |
|
#include "itypes.h" |
#include "rounding.h" |
#include "rounding.h" |
#include "inums.h" |
#include "inums.h" |
#include "io.h" |
#include "io.h" |
|
|
|
extern int dry_run; |
extern int am_root; |
extern int am_root; |
extern int am_server; |
extern int am_server; |
extern int am_daemon; |
extern int am_daemon; |
Line 33 extern int am_sender;
|
Line 35 extern int am_sender;
|
extern int am_generator; |
extern int am_generator; |
extern int inc_recurse; |
extern int inc_recurse; |
extern int always_checksum; |
extern int always_checksum; |
|
extern int basis_dir_cnt; |
|
extern int checksum_type; |
extern int module_id; |
extern int module_id; |
|
extern int ignore_case; |
extern int ignore_errors; |
extern int ignore_errors; |
extern int numeric_ids; |
extern int numeric_ids; |
|
extern int quiet; |
extern int recurse; |
extern int recurse; |
extern int use_qsort; |
extern int use_qsort; |
extern int xfer_dirs; |
extern int xfer_dirs; |
Line 50 extern int preserve_links;
|
Line 56 extern int preserve_links;
|
extern int preserve_hard_links; |
extern int preserve_hard_links; |
extern int preserve_devices; |
extern int preserve_devices; |
extern int preserve_specials; |
extern int preserve_specials; |
|
extern int preserve_fileflags; |
extern int delete_during; |
extern int delete_during; |
extern int missing_args; |
extern int missing_args; |
|
extern int use_db; |
extern int eol_nulls; |
extern int eol_nulls; |
|
extern int atimes_ndx; |
|
extern int crtimes_ndx; |
extern int relative_paths; |
extern int relative_paths; |
extern int implied_dirs; |
extern int implied_dirs; |
extern int ignore_perishable; |
extern int ignore_perishable; |
extern int non_perishable_cnt; |
extern int non_perishable_cnt; |
extern int prune_empty_dirs; |
extern int prune_empty_dirs; |
|
extern int checksum_files; |
extern int copy_links; |
extern int copy_links; |
extern int copy_unsafe_links; |
extern int copy_unsafe_links; |
|
extern int detect_renamed; |
extern int protocol_version; |
extern int protocol_version; |
extern int sanitize_paths; |
extern int sanitize_paths; |
extern int munge_symlinks; |
extern int munge_symlinks; |
Line 69 extern int sender_symlink_iconv;
|
Line 81 extern int sender_symlink_iconv;
|
extern int output_needs_newline; |
extern int output_needs_newline; |
extern int sender_keeps_checksum; |
extern int sender_keeps_checksum; |
extern int unsort_ndx; |
extern int unsort_ndx; |
|
extern char *basis_dir[]; |
extern uid_t our_uid; |
extern uid_t our_uid; |
extern struct stats stats; |
extern struct stats stats; |
extern char *filesfrom_host; |
extern char *filesfrom_host; |
extern char *usermap, *groupmap; |
extern char *usermap, *groupmap; |
|
extern char *tr_opt; |
|
|
extern char curr_dir[MAXPATHLEN]; |
extern char curr_dir[MAXPATHLEN]; |
|
|
Line 80 extern struct chmod_mode_struct *chmod_modes;
|
Line 94 extern struct chmod_mode_struct *chmod_modes;
|
|
|
extern filter_rule_list filter_list; |
extern filter_rule_list filter_list; |
extern filter_rule_list daemon_filter_list; |
extern filter_rule_list daemon_filter_list; |
|
extern filter_rule *last_hit_filter_rule; |
|
|
#ifdef ICONV_OPTION |
#ifdef ICONV_OPTION |
extern int filesfrom_convert; |
extern int filesfrom_convert; |
extern iconv_t ic_send, ic_recv; |
extern iconv_t ic_send, ic_recv; |
#endif |
#endif |
|
|
|
#ifdef HAVE_UTIMENSAT |
|
#ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC |
|
#define ST_MTIME_NSEC st_mtim.tv_nsec |
|
#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC) |
|
#define ST_MTIME_NSEC st_mtimensec |
|
#endif |
|
#endif |
|
|
|
#define RSYNCSUMS_FILE ".rsyncsums" |
|
#define RSYNCSUMS_LEN (sizeof RSYNCSUMS_FILE-1) |
|
|
|
#define CLEAN_STRIP_ROOT (1<<0) |
|
#define CLEAN_KEEP_LAST (1<<1) |
|
|
#define PTR_SIZE (sizeof (struct file_struct *)) |
#define PTR_SIZE (sizeof (struct file_struct *)) |
|
|
|
#define FLAG_SUM_MISSING (1<<1) /* F_SUM() data is undefined */ |
|
#define FLAG_SUM_KEEP (1<<2) /* keep entry when rewriting */ |
|
|
int io_error; |
int io_error; |
int checksum_len; | int flist_csum_len; |
dev_t filesystem_dev; /* used to implement -x */ |
dev_t filesystem_dev; /* used to implement -x */ |
|
|
struct file_list *cur_flist, *first_flist, *dir_flist; |
struct file_list *cur_flist, *first_flist, *dir_flist; |
Line 98 int flist_cnt = 0; /* how many (non-tmp) file list obj
|
Line 130 int flist_cnt = 0; /* how many (non-tmp) file list obj
|
int file_total = 0; /* total of all active items over all file-lists */ |
int file_total = 0; /* total of all active items over all file-lists */ |
int file_old_total = 0; /* total of active items that will soon be gone */ |
int file_old_total = 0; /* total of active items that will soon be gone */ |
int flist_eof = 0; /* all the file-lists are now known */ |
int flist_eof = 0; /* all the file-lists are now known */ |
|
int xfer_flags_as_varint = 0; |
|
|
|
char tr_substitutions[256]; |
|
|
#define NORMAL_NAME 0 |
#define NORMAL_NAME 0 |
#define SLASH_ENDING_NAME 1 |
#define SLASH_ENDING_NAME 1 |
#define DOTDIR_NAME 2 |
#define DOTDIR_NAME 2 |
Line 125 static int64 tmp_dev = -1, tmp_ino;
|
Line 160 static int64 tmp_dev = -1, tmp_ino;
|
#endif |
#endif |
static char tmp_sum[MAX_DIGEST_LEN]; |
static char tmp_sum[MAX_DIGEST_LEN]; |
|
|
|
struct file_list the_fattr_list; |
|
|
static char empty_sum[MAX_DIGEST_LEN]; |
static char empty_sum[MAX_DIGEST_LEN]; |
static int flist_count_offset; /* for --delete --progress */ |
static int flist_count_offset; /* for --delete --progress */ |
|
static int show_filelist_progress; |
|
|
static void flist_sort_and_clean(struct file_list *flist, int strip_root); | #define REGULAR_SKIPPED(flist) ((flist)->to_redo) |
| |
| static struct csum_cache { |
| struct file_list *flist; |
| const char *dirname; |
| int checksum_matches; |
| int checksum_updates; |
| } *csum_cache = NULL; |
| |
| static struct file_list *flist_new(int flags, const char *msg); |
| static void flist_sort_and_clean(struct file_list *flist, int flags); |
static void output_flist(struct file_list *flist); |
static void output_flist(struct file_list *flist); |
|
|
void init_flist(void) |
void init_flist(void) |
Line 137 void init_flist(void)
|
Line 185 void init_flist(void)
|
rprintf(FINFO, "FILE_STRUCT_LEN=%d, EXTRA_LEN=%d\n", |
rprintf(FINFO, "FILE_STRUCT_LEN=%d, EXTRA_LEN=%d\n", |
(int)FILE_STRUCT_LEN, (int)EXTRA_LEN); |
(int)FILE_STRUCT_LEN, (int)EXTRA_LEN); |
} |
} |
checksum_len = protocol_version < 21 ? 2 | flist_csum_len = csum_len_for_type(checksum_type, 1); |
: protocol_version < 30 ? MD4_DIGEST_LEN | |
: MD5_DIGEST_LEN; | |
} | |
|
|
static int show_filelist_p(void) | show_filelist_progress = INFO_GTE(FLIST, 1) && xfer_dirs && !am_server && !inc_recurse; |
{ | |
return INFO_GTE(FLIST, 1) && xfer_dirs && !am_server && !inc_recurse; | |
} |
} |
|
|
static void start_filelist_progress(char *kind) |
static void start_filelist_progress(char *kind) |
{ |
{ |
|
if (quiet) |
|
return; |
rprintf(FCLIENT, "%s ... ", kind); |
rprintf(FCLIENT, "%s ... ", kind); |
output_needs_newline = 1; |
output_needs_newline = 1; |
rflush(FINFO); |
rflush(FINFO); |
Line 156 static void start_filelist_progress(char *kind)
|
Line 201 static void start_filelist_progress(char *kind)
|
|
|
static void emit_filelist_progress(int count) |
static void emit_filelist_progress(int count) |
{ |
{ |
|
if (quiet) |
|
return; |
|
if (output_needs_newline == 2) /* avoid a newline in the middle of this filelist-progress output */ |
|
output_needs_newline = 0; |
rprintf(FCLIENT, " %d files...\r", count); |
rprintf(FCLIENT, " %d files...\r", count); |
|
output_needs_newline = 2; |
} |
} |
|
|
static void maybe_emit_filelist_progress(int count) |
static void maybe_emit_filelist_progress(int count) |
{ |
{ |
if (INFO_GTE(FLIST, 2) && show_filelist_p() && (count % 100) == 0) | if (INFO_GTE(FLIST, 2) && show_filelist_progress && (count % 100) == 0) |
emit_filelist_progress(count); |
emit_filelist_progress(count); |
} |
} |
|
|
static void finish_filelist_progress(const struct file_list *flist) |
static void finish_filelist_progress(const struct file_list *flist) |
{ |
{ |
|
output_needs_newline = 0; |
if (INFO_GTE(FLIST, 2)) { |
if (INFO_GTE(FLIST, 2)) { |
/* This overwrites the progress line */ |
/* This overwrites the progress line */ |
rprintf(FINFO, "%d file%sto consider\n", |
rprintf(FINFO, "%d file%sto consider\n", |
flist->used, flist->used == 1 ? " " : "s "); |
flist->used, flist->used == 1 ? " " : "s "); |
} else { |
} else { |
output_needs_newline = 0; |
|
rprintf(FINFO, "done\n"); |
rprintf(FINFO, "done\n"); |
} |
} |
} |
} |
Line 237 int link_stat(const char *path, STRUCT_STAT *stp, int
|
Line 287 int link_stat(const char *path, STRUCT_STAT *stp, int
|
#endif |
#endif |
} |
} |
|
|
static inline int is_daemon_excluded(const char *fname, int is_dir) |
|
{ |
|
if (daemon_filter_list.head |
|
&& check_filter(&daemon_filter_list, FLOG, fname, is_dir) < 0) { |
|
errno = ENOENT; |
|
return 1; |
|
} |
|
return 0; |
|
} |
|
|
|
static inline int path_is_daemon_excluded(char *path, int ignore_filename) |
static inline int path_is_daemon_excluded(char *path, int ignore_filename) |
{ |
{ |
if (daemon_filter_list.head) { |
if (daemon_filter_list.head) { |
Line 273 static inline int path_is_daemon_excluded(char *path,
|
Line 313 static inline int path_is_daemon_excluded(char *path,
|
return 0; |
return 0; |
} |
} |
|
|
/* This function is used to check if a file should be included/excluded | static inline int is_excluded(const char *fname, int is_dir, int filter_level) |
* from the list of files based on its name and type etc. The value of | |
* filter_level is set to either SERVER_FILTERS or ALL_FILTERS. */ | |
static int is_excluded(const char *fname, int is_dir, int filter_level) | |
{ |
{ |
#if 0 /* This currently never happens, so avoid a useless compare. */ | return name_is_excluded(fname, is_dir ? NAME_IS_DIR : NAME_IS_FILE, filter_level); |
if (filter_level == NO_FILTERS) | } |
return 0; | |
#endif | static int fattr_compare(struct file_struct **file1, struct file_struct **file2) |
if (is_daemon_excluded(fname, is_dir)) | { |
| struct file_struct *f1 = *file1; |
| struct file_struct *f2 = *file2; |
| int64 len1 = F_LENGTH(f1), len2 = F_LENGTH(f2); |
| int diff; |
| |
| if (!f1->basename || !S_ISREG(f1->mode) || !len1) { |
| if (!f2->basename || !S_ISREG(f2->mode) || !len2) |
| return 0; |
return 1; |
return 1; |
if (filter_level != ALL_FILTERS) | } |
| if (!f2->basename || !S_ISREG(f2->mode) || !len2) |
| return -1; |
| |
| /* Don't use diff for values that are longer than an int. */ |
| if (len1 != len2) |
| return len1 < len2 ? -1 : 1; |
| |
| if (always_checksum) { |
| diff = u_memcmp(F_SUM(f1), F_SUM(f2), flist_csum_len); |
| if (diff) |
| return diff; |
| } else if (f1->modtime != f2->modtime) |
| return f1->modtime < f2->modtime ? -1 : 1; |
| |
| diff = u_strcmp(f1->basename, f2->basename); |
| if (diff) |
| return diff; |
| |
| if (f1->dirname == f2->dirname) |
return 0; |
return 0; |
if (filter_list.head | if (!f1->dirname) |
&& check_filter(&filter_list, FINFO, fname, is_dir) < 0) | return -1; |
| if (!f2->dirname) |
return 1; |
return 1; |
return 0; | return u_strcmp(f1->dirname, f2->dirname); |
} |
} |
|
|
static void send_directory(int f, struct file_list *flist, |
static void send_directory(int f, struct file_list *flist, |
Line 318 static void flist_expand(struct file_list *flist, int
|
Line 383 static void flist_expand(struct file_list *flist, int
|
if (flist->malloced < flist->used + extra) |
if (flist->malloced < flist->used + extra) |
flist->malloced = flist->used + extra; |
flist->malloced = flist->used + extra; |
|
|
new_ptr = realloc_array(flist->files, struct file_struct *, | new_ptr = realloc_array(flist->files, struct file_struct *, flist->malloced); |
flist->malloced); | |
|
|
if (DEBUG_GTE(FLIST, 1) && flist->malloced != FLIST_START) { |
if (DEBUG_GTE(FLIST, 1) && flist->malloced != FLIST_START) { |
rprintf(FCLIENT, "[%s] expand file_list pointer array to %s bytes, did%s move\n", |
rprintf(FCLIENT, "[%s] expand file_list pointer array to %s bytes, did%s move\n", |
Line 329 static void flist_expand(struct file_list *flist, int
|
Line 393 static void flist_expand(struct file_list *flist, int
|
} |
} |
|
|
flist->files = new_ptr; |
flist->files = new_ptr; |
|
|
if (!flist->files) |
|
out_of_memory("flist_expand"); |
|
} |
} |
|
|
static void flist_done_allocating(struct file_list *flist) |
static void flist_done_allocating(struct file_list *flist) |
Line 343 static void flist_done_allocating(struct file_list *fl
|
Line 404 static void flist_done_allocating(struct file_list *fl
|
flist->pool_boundary = ptr; |
flist->pool_boundary = ptr; |
} |
} |
|
|
|
static void checksum_filename(int slot, const char *dirname, char *fbuf) |
|
{ |
|
if (dirname && *dirname) { |
|
unsigned int len; |
|
if (slot) { |
|
len = strlcpy(fbuf, basis_dir[slot-1], MAXPATHLEN); |
|
if (len >= MAXPATHLEN) |
|
return; |
|
} else |
|
len = 0; |
|
if (pathjoin(fbuf+len, MAXPATHLEN-len, dirname, RSYNCSUMS_FILE) >= MAXPATHLEN-len) |
|
return; |
|
} else |
|
strlcpy(fbuf, RSYNCSUMS_FILE, MAXPATHLEN); |
|
} |
|
|
|
static void write_checksums(int slot, struct file_list *flist, int whole_dir) |
|
{ |
|
int i; |
|
FILE *out_fp; |
|
char fbuf[MAXPATHLEN]; |
|
int new_entries = csum_cache[slot].checksum_updates != 0; |
|
int counts_match = flist->used == csum_cache[slot].checksum_matches; |
|
int no_skipped = whole_dir && REGULAR_SKIPPED(flist) == 0; |
|
const char *dirname = csum_cache[slot].dirname; |
|
|
|
flist_sort_and_clean(flist, 0); |
|
|
|
if (dry_run && !(checksum_files & CSF_AFFECT_DRYRUN)) |
|
return; |
|
|
|
checksum_filename(slot, dirname, fbuf); |
|
|
|
if (flist->high - flist->low < 0 && no_skipped) { |
|
unlink(fbuf); |
|
return; |
|
} |
|
|
|
if (!new_entries && (counts_match || !whole_dir)) |
|
return; |
|
|
|
if (!(out_fp = fopen(fbuf, "w"))) |
|
return; |
|
|
|
for (i = flist->low; i <= flist->high; i++) { |
|
struct file_struct *file = flist->sorted[i]; |
|
const char *cp = F_SUM(file); |
|
const char *end = cp + flist_csum_len; |
|
const char *alt_sum = file->basename + strlen(file->basename) + 1; |
|
if (whole_dir && !(file->flags & FLAG_SUM_KEEP)) |
|
continue; |
|
if (checksum_type == 5) |
|
fprintf(out_fp, "%s ", alt_sum); |
|
if (file->flags & FLAG_SUM_MISSING) { |
|
do { |
|
fputs("==", out_fp); |
|
} while (++cp != end); |
|
} else { |
|
do { |
|
fprintf(out_fp, "%02x", (int)CVAL(cp, 0)); |
|
} while (++cp != end); |
|
} |
|
if (checksum_type != 5) |
|
fprintf(out_fp, " %s", alt_sum); |
|
fprintf(out_fp, " %10.0f %10.0f %10lu %10lu %s\n", |
|
(double)F_LENGTH(file), (double)file->modtime, |
|
(long)F_CTIME(file), (long)F_INODE(file), file->basename); |
|
} |
|
|
|
fclose(out_fp); |
|
} |
|
|
|
void reset_checksum_cache(int whole_dir) |
|
{ |
|
int slot, slots = am_sender ? 1 : basis_dir_cnt + 1; |
|
|
|
if (!csum_cache) |
|
csum_cache = new_array0(struct csum_cache, slots); |
|
|
|
for (slot = 0; slot < slots; slot++) { |
|
struct file_list *flist = csum_cache[slot].flist; |
|
|
|
if (flist) { |
|
if (checksum_files & CSF_UPDATE && flist->next) |
|
write_checksums(slot, flist, whole_dir); |
|
|
|
/* Reset the pool memory and empty the file-list array. */ |
|
pool_free_old(flist->file_pool, |
|
pool_boundary(flist->file_pool, 0)); |
|
flist->used = 0; |
|
} else |
|
flist = csum_cache[slot].flist = flist_new(FLIST_TEMP, "reset_checksum_cache"); |
|
|
|
flist->low = 0; |
|
flist->high = -1; |
|
flist->next = NULL; |
|
|
|
csum_cache[slot].checksum_matches = 0; |
|
csum_cache[slot].checksum_updates = 0; |
|
REGULAR_SKIPPED(flist) = 0; |
|
} |
|
} |
|
|
|
/* The basename_len count is the length of the basename + 1 for the '\0'. */ |
|
static int add_checksum(struct file_list *flist, const char *dirname, |
|
const char *basename, int basename_len, OFF_T file_length, |
|
time_t mtime, uint32 ctime, uint32 inode, |
|
const char *sum, const char *alt_sum, int flags) |
|
{ |
|
struct file_struct *file; |
|
int alloc_len, extra_len; |
|
char *bp; |
|
|
|
if (basename_len == RSYNCSUMS_LEN+1 && *basename == '.' |
|
&& strcmp(basename, RSYNCSUMS_FILE) == 0) |
|
return 0; |
|
|
|
/* "2" is for a 32-bit ctime num and an 32-bit inode num. */ |
|
extra_len = (file_extra_cnt + (file_length > 0xFFFFFFFFu) + SUM_EXTRA_CNT + 2) |
|
* EXTRA_LEN; |
|
#if EXTRA_ROUNDING > 0 |
|
if (extra_len & (EXTRA_ROUNDING * EXTRA_LEN)) |
|
extra_len = (extra_len | (EXTRA_ROUNDING * EXTRA_LEN)) + EXTRA_LEN; |
|
#endif |
|
alloc_len = FILE_STRUCT_LEN + extra_len + basename_len + flist_csum_len*2 + 1; |
|
bp = pool_alloc(flist->file_pool, alloc_len, "add_checksum"); |
|
|
|
memset(bp, 0, extra_len + FILE_STRUCT_LEN); |
|
bp += extra_len; |
|
file = (struct file_struct *)bp; |
|
bp += FILE_STRUCT_LEN; |
|
|
|
memcpy(bp, basename, basename_len); |
|
if (alt_sum) |
|
strlcpy(bp+basename_len, alt_sum, flist_csum_len*2 + 1); |
|
else { |
|
memset(bp+basename_len, '=', flist_csum_len*2); |
|
bp[basename_len+flist_csum_len*2] = '\0'; |
|
} |
|
|
|
file->flags = flags; |
|
file->mode = S_IFREG; |
|
file->modtime = mtime; |
|
file->len32 = (uint32)file_length; |
|
if (file_length > 0xFFFFFFFFu) { |
|
file->flags |= FLAG_LENGTH64; |
|
OPT_EXTRA(file, 0)->unum = (uint32)(file_length >> 32); |
|
} |
|
file->dirname = dirname; |
|
F_CTIME(file) = ctime; |
|
F_INODE(file) = inode; |
|
bp = F_SUM(file); |
|
memcpy(bp, sum, flist_csum_len); |
|
|
|
flist_expand(flist, 1); |
|
flist->files[flist->used++] = file; |
|
|
|
flist->sorted = flist->files; |
|
|
|
return 1; |
|
} |
|
|
|
/* The "dirname" arg's data must remain unchanged during the lifespan of |
|
* the created csum_cache[].flist object because we use it directly. */ |
|
static void read_checksums(int slot, struct file_list *flist, const char *dirname) |
|
{ |
|
char line[MAXPATHLEN+1024], fbuf[MAXPATHLEN], sum[MAX_DIGEST_LEN]; |
|
FILE *fp; |
|
char *cp; |
|
time_t mtime; |
|
int len, i, flags; |
|
OFF_T file_length; |
|
uint32 ctime, inode; |
|
const char *alt_sum = NULL; |
|
int dlen = dirname ? strlcpy(fbuf, dirname, sizeof fbuf) : 0; |
|
|
|
if (dlen >= (int)(sizeof fbuf - 1 - RSYNCSUMS_LEN)) |
|
return; |
|
if (dlen) |
|
fbuf[dlen++] = '/'; |
|
else |
|
dirname = NULL; |
|
strlcpy(fbuf+dlen, RSYNCSUMS_FILE, sizeof fbuf - dlen); |
|
if (slot) { |
|
pathjoin(line, sizeof line, basis_dir[slot-1], fbuf); |
|
cp = line; |
|
} else |
|
cp = fbuf; |
|
if (!(fp = fopen(cp, "r"))) |
|
return; |
|
|
|
while (fgets(line, sizeof line, fp)) { |
|
cp = line; |
|
if (checksum_type == 5) { |
|
alt_sum = cp; |
|
if (*cp == '=') |
|
while (*++cp == '=') {} |
|
else |
|
while (isHexDigit(cp)) cp++; |
|
if (cp - alt_sum != MD4_DIGEST_LEN*2 || *cp != ' ') |
|
break; |
|
while (*++cp == ' ') {} |
|
} |
|
|
|
if (*cp == '=') { |
|
for (i = 0; i < flist_csum_len*2; i++, cp++) { |
|
if (*cp != '=') { |
|
cp = ""; |
|
break; |
|
} |
|
} |
|
memset(sum, 0, flist_csum_len); |
|
flags = FLAG_SUM_MISSING; |
|
} else { |
|
for (i = 0; i < flist_csum_len*2; i++, cp++) { |
|
int x; |
|
if (isHexDigit(cp)) { |
|
if (isDigit(cp)) |
|
x = *cp - '0'; |
|
else |
|
x = (*cp & 0xF) + 9; |
|
} else { |
|
cp = ""; |
|
break; |
|
} |
|
if (i & 1) |
|
sum[i/2] |= x; |
|
else |
|
sum[i/2] = x << 4; |
|
} |
|
flags = 0; |
|
} |
|
if (*cp != ' ') |
|
break; |
|
while (*++cp == ' ') {} |
|
|
|
if (checksum_type != 5) { |
|
alt_sum = cp; |
|
if (*cp == '=') |
|
while (*++cp == '=') {} |
|
else |
|
while (isHexDigit(cp)) cp++; |
|
if (cp - alt_sum != MD5_DIGEST_LEN*2 || *cp != ' ') |
|
break; |
|
while (*++cp == ' ') {} |
|
} |
|
|
|
file_length = 0; |
|
while (isDigit(cp)) |
|
file_length = file_length * 10 + *cp++ - '0'; |
|
if (*cp != ' ') |
|
break; |
|
while (*++cp == ' ') {} |
|
|
|
mtime = 0; |
|
while (isDigit(cp)) |
|
mtime = mtime * 10 + *cp++ - '0'; |
|
if (*cp != ' ') |
|
break; |
|
while (*++cp == ' ') {} |
|
|
|
ctime = 0; |
|
while (isDigit(cp)) |
|
ctime = ctime * 10 + *cp++ - '0'; |
|
if (*cp != ' ') |
|
break; |
|
while (*++cp == ' ') {} |
|
|
|
inode = 0; |
|
while (isDigit(cp)) |
|
inode = inode * 10 + *cp++ - '0'; |
|
if (*cp != ' ') |
|
break; |
|
while (*++cp == ' ') {} |
|
|
|
len = strlen(cp); |
|
while (len && (cp[len-1] == '\n' || cp[len-1] == '\r')) |
|
len--; |
|
if (!len) |
|
break; |
|
cp[len++] = '\0'; /* len now counts the null */ |
|
if (strchr(cp, '/')) |
|
break; |
|
if (len > MAXPATHLEN) |
|
continue; |
|
|
|
strlcpy(fbuf+dlen, cp, sizeof fbuf - dlen); |
|
if (is_excluded(fbuf, 0, ALL_FILTERS)) { |
|
flags |= FLAG_SUM_KEEP; |
|
csum_cache[slot].checksum_matches++; |
|
} |
|
|
|
add_checksum(flist, dirname, cp, len, file_length, |
|
mtime, ctime, inode, |
|
sum, alt_sum, flags); |
|
} |
|
fclose(fp); |
|
|
|
flist_sort_and_clean(flist, CLEAN_KEEP_LAST); |
|
} |
|
|
|
void set_cached_checksum(struct file_list *file_flist, struct file_struct *file) |
|
{ |
|
int j; |
|
FILE *out_fp; |
|
STRUCT_STAT st; |
|
char fbuf[MAXPATHLEN]; |
|
const char *fn = f_name(file, NULL); |
|
struct file_list *flist = csum_cache[0].flist; |
|
|
|
if (dry_run && !(checksum_files & CSF_AFFECT_DRYRUN)) |
|
return; |
|
|
|
if (stat(fn, &st) < 0) |
|
return; |
|
|
|
checksum_filename(0, file->dirname, fbuf); |
|
|
|
if (file_flist != flist->next) { |
|
const char *cp = F_SUM(file); |
|
const char *end = cp + flist_csum_len; |
|
|
|
if (!(out_fp = fopen(fbuf, "a"))) |
|
return; |
|
|
|
if (checksum_type == 5) { |
|
for (j = 0; j < flist_csum_len; j++) |
|
fputs("==", out_fp); |
|
fputc(' ', out_fp); |
|
} |
|
do { |
|
fprintf(out_fp, "%02x", (int)CVAL(cp, 0)); |
|
} while (++cp != end); |
|
if (checksum_type != 5) { |
|
fputc(' ', out_fp); |
|
for (j = 0; j < flist_csum_len; j++) |
|
fputs("==", out_fp); |
|
} |
|
fprintf(out_fp, " %10.0f %10.0f %10lu %10lu %s\n", |
|
(double)st.st_size, (double)st.st_mtime, |
|
(long)(uint32)st.st_ctime, (long)(uint32)st.st_ino, |
|
file->basename); |
|
|
|
fclose(out_fp); |
|
return; |
|
} |
|
|
|
if ((j = flist_find(flist, file)) >= 0) { |
|
struct file_struct *fp = flist->sorted[j]; |
|
int inc = 0; |
|
if (F_LENGTH(fp) != st.st_size) { |
|
fp->len32 = (uint32)st.st_size; |
|
if (st.st_size > 0xFFFFFFFFu) { |
|
OPT_EXTRA(fp, 0)->unum = (uint32)(st.st_size >> 32); |
|
fp->flags |= FLAG_LENGTH64; |
|
} else |
|
fp->flags &= FLAG_LENGTH64; |
|
inc = 1; |
|
} |
|
if (fp->modtime != st.st_mtime) { |
|
fp->modtime = st.st_mtime; |
|
inc = 1; |
|
} |
|
if (F_CTIME(fp) != (uint32)st.st_ctime) { |
|
F_CTIME(fp) = (uint32)st.st_ctime; |
|
inc = 1; |
|
} |
|
if (F_INODE(fp) != (uint32)st.st_ino) { |
|
F_INODE(fp) = (uint32)st.st_ino; |
|
inc = 1; |
|
} |
|
memcpy(F_SUM(fp), F_SUM(file), MAX_DIGEST_LEN); |
|
csum_cache[0].checksum_updates += inc; |
|
fp->flags &= ~FLAG_SUM_MISSING; |
|
fp->flags |= FLAG_SUM_KEEP; |
|
return; |
|
} |
|
|
|
csum_cache[0].checksum_updates += |
|
add_checksum(flist, file->dirname, file->basename, strlen(file->basename) + 1, |
|
st.st_size, (uint32)st.st_mtime, (uint32)st.st_ctime, |
|
st.st_ino, F_SUM(file), NULL, FLAG_SUM_KEEP); |
|
} |
|
|
|
void get_cached_checksum(int slot, const char *fname, struct file_struct *file, |
|
int basename_len, STRUCT_STAT *stp, char *sum_buf) |
|
{ |
|
struct file_list *flist = csum_cache[slot].flist; |
|
int j; |
|
|
|
if (!flist->next) { |
|
flist->next = cur_flist; /* next points from checksum flist to file flist */ |
|
csum_cache[slot].dirname = file->dirname; |
|
read_checksums(slot, flist, file->dirname); |
|
} |
|
|
|
if ((j = flist_find(flist, file)) >= 0) { |
|
struct file_struct *fp = flist->sorted[j]; |
|
|
|
if (F_LENGTH(fp) == stp->st_size |
|
&& fp->modtime == stp->st_mtime |
|
&& (checksum_files & CSF_LAX |
|
|| (F_CTIME(fp) == (uint32)stp->st_ctime |
|
&& F_INODE(fp) == (uint32)stp->st_ino))) { |
|
if (fp->flags & FLAG_SUM_MISSING) { |
|
fp->flags &= ~FLAG_SUM_MISSING; |
|
csum_cache[slot].checksum_updates++; |
|
file_checksum(fname, stp, sum_buf); |
|
memcpy(F_SUM(fp), sum_buf, MAX_DIGEST_LEN); |
|
} else { |
|
csum_cache[slot].checksum_matches++; |
|
memcpy(sum_buf, F_SUM(fp), MAX_DIGEST_LEN); |
|
} |
|
fp->flags |= FLAG_SUM_KEEP; |
|
return; |
|
} |
|
clear_file(fp); |
|
} |
|
|
|
file_checksum(fname, stp, sum_buf); |
|
|
|
if (checksum_files & CSF_UPDATE) { |
|
if (basename_len < 0) |
|
basename_len = strlen(file->basename) + 1; |
|
csum_cache[slot].checksum_updates += |
|
add_checksum(flist, file->dirname, file->basename, basename_len, |
|
stp->st_size, stp->st_mtime, (uint32)stp->st_ctime, |
|
(uint32)stp->st_ino, sum_buf, NULL, FLAG_SUM_KEEP); |
|
} |
|
} |
|
|
/* Call this with EITHER (1) "file, NULL, 0" to chdir() to the file's |
/* Call this with EITHER (1) "file, NULL, 0" to chdir() to the file's |
* F_PATHNAME(), or (2) "NULL, dir, dirlen" to chdir() to the supplied dir, |
* F_PATHNAME(), or (2) "NULL, dir, dirlen" to chdir() to the supplied dir, |
* with dir == NULL taken to be the starting directory, and dirlen < 0 |
* with dir == NULL taken to be the starting directory, and dirlen < 0 |
Line 397 static void send_file_entry(int f, const char *fname,
|
Line 889 static void send_file_entry(int f, const char *fname,
|
#endif |
#endif |
int ndx, int first_ndx) |
int ndx, int first_ndx) |
{ |
{ |
static time_t modtime; | static time_t modtime, atime; |
| #ifdef SUPPORT_CRTIMES |
| static time_t crtime; |
| #endif |
static mode_t mode; |
static mode_t mode; |
|
#ifdef SUPPORT_FILEFLAGS |
|
static uint32 fileflags; |
|
#endif |
#ifdef SUPPORT_HARD_LINKS |
#ifdef SUPPORT_HARD_LINKS |
static int64 dev; |
static int64 dev; |
#endif |
#endif |
Line 442 static void send_file_entry(int f, const char *fname,
|
Line 940 static void send_file_entry(int f, const char *fname,
|
xflags |= XMIT_SAME_MODE; |
xflags |= XMIT_SAME_MODE; |
else |
else |
mode = file->mode; |
mode = file->mode; |
|
#ifdef SUPPORT_FILEFLAGS |
|
if (preserve_fileflags) { |
|
if (F_FFLAGS(file) == fileflags) |
|
xflags |= XMIT_SAME_FLAGS; |
|
else |
|
fileflags = F_FFLAGS(file); |
|
} |
|
#endif |
|
|
if (preserve_devices && IS_DEVICE(mode)) { |
if (preserve_devices && IS_DEVICE(mode)) { |
if (protocol_version < 28) { |
if (protocol_version < 28) { |
Line 464 static void send_file_entry(int f, const char *fname,
|
Line 970 static void send_file_entry(int f, const char *fname,
|
if (protocol_version < 28) |
if (protocol_version < 28) |
xflags |= XMIT_SAME_RDEV_pre28; |
xflags |= XMIT_SAME_RDEV_pre28; |
else { |
else { |
rdev = MAKEDEV(major(rdev), 0); | rdev = MAKEDEV(rdev_major, 0); |
xflags |= XMIT_SAME_RDEV_MAJOR; |
xflags |= XMIT_SAME_RDEV_MAJOR; |
if (protocol_version < 30) |
if (protocol_version < 30) |
xflags |= XMIT_RDEV_MINOR_8_pre30; |
xflags |= XMIT_RDEV_MINOR_8_pre30; |
Line 497 static void send_file_entry(int f, const char *fname,
|
Line 1003 static void send_file_entry(int f, const char *fname,
|
modtime = file->modtime; |
modtime = file->modtime; |
if (NSEC_BUMP(file) && protocol_version >= 31) |
if (NSEC_BUMP(file) && protocol_version >= 31) |
xflags |= XMIT_MOD_NSEC; |
xflags |= XMIT_MOD_NSEC; |
|
if (atimes_ndx && !S_ISDIR(mode)) { |
|
if (F_ATIME(file) == atime) |
|
xflags |= XMIT_SAME_ATIME; |
|
else |
|
atime = F_ATIME(file); |
|
} |
|
#ifdef SUPPORT_CRTIMES |
|
if (crtimes_ndx) { |
|
crtime = F_CRTIME(file); |
|
if (crtime == modtime) |
|
xflags |= XMIT_CRTIME_EQ_MTIME; |
|
} |
|
#endif |
|
|
#ifdef SUPPORT_HARD_LINKS |
#ifdef SUPPORT_HARD_LINKS |
if (tmp_dev != -1) { |
if (tmp_dev != -1) { |
if (protocol_version >= 30) { |
if (protocol_version >= 30) { |
struct ht_int64_node *np = idev_find(tmp_dev, tmp_ino); |
struct ht_int64_node *np = idev_find(tmp_dev, tmp_ino); |
first_hlink_ndx = (int32)(long)np->data - 1; | first_hlink_ndx = (int32)(long)np->data; /* is -1 when new */ |
if (first_hlink_ndx < 0) { |
if (first_hlink_ndx < 0) { |
np->data = (void*)(long)(first_ndx + ndx + 1); | np->data = (void*)(long)(first_ndx + ndx); |
xflags |= XMIT_HLINK_FIRST; |
xflags |= XMIT_HLINK_FIRST; |
} |
} |
if (DEBUG_GTE(HLINK, 1)) { |
if (DEBUG_GTE(HLINK, 1)) { |
Line 539 static void send_file_entry(int f, const char *fname,
|
Line 1058 static void send_file_entry(int f, const char *fname,
|
if (l2 > 255) |
if (l2 > 255) |
xflags |= XMIT_LONG_NAME; |
xflags |= XMIT_LONG_NAME; |
|
|
/* We must make sure we don't send a zero flag byte or the | /* We must avoid sending a flag value of 0 (or an initial byte of |
* other end will terminate the flist transfer. Note that | * 0 for the older xflags protocol) or it will signal the end of |
* the use of XMIT_TOP_DIR on a non-dir has no meaning, so | * the list. Note that the use of XMIT_TOP_DIR on a non-dir has |
* it's harmless way to add a bit to the first flag byte. */ | * no meaning, so it's a harmless way to add a bit to the first |
if (protocol_version >= 28) { | * flag byte. */ |
| if (xfer_flags_as_varint) |
| write_varint(f, xflags ? xflags : XMIT_EXTENDED_FLAGS); |
| else if (protocol_version >= 28) { |
if (!xflags && !S_ISDIR(mode)) |
if (!xflags && !S_ISDIR(mode)) |
xflags |= XMIT_TOP_DIR; |
xflags |= XMIT_TOP_DIR; |
if ((xflags & 0xFF00) || !xflags) { |
if ((xflags & 0xFF00) || !xflags) { |
Line 581 static void send_file_entry(int f, const char *fname,
|
Line 1103 static void send_file_entry(int f, const char *fname,
|
} |
} |
if (xflags & XMIT_MOD_NSEC) |
if (xflags & XMIT_MOD_NSEC) |
write_varint(f, F_MOD_NSEC(file)); |
write_varint(f, F_MOD_NSEC(file)); |
|
#ifdef SUPPORT_CRTIMES |
|
if (crtimes_ndx && !(xflags & XMIT_CRTIME_EQ_MTIME)) |
|
write_varlong(f, crtime, 4); |
|
#endif |
if (!(xflags & XMIT_SAME_MODE)) |
if (!(xflags & XMIT_SAME_MODE)) |
write_int(f, to_wire_mode(mode)); |
write_int(f, to_wire_mode(mode)); |
|
#ifdef SUPPORT_FILEFLAGS |
|
if (preserve_fileflags && !(xflags & XMIT_SAME_FLAGS)) |
|
write_int(f, (int)fileflags); |
|
#endif |
|
if (atimes_ndx && !S_ISDIR(mode) && !(xflags & XMIT_SAME_ATIME)) |
|
write_varlong(f, atime, 4); |
if (preserve_uid && !(xflags & XMIT_SAME_UID)) { |
if (preserve_uid && !(xflags & XMIT_SAME_UID)) { |
if (protocol_version < 30) |
if (protocol_version < 30) |
write_int(f, uid); |
write_int(f, uid); |
Line 656 static void send_file_entry(int f, const char *fname,
|
Line 1188 static void send_file_entry(int f, const char *fname,
|
/* Prior to 28, we sent a useless set of nulls. */ |
/* Prior to 28, we sent a useless set of nulls. */ |
sum = empty_sum; |
sum = empty_sum; |
} |
} |
write_buf(f, sum, checksum_len); | write_buf(f, sum, flist_csum_len); |
} |
} |
|
|
#ifdef SUPPORT_HARD_LINKS |
#ifdef SUPPORT_HARD_LINKS |
Line 668 static void send_file_entry(int f, const char *fname,
|
Line 1200 static void send_file_entry(int f, const char *fname,
|
stats.total_size += F_LENGTH(file); |
stats.total_size += F_LENGTH(file); |
} |
} |
|
|
|
static void transliterate(char *path, int len) |
|
{ |
|
while (1) { |
|
/* Find position of any char in tr_opt in path, or the end of the path. */ |
|
int span = strcspn(path, tr_opt); |
|
if ((len -= span) == 0) |
|
return; |
|
path += span; |
|
if ((*path = tr_substitutions[*(uchar*)path]) == '\0') |
|
memmove(path, path+1, len--); /* copies the trailing '\0' too. */ |
|
else { |
|
path++; |
|
len--; |
|
} |
|
} |
|
} |
|
|
static struct file_struct *recv_file_entry(int f, struct file_list *flist, int xflags) |
static struct file_struct *recv_file_entry(int f, struct file_list *flist, int xflags) |
{ |
{ |
static int64 modtime; | static int64 modtime, atime; |
| #ifdef SUPPORT_CRTIMES |
| static time_t crtime; |
| #endif |
static mode_t mode; |
static mode_t mode; |
|
#ifdef SUPPORT_FILEFLAGS |
|
static uint32 fileflags; |
|
#endif |
#ifdef SUPPORT_HARD_LINKS |
#ifdef SUPPORT_HARD_LINKS |
static int64 dev; |
static int64 dev; |
#endif |
#endif |
Line 690 static struct file_struct *recv_file_entry(int f, stru
|
Line 1245 static struct file_struct *recv_file_entry(int f, stru
|
int extra_len = file_extra_cnt * EXTRA_LEN; |
int extra_len = file_extra_cnt * EXTRA_LEN; |
int first_hlink_ndx = -1; |
int first_hlink_ndx = -1; |
int64 file_length; |
int64 file_length; |
|
#ifdef CAN_SET_NSEC |
uint32 modtime_nsec; |
uint32 modtime_nsec; |
|
#endif |
const char *basename; |
const char *basename; |
struct file_struct *file; |
struct file_struct *file; |
alloc_pool_t *pool; |
alloc_pool_t *pool; |
Line 733 static struct file_struct *recv_file_entry(int f, stru
|
Line 1290 static struct file_struct *recv_file_entry(int f, stru
|
outbuf.len = 0; |
outbuf.len = 0; |
} |
} |
thisname[outbuf.len] = '\0'; |
thisname[outbuf.len] = '\0'; |
|
basename_len = outbuf.len; |
} |
} |
#endif |
#endif |
|
|
|
if (tr_opt) |
|
transliterate(thisname, basename_len); |
|
|
if (*thisname |
if (*thisname |
&& (clean_fname(thisname, CFN_REFUSE_DOT_DOT_DIRS) < 0 || (!relative_paths && *thisname == '/'))) { |
&& (clean_fname(thisname, CFN_REFUSE_DOT_DOT_DIRS) < 0 || (!relative_paths && *thisname == '/'))) { |
rprintf(FERROR, "ABORTING due to unsafe pathname from sender: %s\n", thisname); |
rprintf(FERROR, "ABORTING due to unsafe pathname from sender: %s\n", thisname); |
Line 777 static struct file_struct *recv_file_entry(int f, stru
|
Line 1338 static struct file_struct *recv_file_entry(int f, stru
|
struct file_struct *first = flist->files[first_hlink_ndx - flist->ndx_start]; |
struct file_struct *first = flist->files[first_hlink_ndx - flist->ndx_start]; |
file_length = F_LENGTH(first); |
file_length = F_LENGTH(first); |
modtime = first->modtime; |
modtime = first->modtime; |
modtime_nsec = F_MOD_NSEC(first); | #ifdef CAN_SET_NSEC |
| modtime_nsec = F_MOD_NSEC_or_0(first); |
| #endif |
mode = first->mode; |
mode = first->mode; |
|
if (atimes_ndx && !S_ISDIR(mode)) |
|
atime = F_ATIME(first); |
|
#ifdef SUPPORT_CRTIMES |
|
if (crtimes_ndx) |
|
crtime = F_CRTIME(first); |
|
#endif |
|
#ifdef SUPPORT_FILEFLAGS |
|
if (preserve_fileflags) |
|
fileflags = F_FFLAGS(first); |
|
#endif |
if (preserve_uid) |
if (preserve_uid) |
uid = F_OWNER(first); |
uid = F_OWNER(first); |
if (preserve_gid) |
if (preserve_gid) |
gid = F_GROUP(first); |
gid = F_GROUP(first); |
if (preserve_devices && IS_DEVICE(mode)) { |
if (preserve_devices && IS_DEVICE(mode)) { |
uint32 *devp = F_RDEV_P(first); |
uint32 *devp = F_RDEV_P(first); |
rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp)); | rdev_major = DEV_MAJOR(devp); |
| rdev = MAKEDEV(rdev_major, DEV_MINOR(devp)); |
extra_len += DEV_EXTRA_CNT * EXTRA_LEN; |
extra_len += DEV_EXTRA_CNT * EXTRA_LEN; |
} |
} |
if (preserve_links && S_ISLNK(mode)) |
if (preserve_links && S_ISLNK(mode)) |
Line 812 static struct file_struct *recv_file_entry(int f, stru
|
Line 1386 static struct file_struct *recv_file_entry(int f, stru
|
modtime = read_int(f); |
modtime = read_int(f); |
} |
} |
if (xflags & XMIT_MOD_NSEC) |
if (xflags & XMIT_MOD_NSEC) |
|
#ifndef CAN_SET_NSEC |
|
(void)read_varint(f); |
|
#else |
modtime_nsec = read_varint(f); |
modtime_nsec = read_varint(f); |
else |
else |
modtime_nsec = 0; |
modtime_nsec = 0; |
|
#endif |
|
#ifdef SUPPORT_CRTIMES |
|
if (crtimes_ndx) { |
|
if (xflags & XMIT_CRTIME_EQ_MTIME) |
|
crtime = modtime; |
|
else |
|
crtime = read_varlong(f, 4); |
|
#if SIZEOF_TIME_T < SIZEOF_INT64 |
|
if (!am_generator && (int64)(time_t)crtime != crtime) { |
|
rprintf(FERROR_XFER, |
|
"Create time value of %s truncated on receiver.\n", |
|
lastname); |
|
} |
|
#endif |
|
} |
|
#endif |
if (!(xflags & XMIT_SAME_MODE)) |
if (!(xflags & XMIT_SAME_MODE)) |
mode = from_wire_mode(read_int(f)); |
mode = from_wire_mode(read_int(f)); |
|
if (atimes_ndx && !S_ISDIR(mode) && !(xflags & XMIT_SAME_ATIME)) { |
|
atime = read_varlong(f, 4); |
|
#if SIZEOF_TIME_T < SIZEOF_INT64 |
|
if (!am_generator && (int64)(time_t)atime != atime) { |
|
rprintf(FERROR_XFER, |
|
"Access time value of %s truncated on receiver.\n", |
|
lastname); |
|
} |
|
#endif |
|
} |
|
|
if (chmod_modes && !S_ISLNK(mode) && mode) |
if (chmod_modes && !S_ISLNK(mode) && mode) |
mode = tweak_mode(mode, chmod_modes); |
mode = tweak_mode(mode, chmod_modes); |
|
#ifdef SUPPORT_FILEFLAGS |
|
if (preserve_fileflags && !(xflags & XMIT_SAME_FLAGS)) |
|
fileflags = (uint32)read_int(f); |
|
#endif |
|
|
if (preserve_uid && !(xflags & XMIT_SAME_UID)) { |
if (preserve_uid && !(xflags & XMIT_SAME_UID)) { |
if (protocol_version < 30) |
if (protocol_version < 30) |
Line 913 static struct file_struct *recv_file_entry(int f, stru
|
Line 1520 static struct file_struct *recv_file_entry(int f, stru
|
if (file_length > 0xFFFFFFFFu && S_ISREG(mode)) |
if (file_length > 0xFFFFFFFFu && S_ISREG(mode)) |
extra_len += EXTRA_LEN; |
extra_len += EXTRA_LEN; |
#endif |
#endif |
#ifdef HAVE_UTIMENSAT | #ifdef CAN_SET_NSEC |
if (modtime_nsec) |
if (modtime_nsec) |
extra_len += EXTRA_LEN; |
extra_len += EXTRA_LEN; |
#endif |
#endif |
Line 959 static struct file_struct *recv_file_entry(int f, stru
|
Line 1566 static struct file_struct *recv_file_entry(int f, stru
|
file->flags |= FLAG_HLINKED; |
file->flags |= FLAG_HLINKED; |
#endif |
#endif |
file->modtime = (time_t)modtime; |
file->modtime = (time_t)modtime; |
#ifdef HAVE_UTIMENSAT | #ifdef CAN_SET_NSEC |
if (modtime_nsec) { |
if (modtime_nsec) { |
file->flags |= FLAG_MOD_NSEC; |
file->flags |= FLAG_MOD_NSEC; |
OPT_EXTRA(file, 0)->unum = modtime_nsec; | F_MOD_NSEC(file) = modtime_nsec; |
} |
} |
#endif |
#endif |
file->len32 = (uint32)file_length; |
file->len32 = (uint32)file_length; |
Line 973 static struct file_struct *recv_file_entry(int f, stru
|
Line 1580 static struct file_struct *recv_file_entry(int f, stru
|
exit_cleanup(RERR_UNSUPPORTED); |
exit_cleanup(RERR_UNSUPPORTED); |
#else |
#else |
file->flags |= FLAG_LENGTH64; |
file->flags |= FLAG_LENGTH64; |
OPT_EXTRA(file, NSEC_BUMP(file))->unum = (uint32)(file_length >> 32); | F_HIGH_LEN(file) = (uint32)(file_length >> 32); |
#endif |
#endif |
} |
} |
#endif |
#endif |
file->mode = mode; |
file->mode = mode; |
|
#ifdef SUPPORT_FILEFLAGS |
|
if (preserve_fileflags) |
|
F_FFLAGS(file) = fileflags; |
|
#endif |
if (preserve_uid) |
if (preserve_uid) |
F_OWNER(file) = uid; |
F_OWNER(file) = uid; |
if (preserve_gid) { |
if (preserve_gid) { |
F_GROUP(file) = gid; |
F_GROUP(file) = gid; |
file->flags |= gid_flags; |
file->flags |= gid_flags; |
} |
} |
|
if (atimes_ndx && !S_ISDIR(mode)) |
|
F_ATIME(file) = atime; |
|
#ifdef SUPPORT_CRTIMES |
|
if (crtimes_ndx) |
|
F_CRTIME(file) = crtime; |
|
#endif |
if (unsort_ndx) |
if (unsort_ndx) |
F_NDX(file) = flist->used + flist->ndx_start; |
F_NDX(file) = flist->used + flist->ndx_start; |
|
|
Line 1093 static struct file_struct *recv_file_entry(int f, stru
|
Line 1710 static struct file_struct *recv_file_entry(int f, stru
|
ino = read_longint(f); |
ino = read_longint(f); |
} |
} |
np = idev_find(dev, ino); |
np = idev_find(dev, ino); |
ndx = (int32)(long)np->data - 1; | ndx = (int32)(long)np->data; /* is -1 when new */ |
if (ndx < 0) { |
if (ndx < 0) { |
ndx = cnt++; |
|
np->data = (void*)(long)cnt; |
np->data = (void*)(long)cnt; |
|
ndx = cnt++; |
} |
} |
F_HL_GNUM(file) = ndx; |
F_HL_GNUM(file) = ndx; |
} |
} |
Line 1112 static struct file_struct *recv_file_entry(int f, stru
|
Line 1729 static struct file_struct *recv_file_entry(int f, stru
|
} |
} |
if (first_hlink_ndx >= flist->ndx_start) { |
if (first_hlink_ndx >= flist->ndx_start) { |
struct file_struct *first = flist->files[first_hlink_ndx - flist->ndx_start]; |
struct file_struct *first = flist->files[first_hlink_ndx - flist->ndx_start]; |
memcpy(bp, F_SUM(first), checksum_len); | memcpy(bp, F_SUM(first), flist_csum_len); |
} else |
} else |
read_buf(f, bp, checksum_len); | read_buf(f, bp, flist_csum_len); |
} |
} |
|
|
#ifdef SUPPORT_ACLS |
#ifdef SUPPORT_ACLS |
Line 1146 struct file_struct *make_file(const char *fname, struc
|
Line 1763 struct file_struct *make_file(const char *fname, struc
|
STRUCT_STAT *stp, int flags, int filter_level) |
STRUCT_STAT *stp, int flags, int filter_level) |
{ |
{ |
static char *lastdir; |
static char *lastdir; |
static int lastdir_len = -1; | static int lastdir_len = -2; |
struct file_struct *file; |
struct file_struct *file; |
char thisname[MAXPATHLEN]; |
char thisname[MAXPATHLEN]; |
char linkname[MAXPATHLEN]; |
char linkname[MAXPATHLEN]; |
Line 1174 struct file_struct *make_file(const char *fname, struc
|
Line 1791 struct file_struct *make_file(const char *fname, struc
|
} else if (readlink_stat(thisname, &st, linkname) != 0) { |
} else if (readlink_stat(thisname, &st, linkname) != 0) { |
int save_errno = errno; |
int save_errno = errno; |
/* See if file is excluded before reporting an error. */ |
/* See if file is excluded before reporting an error. */ |
if (filter_level != NO_FILTERS | if (filter_level != NO_FILTERS && filter_level != ALL_FILTERS_NO_EXCLUDE |
&& (is_excluded(thisname, 0, filter_level) |
&& (is_excluded(thisname, 0, filter_level) |
|| is_excluded(thisname, 1, filter_level))) { |
|| is_excluded(thisname, 1, filter_level))) { |
if (ignore_perishable && save_errno != ENOENT) |
if (ignore_perishable && save_errno != ENOENT) |
Line 1219 struct file_struct *make_file(const char *fname, struc
|
Line 1836 struct file_struct *make_file(const char *fname, struc
|
|
|
if (filter_level == NO_FILTERS) |
if (filter_level == NO_FILTERS) |
goto skip_filters; |
goto skip_filters; |
|
if (filter_level == ALL_FILTERS_NO_EXCLUDE) { |
|
/* Call only for the side effect of setting last_hit_filter_rule to |
|
* any operative include filter, which might affect attributes. */ |
|
is_excluded(thisname, S_ISDIR(st.st_mode) != 0, ALL_FILTERS); |
|
goto skip_filters; |
|
} |
|
|
if (S_ISDIR(st.st_mode)) { |
if (S_ISDIR(st.st_mode)) { |
if (!xfer_dirs) { |
if (!xfer_dirs) { |
Line 1247 struct file_struct *make_file(const char *fname, struc
|
Line 1870 struct file_struct *make_file(const char *fname, struc
|
if (is_excluded(thisname, S_ISDIR(st.st_mode) != 0, filter_level)) { |
if (is_excluded(thisname, S_ISDIR(st.st_mode) != 0, filter_level)) { |
if (ignore_perishable) |
if (ignore_perishable) |
non_perishable_cnt++; |
non_perishable_cnt++; |
|
if (S_ISREG(st.st_mode)) |
|
REGULAR_SKIPPED(flist)++; |
return NULL; |
return NULL; |
} |
} |
|
|
Line 1292 struct file_struct *make_file(const char *fname, struc
|
Line 1917 struct file_struct *make_file(const char *fname, struc
|
memcpy(lastdir, thisname, len); |
memcpy(lastdir, thisname, len); |
lastdir[len] = '\0'; |
lastdir[len] = '\0'; |
lastdir_len = len; |
lastdir_len = len; |
|
if (checksum_files && am_sender && flist) |
|
reset_checksum_cache(0); |
} |
} |
} else | } else { |
basename = thisname; |
basename = thisname; |
|
if (checksum_files && am_sender && flist && lastdir_len == -2) { |
|
lastdir_len = -1; |
|
reset_checksum_cache(0); |
|
} |
|
} |
basename_len = strlen(basename) + 1; /* count the '\0' */ |
basename_len = strlen(basename) + 1; /* count the '\0' */ |
|
|
#ifdef SUPPORT_LINKS |
#ifdef SUPPORT_LINKS |
Line 1312 struct file_struct *make_file(const char *fname, struc
|
Line 1944 struct file_struct *make_file(const char *fname, struc
|
extra_len += EXTRA_LEN; |
extra_len += EXTRA_LEN; |
#endif |
#endif |
|
|
if (always_checksum && am_sender && S_ISREG(st.st_mode)) { | if (sender_keeps_checksum && S_ISREG(st.st_mode)) |
file_checksum(thisname, &st, tmp_sum); | extra_len += SUM_EXTRA_CNT * EXTRA_LEN; |
if (sender_keeps_checksum) | |
extra_len += SUM_EXTRA_CNT * EXTRA_LEN; | |
} | |
|
|
#if EXTRA_ROUNDING > 0 |
#if EXTRA_ROUNDING > 0 |
if (extra_len & (EXTRA_ROUNDING * EXTRA_LEN)) |
if (extra_len & (EXTRA_ROUNDING * EXTRA_LEN)) |
Line 1327 struct file_struct *make_file(const char *fname, struc
|
Line 1956 struct file_struct *make_file(const char *fname, struc
|
+ linkname_len; |
+ linkname_len; |
if (pool) |
if (pool) |
bp = pool_alloc(pool, alloc_len, "make_file"); |
bp = pool_alloc(pool, alloc_len, "make_file"); |
else { | else |
if (!(bp = new_array(char, alloc_len))) | bp = new_array(char, alloc_len); |
out_of_memory("make_file"); | |
} | |
|
|
memset(bp, 0, extra_len + FILE_STRUCT_LEN); |
memset(bp, 0, extra_len + FILE_STRUCT_LEN); |
bp += extra_len; |
bp += extra_len; |
Line 1364 struct file_struct *make_file(const char *fname, struc
|
Line 1991 struct file_struct *make_file(const char *fname, struc
|
#ifdef ST_MTIME_NSEC |
#ifdef ST_MTIME_NSEC |
if (st.ST_MTIME_NSEC && protocol_version >= 31) { |
if (st.ST_MTIME_NSEC && protocol_version >= 31) { |
file->flags |= FLAG_MOD_NSEC; |
file->flags |= FLAG_MOD_NSEC; |
OPT_EXTRA(file, 0)->unum = st.ST_MTIME_NSEC; | F_MOD_NSEC(file) = st.ST_MTIME_NSEC; |
} |
} |
#endif |
#endif |
file->len32 = (uint32)st.st_size; |
file->len32 = (uint32)st.st_size; |
#if SIZEOF_CAPITAL_OFF_T >= 8 |
#if SIZEOF_CAPITAL_OFF_T >= 8 |
if (st.st_size > 0xFFFFFFFFu && S_ISREG(st.st_mode)) { |
if (st.st_size > 0xFFFFFFFFu && S_ISREG(st.st_mode)) { |
file->flags |= FLAG_LENGTH64; |
file->flags |= FLAG_LENGTH64; |
OPT_EXTRA(file, NSEC_BUMP(file))->unum = (uint32)(st.st_size >> 32); | F_HIGH_LEN(file) = (uint32)(st.st_size >> 32); |
} |
} |
#endif |
#endif |
file->mode = st.st_mode; |
file->mode = st.st_mode; |
|
#if defined SUPPORT_FILEFLAGS || defined SUPPORT_FORCE_CHANGE |
|
if (fileflags_ndx) |
|
F_FFLAGS(file) = st.st_flags; |
|
#endif |
if (preserve_uid) |
if (preserve_uid) |
F_OWNER(file) = st.st_uid; |
F_OWNER(file) = st.st_uid; |
if (preserve_gid) |
if (preserve_gid) |
F_GROUP(file) = st.st_gid; |
F_GROUP(file) = st.st_gid; |
if (am_generator && st.st_uid == our_uid) |
if (am_generator && st.st_uid == our_uid) |
file->flags |= FLAG_OWNED_BY_US; |
file->flags |= FLAG_OWNED_BY_US; |
|
if (atimes_ndx && !S_ISDIR(file->mode)) |
|
F_ATIME(file) = st.st_atime; |
|
#ifdef SUPPORT_CRTIMES |
|
if (crtimes_ndx) |
|
F_CRTIME(file) = get_create_time(fname); |
|
#endif |
|
|
if (basename != thisname) |
if (basename != thisname) |
file->dirname = lastdir; |
file->dirname = lastdir; |
Line 1401 struct file_struct *make_file(const char *fname, struc
|
Line 2038 struct file_struct *make_file(const char *fname, struc
|
return NULL; |
return NULL; |
} |
} |
|
|
if (sender_keeps_checksum && S_ISREG(st.st_mode)) | if (always_checksum && am_sender && S_ISREG(st.st_mode)) { |
memcpy(F_SUM(file), tmp_sum, checksum_len); | if (flist && checksum_files) |
| get_cached_checksum(0, thisname, file, basename_len, &st, tmp_sum); |
| else |
| file_checksum(thisname, &st, tmp_sum); |
| if (sender_keeps_checksum) |
| memcpy(F_SUM(file), tmp_sum, flist_csum_len); |
| } |
|
|
if (unsort_ndx) |
if (unsort_ndx) |
F_NDX(file) = stats.num_dirs; |
F_NDX(file) = stats.num_dirs; |
Line 1410 struct file_struct *make_file(const char *fname, struc
|
Line 2053 struct file_struct *make_file(const char *fname, struc
|
return file; |
return file; |
} |
} |
|
|
|
OFF_T get_device_size(int fd, const char *fname) |
|
{ |
|
OFF_T off = lseek(fd, 0, SEEK_END); |
|
|
|
if (off == (OFF_T) -1) { |
|
rsyserr(FERROR, errno, "failed to get device size via seek: %s", fname); |
|
return 0; |
|
} |
|
if (lseek(fd, 0, SEEK_SET) != 0) |
|
rsyserr(FERROR, errno, "failed to seek device back to start: %s", fname); |
|
|
|
return off; |
|
} |
|
|
/* Only called for temporary file_struct entries created by make_file(). */ |
/* Only called for temporary file_struct entries created by make_file(). */ |
void unmake_file(struct file_struct *file) |
void unmake_file(struct file_struct *file) |
{ |
{ |
Line 1421 static struct file_struct *send_file_name(int f, struc
|
Line 2078 static struct file_struct *send_file_name(int f, struc
|
int flags, int filter_level) |
int flags, int filter_level) |
{ |
{ |
struct file_struct *file; |
struct file_struct *file; |
|
BOOL can_tweak_mode; |
|
|
file = make_file(fname, flist, stp, flags, filter_level); |
file = make_file(fname, flist, stp, flags, filter_level); |
if (!file) |
if (!file) |
return NULL; |
return NULL; |
|
|
if (chmod_modes && !S_ISLNK(file->mode) && file->mode) | can_tweak_mode = !S_ISLNK(file->mode) && file->mode; |
| if ((filter_level == ALL_FILTERS || filter_level == ALL_FILTERS_NO_EXCLUDE) |
| && last_hit_filter_rule) { |
| if ((last_hit_filter_rule->rflags & FILTRULE_CHMOD) && can_tweak_mode) |
| file->mode = tweak_mode(file->mode, last_hit_filter_rule->chmod->modes); |
| if ((last_hit_filter_rule->rflags & FILTRULE_FORCE_OWNER) && uid_ndx) |
| F_OWNER(file) = last_hit_filter_rule->force_uid; |
| if ((last_hit_filter_rule->rflags & FILTRULE_FORCE_GROUP) && gid_ndx) |
| F_GROUP(file) = last_hit_filter_rule->force_gid; |
| } |
| if (chmod_modes && can_tweak_mode) |
file->mode = tweak_mode(file->mode, chmod_modes); |
file->mode = tweak_mode(file->mode, chmod_modes); |
|
|
if (f >= 0) { |
if (f >= 0) { |
Line 1521 static struct file_struct *send_file_name(int f, struc
|
Line 2189 static struct file_struct *send_file_name(int f, struc
|
#ifdef SUPPORT_XATTRS |
#ifdef SUPPORT_XATTRS |
if (preserve_xattrs) { |
if (preserve_xattrs) { |
sx.st.st_mode = file->mode; |
sx.st.st_mode = file->mode; |
|
if (preserve_fileflags) |
|
sx.st.st_flags = F_FFLAGS(file); |
|
sx.st.st_mtime = file->modtime; /* get_xattr needs mtime for decmpfs xattrs */ |
if (get_xattr(fname, &sx) < 0) { |
if (get_xattr(fname, &sx) < 0) { |
io_error |= IOERR_GENERAL; |
io_error |= IOERR_GENERAL; |
return NULL; |
return NULL; |
Line 1637 static void fsort(struct file_struct **fp, size_t num)
|
Line 2308 static void fsort(struct file_struct **fp, size_t num)
|
if (use_qsort) |
if (use_qsort) |
qsort(fp, num, PTR_SIZE, file_compare); |
qsort(fp, num, PTR_SIZE, file_compare); |
else { |
else { |
struct file_struct **tmp = new_array(struct file_struct *, | struct file_struct **tmp = new_array(struct file_struct *, (num+1) / 2); |
(num+1) / 2); | |
fsort_tmp(fp, num, tmp); |
fsort_tmp(fp, num, tmp); |
free(tmp); |
free(tmp); |
} |
} |
Line 1654 static void add_dirs_to_tree(int parent_ndx, struct fi
|
Line 2324 static void add_dirs_to_tree(int parent_ndx, struct fi
|
int32 *parent_dp = parent_ndx < 0 ? NULL |
int32 *parent_dp = parent_ndx < 0 ? NULL |
: F_DIR_NODE_P(dir_flist->sorted[parent_ndx]); |
: F_DIR_NODE_P(dir_flist->sorted[parent_ndx]); |
|
|
|
/* The sending side is adding entries to dir_flist in sorted order, so sorted & files are the same. */ |
flist_expand(dir_flist, dir_cnt); |
flist_expand(dir_flist, dir_cnt); |
dir_flist->sorted = dir_flist->files; |
dir_flist->sorted = dir_flist->files; |
|
|
Line 1721 static void send_directory(int f, struct file_list *fl
|
Line 2392 static void send_directory(int f, struct file_list *fl
|
interpret_stat_error(fbuf, True); |
interpret_stat_error(fbuf, True); |
return; |
return; |
} |
} |
|
if (errno == ENOTDIR && (flags & FLAG_PERHAPS_DIR)) |
|
return; |
io_error |= IOERR_GENERAL; |
io_error |= IOERR_GENERAL; |
rsyserr(FERROR_XFER, errno, "opendir %s failed", full_fname(fbuf)); |
rsyserr(FERROR_XFER, errno, "opendir %s failed", full_fname(fbuf)); |
return; |
return; |
Line 1762 static void send_directory(int f, struct file_list *fl
|
Line 2435 static void send_directory(int f, struct file_list *fl
|
} |
} |
|
|
send_file_name(f, flist, fbuf, NULL, flags, filter_level); |
send_file_name(f, flist, fbuf, NULL, flags, filter_level); |
|
/* Sleep for a bit, to avoid hammering the disk. */ |
|
if (sleep_asec) |
|
usleep(sleep_asec); |
} |
} |
|
|
fbuf[len] = '\0'; |
fbuf[len] = '\0'; |
Line 1773 static void send_directory(int f, struct file_list *fl
|
Line 2449 static void send_directory(int f, struct file_list *fl
|
|
|
closedir(d); |
closedir(d); |
|
|
|
if (checksum_files & CSF_UPDATE && am_sender && f >= 0) |
|
reset_checksum_cache(1); |
|
|
if (f >= 0 && recurse && !divert_dirs) { |
if (f >= 0 && recurse && !divert_dirs) { |
int i, end = flist->used - 1; |
int i, end = flist->used - 1; |
/* send_if_directory() bumps flist->used, so use "end". */ |
/* send_if_directory() bumps flist->used, so use "end". */ |
Line 1868 static void send_implied_dirs(int f, struct file_list
|
Line 2547 static void send_implied_dirs(int f, struct file_list
|
len = strlen(limit+1); |
len = strlen(limit+1); |
memcpy(&relname_list, F_DIR_RELNAMES_P(lastpath_struct), sizeof relname_list); |
memcpy(&relname_list, F_DIR_RELNAMES_P(lastpath_struct), sizeof relname_list); |
if (!relname_list) { |
if (!relname_list) { |
if (!(relname_list = new0(item_list))) | relname_list = new0(item_list); |
out_of_memory("send_implied_dirs"); | |
memcpy(F_DIR_RELNAMES_P(lastpath_struct), &relname_list, sizeof relname_list); |
memcpy(F_DIR_RELNAMES_P(lastpath_struct), &relname_list, sizeof relname_list); |
} |
} |
rnpp = EXPAND_ITEM_LIST(relname_list, relnamecache *, 32); |
rnpp = EXPAND_ITEM_LIST(relname_list, relnamecache *, 32); |
if (!(*rnpp = (relnamecache*)new_array(char, sizeof (relnamecache) + len))) | *rnpp = (relnamecache*)new_array(char, RELNAMECACHE_LEN + len + 1); |
out_of_memory("send_implied_dirs"); | |
(*rnpp)->name_type = name_type; |
(*rnpp)->name_type = name_type; |
strlcpy((*rnpp)->fname, limit+1, len + 1); |
strlcpy((*rnpp)->fname, limit+1, len + 1); |
|
|
Line 1959 static void send1extra(int f, struct file_struct *file
|
Line 2636 static void send1extra(int f, struct file_struct *file
|
free(relname_list); |
free(relname_list); |
} |
} |
|
|
|
static void write_end_of_flist(int f, int send_io_error) |
|
{ |
|
if (xfer_flags_as_varint) { |
|
write_varint(f, 0); |
|
write_varint(f, send_io_error ? io_error : 0); |
|
} else if (send_io_error) { |
|
write_shortint(f, XMIT_EXTENDED_FLAGS|XMIT_IO_ERROR_ENDLIST); |
|
write_varint(f, io_error); |
|
} else |
|
write_byte(f, 0); |
|
} |
|
|
void send_extra_file_list(int f, int at_least) |
void send_extra_file_list(int f, int at_least) |
{ |
{ |
struct file_list *flist; |
struct file_list *flist; |
Line 1988 void send_extra_file_list(int f, int at_least)
|
Line 2677 void send_extra_file_list(int f, int at_least)
|
else |
else |
dir_ndx = send_dir_ndx; |
dir_ndx = send_dir_ndx; |
write_ndx(f, NDX_FLIST_OFFSET - dir_ndx); |
write_ndx(f, NDX_FLIST_OFFSET - dir_ndx); |
flist->parent_ndx = dir_ndx; | flist->parent_ndx = send_dir_ndx; /* the sending side must remember the sorted ndx value */ |
|
|
send1extra(f, file, flist); |
send1extra(f, file, flist); |
prev_flags = file->flags; |
prev_flags = file->flags; |
Line 2010 void send_extra_file_list(int f, int at_least)
|
Line 2699 void send_extra_file_list(int f, int at_least)
|
} |
} |
|
|
if (io_error == save_io_error || ignore_errors) |
if (io_error == save_io_error || ignore_errors) |
write_byte(f, 0); | write_end_of_flist(f, 0); |
else if (use_safe_inc_flist) { | else if (use_safe_inc_flist) |
write_shortint(f, XMIT_EXTENDED_FLAGS|XMIT_IO_ERROR_ENDLIST); | write_end_of_flist(f, 1); |
write_varint(f, io_error); | else { |
} else { | |
if (delete_during) |
if (delete_during) |
fatal_unsafe_io_error(); |
fatal_unsafe_io_error(); |
write_byte(f, 0); | write_end_of_flist(f, 0); |
} |
} |
|
|
if (need_unsorted_flist) { |
if (need_unsorted_flist) { |
if (!(flist->sorted = new_array(struct file_struct *, flist->used))) | flist->sorted = new_array(struct file_struct *, flist->used); |
out_of_memory("send_extra_file_list"); | memcpy(flist->sorted, flist->files, flist->used * PTR_SIZE); |
memcpy(flist->sorted, flist->files, | |
flist->used * sizeof (struct file_struct*)); | |
} else |
} else |
flist->sorted = flist->files; |
flist->sorted = flist->files; |
|
|
Line 2063 void send_extra_file_list(int f, int at_least)
|
Line 2749 void send_extra_file_list(int f, int at_least)
|
finish: |
finish: |
if (io_error != save_io_error && protocol_version == 30 && !ignore_errors) |
if (io_error != save_io_error && protocol_version == 30 && !ignore_errors) |
send_msg_int(MSG_IO_ERROR, io_error); |
send_msg_int(MSG_IO_ERROR, io_error); |
|
|
|
if (use_db && flist_eof) |
|
db_disconnect(True); |
} |
} |
|
|
struct file_list *send_file_list(int f, int argc, char *argv[]) |
struct file_list *send_file_list(int f, int argc, char *argv[]) |
Line 2086 struct file_list *send_file_list(int f, int argc, char
|
Line 2775 struct file_list *send_file_list(int f, int argc, char
|
| (eol_nulls || reading_remotely ? RL_EOL_NULLS : 0); |
| (eol_nulls || reading_remotely ? RL_EOL_NULLS : 0); |
int implied_dot_dir = 0; |
int implied_dot_dir = 0; |
|
|
|
if (use_db) { |
|
if (always_checksum) |
|
db_connect(0); /* Will reset use_db on error. */ |
|
else |
|
use_db = 0; |
|
} |
|
|
rprintf(FLOG, "building file list\n"); |
rprintf(FLOG, "building file list\n"); |
if (show_filelist_p()) | if (show_filelist_progress) |
start_filelist_progress("building file list"); |
start_filelist_progress("building file list"); |
else if (inc_recurse && INFO_GTE(FLIST, 1) && !am_server) |
else if (inc_recurse && INFO_GTE(FLIST, 1) && !am_server) |
rprintf(FCLIENT, "sending incremental file list\n"); |
rprintf(FCLIENT, "sending incremental file list\n"); |
Line 2262 struct file_list *send_file_list(int f, int argc, char
|
Line 2958 struct file_list *send_file_list(int f, int argc, char
|
memmove(fbuf, fn, len + 1); |
memmove(fbuf, fn, len + 1); |
|
|
if (link_stat(fbuf, &st, copy_dirlinks || name_type != NORMAL_NAME) != 0 |
if (link_stat(fbuf, &st, copy_dirlinks || name_type != NORMAL_NAME) != 0 |
|| (name_type != DOTDIR_NAME && is_daemon_excluded(fbuf, S_ISDIR(st.st_mode))) | || (name_type != DOTDIR_NAME && is_excluded(fbuf, S_ISDIR(st.st_mode) != 0, SERVER_FILTERS)) |
|| (relative_paths && path_is_daemon_excluded(fbuf, 1))) { |
|| (relative_paths && path_is_daemon_excluded(fbuf, 1))) { |
if (errno != ENOENT || missing_args == 0) { |
if (errno != ENOENT || missing_args == 0) { |
/* This is a transfer error, but inhibit deletion |
/* This is a transfer error, but inhibit deletion |
Line 2317 struct file_list *send_file_list(int f, int argc, char
|
Line 3013 struct file_list *send_file_list(int f, int argc, char
|
struct file_struct *file; |
struct file_struct *file; |
file = send_file_name(f, flist, fbuf, &st, |
file = send_file_name(f, flist, fbuf, &st, |
FLAG_TOP_DIR | FLAG_CONTENT_DIR | flags, |
FLAG_TOP_DIR | FLAG_CONTENT_DIR | flags, |
NO_FILTERS); | ALL_FILTERS_NO_EXCLUDE); |
if (!file) |
if (!file) |
continue; |
continue; |
if (inc_recurse) { |
if (inc_recurse) { |
Line 2331 struct file_list *send_file_list(int f, int argc, char
|
Line 3027 struct file_list *send_file_list(int f, int argc, char
|
} else |
} else |
send_if_directory(f, flist, file, fbuf, len, flags); |
send_if_directory(f, flist, file, fbuf, len, flags); |
} else |
} else |
send_file_name(f, flist, fbuf, &st, flags, NO_FILTERS); | send_file_name(f, flist, fbuf, &st, flags, ALL_FILTERS_NO_EXCLUDE); |
} |
} |
|
|
if (reenable_multiplex >= 0) |
if (reenable_multiplex >= 0) |
Line 2346 struct file_list *send_file_list(int f, int argc, char
|
Line 3042 struct file_list *send_file_list(int f, int argc, char
|
|
|
/* Indicate end of file list */ |
/* Indicate end of file list */ |
if (io_error == 0 || ignore_errors) |
if (io_error == 0 || ignore_errors) |
write_byte(f, 0); | write_end_of_flist(f, 0); |
else if (use_safe_inc_flist) { | else if (use_safe_inc_flist) |
write_shortint(f, XMIT_EXTENDED_FLAGS|XMIT_IO_ERROR_ENDLIST); | write_end_of_flist(f, 1); |
write_varint(f, io_error); | else { |
} else { | |
if (delete_during && inc_recurse) |
if (delete_during && inc_recurse) |
fatal_unsafe_io_error(); |
fatal_unsafe_io_error(); |
write_byte(f, 0); | write_end_of_flist(f, 0); |
} |
} |
|
|
#ifdef SUPPORT_HARD_LINKS |
#ifdef SUPPORT_HARD_LINKS |
Line 2361 struct file_list *send_file_list(int f, int argc, char
|
Line 3056 struct file_list *send_file_list(int f, int argc, char
|
idev_destroy(); |
idev_destroy(); |
#endif |
#endif |
|
|
if (show_filelist_p()) | if (show_filelist_progress) |
finish_filelist_progress(flist); |
finish_filelist_progress(flist); |
|
|
gettimeofday(&end_tv, NULL); |
gettimeofday(&end_tv, NULL); |
Line 2377 struct file_list *send_file_list(int f, int argc, char
|
Line 3072 struct file_list *send_file_list(int f, int argc, char
|
* recursion mode, the sender marks duplicate dirs so that it can |
* recursion mode, the sender marks duplicate dirs so that it can |
* send them together in a single file-list. */ |
* send them together in a single file-list. */ |
if (need_unsorted_flist) { |
if (need_unsorted_flist) { |
if (!(flist->sorted = new_array(struct file_struct *, flist->used))) | flist->sorted = new_array(struct file_struct *, flist->used); |
out_of_memory("send_file_list"); | memcpy(flist->sorted, flist->files, flist->used * PTR_SIZE); |
memcpy(flist->sorted, flist->files, | |
flist->used * sizeof (struct file_struct*)); | |
} else |
} else |
flist->sorted = flist->files; |
flist->sorted = flist->files; |
flist_sort_and_clean(flist, 0); |
flist_sort_and_clean(flist, 0); |
Line 2388 struct file_list *send_file_list(int f, int argc, char
|
Line 3081 struct file_list *send_file_list(int f, int argc, char
|
file_old_total += flist->used; |
file_old_total += flist->used; |
|
|
if (numeric_ids <= 0 && !inc_recurse) |
if (numeric_ids <= 0 && !inc_recurse) |
send_id_list(f); | send_id_lists(f); |
|
|
/* send the io_error flag */ |
/* send the io_error flag */ |
if (protocol_version < 30) |
if (protocol_version < 30) |
Line 2432 struct file_list *send_file_list(int f, int argc, char
|
Line 3125 struct file_list *send_file_list(int f, int argc, char
|
rprintf(FINFO, "[%s] flist_eof=1\n", who_am_i()); |
rprintf(FINFO, "[%s] flist_eof=1\n", who_am_i()); |
} |
} |
|
|
|
if (checksum_files & CSF_UPDATE && flist_eof) |
|
reset_checksum_cache(0); /* writes any last updates */ |
|
|
return flist; |
return flist; |
} |
} |
|
|
Line 2443 struct file_list *recv_file_list(int f, int dir_ndx)
|
Line 3139 struct file_list *recv_file_list(int f, int dir_ndx)
|
int64 start_read; |
int64 start_read; |
|
|
if (!first_flist) { |
if (!first_flist) { |
if (show_filelist_p()) | if (show_filelist_progress) |
start_filelist_progress("receiving file list"); |
start_filelist_progress("receiving file list"); |
else if (inc_recurse && INFO_GTE(FLIST, 1) && !am_server) |
else if (inc_recurse && INFO_GTE(FLIST, 1) && !am_server) |
rprintf(FCLIENT, "receiving incremental file list\n"); |
rprintf(FCLIENT, "receiving incremental file list\n"); |
Line 2452 struct file_list *recv_file_list(int f, int dir_ndx)
|
Line 3148 struct file_list *recv_file_list(int f, int dir_ndx)
|
parse_name_map(usermap, True); |
parse_name_map(usermap, True); |
if (groupmap) |
if (groupmap) |
parse_name_map(groupmap, False); |
parse_name_map(groupmap, False); |
|
if (tr_opt) { /* Parse FROM/TO string and populate tr_substitutions[] */ |
|
char *f, *t; |
|
if ((t = strchr(tr_opt, '/')) != NULL) |
|
*t++ = '\0'; |
|
else |
|
t = ""; |
|
for (f = tr_opt; *f; f++) |
|
tr_substitutions[*(uchar*)f] = *t ? *t++ : '\0'; |
|
} |
} |
} |
|
|
start_read = stats.total_read; |
start_read = stats.total_read; |
Line 2472 struct file_list *recv_file_list(int f, int dir_ndx)
|
Line 3177 struct file_list *recv_file_list(int f, int dir_ndx)
|
dstart = 0; |
dstart = 0; |
} |
} |
|
|
while ((flags = read_byte(f)) != 0) { | while (1) { |
struct file_struct *file; |
struct file_struct *file; |
|
|
if (protocol_version >= 28 && (flags & XMIT_EXTENDED_FLAGS)) | if (xfer_flags_as_varint) { |
flags |= read_byte(f) << 8; | if ((flags = read_varint(f)) == 0) { |
| int err = read_varint(f); |
| if (!ignore_errors) |
| io_error |= err; |
| break; |
| } |
| } else { |
| if ((flags = read_byte(f)) == 0) |
| break; |
|
|
if (flags == (XMIT_EXTENDED_FLAGS|XMIT_IO_ERROR_ENDLIST)) { | if (protocol_version >= 28 && (flags & XMIT_EXTENDED_FLAGS)) |
int err; | flags |= read_byte(f) << 8; |
if (!use_safe_inc_flist) { | |
rprintf(FERROR, "Invalid flist flag: %x\n", flags); | if (flags == (XMIT_EXTENDED_FLAGS|XMIT_IO_ERROR_ENDLIST)) { |
exit_cleanup(RERR_PROTOCOL); | int err; |
| if (!use_safe_inc_flist) { |
| rprintf(FERROR, "Invalid flist flag: %x\n", flags); |
| exit_cleanup(RERR_PROTOCOL); |
| } |
| err = read_varint(f); |
| if (!ignore_errors) |
| io_error |= err; |
| break; |
} |
} |
err = read_varint(f); |
|
if (!ignore_errors) |
|
io_error |= err; |
|
break; |
|
} |
} |
|
|
flist_expand(flist, 1); |
flist_expand(flist, 1); |
Line 2500 struct file_list *recv_file_list(int f, int dir_ndx)
|
Line 3217 struct file_list *recv_file_list(int f, int dir_ndx)
|
cur_dir++; |
cur_dir++; |
if (cur_dir != good_dirname) { |
if (cur_dir != good_dirname) { |
const char *d = dir_ndx >= 0 ? f_name(dir_flist->files[dir_ndx], NULL) : empty_dir; |
const char *d = dir_ndx >= 0 ? f_name(dir_flist->files[dir_ndx], NULL) : empty_dir; |
if (strcmp(cur_dir, d) != 0) { | int dir_differs = ignore_case ? strcasecmp(cur_dir, d) : strcmp(cur_dir, d); |
| if (dir_differs) { |
rprintf(FERROR, |
rprintf(FERROR, |
"ABORTING due to invalid path from sender: %s/%s\n", |
"ABORTING due to invalid path from sender: %s/%s\n", |
cur_dir, file->basename); |
cur_dir, file->basename); |
Line 2539 struct file_list *recv_file_list(int f, int dir_ndx)
|
Line 3257 struct file_list *recv_file_list(int f, int dir_ndx)
|
if (DEBUG_GTE(FLIST, 2)) |
if (DEBUG_GTE(FLIST, 2)) |
rprintf(FINFO, "received %d names\n", flist->used); |
rprintf(FINFO, "received %d names\n", flist->used); |
|
|
if (show_filelist_p()) | if (show_filelist_progress) |
finish_filelist_progress(flist); |
finish_filelist_progress(flist); |
|
|
if (need_unsorted_flist) { |
if (need_unsorted_flist) { |
Line 2548 struct file_list *recv_file_list(int f, int dir_ndx)
|
Line 3266 struct file_list *recv_file_list(int f, int dir_ndx)
|
* order and for calling flist_find()). We keep the "files" |
* order and for calling flist_find()). We keep the "files" |
* list unsorted for our exchange of index numbers with the |
* list unsorted for our exchange of index numbers with the |
* other side (since their names may not sort the same). */ |
* other side (since their names may not sort the same). */ |
if (!(flist->sorted = new_array(struct file_struct *, flist->used))) | flist->sorted = new_array(struct file_struct *, flist->used); |
out_of_memory("recv_file_list"); | memcpy(flist->sorted, flist->files, flist->used * PTR_SIZE); |
memcpy(flist->sorted, flist->files, | |
flist->used * sizeof (struct file_struct*)); | |
if (inc_recurse && dir_flist->used > dstart) { |
if (inc_recurse && dir_flist->used > dstart) { |
static int dir_flist_malloced = 0; |
static int dir_flist_malloced = 0; |
if (dir_flist_malloced < dir_flist->malloced) { |
if (dir_flist_malloced < dir_flist->malloced) { |
Line 2561 struct file_list *recv_file_list(int f, int dir_ndx)
|
Line 3277 struct file_list *recv_file_list(int f, int dir_ndx)
|
dir_flist_malloced = dir_flist->malloced; |
dir_flist_malloced = dir_flist->malloced; |
} |
} |
memcpy(dir_flist->sorted + dstart, dir_flist->files + dstart, |
memcpy(dir_flist->sorted + dstart, dir_flist->files + dstart, |
(dir_flist->used - dstart) * sizeof (struct file_struct*)); | (dir_flist->used - dstart) * PTR_SIZE); |
fsort(dir_flist->sorted + dstart, dir_flist->used - dstart); |
fsort(dir_flist->sorted + dstart, dir_flist->used - dstart); |
} |
} |
} else { |
} else { |
Line 2584 struct file_list *recv_file_list(int f, int dir_ndx)
|
Line 3300 struct file_list *recv_file_list(int f, int dir_ndx)
|
/* The --relative option sends paths with a leading slash, so we need |
/* The --relative option sends paths with a leading slash, so we need |
* to specify the strip_root option here. We rejected leading slashes |
* to specify the strip_root option here. We rejected leading slashes |
* for a non-relative transfer in recv_file_entry(). */ |
* for a non-relative transfer in recv_file_entry(). */ |
flist_sort_and_clean(flist, relative_paths); | flist_sort_and_clean(flist, relative_paths ? CLEAN_STRIP_ROOT : 0); |
|
|
|
if (detect_renamed) { |
|
int j = flist->used; |
|
the_fattr_list.used = j; |
|
the_fattr_list.files = new_array(struct file_struct *, j); |
|
memcpy(the_fattr_list.files, flist->files, |
|
j * sizeof (struct file_struct *)); |
|
qsort(the_fattr_list.files, j, |
|
sizeof the_fattr_list.files[0], (int (*)())fattr_compare); |
|
the_fattr_list.low = 0; |
|
while (j-- > 0) { |
|
struct file_struct *fp = the_fattr_list.files[j]; |
|
if (fp->basename && S_ISREG(fp->mode) && F_LENGTH(fp)) |
|
break; |
|
} |
|
the_fattr_list.high = j; |
|
} |
|
|
if (protocol_version < 30) { |
if (protocol_version < 30) { |
/* Recv the io_error flag */ |
/* Recv the io_error flag */ |
int err = read_int(f); |
int err = read_int(f); |
Line 2693 int flist_find(struct file_list *flist, struct file_st
|
Line 3426 int flist_find(struct file_list *flist, struct file_st
|
* 1=match directories, 0=match non-directories, or -1=match either. */ |
* 1=match directories, 0=match non-directories, or -1=match either. */ |
int flist_find_name(struct file_list *flist, const char *fname, int want_dir_match) |
int flist_find_name(struct file_list *flist, const char *fname, int want_dir_match) |
{ |
{ |
struct { /* We have to create a temporary file_struct for the search. */ | static struct file_struct *f; |
struct file_struct f; | |
char name_space[MAXPATHLEN]; | |
} t; | |
char fbuf[MAXPATHLEN]; |
char fbuf[MAXPATHLEN]; |
const char *slash = strrchr(fname, '/'); |
const char *slash = strrchr(fname, '/'); |
const char *basename = slash ? slash+1 : fname; |
const char *basename = slash ? slash+1 : fname; |
|
|
memset(&t.f, 0, FILE_STRUCT_LEN); | if (!f) |
memcpy((void *)t.f.basename, basename, strlen(basename)+1); | f = (struct file_struct*)new_array(char, FILE_STRUCT_LEN + MAXPATHLEN + 1); |
|
|
|
memset(f, 0, FILE_STRUCT_LEN); |
|
memcpy((void*)f->basename, basename, strlen(basename)+1); |
|
|
if (slash) { |
if (slash) { |
strlcpy(fbuf, fname, slash - fname + 1); |
strlcpy(fbuf, fname, slash - fname + 1); |
t.f.dirname = fbuf; | f->dirname = fbuf; |
} else |
} else |
t.f.dirname = NULL; | f->dirname = NULL; |
|
|
t.f.mode = want_dir_match > 0 ? S_IFDIR : S_IFREG; | f->mode = want_dir_match > 0 ? S_IFDIR : S_IFREG; |
|
|
if (want_dir_match < 0) |
if (want_dir_match < 0) |
return flist_find_ignore_dirness(flist, &t.f); | return flist_find_ignore_dirness(flist, f); |
return flist_find(flist, &t.f); | return flist_find(flist, f); |
} |
} |
|
|
/* Search for an identically-named item in the file list. Differs from |
/* Search for an identically-named item in the file list. Differs from |
Line 2755 void clear_file(struct file_struct *file)
|
Line 3488 void clear_file(struct file_struct *file)
|
} |
} |
|
|
/* Allocate a new file list. */ |
/* Allocate a new file list. */ |
struct file_list *flist_new(int flags, char *msg) | static struct file_list *flist_new(int flags, const char *msg) |
{ |
{ |
struct file_list *flist; |
struct file_list *flist; |
|
|
if (!(flist = new0(struct file_list))) | flist = new0(struct file_list); |
out_of_memory(msg); | |
|
|
if (flags & FLIST_TEMP) { |
if (flags & FLIST_TEMP) { |
if (!(flist->file_pool = pool_create(SMALL_EXTENT, 0, | if (!(flist->file_pool = pool_create(SMALL_EXTENT, 0, _out_of_memory, POOL_INTERN))) |
out_of_memory, | |
POOL_INTERN))) | |
out_of_memory(msg); |
out_of_memory(msg); |
} else { |
} else { |
/* This is a doubly linked list with prev looping back to |
/* This is a doubly linked list with prev looping back to |
* the end of the list, but the last next pointer is NULL. */ |
* the end of the list, but the last next pointer is NULL. */ |
if (!first_flist) { |
if (!first_flist) { |
flist->file_pool = pool_create(NORMAL_EXTENT, 0, | if (!(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); |
out_of_memory(msg); |
|
|
flist->ndx_start = flist->flist_num = inc_recurse ? 1 : 0; |
flist->ndx_start = flist->flist_num = inc_recurse ? 1 : 0; |
Line 2795 struct file_list *flist_new(int flags, char *msg)
|
Line 3522 struct file_list *flist_new(int flags, char *msg)
|
flist_cnt++; |
flist_cnt++; |
} |
} |
|
|
|
if (use_db && (!inc_recurse || flist_eof)) |
|
db_disconnect(True); |
|
|
return flist; |
return flist; |
} |
} |
|
|
Line 2835 void flist_free(struct file_list *flist)
|
Line 3565 void flist_free(struct file_list *flist)
|
|
|
/* This routine ensures we don't have any duplicate names in our file list. |
/* This routine ensures we don't have any duplicate names in our file list. |
* duplicate names can cause corruption because of the pipelining. */ |
* duplicate names can cause corruption because of the pipelining. */ |
static void flist_sort_and_clean(struct file_list *flist, int strip_root) | static void flist_sort_and_clean(struct file_list *flist, int flags) |
{ |
{ |
char fbuf[MAXPATHLEN]; |
char fbuf[MAXPATHLEN]; |
int i, prev_i; |
int i, prev_i; |
Line 2886 static void flist_sort_and_clean(struct file_list *fli
|
Line 3616 static void flist_sort_and_clean(struct file_list *fli
|
/* If one is a dir and the other is not, we want to |
/* If one is a dir and the other is not, we want to |
* keep the dir because it might have contents in the |
* keep the dir because it might have contents in the |
* list. Otherwise keep the first one. */ |
* list. Otherwise keep the first one. */ |
if (S_ISDIR(file->mode)) { | if (S_ISDIR(file->mode) || flags & CLEAN_KEEP_LAST) { |
struct file_struct *fp = flist->sorted[j]; |
struct file_struct *fp = flist->sorted[j]; |
if (!S_ISDIR(fp->mode)) |
if (!S_ISDIR(fp->mode)) |
keep = i, drop = j; |
keep = i, drop = j; |
Line 2902 static void flist_sort_and_clean(struct file_list *fli
|
Line 3632 static void flist_sort_and_clean(struct file_list *fli
|
} else |
} else |
keep = j, drop = i; |
keep = j, drop = i; |
|
|
if (!am_sender) { | if (!am_sender || flags & CLEAN_KEEP_LAST) { |
if (DEBUG_GTE(DUP, 1)) { | if (DEBUG_GTE(DUP, 1) && !(flags & CLEAN_KEEP_LAST)) { |
rprintf(FINFO, |
rprintf(FINFO, |
"removing duplicate name %s from file list (%d)\n", |
"removing duplicate name %s from file list (%d)\n", |
f_name(file, fbuf), drop + flist->ndx_start); |
f_name(file, fbuf), drop + flist->ndx_start); |
Line 2925 static void flist_sort_and_clean(struct file_list *fli
|
Line 3655 static void flist_sort_and_clean(struct file_list *fli
|
} |
} |
flist->high = prev_i; |
flist->high = prev_i; |
|
|
if (strip_root) { | if (flags & CLEAN_STRIP_ROOT) { |
/* We need to strip off the leading slashes for relative |
/* We need to strip off the leading slashes for relative |
* paths, but this must be done _after_ the sorting phase. */ |
* paths, but this must be done _after_ the sorting phase. */ |
for (i = flist->low; i <= flist->high; i++) { |
for (i = flist->low; i <= flist->high; i++) { |
Line 2961 static void flist_sort_and_clean(struct file_list *fli
|
Line 3691 static void flist_sort_and_clean(struct file_list *fli
|
clear_file(fp); |
clear_file(fp); |
} |
} |
prev_depth = F_DEPTH(file); |
prev_depth = F_DEPTH(file); |
if (is_excluded(f_name(file, fbuf), 1, | if (is_excluded(f_name(file, fbuf), 1, ALL_FILTERS)) { |
ALL_FILTERS)) { | |
/* Keep dirs through this dir. */ |
/* Keep dirs through this dir. */ |
for (j = prev_depth-1; ; j--) { |
for (j = prev_depth-1; ; j--) { |
fp = flist->sorted[prev_i]; |
fp = flist->sorted[prev_i]; |
Line 3076 int f_name_cmp(const struct file_struct *f1, const str
|
Line 3805 int f_name_cmp(const struct file_struct *f1, const str
|
{ |
{ |
int dif; |
int dif; |
const uchar *c1, *c2; |
const uchar *c1, *c2; |
|
uchar ch1, ch2; |
enum fnc_state state1, state2; |
enum fnc_state state1, state2; |
enum fnc_type type1, type2; |
enum fnc_type type1, type2; |
enum fnc_type t_path = protocol_version >= 29 ? t_PATH : t_ITEM; |
enum fnc_type t_path = protocol_version >= 29 ? t_PATH : t_ITEM; |
Line 3186 int f_name_cmp(const struct file_struct *f1, const str
|
Line 3916 int f_name_cmp(const struct file_struct *f1, const str
|
if (type1 != type2) |
if (type1 != type2) |
return type1 == t_PATH ? 1 : -1; |
return type1 == t_PATH ? 1 : -1; |
} |
} |
} while ((dif = (int)*c1++ - (int)*c2++) == 0); | ch1 = *c1++; |
| ch2 = *c2++; |
| if (ignore_case) { |
| if (isupper(ch1)) |
| ch1 = tolower(ch1); |
| if (isupper(ch2)) |
| ch2 = tolower(ch2); |
| } |
| } while ((dif = (int)ch1 - (int)ch2) == 0); |
|
|
return dif; |
return dif; |
} |
} |
Line 3247 struct file_list *get_dirlist(char *dirname, int dlen,
|
Line 3985 struct file_list *get_dirlist(char *dirname, int dlen,
|
int save_xfer_dirs = xfer_dirs; |
int save_xfer_dirs = xfer_dirs; |
int save_prune_empty_dirs = prune_empty_dirs; |
int save_prune_empty_dirs = prune_empty_dirs; |
int senddir_fd = flags & GDL_IGNORE_FILTER_RULES ? -2 : -1; |
int senddir_fd = flags & GDL_IGNORE_FILTER_RULES ? -2 : -1; |
|
int senddir_flags = FLAG_CONTENT_DIR; |
|
|
if (dlen < 0) { |
if (dlen < 0) { |
dlen = strlcpy(dirbuf, dirname, MAXPATHLEN); |
dlen = strlcpy(dirbuf, dirname, MAXPATHLEN); |
Line 3257 struct file_list *get_dirlist(char *dirname, int dlen,
|
Line 3996 struct file_list *get_dirlist(char *dirname, int dlen,
|
|
|
dirlist = flist_new(FLIST_TEMP, "get_dirlist"); |
dirlist = flist_new(FLIST_TEMP, "get_dirlist"); |
|
|
|
if (flags & GDL_PERHAPS_DIR) |
|
senddir_flags |= FLAG_PERHAPS_DIR; |
|
|
recurse = 0; |
recurse = 0; |
xfer_dirs = 1; |
xfer_dirs = 1; |
send_directory(senddir_fd, dirlist, dirname, dlen, FLAG_CONTENT_DIR); | send_directory(senddir_fd, dirlist, dirname, dlen, senddir_flags); |
xfer_dirs = save_xfer_dirs; |
xfer_dirs = save_xfer_dirs; |
recurse = save_recurse; |
recurse = save_recurse; |
if (INFO_GTE(PROGRESS, 1)) |
if (INFO_GTE(PROGRESS, 1)) |