Developped getting and setting DOS names (short 8+3 names)

N2009_11_14_FIXES
jpandre 2009-07-01 19:45:59 +00:00
parent 3ddbce3ea6
commit 9a4672ca65
6 changed files with 581 additions and 69 deletions

View File

@ -104,5 +104,11 @@ typedef int (*ntfs_filldir_t)(void *dirent, const ntfschar *name,
extern int ntfs_readdir(ntfs_inode *dir_ni, s64 *pos,
void *dirent, ntfs_filldir_t filldir);
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);
#endif /* defined _NTFS_DIR_H */

View File

@ -65,6 +65,11 @@ extern ntfschar *ntfs_str2ucs(const char *s, int *len);
extern void ntfs_ucsfree(ntfschar *ucs);
extern BOOL ntfs_forbidden_chars(const ntfschar *name, int len);
extern BOOL ntfs_collapsible_chars(ntfs_volume *vol,
const ntfschar *shortname, int shortlen,
const ntfschar *longname, int longlen);
extern int ntfs_set_char_encoding(const char *locale);
#endif /* defined _NTFS_UNISTR_H */

View File

@ -5,7 +5,7 @@
* Copyright (c) 2004-2005 Richard Russon
* Copyright (c) 2004-2008 Szabolcs Szakacsits
* Copyright (c) 2005-2007 Yura Pakhuchiy
* Copyright (c) 2008 Jean-Pierre Andre
* Copyright (c) 2008-2009 Jean-Pierre Andre
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@ -59,6 +59,10 @@
#include "security.h"
#include "reparse.h"
#ifdef HAVE_SETXATTR
#include <sys/xattr.h>
#endif
/*
* The little endian Unicode strings "$I30", "$SII", "$SDH", "$O"
* and "$Q" as global constants.
@ -97,6 +101,8 @@ static int inode_cache_compare(const struct CACHED_GENERIC *cached,
*
* A partial path is compared in order to invalidate all paths
* related to a renamed directory
* inode numbers are also checked, as deleting a long name may
* imply deleting a short name and conversely
*/
static int inode_cache_inv_compare(const struct CACHED_GENERIC *cached,
@ -106,10 +112,12 @@ static int inode_cache_inv_compare(const struct CACHED_GENERIC *cached,
len = strlen(wanted->variable);
return (!cached->variable
|| strncmp((const char*)cached->variable,
|| ((((const struct CACHED_INODE*)wanted)->inum
!= MREF(((const struct CACHED_INODE*)cached)->inum))
&& (strncmp((const char*)cached->variable,
(const char*)wanted->variable,len)
|| ((((const char*)cached->variable)[len] != '\0')
&& (((const char*)cached->variable)[len] != '/')));
&& (((const char*)cached->variable)[len] != '/')))));
}
#endif
@ -1516,6 +1524,7 @@ int ntfs_delete(ntfs_volume *vol, const char *pathname,
#if CACHE_INODE_SIZE
struct CACHED_INODE item;
const char *p;
u64 inum = (u64)-1;
int count;
#endif
@ -1631,6 +1640,9 @@ search:
* case there are no reference to this inode left, so we should free all
* non-resident attributes and mark all MFT record as not in use.
*/
#if CACHE_INODE_SIZE
inum = ni->mft_no;
#endif
if (ni->mrec->link_count) {
ntfs_inode_update_times(ni, NTFS_UPDATE_CTIME);
goto ok;
@ -1685,19 +1697,22 @@ out:
if (ntfs_inode_close(ni) && !err)
err = errno;
#if CACHE_INODE_SIZE
if (pathname) {
/* invalide cache entry, even if there was an error */
/* Remove leading /'s. */
p = pathname;
while (*p == PATH_SEP)
p++;
if (p[0] && (p[strlen(p)-1] == PATH_SEP))
ntfs_log_error("Unnormalized path %s\n",pathname);
item.pathname = p;
count = ntfs_invalidate_cache(vol->xinode_cache, GENERIC(&item),
inode_cache_inv_compare);
if (!count)
ntfs_log_error("Could not delete inode cache entry for %s\n",
/* Remove leading /'s. */
p = pathname;
while (*p == PATH_SEP)
p++;
if (p[0] && (p[strlen(p)-1] == PATH_SEP))
ntfs_log_error("Unnormalized path %s\n",pathname);
item.pathname = p;
item.inum = inum;
count = ntfs_invalidate_cache(vol->xinode_cache, GENERIC(&item),
inode_cache_inv_compare);
if (!count)
ntfs_log_error("Could not delete inode cache entry for %s\n",
pathname);
}
#endif
if (err) {
errno = err;
@ -1726,7 +1741,8 @@ err_out:
*
* Return 0 on success or -1 on error with errno set to the error code.
*/
int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, u8 name_len)
static int ntfs_link_i(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name,
u8 name_len, FILE_NAME_TYPE_FLAGS nametype)
{
FILE_NAME_ATTR *fn = NULL;
int fn_len, err;
@ -1756,7 +1772,7 @@ int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, u8 name_len)
fn->parent_directory = MK_LE_MREF(dir_ni->mft_no,
le16_to_cpu(dir_ni->mrec->sequence_number));
fn->file_name_length = name_len;
fn->file_name_type = FILE_NAME_POSIX;
fn->file_name_type = nametype;
fn->file_attributes = ni->flags;
if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
fn->file_attributes |= FILE_ATTR_I30_INDEX_PRESENT;
@ -1799,3 +1815,284 @@ err_out:
return -1;
}
int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, u8 name_len)
{
return (ntfs_link_i(ni, dir_ni, name, name_len, FILE_NAME_POSIX));
}
#ifdef HAVE_SETXATTR
#define MAX_DOS_NAME_LENGTH 12
/*
* Get a DOS 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_dos_name(ntfs_inode *ni, u64 dnum, ntfschar *dosname)
{
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;
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_DOS)
&& (MREF_LE(fn->parent_directory) == dnum)) {
/*
* Found a DOS or WIN32+DOS name for the entry
* copy name, after truncation for safety
*/
outsize = fn->file_name_length;
/* TODO : reject if name is too long ? */
if (outsize > MAX_DOS_NAME_LENGTH)
outsize = MAX_DOS_NAME_LENGTH;
memcpy(dosname,fn->file_name,outsize*sizeof(ntfschar));
ntfs_name_upcase(dosname, outsize,
ni->vol->upcase, ni->vol->upcase_len);
}
}
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 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,
* encode it into the buffer if there is
* enough space
*/
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)
outsize = -errno;
ntfs_inode_close(dir_ni);
} else
outsize = -errno;
return (outsize);
}
/*
* Set a DOS name to a file and adjust name spaces
*
* This done in three (or four) steps :
*
* - insert the short name (as a DOS name or Posix name if collapsible)
* - delete the old long name or existing short name
* - insert the new long name (as a Win32 or DOS+Win32 name)
* - delete the short name if collapsible
*
* Deleting the old long name will not delete the file
* provided the old name was in the Posix name space,
* because the alternate name has been set before.
*
* Likewise, deleting the existing short name implies
* deleting the long name, but not the file itself
* because the alternate name has been set before.
*
* Note : currently the short name and the long name must be different
*/
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)
{
unsigned int linkcount;
ntfs_volume *vol;
BOOL collapsible;
BOOL deleted;
u64 dnum;
u64 fnum;
int res;
res = -1;
vol = ni->vol;
dnum = dir_ni->mft_no;
fnum = ni->mft_no;
/* save initial link count */
linkcount = le16_to_cpu(ni->mrec->link_count);
/* check whether the same name may be used as DOS and WIN32 */
collapsible = ntfs_collapsible_chars(ni->vol, shortname, shortlen,
longname, longlen);
if (!ntfs_link_i(ni, dir_ni, shortname, shortlen,
(collapsible ? FILE_NAME_POSIX : 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 */
&& !ntfs_delete(vol, fullpath, ni, dir_ni, deletename, deletelen)) {
/* delete closes the inodes, so have to open again */
dir_ni = ntfs_inode_open(vol, dnum);
deleted = FALSE;
if (dir_ni) {
ni = ntfs_inode_open(vol, fnum);
if (ni) {
if (collapsible) {
if (!ntfs_link_i(ni, dir_ni, longname,
longlen, FILE_NAME_WIN32_AND_DOS)) {
if (!ntfs_delete(vol, (const char*)NULL, ni,
dir_ni, shortname, shortlen))
res = 0;
deleted = TRUE;
}
} else
if (!ntfs_link_i(ni, dir_ni, longname,
longlen, FILE_NAME_WIN32))
res = 0;
if (!deleted)
ntfs_inode_close(ni);
}
if (!deleted)
ntfs_inode_close(dir_ni);
}
}
return (res);
}
/*
* Set the ntfs DOS name into an extended attribute
* The DOS name will be added as another file name attribute
* using the existing file name information from the original
* name or overwriting the DOS Name if one exists.
*/
int ntfs_set_ntfs_dos_name(const char *path, const char *value, size_t size,
int flags, ntfs_inode *ni)
{
int res = 0;
int longlen = 0;
int shortlen = 0;
char newname[MAX_DOS_NAME_LENGTH + 1];
ntfschar oldname[MAX_DOS_NAME_LENGTH];
int oldsize;
ntfs_volume *vol;
u64 fnum;
u64 dnum;
ntfschar *shortname = NULL;
ntfschar *longname = NULL;
ntfs_inode *dir_ni = NULL;
char *dirname = (char*)NULL;
const char *rdirname;
char *p;
vol = ni->vol;
fnum = ni->mft_no;
/* convert the string to the NTFS wide chars */
if (size > MAX_DOS_NAME_LENGTH)
size = MAX_DOS_NAME_LENGTH;
strncpy(newname, value, size);
newname[size] = 0;
shortlen = ntfs_mbstoucs(newname, &shortname);
/* make sure the short name has valid chars */
if ((shortlen < 0) || ntfs_forbidden_chars(shortname,shortlen)) {
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);
dnum = dir_ni->mft_no;
}
}
}
if (dir_ni) {
oldsize = get_dos_name(ni, dnum, oldname);
if (oldsize >= 0) {
if (oldsize > 0) {
if (flags & XATTR_CREATE) {
res = -1;
errno = EEXIST;
} else
res = set_dos_name(ni, dir_ni, path,
shortname, shortlen,
longname, longlen,
oldname, oldsize);
} else {
if (flags & XATTR_REPLACE) {
res = -1;
errno = ENODATA;
} else
res = set_dos_name(ni, dir_ni, path,
shortname, shortlen,
longname, longlen,
longname, longlen);
}
} else
res = -1;
} else {
res = -1;
errno = EINVAL;
}
free(dirname);
free(longname);
free(shortname);
return (res ? -1 : 0);
}
#endif

