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