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