aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--fs/cifs/cifsproto.h7
-rw-r--r--fs/cifs/cifssmb.c214
-rw-r--r--fs/cifs/inode.c2
-rw-r--r--fs/cifs/xattr.c8
4 files changed, 54 insertions, 177 deletions
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 5646727e33f5..88e2bc44ac58 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -363,13 +363,10 @@ extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
363 __u32 filter, struct file *file, int multishot, 363 __u32 filter, struct file *file, int multishot,
364 const struct nls_table *nls_codepage); 364 const struct nls_table *nls_codepage);
365extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, 365extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
366 const unsigned char *searchName, char *EAData, 366 const unsigned char *searchName,
367 const unsigned char *ea_name, char *EAData,
367 size_t bufsize, const struct nls_table *nls_codepage, 368 size_t bufsize, const struct nls_table *nls_codepage,
368 int remap_special_chars); 369 int remap_special_chars);
369extern ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
370 const unsigned char *searchName, const unsigned char *ea_name,
371 unsigned char *ea_value, size_t buf_size,
372 const struct nls_table *nls_codepage, int remap_special_chars);
373extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, 370extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon,
374 const char *fileName, const char *ea_name, 371 const char *fileName, const char *ea_name,
375 const void *ea_value, const __u16 ea_value_len, 372 const void *ea_value, const __u16 ea_value_len,
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){