summaryrefslogtreecommitdiff
path: root/source4/ntvfs/posix
diff options
context:
space:
mode:
Diffstat (limited to 'source4/ntvfs/posix')
-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
9 files changed, 291 insertions, 32 deletions
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;