#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"
/* BB Add call to invalidate_inodes(sb) for all superblocks mounted to this tcon */
}
+static int
+small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
+ void **request_buf /* returned */)
+{
+ int rc = 0;
+
+ /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
+ check for tcp and smb session status done differently
+ for those three - in the calling routine */
+ if(tcon) {
+ if((tcon->ses) && (tcon->ses->server)){
+ struct nls_table *nls_codepage;
+ /* Give Demultiplex thread up to 10 seconds to
+ reconnect, should be greater than cifs socket
+ timeout which is 7 seconds */
+ while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
+ wait_event_interruptible_timeout(tcon->ses->server->response_q,
+ (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
+ if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
+ /* on "soft" mounts we wait once */
+ if((tcon->retry == FALSE) ||
+ (tcon->ses->status == CifsExiting)) {
+ cFYI(1,("gave up waiting on reconnect in smb_init"));
+ return -EHOSTDOWN;
+ } /* else "hard" mount - keep retrying until
+ process is killed or server comes back up */
+ } else /* TCP session is reestablished now */
+ break;
+
+ }
+
+ nls_codepage = load_nls_default();
+ /* need to prevent multiple threads trying to
+ simultaneously reconnect the same SMB session */
+ down(&tcon->ses->sesSem);
+ if(tcon->ses->status == CifsNeedReconnect)
+ rc = cifs_setup_session(0, tcon->ses, nls_codepage);
+ if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
+ mark_open_files_invalid(tcon);
+ rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
+ nls_codepage);
+ up(&tcon->ses->sesSem);
+ if(rc == 0)
+ atomic_inc(&tconInfoReconnectCount);
+
+ cFYI(1, ("reconnect tcon rc = %d", rc));
+ /* Removed call to reopen open files here -
+ it is safer (and faster) to reopen files
+ one at a time as needed in read and write */
+
+ /* Check if handle based operation so we
+ know whether we can continue or not without
+ returning to caller to reset file handle */
+ switch(smb_command) {
+ case SMB_COM_READ_ANDX:
+ case SMB_COM_WRITE_ANDX:
+ case SMB_COM_CLOSE:
+ case SMB_COM_FIND_CLOSE2:
+ case SMB_COM_LOCKING_ANDX: {
+ unload_nls(nls_codepage);
+ return -EAGAIN;
+ }
+ }
+ } else {
+ up(&tcon->ses->sesSem);
+ }
+ unload_nls(nls_codepage);
+
+ } else {
+ return -EIO;
+ }
+ }
+ if(rc)
+ return rc;
+
+ *request_buf = cifs_small_buf_get();
+ if (*request_buf == 0) {
+ /* BB should we add a retry in here if not a writepage? */
+ return -ENOMEM;
+ }
+
+ header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
+
+#ifdef CONFIG_CIFS_STATS
+ if(tcon != NULL) {
+ atomic_inc(&tcon->num_smbs_sent);
+ }
+#endif /* CONFIG_CIFS_STATS */
+ return rc;
+}
+
static int
smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
void **request_buf /* returned */ ,
if(tcon != NULL) {
atomic_inc(&tcon->num_smbs_sent);
}
-#endif
+#endif /* CONFIG_CIFS_STATS */
return rc;
}
+static int validate_t2(struct smb_t2_rsp * pSMB)
+{
+ int rc = -EINVAL;
+ int total_size;
+ char * pBCC;
+
+ /* check for plausible wct, bcc and t2 data and parm sizes */
+ /* check for parm and data offset going beyond end of smb */
+ if(pSMB->hdr.WordCount >= 10) {
+ if((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
+ (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
+ /* check that bcc is at least as big as parms + data */
+ /* check that bcc is less than negotiated smb buffer */
+ total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
+ if(total_size < 512) {
+ total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
+ /* BCC le converted in SendReceive */
+ pBCC = (pSMB->hdr.WordCount * 2) + sizeof(struct smb_hdr) +
+ (char *)pSMB;
+ if((total_size <= (*(u16 *)pBCC)) &&
+ (total_size <
+ CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
+ return 0;
+ }
+
+ }
+ }
+ }
+ cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB,
+ sizeof(struct smb_t2_rsp) + 16);
+ return rc;
+}
int
CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
{
int rc = 0;
int bytes_returned;
struct TCP_Server_Info * server;
+ u16 count;
if(ses->server)
server = ses->server;
rc = -EIO;
return rc;
}
- rc = smb_init(SMB_COM_NEGOTIATE, 0, 0 /* no tcon yet */ ,
+ rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
(void **) &pSMB, (void **) &pSMBr);
if (rc)
return rc;
if (extended_security)
pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
- pSMB->ByteCount = strlen(protocols[0].name) + 1;
+ count = strlen(protocols[0].name) + 1;
strncpy(pSMB->DialectsArray, protocols[0].name, 30);
/* null guaranteed to be at end of source and target buffers anyway */
- pSMB->hdr.smb_buf_length += pSMB->ByteCount;
- pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ pSMB->hdr.smb_buf_length += count;
+ pSMB->ByteCount = cpu_to_le16(count);
rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
/* probably no need to store and check maxvcs */
server->maxBuf =
min(le32_to_cpu(pSMBr->MaxBufferSize),
- (__u32) CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE);
+ (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
/* BB might be helpful to save off the domain of server here */
- if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) {
- if (pSMBr->ByteCount < 16)
+ if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
+ (server->capabilities & CAP_EXTENDED_SECURITY)) {
+ count = pSMBr->ByteCount;
+ if (count < 16)
rc = -EIO;
- else if (pSMBr->ByteCount == 16) {
+ else if (count == 16) {
server->secType = RawNTLMSSP;
if (server->socketUseCount.counter > 1) {
if (memcmp
rc = decode_negTokenInit(pSMBr->u.
extended_response.
SecurityBlob,
- pSMBr->ByteCount -
- 16, &server->secType);
+ count - 16,
+ &server->secType);
+ if(rc == 1) {
+ /* BB Need to fill struct for sessetup here */
+ rc = -EOPNOTSUPP;
+ } else {
+ rc = -EINVAL;
+ }
}
} else
server->capabilities &= ~CAP_EXTENDED_SECURITY;
CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
{
struct smb_hdr *smb_buffer;
- struct smb_hdr *smb_buffer_response;
+ struct smb_hdr *smb_buffer_response; /* BB removeme BB */
int rc = 0;
int length;
return 0;
}
-/* BB remove (from server) list of shares - but with smp safety BB */
-/* BB is ses active - do we need to check here - but how? BB */
if((tcon->ses == 0) || (tcon->ses->server == 0)) {
up(&tcon->tconSem);
return -EIO;
}
-
- rc = smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
- (void **) &smb_buffer, (void **) &smb_buffer_response);
+ rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon, (void **)&smb_buffer);
if (rc) {
up(&tcon->tconSem);
return rc;
- }
+ } else {
+ smb_buffer_response = smb_buffer; /* BB removeme BB */
+ }
rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
&length, 0);
if (rc)
cFYI(1, (" Tree disconnect failed %d", rc));
if (smb_buffer)
- cifs_buf_release(smb_buffer);
+ cifs_small_buf_release(smb_buffer);
up(&tcon->tconSem);
/* No need to return error on this operation if tid invalidated and
up(&ses->sesSem);
return -EBUSY;
}
-
- rc = smb_init(SMB_COM_LOGOFF_ANDX, 2, 0 /* no tcon anymore */,
- (void **) &pSMB, (void **) &smb_buffer_response);
-
- if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
- pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+ rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
+ smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
+
+ if(ses->server) {
+ if(ses->server->secMode &
+ (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+ pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+ }
if (rc) {
up(&ses->sesSem);
spin_lock(&GlobalMid_Lock);
ses->server->tcpStatus = CifsExiting;
spin_unlock(&GlobalMid_Lock);
+ rc = -ESHUTDOWN;
}
}
if (pSMB)
- cifs_buf_release(pSMB);
+ cifs_small_buf_release(pSMB);
up(&ses->sesSem);
/* if session dead then we do not need to do ulogoff,
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, 530
+ cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, PATH_MAX
/* 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 = strnlen(fileName, PATH_MAX);
name_len++; /* trailing null */
strncpy(pSMB->fileName, fileName, name_len);
}
pSMB->SearchAttributes =
cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
- pSMB->ByteCount = name_len + 1;
pSMB->BufferFormat = 0x04;
- pSMB->hdr.smb_buf_length += pSMB->ByteCount;
- pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ pSMB->hdr.smb_buf_length += name_len + 1;
+ pSMB->ByteCount = cpu_to_le16(name_len + 1);
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
return rc;
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, 530
+ name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, PATH_MAX
/* 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(dirName, 530);
+ name_len = strnlen(dirName, PATH_MAX);
name_len++; /* trailing null */
strncpy(pSMB->DirName, dirName, name_len);
}
- pSMB->ByteCount = name_len + 1;
pSMB->BufferFormat = 0x04;
- pSMB->hdr.smb_buf_length += pSMB->ByteCount;
- pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ pSMB->hdr.smb_buf_length += name_len + 1;
+ pSMB->ByteCount = cpu_to_le16(name_len + 1);
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
return rc;
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, 530
+ name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, PATH_MAX
/* 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(name, 530);
+ name_len = strnlen(name, PATH_MAX);
name_len++; /* trailing null */
strncpy(pSMB->DirName, name, name_len);
}
- pSMB->ByteCount = name_len + 1 /* for buf format */ ;
pSMB->BufferFormat = 0x04;
- pSMB->hdr.smb_buf_length += pSMB->ByteCount;
- pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ pSMB->hdr.smb_buf_length += name_len + 1;
+ pSMB->ByteCount = cpu_to_le16(name_len + 1);
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
OPEN_RSP *pSMBr = NULL;
int bytes_returned;
int name_len;
+ __u16 count;
openRetry:
rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
pSMB->AndXCommand = 0xFF; /* none */
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- pSMB->ByteCount = 1; /* account for one byte pad to word boundary */
+ count = 1; /* account for one byte pad to word boundary */
name_len =
cifs_strtoUCS((wchar_t *) (pSMB->fileName + 1),
- fileName, 530
+ fileName, PATH_MAX
/* find define for this maxpathcomponent */
, nls_codepage);
name_len++; /* trailing null */
name_len *= 2;
pSMB->NameLength = cpu_to_le16(name_len);
} else { /* BB improve the check for buffer overruns BB */
- pSMB->ByteCount = 0; /* no pad */
- name_len = strnlen(fileName, 530);
+ count = 0; /* no pad */
+ name_len = strnlen(fileName, PATH_MAX);
name_len++; /* trailing null */
pSMB->NameLength = cpu_to_le16(name_len);
strncpy(pSMB->fileName, fileName, name_len);
}
pSMB->DesiredAccess = cpu_to_le32(access_flags);
pSMB->AllocationSize = 0;
- pSMB->FileAttributes = ATTR_NORMAL;
+ pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
/* XP does not handle ATTR_POSIX_SEMANTICS */
/* but it helps speed up case sensitive checks for other
servers such as Samba */
if (tcon->ses->capabilities & CAP_UNIX)
- pSMB->FileAttributes |= ATTR_POSIX_SEMANTICS;
+ pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
/* if ((omode & S_IWUGO) == 0)
- pSMB->FileAttributes |= ATTR_READONLY;*/
+ pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
/* Above line causes problems due to vfs splitting create into two
pieces - need to set mode after file created not while it is
being created */
- pSMB->FileAttributes = cpu_to_le32(pSMB->FileAttributes);
pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
pSMB->CreateDisposition = cpu_to_le32(openDisposition);
pSMB->CreateOptions = cpu_to_le32(create_options);
pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); /* BB ??*/
pSMB->SecurityFlags =
- cpu_to_le32(SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY);
+ SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
- pSMB->ByteCount += name_len;
- pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ count += name_len;
+ pSMB->hdr.smb_buf_length += count;
- pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ pSMB->ByteCount = cpu_to_le16(count);
/* long_op set to 1 to allow for oplock break timeouts */
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 1);
if (rc) {
cERROR(1, ("Send error in read = %d", rc));
} else {
- pSMBr->DataLength = le16_to_cpu(pSMBr->DataLength);
- *nbytes = pSMBr->DataLength;
+ __u16 data_length = le16_to_cpu(pSMBr->DataLength);
+ *nbytes = data_length;
/*check that DataLength would not go beyond end of SMB */
- if ((pSMBr->DataLength > CIFS_MAX_MSGSIZE)
- || (pSMBr->DataLength > count)) {
- cFYI(1,("bad length %d for count %d",pSMBr->DataLength,count));
+ if ((data_length > CIFSMaxBufSize)
+ || (data_length > count)) {
+ cFYI(1,("bad length %d for count %d",data_length,count));
rc = -EIO;
*nbytes = 0;
} else {
pReadData =
(char *) (&pSMBr->hdr.Protocol) +
le16_to_cpu(pSMBr->DataOffset);
-/* if(rc = copy_to_user(buf, pReadData, pSMBr->DataLength)) {
+/* if(rc = copy_to_user(buf, pReadData, data_length)) {
cERROR(1,("Faulting on read rc = %d",rc));
rc = -EFAULT;
}*/ /* can not use copy_to_user when using page cache*/
if(*buf)
- memcpy(*buf,pReadData,pSMBr->DataLength);
+ memcpy(*buf,pReadData,data_length);
}
}
if (pSMB) {
CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
const int netfid, const unsigned int count,
const __u64 offset, unsigned int *nbytes, const char *buf,
- const int long_op)
+ const char __user * ubuf, const int long_op)
{
int rc = -EACCES;
WRITE_REQ *pSMB = NULL;
WRITE_RSP *pSMBr = NULL;
int bytes_returned;
+ unsigned bytes_sent;
+ __u16 byte_count;
rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
(void **) &pSMBr);
pSMB->Fid = netfid;
pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
+ pSMB->Reserved = 0xFFFFFFFF;
+ pSMB->WriteMode = 0;
pSMB->Remaining = 0;
- if (count > ((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00))
- pSMB->DataLengthLow =
- (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00;
- else
- pSMB->DataLengthLow = count;
+ /* BB can relax this if buffer is big enough in some cases - ie we can
+ send more if LARGE_WRITE_X capability returned by the server and if
+ our buffer is big enough or if we convert to iovecs on socket writes
+ and eliminate the copy to the CIFS buffer */
+ bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF;
+ if (bytes_sent > count)
+ bytes_sent = count;
pSMB->DataLengthHigh = 0;
pSMB->DataOffset =
cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
+ if(buf)
+ memcpy(pSMB->Data,buf,bytes_sent);
+ else if(ubuf)
+ copy_from_user(pSMB->Data,ubuf,bytes_sent);
+ else {
+ /* No buffer */
+ if(pSMB)
+ cifs_buf_release(pSMB);
+ return -EINVAL;
+ }
- memcpy(pSMB->Data,buf,pSMB->DataLengthLow);
-
- pSMB->ByteCount += pSMB->DataLengthLow + 1 /* pad */ ;
- pSMB->DataLengthLow = cpu_to_le16(pSMB->DataLengthLow);
- pSMB->hdr.smb_buf_length += pSMB->ByteCount;
- pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ byte_count = bytes_sent + 1 /* pad */ ;
+ pSMB->DataLengthLow = cpu_to_le16(bytes_sent);
+ pSMB->DataLengthHigh = 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, long_op);
return rc;
}
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
+ const int netfid, const unsigned int count,
+ const __u64 offset, unsigned int *nbytes, const char __user *buf,
+ const int long_op)
+{
+ int rc = -EACCES;
+ WRITE_REQ *pSMB = NULL;
+ WRITE_RSP *pSMBr = NULL;
+ /*int bytes_returned;*/
+ unsigned bytes_sent;
+ __u16 byte_count;
+
+ rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB);
+ pSMBr = (WRITE_RSP *)pSMB; /* BB removeme BB */
+
+ if (rc)
+ return rc;
+ /* tcon and ses pointer are checked in smb_init */
+ if (tcon->ses->server == NULL)
+ return -ECONNABORTED;
+
+ pSMB->AndXCommand = 0xFF; /* none */
+ pSMB->Fid = netfid;
+ pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
+ pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
+ pSMB->Reserved = 0xFFFFFFFF;
+ pSMB->WriteMode = 0;
+ pSMB->Remaining = 0;
+ bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF;
+ if (bytes_sent > count)
+ bytes_sent = count;
+ pSMB->DataLengthHigh = 0;
+ pSMB->DataOffset =
+ cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
+
+ byte_count = bytes_sent + 1 /* pad */ ;
+ pSMB->DataLengthLow = cpu_to_le16(bytes_sent);
+ pSMB->DataLengthHigh = 0;
+ pSMB->hdr.smb_buf_length += byte_count;
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+
+/* rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, buf, buflen, &bytes_returned, long_op); */ /* BB fixme BB */
+ if (rc) {
+ cFYI(1, ("Send error in write2 (large write) = %d", rc));
+ *nbytes = 0;
+ } else
+ *nbytes = le16_to_cpu(pSMBr->Count);
+
+ if (pSMB)
+ cifs_small_buf_release(pSMB);
+
+ /* Note: On -EAGAIN error only caller can retry on handle based calls
+ since file handle passed in no longer valid */
+
+ return rc;
+}
+#endif /* CIFS_EXPERIMENTAL */
+
int
CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
const __u16 smb_file_id, const __u64 len,
LOCK_RSP *pSMBr = NULL;
int bytes_returned;
int timeout = 0;
- __u64 temp;
+ __u16 count;
cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB,
pSMB->Timeout = 0;
} else if (waitFlag == TRUE) {
timeout = 3; /* blocking operation, no timeout */
- pSMB->Timeout = -1; /* blocking - do not time out */
+ pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
} else {
pSMB->Timeout = 0;
}
- pSMB->NumberOfLocks = cpu_to_le32(numLock);
- pSMB->NumberOfUnlocks = cpu_to_le32(numUnlock);
+ pSMB->NumberOfLocks = cpu_to_le16(numLock);
+ pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
pSMB->LockType = lockType;
pSMB->AndXCommand = 0xFF; /* none */
pSMB->Fid = smb_file_id; /* netfid stays le */
- pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
- temp = cpu_to_le64(len);
- pSMB->Locks[0].LengthLow = (__u32)(len & 0xFFFFFFFF);
- pSMB->Locks[0].LengthHigh = (__u32)(len>>32);
- temp = cpu_to_le64(offset);
- pSMB->Locks[0].OffsetLow = (__u32)(offset & 0xFFFFFFFF);
- pSMB->Locks[0].OffsetHigh = (__u32)(offset>>32);
- pSMB->ByteCount = sizeof (LOCKING_ANDX_RANGE);
- pSMB->hdr.smb_buf_length += pSMB->ByteCount;
- pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ if((numLock != 0) || (numUnlock != 0)) {
+ pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
+ /* BB where to store pid high? */
+ pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
+ pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
+ pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
+ pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
+ count = sizeof(LOCKING_ANDX_RANGE);
+ } else {
+ /* oplock break */
+ count = 0;
+ }
+ pSMB->hdr.smb_buf_length += count;
+ pSMB->ByteCount = cpu_to_le16(count);
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, timeout);
cFYI(1, ("In CIFSSMBClose"));
/* do not retry on dead session on close */
- rc = smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB,
- (void **) &pSMBr);
+ rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
+ pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
if(rc == -EAGAIN)
return 0;
if (rc)
cERROR(1, ("Send error in Close = %d", rc));
}
}
+
if (pSMB)
- cifs_buf_release(pSMB);
+ cifs_small_buf_release(pSMB);
/* Since session is dead, file will be closed on server already */
if(rc == -EAGAIN)
RENAME_RSP *pSMBr = NULL;
int bytes_returned;
int name_len, name_len2;
+ __u16 count;
cFYI(1, ("In CIFSSMBRename"));
renameRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
+ cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, PATH_MAX
/* find define for this maxpathcomponent */
, nls_codepage);
name_len++; /* trailing null */
pSMB->OldFileName[name_len + 1] = 0x00;
name_len2 =
cifs_strtoUCS((wchar_t *) & pSMB->
- OldFileName[name_len + 2], toName, 530,
+ OldFileName[name_len + 2], toName, PATH_MAX,
nls_codepage);
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
name_len2 *= 2; /* convert to bytes */
} else { /* BB improve the check for buffer overruns BB */
- name_len = strnlen(fromName, 530);
+ name_len = strnlen(fromName, PATH_MAX);
name_len++; /* trailing null */
strncpy(pSMB->OldFileName, fromName, name_len);
- name_len2 = strnlen(toName, 530);
+ name_len2 = strnlen(toName, PATH_MAX);
name_len2++; /* trailing null */
pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
name_len2++; /* signature byte */
}
- pSMB->ByteCount = 1 /* 1st signature byte */ + name_len + name_len2;
- pSMB->hdr.smb_buf_length += pSMB->ByteCount;
- pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ count = 1 /* 1st signature byte */ + name_len + name_len2;
+ pSMB->hdr.smb_buf_length += count;
+ pSMB->ByteCount = cpu_to_le16(count);
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cFYI(1, ("Send error in rename = %d", rc));
+ }
+
+#ifdef CONFIG_CIFS_STATS
+ else {
+ atomic_inc(&tcon->num_renames);
}
+#endif
+
if (pSMB)
cifs_buf_release(pSMB);
int rc = 0;
int bytes_returned = 0;
int len_of_str;
+ __u16 params, param_offset, offset, count, byte_count;
cFYI(1, ("Rename to File by handle"));
rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
if (rc)
return rc;
- pSMB->ParameterCount = 6;
+ params = 6;
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
pSMB->Timeout = 0;
pSMB->Reserved2 = 0;
- pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
- Fid) - 4;
- pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+ param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
+ offset = param_offset + params;
- data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
+ data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
rename_info = (struct set_file_rename *) data_offset;
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
pSMB->SetupCount = 1;
pSMB->Reserved3 = 0;
pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
- pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount;
- pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+ byte_count = 3 /* pad */ + params;
+ pSMB->ParameterCount = cpu_to_le16(params);
pSMB->TotalParameterCount = pSMB->ParameterCount;
- pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
- pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+ pSMB->ParameterOffset = cpu_to_le16(param_offset);
+ pSMB->DataOffset = cpu_to_le16(offset);
/* construct random name ".cifs_tmp<inodenum><mid>" */
rename_info->overwrite = cpu_to_le32(1);
rename_info->root_fid = 0;
sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, dummy_string, 24, nls_codepage);
} else {
- len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, 530, nls_codepage);
+ len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, PATH_MAX, nls_codepage);
}
rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
- pSMB->DataCount = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
- pSMB->ByteCount += pSMB->DataCount;
- pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
+ count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
+ byte_count += count;
+ pSMB->DataCount = cpu_to_le16(count);
pSMB->TotalDataCount = pSMB->DataCount;
pSMB->Fid = netfid;
pSMB->InformationLevel =
cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
pSMB->Reserved4 = 0;
- pSMB->hdr.smb_buf_length += pSMB->ByteCount;
- pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ pSMB->hdr.smb_buf_length += byte_count;
+ pSMB->ByteCount = cpu_to_le16(byte_count);
rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cFYI(1,("Send error in Rename (by file handle) = %d", rc));
}
-
+#ifdef CONFIG_CIFS_STATS
+ else {
+ atomic_inc(&pTcon->num_t2renames);
+ }
+#endif
if (pSMB)
cifs_buf_release(pSMB);
COPY_RSP *pSMBr = NULL;
int bytes_returned;
int name_len, name_len2;
+ __u16 count;
cFYI(1, ("In CIFSSMBCopy"));
copyRetry:
pSMB->BufferFormat = 0x04;
pSMB->Tid2 = target_tid;
- if(flags & COPY_TREE)
- pSMB->Flags |= COPY_TREE;
- pSMB->Flags = cpu_to_le16(pSMB->Flags);
+ pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = cifs_strtoUCS((wchar_t *) pSMB->OldFileName,
fromName,
- 530 /* find define for this maxpathcomponent */,
+ PATH_MAX /* find define for this maxpathcomponent */,
nls_codepage);
name_len++; /* trailing null */
name_len *= 2;
/* protocol requires ASCII signature byte on Unicode string */
pSMB->OldFileName[name_len + 1] = 0x00;
name_len2 = cifs_strtoUCS((wchar_t *) & pSMB->
- OldFileName[name_len + 2], toName, 530,
+ OldFileName[name_len + 2], toName, PATH_MAX,
nls_codepage);
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
name_len2 *= 2; /* convert to bytes */
} else { /* BB improve the check for buffer overruns BB */
- name_len = strnlen(fromName, 530);
+ name_len = strnlen(fromName, PATH_MAX);
name_len++; /* trailing null */
strncpy(pSMB->OldFileName, fromName, name_len);
- name_len2 = strnlen(toName, 530);
+ name_len2 = strnlen(toName, PATH_MAX);
name_len2++; /* trailing null */
pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
name_len2++; /* signature byte */
}
- pSMB->ByteCount = 1 /* 1st signature byte */ + name_len + name_len2;
- pSMB->hdr.smb_buf_length += pSMB->ByteCount;
- pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ count = 1 /* 1st signature byte */ + name_len + name_len2;
+ pSMB->hdr.smb_buf_length += count;
+ pSMB->ByteCount = cpu_to_le16(count);
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cFYI(1, ("Send error in copy = %d with %d files copied",
- rc, pSMBr->CopyCount));
+ rc, le16_to_cpu(pSMBr->CopyCount)));
}
if (pSMB)
cifs_buf_release(pSMB);
int name_len_target;
int rc = 0;
int bytes_returned = 0;
+ __u16 params, param_offset, offset, byte_count;
cFYI(1, ("In Symlink Unix style"));
createSymLinkRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, 530
+ cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, PATH_MAX
/* 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(fromName, 530);
+ name_len = strnlen(fromName, PATH_MAX);
name_len++; /* trailing null */
strncpy(pSMB->FileName, fromName, name_len);
}
- pSMB->ParameterCount = 6 + name_len;
+ params = 6 + name_len;
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
pSMB->Timeout = 0;
pSMB->Reserved2 = 0;
- pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+ param_offset = offsetof(struct smb_com_transaction2_spi_req,
InformationLevel) - 4;
- pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+ offset = param_offset + params;
- data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
+ data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len_target =
- cifs_strtoUCS((wchar_t *) data_offset, toName, 530
+ cifs_strtoUCS((wchar_t *) data_offset, toName, PATH_MAX
/* find define for this maxpathcomponent */
, nls_codepage);
name_len_target++; /* trailing null */
name_len_target *= 2;
} else { /* BB improve the check for buffer overruns BB */
- name_len_target = strnlen(toName, 530);
+ name_len_target = strnlen(toName, PATH_MAX);
name_len_target++; /* trailing null */
strncpy(data_offset, toName, name_len_target);
}
- pSMB->DataCount = name_len_target;
pSMB->MaxParameterCount = cpu_to_le16(2);
/* BB find exact max on data count below from sess */
pSMB->MaxDataCount = cpu_to_le16(1000);
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);
- pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+ byte_count = 3 /* pad */ + params + name_len_target;
+ pSMB->DataCount = cpu_to_le16(name_len_target);
+ pSMB->ParameterCount = cpu_to_le16(params);
pSMB->TotalDataCount = pSMB->DataCount;
pSMB->TotalParameterCount = pSMB->ParameterCount;
- pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
- pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+ pSMB->ParameterOffset = cpu_to_le16(param_offset);
+ pSMB->DataOffset = cpu_to_le16(offset);
pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
pSMB->Reserved4 = 0;
- pSMB->hdr.smb_buf_length += pSMB->ByteCount;
- pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ 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) {
int name_len_target;
int rc = 0;
int bytes_returned = 0;
+ __u16 params, param_offset, offset, byte_count;
cFYI(1, ("In Create Hard link Unix style"));
createHardLinkRetry:
return rc;
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, toName, 530
+ name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, toName, PATH_MAX
/* 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(toName, 530);
+ name_len = strnlen(toName, PATH_MAX);
name_len++; /* trailing null */
strncpy(pSMB->FileName, toName, name_len);
}
- pSMB->ParameterCount = 6 + name_len;
+ params = 6 + name_len;
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
pSMB->Timeout = 0;
pSMB->Reserved2 = 0;
- pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+ param_offset = offsetof(struct smb_com_transaction2_spi_req,
InformationLevel) - 4;
- pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+ offset = param_offset + params;
- data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
+ data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len_target =
- cifs_strtoUCS((wchar_t *) data_offset, fromName, 530
+ cifs_strtoUCS((wchar_t *) data_offset, fromName, PATH_MAX
/* find define for this maxpathcomponent */
, nls_codepage);
name_len_target++; /* trailing null */
name_len_target *= 2;
} else { /* BB improve the check for buffer overruns BB */
- name_len_target = strnlen(fromName, 530);
+ name_len_target = strnlen(fromName, PATH_MAX);
name_len_target++; /* trailing null */
strncpy(data_offset, fromName, name_len_target);
}
- pSMB->DataCount = name_len_target;
pSMB->MaxParameterCount = cpu_to_le16(2);
/* BB find exact max on data count below from sess*/
pSMB->MaxDataCount = cpu_to_le16(1000);
pSMB->SetupCount = 1;
pSMB->Reserved3 = 0;
pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
- pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
- pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+ byte_count = 3 /* pad */ + params + name_len_target;
+ pSMB->ParameterCount = cpu_to_le16(params);
pSMB->TotalParameterCount = pSMB->ParameterCount;
- pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
+ pSMB->DataCount = cpu_to_le16(name_len_target);
pSMB->TotalDataCount = pSMB->DataCount;
- pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
- pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+ pSMB->ParameterOffset = cpu_to_le16(param_offset);
+ pSMB->DataOffset = cpu_to_le16(offset);
pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
pSMB->Reserved4 = 0;
- pSMB->hdr.smb_buf_length += pSMB->ByteCount;
- pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ 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) {
RENAME_RSP *pSMBr = NULL;
int bytes_returned;
int name_len, name_len2;
+ __u16 count;
cFYI(1, ("In CIFSCreateHardLink"));
winCreateHardLinkRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
+ cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, PATH_MAX
/* find define for this maxpathcomponent */
, nls_codepage);
name_len++; /* trailing null */
pSMB->OldFileName[name_len + 1] = 0x04;
name_len2 =
cifs_strtoUCS((wchar_t *) & pSMB->
- OldFileName[name_len + 2], toName, 530,
+ OldFileName[name_len + 2], toName, PATH_MAX,
nls_codepage);
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
name_len2 *= 2; /* convert to bytes */
} else { /* BB improve the check for buffer overruns BB */
- name_len = strnlen(fromName, 530);
+ name_len = strnlen(fromName, PATH_MAX);
name_len++; /* trailing null */
strncpy(pSMB->OldFileName, fromName, name_len);
- name_len2 = strnlen(toName, 530);
+ name_len2 = strnlen(toName, PATH_MAX);
name_len2++; /* trailing null */
pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
name_len2++; /* signature byte */
}
- pSMB->ByteCount = 1 /* string type byte */ + name_len + name_len2;
- pSMB->hdr.smb_buf_length += pSMB->ByteCount;
- pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ count = 1 /* string type byte */ + name_len + name_len2;
+ pSMB->hdr.smb_buf_length += count;
+ pSMB->ByteCount = cpu_to_le16(count);
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
int rc = 0;
int bytes_returned;
int name_len;
+ __u16 params, byte_count;
cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
+ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
/* 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(searchName, 530);
+ name_len = strnlen(searchName, PATH_MAX);
name_len++; /* trailing null */
strncpy(pSMB->FileName, searchName, name_len);
}
- pSMB->TotalParameterCount =
- 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
+ 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->SetupCount = 1;
pSMB->Reserved3 = 0;
pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
- pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
- pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+ byte_count = params + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(params);
pSMB->ParameterCount = pSMB->TotalParameterCount;
pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
pSMB->Reserved4 = 0;
- pSMB->hdr.smb_buf_length += pSMB->ByteCount;
- pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ 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 QuerySymLinkInfo = %d", rc));
- } else { /* decode response */
- pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
- pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
- if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
+ } 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);
+
if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = UniStrnlen((wchar_t *) ((char *)
- &pSMBr->hdr.Protocol +pSMBr->DataOffset),
- min_t(const int, buflen,pSMBr->DataCount) / 2);
+ &pSMBr->hdr.Protocol +data_offset),
+ min_t(const int, buflen,count) / 2);
cifs_strfromUCS_le(symlinkinfo,
(wchar_t *) ((char *)&pSMBr->hdr.Protocol +
- pSMBr->DataOffset),
+ data_offset),
name_len, nls_codepage);
} else {
strncpy(symlinkinfo,
(char *) &pSMBr->hdr.Protocol +
- pSMBr->DataOffset,
- min_t(const int, buflen, pSMBr->DataCount));
+ data_offset,
+ min_t(const int, buflen, count));
}
symlinkinfo[buflen] = 0;
/* just in case so calling code does not go off the end of buffer */
if (rc) {
cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
} else { /* decode response */
- pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
- pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
- if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
+ __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
+ __u32 data_count = le32_to_cpu(pSMBr->DataCount);
+ if ((pSMBr->ByteCount < 2) || (data_offset > 512))
/* BB also check enough total bytes returned */
rc = -EIO; /* bad smb */
else {
- if(pSMBr->DataCount && (pSMBr->DataCount < 2048)) {
+ if(data_count && (data_count < 2048)) {
/* could also validate reparse tag && better check name length */
struct reparse_data * reparse_buf = (struct reparse_data *)
- ((char *)&pSMBr->hdr.Protocol + pSMBr->DataOffset);
+ ((char *)&pSMBr->hdr.Protocol + data_offset);
if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = UniStrnlen((wchar_t *)
(reparse_buf->LinkNamesBuf +
return rc;
}
+#ifdef CONFIG_CIFS_POSIX
+
+/*Convert an Access Control Entry from wire format to local POSIX xattr format*/
+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)le64_to_cpu(cifs_ace->cifs_uid);
+ /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
+
+ return;
+}
+
+/* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
+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((buflen == 0) || (local_acl == NULL)) {
+ /* used to query ACL EA size */
+ } else if(size > buflen) {
+ return -ERANGE;
+ } else /* buffer big enough */ {
+ 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;
+}
+
+__u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
+ const posix_acl_xattr_entry * local_ace)
+{
+ __u16 rc = 0; /* 0 = ACL converted ok */
+
+ cifs_ace->cifs_e_perm = (__u8)cpu_to_le16(local_ace->e_perm);
+ cifs_ace->cifs_e_tag = (__u8)cpu_to_le16(local_ace->e_tag);
+ /* BB is there a better way to handle the large uid? */
+ if(local_ace->e_id == -1) {
+ /* Probably no need to le convert -1 on any arch but can not hurt */
+ cifs_ace->cifs_uid = cpu_to_le64(-1);
+ } else
+ cifs_ace->cifs_uid = (__u64)cpu_to_le32(local_ace->e_id);
+ /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
+ return rc;
+}
+
+/* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
+__u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
+ const int acl_type)
+{
+ __u16 rc = 0;
+ struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
+ posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
+ int count;
+ int i;
+
+ if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
+ return 0;
+
+ count = posix_acl_xattr_count((size_t)buflen);
+ cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
+ count,buflen,local_acl->a_version));
+ if(local_acl->a_version != 2) {
+ cFYI(1,("unknown POSIX ACL version %d",local_acl->a_version));
+ return 0;
+ }
+ cifs_acl->version = cpu_to_le16(1);
+ if(acl_type == ACL_TYPE_ACCESS)
+ cifs_acl->access_entry_count = count;
+ else if(acl_type == ACL_TYPE_DEFAULT)
+ cifs_acl->default_entry_count = count;
+ else {
+ cFYI(1,("unknown ACL type %d",acl_type));
+ return 0;
+ }
+ for(i=0;i<count;i++) {
+ rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
+ &local_acl->a_entries[i]);
+ if(rc != 0) {
+ /* ACE not converted */
+ break;
+ }
+ }
+ if(rc == 0) {
+ rc = (__u16)(count * sizeof(struct cifs_posix_ace));
+ rc += sizeof(struct cifs_posix_acl);
+ /* BB add check to make sure ACL does not overflow SMB */
+ }
+ return rc;
+}
+
int
-CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
- const unsigned char *searchName,
- FILE_ALL_INFO * pFindData,
- const struct nls_table *nls_codepage)
+CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
+ const unsigned char *searchName,
+ char *acl_inf, const int buflen, const int acl_type,
+ const struct nls_table *nls_codepage)
{
-/* level 263 SMB_QUERY_FILE_ALL_INFO */
+/* 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));
- cFYI(1, ("In QPathInfo path %s", searchName));
-QPathInfoRetry:
+queryAclRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
- (void **) &pSMBr);
+ (void **) &pSMBr);
if (rc)
return rc;
-
+
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
- /* find define for this maxpathcomponent */
- , nls_codepage);
- name_len++; /* trailing null */
+ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
+ /* BB fixme 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(searchName, 530);
- name_len++; /* trailing null */
+ pSMB->FileName[name_len] = 0;
+ pSMB->FileName[name_len+1] = 0;
+ } else { /* BB improve the check for buffer overruns BB */
+ name_len = strnlen(searchName, PATH_MAX /* BB fixme */);
+ name_len++; /* trailing null */
strncpy(pSMB->FileName, searchName, name_len);
}
- pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
- name_len /* includes null */ ;
+ params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
pSMB->TotalDataCount = 0;
pSMB->MaxParameterCount = cpu_to_le16(2);
- pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
+ /* 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->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);
- pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
- pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+ byte_count = params + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(params);
pSMB->ParameterCount = pSMB->TotalParameterCount;
- pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
pSMB->Reserved4 = 0;
- pSMB->hdr.smb_buf_length += pSMB->ByteCount;
- pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ 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);
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
- cFYI(1, ("Send error in QPathInfo = %d", rc));
- } else { /* decode response */
- pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
+ 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 */
- /* BB we need to improve the validity checking
- of these trans2 responses */
- if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512))
- rc = -EIO; /* bad smb */
- else if (pFindData){
- memcpy((char *) pFindData,
- (char *) &pSMBr->hdr.Protocol +
- pSMBr->DataOffset, sizeof (FILE_ALL_INFO));
- } else
- rc = -ENOMEM;
+ rc = -EIO; /* bad smb */
+ else {
+ __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+ __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
+ rc = cifs_copy_posix_acl(acl_inf,
+ (char *)&pSMBr->hdr.Protocol+data_offset,
+ buflen,acl_type,count);
+ }
}
if (pSMB)
cifs_buf_release(pSMB);
if (rc == -EAGAIN)
- goto QPathInfoRetry;
-
+ goto queryAclRetry;
return rc;
}
int
-CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
- const unsigned char *searchName,
- FILE_UNIX_BASIC_INFO * pFindData,
- const struct nls_table *nls_codepage)
+CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
+ const unsigned char *fileName,
+ const char *local_acl, const int buflen, const int acl_type,
+ const struct nls_table *nls_codepage)
{
-/* SMB_QUERY_FILE_UNIX_BASIC */
- TRANSACTION2_QPI_REQ *pSMB = NULL;
- TRANSACTION2_QPI_RSP *pSMBr = NULL;
+ struct smb_com_transaction2_spi_req *pSMB = NULL;
+ struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
+ char *parm_data;
+ int name_len;
int rc = 0;
int bytes_returned = 0;
- int name_len;
+ __u16 params, byte_count, data_count, param_offset, offset;
- cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
-UnixQPathInfoRetry:
+ cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
+setAclRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
- (void **) &pSMBr);
+ (void **) &pSMBr);
if (rc)
return rc;
-
- if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
- /* find define for this maxpathcomponent */
+ cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
+ /* BB fixme 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, PATH_MAX);
+ name_len++; /* trailing null */
+ strncpy(pSMB->FileName, fileName, name_len);
+ }
+ params = 6 + name_len;
+ 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;
+ param_offset = offsetof(struct smb_com_transaction2_spi_req,
+ InformationLevel) - 4;
+ offset = param_offset + params;
+ parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
+ pSMB->ParameterOffset = cpu_to_le16(param_offset);
+
+ /* convert to on the wire format for POSIX ACL */
+ data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
+
+ if(data_count == 0) {
+ rc = -EOPNOTSUPP;
+ goto setACLerrorExit;
+ }
+ pSMB->DataOffset = cpu_to_le16(offset);
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
+ byte_count = 3 /* pad */ + params + data_count;
+ pSMB->DataCount = cpu_to_le16(data_count);
+ pSMB->TotalDataCount = pSMB->DataCount;
+ pSMB->ParameterCount = cpu_to_le16(params);
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ 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, ("Set POSIX ACL returned %d", rc));
+ }
+
+setACLerrorExit:
+ if (pSMB)
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto setAclRetry;
+ return rc;
+}
+
+#endif
+
+int
+CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
+ const unsigned char *searchName,
+ FILE_ALL_INFO * pFindData,
+ const struct nls_table *nls_codepage)
+{
+/* level 263 SMB_QUERY_FILE_ALL_INFO */
+ 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 QPathInfo path %s", searchName)); */ /* BB fixme BB */
+QPathInfoRetry:
+ 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, PATH_MAX
+ /* 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(searchName, PATH_MAX);
+ name_len++; /* trailing null */
+ strncpy(pSMB->FileName, searchName, name_len);
+ }
+
+ params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
+ pSMB->TotalDataCount = 0;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
+ 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_FILE_ALL_INFO);
+ 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 QPathInfo = %d", rc));
+ } else { /* decode response */
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+ if (rc || (pSMBr->ByteCount < 40))
+ rc = -EIO; /* bad smb */
+ else if (pFindData){
+ __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+ memcpy((char *) pFindData,
+ (char *) &pSMBr->hdr.Protocol +
+ data_offset, sizeof (FILE_ALL_INFO));
+ } else
+ rc = -ENOMEM;
+ }
+ if (pSMB)
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto QPathInfoRetry;
+
+ return rc;
+}
+
+int
+CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
+ const unsigned char *searchName,
+ FILE_UNIX_BASIC_INFO * pFindData,
+ const struct nls_table *nls_codepage)
+{
+/* SMB_QUERY_FILE_UNIX_BASIC */
+ TRANSACTION2_QPI_REQ *pSMB = NULL;
+ TRANSACTION2_QPI_RSP *pSMBr = NULL;
+ int rc = 0;
+ int bytes_returned = 0;
+ int name_len;
+ __u16 params, byte_count;
+
+ cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
+UnixQPathInfoRetry:
+ 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, PATH_MAX
+ /* 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(searchName, 530);
+ name_len = strnlen(searchName, PATH_MAX);
name_len++; /* trailing null */
strncpy(pSMB->FileName, searchName, name_len);
}
- pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
- name_len /* includes null */ ;
+ params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
pSMB->TotalDataCount = 0;
pSMB->MaxParameterCount = cpu_to_le16(2);
/* BB find exact max SMB PDU from sess structure BB */
pSMB->SetupCount = 1;
pSMB->Reserved3 = 0;
pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
- pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
- pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+ byte_count = params + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(params);
pSMB->ParameterCount = pSMB->TotalParameterCount;
pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
pSMB->Reserved4 = 0;
- pSMB->hdr.smb_buf_length += pSMB->ByteCount;
- pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ 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 QPathInfo = %d", rc));
} else { /* decode response */
- pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
- /* BB also check if enough total bytes returned */
- if ((pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO)) ||
- (pSMBr->DataOffset > 512) ||
- (pSMBr->DataOffset < sizeof(struct smb_hdr))) {
- cFYI(1,("UnixQPathinfo invalid data offset %d bytes returned %d",
- (int)pSMBr->DataOffset,bytes_returned));
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+ if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
rc = -EIO; /* bad smb */
} else {
+ __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
memcpy((char *) pFindData,
(char *) &pSMBr->hdr.Protocol +
- pSMBr->DataOffset,
+ data_offset,
sizeof (FILE_UNIX_BASIC_INFO));
}
}
return rc;
}
+#ifdef CONFIG_CIFS_EXPERIMENTAL /* function unused at present */
int
CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
const char *searchName, FILE_ALL_INFO * findData,
int rc = 0;
int bytes_returned;
int name_len;
+ __u16 params, byte_count;
cFYI(1, ("In FindUnique"));
findUniqueRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
+ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
/* 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(searchName, 530);
+ name_len = strnlen(searchName, PATH_MAX);
name_len++; /* trailing null */
strncpy(pSMB->FileName, searchName, name_len);
}
- pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
+ params = 12 + name_len /* includes null */ ;
pSMB->TotalDataCount = 0; /* no EAs */
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
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 */
pSMB->Reserved3 = 0;
pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
- pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
- pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalDataCount);
+ byte_count = params + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(params);
pSMB->ParameterCount = pSMB->TotalParameterCount;
pSMB->SearchAttributes =
cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
pSMB->SearchFlags = cpu_to_le16(1);
pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
- pSMB->hdr.smb_buf_length += pSMB->ByteCount;
- pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ 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);
return rc;
}
+#endif /* CIFS_EXPERIMENTAL */
int
CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
int rc = 0;
int bytes_returned;
int name_len;
+ __u16 params, byte_count;
cFYI(1, ("In FindFirst"));
findFirstRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
+ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
/* 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(searchName, 530);
+ name_len = strnlen(searchName, PATH_MAX);
name_len++; /* trailing null */
strncpy(pSMB->FileName, searchName, name_len);
}
- pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
+ params = 12 + name_len /* includes null */ ;
pSMB->TotalDataCount = 0; /* no EAs */
pSMB->MaxParameterCount = cpu_to_le16(10);
pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
pSMB->Flags = 0;
pSMB->Timeout = 0;
pSMB->Reserved2 = 0;
- pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
- pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+ 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 */
pSMB->SearchAttributes =
cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
ATTR_DIRECTORY);
- pSMB->SearchCount = cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO)); /* should this be shrunk even more ? */
+ pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_DIRECTORY_INFO)); /* should this be shrunk even more ? */
pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
/* test for Unix extensions */
*pUnixFlag = FALSE;
}
pSMB->SearchStorageType = 0; /* BB what should we set this to? It is not clear if it matters BB */
- pSMB->hdr.smb_buf_length += pSMB->ByteCount;
- pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ 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) { /* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
cFYI(1, ("Error in FindFirst = %d", rc));
- } else { /* decode response */
+ } else {
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+ if(!rc) {
+ /* decode response */
/* BB add safety checks for these memcpys */
- if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
- *pUnicodeFlag = TRUE;
- else
- *pUnicodeFlag = FALSE;
- memcpy(findParms,
- (char *) &pSMBr->hdr.Protocol +
- le16_to_cpu(pSMBr->ParameterOffset),
- sizeof (T2_FFIRST_RSP_PARMS));
- /* search handle can stay LE and EAoffset not needed so not converted */
- findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
- findParms->LastNameOffset =
- le16_to_cpu(findParms->LastNameOffset);
- findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
- response_data =
- (char *) &pSMBr->hdr.Protocol +
- le16_to_cpu(pSMBr->DataOffset);
- memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
+ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
+ *pUnicodeFlag = TRUE;
+ else
+ *pUnicodeFlag = FALSE;
+ memcpy(findParms,
+ (char *) &pSMBr->hdr.Protocol +
+ le16_to_cpu(pSMBr->t2.ParameterOffset),
+ sizeof (T2_FFIRST_RSP_PARMS));
+ response_data =
+ (char *) &pSMBr->hdr.Protocol +
+ le16_to_cpu(pSMBr->t2.DataOffset);
+ memcpy(findData, response_data,
+ le16_to_cpu(pSMBr->t2.DataCount));
+ }
}
if (pSMB)
cifs_buf_release(pSMB);
return rc;
}
+/* xid, tcon, searchName and codepage are input parms, rest are returned */
+int
+CIFSFindFirst2(const int xid, struct cifsTconInfo *tcon,
+ const char *searchName,
+ const struct nls_table *nls_codepage,
+ __u16 * pnetfid,
+ struct cifs_search_info * psrch_inf)
+{
+/* level 257 SMB_ */
+ TRANSACTION2_FFIRST_REQ *pSMB = NULL;
+ TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
+ T2_FFIRST_RSP_PARMS * parms;
+ int rc = 0;
+ int bytes_returned = 0;
+ int name_len;
+ __u16 params, byte_count;
+
+ cFYI(1, ("In FindFirst2"));
+
+findFirst2Retry:
+ 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,
+ PATH_MAX, nls_codepage);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ pSMB->FileName[name_len] = 0; /* null terminate just in case */
+ pSMB->FileName[name_len+1] = 0;
+ } else { /* BB add check for overrun of SMB buf BB */
+ name_len = strnlen(searchName, PATH_MAX);
+ name_len++; /* trailing null */
+/* BB fix here and in unicode clause above ie
+ if(name_len > buffersize-header)
+ free buffer exit; BB */
+ strncpy(pSMB->FileName, searchName, name_len);
+ pSMB->FileName[name_len] = 0; /* just in case */
+ }
+
+ params = 12 + name_len /* includes null */ ;
+ pSMB->TotalDataCount = 0; /* no EAs */
+ pSMB->MaxParameterCount = cpu_to_le16(10);
+ pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
+ MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ 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->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
+ pSMB->SearchAttributes =
+ cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
+ ATTR_DIRECTORY);
+ pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
+ pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
+ CIFS_SEARCH_RETURN_RESUME);
+ pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
+
+ /* BB what should we set StorageType to? Does it matter? BB */
+ pSMB->SearchStorageType = 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) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
+ /* BB Add code to handle unsupported level rc */
+ cFYI(1, ("Error in FindFirst = %d", rc));
+
+ if (pSMB)
+ cifs_buf_release(pSMB);
+
+ /* BB eventually could optimize out free and realloc of buf */
+ /* for this case */
+ if (rc == -EAGAIN)
+ goto findFirst2Retry;
+ } else { /* decode response */
+ /* BB remember to free buffer if error BB */
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+ if(rc == 0) {
+ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
+ psrch_inf->unicode = TRUE;
+ else
+ psrch_inf->unicode = FALSE;
+
+ psrch_inf->ntwrk_buf_start = (char *)pSMBr;
+ psrch_inf->srch_entries_start =
+ (char *) &pSMBr->hdr.Protocol +
+ le16_to_cpu(pSMBr->t2.DataOffset);
+
+ parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
+ le16_to_cpu(pSMBr->t2.ParameterOffset));
+
+ if(parms->EndofSearch)
+ psrch_inf->endOfSearch = TRUE;
+ else
+ psrch_inf->endOfSearch = FALSE;
+
+ psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
+ psrch_inf->index_of_last_entry =
+ psrch_inf->entries_in_buffer;
+/*cFYI(1,("entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
+ *pnetfid = parms->SearchHandle;
+ } else {
+ if(pSMB)
+ cifs_buf_release(pSMB);
+ }
+ }
+
+ return rc;
+}
+
+int CIFSFindNext2(const int xid, struct cifsTconInfo *tcon,
+ __u16 searchHandle, struct cifs_search_info * psrch_inf)
+{
+ TRANSACTION2_FNEXT_REQ *pSMB = NULL;
+ TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
+ T2_FNEXT_RSP_PARMS * parms;
+ char *response_data;
+ int rc = 0;
+ int bytes_returned, name_len;
+ __u16 params, byte_count;
+
+ cFYI(1, ("In FindNext2"));
+
+ if(psrch_inf->endOfSearch == TRUE)
+ return -ENOENT;
+
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ params = 14; /* includes 2 bytes of null string, converted to LE below */
+ byte_count = 0;
+ pSMB->TotalDataCount = 0; /* no EAs */
+ pSMB->MaxParameterCount = cpu_to_le16(8);
+ pSMB->MaxDataCount =
+ cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
+ 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_fnext_req,SearchHandle) - 4);
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
+ pSMB->SearchHandle = searchHandle; /* always kept as le */
+ pSMB->SearchCount =
+ cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
+ /* test for Unix extensions */
+/* if (tcon->ses->capabilities & CAP_UNIX) {
+ pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
+ psrch_inf->info_level = SMB_FIND_FILE_UNIX;
+ } else {
+ pSMB->InformationLevel =
+ cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
+ psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
+ } */
+ pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
+ pSMB->ResumeKey = psrch_inf->resume_key;
+ pSMB->SearchFlags =
+ cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
+
+ name_len = psrch_inf->resume_name_len;
+ params += name_len;
+ if(name_len < PATH_MAX) {
+ memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
+ byte_count += name_len;
+ } else {
+ rc = -EINVAL;
+ goto FNext2_err_exit;
+ }
+ byte_count = params + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(params);
+ pSMB->ParameterCount = pSMB->TotalParameterCount;
+ 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) {
+ if (rc == -EBADF) {
+ psrch_inf->endOfSearch = TRUE;
+ rc = 0; /* search probably was closed at end of search above */
+ } else
+ cFYI(1, ("FindNext returned = %d", rc));
+ } else { /* decode response */
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+ if(rc == 0) {
+ /* BB fixme add lock for file (srch_info) struct here */
+ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
+ psrch_inf->unicode = TRUE;
+ else
+ psrch_inf->unicode = FALSE;
+ response_data = (char *) &pSMBr->hdr.Protocol +
+ le16_to_cpu(pSMBr->t2.ParameterOffset);
+ parms = (T2_FNEXT_RSP_PARMS *)response_data;
+ response_data = (char *)&pSMBr->hdr.Protocol +
+ le16_to_cpu(pSMBr->t2.DataOffset);
+ cifs_buf_release(psrch_inf->ntwrk_buf_start);
+ psrch_inf->srch_entries_start = response_data;
+ psrch_inf->ntwrk_buf_start = (char *)pSMB;
+ if(parms->EndofSearch)
+ psrch_inf->endOfSearch = TRUE;
+ else
+ psrch_inf->endOfSearch = FALSE;
+
+ psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
+ psrch_inf->index_of_last_entry +=
+ psrch_inf->entries_in_buffer;
+/* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
+
+ /* BB fixme add unlock here */
+ }
+
+ }
+
+ /* BB On error, should we leave previous search buf (and count and
+ last entry fields) intact or free the previous one? */
+
+ /* Note: On -EAGAIN error only caller can retry on handle based calls
+ since file handle passed in no longer valid */
+FNext2_err_exit:
+ if ((rc != 0) && pSMB)
+ cifs_buf_release(pSMB);
+
+ return rc;
+}
+
int
CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
FILE_DIRECTORY_INFO * findData, T2_FNEXT_RSP_PARMS * findParms,
char *response_data;
int rc = 0;
int bytes_returned;
+ __u16 params, byte_count;
cFYI(1, ("In FindNext"));
if (rc)
return rc;
- pSMB->TotalParameterCount = 14; /* includes 2 bytes of null string, converted to LE below */
+ params = 14; /* includes 2 bytes of null string, converted to LE below */
+ byte_count = 0;
pSMB->TotalDataCount = 0; /* no EAs */
pSMB->MaxParameterCount = cpu_to_le16(8);
pSMB->MaxDataCount =
pSMB->Flags = 0;
pSMB->Timeout = 0;
pSMB->Reserved2 = 0;
- pSMB->ParameterOffset = cpu_to_le16(offsetof(
- struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
+ pSMB->ParameterOffset = cpu_to_le16(
+ offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
pSMB->DataCount = 0;
pSMB->DataOffset = 0;
pSMB->SetupCount = 1;
pSMB->SearchHandle = searchHandle; /* always kept as le */
findParms->SearchCount = 0; /* set to zero in case of error */
pSMB->SearchCount =
- cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO));
+ cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
/* test for Unix extensions */
if (tcon->ses->capabilities & CAP_UNIX) {
pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
pSMB->SearchFlags =
cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
/* BB add check to make sure we do not cross end of smb */
- if(name_len < CIFS_MAX_MSGSIZE) {
+ if(name_len < PATH_MAX) {
memcpy(pSMB->ResumeFileName, resume_file_name, name_len);
- pSMB->ByteCount += name_len;
+ byte_count += name_len;
}
- pSMB->TotalParameterCount += name_len;
- pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
- pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+ params += name_len;
+ byte_count = params + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(params);
pSMB->ParameterCount = pSMB->TotalParameterCount;
/* BB improve error handling here */
- pSMB->hdr.smb_buf_length += pSMB->ByteCount;
- pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ 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);
else
cFYI(1, ("FindNext returned = %d", rc));
} else { /* decode response */
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
/* BB add safety checks for these memcpys */
- if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
- *pUnicodeFlag = TRUE;
- else
- *pUnicodeFlag = FALSE;
- memcpy(findParms,
- (char *) &pSMBr->hdr.Protocol +
- le16_to_cpu(pSMBr->ParameterOffset),
- sizeof (T2_FNEXT_RSP_PARMS));
- findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
- findParms->LastNameOffset =
- le16_to_cpu(findParms->LastNameOffset);
- findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
- response_data =
- (char *) &pSMBr->hdr.Protocol +
- le16_to_cpu(pSMBr->DataOffset);
- memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
+ if(rc == 0) {
+ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
+ *pUnicodeFlag = TRUE;
+ else
+ *pUnicodeFlag = FALSE;
+ memcpy(findParms,
+ (char *) &pSMBr->hdr.Protocol +
+ le16_to_cpu(pSMBr->t2.ParameterOffset),
+ sizeof (T2_FNEXT_RSP_PARMS));
+ response_data =
+ (char *) &pSMBr->hdr.Protocol +
+ le16_to_cpu(pSMBr->t2.DataOffset);
+ memcpy(findData,response_data,le16_to_cpu(pSMBr->t2.DataCount));
+ }
}
if (pSMB)
cifs_buf_release(pSMB);
{
int rc = 0;
FINDCLOSE_REQ *pSMB = NULL;
- CLOSE_RSP *pSMBr = NULL;
+ CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
int bytes_returned;
cFYI(1, ("In CIFSSMBFindClose"));
- rc = smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **) &pSMB,
- (void **) &pSMBr);
+ rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
+ pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
/* no sense returning error if session restarted
file handle has been closed */
if(rc == -EAGAIN)
cERROR(1, ("Send error in FindClose = %d", rc));
}
if (pSMB)
- cifs_buf_release(pSMB);
+ cifs_small_buf_release(pSMB);
/* Since session is dead, search handle closed on server already */
if (rc == -EAGAIN)
return rc;
}
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+int
+CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
+ const unsigned char *searchName,
+ __u64 * inode_number,
+ const struct nls_table *nls_codepage)
+{
+ int rc = 0;
+ TRANSACTION2_QPI_REQ *pSMB = NULL;
+ TRANSACTION2_QPI_RSP *pSMBr = NULL;
+
+ cFYI(1,("In GetSrvInodeNumber for %s",searchName));
+ if(tcon == NULL)
+ return -ENODEV;
+
+ cFYI(1, ("In QPathInfo path %s", searchName));
+GetInodeNumberRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+/* BB add missing code here */
+
+ if (pSMB)
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto GetInodeNumberRetry;
+ return rc;
+}
+#endif /* CIFS_EXPERIMENTAL */
+
int
CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
const unsigned char *searchName,
int name_len;
unsigned int i;
char * temp;
+ __u16 params, byte_count;
*number_of_UNC_in_array = 0;
*targetUNCs = NULL;
if (ses == NULL)
return -ENODEV;
getDFSRetry:
- rc = smb_init(SMB_COM_TRANSACTION2, 15, 0, (void **) &pSMB,
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
return rc;
pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
name_len =
cifs_strtoUCS((wchar_t *) pSMB->RequestFileName,
- searchName, 530
+ searchName, PATH_MAX
/* 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(searchName, 530);
+ name_len = strnlen(searchName, PATH_MAX);
name_len++; /* trailing null */
strncpy(pSMB->RequestFileName, searchName, name_len);
}
- pSMB->ParameterCount = 2 /* level */ + name_len /*includes null */ ;
+ params = 2 /* level */ + name_len /*includes null */ ;
pSMB->TotalDataCount = 0;
pSMB->DataCount = 0;
pSMB->DataOffset = 0;
pSMB->SetupCount = 1;
pSMB->Reserved3 = 0;
pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
- pSMB->ByteCount = pSMB->ParameterCount + 3 /* pad */ ;
- pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+ byte_count = params + 3 /* pad */ ;
+ pSMB->ParameterCount = cpu_to_le16(params);
pSMB->TotalParameterCount = pSMB->ParameterCount;
pSMB->MaxReferralLevel = cpu_to_le16(3);
- pSMB->hdr.smb_buf_length += pSMB->ByteCount;
- pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ pSMB->hdr.smb_buf_length += byte_count;
+ pSMB->ByteCount = cpu_to_le16(byte_count);
rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
cFYI(1, ("Send error in GetDFSRefer = %d", rc));
} else { /* decode response */
/* BB Add logic to parse referrals here */
- pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
- pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
- cFYI(1,
- ("Decoding GetDFSRefer response. BCC: %d Offset %d",
- pSMBr->ByteCount, pSMBr->DataOffset));
- if ((pSMBr->ByteCount < 17) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */
- rc = -EIO; /* bad smb */
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+ if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
+ rc = -EIO; /* bad smb */
else {
+ __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+ __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
+
+ cFYI(1,
+ ("Decoding GetDFSRefer response. BCC: %d Offset %d",
+ pSMBr->ByteCount, data_offset));
referrals =
(struct dfs_referral_level_3 *)
(8 /* sizeof start of data block */ +
- pSMBr->DataOffset +
+ data_offset +
(char *) &pSMBr->hdr.Protocol);
- cFYI(1,("num_referrals: %d dfs flags: 0x%x ... \nfor referral one refer size: 0x%x srv type: 0x%x refer flags: 0x%x ttl: 0x%x",pSMBr->NumberOfReferrals,pSMBr->DFSFlags, referrals->ReferralSize,referrals->ServerType,referrals->ReferralFlags,referrals->TimeToLive));
+ cFYI(1,("num_referrals: %d dfs flags: 0x%x ... \nfor referral one refer size: 0x%x srv type: 0x%x refer flags: 0x%x ttl: 0x%x",
+ le16_to_cpu(pSMBr->NumberOfReferrals),le16_to_cpu(pSMBr->DFSFlags), le16_to_cpu(referrals->ReferralSize),le16_to_cpu(referrals->ServerType),le16_to_cpu(referrals->ReferralFlags),le16_to_cpu(referrals->TimeToLive)));
/* BB This field is actually two bytes in from start of
data block so we could do safety check that DataBlock
begins at address of pSMBr->NumberOfReferrals */
name_len = 0;
for(i=0;i<*number_of_UNC_in_array;i++) {
/* make sure that DfsPathOffset not past end */
- referrals->DfsPathOffset = le16_to_cpu(referrals->DfsPathOffset);
- if(referrals->DfsPathOffset > pSMBr->DataCount) {
+ __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
+ if (offset > data_count) {
/* if invalid referral, stop here and do
not try to copy any more */
*number_of_UNC_in_array = i;
break;
}
- temp = ((char *)referrals) + referrals->DfsPathOffset;
+ temp = ((char *)referrals) + offset;
if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len += UniStrnlen((wchar_t *)temp,pSMBr->DataCount);
+ name_len += UniStrnlen((wchar_t *)temp,data_count);
} else {
- name_len += strnlen(temp,pSMBr->DataCount);
+ name_len += strnlen(temp,data_count);
}
referrals++;
/* BB add check that referral pointer does not fall off end PDU */
/* BB add check for name_len bigger than bcc */
*targetUNCs =
kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
+ if(*targetUNCs == NULL) {
+ rc = -ENOMEM;
+ goto GetDFSRefExit;
+ }
/* copy the ref strings */
referrals =
(struct dfs_referral_level_3 *)
(8 /* sizeof data hdr */ +
- pSMBr->DataOffset +
+ data_offset +
(char *) &pSMBr->hdr.Protocol);
for(i=0;i<*number_of_UNC_in_array;i++) {
- temp = ((char *)referrals) + referrals->DfsPathOffset;
+ temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
cifs_strfromUCS_le(*targetUNCs,
(wchar_t *) temp, name_len, nls_codepage);
}
}
+GetDFSRefExit:
if (pSMB)
cifs_buf_release(pSMB);
FILE_SYSTEM_INFO *response_data;
int rc = 0;
int bytes_returned = 0;
+ __u16 params, byte_count;
cFYI(1, ("In QFSInfo"));
QFSInfoRetry:
if (rc)
return rc;
- pSMB->TotalParameterCount = 2; /* level */
+ params = 2; /* level */
pSMB->TotalDataCount = 0;
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
pSMB->Flags = 0;
pSMB->Timeout = 0;
pSMB->Reserved2 = 0;
- pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
- pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+ 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_qfsi_req, InformationLevel) - 4);
pSMB->Reserved3 = 0;
pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
- pSMB->hdr.smb_buf_length += pSMB->ByteCount;
- pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ 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) {
cERROR(1, ("Send error in QFSInfo = %d", rc));
} else { /* decode response */
- pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
- cFYI(1,
- ("Decoding qfsinfo response. BCC: %d Offset %d",
- pSMBr->ByteCount, pSMBr->DataOffset));
- if ((pSMBr->ByteCount < 24) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+ if (rc || (pSMBr->ByteCount < 24)) /* BB alsO CHEck enough total bytes returned */
rc = -EIO; /* bad smb */
else {
+ __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+ cFYI(1,
+ ("Decoding qfsinfo response. BCC: %d Offset %d",
+ pSMBr->ByteCount, data_offset));
+
response_data =
(FILE_SYSTEM_INFO
*) (((char *) &pSMBr->hdr.Protocol) +
- pSMBr->DataOffset);
+ data_offset);
FSData->f_bsize =
le32_to_cpu(response_data->BytesPerSector) *
le32_to_cpu(response_data->
}
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 */
FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
int rc = 0;
int bytes_returned = 0;
+ __u16 params, byte_count;
cFYI(1, ("In QFSAttributeInfo"));
QFSAttributeRetry:
if (rc)
return rc;
- pSMB->TotalParameterCount = 2; /* level */
+ params = 2; /* level */
pSMB->TotalDataCount = 0;
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
pSMB->Flags = 0;
pSMB->Timeout = 0;
pSMB->Reserved2 = 0;
- pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
- pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+ 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_qfsi_req, InformationLevel) - 4);
pSMB->Reserved3 = 0;
pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
- pSMB->hdr.smb_buf_length += pSMB->ByteCount;
- pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ 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) {
cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
} else { /* decode response */
- pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
- if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) { /* BB also check enough bytes returned */
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+ if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
rc = -EIO; /* bad smb */
} else {
+ __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
response_data =
(FILE_SYSTEM_ATTRIBUTE_INFO
*) (((char *) &pSMBr->hdr.Protocol) +
- pSMBr->DataOffset);
- response_data->Attributes = le32_to_cpu(response_data->Attributes);
- response_data->MaxPathNameComponentLength =
- le32_to_cpu(response_data->MaxPathNameComponentLength);
- response_data->FileSystemNameLen =
- le32_to_cpu(response_data->FileSystemNameLen);
+ data_offset);
memcpy(&tcon->fsAttrInfo, response_data,
sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
}
}
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 */
FILE_SYSTEM_DEVICE_INFO *response_data;
int rc = 0;
int bytes_returned = 0;
+ __u16 params, byte_count;
cFYI(1, ("In QFSDeviceInfo"));
QFSDeviceRetry:
if (rc)
return rc;
- pSMB->TotalParameterCount = 2; /* level */
+ params = 2; /* level */
pSMB->TotalDataCount = 0;
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
pSMB->Flags = 0;
pSMB->Timeout = 0;
pSMB->Reserved2 = 0;
- pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
- pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+ 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_qfsi_req, InformationLevel) - 4);
pSMB->Reserved3 = 0;
pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
- pSMB->hdr.smb_buf_length += pSMB->ByteCount;
- pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ 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 QFSDeviceInfo = %d", rc));
} else { /* decode response */
- pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
- if ((pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO))
- || (pSMBr->DataOffset > 512))
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+ if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
rc = -EIO; /* bad smb */
else {
+ __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
response_data =
(FILE_SYSTEM_DEVICE_INFO
*) (((char *) &pSMBr->hdr.Protocol) +
- pSMBr->DataOffset);
- response_data->DeviceType =
- le32_to_cpu(response_data->DeviceType);
- response_data->DeviceCharacteristics =
- le32_to_cpu(response_data->DeviceCharacteristics);
+ data_offset);
memcpy(&tcon->fsDevInfo, response_data,
sizeof (FILE_SYSTEM_DEVICE_INFO));
}
}
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 */
FILE_SYSTEM_UNIX_INFO *response_data;
int rc = 0;
int bytes_returned = 0;
+ __u16 params, byte_count;
cFYI(1, ("In QFSUnixInfo"));
QFSUnixRetry:
if (rc)
return rc;
- pSMB->ParameterCount = 2; /* level */
+ params = 2; /* level */
pSMB->TotalDataCount = 0;
pSMB->DataCount = 0;
pSMB->DataOffset = 0;
pSMB->Flags = 0;
pSMB->Timeout = 0;
pSMB->Reserved2 = 0;
- pSMB->ByteCount = pSMB->ParameterCount + 1 /* pad */ ;
- pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+ byte_count = params + 1 /* pad */ ;
+ pSMB->ParameterCount = cpu_to_le16(params);
pSMB->TotalParameterCount = pSMB->ParameterCount;
pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
smb_com_transaction2_qfsi_req, InformationLevel) - 4);
pSMB->Reserved3 = 0;
pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
- pSMB->hdr.smb_buf_length += pSMB->ByteCount;
- pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ 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) {
cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
} else { /* decode response */
- pSMBr->DataOffset = cpu_to_le16(pSMBr->DataOffset);
- if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) {
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+ if (rc || (pSMBr->ByteCount < 13)) {
rc = -EIO; /* bad smb */
} else {
+ __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
response_data =
(FILE_SYSTEM_UNIX_INFO
*) (((char *) &pSMBr->hdr.Protocol) +
- pSMBr->DataOffset);
- response_data->MajorVersionNumber =
- le16_to_cpu(response_data->MajorVersionNumber);
- response_data->MinorVersionNumber =
- le16_to_cpu(response_data->MinorVersionNumber);
- response_data->Capability =
- le64_to_cpu(response_data->Capability);
+ data_offset);
memcpy(&tcon->fsUnixInfo, response_data,
sizeof (FILE_SYSTEM_UNIX_INFO));
}
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;
int name_len;
int rc = 0;
int bytes_returned = 0;
+ __u16 params, byte_count, data_count, param_offset, offset;
cFYI(1, ("In SetEOF"));
SetEOFRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
+ cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
/* 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 = strnlen(fileName, PATH_MAX);
name_len++; /* trailing null */
strncpy(pSMB->FileName, fileName, name_len);
}
- pSMB->ParameterCount = 6 + name_len;
- pSMB->DataCount = sizeof (struct file_end_of_file_info);
+ params = 6 + name_len;
+ data_count = sizeof (struct file_end_of_file_info);
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
pSMB->MaxSetupCount = 0;
pSMB->Flags = 0;
pSMB->Timeout = 0;
pSMB->Reserved2 = 0;
- pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+ param_offset = offsetof(struct smb_com_transaction2_spi_req,
InformationLevel) - 4;
- pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+ offset = param_offset + params;
if(SetAllocation) {
if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
pSMB->InformationLevel =
parm_data =
(struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
- pSMB->DataOffset);
- pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
- pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+ offset);
+ pSMB->ParameterOffset = cpu_to_le16(param_offset);
+ pSMB->DataOffset = cpu_to_le16(offset);
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);
+ byte_count = 3 /* pad */ + params + data_count;
+ pSMB->DataCount = cpu_to_le16(data_count);
pSMB->TotalDataCount = pSMB->DataCount;
- pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+ pSMB->ParameterCount = cpu_to_le16(params);
pSMB->TotalParameterCount = pSMB->ParameterCount;
pSMB->Reserved4 = 0;
- pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ pSMB->hdr.smb_buf_length += byte_count;
parm_data->FileSize = cpu_to_le64(size);
- pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ 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) {
struct file_end_of_file_info *parm_data;
int rc = 0;
int bytes_returned = 0;
- __u32 tmp;
+ __u16 params, param_offset, offset, byte_count, count;
cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
(long long)size));
if (rc)
return rc;
- tmp = cpu_to_le32(pid_of_opener); /* override pid of current process
- so network fid will be valid */
- pSMB->hdr.Pid = tmp & 0xFFFF;
- tmp >>= 16;
- pSMB->hdr.PidHigh = tmp & 0xFFFF;
+ pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
+ pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
- pSMB->ParameterCount = 6;
+ params = 6;
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
pSMB->Timeout = 0;
pSMB->Reserved2 = 0;
- pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
- Fid) - 4;
- pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+ param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
+ offset = param_offset + params;
- data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
+ data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
- pSMB->DataCount = sizeof(struct file_end_of_file_info);
+ count = sizeof(struct file_end_of_file_info);
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
pSMB->SetupCount = 1;
pSMB->Reserved3 = 0;
pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
- pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
- pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
- pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+ byte_count = 3 /* pad */ + params + count;
+ pSMB->DataCount = cpu_to_le16(count);
+ pSMB->ParameterCount = cpu_to_le16(params);
pSMB->TotalDataCount = pSMB->DataCount;
pSMB->TotalParameterCount = pSMB->ParameterCount;
- pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
+ pSMB->ParameterOffset = cpu_to_le16(param_offset);
parm_data =
(struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
- pSMB->DataOffset);
- pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset); /* now safe to change to le */
+ offset);
+ pSMB->DataOffset = cpu_to_le16(offset);
parm_data->FileSize = cpu_to_le64(size);
pSMB->Fid = fid;
if(SetAllocation) {
cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
}
pSMB->Reserved4 = 0;
- pSMB->hdr.smb_buf_length += pSMB->ByteCount;
- pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ 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) {
}
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;
int rc = 0;
int bytes_returned = 0;
char *data_offset;
+ __u16 params, param_offset, offset, byte_count, count;
cFYI(1, ("In SetTimes"));
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
+ cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
/* 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 = strnlen(fileName, PATH_MAX);
name_len++; /* trailing null */
strncpy(pSMB->FileName, fileName, name_len);
}
- pSMB->ParameterCount = 6 + name_len;
- pSMB->DataCount = sizeof (FILE_BASIC_INFO);
+ params = 6 + name_len;
+ count = sizeof (FILE_BASIC_INFO);
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
pSMB->MaxSetupCount = 0;
pSMB->Flags = 0;
pSMB->Timeout = 0;
pSMB->Reserved2 = 0;
- pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+ param_offset = offsetof(struct smb_com_transaction2_spi_req,
InformationLevel) - 4;
- pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
- data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
- pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
- pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+ offset = param_offset + params;
+ data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
+ pSMB->ParameterOffset = cpu_to_le16(param_offset);
+ pSMB->DataOffset = cpu_to_le16(offset);
pSMB->SetupCount = 1;
pSMB->Reserved3 = 0;
pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
- pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
+ byte_count = 3 /* pad */ + params + count;
- pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
- pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+ pSMB->DataCount = cpu_to_le16(count);
+ pSMB->ParameterCount = cpu_to_le16(params);
pSMB->TotalDataCount = pSMB->DataCount;
pSMB->TotalParameterCount = pSMB->ParameterCount;
if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
else
pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
pSMB->Reserved4 = 0;
- pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ pSMB->hdr.smb_buf_length += byte_count;
memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
- pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ 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) {
return rc;
}
+int
+CIFSSMBSetTimesLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
+ FILE_INFO_STANDARD * data, const struct nls_table *nls_codepage)
+{
+ TRANSACTION2_SPI_REQ *pSMB = NULL;
+ TRANSACTION2_SPI_RSP *pSMBr = NULL;
+ int name_len;
+ int rc = 0;
+ int bytes_returned = 0;
+ char *data_offset;
+ __u16 params, param_offset, count, offset, byte_count;
+
+ cFYI(1, ("In SetTimesLegacy"));
+
+SetTimesRetryLegacy:
+ 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, PATH_MAX
+ /* 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, PATH_MAX);
+ name_len++; /* trailing null */
+ strncpy(pSMB->FileName, fileName, name_len);
+ }
+/* BB fixme - we have to map to FILE_STANDARD_INFO (level 1 info
+ in parent function, from the better and ususal FILE_BASIC_INFO */
+ params = 6 + name_len;
+ count = sizeof (FILE_INFO_STANDARD);
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ param_offset = offsetof(struct smb_com_transaction2_spi_req,
+ InformationLevel) - 4;
+ offset = param_offset + params;
+ data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
+ pSMB->ParameterOffset = cpu_to_le16(param_offset);
+ pSMB->DataOffset = cpu_to_le16(offset);
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+ byte_count = 3 /* pad */ + params + count;
+
+ pSMB->DataCount = cpu_to_le16(count);
+ pSMB->ParameterCount = cpu_to_le16(params);
+ pSMB->TotalDataCount = pSMB->DataCount;
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
+ pSMB->Reserved4 = 0;
+ pSMB->hdr.smb_buf_length += byte_count;
+ memcpy(data_offset, data, sizeof (FILE_INFO_STANDARD));
+ 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, ("SetPathInfo (times legacy) returned %d", rc));
+ }
+
+ if (pSMB)
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto SetTimesRetryLegacy;
+
+ return rc;
+}
+
int
CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
char *fileName, __u64 mode, __u64 uid, __u64 gid,
int rc = 0;
int bytes_returned = 0;
FILE_UNIX_BASIC_INFO *data_offset;
+ __u16 params, param_offset, offset, count, byte_count;
cFYI(1, ("In SetUID/GID/Mode"));
setPermsRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
+ cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
/* 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 = strnlen(fileName, PATH_MAX);
name_len++; /* trailing null */
strncpy(pSMB->FileName, fileName, name_len);
}
- pSMB->ParameterCount = 6 + name_len;
- pSMB->DataCount = sizeof (FILE_UNIX_BASIC_INFO);
+ params = 6 + name_len;
+ count = sizeof (FILE_UNIX_BASIC_INFO);
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
pSMB->MaxSetupCount = 0;
pSMB->Flags = 0;
pSMB->Timeout = 0;
pSMB->Reserved2 = 0;
- pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+ param_offset = offsetof(struct smb_com_transaction2_spi_req,
InformationLevel) - 4;
- pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+ offset = param_offset + params;
data_offset =
(FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
- pSMB->DataOffset);
- pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
- pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
+ offset);
+ memset(data_offset, 0, count);
+ pSMB->DataOffset = cpu_to_le16(offset);
+ pSMB->ParameterOffset = cpu_to_le16(param_offset);
pSMB->SetupCount = 1;
pSMB->Reserved3 = 0;
pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
- pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
- pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
- pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
+ byte_count = 3 /* pad */ + params + count;
+ pSMB->ParameterCount = cpu_to_le16(params);
+ pSMB->DataCount = cpu_to_le16(count);
pSMB->TotalParameterCount = pSMB->ParameterCount;
pSMB->TotalDataCount = pSMB->DataCount;
pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
pSMB->Reserved4 = 0;
- pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ pSMB->hdr.smb_buf_length += byte_count;
data_offset->Uid = cpu_to_le64(uid);
data_offset->Gid = cpu_to_le64(gid);
/* better to leave device as zero when it is */
data_offset->DevMajor = cpu_to_le64(MAJOR(device));
data_offset->DevMinor = cpu_to_le64(MINOR(device));
data_offset->Permissions = cpu_to_le64(mode);
- pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+
+ if(S_ISREG(mode))
+ data_offset->Type = cpu_to_le32(UNIX_FILE);
+ else if(S_ISDIR(mode))
+ data_offset->Type = cpu_to_le32(UNIX_DIR);
+ else if(S_ISLNK(mode))
+ data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
+ else if(S_ISCHR(mode))
+ data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
+ else if(S_ISBLK(mode))
+ data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
+ else if(S_ISFIFO(mode))
+ data_offset->Type = cpu_to_le32(UNIX_FIFO);
+ else if(S_ISSOCK(mode))
+ data_offset->Type = cpu_to_le32(UNIX_SOCKET);
+
+
+ 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) {
pSMB->Fid = netfid; /* file handle always le */
pSMB->ByteCount = 0;
- pSMB->hdr.smb_buf_length += pSMB->ByteCount;
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ (struct smb_hdr *) pSMBr, &bytes_returned, -1);
if (rc) {
cFYI(1, ("Error in Notify = %d", rc));
}
return rc;
}
#ifdef CONFIG_CIFS_XATTR
-int
+ssize_t
CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName,
- char * EAData, size_t size,
+ char * EAData, size_t buf_size,
const struct nls_table *nls_codepage)
{
/* BB assumes one setup word */
int rc = 0;
int bytes_returned;
int name_len;
+ struct fea * temp_fea;
+ char * temp_ptr;
+ __u16 params, byte_count;
cFYI(1, ("In Query All EAs path %s", searchName));
QAllEAsRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
+ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
/* 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(searchName, 530);
+ } else { /* BB improve the check for buffer overruns BB */
+ name_len = strnlen(searchName, PATH_MAX);
name_len++; /* trailing null */
strncpy(pSMB->FileName, searchName, name_len);
}
- pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
- name_len /* includes null */ ;
+ params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
pSMB->TotalDataCount = 0;
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
pSMB->SetupCount = 1;
pSMB->Reserved3 = 0;
pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
- pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
- pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+ byte_count = params + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(params);
pSMB->ParameterCount = pSMB->TotalParameterCount;
pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
pSMB->Reserved4 = 0;
- pSMB->hdr.smb_buf_length += pSMB->ByteCount;
- pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ 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 QueryAllEAs = %d", rc));
} else { /* decode response */
- pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
/* BB also check enough total bytes returned */
/* BB we need to improve the validity checking
of these trans2 responses */
- if ((pSMBr->ByteCount < 4) || (pSMBr->DataOffset > 512))
+ if (rc || (pSMBr->ByteCount < 4))
rc = -EIO; /* bad smb */
/* else if (pFindData){
memcpy((char *) pFindData,
(char *) &pSMBr->hdr.Protocol +
- pSMBr->DataOffset, kl);
+ data_offset, kl);
}*/ else {
/* check that length of list is not more than bcc */
/* check that each entry does not go beyond length
of list */
/* check that each element of each entry does not
go beyond end of list */
+ __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
struct fealist * ea_response_data;
rc = 0;
/* validate_trans2_offsets() */
- /* BB to check if(start of smb + pSMBr->DataOffset > &bcc+ bcc)*/
+ /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
ea_response_data = (struct fealist *)
(((char *) &pSMBr->hdr.Protocol) +
- pSMBr->DataOffset);
- cFYI(1,("ea length %d",ea_response_data->list_len));
+ data_offset);
+ name_len = le32_to_cpu(ea_response_data->list_len);
+ cFYI(1,("ea length %d", name_len));
+ if(name_len <= 8) {
+ /* returned EA size zeroed at top of function */
+ cFYI(1,("empty EA list returned from server"));
+ } else {
+ /* account for ea list len */
+ name_len -= 4;
+ temp_fea = ea_response_data->list;
+ temp_ptr = (char *)temp_fea;
+ while(name_len > 0) {
+ __u16 value_len;
+ name_len -= 4;
+ temp_ptr += 4;
+ rc += temp_fea->name_len;
+ /* account for prefix user. and trailing null */
+ rc = rc + 5 + 1;
+ if(rc<(int)buf_size) {
+ memcpy(EAData,"user.",5);
+ EAData+=5;
+ memcpy(EAData,temp_ptr,temp_fea->name_len);
+ EAData+=temp_fea->name_len;
+ /* null terminate name */
+ *EAData = 0;
+ EAData = EAData + 1;
+ } else if(buf_size == 0) {
+ /* skip copy - calc size only */
+ } else {
+ /* stop before overrun buffer */
+ rc = -ERANGE;
+ break;
+ }
+ name_len -= temp_fea->name_len;
+ temp_ptr += temp_fea->name_len;
+ /* account for trailing null */
+ name_len--;
+ temp_ptr++;
+ value_len = le16_to_cpu(temp_fea->value_len);
+ name_len -= value_len;
+ temp_ptr += value_len;
+ /* BB check that temp_ptr is still within smb BB*/
+ /* no trailing null to account for in value len */
+ /* go on to next EA */
+ temp_fea = (struct fea *)temp_ptr;
+ }
+ }
}
}
if (pSMB)
if (rc == -EAGAIN)
goto QAllEAsRetry;
+ return (ssize_t)rc;
+}
+
+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)
+{
+ TRANSACTION2_QPI_REQ *pSMB = NULL;
+ TRANSACTION2_QPI_RSP *pSMBr = NULL;
+ int rc = 0;
+ int bytes_returned;
+ int name_len;
+ struct fea * temp_fea;
+ char * temp_ptr;
+ __u16 params, byte_count;
+
+ cFYI(1, ("In Query EA path %s", searchName));
+QEARetry:
+ 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, PATH_MAX
+ /* 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(searchName, PATH_MAX);
+ name_len++; /* trailing null */
+ strncpy(pSMB->FileName, searchName, name_len);
+ }
+
+ params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
+ pSMB->TotalDataCount = 0;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
+ 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_INFO_QUERY_ALL_EAS);
+ 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 EA = %d", rc));
+ } else { /* decode response */
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+ /* BB also check enough total bytes returned */
+ /* BB we need to improve the validity checking
+ of these trans2 responses */
+ if (rc || (pSMBr->ByteCount < 4))
+ rc = -EIO; /* bad smb */
+ /* else if (pFindData){
+ memcpy((char *) pFindData,
+ (char *) &pSMBr->hdr.Protocol +
+ data_offset, kl);
+ }*/ else {
+ /* check that length of list is not more than bcc */
+ /* check that each entry does not go beyond length
+ of list */
+ /* check that each element of each entry does not
+ go beyond end of list */
+ __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+ struct fealist * ea_response_data;
+ rc = -ENODATA;
+ /* validate_trans2_offsets() */
+ /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
+ ea_response_data = (struct fealist *)
+ (((char *) &pSMBr->hdr.Protocol) +
+ data_offset);
+ name_len = le32_to_cpu(ea_response_data->list_len);
+ cFYI(1,("ea length %d", name_len));
+ if(name_len <= 8) {
+ /* returned EA size zeroed at top of function */
+ cFYI(1,("empty EA list returned from server"));
+ } else {
+ /* account for ea list len */
+ name_len -= 4;
+ temp_fea = ea_response_data->list;
+ temp_ptr = (char *)temp_fea;
+ /* loop through checking if we have a matching
+ name and then return the associated value */
+ while(name_len > 0) {
+ __u16 value_len;
+ name_len -= 4;
+ temp_ptr += 4;
+ value_len = le16_to_cpu(temp_fea->value_len);
+ /* BB validate that value_len falls within SMB,
+ even though maximum for name_len is 255 */
+ if(memcmp(temp_fea->name,ea_name,
+ temp_fea->name_len) == 0) {
+ /* found a match */
+ rc = value_len;
+ /* account for prefix user. and trailing null */
+ if(rc<=(int)buf_size) {
+ memcpy(ea_value,
+ temp_fea->name+temp_fea->name_len+1,
+ rc);
+ /* ea values, unlike ea names,
+ are not null terminated */
+ } else if(buf_size == 0) {
+ /* skip copy - calc size only */
+ } else {
+ /* stop before overrun buffer */
+ rc = -ERANGE;
+ }
+ break;
+ }
+ name_len -= temp_fea->name_len;
+ temp_ptr += temp_fea->name_len;
+ /* account for trailing null */
+ name_len--;
+ temp_ptr++;
+ name_len -= value_len;
+ temp_ptr += value_len;
+ /* no trailing null to account for in value len */
+ /* go on to next EA */
+ temp_fea = (struct fea *)temp_ptr;
+ }
+ }
+ }
+ }
+ if (pSMB)
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto QEARetry;
+
+ return (ssize_t)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;
+ __u16 params, param_offset, byte_count, offset, count;
+
+ 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, PATH_MAX
+ /* 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, PATH_MAX);
+ name_len++; /* trailing null */
+ strncpy(pSMB->FileName, fileName, name_len);
+ }
+
+ params = 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);
+
+ count = 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;
+ param_offset = offsetof(struct smb_com_transaction2_spi_req,
+ InformationLevel) - 4;
+ offset = param_offset + params;
+ pSMB->InformationLevel =
+ cpu_to_le16(SMB_SET_FILE_EA);
+
+ parm_data =
+ (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
+ offset);
+ pSMB->ParameterOffset = cpu_to_le16(param_offset);
+ pSMB->DataOffset = cpu_to_le16(offset);
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+ byte_count = 3 /* pad */ + params + count;
+ pSMB->DataCount = cpu_to_le16(count);
+ parm_data->list_len = cpu_to_le32(count);
+ 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)) */
+ if(ea_value_len)
+ memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
+
+ pSMB->TotalDataCount = pSMB->DataCount;
+ pSMB->ParameterCount = cpu_to_le16(params);
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ 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, ("SetPathInfo (EA) returned %d", rc));
+ }
+
+ if (pSMB)
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto SetEARetry;
+
return rc;
}
+
#endif