--- /dev/null
+This tries to keep symlink loops from happening when using
+the --copy-links option (on the sender) and when using the
+--keep-dirlinks option with --delete (on the receiver). It
+would be nice to improve this so that duplicates get turned
+back into symlinks, but the code needs to know which one is
+the real dir (if it is present in the list) because that one
+entry can't be turned into a symlink.
+
+--- flist.c 12 Aug 2004 18:20:07 -0000 1.236
++++ flist.c 31 Aug 2004 20:44:33 -0000
+@@ -724,6 +724,43 @@ void receive_file_entry(struct file_stru
+ }
+
+
++static BOOL saw_dir(dev_t dev, ino_t ino)
++{
++ static struct dirinfo { dev_t dev; ino_t ino; } *dirarray;
++ static int dirarray_cnt, dirarray_size;
++ int low, high;
++
++ if (dirarray_cnt == dirarray_size) {
++ dirarray = realloc_array(dirarray, struct dirinfo,
++ dirarray_size += 4096);
++ }
++
++ for (low = 0, high = dirarray_cnt - 1; low <= high; ) {
++ int mid = (low + high) / 2;
++ if (ino == dirarray[mid].ino) {
++ if (dev == dirarray[mid].dev)
++ return True;
++ if (dev > dirarray[mid].dev)
++ low = mid + 1;
++ else
++ high = mid - 1;
++ } else if (ino > dirarray[mid].ino)
++ low = mid + 1;
++ else
++ high = mid - 1;
++ }
++
++ if (low < dirarray_cnt) {
++ memmove(dirarray + low + 1, dirarray + low,
++ (dirarray_cnt - low) * sizeof dirarray[0]);
++ }
++ dirarray[low].dev = dev;
++ dirarray[low].ino = ino;
++ dirarray_cnt++;
++
++ return False;
++}
++
+ /**
+ * Create a file_struct for a named file by reading its stat()
+ * information and performing extensive checks against global
+@@ -802,9 +839,17 @@ struct file_struct *make_file(char *fnam
+ if (exclude_level == NO_EXCLUDES)
+ goto skip_excludes;
+
+- if (S_ISDIR(st.st_mode) && !recurse && !files_from) {
+- rprintf(FINFO, "skipping directory %s\n", thisname);
+- return NULL;
++ if (S_ISDIR(st.st_mode)) {
++ if (!recurse && !files_from) {
++ rprintf(FINFO, "skipping directory %s\n", thisname);
++ return NULL;
++ }
++ if ((keep_dirlinks || copy_links)
++ && saw_dir(st.st_dev, st.st_ino)) {
++ rprintf(FINFO, "skipping duplicate directory %s\n",
++ thisname);
++ return NULL;
++ }
+ }
+
+ /* We only care about directories because we need to avoid recursing