X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/429f98283fd8aef3ed01041c637749d7c01899d6..daa598df119f67e96739a1bfcdf5d6ea75efee78:/flist.c diff --git a/flist.c b/flist.c index 1cf9c87c..71667620 100644 --- a/flist.c +++ b/flist.c @@ -57,7 +57,7 @@ extern int relative_paths; extern int implied_dirs; extern int copy_links; extern int copy_unsafe_links; -extern int remote_version; +extern int protocol_version; extern int io_error; extern int sanitize_paths; @@ -258,23 +258,30 @@ int link_stat(const char *path, STRUCT_STAT * buffer) */ static int check_exclude_file(char *fname, int is_dir, int exclude_level) { -#if 0 // This currently never happens, so avoid a useless compare. +#if 0 /* This currently never happens, so avoid a useless compare. */ if (exclude_level == NO_EXCLUDES) return 0; #endif - if (fname && fname[0] == '.' && !fname[1]) { + if (fname) { /* never exclude '.', even if somebody does --exclude '*' */ - return 0; + if (fname[0] == '.' && !fname[1]) + return 0; + /* Handle the -R version of the '.' dir. */ + if (fname[0] == '/') { + int len = strlen(fname); + if (fname[len-1] == '.' && fname[len-2] == '/') + return 0; + } } - if (server_exclude_list && - check_exclude(server_exclude_list, fname, is_dir)) + if (server_exclude_list + && check_exclude(server_exclude_list, fname, is_dir)) return 1; if (exclude_level != ALL_EXCLUDES) return 0; if (exclude_list && check_exclude(exclude_list, fname, is_dir)) return 1; - if (local_exclude_list && - check_exclude(local_exclude_list, fname, is_dir)) + if (local_exclude_list + && check_exclude(local_exclude_list, fname, is_dir)) return 1; return 0; } @@ -439,7 +446,7 @@ static void send_file_entry(struct file_struct *file, int f, #if SUPPORT_HARD_LINKS if (preserve_hard_links && S_ISREG(file->mode)) { - if (remote_version < 26) { + if (protocol_version < 26) { /* 32-bit dev_t and ino_t */ write_int(f, (int) file->dev); write_int(f, (int) file->inode); @@ -452,7 +459,7 @@ static void send_file_entry(struct file_struct *file, int f, #endif if (always_checksum) { - if (remote_version < 21) { + if (protocol_version < 21) { write_buf(f, file->sum, 2); } else { write_buf(f, file->sum, MD4_SUM_LENGTH); @@ -572,7 +579,7 @@ static void receive_file_entry(struct file_struct **fptr, } #if SUPPORT_HARD_LINKS if (preserve_hard_links && S_ISREG(file->mode)) { - if (remote_version < 26) { + if (protocol_version < 26) { file->dev = read_int(f); file->inode = read_int(f); } else { @@ -586,7 +593,7 @@ static void receive_file_entry(struct file_struct **fptr, file->sum = (char *) malloc(MD4_SUM_LENGTH); if (!file->sum) out_of_memory("md4 sum"); - if (remote_version < 21) { + if (protocol_version < 21) { read_buf(f, file->sum, 2); } else { read_buf(f, file->sum, MD4_SUM_LENGTH); @@ -938,14 +945,10 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) } l = strlen(fname); - if (l != 1 && fname[l - 1] == '/') { - if ((l == 2) && (fname[0] == '.')) { - /* Turn ./ into just . rather than ./. - This was put in to avoid a problem with - rsync -aR --delete from ./ - The send_file_name() below of ./ was - mysteriously preventing deletes */ - fname[1] = 0; + if (fname[l - 1] == '/') { + if (l == 2 && fname[0] == '.') { + /* Turn "./" into just "." rather than "./." */ + fname[1] = '\0'; } else { strlcat(fname, ".", MAXPATHLEN); } @@ -1290,7 +1293,7 @@ void flist_free(struct file_list *flist) */ static void clean_flist(struct file_list *flist, int strip_root, int no_dups) { - int i; + int i, prev_i = 0; char *name, *prev_name = NULL; if (!flist || flist->count == 0) @@ -1301,6 +1304,7 @@ static void clean_flist(struct file_list *flist, int strip_root, int no_dups) for (i = no_dups? 0 : flist->count; i < flist->count; i++) { if (flist->files[i]->basename) { + prev_i = i; prev_name = f_name(flist->files[i]); break; } @@ -1315,6 +1319,11 @@ static void clean_flist(struct file_list *flist, int strip_root, int no_dups) "removing duplicate name %s from file list %d\n", name, i); } + /* 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_DELETE) + flist->files[prev_i]->flags |= FLAG_DELETE; /* it's not great that the flist knows the semantics of * the file memory usage, but i'd rather not add a flag * byte to that struct. @@ -1324,6 +1333,10 @@ static void clean_flist(struct file_list *flist, int strip_root, int no_dups) else free_file(flist->files[i]); } + else + prev_i = i; + /* We set prev_name every iteration to avoid it becoming + * invalid when names[][] in f_name() wraps around. */ prev_name = name; }