Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 22 Aug 2008 10:07:29 -0500
From:      Brooks Davis <brooks@freebsd.org>
To:        Luigi Rizzo <rizzo@iet.unipi.it>
Cc:        Ivan Voras <ivoras@freebsd.org>, Christian Brueffer <brueffer@freebsd.org>, freebsd-arch@freebsd.org
Subject:   Re: Magic symlinks redux
Message-ID:  <20080822150728.GB57443@lor.one-eyed-alien.net>
In-Reply-To: <20080822145616.GA61094@onelab2.iet.unipi.it>
References:  <g8kv7v$sp2$1@ger.gmane.org> <20080822090448.GB57441@onelab2.iet.unipi.it> <48AE89DC.9080408@yandex.ru> <g8m458$d3$1@ger.gmane.org> <20080822120525.GA1366@haakonia.hitnet.RWTH-Aachen.DE> <20080822145616.GA61094@onelab2.iet.unipi.it>

next in thread | previous in thread | raw e-mail | index | archive | help

--4SFOXa2GPu3tIq4H
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

On Fri, Aug 22, 2008 at 04:56:16PM +0200, Luigi Rizzo wrote:
> On Fri, Aug 22, 2008 at 02:05:26PM +0200, Christian Brueffer wrote:
> > On Fri, Aug 22, 2008 at 12:24:41PM +0200, Ivan Voras wrote:
> ...
> > > This patch is huge. As far as I can tell DragonflyBSD has a whole=20
> > > framework dedicated to varsyms, spread across a fair part of the kern=
el=20
> > > and with at least one special userland utility. It allows the operato=
r=20
> > > to define his own variables that can be used in the substitutions, an=
d I=20
> > > don't see that it predefines "special" variables like "uid" and=20
> > > "hostname". It's not necessarily a bad solution but I consider it ove=
rkill.
> ...
> > Brooks has a varsym port in p4, see //depot/user/brooks/varsym/
>=20
> this also seems to be based on Dragonfly's code, quite intrusive.

This code adds one global symbol, one function call in the vfs code,
and two pointers to struct proc.  For that we get a system which is
significantly more flexible than the NetBSD code.

While the simplicity of the NetBSD code is somewhat attractive, the
fact that variables can not be defined renders it useless for my
purposes which are providing partial file system virtulization for
computing job/sessions where I need to key off of externally derived job
IDs or job specific temporary paths.

-- Brooks

