Commit | Line | Data |
---|---|---|
3848d3f0 WD |
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. | |
8 | ||
a6587818 WD |
9 | --- orig/flist.c 2004-09-21 09:40:27 |
10 | +++ flist.c 2004-08-31 20:44:33 | |
11 | @@ -726,6 +726,43 @@ void receive_file_entry(struct file_stru | |
3848d3f0 WD |
12 | } |
13 | ||
14 | ||
15 | +static BOOL saw_dir(dev_t dev, ino_t ino) | |
16 | +{ | |
17 | + static struct dirinfo { dev_t dev; ino_t ino; } *dirarray; | |
18 | + static int dirarray_cnt, dirarray_size; | |
19 | + int low, high; | |
20 | + | |
21 | + if (dirarray_cnt == dirarray_size) { | |
22 | + dirarray = realloc_array(dirarray, struct dirinfo, | |
23 | + dirarray_size += 4096); | |
24 | + } | |
25 | + | |
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) | |
30 | + return True; | |
31 | + if (dev > dirarray[mid].dev) | |
32 | + low = mid + 1; | |
33 | + else | |
34 | + high = mid - 1; | |
35 | + } else if (ino > dirarray[mid].ino) | |
36 | + low = mid + 1; | |
37 | + else | |
38 | + high = mid - 1; | |
39 | + } | |
40 | + | |
41 | + if (low < dirarray_cnt) { | |
42 | + memmove(dirarray + low + 1, dirarray + low, | |
43 | + (dirarray_cnt - low) * sizeof dirarray[0]); | |
44 | + } | |
45 | + dirarray[low].dev = dev; | |
46 | + dirarray[low].ino = ino; | |
47 | + dirarray_cnt++; | |
48 | + | |
49 | + return False; | |
50 | +} | |
51 | + | |
52 | /** | |
53 | * Create a file_struct for a named file by reading its stat() | |
54 | * information and performing extensive checks against global | |
a6587818 | 55 | @@ -804,9 +841,17 @@ struct file_struct *make_file(char *fnam |
3848d3f0 WD |
56 | if (exclude_level == NO_EXCLUDES) |
57 | goto skip_excludes; | |
58 | ||
59 | - if (S_ISDIR(st.st_mode) && !recurse && !files_from) { | |
60 | - rprintf(FINFO, "skipping directory %s\n", thisname); | |
61 | - return NULL; | |
62 | + if (S_ISDIR(st.st_mode)) { | |
63 | + if (!recurse && !files_from) { | |
64 | + rprintf(FINFO, "skipping directory %s\n", thisname); | |
65 | + return NULL; | |
66 | + } | |
67 | + if ((keep_dirlinks || copy_links) | |
68 | + && saw_dir(st.st_dev, st.st_ino)) { | |
69 | + rprintf(FINFO, "skipping duplicate directory %s\n", | |
70 | + thisname); | |
71 | + return NULL; | |
72 | + } | |
73 | } | |
74 | ||
75 | /* We only care about directories because we need to avoid recursing |