}
#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);
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);
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
}
#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) {
if (l == 2 && fname[0] == '.') {
/* Turn "./" into just "." rather than "./." */
fname[1] = '\0';
- } else if (l < MAXPATHLEN) {
+ } else {
+ if (l + 1 >= MAXPATHLEN)
+ overflow_exit("send_file_list");
fname[l++] = '.';
fname[l] = '\0';
}
is_dot_dir = 1;
+ } else if (l > 1 && fname[l-1] == '.' && fname[l-2] == '.'
+ && (l == 2 || fname[l-3] == '/')) {
+ if (l + 2 >= MAXPATHLEN)
+ overflow_exit("send_file_list");
+ fname[l++] = '/';
+ fname[l++] = '.';
+ fname[l] = '\0';
+ is_dot_dir = 1;
} else {
is_dot_dir = fname[l-1] == '.'
&& (l == 1 || fname[l-2] == '/');
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)
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;
}
}
+ 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;
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);
}
}
{
int i, prev_i = 0;
- if (!flist || flist->count == 0)
+ if (!flist)
+ return;
+ if (flist->count == 0) {
+ flist->high = -1;
return;
+ }
sorting_flist = flist;
qsort(flist->files, flist->count,
}
/* Make sure that if we unduplicate '.', that we don't
* lose track of a user-specified top directory. */
- if (flist->files[drop]->flags & FLAG_TOP_DIR)
- flist->files[keep]->flags |= FLAG_TOP_DIR;
+ flist->files[keep]->flags |= flist->files[drop]->flags
+ & (FLAG_TOP_DIR|FLAG_DEL_HERE);
clear_file(drop, flist);
break;
case s_SLASH:
type1 = S_ISDIR(f1->mode) ? t_path : t_ITEM;
- state1 = s_BASE;
c1 = (uchar*)f1->basename;
+ if (type1 == t_PATH && *c1 == '.' && !c1[1]) {
+ type1 = t_ITEM;
+ state1 = s_TRAILING;
+ c1 = (uchar*)"";
+ } else
+ state1 = s_BASE;
break;
case s_BASE:
state1 = s_TRAILING;
break;
case s_SLASH:
type2 = S_ISDIR(f2->mode) ? t_path : t_ITEM;
- state2 = s_BASE;
c2 = (uchar*)f2->basename;
+ if (type2 == t_PATH && *c2 == '.' && !c2[1]) {
+ type2 = t_ITEM;
+ state2 = s_TRAILING;
+ c2 = (uchar*)"";
+ } else
+ state2 = s_BASE;
break;
case s_BASE:
state2 = s_TRAILING;