aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/cifssmb.c
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2010-02-10 16:18:26 -0500
committerSteve French <sfrench@us.ibm.com>2010-02-23 15:47:32 -0500
commit31c0519f7af99ae60fd39f7f1c1f7ae1efb56760 (patch)
treed27678094c2b077756e148024d0d3fa5891afa93 /fs/cifs/cifssmb.c
parent0cd126b504cede8a74acf7583a44eba32f9a1da1 (diff)
cifs: merge CIFSSMBQueryEA with CIFSSMBQAllEAs
Add an "ea_name" parameter to CIFSSMBQAllEAs. When it's set make it behave like CIFSSMBQueryEA does now. The current callers of CIFSSMBQueryEA are converted to use CIFSSMBQAllEAs, and the old CIFSSMBQueryEA function is removed. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r--fs/cifs/cifssmb.c214
1 files changed, 47 insertions, 167 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index e197e1647d5d..d6d40b883abc 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -5269,12 +5269,22 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5269 cifs_buf_release(pSMB); 5269 cifs_buf_release(pSMB);
5270 return rc; 5270 return rc;
5271} 5271}
5272
5272#ifdef CONFIG_CIFS_XATTR 5273#ifdef CONFIG_CIFS_XATTR
5274/*
5275 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
5276 * function used by listxattr and getxattr type calls. When ea_name is set,
5277 * it looks for that attribute name and stuffs that value into the EAData
5278 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
5279 * buffer. In both cases, the return value is either the length of the
5280 * resulting data or a negative error code. If EAData is a NULL pointer then
5281 * the data isn't copied to it, but the length is returned.
5282 */
5273ssize_t 5283ssize_t
5274CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, 5284CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5275 const unsigned char *searchName, 5285 const unsigned char *searchName, const unsigned char *ea_name,
5276 char *EAData, size_t buf_size, 5286 char *EAData, size_t buf_size,
5277 const struct nls_table *nls_codepage, int remap) 5287 const struct nls_table *nls_codepage, int remap)
5278{ 5288{
5279 /* BB assumes one setup word */ 5289 /* BB assumes one setup word */
5280 TRANSACTION2_QPI_REQ *pSMB = NULL; 5290 TRANSACTION2_QPI_REQ *pSMB = NULL;
@@ -5403,27 +5413,46 @@ QAllEAsRetry:
5403 goto QAllEAsOut; 5413 goto QAllEAsOut;
5404 } 5414 }
5405 5415
5406 /* account for prefix user. and trailing null */ 5416 if (ea_name) {
5407 rc += (5 + 1 + name_len); 5417 if (strncmp(ea_name, temp_ptr, name_len) == 0) {
5408 if (rc < (int) buf_size) { 5418 temp_ptr += name_len + 1;
5409 memcpy(EAData, "user.", 5); 5419 rc = value_len;
5410 EAData += 5; 5420 if (buf_size == 0)
5411 memcpy(EAData, temp_ptr, name_len); 5421 goto QAllEAsOut;
5412 EAData += name_len; 5422 if ((size_t)value_len > buf_size) {
5413 /* null terminate name */ 5423 rc = -ERANGE;
5414 *EAData = 0; 5424 goto QAllEAsOut;
5415 ++EAData; 5425 }
5416 } else if (buf_size == 0) { 5426 memcpy(EAData, temp_ptr, value_len);
5417 /* skip copy - calc size only */ 5427 goto QAllEAsOut;
5428 }
5418 } else { 5429 } else {
5419 /* stop before overrun buffer */ 5430 /* account for prefix user. and trailing null */
5420 rc = -ERANGE; 5431 rc += (5 + 1 + name_len);
5421 break; 5432 if (rc < (int) buf_size) {
5433 memcpy(EAData, "user.", 5);
5434 EAData += 5;
5435 memcpy(EAData, temp_ptr, name_len);
5436 EAData += name_len;
5437 /* null terminate name */
5438 *EAData = 0;
5439 ++EAData;
5440 } else if (buf_size == 0) {
5441 /* skip copy - calc size only */
5442 } else {
5443 /* stop before overrun buffer */
5444 rc = -ERANGE;
5445 break;
5446 }
5422 } 5447 }
5423 temp_ptr += name_len + 1 + value_len; 5448 temp_ptr += name_len + 1 + value_len;
5424 temp_fea = (struct fea *)temp_ptr; 5449 temp_fea = (struct fea *)temp_ptr;
5425 } 5450 }
5426 5451
5452 /* didn't find the named attribute */
5453 if (ea_name)
5454 rc = -ENODATA;
5455
5427QAllEAsOut: 5456QAllEAsOut:
5428 cifs_buf_release(pSMB); 5457 cifs_buf_release(pSMB);
5429 if (rc == -EAGAIN) 5458 if (rc == -EAGAIN)
@@ -5432,155 +5461,6 @@ QAllEAsOut:
5432 return (ssize_t)rc; 5461 return (ssize_t)rc;
5433} 5462}
5434 5463
5435ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
5436 const unsigned char *searchName, const unsigned char *ea_name,
5437 unsigned char *ea_value, size_t buf_size,
5438 const struct nls_table *nls_codepage, int remap)
5439{
5440 TRANSACTION2_QPI_REQ *pSMB = NULL;
5441 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5442 int rc = 0;
5443 int bytes_returned;
5444 int name_len;
5445 struct fea *temp_fea;
5446 char *temp_ptr;
5447 __u16 params, byte_count;
5448
5449 cFYI(1, ("In Query EA path %s", searchName));
5450QEARetry:
5451 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5452 (void **) &pSMBr);
5453 if (rc)
5454 return rc;
5455
5456 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5457 name_len =
5458 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5459 PATH_MAX, nls_codepage, remap);
5460 name_len++; /* trailing null */
5461 name_len *= 2;
5462 } else { /* BB improve the check for buffer overruns BB */
5463 name_len = strnlen(searchName, PATH_MAX);
5464 name_len++; /* trailing null */
5465 strncpy(pSMB->FileName, searchName, name_len);
5466 }
5467
5468 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5469 pSMB->TotalDataCount = 0;
5470 pSMB->MaxParameterCount = cpu_to_le16(2);
5471 /* BB find exact max SMB PDU from sess structure BB */
5472 pSMB->MaxDataCount = cpu_to_le16(4000);
5473 pSMB->MaxSetupCount = 0;
5474 pSMB->Reserved = 0;
5475 pSMB->Flags = 0;
5476 pSMB->Timeout = 0;
5477 pSMB->Reserved2 = 0;
5478 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5479 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5480 pSMB->DataCount = 0;
5481 pSMB->DataOffset = 0;
5482 pSMB->SetupCount = 1;
5483 pSMB->Reserved3 = 0;
5484 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5485 byte_count = params + 1 /* pad */ ;
5486 pSMB->TotalParameterCount = cpu_to_le16(params);
5487 pSMB->ParameterCount = pSMB->TotalParameterCount;
5488 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5489 pSMB->Reserved4 = 0;
5490 pSMB->hdr.smb_buf_length += byte_count;
5491 pSMB->ByteCount = cpu_to_le16(byte_count);
5492
5493 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5494 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5495 if (rc) {
5496 cFYI(1, ("Send error in Query EA = %d", rc));
5497 } else { /* decode response */
5498 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5499
5500 /* BB also check enough total bytes returned */
5501 /* BB we need to improve the validity checking
5502 of these trans2 responses */
5503 if (rc || (pSMBr->ByteCount < 4))
5504 rc = -EIO; /* bad smb */
5505 /* else if (pFindData){
5506 memcpy((char *) pFindData,
5507 (char *) &pSMBr->hdr.Protocol +
5508 data_offset, kl);
5509 }*/ else {
5510 /* check that length of list is not more than bcc */
5511 /* check that each entry does not go beyond length
5512 of list */
5513 /* check that each element of each entry does not
5514 go beyond end of list */
5515 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5516 struct fealist *ea_response_data;
5517 rc = -ENODATA;
5518 /* validate_trans2_offsets() */
5519 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5520 ea_response_data = (struct fealist *)
5521 (((char *) &pSMBr->hdr.Protocol) +
5522 data_offset);
5523 name_len = le32_to_cpu(ea_response_data->list_len);
5524 cFYI(1, ("ea length %d", name_len));
5525 if (name_len <= 8) {
5526 /* returned EA size zeroed at top of function */
5527 cFYI(1, ("empty EA list returned from server"));
5528 } else {
5529 /* account for ea list len */
5530 name_len -= 4;
5531 temp_fea = ea_response_data->list;
5532 temp_ptr = (char *)temp_fea;
5533 /* loop through checking if we have a matching
5534 name and then return the associated value */
5535 while (name_len > 0) {
5536 __u16 value_len;
5537 name_len -= 4;
5538 temp_ptr += 4;
5539 value_len =
5540 le16_to_cpu(temp_fea->value_len);
5541 /* BB validate that value_len falls within SMB,
5542 even though maximum for name_len is 255 */
5543 if (memcmp(temp_fea->name, ea_name,
5544 temp_fea->name_len) == 0) {
5545 /* found a match */
5546 rc = value_len;
5547 /* account for prefix user. and trailing null */
5548 if (rc <= (int)buf_size) {
5549 memcpy(ea_value,
5550 temp_fea->name+temp_fea->name_len+1,
5551 rc);
5552 /* ea values, unlike ea
5553 names, are not null
5554 terminated */
5555 } else if (buf_size == 0) {
5556 /* skip copy - calc size only */
5557 } else {
5558 /* stop before overrun buffer */
5559 rc = -ERANGE;
5560 }
5561 break;
5562 }
5563 name_len -= temp_fea->name_len;
5564 temp_ptr += temp_fea->name_len;
5565 /* account for trailing null */
5566 name_len--;
5567 temp_ptr++;
5568 name_len -= value_len;
5569 temp_ptr += value_len;
5570 /* No trailing null to account for in
5571 value_len. Go on to next EA */
5572 temp_fea = (struct fea *)temp_ptr;
5573 }
5574 }
5575 }
5576 }
5577 cifs_buf_release(pSMB);
5578 if (rc == -EAGAIN)
5579 goto QEARetry;
5580
5581 return (ssize_t)rc;
5582}
5583
5584int 5464int
5585CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName, 5465CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5586 const char *ea_name, const void *ea_value, 5466 const char *ea_name, const void *ea_value,