Using --keep-dirlinks : recursive symlinks problem
Ivan S. Manida
Ivan.Manida at Sun.COM
Wed Aug 25 08:51:17 GMT 2004
Seems fine, using inodes to sort out duplicates is a great idea. I
suppose using hashes won't give much speedup here, since quantity of
directories is not known beforehand. I will apply and test the patch
today, thanks!
Wayne Davison wrote:
> On Fri, Aug 20, 2004 at 04:50:45PM +0400, Ivan S. Manida wrote:
>
>>Or please kick me in the right direction for a workaround which would
>>make --keep-dirlinks consider sane symlinks only.
>
>
> Seems like the only good solution for this is to keep track of the
> device and inode of all the dirs we visit so that we can eliminate all
> duplicate directories. Attached is a patch that does this using a
> simple binary insertion sort. Very minimally tested. Thoughts?
> Optimizations?
>
> ..wayne..
>
>
> ------------------------------------------------------------------------
>
> --- flist.c 12 Aug 2004 18:20:07 -0000 1.236
> +++ flist.c 25 Aug 2004 07:27:12 -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 j = (low + high) / 2;
> + if (ino == dirarray[j].ino) {
> + if (dev == dirarray[j].dev)
> + return True;
> + if (dev > dirarray[j].dev)
> + low = j + 1;
> + else
> + high = j - 1;
> + } else if (ino > dirarray[j].ino)
> + low = j + 1;
> + else
> + high = j - 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,14 @@ 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))
> + return NULL;
> }
>
> /* We only care about directories because we need to avoid recursing
>
--
Ivan S. Manida, cdev/buildmaster
Sun SPb: 33033, Bld. 1, Room 217
More information about the rsync
mailing list