X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/5e4ff5f9c58c2b84ef32d43e542a8fa12b64bc65..1902a7652f138e34519ed5b373d1532c91d3c5eb:/flist.c diff --git a/flist.c b/flist.c index 2eafdccf..08ac3c92 100644 --- a/flist.c +++ b/flist.c @@ -74,7 +74,6 @@ dev_t filesystem_dev; /* used to implement -x */ static char empty_sum[MD4_SUM_LENGTH]; static int flist_count_offset; static unsigned int file_struct_len; -static struct file_list *sorting_flist; static void clean_flist(struct file_list *flist, int strip_root, int no_dups); static void output_flist(struct file_list *flist); @@ -1103,7 +1102,10 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) } len = strlen(fbuf); - if (!len || fbuf[len - 1] == '/') { + if (relative_paths) { + /* We clean up fbuf below. */ + is_dot_dir = 0; + } else if (!len || fbuf[len - 1] == '/') { if (len == 2 && fbuf[0] == '.') { /* Turn "./" into just "." rather than "./." */ fbuf[1] = '\0'; @@ -1154,16 +1156,41 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) fn = p + 1; } else fn = fbuf; - } else if ((p = strstr(fbuf, "/./")) != NULL) { - *p = '\0'; - if (p == fbuf) - dir = "/"; - else - dir = fbuf; - len -= p - fbuf + 3; - fn = p + 3; - } else - fn = fbuf; + } else { + if ((p = strstr(fbuf, "/./")) != NULL) { + *p = '\0'; + if (p == fbuf) + dir = "/"; + else + dir = fbuf; + len -= p - fbuf + 3; + fn = p + 3; + } else + fn = fbuf; + /* Get rid of trailing "/" and "/.". */ + while (len) { + if (fn[len - 1] == '/') + len--; + else if (len >= 2 && fn[len - 1] == '.' + && fn[len - 2] == '/') { + if (!(len -= 2) && !dir) { + len++; + break; + } + } else + break; + } + fn[len] = '\0'; + /* Reject a ".." dir in the active part of the path. */ + if ((p = strstr(fbuf, "..")) != NULL + && (p[2] == '/' || p[2] == '\0') + && (p == fbuf || p[-1] == '/')) { + rprintf(FERROR, + "using a \"..\" dir is invalid with --relative: %s\n", + fbuf); + exit_cleanup(RERR_SYNTAX); + } + } if (!*fn) { len = 1; @@ -1476,10 +1503,8 @@ static void clean_flist(struct file_list *flist, int strip_root, int no_dups) return; } - sorting_flist = flist; qsort(flist->files, flist->count, sizeof flist->files[0], (int (*)())file_compare); - sorting_flist = NULL; for (i = no_dups? 0 : flist->count; i < flist->count; i++) { if (flist->files[i]->basename) {