Mapped a few NTFS internal data to extended attributes

N2009_11_14_FIXES
jpandre 2009-01-05 13:56:05 +00:00
parent d3f3a19866
commit ca6466c6bb
7 changed files with 495 additions and 94 deletions

View File

@ -345,5 +345,11 @@ extern int ntfs_attr_remove(ntfs_inode *ni, const ATTR_TYPES type,
ntfschar *name, u32 name_len);
extern s64 ntfs_attr_get_free_bits(ntfs_attr *na);
int ntfs_get_ntfs_attrib(const char *path,
char *value, size_t size, ntfs_inode *ni);
int ntfs_set_ntfs_attrib(const char *path,
const char *value, size_t size, int flags,
ntfs_inode *ni);
#endif /* defined _NTFS_ATTRIB_H */

View File

@ -28,4 +28,10 @@ char *ntfs_make_symlink(const char *org_path,
ntfs_inode *ni, int *pattr_size);
BOOL ntfs_possible_symlink(ntfs_inode *ni);
int ntfs_get_ntfs_reparse_data(const char *path,
char *value, size_t size, ntfs_inode *ni);
int ntfs_set_ntfs_reparse_data(const char *path, const char *value,
size_t size, int flags, ntfs_inode *ni);
int ntfs_remove_ntfs_reparse_data(const char *path, ntfs_inode *ni);
#endif /* REPARSE_H */

View File

@ -30,6 +30,10 @@
#include "inode.h"
#include "dir.h"
#ifndef POSIXACLS
#define POSIXACLS 0
#endif
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define const_cpu_to_be16(x) ((((x) & 255L) << 8) + (((x) >> 8) & 255L))
#define const_cpu_to_be32(x) ((((x) & 255L) << 24) + (((x) & 0xff00L) << 8) \
@ -277,7 +281,7 @@ int ntfs_get_posix_acl(struct SECURITY_CONTEXT *scx, const char *path,
ntfs_inode *ni);
int ntfs_set_posix_acl(struct SECURITY_CONTEXT *scx, const char *path,
const char *name, const char *value, size_t size,
ntfs_inode *ni);
int flags, ntfs_inode *ni);
int ntfs_remove_posix_acl(struct SECURITY_CONTEXT *scx, const char *path,
const char *name, ntfs_inode *ni);
#endif
@ -287,7 +291,7 @@ int ntfs_get_ntfs_acl(struct SECURITY_CONTEXT *scx, const char *path,
ntfs_inode *ni);
int ntfs_set_ntfs_acl(struct SECURITY_CONTEXT *scx, const char *path,
const char *name, const char *value, size_t size,
ntfs_inode *ni);
int flags, ntfs_inode *ni);
/*
* Security API for direct access to security descriptors

View File

@ -39,6 +39,9 @@
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_SETXATTR
#include <sys/xattr.h>
#endif
#include "compat.h"
#include "attrib.h"
@ -5137,3 +5140,61 @@ s64 ntfs_attr_get_free_bits(ntfs_attr *na)
return nr_free;
}
/*
* Get the ntfs attribute into an extended attribute
* The attribute is returned according to cpu endianness
*/
int ntfs_get_ntfs_attrib(const char *path __attribute__((unused)),
char *value, size_t size, ntfs_inode *ni)
{
u32 attrib;
size_t outsize;
outsize = 0; /* default to no data and no error */
if (ni) {
attrib = le32_to_cpu(ni->flags);
if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
attrib |= const_le32_to_cpu(FILE_ATTR_DIRECTORY);
else
attrib &= ~const_le32_to_cpu(FILE_ATTR_DIRECTORY);
outsize = sizeof(FILE_ATTR_FLAGS);
if (size >= outsize) {
if (value)
memcpy(value,&attrib,outsize);
else
errno = EINVAL;
}
}
return (outsize ? (int)outsize : -errno);
}
/*
* Return the ntfs attribute into an extended attribute
* The attribute is expected according to cpu endianness
*
* Returns 0, or -1 if there is a problem
*/
int ntfs_set_ntfs_attrib(const char *path __attribute__((unused)),
const char *value, size_t size, int flags,
ntfs_inode *ni)
{
u32 attrib;
int res;
res = -1;
if (ni && value && (size >= sizeof(FILE_ATTR_FLAGS))) {
if (!(flags & XATTR_CREATE)) {
/* copy to avoid alignment problems */
memcpy(&attrib,value,sizeof(FILE_ATTR_FLAGS));
ni->flags = (ni->flags & ~const_cpu_to_le32(0x31a7))
| cpu_to_le32(attrib & 0x31a7);
NInoSetDirty(ni);
res = 0;
} else
errno = EEXIST;
} else
errno = EINVAL;
return (res ? -1 : 0);
}

