[RFC] vfs_fruit uses wrong xattr name for Mac metadata on FreeBSD

Jeremy Allison jra at samba.org
Fri Feb 10 00:53:42 UTC 2017


On Sat, Feb 04, 2017 at 10:17:17AM +0100, Ralph Böhme wrote:
> On Sun, Jan 22, 2017 at 05:08:08PM +0100, Ralph Böhme wrote:
> > On Sun, Jan 22, 2017 at 06:48:03AM +0800, Evan Champion wrote:
> > > Another way would be to change the default xattr name in 4.6.0 and provide a
> > > conversion tool.
> > 
> > hm...
> 
> and here's the patchset that does this.
> 
> 1. It renames the Netatalk metadata xattr name.
> 
> 2. Adds a tool mvxattr to rename xattrs. The name seems not to be in use, so
> hopefully it doesn't clash with anything. It uses nftw under the hood for the
> directory traversal, it's in POSIX.1-2001, available on FreeBSD (which this is
> all about, Linux has it as well) and I'd like to avoid reinventing the wheel.
> 
> 3. Fixes our libreplace xattr implementation on FreeBSD to validata xattr
> names. This is a prerequisite for 2, otherwise users might call the mvxattr tool
> with xattr name like "org.netatalk.Metadata" without a namespace prefix leading
> to unexpected results: the xattr name on the fs would be "netatalk.Metadata" as
> the "org" part gets stripped.
> 
> Once this is in master, I'll prepare a backport for 4.6 with an update for
> WHATSNEW.
> 
> Please review & push if happy. Thanks!

That's a really nice patchset Ralph, I really like the mvxattr
utility !

RB+

Pushed.


