summaryrefslogtreecommitdiff
path: root/source4/ntvfs/posix/pvfs_xattr.c
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/ntvfs/posix/pvfs_xattr.c
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/ntvfs/posix/pvfs_xattr.c')
-rw-r--r--source4/ntvfs/posix/pvfs_xattr.c197
1 files changed, 197 insertions, 0 deletions
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;
+}