X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/8c48382049712e11691ca99a4c7583510abf1a32..82471e68a8bb3da8ca95f2b6564c330c52ce891e:/flist.c diff --git a/flist.c b/flist.c index 7e655820..21eef260 100644 --- a/flist.c +++ b/flist.c @@ -43,7 +43,7 @@ extern int numeric_ids; extern int cvs_exclude; extern int recurse; -extern int keep_dirs; +extern int xfer_dirs; extern char curr_dir[MAXPATHLEN]; extern int filesfrom_fd; @@ -89,7 +89,7 @@ void init_flist(void) static int show_filelist_p(void) { - return verbose && keep_dirs && !am_server; + return verbose && xfer_dirs && !am_server; } static void start_filelist_progress(char *kind) @@ -422,11 +422,11 @@ void send_file_entry(struct file_struct *file, int f, unsigned short base_flags) /* We must make sure we don't send a zero flag byte or the * other end will terminate the flist transfer. Note that - * the use of XMIT_TOP_DIR on a non-dir has no meaning, so + * the use of XMIT_DEL_START on a non-dir has no meaning, so * it's harmless way to add a bit to the first flag byte. */ if (protocol_version >= 28) { if (!flags && !S_ISDIR(mode)) - flags |= XMIT_TOP_DIR; + flags |= XMIT_DEL_START; if ((flags & 0xFF00) || !flags) { flags |= XMIT_EXTENDED_FLAGS; write_byte(f, flags); @@ -435,7 +435,7 @@ void send_file_entry(struct file_struct *file, int f, unsigned short base_flags) write_byte(f, flags); } else { if (!(flags & 0xFF) && !S_ISDIR(mode)) - flags |= XMIT_TOP_DIR; + flags |= XMIT_DEL_START; if (!(flags & 0xFF)) flags |= XMIT_LONG_NAME; write_byte(f, flags); @@ -645,7 +645,7 @@ void receive_file_entry(struct file_struct **fptr, unsigned short flags, memset(bp, 0, file_struct_len); bp += file_struct_len; - file->flags = flags & XMIT_TOP_DIR ? FLAG_TOP_DIR : 0; + file->flags = flags & XMIT_DEL_START ? FLAG_DEL_START : 0; file->modtime = modtime; file->length = file_length; file->mode = mode; @@ -804,7 +804,7 @@ struct file_struct *make_file(char *fname, struct file_list *flist, if (exclude_level == NO_EXCLUDES) goto skip_excludes; - if (S_ISDIR(st.st_mode) && !keep_dirs) { + if (S_ISDIR(st.st_mode) && !xfer_dirs) { rprintf(FINFO, "skipping directory %s\n", thisname); return NULL; } @@ -996,6 +996,8 @@ void send_file_name(int f, struct file_list *flist, char *fname, } +/* Note that the "recurse" value either contains -1, for infinite recursion, + * or a number >= 0 indicating how many levels of recursion we will allow. */ static void send_directory(int f, struct file_list *flist, char *dir) { DIR *d; @@ -1044,7 +1046,8 @@ static void send_directory(int f, struct file_list *flist, char *dir) || (dname[1] == '.' && dname[2] == '\0'))) continue; if (strlcpy(p, dname, MAXPATHLEN - offset) < MAXPATHLEN - offset) { - send_file_name(f, flist, fname, recurse, 0); + int do_subdirs = recurse >= 1 ? recurse-- : recurse; + send_file_name(f, flist, fname, do_subdirs, 0); } else { io_error |= IOERR_GENERAL; rprintf(FINFO, @@ -1085,7 +1088,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) start_write = stats.total_written; flist = flist_new(f == -1 ? WITHOUT_HLINK : WITH_HLINK, - "send_file_list"); + "send_file_list"); if (f != -1) { io_start_buffering_out(); @@ -1102,6 +1105,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) while (1) { char fname2[MAXPATHLEN]; char *fname = fname2; + int do_subdirs; if (use_ff_fd) { if (read_filesfrom_line(filesfrom_fd, fname) == 0) @@ -1116,7 +1120,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) } l = strlen(fname); - if (fname[l - 1] == '/') { + if (!l || fname[l - 1] == '/') { if (l == 2 && fname[0] == '.') { /* Turn "./" into just "." rather than "./." */ fname[1] = '\0'; @@ -1125,6 +1129,11 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) fname[l] = '\0'; } } + if (fname[l-1] == '.' && (l == 1 || fname[l-2] == '/')) { + if (!recurse && xfer_dirs) + recurse = 1; /* allow one level */ + } else if (recurse > 0) + recurse = 0; if (link_stat(fname, &st, keep_dirlinks) != 0) { if (f != -1) { @@ -1135,7 +1144,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) continue; } - if (S_ISDIR(st.st_mode) && !keep_dirs) { + if (S_ISDIR(st.st_mode) && !xfer_dirs) { rprintf(FINFO, "skipping directory %s\n", fname); continue; } @@ -1168,16 +1177,16 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) *p = '/'; if (fn != p || (*lp && *lp != '/')) { int save_copy_links = copy_links; - int save_keep_dirs = keep_dirs; + int save_xfer_dirs = xfer_dirs; copy_links = copy_unsafe_links; - keep_dirs = 1; + xfer_dirs = 1; while ((slash = strchr(slash+1, '/')) != 0) { *slash = 0; send_file_name(f, flist, fname, 0, 0); *slash = '/'; } copy_links = save_copy_links; - keep_dirs = save_keep_dirs; + xfer_dirs = save_xfer_dirs; *p = 0; strlcpy(lastpath, fname, sizeof lastpath); *p = '/'; @@ -1212,7 +1221,8 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) if (one_file_system) set_filesystem(fname); - send_file_name(f, flist, fname, recurse, XMIT_TOP_DIR); + do_subdirs = recurse >= 1 ? recurse-- : recurse; + send_file_name(f, flist, fname, do_subdirs, XMIT_DEL_START); if (olddir[0]) { flist_dir = NULL; @@ -1475,8 +1485,8 @@ static void clean_flist(struct file_list *flist, int strip_root, int no_dups) /* Make sure that if we unduplicate '.', that we don't * lose track of a user-specified starting point (or * else deletions will mysteriously fail with -R). */ - if (flist->files[i]->flags & FLAG_TOP_DIR) - flist->files[prev_i]->flags |= FLAG_TOP_DIR; + if (flist->files[i]->flags & FLAG_DEL_START) + flist->files[prev_i]->flags |= FLAG_DEL_START; clear_file(i, flist); } else