extern int copy_unsafe_links;
extern int protocol_version;
extern int sanitize_paths;
+extern int munge_symlinks;
+extern int need_unsorted_flist;
+extern int unsort_ndx;
extern struct stats stats;
extern char *filesfrom_host;
-#ifdef ICONV_OPTION
-extern char *iconv_opt;
-#endif
extern char curr_dir[MAXPATHLEN];
extern struct filter_list_struct server_filter_list;
#ifdef ICONV_OPTION
-extern int ic_ndx;
extern int filesfrom_convert;
-extern int need_unsorted_flist;
extern iconv_t ic_send, ic_recv;
#endif
static char empty_sum[MAX_DIGEST_LEN];
static int flist_count_offset; /* for --delete --progress */
static int dir_count = 0;
-static int high_hlink_ndx;
-static void clean_flist(struct file_list *flist, int strip_root);
+static void flist_sort_and_clean(struct file_list *flist, int strip_root);
static void output_flist(struct file_list *flist);
void init_flist(void)
}
return x_stat(path, stp, NULL);
}
+ if (munge_symlinks && am_sender && llen > SYMLINK_PREFIX_LEN
+ && strncmp(linkbuf, SYMLINK_PREFIX, SYMLINK_PREFIX_LEN) == 0) {
+ memmove(linkbuf, linkbuf + SYMLINK_PREFIX_LEN,
+ llen - SYMLINK_PREFIX_LEN + 1);
+ }
}
return 0;
#else
/* Initialize starting value of xflags. */
if (protocol_version >= 30 && S_ISDIR(file->mode)) {
+ dir_count++;
if (file->flags & FLAG_CONTENT_DIR)
xflags = file->flags & FLAG_TOP_DIR;
else if (file->flags & FLAG_IMPLIED_DIR)
struct ht_int64_node *np = idev_find(tmp_dev, tmp_ino);
first_hlink_ndx = (int32)(long)np->data - 1;
if (first_hlink_ndx < 0) {
- high_hlink_ndx = ndx + first_ndx;
- np->data = (void*)(long)(high_hlink_ndx + 1);
+ np->data = (void*)(long)(first_ndx + ndx + 1);
xflags |= XMIT_HLINK_FIRST;
}
xflags |= XMIT_HLINKED;
clean_fname(thisname, 0);
if (sanitize_paths)
- sanitize_path(thisname, thisname, "", 0, NULL);
+ sanitize_path(thisname, thisname, "", 0);
if ((basename = strrchr(thisname, '/')) != NULL) {
int len = basename++ - thisname;
if (protocol_version >= 30) {
modtime = read_varlong(f, 4);
#if SIZEOF_TIME_T < SIZEOF_INT64
- if ((modtime > INT_MAX || modtime < INT_MIN) && !am_generator) {
- rprintf(FERROR,
+ if (!am_generator && (int64)(time_t)modtime != modtime) {
+ rprintf(FERROR_XFER,
"Time value of %s truncated on receiver.\n",
lastname);
}
linkname_len - 1);
overflow_exit("recv_file_entry");
}
+ if (munge_symlinks)
+ linkname_len += SYMLINK_PREFIX_LEN;
}
else
#endif
if (file_length > 0xFFFFFFFFu && S_ISREG(mode))
extra_len += EXTRA_LEN;
-#if EXTRA_ROUNDING > 0
- if (extra_len & (EXTRA_ROUNDING * EXTRA_LEN))
- extra_len = (extra_len | (EXTRA_ROUNDING * EXTRA_LEN)) + EXTRA_LEN;
-#endif
-
if (inc_recurse && S_ISDIR(mode)) {
if (one_file_system) {
/* Room to save the dir's device for -x */
} else
pool = flist->file_pool;
+#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
+ linkname_len;
bp = pool_alloc(pool, alloc_len, "recv_file_entry");
F_GROUP(file) = gid;
file->flags |= gid_flags;
}
-#ifdef ICONV_OPTION
- if (ic_ndx)
+ if (unsort_ndx)
F_NDX(file) = flist->used + flist->ndx_start;
-#endif
if (basename != thisname) {
file->dirname = lastdir;
if (first_hlink_ndx >= flist->ndx_start) {
struct file_struct *first = flist->files[first_hlink_ndx - flist->ndx_start];
memcpy(bp, F_SYMLINK(first), linkname_len);
- } else
+ } else if (munge_symlinks) {
+ strlcpy(bp, SYMLINK_PREFIX, linkname_len);
+ bp += SYMLINK_PREFIX_LEN;
+ linkname_len -= SYMLINK_PREFIX_LEN;
read_sbuf(f, bp, linkname_len - 1);
- if (sanitize_paths)
- sanitize_path(bp, bp, "", lastdir_depth, NULL);
+ } else {
+ read_sbuf(f, bp, linkname_len - 1);
+ if (sanitize_paths)
+ sanitize_path(bp, bp, "", lastdir_depth);
+ }
}
#endif
if (preserve_hard_links && xflags & XMIT_HLINKED) {
if (protocol_version >= 30) {
if (xflags & XMIT_HLINK_FIRST) {
- high_hlink_ndx = flist->ndx_start + flist->used;
- F_HL_GNUM(file) = high_hlink_ndx;
+ F_HL_GNUM(file) = flist->ndx_start + flist->used;
} else
F_HL_GNUM(file) = first_hlink_ndx;
} else {
}
clean_fname(thisname, 0);
if (sanitize_paths)
- sanitize_path(thisname, thisname, "", 0, NULL);
+ sanitize_path(thisname, thisname, "", 0);
if (stp && S_ISDIR(stp->st_mode)) {
st = *stp; /* Needed for "symlink/." with --relative. */
if (copy_links && x_lstat(thisname, &st, NULL) == 0
&& S_ISLNK(st.st_mode)) {
io_error |= IOERR_GENERAL;
- rprintf(FERROR, "symlink has no referent: %s\n",
+ rprintf(FERROR_XFER, "symlink has no referent: %s\n",
full_fname(thisname));
} else
#endif
{
enum logcode c = am_daemon && protocol_version < 28
- ? FERROR : FINFO;
+ ? FERROR : FWARNING;
io_error |= IOERR_VANISHED;
rprintf(c, "file has vanished: %s\n",
full_fname(thisname));
}
} else {
io_error |= IOERR_GENERAL;
- rsyserr(FERROR, save_errno, "readlink %s failed",
+ rsyserr(FERROR_XFER, save_errno, "readlink %s failed",
full_fname(thisname));
}
return NULL;
extra_len += DIRNODE_EXTRA_CNT * EXTRA_LEN;
if (relative_paths)
extra_len += PTR_EXTRA_CNT * EXTRA_LEN;
- dir_count++;
pool = dir_flist->file_pool;
} else
pool = flist->file_pool;
file->mode = save_mode;
}
- if (basename_len == 0+1)
+ if (basename_len == 0+1) {
+ if (!pool)
+ unmake_file(file);
return NULL;
+ }
-#ifdef ICONV_OPTION
- if (ic_ndx)
- F_NDX(file) = dir_count - 1;
-#endif
+ if (unsort_ndx)
+ F_NDX(file) = dir_count;
return file;
}
fbuf[--len] = '\0';
if (len >= MAXPATHLEN - 1) {
io_error |= IOERR_GENERAL;
- rprintf(FERROR, "skipping long-named directory: %s\n",
+ rprintf(FERROR_XFER, "skipping long-named directory: %s\n",
full_fname(fbuf));
return;
}
if (!(d = opendir(fbuf))) {
io_error |= IOERR_GENERAL;
- rsyserr(FERROR, errno, "opendir %s failed", full_fname(fbuf));
+ rsyserr(FERROR_XFER, errno, "opendir %s failed", full_fname(fbuf));
return;
}
if (errno) {
io_error |= IOERR_GENERAL;
- rsyserr(FERROR, errno, "readdir(%s)", full_fname(fbuf));
+ rsyserr(FERROR_XFER, errno, "readdir(%s)", full_fname(fbuf));
}
closedir(d);
STRUCT_STAT st;
if (link_stat(fbuf, &st, copy_dirlinks) != 0) {
io_error |= IOERR_GENERAL;
- rsyserr(FERROR, errno, "link_stat %s failed",
+ rsyserr(FERROR_XFER, errno, "link_stat %s failed",
full_fname(fbuf));
return;
}
STRUCT_STAT st;
if (link_stat(fbuf, &st, 1) != 0) {
io_error |= IOERR_GENERAL;
- rsyserr(FERROR, errno, "link_stat %s failed",
+ rsyserr(FERROR_XFER, errno, "link_stat %s failed",
full_fname(fbuf));
continue;
}
flist = flist_new(0, "send_extra_file_list");
start_write = stats.total_written;
-#ifdef ICONV_OPTION
- if (ic_ndx)
+ if (unsort_ndx)
dir_ndx = F_NDX(file);
else
-#endif
dir_ndx = send_dir_ndx;
write_ndx(f, NDX_FLIST_OFFSET - dir_ndx);
flist->parent_ndx = dir_ndx;
write_byte(f, 0);
-#ifdef ICONV_OPTION
if (need_unsorted_flist) {
if (!(flist->sorted = new_array(struct file_struct *, flist->used)))
out_of_memory("send_extra_file_list");
memcpy(flist->sorted, flist->files,
flist->used * sizeof (struct file_struct*));
} else
-#endif
flist->sorted = flist->files;
- clean_flist(flist, 0);
-
- flist->ndx_end = flist->ndx_start + flist->used - 1;
-#ifdef ICONV_OPTION
- if (!iconv_opt)
-#endif
- flist->ndx_end -= (dir_count - dstart);
+ flist_sort_and_clean(flist, 0);
add_dirs_to_tree(send_dir_ndx, flist, dir_count - dstart);
flist_done_allocating(flist);
disable_buffering = io_start_buffering_out(f);
if (filesfrom_fd >= 0) {
if (argv[0] && !push_dir(argv[0], 0)) {
- rsyserr(FERROR, errno, "push_dir %s failed in %s",
+ rsyserr(FERROR_XFER, errno, "push_dir %s failed in %s",
full_fname(argv[0]), curr_dir);
exit_cleanup(RERR_FILESELECT);
}
if (use_ff_fd) {
if (read_line(filesfrom_fd, fbuf, sizeof fbuf, rl_flags) == 0)
break;
- sanitize_path(fbuf, fbuf, "", 0, NULL);
+ sanitize_path(fbuf, fbuf, "", 0);
} else {
if (argc-- == 0)
break;
strlcpy(fbuf, *argv++, MAXPATHLEN);
if (sanitize_paths)
- sanitize_path(fbuf, fbuf, "", 0, NULL);
+ sanitize_path(fbuf, fbuf, "", 0);
}
len = strlen(fbuf);
if (link_stat(fbuf, &st, copy_dirlinks || name_type != NORMAL_NAME) != 0) {
io_error |= IOERR_GENERAL;
- rsyserr(FERROR, errno, "link_stat %s failed",
+ rsyserr(FERROR_XFER, errno, "link_stat %s failed",
full_fname(fbuf));
continue;
}
file = send_file_name(f, flist, fbuf, &st,
top_flags, ALL_FILTERS);
if (inc_recurse) {
- if (name_type == DOT_NAME) {
+ if (name_type == DOT_NAME && file) {
if (send_dir_depth < 0) {
send_dir_depth = 0;
change_local_filter_dir(fbuf, len, send_dir_depth);
* receiving side to ask for whatever name it kept. For incremental
* recursion mode, the sender marks duplicate dirs so that it can
* send them together in a single file-list. */
-#ifdef ICONV_OPTION
if (need_unsorted_flist) {
- if (inc_recurse) {
- if (!(flist->sorted = new_array(struct file_struct *, flist->used)))
- out_of_memory("send_file_list");
- memcpy(flist->sorted, flist->files,
- flist->used * sizeof (struct file_struct*));
- clean_flist(flist, 0);
- } else {
- flist->sorted = flist->files;
- flist->low = 0;
- flist->high = flist->used - 1;
- }
+ if (!(flist->sorted = new_array(struct file_struct *, flist->used)))
+ out_of_memory("send_file_list");
+ memcpy(flist->sorted, flist->files,
+ flist->used * sizeof (struct file_struct*));
} else
-#endif
- {
flist->sorted = flist->files;
- clean_flist(flist, 0);
- }
+ flist_sort_and_clean(flist, 0);
file_total += flist->used;
- /* We don't subtract dir_count for the first send since we
- * might have one or more dot dirs which need to get sent. */
- flist->ndx_end = flist->ndx_start + flist->used - 1;
-
if (!numeric_ids && !inc_recurse)
send_id_list(f);
}
file_total += flist->used;
- flist->ndx_end = flist->ndx_start + flist->used - 1;
- if (inc_recurse
-#ifdef ICONV_OPTION
- && !iconv_opt
-#endif
- && flist->ndx_start > 1)
- flist->ndx_end -= dir_flist->used - dstart;
-
if (verbose > 2)
rprintf(FINFO, "received %d names\n", flist->used);
if (show_filelist_p())
finish_filelist_progress(flist);
-#ifdef ICONV_OPTION
if (need_unsorted_flist) {
/* Create an extra array of index pointers that we can sort for
* the generator's use (for wading through the files in sorted
memcpy(flist->sorted, flist->files,
flist->used * sizeof (struct file_struct*));
if (inc_recurse && dir_flist->used > dstart) {
- dir_flist->sorted = realloc_array(dir_flist->sorted,
- struct file_struct *,
- dir_flist->used);
+ static int dir_flist_malloced = 0;
+ if (dir_flist_malloced < dir_flist->malloced) {
+ dir_flist->sorted = realloc_array(dir_flist->sorted,
+ struct file_struct *,
+ dir_flist->malloced);
+ dir_flist_malloced = dir_flist->malloced;
+ }
memcpy(dir_flist->sorted + dstart, dir_flist->files + dstart,
(dir_flist->used - dstart) * sizeof (struct file_struct*));
fsort(dir_flist->sorted + dstart, dir_flist->used - dstart);
}
- } else
-#endif
- {
+ } else {
flist->sorted = flist->files;
if (inc_recurse && dir_flist->used > dstart) {
dir_flist->sorted = dir_flist->files;
else if (f >= 0)
recv_id_list(f, flist);
- clean_flist(flist, relative_paths);
+ flist_sort_and_clean(flist, relative_paths);
if (protocol_version < 30) {
/* Recv the io_error flag */
if (!flist->file_pool)
out_of_memory(msg);
- flist->ndx_start = inc_recurse ? 1 : 0;
+ flist->ndx_start = flist->flist_num = inc_recurse ? 1 : 0;
first_flist = cur_flist = flist->prev = flist;
} else {
+ struct file_list *prev = first_flist->prev;
+
flist->file_pool = first_flist->file_pool;
- flist->ndx_start = first_flist->prev->ndx_end + 2;
- if (flist->ndx_start <= high_hlink_ndx)
- flist->ndx_start = high_hlink_ndx + 1;
+ flist->ndx_start = prev->ndx_start + prev->used + 1;
+ flist->flist_num = prev->flist_num + 1;
- flist->prev = first_flist->prev;
- flist->prev->next = first_flist->prev = flist;
+ flist->prev = prev;
+ prev->next = first_flist->prev = flist;
}
flist->pool_boundary = pool_boundary(flist->file_pool, 0);
flist_cnt++;
/* This routine ensures we don't have any duplicate names in our file list.
* duplicate names can cause corruption because of the pipelining. */
-static void clean_flist(struct file_list *flist, int strip_root)
+static void flist_sort_and_clean(struct file_list *flist, int strip_root)
{
char fbuf[MAXPATHLEN];
int i, prev_i;
const char *who = who_am_i();
int i;
- rprintf(FINFO, "[%s] flist start=%d, end=%d, used=%d, low=%d, high=%d\n",
- who, flist->ndx_start, flist->ndx_end, flist->used, flist->low, flist->high);
+ rprintf(FINFO, "[%s] flist start=%d, used=%d, low=%d, high=%d\n",
+ who, flist->ndx_start, flist->used, flist->low, flist->high);
for (i = 0; i < flist->used; i++) {
file = flist->files[i];
if ((am_root || am_sender) && uid_ndx) {
prune_empty_dirs = 0;
dirlist->sorted = dirlist->files;
- clean_flist(dirlist, 0);
+ flist_sort_and_clean(dirlist, 0);
prune_empty_dirs = save_prune_empty_dirs;
if (verbose > 3)