Commit 5b64aaf9 authored by Steve French's avatar Steve French Committed by Steve French

[CIFS] xattr support part 4 add set EA support

Signed-off-by: Steve French (sfrench@us.ibm.com)
parent 05a15ce5
......@@ -1046,6 +1046,8 @@ typedef union smb_com_transaction2 {
/* PathInfo/FileInfo infolevels */
#define SMB_INFO_STANDARD 1
#define SMB_SET_FILE_EA 2
#define SMB_QUERY_FILE_EA_SIZE 2
#define SMB_INFO_QUERY_EAS_FROM_LIST 3
#define SMB_INFO_QUERY_ALL_EAS 4
#define SMB_INFO_IS_NAME_VALID 6
......
......@@ -128,10 +128,10 @@ extern int CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
const struct nls_table *nls_codepage);
extern int CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon,
char *fileName, FILE_BASIC_INFO * data,
const char *fileName, const FILE_BASIC_INFO * data,
const struct nls_table *nls_codepage);
extern int CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon,
char *fileName, __u64 size,int setAllocationSizeFlag,
const char *fileName, __u64 size,int setAllocationSizeFlag,
const struct nls_table *nls_codepage);
extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon,
__u64 size, __u16 fileHandle,__u32 opener_pid, int AllocSizeFlag);
......@@ -229,4 +229,8 @@ extern ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
const unsigned char * searchName,const unsigned char * ea_name,
unsigned char * ea_value, size_t buf_size,
const struct nls_table *nls_codepage);
extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon,
const char *fileName, const char * ea_name,
const void * ea_value, const __u16 ea_value_len,
const struct nls_table *nls_codepage);
#endif /* _CIFSPROTO_H */
......@@ -2287,7 +2287,7 @@ CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
}
int
CIFSSMBQFSAttributeInfo(int xid, struct cifsTconInfo *tcon,
CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon,
const struct nls_table *nls_codepage)
{
/* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
......@@ -2359,7 +2359,7 @@ CIFSSMBQFSAttributeInfo(int xid, struct cifsTconInfo *tcon,
}
int
CIFSSMBQFSDeviceInfo(int xid, struct cifsTconInfo *tcon,
CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon,
const struct nls_table *nls_codepage)
{
/* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
......@@ -2432,7 +2432,7 @@ CIFSSMBQFSDeviceInfo(int xid, struct cifsTconInfo *tcon,
}
int
CIFSSMBQFSUnixInfo(int xid, struct cifsTconInfo *tcon,
CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
const struct nls_table *nls_codepage)
{
/* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
......@@ -2512,7 +2512,7 @@ CIFSSMBQFSUnixInfo(int xid, struct cifsTconInfo *tcon,
in Samba which this routine can run into */
int
CIFSSMBSetEOF(int xid, struct cifsTconInfo *tcon, char *fileName,
CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
__u64 size, int SetAllocation, const struct nls_table *nls_codepage)
{
struct smb_com_transaction2_spi_req *pSMB = NULL;
......@@ -2692,8 +2692,9 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
}
int
CIFSSMBSetTimes(int xid, struct cifsTconInfo *tcon, char *fileName,
FILE_BASIC_INFO * data, const struct nls_table *nls_codepage)
CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
const FILE_BASIC_INFO * data,
const struct nls_table *nls_codepage)
{
TRANSACTION2_SPI_REQ *pSMB = NULL;
TRANSACTION2_SPI_RSP *pSMBr = NULL;
......@@ -3290,4 +3291,106 @@ ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
return rc;
}
int
CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
const char * ea_name, const void * ea_value,
const __u16 ea_value_len, const struct nls_table *nls_codepage)
{
struct smb_com_transaction2_spi_req *pSMB = NULL;
struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
struct fealist *parm_data;
int name_len;
int rc = 0;
int bytes_returned = 0;
cFYI(1, ("In SetEA"));
SetEARetry:
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, fileName, 530
/* find define for this maxpathcomponent */
, nls_codepage);
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */
name_len = strnlen(fileName, 530);
name_len++; /* trailing null */
strncpy(pSMB->FileName, fileName, name_len);
}
pSMB->ParameterCount = 6 + name_len;
/* done calculating parms using name_len of file name,
now use name_len to calculate length of ea name
we are going to create in the inode xattrs */
if(ea_name == NULL)
name_len = 0;
else
name_len = strnlen(ea_name,255);
pSMB->DataCount = sizeof(*parm_data) + ea_value_len + name_len + 1;
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
pSMB->Timeout = 0;
pSMB->Reserved2 = 0;
pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
InformationLevel) - 4;
pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
pSMB->InformationLevel =
cpu_to_le16(SMB_SET_FILE_EA);
parm_data =
(struct fealist *) (((char *) &pSMB->hdr.Protocol) +
pSMB->DataOffset);
pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
pSMB->SetupCount = 1;
pSMB->Reserved3 = 0;
pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
parm_data->list_len = (__u32)(pSMB->DataCount);
parm_data->list[0].EA_flags = 0;
/* we checked above that name len is less than 255 */
parm_data->list[0].name_len = (__u8)name_len;;
/* EA names are always ASCII */
strncpy(parm_data->list[0].name,ea_name,name_len);
parm_data->list[0].name[name_len] = 0;
parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
/* caller ensures that ea_value_len is less than 64K but
we need to ensure that it fits within the smb */
/*BB add length check that it would fit in negotiated SMB buffer size BB */
/* if(ea_value_len > buffer_size - 512 (enough for header)) */
memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
pSMB->TotalDataCount = pSMB->DataCount;
pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
pSMB->TotalParameterCount = pSMB->ParameterCount;
pSMB->Reserved4 = 0;
pSMB->hdr.smb_buf_length += pSMB->ByteCount;
pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cFYI(1, ("SetPathInfo (EA) returned %d", rc));
}
if (pSMB)
cifs_buf_release(pSMB);
if (rc == -EAGAIN)
goto SetEARetry;
return rc;
}
#endif
......@@ -26,6 +26,7 @@
#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."
......@@ -40,7 +41,7 @@ int cifs_removexattr(struct dentry * direntry, const char * name)
}
int cifs_setxattr(struct dentry * direntry, const char * ea_name,
const void * ea_value, size_t buf_size, int flags)
const void * ea_value, size_t value_size, int flags)
{
int rc = -EOPNOTSUPP;
#ifdef CONFIG_CIFS_XATTR
......@@ -75,8 +76,26 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name,
/* if proc/fs/cifs/streamstoxattr is set then
search server for EAs or streams to
returns as xattrs */
/* rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value,buf_size,
cifs_sb->local_nls);*/
if(value_size > MAX_EA_VALUE_SIZE) {
cFYI(1,("size of EA value too large"));
if(full_path)
kfree(full_path);
FreeXid(xid);
return -EOPNOTSUPP;
}
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));
/* 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);
......@@ -116,7 +135,7 @@ 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(memcmp(ea_name,CIFS_XATTR_USER_PREFIX,5)) {
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? */
......
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