extern int sanitize_paths;
extern int munge_symlinks;
extern int need_unsorted_flist;
+extern int sender_symlink_iconv;
extern int unsort_ndx;
extern struct stats stats;
extern char *filesfrom_host;
if (!change_dir(dir, CD_NORMAL)) {
chdir_error:
io_error |= IOERR_GENERAL;
- rsyserr(FERROR, errno, "change_dir %s failed", full_fname(dir));
+ rsyserr(FERROR_XFER, errno, "change_dir %s failed", full_fname(dir));
if (dir != orig_dir)
change_dir(orig_dir, CD_NORMAL);
pathname = NULL;
return 1;
}
-static void send_file_entry(int f, const char *fname, struct file_struct *file, int ndx, int first_ndx)
+static void send_file_entry(int f, const char *fname, struct file_struct *file,
+#ifdef SUPPORT_LINKS
+ const char *symlink_name, int symlink_len,
+#endif
+ int ndx, int first_ndx)
{
static time_t modtime;
static mode_t mode;
}
#ifdef SUPPORT_LINKS
- if (preserve_links && S_ISLNK(mode)) {
- const char *sl = F_SYMLINK(file);
- int len = strlen(sl);
- write_varint30(f, len);
- write_buf(f, sl, len);
+ if (symlink_len) {
+ write_varint30(f, symlink_len);
+ write_buf(f, symlink_name, symlink_len);
}
#endif
if (iconvbufs(ic_recv, &inbuf, &outbuf, 0) < 0) {
io_error |= IOERR_GENERAL;
- rprintf(FINFO,
+ rprintf(FERROR_UTF8,
"[%s] cannot convert filename: %s (%s)\n",
who_am_i(), lastname, strerror(errno));
outbuf.len = 0;
}
- outbuf.buf[outbuf.len] = '\0';
+ thisname[outbuf.len] = '\0';
}
#endif
linkname_len - 1);
overflow_exit("recv_file_entry");
}
+#ifdef ICONV_OPTION
+ /* We don't know how much extra room we need to convert
+ * the as-yet-unread symlink data, so let's hope that a
+ * double-size buffer is plenty. */
+ if (sender_symlink_iconv)
+ linkname_len *= 2;
+#endif
if (munge_symlinks)
linkname_len += SYMLINK_PREFIX_LEN;
}
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 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);
} else {
- read_sbuf(f, bp, linkname_len - 1);
- if (sanitize_paths)
+ if (munge_symlinks) {
+ strlcpy(bp, SYMLINK_PREFIX, linkname_len);
+ bp += SYMLINK_PREFIX_LEN;
+ linkname_len -= SYMLINK_PREFIX_LEN;
+ }
+#ifdef ICONV_OPTION
+ if (sender_symlink_iconv) {
+ xbuf outbuf, inbuf;
+
+ alloc_len = linkname_len;
+ linkname_len /= 2;
+
+ /* Read the symlink data into the end of our double-sized
+ * buffer and then convert it into the right spot. */
+ INIT_XBUF(inbuf, bp + alloc_len - linkname_len,
+ linkname_len - 1, (size_t)-1);
+ read_sbuf(f, inbuf.buf, inbuf.len);
+ INIT_XBUF(outbuf, bp, 0, alloc_len);
+
+ if (iconvbufs(ic_recv, &inbuf, &outbuf, 0) < 0) {
+ io_error |= IOERR_GENERAL;
+ rprintf(FERROR_XFER,
+ "[%s] cannot convert symlink data for: %s (%s)\n",
+ who_am_i(), full_fname(thisname), strerror(errno));
+ bp = (char*)file->basename;
+ *bp++ = '\0';
+ outbuf.len = 0;
+ }
+ bp[outbuf.len] = '\0';
+ } else
+#endif
+ read_sbuf(f, bp, linkname_len - 1);
+ if (sanitize_paths && !munge_symlinks && *bp)
sanitize_path(bp, bp, "", lastdir_depth, SP_DEFAULT);
}
}
if (strlcpy(thisname, fname, sizeof thisname) >= sizeof thisname) {
io_error |= IOERR_GENERAL;
- rprintf(FINFO, "skipping overly long name: %s\n", fname);
+ rprintf(FERROR_XFER, "skipping overly long name: %s\n", fname);
return NULL;
}
clean_fname(thisname, 0);
}
} else {
io_error |= IOERR_GENERAL;
- rsyserr(FERROR_XFER, save_errno, "readlink %s failed",
+ rsyserr(FERROR_XFER, save_errno, "readlink_stat(%s) failed",
full_fname(thisname));
}
return NULL;
if (protocol_version >= 28
? (!S_ISDIR(st.st_mode) && st.st_nlink > 1)
: S_ISREG(st.st_mode)) {
- tmp_dev = st.st_dev;
- tmp_ino = st.st_ino;
+ tmp_dev = (int64)st.st_dev + 1;
+ tmp_ino = (int64)st.st_ino;
} else
tmp_dev = 0;
}
if (f >= 0) {
char fbuf[MAXPATHLEN];
+#ifdef SUPPORT_LINKS
+ const char *symlink_name;
+ int symlink_len;
+#ifdef ICONV_OPTION
+ char symlink_buf[MAXPATHLEN];
+#endif
+#endif
#if defined SUPPORT_ACLS || defined SUPPORT_XATTRS
stat_x sx;
#endif
+#ifdef SUPPORT_LINKS
+ if (preserve_links && S_ISLNK(file->mode)) {
+ symlink_name = F_SYMLINK(file);
+ symlink_len = strlen(symlink_name);
+ } else {
+ symlink_name = NULL;
+ symlink_len = 0;
+ }
+#endif
+
#ifdef ICONV_OPTION
if (ic_send != (iconv_t)-1) {
xbuf outbuf, inbuf;
if (iconvbufs(ic_send, &inbuf, &outbuf, 0) < 0)
goto convert_error;
outbuf.size += 2;
- outbuf.buf[outbuf.len++] = '/';
+ fbuf[outbuf.len++] = '/';
}
INIT_XBUF_STRLEN(inbuf, (char*)file->basename);
if (iconvbufs(ic_send, &inbuf, &outbuf, 0) < 0) {
convert_error:
io_error |= IOERR_GENERAL;
- rprintf(FINFO,
+ rprintf(FERROR_XFER,
"[%s] cannot convert filename: %s (%s)\n",
who_am_i(), f_name(file, fbuf), strerror(errno));
return NULL;
}
- outbuf.buf[outbuf.len] = '\0';
+ fbuf[outbuf.len] = '\0';
+
+#ifdef SUPPORT_LINKS
+ if (symlink_len && sender_symlink_iconv) {
+ INIT_XBUF(inbuf, (char*)symlink_name, symlink_len, (size_t)-1);
+ INIT_CONST_XBUF(outbuf, symlink_buf);
+ if (iconvbufs(ic_send, &inbuf, &outbuf, 0) < 0) {
+ io_error |= IOERR_GENERAL;
+ f_name(file, fbuf);
+ rprintf(FERROR_XFER,
+ "[%s] cannot convert symlink data for: %s (%s)\n",
+ who_am_i(), full_fname(fbuf), strerror(errno));
+ return NULL;
+ }
+ symlink_buf[outbuf.len] = '\0';
+
+ symlink_name = symlink_buf;
+ symlink_len = outbuf.len;
+ }
+#endif
} else
#endif
f_name(file, fbuf);
}
#endif
- send_file_entry(f, fbuf, file, flist->used, flist->ndx_start);
+ send_file_entry(f, fbuf, file,
+#ifdef SUPPORT_LINKS
+ symlink_name, symlink_len,
+#endif
+ flist->used, flist->ndx_start);
#ifdef SUPPORT_ACLS
if (preserve_acls && !S_ISLNK(file->mode)) {
continue;
if (strlcpy(p, dname, remainder) >= remainder) {
io_error |= IOERR_GENERAL;
- rprintf(FINFO,
+ rprintf(FERROR_XFER,
"cannot send long-named file %s\n",
full_fname(fbuf));
continue;
}
if (dname[0] == '\0') {
io_error |= IOERR_GENERAL;
- rprintf(FINFO,
+ rprintf(FERROR_XFER,
"cannot send file with empty name in %s\n",
full_fname(fbuf));
continue;
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[flist->low]->basename, ".") != 0)
flist->parent_ndx = -1;
flist_done_allocating(flist);
if (send_dir_ndx < 0) {
maybe_emit_filelist_progress(flist->used);
if (verbose > 2) {
- rprintf(FINFO, "recv_file_name(%s)\n",
- f_name(file, NULL));
+ char *name = f_name(file, NULL);
+ rprintf(FINFO, "recv_file_name(%s)\n", NS(name));
}
}
file_total += flist->used;
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[flist->low]->basename, ".") != 0)
flist->parent_ndx = -1;
}