summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;