s4-ntvfs: Rename xattr_tdb.c to posix_eadb.c and make more generally useful
[kai/samba.git] / source4 / ntvfs / posix / pvfs_xattr.c
index c2af2e10bdea261f123a478d43a6dd934901d58a..82ce579676a6f6a7c969ccb8e672029bd0841f8f 100644 (file)
@@ -7,7 +7,7 @@
 
    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
+   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,
    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.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
 #include "vfs_posix.h"
+#include "../lib/util/unix_privs.h"
 #include "librpc/gen_ndr/ndr_xattr.h"
+#include "param/param.h"
+#include "ntvfs/posix/posix_eadb_proto.h"
 
 /*
   pull a xattr as a blob
@@ -46,8 +48,10 @@ static NTSTATUS pull_xattr_blob(struct pvfs_state *pvfs,
                                        fd, 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"));
+       if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)||
+           NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)||
+           NT_STATUS_EQUAL(status, NT_STATUS_INVALID_SYSTEM_SERVICE)) {
+               DEBUG(2,("pvfs_xattr: xattr not supported in filesystem: %s\n", nt_errstr(status)));
                pvfs->flags &= ~PVFS_FLAG_XATTR_ENABLE;
                status = NT_STATUS_NOT_FOUND;
        }
@@ -78,7 +82,7 @@ static NTSTATUS delete_xattr(struct pvfs_state *pvfs, const char *attr_name,
                             const char *fname, int fd)
 {
        if (pvfs->ea_db) {
-               return delete_xattr_tdb(pvfs, attr_name, fname, fd);
+               return delete_posix_eadb(pvfs, attr_name, fname, fd);
        }
        return delete_xattr_system(pvfs, attr_name, fname, fd);
 }
@@ -89,7 +93,7 @@ static NTSTATUS delete_xattr(struct pvfs_state *pvfs, const char *attr_name,
 NTSTATUS pvfs_xattr_unlink_hook(struct pvfs_state *pvfs, const char *fname)
 {
        if (pvfs->ea_db) {
-               return unlink_xattr_tdb(pvfs, fname);
+               return unlink_posix_eadb(pvfs, fname);
        }
        return unlink_xattr_system(pvfs, fname);
 }
@@ -98,13 +102,14 @@ NTSTATUS pvfs_xattr_unlink_hook(struct pvfs_state *pvfs, const char *fname)
 /*
   load a NDR structure from a xattr
 */
-static NTSTATUS pvfs_xattr_ndr_load(struct pvfs_state *pvfs,
-                                   TALLOC_CTX *mem_ctx,
-                                   const char *fname, int fd, const char *attr_name,
-                                   void *p, ndr_pull_flags_fn_t pull_fn)
+NTSTATUS pvfs_xattr_ndr_load(struct pvfs_state *pvfs,
+                            TALLOC_CTX *mem_ctx,
+                            const char *fname, int fd, const char *attr_name,
+                            void *p, void *pull_fn)
 {
        NTSTATUS status;
        DATA_BLOB blob;
+       enum ndr_err_code ndr_err;
 
        status = pull_xattr_blob(pvfs, mem_ctx, attr_name, fname, 
                                 fd, XATTR_DOSATTRIB_ESTIMATED_SIZE, &blob);
@@ -113,28 +118,33 @@ static NTSTATUS pvfs_xattr_ndr_load(struct pvfs_state *pvfs,
        }
 
        /* pull the blob */
-       status = ndr_pull_struct_blob(&blob, mem_ctx, p, pull_fn);
+       ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, p,
+                                                                  (ndr_pull_flags_fn_t)pull_fn);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               return ndr_map_error2ntstatus(ndr_err);
+       }
 
        data_blob_free(&blob);
 
-       return status;
+       return NT_STATUS_OK;
 }
 
 /*
   save a NDR structure into a xattr
 */
