r3545: initial support for using extended attributes to hold extended dos attributes...
authorAndrew Tridgell <tridge@samba.org>
Fri, 5 Nov 2004 07:29:02 +0000 (07:29 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:05:30 +0000 (13:05 -0500)
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)

15 files changed:
source4/build/m4/rewrite.m4
source4/libcli/util/errormap.c
source4/librpc/config.m4
source4/librpc/config.mk
source4/librpc/idl/xattr.idl [new file with mode: 0644]
source4/librpc/ndr/ndr.c
source4/ntvfs/posix/config.m4
source4/ntvfs/posix/config.mk
source4/ntvfs/posix/pvfs_fileinfo.c
source4/ntvfs/posix/pvfs_open.c
source4/ntvfs/posix/pvfs_resolve.c
source4/ntvfs/posix/pvfs_setfileinfo.c
source4/ntvfs/posix/pvfs_xattr.c [new file with mode: 0644]
source4/ntvfs/posix/vfs_posix.c
source4/ntvfs/posix/vfs_posix.h

index 04d904a68daec2216feaeb63e2972968644c6f13..7a24a11a5ca0c4860c2216404e139fdc53190997 100644 (file)
@@ -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
 
index 46e4831f89834719f2b090a89f61a12825ca15ec..417f4571a792df200ab69e323855817cc33023d3 100644 (file)
@@ -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
index 76dc8c9c0fd9e8e35cff5bf89e541d7e13a33295..5c137b738b23b5e22d4d76373a47278889bf6f35 100644 (file)
@@ -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)
index 6e33b5c104413b791d3c7d1fac2b77c8fe721a63..a359f13f548cc64c831afbe6f14f9a4a3c3a5341 100644 (file)
@@ -27,6 +27,56 @@ ADD_OBJ_FILES = \
 # End SUBSYSTEM LIBRPC_RAW
 ################################################
 
+################################################
+# 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]
diff --git a/source4/librpc/idl/xattr.idl b/source4/librpc/idl/xattr.idl
new file mode 100644 (file)
index 0000000..aa5c0a0
--- /dev/null
@@ -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;
+}
index 8e8e49e2202b97a415948b1b79862ab2b063352e..71019030ac3f72c2b4181ade25b5bb222f367e0b 100644 (file)
@@ -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;
index b1de4c20e50e60472f0b0464fb9ff22232de709b..2fb69b65b0c3becbe0e003381ffb0747c120bf28 100644 (file)
@@ -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)
index 4918ee61eb58ec8c88a12d22367c05ee21d71b08..d44200d8c35b4b54fb0413a2b5f6cf61ac5650cc 100644 (file)
@@ -1,3 +1,12 @@
+################################################
+# 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]
index 42aad1a20edba387a5a974ee6ad01c52f54bce32..49678e599852d3c18de32d87ae586f4567dcef0e 100644 (file)
@@ -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;
index c8f96849ecece53089bf5516e60a84abd46a5247..ed6da83e73c7c4bd7f1327f205073231c8ade5a4 100644 (file)
@@ -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);
index 551b05b248a32dc9cc12ee1d76485be43b43472d..30602b964a1c6b42b26b69ce8361c4443235aacf 100644 (file)
@@ -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);
 }
index 8a4c6e433dea2aec1dfff3e5b4e8a1e839bdac45..fe489c2e694720c0ff9bcc59efe92160ff8ac3c0 100644 (file)
@@ -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 (file)
index 0000000..24fa491
--- /dev/null
@@ -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;
+}
index 2f0f38dd22c9c953bd26bc2bcc2172a7923c6c8c..da4296d06248af968f656965114e0e5f1b1b5c99 100644 (file)
@@ -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) {
index 4ee06723ac50109205ada990e3d95e76d0d1f775..64b9a0d653d2932a622cbbd80e808bf426cf35a5 100644 (file)
@@ -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;