> I am playing with a rewrite (attached below) of the original patch,
> which fixes at least one memory leak and addresses some of the
> issues that i mentioned in this thread (abuse of macros, performance,
> behaviour on errors, etc.).
>=20
> (i haven't looked up yet the original copyright but i guess it
> is from netbsd...)
>=20
> 	cheers
> 	luigi
>=20
> Index: src/sys/kern/vfs_lookup.c
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> --- src/sys/kern/vfs_lookup.c	(revision 181995)
> +++ src/sys/kern/vfs_lookup.c	(working copy)
> @@ -46,6 +46,7 @@
>  #include <sys/kernel.h>
>  #include <sys/lock.h>
>  #include <sys/mutex.h>
> +#include <sys/jail.h>	// XXX symlinks
>  #include <sys/namei.h>
>  #include <sys/vnode.h>
>  #include <sys/mount.h>
> @@ -88,6 +89,123 @@
>  }
>  SYSINIT(vfs, SI_SUB_VFS, SI_ORDER_SECOND, nameiinit, NULL);
> =20
> +#ifdef MAGICLINKS
> +static int vfs_magiclinks =3D 1;
> +#else
> +static int vfs_magiclinks =3D 1;
> +#endif
> +SYSCTL_INT(_vfs, OID_AUTO, magiclinks, CTLFLAG_RW, &vfs_magiclinks, 0,
> +	"Whether \"magic\" symlinks are expanded");
> +
> +/* looks up a string returns the match len or 0 */
> +static int
> +s_match(const char *key, int keylen, const char *haystack, const char *e=
nd)
> +{
> +	if (haystack + keylen >=3D end || haystack[keylen] !=3D '}')
> +		return 0;
> +	if (strncmp(key, haystack, keylen))
> +		return 0;
> +	return keylen;
> +}
> +#define	MATCH(str) s_match(str, sizeof(str) - 1, src, end)
> +
> +static char *
> +s_subst(char *dst, const char *max, const char *value, int len)
> +{
> +	if (value =3D=3D dst) {	/* already copied, locate end of string */
> +		while (*dst)
> +			dst++;
> +		return dst;
> +	}
> +	/* check size, copy and replace */
> +	if (dst + len > max) /* overflow */
> +		return NULL;
> +	bcopy(value, dst, len);
> +	dst +=3D len;
> +	return dst;
> +}
> +
> +/*
> + * Substitute replacement text for 'magic' strings in symlinks.
> + * Looks for "@{string}", where <string> is a
> + * recognized 'magic' string.  Replaces the original with the
> + * appropriate replacement text.  (Note that in some cases the
> + * replacement text may have zero length.)
> + * Assume *len is at least 3.
> + */
> +static void
> +symlink_magic(struct thread *td, char *cp, int *len)
> +{
> +	char *src, *dst, *tmp, *end =3D cp + *len, *max;
> +	int change =3D 0;
> +
> +	/* quick return if nothing to replace */
> +	for (src =3D cp; src < end - 1; src++) {
> +		if (src[0] =3D=3D '@' && src[1] =3D=3D '{')
> +			break;
> +	}
> +	if (src =3D=3D end - 1)	/* no replacement */
> +		return;
> +
> +	/* allocate a buffer for the replacement */
> +	dst =3D tmp =3D uma_zalloc(namei_zone, M_WAITOK);
> +	if (dst =3D=3D NULL) {	/* no space for replacement */
> +		printf("zalloc fail in %s\n", __FUNCTION__);
> +		return;
> +	}
> +	max =3D dst + MAXPATHLEN - 1;
> +	for (src =3D cp; src < end - 1 && dst < max - 1;) {
> +		int l;
> +		if (src[0] !=3D '@' || src[1] !=3D '{') {
> +			*dst++ =3D *src++;	/* copy current char */
> +			continue;
> +		}
> +		src +=3D 2;	/* skip @{ */
> +
> +printf("replace magic at %s\n", src);
> +		/*
> +		 * The following checks should be ordered according
> +		 * to frequency of use.
> +		 */
> +		if ( (l =3D MATCH("machine_arch")) ) {
> +			dst =3D s_subst(dst, max, MACHINE_ARCH, sizeof(MACHINE_ARCH) - 1);
> +		} else if ( (l=3D MATCH("machine")) ) {
> +			dst =3D s_subst(dst, max, MACHINE_ARCH, sizeof(MACHINE_ARCH) - 1);
> +		} else if ( (l=3D MATCH("hostname")) ) {
> +			getcredhostname(td->td_ucred, dst, max - dst);
> +			dst =3D s_subst(dst, max, dst, 0);
> +		} else if ( (l=3D MATCH("osrelease")) ) {
> +			dst =3D s_subst(dst, max, osrelease, strlen(osrelease));
> +		} else if ( (l=3D MATCH("kernel_ident")) ) {
> +			dst =3D s_subst(dst, max, kern_ident, strlen(kern_ident));
> +		} else if ( (l=3D MATCH("domainname")) ) {
> +			dst =3D s_subst(dst, max, domainname, strlen(domainname));
> +		} else if ( (l=3D MATCH("ostype")) ) {
> +			dst =3D s_subst(dst, max, ostype, strlen(ostype));
> +		}
> +		if (dst =3D=3D NULL)	/* overflow */
> +			break;
> +		if (l =3D=3D 0) { /* no match, restore original */
> +			*dst++ =3D '@';
> +			*dst++ =3D '{';
> +			continue;
> +		}
> +		/* otherwise skip original name and } */
> +		src +=3D l + 1;
> +		change =3D 1;
> +	}
> +	if (change && dst) {
> +		if (src < end)	/* copy last char */
> +			*dst++ =3D *src;
> +		*dst =3D '\0';
> +		printf("translating into %s\n", tmp);
> +		*len =3D dst - tmp;
> +		bcopy(tmp, cp, *len);
> +	}
> +	uma_zfree(namei_zone, tmp);
> +}
> +#undef MATCH
> +
>  #ifdef LOOKUP_SHARED
>  static int lookup_shared =3D 1;
>  #else
> @@ -284,6 +402,8 @@
>  			error =3D ENOENT;
>  			break;
>  		}
> +		if (vfs_magiclinks && linklen >3) /* at least @{} in the symlink */
> +			symlink_magic(td, cp, &linklen);
>  		if (linklen + ndp->ni_pathlen >=3D MAXPATHLEN) {
>  			if (ndp->ni_pathlen > 1)
>  				uma_zfree(namei_zone, cp);
> _______________________________________________
> freebsd-arch@freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-arch
> To unsubscribe, send any mail to "freebsd-arch-unsubscribe@freebsd.org"
>=20

--4SFOXa2GPu3tIq4H
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.8 (FreeBSD)

iD8DBQFIrtYwXY6L6fI4GtQRAq1GAJ94/aYauKaXMGLbgbdCgyDNskzHqQCaAtgx
EQOySBn1LVkKImSSH0Pd318=
=ez0s
-----END PGP SIGNATURE-----

--4SFOXa2GPu3tIq4H--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20080822150728.GB57443>