Knob to turn off _POSIX_NO_TRUNC

Gary Jennejohn gljennjohn at googlemail.com
Tue Apr 5 15:27:51 UTC 2011


On Tue, 5 Apr 2011 17:16:31 +0300
Kostik Belousov <kostikbel at gmail.com> wrote:

> From very old and gloomy SysV times I remembered filesystem behaviour
> that silently truncated the file name components to the NAME_MAX limit,
> that was, AFAIR, 14. To much of my dismay, I met some usermode software
> recently that blindly tried to create the file from externally provided
> name, and sometimes failed with ENAMETOOLONG in similar situation.
> The authors are not cooperative.
> 
> I ended up with the following hack, which almost turns off the
> _POSIX_NO_TRUNC behaviour, globally on the system. Patch allowed me
> to proceed. The cost in the default case is a single check, which is
> performed only on ENAMETOOLONG path.
> 
> I am too chicken to commit it without prior discussion.
> 
> diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c
> index 50a2570..e9e7697 100644
> --- a/sys/kern/vfs_lookup.c
> +++ b/sys/kern/vfs_lookup.c
> @@ -99,6 +99,11 @@ SYSCTL_INT(_vfs, OID_AUTO, lookup_shared, CTLFLAG_RW, &lookup_shared, 0,
>      "Enables/Disables shared locks for path name translation");
>  TUNABLE_INT("vfs.lookup_shared", &lookup_shared);
>  
> +static int lookup_trim;
> +SYSCTL_INT(_vfs, OID_AUTO, lookup_trim, CTLFLAG_RW, &lookup_trim, 0,
> +    "Enables/Disables trim of the long path component instead of ENAMETOOLONG");
> +TUNABLE_INT("vfs.lookup_trim", &lookup_trim);
> +
>  /*
>   * Convert a pathname into a pointer to a locked vnode.
>   *
> @@ -514,8 +519,14 @@ dirloop:
>  		continue;
>  	cnp->cn_namelen = cp - cnp->cn_nameptr;
>  	if (cnp->cn_namelen > NAME_MAX) {
> -		error = ENAMETOOLONG;
> -		goto bad;
> +		if (!lookup_trim) {

I would intuitively expect trimming to be enabled when the sysctl is set
to 1, but this is exactly the opposite of that.  I personally would
initialize it to 1.

> +			error = ENAMETOOLONG;
> +			goto bad;
> +		}
> +		ndp->ni_pathlen -= cnp->cn_namelen - NAME_MAX;
> +		cnp->cn_namelen = NAME_MAX;
> +		strcpy(cnp->cn_nameptr + cnp->cn_namelen, cp);
> +		cp = cnp->cn_nameptr + cnp->cn_namelen;
>  	}
>  #ifdef NAMEI_DIAGNOSTIC
>  	{ char c = *cp;

I must admit that I don't care for hacks like this to suit the vagaries
of some idiot software developers who never heard of POSIX.  But as long
as it's off by default, then I guess it would be acceptable.

-- 
Gary Jennejohn (gj@)


More information about the freebsd-fs mailing list