mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-10-21 13:24:15 -04:00
- Fixed a problem with merging dot dirs with non-dot-dir args
in inc-recursive mode.
- Clean up a relative name to remove interior dot dirs and extra
slashes.
- Fixed the error output about /../ in a -R path after a /./ cut-off.
- Changed the starting ndx value to 1 so that a dot-dir flist can
use 0 to refer to its parent (".") directory.
This commit is contained in:
1 parent
b58bfb2f20
commit
4e42173508
1 file changed
+67
-47
@@ -87,11 +87,15 @@ int checksum_len;
|
||||
dev_t filesystem_dev; /* used to implement -x */
|
||||
|
||||
struct file_list *cur_flist, *first_flist, *dir_flist;
|
||||
int send_dir_ndx = -1, send_dir_depth = 0;
|
||||
int send_dir_ndx = -1, send_dir_depth = -1;
|
||||
int flist_cnt = 0; /* how many (non-tmp) file list objects exist */
|
||||
int file_total = 0; /* total of all active items over all file-lists */
|
||||
int flist_eof = 0; /* all the file-lists are now known */
|
||||
|
||||
#define NORMAL_NAME 0
|
||||
#define SLASH_ENDING_NAME 1
|
||||
#define DOT_NAME 2
|
||||
|
||||
/* Starting from protocol version 26, we always use 64-bit ino_t and dev_t
|
||||
* internally, even if this platform does not allow files to have 64-bit inums.
|
||||
* The only exception is if we're on a platform with no 64-bit type at all.
|
||||
@@ -1411,6 +1415,9 @@ static void add_dirs_to_tree(int parent_ndx, struct file_list *from_flist,
|
||||
dir_flist->files[dir_flist->used++] = file;
|
||||
dir_cnt--;
|
||||
|
||||
if (file->basename[0] == '.' && file->basename[1] == '\0')
|
||||
continue;
|
||||
|
||||
if (dp)
|
||||
DIR_NEXT_SIBLING(dp) = dir_flist->used - 1;
|
||||
else if (parent_dp)
|
||||
@@ -1501,7 +1508,7 @@ static int lastpath_len = 0;
|
||||
static struct file_struct *lastpath_struct;
|
||||
|
||||
static void send_implied_dirs(int f, struct file_list *flist, char *fname,
|
||||
char *start, char *limit, int flags, int is_dot_dir)
|
||||
char *start, char *limit, int flags, char name_type)
|
||||
{
|
||||
struct file_struct *file;
|
||||
item_list *relname_list;
|
||||
@@ -1567,7 +1574,7 @@ static void send_implied_dirs(int f, struct file_list *flist, char *fname,
|
||||
rnpp = EXPAND_ITEM_LIST(relname_list, relnamecache *, 32);
|
||||
if (!(*rnpp = (relnamecache*)new_array(char, sizeof (relnamecache) + len)))
|
||||
out_of_memory("send_implied_dirs");
|
||||
(*rnpp)->is_dot_dir = is_dot_dir;
|
||||
(*rnpp)->name_type = name_type;
|
||||
strlcpy((*rnpp)->fname, limit+1, len + 1);
|
||||
}
|
||||
|
||||
@@ -1612,7 +1619,7 @@ static void send1extra(int f, struct file_struct *file, struct file_list *flist)
|
||||
for (j = 0; j < relname_list->count; j++) {
|
||||
char *slash;
|
||||
relnamecache *rnp = ((relnamecache**)relname_list->items)[j];
|
||||
int is_dot_dir = rnp->is_dot_dir;
|
||||
char name_type = rnp->name_type;
|
||||
|
||||
fbuf[dlen] = '/';
|
||||
len = strlcpy(fbuf + dlen + 1, rnp->fname, sizeof fbuf - dlen - 1);
|
||||
@@ -1622,11 +1629,11 @@ static void send1extra(int f, struct file_struct *file, struct file_list *flist)
|
||||
|
||||
slash = strchr(fbuf+dlen+1, '/');
|
||||
if (slash) {
|
||||
send_implied_dirs(f, flist, fbuf, fbuf+dlen+1, slash, flags, is_dot_dir);
|
||||
send_implied_dirs(f, flist, fbuf, fbuf+dlen+1, slash, flags, name_type);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_dot_dir) {
|
||||
if (name_type != NORMAL_NAME) {
|
||||
STRUCT_STAT st;
|
||||
if (link_stat(fbuf, &st, 1) != 0) {
|
||||
io_error |= IOERR_GENERAL;
|
||||
@@ -1802,9 +1809,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
|
||||
}
|
||||
|
||||
while (1) {
|
||||
char fbuf[MAXPATHLEN];
|
||||
char *fn;
|
||||
int is_dot_dir;
|
||||
char fbuf[MAXPATHLEN], *fn, name_type;
|
||||
|
||||
if (use_ff_fd) {
|
||||
if (read_line(filesfrom_fd, fbuf, sizeof fbuf, rl_flags) == 0)
|
||||
@@ -1821,7 +1826,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
|
||||
len = strlen(fbuf);
|
||||
if (relative_paths) {
|
||||
/* We clean up fbuf below. */
|
||||
is_dot_dir = 0;
|
||||
name_type = NORMAL_NAME;
|
||||
} else if (!len || fbuf[len - 1] == '/') {
|
||||
if (len == 2 && fbuf[0] == '.') {
|
||||
/* Turn "./" into just "." rather than "./." */
|
||||
@@ -1832,7 +1837,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
|
||||
fbuf[len++] = '.';
|
||||
fbuf[len] = '\0';
|
||||
}
|
||||
is_dot_dir = 1;
|
||||
name_type = DOT_NAME;
|
||||
} else if (len > 1 && fbuf[len-1] == '.' && fbuf[len-2] == '.'
|
||||
&& (len == 2 || fbuf[len-3] == '/')) {
|
||||
if (len + 2 >= MAXPATHLEN)
|
||||
@@ -1840,11 +1845,11 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
|
||||
fbuf[len++] = '/';
|
||||
fbuf[len++] = '.';
|
||||
fbuf[len] = '\0';
|
||||
is_dot_dir = 1;
|
||||
} else {
|
||||
is_dot_dir = fbuf[len-1] == '.'
|
||||
&& (len == 1 || fbuf[len-2] == '/');
|
||||
}
|
||||
name_type = DOT_NAME;
|
||||
} else if (fbuf[len-1] == '.' && (len == 1 || fbuf[len-2] == '/'))
|
||||
name_type = DOT_NAME;
|
||||
else
|
||||
name_type = NORMAL_NAME;
|
||||
|
||||
dir = NULL;
|
||||
|
||||
@@ -1867,36 +1872,29 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
|
||||
dir = "/";
|
||||
else
|
||||
dir = fbuf;
|
||||
len -= p - fbuf + 3;
|
||||
fn = p + 3;
|
||||
while (*fn == '/')
|
||||
fn++;
|
||||
if (!*fn)
|
||||
*--fn = '\0'; /* ensure room for '.' */
|
||||
} else
|
||||
fn = fbuf;
|
||||
/* Get rid of trailing "/" and "/.". */
|
||||
while (len) {
|
||||
if (fn[len - 1] == '/') {
|
||||
is_dot_dir = 1;
|
||||
if (!--len && !dir) {
|
||||
len++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (len >= 2 && fn[len - 1] == '.'
|
||||
&& fn[len - 2] == '/') {
|
||||
is_dot_dir = 1;
|
||||
if (!(len -= 2) && !dir) {
|
||||
len++;
|
||||
break;
|
||||
}
|
||||
} else
|
||||
break;
|
||||
}
|
||||
fn[len] = '\0';
|
||||
len = clean_fname(fn, CFN_KEEP_LEADING_DOT_DIR
|
||||
| CFN_KEEP_TRAILING_SLASH
|
||||
| CFN_DROP_TRAILING_DOT_DIR);
|
||||
if (len == 1) {
|
||||
if (fn[0] == '/') {
|
||||
fn = "/.";
|
||||
len = 2;
|
||||
name_type = DOT_NAME;
|
||||
} else if (fn[0] == '.')
|
||||
is_dot_dir = 1;
|
||||
name_type = DOT_NAME;
|
||||
} else if (fn[len-1] == '/') {
|
||||
fn[--len] = '\0';
|
||||
if (len == 1 && *fn == '.')
|
||||
name_type = DOT_NAME;
|
||||
else
|
||||
name_type = SLASH_ENDING_NAME;
|
||||
}
|
||||
/* Reject a ".." dir in the active part of the path. */
|
||||
for (p = fn; (p = strstr(p, "..")) != NULL; p += 2) {
|
||||
@@ -1904,7 +1902,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
|
||||
&& (p == fn || p[-1] == '/')) {
|
||||
rprintf(FERROR,
|
||||
"found \"..\" dir in relative path: %s\n",
|
||||
fbuf);
|
||||
fn);
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
}
|
||||
@@ -1913,7 +1911,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
|
||||
if (!*fn) {
|
||||
len = 1;
|
||||
fn = ".";
|
||||
is_dot_dir = 1;
|
||||
name_type = DOT_NAME;
|
||||
}
|
||||
|
||||
dirlen = dir ? strlen(dir) : 0;
|
||||
@@ -1928,7 +1926,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
|
||||
if (fn != fbuf)
|
||||
memmove(fbuf, fn, len + 1);
|
||||
|
||||
if (link_stat(fbuf, &st, copy_dirlinks || is_dot_dir) != 0) {
|
||||
if (link_stat(fbuf, &st, copy_dirlinks || name_type != NORMAL_NAME) != 0) {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rsyserr(FERROR, errno, "link_stat %s failed",
|
||||
full_fname(fbuf));
|
||||
@@ -1942,8 +1940,14 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
|
||||
|
||||
if (inc_recurse && relative_paths && *fbuf) {
|
||||
if ((p = strchr(fbuf+1, '/')) != NULL) {
|
||||
send_implied_dirs(f, flist, fbuf, fbuf, p, flags, is_dot_dir);
|
||||
continue;
|
||||
if (p - fbuf == 1 && *fbuf == '.') {
|
||||
if ((fn = strchr(p+1, '/')) != NULL)
|
||||
p = fn;
|
||||
} else
|
||||
fn = p;
|
||||
send_implied_dirs(f, flist, fbuf, fbuf, p, flags, name_type);
|
||||
if (fn == p)
|
||||
continue;
|
||||
}
|
||||
} else if (implied_dirs && (p=strrchr(fbuf,'/')) && p != fbuf) {
|
||||
/* Send the implied directories at the start of the
|
||||
@@ -1964,12 +1968,20 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
|
||||
if (one_file_system)
|
||||
filesystem_dev = st.st_dev;
|
||||
|
||||
if (recurse || (xfer_dirs && is_dot_dir)) {
|
||||
if (recurse || (xfer_dirs && name_type != NORMAL_NAME)) {
|
||||
struct file_struct *file;
|
||||
int top_flags = FLAG_TOP_DIR | FLAG_CONTENT_DIR | flags;
|
||||
file = send_file_name(f, flist, fbuf, &st,
|
||||
top_flags, ALL_FILTERS);
|
||||
if (file && !inc_recurse)
|
||||
if (inc_recurse) {
|
||||
if (name_type == DOT_NAME) {
|
||||
if (send_dir_depth < 0) {
|
||||
send_dir_depth = 0;
|
||||
change_local_filter_dir(fbuf, len, send_dir_depth);
|
||||
}
|
||||
send_directory(f, flist, fbuf, len, flags);
|
||||
}
|
||||
} else if (file)
|
||||
send_if_directory(f, flist, file, fbuf, len, flags);
|
||||
} else
|
||||
send_file_name(f, flist, fbuf, &st, flags, ALL_FILTERS);
|
||||
@@ -2051,7 +2063,10 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
|
||||
rprintf(FINFO, "send_file_list done\n");
|
||||
|
||||
if (inc_recurse) {
|
||||
send_dir_depth = 1;
|
||||
add_dirs_to_tree(-1, flist, dir_count);
|
||||
if (!file_total || strcmp(flist->sorted[0]->basename, ".") != 0)
|
||||
flist->parent_ndx = -1;
|
||||
flist_done_allocating(flist);
|
||||
if (send_dir_ndx < 0) {
|
||||
write_ndx(f, NDX_FLIST_EOF);
|
||||
@@ -2091,7 +2106,7 @@ struct file_list *recv_file_list(int f)
|
||||
flist = flist_new(0, "recv_file_list");
|
||||
|
||||
if (inc_recurse) {
|
||||
if (flist->ndx_start == 0)
|
||||
if (flist->ndx_start == 1)
|
||||
dir_flist = flist_new(FLIST_TEMP, "recv_file_list");
|
||||
dstart = dir_flist->used;
|
||||
} else {
|
||||
@@ -2125,7 +2140,7 @@ struct file_list *recv_file_list(int f)
|
||||
file_total += flist->used;
|
||||
|
||||
flist->ndx_end = flist->ndx_start + flist->used - 1;
|
||||
if (inc_recurse && flist->ndx_start)
|
||||
if (inc_recurse && flist->ndx_start > 1)
|
||||
flist->ndx_end -= dir_flist->used - dstart;
|
||||
|
||||
if (verbose > 2)
|
||||
@@ -2176,6 +2191,9 @@ struct file_list *recv_file_list(int f)
|
||||
read_int(f);
|
||||
else
|
||||
io_error |= read_int(f);
|
||||
} else if (inc_recurse && flist->ndx_start == 1) {
|
||||
if (!file_total || strcmp(flist->sorted[0]->basename, ".") != 0)
|
||||
flist->parent_ndx = -1;
|
||||
}
|
||||
|
||||
if (verbose > 3)
|
||||
@@ -2305,6 +2323,8 @@ struct file_list *flist_new(int flags, char *msg)
|
||||
if (!flist->file_pool)
|
||||
out_of_memory(msg);
|
||||
|
||||
flist->ndx_start = 1;
|
||||
|
||||
first_flist = cur_flist = flist->prev = flist;
|
||||
} else {
|
||||
flist->file_pool = first_flist->file_pool;
|
||||
|
||||
Reference in new issue
Block a user