diff options
| -rw-r--r-- | fs/cifs/cifsproto.h | 8 | ||||
| -rw-r--r-- | fs/cifs/cifssmb.c | 150 |
2 files changed, 86 insertions, 72 deletions
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index e88c3b192ef5..582ae61f45b6 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
| @@ -363,10 +363,10 @@ extern int CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 363 | extern int CIFSSMB_set_compression(const unsigned int xid, | 363 | extern int CIFSSMB_set_compression(const unsigned int xid, |
| 364 | struct cifs_tcon *tcon, __u16 fid); | 364 | struct cifs_tcon *tcon, __u16 fid); |
| 365 | extern int CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon, | 365 | extern int CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon, |
| 366 | const char *fileName, const int disposition, | 366 | const char *path, const int disposition, |
| 367 | const int access_flags, const int omode, | 367 | const int desired_access, const int create_options, |
| 368 | __u16 *netfid, int *pOplock, FILE_ALL_INFO *, | 368 | __u16 *netfid, int *oplock, FILE_ALL_INFO *buf, |
| 369 | const struct nls_table *nls_codepage, int remap); | 369 | const struct nls_table *nls, int remap); |
| 370 | extern int SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon, | 370 | extern int SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon, |
| 371 | const char *fileName, const int disposition, | 371 | const char *fileName, const int disposition, |
| 372 | const int access_flags, const int omode, | 372 | const int access_flags, const int omode, |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index d707edb6b852..8e1ebc2dc0db 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
| @@ -1274,103 +1274,117 @@ OldOpenRetry: | |||
| 1274 | 1274 | ||
| 1275 | int | 1275 | int |
| 1276 | CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon, | 1276 | CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon, |
| 1277 | const char *fileName, const int openDisposition, | 1277 | const char *path, const int disposition, const int desired_access, |
| 1278 | const int access_flags, const int create_options, __u16 *netfid, | 1278 | const int create_options, __u16 *netfid, int *oplock, |
| 1279 | int *pOplock, FILE_ALL_INFO *pfile_info, | 1279 | FILE_ALL_INFO *buf, const struct nls_table *nls, int remap) |
| 1280 | const struct nls_table *nls_codepage, int remap) | ||
| 1281 | { | 1280 | { |
| 1282 | int rc = -EACCES; | 1281 | int rc = -EACCES; |
| 1283 | OPEN_REQ *pSMB = NULL; | 1282 | OPEN_REQ *req = NULL; |
| 1284 | OPEN_RSP *pSMBr = NULL; | 1283 | OPEN_RSP *rsp = NULL; |
| 1285 | int bytes_returned; | 1284 | int bytes_returned; |
| 1286 | int name_len; | 1285 | int name_len; |
| 1287 | __u16 count; | 1286 | __u16 count; |
| 1288 | 1287 | ||
| 1289 | openRetry: | 1288 | openRetry: |
| 1290 | rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB, | 1289 | rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **)&req, |
| 1291 | (void **) &pSMBr); | 1290 | (void **)&rsp); |
| 1292 | if (rc) | 1291 | if (rc) |
| 1293 | return rc; | 1292 | return rc; |
| 1294 | 1293 | ||
| 1295 | pSMB->AndXCommand = 0xFF; /* none */ | 1294 | /* no commands go after this */ |
| 1295 | req->AndXCommand = 0xFF; | ||
| 1296 | 1296 | ||
| 1297 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 1297 | if (req->hdr.Flags2 & SMBFLG2_UNICODE) { |
| 1298 | count = 1; /* account for one byte pad to word boundary */ | 1298 | /* account for one byte pad to word boundary */ |
| 1299 | name_len = | 1299 | count = 1; |
| 1300 | cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1), | 1300 | name_len = cifsConvertToUTF16((__le16 *)(req->fileName + 1), |
| 1301 | fileName, PATH_MAX, nls_codepage, remap); | 1301 | path, PATH_MAX, nls, remap); |
| 1302 | name_len++; /* trailing null */ | 1302 | /* trailing null */ |
| 1303 | name_len++; | ||
| 1303 | name_len *= 2; | 1304 | name_len *= 2; |
| 1304 | pSMB->NameLength = cpu_to_le16(name_len); | 1305 | req->NameLength = cpu_to_le16(name_len); |
| 1305 | } else { /* BB improve check for buffer overruns BB */ | 1306 | } else { |
| 1306 | count = 0; /* no pad */ | 1307 | /* BB improve check for buffer overruns BB */ |
| 1307 | name_len = strnlen(fileName, PATH_MAX); | 1308 | /* no pad */ |
| 1308 | name_len++; /* trailing null */ | 1309 | count = 0; |
| 1309 | pSMB->NameLength = cpu_to_le16(name_len); | 1310 | name_len = strnlen(path, PATH_MAX); |
| 1310 | strncpy(pSMB->fileName, fileName, name_len); | 1311 | /* trailing null */ |
| 1312 | name_len++; | ||
| 1313 | req->NameLength = cpu_to_le16(name_len); | ||
| 1314 | strncpy(req->fileName, path, name_len); | ||
| 1311 | } | 1315 | } |
| 1312 | if (*pOplock & REQ_OPLOCK) | 1316 | |
| 1313 | pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK); | 1317 | if (*oplock & REQ_OPLOCK) |
| 1314 | else if (*pOplock & REQ_BATCHOPLOCK) | 1318 | req->OpenFlags = cpu_to_le32(REQ_OPLOCK); |
| 1315 | pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK); | 1319 | else if (*oplock & REQ_BATCHOPLOCK) |
| 1316 | pSMB->DesiredAccess = cpu_to_le32(access_flags); | 1320 | req->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK); |
| 1317 | pSMB->AllocationSize = 0; | 1321 | |
| 1318 | /* set file as system file if special file such | 1322 | req->DesiredAccess = cpu_to_le32(desired_access); |
| 1319 | as fifo and server expecting SFU style and | 1323 | req->AllocationSize = 0; |
| 1320 | no Unix extensions */ | 1324 | |
| 1325 | /* | ||
| 1326 | * Set file as system file if special file such as fifo and server | ||
| 1327 | * expecting SFU style and no Unix extensions. | ||
| 1328 | */ | ||
| 1321 | if (create_options & CREATE_OPTION_SPECIAL) | 1329 | if (create_options & CREATE_OPTION_SPECIAL) |
| 1322 | pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM); | 1330 | req->FileAttributes = cpu_to_le32(ATTR_SYSTEM); |
| 1323 | else | 1331 | else |
| 1324 | pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL); | 1332 | req->FileAttributes = cpu_to_le32(ATTR_NORMAL); |
| 1325 | 1333 | ||
| 1326 | /* XP does not handle ATTR_POSIX_SEMANTICS */ | 1334 | /* |
| 1327 | /* but it helps speed up case sensitive checks for other | 1335 | * XP does not handle ATTR_POSIX_SEMANTICS but it helps speed up case |
| 1328 | servers such as Samba */ | 1336 | * sensitive checks for other servers such as Samba. |
| 1337 | */ | ||
| 1329 | if (tcon->ses->capabilities & CAP_UNIX) | 1338 | if (tcon->ses->capabilities & CAP_UNIX) |
| 1330 | pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS); | 1339 | req->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS); |
| 1331 | 1340 | ||
| 1332 | if (create_options & CREATE_OPTION_READONLY) | 1341 | if (create_options & CREATE_OPTION_READONLY) |
| 1333 | pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY); | 1342 | req->FileAttributes |= cpu_to_le32(ATTR_READONLY); |
| 1343 | |||
| 1344 | req->ShareAccess = cpu_to_le32(FILE_SHARE_ALL); | ||
| 1345 | req->CreateDisposition = cpu_to_le32(disposition); | ||
| 1346 | req->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); | ||
| 1334 | 1347 | ||
| 1335 | pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL); | ||
| 1336 | pSMB->CreateDisposition = cpu_to_le32(openDisposition); | ||
| 1337 | pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); | ||
| 1338 | /* BB Expirement with various impersonation levels and verify */ | 1348 | /* BB Expirement with various impersonation levels and verify */ |
| 1339 | pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); | 1349 | req->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); |
| 1340 | pSMB->SecurityFlags = | 1350 | req->SecurityFlags = SECURITY_CONTEXT_TRACKING|SECURITY_EFFECTIVE_ONLY; |
| 1341 | SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY; | ||
| 1342 | 1351 | ||
| 1343 | count += name_len; | 1352 | count += name_len; |
| 1344 | inc_rfc1001_len(pSMB, count); | 1353 | inc_rfc1001_len(req, count); |
| 1345 | 1354 | ||
| 1346 | pSMB->ByteCount = cpu_to_le16(count); | 1355 | req->ByteCount = cpu_to_le16(count); |
| 1347 | /* long_op set to 1 to allow for oplock break timeouts */ | 1356 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)req, |
| 1348 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1357 | (struct smb_hdr *)rsp, &bytes_returned, 0); |
| 1349 | (struct smb_hdr *)pSMBr, &bytes_returned, 0); | ||
| 1350 | cifs_stats_inc(&tcon->stats.cifs_stats.num_opens); | 1358 | cifs_stats_inc(&tcon->stats.cifs_stats.num_opens); |
| 1351 | if (rc) { | 1359 | if (rc) { |
| 1352 | cifs_dbg(FYI, "Error in Open = %d\n", rc); | 1360 | cifs_dbg(FYI, "Error in Open = %d\n", rc); |
| 1353 | } else { | 1361 | cifs_buf_release(req); |
| 1354 | *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */ | 1362 | if (rc == -EAGAIN) |
| 1355 | *netfid = pSMBr->Fid; /* cifs fid stays in le */ | 1363 | goto openRetry; |
| 1356 | /* Let caller know file was created so we can set the mode. */ | 1364 | return rc; |
| 1357 | /* Do we care about the CreateAction in any other cases? */ | ||
| 1358 | if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction) | ||
| 1359 | *pOplock |= CIFS_CREATE_ACTION; | ||
| 1360 | if (pfile_info) { | ||
| 1361 | memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime, | ||
| 1362 | 36 /* CreationTime to Attributes */); | ||
| 1363 | /* the file_info buf is endian converted by caller */ | ||
| 1364 | pfile_info->AllocationSize = pSMBr->AllocationSize; | ||
| 1365 | pfile_info->EndOfFile = pSMBr->EndOfFile; | ||
| 1366 | pfile_info->NumberOfLinks = cpu_to_le32(1); | ||
| 1367 | pfile_info->DeletePending = 0; | ||
| 1368 | } | ||
| 1369 | } | 1365 | } |
| 1370 | 1366 | ||
| 1371 | cifs_buf_release(pSMB); | 1367 | /* 1 byte no need to le_to_cpu */ |
| 1372 | if (rc == -EAGAIN) | 1368 | *oplock = rsp->OplockLevel; |
| 1373 | goto openRetry; | 1369 | /* cifs fid stays in le */ |
| 1370 | *netfid = rsp->Fid; | ||
| 1371 | |||
| 1372 | /* Let caller know file was created so we can set the mode. */ | ||
| 1373 | /* Do we care about the CreateAction in any other cases? */ | ||
| 1374 | if (cpu_to_le32(FILE_CREATE) == rsp->CreateAction) | ||
| 1375 | *oplock |= CIFS_CREATE_ACTION; | ||
| 1376 | |||
| 1377 | if (buf) { | ||
| 1378 | /* copy from CreationTime to Attributes */ | ||
| 1379 | memcpy((char *)buf, (char *)&rsp->CreationTime, 36); | ||
| 1380 | /* the file_info buf is endian converted by caller */ | ||
| 1381 | buf->AllocationSize = rsp->AllocationSize; | ||
| 1382 | buf->EndOfFile = rsp->EndOfFile; | ||
| 1383 | buf->NumberOfLinks = cpu_to_le32(1); | ||
| 1384 | buf->DeletePending = 0; | ||
| 1385 | } | ||
| 1386 | |||
| 1387 | cifs_buf_release(req); | ||
| 1374 | return rc; | 1388 | return rc; |
| 1375 | } | 1389 | } |
| 1376 | 1390 | ||