View File

@ -2173,6 +2173,110 @@ int ntfs_get_posix_acl(struct SECURITY_CONTEXT *scx, const char *path,
return (outsize ? (int)outsize : -errno);
}
#else /* POSIXACLS */
/*
* Get permissions to access a file
* Takes into account the relation of user to file (owner, group, ...)
* Do no use as mode of the file
*
* returns -1 if there is a problem
*
* This is only used for checking creation of DOS file names
*/
static int ntfs_get_perm(struct SECURITY_CONTEXT *scx,
const char *path, ntfs_inode *ni,
mode_t request __attribute__((unused)))
{
const SECURITY_DESCRIPTOR_RELATIVE *phead;
const struct CACHED_PERMISSIONS *cached;
char *securattr;
const SID *usid; /* owner of file/directory */
const SID *gsid; /* group of file/directory */
BOOL isdir;
uid_t uid;
gid_t gid;
int perm;
if (!scx->mapping[MAPUSERS] || !scx->uid)
perm = 07777;
else {
/* check whether available in cache */
cached = fetch_cache(scx,ni);
if (cached) {
perm = cached->mode;
uid = cached->uid;
gid = cached->gid;
} else {
perm = 0; /* default to no permission */
isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
!= const_cpu_to_le16(0);
securattr = getsecurityattr(scx->vol, path, ni);
if (securattr) {
phead = (const SECURITY_DESCRIPTOR_RELATIVE*)
securattr;
gsid = (const SID*)&
securattr[le32_to_cpu(phead->group)];
gid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid);
#if OWNERFROMACL
usid = ntfs_acl_owner(securattr);
perm = ntfs_build_permissions(securattr,
usid, gsid, isdir);
uid = ntfs_find_user(scx->mapping[MAPUSERS],usid);
#else
usid = (const SID*)&
securattr[le32_to_cpu(phead->owner)];
perm = ntfs_build_permissions(securattr,
usid, gsid, isdir);
if (!perm && ntfs_same_sid(usid, adminsid)) {
uid = find_tenant(scx, securattr);
if (uid)
perm = 0700;
} else
uid = ntfs_find_user(scx->mapping[MAPUSERS],usid);
#endif
/*
* Create a security id if there were none
* and upgrade option is selected
*/
if (!test_nino_flag(ni, v3_Extensions)
&& (perm >= 0)
&& (scx->vol->secure_flags
& (1 << SECURITY_ADDSECURIDS))) {
upgrade_secur_desc(scx->vol, path,
securattr, ni);
/*
* fetch owner and group for cacheing
* if there is a securid
*/
}
if (test_nino_flag(ni, v3_Extensions)
&& (perm >= 0)) {
enter_cache(scx, ni, uid,
gid, perm);
}
free(securattr);
} else {
perm = -1;
uid = gid = 0;
}
}
if (perm >= 0) {
if (uid == scx->uid)
perm &= 07700;
else
if ((gid == scx->gid)
|| groupmember(scx, scx->uid, gid))
perm &= 07070;
else
perm &= 07007;
}
}
return (perm);
}
#endif /* POSIXACLS */
/*
@ -3154,8 +3258,6 @@ int ntfs_sd_add_everyone(ntfs_inode *ni)
return ret;
}
#if POSIXACLS
/*
* Check whether user can access a file in a specific way
*
@ -3164,6 +3266,8 @@ int ntfs_sd_add_everyone(ntfs_inode *ni)
* 2 if sticky and accesstype is S_IWRITE + S_IEXEC + S_ISVTX
* 0 and sets errno if there is a problem or if access
* is not allowed
*
* This is used for Posix ACL and checking creation of DOS file names
*/
int ntfs_allowed_access(struct SECURITY_CONTEXT *scx,
@ -3175,7 +3279,10 @@ int ntfs_allowed_access(struct SECURITY_CONTEXT *scx,
int allow;
struct stat stbuf;
#if POSIXACLS
/* shortcut, use only if Posix ACLs in use */
if (scx->vol->secure_flags & (1 << SECURITY_DEFAULT)) return (1);
#endif
/*
* Always allow for root unless execution is requested.
* (was checked by fuse until kernel 2.6.29)
@ -3244,6 +3351,8 @@ int ntfs_allowed_access(struct SECURITY_CONTEXT *scx,
* no user mapping defined
*
* Sets errno if there is a problem or if not allowed
*
* This is used for Posix ACL and checking creation of DOS file names
*/
BOOL ntfs_allowed_dir_access(struct SECURITY_CONTEXT *scx,
@ -3256,7 +3365,10 @@ BOOL ntfs_allowed_dir_access(struct SECURITY_CONTEXT *scx,
ntfs_inode *dir_ni;
struct stat stbuf;
#if POSIXACLS
/* shortcut, use only if Posix ACLs in use */
if (scx->vol->secure_flags & (1 << SECURITY_DEFAULT)) return (TRUE);
#endif
allow = 0;
dirpath = strdup(path);
if (dirpath) {
@ -3290,8 +3402,6 @@ BOOL ntfs_allowed_dir_access(struct SECURITY_CONTEXT *scx,
return (allow); /* errno is set if not allowed */
}
#endif
/*
* Define a new owner/group to a file
*

View File

@ -1076,6 +1076,68 @@ void ntfs_ucsfree(ntfschar *ucs)
free(ucs);
}
/*
* Check whether a name contains no chars forbidden
* for DOS or Win32 use
*
* If there is a bad char, errno is set to EINVAL
*/
BOOL ntfs_forbidden_chars(const ntfschar *name, int len)
{
BOOL forbidden = FALSE;
int ch;
int i;
u32 mainset = (1L << ('\"' - 0x20))
| (1L << ('*' - 0x20))
| (1L << ('/' - 0x20))
| (1L << (':' - 0x20))
| (1L << ('<' - 0x20))
| (1L << ('>' - 0x20))
| (1L << ('?' - 0x20));
for (i=0; i<len; i++) {
ch = le16_to_cpu(name[i]);
if ((ch <= 0x20)
|| ((ch < 0x40)
&& ((1L << (ch - 0x20)) & mainset))
|| (ch == '\\')
|| (ch == '|'))
forbidden = TRUE;
}
if (forbidden)
errno = EINVAL;
return (forbidden);
}
/*
* Check whether the same name can be used as a DOS and
* a Win32 name
*
* The names must be the same, or the short name the uppercase
* variant of the long name
*/
BOOL ntfs_collapsible_chars(ntfs_volume *vol,
const ntfschar *shortname, int shortlen,
const ntfschar *longname, int longlen)
{
BOOL collapsible;
unsigned int ch;
int i;
collapsible = shortlen == longlen;
if (collapsible)
for (i=0; i<shortlen; i++) {
ch = le16_to_cpu(longname[i]);
if ((ch >= vol->upcase_len)
|| ((shortname[i] != longname[i])
&& (shortname[i] != vol->upcase[ch])))
collapsible = FALSE;
}
return (collapsible);
}
/*
* Define the character encoding to be used.
* Use UTF-8 unless specified otherwise.

View File

@ -1995,17 +1995,33 @@ enum { XATTR_UNMAPPED,
XATTR_NTFS_ATTRIB,
XATTR_NTFS_EFSINFO,
XATTR_NTFS_REPARSE_DATA,
XATTR_NTFS_DOS_NAME,
XATTR_POSIX_ACC,
XATTR_POSIX_DEF } ;
static const char nf_ns_xattr_ntfs[] = "system.ntfs_acl";
static const char nf_ns_xattr_ntfs_acl[] = "system.ntfs_acl";
static const char nf_ns_xattr_attrib[] = "system.ntfs_attrib";
static const char nf_ns_xattr_efsinfo[] = "user.ntfs.efsinfo";
static const char nf_ns_xattr_reparse[] = "system.ntfs_reparse_data";
static const char nf_ns_xattr_dos_name[] = "system.ntfs_dos_name";
static const char nf_ns_xattr_posix_access[] = "system.posix_acl_access";
static const char nf_ns_xattr_posix_default[] = "system.posix_acl_default";
#if POSIXACLS
struct XATTRNAME {
int xattr;
const char *name;
} ;
static struct XATTRNAME nf_ns_xattr_names[] = {
{ XATTR_NTFS_ACL, nf_ns_xattr_ntfs_acl },
{ XATTR_NTFS_ATTRIB, nf_ns_xattr_attrib },
{ XATTR_NTFS_EFSINFO, nf_ns_xattr_efsinfo },
{ XATTR_NTFS_REPARSE_DATA, nf_ns_xattr_reparse },
{ XATTR_NTFS_DOS_NAME, nf_ns_xattr_dos_name },
{ XATTR_POSIX_ACC, nf_ns_xattr_posix_access },
{ XATTR_POSIX_DEF, nf_ns_xattr_posix_default },
{ XATTR_UNMAPPED, (char*)NULL } /* terminator */
};
/*
* Check whether access to internal data as an extended
@ -2016,10 +2032,11 @@ static const char nf_ns_xattr_posix_default[] = "system.posix_acl_default";
*/
static ntfs_inode *ntfs_check_access_xattr(struct SECURITY_CONTEXT *security,
const char *path, int attr)
const char *path, int attr, BOOL setting)
{
ntfs_inode *ni;
BOOL foracl;
mode_t acctype;
ni = (ntfs_inode*)NULL;
if (ntfs_fuse_is_named_data_stream(path))
@ -2038,8 +2055,15 @@ static ntfs_inode *ntfs_check_access_xattr(struct SECURITY_CONTEXT *security,
&& foracl) {
errno = EOPNOTSUPP;
} else {
/* parent directory must be executable */
if (ntfs_allowed_dir_access(security,path,S_IEXEC)) {
/*
* parent directory must be executable, and
* for setting a DOS name it must be writeable
*/
if (setting && (attr == XATTR_NTFS_DOS_NAME))
acctype = S_IEXEC | S_IWRITE;
else
acctype = S_IEXEC;
if (ntfs_allowed_dir_access(security,path,acctype)) {
ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
}
}
@ -2047,8 +2071,6 @@ static ntfs_inode *ntfs_check_access_xattr(struct SECURITY_CONTEXT *security,
return (ni);
}
#endif
/*
* Determine whether an extended attribute is in the system
* name space and mapped to internal data
@ -2056,31 +2078,12 @@ static ntfs_inode *ntfs_check_access_xattr(struct SECURITY_CONTEXT *security,
static int mapped_xattr_system(const char *name)
{
int num;
struct XATTRNAME *p;
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 (!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
if (ctx->efs_raw
&& !strcmp(name,
nf_ns_xattr_efsinfo))
num = XATTR_NTFS_EFSINFO;
else
num = XATTR_UNMAPPED;
return (num);
p = nf_ns_xattr_names;
while (p->name && strcmp(p->name,name))
p++;
return (p->xattr);
}
/*
@ -2362,11 +2365,11 @@ static int ntfs_fuse_getxattr(const char *path, const char *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)
* hijack internal data and ACL retrieval, whatever
* mode was selected for xattr (from the user's
* point of view, ACLs are not xattr)
*/
ni = ntfs_check_access_xattr(&security,path,attr);
ni = ntfs_check_access_xattr(&security,path,attr,FALSE);
if (ni) {
if (ntfs_allowed_access(&security,path,ni,S_IREAD)) {
/*
@ -2397,6 +2400,10 @@ static int ntfs_fuse_getxattr(const char *path, const char *name,
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;
default : /* not possible */
break;
}
@ -2443,6 +2450,10 @@ static int ntfs_fuse_getxattr(const char *path, const char *name,
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;
default :
/*
* make sure applications do not see
@ -2537,12 +2548,12 @@ static int ntfs_fuse_setxattr(const char *path, const char *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)
* hijack internal data and ACL setting, 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
*/
ni = ntfs_check_access_xattr(&security,path,attr);
ni = ntfs_check_access_xattr(&security,path,attr,TRUE);
if (ni) {
if (ntfs_allowed_as_owner(&security,path,ni)) {
switch (attr) {
@ -2567,6 +2578,11 @@ static int ntfs_fuse_setxattr(const char *path, const char *name,
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;
default : /* not possible */
break;
}
@ -2574,7 +2590,8 @@ static int ntfs_fuse_setxattr(const char *path, const char *name,
res = -errno;
} else
res = -errno;
if (ntfs_inode_close(ni))
if ((attr != XATTR_NTFS_DOS_NAME)
&& ntfs_inode_close(ni))
set_fuse_error(&res);
} else
res = -errno;
@ -2587,7 +2604,11 @@ static int ntfs_fuse_setxattr(const char *path, const char *name,
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);
/* creation of a new name is not controlled by fuse */
if (attr == XATTR_NTFS_DOS_NAME)
ni = ntfs_check_access_xattr(&security,path,attr,TRUE);
else
ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
if (ni) {
/*
* user mapping is not mandatory
@ -2612,6 +2633,11 @@ static int ntfs_fuse_setxattr(const char *path, const char *name,
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;
default :
/*
* make sure applications do not see
@ -2625,7 +2651,8 @@ static int ntfs_fuse_setxattr(const char *path, const char *name,
res = -errno;
} else
res = -errno;
if (ntfs_inode_close(ni))
if ((attr != XATTR_NTFS_DOS_NAME)
&& ntfs_inode_close(ni))
set_fuse_error(&res);
} else
res = -errno;
@ -2752,9 +2779,9 @@ static int ntfs_fuse_removexattr(const char *path, const char *name)
#if POSIXACLS
/*
* hijack Posix/NTFS ACL retrieval, whatever mode
* was selected for xattr (from the user's point
* of view, ACLs are not xattr)
* hijack internal data and ACL removal, 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
*/
res = 0;
@ -2769,7 +2796,7 @@ static int ntfs_fuse_removexattr(const char *path, const char *name)
break;
case XATTR_POSIX_ACC :
case XATTR_POSIX_DEF :
ni = ntfs_check_access_xattr(&security,path,attr);
ni = ntfs_check_access_xattr(&security,path,attr,TRUE);
if (ni) {
if (!ntfs_allowed_as_owner(&security,path,ni)
|| ntfs_remove_posix_acl(&security,path,
@ -2781,7 +2808,7 @@ static int ntfs_fuse_removexattr(const char *path, const char *name)
res = -errno;
break;
case XATTR_NTFS_REPARSE_DATA :
ni = ntfs_check_access_xattr(&security,path,attr);
ni = ntfs_check_access_xattr(&security,path,attr,TRUE);
if (ni) {
if (!ntfs_allowed_as_owner(&security,path,ni)
|| ntfs_remove_ntfs_reparse_data(path,ni))
@ -2791,7 +2818,11 @@ static int ntfs_fuse_removexattr(const char *path, const char *name)
} else
res = -errno;
break;
default : /* not possible */
case XATTR_NTFS_DOS_NAME:
default :
errno = EOPNOTSUPP;
res = -errno;
break;
break;
}
#else
@ -2828,7 +2859,8 @@ static int ntfs_fuse_removexattr(const char *path, const char *name)
} else
res = -errno;
break;
default : /* not possible */
case XATTR_NTFS_DOS_NAME:
default :
/*
* make sure applications do not see
* Posix ACL not consistent with mode