From 287b24d7aed60e099572cdd7a53d4feb8e4b4756 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 3 Feb 2017 16:33:00 +0100 Subject: [PATCH 1/5] vfs_fruit: correct Netatalk metadata xattr on FreeBSD Bug: https://bugzilla.samba.org/show_bug.cgi?id=12490 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 73557605fdf72221e3cbc218fc9782d163029a08) --- 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 0248f97..a57b53b 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 765aa3c8d3699286685a4d5e2c622a94776e96fb Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 3 Feb 2017 16:43:26 +0100 Subject: [PATCH 2/5] 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 Reviewed-by: Jeremy Allison (cherry picked from commit e4d1f8354f97ab9007e4c5f7d164937bdc5cd6f1) --- 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 a57b53b..f0c7c5a 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 ffaeb66b3c95e4feabc401589d845e048640aa62 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Sun, 12 Feb 2017 09:05:50 +0100 Subject: [PATCH 3/5] vfs_fruit: fix resource fork xattr name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix resource fork xattr name broken in e4d1f8354f97ab9007e4c5f7d164937bdc5cd6f1. Bug: https://bugzilla.samba.org/show_bug.cgi?id=12490 Signed-off-by: Ralph Boehme Reviewed-by: Ralph Boehme Autobuild-User(master): Ralph Böhme Autobuild-Date(master): Tue Feb 14 21:26:01 CET 2017 on sn-devel-144 (cherry picked from commit 221faba006e84b05004500d2261307f269858a18) --- 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 f0c7c5a..d917c73 100644 --- a/source3/modules/vfs_fruit.c +++ b/source3/modules/vfs_fruit.c @@ -101,7 +101,7 @@ static int vfs_fruit_debug_level = DBGC_VFS; #define ADOUBLE_NAME_PREFIX "._" #define NETATALK_META_XATTR "org.netatalk.Metadata" -#define NETATALK_RSRC_XATTR "org.netatalk.Metadata" +#define NETATALK_RSRC_XATTR "org.netatalk.ResourceFork" #if defined(HAVE_ATTROPEN) #define AFPINFO_EA_NETATALK NETATALK_META_XATTR -- 2.9.3 From cd1af28286f4cf57d14e4362b6b5aa1544a6a13c Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 3 Feb 2017 18:08:12 +0100 Subject: [PATCH 4/5] 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 namespace 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 Reviewed-by: Jeremy Allison (cherry picked from commit 738797d8ad6908de457786cc948dcde151e2b9e1) --- 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 e8cc32a4780cbfaa40e2561197ac392533cd992a Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 3 Feb 2017 14:57:45 +0100 Subject: [PATCH 5/5] 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 Reviewed-by: Jeremy Allison Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Fri Feb 10 22:24:59 CET 2017 on sn-devel-144 (cherry picked from commit 32116e015b14cfa697569fce01daf8cde3285970) --- 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 @@ + + + + + + mvxattr + 1 + Samba + User Commands + 4.7 + + + + + mvxattr + Recursively rename extended attributes + + + + + mvxattr + -s STRING, --from=STRING + -d STRING, --to=STRING + -l, --follow-symlinks + -p, --print + -v, --verbose + -f, --force + PATH [PATH ...] + + + + + DESCRIPTION + + This tool is part of the samba + 1 suite. + + mvxattr is a simple utility to recursively rename extended + attributes. + + By default all symlinks are ignored, use to + follow them. + + + + OPTIONS + + + + -s STRING, --from=STRING + Source xattr name + + + + -d STRING, --to=STRING + Destination xattr 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. + + + + + + + VERSION + + This man page is correct for version 4 of the Samba suite. + + + + AUTHOR + + 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. + + The mvxattr manpage was written by Ralph Boehme. + + + + 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 . +*/ + +#include "includes.h" +#include "system/filesys.h" +#include "popt_common.h" +#include + +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 c6b2421..8422ea0 100644 --- a/source3/wscript +++ b/source3/wscript @@ -1632,6 +1632,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