> From e661ceb3f27582b0c699584f116d51787db3e2b2 Mon Sep 17 00:00:00 2001
> From: Ralph Boehme <slow at samba.org>
> Date: Fri, 3 Feb 2017 16:33:00 +0100
> Subject: [PATCH 1/4] vfs_fruit: correct Netatalk metadata xattr on FreeBSD
> 
> Bug: https://bugzilla.samba.org/show_bug.cgi?id=12490
> 
> Signed-off-by: Ralph Boehme <slow at samba.org>
> ---
>  source3/modules/vfs_fruit.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c
> index 3599dcb..828d6d1 100644
> --- a/source3/modules/vfs_fruit.c
> +++ b/source3/modules/vfs_fruit.c
> @@ -105,7 +105,7 @@ static int vfs_fruit_debug_level = DBGC_VFS;
>   * This is hokey, but what else can we do?
>   */
>  #define NETATALK_META_XATTR "org.netatalk.Metadata"
> -#if defined(HAVE_ATTROPEN) || defined(FREEBSD)
> +#if defined(HAVE_ATTROPEN)
>  #define AFPINFO_EA_NETATALK NETATALK_META_XATTR
>  #define AFPRESOURCE_EA_NETATALK "org.netatalk.ResourceFork"
>  #else
> -- 
> 2.9.3
> 
> 
> From 1fe44e3f5b2bdff92e4c7267e07b69733fbf4758 Mon Sep 17 00:00:00 2001
> From: Ralph Boehme <slow at samba.org>
> Date: Fri, 3 Feb 2017 16:43:26 +0100
> Subject: [PATCH 2/4] vfs_fruit: cleanup metadata and resource xattr name
>  defines
> 
> Just some cleanup, no change in behaviour. This also removes the hokey
> tag. :)
> 
> Bug: https://bugzilla.samba.org/show_bug.cgi?id=12490
> 
> Signed-off-by: Ralph Boehme <slow at samba.org>
> ---
>  source3/modules/vfs_fruit.c | 10 ++++------
>  1 file changed, 4 insertions(+), 6 deletions(-)
> 
> diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c
> index 828d6d1..4387447 100644
> --- a/source3/modules/vfs_fruit.c
> +++ b/source3/modules/vfs_fruit.c
> @@ -100,17 +100,15 @@ static int vfs_fruit_debug_level = DBGC_VFS;
>  #define FRUIT_PARAM_TYPE_NAME "fruit"
>  #define ADOUBLE_NAME_PREFIX "._"
>  
> -/*
> - * REVIEW:
> - * This is hokey, but what else can we do?
> - */
>  #define NETATALK_META_XATTR "org.netatalk.Metadata"
> +#define NETATALK_RSRC_XATTR "org.netatalk.Metadata"
> +
>  #if defined(HAVE_ATTROPEN)
>  #define AFPINFO_EA_NETATALK NETATALK_META_XATTR
> -#define AFPRESOURCE_EA_NETATALK "org.netatalk.ResourceFork"
> +#define AFPRESOURCE_EA_NETATALK NETATALK_RSRC_XATTR
>  #else
>  #define AFPINFO_EA_NETATALK "user." NETATALK_META_XATTR
> -#define AFPRESOURCE_EA_NETATALK "user.org.netatalk.ResourceFork"
> +#define AFPRESOURCE_EA_NETATALK "user." NETATALK_RSRC_XATTR
>  #endif
>  
>  enum apple_fork {APPLE_FORK_DATA, APPLE_FORK_RSRC};
> -- 
> 2.9.3
> 
> 
> From 03d73c0da1955aa703c11e79ff23fd97246d3e79 Mon Sep 17 00:00:00 2001
> From: Ralph Boehme <slow at samba.org>
> Date: Fri, 3 Feb 2017 18:08:12 +0100
> Subject: [PATCH 3/4] lib/replace: validate xattr namespace prefix on FreeBSD
> 
> We should validate the xattr name string ensuring it either begins with
> "sytem." or "user.". If it doesn't, we should fail the request with
> EINVAL.
> 
> The FreeBSD xattr API uses namespaces but doesn't put the namespace name
> as a string prefix at the beginning of the xattr name. It gets passed as
> an additional int arg instead.
> 
> On the other hand, our libreplace xattr API expects the caller to put a
> namespace prefix into the xattr name.
> 
> Unfortunately the conversion and stripping of the namespae string prefix
> from the xattr name gives the following unexpected result on FreeBSD:
> 
> rep_setxattr("foo.bar", ...) => xattr with name "bar"
> 
> The code checks if the name begins with "system.", if it doesn't find
> it, it defaults to the user namespace and then does a strchr(name, '.')
> which skips *any* leading string before the first dot.
> 
> Bug: https://bugzilla.samba.org/show_bug.cgi?id=12490
> 
> Signed-off-by: Ralph Boehme <slow at samba.org>
> ---
>  lib/replace/xattr.c | 105 ++++++++++++++++++++++++++++++++++++++++------------
>  1 file changed, 81 insertions(+), 24 deletions(-)
> 
> diff --git a/lib/replace/xattr.c b/lib/replace/xattr.c
> index ce52d1a..2479c21 100644
> --- a/lib/replace/xattr.c
> +++ b/lib/replace/xattr.c
> @@ -61,11 +61,21 @@ ssize_t rep_getxattr (const char *path, const char *name, void *value, size_t si
>  #elif defined(HAVE_GETEA)
>  	return getea(path, name, value, size);
>  #elif defined(HAVE_EXTATTR_GET_FILE)
> -	char *s;
>  	ssize_t retval;
> -	int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
> -		EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
> -	const char *attrname = ((s=strchr(name, '.')) == NULL) ? name : s + 1;
> +	int attrnamespace;
> +	const char *attrname;
> +
> +	if (strncmp(name, "system.", 7) == 0) {
> +		attrnamespace = EXTATTR_NAMESPACE_SYSTEM;
> +		attrname = name + 7;
> +	} else if (strncmp(name, "user.", 5) == 0) {
> +		attrnamespace = EXTATTR_NAMESPACE_USER;
> +		attrname = name + 5;
> +	} else {
> +		errno = EINVAL;
> +		return -1;
> +	}
> +
>  	/*
>  	 * The BSD implementation has a nasty habit of silently truncating
>  	 * the returned value to the size of the buffer, so we have to check
> @@ -125,11 +135,20 @@ ssize_t rep_fgetxattr (int filedes, const char *name, void *value, size_t size)
>  #elif defined(HAVE_FGETEA)
>  	return fgetea(filedes, name, value, size);
>  #elif defined(HAVE_EXTATTR_GET_FD)
> -	char *s;
>  	ssize_t retval;
> -	int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
> -		EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
> -	const char *attrname = ((s=strchr(name, '.')) == NULL) ? name : s + 1;
> +	int attrnamespace;
> +	const char *attrname;
> +
> +	if (strncmp(name, "system.", 7) == 0) {
> +		attrnamespace = EXTATTR_NAMESPACE_SYSTEM;
> +		attrname = name + 7;
> +	} else if (strncmp(name, "user.", 5) == 0) {
> +		attrnamespace = EXTATTR_NAMESPACE_USER;
> +		attrname = name + 5;
> +	} else {
> +		errno = EINVAL;
> +		return -1;
> +	}
>  
>  	if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
>  		if (size == 0) {
> @@ -414,10 +433,19 @@ int rep_removexattr (const char *path, const char *name)
>  #elif defined(HAVE_REMOVEEA)
>  	return removeea(path, name);
>  #elif defined(HAVE_EXTATTR_DELETE_FILE)
> -	char *s;
> -	int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
> -		EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
> -	const char *attrname = ((s=strchr(name, '.')) == NULL) ? name : s + 1;
> +	int attrnamespace;
> +	const char *attrname;
> +
> +	if (strncmp(name, "system.", 7) == 0) {
> +		attrnamespace = EXTATTR_NAMESPACE_SYSTEM;
> +		attrname = name + 7;
> +	} else if (strncmp(name, "user.", 5) == 0) {
> +		attrnamespace = EXTATTR_NAMESPACE_USER;
> +		attrname = name + 5;
> +	} else {
> +		errno = EINVAL;
> +		return -1;
> +	}
>  
>  	return extattr_delete_file(path, attrnamespace, attrname);
>  #elif defined(HAVE_ATTR_REMOVE)
> @@ -455,10 +483,19 @@ int rep_fremovexattr (int filedes, const char *name)
>  #elif defined(HAVE_FREMOVEEA)
>  	return fremoveea(filedes, name);
>  #elif defined(HAVE_EXTATTR_DELETE_FD)
> -	char *s;
> -	int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
> -		EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
> -	const char *attrname = ((s=strchr(name, '.')) == NULL) ? name : s + 1;
> +	int attrnamespace;
> +	const char *attrname;
> +
> +	if (strncmp(name, "system.", 7) == 0) {
> +		attrnamespace = EXTATTR_NAMESPACE_SYSTEM;
> +		attrname = name + 7;
> +	} else if (strncmp(name, "user.", 5) == 0) {
> +		attrnamespace = EXTATTR_NAMESPACE_USER;
> +		attrname = name + 5;
> +	} else {
> +		errno = EINVAL;
> +		return -1;
> +	}
>  
>  	return extattr_delete_fd(filedes, attrnamespace, attrname);
>  #elif defined(HAVE_ATTR_REMOVEF)
> @@ -496,11 +533,21 @@ int rep_setxattr (const char *path, const char *name, const void *value, size_t
>  #elif defined(HAVE_SETEA)
>  	return setea(path, name, value, size, flags);
>  #elif defined(HAVE_EXTATTR_SET_FILE)
> -	char *s;
>  	int retval = 0;
> -	int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
> -		EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
> -	const char *attrname = ((s=strchr(name, '.')) == NULL) ? name : s + 1;
> +	int attrnamespace;
> +	const char *attrname;
> +
> +	if (strncmp(name, "system.", 7) == 0) {
> +		attrnamespace = EXTATTR_NAMESPACE_SYSTEM;
> +		attrname = name + 7;
> +	} else if (strncmp(name, "user.", 5) == 0) {
> +		attrnamespace = EXTATTR_NAMESPACE_USER;
> +		attrname = name + 5;
> +	} else {
> +		errno = EINVAL;
> +		return -1;
> +	}
> +
>  	if (flags) {
>  		/* Check attribute existence */
>  		retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
> @@ -563,11 +610,21 @@ int rep_fsetxattr (int filedes, const char *name, const void *value, size_t size
>  #elif defined(HAVE_FSETEA)
>  	return fsetea(filedes, name, value, size, flags);
>  #elif defined(HAVE_EXTATTR_SET_FD)
> -	char *s;
>  	int retval = 0;
> -	int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
> -		EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
> -	const char *attrname = ((s=strchr(name, '.')) == NULL) ? name : s + 1;
> +	int attrnamespace;
> +	const char *attrname;
> +
> +	if (strncmp(name, "system.", 7) == 0) {
> +		attrnamespace = EXTATTR_NAMESPACE_SYSTEM;
> +		attrname = name + 7;
> +	} else if (strncmp(name, "user.", 5) == 0) {
> +		attrnamespace = EXTATTR_NAMESPACE_USER;
> +		attrname = name + 5;
> +	} else {
> +		errno = EINVAL;
> +		return -1;
> +	}
> +
>  	if (flags) {
>  		/* Check attribute existence */
>  		retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
> -- 
> 2.9.3
> 
> 
> From 6a5867a6938926e355ff3bfba566af227e6c5c92 Mon Sep 17 00:00:00 2001
> From: Ralph Boehme <slow at samba.org>
> Date: Fri, 3 Feb 2017 14:57:45 +0100
> Subject: [PATCH 4/4] s3/util: mvxattr, a tool to rename extended attributes
> 
> Usage: mvxattr -s STRING -d STRING PATH [PATH ...]
>   -s, --from=STRING         xattr source name
>   -d, --to=STRING           xattr destination name
>   -l, --follow-symlinks     follow symlinks, the default is to ignore them
>   -p, --print               print files where the xattr got renamed
>   -v, --verbose             print files as they are checked
>   -f, --force               force overwriting of destination xattr
> 
> Help options:
>   -?, --help            Show this help message
>   --usage               Display brief usage message
> 
> Bug: https://bugzilla.samba.org/show_bug.cgi?id=12490
> 
> Signed-off-by: Ralph Boehme <slow at samba.org>
> ---
>  docs-xml/manpages/mvxattr.1.xml | 100 ++++++++++++++++++++++
>  docs-xml/wscript_build          |   1 +
>  source3/utils/mvxattr.c         | 178 ++++++++++++++++++++++++++++++++++++++++
>  source3/utils/wscript_build     |   8 ++
>  source3/wscript                 |   3 +
>  5 files changed, 290 insertions(+)
>  create mode 100644 docs-xml/manpages/mvxattr.1.xml
>  create mode 100644 source3/utils/mvxattr.c
> 
> diff --git a/docs-xml/manpages/mvxattr.1.xml b/docs-xml/manpages/mvxattr.1.xml
> new file mode 100644
> index 0000000..034dc3a
> --- /dev/null
> +++ b/docs-xml/manpages/mvxattr.1.xml
> @@ -0,0 +1,100 @@
> +<?xml version="1.0" encoding="iso-8859-1"?>
> +<!DOCTYPE refentry PUBLIC "-//Samba-Team//DTD DocBook V4.2-Based Variant V1.0//EN" "http://www.samba.org/samba/DTD/samba-doc">
> +<refentry id="mvxattr.1">
> +
> +<refmeta>
> +	<refentrytitle>mvxattr</refentrytitle>
> +	<manvolnum>1</manvolnum>
> +	<refmiscinfo class="source">Samba</refmiscinfo>
> +	<refmiscinfo class="manual">User Commands</refmiscinfo>
> +	<refmiscinfo class="version">4.7</refmiscinfo>
> +</refmeta>
> +
> +
> +<refnamediv>
> +	<refname>mvxattr</refname>
> +	<refpurpose>Recursively rename extended attributes</refpurpose>
> +</refnamediv>
> +
> +<refsynopsisdiv>
> +	<cmdsynopsis>
> +		<command>mvxattr</command>
> +		<arg choice="req">-s STRING, --from=STRING</arg>
> +		<arg choice="req">-d STRING, --to=STRING</arg>
> +		<arg choice="opt">-l, --follow-symlinks</arg>
> +		<arg choice="opt">-p, --print</arg>
> +		<arg choice="opt">-v, --verbose</arg>
> +		<arg choice="opt">-f, --force</arg>
> +		<arg choice="req">PATH [PATH ...]</arg>
> +	</cmdsynopsis>
> +</refsynopsisdiv>
> +
> +<refsect1>
> +	<title>DESCRIPTION</title>
> +
> +	<para>This tool is part of the <citerefentry><refentrytitle>samba</refentrytitle>
> +	<manvolnum>1</manvolnum></citerefentry> suite.</para>
> +
> +	<para>mvxattr is a simple utility to recursively rename extended
> +	attributes.</para>
> +
> +	<para>By default all symlinks are ignored, use <option>-l</option> to
> +	follow them.</para>
> +</refsect1>
> +
> +<refsect1>
> +	<title>OPTIONS</title>
> +
> +	<variablelist>
> +	<varlistentry>
> +		<term>-s STRING, --from=STRING</term>
> +		<listitem><para>Source xattr name</para></listitem>
> +	</varlistentry>
> +
> +	<varlistentry>
> +		<term>-d STRING, --to=STRING</term>
> +		<listitem><para>Destination xattr name</para></listitem>
> +	</varlistentry>
> +
> +	<varlistentry>
> +		<term>-l, --follow-symlinks</term>
> +		<listitem><para>Follow symlinks, the default is to ignore
> +		them.</para></listitem>
> +	</varlistentry>
> +
> +	<varlistentry>
> +		<term>-p, --print</term>
> +		<listitem><para>Print files where the xattr got renamed.</para></listitem>
> +	</varlistentry>
> +
> +	<varlistentry>
> +		<term>-v, --verbose</term>
> +		<listitem><para>Print files as they are checked.</para></listitem>
> +	</varlistentry>
> +
> +	<varlistentry>
> +		<term>-f, --force</term>
> +		<listitem><para>Force overwriting of destination xattr.</para></listitem>
> +	</varlistentry>
> +	</variablelist>
> +
> +</refsect1>
> +
> +<refsect1>
> +	<title>VERSION</title>
> +
> +	<para>This man page is correct for version 4 of the Samba suite.</para>
> +</refsect1>
> +
> +<refsect1>
> +	<title>AUTHOR</title>
> +
> +	<para>The original Samba software and related utilities were created by
> +	Andrew Tridgell. Samba is now developed by the Samba Team as an Open
> +	Source project similar to the way the Linux kernel is developed.</para>
> +
> +	<para>The mvxattr manpage was written by Ralph Boehme.</para>
> +
> +</refsect1>
> +
> +</refentry>
> diff --git a/docs-xml/wscript_build b/docs-xml/wscript_build
> index 2b3a180..0b690a8 100644
> --- a/docs-xml/wscript_build
> +++ b/docs-xml/wscript_build
> @@ -18,6 +18,7 @@ manpages='''
>           manpages/idmap_script.8
>           manpages/idmap_tdb.8
>           manpages/idmap_tdb2.8
> +         manpages/mvxattr.1
>           manpages/net.8
>           manpages/nmbd.8
>           manpages/nmblookup.1
> diff --git a/source3/utils/mvxattr.c b/source3/utils/mvxattr.c
> new file mode 100644
> index 0000000..9cc2ec0
> --- /dev/null
> +++ b/source3/utils/mvxattr.c
> @@ -0,0 +1,178 @@
> +/*
> +   Unix SMB/CIFS implementation.
> +   xattr renaming
> +   Copyright (C) Ralph Boehme 2017
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <http://www.gnu.org/licenses/>.
> +*/
> +
> +#include "includes.h"
> +#include "system/filesys.h"
> +#include "popt_common.h"
> +#include <ftw.h>
> +
> +static struct rename_xattr_state {
> +	int follow_symlink;
> +	int print;
> +	int force;
> +	int verbose;
> +	char *xattr_from;
> +	char *xattr_to;
> +} state;
> +
> +static int rename_xattr(const char *path,
> +			const struct stat *sb,
> +			int typeflag,
> +			struct FTW *ftwbuf)
> +{
> +	ssize_t len;
> +	int ret;
> +
> +	if (typeflag == FTW_SL) {
> +		d_printf("Ignoring symlink %s\n", path);
> +		return 0;
> +	}
> +
> +	if (state.verbose) {
> +		d_printf("%s\n", path);
> +	}
> +
> +	len = getxattr(path, state.xattr_from, NULL, 0);
> +	if (len < 0) {
> +		if (errno == ENOATTR) {
> +			return 0;
> +		}
> +		d_printf("getxattr [%s] failed [%s]\n",
> +			 path, strerror(errno));
> +		return -1;
> +	}
> +
> +	{
> +		uint8_t buf[len];
> +
> +		len = getxattr(path, state.xattr_from, &buf[0], len);
> +		if (len == -1) {
> +			d_printf("getxattr [%s] failed [%s]\n",
> +				 path, strerror(errno));
> +			return -1;
> +		}
> +
> +		ret = setxattr(path, state.xattr_to, &buf[0], len, XATTR_CREATE);
> +		if (ret != 0) {
> +			if (errno != EEXIST) {
> +				d_printf("setxattr [%s] failed [%s]\n",
> +					 path, strerror(errno));
> +				return -1;
> +			}
> +			if (!state.force) {
> +				d_printf("destination [%s:%s] exists, use -f to force\n",
> +					 path, state.xattr_to);
> +				return -1;
> +			}
> +			ret = setxattr(path, state.xattr_to, &buf[0], len, XATTR_REPLACE);
> +			if (ret != 0) {
> +				d_printf("setxattr [%s:%s] failed [%s]\n",
> +					 path, state.xattr_to, strerror(errno));
> +				return -1;
> +			}
> +		}
> +
> +		ret = removexattr(path, state.xattr_from);
> +		if (ret != 0) {
> +			d_printf("removexattr [%s:%s] failed [%s]\n",
> +				 path, state.xattr_from, strerror(errno));
> +			return -1;
> +		}
> +
> +		if (state.print) {
> +			d_printf("Renamed %s to %s on %s\n",
> +				 state.xattr_from, state.xattr_to, path);
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +int main(int argc, const char *argv[])
> +{
> +	int c;
> +	const char *path = NULL;
> +	poptContext pc;
> +	struct poptOption long_options[] = {
> +		POPT_AUTOHELP
> +		{"from", 		's', POPT_ARG_STRING,	&state.xattr_from,	's', "xattr source name" },
> +		{"to",			'd', POPT_ARG_STRING, 	&state.xattr_to, 	'd', "xattr destination name" },
> +		{"follow-symlinks",	'l', POPT_ARG_NONE,	&state.follow_symlink,	'l', "follow symlinks, the default is to ignore them" },
> +		{"print",		'p', POPT_ARG_NONE,	&state.print,		'p', "print files where the xattr got renamed" },
> +		{"verbose",		'v', POPT_ARG_NONE,	&state.verbose,		'v', "print files as they are checked" },
> +		{"force",		'f', POPT_ARG_NONE,	&state.force,		'f', "force overwriting of destination xattr" },
> +		POPT_TABLEEND
> +	};
> +	TALLOC_CTX *frame = talloc_stackframe();
> +	const char *s = NULL;
> +	int ret = 0;
> +
> +	if (getuid() != 0) {
> +		d_printf("%s only works as root!\n", argv[0]);
> +		ret = 1;
> +		goto done;
> +	}
> +
> +	pc = poptGetContext(NULL, argc, argv, long_options, 0);
> +	poptSetOtherOptionHelp(pc, "-s STRING -d STRING PATH [PATH ...]");
> +
> +	while ((c = poptGetNextOpt(pc)) != -1) {
> +		switch (c) {
> +		case 's':
> +			s = poptGetOptArg(pc);
> +			state.xattr_from = talloc_strdup(frame, s);
> +			if (state.xattr_from == NULL) {
> +				ret = 1;
> +				goto done;
> +			}
> +			break;
> +		case 'd':
> +			s = poptGetOptArg(pc);
> +			state.xattr_to = talloc_strdup(frame, s);
> +			if (state.xattr_to == NULL) {
> +				ret = 1;
> +				goto done;
> +			}
> +			break;
> +		}
> +	}
> +
> +	if (state.xattr_from == NULL || state.xattr_to == NULL) {
> +		poptPrintUsage(pc, stderr, 0);
> +		ret = 1;
> +		goto done;
> +	}
> +
> +	if (poptPeekArg(pc) == NULL) {
> +		poptPrintUsage(pc, stderr, 0);
> +		ret = 1;
> +		goto done;
> +	}
> +
> +	while ((path = poptGetArg(pc)) != NULL) {
> +		ret = nftw(path, rename_xattr, 256,
> +			   state.follow_symlink ? 0 : FTW_PHYS);
> +	}
> +
> +	poptFreeContext(pc);
> +
> +done:
> +	TALLOC_FREE(frame);
> +	return ret;
> +}
> diff --git a/source3/utils/wscript_build b/source3/utils/wscript_build
> index 0b9356a..4295f85 100644
> --- a/source3/utils/wscript_build
> +++ b/source3/utils/wscript_build
> @@ -249,3 +249,11 @@ bld.SAMBA3_BINARY('net',
>                   trusts_util
>                   IDMAP_AUTORID_TDB
>                   ''')
> +
> +bld.SAMBA3_BINARY('mvxattr',
> +                 source='mvxattr.c',
> +                 deps='''
> +                 talloc
> +                 popt_samba3
> +                 ''',
> +                 enabled=bld.env.build_mvxattr)
> diff --git a/source3/wscript b/source3/wscript
> index 443affd..907e400 100644
> --- a/source3/wscript
> +++ b/source3/wscript
> @@ -1633,6 +1633,9 @@ main() {
>          else:
>              Logs.info("ncurses not available, not building regedit")
>  
> +    if conf.CHECK_HEADERS('ftw.h') and conf.CHECK_FUNCS('nftw'):
> +        conf.env.build_mvxattr = True
> +
>      conf.CHECK_FUNCS_IN('DES_pcbc_encrypt', 'crypto')
>      if Options.options.with_fake_kaserver == True:
>          conf.CHECK_HEADERS('afs/param.h afs/stds.h', together=True)
> -- 
> 2.9.3
> 




More information about the samba-technical mailing list