if (preserve_links && S_ISLNK(file->mode)) {
symlink_name = F_SYMLINK(file);
symlink_len = strlen(symlink_name);
+ if (symlink_len == 0) {
+ io_error |= IOERR_GENERAL;
+ f_name(file, fbuf);
+ rprintf(FERROR_XFER,
+ "skipping symlink with 0-length value: %s\n",
+ full_fname(fbuf));
+ return NULL;
+ }
} else {
symlink_name = NULL;
symlink_len = 0;
DIR_NEXT_SIBLING(dp) = -1;
}
+static void interpret_stat_error(const char *fname, int is_dir)
+{
+ if (errno == ENOENT) {
+ io_error |= IOERR_VANISHED;
+ rprintf(FWARNING, "%s has vanished: %s\n",
+ is_dir ? "directory" : "file", full_fname(fname));
+ } else {
+ io_error |= IOERR_GENERAL;
+ rsyserr(FERROR_XFER, errno, "link_stat %s failed",
+ full_fname(fname));
+ }
+}
+
/* This function is normally called by the sender, but the receiving side also
* calls it from get_dirlist() with f set to -1 so that we just construct the
* file list in memory without sending it over the wire. Also, get_dirlist()
assert(flist != NULL);
if (!(d = opendir(fbuf))) {
- if (errno == ENOENT)
+ if (errno == ENOENT) {
+ if (am_sender) /* Can abuse this for vanished error w/ENOENT: */
+ interpret_stat_error(fbuf, True);
return;
+ }
io_error |= IOERR_GENERAL;
rsyserr(FERROR_XFER, errno, "opendir %s failed", full_fname(fbuf));
return;
if (one_file_system) {
STRUCT_STAT st;
if (link_stat(fbuf, &st, copy_dirlinks) != 0) {
- io_error |= IOERR_GENERAL;
- rsyserr(FERROR_XFER, errno, "link_stat %s failed",
- full_fname(fbuf));
+ interpret_stat_error(fbuf, True);
return;
}
filesystem_dev = st.st_dev;
if (name_type != NORMAL_NAME) {
STRUCT_STAT st;
if (link_stat(fbuf, &st, 1) != 0) {
- io_error |= IOERR_GENERAL;
- rsyserr(FERROR_XFER, errno, "link_stat %s failed",
- full_fname(fbuf));
+ interpret_stat_error(fbuf, True);
continue;
}
send_file_name(f, flist, fbuf, &st, FLAG_TOP_DIR | flags, ALL_FILTERS);
write_byte(f, 0);
else {
write_shortint(f, XMIT_EXTENDED_FLAGS|XMIT_IO_ERROR_ENDLIST);
- write_int(f, io_error);
+ write_varint(f, io_error);
}
if (need_unsorted_flist) {
write_byte(f, 0);
else {
write_shortint(f, XMIT_EXTENDED_FLAGS|XMIT_IO_ERROR_ENDLIST);
- write_int(f, io_error);
+ write_varint(f, io_error);
}
#ifdef SUPPORT_HARD_LINKS
if (numeric_ids <= 0 && !inc_recurse)
send_id_list(f);
+ set_msg_fd_in(-1);
+
/* send the io_error flag */
if (protocol_version < 30)
write_int(f, ignore_errors ? 0 : io_error);
* file-list to check if this is a 1-file xfer. */
send_extra_file_list(f, 1);
}
- }
+ } else
+ flist_eof = 1;
return flist;
}
rprintf(FERROR, "Invalid flist flag: %x\n", flags);
exit_cleanup(RERR_PROTOCOL);
}
- err = read_int(f);
+ err = read_varint(f);
if (!ignore_errors)
io_error |= err;
break;
if (inc_recurse)
flist_done_allocating(flist);
- else if (f >= 0)
+ else if (f >= 0) {
recv_id_list(f, flist);
+ flist_eof = 1;
+ }
flist_sort_and_clean(flist, relative_paths);