extern int implied_dirs;
extern int copy_links;
extern int copy_unsafe_links;
-extern int remote_version;
+extern int protocol_version;
extern int io_error;
extern int sanitize_paths;
*/
static int check_exclude_file(char *fname, int is_dir, int exclude_level)
{
-#if 0 // This currently never happens, so avoid a useless compare.
+#if 0 /* This currently never happens, so avoid a useless compare. */
if (exclude_level == NO_EXCLUDES)
return 0;
#endif
- if (fname && fname[0] == '.' && !fname[1]) {
+ if (fname) {
/* never exclude '.', even if somebody does --exclude '*' */
- return 0;
+ if (fname[0] == '.' && !fname[1])
+ return 0;
+ /* Handle the -R version of the '.' dir. */
+ if (fname[0] == '/') {
+ int len = strlen(fname);
+ if (fname[len-1] == '.' && fname[len-2] == '/')
+ return 0;
+ }
}
- if (server_exclude_list &&
- check_exclude(server_exclude_list, fname, is_dir))
+ if (server_exclude_list
+ && check_exclude(server_exclude_list, fname, is_dir))
return 1;
if (exclude_level != ALL_EXCLUDES)
return 0;
if (exclude_list && check_exclude(exclude_list, fname, is_dir))
return 1;
- if (local_exclude_list &&
- check_exclude(local_exclude_list, fname, is_dir))
+ if (local_exclude_list
+ && check_exclude(local_exclude_list, fname, is_dir))
return 1;
return 0;
}
#if SUPPORT_HARD_LINKS
if (preserve_hard_links && S_ISREG(file->mode)) {
- if (remote_version < 26) {
+ if (protocol_version < 26) {
/* 32-bit dev_t and ino_t */
write_int(f, (int) file->dev);
write_int(f, (int) file->inode);
#endif
if (always_checksum) {
- if (remote_version < 21) {
+ if (protocol_version < 21) {
write_buf(f, file->sum, 2);
} else {
write_buf(f, file->sum, MD4_SUM_LENGTH);
}
#if SUPPORT_HARD_LINKS
if (preserve_hard_links && S_ISREG(file->mode)) {
- if (remote_version < 26) {
+ if (protocol_version < 26) {
file->dev = read_int(f);
file->inode = read_int(f);
} else {
file->sum = (char *) malloc(MD4_SUM_LENGTH);
if (!file->sum)
out_of_memory("md4 sum");
- if (remote_version < 21) {
+ if (protocol_version < 21) {
read_buf(f, file->sum, 2);
} else {
read_buf(f, file->sum, MD4_SUM_LENGTH);
}
}
io_error = 1;
- rprintf(FERROR, "readlink %s: %s\n",
- fname, strerror(save_errno));
+ rprintf(FERROR, "readlink %s failed: %s\n",
+ full_fname(fname), strerror(save_errno));
return NULL;
}
d = opendir(dir);
if (!d) {
io_error = 1;
- rprintf(FERROR, "opendir(%s): %s\n", dir, strerror(errno));
+ rprintf(FERROR, "opendir %s failed: %s\n",
+ full_fname(dir), strerror(errno));
return;
}
if (fname[l - 1] != '/') {
if (l == MAXPATHLEN - 1) {
io_error = 1;
- rprintf(FERROR,
- "skipping long-named directory %s\n",
- fname);
+ rprintf(FERROR, "skipping long-named directory: %s\n",
+ full_fname(fname));
closedir(d);
return;
}
io_error = 1;
rprintf(FINFO,
"cannot cvs-exclude in long-named directory %s\n",
- fname);
+ full_fname(fname));
}
}
- for (di = readdir(d); di; di = readdir(d)) {
+ for (errno = 0, di = readdir(d); di; errno = 0, di = readdir(d)) {
char *dname = d_name(di);
- if (dname[0] == '.' && (dname[1] == '\0' ||
- (dname[1] == '.' && dname[2] == '\0')))
+ if (dname[0] == '.' && (dname[1] == '\0'
+ || (dname[1] == '.' && dname[2] == '\0')))
continue;
strlcpy(p, dname, MAXPATHLEN - l);
send_file_name(f, flist, fname, recurse, 0);
}
+ if (errno) {
+ io_error = 1;
+ rprintf(FERROR, "readdir(%s): (%d) %s\n",
+ dir, errno, strerror(errno));
+ }
if (local_exclude_list)
free_exclude_list(&local_exclude_list); /* Zeros pointer too */
io_start_buffering(f);
if (filesfrom_fd >= 0) {
if (argv[0] && !push_dir(argv[0], 0)) {
- rprintf(FERROR, "push_dir %s : %s\n",
- argv[0], strerror(errno));
+ rprintf(FERROR, "push_dir %s failed: %s\n",
+ full_fname(argv[0]), strerror(errno));
exit_cleanup(RERR_FILESELECT);
}
use_ff_fd = 1;
}
l = strlen(fname);
- if (l != 1 && fname[l - 1] == '/') {
- if ((l == 2) && (fname[0] == '.')) {
- /* Turn ./ into just . rather than ./.
- This was put in to avoid a problem with
- rsync -aR --delete from ./
- The send_file_name() below of ./ was
- mysteriously preventing deletes */
- fname[1] = 0;
+ if (fname[l - 1] == '/') {
+ if (l == 2 && fname[0] == '.') {
+ /* Turn "./" into just "." rather than "./." */
+ fname[1] = '\0';
} else {
strlcat(fname, ".", MAXPATHLEN);
}
if (link_stat(fname, &st) != 0) {
if (f != -1) {
io_error = 1;
- rprintf(FERROR, "link_stat %s : %s\n",
- fname, strerror(errno));
+ rprintf(FERROR, "link_stat %s failed: %s\n",
+ full_fname(fname), strerror(errno));
}
continue;
}
if (!olddir) {
io_error = 1;
- rprintf(FERROR, "push_dir %s : %s\n",
- dir, strerror(errno));
+ rprintf(FERROR, "push_dir %s failed: %s\n",
+ full_fname(dir), strerror(errno));
continue;
}
if (olddir != NULL) {
flist_dir = NULL;
if (pop_dir(olddir) != 0) {
- rprintf(FERROR, "pop_dir %s : %s\n",
- dir, strerror(errno));
+ rprintf(FERROR, "pop_dir %s failed: %s\n",
+ full_fname(dir), strerror(errno));
exit_cleanup(RERR_FILESELECT);
}
}
*/
static void clean_flist(struct file_list *flist, int strip_root, int no_dups)
{
- int i;
+ int i, prev_i = 0;
char *name, *prev_name = NULL;
if (!flist || flist->count == 0)
for (i = no_dups? 0 : flist->count; i < flist->count; i++) {
if (flist->files[i]->basename) {
+ prev_i = i;
prev_name = f_name(flist->files[i]);
break;
}
"removing duplicate name %s from file list %d\n",
name, i);
}
+ /* Make sure that if we unduplicate '.', that we don't
+ * lose track of a user-specified starting point (or
+ * else deletions will mysteriously fail with -R). */
+ if (flist->files[i]->flags & FLAG_DELETE)
+ flist->files[prev_i]->flags |= FLAG_DELETE;
/* it's not great that the flist knows the semantics of
* the file memory usage, but i'd rather not add a flag
* byte to that struct.
else
free_file(flist->files[i]);
}
+ else
+ prev_i = i;
+ /* We set prev_name every iteration to avoid it becoming
+ * invalid when names[][] in f_name() wraps around. */
prev_name = name;
}