int io_error;
int checksum_len;
-dev_t filesystem_dev; /* used to implement -x */
static char empty_sum[MD4_SUM_LENGTH];
static int flist_count_offset;
if (!(flags & XMIT_SAME_MODE))
mode = from_wire_mode(read_int(f));
- if (chmod_modes && (S_ISREG(mode) || S_ISDIR(mode)))
+ if (chmod_modes && !S_ISLNK(mode))
mode = tweak_mode(mode, chmod_modes);
if (preserve_uid && !(flags & XMIT_SAME_UID))
/* We only care about directories because we need to avoid recursing
* into a mount-point directory, not to avoid copying a symlinked
* file if -L (or similar) was specified. */
- if (one_file_system && st.st_dev != filesystem_dev
- && S_ISDIR(st.st_mode)) {
- if (one_file_system > 1)
- return NULL;
- flags |= FLAG_MOUNT_POINT;
+ if (one_file_system && S_ISDIR(st.st_mode) && !(flags & FLAG_TOP_DIR)) {
+ STRUCT_STAT st2;
+ unsigned int len = strlcat(thisname, "/..", sizeof thisname);
+ /* If the directory's .. dir is on a different filesystem,
+ * either mark this dir as a mount-point or skip it. */
+ if (len < sizeof thisname && do_stat(thisname, &st2) == 0
+ && (st.st_dev != st2.st_dev || st.st_ino != st2.st_ino)) {
+ if (one_file_system > 1) {
+ if (verbose > 2) {
+ rprintf(FINFO,
+ "skipping mount-point dir %s\n",
+ thisname);
+ }
+ return NULL;
+ }
+ flags |= FLAG_MOUNT_POINT;
+ }
+ thisname[len-3] = '\0';
}
if (is_excluded(thisname, S_ISDIR(st.st_mode) != 0, filter_level))
if (!file)
return NULL;
- if (chmod_modes && (S_ISREG(file->mode) || S_ISDIR(file->mode)))
+ if (chmod_modes && !S_ISLNK(file->mode))
file->mode = tweak_mode(file->mode, chmod_modes);
maybe_emit_filelist_progress(flist->count + flist_count_offset);
}
}
- if (one_file_system)
- filesystem_dev = st.st_dev;
-
if (recurse || (xfer_dirs && is_dot_dir)) {
struct file_struct *file;
file = send_file_name(f, flist, fbuf, &st, FLAG_TOP_DIR);