Mapped a few NTFS internal data to extended attributes
parent
d3f3a19866
commit
ca6466c6bb
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
247
src/ntfs-3g.c
247
src/ntfs-3g.c
|
@ -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) ||
|
||||
|
|
Loading…
Reference in New Issue