-static NTSTATUS pvfs_xattr_ndr_save(struct pvfs_state *pvfs,
-                                   const char *fname, int fd, const char *attr_name, 
-                                   void *p, ndr_push_flags_fn_t push_fn)
+NTSTATUS pvfs_xattr_ndr_save(struct pvfs_state *pvfs,
+                            const char *fname, int fd, const char *attr_name, 
+                            void *p, void *push_fn)
 {
        TALLOC_CTX *mem_ctx = talloc_new(NULL);
        DATA_BLOB blob;
        NTSTATUS status;
+       enum ndr_err_code ndr_err;
 
-       status = ndr_push_struct_blob(&blob, mem_ctx, p, push_fn);
-       if (!NT_STATUS_IS_OK(status)) {
+       ndr_err = ndr_push_struct_blob(&blob, mem_ctx, p, (ndr_push_flags_fn_t)push_fn);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                talloc_free(mem_ctx);
-               return status;
+               return ndr_map_error2ntstatus(ndr_err);
        }
 
        status = push_xattr_blob(pvfs, attr_name, fname, fd, &blob);
@@ -153,12 +163,12 @@ NTSTATUS pvfs_dosattrib_load(struct pvfs_state *pvfs, struct pvfs_filename *name
        struct xattr_DosAttrib attrib;
        TALLOC_CTX *mem_ctx = talloc_new(name);
        struct xattr_DosInfo1 *info1;
-       struct xattr_DosInfo2 *info2;
+       struct xattr_DosInfo2Old *info2;
 
        if (name->stream_name != NULL) {
-               name->stream_exists = False;
+               name->stream_exists = false;
        } else {
-               name->stream_exists = True;
+               name->stream_exists = true;
        }
 
        if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) {
@@ -167,8 +177,8 @@ NTSTATUS pvfs_dosattrib_load(struct pvfs_state *pvfs, struct pvfs_filename *name
 
        status = pvfs_xattr_ndr_load(pvfs, mem_ctx, name->full_name, 
                                     fd, XATTR_DOSATTRIB_NAME,
-                                    &attrib, 
-                                    (ndr_pull_flags_fn_t)ndr_pull_xattr_DosAttrib);
+                                    &attrib,
+                                    (void *) ndr_pull_xattr_DosAttrib);
 
        /* not having a DosAttrib is not an error */
        if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
@@ -184,7 +194,8 @@ NTSTATUS pvfs_dosattrib_load(struct pvfs_state *pvfs, struct pvfs_filename *name
        switch (attrib.version) {
        case 1:
                info1 = &attrib.info.info1;
-               name->dos.attrib = pvfs_attrib_normalise(info1->attrib);
+               name->dos.attrib = pvfs_attrib_normalise(info1->attrib, 
+                                                        name->st.st_mode);
                name->dos.ea_size = info1->ea_size;
                if (name->st.st_size == info1->size) {
                        name->dos.alloc_size = 
@@ -200,8 +211,13 @@ NTSTATUS pvfs_dosattrib_load(struct pvfs_state *pvfs, struct pvfs_filename *name
                break;
 
        case 2:
-               info2 = &attrib.info.info2;
-               name->dos.attrib = pvfs_attrib_normalise(info2->attrib);
+               /*
+                * Note: This is only used to parse existing values from disk
+                *       We use xattr_DosInfo1 again for storing new values
+                */
+               info2 = &attrib.info.oldinfo2;
+               name->dos.attrib = pvfs_attrib_normalise(info2->attrib, 
+                                                        name->st.st_mode);
                name->dos.ea_size = info2->ea_size;
                if (name->st.st_size == info2->size) {
                        name->dos.alloc_size = 
@@ -214,9 +230,6 @@ NTSTATUS pvfs_dosattrib_load(struct pvfs_state *pvfs, struct pvfs_filename *name
                        name->dos.change_time = info2->change_time;
                }
                name->dos.flags = info2->flags;
-               if (name->dos.flags & XATTR_ATTRIB_FLAG_STICKY_WRITE_TIME) {
-                       name->dos.write_time = info2->write_time;
-               }
                break;
 
        default:
@@ -239,30 +252,27 @@ NTSTATUS pvfs_dosattrib_load(struct pvfs_state *pvfs, struct pvfs_filename *name
 NTSTATUS pvfs_dosattrib_save(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd)
 {
        struct xattr_DosAttrib attrib;
-       struct xattr_DosInfo2 *info2;
+       struct xattr_DosInfo1 *info1;
 
        if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) {
                return NT_STATUS_OK;
        }
 
-       attrib.version = 2;
-       info2 = &attrib.info.info2;
+       attrib.version = 1;
+       info1 = &attrib.info.info1;
 
-       name->dos.attrib = pvfs_attrib_normalise(name->dos.attrib);
+       name->dos.attrib = pvfs_attrib_normalise(name->dos.attrib, name->st.st_mode);
 
-       info2->attrib      = name->dos.attrib;
-       info2->ea_size     = name->dos.ea_size;
-       info2->size        = name->st.st_size;
-       info2->alloc_size  = name->dos.alloc_size;
-       info2->create_time = name->dos.create_time;
-       info2->change_time = name->dos.change_time;
-       info2->write_time  = name->dos.write_time;
-       info2->flags       = name->dos.flags;
-       info2->name        = "";
+       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;
 
        return pvfs_xattr_ndr_save(pvfs, name->full_name, fd, 
                                   XATTR_DOSATTRIB_NAME, &attrib, 
-                                  (ndr_push_flags_fn_t)ndr_push_xattr_DosAttrib);
+                                  (void *) ndr_push_xattr_DosAttrib);
 }
 
 
@@ -278,7 +288,7 @@ NTSTATUS pvfs_doseas_load(struct pvfs_state *pvfs, struct pvfs_filename *name, i
                return NT_STATUS_OK;
        }
        status = pvfs_xattr_ndr_load(pvfs, eas, name->full_name, fd, XATTR_DOSEAS_NAME,
-                                    eas, (ndr_pull_flags_fn_t)ndr_pull_xattr_DosEAs);
+                                    eas, (void *) ndr_pull_xattr_DosEAs);
        if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
                return NT_STATUS_OK;
        }
@@ -295,7 +305,7 @@ NTSTATUS pvfs_doseas_save(struct pvfs_state *pvfs, struct pvfs_filename *name, i
                return NT_STATUS_OK;
        }
        return pvfs_xattr_ndr_save(pvfs, name->full_name, fd, XATTR_DOSEAS_NAME, eas, 
-                                  (ndr_push_flags_fn_t)ndr_push_xattr_DosEAs);
+                                  (void *) ndr_push_xattr_DosEAs);
 }
 
 
@@ -313,7 +323,7 @@ NTSTATUS pvfs_streams_load(struct pvfs_state *pvfs, struct pvfs_filename *name,
        status = pvfs_xattr_ndr_load(pvfs, streams, name->full_name, fd, 
                                     XATTR_DOSSTREAMS_NAME,
                                     streams, 
-                                    (ndr_pull_flags_fn_t)ndr_pull_xattr_DosStreams);
+                                    (void *) ndr_pull_xattr_DosStreams);
        if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
                return NT_STATUS_OK;
        }
@@ -332,7 +342,7 @@ NTSTATUS pvfs_streams_save(struct pvfs_state *pvfs, struct pvfs_filename *name,
        return pvfs_xattr_ndr_save(pvfs, name->full_name, fd, 
                                   XATTR_DOSSTREAMS_NAME, 
                                   streams, 
-                                  (ndr_push_flags_fn_t)ndr_push_xattr_DosStreams);
+                                  (void *) ndr_push_xattr_DosStreams);
 }
 
 