View File

@ -39,6 +39,10 @@
#include <sys/stat.h>
#endif
#ifdef HAVE_SETXATTR
#include <sys/xattr.h>
#endif
#ifdef HAVE_SYS_SYSMACROS_H
#include <sys/sysmacros.h>
#endif
@ -112,6 +116,23 @@ static const ntfschar vol_junction_head[] = {
const_cpu_to_le16('{'),
} ;
static ntfschar reparse_point_name[] = {
const_cpu_to_le16('$'),
const_cpu_to_le16('R'),
const_cpu_to_le16('E'),
const_cpu_to_le16('P'),
const_cpu_to_le16('A'),
const_cpu_to_le16('R'),
const_cpu_to_le16('S'),
const_cpu_to_le16('E'),
const_cpu_to_le16('_'),
const_cpu_to_le16('P'),
const_cpu_to_le16('O'),
const_cpu_to_le16('I'),
const_cpu_to_le16('N'),
const_cpu_to_le16('T'),
} ;
static const char mappingdir[] = ".NTFS-3G/";
/*
@ -891,3 +912,145 @@ BOOL ntfs_possible_symlink(ntfs_inode *ni)
}
return (possible);
}
/*
* Get the ntfs reparse data into an extended attribute
*
* Returns the reparse data size
* and the buffer is updated if it is long enough
*/
int ntfs_get_ntfs_reparse_data(const char *path __attribute__((unused)),
char *value, size_t size, ntfs_inode *ni)
{
REPARSE_POINT *reparse_attr;
s64 attr_size;
attr_size = 0; /* default to no data and no error */
if (ni) {
if (ni->flags & FILE_ATTR_REPARSE_POINT) {
reparse_attr = (REPARSE_POINT*)ntfs_attr_readall(ni,
AT_REPARSE_POINT,(ntfschar*)NULL, 0, &attr_size);
if (reparse_attr) {
if (attr_size <= (s64)size) {
if (value)
memcpy(value,reparse_attr,
attr_size);
else
errno = EINVAL;
}
free(reparse_attr);
}
} else
errno = ENODATA;
}
return (attr_size ? (int)attr_size : -errno);
}
/*
* Set the reparse data from an extended attribute
*
* Warning : the new data is not checked
*
* Returns 0, or -1 if there is a problem
*/
int ntfs_set_ntfs_reparse_data(const char *path __attribute__((unused)),
const char *value, size_t size, int flags,
ntfs_inode *ni)
{
int res;
int written;
ntfs_attr *na;
res = 0;
if (ni && (value || !size)) {
if (!ntfs_attr_exist(ni,AT_REPARSE_POINT,(ntfschar*)NULL,0)) {
if (!(flags & XATTR_REPLACE)) {
/*
* no reparse data attribute : add one,
* apparently, this does not feed the new value in
*/
res = ntfs_attr_add(ni,AT_REPARSE_POINT,
reparse_point_name,14,(u8*)NULL,(s64)size);
if (!res)
ni->flags |= FILE_ATTR_REPARSE_POINT;
NInoSetDirty(ni);
} else {
errno = ENODATA;
res = -1;
}
} else {
if (flags & XATTR_CREATE) {
errno = EEXIST;
res = -1;
}
}
if (!res) {
/*
* open and update the existing reparse data
*/
na = ntfs_attr_open(ni, AT_REPARSE_POINT,
reparse_point_name, 14);
if (na) {
/* resize attribute */
res = ntfs_attr_truncate(na, (s64)size);
/* overwrite value if any */
if (!res && value) {
written = (int)ntfs_attr_pwrite(na,
(s64)0, (s64)size, value);
if (written != (s64)size) {
ntfs_log_error("Failed to update "
"reparse data\n");
errno = EIO;
res = -1;
}
}
ntfs_attr_close(na);
NInoSetDirty(ni);
} else
res = -1;
}
} else {
errno = EINVAL;
res = -1;
}
return (res ? -1 : 0);
}
/*
* Remove the reparse data
*
* Returns 0, or -1 if there is a problem
*/
int ntfs_remove_ntfs_reparse_data(const char *path __attribute__((unused)),
ntfs_inode *ni)
{
int res;
ntfs_attr *na;
res = 0;
if (ni) {
/*
* open and delete the reparse data
*/
na = ntfs_attr_open(ni, AT_REPARSE_POINT,
reparse_point_name, 14);
if (na) {
/* remove attribute */
res = ntfs_attr_rm(na);
if (!res)
ni->flags &= ~FILE_ATTR_REPARSE_POINT;
} else {
errno = ENODATA;
res = -1;
}
NInoSetDirty(ni);
} else {
errno = EINVAL;
res = -1;
}
return (res ? -1 : 0);
}

