Commit d276f715 authored by Steve French's avatar Steve French Committed by Steve French

[CIFS] POSIX ACL support part 3

Signed-off-by: Steve French (sfrench@us.ibm.com)
parent 27cf3d72
......@@ -495,6 +495,12 @@ struct inode_operations cifs_dir_inode_ops = {
.setattr = cifs_setattr,
.symlink = cifs_symlink,
.mknod = cifs_mknod,
#ifdef CONFIG_CIFS_XATTR
.setxattr = cifs_setxattr,
.getxattr = cifs_getxattr,
.listxattr = cifs_listxattr,
.removexattr = cifs_removexattr,
#endif
};
struct inode_operations cifs_file_inode_ops = {
......
......@@ -1645,14 +1645,14 @@ struct file_compression_info {
struct cifs_posix_ace { /* access control entry (ACE) */
__u8 cifs_e_tag;
__u8 cifs_e_perm;
__u64 cifs_uid; /* or gid */
__le64 cifs_uid; /* or gid */
};
struct cifs_posix_acl { /* access conrol list (ACL) */
__le16 version;
__le16 access_entry_count; /* access ACL - count of entries */
__le16 default_entry_count; /* default ACL - count of entries */
struct cifs_posix_ace ace_array[1];
struct cifs_posix_ace ace_array[0];
/* followed by
struct cifs_posix_ace default_ace_arraay[] */
}; /* level 0x204 */
......
......@@ -234,8 +234,8 @@ extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon,
const void * ea_value, const __u16 ea_value_len,
const struct nls_table *nls_codepage);
extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName,
char *acl_inf, const int buflen,
const struct nls_table *nls_codepage);
const unsigned char *searchName,
char *acl_inf, const int buflen,const int acl_type,
const struct nls_table *nls_codepage);
#endif /* _CIFSPROTO_H */
......@@ -30,6 +30,7 @@
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/vfs.h>
#include <linux/posix_acl_xattr.h>
#include <asm/uaccess.h>
#include "cifspdu.h"
#include "cifsglob.h"
......@@ -1586,10 +1587,75 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
}
#ifdef CONFIG_CIFS_POSIX
static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
{
/* u8 cifs fields do not need le conversion */
ace->e_perm = (u16)cifs_ace->cifs_e_perm;
ace->e_tag = (u16)cifs_ace->cifs_e_tag;
ace->e_id = (u32)le32_to_cpu(cifs_ace->cifs_uid);
/* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
return;
}
static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,const int acl_type,const int size_of_data_area)
{
int size = 0;
int i;
__u16 count;
struct cifs_posix_ace * pACE;
struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
return -EOPNOTSUPP;
if(acl_type & ACL_TYPE_ACCESS) {
count = le16_to_cpu(cifs_acl->access_entry_count);
pACE = &cifs_acl->ace_array[0];
size = sizeof(struct cifs_posix_acl);
size += sizeof(struct cifs_posix_ace) * count;
/* check if we would go beyond end of SMB */
if(size_of_data_area < size) {
cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
return -EINVAL;
}
} else if(acl_type & ACL_TYPE_DEFAULT) {
count = le16_to_cpu(cifs_acl->access_entry_count);
size = sizeof(struct cifs_posix_acl);
size += sizeof(struct cifs_posix_ace) * count;
/* skip past access ACEs to get to default ACEs */
pACE = &cifs_acl->ace_array[count];
count = le16_to_cpu(cifs_acl->default_entry_count);
size += sizeof(struct cifs_posix_ace) * count;
/* check if we would go beyond end of SMB */
if(size_of_data_area < size)
return -EINVAL;
} else {
/* illegal type */
return -EINVAL;
}
size = posix_acl_xattr_size(count);
if(size > buflen) {
/* BB should we fill in as much data as we can first? */
/* seems odd that API was not designed so one could query ACL size */
return -ERANGE;
}
local_acl->a_version = POSIX_ACL_XATTR_VERSION;
for(i = 0;i < count ;i++) {
cifs_convert_ace(&local_acl->a_entries[i],pACE);
pACE ++;
}
return size;
}
int
CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName,
char *acl_inf, const int buflen,
char *acl_inf, const int buflen, const int acl_type,
const struct nls_table *nls_codepage)
{
/* SMB_QUERY_POSIX_ACL */
......@@ -1662,9 +1728,9 @@ CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
else {
__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
__u16 count = le16_to_cpu(pSMBr->t2.DataCount);
memcpy(acl_inf,(char *)&pSMBr->hdr.Protocol+data_offset,
min_t(const int, buflen, count));
rc = cifs_copy_posix_acl(acl_inf,
(char *)&pSMBr->hdr.Protocol+data_offset,
buflen,acl_type,count);
}
}
if (pSMB)
......@@ -3641,7 +3707,7 @@ ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
go beyond end of list */
__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
struct fealist * ea_response_data;
rc = -ENOENT;
rc = -ENODATA;
/* validate_trans2_offsets() */
/* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
ea_response_data = (struct fealist *)
......
......@@ -73,6 +73,7 @@ const struct smb_to_posix_error mapping_table_ERRDOS[] = {
{ERRnotlocked, -ENOLCK},
{ERRalreadyexists, -EEXIST},
{ERRmoredata, -EOVERFLOW},
{ERReasnotsupported,-EOPNOTSUPP},
{ErrQuota, -EDQUOT},
{ErrNotALink, -ENOLINK},
{ERRnetlogonNotStarted,-ENOPROTOOPT},
......@@ -287,7 +288,7 @@ static const struct {
ERRDOS, 87, NT_STATUS_BAD_WORKING_SET_LIMIT}, {
ERRDOS, 87, NT_STATUS_INCOMPATIBLE_FILE_MAP}, {
ERRDOS, 87, NT_STATUS_SECTION_PROTECTION}, {
ERRDOS, 282, NT_STATUS_EAS_NOT_SUPPORTED}, {
ERRDOS, ERReasnotsupported, NT_STATUS_EAS_NOT_SUPPORTED}, {
ERRDOS, 255, NT_STATUS_EA_TOO_LARGE}, {
ERRHRD, ERRgeneral, NT_STATUS_NONEXISTENT_EA_ENTRY}, {
ERRHRD, ERRgeneral, NT_STATUS_NO_EAS_ON_FILE}, {
......
......@@ -69,6 +69,7 @@
#define ERRpipeclosing 232
#define ERRnotconnected 233
#define ERRmoredata 234
#define ERReasnotsupported 282
#define ErrQuota 0x200 /* The operation would cause a quota limit to be exceeded. */
#define ErrNotALink 0x201 /* A link operation was performed on a pathname that
was not a link. */
......
......@@ -164,9 +164,6 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
void * ea_value, size_t buf_size)
{
ssize_t rc = -EOPNOTSUPP;
#ifdef CONFIG_CIFS_POSIX
struct cifs_posix_ace * acl_inf;
#endif
#ifdef CONFIG_CIFS_XATTR
int xid;
struct cifs_sb_info *cifs_sb;
......@@ -183,6 +180,8 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
return -EIO;
xid = GetXid();
cFYI(1,("getxattr %s with size %d",ea_name,buf_size));
cifs_sb = CIFS_SB(sb);
pTcon = cifs_sb->tcon;
......@@ -210,31 +209,18 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
buf_size, cifs_sb->local_nls);
} else if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,strlen(POSIX_ACL_XATTR_ACCESS)) == 0) {
#ifdef CONFIG_CIFS_POSIX
acl_inf = (struct cifs_posix_ace *)kmalloc(4096,GFP_KERNEL);
if(acl_inf == NULL)
rc = -ENOMEM;
else {
rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
(char *)acl_inf, 4096, cifs_sb->local_nls);
/* BB fixme - add parsing */
kfree(acl_inf);
}
rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
ea_value, buf_size, ACL_TYPE_ACCESS,
cifs_sb->local_nls);
#else
cFYI(1,("query POSIX ACL not supported yet"));
#endif /* CONFIG_CIFS_POSIX */
} else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
#ifdef CONFIG_CIFS_POSIX
acl_inf = (struct cifs_posix_ace *)kmalloc(4096,GFP_KERNEL);
if(acl_inf == NULL)
rc = -ENOMEM;
else {
rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
(char *)acl_inf, 4096, cifs_sb->local_nls);
/* BB fixme - add parsing */
kfree(acl_inf);
}
rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
ea_value, buf_size, ACL_TYPE_DEFAULT,
cifs_sb->local_nls);
#else
cFYI(1,("query POSIX default ACL not supported yet"));
#endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment