From: Wayne Davison Date: Tue, 10 Oct 2006 23:44:59 +0000 (+0000) Subject: Changed the fix_basis_dirs() function to only remove a single ../ X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/commitdiff_plain/ddcba3f0750473678dc9a4a5209e3a628627cf7e Changed the fix_basis_dirs() function to only remove a single ../ prefix from each --*-dest option's path. --- diff --git a/main.c b/main.c index ed0ce0ad..eed9c0fd 100644 --- a/main.c +++ b/main.c @@ -579,17 +579,30 @@ static char *get_local_name(struct file_list *flist, char *dest_path) * mode. We'll fix dirs that can be relative to the non-existent dir. */ static void fix_basis_dirs(void) { - char **dir, *new; + char **dir, *new, *slash; int len; + if (dry_run <= 1) + return; + + slash = strrchr(curr_dir, '/'); + for (dir = basis_dir; *dir; dir++) { if (**dir == '/') continue; len = curr_dir_len + 1 + strlen(*dir) + 1; if (!(new = new_array(char, len))) out_of_memory("fix_basis_dirs"); - pathjoin(new, len, curr_dir, *dir); - clean_fname(new, 1); + if (slash && strncmp(*dir, "../", 3) == 0) { + /* We want to remove only one leading "../" prefix for + * the directory we couldn't create in dry-run mode: + * this ensures that any other ".." references get + * evaluated the same as they would for a live copy. */ + *slash = '\0'; + pathjoin(new, len, curr_dir, *dir + 3); + *slash = '/'; + } else + pathjoin(new, len, curr_dir, *dir); *dir = new; } } @@ -847,8 +860,7 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[]) die_on_unsafe_path(partial_dir, 0); } } - if (dry_run > 1) - fix_basis_dirs(); + fix_basis_dirs(); if (server_filter_list.head) { char **dir; @@ -997,8 +1009,7 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[]) if (flist && flist->count > 0) { local_name = get_local_name(flist, argv[0]); - if (dry_run > 1) - fix_basis_dirs(); + fix_basis_dirs(); exit_code2 = do_recv(f_in, f_out, flist, local_name); } else {