Enabled renaming of system extended attributes

This commit is contained in:
Jean-Pierre André 2010-10-26 08:59:52 +02:00
parent f43e972342
commit 351aec3f7a
14 changed files with 571 additions and 142 deletions

View File

@ -113,6 +113,13 @@ AC_ARG_ENABLE(
[enable_posix_acls="no"]
)
AC_ARG_ENABLE(
[xattr-mappings],
[AS_HELP_STRING([--enable-xattr-mappings],[enable system extended attributes mappings])],
,
[enable_xattr_mappings="no"]
)
AC_ARG_ENABLE(
[device-default-io-ops],
[AS_HELP_STRING([--disable-device-default-io-ops],[install default IO ops])],
@ -349,6 +356,7 @@ test "${enable_device_default_io_ops}" = "no" && AC_DEFINE(
test "${enable_mtab}" = "no" && AC_DEFINE([IGNORE_MTAB], [1], [Don't update /etc/mtab])
test "${enable_posix_acls}" != "no" && AC_DEFINE([POSIXACLS], [1], [POSIX ACL support])
test "${enable_xattr_mappings}" != "no" && AC_DEFINE([XATTR_MAPPINGS], [1], [system extended attributes mappings])
test "${enable_really_static}" = "yes" && enable_library="no"
test "${enable_library}" = "no" && enable_ldconfig="no"

View File

@ -4,6 +4,7 @@
* Copyright (c) 2000-2004 Anton Altaparmakov
* Copyright (c) 2004-2005 Yura Pakhuchiy
* Copyright (c) 2006-2007 Szabolcs Szakacsits
* Copyright (c) 2010 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
@ -380,6 +381,12 @@ extern int ntfs_attr_exist(ntfs_inode *ni, const ATTR_TYPES type,
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);
extern int ntfs_attr_data_read(ntfs_inode *ni,
ntfschar *stream_name, int stream_name_len,
char *buf, size_t size, off_t offset);
extern int ntfs_attr_data_write(ntfs_inode *ni,
ntfschar *stream_name, int stream_name_len,
char *buf, size_t size, off_t offset);
#endif /* defined _NTFS_ATTRIB_H */

View File

@ -114,5 +114,8 @@ int ntfs_log_redirect(const char *function, const char *file, int line,
#define ntfs_log_leave(FORMAT, ARGS...)do {} while (0)
#endif /* DEBUG */
void ntfs_log_early_error(const char *format, ...)
__attribute__((format(printf, 1, 2)));
#endif /* _LOGGING_H_ */

View File

@ -1,7 +1,7 @@
/*
* param.h - Parameter values for ntfs-3g
*
* Copyright (c) 2009 Jean-Pierre Andre
* Copyright (c) 2009-2010 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
@ -57,6 +57,13 @@ enum {
/* only update the final extent of a runlist when appending data */
#define PARTIAL_RUNLIST_UPDATING 1
/*
* Parameters for user and xattr mappings
*/
#define XATTRMAPPINGFILE ".NTFS-3G/XattrMapping" /* default mapping file */
/*
* Permission checking modes for high level and low level
*

View File

@ -5,6 +5,7 @@
* Copyright (c) 2004-2005 Richard Russon
* Copyright (c) 2005-2006 Yura Pakhuchiy
* Copyright (c) 2005-2009 Szabolcs Szakacsits
* Copyright (c) 2010 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
@ -251,7 +252,9 @@ struct _ntfs_volume {
s64 free_mft_records; /* Same for free mft records (see above) */
BOOL efs_raw; /* volume is mounted for raw access to
efs-encrypted files */
#ifdef XATTR_MAPPINGS
struct XATTRMAPPING *xattr_mapping;
#endif /* XATTR_MAPPINGS */
#if CACHE_INODE_SIZE
struct CACHE_HEADER *xinode_cache;
#endif

View File

@ -43,10 +43,25 @@ enum SYSTEMXATTRS {
XATTR_POSIX_DEF
} ;
enum SYSTEMXATTRS ntfs_xattr_system_type(const char *name);
struct XATTRMAPPING {
struct XATTRMAPPING *next;
enum SYSTEMXATTRS xattr;
char name[1]; /* variable length */
} ;
#ifdef XATTR_MAPPINGS
struct XATTRMAPPING *ntfs_xattr_build_mapping(ntfs_volume *vol,
const char *path);
void ntfs_xattr_free_mapping(struct XATTRMAPPING*);
#endif /* XATTR_MAPPINGS */
enum SYSTEMXATTRS ntfs_xattr_system_type(const char *name,
ntfs_volume *vol);
int ntfs_xattr_listxattr(ntfs_inode *ni, ntfs_attr_search_ctx *actx,
char *list, size_t size, BOOL prefixing);
char *list, size_t size, BOOL prefixing);
int ntfs_xattr_system_getxattr(struct SECURITY_CONTEXT *scx,
enum SYSTEMXATTRS attr,
ntfs_inode *ni, ntfs_inode *dir_ni,

View File

@ -4,7 +4,7 @@
* This module is part of ntfs-3g library, but may also be
* integrated in tools running over Linux or Windows
*
* Copyright (c) 2007-2009 Jean-Pierre Andre
* Copyright (c) 2007-2010 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
@ -3956,33 +3956,6 @@ static SID *encodesid(const char *sidstr)
return (sid);
}
/*
* Early logging before the logs are redirected
*
* (not quite satisfactory : this appears before the ntfs-g banner,
* and with a different pid)
*/
static void log_early_error(const char *format, ...)
__attribute__((format(printf, 1, 2)));
static void log_early_error(const char *format, ...)
{
va_list args;
va_start(args, format);
#ifdef HAVE_SYSLOG_H
openlog("ntfs-3g", LOG_PID, LOG_USER);
ntfs_log_handler_syslog(NULL, NULL, 0,
NTFS_LOG_LEVEL_ERROR, NULL,
format, args);
#else
vfprintf(stderr,format,args);
#endif
va_end(args);
}
/*
* Get a single mapping item from buffer
*
@ -4045,7 +4018,7 @@ static struct MAPLIST *getmappingitem(FILEREADER reader, void *fileid,
if (pu && pg)
*pu = *pg = '\0';
else {
log_early_error("Bad mapping item \"%s\"\n",
ntfs_log_early_error("Bad mapping item \"%s\"\n",
item->maptext);
free(item);
item = (struct MAPLIST*)NULL;
@ -4174,7 +4147,7 @@ struct MAPPING *ntfs_do_user_mapping(struct MAPLIST *firstitem)
if (pwd)
uid = pwd->pw_uid;
else
log_early_error("Invalid user \"%s\"\n",
ntfs_log_early_error("Invalid user \"%s\"\n",
item->uidstr);
}
}
@ -4254,7 +4227,7 @@ struct MAPPING *ntfs_do_group_mapping(struct MAPLIST *firstitem)
if (grp)
gid = grp->gr_gid;
else
log_early_error("Invalid group \"%s\"\n",
ntfs_log_early_error("Invalid group \"%s\"\n",
item->gidstr);
}
}

View File

@ -6542,6 +6542,89 @@ err_exit:
return ret;
}
/*
* Read some data from a data attribute
*
* Returns the amount of data read, negative if there was an error
*/
int ntfs_attr_data_read(ntfs_inode *ni,
ntfschar *stream_name, int stream_name_len,
char *buf, size_t size, off_t offset)
{
ntfs_attr *na = NULL;
int res, total = 0;
na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len);
if (!na) {
res = -errno;
goto exit;
}
if ((size_t)offset < (size_t)na->data_size) {
if (offset + size > (size_t)na->data_size)
size = na->data_size - offset;
while (size) {
res = ntfs_attr_pread(na, offset, size, buf + total);
if ((off_t)res < (off_t)size)
ntfs_log_perror("ntfs_attr_pread partial read "
"(%lld : %lld <> %d)",
(long long)offset,
(long long)size, res);
if (res <= 0) {
res = -errno;
goto exit;
}
size -= res;
offset += res;
total += res;
}
}
res = total;
exit:
if (na)
ntfs_attr_close(na);
return res;
}
/*
* Write some data into a data attribute
*
* Returns the amount of data written, negative if there was an error
*/
int ntfs_attr_data_write(ntfs_inode *ni,
ntfschar *stream_name, int stream_name_len,
char *buf, size_t size, off_t offset)
{
ntfs_attr *na = NULL;
int res, total = 0;
na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len);
if (!na) {
res = -errno;
goto exit;
}
while (size) {
res = ntfs_attr_pwrite(na, offset, size, buf + total);
if (res < (s64)size)
ntfs_log_perror("ntfs_attr_pwrite partial write (%lld: "
"%lld <> %d)", (long long)offset,
(long long)size, res);
if (res <= 0) {
res = -errno;
goto exit;
}
size -= res;
offset += res;
total += res;
}
res = total;
exit:
if (na)
ntfs_attr_close(na);
return res;
}
int ntfs_attr_exist(ntfs_inode *ni, const ATTR_TYPES type, ntfschar *name,

View File

@ -3,6 +3,7 @@
*
* Copyright (c) 2005 Richard Russon
* Copyright (c) 2005-2008 Szabolcs Szakacsits
* Copyright (c) 2010 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
@ -388,6 +389,29 @@ out:
}
#endif
/*
* Early logging before the logs are redirected
*
* (not quite satisfactory : this appears before the ntfs-g banner,
* and with a different pid)
*/
void ntfs_log_early_error(const char *format, ...)
{
va_list args;
va_start(args, format);
#ifdef HAVE_SYSLOG_H
openlog("ntfs-3g", LOG_PID, LOG_USER);
ntfs_log_handler_syslog(NULL, NULL, 0,
NTFS_LOG_LEVEL_ERROR, NULL,
format, args);
#else
vfprintf(stderr,format,args);
#endif
va_end(args);
}
/**
* ntfs_log_handler_fprintf - Basic logging handler
* @function: Function in which the log line occurred

View File

@ -4,7 +4,7 @@
* Copyright (c) 2004 Anton Altaparmakov
* Copyright (c) 2005-2006 Szabolcs Szakacsits
* Copyright (c) 2006 Yura Pakhuchiy
* Copyright (c) 2007-2009 Jean-Pierre Andre
* Copyright (c) 2007-2010 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
@ -404,91 +404,6 @@ le32 ntfs_security_hash(const SECURITY_DESCRIPTOR_RELATIVE *sd, const u32 len)
return cpu_to_le32(hash);
}
/*
* Internal read
* copied and pasted from ntfs_fuse_read() and made independent
* of fuse context
*/
static int ntfs_local_read(ntfs_inode *ni,
ntfschar *stream_name, int stream_name_len,
char *buf, size_t size, off_t offset)
{
ntfs_attr *na = NULL;
int res, total = 0;
na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len);
if (!na) {
res = -errno;
goto exit;
}
if ((size_t)offset < (size_t)na->data_size) {
if (offset + size > (size_t)na->data_size)
size = na->data_size - offset;
while (size) {
res = ntfs_attr_pread(na, offset, size, buf);
if ((off_t)res < (off_t)size)
ntfs_log_perror("ntfs_attr_pread partial read "
"(%lld : %lld <> %d)",
(long long)offset,
(long long)size, res);
if (res <= 0) {
res = -errno;
goto exit;
}
size -= res;
offset += res;
total += res;
}
}
res = total;
exit:
if (na)
ntfs_attr_close(na);
return res;
}
/*
* Internal write
* copied and pasted from ntfs_fuse_write() and made independent
* of fuse context
*/
static int ntfs_local_write(ntfs_inode *ni,
ntfschar *stream_name, int stream_name_len,
char *buf, size_t size, off_t offset)
{
ntfs_attr *na = NULL;
int res, total = 0;
na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len);
if (!na) {
res = -errno;
goto exit;
}
while (size) {
res = ntfs_attr_pwrite(na, offset, size, buf);
if (res < (s64)size)
ntfs_log_perror("ntfs_attr_pwrite partial write (%lld: "
"%lld <> %d)", (long long)offset,
(long long)size, res);
if (res <= 0) {
res = -errno;
goto exit;
}
size -= res;
offset += res;
total += res;
}
res = total;
exit:
if (na)
ntfs_attr_close(na);
return res;
}
/*
* Get the first entry of current index block
* cut and pasted form ntfs_ie_get_first() in index.c
@ -531,7 +446,7 @@ static int entersecurity_stuff(ntfs_volume *vol, off_t offs)
if (stuff) {
memset(stuff, 0, STUFFSZ);
do {
written = ntfs_local_write(vol->secure_ni,
written = ntfs_attr_data_write(vol->secure_ni,
STREAM_SDS, 4, stuff, STUFFSZ, offs);
if (written == STUFFSZ) {
total += STUFFSZ;
@ -589,10 +504,10 @@ static int entersecurity_data(ntfs_volume *vol,
phsds->security_id = keyid;
phsds->offset = cpu_to_le64(offs);
phsds->length = cpu_to_le32(fullsz - gap);
written1 = ntfs_local_write(vol->secure_ni,
written1 = ntfs_attr_data_write(vol->secure_ni,
STREAM_SDS, 4, fullattr, fullsz,
offs - gap);
written2 = ntfs_local_write(vol->secure_ni,
written2 = ntfs_attr_data_write(vol->secure_ni,
STREAM_SDS, 4, fullattr, fullsz,
offs - gap + ALIGN_SDS_BLOCK);
if ((written1 == fullsz)
@ -950,7 +865,7 @@ static le32 setsecurityattr(ntfs_volume *vol,
+ sizeof(SECURITY_DESCRIPTOR_HEADER);
oldattr = (char*)ntfs_malloc(size);
if (oldattr) {
rdsize = ntfs_local_read(
rdsize = ntfs_attr_data_read(
vol->secure_ni,
STREAM_SDS, 4,
oldattr, size, offs);
@ -1772,7 +1687,7 @@ static char *retrievesecurityattr(ntfs_volume *vol, SII_INDEX_KEY id)
securattr = (char*)ntfs_malloc(size);
if (securattr) {
rdsize = ntfs_local_read(
rdsize = ntfs_attr_data_read(
ni, STREAM_SDS, 4,
securattr, size, offs);
if ((rdsize != size)
@ -4097,7 +4012,7 @@ static int basicread(void *fileid, char *buf, size_t size, off_t offs __attribut
static int localread(void *fileid, char *buf, size_t size, off_t offs)
{
return (ntfs_local_read((ntfs_inode*)fileid,
return (ntfs_attr_data_read((ntfs_inode*)fileid,
AT_UNNAMED, 0, buf, size, offs));
}
@ -4919,7 +4834,7 @@ int ntfs_read_sds(struct SECURITY_API *scapi,
got = -1; /* default return */
if (scapi && (scapi->magic == MAGIC_API)) {
if (scapi->security.vol->secure_ni)
got = ntfs_local_read(scapi->security.vol->secure_ni,
got = ntfs_attr_data_read(scapi->security.vol->secure_ni,
STREAM_SDS, 4, buf, size, offset);
else
errno = EOPNOTSUPP;

View File

@ -89,7 +89,7 @@ static const int nf_ns_user_prefix_len = sizeof(nf_ns_user_prefix) - 1;
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_attrib_be[] = "system.ntfs_attrib_be";
static const char nf_ns_xattr_efsinfo[] = "user.ntfs.efsinfo";
static const char nf_ns_xattr_efsinfo[] = "system.ntfs_efsinfo";
static const char nf_ns_xattr_reparse[] = "system.ntfs_reparse_data";
static const char nf_ns_xattr_object_id[] = "system.ntfs_object_id";
static const char nf_ns_xattr_dos_name[] = "system.ntfs_dos_name";
@ -202,21 +202,286 @@ int cpu_to_le_acl(const struct POSIX_ACL *acl, size_t size,
* internal data (original name in system namespace, or renamed)
*/
enum SYSTEMXATTRS ntfs_xattr_system_type(const char *name)
enum SYSTEMXATTRS ntfs_xattr_system_type(const char *name,
ntfs_volume *vol)
{
struct XATTRNAME *p;
enum SYSTEMXATTRS ret;
#ifdef XATTR_MAPPINGS
const struct XATTRMAPPING *q;
#endif /* XATTR_MAPPINGS */
p = nf_ns_xattr_names;
while (p->name && strcmp(p->name,name))
p++;
return (p->xattr);
ret = p->xattr;
#ifdef XATTR_MAPPINGS
if (!p->name && vol && vol->xattr_mapping) {
q = vol->xattr_mapping;
while (q && strcmp(q->name,name))
q = q->next;
if (q)
ret = q->xattr;
}
#else /* XATTR_MAPPINGS */
if (!p->name
&& vol
&& vol->efs_raw
&& !strcmp(nf_ns_alt_xattr_efsinfo,name))
ret = XATTR_NTFS_EFSINFO;
#endif /* XATTR_MAPPINGS */
return (ret);
}
#ifdef XATTR_MAPPINGS
/*
* Basic read from a user mapping file on another volume
*/
static int basicread(void *fileid, char *buf, size_t size, off_t offs __attribute__((unused)))
{
return (read(*(int*)fileid, buf, size));
}
/*
* Read from a user mapping file on current NTFS partition
*/
static int localread(void *fileid, char *buf, size_t size, off_t offs)
{
return (ntfs_attr_data_read((ntfs_inode*)fileid,
AT_UNNAMED, 0, buf, size, offs));
}
/*
* Get a single mapping item from buffer
*
* Always reads a full line, truncating long lines
* Refills buffer when exhausted
* Returns pointer to item, or NULL when there is no more
* Note : errors are logged, but not returned
// TODO partially share with acls.c
*/
static struct XATTRMAPPING *getmappingitem(FILEREADER reader, void *fileid,
off_t *poffs, char *buf, int *psrc, s64 *psize)
{
int src;
int dst;
char *pe;
char *ps;
char *pu;
enum SYSTEMXATTRS xattr;
int gotend;
char maptext[LINESZ];
struct XATTRMAPPING *item;
src = *psrc;
dst = 0;
do {
gotend = 0;
while ((src < *psize)
&& (buf[src] != '\n')) {
/* ignore spaces */
if ((dst < LINESZ)
&& (buf[src] != '\r')
&& (buf[src] != '\t')
&& (buf[src] != ' '))
maptext[dst++] = buf[src];
src++;
}
if (src >= *psize) {
*poffs += *psize;
*psize = reader(fileid, buf, (size_t)BUFSZ, *poffs);
src = 0;
} else {
gotend = 1;
src++;
maptext[dst] = '\0';
dst = 0;
}
} while (*psize && ((maptext[0] == '#') || !gotend));
item = (struct XATTRMAPPING*)NULL;
if (gotend) {
/* decompose into system name and user name */
ps = maptext;
pu = strchr(maptext,':');
if (pu) {
*pu++ = 0;
pe = strchr(pu,':');
if (pe)
*pe = 0;
/* check name validity */
if ((strlen(pu) < 6) || strncmp(pu,"user.",5))
pu = (char*)NULL;
xattr = ntfs_xattr_system_type(ps,
(ntfs_volume*)NULL);
if (xattr == XATTR_UNMAPPED)
pu = (char*)NULL;
}
if (pu) {
item = (struct XATTRMAPPING*)ntfs_malloc(
sizeof(struct XATTRMAPPING)
+ strlen(pu));
if (item) {
item->xattr = xattr;
strcpy(item->name,pu);
item->next = (struct XATTRMAPPING*)NULL;
}
} else {
ntfs_log_early_error("Bad xattr mapping item, aborting\n");
}
}
*psrc = src;
return (item);
}
/*
* Read xattr mapping file and split into their attribute.
* Parameters are kept in a chained list.
* Returns the head of list, if any
* Errors are logged, but not returned
*
* If an absolute path is provided, the mapping file is assumed
* to be located in another mounted file system, and plain read()
* are used to get its contents.
* If a relative path is provided, the mapping file is assumed
* to be located on the current file system, and internal IO
* have to be used since we are still mounting and we have not
* entered the fuse loop yet.
*/
static struct XATTRMAPPING *ntfs_read_xattr_mapping(FILEREADER reader,
void *fileid)
{
char buf[BUFSZ];
struct XATTRMAPPING *item;
struct XATTRMAPPING *current;
struct XATTRMAPPING *firstitem;
struct XATTRMAPPING *lastitem;
BOOL duplicated;
int src;
off_t offs;
s64 size;
firstitem = (struct XATTRMAPPING*)NULL;
lastitem = (struct XATTRMAPPING*)NULL;
offs = 0;
size = reader(fileid, buf, (size_t)BUFSZ, (off_t)0);
if (size > 0) {
src = 0;
do {
item = getmappingitem(reader, fileid, &offs,
buf, &src, &size);
if (item) {
/* check no double mapping */
duplicated = FALSE;
for (current=firstitem; current; current=current->next)
if ((current->xattr == item->xattr)
|| !strcmp(current->name,item->name))
duplicated = TRUE;
if (duplicated) {
free(item);
ntfs_log_early_error("Conflicting xattr mapping ignored\n");
} else {
item->next = (struct XATTRMAPPING*)NULL;
if (lastitem)
lastitem->next = item;
else
firstitem = item;
lastitem = item;
}
}
} while (item);
}
return (firstitem);
}
/*
* Build the extended attribute mappings to user namespace
*
* Note : no error is returned. If we refused mounting when there
* is an error it would be too difficult to fix the offending file
*/
struct XATTRMAPPING *ntfs_xattr_build_mapping(ntfs_volume *vol,
const char *xattrmap_path)
{
struct XATTRMAPPING *firstmapping;
struct XATTRMAPPING *mapping;
BOOL user_efs;
BOOL notfound;
ntfs_inode *ni;
int fd;
firstmapping = (struct XATTRMAPPING*)NULL;
notfound = FALSE;
if (!xattrmap_path)
xattrmap_path = XATTRMAPPINGFILE;
if (xattrmap_path[0] == '/') {
fd = open(xattrmap_path,O_RDONLY);
if (fd > 0) {
firstmapping = ntfs_read_xattr_mapping(basicread, (void*)&fd);
close(fd);
} else
notfound = TRUE;
} else {
ni = ntfs_pathname_to_inode(vol, NULL, xattrmap_path);
if (ni) {
firstmapping = ntfs_read_xattr_mapping(localread, ni);
ntfs_inode_close(ni);
} else
notfound = TRUE;
}
if (notfound && strcmp(xattrmap_path, XATTRMAPPINGFILE)) {
ntfs_log_early_error("Could not open \"%s\"\n",xattrmap_path);
}
if (vol->efs_raw) {
user_efs = TRUE;
for (mapping=firstmapping; mapping; mapping=mapping->next)
if (mapping->xattr == XATTR_NTFS_EFSINFO)
user_efs = FALSE;
} else
user_efs = FALSE;
if (user_efs) {
mapping = (struct XATTRMAPPING*)ntfs_malloc(
sizeof(struct XATTRMAPPING)
+ strlen(nf_ns_alt_xattr_efsinfo));
if (mapping) {
mapping->next = firstmapping;
mapping->xattr = XATTR_NTFS_EFSINFO;
strcpy(mapping->name,nf_ns_alt_xattr_efsinfo);
firstmapping = mapping;
}
}
return (firstmapping);
}
void ntfs_xattr_free_mapping(struct XATTRMAPPING *mapping)
{
struct XATTRMAPPING *p, *q;
p = mapping;
while (p) {
q = p->next;
free(p);
p = q;
}
}
#endif /* XATTR_MAPPINGS */
int ntfs_xattr_listxattr(ntfs_inode *ni, ntfs_attr_search_ctx *actx,
char *list, size_t size, BOOL prefixing)
{
int ret = 0;
char *to = list;
#ifdef XATTR_MAPPINGS
BOOL accepted;
const struct XATTRMAPPING *item;
#endif /* XATTR_MAPPINGS */
/* first list the regular user attributes (ADS) */
while (!ntfs_attr_lookup(AT_DATA, NULL, 0, CASE_SENSITIVE,
@ -268,13 +533,44 @@ int ntfs_xattr_listxattr(ntfs_inode *ni, ntfs_attr_search_ctx *actx,
}
free(tmp_name);
}
#ifdef XATTR_MAPPINGS
/* now append the system attributes mapped to user space */
for (item=ni->vol->xattr_mapping; item; item=item->next) {
switch (item->xattr) {
case XATTR_NTFS_EFSINFO :
accepted = ni->vol->efs_raw
&& (ni->flags & FILE_ATTR_ENCRYPTED);
break;
case XATTR_NTFS_REPARSE_DATA :
accepted = (ni->flags & FILE_ATTR_REPARSE_POINT)
!= const_cpu_to_le32(0);
break;
// TODO : we are supposed to only return xattrs which are set
// this is more complex for OBJECT_ID and DOS_NAME
default : accepted = TRUE;
break;
}
if (accepted) {
ret += strlen(item->name) + 1;
if (size) {
if ((size_t)ret <= size) {
strcpy(to, item->name);
to += strlen(item->name);
*to++ = 0;
} else {
ret = -ERANGE;
goto exit;
}
}
#else /* XATTR_MAPPINGS */
/* List efs info xattr for encrypted files */
if (ni->vol->efs_raw && (ni->flags & FILE_ATTR_ENCRYPTED)) {
ret += sizeof(nf_ns_xattr_efsinfo);
ret += sizeof(nf_ns_alt_xattr_efsinfo);
if ((size_t)ret <= size) {
memcpy(to, nf_ns_xattr_efsinfo,
sizeof(nf_ns_xattr_efsinfo));
to += sizeof(nf_ns_xattr_efsinfo);
memcpy(to, nf_ns_alt_xattr_efsinfo,
sizeof(nf_ns_alt_xattr_efsinfo));
to += sizeof(nf_ns_alt_xattr_efsinfo);
#endif /* XATTR_MAPPINGS */
}
}
exit :

View File

@ -224,6 +224,9 @@ typedef struct {
BOOL mounted;
#ifdef HAVE_SETXATTR /* extended attributes interface required */
BOOL efs_raw;
#ifdef XATTR_MAPPINGS
char *xattrmap_path;
#endif /* XATTR_MAPPINGS */
#endif /* HAVE_SETXATTR */
struct fuse_chan *fc;
BOOL inherit;
@ -2806,7 +2809,7 @@ static void ntfs_fuse_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
int namespace;
struct SECURITY_CONTEXT security;
attr = ntfs_xattr_system_type(name);
attr = ntfs_xattr_system_type(name,ctx->vol);
if (attr != XATTR_UNMAPPED) {
/*
* hijack internal data and ACL retrieval, whatever
@ -2959,7 +2962,7 @@ static void ntfs_fuse_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
int namespace;
struct SECURITY_CONTEXT security;
attr = ntfs_xattr_system_type(name);
attr = ntfs_xattr_system_type(name,ctx->vol);
if (attr != XATTR_UNMAPPED) {
/*
* hijack internal data and ACL setting, whatever
@ -3167,7 +3170,7 @@ static void ntfs_fuse_removexattr(fuse_req_t req, fuse_ino_t ino, const char *na
int namespace;
struct SECURITY_CONTEXT security;
attr = ntfs_xattr_system_type(name);
attr = ntfs_xattr_system_type(name,ctx->vol);
if (attr != XATTR_UNMAPPED) {
switch (attr) {
/*
@ -3783,6 +3786,20 @@ static char *parse_mount_options(const char *orig_opts)
goto err_exit;
}
#ifdef HAVE_SETXATTR /* extended attributes interface required */
#ifdef XATTR_MAPPINGS
} else if (!strcmp(opt, "xattrmapping")) {
if (!val) {
ntfs_log_error("'xattrmapping' option should have "
"a value.\n");
goto err_exit;
}
ctx->xattrmap_path = strdup(val);
if (!ctx->xattrmap_path) {
ntfs_log_error("no more memory to store "
"'xattrmapping' option.\n");
goto err_exit;
}
#endif /* XATTR_MAPPINGS */
} else if (!strcmp(opt, "efs_raw")) {
if (bogus_option_value(val, "efs_raw"))
goto err_exit;
@ -4161,6 +4178,9 @@ int main(int argc, char *argv[])
#endif
const char *permissions_mode = (const char*)NULL;
const char *failed_secure = (const char*)NULL;
#if defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS)
struct XATTRMAPPING *xattr_mapping = (struct XATTRMAPPING*)NULL;
#endif /* defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS) */
struct stat sbuf;
unsigned long existing_mount;
int err, fd;
@ -4342,6 +4362,18 @@ int main(int argc, char *argv[])
if (ctx->usermap_path)
free (ctx->usermap_path);
#if defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS)
xattr_mapping = ntfs_xattr_build_mapping(ctx->vol,
ctx->xattrmap_path);
ctx->vol->xattr_mapping = xattr_mapping;
/*
* Errors are logged, do not refuse mounting, it would be
* too difficult to fix the unmountable mapping file.
*/
if (ctx->xattrmap_path)
free(ctx->xattrmap_path);
#endif /* defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS) */
se = mount_fuse(parsed_options);
if (!se) {
err = NTFS_VOLUME_FUSE_ERROR;
@ -4372,6 +4404,9 @@ err_out:
ntfs_mount_error(opts.device, opts.mnt_point, err);
if (ctx->abs_mnt_point)
free(ctx->abs_mnt_point);
#if defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS)
ntfs_xattr_free_mapping(xattr_mapping);
#endif /* defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS) */
err2:
ntfs_close();
free(ctx);

View File

@ -185,6 +185,9 @@ typedef struct {
BOOL mounted;
#ifdef HAVE_SETXATTR /* extended attributes interface required */
BOOL efs_raw;
#ifdef XATTR_MAPPINGS
char *xattrmap_path;
#endif /* XATTR_MAPPINGS */
#endif /* HAVE_SETXATTR */
struct fuse_chan *fc;
BOOL inherit;
@ -2752,7 +2755,7 @@ static int ntfs_fuse_getxattr(const char *path, const char *name,
int namespace;
struct SECURITY_CONTEXT security;
attr = ntfs_xattr_system_type(name);
attr = ntfs_xattr_system_type(name,ctx->vol);
if (attr != XATTR_UNMAPPED) {
#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
/*
@ -2884,7 +2887,7 @@ static int ntfs_fuse_setxattr(const char *path, const char *name,
int namespace;
struct SECURITY_CONTEXT security;
attr = ntfs_xattr_system_type(name);
attr = ntfs_xattr_system_type(name,ctx->vol);
if (attr != XATTR_UNMAPPED) {
#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
/*
@ -3078,7 +3081,7 @@ static int ntfs_fuse_removexattr(const char *path, const char *name)
int namespace;
struct SECURITY_CONTEXT security;
attr = ntfs_xattr_system_type(name);
attr = ntfs_xattr_system_type(name,ctx->vol);
if (attr != XATTR_UNMAPPED) {
switch (attr) {
/*
@ -3692,6 +3695,20 @@ static char *parse_mount_options(const char *orig_opts)
goto err_exit;
}
#ifdef HAVE_SETXATTR /* extended attributes interface required */
#ifdef XATTR_MAPPINGS
} else if (!strcmp(opt, "xattrmapping")) {
if (!val) {
ntfs_log_error("'xattrmapping' option should have "
"a value.\n");
goto err_exit;
}
ctx->xattrmap_path = strdup(val);
if (!ctx->xattrmap_path) {
ntfs_log_error("no more memory to store "
"'xattrmapping' option.\n");
goto err_exit;
}
#endif /* XATTR_MAPPINGS */
} else if (!strcmp(opt, "efs_raw")) {
if (bogus_option_value(val, "efs_raw"))
goto err_exit;
@ -4073,6 +4090,9 @@ int main(int argc, char *argv[])
#endif
const char *permissions_mode = (const char*)NULL;
const char *failed_secure = (const char*)NULL;
#if defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS)
struct XATTRMAPPING *xattr_mapping = (struct XATTRMAPPING*)NULL;
#endif /* defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS) */
struct stat sbuf;
unsigned long existing_mount;
int err, fd;
@ -4253,6 +4273,18 @@ int main(int argc, char *argv[])
if (ctx->usermap_path)
free (ctx->usermap_path);
#if defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS)
xattr_mapping = ntfs_xattr_build_mapping(ctx->vol,
ctx->xattrmap_path);
ctx->vol->xattr_mapping = xattr_mapping;
/*
* Errors are logged, do not refuse mounting, it would be
* too difficult to fix the unmountable mapping file.
*/
if (ctx->xattrmap_path)
free(ctx->xattrmap_path);
#endif /* defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS) */
fh = mount_fuse(parsed_options);
if (!fh) {
err = NTFS_VOLUME_FUSE_ERROR;
@ -4285,6 +4317,9 @@ err_out:
ntfs_mount_error(opts.device, opts.mnt_point, err);
if (ctx->abs_mnt_point)
free(ctx->abs_mnt_point);
#if defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS)
ntfs_xattr_free_mapping(xattr_mapping);
#endif /* defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS) */
err2:
ntfs_close();
free(ctx);

View File

@ -175,6 +175,9 @@
* Mar 2010, version 1.3.17
* - adapted to new default user mapping
* - fixed #ifdef'd code for selftest
*
* May 2010, version 1.3.18
* - redefined early error logging
*/
/*
@ -198,7 +201,7 @@
* General parameters which may have to be adapted to needs
*/
#define AUDT_VERSION "1.3.17"
#define AUDT_VERSION "1.3.18"
#define GET_FILE_SECURITY "ntfs_get_file_security"
#define SET_FILE_SECURITY "ntfs_set_file_security"
@ -312,6 +315,11 @@ typedef int (*dircallback)(struct CALLBACK *context, char *ntfsname,
int length, int type, long long pos, u64 mft_ref,
unsigned int dt_type);
#ifndef HAVE_SYSLOG_H
void ntfs_log_early_error(const char *format, ...)
__attribute__((format(printf, 1, 2)));
#endif
#if USESTUBS | defined(STSC)
int ntfs_get_file_security(void *scapi,
@ -1271,6 +1279,23 @@ void printerror(FILE *file)
#endif
}
#ifndef HAVE_SYSLOG_H
/*
* Redefine early error messages in stand-alone situations
*/
void ntfs_log_early_error(const char *format, ...)
{
va_list args;
va_start(args, format);
vfprintf(stderr,format,args);
va_end(args);
}
#endif
/*
* Guess whether a security attribute is intended for a directory
* based on the presence of inheritable ACE