X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/beaf49540079b193da4639b48601e85365899904..1902a7652f138e34519ed5b373d1532c91d3c5eb:/flist.c diff --git a/flist.c b/flist.c index df9988a7..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); @@ -143,14 +142,14 @@ static void list_file_entry(struct file_struct *f) rprintf(FINFO, "%s %11.0f %s %s -> %s\n", perms, (double)f->length, timestring(f->modtime), - f_name(f), f->u.link); + f_name(f, NULL), f->u.link); } else #endif { rprintf(FINFO, "%s %11.0f %s %s\n", perms, (double)f->length, timestring(f->modtime), - f_name(f)); + f_name(f, NULL)); } } @@ -336,7 +335,7 @@ void send_file_entry(struct file_struct *file, int f, unsigned short base_flags) io_write_phase = "send_file_entry"; - f_name_to(file, fname); + f_name(file, fname); flags = base_flags; @@ -852,12 +851,11 @@ struct file_struct *make_file(char *fname, struct file_list *flist, alloc_len = file_struct_len + dirname_len + basename_len + linkname_len + sum_len; - if (flist) { - bp = pool_alloc(flist->file_pool, alloc_len, - "receive_file_entry"); - } else { + if (flist) + bp = pool_alloc(flist->file_pool, alloc_len, "make_file"); + else { if (!(bp = new_array(char, alloc_len))) - out_of_memory("receive_file_entry"); + out_of_memory("make_file"); } file = (struct file_struct *)bp; @@ -979,7 +977,7 @@ static void send_if_directory(int f, struct file_list *flist, char is_dot_dir = fbuf[ol-1] == '.' && (ol == 1 || fbuf[ol-2] == '/'); if (S_ISDIR(file->mode) - && !(file->flags & FLAG_MOUNT_POINT) && f_name_to(file, fbuf)) { + && !(file->flags & FLAG_MOUNT_POINT) && f_name(file, fbuf)) { void *save_filters; unsigned int len = strlen(fbuf); if (len > 1 && fbuf[len-1] == '/') @@ -1104,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'; @@ -1155,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; @@ -1329,8 +1355,10 @@ struct file_list *recv_file_list(int f) maybe_emit_filelist_progress(flist->count); - if (verbose > 2) - rprintf(FINFO, "recv_file_name(%s)\n", f_name(file)); + if (verbose > 2) { + rprintf(FINFO, "recv_file_name(%s)\n", + f_name(file, NULL)); + } } receive_file_entry(NULL, 0, 0); /* Signal that we're done. */ @@ -1475,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) { @@ -1521,7 +1547,7 @@ static void clean_flist(struct file_list *flist, int strip_root, int no_dups) if (verbose > 1 && !am_server) { rprintf(FINFO, "removing duplicate name %s from file list (%d)\n", - f_name(file), drop); + f_name(file, NULL), drop); } /* Make sure that if we unduplicate '.', that we don't * lose track of a user-specified top directory. */ @@ -1739,14 +1765,23 @@ int f_name_cmp(struct file_struct *f1, struct file_struct *f2) } /* Return a copy of the full filename of a flist entry, using the indicated - * buffer. No size-checking is done because we checked the size when creating - * the file_struct entry. + * buffer or one of 5 static buffers if fbuf is NULL. No size-checking is + * done because we checked the size when creating the file_struct entry. */ -char *f_name_to(struct file_struct *f, char *fbuf) +char *f_name(struct file_struct *f, char *fbuf) { if (!f || !f->basename) return NULL; + if (!fbuf) { + static char names[5][MAXPATHLEN]; + static unsigned int n; + + n = (n + 1) % (sizeof names / sizeof names[0]); + + fbuf = names[n]; + } + if (f->dirname) { int len = strlen(f->dirname); memcpy(fbuf, f->dirname, len); @@ -1758,17 +1793,6 @@ char *f_name_to(struct file_struct *f, char *fbuf) return fbuf; } -/* Like f_name_to(), but we rotate through 5 static buffers of our own. */ -char *f_name(struct file_struct *f) -{ - static char names[5][MAXPATHLEN]; - static unsigned int n; - - n = (n + 1) % (sizeof names / sizeof names[0]); - - return f_name_to(f, names[n]); -} - /* Do a non-recursive scan of the named directory, possibly ignoring all * exclude rules except for the daemon's. If "dlen" is >=0, it is the length * of the dirname string, and also indicates that "dirname" is a MAXPATHLEN