aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
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
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')
-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){
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,
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index e3fda978f481..5e9cc9c2fc7d 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -366,7 +366,7 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
366 char ea_value[4]; 366 char ea_value[4];
367 __u32 mode; 367 __u32 mode;
368 368
369 rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS", 369 rc = CIFSSMBQAllEAs(xid, cifs_sb->tcon, path, "SETFILEBITS",
370 ea_value, 4 /* size of buf */, cifs_sb->local_nls, 370 ea_value, 4 /* size of buf */, cifs_sb->local_nls,
371 cifs_sb->mnt_cifs_flags & 371 cifs_sb->mnt_cifs_flags &
372 CIFS_MOUNT_MAP_SPECIAL_CHR); 372 CIFS_MOUNT_MAP_SPECIAL_CHR);
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index a75afa3dd9e1..3e2ef0de1209 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -244,7 +244,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
244 /* revalidate/getattr then populate from inode */ 244 /* revalidate/getattr then populate from inode */
245 } /* BB add else when above is implemented */ 245 } /* BB add else when above is implemented */
246 ea_name += 5; /* skip past user. prefix */ 246 ea_name += 5; /* skip past user. prefix */
247 rc = CIFSSMBQueryEA(xid, pTcon, full_path, ea_name, ea_value, 247 rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value,
248 buf_size, cifs_sb->local_nls, 248 buf_size, cifs_sb->local_nls,
249 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 249 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
250 } else if (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4) == 0) { 250 } else if (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4) == 0) {
@@ -252,7 +252,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
252 goto get_ea_exit; 252 goto get_ea_exit;
253 253
254 ea_name += 4; /* skip past os2. prefix */ 254 ea_name += 4; /* skip past os2. prefix */
255 rc = CIFSSMBQueryEA(xid, pTcon, full_path, ea_name, ea_value, 255 rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value,
256 buf_size, cifs_sb->local_nls, 256 buf_size, cifs_sb->local_nls,
257 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 257 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
258 } else if (strncmp(ea_name, POSIX_ACL_XATTR_ACCESS, 258 } else if (strncmp(ea_name, POSIX_ACL_XATTR_ACCESS,
@@ -364,8 +364,8 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
364 /* if proc/fs/cifs/streamstoxattr is set then 364 /* if proc/fs/cifs/streamstoxattr is set then
365 search server for EAs or streams to 365 search server for EAs or streams to
366 returns as xattrs */ 366 returns as xattrs */
367 rc = CIFSSMBQAllEAs(xid, pTcon, full_path, data, buf_size, 367 rc = CIFSSMBQAllEAs(xid, pTcon, full_path, NULL, data,
368 cifs_sb->local_nls, 368 buf_size, cifs_sb->local_nls,
369 cifs_sb->mnt_cifs_flags & 369 cifs_sb->mnt_cifs_flags &
370 CIFS_MOUNT_MAP_SPECIAL_CHR); 370 CIFS_MOUNT_MAP_SPECIAL_CHR);
371 371