Commit 3921b8ae authored by Steve French's avatar Steve French

[CIFS] POSIX ACL support part 1

Signed-off-by: Steve French (sfrench@us.ibm.com)
parent d14353f9
......@@ -90,5 +90,5 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *,
size_t, int);
extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
#define CIFS_VERSION "1.24"
#define CIFS_VERSION "1.25"
#endif /* _CIFSFS_H */
......@@ -1076,6 +1076,7 @@ struct smb_t2_rsp {
#define SMB_QUERY_FILE_COMPRESSION_INFO 0x10B
#define SMB_QUERY_FILE_UNIX_BASIC 0x200
#define SMB_QUERY_FILE_UNIX_LINK 0x201
#define SMB_QUERY_POSIX_ACL 0x204
#define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee
#define SMB_QUERY_FILE_ACCESS_INFO 0x3f0
#define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */
......@@ -1090,6 +1091,7 @@ struct smb_t2_rsp {
#define SMB_SET_FILE_END_OF_FILE_INFO 0x104
#define SMB_SET_FILE_UNIX_BASIC 0x200
#define SMB_SET_FILE_UNIX_LINK 0x201
#define SMB_SET_POSIX_ACL 0x204
#define SMB_SET_FILE_UNIX_HLINK 0x203
#define SMB_SET_FILE_BASIC_INFO2 0x3ec
#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo level too */
......@@ -1638,6 +1640,27 @@ struct file_compression_info {
__u8 pad[3];
}; /* level 0x10b */
/* POSIX ACL set/query path info structures */
#define CIFS_ACL_VERSION 1
struct cifs_posix_acl {
/* BB fixme add here */
}; /* level 0x204 */
/* types of access control entries */
#define CIFS_POSIX_ACL_USER_OBJ 0x01
#define CIFS_POSIX_ACL_USER 0x02
#define CIFS_POSIX_ACL_GROUP_OBJ 0x04
#define CIFS_POSIX_ACL_GROUP 0x08
#define CIFS_POSIX_ACL_MASK 0x10
#define CIFS_POSIX_ACL_OTHER 0x20
/* types of perms */
#define CIFS_POSIX_ACL_EXECUTE 0x01
#define CIFS_POSIX_ACL_WRITE 0x02
#define CIFS_POSIX_ACL_READ 0x04
/* end of POSIX ACL definitions */
struct file_internal_info {
__u64 UniqueId; /* inode number */
}; /* level 0x3ee */
......
......@@ -1585,6 +1585,96 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
return rc;
}
#ifdef CONFIG_CIFS_POSIX
int
CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName,
char *acl_inf, const int buflen,
const struct nls_table *nls_codepage)
{
/* SMB_QUERY_POSIX_ACL */
TRANSACTION2_QPI_REQ *pSMB = NULL;
TRANSACTION2_QPI_RSP *pSMBr = NULL;
int rc = 0;
int bytes_returned;
int name_len;
__u16 params, byte_count;
cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
queryAclRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
return rc;
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
/* BB fixme find define for this maxpathcomponent */
, nls_codepage);
name_len++; /* trailing null */
name_len *= 2;
pSMB->FileName[name_len] = 0;
pSMB->FileName[name_len+1] = 0;
} else { /* BB improve the check for buffer overruns BB */
name_len = strnlen(searchName, 530 /* BB fixme */);
name_len++; /* trailing null */
strncpy(pSMB->FileName, searchName, name_len);
}
params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
pSMB->TotalDataCount = 0;
pSMB->MaxParameterCount = cpu_to_le16(2);
/* BB find exact max data count below from sess structure BB */
pSMB->MaxDataCount = cpu_to_le16(4000);
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
pSMB->Timeout = 0;
pSMB->Reserved2 = 0;
pSMB->ParameterOffset = cpu_to_le16(
offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
pSMB->DataCount = 0;
pSMB->DataOffset = 0;
pSMB->SetupCount = 1;
pSMB->Reserved3 = 0;
pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
byte_count = params + 1 /* pad */ ;
pSMB->TotalParameterCount = cpu_to_le16(params);
pSMB->ParameterCount = pSMB->TotalParameterCount;
pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
pSMB->Reserved4 = 0;
pSMB->hdr.smb_buf_length += byte_count;
pSMB->ByteCount = cpu_to_le16(byte_count);
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
} else {
/* decode response */
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
if (rc || (pSMBr->ByteCount < 2))
/* BB also check enough total bytes returned */
rc = -EIO; /* bad smb */
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));
}
}
if (pSMB)
cifs_buf_release(pSMB);
if (rc == -EAGAIN)
goto queryAclRetry;
return rc;
}
#endif
int
CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName,
......@@ -1795,7 +1885,7 @@ CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
pSMB->Timeout = 0;
pSMB->Reserved2 = 0;
pSMB->ParameterOffset = cpu_to_le16(
offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
pSMB->DataCount = 0;
pSMB->DataOffset = 0;
pSMB->SetupCount = 1; /* one byte, no need to le convert */
......@@ -1880,8 +1970,8 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
byte_count = params + 1 /* pad */ ;
pSMB->TotalParameterCount = cpu_to_le16(params);
pSMB->ParameterCount = pSMB->TotalParameterCount;
pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
pSMB->ParameterOffset = cpu_to_le16(
offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
pSMB->DataCount = 0;
pSMB->DataOffset = 0;
pSMB->SetupCount = 1; /* one byte no need to make endian neutral */
......@@ -1997,8 +2087,8 @@ CIFSFindFirst2(const int xid, struct cifsTconInfo *tcon,
byte_count = params + 1 /* pad */ ;
pSMB->TotalParameterCount = cpu_to_le16(params);
pSMB->ParameterCount = pSMB->TotalParameterCount;
pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
pSMB->ParameterOffset = cpu_to_le16(
offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
pSMB->DataCount = 0;
pSMB->DataOffset = 0;
pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
......
......@@ -75,7 +75,7 @@ static int initiate_cifs_search(const int xid, struct file * file, char * full_p
}
/* find the corresponding entry in the search */
static int find_cifs_entry(const int xid, const struct cifsTconInfo * pTcon,
static int find_cifs_entry(const int xid, struct cifsTconInfo * pTcon,
const loff_t index_to_find, struct cifsFileInfo * cifsFile /* BB add missing parm */)
{
int rc = 0;
......
......@@ -20,6 +20,7 @@
*/
#include <linux/fs.h>
#include <linux/posix_acl_xattr.h>
#include "cifsfs.h"
#include "cifspdu.h"
#include "cifsglob.h"
......@@ -27,10 +28,10 @@
#include "cifs_debug.h"
#define MAX_EA_VALUE_SIZE 65535
#define CIFS_XATTR_DOS_ATTRIB "user.DOSATTRIB"
#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." /* BB should check for this someday */
#define CIFS_XATTR_OS2_PREFIX "os2." /* BB should check for this someday */
/* also note could add check for security prefix XATTR_SECURITY_PREFIX */
......@@ -128,16 +129,30 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name,
if(ea_name == NULL) {
cFYI(1,("Null xattr names not supported"));
} else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5)) {
cFYI(1,("illegal xattr namespace %s (only user namespace supported)",ea_name));
} else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5) == 0) {
if(strncmp(ea_name,CIFS_XATTR_DOS_ATTRIB,14) == 0) {
cFYI(1,("attempt to set cifs inode metadata"));
}
ea_name += 5; /* skip past user. prefix */
rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value,
(__u16)value_size, cifs_sb->local_nls);
} else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) {
ea_name += 4; /* skip past os2. prefix */
rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value,
(__u16)value_size, cifs_sb->local_nls);
} else {
if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,strlen(POSIX_ACL_XATTR_ACCESS) == 0)) {
cFYI(1,("set POSIX ACL not supported yet"));
} else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
cFYI(1,("set default POSIX ACL not supported yet"));
} else {
cFYI(1,("illegal xattr name request %s (only user namespace supported)",ea_name));
/* BB what if no namespace prefix? */
/* Should we just pass them to server, except for
system and perhaps security prefixes? */
} else {
ea_name+=5; /* skip past user. prefix */
rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value,
(__u16)value_size, cifs_sb->local_nls);
}
}
if (full_path)
kfree(full_path);
FreeXid(xid);
......@@ -177,19 +192,43 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
}
/* return dos attributes as pseudo xattr */
/* return alt name if available as pseudo attr */
if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5)) {
cFYI(1,("illegal xattr namespace %s (only user namespace supported)",ea_name));
/* BB what if no namespace prefix? */
/* Should we just pass them to server, except for system? */
if(ea_name == NULL) {
cFYI(1,("Null xattr names not supported"));
} else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5) == 0) {
if(strncmp(ea_name,CIFS_XATTR_DOS_ATTRIB,14) == 0) {
cFYI(1,("attempt to query cifs inode metadata"));
/* revalidate/getattr then populate from inode */
} /* BB add else when above is implemented */
ea_name += 5; /* skip past user. prefix */
rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
buf_size, cifs_sb->local_nls);
} else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) {
ea_name += 4; /* skip past os2. prefix */
rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
buf_size, cifs_sb->local_nls);
} else {
/* We could add a check here
if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,strlen(POSIX_ACL_XATTR_ACCESS)) == 0) {
cFYI(1,("query POSIX ACL not supported yet"));
/* rc = CIFSSMBGetPosixACL(xid, pTcon,
const unsigned char *searchName,
char *acl_inf, const int buflen,
cifs_sb->local_nls); */
} else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
cFYI(1,("query default POSIX ACL not supported yet"));
/* rc = CIFSSMBGetPosixACL(xid, pTcon,
const unsigned char *searchName,
char *acl_inf, const int buflen,
cifs_sb->local_nls); */
} else {
cFYI(1,("illegal xattr name request %s (only user namespace supported)",ea_name));
}
}
/* We could add an additional check for streams ie
if proc/fs/cifs/streamstoxattr is set then
search server for EAs or streams to
returns as xattrs */
ea_name+=5; /* skip past user. */
rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
buf_size, cifs_sb->local_nls);
}
if (full_path)
kfree(full_path);
FreeXid(xid);
......
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