2005-04-17 02:20:36 +04:00
/*
* fs / cifs / xattr . c
*
2007-07-07 02:44:50 +04:00
* Copyright ( c ) International Business Machines Corp . , 2003 , 2007
2005-04-17 02:20:36 +04:00
* Author ( s ) : Steve French ( sfrench @ us . ibm . com )
*
* This library is free software ; you can redistribute it and / or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation ; either version 2.1 of the License , or
* ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See
* the GNU Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
# include <linux/fs.h>
# include <linux/posix_acl_xattr.h>
# include "cifsfs.h"
# include "cifspdu.h"
# include "cifsglob.h"
# include "cifsproto.h"
# include "cifs_debug.h"
# define MAX_EA_VALUE_SIZE 65535
# define CIFS_XATTR_DOS_ATTRIB "user.DosAttrib"
# define CIFS_XATTR_USER_PREFIX "user."
# define CIFS_XATTR_SYSTEM_PREFIX "system."
# define CIFS_XATTR_OS2_PREFIX "os2."
# define CIFS_XATTR_SECURITY_PREFIX ".security"
# define CIFS_XATTR_TRUSTED_PREFIX "trusted."
# define XATTR_TRUSTED_PREFIX_LEN 8
# define XATTR_SECURITY_PREFIX_LEN 9
/* BB need to add server (Samba e.g) support for security and trusted prefix */
2007-07-13 04:33:32 +04:00
2005-04-17 02:20:36 +04:00
2007-07-07 02:44:50 +04:00
int cifs_removexattr ( struct dentry * direntry , const char * ea_name )
2005-04-17 02:20:36 +04:00
{
int rc = - EOPNOTSUPP ;
# ifdef CONFIG_CIFS_XATTR
int xid ;
struct cifs_sb_info * cifs_sb ;
struct cifsTconInfo * pTcon ;
2007-07-07 02:44:50 +04:00
struct super_block * sb ;
char * full_path ;
if ( direntry = = NULL )
2005-04-17 02:20:36 +04:00
return - EIO ;
2007-07-07 02:44:50 +04:00
if ( direntry - > d_inode = = NULL )
2005-04-17 02:20:36 +04:00
return - EIO ;
sb = direntry - > d_inode - > i_sb ;
2007-07-07 02:44:50 +04:00
if ( sb = = NULL )
2005-04-17 02:20:36 +04:00
return - EIO ;
xid = GetXid ( ) ;
2007-07-07 02:44:50 +04:00
2005-04-17 02:20:36 +04:00
cifs_sb = CIFS_SB ( sb ) ;
pTcon = cifs_sb - > tcon ;
2007-07-07 02:44:50 +04:00
2005-04-17 02:20:36 +04:00
full_path = build_path_from_dentry ( direntry ) ;
2007-07-07 02:44:50 +04:00
if ( full_path = = NULL ) {
2005-04-17 02:20:36 +04:00
FreeXid ( xid ) ;
return - ENOMEM ;
}
2007-07-07 02:44:50 +04:00
if ( ea_name = = NULL ) {
cFYI ( 1 , ( " Null xattr names not supported " ) ) ;
} else if ( strncmp ( ea_name , CIFS_XATTR_USER_PREFIX , 5 )
& & ( strncmp ( ea_name , CIFS_XATTR_OS2_PREFIX , 4 ) ) ) {
cFYI ( 1 ,
( " illegal xattr request %s (only user namespace supported) " ,
ea_name ) ) ;
2005-04-17 02:20:36 +04:00
/* BB what if no namespace prefix? */
/* Should we just pass them to server, except for
system and perhaps security prefixes ? */
} else {
2007-07-07 02:44:50 +04:00
if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_NO_XATTR )
2005-04-17 02:20:36 +04:00
goto remove_ea_exit ;
2007-07-07 02:44:50 +04:00
ea_name + = 5 ; /* skip past user. prefix */
rc = CIFSSMBSetEA ( xid , pTcon , full_path , ea_name , NULL ,
2005-04-29 09:41:06 +04:00
( __u16 ) 0 , cifs_sb - > local_nls ,
cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR ) ;
2005-04-17 02:20:36 +04:00
}
remove_ea_exit :
2005-11-07 12:01:34 +03:00
kfree ( full_path ) ;
2005-04-17 02:20:36 +04:00
FreeXid ( xid ) ;
# endif
return rc ;
}
2007-07-07 02:44:50 +04:00
int cifs_setxattr ( struct dentry * direntry , const char * ea_name ,
const void * ea_value , size_t value_size , int flags )
2005-04-17 02:20:36 +04:00
{
int rc = - EOPNOTSUPP ;
# ifdef CONFIG_CIFS_XATTR
int xid ;
struct cifs_sb_info * cifs_sb ;
struct cifsTconInfo * pTcon ;
2007-07-07 02:44:50 +04:00
struct super_block * sb ;
char * full_path ;
2005-04-17 02:20:36 +04:00
2007-07-07 02:44:50 +04:00
if ( direntry = = NULL )
2005-04-17 02:20:36 +04:00
return - EIO ;
2007-07-07 02:44:50 +04:00
if ( direntry - > d_inode = = NULL )
2005-04-17 02:20:36 +04:00
return - EIO ;
sb = direntry - > d_inode - > i_sb ;
2007-07-07 02:44:50 +04:00
if ( sb = = NULL )
2005-04-17 02:20:36 +04:00
return - EIO ;
xid = GetXid ( ) ;
cifs_sb = CIFS_SB ( sb ) ;
pTcon = cifs_sb - > tcon ;
full_path = build_path_from_dentry ( direntry ) ;
2007-07-07 02:44:50 +04:00
if ( full_path = = NULL ) {
2005-04-17 02:20:36 +04:00
FreeXid ( xid ) ;
return - ENOMEM ;
}
/* return dos attributes as pseudo xattr */
/* return alt name if available as pseudo attr */
/* if proc/fs/cifs/streamstoxattr is set then
2007-07-07 02:44:50 +04:00
search server for EAs or streams to
2005-04-17 02:20:36 +04:00
returns as xattrs */
2007-07-07 02:44:50 +04:00
if ( value_size > MAX_EA_VALUE_SIZE ) {
cFYI ( 1 , ( " size of EA value too large " ) ) ;
2005-11-07 12:01:34 +03:00
kfree ( full_path ) ;
2005-04-17 02:20:36 +04:00
FreeXid ( xid ) ;
return - EOPNOTSUPP ;
}
2007-07-07 02:44:50 +04:00
if ( ea_name = = NULL ) {
cFYI ( 1 , ( " Null xattr names not supported " ) ) ;
} else if ( strncmp ( ea_name , CIFS_XATTR_USER_PREFIX , 5 ) = = 0 ) {
if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_NO_XATTR )
2005-04-17 02:20:36 +04:00
goto set_ea_exit ;
2007-07-07 02:44:50 +04:00
if ( strncmp ( ea_name , CIFS_XATTR_DOS_ATTRIB , 14 ) = = 0 ) {
cFYI ( 1 , ( " attempt to set cifs inode metadata " ) ) ;
2005-04-17 02:20:36 +04:00
}
ea_name + = 5 ; /* skip past user. prefix */
2007-07-07 02:44:50 +04:00
rc = CIFSSMBSetEA ( xid , pTcon , full_path , ea_name , ea_value ,
2005-04-29 09:41:06 +04:00
( __u16 ) value_size , cifs_sb - > local_nls ,
cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR ) ;
2007-07-07 02:44:50 +04:00
} else if ( strncmp ( ea_name , CIFS_XATTR_OS2_PREFIX , 4 ) = = 0 ) {
if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_NO_XATTR )
2005-04-17 02:20:36 +04:00
goto set_ea_exit ;
ea_name + = 4 ; /* skip past os2. prefix */
2007-07-07 02:44:50 +04:00
rc = CIFSSMBSetEA ( xid , pTcon , full_path , ea_name , ea_value ,
2005-04-29 09:41:06 +04:00
( __u16 ) value_size , cifs_sb - > local_nls ,
cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR ) ;
2005-04-17 02:20:36 +04:00
} else {
2007-07-07 02:44:50 +04:00
int temp ;
temp = strncmp ( ea_name , POSIX_ACL_XATTR_ACCESS ,
2005-04-17 02:20:36 +04:00
strlen ( POSIX_ACL_XATTR_ACCESS ) ) ;
if ( temp = = 0 ) {
# ifdef CONFIG_CIFS_POSIX
2007-07-07 02:44:50 +04:00
if ( sb - > s_flags & MS_POSIXACL )
rc = CIFSSMBSetPosixACL ( xid , pTcon , full_path ,
ea_value , ( const int ) value_size ,
ACL_TYPE_ACCESS , cifs_sb - > local_nls ,
cifs_sb - > mnt_cifs_flags &
2005-04-29 09:41:06 +04:00
CIFS_MOUNT_MAP_SPECIAL_CHR ) ;
2007-07-07 02:44:50 +04:00
cFYI ( 1 , ( " set POSIX ACL rc %d " , rc ) ) ;
2005-04-17 02:20:36 +04:00
# else
2007-07-07 02:44:50 +04:00
cFYI ( 1 , ( " set POSIX ACL not supported " ) ) ;
2005-04-17 02:20:36 +04:00
# endif
2007-07-07 02:44:50 +04:00
} else if ( strncmp ( ea_name , POSIX_ACL_XATTR_DEFAULT ,
strlen ( POSIX_ACL_XATTR_DEFAULT ) ) = = 0 ) {
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_CIFS_POSIX
2007-07-07 02:44:50 +04:00
if ( sb - > s_flags & MS_POSIXACL )
rc = CIFSSMBSetPosixACL ( xid , pTcon , full_path ,
ea_value , ( const int ) value_size ,
2005-04-29 09:41:06 +04:00
ACL_TYPE_DEFAULT , cifs_sb - > local_nls ,
2007-07-07 02:44:50 +04:00
cifs_sb - > mnt_cifs_flags &
2005-04-29 09:41:06 +04:00
CIFS_MOUNT_MAP_SPECIAL_CHR ) ;
2007-07-07 02:44:50 +04:00
cFYI ( 1 , ( " set POSIX default ACL rc %d " , rc ) ) ;
2005-04-17 02:20:36 +04:00
# else
2007-07-07 02:44:50 +04:00
cFYI ( 1 , ( " set default POSIX ACL not supported " ) ) ;
2005-04-17 02:20:36 +04:00
# endif
} else {
2007-07-17 21:34:02 +04:00
cFYI ( 1 , ( " illegal xattr request %s (only user namespace "
" supported) " , ea_name ) ) ;
2005-04-17 02:20:36 +04:00
/* BB what if no namespace prefix? */
2007-07-07 02:44:50 +04:00
/* Should we just pass them to server, except for
2005-04-17 02:20:36 +04:00
system and perhaps security prefixes ? */
}
}
set_ea_exit :
2005-11-07 12:01:34 +03:00
kfree ( full_path ) ;
2005-04-17 02:20:36 +04:00
FreeXid ( xid ) ;
# endif
return rc ;
}
2007-07-07 02:44:50 +04:00
ssize_t cifs_getxattr ( struct dentry * direntry , const char * ea_name ,
void * ea_value , size_t buf_size )
2005-04-17 02:20:36 +04:00
{
ssize_t rc = - EOPNOTSUPP ;
# ifdef CONFIG_CIFS_XATTR
int xid ;
struct cifs_sb_info * cifs_sb ;
struct cifsTconInfo * pTcon ;
2007-07-07 02:44:50 +04:00
struct super_block * sb ;
char * full_path ;
2005-04-17 02:20:36 +04:00
2007-07-07 02:44:50 +04:00
if ( direntry = = NULL )
2005-04-17 02:20:36 +04:00
return - EIO ;
2007-07-07 02:44:50 +04:00
if ( direntry - > d_inode = = NULL )
2005-04-17 02:20:36 +04:00
return - EIO ;
sb = direntry - > d_inode - > i_sb ;
2007-07-07 02:44:50 +04:00
if ( sb = = NULL )
2005-04-17 02:20:36 +04:00
return - EIO ;
xid = GetXid ( ) ;
cifs_sb = CIFS_SB ( sb ) ;
pTcon = cifs_sb - > tcon ;
full_path = build_path_from_dentry ( direntry ) ;
2007-07-07 02:44:50 +04:00
if ( full_path = = NULL ) {
2005-04-17 02:20:36 +04:00
FreeXid ( xid ) ;
return - ENOMEM ;
}
/* return dos attributes as pseudo xattr */
/* return alt name if available as pseudo attr */
2007-07-07 02:44:50 +04:00
if ( ea_name = = NULL ) {
cFYI ( 1 , ( " Null xattr names not supported " ) ) ;
} else if ( strncmp ( ea_name , CIFS_XATTR_USER_PREFIX , 5 ) = = 0 ) {
if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_NO_XATTR )
2005-04-17 02:20:36 +04:00
goto get_ea_exit ;
2007-07-07 02:44:50 +04:00
if ( strncmp ( ea_name , CIFS_XATTR_DOS_ATTRIB , 14 ) = = 0 ) {
cFYI ( 1 , ( " attempt to query cifs inode metadata " ) ) ;
2005-04-17 02:20:36 +04:00
/* revalidate/getattr then populate from inode */
} /* BB add else when above is implemented */
ea_name + = 5 ; /* skip past user. prefix */
2007-07-07 02:44:50 +04:00
rc = CIFSSMBQueryEA ( xid , pTcon , full_path , ea_name , ea_value ,
2005-04-29 09:41:06 +04:00
buf_size , cifs_sb - > local_nls ,
cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR ) ;
2007-07-07 02:44:50 +04:00
} else if ( strncmp ( ea_name , CIFS_XATTR_OS2_PREFIX , 4 ) = = 0 ) {
if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_NO_XATTR )
2005-04-17 02:20:36 +04:00
goto get_ea_exit ;
ea_name + = 4 ; /* skip past os2. prefix */
2007-07-07 02:44:50 +04:00
rc = CIFSSMBQueryEA ( xid , pTcon , full_path , ea_name , ea_value ,
2005-04-29 09:41:06 +04:00
buf_size , cifs_sb - > local_nls ,
cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR ) ;
2007-07-07 02:44:50 +04:00
} else if ( strncmp ( ea_name , POSIX_ACL_XATTR_ACCESS ,
2006-01-13 02:44:21 +03:00
strlen ( POSIX_ACL_XATTR_ACCESS ) ) = = 0 ) {
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_CIFS_POSIX
2007-07-07 02:44:50 +04:00
if ( sb - > s_flags & MS_POSIXACL )
2005-04-29 09:41:04 +04:00
rc = CIFSSMBGetPosixACL ( xid , pTcon , full_path ,
2007-07-07 02:44:50 +04:00
ea_value , buf_size , ACL_TYPE_ACCESS ,
2005-04-29 09:41:06 +04:00
cifs_sb - > local_nls ,
2007-07-07 02:44:50 +04:00
cifs_sb - > mnt_cifs_flags &
2005-04-29 09:41:06 +04:00
CIFS_MOUNT_MAP_SPECIAL_CHR ) ;
2007-10-03 23:43:19 +04:00
# ifdef CONFIG_CIFS_EXPERIMENTAL
else if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL ) {
2006-01-13 02:44:21 +03:00
__u16 fid ;
int oplock = FALSE ;
2007-10-26 01:17:17 +04:00
struct cifs_ntsd * pacl = NULL ;
__u32 buflen = 0 ;
2007-10-03 23:43:19 +04:00
if ( experimEnabled )
rc = CIFSSMBOpen ( xid , pTcon , full_path ,
FILE_OPEN , GENERIC_READ , 0 , & fid ,
& oplock , NULL , cifs_sb - > local_nls ,
cifs_sb - > mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR ) ;
/* else rc is EOPNOTSUPP from above */
2006-01-13 02:44:21 +03:00
if ( rc = = 0 ) {
2007-10-26 01:17:17 +04:00
rc = CIFSSMBGetCIFSACL ( xid , pTcon , fid , & pacl ,
& buflen ) ;
2006-09-21 11:02:52 +04:00
CIFSSMBClose ( xid , pTcon , fid ) ;
2006-01-13 02:44:21 +03:00
}
2007-10-03 23:43:19 +04:00
}
# endif /* EXPERIMENTAL */
2007-07-07 02:44:50 +04:00
# else
cFYI ( 1 , ( " query POSIX ACL not supported yet " ) ) ;
2005-04-17 02:20:36 +04:00
# endif /* CONFIG_CIFS_POSIX */
2007-07-07 02:44:50 +04:00
} else if ( strncmp ( ea_name , POSIX_ACL_XATTR_DEFAULT ,
2006-01-13 02:44:21 +03:00
strlen ( POSIX_ACL_XATTR_DEFAULT ) ) = = 0 ) {
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_CIFS_POSIX
2007-07-07 02:44:50 +04:00
if ( sb - > s_flags & MS_POSIXACL )
2005-04-29 09:41:04 +04:00
rc = CIFSSMBGetPosixACL ( xid , pTcon , full_path ,
2007-07-07 02:44:50 +04:00
ea_value , buf_size , ACL_TYPE_DEFAULT ,
2005-04-29 09:41:06 +04:00
cifs_sb - > local_nls ,
2007-07-07 02:44:50 +04:00
cifs_sb - > mnt_cifs_flags &
2005-04-29 09:41:06 +04:00
CIFS_MOUNT_MAP_SPECIAL_CHR ) ;
2007-07-07 02:44:50 +04:00
# else
cFYI ( 1 , ( " query POSIX default ACL not supported yet " ) ) ;
2005-04-17 02:20:36 +04:00
# endif
2007-07-07 02:44:50 +04:00
} else if ( strncmp ( ea_name ,
CIFS_XATTR_TRUSTED_PREFIX , XATTR_TRUSTED_PREFIX_LEN ) = = 0 ) {
cFYI ( 1 , ( " Trusted xattr namespace not supported yet " ) ) ;
} else if ( strncmp ( ea_name ,
CIFS_XATTR_SECURITY_PREFIX , XATTR_SECURITY_PREFIX_LEN ) = = 0 ) {
cFYI ( 1 , ( " Security xattr namespace not supported yet " ) ) ;
2005-04-17 02:20:36 +04:00
} else {
2007-07-07 02:44:50 +04:00
cFYI ( 1 ,
( " illegal xattr request %s (only user namespace supported) " ,
ea_name ) ) ;
2005-04-17 02:20:36 +04:00
}
2007-07-07 02:44:50 +04:00
/* We could add an additional check for streams ie
2005-04-17 02:20:36 +04:00
if proc / fs / cifs / streamstoxattr is set then
2007-07-07 02:44:50 +04:00
search server for EAs or streams to
2005-04-17 02:20:36 +04:00
returns as xattrs */
2007-07-07 02:44:50 +04:00
if ( rc = = - EINVAL )
rc = - EOPNOTSUPP ;
2005-04-17 02:20:36 +04:00
get_ea_exit :
2005-11-07 12:01:34 +03:00
kfree ( full_path ) ;
2005-04-17 02:20:36 +04:00
FreeXid ( xid ) ;
# endif
return rc ;
}
2007-07-07 02:44:50 +04:00
ssize_t cifs_listxattr ( struct dentry * direntry , char * data , size_t buf_size )
2005-04-17 02:20:36 +04:00
{
ssize_t rc = - EOPNOTSUPP ;
# ifdef CONFIG_CIFS_XATTR
int xid ;
struct cifs_sb_info * cifs_sb ;
struct cifsTconInfo * pTcon ;
2007-07-07 02:44:50 +04:00
struct super_block * sb ;
char * full_path ;
2005-04-17 02:20:36 +04:00
2007-07-07 02:44:50 +04:00
if ( direntry = = NULL )
2005-04-17 02:20:36 +04:00
return - EIO ;
2007-07-07 02:44:50 +04:00
if ( direntry - > d_inode = = NULL )
2005-04-17 02:20:36 +04:00
return - EIO ;
sb = direntry - > d_inode - > i_sb ;
2007-07-07 02:44:50 +04:00
if ( sb = = NULL )
2005-04-17 02:20:36 +04:00
return - EIO ;
cifs_sb = CIFS_SB ( sb ) ;
pTcon = cifs_sb - > tcon ;
2007-07-07 02:44:50 +04:00
if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_NO_XATTR )
2006-08-16 23:44:25 +04:00
return - EOPNOTSUPP ;
xid = GetXid ( ) ;
2005-04-17 02:20:36 +04:00
full_path = build_path_from_dentry ( direntry ) ;
2007-07-07 02:44:50 +04:00
if ( full_path = = NULL ) {
2005-04-17 02:20:36 +04:00
FreeXid ( xid ) ;
return - ENOMEM ;
}
/* return dos attributes as pseudo xattr */
/* return alt name if available as pseudo attr */
/* if proc/fs/cifs/streamstoxattr is set then
2007-07-07 02:44:50 +04:00
search server for EAs or streams to
2005-04-17 02:20:36 +04:00
returns as xattrs */
2007-07-07 02:44:50 +04:00
rc = CIFSSMBQAllEAs ( xid , pTcon , full_path , data , buf_size ,
2005-04-29 09:41:06 +04:00
cifs_sb - > local_nls ,
2007-07-07 02:44:50 +04:00
cifs_sb - > mnt_cifs_flags &
2005-04-29 09:41:06 +04:00
CIFS_MOUNT_MAP_SPECIAL_CHR ) ;
2005-04-17 02:20:36 +04:00
2005-11-07 12:01:34 +03:00
kfree ( full_path ) ;
2005-04-17 02:20:36 +04:00
FreeXid ( xid ) ;
# endif
return rc ;
}