extern int cvs_exclude;
extern int recurse;
+extern char *files_from;
+extern int filesfrom_fd;
extern int one_file_system;
extern int make_backups;
extern int preserve_gid;
extern int preserve_times;
extern int relative_paths;
+extern int implied_dirs;
extern int copy_links;
extern int copy_unsafe_links;
extern int remote_version;
extern int read_batch;
extern int write_batch;
-static struct exclude_struct **local_exclude_list;
+extern struct exclude_struct **exclude_list;
+extern struct exclude_struct **server_exclude_list;
+extern struct exclude_struct **local_exclude_list;
static struct file_struct null_file;
static int show_filelist_p(void)
{
- return verbose && recurse && !am_server;
+ return verbose && (recurse || files_from) && !am_server;
}
static void start_filelist_progress(char *kind)
}
/*
- This function is used to check if a file should be included/excluded
- from the list of files based on its name and type etc
+ * This function is used to check if a file should be included/excluded
+ * from the list of files based on its name and type etc. The value of
+ * exclude_level is set to either SERVER_EXCLUDES or ALL_EXCLUDES.
*/
-static int check_exclude_file(int f, char *fname, STRUCT_STAT * st)
+static int check_exclude_file(char *fname, int is_dir, int exclude_level)
{
- extern int delete_excluded;
-
- /* f is set to -1 when calculating deletion file list */
- if ((f == -1) && delete_excluded) {
+#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]) {
+ /* never exclude '.', even if somebody does --exclude '*' */
return 0;
}
- if (check_exclude(fname, local_exclude_list, st)) {
+ 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))
return 1;
- }
return 0;
}
* statting directories if we're not recursing, but this is not a very
* important case. Some systems may not have d_type.
**/
-struct file_struct *make_file(int f, char *fname, struct string_area **ap,
- int noexcludes)
+struct file_struct *make_file(char *fname, struct string_area **ap,
+ int exclude_level)
{
struct file_struct *file;
STRUCT_STAT st;
if (readlink_stat(fname, &st, linkbuf) != 0) {
int save_errno = errno;
- if ((errno == ENOENT) && !noexcludes) {
+ if (errno == ENOENT && exclude_level != NO_EXCLUDES) {
/* either symlink pointing nowhere or file that
* was removed during rsync run; see if excluded
* before reporting an error */
- memset((char *) &st, 0, sizeof(st));
- if (check_exclude_file(f, fname, &st)) {
+ if (check_exclude_file(fname, 0, exclude_level)) {
/* file is excluded anyway, ignore silently */
return NULL;
}
return NULL;
}
- /* we use noexcludes from backup.c */
- if (noexcludes)
+ /* backup.c calls us with exclude_level set to NO_EXCLUDES. */
+ if (exclude_level == NO_EXCLUDES)
goto skip_excludes;
- if (S_ISDIR(st.st_mode) && !recurse) {
+ if (S_ISDIR(st.st_mode) && !recurse && !files_from) {
rprintf(FINFO, "skipping directory %s\n", fname);
return NULL;
}
return NULL;
}
- if (check_exclude_file(f, fname, &st))
+ if (check_exclude_file(fname, S_ISDIR(st.st_mode) != 0, exclude_level))
return NULL;
-
if (lp_ignore_nonreadable(module_id) && access(fname, R_OK) != 0)
return NULL;
skip_excludes:
if (verbose > 2)
- rprintf(FINFO, "make_file(%d,%s)\n", f, fname);
+ rprintf(FINFO, "make_file(%s,*,%d)\n", fname, exclude_level);
file = (struct file_struct *) malloc(sizeof(*file));
if (!file)
int recursive, unsigned base_flags)
{
struct file_struct *file;
+ extern int delete_excluded;
- file = make_file(f, fname, &flist->string_area, 0);
+ /* f is set to -1 when calculating deletion file list */
+ file = make_file(fname, &flist->string_area,
+ f == -1 && delete_excluded? SERVER_EXCLUDES
+ : ALL_EXCLUDES);
if (!file)
return;
if (write_batch) /* dw */
file->flags = FLAG_DELETE;
- if (strcmp(file->basename, "")) {
+ if (file->basename[0]) {
flist->files[flist->count++] = file;
send_file_entry(file, f, base_flags);
}
if (cvs_exclude) {
if (strlen(fname) + strlen(".cvsignore") <= MAXPATHLEN - 1) {
strcpy(p, ".cvsignore");
- local_exclude_list =
- make_exclude_list(fname, NULL, 0, 0);
+ add_exclude_file(&exclude_list,fname,MISSING_OK,ADD_EXCLUDE);
} else {
io_error = 1;
rprintf(FINFO,
for (di = readdir(d); di; di = readdir(d)) {
char *dname = d_name(di);
- if (strcmp(dname, ".") == 0 || strcmp(dname, "..") == 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 (local_exclude_list) {
- add_exclude_list("!", &local_exclude_list, 0);
- }
+ if (local_exclude_list)
+ free_exclude_list(&local_exclude_list); /* Zeros pointer too */
closedir(d);
}
/**
- *
- * I <b>think</b> f==-1 means that the list should just be built in
- * memory and not transmitted. But who can tell? -- mbp
+ * The delete_files() function in receiver.c sets f to -1 so that we just
+ * construct the file list in memory without sending it over the wire. It
+ * also has the side-effect of ignoring user-excludes if delete_excluded
+ * is set (so that the delete list includes user-excluded files).
**/
struct file_list *send_file_list(int f, int argc, char *argv[])
{
- int i, l;
+ int l;
STRUCT_STAT st;
char *p, *dir, *olddir;
char lastpath[MAXPATHLEN] = "";
struct file_list *flist;
int64 start_write;
+ int use_ff_fd = 0;
if (show_filelist_p() && f != -1)
start_filelist_progress("building file list");
if (f != -1) {
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));
+ exit_cleanup(RERR_FILESELECT);
+ }
+ use_ff_fd = 1;
+ }
}
- for (i = 0; i < argc; i++) {
+ while (1) {
char fname2[MAXPATHLEN];
char *fname = fname2;
- strlcpy(fname, argv[i], MAXPATHLEN);
+ if (use_ff_fd) {
+ if (read_filesfrom_line(filesfrom_fd, fname) == 0)
+ break;
+ sanitize_path(fname, NULL);
+ } else {
+ if (argc-- == 0)
+ break;
+ strlcpy(fname, *argv++, MAXPATHLEN);
+ if (sanitize_paths)
+ sanitize_path(fname, NULL);
+ }
l = strlen(fname);
if (l != 1 && fname[l - 1] == '/') {
continue;
}
- if (S_ISDIR(st.st_mode) && !recurse) {
+ if (S_ISDIR(st.st_mode) && !recurse && !files_from) {
rprintf(FINFO, "skipping directory %s\n", fname);
continue;
}
dir = fname;
fname = p + 1;
}
- } else if (f != -1 && (p=strrchr(fname,'/')) && p != fname) {
+ } else if (f != -1 && 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;
/* now send the uid/gid list. This was introduced in protocol
version 15 */
- if (f != -1 && remote_version >= 15) {
+ if (f != -1) {
send_uid_list(f);
}
- /* if protocol version is >= 17 then send the io_error flag */
- if (f != -1 && remote_version >= 17) {
+ /* send the io_error flag */
+ if (f != -1) {
extern int module_id;
write_int(f, lp_ignore_errors(module_id) ? 0 : io_error);
}
}
/* now recv the uid/gid list. This was introduced in protocol version 15 */
- if (f != -1 && remote_version >= 15) {
+ if (f != -1) {
recv_uid_list(f, flist);
}
- /* if protocol version is >= 17 then recv the io_error flag */
- if (f != -1 && remote_version >= 17 && !read_batch) { /* dw-added readbatch */
+ /* recv the io_error flag */
+ if (f != -1 && !read_batch) { /* dw-added readbatch */
extern int module_id;
extern int ignore_errors;
if (lp_ignore_errors(module_id) || ignore_errors) {