View File

@ -41,6 +41,10 @@
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_SETXATTR
#include <sys/xattr.h>
#endif
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
@ -2687,8 +2691,6 @@ int ntfs_set_owner_mode(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
return (res);
}
#if POSIXACLS
/*
* Check whether user has ownership rights on a file
*
@ -2741,6 +2743,8 @@ BOOL ntfs_allowed_as_owner(struct SECURITY_CONTEXT *scx,
return (allowed);
}
#if POSIXACLS
/*
* Set a new access or default Posix ACL to a file
* (or remove ACL if no input data)
@ -2751,7 +2755,7 @@ BOOL ntfs_allowed_as_owner(struct SECURITY_CONTEXT *scx,
int ntfs_set_posix_acl(struct SECURITY_CONTEXT *scx, const char *path,
const char *name, const char *value, size_t size,
ntfs_inode *ni)
int flags, ntfs_inode *ni)
{
const SECURITY_DESCRIPTOR_RELATIVE *phead;
const struct CACHED_PERMISSIONS *cached;
@ -2765,6 +2769,7 @@ int ntfs_set_posix_acl(struct SECURITY_CONTEXT *scx, const char *path,
mode_t mode;
BOOL isdir;
BOOL deflt;
BOOL exist;
int count;
struct POSIX_SECURITY *oldpxdesc;
struct POSIX_SECURITY *newpxdesc;
@ -2804,9 +2809,18 @@ int ntfs_set_posix_acl(struct SECURITY_CONTEXT *scx, const char *path,
oldpxdesc = ntfs_build_permissions_posix(scx->mapping,
oldattr, usid, gsid, ni);
if (oldpxdesc) {
mode = oldpxdesc->mode;
newpxdesc = ntfs_replace_acl(oldpxdesc,
if (deflt)
exist = oldpxdesc->defcnt > 0;
else
exist = oldpxdesc->acccnt > 3;
if ((exist && (flags & XATTR_CREATE))
|| (!exist && (flags & XATTR_REPLACE))) {
errno = (exist ? EEXIST : ENODATA);
} else {
mode = oldpxdesc->mode;
newpxdesc = ntfs_replace_acl(oldpxdesc,
(const struct POSIX_ACL*)value,count,deflt);
}
free(oldpxdesc);
}
free(oldattr);
@ -2846,7 +2860,7 @@ int ntfs_remove_posix_acl(struct SECURITY_CONTEXT *scx, const char *path,
const char *name, ntfs_inode *ni)
{
return (ntfs_set_posix_acl(scx, path, name,
(const char*)NULL, 0, ni));
(const char*)NULL, 0, 0, ni));
}
#endif
@ -2860,55 +2874,51 @@ int ntfs_remove_posix_acl(struct SECURITY_CONTEXT *scx, const char *path,
int ntfs_set_ntfs_acl(struct SECURITY_CONTEXT *scx,
const char *path __attribute__((unused)),
const char *name __attribute__((unused)),
const char *value, size_t size, ntfs_inode *ni)
const char *value, size_t size, int flags,
ntfs_inode *ni)
{
char *attr;
int res;
res = -1;
if ((size > 0)
&& !(flags & XATTR_CREATE)
&& ntfs_valid_descr(value,size)
&& (ntfs_attr_size(value) == size)) {
#if POSIXACLS
if (ntfs_allowed_as_owner(scx,path,ni)) {
#else
{ /* relying on fuse for access control */
#endif
/* need copying in order to write */
attr = (char*)ntfs_malloc(size);
if (attr) {
memcpy(attr,value,size);
res = update_secur_descr(scx->vol, attr, ni);
/*
* No need to invalidate standard caches :
* the relation between a securid and
* the associated protection is unchanged,
* only the relation between a file and
* its securid and protection is changed.
*/
/* need copying in order to write */
attr = (char*)ntfs_malloc(size);
if (attr) {
memcpy(attr,value,size);
res = update_secur_descr(scx->vol, attr, ni);
/*
* No need to invalidate standard caches :
* the relation between a securid and
* the associated protection is unchanged,
* only the relation between a file and
* its securid and protection is changed.
*/
#if CACHE_LEGACY_SIZE
/*
* we must however invalidate the legacy
* cache, which is based on inode numbers.
* For safety, invalidate even if updating
* failed.
*/
if ((ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
&& !ni->security_id) {
struct CACHED_PERMISSIONS_LEGACY legacy;
/*
* we must however invalidate the legacy
* cache, which is based on inode numbers.
* For safety, invalidate even if updating
* failed.
*/
if ((ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
&& !ni->security_id) {
struct CACHED_PERMISSIONS_LEGACY legacy;
legacy.mft_no = ni->mft_no;
legacy.variable = (char*)NULL;
legacy.varsize = 0;
ntfs_invalidate_cache(scx->vol->legacy_cache,
GENERIC(&legacy),
(cache_compare)leg_compare);
}
legacy.mft_no = ni->mft_no;
legacy.variable = (char*)NULL;
legacy.varsize = 0;
ntfs_invalidate_cache(scx->vol->legacy_cache,
GENERIC(&legacy),
(cache_compare)leg_compare);
}
#endif
free(attr);
} else
errno = ENOMEM;
}
free(attr);
} else
errno = ENOMEM;
} else
errno = EINVAL;
return (res ? -1 : 0);

