summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2004-11-05 07:29:02 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:05:30 -0500
commit9fe5fa11d637252f1fbe79c7baf778e2d3cdade2 (patch)
tree40f628c02dcc23d3ec4724e43cb9a6fcdeb5c548 /source4
parent0a8dff9e475aea5312ecc4bc283e8007ee653185 (diff)
downloadsamba-9fe5fa11d637252f1fbe79c7baf778e2d3cdade2.tar.gz
samba-9fe5fa11d637252f1fbe79c7baf778e2d3cdade2.tar.bz2
samba-9fe5fa11d637252f1fbe79c7baf778e2d3cdade2.zip
r3545: initial support for using extended attributes to hold extended dos attributes of files.
I decided to use IDL/NDR to encode the attribute, as it gives us a simple way to describe and extend the saved attributes. The xattr code needs to hook into quite a few more places in the pvfs code, but this at least gets the basics done. I will start encoding alternate data streams streams, DOS EAs etc soon using the same basic mechanism. I'll probably stick to "version 1" for the xattr.idl for quite a while even though it will be changing, as I don't expect anyone to be deploying this in production just yet. Once we have production users we will need to keep compatibility by supporting all the old version numbers in xattr.idl. (This used to be commit c54253ed1b7dce1d14f43e747da61089aea87094)
Diffstat (limited to 'source4')
-rw-r--r--source4/build/m4/rewrite.m410
-rw-r--r--source4/libcli/util/errormap.c7
-rw-r--r--source4/librpc/config.m446
-rw-r--r--source4/librpc/config.mk50
-rw-r--r--source4/librpc/idl/xattr.idl35
-rw-r--r--source4/librpc/ndr/ndr.c58
-rw-r--r--source4/ntvfs/posix/config.m413
-rw-r--r--source4/ntvfs/posix/config.mk9
-rw-r--r--source4/ntvfs/posix/pvfs_fileinfo.c56
-rw-r--r--source4/ntvfs/posix/pvfs_open.c14
-rw-r--r--source4/ntvfs/posix/pvfs_resolve.c10
-rw-r--r--source4/ntvfs/posix/pvfs_setfileinfo.c17
-rw-r--r--source4/ntvfs/posix/pvfs_xattr.c197
-rw-r--r--source4/ntvfs/posix/vfs_posix.c6
-rw-r--r--source4/ntvfs/posix/vfs_posix.h1
15 files changed, 403 insertions, 126 deletions
diff --git a/source4/build/m4/rewrite.m4 b/source4/build/m4/rewrite.m4
index 04d904a68d..7a24a11a5c 100644
--- a/source4/build/m4/rewrite.m4
+++ b/source4/build/m4/rewrite.m4
@@ -1455,16 +1455,6 @@ if test x"$samba_cv_HAVE_COMPARISON_FN_T" = x"yes"; then
AC_DEFINE(HAVE_COMPARISON_FN_T,1,[Whether or not we have comparison_fn_t])
fi
-############################################
-# Check if we have extended attributes
-AC_CHECK_HEADERS(sys/attributes.h attr/xattr.h sys/xattr.h)
-AC_SEARCH_LIBS(getxattr, [attr])
-AC_CHECK_FUNCS(getxattr lgetxattr fgetxattr listxattr llistxattr)
-AC_CHECK_FUNCS(flistxattr removexattr lremovexattr fremovexattr)
-AC_CHECK_FUNCS(setxattr lsetxattr fsetxattr)
-AC_CHECK_FUNCS(attr_get attr_list attr_set attr_remove)
-AC_CHECK_FUNCS(attr_getf attr_listf attr_setf attr_removef)
-
#################################################
# check for ACL support
diff --git a/source4/libcli/util/errormap.c b/source4/libcli/util/errormap.c
index 46e4831f89..417f4571a7 100644
--- a/source4/libcli/util/errormap.c
+++ b/source4/libcli/util/errormap.c
@@ -1517,6 +1517,13 @@ const struct unix_error_map unix_nt_errmap[] = {
{ EPIPE, NT_STATUS_CONNECTION_DISCONNECTED },
{ ECONNREFUSED, NT_STATUS_CONNECTION_REFUSED },
{ EBUSY, NT_STATUS_SHARING_VIOLATION },
+ { ENOTSUP, NT_STATUS_NOT_SUPPORTED},
+#ifdef ENOATTR
+ { ENOATTR, NT_STATUS_NOT_FOUND },
+#endif
+#ifdef ENODATA
+ { ENODATA, NT_STATUS_NOT_FOUND },
+#endif
#ifdef EDQUOT
{ EDQUOT, NT_STATUS_QUOTA_EXCEEDED },
#endif
diff --git a/source4/librpc/config.m4 b/source4/librpc/config.m4
index 76dc8c9c0f..5c137b738b 100644
--- a/source4/librpc/config.m4
+++ b/source4/librpc/config.m4
@@ -1,50 +1,8 @@
dnl # LIBRPC subsystem
-SMB_SUBSYSTEM_MK(LIBNDR_RAW,librpc/config.mk)
-
SMB_SUBSYSTEM_NOPROTO(LIBNDR_GEN)
-SMB_SUBSYSTEM(LIBNDR_GEN,[],
- [librpc/gen_ndr/tables.o
- librpc/gen_ndr/ndr_audiosrv.o
- librpc/gen_ndr/ndr_dcerpc.o
- librpc/gen_ndr/ndr_echo.o
- librpc/gen_ndr/ndr_exchange.o
- librpc/gen_ndr/ndr_dsbackup.o
- librpc/gen_ndr/ndr_efs.o
- librpc/gen_ndr/ndr_misc.o
- librpc/gen_ndr/ndr_lsa.o
- librpc/gen_ndr/ndr_lsads.o
- librpc/gen_ndr/ndr_dfs.o
- librpc/gen_ndr/ndr_drsuapi.o
- librpc/gen_ndr/ndr_policyagent.o
- librpc/gen_ndr/ndr_samr.o
- librpc/gen_ndr/ndr_spoolss.o
- librpc/gen_ndr/ndr_wkssvc.o
- librpc/gen_ndr/ndr_srvsvc.o
- librpc/gen_ndr/ndr_svcctl.o
- librpc/gen_ndr/ndr_atsvc.o
- librpc/gen_ndr/ndr_eventlog.o
- librpc/gen_ndr/ndr_epmapper.o
- librpc/gen_ndr/ndr_dbgidl.o
- librpc/gen_ndr/ndr_dssetup.o
- librpc/gen_ndr/ndr_msgsvc.o
- librpc/gen_ndr/ndr_wins.o
- librpc/gen_ndr/ndr_winreg.o
- librpc/gen_ndr/ndr_mgmt.o
- librpc/gen_ndr/ndr_protected_storage.o
- librpc/gen_ndr/ndr_dcom.o
- librpc/gen_ndr/ndr_oxidresolver.o
- librpc/gen_ndr/ndr_remact.o
- librpc/gen_ndr/ndr_wzcsvc.o
- librpc/gen_ndr/ndr_browser.o
- librpc/gen_ndr/ndr_w32time.o
- librpc/gen_ndr/ndr_scerpc.o
- librpc/gen_ndr/ndr_ntsvcs.o
- librpc/gen_ndr/ndr_netlogon.o
- librpc/gen_ndr/ndr_trkwks.o
- librpc/gen_ndr/ndr_keysvc.o
- librpc/gen_ndr/ndr_krb5pac.o
- librpc/gen_ndr/ndr_schannel.o])
+SMB_SUBSYSTEM_MK(LIBNDR_GEN,librpc/config.mk)
+SMB_SUBSYSTEM_MK(LIBNDR_RAW,librpc/config.mk)
SMB_SUBSYSTEM_MK(LIBRPC_RAW,librpc/config.mk)
SMB_SUBSYSTEM_MK(LIBRPC,librpc/config.mk)
diff --git a/source4/librpc/config.mk b/source4/librpc/config.mk
index 6e33b5c104..a359f13f54 100644
--- a/source4/librpc/config.mk
+++ b/source4/librpc/config.mk
@@ -28,6 +28,56 @@ ADD_OBJ_FILES = \
################################################
################################################
+# Start SUBSYSTEM LIBNDR_GEN
+[SUBSYSTEM::LIBNDR_GEN]
+INIT_OBJ_FILES = \
+ librpc/gen_ndr/tables.o
+ADD_OBJ_FILES = \
+ librpc/gen_ndr/ndr_audiosrv.o \
+ librpc/gen_ndr/ndr_dcerpc.o \
+ librpc/gen_ndr/ndr_echo.o \
+ librpc/gen_ndr/ndr_exchange.o \
+ librpc/gen_ndr/ndr_dsbackup.o \
+ librpc/gen_ndr/ndr_efs.o \
+ librpc/gen_ndr/ndr_misc.o \
+ librpc/gen_ndr/ndr_lsa.o \
+ librpc/gen_ndr/ndr_lsads.o \
+ librpc/gen_ndr/ndr_dfs.o \
+ librpc/gen_ndr/ndr_drsuapi.o \
+ librpc/gen_ndr/ndr_policyagent.o \
+ librpc/gen_ndr/ndr_samr.o \
+ librpc/gen_ndr/ndr_spoolss.o \
+ librpc/gen_ndr/ndr_wkssvc.o \
+ librpc/gen_ndr/ndr_srvsvc.o \
+ librpc/gen_ndr/ndr_svcctl.o \
+ librpc/gen_ndr/ndr_atsvc.o \
+ librpc/gen_ndr/ndr_eventlog.o \
+ librpc/gen_ndr/ndr_epmapper.o \
+ librpc/gen_ndr/ndr_dbgidl.o \
+ librpc/gen_ndr/ndr_dssetup.o \
+ librpc/gen_ndr/ndr_msgsvc.o \
+ librpc/gen_ndr/ndr_wins.o \
+ librpc/gen_ndr/ndr_winreg.o \
+ librpc/gen_ndr/ndr_mgmt.o \
+ librpc/gen_ndr/ndr_protected_storage.o \
+ librpc/gen_ndr/ndr_dcom.o \
+ librpc/gen_ndr/ndr_oxidresolver.o \
+ librpc/gen_ndr/ndr_remact.o \
+ librpc/gen_ndr/ndr_wzcsvc.o \
+ librpc/gen_ndr/ndr_browser.o \
+ librpc/gen_ndr/ndr_w32time.o \
+ librpc/gen_ndr/ndr_scerpc.o \
+ librpc/gen_ndr/ndr_ntsvcs.o \
+ librpc/gen_ndr/ndr_netlogon.o \
+ librpc/gen_ndr/ndr_trkwks.o \
+ librpc/gen_ndr/ndr_keysvc.o \
+ librpc/gen_ndr/ndr_krb5pac.o \
+ librpc/gen_ndr/ndr_xattr.o \
+ librpc/gen_ndr/ndr_schannel.o
+# End SUBSYSTEM LIBNDR_GEN
+################################################
+
+################################################
# Start SUBSYSTEM LIBRPC
[SUBSYSTEM::LIBRPC]
REQUIRED_SUBSYSTEMS = LIBNDR_RAW LIBNDR_GEN LIBRPC_RAW
diff --git a/source4/librpc/idl/xattr.idl b/source4/librpc/idl/xattr.idl
new file mode 100644
index 0000000000..aa5c0a0d6a
--- /dev/null
+++ b/source4/librpc/idl/xattr.idl
@@ -0,0 +1,35 @@
+#include "idl_types.h"
+
+/*
+ IDL structures for xattr file attributes
+
+ this has nothing to do with RPC, we are just using our NDR/IDL
+ infrastructure as a convenient way to store linearised information
+ about a file in a architecture independent manner
+*/
+
+interface xattr
+{
+ const string XATTR_DOSATTRIB_NAME = "user.DosAttrib";
+ const string XATTR_DOSATTRIB_ESTIMATED_SIZE = 64;
+
+ /* by using a union we can cope with new version of
+ this structure more easily */
+ typedef struct {
+ uint32 attrib;
+ uint32 ea_size;
+ uint64 size;
+ uint64 alloc_size;
+ NTTIME create_time;
+ NTTIME change_time;
+ } xattr_DosInfo1;
+
+ typedef union {
+ [case(1)] xattr_DosInfo1 info1;
+ } xattr_DosInfo;
+
+ typedef [public] struct {
+ uint16 version;
+ [switch_is(version)] xattr_DosInfo info;
+ } xattr_DosAttrib;
+}
diff --git a/source4/librpc/ndr/ndr.c b/source4/librpc/ndr/ndr.c
index 8e8e49e220..71019030ac 100644
--- a/source4/librpc/ndr/ndr.c
+++ b/source4/librpc/ndr/ndr.c
@@ -318,9 +318,7 @@ void ndr_print_debug_helper(struct ndr_print *ndr, const char *format, ...) _PRI
/*
a useful helper function for printing idl structures via DEBUG()
*/
-void ndr_print_debug(void (*fn)(struct ndr_print *, const char *, void *),
- const char *name,
- void *ptr)
+void ndr_print_debug(ndr_print_fn_t fn, const char *name, void *ptr)
{
struct ndr_print *ndr;
@@ -337,10 +335,7 @@ void ndr_print_debug(void (*fn)(struct ndr_print *, const char *, void *),
/*
a useful helper function for printing idl unions via DEBUG()
*/
-void ndr_print_union_debug(void (*fn)(struct ndr_print *, const char *, uint32_t, void *),
- const char *name,
- uint32_t level,
- void *ptr)
+void ndr_print_union_debug(ndr_print_union_fn_t fn, const char *name, uint32_t level, void *ptr)
{
struct ndr_print *ndr;
@@ -356,10 +351,7 @@ void ndr_print_union_debug(void (*fn)(struct ndr_print *, const char *, uint32_t
/*
a useful helper function for printing idl function calls via DEBUG()
*/
-void ndr_print_function_debug(void (*fn)(struct ndr_print *, const char *, int , void *),
- const char *name,
- int flags,
- void *ptr)
+void ndr_print_function_debug(ndr_print_function_t fn, const char *name, int flags, void *ptr)
{
struct ndr_print *ndr;
@@ -481,10 +473,8 @@ static NTSTATUS ndr_pull_subcontext_header(struct ndr_pull *ndr,
handle subcontext buffers, which in midl land are user-marshalled, but
we use magic in pidl to make them easier to cope with
*/
-NTSTATUS ndr_pull_subcontext_fn(struct ndr_pull *ndr,
- size_t sub_size,
- void *base,
- NTSTATUS (*fn)(struct ndr_pull *, void *))
+NTSTATUS ndr_pull_subcontext_fn(struct ndr_pull *ndr, size_t sub_size,
+ void *base, ndr_pull_fn_t fn)
{
struct ndr_pull *ndr2;
NDR_ALLOC(ndr, ndr2);
@@ -499,10 +489,8 @@ NTSTATUS ndr_pull_subcontext_fn(struct ndr_pull *ndr,
}
-NTSTATUS ndr_pull_subcontext_flags_fn(struct ndr_pull *ndr,
- size_t sub_size,
- void *base,
- NTSTATUS (*fn)(struct ndr_pull *, int , void *))
+NTSTATUS ndr_pull_subcontext_flags_fn(struct ndr_pull *ndr, size_t sub_size,
+ void *base, ndr_pull_flags_fn_t fn)
{
struct ndr_pull *ndr2;
NDR_ALLOC(ndr, ndr2);
@@ -516,11 +504,8 @@ NTSTATUS ndr_pull_subcontext_flags_fn(struct ndr_pull *ndr,
return NT_STATUS_OK;
}
-NTSTATUS ndr_pull_subcontext_union_fn(struct ndr_pull *ndr,
- size_t sub_size,
- uint32_t level,
- void *base,
- NTSTATUS (*fn)(struct ndr_pull *, int , uint32_t , void *))
+NTSTATUS ndr_pull_subcontext_union_fn(struct ndr_pull *ndr, size_t sub_size,
+ uint32_t level, void *base, ndr_pull_union_fn_t fn)
{
struct ndr_pull *ndr2;
@@ -566,10 +551,8 @@ static NTSTATUS ndr_push_subcontext_header(struct ndr_push *ndr,
handle subcontext buffers, which in midl land are user-marshalled, but
we use magic in pidl to make them easier to cope with
*/
-NTSTATUS ndr_push_subcontext_fn(struct ndr_push *ndr,
- size_t sub_size,
- void *base,
- NTSTATUS (*fn)(struct ndr_push *, void *))
+NTSTATUS ndr_push_subcontext_fn(struct ndr_push *ndr, size_t sub_size,
+ void *base, ndr_push_fn_t fn)
{
struct ndr_push *ndr2;
@@ -586,10 +569,8 @@ NTSTATUS ndr_push_subcontext_fn(struct ndr_push *ndr,
/*
handle subcontext buffers for function that take a flags arg
*/
-NTSTATUS ndr_push_subcontext_flags_fn(struct ndr_push *ndr,
- size_t sub_size,
- void *base,
- NTSTATUS (*fn)(struct ndr_push *, int, void *))
+NTSTATUS ndr_push_subcontext_flags_fn(struct ndr_push *ndr, size_t sub_size,
+ void *base, ndr_push_flags_fn_t fn)
{
struct ndr_push *ndr2;
@@ -606,11 +587,8 @@ NTSTATUS ndr_push_subcontext_flags_fn(struct ndr_push *ndr,
/*
handle subcontext buffers for function that take a union
*/
-NTSTATUS ndr_push_subcontext_union_fn(struct ndr_push *ndr,
- size_t sub_size,
- uint32_t level,
- void *base,
- NTSTATUS (*fn)(struct ndr_push *, int, uint32_t, void *))
+NTSTATUS ndr_push_subcontext_union_fn(struct ndr_push *ndr, size_t sub_size,
+ uint32_t level, void *base, ndr_push_union_fn_t fn)
{
struct ndr_push *ndr2;
@@ -763,7 +741,7 @@ NTSTATUS ndr_push_relative2(struct ndr_push *ndr, const void *p)
pull a union from a blob using NDR
*/
NTSTATUS ndr_pull_union_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, uint32_t level, void *p,
- NTSTATUS (*fn)(struct ndr_pull *, int ndr_flags, uint32_t, void *))
+ ndr_pull_union_fn_t fn)
{
struct ndr_pull *ndr;
ndr = ndr_pull_init_blob(blob, mem_ctx);
@@ -777,7 +755,7 @@ NTSTATUS ndr_pull_union_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, uint32_t leve
pull a struct from a blob using NDR
*/
NTSTATUS ndr_pull_struct_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
- NTSTATUS (*fn)(struct ndr_pull *, int , void *))
+ ndr_pull_flags_fn_t fn)
{
struct ndr_pull *ndr;
ndr = ndr_pull_init_blob(blob, mem_ctx);
@@ -791,7 +769,7 @@ NTSTATUS ndr_pull_struct_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *
push a struct to a blob using NDR
*/
NTSTATUS ndr_push_struct_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
- NTSTATUS (*fn)(struct ndr_push *, int , void *))
+ ndr_push_flags_fn_t fn)
{
NTSTATUS status;
struct ndr_push *ndr;
diff --git a/source4/ntvfs/posix/config.m4 b/source4/ntvfs/posix/config.m4
index b1de4c20e5..2fb69b65b0 100644
--- a/source4/ntvfs/posix/config.m4
+++ b/source4/ntvfs/posix/config.m4
@@ -1,4 +1,3 @@
-SMB_MODULE_MK(ntvfs_posix, NTVFS, STATIC, ntvfs/config.mk)
dnl #############################################
@@ -22,4 +21,16 @@ if test x"$ac_cv_decl_have_stat_tv_nsec" = x"yes"; then
AC_DEFINE(HAVE_STAT_TV_NSEC,1,[Whether stat has tv_nsec nanosecond fields])
fi
+dnl ############################################
+dnl use flistxattr as the key function for having
+dnl sufficient xattr support for posix xattr backend
+AC_CHECK_HEADERS(sys/attributes.h attr/xattr.h sys/xattr.h)
+AC_SEARCH_LIBS(flistxattr, [attr])
+
+if test x"$ac_cv_func_flistxattr" = x"yes"; then
+ SMB_MODULE_DEFAULT(posix_xattr, STATIC)
+ AC_DEFINE(HAVE_XATTR_SUPPORT,1,[Whether we have xattr support])
+fi
+SMB_MODULE_MK(posix_xattr, NTVFS, NOT, ntvfs/posix/config.mk)
+SMB_MODULE_MK(ntvfs_posix, NTVFS, STATIC, ntvfs/config.mk)
diff --git a/source4/ntvfs/posix/config.mk b/source4/ntvfs/posix/config.mk
index 4918ee61eb..d44200d8c3 100644
--- a/source4/ntvfs/posix/config.mk
+++ b/source4/ntvfs/posix/config.mk
@@ -1,4 +1,13 @@
################################################
+# Start MODULE posix_xattr
+[MODULE::posix_xattr]
+INIT_OBJ_FILES = \
+ ntvfs/posix/pvfs_xattr.o
+# End MODULE posix_xattr
+################################################
+
+
+################################################
# Start MODULE ntvfs_posix
[MODULE::ntvfs_posix]
INIT_OBJ_FILES = \
diff --git a/source4/ntvfs/posix/pvfs_fileinfo.c b/source4/ntvfs/posix/pvfs_fileinfo.c
index 42aad1a20e..49678e5998 100644
--- a/source4/ntvfs/posix/pvfs_fileinfo.c
+++ b/source4/ntvfs/posix/pvfs_fileinfo.c
@@ -20,7 +20,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include "include/includes.h"
+#include "includes.h"
#include "vfs_posix.h"
@@ -45,14 +45,16 @@ static uint32_t dos_mode_from_stat(struct pvfs_state *pvfs, struct stat *st)
if ((st->st_mode & S_IWUSR) == 0)
result |= FILE_ATTRIBUTE_READONLY;
- if ((pvfs->flags & PVFS_FLAG_MAP_ARCHIVE) && ((st->st_mode & S_IXUSR) != 0))
- result |= FILE_ATTRIBUTE_ARCHIVE;
-
- if ((pvfs->flags & PVFS_FLAG_MAP_SYSTEM) && ((st->st_mode & S_IXGRP) != 0))
- result |= FILE_ATTRIBUTE_SYSTEM;
-
- if ((pvfs->flags & PVFS_FLAG_MAP_HIDDEN) && ((st->st_mode & S_IXOTH) != 0))
- result |= FILE_ATTRIBUTE_HIDDEN;
+ if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) {
+ if ((pvfs->flags & PVFS_FLAG_MAP_ARCHIVE) && ((st->st_mode & S_IXUSR) != 0))
+ result |= FILE_ATTRIBUTE_ARCHIVE;
+
+ if ((pvfs->flags & PVFS_FLAG_MAP_SYSTEM) && ((st->st_mode & S_IXGRP) != 0))
+ result |= FILE_ATTRIBUTE_SYSTEM;
+
+ if ((pvfs->flags & PVFS_FLAG_MAP_HIDDEN) && ((st->st_mode & S_IXOTH) != 0))
+ result |= FILE_ATTRIBUTE_HIDDEN;
+ }
if (S_ISDIR(st->st_mode))
result = FILE_ATTRIBUTE_DIRECTORY | (result & FILE_ATTRIBUTE_READONLY);
@@ -74,7 +76,7 @@ static uint32_t dos_mode_from_stat(struct pvfs_state *pvfs, struct stat *st)
/*
fill in the dos file attributes for a file
*/
-NTSTATUS pvfs_fill_dos_info(struct pvfs_state *pvfs, struct pvfs_filename *name)
+NTSTATUS pvfs_fill_dos_info(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd)
{
/* make directories appear as size 0 */
if (S_ISDIR(name->st.st_mode)) {
@@ -98,6 +100,12 @@ NTSTATUS pvfs_fill_dos_info(struct pvfs_state *pvfs, struct pvfs_filename *name)
name->dos.ea_size = 0;
name->dos.file_id = (((uint64_t)name->st.st_dev)<<32) | name->st.st_ino;
+#if HAVE_XATTR_SUPPORT
+ if (pvfs->flags & PVFS_FLAG_XATTR_ENABLE) {
+ return pvfs_xattr_load(pvfs, name, fd);
+ }
+#endif
+
return NT_STATUS_OK;
}
@@ -117,19 +125,21 @@ mode_t pvfs_fileperms(struct pvfs_state *pvfs, uint32 attrib)
mode |= S_IWUSR;
}
- if ((attrib & FILE_ATTRIBUTE_ARCHIVE) &&
- (pvfs->flags & PVFS_FLAG_MAP_ARCHIVE)) {
- mode |= S_IXUSR;
- }
-
- if ((attrib & FILE_ATTRIBUTE_SYSTEM) &&
- (pvfs->flags & PVFS_FLAG_MAP_SYSTEM)) {
- mode |= S_IXGRP;
- }
-
- if ((attrib & FILE_ATTRIBUTE_HIDDEN) &&
- (pvfs->flags & PVFS_FLAG_MAP_HIDDEN)) {
- mode |= S_IXOTH;
+ if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) {
+ if ((attrib & FILE_ATTRIBUTE_ARCHIVE) &&
+ (pvfs->flags & PVFS_FLAG_MAP_ARCHIVE)) {
+ mode |= S_IXUSR;
+ }
+
+ if ((attrib & FILE_ATTRIBUTE_SYSTEM) &&
+ (pvfs->flags & PVFS_FLAG_MAP_SYSTEM)) {
+ mode |= S_IXGRP;
+ }
+
+ if ((attrib & FILE_ATTRIBUTE_HIDDEN) &&
+ (pvfs->flags & PVFS_FLAG_MAP_HIDDEN)) {
+ mode |= S_IXOTH;
+ }
}
return mode;
diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c
index c8f96849ec..ed6da83e73 100644
--- a/source4/ntvfs/posix/pvfs_open.c
+++ b/source4/ntvfs/posix/pvfs_open.c
@@ -20,7 +20,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include "include/includes.h"
+#include "includes.h"
#include "vfs_posix.h"
#include "system/time.h"
#include "system/filesys.h"
@@ -330,6 +330,14 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs,
return status;
}
+
+#if HAVE_XATTR_SUPPORT
+ name->dos.attrib = io->ntcreatex.in.file_attr;
+ if (pvfs->flags & PVFS_FLAG_XATTR_ENABLE) {
+ status = pvfs_xattr_save(pvfs, name, fd);
+ }
+#endif
+
/* form the lock context used for byte range locking and
opendb locking */
status = pvfs_locking_key(name, f, &f->locking_key);
@@ -472,6 +480,10 @@ static void pvfs_open_retry(void *private, enum pvfs_wait_notice reason)
return;
}
+ /* re-mark it async, just in case someone up the chain does
+ paranoid checking */
+ req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC;
+
/* send the reply up the chain */
req->async_states->status = status;
req->async_states->send_fn(req);
diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c
index 551b05b248..30602b964a 100644
--- a/source4/ntvfs/posix/pvfs_resolve.c
+++ b/source4/ntvfs/posix/pvfs_resolve.c
@@ -27,7 +27,7 @@
*/
-#include "include/includes.h"
+#include "includes.h"
#include "vfs_posix.h"
#include "system/dir.h"
@@ -175,7 +175,7 @@ static NTSTATUS pvfs_case_search(struct pvfs_state *pvfs, struct pvfs_filename *
name->full_name = partial_name;
if (name->exists) {
- return pvfs_fill_dos_info(pvfs, name);
+ return pvfs_fill_dos_info(pvfs, name, -1);
}
return NT_STATUS_OK;
@@ -446,7 +446,7 @@ NTSTATUS pvfs_resolve_name(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx,
/* if we can stat() the full name now then we are done */
if (stat((*name)->full_name, &(*name)->st) == 0) {
(*name)->exists = True;
- return pvfs_fill_dos_info(pvfs, *name);
+ return pvfs_fill_dos_info(pvfs, *name, -1);
}
/* search for a matching filename */
@@ -489,7 +489,7 @@ NTSTATUS pvfs_resolve_partial(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx,
(*name)->original_name = talloc_strdup(*name, fname);
(*name)->stream_name = NULL;
- status = pvfs_fill_dos_info(pvfs, *name);
+ status = pvfs_fill_dos_info(pvfs, *name, -1);
return status;
}
@@ -534,5 +534,5 @@ NTSTATUS pvfs_resolve_name_fd(struct pvfs_state *pvfs, int fd,
name->exists = True;
- return pvfs_fill_dos_info(pvfs, name);
+ return pvfs_fill_dos_info(pvfs, name, fd);
}
diff --git a/source4/ntvfs/posix/pvfs_setfileinfo.c b/source4/ntvfs/posix/pvfs_setfileinfo.c
index 8a4c6e433d..fe489c2e69 100644
--- a/source4/ntvfs/posix/pvfs_setfileinfo.c
+++ b/source4/ntvfs/posix/pvfs_setfileinfo.c
@@ -20,7 +20,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include "include/includes.h"
+#include "includes.h"
#include "vfs_posix.h"
#include "system/time.h"
@@ -163,6 +163,13 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs,
}
}
+ *f->name = newstats;
+
+#if HAVE_XATTR_SUPPORT
+ if (pvfs->flags & PVFS_FLAG_XATTR_ENABLE) {
+ return pvfs_xattr_save(pvfs, f->name, f->fd);
+ }
+#endif
return NT_STATUS_OK;
}
@@ -287,6 +294,14 @@ NTSTATUS pvfs_setpathinfo(struct ntvfs_module_context *ntvfs,
}
}
+ *name = newstats;
+
+#if HAVE_XATTR_SUPPORT
+ if (pvfs->flags & PVFS_FLAG_XATTR_ENABLE) {
+ return pvfs_xattr_save(pvfs, name, -1);
+ }
+#endif
+
return NT_STATUS_OK;
}
diff --git a/source4/ntvfs/posix/pvfs_xattr.c b/source4/ntvfs/posix/pvfs_xattr.c
new file mode 100644
index 0000000000..24fa49108a
--- /dev/null
+++ b/source4/ntvfs/posix/pvfs_xattr.c
@@ -0,0 +1,197 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ POSIX NTVFS backend - xattr support
+
+ Copyright (C) Andrew Tridgell 2004
+
+ 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 2 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, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "system/filesys.h"
+#include "vfs_posix.h"
+#include "librpc/gen_ndr/ndr_xattr.h"
+
+
+/*
+ pull a xattr as a blob, from either a file or a file descriptor
+*/
+static NTSTATUS pull_xattr_blob(TALLOC_CTX *mem_ctx,
+ const char *attr_name,
+ const char *fname,
+ int fd,
+ size_t estimated_size,
+ DATA_BLOB *blob)
+{
+ int ret;
+
+ *blob = data_blob_talloc(mem_ctx, NULL, estimated_size);
+ if (blob->data == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+again:
+ if (fd != -1) {
+ ret = fgetxattr(fd, attr_name, blob->data, estimated_size);
+ } else {
+ ret = getxattr(fname, attr_name, blob->data, estimated_size);
+ }
+ if (ret == -1 && errno == ERANGE) {
+ estimated_size *= 2;
+ blob->data = talloc_realloc(mem_ctx, blob->data, estimated_size);
+ if (blob->data == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ blob->length = estimated_size;
+ goto again;
+ }
+
+ if (ret == -1) {
+ data_blob_free(blob);
+ return map_nt_error_from_unix(errno);
+ }
+
+ blob->length = ret;
+
+ return NT_STATUS_OK;
+}
+
+/*
+ push a xattr as a blob, from either a file or a file descriptor
+*/
+static NTSTATUS push_xattr_blob(TALLOC_CTX *mem_ctx,
+ const char *attr_name,
+ const char *fname,
+ int fd,
+ const DATA_BLOB *blob)
+{
+ int ret;
+
+ if (fd != -1) {
+ ret = fsetxattr(fd, attr_name, blob->data, blob->length, 0);
+ } else {
+ ret = setxattr(fname, attr_name, blob->data, blob->length, 0);
+ }
+ if (ret == -1) {
+ return map_nt_error_from_unix(errno);
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/*
+ fill in file attributes from extended attributes
+*/
+NTSTATUS pvfs_xattr_load(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd)
+{
+ DATA_BLOB blob;
+ NTSTATUS status;
+ struct xattr_DosAttrib attrib;
+ TALLOC_CTX *mem_ctx = talloc(name, 0);
+ struct xattr_DosInfo1 *info1;
+
+ status = pull_xattr_blob(mem_ctx, XATTR_DOSATTRIB_NAME, name->full_name,
+ fd, XATTR_DOSATTRIB_ESTIMATED_SIZE, &blob);
+
+ /* if the filesystem doesn't support them, then tell pvfs not to try again */
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
+ DEBUG(5,("pvfs_xattr: xattr not supported in filesystem\n"));
+ pvfs->flags &= ~PVFS_FLAG_XATTR_ENABLE;
+ talloc_free(mem_ctx);
+ return NT_STATUS_OK;
+ }
+
+ /* not having a DosAttrib is not an error */
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
+ talloc_free(mem_ctx);
+ return NT_STATUS_OK;
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(mem_ctx);
+ return status;
+ }
+
+ /* pull the blob */
+ status = ndr_pull_struct_blob(&blob, mem_ctx, &attrib,
+ (ndr_pull_flags_fn_t)ndr_pull_xattr_DosAttrib);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(mem_ctx);
+ return status;
+ }
+
+ switch (attrib.version) {
+ case 1:
+ info1 = &attrib.info.info1;
+ name->dos.attrib = info1->attrib;
+ name->dos.ea_size = info1->ea_size;
+ if (name->st.st_size == info1->size) {
+ name->dos.alloc_size = info1->alloc_size;
+ }
+ if (info1->create_time != 0) {
+ name->dos.create_time = info1->create_time;
+ }
+ if (info1->change_time != 0) {
+ name->dos.change_time = info1->change_time;
+ }
+ break;
+
+ default:
+ DEBUG(0,("ERROR: Unsupported xattr DosAttrib version %d on '%s'\n",
+ attrib.version, name->full_name));
+ talloc_free(mem_ctx);
+ return NT_STATUS_INVALID_LEVEL;
+ }
+
+ talloc_free(mem_ctx);
+ return NT_STATUS_OK;
+}
+
+
+/*
+ save the file attribute into into the xattr
+*/
+NTSTATUS pvfs_xattr_save(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd)
+{
+ struct xattr_DosAttrib attrib;
+ struct xattr_DosInfo1 *info1;
+ TALLOC_CTX *mem_ctx = talloc(name, 0);
+ DATA_BLOB blob;
+ NTSTATUS status;
+
+ attrib.version = 1;
+ info1 = &attrib.info.info1;
+
+ info1->attrib = name->dos.attrib;
+ info1->ea_size = name->dos.ea_size;
+ info1->size = name->st.st_size;
+ info1->alloc_size = name->dos.alloc_size;
+ info1->create_time = name->dos.create_time;
+ info1->change_time = name->dos.change_time;
+
+ status = ndr_push_struct_blob(&blob, mem_ctx, &attrib,
+ (ndr_push_flags_fn_t)ndr_push_xattr_DosAttrib);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(mem_ctx);
+ return status;
+ }
+
+ status = push_xattr_blob(mem_ctx, XATTR_DOSATTRIB_NAME, name->full_name, fd, &blob);
+ talloc_free(mem_ctx);
+
+ return status;
+}
diff --git a/source4/ntvfs/posix/vfs_posix.c b/source4/ntvfs/posix/vfs_posix.c
index 2f0f38dd22..da4296d062 100644
--- a/source4/ntvfs/posix/vfs_posix.c
+++ b/source4/ntvfs/posix/vfs_posix.c
@@ -24,7 +24,7 @@
This is the default backend
*/
-#include "include/includes.h"
+#include "includes.h"
#include "vfs_posix.h"
@@ -44,6 +44,10 @@ static void pvfs_setup_options(struct pvfs_state *pvfs)
if (lp_strict_locking(snum)) pvfs->flags |= PVFS_FLAG_STRICT_LOCKING;
if (lp_ci_filesystem(snum)) pvfs->flags |= PVFS_FLAG_CI_FILESYSTEM;
+#if HAVE_XATTR_SUPPORT
+ if (lp_parm_bool(snum, "posix", "xattr", True)) pvfs->flags |= PVFS_FLAG_XATTR_ENABLE;
+#endif
+
pvfs->sharing_violation_delay = 1000000;
delay = lp_parm_int(snum, "posix", "sharedelay");
if (delay != -1) {
diff --git a/source4/ntvfs/posix/vfs_posix.h b/source4/ntvfs/posix/vfs_posix.h
index 4ee06723ac..64b9a0d653 100644
--- a/source4/ntvfs/posix/vfs_posix.h
+++ b/source4/ntvfs/posix/vfs_posix.h
@@ -161,6 +161,7 @@ struct pvfs_mangle_context {
#define PVFS_FLAG_READONLY (1<<4)
#define PVFS_FLAG_STRICT_SYNC (1<<5)
#define PVFS_FLAG_STRICT_LOCKING (1<<6)
+#define PVFS_FLAG_XATTR_ENABLE (1<<7)
/* forward declare some anonymous structures */
struct pvfs_dir;