Subject: Re: hardlink to symlink
To: Hubert Feyrer <hubert.feyrer@rz.uni-regensburg.de>
From: Bill Studenmund <wrstuden@nas.nasa.gov>
List: tech-kern
Date: 05/12/1999 11:08:46
Checking through old mail, and found this.

On Fri, 9 Apr 1999, Hubert Feyrer wrote:

> 
> Hi,
> 
> I've used hardlinks to symlinks under Solaris, and understanding
> hardlinks as "just another directory entry" for whatever object
> (referenced by i/vnode), was wondering why NetBSD didn't support
> this.

Do standards have anything to say?

> Example:
> $ ln -s /etc/passwd symlink
> $ ln symlink hardlink
> ln: hardlink: Cross-device link
> 
> 
> It seems this has two causes:
> 1. the kernel tried to follow the symlink which caused it to abort
>    if the target of the symlink was on a different filesystem.
> 
>    If the link points to a (valid) file on the same filesystem,
>    traversal of the link will result in a hardlink to the target
>    file, which may not be what's intended.
> 
>    These two cases can be caught by not traversing the symlink.
> 
> 2. the ln(1) command failed if the symlink didn't point to a valid
>    file. Again, not traversing the link here solves this. 
> 
> The patches below fix these two errors:
> 
> $ ln symlink hardlink
> $ ls -lai hardlink symlink
> 368953 lrwxr-xr-x  2 feyrer  wheel  11 Apr  9 05:52 hardlink -> /etc/passwd
> 368953 lrwxr-xr-x  2 feyrer  wheel  11 Apr  9 05:52 symlink -> /etc/passwd
> 
> I'm not a kernel hacker so I would appreciate any inputs on this.
> Else I'll be happy to commit this.

Except that you commented out the old code rather than deleting it, I
think they look great!

Take care,

Bill

> Index: bin/ln/ln.c
> ===================================================================
> RCS file: /cvsroot/src/bin/ln/ln.c,v
> retrieving revision 1.15
> diff -u -r1.15 ln.c
> --- ln.c	1998/07/28 05:31:25	1.15
> +++ ln.c	1999/04/09 03:42:09
> @@ -137,7 +137,8 @@
>  
>  	if (!sflag) {
>  		/* If target doesn't exist, quit now. */
> -		if (stat(target, &sb)) {
> + /* 		if (stat(target, &sb)) { */ /*HF*/
> +		if (lstat(target, &sb)) {
>  			warn("%s", target);
>  			return (1);
>  		}
> Index: sys/kern/vfs_syscalls.c
> ===================================================================
> RCS file: /cvsroot/src/sys/kern/vfs_syscalls.c,v
> retrieving revision 1.133
> diff -u -r1.133 vfs_syscalls.c
> --- vfs_syscalls.c	1999/03/31 19:18:45	1.133
> +++ vfs_syscalls.c	1999/04/09 03:42:13
> @@ -1116,7 +1116,9 @@
>  	struct nameidata nd;
>  	int error;
>  
> -	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
> +	
> + /*HF*//* NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); */
> +	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
>  	if ((error = namei(&nd)) != 0)
>  		return (error);
>  	vp = nd.ni_vp;
> 
> -- 
> Hubert Feyrer <hubert.feyrer@rz.uni-regensburg.de>
> 
> 
>