summaryrefslogtreecommitdiff
path: root/source4/ntvfs/posix
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2004-11-05 11:31:35 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:05:31 -0500
commit12f4a44cf549b4ccd729494c242a5ec186d2d670 (patch)
tree28045ce9c687afe92430fd0caa71243136c39e14 /source4/ntvfs/posix
parent2b4e716f7aec49469b2b523c86762c8d4bacb4d1 (diff)
downloadsamba-12f4a44cf549b4ccd729494c242a5ec186d2d670.tar.gz
samba-12f4a44cf549b4ccd729494c242a5ec186d2d670.tar.bz2
samba-12f4a44cf549b4ccd729494c242a5ec186d2d670.zip
r3549: added support for DOS extended attribute lists (name/value pairs)
stored in posix xattrs (This used to be commit bad6a88371264cffce2bf5d6ce904b7b357081de)
Diffstat (limited to 'source4/ntvfs/posix')
-rw-r--r--source4/ntvfs/posix/config.m42
-rw-r--r--source4/ntvfs/posix/config.mk10
-rw-r--r--source4/ntvfs/posix/pvfs_fileinfo.c26
-rw-r--r--source4/ntvfs/posix/pvfs_open.c10
-rw-r--r--source4/ntvfs/posix/pvfs_qfileinfo.c39
-rw-r--r--source4/ntvfs/posix/pvfs_setfileinfo.c78
-rw-r--r--source4/ntvfs/posix/pvfs_xattr.c128
7 files changed, 212 insertions, 81 deletions
diff --git a/source4/ntvfs/posix/config.m4 b/source4/ntvfs/posix/config.m4
index 2fb69b65b0..975da5f2a9 100644
--- a/source4/ntvfs/posix/config.m4
+++ b/source4/ntvfs/posix/config.m4
@@ -28,9 +28,7 @@ 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 d44200d8c3..dd72468216 100644
--- a/source4/ntvfs/posix/config.mk
+++ b/source4/ntvfs/posix/config.mk
@@ -1,13 +1,4 @@
################################################
-# 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 = \
@@ -33,6 +24,7 @@ ADD_OBJ_FILES = \
ntvfs/posix/pvfs_wait.o \
ntvfs/posix/pvfs_seek.o \
ntvfs/posix/pvfs_ioctl.o \
+ ntvfs/posix/pvfs_xattr.o \
ntvfs/common/opendb.o \
ntvfs/common/brlock.o
# End MODULE ntvfs_posix
diff --git a/source4/ntvfs/posix/pvfs_fileinfo.c b/source4/ntvfs/posix/pvfs_fileinfo.c
index 49678e5998..2419893049 100644
--- a/source4/ntvfs/posix/pvfs_fileinfo.c
+++ b/source4/ntvfs/posix/pvfs_fileinfo.c
@@ -45,16 +45,14 @@ 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_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 ((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);
@@ -100,13 +98,7 @@ 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;
+ return pvfs_dosattrib_load(pvfs, name, fd);
}
diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c
index ed6da83e73..d640bae279 100644
--- a/source4/ntvfs/posix/pvfs_open.c
+++ b/source4/ntvfs/posix/pvfs_open.c
@@ -330,13 +330,13 @@ 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);
+ status = pvfs_dosattrib_save(pvfs, name, fd);
+ if (!NT_STATUS_IS_OK(status)) {
+ idr_remove(pvfs->idtree_fnum, fnum);
+ close(fd);
+ return status;
}
-#endif
/* form the lock context used for byte range locking and
opendb locking */
diff --git a/source4/ntvfs/posix/pvfs_qfileinfo.c b/source4/ntvfs/posix/pvfs_qfileinfo.c
index 4c699d63ce..51aadc07a5 100644
--- a/source4/ntvfs/posix/pvfs_qfileinfo.c
+++ b/source4/ntvfs/posix/pvfs_qfileinfo.c
@@ -22,13 +22,42 @@
#include "includes.h"
#include "vfs_posix.h"
+#include "librpc/gen_ndr/ndr_xattr.h"
+/*
+ reply to a RAW_FILEINFO_ALL_EAS call
+*/
+static NTSTATUS pvfs_query_all_eas(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx,
+ struct pvfs_filename *name, int fd, struct smb_all_eas *eas)
+{
+ NTSTATUS status;
+ int i;
+ struct xattr_DosEAs *ealist = talloc_p(mem_ctx, struct xattr_DosEAs);
+
+ ZERO_STRUCTP(eas);
+ status = pvfs_doseas_load(pvfs, name, fd, ealist);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ eas->num_eas = ealist->num_eas;
+ eas->eas = talloc_array_p(mem_ctx, struct ea_struct, eas->num_eas);
+ if (eas->eas == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ for (i=0;i<eas->num_eas;i++) {
+ eas->eas[i].flags = 0;
+ eas->eas[i].name.s = ealist->eas[i].name;
+ eas->eas[i].value = ealist->eas[i].value;
+ }
+ return NT_STATUS_OK;
+}
/*
approximately map a struct pvfs_filename to a generic fileinfo struct
*/
static NTSTATUS pvfs_map_fileinfo(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx,
- struct pvfs_filename *name, union smb_fileinfo *info)
+ struct pvfs_filename *name, union smb_fileinfo *info,
+ int fd)
{
switch (info->generic.level) {
case RAW_FILEINFO_GENERIC:
@@ -61,9 +90,7 @@ static NTSTATUS pvfs_map_fileinfo(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx,
return NT_STATUS_OK;
case RAW_FILEINFO_ALL_EAS:
- info->all_eas.out.num_eas = 0;
- info->all_eas.out.eas = NULL;
- return NT_STATUS_OK;
+ return pvfs_query_all_eas(pvfs, mem_ctx, name, fd, &info->all_eas.out);
case RAW_FILEINFO_IS_NAME_VALID:
return NT_STATUS_OK;
@@ -202,7 +229,7 @@ NTSTATUS pvfs_qpathinfo(struct ntvfs_module_context *ntvfs,
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
- status = pvfs_map_fileinfo(pvfs, req, name, info);
+ status = pvfs_map_fileinfo(pvfs, req, name, info, -1);
return status;
}
@@ -228,7 +255,7 @@ NTSTATUS pvfs_qfileinfo(struct ntvfs_module_context *ntvfs,
return status;
}
- status = pvfs_map_fileinfo(pvfs, req, f->name, info);
+ status = pvfs_map_fileinfo(pvfs, req, f->name, info, f->fd);
/* a qfileinfo can fill in a bit more info than a qpathinfo -
now modify the levels that need to be fixed up */
diff --git a/source4/ntvfs/posix/pvfs_setfileinfo.c b/source4/ntvfs/posix/pvfs_setfileinfo.c
index fe489c2e69..e570743aba 100644
--- a/source4/ntvfs/posix/pvfs_setfileinfo.c
+++ b/source4/ntvfs/posix/pvfs_setfileinfo.c
@@ -23,6 +23,62 @@
#include "includes.h"
#include "vfs_posix.h"
#include "system/time.h"
+#include "librpc/gen_ndr/ndr_xattr.h"
+
+
+/*
+ add a single DOS EA
+*/
+static NTSTATUS pvfs_setfileinfo_ea_set(struct pvfs_state *pvfs,
+ struct pvfs_filename *name,
+ int fd, struct ea_struct *ea)
+{
+ struct xattr_DosEAs *ealist = talloc_p(pvfs, struct xattr_DosEAs);
+ int i;
+ NTSTATUS status;
+
+ if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) {
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+
+ /* load the current list */
+ status = pvfs_doseas_load(pvfs, name, fd, ealist);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /* see if its already there */
+ for (i=0;i<ealist->num_eas;i++) {
+ if (StrCaseCmp(ealist->eas[i].name, ea->name.s) == 0) {
+ ealist->eas[i].value = ea->value;
+ goto save;
+ }
+ }
+
+ /* add it */
+ ealist->eas = talloc_realloc_p(ealist, ealist->eas, struct xattr_EA, ealist->num_eas+1);
+ if (ealist->eas == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ ealist->eas[i].name = ea->name.s;
+ ealist->eas[i].value = ea->value;
+ ealist->num_eas++;
+
+save:
+ status = pvfs_doseas_save(pvfs, name, fd, ealist);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ name->dos.ea_size = 4;
+ for (i=0;i<ealist->num_eas;i++) {
+ name->dos.ea_size += 4 + strlen(ealist->eas[i].name)+1 +
+ ealist->eas[i].value.length;
+ }
+
+ /* update the ea_size attrib */
+ return pvfs_dosattrib_save(pvfs, name, fd);
+}
/*
set info on a open file
@@ -77,6 +133,9 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs,
}
break;
+ case RAW_SFILEINFO_EA_SET:
+ return pvfs_setfileinfo_ea_set(pvfs, f->name, f->fd, &info->ea_set.in.ea);
+
case RAW_SFILEINFO_BASIC_INFO:
case RAW_SFILEINFO_BASIC_INFORMATION:
if (info->basic_info.in.create_time) {
@@ -165,13 +224,7 @@ 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;
+ return pvfs_dosattrib_save(pvfs, f->name, f->fd);
}
@@ -227,6 +280,9 @@ NTSTATUS pvfs_setpathinfo(struct ntvfs_module_context *ntvfs,
}
break;
+ case RAW_SFILEINFO_EA_SET:
+ return pvfs_setfileinfo_ea_set(pvfs, name, -1, &info->ea_set.in.ea);
+
case RAW_SFILEINFO_BASIC_INFO:
case RAW_SFILEINFO_BASIC_INFORMATION:
if (info->basic_info.in.create_time) {
@@ -296,12 +352,6 @@ 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;
+ return pvfs_dosattrib_save(pvfs, name, -1);
}
diff --git a/source4/ntvfs/posix/pvfs_xattr.c b/source4/ntvfs/posix/pvfs_xattr.c
index 24fa49108a..e086a019ba 100644
--- a/source4/ntvfs/posix/pvfs_xattr.c
+++ b/source4/ntvfs/posix/pvfs_xattr.c
@@ -25,7 +25,6 @@
#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
*/
@@ -36,6 +35,7 @@ static NTSTATUS pull_xattr_blob(TALLOC_CTX *mem_ctx,
size_t estimated_size,
DATA_BLOB *blob)
{
+#if HAVE_XATTR_SUPPORT
int ret;
*blob = data_blob_talloc(mem_ctx, NULL, estimated_size);
@@ -67,17 +67,20 @@ again:
blob->length = ret;
return NT_STATUS_OK;
+#else
+ return NT_STATUS_NOT_SUPPORTED;
+#endif
}
/*
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,
+static NTSTATUS push_xattr_blob(const char *attr_name,
const char *fname,
int fd,
const DATA_BLOB *blob)
{
+#if HAVE_XATTR_SUPPORT
int ret;
if (fd != -1) {
@@ -90,22 +93,74 @@ static NTSTATUS push_xattr_blob(TALLOC_CTX *mem_ctx,
}
return NT_STATUS_OK;
+#else
+ return NT_STATUS_NOT_SUPPORTED;
+#endif
}
+/*
+ load a NDR structure from a xattr
+*/
+static NTSTATUS pvfs_xattr_ndr_load(TALLOC_CTX *mem_ctx,
+ const char *fname, int fd, const char *attr_name,
+ void *p, ndr_pull_flags_fn_t pull_fn)
+{
+ NTSTATUS status;
+ DATA_BLOB blob;
+
+ status = pull_xattr_blob(mem_ctx, attr_name, fname,
+ fd, XATTR_DOSATTRIB_ESTIMATED_SIZE, &blob);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /* pull the blob */
+ status = ndr_pull_struct_blob(&blob, mem_ctx, p, pull_fn);
+
+ data_blob_free(&blob);
+
+ return status;
+}
/*
- fill in file attributes from extended attributes
+ save a NDR structure into a xattr
*/
-NTSTATUS pvfs_xattr_load(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd)
+static NTSTATUS pvfs_xattr_ndr_save(const char *fname, int fd, const char *attr_name,
+ void *p, ndr_push_flags_fn_t push_fn)
{
+ TALLOC_CTX *mem_ctx = talloc(NULL, 0);
DATA_BLOB blob;
NTSTATUS status;
+
+ status = ndr_push_struct_blob(&blob, mem_ctx, p, (ndr_push_flags_fn_t)push_fn);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(mem_ctx);
+ return status;
+ }
+
+ status = push_xattr_blob(attr_name, fname, fd, &blob);
+ talloc_free(mem_ctx);
+
+ return status;
+}
+
+
+/*
+ fill in file attributes from extended attributes
+*/
+NTSTATUS pvfs_dosattrib_load(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd)
+{
+ 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 (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) {
+ return NT_STATUS_OK;
+ }
+
+ status = pvfs_xattr_ndr_load(mem_ctx, name->full_name, fd, XATTR_DOSATTRIB_NAME,
+ &attrib, (ndr_pull_flags_fn_t)ndr_pull_xattr_DosAttrib);
/* if the filesystem doesn't support them, then tell pvfs not to try again */
if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
@@ -126,14 +181,6 @@ NTSTATUS pvfs_xattr_load(struct pvfs_state *pvfs, struct pvfs_filename *name, in
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;
@@ -163,15 +210,16 @@ NTSTATUS pvfs_xattr_load(struct pvfs_state *pvfs, struct pvfs_filename *name, in
/*
- save the file attribute into into the xattr
+ save the file attribute into the xattr
*/
-NTSTATUS pvfs_xattr_save(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd)
+NTSTATUS pvfs_dosattrib_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;
+
+ if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) {
+ return NT_STATUS_OK;
+ }
attrib.version = 1;
info1 = &attrib.info.info1;
@@ -183,15 +231,39 @@ NTSTATUS pvfs_xattr_save(struct pvfs_state *pvfs, struct pvfs_filename *name, in
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;
- }
+ return pvfs_xattr_ndr_save(name->full_name, fd, XATTR_DOSATTRIB_NAME, &attrib,
+ (ndr_push_flags_fn_t)ndr_push_xattr_DosAttrib);
+}
- status = push_xattr_blob(mem_ctx, XATTR_DOSATTRIB_NAME, name->full_name, fd, &blob);
- talloc_free(mem_ctx);
+/*
+ load the set of DOS EAs
+*/
+NTSTATUS pvfs_doseas_load(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd,
+ struct xattr_DosEAs *eas)
+{
+ NTSTATUS status;
+ ZERO_STRUCTP(eas);
+ if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) {
+ return NT_STATUS_OK;
+ }
+ status = pvfs_xattr_ndr_load(eas, name->full_name, fd, XATTR_DOSEAS_NAME,
+ eas, (ndr_pull_flags_fn_t)ndr_pull_xattr_DosEAs);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
+ return NT_STATUS_OK;
+ }
return status;
}
+
+/*
+ save the set of DOS EAs
+*/
+NTSTATUS pvfs_doseas_save(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd,
+ struct xattr_DosEAs *eas)
+{
+ if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) {
+ return NT_STATUS_OK;
+ }
+ return pvfs_xattr_ndr_save(name->full_name, fd, XATTR_DOSEAS_NAME, eas,
+ (ndr_push_flags_fn_t)ndr_push_xattr_DosEAs);
+}