X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/ede1f0ebc97a7ed154e10c721f69ef3e9309ff72..7b6fa00ff8abf063dae4a974fc824d430d228d14:/flist.c diff --git a/flist.c b/flist.c index af1e6a72..87a2ba79 100644 --- a/flist.c +++ b/flist.c @@ -70,10 +70,10 @@ extern struct filter_list_struct server_filter_list; int io_error; int checksum_len; dev_t filesystem_dev; /* used to implement -x */ +unsigned int file_struct_len; static char empty_sum[MD4_SUM_LENGTH]; static int flist_count_offset; -static unsigned int file_struct_len; static void clean_flist(struct file_list *flist, int strip_root, int no_dups); static void output_flist(struct file_list *flist); @@ -306,7 +306,7 @@ void flist_expand(struct file_list *flist) out_of_memory("flist_expand"); } -void send_file_entry(struct file_struct *file, int f, unsigned short base_flags) +static void send_file_entry(struct file_struct *file, int f) { unsigned short flags; static time_t modtime; @@ -337,7 +337,7 @@ void send_file_entry(struct file_struct *file, int f, unsigned short base_flags) f_name(file, fname); - flags = base_flags; + flags = file->flags & XMIT_TOP_DIR; if (file->mode == mode) flags |= XMIT_SAME_MODE; @@ -569,6 +569,9 @@ static struct file_struct *receive_file_entry(struct file_list *flist, if (!(flags & XMIT_SAME_MODE)) mode = from_wire_mode(read_int(f)); + if (chmod_modes && !S_ISLNK(mode)) + mode = tweak_mode(mode, chmod_modes); + if (preserve_uid && !(flags & XMIT_SAME_UID)) uid = (uid_t)read_int(f); if (preserve_gid && !(flags & XMIT_SAME_GID)) @@ -616,7 +619,6 @@ static struct file_struct *receive_file_entry(struct file_list *flist, memset(bp, 0, file_struct_len); bp += file_struct_len; - file->flags = 0; file->modtime = modtime; file->length = file_length; file->mode = mode; @@ -644,13 +646,14 @@ static struct file_struct *receive_file_entry(struct file_list *flist, in_del_hier = recurse; del_hier_name_len = file->dir.depth == 0 ? 0 : l1 + l2; if (relative_paths && del_hier_name_len > 2 - && basename_len == 1+1 && *basename == '.') + && lastname[del_hier_name_len-1] == '.' + && lastname[del_hier_name_len-2] == '/') del_hier_name_len -= 2; file->flags |= FLAG_TOP_DIR | FLAG_DEL_HERE; } else if (in_del_hier) { if (!relative_paths || !del_hier_name_len || (l1 >= del_hier_name_len - && thisname[del_hier_name_len] == '/')) + && lastname[del_hier_name_len] == '/')) file->flags |= FLAG_DEL_HERE; else in_del_hier = 0; @@ -733,7 +736,8 @@ static struct file_struct *receive_file_entry(struct file_list *flist, * important case. Some systems may not have d_type. **/ struct file_struct *make_file(char *fname, struct file_list *flist, - STRUCT_STAT *stp, int filter_level) + STRUCT_STAT *stp, unsigned short flags, + int filter_level) { static char *lastdir; static int lastdir_len = -1; @@ -744,7 +748,6 @@ struct file_struct *make_file(char *fname, struct file_list *flist, char linkname[MAXPATHLEN]; int alloc_len, basename_len, dirname_len, linkname_len, sum_len; char *basename, *dirname, *bp; - unsigned short flags = 0; if (!flist || !flist->count) /* Ignore lastdir when invalid. */ lastdir_len = -1; @@ -806,8 +809,16 @@ struct file_struct *make_file(char *fname, struct file_list *flist, * 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)) + && S_ISDIR(st.st_mode)) { + if (one_file_system > 1) { + if (verbose > 2) { + rprintf(FINFO, "skipping mount-point dir %s\n", + thisname); + } + return NULL; + } flags |= FLAG_MOUNT_POINT; + } if (is_excluded(thisname, S_ISDIR(st.st_mode) != 0, filter_level)) return NULL; @@ -867,10 +878,7 @@ struct file_struct *make_file(char *fname, struct file_list *flist, file->flags = flags; file->modtime = st.st_mtime; file->length = st.st_size; - if (chmod_modes && am_sender && (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))) - file->mode = tweak_mode(st.st_mode, chmod_modes); - else - file->mode = st.st_mode; + file->mode = st.st_mode; file->uid = st.st_uid; file->gid = st.st_gid; @@ -933,7 +941,7 @@ struct file_struct *make_file(char *fname, struct file_list *flist, if (keep_dirlinks && linkname_len && flist) { STRUCT_STAT st2; int save_mode = file->mode; - file->mode = S_IFDIR; /* find a directory w/our name */ + file->mode = S_IFDIR; /* Find a directory with our name. */ if (flist_find(the_file_list, file) >= 0 && do_stat(thisname, &st2) == 0 && S_ISDIR(st2.st_mode)) { file->modtime = st2.st_mtime; @@ -954,22 +962,25 @@ struct file_struct *make_file(char *fname, struct file_list *flist, static struct file_struct *send_file_name(int f, struct file_list *flist, char *fname, STRUCT_STAT *stp, - unsigned short base_flags) + unsigned short flags) { struct file_struct *file; - file = make_file(fname, flist, stp, + file = make_file(fname, flist, stp, flags, f == -2 ? SERVER_FILTERS : ALL_FILTERS); if (!file) return NULL; + if (chmod_modes && !S_ISLNK(file->mode)) + file->mode = tweak_mode(file->mode, chmod_modes); + maybe_emit_filelist_progress(flist->count + flist_count_offset); flist_expand(flist); if (file->basename[0]) { flist->files[flist->count++] = file; - send_file_entry(file, f, base_flags); + send_file_entry(file, f); } return file; } @@ -1268,7 +1279,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) if (recurse || (xfer_dirs && is_dot_dir)) { struct file_struct *file; - file = send_file_name(f, flist, fbuf, &st, XMIT_TOP_DIR); + file = send_file_name(f, flist, fbuf, &st, FLAG_TOP_DIR); if (file) send_if_directory(f, flist, file, fbuf, len); } else @@ -1292,7 +1303,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) stats.flist_buildtime = 1; start_tv = end_tv; - send_file_entry(NULL, f, 0); + send_file_entry(NULL, f); if (show_filelist_p()) finish_filelist_progress(flist); @@ -1312,8 +1323,6 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) * without causing a compatibility problem with older versions. */ clean_flist(flist, 0, 0); - /* Now send the uid/gid list. This was introduced in - * protocol version 15 */ send_uid_list(f); /* send the io_error flag */ @@ -1383,8 +1392,6 @@ struct file_list *recv_file_list(int f) clean_flist(flist, relative_paths, 1); if (f >= 0) { - /* Now send the uid/gid list. This was introduced in - * protocol version 15 */ recv_uid_list(f, flist); /* Recv the io_error flag */