Changed the interfaces to use extended attributes

PERMISSION_HANDLING_BRANCH
jpandre 2009-12-17 08:24:13 +00:00
parent 9cad01c628
commit d990f7996c
9 changed files with 408 additions and 420 deletions

View File

@ -106,12 +106,11 @@ extern int ntfs_readdir(ntfs_inode *dir_ni, s64 *pos,
ntfs_inode *ntfs_dir_parent_inode(ntfs_inode *ni);
int ntfs_get_ntfs_dos_name(const char *path,
char *value, size_t size, ntfs_inode *ni);
int ntfs_set_ntfs_dos_name(const char *path,
const char *value, size_t size, int flags,
ntfs_inode *ni);
int ntfs_remove_ntfs_dos_name(const char *path, ntfs_inode *ni);
int ntfs_get_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
char *value, size_t size);
int ntfs_set_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
const char *value, size_t size, int flags);
int ntfs_remove_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni);
#endif /* defined _NTFS_DIR_H */

View File

@ -21,11 +21,10 @@
#ifndef EFS_H
#define EFS_H
int ntfs_get_efs_info(const char *path,
char *value, size_t size, ntfs_inode *ni);
int ntfs_set_efs_info(const char *path,
const char *value, size_t size, int flags,
ntfs_inode *ni);
int ntfs_get_efs_info(ntfs_inode *ni, char *value, size_t size);
int ntfs_set_efs_info(ntfs_inode *ni,
const char *value, size_t size, int flags);
int ntfs_efs_fixup_attribute(ntfs_attr_search_ctx *ctx, ntfs_attr *na);
#endif /* EFS_H */

View File

@ -196,9 +196,9 @@ extern int ntfs_inode_free_space(ntfs_inode *ni, int size);
extern int ntfs_inode_badclus_bad(u64 mft_no, ATTR_RECORD *a);
extern int ntfs_inode_get_times(const char *path, char *value,
size_t size, ntfs_inode *ni);
extern int ntfs_inode_set_times(const char *path, const char *value,
size_t size, int flags, ntfs_inode *ni);
extern int ntfs_inode_get_times(ntfs_inode *ni, char *value, size_t size);
extern int ntfs_inode_set_times(ntfs_inode *ni, const char *value,
size_t size, int flags);
#endif /* defined _NTFS_INODE_H */

View File

@ -28,11 +28,11 @@ char *ntfs_make_symlink(ntfs_inode *ni, const char *mnt_point,
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);
int ntfs_get_ntfs_reparse_data(ntfs_inode *ni, char *value, size_t size);
int ntfs_set_ntfs_reparse_data(ntfs_inode *ni, const char *value,
size_t size, int flags);
int ntfs_remove_ntfs_reparse_data(ntfs_inode *ni);
int ntfs_delete_reparse_index(ntfs_inode *ni);

View File

