1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-24 21:34:56 +03:00

r3549: added support for DOS extended attribute lists (name/value pairs)

stored in posix xattrs
This commit is contained in:
Andrew Tridgell 2004-11-05 11:31:35 +00:00 committed by Gerald (Jerry) Carter
parent 1551f211d9
commit bad6a88371
13 changed files with 255 additions and 87 deletions

View File

@ -433,7 +433,7 @@ union smb_fileinfo {
enum smb_fileinfo_level level;
union smb_fileinfo_in in;
struct {
struct smb_all_eas {
/* the ea_size is implied by the list */
uint_t num_eas;
struct ea_struct *eas;

View File

@ -108,3 +108,5 @@ struct net_functable;
struct net_context;
struct file_info;
struct xattr_DosEAs;

View File

@ -8,6 +8,7 @@
#define STR_FIXLEN32 LIBNDR_FLAG_STR_FIXLEN32
#define STR_CONFORMANT LIBNDR_FLAG_STR_CONFORMANT
#define STR_CHARLEN LIBNDR_FLAG_STR_CHARLEN
#define STR_UTF8 LIBNDR_FLAG_STR_UTF8
/*
a UCS2 string prefixed with [size] [offset] [length], all 32 bits
@ -64,6 +65,11 @@
*/
#define astring [flag(STR_ASCII|STR_NULLTERM)] string
/*
a null terminated UTF8 string
*/
#define utf8string [flag(STR_UTF8|STR_NULLTERM)] string
#define NDR_NOALIGN LIBNDR_FLAG_NOALIGN
#define NDR_REMAINING LIBNDR_FLAG_REMAINING

View File

@ -13,8 +13,9 @@ interface xattr
const string XATTR_DOSATTRIB_NAME = "user.DosAttrib";
const string XATTR_DOSATTRIB_ESTIMATED_SIZE = 64;
/* by using a union we can cope with new version of
this structure more easily */
/* we store basic dos attributes in a DosAttrib xattr. By
using a union we can cope with new version of this
structure more easily */
typedef struct {
uint32 attrib;
uint32 ea_size;
@ -32,4 +33,19 @@ interface xattr
uint16 version;
[switch_is(version)] xattr_DosInfo info;
} xattr_DosAttrib;
/* we store DOS style extended attributes in a DosEAs xattr */
const string XATTR_DOSEAS_NAME = "user.DosEAs";
const string XATTR_DOSEAS_ESTIMATED_SIZE = 100;
typedef struct {
utf8string name;
DATA_BLOB value;
} xattr_EA;
typedef [public] struct {
uint16 num_eas;
[size_is(num_eas)] xattr_EA *eas;
} xattr_DosEAs;
}

View File

@ -99,7 +99,8 @@ struct ndr_print {
#define LIBNDR_FLAG_STR_FIXLEN32 (1<<9)
#define LIBNDR_FLAG_STR_CONFORMANT (1<<10)
#define LIBNDR_FLAG_STR_CHARLEN (1<<11)
#define LIBNDR_STRING_FLAGS (0xFFC)
#define LIBNDR_FLAG_STR_UTF8 (1<<12)
#define LIBNDR_STRING_FLAGS (0x1FFC)
#define LIBNDR_FLAG_REF_ALLOC (1<<20)

View File

@ -522,6 +522,12 @@ NTSTATUS ndr_pull_string(struct ndr_pull *ndr, int ndr_flags, const char **s)
flags &= ~LIBNDR_FLAG_STR_ASCII;
}
if (flags & LIBNDR_FLAG_STR_UTF8) {
chset = CH_UTF8;
byte_mul = 1;
flags &= ~LIBNDR_FLAG_STR_UTF8;
}
flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
flags &= ~LIBNDR_FLAG_STR_CHARLEN;
@ -762,6 +768,12 @@ NTSTATUS ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s)
flags &= ~LIBNDR_FLAG_STR_ASCII;
}
if (flags & LIBNDR_FLAG_STR_UTF8) {
chset = CH_UTF8;
byte_mul = 1;
flags &= ~LIBNDR_FLAG_STR_UTF8;
}
flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
if (flags & LIBNDR_FLAG_STR_CHARLEN) {
@ -902,7 +914,7 @@ size_t ndr_string_array_size(struct ndr_push *ndr, const char *s)
c_len = s?strlen_m(s):0;
if (flags & LIBNDR_FLAG_STR_ASCII) {
if (flags & (LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_UTF8)) {
byte_mul = 1;
}

View File

@ -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)

View File

@ -1,12 +1,3 @@
################################################
# 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]
@ -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

View File

@ -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);
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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);
}

View File

@ -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;
}
/*
save a NDR structure into a xattr
*/
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_xattr_load(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd)
NTSTATUS pvfs_dosattrib_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 (!(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);
}
/*
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;
}
status = push_xattr_blob(mem_ctx, XATTR_DOSATTRIB_NAME, name->full_name, fd, &blob);
talloc_free(mem_ctx);
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);
}