? .cproject ? .project ? thediff Index: flist.c =================================================================== RCS file: /cvsroot/rsync/flist.c,v retrieving revision 1.435 diff -u -r1.435 flist.c --- flist.c 4 Aug 2007 17:47:02 -0000 1.435 +++ flist.c 21 Aug 2007 10:55:06 -0000 @@ -1009,6 +1009,7 @@ const char *basename; alloc_pool_t *pool; char *bp; + BOOL exclude_dir = 0, exclude_non_dir = 0; if (strlcpy(thisname, fname, sizeof thisname) >= sizeof thisname) { rprintf(FINFO, "skipping overly long name: %s\n", fname); @@ -1018,20 +1019,22 @@ if (sanitize_paths) sanitize_path(thisname, thisname, "", 0, NULL); + /* If the file would be excluded whether or not it is a directory, skip + * it now and avoid stat-ing it. See bug 4899. */ + if (filter_level != NO_FILTERS) { + exclude_non_dir = is_excluded(thisname, 0, filter_level); + exclude_dir = is_excluded(thisname, 1, filter_level); + if (exclude_non_dir && exclude_dir) { + if (ignore_perishable) + non_perishable_cnt++; + return NULL; + } + } if (stp && S_ISDIR(stp->st_mode)) { st = *stp; /* Needed for "symlink/." with --relative. */ *linkname = '\0'; /* make IBM code checker happy */ } else if (readlink_stat(thisname, &st, linkname) != 0) { - int save_errno = errno; - /* See if file is excluded before reporting an error. */ - if (filter_level != NO_FILTERS - && (is_excluded(thisname, 0, filter_level) - || is_excluded(thisname, 1, filter_level))) { - if (ignore_perishable && save_errno != ENOENT) - non_perishable_cnt++; - return NULL; - } - if (save_errno == ENOENT) { + if (errno == ENOENT) { #ifdef SUPPORT_LINKS /* Avoid "vanished" error if symlink points nowhere. */ if (copy_links && x_lstat(thisname, &st, NULL) == 0 @@ -1050,7 +1053,7 @@ } } else { io_error |= IOERR_GENERAL; - rsyserr(FERROR, save_errno, "readlink %s failed", + rsyserr(FERROR, errno, "readlink %s failed", full_fname(thisname)); } return NULL; @@ -1083,7 +1086,7 @@ flags |= FLAG_MOUNT_DIR; } - if (is_excluded(thisname, S_ISDIR(st.st_mode) != 0, filter_level)) { + if (S_ISDIR(st.st_mode) ? exclude_dir : exclude_non_dir) { if (ignore_perishable) non_perishable_cnt++; return NULL;