@ -1899,65 +1899,107 @@ static int get_dos_name(ntfs_inode *ni, u64 dnum, ntfschar *dosname)
}
/*
* Get a long name for a file in designated directory
*
* Returns size if found
* 0 if not found
* -1 if there was an error (described by errno)
*/
static int get_long_name(ntfs_inode *ni, u64 dnum, ntfschar *longname)
{
size_t outsize = 0;
FILE_NAME_ATTR *fn;
ntfs_attr_search_ctx *ctx;
/* find the name in the attributes */
ctx = ntfs_attr_get_search_ctx(ni, NULL);
if (!ctx)
return -1;
/* first search for WIN32 or DOS+WIN32 names */
while (!ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, CASE_SENSITIVE,
0, NULL, 0, ctx)) {
/* We know this will always be resident. */
fn = (FILE_NAME_ATTR*)((u8*)ctx->attr +
le16_to_cpu(ctx->attr->value_offset));
if ((fn->file_name_type & FILE_NAME_WIN32)
&& (MREF_LE(fn->parent_directory) == dnum)) {
/*
* Found a WIN32 or WIN32+DOS name for the entry
* copy name
*/
outsize = fn->file_name_length;
memcpy(longname,fn->file_name,outsize*sizeof(ntfschar));
}
}
/* if not found search for POSIX names */
if (!outsize) {
ntfs_attr_reinit_search_ctx(ctx);
while (!ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, CASE_SENSITIVE,
0, NULL, 0, ctx)) {
/* We know this will always be resident. */
fn = (FILE_NAME_ATTR*)((u8*)ctx->attr +
le16_to_cpu(ctx->attr->value_offset));
if ((fn->file_name_type == FILE_NAME_POSIX)
&& (MREF_LE(fn->parent_directory) == dnum)) {
/*
* Found a POSIX name for the entry
* copy name
*/
outsize = fn->file_name_length;
memcpy(longname,fn->file_name,outsize*sizeof(ntfschar));
}
}
}
ntfs_attr_put_search_ctx(ctx);
return (outsize);
}
/*
* Get the ntfs DOS name into an extended attribute
*/
int ntfs_get_ntfs_dos_name(const char *path,
char *value, size_t size, ntfs_inode *ni)
int ntfs_get_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
char *value, size_t size)
{
int outsize = 0;
char *outname = (char*)NULL;
ntfs_inode *dir_ni = NULL;
u64 dnum;
char *dirname;
const char *rdirname;
char *p;
int doslen;
ntfschar dosname[MAX_DOS_NAME_LENGTH];
/* get the parent directory */
dirname = strdup(path);
if (dirname) {
p = strrchr(dirname,'/');
if (p) {
*p++ = 0;
rdirname = (dirname[0] ? dirname : "/");
dir_ni = ntfs_pathname_to_inode(ni->vol, NULL, rdirname);
dnum = dir_ni->mft_no;
free(dirname);
}
}
if (dir_ni) {
doslen = get_dos_name(ni, dnum, dosname);
if (doslen > 0) {
/*
* Found a DOS name for the entry, make
* uppercase and encode into the buffer
* if there is enough space
*/
ntfs_name_upcase(dosname, doslen,
ni->vol->upcase, ni->vol->upcase_len);
if (ntfs_ucstombs(dosname, doslen, &outname, size) < 0) {
ntfs_log_error("Cannot represent dosname in current locale.\n");
outsize = -errno;
} else {
outsize = strlen(outname);
if (value && (outsize <= (int)size))
memcpy(value, outname, outsize);
else
if (size && (outsize > (int)size))
outsize = -ERANGE;
free(outname);
}
} else {
if (doslen == 0)
errno = ENODATA;
dnum = dir_ni->mft_no;
doslen = get_dos_name(ni, dnum, dosname);
if (doslen > 0) {
/*
* Found a DOS name for the entry, make
* uppercase and encode into the buffer
* if there is enough space
*/
ntfs_name_upcase(dosname, doslen,
ni->vol->upcase, ni->vol->upcase_len);
if (ntfs_ucstombs(dosname, doslen, &outname, size) < 0) {
ntfs_log_error("Cannot represent dosname in current locale.\n");
outsize = -errno;
} else {
outsize = strlen(outname);
if (value && (outsize <= (int)size))
memcpy(value, outname, outsize);
else
if (size && (outsize > (int)size))
outsize = -ERANGE;
free(outname);
}
ntfs_inode_close(dir_ni);
} else
} else {
if (doslen == 0)
errno = ENODATA;
outsize = -errno;
}
return (outsize);
}
@ -2043,7 +2085,6 @@ static int set_namespace(ntfs_inode *ni, ntfs_inode *dir_ni,
*/
static int set_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
const char *fullpath,
ntfschar *shortname, int shortlen,
ntfschar *longname, int longlen,
ntfschar *deletename, int deletelen, BOOL existed)
@ -2091,19 +2132,22 @@ static int set_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
longname, longlen,
FILE_NAME_WIN32_AND_DOS) >= 0))
res = 0;
ntfs_inode_update_times(ni, NTFS_UPDATE_CTIME);
ntfs_inode_update_times(dir_ni, NTFS_UPDATE_MCTIME);
if (ntfs_inode_close_in_dir(ni,dir_ni) && !res)
res = -1;
if (ntfs_inode_close(dir_ni) && !res)
res = -1;
}
} else
} else {
if (!ntfs_link_i(ni, dir_ni, shortname, shortlen,
FILE_NAME_DOS)
/* make sure a new link was recorded */
&& (le16_to_cpu(ni->mrec->link_count) > linkcount)) {
/* delete the existing long name or short name */
if (!ntfs_delete(vol, fullpath, ni, dir_ni,
deletename, deletelen)) {
// is it ok to not provide the path ?
if (!ntfs_delete(vol, (char*)NULL, ni, dir_ni,
deletename, deletelen)) {
/* delete closes the inodes, so have to open again */
dir_ni = ntfs_inode_open(vol, dnum);
if (dir_ni) {
@ -2126,6 +2170,7 @@ static int set_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
ntfs_inode_close_in_dir(ni,dir_ni);
ntfs_inode_close(dir_ni);
}
}
return (res);
}
@ -2140,8 +2185,8 @@ static int set_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
* The inode of the file is always closed
*/
int ntfs_set_ntfs_dos_name(const char *path, const char *value, size_t size,
int flags, ntfs_inode *ni)
int ntfs_set_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
const char *value, size_t size, int flags)
{
int res = 0;
int longlen = 0;
@ -2154,11 +2199,7 @@ int ntfs_set_ntfs_dos_name(const char *path, const char *value, size_t size,
u64 dnum;
BOOL closed = FALSE;
ntfschar *shortname = NULL;
ntfschar *longname = NULL;
ntfs_inode *dir_ni = NULL;
char *dirname = (char*)NULL;
const char *rdirname;
char *p;
ntfschar longname[NTFS_MAX_NAME_LEN];
vol = ni->vol;
fnum = ni->mft_no;
@ -2170,28 +2211,17 @@ int ntfs_set_ntfs_dos_name(const char *path, const char *value, size_t size,
shortlen = ntfs_mbstoucs(newname, &shortname);
/* make sure the short name has valid chars */
if ((shortlen < 0) || ntfs_forbidden_chars(shortname,shortlen)) {
ntfs_inode_close(ni);
ntfs_inode_close_in_dir(ni,dir_ni);
ntfs_inode_close(dir_ni);
res = -errno;
return res;
}
/* get the parent directory */
dirname = strdup(path);
if (dirname) {
p = strrchr(dirname,'/');
if (p) {
*p++ = 0;
longlen = ntfs_mbstoucs(p, &longname);
/* make sure the long name had valid chars */
if (!ntfs_forbidden_chars(longname,longlen)) {
rdirname = (dirname[0] ? dirname : "/");
dir_ni = ntfs_pathname_to_inode(vol, NULL, rdirname);
}
}
}
if (dir_ni) {
dnum = dir_ni->mft_no;
dnum = dir_ni->mft_no;
longlen = get_long_name(ni, dnum, longname);
if (longlen > 0) {
oldlen = get_dos_name(ni, dnum, oldname);
if (oldlen >= 0) {
if ((oldlen >= 0)
&& !ntfs_forbidden_chars(longname, longlen)) {
if (oldlen > 0) {
if (flags & XATTR_CREATE) {
res = -1;
@ -2204,7 +2234,6 @@ int ntfs_set_ntfs_dos_name(const char *path, const char *value, size_t size,
res = 0;
else {
res = set_dos_name(ni, dir_ni,
path,
shortname, shortlen,
longname, longlen,
oldname, oldlen, TRUE);
@ -2215,7 +2244,7 @@ int ntfs_set_ntfs_dos_name(const char *path, const char *value, size_t size,
res = -1;
errno = ENODATA;
} else {
res = set_dos_name(ni, dir_ni, path,
res = set_dos_name(ni, dir_ni,
shortname, shortlen,
longname, longlen,
longname, longlen, FALSE);
@ -2224,17 +2253,15 @@ int ntfs_set_ntfs_dos_name(const char *path, const char *value, size_t size,
}
} else
res = -1;
if (!closed)
ntfs_inode_close(dir_ni);
} else {
res = -1;
errno = EINVAL;
errno = ENOENT;
}
free(dirname);
free(longname);
free(shortname);
if (!closed)
ntfs_inode_close(ni);
if (!closed) {
ntfs_inode_close_in_dir(ni,dir_ni);
ntfs_inode_close(dir_ni);
}
return (res ? -1 : 0);
}
@ -2242,7 +2269,7 @@ int ntfs_set_ntfs_dos_name(const char *path, const char *value, size_t size,
* Delete the ntfs DOS name
*/
int ntfs_remove_ntfs_dos_name(const char *path, ntfs_inode *ni)
int ntfs_remove_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni)
{
int res;
int oldnametype;
@ -2252,27 +2279,13 @@ int ntfs_remove_ntfs_dos_name(const char *path, ntfs_inode *ni)
ntfs_volume *vol;
BOOL deleted = FALSE;
ntfschar shortname[MAX_DOS_NAME_LENGTH];
ntfschar *longname = NULL;
ntfs_inode *dir_ni = NULL;
char *dirname = (char*)NULL;
const char *rdirname;
char *p;
ntfschar longname[NTFS_MAX_NAME_LEN];
res = -1;
vol = ni->vol;
/* get the parent directory */
dirname = strdup(path);
if (dirname) {
p = strrchr(dirname,'/');
if (p) {
*p++ = 0;
longlen = ntfs_mbstoucs(p, &longname);
rdirname = (dirname[0] ? dirname : "/");
dir_ni = ntfs_pathname_to_inode(vol, NULL, rdirname);
}
}
if (dir_ni) {
dnum = dir_ni->mft_no;
dnum = dir_ni->mft_no;
longlen = get_long_name(ni, dnum, longname);
if (longlen > 0) {
shortlen = get_dos_name(ni, dnum, shortname);
if (shortlen >= 0) {
/* migrate the long name as Posix */
@ -2307,8 +2320,8 @@ int ntfs_remove_ntfs_dos_name(const char *path, ntfs_inode *ni)
*/
errno = EIO;
ntfs_log_error("Could not change"
" DOS name of %s to Posix\n",
path);
" DOS name of inode %lld to Posix\n",
(long long)ni->mft_no);
}
break;
default :
@ -2317,13 +2330,14 @@ int ntfs_remove_ntfs_dos_name(const char *path, ntfs_inode *ni)
break;
}
}
if (!deleted)
ntfs_inode_close(dir_ni);
} else {
errno = ENOENT;
res = -1;
}
if (!deleted) {
ntfs_inode_close_in_dir(ni,dir_ni);
ntfs_inode_close(dir_ni);
}
if (!deleted)
ntfs_inode_close(ni);
free(longname);
free(dirname);
return (res);
}

View File

@ -71,8 +71,7 @@ static ntfschar logged_utility_stream_name[] = {
* Get the ntfs EFS info into an extended attribute
*/
int ntfs_get_efs_info(const char *path,
char *value, size_t size, ntfs_inode *ni)
int ntfs_get_efs_info(ntfs_inode *ni, char *value, size_t size)
{
EFS_ATTR_HEADER *efs_info;
s64 attr_size = 0;
@ -100,17 +99,20 @@ int ntfs_get_efs_info(const char *path,
} else {
if (efs_info) {
free(efs_info);
ntfs_log_error("Bad efs_info for file %s\n",path);
ntfs_log_error("Bad efs_info for inode %lld\n",
(long long)ni->mft_no);
} else {
ntfs_log_error("Could not get efsinfo"
" for file %s\n", path);
" for inode %lld\n",
(long long)ni->mft_no);
}
errno = EIO;
attr_size = 0;
}
} else {
errno = ENODATA;
ntfs_log_trace("File %s is not encrypted\n",path);
ntfs_log_trace("Inode %lld is not encrypted\n",
(long long)ni->mft_no);
}
}
return (attr_size ? (int)attr_size : -errno);
@ -122,9 +124,9 @@ int ntfs_get_efs_info(const char *path,
* Returns 0, or -1 if there is a problem
*/
int ntfs_set_efs_info(const char *path __attribute__((unused)),
const char *value, size_t size, int flags,
ntfs_inode *ni)
int ntfs_set_efs_info(ntfs_inode *ni, const char *value, size_t size,
int flags)
{
int res;
int written;
@ -136,7 +138,8 @@ int ntfs_set_efs_info(const char *path __attribute__((unused)),
if (ni && value && size) {
if (ni->flags & (FILE_ATTR_ENCRYPTED | FILE_ATTR_COMPRESSED)) {
if (ni->flags & FILE_ATTR_ENCRYPTED) {
ntfs_log_trace("File %s already encrypted\n",path);
ntfs_log_trace("Inode %lld already encrypted\n",
(long long)ni->mft_no);
errno = EEXIST;
} else {
/*
@ -145,8 +148,8 @@ int ntfs_set_efs_info(const char *path __attribute__((unused)),
* restored as compressed.
* TODO : decompress first.
*/
ntfs_log_error("File %s cannot be encrypted and compressed\n",
path);
ntfs_log_error("Inode %lld cannot be encrypted and compressed\n",
(long long)ni->mft_no);
errno = EIO;
}
return -1;

View File

@ -1239,8 +1239,7 @@ int ntfs_inode_badclus_bad(u64 mft_no, ATTR_RECORD *attr)
* -errno if failed
*/
int ntfs_inode_get_times(const char *path __attribute__((unused)),
char *value, size_t size, ntfs_inode *ni)
int ntfs_inode_get_times(ntfs_inode *ni, char *value, size_t size)
{
ntfs_attr_search_ctx *ctx;
STANDARD_INFORMATION *std_info;
@ -1298,9 +1297,8 @@ int ntfs_inode_get_times(const char *path __attribute__((unused)),
* -1 if there were an error (described by errno)
*/
int ntfs_inode_set_times(const char *path __attribute__((unused)),
const char *value, size_t size,
int flags, ntfs_inode *ni)
int ntfs_inode_set_times(ntfs_inode *ni, const char *value, size_t size,
int flags)
{
ntfs_attr_search_ctx *ctx;
STANDARD_INFORMATION *std_info;

View File

@ -1028,8 +1028,7 @@ int ntfs_delete_reparse_index(ntfs_inode *ni)
* 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)
int ntfs_get_ntfs_reparse_data(ntfs_inode *ni, char *value, size_t size)
{
REPARSE_POINT *reparse_attr;
s64 attr_size;
@ -1063,9 +1062,8 @@ int ntfs_get_ntfs_reparse_data(const char *path __attribute__((unused)),
* 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 ntfs_set_ntfs_reparse_data(ntfs_inode *ni,
const char *value, size_t size, int flags)
{
int res;
u8 dummy;
@ -1134,8 +1132,7 @@ int ntfs_set_ntfs_reparse_data(const char *path __attribute__((unused)),
* Returns 0, or -1 if there is a problem
*/
int ntfs_remove_ntfs_reparse_data(const char *path __attribute__((unused)),
ntfs_inode *ni)
int ntfs_remove_ntfs_reparse_data(ntfs_inode *ni)
{
int res;
int olderrno;

View File

@ -2653,6 +2653,83 @@ exit:
return ret;
}
static __inline__ int ntfs_system_getxattr(struct SECURITY_CONTEXT *scx,
const char *path, int attr, ntfs_inode *ni,
char *value, size_t size)
{
int res;
ntfs_inode *dir_ni;
char *dirpath;
char *p;
/*
* the returned value is the needed
* size. If it is too small, no copy
* is done, and the caller has to
* issue a new call with correct size.
*/
switch (attr) {
case XATTR_NTFS_ACL :
res = ntfs_get_ntfs_acl(scx, ni, value, size);
break;
#if POSIXACLS
case XATTR_POSIX_ACC :
res = ntfs_get_posix_acl(scx, ni, nf_ns_xattr_posix_access,
value, size);
break;
case XATTR_POSIX_DEF :
res = ntfs_get_posix_acl(scx, ni, nf_ns_xattr_posix_default,
value, size);
break;
#endif
case XATTR_NTFS_ATTRIB :
res = ntfs_get_ntfs_attrib(ni, value, size);
break;
case XATTR_NTFS_EFSINFO :
if (ctx->efs_raw)
res = ntfs_get_efs_info(ni, value, size);
else
res = -EPERM;
break;
case XATTR_NTFS_REPARSE_DATA :
res = ntfs_get_ntfs_reparse_data(ni, value, size);
break;
case XATTR_NTFS_DOS_NAME:
res = 0;
dirpath = strdup(path);
if (dirpath) {
p = strrchr(dirpath,'/'); /* always present */
*p = 0;
dir_ni = ntfs_pathname_to_inode(ni->vol,
NULL, dirpath);
if (dir_ni) {
res = ntfs_get_ntfs_dos_name(ni,
dir_ni, value, size);
if (ntfs_inode_close(dir_ni))
set_fuse_error(&res);
} else
res = -errno;
free(dirpath);
} else
res = -ENOMEM;
if (res < 0)
errno = -res;
break;
case XATTR_NTFS_TIMES:
res = ntfs_inode_get_times(ni, value, size);
break;
default :
/*
* make sure applications do not see
* Posix ACL not consistent with mode
*/
errno = EOPNOTSUPP;
res = -errno;
break;
}
return (res);
}
static int ntfs_fuse_getxattr(const char *path, const char *name,
char *value, size_t size)
{
@ -2676,54 +2753,8 @@ static int ntfs_fuse_getxattr(const char *path, const char *name,
ni = ntfs_check_access_xattr(&security, path, attr, FALSE);
if (ni) {
if (ntfs_allowed_access(&security,ni,S_IREAD)) {
/*
* the returned value is the needed
* size. If it is too small, no copy
* is done, and the caller has to
* issue a new call with correct size.
*/
switch (attr) {
case XATTR_NTFS_ACL :
res = ntfs_get_ntfs_acl(&security, ni,
value, size);
break;
case XATTR_POSIX_ACC :
case XATTR_POSIX_DEF :
res = ntfs_get_posix_acl(&security, ni,
name, value, size);
break;
case XATTR_NTFS_ATTRIB :
res = ntfs_get_ntfs_attrib(ni,
value, size);
break;
case XATTR_NTFS_EFSINFO :
if (ctx->efs_raw)
res = ntfs_get_efs_info(path,
value,size,ni);
else
res = -EPERM;
break;
case XATTR_NTFS_REPARSE_DATA :
res = ntfs_get_ntfs_reparse_data(path,
value,size,ni);
break;
case XATTR_NTFS_DOS_NAME:
res = ntfs_get_ntfs_dos_name(path,
value,size,ni);
break;
case XATTR_NTFS_TIMES:
res = ntfs_inode_get_times(path,
value,size,ni);
break;
default :
/*
* make sure applications do not see
* Posix ACL not consistent with mode
*/
errno = EOPNOTSUPP;
res = -errno;
break;
}
res = ntfs_system_getxattr(&security,
path, attr, ni, value, size);
} else {
res = -errno;
}
@ -2744,49 +2775,8 @@ static int ntfs_fuse_getxattr(const char *path, const char *name,
if (ni) {
/* user mapping not mandatory */
ntfs_fuse_fill_security_context(&security);
/*
* the returned value is the needed
* size. If it is too small, no copy
* is done, and the caller has to
* issue a new call with correct size.
*/
switch (attr) {
case XATTR_NTFS_ACL :
res = ntfs_get_ntfs_acl(&security, ni,
value, size);
break;
case XATTR_NTFS_ATTRIB :
res = ntfs_get_ntfs_attrib(ni,
value, size);
break;
case XATTR_NTFS_EFSINFO :
if (ctx->efs_raw)
res = ntfs_get_efs_info(path,
value,size,ni);
else
res = -EPERM;
break;
case XATTR_NTFS_REPARSE_DATA :
res = ntfs_get_ntfs_reparse_data(path,
value,size,ni);
break;
case XATTR_NTFS_DOS_NAME:
res = ntfs_get_ntfs_dos_name(path,
value,size,ni);
break;
case XATTR_NTFS_TIMES:
res = ntfs_inode_get_times(path,
value,size,ni);
break;
default :
/*
* make sure applications do not see
* Posix ACL not consistent with mode
*/
errno = EOPNOTSUPP;
res = -errno;
break;
}
res = ntfs_system_getxattr(&security,
path, attr, ni, value, size);
if (ntfs_inode_close(ni))
set_fuse_error(&res);
} else
@ -2857,6 +2847,77 @@ exit:
return res;
}
static __inline__ int ntfs_system_setxattr(struct SECURITY_CONTEXT *scx,
const char *path, int attr, ntfs_inode *ni,
const char *value, size_t size, int flags)
{
int res;
char *dirpath;
char *p;
ntfs_inode *dir_ni;
switch (attr) {
case XATTR_NTFS_ACL :
res = ntfs_set_ntfs_acl(scx, ni, value, size, flags);
break;
#if POSIXACLS
case XATTR_POSIX_ACC :
res = ntfs_set_posix_acl(scx,ni, nf_ns_xattr_posix_access,
value, size, flags);
break;
case XATTR_POSIX_DEF :
res = ntfs_set_posix_acl(scx, ni, nf_ns_xattr_posix_default,
value, size, flags);
break;
#endif
case XATTR_NTFS_ATTRIB :
res = ntfs_set_ntfs_attrib(ni, value, size, flags);
break;
case XATTR_NTFS_EFSINFO :
if (ctx->efs_raw)
res = ntfs_set_efs_info(ni, value, size, flags);
else
res = -EPERM;
break;
case XATTR_NTFS_REPARSE_DATA :
res = ntfs_set_ntfs_reparse_data(ni, value, size, flags);
break;
case XATTR_NTFS_DOS_NAME:
res = 0;
dirpath = strdup(path);
if (dirpath) {
p = strrchr(dirpath,'/'); /* always present */
*p = 0;
dir_ni = ntfs_pathname_to_inode(ni->vol,
NULL, dirpath);
if (dir_ni)
/* warning : this closes both inodes */
res = ntfs_set_ntfs_dos_name(ni, dir_ni,
value,size,flags);
else
res = -errno;
free(dirpath);
} else
res = -ENOMEM;
if (res < 0)
errno = -res;
break;
case XATTR_NTFS_TIMES:
res = ntfs_inode_set_times(ni, value, size, flags);
break;
default :
/*
* make sure applications do not see
* Posix ACL not consistent with mode
*/
errno = EOPNOTSUPP;
res = -errno;
break;
}
return (res);
}
static int ntfs_fuse_setxattr(const char *path, const char *name,
const char *value, size_t size, int flags)
{
@ -2881,49 +2942,8 @@ static int ntfs_fuse_setxattr(const char *path, const char *name,
ni = ntfs_check_access_xattr(&security,path,attr,TRUE);
if (ni) {
if (ntfs_allowed_as_owner(&security,ni)) {
switch (attr) {
case XATTR_NTFS_ACL :
res = ntfs_set_ntfs_acl(&security, ni,
value, size, flags);
break;
case XATTR_POSIX_ACC :
case XATTR_POSIX_DEF :
res = ntfs_set_posix_acl(&security, ni,
name, value, size, flags);
break;
case XATTR_NTFS_ATTRIB :
res = ntfs_set_ntfs_attrib(ni,
value, size, flags);
break;
case XATTR_NTFS_EFSINFO :
if (ctx->efs_raw)
res = ntfs_set_efs_info(path,
value,size,flags,ni);
else
res = -EPERM;
break;
case XATTR_NTFS_REPARSE_DATA :
res = ntfs_set_ntfs_reparse_data(path,
value,size,flags,ni);
break;
case XATTR_NTFS_DOS_NAME:
/* warning : this closes the inode */
res = ntfs_set_ntfs_dos_name(path,
value,size,flags,ni);
break;
case XATTR_NTFS_TIMES:
res = ntfs_inode_set_times(path,
value,size,flags,ni);
break;
default :
/*
* make sure applications do not see
* Posix ACL not consistent with mode
*/
errno = EOPNOTSUPP;
res = -errno;
break;
}
res = ntfs_system_setxattr(&security,
path, attr, ni, value, size, flags);
if (res)
res = -errno;
} else
@ -2953,45 +2973,10 @@ static int ntfs_fuse_setxattr(const char *path, const char *name,
* if defined, only owner is allowed
*/
if (!ntfs_fuse_fill_security_context(&security)
|| ntfs_allowed_as_owner(&security, ni)) {
switch (attr) {
case XATTR_NTFS_ACL :
res = ntfs_set_ntfs_acl(&security, ni,
value, size, flags);
break;
case XATTR_NTFS_ATTRIB :
res = ntfs_set_ntfs_attrib(ni,
value, size, flags);
break;
case XATTR_NTFS_EFSINFO :
if (ctx->efs_raw)
res = ntfs_set_efs_info(path,
value,size,flags,ni);
else
res = -EPERM;
break;
case XATTR_NTFS_REPARSE_DATA :
res = ntfs_set_ntfs_reparse_data(path,
value,size,flags,ni);
break;
case XATTR_NTFS_DOS_NAME:
/* warning : this closes the inode */
res = ntfs_set_ntfs_dos_name(path,
value,size,flags,ni);
break;
case XATTR_NTFS_TIMES:
res = ntfs_inode_set_times(path,
value,size,flags,ni);
break;
default :
/*
* make sure applications do not see
* Posix ACL not consistent with mode
*/
errno = EOPNOTSUPP;
res = -errno;
break;
}
|| ntfs_allowed_as_owner(&security,ni)) {
res = ntfs_system_setxattr(&security,
path, attr, ni, value,
size, flags);
if (res)
res = -errno;
} else
@ -3111,6 +3096,89 @@ exit:
return res;
}
static __inline__ int ntfs_system_removexattr(const char *path,
int attr)
{
int res;
ntfs_inode *dir_ni;
ntfs_inode *ni;
char *dirpath;
char *p;
struct SECURITY_CONTEXT security;
res = 0;
switch (attr) {
/*
* Removal of NTFS ACL, ATTRIB, EFSINFO or TIMES
* is never allowed
*/
case XATTR_NTFS_ACL :
case XATTR_NTFS_ATTRIB :
case XATTR_NTFS_EFSINFO :
case XATTR_NTFS_TIMES :
res = -EPERM;
break;
#if POSIXACLS
case XATTR_POSIX_ACC :
case XATTR_POSIX_DEF :
ni = ntfs_check_access_xattr(&security, path, attr, TRUE);
if (ni) {
if (!ntfs_allowed_as_owner(&security,ni)
|| ntfs_remove_posix_acl(&security,ni,
(attr == XATTR_POSIX_ACC ?
nf_ns_xattr_posix_access :
nf_ns_xattr_posix_default)))
res = -errno;
if (ntfs_inode_close(ni))
set_fuse_error(&res);
} else
res = -errno;
break;
#endif
case XATTR_NTFS_REPARSE_DATA :
ni = ntfs_check_access_xattr(&security, path, attr, TRUE);
if (ni) {
if (!ntfs_allowed_as_owner(&security,ni)
|| ntfs_remove_ntfs_reparse_data(ni))
res = -errno;
if (ntfs_inode_close(ni))
set_fuse_error(&res);
} else
res = -errno;
break;
case XATTR_NTFS_DOS_NAME:
res = 0;
ni = ntfs_check_access_xattr(&security,path,attr,TRUE);
if (ni) {
dirpath = strdup(path);
if (dirpath) {
p = strrchr(dirpath,'/'); /* always present */
*p = 0;
dir_ni = ntfs_pathname_to_inode(ni->vol,
NULL, dirpath);
if (!dir_ni
|| ntfs_remove_ntfs_dos_name(ni, dir_ni))
res = -errno;
free(dirpath);
} else
res = -ENOMEM;
if (res < 0)
errno = -res;
} else
res = -errno;
break;
default :
/*
* make sure applications do not see
* Posix ACL not consistent with mode
*/
errno = EOPNOTSUPP;
res = -errno;
break;
}
return (res);
}
static int ntfs_fuse_removexattr(const char *path, const char *name)
{
ntfs_inode *ni;
@ -3118,7 +3186,9 @@ static int ntfs_fuse_removexattr(const char *path, const char *name)
int res = 0, lename_len;
int attr;
int namespace;
#if POSIXACLS
struct SECURITY_CONTEXT security;
#endif
attr = mapped_xattr_system(name);
if (attr != XATTR_UNMAPPED) {
@ -3130,56 +3200,7 @@ static int ntfs_fuse_removexattr(const char *path, const char *name)
* point of view, ACLs are not xattr)
* Note : updating an ACL does not set ctime
*/
res = 0;
switch (attr) {
/*
* Removal of NTFS ACL, ATTRIB, EFSINFO or TIMES
* is never allowed
*/
case XATTR_NTFS_ACL :
case XATTR_NTFS_ATTRIB :
case XATTR_NTFS_EFSINFO :
case XATTR_NTFS_TIMES :
res = -EPERM;
break;
case XATTR_POSIX_ACC :
case XATTR_POSIX_DEF :
ni = ntfs_check_access_xattr(&security,path,attr,TRUE);
if (ni) {
if (!ntfs_allowed_as_owner(&security, ni)
|| ntfs_remove_posix_acl(&security, ni,
name))
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,attr,TRUE);
if (ni) {
if (!ntfs_allowed_as_owner(&security, ni)
|| ntfs_remove_ntfs_reparse_data(path,ni))
res = -errno;
if (ntfs_inode_close(ni))
set_fuse_error(&res);
} else
res = -errno;
break;
case XATTR_NTFS_DOS_NAME:
ni = ntfs_check_access_xattr(&security,path,attr,TRUE);
if (ni) {
if (ntfs_remove_ntfs_dos_name(path,ni))
res = -errno;
} else
res = -errno;
break;
default :
errno = EOPNOTSUPP;
res = -errno;
break;
break;
}
res = ntfs_system_removexattr(path, attr);
#else
/*
* Only hijack NTFS ACL and ATTRIB removal if POSIX ACLS
@ -3189,50 +3210,7 @@ static int ntfs_fuse_removexattr(const char *path, const char *name)
if (ntfs_fuse_is_named_data_stream(path))
res = -EINVAL; /* n/a for named data streams. */
else {
switch (attr) {
/*
* Removal of NTFS ACL, ATTRIB, EFSINFO or TIMES
* is never allowed
*/
case XATTR_NTFS_ACL :
case XATTR_NTFS_ATTRIB :
case XATTR_NTFS_EFSINFO :
case XATTR_NTFS_TIMES :
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, ni))
|| ntfs_remove_ntfs_reparse_data(path,ni))
res = -errno;
if (ntfs_inode_close(ni))
set_fuse_error(&res);
} else
res = -errno;
break;
case XATTR_NTFS_DOS_NAME:
ni = ntfs_check_access_xattr(&security,path,attr,TRUE);
if (ni) {
if (ntfs_remove_ntfs_dos_name(path,ni))
res = -errno;
} else
res = -errno;
break;
default :
/*
* make sure applications do not see
* Posix ACL not consistent with mode
*/
errno = EOPNOTSUPP;
res = -errno;
break;
}
res = ntfs_system_removexattr(path, attr);
}
#endif
return (res);