View File

@ -1754,9 +1754,17 @@ close_inode:
#ifdef HAVE_SETXATTR
enum { XATTR_UNMAPPED,
XATTR_NTFS_ACL,
XATTR_NTFS_ATTRIB,
XATTR_NTFS_REPARSE_DATA,
XATTR_POSIX_ACC, XATTR_POSIX_DEF } ;
static const char nf_ns_xattr_preffix[] = "user.";
static const int nf_ns_xattr_preffix_len = 5;
static const char nf_ns_xattr_ntfs[] = "system.ntfs_acl";
static const char nf_ns_xattr_attrib[] = "system.ntfs_attrib";
static const char nf_ns_xattr_reparse[] = "system.ntfs_reparse_data";
#if POSIXACLS
@ -1771,8 +1779,8 @@ static const char nf_ns_xattr_posix_default[] = "system.posix_acl_default";
* NULL and errno set if not allowed
*/
static ntfs_inode *ntfs_check_access_xattr(const char *path,
struct SECURITY_CONTEXT *security)
static ntfs_inode *ntfs_check_access_xattr(struct SECURITY_CONTEXT *security,
const char *path)
{
ntfs_inode *ni;
@ -1801,6 +1809,32 @@ static ntfs_inode *ntfs_check_access_xattr(const char *path,
#endif
static int mapped_xattr(const char *name)
{
int num;
if (!strcmp(name,nf_ns_xattr_ntfs))
num = XATTR_NTFS_ACL;
else
if (!strcmp(name,nf_ns_xattr_attrib))
num = XATTR_NTFS_ATTRIB;
else
if (!strcmp(name,nf_ns_xattr_reparse))
num = XATTR_NTFS_REPARSE_DATA;
else
#if POSIXACLS
if (!strcmp(name,nf_ns_xattr_posix_access))
num = XATTR_POSIX_ACC;
else
if (!strcmp(name,nf_ns_xattr_posix_default))
num = XATTR_POSIX_DEF;
else
#endif
num = XATTR_UNMAPPED;
return (num);
}
static int ntfs_fuse_listxattr(const char *path, char *list, size_t size)
{
ntfs_attr_search_ctx *actx = NULL;
@ -1950,19 +1984,18 @@ static int ntfs_fuse_getxattr(const char *path, const char *name,
ntfs_attr *na = NULL;
ntfschar *lename = NULL;
int res, lename_len;
int attr;
struct SECURITY_CONTEXT security;
attr = mapped_xattr(name);
if (attr != XATTR_UNMAPPED) {
#if POSIXACLS
/*
* hijack Posix/NTFS ACL retrieval, whatever mode
* was selected for xattr (from the user's point
* of view, ACLs are not xattr)
*/
if ((!strcmp(name,nf_ns_xattr_posix_access)
|| !strcmp(name,nf_ns_xattr_posix_default)
|| !strcmp(name,nf_ns_xattr_ntfs))) {
ni = ntfs_check_access_xattr(path,&security);
ni = ntfs_check_access_xattr(&security,path);
if (ni) {
/*
* the returned value is the needed
@ -1970,25 +2003,37 @@ static int ntfs_fuse_getxattr(const char *path, const char *name,
* is done, and the caller has to
* issue a new call with correct size.
*/
if (!strcmp(name,nf_ns_xattr_ntfs))
switch (attr) {
case XATTR_NTFS_ACL :
res = ntfs_get_ntfs_acl(&security,path,
name,value,size,ni);
else
break;
case XATTR_POSIX_ACC :
case XATTR_POSIX_DEF :
res = ntfs_get_posix_acl(&security,path,
name,value,size,ni);
break;
case XATTR_NTFS_ATTRIB :
res = ntfs_get_ntfs_attrib(path,
value,size,ni);
break;
case XATTR_NTFS_REPARSE_DATA :
res = ntfs_get_ntfs_reparse_data(path,
value,size,ni);
break;
default : /* not possible */
break;
}
if (ntfs_inode_close(ni))
set_fuse_error(&res);
} else
res = -errno;
return (res);
}
#else
/*
* Only hijack NTFS ACL retrieval if POSIX ACLS
* option is not selected
* Access control is done by fuse
*/
if (!strcmp(name,nf_ns_xattr_ntfs)) {
if (ntfs_fuse_is_named_data_stream(path))
res = -EINVAL; /* n/a for named data streams. */
else {
@ -2002,16 +2047,30 @@ static int ntfs_fuse_getxattr(const char *path, const char *name,
* is done, and the caller has to
* issue a new call with correct size.
*/
res = ntfs_get_ntfs_acl(&security,path,
switch (attr) {
case XATTR_NTFS_ACL :
res = ntfs_get_ntfs_acl(&security,path,
name,value,size,ni);
break;
case XATTR_NTFS_ATTRIB :
res = ntfs_get_ntfs_attrib(path,
value,size,ni);
break;
case XATTR_NTFS_REPARSE_DATA :
res = ntfs_get_ntfs_reparse_data(path,
value,size,ni);
break;
default : /* not possible */
break;
}
if (ntfs_inode_close(ni))
set_fuse_error(&res);
} else
res = -errno;
}
#endif
return (res);
}
#endif
if (ctx->streams == NF_STREAMS_INTERFACE_WINDOWS)
return ntfs_fuse_getxattr_windows(path, name, value, size);
if (ctx->streams != NF_STREAMS_INTERFACE_XATTR)
@ -2057,8 +2116,11 @@ static int ntfs_fuse_setxattr(const char *path, const char *name,
ntfs_attr *na = NULL;
ntfschar *lename = NULL;
int res, lename_len;
int attr;
struct SECURITY_CONTEXT security;
attr = mapped_xattr(name);
if (attr != XATTR_UNMAPPED) {
#if POSIXACLS
/*
* hijack Posix/NTFS ACL retrieval, whatever mode
@ -2066,50 +2128,83 @@ static int ntfs_fuse_setxattr(const char *path, const char *name,
* of view, ACLs are not xattr)
* Note : updating an ACL does not set ctime
*/
if (!strcmp(name,nf_ns_xattr_posix_access)
|| !strcmp(name,nf_ns_xattr_posix_default)
|| !strcmp(name,nf_ns_xattr_ntfs)) {
ni = ntfs_check_access_xattr(path,&security);
ni = ntfs_check_access_xattr(&security,path);
if (ni) {
if (!strcmp(name,nf_ns_xattr_ntfs))
res = ntfs_set_ntfs_acl(&security,path,
name,value,size,ni);
else
res = ntfs_set_posix_acl(&security,path,
name,value,size,ni);
if (res)
if (ntfs_allowed_as_owner(&security,path,ni)) {
switch (attr) {
case XATTR_NTFS_ACL :
res = ntfs_set_ntfs_acl(&security,path,
name,value,size,flags,ni);
break;
case XATTR_POSIX_ACC :
case XATTR_POSIX_DEF :
res = ntfs_set_posix_acl(&security,path,
name,value,size,flags,ni);
break;
case XATTR_NTFS_ATTRIB :
res = ntfs_set_ntfs_attrib(path,
value,size,flags,ni);
break;
case XATTR_NTFS_REPARSE_DATA :
res = ntfs_set_ntfs_reparse_data(path,
value,size,flags,ni);
break;
default : /* not possible */
break;
}
if (res)
res = -errno;
} else
res = -errno;
if (ntfs_inode_close(ni))
set_fuse_error(&res);
} else
res = -errno;
return (res);
}
#else
/*
* Only hijack NTFS ACL setting if POSIX ACLS
* option is not selected
* Access control is done by fuse
* Access control is partially done by fuse
*/
if (!strcmp(name,nf_ns_xattr_ntfs)) {
if (ntfs_fuse_is_named_data_stream(path))
res = -EINVAL; /* n/a for named data streams. */
else {
ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
if (ni) {
/* user mapping not mandatory */
ntfs_fuse_fill_security_context(&security);
res = ntfs_set_ntfs_acl(&security,path,
name,value,size,ni);
/*
* user mapping is not mandatory
* if defined, only owner is allowed
*/
if (!ntfs_fuse_fill_security_context(&security)
|| ntfs_allowed_as_owner(&security,path,ni)) {
switch (attr) {
case XATTR_NTFS_ACL :
res = ntfs_set_ntfs_acl(&security,path,
name,value,size,flags,ni);
break;
case XATTR_NTFS_ATTRIB :
res = ntfs_set_ntfs_attrib(path,
value,size,flags,ni);
break;
case XATTR_NTFS_REPARSE_DATA :
res = ntfs_set_ntfs_reparse_data(path,
value,size,flags,ni);
break;
default : /* not possible */
break;
}
if (res)
res = -errno;
} else
res = -errno;
if (ntfs_inode_close(ni))
set_fuse_error(&res);
} else
res = -errno;
}
#endif
return (res);
}
#endif
if (ctx->streams != NF_STREAMS_INTERFACE_XATTR)
return -EOPNOTSUPP;
if (strncmp(name, nf_ns_xattr_preffix, nf_ns_xattr_preffix_len) ||
@ -2176,39 +2271,95 @@ static int ntfs_fuse_removexattr(const char *path, const char *name)
ntfs_inode *ni;
ntfschar *lename = NULL;
int res = 0, lename_len;
#if POSIXACLS
int attr;
struct SECURITY_CONTEXT security;
attr = mapped_xattr(name);
if (attr != XATTR_UNMAPPED) {
#if POSIXACLS
/*
* hijack Posix/NTFS ACL retrieval, whatever mode
* was selected for xattr (from the user's point
* of view, ACLs are not xattr)
* Note : updating an ACL does not set ctime
*/
if (!strcmp(name,nf_ns_xattr_posix_access)
|| !strcmp(name,nf_ns_xattr_posix_default)
|| !strcmp(name,nf_ns_xattr_ntfs)) {
res = 0;
switch (attr) {
/*
* Removal of NTFS ACL is never allowed
* Removal of NTFS ACL or ATTRIB is never allowed
*/
if (!strcmp(name,nf_ns_xattr_ntfs))
case XATTR_NTFS_ACL :
case XATTR_NTFS_ATTRIB :
res = -EPERM;
else {
ni = ntfs_check_access_xattr(path,&security);
break;
case XATTR_POSIX_ACC :
case XATTR_POSIX_DEF :
ni = ntfs_check_access_xattr(&security,path);
if (ni) {
if (ntfs_remove_posix_acl(&security,path,
if (!ntfs_allowed_as_owner(&security,path,ni)
|| ntfs_remove_posix_acl(&security,path,
name,ni))
res = -errno;
if (ntfs_inode_close(ni))
set_fuse_error(&res);
} else
res = -errno;
break;
case XATTR_NTFS_REPARSE_DATA :
ni = ntfs_check_access_xattr(&security,path);
if (ni) {
if (!ntfs_allowed_as_owner(&security,path,ni)
|| ntfs_remove_ntfs_reparse_data(path,ni))
res = -errno;
if (ntfs_inode_close(ni))
set_fuse_error(&res);
} else
res = -errno;
break;
default : /* not possible */
break;
}
#else
/*
* Only hijack NTFS ACL and ATTRIB removal if POSIX ACLS
* option is not selected
* Access control is partially done by fuse
*/
if (ntfs_fuse_is_named_data_stream(path))
res = -EINVAL; /* n/a for named data streams. */
else {
switch (attr) {
/*
* Removal of NTFS ACL or ATTRIB is never allowed
*/
case XATTR_NTFS_ACL :
case XATTR_NTFS_ATTRIB :
res = -EPERM;
break;
case XATTR_NTFS_REPARSE_DATA :
ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
if (ni) {
/*
* user mapping is not mandatory
* if defined, only owner is allowed
*/
if ((ntfs_fuse_fill_security_context(&security)
&& !ntfs_allowed_as_owner(&security,path,ni))
|| ntfs_remove_ntfs_reparse_data(path,ni))
res = -errno;
if (ntfs_inode_close(ni))
set_fuse_error(&res);
} else
res = -errno;
break;
default : /* not possible */
break;
}
}
return (res);
}
#endif
return (res);
}
if (ctx->streams != NF_STREAMS_INTERFACE_XATTR)
return -EOPNOTSUPP;
if (strncmp(name, nf_ns_xattr_preffix, nf_ns_xattr_preffix_len) ||