X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/eddd5d129e20bb27aa8ffde4f63e92a35f6bedf8..64f21c31bf5df798c0f5a2dc70c46f5ad9e2b778:/flist.c diff --git a/flist.c b/flist.c index 4c7331f5..7ea494f8 100644 --- a/flist.c +++ b/flist.c @@ -43,6 +43,7 @@ extern int ignore_errors; extern int cvs_exclude; extern int recurse; +extern char curr_dir[MAXPATHLEN]; extern char *files_from; extern int filesfrom_fd; @@ -292,6 +293,7 @@ static void set_filesystem(char *fname) STRUCT_STAT st; if (link_stat(fname, &st) != 0) return; + filesystem_dev = st.st_dev; } @@ -314,6 +316,7 @@ static mode_t from_wire_mode(int mode) static void send_directory(int f, struct file_list *flist, char *dir); static char *flist_dir; +static int flist_dir_len; /** @@ -380,7 +383,7 @@ void send_file_entry(struct file_struct *file, int f, unsigned short base_flags) io_write_phase = "send_file_entry"; - fname = f_name_to(file, fbuf, sizeof fbuf); + fname = f_name_to(file, fbuf); flags = base_flags; @@ -521,7 +524,6 @@ void send_file_entry(struct file_struct *file, int f, unsigned short base_flags) } strlcpy(lastname, fname, MAXPATHLEN); - lastname[MAXPATHLEN - 1] = 0; io_write_phase = "unknown"; } @@ -602,7 +604,7 @@ void receive_file_entry(struct file_struct **fptr, unsigned short flags, int f) if (!file->basename) out_of_memory("receive_file_entry 1"); - file->flags = flags; + file->flags = flags & LIVE_FLAGS; file->length = read_longint(f); if (!(flags & SAME_TIME)) modtime = (time_t)read_int(f); @@ -694,28 +696,24 @@ void receive_file_entry(struct file_struct **fptr, unsigned short flags, int f) } -/* determine if a file in a different filesstem should be skipped +/* determine if a file in a different filesystem should be skipped when one_file_system is set. We bascally only want to include the mount points - but they can be hard to find! */ static int skip_filesystem(char *fname, STRUCT_STAT * st) { STRUCT_STAT st2; - char *p = strrchr(fname, '/'); /* skip all but directories */ if (!S_ISDIR(st->st_mode)) return 1; /* if its not a subdirectory then allow */ - if (!p) + if (!strrchr(fname, '/')) return 0; - *p = 0; - if (link_stat(fname, &st2)) { - *p = '/'; + if (link_stat(fname, &st2) != 0) { return 0; } - *p = '/'; return (st2.st_dev != filesystem_dev); } @@ -749,8 +747,11 @@ struct file_struct *make_file(char *fname, struct string_area **ap, char cleaned_name[MAXPATHLEN]; char linkbuf[MAXPATHLEN]; - strlcpy(cleaned_name, fname, MAXPATHLEN); - cleaned_name[MAXPATHLEN - 1] = 0; + if (strlcpy(cleaned_name, fname, sizeof cleaned_name) + >= sizeof cleaned_name - flist_dir_len) { + rprintf(FINFO, "skipping overly long name: %s\n", fname); + return NULL; + } clean_fname(cleaned_name); if (sanitize_paths) sanitize_path(cleaned_name, NULL); @@ -851,16 +852,7 @@ struct file_struct *make_file(char *fname, struct string_area **ap, file_checksum(fname, file->u.sum, st.st_size); } - if (flist_dir) { - static char *lastdir; - if (lastdir && strcmp(lastdir, flist_dir) == 0) - file->basedir = lastdir; - else { - file->basedir = strdup(flist_dir); - lastdir = file->basedir; - } - } else - file->basedir = NULL; + file->basedir = flist_dir; if (!S_ISDIR(st.st_mode)) stats.total_size += st.st_size; @@ -899,7 +891,7 @@ void send_file_name(int f, struct file_list *flist, char *fname, if (S_ISDIR(file->mode) && recursive) { struct exclude_struct **last_exclude_list = local_exclude_list; - send_directory(f, flist, f_name_to(file, fbuf, sizeof fbuf)); + send_directory(f, flist, f_name_to(file, fbuf)); local_exclude_list = last_exclude_list; return; } @@ -987,7 +979,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) { int l; STRUCT_STAT st; - char *p, *dir, *olddir; + char *p, *dir, olddir[sizeof curr_dir]; char lastpath[MAXPATHLEN] = ""; struct file_list *flist; int64 start_write; @@ -1003,7 +995,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) if (f != -1) { io_start_buffering_out(f); if (filesfrom_fd >= 0) { - if (argv[0] && !push_dir(argv[0], 0)) { + if (argv[0] && !push_dir(argv[0])) { rprintf(FERROR, "push_dir %s failed: %s\n", full_fname(argv[0]), strerror(errno)); exit_cleanup(RERR_FILESELECT); @@ -1054,7 +1046,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) } dir = NULL; - olddir = NULL; + olddir[0] = '\0'; if (!relative_paths) { p = strrchr(fname, '/'); @@ -1105,16 +1097,27 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) fname = "."; if (dir && *dir) { - olddir = push_dir(dir, 1); + static char *lastdir; + static int lastdir_len; - if (!olddir) { + strcpy(olddir, curr_dir); /* can't overflow */ + + if (!push_dir(dir)) { io_error |= IOERR_GENERAL; rprintf(FERROR, "push_dir %s failed: %s\n", full_fname(dir), strerror(errno)); continue; } - flist_dir = dir; + if (lastdir && strcmp(lastdir, dir) == 0) { + flist_dir = lastdir; + flist_dir_len = lastdir_len; + } else { + if (lastdir) + free(lastdir); + flist_dir = lastdir = strdup(dir); + flist_dir_len = lastdir_len = strlen(dir); + } } if (one_file_system) @@ -1122,9 +1125,10 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) send_file_name(f, flist, fname, recurse, FLAG_DELETE); - if (olddir != NULL) { + if (olddir[0]) { flist_dir = NULL; - if (pop_dir(olddir) != 0) { + flist_dir_len = 0; + if (!pop_dir(olddir)) { rprintf(FERROR, "pop_dir %s failed: %s\n", full_fname(dir), strerror(errno)); exit_cleanup(RERR_FILESELECT); @@ -1509,19 +1513,21 @@ 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. + * buffer. 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, int bsize) +char *f_name_to(struct file_struct *f, char *fbuf) { if (!f || !f->basename) return NULL; if (f->dirname) { - int off = strlcpy(fbuf, f->dirname, bsize); - off += strlcpy(fbuf + off, "/", bsize - off); - strlcpy(fbuf + off, f->basename, bsize - off); + int len = strlen(f->dirname); + memcpy(fbuf, f->dirname, len); + fbuf[len] = '/'; + strcpy(fbuf + len + 1, f->basename); } else - strlcpy(fbuf, f->basename, bsize); + strcpy(fbuf, f->basename); return fbuf; } @@ -1535,5 +1541,5 @@ char *f_name(struct file_struct *f) n = (n + 1) % (sizeof names / sizeof names[0]); - return f_name_to(f, names[n], sizeof names[0]); + return f_name_to(f, names[n]); }