static char empty_sum[MD4_SUM_LENGTH];
static unsigned int file_struct_len;
-static struct file_list *received_flist;
+static struct file_list *received_flist, *sorting_flist;
static dev_t filesystem_dev; /* used to implement -x */
static int deletion_count = 0; /* used to implement --max-delete */
permstring(perms, f->mode);
-#if SUPPORT_LINKS
+#ifdef SUPPORT_LINKS
if (preserve_links && S_ISLNK(f->mode)) {
rprintf(FINFO, "%s %11.0f %s %s -> %s\n",
perms,
**/
static int readlink_stat(const char *path, STRUCT_STAT *buffer, char *linkbuf)
{
-#if SUPPORT_LINKS
+#ifdef SUPPORT_LINKS
if (copy_links)
return do_stat(path, buffer);
if (link_stat(path, buffer, 0) < 0)
int link_stat(const char *path, STRUCT_STAT *buffer, int follow_dirlinks)
{
-#if SUPPORT_LINKS
+#ifdef SUPPORT_LINKS
if (copy_links)
return do_stat(path, buffer);
if (do_lstat(path, buffer) < 0)
static int to_wire_mode(mode_t mode)
{
-#if SUPPORT_LINKS
+#ifdef SUPPORT_LINKS
if (S_ISLNK(mode) && (_S_IFLNK != 0120000))
return (mode & ~(_S_IFMT)) | 0120000;
#endif
char fname[MAXPATHLEN];
int l1, l2;
- if (f == -1)
+ if (f < 0)
return;
if (!file) {
else
modtime = file->modtime;
-#if SUPPORT_HARD_LINKS
+#ifdef SUPPORT_HARD_LINKS
if (file->link_u.idev) {
if (file->F_DEV == dev) {
if (protocol_version >= 28)
}
}
-#if SUPPORT_LINKS
+#ifdef SUPPORT_LINKS
if (preserve_links && S_ISLNK(mode)) {
int len = strlen(file->u.link);
write_int(f, len);
}
#endif
-#if SUPPORT_HARD_LINKS
+#ifdef SUPPORT_HARD_LINKS
if (flags & XMIT_HAS_IDEV_DATA) {
if (protocol_version < 26) {
/* 32-bit dev_t and ino_t */
}
}
-#if SUPPORT_LINKS
+#ifdef SUPPORT_LINKS
if (preserve_links && S_ISLNK(mode)) {
linkname_len = read_int(f) + 1; /* count the '\0' */
if (linkname_len <= 0 || linkname_len > MAXPATHLEN) {
if (preserve_devices && IS_DEVICE(mode))
file->u.rdev = rdev;
-#if SUPPORT_LINKS
+#ifdef SUPPORT_LINKS
if (linkname_len) {
file->u.link = bp;
read_sbuf(f, bp, linkname_len - 1);
}
#endif
-#if SUPPORT_HARD_LINKS
+#ifdef SUPPORT_HARD_LINKS
if (preserve_hard_links && protocol_version < 28 && S_ISREG(mode))
flags |= XMIT_HAS_IDEV_DATA;
if (flags & XMIT_HAS_IDEV_DATA) {
&& is_excluded(thisname, 0, filter_level))
return NULL;
if (save_errno == ENOENT) {
-#if SUPPORT_LINKS
+#ifdef SUPPORT_LINKS
/* Avoid "vanished" error if symlink points nowhere. */
if (copy_links && do_lstat(thisname, &st) == 0
&& S_ISLNK(st.st_mode)) {
return NULL;
if (lp_ignore_nonreadable(module_id)) {
-#if SUPPORT_LINKS
+#ifdef SUPPORT_LINKS
if (!S_ISLNK(st.st_mode))
#endif
if (access(thisname, R_OK) != 0)
}
basename_len = strlen(basename) + 1; /* count the '\0' */
-#if SUPPORT_LINKS
+#ifdef SUPPORT_LINKS
linkname_len = S_ISLNK(st.st_mode) ? strlen(linkname) + 1 : 0;
#else
linkname_len = 0;
file->uid = st.st_uid;
file->gid = st.st_gid;
-#if SUPPORT_HARD_LINKS
+#ifdef SUPPORT_HARD_LINKS
if (flist && flist->hlink_pool) {
if (protocol_version < 28) {
if (S_ISREG(st.st_mode))
memcpy(bp, basename, basename_len);
bp += basename_len;
-#if HAVE_STRUCT_STAT_ST_RDEV
+#ifdef HAVE_STRUCT_STAT_ST_RDEV
if (preserve_devices && IS_DEVICE(st.st_mode))
file->u.rdev = st.st_rdev;
#endif
-#if SUPPORT_LINKS
+#ifdef SUPPORT_LINKS
if (linkname_len) {
file->u.link = bp;
memcpy(bp, linkname, linkname_len);
struct file_struct *file;
char fbuf[MAXPATHLEN];
- if (!(file = make_file(fname, flist, ALL_FILTERS)))
+ file = make_file(fname, flist, f == -2 ? SERVER_FILTERS : ALL_FILTERS);
+ if (!file)
return;
maybe_emit_filelist_progress(flist);
* or a number >= 0 indicating how many levels of recursion we will allow.
* This function is normally called by the sender, but the receiving side
* also calls it from delete_in_dir() with f set to -1 so that we just
- * construct the file list in memory without sending it over the wire. */
+ * construct the file list in memory without sending it over the wire. Also,
+ * get_dirlist() calls this with f set to -2, which indicates that local
+ * filter rules should be ignored. */
static void send_directory(int f, struct file_list *flist,
char *fbuf, unsigned int len)
{
clean_flist(flist, relative_paths, 1);
- if (f != -1) {
+ if (f >= 0) {
/* Now send the uid/gid list. This was introduced in
* protocol version 15 */
recv_uid_list(f, flist);
out_of_memory, POOL_INTERN)))
out_of_memory(msg);
-#if SUPPORT_HARD_LINKS
+#ifdef SUPPORT_HARD_LINKS
if (with_hlink && preserve_hard_links) {
if (!(flist->hlink_pool = pool_create(HLINK_EXTENT,
sizeof (struct idev), out_of_memory, POOL_INTERN)))
if (!flist || flist->count == 0)
return;
+ sorting_flist = flist;
qsort(flist->files, flist->count,
sizeof flist->files[0], (int (*)())file_compare);
+ sorting_flist = NULL;
for (i = no_dups? 0 : flist->count; i < flist->count; i++) {
if (flist->files[i]->basename) {
if (!*c2) {
switch (state2) {
case s_DIR:
+ if (state1 == s_SLASH && sorting_flist) {
+ int j;
+ /* Optimize for future comparisons. */
+ for (j = 0;
+ j < sorting_flist->count;
+ j++) {
+ struct file_struct *fp
+ = sorting_flist->files[j];
+ if (fp->dirname == f2->dirname)
+ fp->dirname = f1->dirname;
+ }
+ }
state2 = s_SLASH;
c2 = (uchar*)"/";
break;
return k > 0 && strcmp(fn+k, backup_suffix) == 0;
}
+struct file_list *get_dirlist(const char *dirname, int ignore_filter_rules)
+{
+ struct file_list *dirlist;
+ char dirbuf[MAXPATHLEN];
+ int dlen;
+ int save_recurse = recurse;
+
+ dlen = strlcpy(dirbuf, dirname, MAXPATHLEN);
+ if (dlen >= MAXPATHLEN)
+ return NULL;
+
+ dirlist = flist_new(WITHOUT_HLINK, "get_dirlist");
+ recurse = 0;
+ send_directory(ignore_filter_rules ? -2 : -1, dirlist, dirbuf, dlen);
+ recurse = save_recurse;
+
+ return dirlist;
+}
+
/* This function is used to implement per-directory deletion, and
* is used by all the --delete-WHEN options. Note that the fbuf