X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/910ee8c92e1c129b5699940aef4cfb8e5ca23df9..0417c34e2d641cbac292ba5cf8a619249c87d4e3:/flist.c diff --git a/flist.c b/flist.c index 64ff0077..1f11193f 100644 --- a/flist.c +++ b/flist.c @@ -480,19 +480,16 @@ void send_file_entry(struct file_struct *file, int f, unsigned short base_flags) } #endif - if (always_checksum) { + if (always_checksum && (S_ISREG(mode) || protocol_version < 28)) { char *sum; + int slen = protocol_version < 21 ? 2 : MD4_SUM_LENGTH; if (S_ISREG(mode)) sum = file->u.sum; - else if (protocol_version < 28) { + else { /* Prior to 28, we sent a useless set of nulls. */ sum = empty_sum; - } else - sum = NULL; - if (sum) { - write_buf(f, sum, - protocol_version < 21 ? 2 : MD4_SUM_LENGTH); } + write_buf(f, sum, slen); } strlcpy(lastname, fname, MAXPATHLEN); @@ -546,7 +543,7 @@ static struct file_struct *receive_file_entry(struct file_list *flist, rprintf(FERROR, "overflow: flags=0x%x l1=%d l2=%d lastname=%s\n", flags, l1, l2, safe_fname(lastname)); - overflow("receive_file_entry"); + overflow_exit("receive_file_entry"); } strlcpy(thisname, lastname, l1 + 1); @@ -611,7 +608,7 @@ static struct file_struct *receive_file_entry(struct file_list *flist, if (linkname_len <= 0 || linkname_len > MAXPATHLEN) { rprintf(FERROR, "overflow: linkname_len=%d\n", linkname_len - 1); - overflow("receive_file_entry"); + overflow_exit("receive_file_entry"); } } else @@ -708,20 +705,17 @@ static struct file_struct *receive_file_entry(struct file_list *flist, } #endif - if (always_checksum) { + if (always_checksum && (sum_len || protocol_version < 28)) { char *sum; + int slen = protocol_version < 21 ? 2 : MD4_SUM_LENGTH; if (sum_len) { file->u.sum = sum = bp; /*bp += sum_len;*/ - } else if (protocol_version < 28) { + } else { /* Prior to 28, we get a useless set of nulls. */ sum = empty_sum; - } else - sum = NULL; - if (sum) { - read_buf(f, sum, - protocol_version < 21 ? 2 : MD4_SUM_LENGTH); } + read_buf(f, sum, slen); } if (!preserve_perms) { @@ -1122,7 +1116,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) fname[1] = '\0'; } else { if (l + 1 >= MAXPATHLEN) - overflow("send_file_list"); + overflow_exit("send_file_list"); fname[l++] = '.'; fname[l] = '\0'; } @@ -1130,7 +1124,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) } else if (l > 1 && fname[l-1] == '.' && fname[l-2] == '.' && (l == 2 || fname[l-3] == '/')) { if (l + 2 >= MAXPATHLEN) - overflow("send_file_list"); + overflow_exit("send_file_list"); fname[l++] = '/'; fname[l++] = '.'; fname[l] = '\0'; @@ -1159,42 +1153,20 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) if (!relative_paths) { p = strrchr(fname, '/'); if (p) { - *p = 0; + *p = '\0'; if (p == fname) dir = "/"; else dir = fname; fname = p + 1; } - } else if (implied_dirs && (p=strrchr(fname,'/')) && p != fname) { - /* this ensures we send the intermediate directories, - thus getting their permissions right */ - char *lp = lastpath, *fn = fname, *slash = fname; - *p = 0; - /* Skip any initial directories in our path that we - * have in common with lastpath. */ - while (*fn && *lp == *fn) { - if (*fn == '/') - slash = fn; - lp++, fn++; - } - *p = '/'; - if (fn != p || (*lp && *lp != '/')) { - int save_copy_links = copy_links; - int save_xfer_dirs = xfer_dirs; - copy_links = copy_unsafe_links; - xfer_dirs = 1; - while ((slash = strchr(slash+1, '/')) != 0) { - *slash = 0; - send_file_name(f, flist, fname, 0); - *slash = '/'; - } - copy_links = save_copy_links; - xfer_dirs = save_xfer_dirs; - *p = 0; - strlcpy(lastpath, fname, sizeof lastpath); - *p = '/'; - } + } else if ((p = strstr(fname, "/./")) != NULL) { + *p = '\0'; + if (p == fname) + dir = "/"; + else + dir = fname; + fname = p + 3; } if (!*fname) @@ -1204,7 +1176,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) static char *lastdir; static int lastdir_len; - strcpy(olddir, curr_dir); /* can't overflow */ + strlcpy(olddir, curr_dir, sizeof olddir); if (!push_dir(dir)) { io_error |= IOERR_GENERAL; @@ -1222,6 +1194,37 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) } } + if (implied_dirs && (p=strrchr(fname,'/')) && p != fname) { + /* Send the implied directories at the start of the + * source spec, so we get their permissions right. */ + char *lp = lastpath, *fn = fname, *slash = fname; + *p = '\0'; + /* Skip any initial directories in our path that we + * have in common with lastpath. */ + while (*fn && *lp == *fn) { + if (*fn == '/') + slash = fn; + lp++, fn++; + } + *p = '/'; + if (fn != p || (*lp && *lp != '/')) { + int save_copy_links = copy_links; + int save_xfer_dirs = xfer_dirs; + copy_links = copy_unsafe_links; + xfer_dirs = 1; + while ((slash = strchr(slash+1, '/')) != 0) { + *slash = '\0'; + send_file_name(f, flist, fname, 0); + *slash = '/'; + } + copy_links = save_copy_links; + xfer_dirs = save_xfer_dirs; + *p = '\0'; + strlcpy(lastpath, fname, sizeof lastpath); + *p = '/'; + } + } + if (one_file_system) filesystem_dev = st.st_dev; @@ -1235,7 +1238,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) flist_dir_len = 0; if (!pop_dir(olddir)) { rsyserr(FERROR, errno, "pop_dir %s failed", - full_fname(dir)); + full_fname(olddir)); exit_cleanup(RERR_FILESELECT); } }