@@ -350,7 +360,7 @@ NTSTATUS pvfs_acl_load(struct pvfs_state *pvfs, struct pvfs_filename *name, int
        status = pvfs_xattr_ndr_load(pvfs, acl, name->full_name, fd, 
                                     XATTR_NTACL_NAME,
                                     acl, 
-                                    (ndr_pull_flags_fn_t)ndr_pull_xattr_NTACL);
+                                    (void *) ndr_pull_xattr_NTACL);
        return status;
 }
 
@@ -373,7 +383,7 @@ NTSTATUS pvfs_acl_save(struct pvfs_state *pvfs, struct pvfs_filename *name, int
        status = pvfs_xattr_ndr_save(pvfs, name->full_name, fd, 
                                     XATTR_NTACL_NAME, 
                                     acl, 
-                                    (ndr_push_flags_fn_t)ndr_push_xattr_NTACL);
+                                    (void *) ndr_push_xattr_NTACL);
        talloc_free(privs);
        return status;
 }
@@ -456,3 +466,17 @@ NTSTATUS pvfs_xattr_save(struct pvfs_state *pvfs,
        return status;
 }
 
+
+/*
+  probe for system support for xattrs
+*/
+void pvfs_xattr_probe(struct pvfs_state *pvfs)
+{
+       TALLOC_CTX *tmp_ctx = talloc_new(pvfs);
+       DATA_BLOB blob;
+       pull_xattr_blob(pvfs, tmp_ctx, "user.XattrProbe", pvfs->base_directory, 
+                       -1, 1, &blob);
+       pull_xattr_blob(pvfs, tmp_ctx, "security.XattrProbe", pvfs->base_directory, 
+                       -1, 1, &blob);
+       talloc_free(tmp_ctx);
+}