diff options
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r-- | fs/cifs/cifssmb.c | 77 |
1 files changed, 74 insertions, 3 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index b31158a2643d..81c9d3f393f5 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -2416,7 +2416,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, | |||
2416 | const char *searchName, | 2416 | const char *searchName, |
2417 | const struct nls_table *nls_codepage, | 2417 | const struct nls_table *nls_codepage, |
2418 | __u16 * pnetfid, | 2418 | __u16 * pnetfid, |
2419 | struct cifs_search_info * psrch_inf, int remap) | 2419 | struct cifs_search_info * psrch_inf, int remap, const char dirsep) |
2420 | { | 2420 | { |
2421 | /* level 257 SMB_ */ | 2421 | /* level 257 SMB_ */ |
2422 | TRANSACTION2_FFIRST_REQ *pSMB = NULL; | 2422 | TRANSACTION2_FFIRST_REQ *pSMB = NULL; |
@@ -2443,7 +2443,7 @@ findFirstRetry: | |||
2443 | it got remapped to 0xF03A as if it were part of the | 2443 | it got remapped to 0xF03A as if it were part of the |
2444 | directory name instead of a wildcard */ | 2444 | directory name instead of a wildcard */ |
2445 | name_len *= 2; | 2445 | name_len *= 2; |
2446 | pSMB->FileName[name_len] = '\\'; | 2446 | pSMB->FileName[name_len] = dirsep; |
2447 | pSMB->FileName[name_len+1] = 0; | 2447 | pSMB->FileName[name_len+1] = 0; |
2448 | pSMB->FileName[name_len+2] = '*'; | 2448 | pSMB->FileName[name_len+2] = '*'; |
2449 | pSMB->FileName[name_len+3] = 0; | 2449 | pSMB->FileName[name_len+3] = 0; |
@@ -2457,7 +2457,7 @@ findFirstRetry: | |||
2457 | if(name_len > buffersize-header) | 2457 | if(name_len > buffersize-header) |
2458 | free buffer exit; BB */ | 2458 | free buffer exit; BB */ |
2459 | strncpy(pSMB->FileName, searchName, name_len); | 2459 | strncpy(pSMB->FileName, searchName, name_len); |
2460 | pSMB->FileName[name_len] = '\\'; | 2460 | pSMB->FileName[name_len] = dirsep; |
2461 | pSMB->FileName[name_len+1] = '*'; | 2461 | pSMB->FileName[name_len+1] = '*'; |
2462 | pSMB->FileName[name_len+2] = 0; | 2462 | pSMB->FileName[name_len+2] = 0; |
2463 | name_len += 3; | 2463 | name_len += 3; |
@@ -3265,6 +3265,77 @@ QFSUnixRetry: | |||
3265 | return rc; | 3265 | return rc; |
3266 | } | 3266 | } |
3267 | 3267 | ||
3268 | int | ||
3269 | CIFSSMBSETFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap) | ||
3270 | { | ||
3271 | /* level 0x200 SMB_SET_CIFS_UNIX_INFO */ | ||
3272 | TRANSACTION2_SETFSI_REQ *pSMB = NULL; | ||
3273 | TRANSACTION2_SETFSI_RSP *pSMBr = NULL; | ||
3274 | int rc = 0; | ||
3275 | int bytes_returned = 0; | ||
3276 | __u16 params, param_offset, offset, byte_count; | ||
3277 | |||
3278 | cFYI(1, ("In SETFSUnixInfo")); | ||
3279 | SETFSUnixRetry: | ||
3280 | rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, | ||
3281 | (void **) &pSMBr); | ||
3282 | if (rc) | ||
3283 | return rc; | ||
3284 | |||
3285 | params = 4; /* 2 bytes zero followed by info level. */ | ||
3286 | pSMB->MaxSetupCount = 0; | ||
3287 | pSMB->Reserved = 0; | ||
3288 | pSMB->Flags = 0; | ||
3289 | pSMB->Timeout = 0; | ||
3290 | pSMB->Reserved2 = 0; | ||
3291 | param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4; | ||
3292 | offset = param_offset + params; | ||
3293 | |||
3294 | pSMB->MaxParameterCount = cpu_to_le16(4); | ||
3295 | pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */ | ||
3296 | pSMB->SetupCount = 1; | ||
3297 | pSMB->Reserved3 = 0; | ||
3298 | pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION); | ||
3299 | byte_count = 1 /* pad */ + params + 12; | ||
3300 | |||
3301 | pSMB->DataCount = cpu_to_le16(12); | ||
3302 | pSMB->ParameterCount = cpu_to_le16(params); | ||
3303 | pSMB->TotalDataCount = pSMB->DataCount; | ||
3304 | pSMB->TotalParameterCount = pSMB->ParameterCount; | ||
3305 | pSMB->ParameterOffset = cpu_to_le16(param_offset); | ||
3306 | pSMB->DataOffset = cpu_to_le16(offset); | ||
3307 | |||
3308 | /* Params. */ | ||
3309 | pSMB->FileNum = 0; | ||
3310 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO); | ||
3311 | |||
3312 | /* Data. */ | ||
3313 | pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION); | ||
3314 | pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION); | ||
3315 | pSMB->ClientUnixCap = cpu_to_le64(cap); | ||
3316 | |||
3317 | pSMB->hdr.smb_buf_length += byte_count; | ||
3318 | pSMB->ByteCount = cpu_to_le16(byte_count); | ||
3319 | |||
3320 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | ||
3321 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | ||
3322 | if (rc) { | ||
3323 | cERROR(1, ("Send error in SETFSUnixInfo = %d", rc)); | ||
3324 | } else { /* decode response */ | ||
3325 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | ||
3326 | if (rc) { | ||
3327 | rc = -EIO; /* bad smb */ | ||
3328 | } | ||
3329 | } | ||
3330 | cifs_buf_release(pSMB); | ||
3331 | |||
3332 | if (rc == -EAGAIN) | ||
3333 | goto SETFSUnixRetry; | ||
3334 | |||
3335 | return rc; | ||
3336 | } | ||
3337 | |||
3338 | |||
3268 | 3339 | ||
3269 | int | 3340 | int |
3270 | CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, | 3341 | CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, |