Finish removal of iconv_convenience in public API's.
[bbaumbach/samba-autobuild/.git] / source4 / ntvfs / posix / pvfs_xattr.c
index ca535db1686933808a1bf93853ad23001b02338a..1eb7c318680b55268dc8d40626ed08c71eafef60 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"
 
 /*
   pull a xattr as a blob
@@ -46,8 +47,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;
        }
@@ -98,13 +101,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 +117,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, (ndr_push_flags_fn_t)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 +162,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)) {
@@ -184,39 +193,42 @@ 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 = 
                                pvfs_round_alloc_size(pvfs, info1->alloc_size);
                }
-               if (info1->create_time != 0) {
+               if (!null_nttime(info1->create_time)) {
                        name->dos.create_time = info1->create_time;
                }
-               if (info1->change_time != 0) {
+               if (!null_nttime(info1->change_time)) {
                        name->dos.change_time = info1->change_time;
                }
                name->dos.flags = 0;
                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 = 
                                pvfs_round_alloc_size(pvfs, info2->alloc_size);
                }
-               if (info2->create_time != 0) {
+               if (!null_nttime(info2->create_time)) {
                        name->dos.create_time = info2->create_time;
                }
-               if (info2->change_time != 0) {
+               if (!null_nttime(info2->change_time)) {
                        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,26 +251,23 @@ 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, 
@@ -456,3 +465,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);
+}