diff options
author | Jeff Layton <jlayton@redhat.com> | 2010-02-10 16:18:26 -0500 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2010-02-23 15:47:32 -0500 |
commit | 31c0519f7af99ae60fd39f7f1c1f7ae1efb56760 (patch) | |
tree | d27678094c2b077756e148024d0d3fa5891afa93 | |
parent | 0cd126b504cede8a74acf7583a44eba32f9a1da1 (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.h | 7 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 214 | ||||
-rw-r--r-- | fs/cifs/inode.c | 2 | ||||
-rw-r--r-- | fs/cifs/xattr.c | 8 |
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); |
365 | extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, | 365 | extern 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); |
369 | extern 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); | ||
373 | extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, | 370 | extern 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 | */ | ||
5273 | ssize_t | 5283 | ssize_t |
5274 | CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, | 5284 | CIFSSMBQAllEAs(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 | |||
5427 | QAllEAsOut: | 5456 | QAllEAsOut: |
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 | ||
5435 | ssize_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)); | ||
5450 | QEARetry: | ||
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 | |||
5584 | int | 5464 | int |
5585 | CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName, | 5465 | CIFSSMBSetEA(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 | ||