0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include <linux/fs.h>
0018 #include <linux/kernel.h>
0019 #include <linux/vfs.h>
0020 #include <linux/slab.h>
0021 #include <linux/posix_acl_xattr.h>
0022 #include <linux/pagemap.h>
0023 #include <linux/swap.h>
0024 #include <linux/task_io_accounting_ops.h>
0025 #include <linux/uaccess.h>
0026 #include "cifspdu.h"
0027 #include "cifsglob.h"
0028 #include "cifsacl.h"
0029 #include "cifsproto.h"
0030 #include "cifs_unicode.h"
0031 #include "cifs_debug.h"
0032 #include "fscache.h"
0033 #include "smbdirect.h"
0034 #ifdef CONFIG_CIFS_DFS_UPCALL
0035 #include "dfs_cache.h"
0036 #endif
0037
0038 #ifdef CONFIG_CIFS_POSIX
0039 static struct {
0040 int index;
0041 char *name;
0042 } protocols[] = {
0043 {CIFS_PROT, "\2NT LM 0.12"},
0044 {POSIX_PROT, "\2POSIX 2"},
0045 {BAD_PROT, "\2"}
0046 };
0047 #else
0048 static struct {
0049 int index;
0050 char *name;
0051 } protocols[] = {
0052 {CIFS_PROT, "\2NT LM 0.12"},
0053 {BAD_PROT, "\2"}
0054 };
0055 #endif
0056
0057
0058 #ifdef CONFIG_CIFS_POSIX
0059 #define CIFS_NUM_PROT 2
0060 #else
0061 #define CIFS_NUM_PROT 1
0062 #endif
0063
0064
0065
0066 static int
0067 cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
0068 {
0069 int rc;
0070 struct cifs_ses *ses;
0071 struct TCP_Server_Info *server;
0072 struct nls_table *nls_codepage;
0073 int retries;
0074
0075
0076
0077
0078
0079
0080 if (!tcon)
0081 return 0;
0082
0083 ses = tcon->ses;
0084 server = ses->server;
0085
0086
0087
0088
0089
0090 spin_lock(&tcon->tc_lock);
0091 if (tcon->status == TID_EXITING) {
0092 if (smb_command != SMB_COM_WRITE_ANDX &&
0093 smb_command != SMB_COM_OPEN_ANDX &&
0094 smb_command != SMB_COM_TREE_DISCONNECT) {
0095 spin_unlock(&tcon->tc_lock);
0096 cifs_dbg(FYI, "can not send cmd %d while umounting\n",
0097 smb_command);
0098 return -ENODEV;
0099 }
0100 }
0101 spin_unlock(&tcon->tc_lock);
0102
0103 retries = server->nr_targets;
0104
0105
0106
0107
0108
0109
0110 while (server->tcpStatus == CifsNeedReconnect) {
0111 rc = wait_event_interruptible_timeout(server->response_q,
0112 (server->tcpStatus != CifsNeedReconnect),
0113 10 * HZ);
0114 if (rc < 0) {
0115 cifs_dbg(FYI, "%s: aborting reconnect due to a received signal by the process\n",
0116 __func__);
0117 return -ERESTARTSYS;
0118 }
0119
0120
0121 spin_lock(&server->srv_lock);
0122 if (server->tcpStatus != CifsNeedReconnect) {
0123 spin_unlock(&server->srv_lock);
0124 break;
0125 }
0126 spin_unlock(&server->srv_lock);
0127
0128 if (retries && --retries)
0129 continue;
0130
0131
0132
0133
0134
0135
0136 if (!tcon->retry) {
0137 cifs_dbg(FYI, "gave up waiting on reconnect in smb_init\n");
0138 return -EHOSTDOWN;
0139 }
0140 retries = server->nr_targets;
0141 }
0142
0143 spin_lock(&ses->chan_lock);
0144 if (!cifs_chan_needs_reconnect(ses, server) && !tcon->need_reconnect) {
0145 spin_unlock(&ses->chan_lock);
0146 return 0;
0147 }
0148 spin_unlock(&ses->chan_lock);
0149
0150 nls_codepage = load_nls_default();
0151
0152
0153
0154
0155
0156
0157 spin_lock(&server->srv_lock);
0158 if (server->tcpStatus == CifsNeedReconnect) {
0159 spin_unlock(&server->srv_lock);
0160 rc = -EHOSTDOWN;
0161 goto out;
0162 }
0163 spin_unlock(&server->srv_lock);
0164
0165
0166
0167
0168
0169 spin_lock(&ses->chan_lock);
0170 if (!cifs_chan_needs_reconnect(ses, server)) {
0171 spin_unlock(&ses->chan_lock);
0172
0173
0174 if (tcon->need_reconnect)
0175 goto skip_sess_setup;
0176
0177 rc = -EHOSTDOWN;
0178 goto out;
0179 }
0180 spin_unlock(&ses->chan_lock);
0181
0182 mutex_lock(&ses->session_mutex);
0183 rc = cifs_negotiate_protocol(0, ses, server);
0184 if (!rc)
0185 rc = cifs_setup_session(0, ses, server, nls_codepage);
0186
0187
0188 if (rc || !tcon->need_reconnect) {
0189 mutex_unlock(&ses->session_mutex);
0190 goto out;
0191 }
0192
0193 skip_sess_setup:
0194 cifs_mark_open_files_invalid(tcon);
0195 rc = cifs_tree_connect(0, tcon, nls_codepage);
0196 mutex_unlock(&ses->session_mutex);
0197 cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
0198
0199 if (rc) {
0200 pr_warn_once("reconnect tcon failed rc = %d\n", rc);
0201 goto out;
0202 }
0203
0204 atomic_inc(&tconInfoReconnectCount);
0205
0206
0207 if (cap_unix(ses))
0208 reset_cifs_unix_caps(0, tcon, NULL, NULL);
0209
0210
0211
0212
0213
0214
0215
0216
0217 out:
0218
0219
0220
0221
0222 switch (smb_command) {
0223 case SMB_COM_READ_ANDX:
0224 case SMB_COM_WRITE_ANDX:
0225 case SMB_COM_CLOSE:
0226 case SMB_COM_FIND_CLOSE2:
0227 case SMB_COM_LOCKING_ANDX:
0228 rc = -EAGAIN;
0229 }
0230
0231 unload_nls(nls_codepage);
0232 return rc;
0233 }
0234
0235
0236
0237
0238 static int
0239 small_smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
0240 void **request_buf)
0241 {
0242 int rc;
0243
0244 rc = cifs_reconnect_tcon(tcon, smb_command);
0245 if (rc)
0246 return rc;
0247
0248 *request_buf = cifs_small_buf_get();
0249 if (*request_buf == NULL) {
0250
0251 return -ENOMEM;
0252 }
0253
0254 header_assemble((struct smb_hdr *) *request_buf, smb_command,
0255 tcon, wct);
0256
0257 if (tcon != NULL)
0258 cifs_stats_inc(&tcon->num_smbs_sent);
0259
0260 return 0;
0261 }
0262
0263 int
0264 small_smb_init_no_tc(const int smb_command, const int wct,
0265 struct cifs_ses *ses, void **request_buf)
0266 {
0267 int rc;
0268 struct smb_hdr *buffer;
0269
0270 rc = small_smb_init(smb_command, wct, NULL, request_buf);
0271 if (rc)
0272 return rc;
0273
0274 buffer = (struct smb_hdr *)*request_buf;
0275 buffer->Mid = get_next_mid(ses->server);
0276 if (ses->capabilities & CAP_UNICODE)
0277 buffer->Flags2 |= SMBFLG2_UNICODE;
0278 if (ses->capabilities & CAP_STATUS32)
0279 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
0280
0281
0282
0283
0284
0285
0286 return rc;
0287 }
0288
0289
0290 static int
0291 __smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
0292 void **request_buf, void **response_buf)
0293 {
0294 *request_buf = cifs_buf_get();
0295 if (*request_buf == NULL) {
0296
0297 return -ENOMEM;
0298 }
0299
0300
0301
0302
0303 if (response_buf)
0304 *response_buf = *request_buf;
0305
0306 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
0307 wct);
0308
0309 if (tcon != NULL)
0310 cifs_stats_inc(&tcon->num_smbs_sent);
0311
0312 return 0;
0313 }
0314
0315
0316 static int
0317 smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
0318 void **request_buf, void **response_buf)
0319 {
0320 int rc;
0321
0322 rc = cifs_reconnect_tcon(tcon, smb_command);
0323 if (rc)
0324 return rc;
0325
0326 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
0327 }
0328
0329 static int
0330 smb_init_no_reconnect(int smb_command, int wct, struct cifs_tcon *tcon,
0331 void **request_buf, void **response_buf)
0332 {
0333 spin_lock(&tcon->ses->chan_lock);
0334 if (cifs_chan_needs_reconnect(tcon->ses, tcon->ses->server) ||
0335 tcon->need_reconnect) {
0336 spin_unlock(&tcon->ses->chan_lock);
0337 return -EHOSTDOWN;
0338 }
0339 spin_unlock(&tcon->ses->chan_lock);
0340
0341 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
0342 }
0343
0344 static int validate_t2(struct smb_t2_rsp *pSMB)
0345 {
0346 unsigned int total_size;
0347
0348
0349 if (pSMB->hdr.WordCount < 10)
0350 goto vt2_err;
0351
0352
0353 if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
0354 get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
0355 goto vt2_err;
0356
0357 total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
0358 if (total_size >= 512)
0359 goto vt2_err;
0360
0361
0362
0363
0364 total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
0365 if (total_size > get_bcc(&pSMB->hdr) ||
0366 total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
0367 goto vt2_err;
0368
0369 return 0;
0370 vt2_err:
0371 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
0372 sizeof(struct smb_t2_rsp) + 16);
0373 return -EINVAL;
0374 }
0375
0376 static int
0377 decode_ext_sec_blob(struct cifs_ses *ses, NEGOTIATE_RSP *pSMBr)
0378 {
0379 int rc = 0;
0380 u16 count;
0381 char *guid = pSMBr->u.extended_response.GUID;
0382 struct TCP_Server_Info *server = ses->server;
0383
0384 count = get_bcc(&pSMBr->hdr);
0385 if (count < SMB1_CLIENT_GUID_SIZE)
0386 return -EIO;
0387
0388 spin_lock(&cifs_tcp_ses_lock);
0389 if (server->srv_count > 1) {
0390 spin_unlock(&cifs_tcp_ses_lock);
0391 if (memcmp(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE) != 0) {
0392 cifs_dbg(FYI, "server UID changed\n");
0393 memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
0394 }
0395 } else {
0396 spin_unlock(&cifs_tcp_ses_lock);
0397 memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
0398 }
0399
0400 if (count == SMB1_CLIENT_GUID_SIZE) {
0401 server->sec_ntlmssp = true;
0402 } else {
0403 count -= SMB1_CLIENT_GUID_SIZE;
0404 rc = decode_negTokenInit(
0405 pSMBr->u.extended_response.SecurityBlob, count, server);
0406 if (rc != 1)
0407 return -EINVAL;
0408 }
0409
0410 return 0;
0411 }
0412
0413 static bool
0414 should_set_ext_sec_flag(enum securityEnum sectype)
0415 {
0416 switch (sectype) {
0417 case RawNTLMSSP:
0418 case Kerberos:
0419 return true;
0420 case Unspecified:
0421 if (global_secflags &
0422 (CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP))
0423 return true;
0424 fallthrough;
0425 default:
0426 return false;
0427 }
0428 }
0429
0430 int
0431 CIFSSMBNegotiate(const unsigned int xid,
0432 struct cifs_ses *ses,
0433 struct TCP_Server_Info *server)
0434 {
0435 NEGOTIATE_REQ *pSMB;
0436 NEGOTIATE_RSP *pSMBr;
0437 int rc = 0;
0438 int bytes_returned;
0439 int i;
0440 u16 count;
0441
0442 if (!server) {
0443 WARN(1, "%s: server is NULL!\n", __func__);
0444 return -EIO;
0445 }
0446
0447 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL ,
0448 (void **) &pSMB, (void **) &pSMBr);
0449 if (rc)
0450 return rc;
0451
0452 pSMB->hdr.Mid = get_next_mid(server);
0453 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
0454
0455 if (should_set_ext_sec_flag(ses->sectype)) {
0456 cifs_dbg(FYI, "Requesting extended security\n");
0457 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
0458 }
0459
0460 count = 0;
0461
0462
0463
0464
0465 for (i = 0; i < CIFS_NUM_PROT; i++) {
0466 size_t len = strlen(protocols[i].name) + 1;
0467
0468 memcpy(pSMB->DialectsArray+count, protocols[i].name, len);
0469 count += len;
0470 }
0471 inc_rfc1001_len(pSMB, count);
0472 pSMB->ByteCount = cpu_to_le16(count);
0473
0474 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
0475 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
0476 if (rc != 0)
0477 goto neg_err_exit;
0478
0479 server->dialect = le16_to_cpu(pSMBr->DialectIndex);
0480 cifs_dbg(FYI, "Dialect: %d\n", server->dialect);
0481
0482 if ((pSMBr->hdr.WordCount <= 13) || (server->dialect == BAD_PROT)) {
0483
0484
0485
0486 rc = -EOPNOTSUPP;
0487 goto neg_err_exit;
0488 } else if (pSMBr->hdr.WordCount != 17) {
0489
0490 rc = -EOPNOTSUPP;
0491 goto neg_err_exit;
0492 }
0493
0494
0495 server->sec_mode = pSMBr->SecurityMode;
0496 if ((server->sec_mode & SECMODE_USER) == 0)
0497 cifs_dbg(FYI, "share mode security\n");
0498
0499
0500
0501 server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
0502 cifs_max_pending);
0503 set_credits(server, server->maxReq);
0504
0505 server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
0506
0507 server->max_read = server->maxBuf;
0508 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
0509 cifs_dbg(NOISY, "Max buf = %d\n", ses->server->maxBuf);
0510 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
0511 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
0512 server->timeAdj *= 60;
0513
0514 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
0515 server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
0516 memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
0517 CIFS_CRYPTO_KEY_SIZE);
0518 } else if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
0519 server->capabilities & CAP_EXTENDED_SECURITY) {
0520 server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
0521 rc = decode_ext_sec_blob(ses, pSMBr);
0522 } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
0523 rc = -EIO;
0524 } else {
0525 server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
0526 server->capabilities &= ~CAP_EXTENDED_SECURITY;
0527 }
0528
0529 if (!rc)
0530 rc = cifs_enable_signing(server, ses->sign);
0531 neg_err_exit:
0532 cifs_buf_release(pSMB);
0533
0534 cifs_dbg(FYI, "negprot rc %d\n", rc);
0535 return rc;
0536 }
0537
0538 int
0539 CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon)
0540 {
0541 struct smb_hdr *smb_buffer;
0542 int rc = 0;
0543
0544 cifs_dbg(FYI, "In tree disconnect\n");
0545
0546
0547 if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
0548 return -EIO;
0549
0550
0551
0552
0553
0554
0555
0556 spin_lock(&tcon->ses->chan_lock);
0557 if ((tcon->need_reconnect) || CIFS_ALL_CHANS_NEED_RECONNECT(tcon->ses)) {
0558 spin_unlock(&tcon->ses->chan_lock);
0559 return -EIO;
0560 }
0561 spin_unlock(&tcon->ses->chan_lock);
0562
0563 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
0564 (void **)&smb_buffer);
0565 if (rc)
0566 return rc;
0567
0568 rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, 0);
0569 cifs_small_buf_release(smb_buffer);
0570 if (rc)
0571 cifs_dbg(FYI, "Tree disconnect failed %d\n", rc);
0572
0573
0574
0575 if (rc == -EAGAIN)
0576 rc = 0;
0577
0578 return rc;
0579 }
0580
0581
0582
0583
0584
0585
0586
0587
0588 static void
0589 cifs_echo_callback(struct mid_q_entry *mid)
0590 {
0591 struct TCP_Server_Info *server = mid->callback_data;
0592 struct cifs_credits credits = { .value = 1, .instance = 0 };
0593
0594 release_mid(mid);
0595 add_credits(server, &credits, CIFS_ECHO_OP);
0596 }
0597
0598 int
0599 CIFSSMBEcho(struct TCP_Server_Info *server)
0600 {
0601 ECHO_REQ *smb;
0602 int rc = 0;
0603 struct kvec iov[2];
0604 struct smb_rqst rqst = { .rq_iov = iov,
0605 .rq_nvec = 2 };
0606
0607 cifs_dbg(FYI, "In echo request\n");
0608
0609 rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
0610 if (rc)
0611 return rc;
0612
0613 if (server->capabilities & CAP_UNICODE)
0614 smb->hdr.Flags2 |= SMBFLG2_UNICODE;
0615
0616
0617 smb->hdr.Tid = 0xffff;
0618 smb->hdr.WordCount = 1;
0619 put_unaligned_le16(1, &smb->EchoCount);
0620 put_bcc(1, &smb->hdr);
0621 smb->Data[0] = 'a';
0622 inc_rfc1001_len(smb, 3);
0623
0624 iov[0].iov_len = 4;
0625 iov[0].iov_base = smb;
0626 iov[1].iov_len = get_rfc1002_length(smb);
0627 iov[1].iov_base = (char *)smb + 4;
0628
0629 rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback, NULL,
0630 server, CIFS_NON_BLOCKING | CIFS_ECHO_OP, NULL);
0631 if (rc)
0632 cifs_dbg(FYI, "Echo request failed: %d\n", rc);
0633
0634 cifs_small_buf_release(smb);
0635
0636 return rc;
0637 }
0638
0639 int
0640 CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses)
0641 {
0642 LOGOFF_ANDX_REQ *pSMB;
0643 int rc = 0;
0644
0645 cifs_dbg(FYI, "In SMBLogoff for session disconnect\n");
0646
0647
0648
0649
0650
0651
0652 if (!ses || !ses->server)
0653 return -EIO;
0654
0655 mutex_lock(&ses->session_mutex);
0656 spin_lock(&ses->chan_lock);
0657 if (CIFS_ALL_CHANS_NEED_RECONNECT(ses)) {
0658 spin_unlock(&ses->chan_lock);
0659 goto session_already_dead;
0660
0661 }
0662 spin_unlock(&ses->chan_lock);
0663
0664 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
0665 if (rc) {
0666 mutex_unlock(&ses->session_mutex);
0667 return rc;
0668 }
0669
0670 pSMB->hdr.Mid = get_next_mid(ses->server);
0671
0672 if (ses->server->sign)
0673 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
0674
0675 pSMB->hdr.Uid = ses->Suid;
0676
0677 pSMB->AndXCommand = 0xFF;
0678 rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, 0);
0679 cifs_small_buf_release(pSMB);
0680 session_already_dead:
0681 mutex_unlock(&ses->session_mutex);
0682
0683
0684
0685
0686 if (rc == -EAGAIN)
0687 rc = 0;
0688 return rc;
0689 }
0690
0691 int
0692 CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
0693 const char *fileName, __u16 type,
0694 const struct nls_table *nls_codepage, int remap)
0695 {
0696 TRANSACTION2_SPI_REQ *pSMB = NULL;
0697 TRANSACTION2_SPI_RSP *pSMBr = NULL;
0698 struct unlink_psx_rq *pRqD;
0699 int name_len;
0700 int rc = 0;
0701 int bytes_returned = 0;
0702 __u16 params, param_offset, offset, byte_count;
0703
0704 cifs_dbg(FYI, "In POSIX delete\n");
0705 PsxDelete:
0706 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
0707 (void **) &pSMBr);
0708 if (rc)
0709 return rc;
0710
0711 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
0712 name_len =
0713 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
0714 PATH_MAX, nls_codepage, remap);
0715 name_len++;
0716 name_len *= 2;
0717 } else {
0718 name_len = copy_path_name(pSMB->FileName, fileName);
0719 }
0720
0721 params = 6 + name_len;
0722 pSMB->MaxParameterCount = cpu_to_le16(2);
0723 pSMB->MaxDataCount = 0;
0724 pSMB->MaxSetupCount = 0;
0725 pSMB->Reserved = 0;
0726 pSMB->Flags = 0;
0727 pSMB->Timeout = 0;
0728 pSMB->Reserved2 = 0;
0729 param_offset = offsetof(struct smb_com_transaction2_spi_req,
0730 InformationLevel) - 4;
0731 offset = param_offset + params;
0732
0733
0734
0735
0736
0737 pRqD = (struct unlink_psx_rq *)((char *)(pSMB) + offset + 4);
0738 pRqD->type = cpu_to_le16(type);
0739 pSMB->ParameterOffset = cpu_to_le16(param_offset);
0740 pSMB->DataOffset = cpu_to_le16(offset);
0741 pSMB->SetupCount = 1;
0742 pSMB->Reserved3 = 0;
0743 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
0744 byte_count = 3 + params + sizeof(struct unlink_psx_rq);
0745
0746 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
0747 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
0748 pSMB->ParameterCount = cpu_to_le16(params);
0749 pSMB->TotalParameterCount = pSMB->ParameterCount;
0750 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
0751 pSMB->Reserved4 = 0;
0752 inc_rfc1001_len(pSMB, byte_count);
0753 pSMB->ByteCount = cpu_to_le16(byte_count);
0754 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
0755 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
0756 if (rc)
0757 cifs_dbg(FYI, "Posix delete returned %d\n", rc);
0758 cifs_buf_release(pSMB);
0759
0760 cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
0761
0762 if (rc == -EAGAIN)
0763 goto PsxDelete;
0764
0765 return rc;
0766 }
0767
0768 int
0769 CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
0770 struct cifs_sb_info *cifs_sb)
0771 {
0772 DELETE_FILE_REQ *pSMB = NULL;
0773 DELETE_FILE_RSP *pSMBr = NULL;
0774 int rc = 0;
0775 int bytes_returned;
0776 int name_len;
0777 int remap = cifs_remap(cifs_sb);
0778
0779 DelFileRetry:
0780 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
0781 (void **) &pSMBr);
0782 if (rc)
0783 return rc;
0784
0785 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
0786 name_len = cifsConvertToUTF16((__le16 *) pSMB->fileName, name,
0787 PATH_MAX, cifs_sb->local_nls,
0788 remap);
0789 name_len++;
0790 name_len *= 2;
0791 } else {
0792 name_len = copy_path_name(pSMB->fileName, name);
0793 }
0794 pSMB->SearchAttributes =
0795 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
0796 pSMB->BufferFormat = 0x04;
0797 inc_rfc1001_len(pSMB, name_len + 1);
0798 pSMB->ByteCount = cpu_to_le16(name_len + 1);
0799 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
0800 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
0801 cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
0802 if (rc)
0803 cifs_dbg(FYI, "Error in RMFile = %d\n", rc);
0804
0805 cifs_buf_release(pSMB);
0806 if (rc == -EAGAIN)
0807 goto DelFileRetry;
0808
0809 return rc;
0810 }
0811
0812 int
0813 CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
0814 struct cifs_sb_info *cifs_sb)
0815 {
0816 DELETE_DIRECTORY_REQ *pSMB = NULL;
0817 DELETE_DIRECTORY_RSP *pSMBr = NULL;
0818 int rc = 0;
0819 int bytes_returned;
0820 int name_len;
0821 int remap = cifs_remap(cifs_sb);
0822
0823 cifs_dbg(FYI, "In CIFSSMBRmDir\n");
0824 RmDirRetry:
0825 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
0826 (void **) &pSMBr);
0827 if (rc)
0828 return rc;
0829
0830 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
0831 name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
0832 PATH_MAX, cifs_sb->local_nls,
0833 remap);
0834 name_len++;
0835 name_len *= 2;
0836 } else {
0837 name_len = copy_path_name(pSMB->DirName, name);
0838 }
0839
0840 pSMB->BufferFormat = 0x04;
0841 inc_rfc1001_len(pSMB, name_len + 1);
0842 pSMB->ByteCount = cpu_to_le16(name_len + 1);
0843 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
0844 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
0845 cifs_stats_inc(&tcon->stats.cifs_stats.num_rmdirs);
0846 if (rc)
0847 cifs_dbg(FYI, "Error in RMDir = %d\n", rc);
0848
0849 cifs_buf_release(pSMB);
0850 if (rc == -EAGAIN)
0851 goto RmDirRetry;
0852 return rc;
0853 }
0854
0855 int
0856 CIFSSMBMkDir(const unsigned int xid, struct inode *inode, umode_t mode,
0857 struct cifs_tcon *tcon, const char *name,
0858 struct cifs_sb_info *cifs_sb)
0859 {
0860 int rc = 0;
0861 CREATE_DIRECTORY_REQ *pSMB = NULL;
0862 CREATE_DIRECTORY_RSP *pSMBr = NULL;
0863 int bytes_returned;
0864 int name_len;
0865 int remap = cifs_remap(cifs_sb);
0866
0867 cifs_dbg(FYI, "In CIFSSMBMkDir\n");
0868 MkDirRetry:
0869 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
0870 (void **) &pSMBr);
0871 if (rc)
0872 return rc;
0873
0874 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
0875 name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
0876 PATH_MAX, cifs_sb->local_nls,
0877 remap);
0878 name_len++;
0879 name_len *= 2;
0880 } else {
0881 name_len = copy_path_name(pSMB->DirName, name);
0882 }
0883
0884 pSMB->BufferFormat = 0x04;
0885 inc_rfc1001_len(pSMB, name_len + 1);
0886 pSMB->ByteCount = cpu_to_le16(name_len + 1);
0887 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
0888 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
0889 cifs_stats_inc(&tcon->stats.cifs_stats.num_mkdirs);
0890 if (rc)
0891 cifs_dbg(FYI, "Error in Mkdir = %d\n", rc);
0892
0893 cifs_buf_release(pSMB);
0894 if (rc == -EAGAIN)
0895 goto MkDirRetry;
0896 return rc;
0897 }
0898
0899 int
0900 CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon,
0901 __u32 posix_flags, __u64 mode, __u16 *netfid,
0902 FILE_UNIX_BASIC_INFO *pRetData, __u32 *pOplock,
0903 const char *name, const struct nls_table *nls_codepage,
0904 int remap)
0905 {
0906 TRANSACTION2_SPI_REQ *pSMB = NULL;
0907 TRANSACTION2_SPI_RSP *pSMBr = NULL;
0908 int name_len;
0909 int rc = 0;
0910 int bytes_returned = 0;
0911 __u16 params, param_offset, offset, byte_count, count;
0912 OPEN_PSX_REQ *pdata;
0913 OPEN_PSX_RSP *psx_rsp;
0914
0915 cifs_dbg(FYI, "In POSIX Create\n");
0916 PsxCreat:
0917 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
0918 (void **) &pSMBr);
0919 if (rc)
0920 return rc;
0921
0922 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
0923 name_len =
0924 cifsConvertToUTF16((__le16 *) pSMB->FileName, name,
0925 PATH_MAX, nls_codepage, remap);
0926 name_len++;
0927 name_len *= 2;
0928 } else {
0929 name_len = copy_path_name(pSMB->FileName, name);
0930 }
0931
0932 params = 6 + name_len;
0933 count = sizeof(OPEN_PSX_REQ);
0934 pSMB->MaxParameterCount = cpu_to_le16(2);
0935 pSMB->MaxDataCount = cpu_to_le16(1000);
0936 pSMB->MaxSetupCount = 0;
0937 pSMB->Reserved = 0;
0938 pSMB->Flags = 0;
0939 pSMB->Timeout = 0;
0940 pSMB->Reserved2 = 0;
0941 param_offset = offsetof(struct smb_com_transaction2_spi_req,
0942 InformationLevel) - 4;
0943 offset = param_offset + params;
0944
0945 pdata = (OPEN_PSX_REQ *)((char *)(pSMB) + offset + 4);
0946 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
0947 pdata->Permissions = cpu_to_le64(mode);
0948 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
0949 pdata->OpenFlags = cpu_to_le32(*pOplock);
0950 pSMB->ParameterOffset = cpu_to_le16(param_offset);
0951 pSMB->DataOffset = cpu_to_le16(offset);
0952 pSMB->SetupCount = 1;
0953 pSMB->Reserved3 = 0;
0954 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
0955 byte_count = 3 + params + count;
0956
0957 pSMB->DataCount = cpu_to_le16(count);
0958 pSMB->ParameterCount = cpu_to_le16(params);
0959 pSMB->TotalDataCount = pSMB->DataCount;
0960 pSMB->TotalParameterCount = pSMB->ParameterCount;
0961 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
0962 pSMB->Reserved4 = 0;
0963 inc_rfc1001_len(pSMB, byte_count);
0964 pSMB->ByteCount = cpu_to_le16(byte_count);
0965 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
0966 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
0967 if (rc) {
0968 cifs_dbg(FYI, "Posix create returned %d\n", rc);
0969 goto psx_create_err;
0970 }
0971
0972 cifs_dbg(FYI, "copying inode info\n");
0973 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
0974
0975 if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
0976 rc = -EIO;
0977 goto psx_create_err;
0978 }
0979
0980
0981 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
0982 + le16_to_cpu(pSMBr->t2.DataOffset));
0983
0984 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
0985 if (netfid)
0986 *netfid = psx_rsp->Fid;
0987
0988
0989 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
0990 *pOplock |= CIFS_CREATE_ACTION;
0991
0992 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
0993 pRetData->Type = cpu_to_le32(-1);
0994 cifs_dbg(NOISY, "unknown type\n");
0995 } else {
0996 if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
0997 + sizeof(FILE_UNIX_BASIC_INFO)) {
0998 cifs_dbg(VFS, "Open response data too small\n");
0999 pRetData->Type = cpu_to_le32(-1);
1000 goto psx_create_err;
1001 }
1002 memcpy((char *) pRetData,
1003 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1004 sizeof(FILE_UNIX_BASIC_INFO));
1005 }
1006
1007 psx_create_err:
1008 cifs_buf_release(pSMB);
1009
1010 if (posix_flags & SMB_O_DIRECTORY)
1011 cifs_stats_inc(&tcon->stats.cifs_stats.num_posixmkdirs);
1012 else
1013 cifs_stats_inc(&tcon->stats.cifs_stats.num_posixopens);
1014
1015 if (rc == -EAGAIN)
1016 goto PsxCreat;
1017
1018 return rc;
1019 }
1020
1021 static __u16 convert_disposition(int disposition)
1022 {
1023 __u16 ofun = 0;
1024
1025 switch (disposition) {
1026 case FILE_SUPERSEDE:
1027 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1028 break;
1029 case FILE_OPEN:
1030 ofun = SMBOPEN_OAPPEND;
1031 break;
1032 case FILE_CREATE:
1033 ofun = SMBOPEN_OCREATE;
1034 break;
1035 case FILE_OPEN_IF:
1036 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1037 break;
1038 case FILE_OVERWRITE:
1039 ofun = SMBOPEN_OTRUNC;
1040 break;
1041 case FILE_OVERWRITE_IF:
1042 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1043 break;
1044 default:
1045 cifs_dbg(FYI, "unknown disposition %d\n", disposition);
1046 ofun = SMBOPEN_OAPPEND;
1047 }
1048 return ofun;
1049 }
1050
1051 static int
1052 access_flags_to_smbopen_mode(const int access_flags)
1053 {
1054 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1055
1056 if (masked_flags == GENERIC_READ)
1057 return SMBOPEN_READ;
1058 else if (masked_flags == GENERIC_WRITE)
1059 return SMBOPEN_WRITE;
1060
1061
1062 return SMBOPEN_READWRITE;
1063 }
1064
1065 int
1066 SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
1067 const char *fileName, const int openDisposition,
1068 const int access_flags, const int create_options, __u16 *netfid,
1069 int *pOplock, FILE_ALL_INFO *pfile_info,
1070 const struct nls_table *nls_codepage, int remap)
1071 {
1072 int rc;
1073 OPENX_REQ *pSMB = NULL;
1074 OPENX_RSP *pSMBr = NULL;
1075 int bytes_returned;
1076 int name_len;
1077 __u16 count;
1078
1079 OldOpenRetry:
1080 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1081 (void **) &pSMBr);
1082 if (rc)
1083 return rc;
1084
1085 pSMB->AndXCommand = 0xFF;
1086
1087 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1088 count = 1;
1089 name_len =
1090 cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1091 fileName, PATH_MAX, nls_codepage, remap);
1092 name_len++;
1093 name_len *= 2;
1094 } else {
1095 count = 0;
1096 name_len = copy_path_name(pSMB->fileName, fileName);
1097 }
1098 if (*pOplock & REQ_OPLOCK)
1099 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1100 else if (*pOplock & REQ_BATCHOPLOCK)
1101 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1102
1103 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1104 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1105 pSMB->Mode |= cpu_to_le16(0x40);
1106
1107
1108
1109
1110 if (create_options & CREATE_OPTION_SPECIAL)
1111 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1112 else
1113 pSMB->FileAttributes = cpu_to_le16(0);
1114
1115 if (create_options & CREATE_OPTION_READONLY)
1116 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1117
1118
1119
1120
1121
1122
1123 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1124 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1125 count += name_len;
1126 inc_rfc1001_len(pSMB, count);
1127
1128 pSMB->ByteCount = cpu_to_le16(count);
1129 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1130 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1131 cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1132 if (rc) {
1133 cifs_dbg(FYI, "Error in Open = %d\n", rc);
1134 } else {
1135
1136
1137
1138
1139 *netfid = pSMBr->Fid;
1140
1141
1142
1143
1144
1145
1146
1147 if (pfile_info) {
1148 pfile_info->CreationTime = 0;
1149 pfile_info->LastAccessTime = 0;
1150 pfile_info->LastWriteTime = 0;
1151 pfile_info->ChangeTime = 0;
1152 pfile_info->Attributes =
1153 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1154
1155 pfile_info->AllocationSize =
1156 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1157 pfile_info->EndOfFile = pfile_info->AllocationSize;
1158 pfile_info->NumberOfLinks = cpu_to_le32(1);
1159 pfile_info->DeletePending = 0;
1160 }
1161 }
1162
1163 cifs_buf_release(pSMB);
1164 if (rc == -EAGAIN)
1165 goto OldOpenRetry;
1166 return rc;
1167 }
1168
1169 int
1170 CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,
1171 FILE_ALL_INFO *buf)
1172 {
1173 int rc;
1174 OPEN_REQ *req = NULL;
1175 OPEN_RSP *rsp = NULL;
1176 int bytes_returned;
1177 int name_len;
1178 __u16 count;
1179 struct cifs_sb_info *cifs_sb = oparms->cifs_sb;
1180 struct cifs_tcon *tcon = oparms->tcon;
1181 int remap = cifs_remap(cifs_sb);
1182 const struct nls_table *nls = cifs_sb->local_nls;
1183 int create_options = oparms->create_options;
1184 int desired_access = oparms->desired_access;
1185 int disposition = oparms->disposition;
1186 const char *path = oparms->path;
1187
1188 openRetry:
1189 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **)&req,
1190 (void **)&rsp);
1191 if (rc)
1192 return rc;
1193
1194
1195 req->AndXCommand = 0xFF;
1196
1197 if (req->hdr.Flags2 & SMBFLG2_UNICODE) {
1198
1199 count = 1;
1200 name_len = cifsConvertToUTF16((__le16 *)(req->fileName + 1),
1201 path, PATH_MAX, nls, remap);
1202
1203 name_len++;
1204 name_len *= 2;
1205 req->NameLength = cpu_to_le16(name_len);
1206 } else {
1207
1208
1209 count = 0;
1210 name_len = copy_path_name(req->fileName, path);
1211 req->NameLength = cpu_to_le16(name_len);
1212 }
1213
1214 if (*oplock & REQ_OPLOCK)
1215 req->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1216 else if (*oplock & REQ_BATCHOPLOCK)
1217 req->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1218
1219 req->DesiredAccess = cpu_to_le32(desired_access);
1220 req->AllocationSize = 0;
1221
1222
1223
1224
1225
1226 if (create_options & CREATE_OPTION_SPECIAL)
1227 req->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1228 else
1229 req->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1230
1231
1232
1233
1234
1235 if (tcon->ses->capabilities & CAP_UNIX)
1236 req->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1237
1238 if (create_options & CREATE_OPTION_READONLY)
1239 req->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1240
1241 req->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1242 req->CreateDisposition = cpu_to_le32(disposition);
1243 req->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1244
1245
1246 req->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1247 req->SecurityFlags = SECURITY_CONTEXT_TRACKING|SECURITY_EFFECTIVE_ONLY;
1248
1249 count += name_len;
1250 inc_rfc1001_len(req, count);
1251
1252 req->ByteCount = cpu_to_le16(count);
1253 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)req,
1254 (struct smb_hdr *)rsp, &bytes_returned, 0);
1255 cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1256 if (rc) {
1257 cifs_dbg(FYI, "Error in Open = %d\n", rc);
1258 cifs_buf_release(req);
1259 if (rc == -EAGAIN)
1260 goto openRetry;
1261 return rc;
1262 }
1263
1264
1265 *oplock = rsp->OplockLevel;
1266
1267 oparms->fid->netfid = rsp->Fid;
1268 oparms->fid->access = desired_access;
1269
1270
1271
1272 if (cpu_to_le32(FILE_CREATE) == rsp->CreateAction)
1273 *oplock |= CIFS_CREATE_ACTION;
1274
1275 if (buf) {
1276
1277 memcpy((char *)buf, (char *)&rsp->CreationTime, 36);
1278
1279 buf->AllocationSize = rsp->AllocationSize;
1280 buf->EndOfFile = rsp->EndOfFile;
1281 buf->NumberOfLinks = cpu_to_le32(1);
1282 buf->DeletePending = 0;
1283 }
1284
1285 cifs_buf_release(req);
1286 return rc;
1287 }
1288
1289 static void
1290 cifs_readv_callback(struct mid_q_entry *mid)
1291 {
1292 struct cifs_readdata *rdata = mid->callback_data;
1293 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1294 struct TCP_Server_Info *server = tcon->ses->server;
1295 struct smb_rqst rqst = { .rq_iov = rdata->iov,
1296 .rq_nvec = 2,
1297 .rq_pages = rdata->pages,
1298 .rq_offset = rdata->page_offset,
1299 .rq_npages = rdata->nr_pages,
1300 .rq_pagesz = rdata->pagesz,
1301 .rq_tailsz = rdata->tailsz };
1302 struct cifs_credits credits = { .value = 1, .instance = 0 };
1303
1304 cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%u\n",
1305 __func__, mid->mid, mid->mid_state, rdata->result,
1306 rdata->bytes);
1307
1308 switch (mid->mid_state) {
1309 case MID_RESPONSE_RECEIVED:
1310
1311 if (server->sign) {
1312 int rc = 0;
1313
1314 rc = cifs_verify_signature(&rqst, server,
1315 mid->sequence_number);
1316 if (rc)
1317 cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
1318 rc);
1319 }
1320
1321 task_io_account_read(rdata->got_bytes);
1322 cifs_stats_bytes_read(tcon, rdata->got_bytes);
1323 break;
1324 case MID_REQUEST_SUBMITTED:
1325 case MID_RETRY_NEEDED:
1326 rdata->result = -EAGAIN;
1327 if (server->sign && rdata->got_bytes)
1328
1329 rdata->got_bytes = 0;
1330
1331 task_io_account_read(rdata->got_bytes);
1332 cifs_stats_bytes_read(tcon, rdata->got_bytes);
1333 break;
1334 default:
1335 rdata->result = -EIO;
1336 }
1337
1338 queue_work(cifsiod_wq, &rdata->work);
1339 release_mid(mid);
1340 add_credits(server, &credits, 0);
1341 }
1342
1343
1344 int
1345 cifs_async_readv(struct cifs_readdata *rdata)
1346 {
1347 int rc;
1348 READ_REQ *smb = NULL;
1349 int wct;
1350 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1351 struct smb_rqst rqst = { .rq_iov = rdata->iov,
1352 .rq_nvec = 2 };
1353
1354 cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n",
1355 __func__, rdata->offset, rdata->bytes);
1356
1357 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1358 wct = 12;
1359 else {
1360 wct = 10;
1361 if ((rdata->offset >> 32) > 0) {
1362
1363 return -EIO;
1364 }
1365 }
1366
1367 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
1368 if (rc)
1369 return rc;
1370
1371 smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid);
1372 smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
1373
1374 smb->AndXCommand = 0xFF;
1375 smb->Fid = rdata->cfile->fid.netfid;
1376 smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
1377 if (wct == 12)
1378 smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
1379 smb->Remaining = 0;
1380 smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
1381 smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
1382 if (wct == 12)
1383 smb->ByteCount = 0;
1384 else {
1385
1386 struct smb_com_readx_req *smbr =
1387 (struct smb_com_readx_req *)smb;
1388 smbr->ByteCount = 0;
1389 }
1390
1391
1392 rdata->iov[0].iov_base = smb;
1393 rdata->iov[0].iov_len = 4;
1394 rdata->iov[1].iov_base = (char *)smb + 4;
1395 rdata->iov[1].iov_len = get_rfc1002_length(smb);
1396
1397 kref_get(&rdata->refcount);
1398 rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive,
1399 cifs_readv_callback, NULL, rdata, 0, NULL);
1400
1401 if (rc == 0)
1402 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1403 else
1404 kref_put(&rdata->refcount, cifs_readdata_release);
1405
1406 cifs_small_buf_release(smb);
1407 return rc;
1408 }
1409
1410 int
1411 CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
1412 unsigned int *nbytes, char **buf, int *pbuf_type)
1413 {
1414 int rc = -EACCES;
1415 READ_REQ *pSMB = NULL;
1416 READ_RSP *pSMBr = NULL;
1417 char *pReadData = NULL;
1418 int wct;
1419 int resp_buf_type = 0;
1420 struct kvec iov[1];
1421 struct kvec rsp_iov;
1422 __u32 pid = io_parms->pid;
1423 __u16 netfid = io_parms->netfid;
1424 __u64 offset = io_parms->offset;
1425 struct cifs_tcon *tcon = io_parms->tcon;
1426 unsigned int count = io_parms->length;
1427
1428 cifs_dbg(FYI, "Reading %d bytes on fid %d\n", count, netfid);
1429 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1430 wct = 12;
1431 else {
1432 wct = 10;
1433 if ((offset >> 32) > 0) {
1434
1435 return -EIO;
1436 }
1437 }
1438
1439 *nbytes = 0;
1440 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1441 if (rc)
1442 return rc;
1443
1444 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1445 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1446
1447
1448 if (tcon->ses->server == NULL)
1449 return -ECONNABORTED;
1450
1451 pSMB->AndXCommand = 0xFF;
1452 pSMB->Fid = netfid;
1453 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1454 if (wct == 12)
1455 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1456
1457 pSMB->Remaining = 0;
1458 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1459 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1460 if (wct == 12)
1461 pSMB->ByteCount = 0;
1462 else {
1463
1464 struct smb_com_readx_req *pSMBW =
1465 (struct smb_com_readx_req *)pSMB;
1466 pSMBW->ByteCount = 0;
1467 }
1468
1469 iov[0].iov_base = (char *)pSMB;
1470 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1471 rc = SendReceive2(xid, tcon->ses, iov, 1, &resp_buf_type,
1472 CIFS_LOG_ERROR, &rsp_iov);
1473 cifs_small_buf_release(pSMB);
1474 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1475 pSMBr = (READ_RSP *)rsp_iov.iov_base;
1476 if (rc) {
1477 cifs_dbg(VFS, "Send error in read = %d\n", rc);
1478 } else {
1479 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1480 data_length = data_length << 16;
1481 data_length += le16_to_cpu(pSMBr->DataLength);
1482 *nbytes = data_length;
1483
1484
1485 if ((data_length > CIFSMaxBufSize)
1486 || (data_length > count)) {
1487 cifs_dbg(FYI, "bad length %d for count %d\n",
1488 data_length, count);
1489 rc = -EIO;
1490 *nbytes = 0;
1491 } else {
1492 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1493 le16_to_cpu(pSMBr->DataOffset);
1494
1495
1496
1497
1498 if (*buf)
1499 memcpy(*buf, pReadData, data_length);
1500 }
1501 }
1502
1503 if (*buf) {
1504 free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
1505 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1506
1507 *buf = rsp_iov.iov_base;
1508 if (resp_buf_type == CIFS_SMALL_BUFFER)
1509 *pbuf_type = CIFS_SMALL_BUFFER;
1510 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1511 *pbuf_type = CIFS_LARGE_BUFFER;
1512 }
1513
1514
1515
1516 return rc;
1517 }
1518
1519
1520 int
1521 CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
1522 unsigned int *nbytes, const char *buf)
1523 {
1524 int rc = -EACCES;
1525 WRITE_REQ *pSMB = NULL;
1526 WRITE_RSP *pSMBr = NULL;
1527 int bytes_returned, wct;
1528 __u32 bytes_sent;
1529 __u16 byte_count;
1530 __u32 pid = io_parms->pid;
1531 __u16 netfid = io_parms->netfid;
1532 __u64 offset = io_parms->offset;
1533 struct cifs_tcon *tcon = io_parms->tcon;
1534 unsigned int count = io_parms->length;
1535
1536 *nbytes = 0;
1537
1538
1539 if (tcon->ses == NULL)
1540 return -ECONNABORTED;
1541
1542 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1543 wct = 14;
1544 else {
1545 wct = 12;
1546 if ((offset >> 32) > 0) {
1547
1548 return -EIO;
1549 }
1550 }
1551
1552 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1553 (void **) &pSMBr);
1554 if (rc)
1555 return rc;
1556
1557 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1558 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1559
1560
1561 if (tcon->ses->server == NULL)
1562 return -ECONNABORTED;
1563
1564 pSMB->AndXCommand = 0xFF;
1565 pSMB->Fid = netfid;
1566 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1567 if (wct == 14)
1568 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1569
1570 pSMB->Reserved = 0xFFFFFFFF;
1571 pSMB->WriteMode = 0;
1572 pSMB->Remaining = 0;
1573
1574
1575
1576
1577
1578 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1579 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1580 } else {
1581 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1582 & ~0xFF;
1583 }
1584
1585 if (bytes_sent > count)
1586 bytes_sent = count;
1587 pSMB->DataOffset =
1588 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1589 if (buf)
1590 memcpy(pSMB->Data, buf, bytes_sent);
1591 else if (count != 0) {
1592
1593 cifs_buf_release(pSMB);
1594 return -EINVAL;
1595 }
1596 if (wct == 14)
1597 byte_count = bytes_sent + 1;
1598 else
1599 byte_count = bytes_sent + 5;
1600
1601 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1602 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1603 inc_rfc1001_len(pSMB, byte_count);
1604
1605 if (wct == 14)
1606 pSMB->ByteCount = cpu_to_le16(byte_count);
1607 else {
1608
1609 struct smb_com_writex_req *pSMBW =
1610 (struct smb_com_writex_req *)pSMB;
1611 pSMBW->ByteCount = cpu_to_le16(byte_count);
1612 }
1613
1614 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1615 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1616 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1617 if (rc) {
1618 cifs_dbg(FYI, "Send error in write = %d\n", rc);
1619 } else {
1620 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1621 *nbytes = (*nbytes) << 16;
1622 *nbytes += le16_to_cpu(pSMBr->Count);
1623
1624
1625
1626
1627
1628
1629 if (*nbytes > count)
1630 *nbytes &= 0xFFFF;
1631 }
1632
1633 cifs_buf_release(pSMB);
1634
1635
1636
1637
1638 return rc;
1639 }
1640
1641
1642
1643
1644
1645 static void
1646 cifs_writev_callback(struct mid_q_entry *mid)
1647 {
1648 struct cifs_writedata *wdata = mid->callback_data;
1649 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
1650 unsigned int written;
1651 WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
1652 struct cifs_credits credits = { .value = 1, .instance = 0 };
1653
1654 switch (mid->mid_state) {
1655 case MID_RESPONSE_RECEIVED:
1656 wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
1657 if (wdata->result != 0)
1658 break;
1659
1660 written = le16_to_cpu(smb->CountHigh);
1661 written <<= 16;
1662 written += le16_to_cpu(smb->Count);
1663
1664
1665
1666
1667
1668
1669 if (written > wdata->bytes)
1670 written &= 0xFFFF;
1671
1672 if (written < wdata->bytes)
1673 wdata->result = -ENOSPC;
1674 else
1675 wdata->bytes = written;
1676 break;
1677 case MID_REQUEST_SUBMITTED:
1678 case MID_RETRY_NEEDED:
1679 wdata->result = -EAGAIN;
1680 break;
1681 default:
1682 wdata->result = -EIO;
1683 break;
1684 }
1685
1686 queue_work(cifsiod_wq, &wdata->work);
1687 release_mid(mid);
1688 add_credits(tcon->ses->server, &credits, 0);
1689 }
1690
1691
1692 int
1693 cifs_async_writev(struct cifs_writedata *wdata,
1694 void (*release)(struct kref *kref))
1695 {
1696 int rc = -EACCES;
1697 WRITE_REQ *smb = NULL;
1698 int wct;
1699 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
1700 struct kvec iov[2];
1701 struct smb_rqst rqst = { };
1702
1703 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1704 wct = 14;
1705 } else {
1706 wct = 12;
1707 if (wdata->offset >> 32 > 0) {
1708
1709 return -EIO;
1710 }
1711 }
1712
1713 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
1714 if (rc)
1715 goto async_writev_out;
1716
1717 smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
1718 smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
1719
1720 smb->AndXCommand = 0xFF;
1721 smb->Fid = wdata->cfile->fid.netfid;
1722 smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
1723 if (wct == 14)
1724 smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
1725 smb->Reserved = 0xFFFFFFFF;
1726 smb->WriteMode = 0;
1727 smb->Remaining = 0;
1728
1729 smb->DataOffset =
1730 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1731
1732
1733 iov[0].iov_len = 4;
1734 iov[0].iov_base = smb;
1735 iov[1].iov_len = get_rfc1002_length(smb) + 1;
1736 iov[1].iov_base = (char *)smb + 4;
1737
1738 rqst.rq_iov = iov;
1739 rqst.rq_nvec = 2;
1740 rqst.rq_pages = wdata->pages;
1741 rqst.rq_offset = wdata->page_offset;
1742 rqst.rq_npages = wdata->nr_pages;
1743 rqst.rq_pagesz = wdata->pagesz;
1744 rqst.rq_tailsz = wdata->tailsz;
1745
1746 cifs_dbg(FYI, "async write at %llu %u bytes\n",
1747 wdata->offset, wdata->bytes);
1748
1749 smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
1750 smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
1751
1752 if (wct == 14) {
1753 inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
1754 put_bcc(wdata->bytes + 1, &smb->hdr);
1755 } else {
1756
1757 struct smb_com_writex_req *smbw =
1758 (struct smb_com_writex_req *)smb;
1759 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
1760 put_bcc(wdata->bytes + 5, &smbw->hdr);
1761 iov[1].iov_len += 4;
1762 }
1763
1764 kref_get(&wdata->refcount);
1765 rc = cifs_call_async(tcon->ses->server, &rqst, NULL,
1766 cifs_writev_callback, NULL, wdata, 0, NULL);
1767
1768 if (rc == 0)
1769 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1770 else
1771 kref_put(&wdata->refcount, release);
1772
1773 async_writev_out:
1774 cifs_small_buf_release(smb);
1775 return rc;
1776 }
1777
1778 int
1779 CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
1780 unsigned int *nbytes, struct kvec *iov, int n_vec)
1781 {
1782 int rc;
1783 WRITE_REQ *pSMB = NULL;
1784 int wct;
1785 int smb_hdr_len;
1786 int resp_buf_type = 0;
1787 __u32 pid = io_parms->pid;
1788 __u16 netfid = io_parms->netfid;
1789 __u64 offset = io_parms->offset;
1790 struct cifs_tcon *tcon = io_parms->tcon;
1791 unsigned int count = io_parms->length;
1792 struct kvec rsp_iov;
1793
1794 *nbytes = 0;
1795
1796 cifs_dbg(FYI, "write2 at %lld %d bytes\n", (long long)offset, count);
1797
1798 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1799 wct = 14;
1800 } else {
1801 wct = 12;
1802 if ((offset >> 32) > 0) {
1803
1804 return -EIO;
1805 }
1806 }
1807 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1808 if (rc)
1809 return rc;
1810
1811 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1812 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1813
1814
1815 if (tcon->ses->server == NULL)
1816 return -ECONNABORTED;
1817
1818 pSMB->AndXCommand = 0xFF;
1819 pSMB->Fid = netfid;
1820 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1821 if (wct == 14)
1822 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1823 pSMB->Reserved = 0xFFFFFFFF;
1824 pSMB->WriteMode = 0;
1825 pSMB->Remaining = 0;
1826
1827 pSMB->DataOffset =
1828 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1829
1830 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1831 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1832
1833 smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
1834 if (wct == 14)
1835 inc_rfc1001_len(pSMB, count + 1);
1836 else
1837 inc_rfc1001_len(pSMB, count + 5);
1838 if (wct == 14)
1839 pSMB->ByteCount = cpu_to_le16(count + 1);
1840 else {
1841 struct smb_com_writex_req *pSMBW =
1842 (struct smb_com_writex_req *)pSMB;
1843 pSMBW->ByteCount = cpu_to_le16(count + 5);
1844 }
1845 iov[0].iov_base = pSMB;
1846 if (wct == 14)
1847 iov[0].iov_len = smb_hdr_len + 4;
1848 else
1849 iov[0].iov_len = smb_hdr_len + 8;
1850
1851 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, 0,
1852 &rsp_iov);
1853 cifs_small_buf_release(pSMB);
1854 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1855 if (rc) {
1856 cifs_dbg(FYI, "Send error Write2 = %d\n", rc);
1857 } else if (resp_buf_type == 0) {
1858
1859 rc = -EIO;
1860 } else {
1861 WRITE_RSP *pSMBr = (WRITE_RSP *)rsp_iov.iov_base;
1862 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1863 *nbytes = (*nbytes) << 16;
1864 *nbytes += le16_to_cpu(pSMBr->Count);
1865
1866
1867
1868
1869
1870
1871 if (*nbytes > count)
1872 *nbytes &= 0xFFFF;
1873 }
1874
1875 free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
1876
1877
1878
1879
1880 return rc;
1881 }
1882
1883 int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
1884 const __u16 netfid, const __u8 lock_type, const __u32 num_unlock,
1885 const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
1886 {
1887 int rc = 0;
1888 LOCK_REQ *pSMB = NULL;
1889 struct kvec iov[2];
1890 struct kvec rsp_iov;
1891 int resp_buf_type;
1892 __u16 count;
1893
1894 cifs_dbg(FYI, "cifs_lockv num lock %d num unlock %d\n",
1895 num_lock, num_unlock);
1896
1897 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1898 if (rc)
1899 return rc;
1900
1901 pSMB->Timeout = 0;
1902 pSMB->NumberOfLocks = cpu_to_le16(num_lock);
1903 pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
1904 pSMB->LockType = lock_type;
1905 pSMB->AndXCommand = 0xFF;
1906 pSMB->Fid = netfid;
1907
1908 count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
1909 inc_rfc1001_len(pSMB, count);
1910 pSMB->ByteCount = cpu_to_le16(count);
1911
1912 iov[0].iov_base = (char *)pSMB;
1913 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
1914 (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
1915 iov[1].iov_base = (char *)buf;
1916 iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
1917
1918 cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
1919 rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type,
1920 CIFS_NO_RSP_BUF, &rsp_iov);
1921 cifs_small_buf_release(pSMB);
1922 if (rc)
1923 cifs_dbg(FYI, "Send error in cifs_lockv = %d\n", rc);
1924
1925 return rc;
1926 }
1927
1928 int
1929 CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
1930 const __u16 smb_file_id, const __u32 netpid, const __u64 len,
1931 const __u64 offset, const __u32 numUnlock,
1932 const __u32 numLock, const __u8 lockType,
1933 const bool waitFlag, const __u8 oplock_level)
1934 {
1935 int rc = 0;
1936 LOCK_REQ *pSMB = NULL;
1937
1938 int bytes_returned;
1939 int flags = 0;
1940 __u16 count;
1941
1942 cifs_dbg(FYI, "CIFSSMBLock timeout %d numLock %d\n",
1943 (int)waitFlag, numLock);
1944 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1945
1946 if (rc)
1947 return rc;
1948
1949 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1950
1951 flags = CIFS_NO_SRV_RSP | CIFS_NON_BLOCKING | CIFS_OBREAK_OP;
1952 pSMB->Timeout = 0;
1953 } else if (waitFlag) {
1954 flags = CIFS_BLOCKING_OP;
1955 pSMB->Timeout = cpu_to_le32(-1);
1956 } else {
1957 pSMB->Timeout = 0;
1958 }
1959
1960 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1961 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1962 pSMB->LockType = lockType;
1963 pSMB->OplockLevel = oplock_level;
1964 pSMB->AndXCommand = 0xFF;
1965 pSMB->Fid = smb_file_id;
1966
1967 if ((numLock != 0) || (numUnlock != 0)) {
1968 pSMB->Locks[0].Pid = cpu_to_le16(netpid);
1969
1970 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1971 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1972 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1973 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1974 count = sizeof(LOCKING_ANDX_RANGE);
1975 } else {
1976
1977 count = 0;
1978 }
1979 inc_rfc1001_len(pSMB, count);
1980 pSMB->ByteCount = cpu_to_le16(count);
1981
1982 if (waitFlag)
1983 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1984 (struct smb_hdr *) pSMB, &bytes_returned);
1985 else
1986 rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags);
1987 cifs_small_buf_release(pSMB);
1988 cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
1989 if (rc)
1990 cifs_dbg(FYI, "Send error in Lock = %d\n", rc);
1991
1992
1993
1994 return rc;
1995 }
1996
1997 int
1998 CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
1999 const __u16 smb_file_id, const __u32 netpid,
2000 const loff_t start_offset, const __u64 len,
2001 struct file_lock *pLockData, const __u16 lock_type,
2002 const bool waitFlag)
2003 {
2004 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2005 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2006 struct cifs_posix_lock *parm_data;
2007 int rc = 0;
2008 int timeout = 0;
2009 int bytes_returned = 0;
2010 int resp_buf_type = 0;
2011 __u16 params, param_offset, offset, byte_count, count;
2012 struct kvec iov[1];
2013 struct kvec rsp_iov;
2014
2015 cifs_dbg(FYI, "Posix Lock\n");
2016
2017 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2018
2019 if (rc)
2020 return rc;
2021
2022 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2023
2024 params = 6;
2025 pSMB->MaxSetupCount = 0;
2026 pSMB->Reserved = 0;
2027 pSMB->Flags = 0;
2028 pSMB->Reserved2 = 0;
2029 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2030 offset = param_offset + params;
2031
2032 count = sizeof(struct cifs_posix_lock);
2033 pSMB->MaxParameterCount = cpu_to_le16(2);
2034 pSMB->MaxDataCount = cpu_to_le16(1000);
2035 pSMB->SetupCount = 1;
2036 pSMB->Reserved3 = 0;
2037 if (pLockData)
2038 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2039 else
2040 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2041 byte_count = 3 + params + count;
2042 pSMB->DataCount = cpu_to_le16(count);
2043 pSMB->ParameterCount = cpu_to_le16(params);
2044 pSMB->TotalDataCount = pSMB->DataCount;
2045 pSMB->TotalParameterCount = pSMB->ParameterCount;
2046 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2047
2048 parm_data = (struct cifs_posix_lock *)
2049 (((char *)pSMB) + offset + 4);
2050
2051 parm_data->lock_type = cpu_to_le16(lock_type);
2052 if (waitFlag) {
2053 timeout = CIFS_BLOCKING_OP;
2054 parm_data->lock_flags = cpu_to_le16(1);
2055 pSMB->Timeout = cpu_to_le32(-1);
2056 } else
2057 pSMB->Timeout = 0;
2058
2059 parm_data->pid = cpu_to_le32(netpid);
2060 parm_data->start = cpu_to_le64(start_offset);
2061 parm_data->length = cpu_to_le64(len);
2062
2063 pSMB->DataOffset = cpu_to_le16(offset);
2064 pSMB->Fid = smb_file_id;
2065 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2066 pSMB->Reserved4 = 0;
2067 inc_rfc1001_len(pSMB, byte_count);
2068 pSMB->ByteCount = cpu_to_le16(byte_count);
2069 if (waitFlag) {
2070 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2071 (struct smb_hdr *) pSMBr, &bytes_returned);
2072 } else {
2073 iov[0].iov_base = (char *)pSMB;
2074 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2075 rc = SendReceive2(xid, tcon->ses, iov, 1 ,
2076 &resp_buf_type, timeout, &rsp_iov);
2077 pSMBr = (struct smb_com_transaction2_sfi_rsp *)rsp_iov.iov_base;
2078 }
2079 cifs_small_buf_release(pSMB);
2080
2081 if (rc) {
2082 cifs_dbg(FYI, "Send error in Posix Lock = %d\n", rc);
2083 } else if (pLockData) {
2084
2085 __u16 data_offset;
2086 __u16 data_count;
2087 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2088
2089 if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2090 rc = -EIO;
2091 goto plk_err_exit;
2092 }
2093 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2094 data_count = le16_to_cpu(pSMBr->t2.DataCount);
2095 if (data_count < sizeof(struct cifs_posix_lock)) {
2096 rc = -EIO;
2097 goto plk_err_exit;
2098 }
2099 parm_data = (struct cifs_posix_lock *)
2100 ((char *)&pSMBr->hdr.Protocol + data_offset);
2101 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
2102 pLockData->fl_type = F_UNLCK;
2103 else {
2104 if (parm_data->lock_type ==
2105 cpu_to_le16(CIFS_RDLCK))
2106 pLockData->fl_type = F_RDLCK;
2107 else if (parm_data->lock_type ==
2108 cpu_to_le16(CIFS_WRLCK))
2109 pLockData->fl_type = F_WRLCK;
2110
2111 pLockData->fl_start = le64_to_cpu(parm_data->start);
2112 pLockData->fl_end = pLockData->fl_start +
2113 (le64_to_cpu(parm_data->length) ?
2114 le64_to_cpu(parm_data->length) - 1 : 0);
2115 pLockData->fl_pid = -le32_to_cpu(parm_data->pid);
2116 }
2117 }
2118
2119 plk_err_exit:
2120 free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
2121
2122
2123
2124
2125 return rc;
2126 }
2127
2128
2129 int
2130 CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2131 {
2132 int rc = 0;
2133 CLOSE_REQ *pSMB = NULL;
2134 cifs_dbg(FYI, "In CIFSSMBClose\n");
2135
2136
2137 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2138 if (rc == -EAGAIN)
2139 return 0;
2140 if (rc)
2141 return rc;
2142
2143 pSMB->FileID = (__u16) smb_file_id;
2144 pSMB->LastWriteTime = 0xFFFFFFFF;
2145 pSMB->ByteCount = 0;
2146 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2147 cifs_small_buf_release(pSMB);
2148 cifs_stats_inc(&tcon->stats.cifs_stats.num_closes);
2149 if (rc) {
2150 if (rc != -EINTR) {
2151
2152 cifs_dbg(VFS, "Send error in Close = %d\n", rc);
2153 }
2154 }
2155
2156
2157 if (rc == -EAGAIN)
2158 rc = 0;
2159
2160 return rc;
2161 }
2162
2163 int
2164 CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2165 {
2166 int rc = 0;
2167 FLUSH_REQ *pSMB = NULL;
2168 cifs_dbg(FYI, "In CIFSSMBFlush\n");
2169
2170 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2171 if (rc)
2172 return rc;
2173
2174 pSMB->FileID = (__u16) smb_file_id;
2175 pSMB->ByteCount = 0;
2176 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2177 cifs_small_buf_release(pSMB);
2178 cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);
2179 if (rc)
2180 cifs_dbg(VFS, "Send error in Flush = %d\n", rc);
2181
2182 return rc;
2183 }
2184
2185 int
2186 CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
2187 const char *from_name, const char *to_name,
2188 struct cifs_sb_info *cifs_sb)
2189 {
2190 int rc = 0;
2191 RENAME_REQ *pSMB = NULL;
2192 RENAME_RSP *pSMBr = NULL;
2193 int bytes_returned;
2194 int name_len, name_len2;
2195 __u16 count;
2196 int remap = cifs_remap(cifs_sb);
2197
2198 cifs_dbg(FYI, "In CIFSSMBRename\n");
2199 renameRetry:
2200 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2201 (void **) &pSMBr);
2202 if (rc)
2203 return rc;
2204
2205 pSMB->BufferFormat = 0x04;
2206 pSMB->SearchAttributes =
2207 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2208 ATTR_DIRECTORY);
2209
2210 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2211 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2212 from_name, PATH_MAX,
2213 cifs_sb->local_nls, remap);
2214 name_len++;
2215 name_len *= 2;
2216 pSMB->OldFileName[name_len] = 0x04;
2217
2218 pSMB->OldFileName[name_len + 1] = 0x00;
2219 name_len2 =
2220 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2221 to_name, PATH_MAX, cifs_sb->local_nls,
2222 remap);
2223 name_len2 += 1 + 1 ;
2224 name_len2 *= 2;
2225 } else {
2226 name_len = copy_path_name(pSMB->OldFileName, from_name);
2227 name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
2228 pSMB->OldFileName[name_len] = 0x04;
2229 name_len2++;
2230 }
2231
2232 count = 1 + name_len + name_len2;
2233 inc_rfc1001_len(pSMB, count);
2234 pSMB->ByteCount = cpu_to_le16(count);
2235
2236 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2237 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2238 cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);
2239 if (rc)
2240 cifs_dbg(FYI, "Send error in rename = %d\n", rc);
2241
2242 cifs_buf_release(pSMB);
2243
2244 if (rc == -EAGAIN)
2245 goto renameRetry;
2246
2247 return rc;
2248 }
2249
2250 int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
2251 int netfid, const char *target_name,
2252 const struct nls_table *nls_codepage, int remap)
2253 {
2254 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2255 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2256 struct set_file_rename *rename_info;
2257 char *data_offset;
2258 char dummy_string[30];
2259 int rc = 0;
2260 int bytes_returned = 0;
2261 int len_of_str;
2262 __u16 params, param_offset, offset, count, byte_count;
2263
2264 cifs_dbg(FYI, "Rename to File by handle\n");
2265 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2266 (void **) &pSMBr);
2267 if (rc)
2268 return rc;
2269
2270 params = 6;
2271 pSMB->MaxSetupCount = 0;
2272 pSMB->Reserved = 0;
2273 pSMB->Flags = 0;
2274 pSMB->Timeout = 0;
2275 pSMB->Reserved2 = 0;
2276 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2277 offset = param_offset + params;
2278
2279
2280 data_offset = (char *)(pSMB) + offset + 4;
2281 rename_info = (struct set_file_rename *) data_offset;
2282 pSMB->MaxParameterCount = cpu_to_le16(2);
2283 pSMB->MaxDataCount = cpu_to_le16(1000);
2284 pSMB->SetupCount = 1;
2285 pSMB->Reserved3 = 0;
2286 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2287 byte_count = 3 + params;
2288 pSMB->ParameterCount = cpu_to_le16(params);
2289 pSMB->TotalParameterCount = pSMB->ParameterCount;
2290 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2291 pSMB->DataOffset = cpu_to_le16(offset);
2292
2293 rename_info->overwrite = cpu_to_le32(1);
2294 rename_info->root_fid = 0;
2295
2296 if (target_name == NULL) {
2297 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2298 len_of_str =
2299 cifsConvertToUTF16((__le16 *)rename_info->target_name,
2300 dummy_string, 24, nls_codepage, remap);
2301 } else {
2302 len_of_str =
2303 cifsConvertToUTF16((__le16 *)rename_info->target_name,
2304 target_name, PATH_MAX, nls_codepage,
2305 remap);
2306 }
2307 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2308 count = 12 + (2 * len_of_str);
2309 byte_count += count;
2310 pSMB->DataCount = cpu_to_le16(count);
2311 pSMB->TotalDataCount = pSMB->DataCount;
2312 pSMB->Fid = netfid;
2313 pSMB->InformationLevel =
2314 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2315 pSMB->Reserved4 = 0;
2316 inc_rfc1001_len(pSMB, byte_count);
2317 pSMB->ByteCount = cpu_to_le16(byte_count);
2318 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2319 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2320 cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);
2321 if (rc)
2322 cifs_dbg(FYI, "Send error in Rename (by file handle) = %d\n",
2323 rc);
2324
2325 cifs_buf_release(pSMB);
2326
2327
2328
2329
2330 return rc;
2331 }
2332
2333 int
2334 CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon,
2335 const char *fromName, const __u16 target_tid, const char *toName,
2336 const int flags, const struct nls_table *nls_codepage, int remap)
2337 {
2338 int rc = 0;
2339 COPY_REQ *pSMB = NULL;
2340 COPY_RSP *pSMBr = NULL;
2341 int bytes_returned;
2342 int name_len, name_len2;
2343 __u16 count;
2344
2345 cifs_dbg(FYI, "In CIFSSMBCopy\n");
2346 copyRetry:
2347 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2348 (void **) &pSMBr);
2349 if (rc)
2350 return rc;
2351
2352 pSMB->BufferFormat = 0x04;
2353 pSMB->Tid2 = target_tid;
2354
2355 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2356
2357 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2358 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2359 fromName, PATH_MAX, nls_codepage,
2360 remap);
2361 name_len++;
2362 name_len *= 2;
2363 pSMB->OldFileName[name_len] = 0x04;
2364
2365 pSMB->OldFileName[name_len + 1] = 0x00;
2366 name_len2 =
2367 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2368 toName, PATH_MAX, nls_codepage, remap);
2369 name_len2 += 1 + 1 ;
2370 name_len2 *= 2;
2371 } else {
2372 name_len = copy_path_name(pSMB->OldFileName, fromName);
2373 pSMB->OldFileName[name_len] = 0x04;
2374 name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, toName);
2375 name_len2++;
2376 }
2377
2378 count = 1 + name_len + name_len2;
2379 inc_rfc1001_len(pSMB, count);
2380 pSMB->ByteCount = cpu_to_le16(count);
2381
2382 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2383 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2384 if (rc) {
2385 cifs_dbg(FYI, "Send error in copy = %d with %d files copied\n",
2386 rc, le16_to_cpu(pSMBr->CopyCount));
2387 }
2388 cifs_buf_release(pSMB);
2389
2390 if (rc == -EAGAIN)
2391 goto copyRetry;
2392
2393 return rc;
2394 }
2395
2396 int
2397 CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
2398 const char *fromName, const char *toName,
2399 const struct nls_table *nls_codepage, int remap)
2400 {
2401 TRANSACTION2_SPI_REQ *pSMB = NULL;
2402 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2403 char *data_offset;
2404 int name_len;
2405 int name_len_target;
2406 int rc = 0;
2407 int bytes_returned = 0;
2408 __u16 params, param_offset, offset, byte_count;
2409
2410 cifs_dbg(FYI, "In Symlink Unix style\n");
2411 createSymLinkRetry:
2412 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2413 (void **) &pSMBr);
2414 if (rc)
2415 return rc;
2416
2417 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2418 name_len =
2419 cifsConvertToUTF16((__le16 *) pSMB->FileName, fromName,
2420
2421 PATH_MAX, nls_codepage, remap);
2422 name_len++;
2423 name_len *= 2;
2424
2425 } else {
2426 name_len = copy_path_name(pSMB->FileName, fromName);
2427 }
2428 params = 6 + name_len;
2429 pSMB->MaxSetupCount = 0;
2430 pSMB->Reserved = 0;
2431 pSMB->Flags = 0;
2432 pSMB->Timeout = 0;
2433 pSMB->Reserved2 = 0;
2434 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2435 InformationLevel) - 4;
2436 offset = param_offset + params;
2437
2438
2439 data_offset = (char *)pSMB + offset + 4;
2440 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2441 name_len_target =
2442 cifsConvertToUTF16((__le16 *) data_offset, toName,
2443
2444 PATH_MAX, nls_codepage, remap);
2445 name_len_target++;
2446 name_len_target *= 2;
2447 } else {
2448 name_len_target = copy_path_name(data_offset, toName);
2449 }
2450
2451 pSMB->MaxParameterCount = cpu_to_le16(2);
2452
2453 pSMB->MaxDataCount = cpu_to_le16(1000);
2454 pSMB->SetupCount = 1;
2455 pSMB->Reserved3 = 0;
2456 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2457 byte_count = 3 + params + name_len_target;
2458 pSMB->DataCount = cpu_to_le16(name_len_target);
2459 pSMB->ParameterCount = cpu_to_le16(params);
2460 pSMB->TotalDataCount = pSMB->DataCount;
2461 pSMB->TotalParameterCount = pSMB->ParameterCount;
2462 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2463 pSMB->DataOffset = cpu_to_le16(offset);
2464 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2465 pSMB->Reserved4 = 0;
2466 inc_rfc1001_len(pSMB, byte_count);
2467 pSMB->ByteCount = cpu_to_le16(byte_count);
2468 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2469 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2470 cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);
2471 if (rc)
2472 cifs_dbg(FYI, "Send error in SetPathInfo create symlink = %d\n",
2473 rc);
2474
2475 cifs_buf_release(pSMB);
2476
2477 if (rc == -EAGAIN)
2478 goto createSymLinkRetry;
2479
2480 return rc;
2481 }
2482
2483 int
2484 CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2485 const char *fromName, const char *toName,
2486 const struct nls_table *nls_codepage, int remap)
2487 {
2488 TRANSACTION2_SPI_REQ *pSMB = NULL;
2489 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2490 char *data_offset;
2491 int name_len;
2492 int name_len_target;
2493 int rc = 0;
2494 int bytes_returned = 0;
2495 __u16 params, param_offset, offset, byte_count;
2496
2497 cifs_dbg(FYI, "In Create Hard link Unix style\n");
2498 createHardLinkRetry:
2499 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2500 (void **) &pSMBr);
2501 if (rc)
2502 return rc;
2503
2504 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2505 name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
2506 PATH_MAX, nls_codepage, remap);
2507 name_len++;
2508 name_len *= 2;
2509
2510 } else {
2511 name_len = copy_path_name(pSMB->FileName, toName);
2512 }
2513 params = 6 + name_len;
2514 pSMB->MaxSetupCount = 0;
2515 pSMB->Reserved = 0;
2516 pSMB->Flags = 0;
2517 pSMB->Timeout = 0;
2518 pSMB->Reserved2 = 0;
2519 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2520 InformationLevel) - 4;
2521 offset = param_offset + params;
2522
2523
2524 data_offset = (char *)pSMB + offset + 4;
2525 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2526 name_len_target =
2527 cifsConvertToUTF16((__le16 *) data_offset, fromName,
2528 PATH_MAX, nls_codepage, remap);
2529 name_len_target++;
2530 name_len_target *= 2;
2531 } else {
2532 name_len_target = copy_path_name(data_offset, fromName);
2533 }
2534
2535 pSMB->MaxParameterCount = cpu_to_le16(2);
2536
2537 pSMB->MaxDataCount = cpu_to_le16(1000);
2538 pSMB->SetupCount = 1;
2539 pSMB->Reserved3 = 0;
2540 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2541 byte_count = 3 + params + name_len_target;
2542 pSMB->ParameterCount = cpu_to_le16(params);
2543 pSMB->TotalParameterCount = pSMB->ParameterCount;
2544 pSMB->DataCount = cpu_to_le16(name_len_target);
2545 pSMB->TotalDataCount = pSMB->DataCount;
2546 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2547 pSMB->DataOffset = cpu_to_le16(offset);
2548 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2549 pSMB->Reserved4 = 0;
2550 inc_rfc1001_len(pSMB, byte_count);
2551 pSMB->ByteCount = cpu_to_le16(byte_count);
2552 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2553 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2554 cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
2555 if (rc)
2556 cifs_dbg(FYI, "Send error in SetPathInfo (hard link) = %d\n",
2557 rc);
2558
2559 cifs_buf_release(pSMB);
2560 if (rc == -EAGAIN)
2561 goto createHardLinkRetry;
2562
2563 return rc;
2564 }
2565
2566 int
2567 CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2568 const char *from_name, const char *to_name,
2569 struct cifs_sb_info *cifs_sb)
2570 {
2571 int rc = 0;
2572 NT_RENAME_REQ *pSMB = NULL;
2573 RENAME_RSP *pSMBr = NULL;
2574 int bytes_returned;
2575 int name_len, name_len2;
2576 __u16 count;
2577 int remap = cifs_remap(cifs_sb);
2578
2579 cifs_dbg(FYI, "In CIFSCreateHardLink\n");
2580 winCreateHardLinkRetry:
2581
2582 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2583 (void **) &pSMBr);
2584 if (rc)
2585 return rc;
2586
2587 pSMB->SearchAttributes =
2588 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2589 ATTR_DIRECTORY);
2590 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2591 pSMB->ClusterCount = 0;
2592
2593 pSMB->BufferFormat = 0x04;
2594
2595 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2596 name_len =
2597 cifsConvertToUTF16((__le16 *) pSMB->OldFileName, from_name,
2598 PATH_MAX, cifs_sb->local_nls, remap);
2599 name_len++;
2600 name_len *= 2;
2601
2602
2603 pSMB->OldFileName[name_len] = 0x04;
2604 pSMB->OldFileName[name_len + 1] = 0x00;
2605 name_len2 =
2606 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2607 to_name, PATH_MAX, cifs_sb->local_nls,
2608 remap);
2609 name_len2 += 1 + 1 ;
2610 name_len2 *= 2;
2611 } else {
2612 name_len = copy_path_name(pSMB->OldFileName, from_name);
2613 pSMB->OldFileName[name_len] = 0x04;
2614 name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
2615 name_len2++;
2616 }
2617
2618 count = 1 + name_len + name_len2;
2619 inc_rfc1001_len(pSMB, count);
2620 pSMB->ByteCount = cpu_to_le16(count);
2621
2622 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2623 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2624 cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
2625 if (rc)
2626 cifs_dbg(FYI, "Send error in hard link (NT rename) = %d\n", rc);
2627
2628 cifs_buf_release(pSMB);
2629 if (rc == -EAGAIN)
2630 goto winCreateHardLinkRetry;
2631
2632 return rc;
2633 }
2634
2635 int
2636 CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
2637 const unsigned char *searchName, char **symlinkinfo,
2638 const struct nls_table *nls_codepage, int remap)
2639 {
2640
2641 TRANSACTION2_QPI_REQ *pSMB = NULL;
2642 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2643 int rc = 0;
2644 int bytes_returned;
2645 int name_len;
2646 __u16 params, byte_count;
2647 char *data_start;
2648
2649 cifs_dbg(FYI, "In QPathSymLinkInfo (Unix) for path %s\n", searchName);
2650
2651 querySymLinkRetry:
2652 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2653 (void **) &pSMBr);
2654 if (rc)
2655 return rc;
2656
2657 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2658 name_len =
2659 cifsConvertToUTF16((__le16 *) pSMB->FileName,
2660 searchName, PATH_MAX, nls_codepage,
2661 remap);
2662 name_len++;
2663 name_len *= 2;
2664 } else {
2665 name_len = copy_path_name(pSMB->FileName, searchName);
2666 }
2667
2668 params = 2 + 4 + name_len ;
2669 pSMB->TotalDataCount = 0;
2670 pSMB->MaxParameterCount = cpu_to_le16(2);
2671 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
2672 pSMB->MaxSetupCount = 0;
2673 pSMB->Reserved = 0;
2674 pSMB->Flags = 0;
2675 pSMB->Timeout = 0;
2676 pSMB->Reserved2 = 0;
2677 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2678 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2679 pSMB->DataCount = 0;
2680 pSMB->DataOffset = 0;
2681 pSMB->SetupCount = 1;
2682 pSMB->Reserved3 = 0;
2683 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2684 byte_count = params + 1 ;
2685 pSMB->TotalParameterCount = cpu_to_le16(params);
2686 pSMB->ParameterCount = pSMB->TotalParameterCount;
2687 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2688 pSMB->Reserved4 = 0;
2689 inc_rfc1001_len(pSMB, byte_count);
2690 pSMB->ByteCount = cpu_to_le16(byte_count);
2691
2692 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2693 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2694 if (rc) {
2695 cifs_dbg(FYI, "Send error in QuerySymLinkInfo = %d\n", rc);
2696 } else {
2697
2698
2699 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2700
2701 if (rc || get_bcc(&pSMBr->hdr) < 2)
2702 rc = -EIO;
2703 else {
2704 bool is_unicode;
2705 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2706
2707 data_start = ((char *) &pSMBr->hdr.Protocol) +
2708 le16_to_cpu(pSMBr->t2.DataOffset);
2709
2710 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2711 is_unicode = true;
2712 else
2713 is_unicode = false;
2714
2715
2716 *symlinkinfo = cifs_strndup_from_utf16(data_start,
2717 count, is_unicode, nls_codepage);
2718 if (!*symlinkinfo)
2719 rc = -ENOMEM;
2720 }
2721 }
2722 cifs_buf_release(pSMB);
2723 if (rc == -EAGAIN)
2724 goto querySymLinkRetry;
2725 return rc;
2726 }
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738 int
2739 CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
2740 __u16 fid, char **symlinkinfo,
2741 const struct nls_table *nls_codepage)
2742 {
2743 int rc = 0;
2744 int bytes_returned;
2745 struct smb_com_transaction_ioctl_req *pSMB;
2746 struct smb_com_transaction_ioctl_rsp *pSMBr;
2747 bool is_unicode;
2748 unsigned int sub_len;
2749 char *sub_start;
2750 struct reparse_symlink_data *reparse_buf;
2751 struct reparse_posix_data *posix_buf;
2752 __u32 data_offset, data_count;
2753 char *end_of_smb;
2754
2755 cifs_dbg(FYI, "In Windows reparse style QueryLink for fid %u\n", fid);
2756 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2757 (void **) &pSMBr);
2758 if (rc)
2759 return rc;
2760
2761 pSMB->TotalParameterCount = 0 ;
2762 pSMB->TotalDataCount = 0;
2763 pSMB->MaxParameterCount = cpu_to_le32(2);
2764
2765 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
2766 pSMB->MaxSetupCount = 4;
2767 pSMB->Reserved = 0;
2768 pSMB->ParameterOffset = 0;
2769 pSMB->DataCount = 0;
2770 pSMB->DataOffset = 0;
2771 pSMB->SetupCount = 4;
2772 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2773 pSMB->ParameterCount = pSMB->TotalParameterCount;
2774 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2775 pSMB->IsFsctl = 1;
2776 pSMB->IsRootFlag = 0;
2777 pSMB->Fid = fid;
2778 pSMB->ByteCount = 0;
2779
2780 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2781 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2782 if (rc) {
2783 cifs_dbg(FYI, "Send error in QueryReparseLinkInfo = %d\n", rc);
2784 goto qreparse_out;
2785 }
2786
2787 data_offset = le32_to_cpu(pSMBr->DataOffset);
2788 data_count = le32_to_cpu(pSMBr->DataCount);
2789 if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
2790
2791 rc = -EIO;
2792 goto qreparse_out;
2793 }
2794 if (!data_count || (data_count > 2048)) {
2795 rc = -EIO;
2796 cifs_dbg(FYI, "Invalid return data count on get reparse info ioctl\n");
2797 goto qreparse_out;
2798 }
2799 end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
2800 reparse_buf = (struct reparse_symlink_data *)
2801 ((char *)&pSMBr->hdr.Protocol + data_offset);
2802 if ((char *)reparse_buf >= end_of_smb) {
2803 rc = -EIO;
2804 goto qreparse_out;
2805 }
2806 if (reparse_buf->ReparseTag == cpu_to_le32(IO_REPARSE_TAG_NFS)) {
2807 cifs_dbg(FYI, "NFS style reparse tag\n");
2808 posix_buf = (struct reparse_posix_data *)reparse_buf;
2809
2810 if (posix_buf->InodeType != cpu_to_le64(NFS_SPECFILE_LNK)) {
2811 cifs_dbg(FYI, "unsupported file type 0x%llx\n",
2812 le64_to_cpu(posix_buf->InodeType));
2813 rc = -EOPNOTSUPP;
2814 goto qreparse_out;
2815 }
2816 is_unicode = true;
2817 sub_len = le16_to_cpu(reparse_buf->ReparseDataLength);
2818 if (posix_buf->PathBuffer + sub_len > end_of_smb) {
2819 cifs_dbg(FYI, "reparse buf beyond SMB\n");
2820 rc = -EIO;
2821 goto qreparse_out;
2822 }
2823 *symlinkinfo = cifs_strndup_from_utf16(posix_buf->PathBuffer,
2824 sub_len, is_unicode, nls_codepage);
2825 goto qreparse_out;
2826 } else if (reparse_buf->ReparseTag !=
2827 cpu_to_le32(IO_REPARSE_TAG_SYMLINK)) {
2828 rc = -EOPNOTSUPP;
2829 goto qreparse_out;
2830 }
2831
2832
2833 sub_start = le16_to_cpu(reparse_buf->SubstituteNameOffset) +
2834 reparse_buf->PathBuffer;
2835 sub_len = le16_to_cpu(reparse_buf->SubstituteNameLength);
2836 if (sub_start + sub_len > end_of_smb) {
2837 cifs_dbg(FYI, "reparse buf beyond SMB\n");
2838 rc = -EIO;
2839 goto qreparse_out;
2840 }
2841 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2842 is_unicode = true;
2843 else
2844 is_unicode = false;
2845
2846
2847 *symlinkinfo = cifs_strndup_from_utf16(sub_start, sub_len, is_unicode,
2848 nls_codepage);
2849 if (!*symlinkinfo)
2850 rc = -ENOMEM;
2851 qreparse_out:
2852 cifs_buf_release(pSMB);
2853
2854
2855
2856
2857
2858 return rc;
2859 }
2860
2861 int
2862 CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
2863 __u16 fid)
2864 {
2865 int rc = 0;
2866 int bytes_returned;
2867 struct smb_com_transaction_compr_ioctl_req *pSMB;
2868 struct smb_com_transaction_ioctl_rsp *pSMBr;
2869
2870 cifs_dbg(FYI, "Set compression for %u\n", fid);
2871 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2872 (void **) &pSMBr);
2873 if (rc)
2874 return rc;
2875
2876 pSMB->compression_state = cpu_to_le16(COMPRESSION_FORMAT_DEFAULT);
2877
2878 pSMB->TotalParameterCount = 0;
2879 pSMB->TotalDataCount = cpu_to_le32(2);
2880 pSMB->MaxParameterCount = 0;
2881 pSMB->MaxDataCount = 0;
2882 pSMB->MaxSetupCount = 4;
2883 pSMB->Reserved = 0;
2884 pSMB->ParameterOffset = 0;
2885 pSMB->DataCount = cpu_to_le32(2);
2886 pSMB->DataOffset =
2887 cpu_to_le32(offsetof(struct smb_com_transaction_compr_ioctl_req,
2888 compression_state) - 4);
2889 pSMB->SetupCount = 4;
2890 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2891 pSMB->ParameterCount = 0;
2892 pSMB->FunctionCode = cpu_to_le32(FSCTL_SET_COMPRESSION);
2893 pSMB->IsFsctl = 1;
2894 pSMB->IsRootFlag = 0;
2895 pSMB->Fid = fid;
2896
2897 pSMB->ByteCount = cpu_to_le16(5);
2898 inc_rfc1001_len(pSMB, 5);
2899
2900 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2901 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2902 if (rc)
2903 cifs_dbg(FYI, "Send error in SetCompression = %d\n", rc);
2904
2905 cifs_buf_release(pSMB);
2906
2907
2908
2909
2910
2911 return rc;
2912 }
2913
2914
2915 #ifdef CONFIG_CIFS_POSIX
2916
2917
2918 static void cifs_convert_ace(struct posix_acl_xattr_entry *ace,
2919 struct cifs_posix_ace *cifs_ace)
2920 {
2921
2922 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2923 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2924 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2925
2926
2927
2928
2929
2930 return;
2931 }
2932
2933
2934 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2935 const int acl_type, const int size_of_data_area)
2936 {
2937 int size = 0;
2938 int i;
2939 __u16 count;
2940 struct cifs_posix_ace *pACE;
2941 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2942 struct posix_acl_xattr_header *local_acl = (void *)trgt;
2943
2944 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2945 return -EOPNOTSUPP;
2946
2947 if (acl_type == ACL_TYPE_ACCESS) {
2948 count = le16_to_cpu(cifs_acl->access_entry_count);
2949 pACE = &cifs_acl->ace_array[0];
2950 size = sizeof(struct cifs_posix_acl);
2951 size += sizeof(struct cifs_posix_ace) * count;
2952
2953 if (size_of_data_area < size) {
2954 cifs_dbg(FYI, "bad CIFS POSIX ACL size %d vs. %d\n",
2955 size_of_data_area, size);
2956 return -EINVAL;
2957 }
2958 } else if (acl_type == ACL_TYPE_DEFAULT) {
2959 count = le16_to_cpu(cifs_acl->access_entry_count);
2960 size = sizeof(struct cifs_posix_acl);
2961 size += sizeof(struct cifs_posix_ace) * count;
2962
2963 pACE = &cifs_acl->ace_array[count];
2964 count = le16_to_cpu(cifs_acl->default_entry_count);
2965 size += sizeof(struct cifs_posix_ace) * count;
2966
2967 if (size_of_data_area < size)
2968 return -EINVAL;
2969 } else {
2970
2971 return -EINVAL;
2972 }
2973
2974 size = posix_acl_xattr_size(count);
2975 if ((buflen == 0) || (local_acl == NULL)) {
2976
2977 } else if (size > buflen) {
2978 return -ERANGE;
2979 } else {
2980 struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
2981
2982 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2983 for (i = 0; i < count ; i++) {
2984 cifs_convert_ace(&ace[i], pACE);
2985 pACE++;
2986 }
2987 }
2988 return size;
2989 }
2990
2991 static void convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2992 const struct posix_acl_xattr_entry *local_ace)
2993 {
2994 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2995 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2996
2997 if (local_ace->e_id == cpu_to_le32(-1)) {
2998
2999 cifs_ace->cifs_uid = cpu_to_le64(-1);
3000 } else
3001 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
3002
3003
3004
3005
3006 }
3007
3008
3009 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
3010 const int buflen, const int acl_type)
3011 {
3012 __u16 rc = 0;
3013 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
3014 struct posix_acl_xattr_header *local_acl = (void *)pACL;
3015 struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
3016 int count;
3017 int i;
3018
3019 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
3020 return 0;
3021
3022 count = posix_acl_xattr_count((size_t)buflen);
3023 cifs_dbg(FYI, "setting acl with %d entries from buf of length %d and version of %d\n",
3024 count, buflen, le32_to_cpu(local_acl->a_version));
3025 if (le32_to_cpu(local_acl->a_version) != 2) {
3026 cifs_dbg(FYI, "unknown POSIX ACL version %d\n",
3027 le32_to_cpu(local_acl->a_version));
3028 return 0;
3029 }
3030 cifs_acl->version = cpu_to_le16(1);
3031 if (acl_type == ACL_TYPE_ACCESS) {
3032 cifs_acl->access_entry_count = cpu_to_le16(count);
3033 cifs_acl->default_entry_count = cpu_to_le16(0xFFFF);
3034 } else if (acl_type == ACL_TYPE_DEFAULT) {
3035 cifs_acl->default_entry_count = cpu_to_le16(count);
3036 cifs_acl->access_entry_count = cpu_to_le16(0xFFFF);
3037 } else {
3038 cifs_dbg(FYI, "unknown ACL type %d\n", acl_type);
3039 return 0;
3040 }
3041 for (i = 0; i < count; i++)
3042 convert_ace_to_cifs_ace(&cifs_acl->ace_array[i], &ace[i]);
3043 if (rc == 0) {
3044 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3045 rc += sizeof(struct cifs_posix_acl);
3046
3047 }
3048 return rc;
3049 }
3050
3051 int
3052 CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3053 const unsigned char *searchName,
3054 char *acl_inf, const int buflen, const int acl_type,
3055 const struct nls_table *nls_codepage, int remap)
3056 {
3057
3058 TRANSACTION2_QPI_REQ *pSMB = NULL;
3059 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3060 int rc = 0;
3061 int bytes_returned;
3062 int name_len;
3063 __u16 params, byte_count;
3064
3065 cifs_dbg(FYI, "In GetPosixACL (Unix) for path %s\n", searchName);
3066
3067 queryAclRetry:
3068 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3069 (void **) &pSMBr);
3070 if (rc)
3071 return rc;
3072
3073 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3074 name_len =
3075 cifsConvertToUTF16((__le16 *) pSMB->FileName,
3076 searchName, PATH_MAX, nls_codepage,
3077 remap);
3078 name_len++;
3079 name_len *= 2;
3080 pSMB->FileName[name_len] = 0;
3081 pSMB->FileName[name_len+1] = 0;
3082 } else {
3083 name_len = copy_path_name(pSMB->FileName, searchName);
3084 }
3085
3086 params = 2 + 4 + name_len ;
3087 pSMB->TotalDataCount = 0;
3088 pSMB->MaxParameterCount = cpu_to_le16(2);
3089
3090 pSMB->MaxDataCount = cpu_to_le16(4000);
3091 pSMB->MaxSetupCount = 0;
3092 pSMB->Reserved = 0;
3093 pSMB->Flags = 0;
3094 pSMB->Timeout = 0;
3095 pSMB->Reserved2 = 0;
3096 pSMB->ParameterOffset = cpu_to_le16(
3097 offsetof(struct smb_com_transaction2_qpi_req,
3098 InformationLevel) - 4);
3099 pSMB->DataCount = 0;
3100 pSMB->DataOffset = 0;
3101 pSMB->SetupCount = 1;
3102 pSMB->Reserved3 = 0;
3103 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3104 byte_count = params + 1 ;
3105 pSMB->TotalParameterCount = cpu_to_le16(params);
3106 pSMB->ParameterCount = pSMB->TotalParameterCount;
3107 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3108 pSMB->Reserved4 = 0;
3109 inc_rfc1001_len(pSMB, byte_count);
3110 pSMB->ByteCount = cpu_to_le16(byte_count);
3111
3112 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3113 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3114 cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3115 if (rc) {
3116 cifs_dbg(FYI, "Send error in Query POSIX ACL = %d\n", rc);
3117 } else {
3118
3119
3120 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3121
3122 if (rc || get_bcc(&pSMBr->hdr) < 2)
3123 rc = -EIO;
3124 else {
3125 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3126 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3127 rc = cifs_copy_posix_acl(acl_inf,
3128 (char *)&pSMBr->hdr.Protocol+data_offset,
3129 buflen, acl_type, count);
3130 }
3131 }
3132 cifs_buf_release(pSMB);
3133 if (rc == -EAGAIN)
3134 goto queryAclRetry;
3135 return rc;
3136 }
3137
3138 int
3139 CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3140 const unsigned char *fileName,
3141 const char *local_acl, const int buflen,
3142 const int acl_type,
3143 const struct nls_table *nls_codepage, int remap)
3144 {
3145 struct smb_com_transaction2_spi_req *pSMB = NULL;
3146 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3147 char *parm_data;
3148 int name_len;
3149 int rc = 0;
3150 int bytes_returned = 0;
3151 __u16 params, byte_count, data_count, param_offset, offset;
3152
3153 cifs_dbg(FYI, "In SetPosixACL (Unix) for path %s\n", fileName);
3154 setAclRetry:
3155 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3156 (void **) &pSMBr);
3157 if (rc)
3158 return rc;
3159 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3160 name_len =
3161 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
3162 PATH_MAX, nls_codepage, remap);
3163 name_len++;
3164 name_len *= 2;
3165 } else {
3166 name_len = copy_path_name(pSMB->FileName, fileName);
3167 }
3168 params = 6 + name_len;
3169 pSMB->MaxParameterCount = cpu_to_le16(2);
3170
3171 pSMB->MaxDataCount = cpu_to_le16(1000);
3172 pSMB->MaxSetupCount = 0;
3173 pSMB->Reserved = 0;
3174 pSMB->Flags = 0;
3175 pSMB->Timeout = 0;
3176 pSMB->Reserved2 = 0;
3177 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3178 InformationLevel) - 4;
3179 offset = param_offset + params;
3180 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3181 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3182
3183
3184 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
3185
3186 if (data_count == 0) {
3187 rc = -EOPNOTSUPP;
3188 goto setACLerrorExit;
3189 }
3190 pSMB->DataOffset = cpu_to_le16(offset);
3191 pSMB->SetupCount = 1;
3192 pSMB->Reserved3 = 0;
3193 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3194 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3195 byte_count = 3 + params + data_count;
3196 pSMB->DataCount = cpu_to_le16(data_count);
3197 pSMB->TotalDataCount = pSMB->DataCount;
3198 pSMB->ParameterCount = cpu_to_le16(params);
3199 pSMB->TotalParameterCount = pSMB->ParameterCount;
3200 pSMB->Reserved4 = 0;
3201 inc_rfc1001_len(pSMB, byte_count);
3202 pSMB->ByteCount = cpu_to_le16(byte_count);
3203 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3204 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3205 if (rc)
3206 cifs_dbg(FYI, "Set POSIX ACL returned %d\n", rc);
3207
3208 setACLerrorExit:
3209 cifs_buf_release(pSMB);
3210 if (rc == -EAGAIN)
3211 goto setAclRetry;
3212 return rc;
3213 }
3214
3215 int
3216 CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
3217 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3218 {
3219 int rc = 0;
3220 struct smb_t2_qfi_req *pSMB = NULL;
3221 struct smb_t2_qfi_rsp *pSMBr = NULL;
3222 int bytes_returned;
3223 __u16 params, byte_count;
3224
3225 cifs_dbg(FYI, "In GetExtAttr\n");
3226 if (tcon == NULL)
3227 return -ENODEV;
3228
3229 GetExtAttrRetry:
3230 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3231 (void **) &pSMBr);
3232 if (rc)
3233 return rc;
3234
3235 params = 2 + 2 ;
3236 pSMB->t2.TotalDataCount = 0;
3237 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3238
3239 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3240 pSMB->t2.MaxSetupCount = 0;
3241 pSMB->t2.Reserved = 0;
3242 pSMB->t2.Flags = 0;
3243 pSMB->t2.Timeout = 0;
3244 pSMB->t2.Reserved2 = 0;
3245 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3246 Fid) - 4);
3247 pSMB->t2.DataCount = 0;
3248 pSMB->t2.DataOffset = 0;
3249 pSMB->t2.SetupCount = 1;
3250 pSMB->t2.Reserved3 = 0;
3251 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3252 byte_count = params + 1 ;
3253 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3254 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3255 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3256 pSMB->Pad = 0;
3257 pSMB->Fid = netfid;
3258 inc_rfc1001_len(pSMB, byte_count);
3259 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3260
3261 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3262 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3263 if (rc) {
3264 cifs_dbg(FYI, "error %d in GetExtAttr\n", rc);
3265 } else {
3266
3267 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3268
3269 if (rc || get_bcc(&pSMBr->hdr) < 2)
3270
3271
3272 rc = -EIO;
3273 else {
3274 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3275 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3276 struct file_chattr_info *pfinfo;
3277
3278 if (count != 16) {
3279 cifs_dbg(FYI, "Invalid size ret in GetExtAttr\n");
3280 rc = -EIO;
3281 goto GetExtAttrOut;
3282 }
3283 pfinfo = (struct file_chattr_info *)
3284 (data_offset + (char *) &pSMBr->hdr.Protocol);
3285 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3286 *pMask = le64_to_cpu(pfinfo->mask);
3287 }
3288 }
3289 GetExtAttrOut:
3290 cifs_buf_release(pSMB);
3291 if (rc == -EAGAIN)
3292 goto GetExtAttrRetry;
3293 return rc;
3294 }
3295
3296 #endif
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306 static int
3307 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3308 const int parm_len, struct cifs_tcon *tcon,
3309 void **ret_buf)
3310 {
3311 int rc;
3312 __u32 temp_offset;
3313 struct smb_com_ntransact_req *pSMB;
3314
3315 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3316 (void **)&pSMB);
3317 if (rc)
3318 return rc;
3319 *ret_buf = (void *)pSMB;
3320 pSMB->Reserved = 0;
3321 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3322 pSMB->TotalDataCount = 0;
3323 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3324 pSMB->ParameterCount = pSMB->TotalParameterCount;
3325 pSMB->DataCount = pSMB->TotalDataCount;
3326 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3327 (setup_count * 2) - 4 ;
3328 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3329 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3330 pSMB->SetupCount = setup_count;
3331 pSMB->SubCommand = cpu_to_le16(sub_command);
3332 return 0;
3333 }
3334
3335 static int
3336 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3337 __u32 *pparmlen, __u32 *pdatalen)
3338 {
3339 char *end_of_smb;
3340 __u32 data_count, data_offset, parm_count, parm_offset;
3341 struct smb_com_ntransact_rsp *pSMBr;
3342 u16 bcc;
3343
3344 *pdatalen = 0;
3345 *pparmlen = 0;
3346
3347 if (buf == NULL)
3348 return -EINVAL;
3349
3350 pSMBr = (struct smb_com_ntransact_rsp *)buf;
3351
3352 bcc = get_bcc(&pSMBr->hdr);
3353 end_of_smb = 2 + bcc +
3354 (char *)&pSMBr->ByteCount;
3355
3356 data_offset = le32_to_cpu(pSMBr->DataOffset);
3357 data_count = le32_to_cpu(pSMBr->DataCount);
3358 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3359 parm_count = le32_to_cpu(pSMBr->ParameterCount);
3360
3361 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3362 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3363
3364
3365 if (*ppparm > end_of_smb) {
3366 cifs_dbg(FYI, "parms start after end of smb\n");
3367 return -EINVAL;
3368 } else if (parm_count + *ppparm > end_of_smb) {
3369 cifs_dbg(FYI, "parm end after end of smb\n");
3370 return -EINVAL;
3371 } else if (*ppdata > end_of_smb) {
3372 cifs_dbg(FYI, "data starts after end of smb\n");
3373 return -EINVAL;
3374 } else if (data_count + *ppdata > end_of_smb) {
3375 cifs_dbg(FYI, "data %p + count %d (%p) past smb end %p start %p\n",
3376 *ppdata, data_count, (data_count + *ppdata),
3377 end_of_smb, pSMBr);
3378 return -EINVAL;
3379 } else if (parm_count + data_count > bcc) {
3380 cifs_dbg(FYI, "parm count and data count larger than SMB\n");
3381 return -EINVAL;
3382 }
3383 *pdatalen = data_count;
3384 *pparmlen = parm_count;
3385 return 0;
3386 }
3387
3388
3389 int
3390 CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3391 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3392 {
3393 int rc = 0;
3394 int buf_type = 0;
3395 QUERY_SEC_DESC_REQ *pSMB;
3396 struct kvec iov[1];
3397 struct kvec rsp_iov;
3398
3399 cifs_dbg(FYI, "GetCifsACL\n");
3400
3401 *pbuflen = 0;
3402 *acl_inf = NULL;
3403
3404 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3405 8 , tcon, (void **) &pSMB);
3406 if (rc)
3407 return rc;
3408
3409 pSMB->MaxParameterCount = cpu_to_le32(4);
3410
3411 pSMB->MaxSetupCount = 0;
3412 pSMB->Fid = fid;
3413 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3414 CIFS_ACL_DACL);
3415 pSMB->ByteCount = cpu_to_le16(11);
3416 inc_rfc1001_len(pSMB, 11);
3417 iov[0].iov_base = (char *)pSMB;
3418 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3419
3420 rc = SendReceive2(xid, tcon->ses, iov, 1 , &buf_type,
3421 0, &rsp_iov);
3422 cifs_small_buf_release(pSMB);
3423 cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3424 if (rc) {
3425 cifs_dbg(FYI, "Send error in QuerySecDesc = %d\n", rc);
3426 } else {
3427 __le32 *parm;
3428 __u32 parm_len;
3429 __u32 acl_len;
3430 struct smb_com_ntransact_rsp *pSMBr;
3431 char *pdata;
3432
3433
3434 rc = validate_ntransact(rsp_iov.iov_base, (char **)&parm,
3435 &pdata, &parm_len, pbuflen);
3436 if (rc)
3437 goto qsec_out;
3438 pSMBr = (struct smb_com_ntransact_rsp *)rsp_iov.iov_base;
3439
3440 cifs_dbg(FYI, "smb %p parm %p data %p\n",
3441 pSMBr, parm, *acl_inf);
3442
3443 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3444 rc = -EIO;
3445 *pbuflen = 0;
3446 goto qsec_out;
3447 }
3448
3449
3450
3451 acl_len = le32_to_cpu(*parm);
3452 if (acl_len != *pbuflen) {
3453 cifs_dbg(VFS, "acl length %d does not match %d\n",
3454 acl_len, *pbuflen);
3455 if (*pbuflen > acl_len)
3456 *pbuflen = acl_len;
3457 }
3458
3459
3460
3461 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3462 (*pbuflen >= 64 * 1024)) {
3463 cifs_dbg(VFS, "bad acl length %d\n", *pbuflen);
3464 rc = -EINVAL;
3465 *pbuflen = 0;
3466 } else {
3467 *acl_inf = kmemdup(pdata, *pbuflen, GFP_KERNEL);
3468 if (*acl_inf == NULL) {
3469 *pbuflen = 0;
3470 rc = -ENOMEM;
3471 }
3472 }
3473 }
3474 qsec_out:
3475 free_rsp_buf(buf_type, rsp_iov.iov_base);
3476 return rc;
3477 }
3478
3479 int
3480 CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3481 struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
3482 {
3483 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3484 int rc = 0;
3485 int bytes_returned = 0;
3486 SET_SEC_DESC_REQ *pSMB = NULL;
3487 void *pSMBr;
3488
3489 setCifsAclRetry:
3490 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
3491 if (rc)
3492 return rc;
3493
3494 pSMB->MaxSetupCount = 0;
3495 pSMB->Reserved = 0;
3496
3497 param_count = 8;
3498 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3499 data_count = acllen;
3500 data_offset = param_offset + param_count;
3501 byte_count = 3 + param_count;
3502
3503 pSMB->DataCount = cpu_to_le32(data_count);
3504 pSMB->TotalDataCount = pSMB->DataCount;
3505 pSMB->MaxParameterCount = cpu_to_le32(4);
3506 pSMB->MaxDataCount = cpu_to_le32(16384);
3507 pSMB->ParameterCount = cpu_to_le32(param_count);
3508 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3509 pSMB->TotalParameterCount = pSMB->ParameterCount;
3510 pSMB->DataOffset = cpu_to_le32(data_offset);
3511 pSMB->SetupCount = 0;
3512 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3513 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3514
3515 pSMB->Fid = fid;
3516 pSMB->Reserved2 = 0;
3517 pSMB->AclFlags = cpu_to_le32(aclflag);
3518
3519 if (pntsd && acllen) {
3520 memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
3521 data_offset, pntsd, acllen);
3522 inc_rfc1001_len(pSMB, byte_count + data_count);
3523 } else
3524 inc_rfc1001_len(pSMB, byte_count);
3525
3526 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3527 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3528
3529 cifs_dbg(FYI, "SetCIFSACL bytes_returned: %d, rc: %d\n",
3530 bytes_returned, rc);
3531 if (rc)
3532 cifs_dbg(FYI, "Set CIFS ACL returned %d\n", rc);
3533 cifs_buf_release(pSMB);
3534
3535 if (rc == -EAGAIN)
3536 goto setCifsAclRetry;
3537
3538 return (rc);
3539 }
3540
3541
3542
3543
3544 int
3545 SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
3546 const char *search_name, FILE_ALL_INFO *data,
3547 const struct nls_table *nls_codepage, int remap)
3548 {
3549 QUERY_INFORMATION_REQ *pSMB;
3550 QUERY_INFORMATION_RSP *pSMBr;
3551 int rc = 0;
3552 int bytes_returned;
3553 int name_len;
3554
3555 cifs_dbg(FYI, "In SMBQPath path %s\n", search_name);
3556 QInfRetry:
3557 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3558 (void **) &pSMBr);
3559 if (rc)
3560 return rc;
3561
3562 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3563 name_len =
3564 cifsConvertToUTF16((__le16 *) pSMB->FileName,
3565 search_name, PATH_MAX, nls_codepage,
3566 remap);
3567 name_len++;
3568 name_len *= 2;
3569 } else {
3570 name_len = copy_path_name(pSMB->FileName, search_name);
3571 }
3572 pSMB->BufferFormat = 0x04;
3573 name_len++;
3574 inc_rfc1001_len(pSMB, (__u16)name_len);
3575 pSMB->ByteCount = cpu_to_le16(name_len);
3576
3577 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3578 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3579 if (rc) {
3580 cifs_dbg(FYI, "Send error in QueryInfo = %d\n", rc);
3581 } else if (data) {
3582 struct timespec64 ts;
3583 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3584
3585
3586
3587 memset(data, 0, sizeof(FILE_ALL_INFO));
3588 ts.tv_nsec = 0;
3589 ts.tv_sec = time;
3590
3591 data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3592 data->LastWriteTime = data->ChangeTime;
3593 data->LastAccessTime = 0;
3594 data->AllocationSize =
3595 cpu_to_le64(le32_to_cpu(pSMBr->size));
3596 data->EndOfFile = data->AllocationSize;
3597 data->Attributes =
3598 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3599 } else
3600 rc = -EIO;
3601
3602 cifs_buf_release(pSMB);
3603
3604 if (rc == -EAGAIN)
3605 goto QInfRetry;
3606
3607 return rc;
3608 }
3609
3610 int
3611 CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
3612 u16 netfid, FILE_ALL_INFO *pFindData)
3613 {
3614 struct smb_t2_qfi_req *pSMB = NULL;
3615 struct smb_t2_qfi_rsp *pSMBr = NULL;
3616 int rc = 0;
3617 int bytes_returned;
3618 __u16 params, byte_count;
3619
3620 QFileInfoRetry:
3621 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3622 (void **) &pSMBr);
3623 if (rc)
3624 return rc;
3625
3626 params = 2 + 2 ;
3627 pSMB->t2.TotalDataCount = 0;
3628 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3629
3630 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3631 pSMB->t2.MaxSetupCount = 0;
3632 pSMB->t2.Reserved = 0;
3633 pSMB->t2.Flags = 0;
3634 pSMB->t2.Timeout = 0;
3635 pSMB->t2.Reserved2 = 0;
3636 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3637 Fid) - 4);
3638 pSMB->t2.DataCount = 0;
3639 pSMB->t2.DataOffset = 0;
3640 pSMB->t2.SetupCount = 1;
3641 pSMB->t2.Reserved3 = 0;
3642 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3643 byte_count = params + 1 ;
3644 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3645 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3646 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3647 pSMB->Pad = 0;
3648 pSMB->Fid = netfid;
3649 inc_rfc1001_len(pSMB, byte_count);
3650 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3651
3652 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3653 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3654 if (rc) {
3655 cifs_dbg(FYI, "Send error in QFileInfo = %d\n", rc);
3656 } else {
3657 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3658
3659 if (rc)
3660 rc = -EIO;
3661 else if (get_bcc(&pSMBr->hdr) < 40)
3662 rc = -EIO;
3663 else if (pFindData) {
3664 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3665 memcpy((char *) pFindData,
3666 (char *) &pSMBr->hdr.Protocol +
3667 data_offset, sizeof(FILE_ALL_INFO));
3668 } else
3669 rc = -ENOMEM;
3670 }
3671 cifs_buf_release(pSMB);
3672 if (rc == -EAGAIN)
3673 goto QFileInfoRetry;
3674
3675 return rc;
3676 }
3677
3678 int
3679 CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
3680 const char *search_name, FILE_ALL_INFO *data,
3681 int legacy ,
3682 const struct nls_table *nls_codepage, int remap)
3683 {
3684
3685 TRANSACTION2_QPI_REQ *pSMB = NULL;
3686 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3687 int rc = 0;
3688 int bytes_returned;
3689 int name_len;
3690 __u16 params, byte_count;
3691
3692
3693 QPathInfoRetry:
3694 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3695 (void **) &pSMBr);
3696 if (rc)
3697 return rc;
3698
3699 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3700 name_len =
3701 cifsConvertToUTF16((__le16 *) pSMB->FileName, search_name,
3702 PATH_MAX, nls_codepage, remap);
3703 name_len++;
3704 name_len *= 2;
3705 } else {
3706 name_len = copy_path_name(pSMB->FileName, search_name);
3707 }
3708
3709 params = 2 + 4 + name_len ;
3710 pSMB->TotalDataCount = 0;
3711 pSMB->MaxParameterCount = cpu_to_le16(2);
3712
3713 pSMB->MaxDataCount = cpu_to_le16(4000);
3714 pSMB->MaxSetupCount = 0;
3715 pSMB->Reserved = 0;
3716 pSMB->Flags = 0;
3717 pSMB->Timeout = 0;
3718 pSMB->Reserved2 = 0;
3719 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3720 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3721 pSMB->DataCount = 0;
3722 pSMB->DataOffset = 0;
3723 pSMB->SetupCount = 1;
3724 pSMB->Reserved3 = 0;
3725 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3726 byte_count = params + 1 ;
3727 pSMB->TotalParameterCount = cpu_to_le16(params);
3728 pSMB->ParameterCount = pSMB->TotalParameterCount;
3729 if (legacy)
3730 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3731 else
3732 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3733 pSMB->Reserved4 = 0;
3734 inc_rfc1001_len(pSMB, byte_count);
3735 pSMB->ByteCount = cpu_to_le16(byte_count);
3736
3737 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3738 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3739 if (rc) {
3740 cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
3741 } else {
3742 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3743
3744 if (rc)
3745 rc = -EIO;
3746 else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
3747 rc = -EIO;
3748 else if (legacy && get_bcc(&pSMBr->hdr) < 24)
3749 rc = -EIO;
3750
3751 else if (data) {
3752 int size;
3753 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3754
3755
3756
3757
3758
3759
3760
3761 if (legacy)
3762 size = sizeof(FILE_INFO_STANDARD);
3763 else
3764 size = sizeof(FILE_ALL_INFO);
3765 memcpy((char *) data, (char *) &pSMBr->hdr.Protocol +
3766 data_offset, size);
3767 } else
3768 rc = -ENOMEM;
3769 }
3770 cifs_buf_release(pSMB);
3771 if (rc == -EAGAIN)
3772 goto QPathInfoRetry;
3773
3774 return rc;
3775 }
3776
3777 int
3778 CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
3779 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
3780 {
3781 struct smb_t2_qfi_req *pSMB = NULL;
3782 struct smb_t2_qfi_rsp *pSMBr = NULL;
3783 int rc = 0;
3784 int bytes_returned;
3785 __u16 params, byte_count;
3786
3787 UnixQFileInfoRetry:
3788 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3789 (void **) &pSMBr);
3790 if (rc)
3791 return rc;
3792
3793 params = 2 + 2 ;
3794 pSMB->t2.TotalDataCount = 0;
3795 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3796
3797 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3798 pSMB->t2.MaxSetupCount = 0;
3799 pSMB->t2.Reserved = 0;
3800 pSMB->t2.Flags = 0;
3801 pSMB->t2.Timeout = 0;
3802 pSMB->t2.Reserved2 = 0;
3803 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3804 Fid) - 4);
3805 pSMB->t2.DataCount = 0;
3806 pSMB->t2.DataOffset = 0;
3807 pSMB->t2.SetupCount = 1;
3808 pSMB->t2.Reserved3 = 0;
3809 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3810 byte_count = params + 1 ;
3811 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3812 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3813 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3814 pSMB->Pad = 0;
3815 pSMB->Fid = netfid;
3816 inc_rfc1001_len(pSMB, byte_count);
3817 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3818
3819 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3820 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3821 if (rc) {
3822 cifs_dbg(FYI, "Send error in UnixQFileInfo = %d\n", rc);
3823 } else {
3824 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3825
3826 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
3827 cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
3828 rc = -EIO;
3829 } else {
3830 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3831 memcpy((char *) pFindData,
3832 (char *) &pSMBr->hdr.Protocol +
3833 data_offset,
3834 sizeof(FILE_UNIX_BASIC_INFO));
3835 }
3836 }
3837
3838 cifs_buf_release(pSMB);
3839 if (rc == -EAGAIN)
3840 goto UnixQFileInfoRetry;
3841
3842 return rc;
3843 }
3844
3845 int
3846 CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
3847 const unsigned char *searchName,
3848 FILE_UNIX_BASIC_INFO *pFindData,
3849 const struct nls_table *nls_codepage, int remap)
3850 {
3851
3852 TRANSACTION2_QPI_REQ *pSMB = NULL;
3853 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3854 int rc = 0;
3855 int bytes_returned = 0;
3856 int name_len;
3857 __u16 params, byte_count;
3858
3859 cifs_dbg(FYI, "In QPathInfo (Unix) the path %s\n", searchName);
3860 UnixQPathInfoRetry:
3861 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3862 (void **) &pSMBr);
3863 if (rc)
3864 return rc;
3865
3866 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3867 name_len =
3868 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
3869 PATH_MAX, nls_codepage, remap);
3870 name_len++;
3871 name_len *= 2;
3872 } else {
3873 name_len = copy_path_name(pSMB->FileName, searchName);
3874 }
3875
3876 params = 2 + 4 + name_len ;
3877 pSMB->TotalDataCount = 0;
3878 pSMB->MaxParameterCount = cpu_to_le16(2);
3879
3880 pSMB->MaxDataCount = cpu_to_le16(4000);
3881 pSMB->MaxSetupCount = 0;
3882 pSMB->Reserved = 0;
3883 pSMB->Flags = 0;
3884 pSMB->Timeout = 0;
3885 pSMB->Reserved2 = 0;
3886 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3887 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3888 pSMB->DataCount = 0;
3889 pSMB->DataOffset = 0;
3890 pSMB->SetupCount = 1;
3891 pSMB->Reserved3 = 0;
3892 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3893 byte_count = params + 1 ;
3894 pSMB->TotalParameterCount = cpu_to_le16(params);
3895 pSMB->ParameterCount = pSMB->TotalParameterCount;
3896 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3897 pSMB->Reserved4 = 0;
3898 inc_rfc1001_len(pSMB, byte_count);
3899 pSMB->ByteCount = cpu_to_le16(byte_count);
3900
3901 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3902 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3903 if (rc) {
3904 cifs_dbg(FYI, "Send error in UnixQPathInfo = %d\n", rc);
3905 } else {
3906 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3907
3908 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
3909 cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
3910 rc = -EIO;
3911 } else {
3912 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3913 memcpy((char *) pFindData,
3914 (char *) &pSMBr->hdr.Protocol +
3915 data_offset,
3916 sizeof(FILE_UNIX_BASIC_INFO));
3917 }
3918 }
3919 cifs_buf_release(pSMB);
3920 if (rc == -EAGAIN)
3921 goto UnixQPathInfoRetry;
3922
3923 return rc;
3924 }
3925
3926
3927 int
3928 CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
3929 const char *searchName, struct cifs_sb_info *cifs_sb,
3930 __u16 *pnetfid, __u16 search_flags,
3931 struct cifs_search_info *psrch_inf, bool msearch)
3932 {
3933
3934 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3935 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3936 T2_FFIRST_RSP_PARMS *parms;
3937 int rc = 0;
3938 int bytes_returned = 0;
3939 int name_len, remap;
3940 __u16 params, byte_count;
3941 struct nls_table *nls_codepage;
3942
3943 cifs_dbg(FYI, "In FindFirst for %s\n", searchName);
3944
3945 findFirstRetry:
3946 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3947 (void **) &pSMBr);
3948 if (rc)
3949 return rc;
3950
3951 nls_codepage = cifs_sb->local_nls;
3952 remap = cifs_remap(cifs_sb);
3953
3954 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3955 name_len =
3956 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
3957 PATH_MAX, nls_codepage, remap);
3958
3959
3960
3961 name_len *= 2;
3962 if (msearch) {
3963 pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
3964 pSMB->FileName[name_len+1] = 0;
3965 pSMB->FileName[name_len+2] = '*';
3966 pSMB->FileName[name_len+3] = 0;
3967 name_len += 4;
3968
3969 pSMB->FileName[name_len] = 0;
3970 pSMB->FileName[name_len+1] = 0;
3971 name_len += 2;
3972 }
3973 } else {
3974 name_len = copy_path_name(pSMB->FileName, searchName);
3975 if (msearch) {
3976 if (WARN_ON_ONCE(name_len > PATH_MAX-2))
3977 name_len = PATH_MAX-2;
3978
3979 pSMB->FileName[name_len-1] = CIFS_DIR_SEP(cifs_sb);
3980 pSMB->FileName[name_len] = '*';
3981 pSMB->FileName[name_len+1] = 0;
3982 name_len += 2;
3983 }
3984 }
3985
3986 params = 12 + name_len ;
3987 pSMB->TotalDataCount = 0;
3988 pSMB->MaxParameterCount = cpu_to_le16(10);
3989 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
3990 pSMB->MaxSetupCount = 0;
3991 pSMB->Reserved = 0;
3992 pSMB->Flags = 0;
3993 pSMB->Timeout = 0;
3994 pSMB->Reserved2 = 0;
3995 byte_count = params + 1 ;
3996 pSMB->TotalParameterCount = cpu_to_le16(params);
3997 pSMB->ParameterCount = pSMB->TotalParameterCount;
3998 pSMB->ParameterOffset = cpu_to_le16(
3999 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
4000 - 4);
4001 pSMB->DataCount = 0;
4002 pSMB->DataOffset = 0;
4003 pSMB->SetupCount = 1;
4004 pSMB->Reserved3 = 0;
4005 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4006 pSMB->SearchAttributes =
4007 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4008 ATTR_DIRECTORY);
4009 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
4010 pSMB->SearchFlags = cpu_to_le16(search_flags);
4011 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4012
4013
4014 pSMB->SearchStorageType = 0;
4015 inc_rfc1001_len(pSMB, byte_count);
4016 pSMB->ByteCount = cpu_to_le16(byte_count);
4017
4018 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4019 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4020 cifs_stats_inc(&tcon->stats.cifs_stats.num_ffirst);
4021
4022 if (rc) {
4023
4024
4025 cifs_dbg(FYI, "Error in FindFirst = %d\n", rc);
4026
4027 cifs_buf_release(pSMB);
4028
4029
4030
4031 if (rc == -EAGAIN)
4032 goto findFirstRetry;
4033 } else {
4034
4035 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4036 if (rc == 0) {
4037 unsigned int lnoff;
4038
4039 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4040 psrch_inf->unicode = true;
4041 else
4042 psrch_inf->unicode = false;
4043
4044 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4045 psrch_inf->smallBuf = false;
4046 psrch_inf->srch_entries_start =
4047 (char *) &pSMBr->hdr.Protocol +
4048 le16_to_cpu(pSMBr->t2.DataOffset);
4049 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
4050 le16_to_cpu(pSMBr->t2.ParameterOffset));
4051
4052 if (parms->EndofSearch)
4053 psrch_inf->endOfSearch = true;
4054 else
4055 psrch_inf->endOfSearch = false;
4056
4057 psrch_inf->entries_in_buffer =
4058 le16_to_cpu(parms->SearchCount);
4059 psrch_inf->index_of_last_entry = 2 +
4060 psrch_inf->entries_in_buffer;
4061 lnoff = le16_to_cpu(parms->LastNameOffset);
4062 if (CIFSMaxBufSize < lnoff) {
4063 cifs_dbg(VFS, "ignoring corrupt resume name\n");
4064 psrch_inf->last_entry = NULL;
4065 return rc;
4066 }
4067
4068 psrch_inf->last_entry = psrch_inf->srch_entries_start +
4069 lnoff;
4070
4071 if (pnetfid)
4072 *pnetfid = parms->SearchHandle;
4073 } else {
4074 cifs_buf_release(pSMB);
4075 }
4076 }
4077
4078 return rc;
4079 }
4080
4081 int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
4082 __u16 searchHandle, __u16 search_flags,
4083 struct cifs_search_info *psrch_inf)
4084 {
4085 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4086 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4087 T2_FNEXT_RSP_PARMS *parms;
4088 char *response_data;
4089 int rc = 0;
4090 int bytes_returned;
4091 unsigned int name_len;
4092 __u16 params, byte_count;
4093
4094 cifs_dbg(FYI, "In FindNext\n");
4095
4096 if (psrch_inf->endOfSearch)
4097 return -ENOENT;
4098
4099 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4100 (void **) &pSMBr);
4101 if (rc)
4102 return rc;
4103
4104 params = 14;
4105 byte_count = 0;
4106 pSMB->TotalDataCount = 0;
4107 pSMB->MaxParameterCount = cpu_to_le16(8);
4108 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4109 pSMB->MaxSetupCount = 0;
4110 pSMB->Reserved = 0;
4111 pSMB->Flags = 0;
4112 pSMB->Timeout = 0;
4113 pSMB->Reserved2 = 0;
4114 pSMB->ParameterOffset = cpu_to_le16(
4115 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4116 pSMB->DataCount = 0;
4117 pSMB->DataOffset = 0;
4118 pSMB->SetupCount = 1;
4119 pSMB->Reserved3 = 0;
4120 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4121 pSMB->SearchHandle = searchHandle;
4122 pSMB->SearchCount =
4123 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4124 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4125 pSMB->ResumeKey = psrch_inf->resume_key;
4126 pSMB->SearchFlags = cpu_to_le16(search_flags);
4127
4128 name_len = psrch_inf->resume_name_len;
4129 params += name_len;
4130 if (name_len < PATH_MAX) {
4131 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4132 byte_count += name_len;
4133
4134 pSMB->ResumeFileName[name_len] = 0;
4135 pSMB->ResumeFileName[name_len+1] = 0;
4136 } else {
4137 rc = -EINVAL;
4138 goto FNext2_err_exit;
4139 }
4140 byte_count = params + 1 ;
4141 pSMB->TotalParameterCount = cpu_to_le16(params);
4142 pSMB->ParameterCount = pSMB->TotalParameterCount;
4143 inc_rfc1001_len(pSMB, byte_count);
4144 pSMB->ByteCount = cpu_to_le16(byte_count);
4145
4146 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4147 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4148 cifs_stats_inc(&tcon->stats.cifs_stats.num_fnext);
4149 if (rc) {
4150 if (rc == -EBADF) {
4151 psrch_inf->endOfSearch = true;
4152 cifs_buf_release(pSMB);
4153 rc = 0;
4154 } else
4155 cifs_dbg(FYI, "FindNext returned = %d\n", rc);
4156 } else {
4157 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4158
4159 if (rc == 0) {
4160 unsigned int lnoff;
4161
4162
4163 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4164 psrch_inf->unicode = true;
4165 else
4166 psrch_inf->unicode = false;
4167 response_data = (char *) &pSMBr->hdr.Protocol +
4168 le16_to_cpu(pSMBr->t2.ParameterOffset);
4169 parms = (T2_FNEXT_RSP_PARMS *)response_data;
4170 response_data = (char *)&pSMBr->hdr.Protocol +
4171 le16_to_cpu(pSMBr->t2.DataOffset);
4172 if (psrch_inf->smallBuf)
4173 cifs_small_buf_release(
4174 psrch_inf->ntwrk_buf_start);
4175 else
4176 cifs_buf_release(psrch_inf->ntwrk_buf_start);
4177 psrch_inf->srch_entries_start = response_data;
4178 psrch_inf->ntwrk_buf_start = (char *)pSMB;
4179 psrch_inf->smallBuf = false;
4180 if (parms->EndofSearch)
4181 psrch_inf->endOfSearch = true;
4182 else
4183 psrch_inf->endOfSearch = false;
4184 psrch_inf->entries_in_buffer =
4185 le16_to_cpu(parms->SearchCount);
4186 psrch_inf->index_of_last_entry +=
4187 psrch_inf->entries_in_buffer;
4188 lnoff = le16_to_cpu(parms->LastNameOffset);
4189 if (CIFSMaxBufSize < lnoff) {
4190 cifs_dbg(VFS, "ignoring corrupt resume name\n");
4191 psrch_inf->last_entry = NULL;
4192 return rc;
4193 } else
4194 psrch_inf->last_entry =
4195 psrch_inf->srch_entries_start + lnoff;
4196
4197
4198
4199
4200
4201 }
4202
4203 }
4204
4205
4206
4207
4208
4209
4210 FNext2_err_exit:
4211 if (rc != 0)
4212 cifs_buf_release(pSMB);
4213 return rc;
4214 }
4215
4216 int
4217 CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
4218 const __u16 searchHandle)
4219 {
4220 int rc = 0;
4221 FINDCLOSE_REQ *pSMB = NULL;
4222
4223 cifs_dbg(FYI, "In CIFSSMBFindClose\n");
4224 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4225
4226
4227
4228 if (rc == -EAGAIN)
4229 return 0;
4230 if (rc)
4231 return rc;
4232
4233 pSMB->FileID = searchHandle;
4234 pSMB->ByteCount = 0;
4235 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
4236 cifs_small_buf_release(pSMB);
4237 if (rc)
4238 cifs_dbg(VFS, "Send error in FindClose = %d\n", rc);
4239
4240 cifs_stats_inc(&tcon->stats.cifs_stats.num_fclose);
4241
4242
4243 if (rc == -EAGAIN)
4244 rc = 0;
4245
4246 return rc;
4247 }
4248
4249 int
4250 CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
4251 const char *search_name, __u64 *inode_number,
4252 const struct nls_table *nls_codepage, int remap)
4253 {
4254 int rc = 0;
4255 TRANSACTION2_QPI_REQ *pSMB = NULL;
4256 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4257 int name_len, bytes_returned;
4258 __u16 params, byte_count;
4259
4260 cifs_dbg(FYI, "In GetSrvInodeNum for %s\n", search_name);
4261 if (tcon == NULL)
4262 return -ENODEV;
4263
4264 GetInodeNumberRetry:
4265 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4266 (void **) &pSMBr);
4267 if (rc)
4268 return rc;
4269
4270 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4271 name_len =
4272 cifsConvertToUTF16((__le16 *) pSMB->FileName,
4273 search_name, PATH_MAX, nls_codepage,
4274 remap);
4275 name_len++;
4276 name_len *= 2;
4277 } else {
4278 name_len = copy_path_name(pSMB->FileName, search_name);
4279 }
4280
4281 params = 2 + 4 + name_len ;
4282 pSMB->TotalDataCount = 0;
4283 pSMB->MaxParameterCount = cpu_to_le16(2);
4284
4285 pSMB->MaxDataCount = cpu_to_le16(4000);
4286 pSMB->MaxSetupCount = 0;
4287 pSMB->Reserved = 0;
4288 pSMB->Flags = 0;
4289 pSMB->Timeout = 0;
4290 pSMB->Reserved2 = 0;
4291 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4292 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4293 pSMB->DataCount = 0;
4294 pSMB->DataOffset = 0;
4295 pSMB->SetupCount = 1;
4296 pSMB->Reserved3 = 0;
4297 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4298 byte_count = params + 1 ;
4299 pSMB->TotalParameterCount = cpu_to_le16(params);
4300 pSMB->ParameterCount = pSMB->TotalParameterCount;
4301 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4302 pSMB->Reserved4 = 0;
4303 inc_rfc1001_len(pSMB, byte_count);
4304 pSMB->ByteCount = cpu_to_le16(byte_count);
4305
4306 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4307 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4308 if (rc) {
4309 cifs_dbg(FYI, "error %d in QueryInternalInfo\n", rc);
4310 } else {
4311
4312 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4313
4314 if (rc || get_bcc(&pSMBr->hdr) < 2)
4315
4316
4317 rc = -EIO;
4318 else {
4319 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4320 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4321 struct file_internal_info *pfinfo;
4322
4323 if (count < 8) {
4324 cifs_dbg(FYI, "Invalid size ret in QryIntrnlInf\n");
4325 rc = -EIO;
4326 goto GetInodeNumOut;
4327 }
4328 pfinfo = (struct file_internal_info *)
4329 (data_offset + (char *) &pSMBr->hdr.Protocol);
4330 *inode_number = le64_to_cpu(pfinfo->UniqueId);
4331 }
4332 }
4333 GetInodeNumOut:
4334 cifs_buf_release(pSMB);
4335 if (rc == -EAGAIN)
4336 goto GetInodeNumberRetry;
4337 return rc;
4338 }
4339
4340 int
4341 CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
4342 const char *search_name, struct dfs_info3_param **target_nodes,
4343 unsigned int *num_of_nodes,
4344 const struct nls_table *nls_codepage, int remap)
4345 {
4346
4347 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4348 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4349 int rc = 0;
4350 int bytes_returned;
4351 int name_len;
4352 __u16 params, byte_count;
4353 *num_of_nodes = 0;
4354 *target_nodes = NULL;
4355
4356 cifs_dbg(FYI, "In GetDFSRefer the path %s\n", search_name);
4357 if (ses == NULL || ses->tcon_ipc == NULL)
4358 return -ENODEV;
4359
4360 getDFSRetry:
4361 rc = smb_init(SMB_COM_TRANSACTION2, 15, ses->tcon_ipc, (void **) &pSMB,
4362 (void **) &pSMBr);
4363 if (rc)
4364 return rc;
4365
4366
4367
4368 pSMB->hdr.Mid = get_next_mid(ses->server);
4369 pSMB->hdr.Tid = ses->tcon_ipc->tid;
4370 pSMB->hdr.Uid = ses->Suid;
4371 if (ses->capabilities & CAP_STATUS32)
4372 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4373 if (ses->capabilities & CAP_DFS)
4374 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4375
4376 if (ses->capabilities & CAP_UNICODE) {
4377 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4378 name_len =
4379 cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
4380 search_name, PATH_MAX, nls_codepage,
4381 remap);
4382 name_len++;
4383 name_len *= 2;
4384 } else {
4385 name_len = copy_path_name(pSMB->RequestFileName, search_name);
4386 }
4387
4388 if (ses->server->sign)
4389 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4390
4391 pSMB->hdr.Uid = ses->Suid;
4392
4393 params = 2 + name_len ;
4394 pSMB->TotalDataCount = 0;
4395 pSMB->DataCount = 0;
4396 pSMB->DataOffset = 0;
4397 pSMB->MaxParameterCount = 0;
4398
4399 pSMB->MaxDataCount = cpu_to_le16(4000);
4400 pSMB->MaxSetupCount = 0;
4401 pSMB->Reserved = 0;
4402 pSMB->Flags = 0;
4403 pSMB->Timeout = 0;
4404 pSMB->Reserved2 = 0;
4405 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4406 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4407 pSMB->SetupCount = 1;
4408 pSMB->Reserved3 = 0;
4409 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4410 byte_count = params + 3 ;
4411 pSMB->ParameterCount = cpu_to_le16(params);
4412 pSMB->TotalParameterCount = pSMB->ParameterCount;
4413 pSMB->MaxReferralLevel = cpu_to_le16(3);
4414 inc_rfc1001_len(pSMB, byte_count);
4415 pSMB->ByteCount = cpu_to_le16(byte_count);
4416
4417 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4418 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4419 if (rc) {
4420 cifs_dbg(FYI, "Send error in GetDFSRefer = %d\n", rc);
4421 goto GetDFSRefExit;
4422 }
4423 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4424
4425
4426 if (rc || get_bcc(&pSMBr->hdr) < 17) {
4427 rc = -EIO;
4428 goto GetDFSRefExit;
4429 }
4430
4431 cifs_dbg(FYI, "Decoding GetDFSRefer response BCC: %d Offset %d\n",
4432 get_bcc(&pSMBr->hdr), le16_to_cpu(pSMBr->t2.DataOffset));
4433
4434
4435 rc = parse_dfs_referrals(&pSMBr->dfs_data,
4436 le16_to_cpu(pSMBr->t2.DataCount),
4437 num_of_nodes, target_nodes, nls_codepage,
4438 remap, search_name,
4439 (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) != 0);
4440
4441 GetDFSRefExit:
4442 cifs_buf_release(pSMB);
4443
4444 if (rc == -EAGAIN)
4445 goto getDFSRetry;
4446
4447 return rc;
4448 }
4449
4450
4451 int
4452 SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4453 struct kstatfs *FSData)
4454 {
4455
4456 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4457 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4458 FILE_SYSTEM_ALLOC_INFO *response_data;
4459 int rc = 0;
4460 int bytes_returned = 0;
4461 __u16 params, byte_count;
4462
4463 cifs_dbg(FYI, "OldQFSInfo\n");
4464 oldQFSInfoRetry:
4465 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4466 (void **) &pSMBr);
4467 if (rc)
4468 return rc;
4469
4470 params = 2;
4471 pSMB->TotalDataCount = 0;
4472 pSMB->MaxParameterCount = cpu_to_le16(2);
4473 pSMB->MaxDataCount = cpu_to_le16(1000);
4474 pSMB->MaxSetupCount = 0;
4475 pSMB->Reserved = 0;
4476 pSMB->Flags = 0;
4477 pSMB->Timeout = 0;
4478 pSMB->Reserved2 = 0;
4479 byte_count = params + 1 ;
4480 pSMB->TotalParameterCount = cpu_to_le16(params);
4481 pSMB->ParameterCount = pSMB->TotalParameterCount;
4482 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4483 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4484 pSMB->DataCount = 0;
4485 pSMB->DataOffset = 0;
4486 pSMB->SetupCount = 1;
4487 pSMB->Reserved3 = 0;
4488 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4489 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4490 inc_rfc1001_len(pSMB, byte_count);
4491 pSMB->ByteCount = cpu_to_le16(byte_count);
4492
4493 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4494 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4495 if (rc) {
4496 cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
4497 } else {
4498 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4499
4500 if (rc || get_bcc(&pSMBr->hdr) < 18)
4501 rc = -EIO;
4502 else {
4503 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4504 cifs_dbg(FYI, "qfsinf resp BCC: %d Offset %d\n",
4505 get_bcc(&pSMBr->hdr), data_offset);
4506
4507 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4508 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4509 FSData->f_bsize =
4510 le16_to_cpu(response_data->BytesPerSector) *
4511 le32_to_cpu(response_data->
4512 SectorsPerAllocationUnit);
4513
4514
4515
4516
4517 if (FSData->f_bsize < 512)
4518 FSData->f_bsize = 4096;
4519
4520 FSData->f_blocks =
4521 le32_to_cpu(response_data->TotalAllocationUnits);
4522 FSData->f_bfree = FSData->f_bavail =
4523 le32_to_cpu(response_data->FreeAllocationUnits);
4524 cifs_dbg(FYI, "Blocks: %lld Free: %lld Block size %ld\n",
4525 (unsigned long long)FSData->f_blocks,
4526 (unsigned long long)FSData->f_bfree,
4527 FSData->f_bsize);
4528 }
4529 }
4530 cifs_buf_release(pSMB);
4531
4532 if (rc == -EAGAIN)
4533 goto oldQFSInfoRetry;
4534
4535 return rc;
4536 }
4537
4538 int
4539 CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4540 struct kstatfs *FSData)
4541 {
4542
4543 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4544 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4545 FILE_SYSTEM_INFO *response_data;
4546 int rc = 0;
4547 int bytes_returned = 0;
4548 __u16 params, byte_count;
4549
4550 cifs_dbg(FYI, "In QFSInfo\n");
4551 QFSInfoRetry:
4552 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4553 (void **) &pSMBr);
4554 if (rc)
4555 return rc;
4556
4557 params = 2;
4558 pSMB->TotalDataCount = 0;
4559 pSMB->MaxParameterCount = cpu_to_le16(2);
4560 pSMB->MaxDataCount = cpu_to_le16(1000);
4561 pSMB->MaxSetupCount = 0;
4562 pSMB->Reserved = 0;
4563 pSMB->Flags = 0;
4564 pSMB->Timeout = 0;
4565 pSMB->Reserved2 = 0;
4566 byte_count = params + 1 ;
4567 pSMB->TotalParameterCount = cpu_to_le16(params);
4568 pSMB->ParameterCount = pSMB->TotalParameterCount;
4569 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4570 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4571 pSMB->DataCount = 0;
4572 pSMB->DataOffset = 0;
4573 pSMB->SetupCount = 1;
4574 pSMB->Reserved3 = 0;
4575 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4576 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4577 inc_rfc1001_len(pSMB, byte_count);
4578 pSMB->ByteCount = cpu_to_le16(byte_count);
4579
4580 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4581 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4582 if (rc) {
4583 cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
4584 } else {
4585 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4586
4587 if (rc || get_bcc(&pSMBr->hdr) < 24)
4588 rc = -EIO;
4589 else {
4590 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4591
4592 response_data =
4593 (FILE_SYSTEM_INFO
4594 *) (((char *) &pSMBr->hdr.Protocol) +
4595 data_offset);
4596 FSData->f_bsize =
4597 le32_to_cpu(response_data->BytesPerSector) *
4598 le32_to_cpu(response_data->
4599 SectorsPerAllocationUnit);
4600
4601
4602
4603
4604 if (FSData->f_bsize < 512)
4605 FSData->f_bsize = 4096;
4606
4607 FSData->f_blocks =
4608 le64_to_cpu(response_data->TotalAllocationUnits);
4609 FSData->f_bfree = FSData->f_bavail =
4610 le64_to_cpu(response_data->FreeAllocationUnits);
4611 cifs_dbg(FYI, "Blocks: %lld Free: %lld Block size %ld\n",
4612 (unsigned long long)FSData->f_blocks,
4613 (unsigned long long)FSData->f_bfree,
4614 FSData->f_bsize);
4615 }
4616 }
4617 cifs_buf_release(pSMB);
4618
4619 if (rc == -EAGAIN)
4620 goto QFSInfoRetry;
4621
4622 return rc;
4623 }
4624
4625 int
4626 CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)
4627 {
4628
4629 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4630 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4631 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4632 int rc = 0;
4633 int bytes_returned = 0;
4634 __u16 params, byte_count;
4635
4636 cifs_dbg(FYI, "In QFSAttributeInfo\n");
4637 QFSAttributeRetry:
4638 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4639 (void **) &pSMBr);
4640 if (rc)
4641 return rc;
4642
4643 params = 2;
4644 pSMB->TotalDataCount = 0;
4645 pSMB->MaxParameterCount = cpu_to_le16(2);
4646
4647 pSMB->MaxDataCount = cpu_to_le16(1000);
4648 pSMB->MaxSetupCount = 0;
4649 pSMB->Reserved = 0;
4650 pSMB->Flags = 0;
4651 pSMB->Timeout = 0;
4652 pSMB->Reserved2 = 0;
4653 byte_count = params + 1 ;
4654 pSMB->TotalParameterCount = cpu_to_le16(params);
4655 pSMB->ParameterCount = pSMB->TotalParameterCount;
4656 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4657 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4658 pSMB->DataCount = 0;
4659 pSMB->DataOffset = 0;
4660 pSMB->SetupCount = 1;
4661 pSMB->Reserved3 = 0;
4662 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4663 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4664 inc_rfc1001_len(pSMB, byte_count);
4665 pSMB->ByteCount = cpu_to_le16(byte_count);
4666
4667 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4668 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4669 if (rc) {
4670 cifs_dbg(VFS, "Send error in QFSAttributeInfo = %d\n", rc);
4671 } else {
4672 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4673
4674 if (rc || get_bcc(&pSMBr->hdr) < 13) {
4675
4676 rc = -EIO;
4677 } else {
4678 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4679 response_data =
4680 (FILE_SYSTEM_ATTRIBUTE_INFO
4681 *) (((char *) &pSMBr->hdr.Protocol) +
4682 data_offset);
4683 memcpy(&tcon->fsAttrInfo, response_data,
4684 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4685 }
4686 }
4687 cifs_buf_release(pSMB);
4688
4689 if (rc == -EAGAIN)
4690 goto QFSAttributeRetry;
4691
4692 return rc;
4693 }
4694
4695 int
4696 CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)
4697 {
4698
4699 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4700 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4701 FILE_SYSTEM_DEVICE_INFO *response_data;
4702 int rc = 0;
4703 int bytes_returned = 0;
4704 __u16 params, byte_count;
4705
4706 cifs_dbg(FYI, "In QFSDeviceInfo\n");
4707 QFSDeviceRetry:
4708 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4709 (void **) &pSMBr);
4710 if (rc)
4711 return rc;
4712
4713 params = 2;
4714 pSMB->TotalDataCount = 0;
4715 pSMB->MaxParameterCount = cpu_to_le16(2);
4716
4717 pSMB->MaxDataCount = cpu_to_le16(1000);
4718 pSMB->MaxSetupCount = 0;
4719 pSMB->Reserved = 0;
4720 pSMB->Flags = 0;
4721 pSMB->Timeout = 0;
4722 pSMB->Reserved2 = 0;
4723 byte_count = params + 1 ;
4724 pSMB->TotalParameterCount = cpu_to_le16(params);
4725 pSMB->ParameterCount = pSMB->TotalParameterCount;
4726 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4727 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4728
4729 pSMB->DataCount = 0;
4730 pSMB->DataOffset = 0;
4731 pSMB->SetupCount = 1;
4732 pSMB->Reserved3 = 0;
4733 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4734 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4735 inc_rfc1001_len(pSMB, byte_count);
4736 pSMB->ByteCount = cpu_to_le16(byte_count);
4737
4738 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4739 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4740 if (rc) {
4741 cifs_dbg(FYI, "Send error in QFSDeviceInfo = %d\n", rc);
4742 } else {
4743 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4744
4745 if (rc || get_bcc(&pSMBr->hdr) <
4746 sizeof(FILE_SYSTEM_DEVICE_INFO))
4747 rc = -EIO;
4748 else {
4749 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4750 response_data =
4751 (FILE_SYSTEM_DEVICE_INFO *)
4752 (((char *) &pSMBr->hdr.Protocol) +
4753 data_offset);
4754 memcpy(&tcon->fsDevInfo, response_data,
4755 sizeof(FILE_SYSTEM_DEVICE_INFO));
4756 }
4757 }
4758 cifs_buf_release(pSMB);
4759
4760 if (rc == -EAGAIN)
4761 goto QFSDeviceRetry;
4762
4763 return rc;
4764 }
4765
4766 int
4767 CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)
4768 {
4769
4770 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4771 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4772 FILE_SYSTEM_UNIX_INFO *response_data;
4773 int rc = 0;
4774 int bytes_returned = 0;
4775 __u16 params, byte_count;
4776
4777 cifs_dbg(FYI, "In QFSUnixInfo\n");
4778 QFSUnixRetry:
4779 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
4780 (void **) &pSMB, (void **) &pSMBr);
4781 if (rc)
4782 return rc;
4783
4784 params = 2;
4785 pSMB->TotalDataCount = 0;
4786 pSMB->DataCount = 0;
4787 pSMB->DataOffset = 0;
4788 pSMB->MaxParameterCount = cpu_to_le16(2);
4789
4790 pSMB->MaxDataCount = cpu_to_le16(100);
4791 pSMB->MaxSetupCount = 0;
4792 pSMB->Reserved = 0;
4793 pSMB->Flags = 0;
4794 pSMB->Timeout = 0;
4795 pSMB->Reserved2 = 0;
4796 byte_count = params + 1 ;
4797 pSMB->ParameterCount = cpu_to_le16(params);
4798 pSMB->TotalParameterCount = pSMB->ParameterCount;
4799 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4800 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4801 pSMB->SetupCount = 1;
4802 pSMB->Reserved3 = 0;
4803 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4804 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4805 inc_rfc1001_len(pSMB, byte_count);
4806 pSMB->ByteCount = cpu_to_le16(byte_count);
4807
4808 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4809 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4810 if (rc) {
4811 cifs_dbg(VFS, "Send error in QFSUnixInfo = %d\n", rc);
4812 } else {
4813 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4814
4815 if (rc || get_bcc(&pSMBr->hdr) < 13) {
4816 rc = -EIO;
4817 } else {
4818 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4819 response_data =
4820 (FILE_SYSTEM_UNIX_INFO
4821 *) (((char *) &pSMBr->hdr.Protocol) +
4822 data_offset);
4823 memcpy(&tcon->fsUnixInfo, response_data,
4824 sizeof(FILE_SYSTEM_UNIX_INFO));
4825 }
4826 }
4827 cifs_buf_release(pSMB);
4828
4829 if (rc == -EAGAIN)
4830 goto QFSUnixRetry;
4831
4832
4833 return rc;
4834 }
4835
4836 int
4837 CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)
4838 {
4839
4840 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4841 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4842 int rc = 0;
4843 int bytes_returned = 0;
4844 __u16 params, param_offset, offset, byte_count;
4845
4846 cifs_dbg(FYI, "In SETFSUnixInfo\n");
4847 SETFSUnixRetry:
4848
4849 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
4850 (void **) &pSMB, (void **) &pSMBr);
4851 if (rc)
4852 return rc;
4853
4854 params = 4;
4855 pSMB->MaxSetupCount = 0;
4856 pSMB->Reserved = 0;
4857 pSMB->Flags = 0;
4858 pSMB->Timeout = 0;
4859 pSMB->Reserved2 = 0;
4860 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4861 - 4;
4862 offset = param_offset + params;
4863
4864 pSMB->MaxParameterCount = cpu_to_le16(4);
4865
4866 pSMB->MaxDataCount = cpu_to_le16(100);
4867 pSMB->SetupCount = 1;
4868 pSMB->Reserved3 = 0;
4869 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4870 byte_count = 1 + params + 12;
4871
4872 pSMB->DataCount = cpu_to_le16(12);
4873 pSMB->ParameterCount = cpu_to_le16(params);
4874 pSMB->TotalDataCount = pSMB->DataCount;
4875 pSMB->TotalParameterCount = pSMB->ParameterCount;
4876 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4877 pSMB->DataOffset = cpu_to_le16(offset);
4878
4879
4880 pSMB->FileNum = 0;
4881 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4882
4883
4884 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4885 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4886 pSMB->ClientUnixCap = cpu_to_le64(cap);
4887
4888 inc_rfc1001_len(pSMB, byte_count);
4889 pSMB->ByteCount = cpu_to_le16(byte_count);
4890
4891 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4892 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4893 if (rc) {
4894 cifs_dbg(VFS, "Send error in SETFSUnixInfo = %d\n", rc);
4895 } else {
4896 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4897 if (rc)
4898 rc = -EIO;
4899 }
4900 cifs_buf_release(pSMB);
4901
4902 if (rc == -EAGAIN)
4903 goto SETFSUnixRetry;
4904
4905 return rc;
4906 }
4907
4908
4909
4910 int
4911 CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
4912 struct kstatfs *FSData)
4913 {
4914
4915 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4916 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4917 FILE_SYSTEM_POSIX_INFO *response_data;
4918 int rc = 0;
4919 int bytes_returned = 0;
4920 __u16 params, byte_count;
4921
4922 cifs_dbg(FYI, "In QFSPosixInfo\n");
4923 QFSPosixRetry:
4924 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4925 (void **) &pSMBr);
4926 if (rc)
4927 return rc;
4928
4929 params = 2;
4930 pSMB->TotalDataCount = 0;
4931 pSMB->DataCount = 0;
4932 pSMB->DataOffset = 0;
4933 pSMB->MaxParameterCount = cpu_to_le16(2);
4934
4935 pSMB->MaxDataCount = cpu_to_le16(100);
4936 pSMB->MaxSetupCount = 0;
4937 pSMB->Reserved = 0;
4938 pSMB->Flags = 0;
4939 pSMB->Timeout = 0;
4940 pSMB->Reserved2 = 0;
4941 byte_count = params + 1 ;
4942 pSMB->ParameterCount = cpu_to_le16(params);
4943 pSMB->TotalParameterCount = pSMB->ParameterCount;
4944 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4945 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4946 pSMB->SetupCount = 1;
4947 pSMB->Reserved3 = 0;
4948 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4949 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4950 inc_rfc1001_len(pSMB, byte_count);
4951 pSMB->ByteCount = cpu_to_le16(byte_count);
4952
4953 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4954 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4955 if (rc) {
4956 cifs_dbg(FYI, "Send error in QFSUnixInfo = %d\n", rc);
4957 } else {
4958 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4959
4960 if (rc || get_bcc(&pSMBr->hdr) < 13) {
4961 rc = -EIO;
4962 } else {
4963 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4964 response_data =
4965 (FILE_SYSTEM_POSIX_INFO
4966 *) (((char *) &pSMBr->hdr.Protocol) +
4967 data_offset);
4968 FSData->f_bsize =
4969 le32_to_cpu(response_data->BlockSize);
4970
4971
4972
4973
4974 if (FSData->f_bsize < 512)
4975 FSData->f_bsize = 4096;
4976
4977 FSData->f_blocks =
4978 le64_to_cpu(response_data->TotalBlocks);
4979 FSData->f_bfree =
4980 le64_to_cpu(response_data->BlocksAvail);
4981 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4982 FSData->f_bavail = FSData->f_bfree;
4983 } else {
4984 FSData->f_bavail =
4985 le64_to_cpu(response_data->UserBlocksAvail);
4986 }
4987 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4988 FSData->f_files =
4989 le64_to_cpu(response_data->TotalFileNodes);
4990 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4991 FSData->f_ffree =
4992 le64_to_cpu(response_data->FreeFileNodes);
4993 }
4994 }
4995 cifs_buf_release(pSMB);
4996
4997 if (rc == -EAGAIN)
4998 goto QFSPosixRetry;
4999
5000 return rc;
5001 }
5002
5003
5004
5005
5006
5007
5008
5009
5010 int
5011 CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
5012 const char *file_name, __u64 size, struct cifs_sb_info *cifs_sb,
5013 bool set_allocation)
5014 {
5015 struct smb_com_transaction2_spi_req *pSMB = NULL;
5016 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5017 struct file_end_of_file_info *parm_data;
5018 int name_len;
5019 int rc = 0;
5020 int bytes_returned = 0;
5021 int remap = cifs_remap(cifs_sb);
5022
5023 __u16 params, byte_count, data_count, param_offset, offset;
5024
5025 cifs_dbg(FYI, "In SetEOF\n");
5026 SetEOFRetry:
5027 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5028 (void **) &pSMBr);
5029 if (rc)
5030 return rc;
5031
5032 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5033 name_len =
5034 cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
5035 PATH_MAX, cifs_sb->local_nls, remap);
5036 name_len++;
5037 name_len *= 2;
5038 } else {
5039 name_len = copy_path_name(pSMB->FileName, file_name);
5040 }
5041 params = 6 + name_len;
5042 data_count = sizeof(struct file_end_of_file_info);
5043 pSMB->MaxParameterCount = cpu_to_le16(2);
5044 pSMB->MaxDataCount = cpu_to_le16(4100);
5045 pSMB->MaxSetupCount = 0;
5046 pSMB->Reserved = 0;
5047 pSMB->Flags = 0;
5048 pSMB->Timeout = 0;
5049 pSMB->Reserved2 = 0;
5050 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5051 InformationLevel) - 4;
5052 offset = param_offset + params;
5053 if (set_allocation) {
5054 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5055 pSMB->InformationLevel =
5056 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5057 else
5058 pSMB->InformationLevel =
5059 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5060 } else {
5061 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5062 pSMB->InformationLevel =
5063 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5064 else
5065 pSMB->InformationLevel =
5066 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5067 }
5068
5069 parm_data =
5070 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5071 offset);
5072 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5073 pSMB->DataOffset = cpu_to_le16(offset);
5074 pSMB->SetupCount = 1;
5075 pSMB->Reserved3 = 0;
5076 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5077 byte_count = 3 + params + data_count;
5078 pSMB->DataCount = cpu_to_le16(data_count);
5079 pSMB->TotalDataCount = pSMB->DataCount;
5080 pSMB->ParameterCount = cpu_to_le16(params);
5081 pSMB->TotalParameterCount = pSMB->ParameterCount;
5082 pSMB->Reserved4 = 0;
5083 inc_rfc1001_len(pSMB, byte_count);
5084 parm_data->FileSize = cpu_to_le64(size);
5085 pSMB->ByteCount = cpu_to_le16(byte_count);
5086 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5087 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5088 if (rc)
5089 cifs_dbg(FYI, "SetPathInfo (file size) returned %d\n", rc);
5090
5091 cifs_buf_release(pSMB);
5092
5093 if (rc == -EAGAIN)
5094 goto SetEOFRetry;
5095
5096 return rc;
5097 }
5098
5099 int
5100 CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
5101 struct cifsFileInfo *cfile, __u64 size, bool set_allocation)
5102 {
5103 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5104 struct file_end_of_file_info *parm_data;
5105 int rc = 0;
5106 __u16 params, param_offset, offset, byte_count, count;
5107
5108 cifs_dbg(FYI, "SetFileSize (via SetFileInfo) %lld\n",
5109 (long long)size);
5110 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5111
5112 if (rc)
5113 return rc;
5114
5115 pSMB->hdr.Pid = cpu_to_le16((__u16)cfile->pid);
5116 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(cfile->pid >> 16));
5117
5118 params = 6;
5119 pSMB->MaxSetupCount = 0;
5120 pSMB->Reserved = 0;
5121 pSMB->Flags = 0;
5122 pSMB->Timeout = 0;
5123 pSMB->Reserved2 = 0;
5124 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5125 offset = param_offset + params;
5126
5127 count = sizeof(struct file_end_of_file_info);
5128 pSMB->MaxParameterCount = cpu_to_le16(2);
5129
5130 pSMB->MaxDataCount = cpu_to_le16(1000);
5131 pSMB->SetupCount = 1;
5132 pSMB->Reserved3 = 0;
5133 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5134 byte_count = 3 + params + count;
5135 pSMB->DataCount = cpu_to_le16(count);
5136 pSMB->ParameterCount = cpu_to_le16(params);
5137 pSMB->TotalDataCount = pSMB->DataCount;
5138 pSMB->TotalParameterCount = pSMB->ParameterCount;
5139 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5140
5141 parm_data =
5142 (struct file_end_of_file_info *)(((char *)pSMB) + offset + 4);
5143 pSMB->DataOffset = cpu_to_le16(offset);
5144 parm_data->FileSize = cpu_to_le64(size);
5145 pSMB->Fid = cfile->fid.netfid;
5146 if (set_allocation) {
5147 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5148 pSMB->InformationLevel =
5149 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5150 else
5151 pSMB->InformationLevel =
5152 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5153 } else {
5154 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5155 pSMB->InformationLevel =
5156 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5157 else
5158 pSMB->InformationLevel =
5159 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5160 }
5161 pSMB->Reserved4 = 0;
5162 inc_rfc1001_len(pSMB, byte_count);
5163 pSMB->ByteCount = cpu_to_le16(byte_count);
5164 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5165 cifs_small_buf_release(pSMB);
5166 if (rc) {
5167 cifs_dbg(FYI, "Send error in SetFileInfo (SetFileSize) = %d\n",
5168 rc);
5169 }
5170
5171
5172
5173
5174 return rc;
5175 }
5176
5177
5178
5179
5180
5181
5182
5183 int
5184 CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5185 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5186 {
5187 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5188 char *data_offset;
5189 int rc = 0;
5190 __u16 params, param_offset, offset, byte_count, count;
5191
5192 cifs_dbg(FYI, "Set Times (via SetFileInfo)\n");
5193 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5194
5195 if (rc)
5196 return rc;
5197
5198 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5199 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5200
5201 params = 6;
5202 pSMB->MaxSetupCount = 0;
5203 pSMB->Reserved = 0;
5204 pSMB->Flags = 0;
5205 pSMB->Timeout = 0;
5206 pSMB->Reserved2 = 0;
5207 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5208 offset = param_offset + params;
5209
5210 data_offset = (char *)pSMB +
5211 offsetof(struct smb_hdr, Protocol) + offset;
5212
5213 count = sizeof(FILE_BASIC_INFO);
5214 pSMB->MaxParameterCount = cpu_to_le16(2);
5215
5216 pSMB->MaxDataCount = cpu_to_le16(1000);
5217 pSMB->SetupCount = 1;
5218 pSMB->Reserved3 = 0;
5219 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5220 byte_count = 3 + params + count;
5221 pSMB->DataCount = cpu_to_le16(count);
5222 pSMB->ParameterCount = cpu_to_le16(params);
5223 pSMB->TotalDataCount = pSMB->DataCount;
5224 pSMB->TotalParameterCount = pSMB->ParameterCount;
5225 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5226 pSMB->DataOffset = cpu_to_le16(offset);
5227 pSMB->Fid = fid;
5228 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5229 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5230 else
5231 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5232 pSMB->Reserved4 = 0;
5233 inc_rfc1001_len(pSMB, byte_count);
5234 pSMB->ByteCount = cpu_to_le16(byte_count);
5235 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5236 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5237 cifs_small_buf_release(pSMB);
5238 if (rc)
5239 cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
5240 rc);
5241
5242
5243
5244
5245 return rc;
5246 }
5247
5248 int
5249 CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
5250 bool delete_file, __u16 fid, __u32 pid_of_opener)
5251 {
5252 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5253 char *data_offset;
5254 int rc = 0;
5255 __u16 params, param_offset, offset, byte_count, count;
5256
5257 cifs_dbg(FYI, "Set File Disposition (via SetFileInfo)\n");
5258 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5259
5260 if (rc)
5261 return rc;
5262
5263 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5264 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5265
5266 params = 6;
5267 pSMB->MaxSetupCount = 0;
5268 pSMB->Reserved = 0;
5269 pSMB->Flags = 0;
5270 pSMB->Timeout = 0;
5271 pSMB->Reserved2 = 0;
5272 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5273 offset = param_offset + params;
5274
5275
5276 data_offset = (char *)(pSMB) + offset + 4;
5277
5278 count = 1;
5279 pSMB->MaxParameterCount = cpu_to_le16(2);
5280
5281 pSMB->MaxDataCount = cpu_to_le16(1000);
5282 pSMB->SetupCount = 1;
5283 pSMB->Reserved3 = 0;
5284 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5285 byte_count = 3 + params + count;
5286 pSMB->DataCount = cpu_to_le16(count);
5287 pSMB->ParameterCount = cpu_to_le16(params);
5288 pSMB->TotalDataCount = pSMB->DataCount;
5289 pSMB->TotalParameterCount = pSMB->ParameterCount;
5290 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5291 pSMB->DataOffset = cpu_to_le16(offset);
5292 pSMB->Fid = fid;
5293 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5294 pSMB->Reserved4 = 0;
5295 inc_rfc1001_len(pSMB, byte_count);
5296 pSMB->ByteCount = cpu_to_le16(byte_count);
5297 *data_offset = delete_file ? 1 : 0;
5298 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5299 cifs_small_buf_release(pSMB);
5300 if (rc)
5301 cifs_dbg(FYI, "Send error in SetFileDisposition = %d\n", rc);
5302
5303 return rc;
5304 }
5305
5306 static int
5307 CIFSSMBSetPathInfoFB(const unsigned int xid, struct cifs_tcon *tcon,
5308 const char *fileName, const FILE_BASIC_INFO *data,
5309 const struct nls_table *nls_codepage,
5310 struct cifs_sb_info *cifs_sb)
5311 {
5312 int oplock = 0;
5313 struct cifs_open_parms oparms;
5314 struct cifs_fid fid;
5315 int rc;
5316
5317 oparms.tcon = tcon;
5318 oparms.cifs_sb = cifs_sb;
5319 oparms.desired_access = GENERIC_WRITE;
5320 oparms.create_options = cifs_create_options(cifs_sb, 0);
5321 oparms.disposition = FILE_OPEN;
5322 oparms.path = fileName;
5323 oparms.fid = &fid;
5324 oparms.reconnect = false;
5325
5326 rc = CIFS_open(xid, &oparms, &oplock, NULL);
5327 if (rc)
5328 goto out;
5329
5330 rc = CIFSSMBSetFileInfo(xid, tcon, data, fid.netfid, current->tgid);
5331 CIFSSMBClose(xid, tcon, fid.netfid);
5332 out:
5333
5334 return rc;
5335 }
5336
5337 int
5338 CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5339 const char *fileName, const FILE_BASIC_INFO *data,
5340 const struct nls_table *nls_codepage,
5341 struct cifs_sb_info *cifs_sb)
5342 {
5343 TRANSACTION2_SPI_REQ *pSMB = NULL;
5344 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5345 int name_len;
5346 int rc = 0;
5347 int bytes_returned = 0;
5348 char *data_offset;
5349 __u16 params, param_offset, offset, byte_count, count;
5350 int remap = cifs_remap(cifs_sb);
5351
5352 cifs_dbg(FYI, "In SetTimes\n");
5353
5354 SetTimesRetry:
5355 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5356 (void **) &pSMBr);
5357 if (rc)
5358 return rc;
5359
5360 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5361 name_len =
5362 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5363 PATH_MAX, nls_codepage, remap);
5364 name_len++;
5365 name_len *= 2;
5366 } else {
5367 name_len = copy_path_name(pSMB->FileName, fileName);
5368 }
5369
5370 params = 6 + name_len;
5371 count = sizeof(FILE_BASIC_INFO);
5372 pSMB->MaxParameterCount = cpu_to_le16(2);
5373
5374 pSMB->MaxDataCount = cpu_to_le16(1000);
5375 pSMB->MaxSetupCount = 0;
5376 pSMB->Reserved = 0;
5377 pSMB->Flags = 0;
5378 pSMB->Timeout = 0;
5379 pSMB->Reserved2 = 0;
5380 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5381 InformationLevel) - 4;
5382 offset = param_offset + params;
5383 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5384 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5385 pSMB->DataOffset = cpu_to_le16(offset);
5386 pSMB->SetupCount = 1;
5387 pSMB->Reserved3 = 0;
5388 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5389 byte_count = 3 + params + count;
5390
5391 pSMB->DataCount = cpu_to_le16(count);
5392 pSMB->ParameterCount = cpu_to_le16(params);
5393 pSMB->TotalDataCount = pSMB->DataCount;
5394 pSMB->TotalParameterCount = pSMB->ParameterCount;
5395 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5396 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5397 else
5398 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5399 pSMB->Reserved4 = 0;
5400 inc_rfc1001_len(pSMB, byte_count);
5401 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5402 pSMB->ByteCount = cpu_to_le16(byte_count);
5403 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5404 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5405 if (rc)
5406 cifs_dbg(FYI, "SetPathInfo (times) returned %d\n", rc);
5407
5408 cifs_buf_release(pSMB);
5409
5410 if (rc == -EAGAIN)
5411 goto SetTimesRetry;
5412
5413 if (rc == -EOPNOTSUPP)
5414 return CIFSSMBSetPathInfoFB(xid, tcon, fileName, data,
5415 nls_codepage, cifs_sb);
5416
5417 return rc;
5418 }
5419
5420 static void
5421 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5422 const struct cifs_unix_set_info_args *args)
5423 {
5424 u64 uid = NO_CHANGE_64, gid = NO_CHANGE_64;
5425 u64 mode = args->mode;
5426
5427 if (uid_valid(args->uid))
5428 uid = from_kuid(&init_user_ns, args->uid);
5429 if (gid_valid(args->gid))
5430 gid = from_kgid(&init_user_ns, args->gid);
5431
5432
5433
5434
5435
5436
5437
5438
5439 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5440 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5441 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5442 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5443 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5444 data_offset->Uid = cpu_to_le64(uid);
5445 data_offset->Gid = cpu_to_le64(gid);
5446
5447 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5448 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5449 data_offset->Permissions = cpu_to_le64(mode);
5450
5451 if (S_ISREG(mode))
5452 data_offset->Type = cpu_to_le32(UNIX_FILE);
5453 else if (S_ISDIR(mode))
5454 data_offset->Type = cpu_to_le32(UNIX_DIR);
5455 else if (S_ISLNK(mode))
5456 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5457 else if (S_ISCHR(mode))
5458 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5459 else if (S_ISBLK(mode))
5460 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5461 else if (S_ISFIFO(mode))
5462 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5463 else if (S_ISSOCK(mode))
5464 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5465 }
5466
5467 int
5468 CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5469 const struct cifs_unix_set_info_args *args,
5470 u16 fid, u32 pid_of_opener)
5471 {
5472 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5473 char *data_offset;
5474 int rc = 0;
5475 u16 params, param_offset, offset, byte_count, count;
5476
5477 cifs_dbg(FYI, "Set Unix Info (via SetFileInfo)\n");
5478 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5479
5480 if (rc)
5481 return rc;
5482
5483 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5484 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5485
5486 params = 6;
5487 pSMB->MaxSetupCount = 0;
5488 pSMB->Reserved = 0;
5489 pSMB->Flags = 0;
5490 pSMB->Timeout = 0;
5491 pSMB->Reserved2 = 0;
5492 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5493 offset = param_offset + params;
5494
5495 data_offset = (char *)pSMB +
5496 offsetof(struct smb_hdr, Protocol) + offset;
5497
5498 count = sizeof(FILE_UNIX_BASIC_INFO);
5499
5500 pSMB->MaxParameterCount = cpu_to_le16(2);
5501
5502 pSMB->MaxDataCount = cpu_to_le16(1000);
5503 pSMB->SetupCount = 1;
5504 pSMB->Reserved3 = 0;
5505 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5506 byte_count = 3 + params + count;
5507 pSMB->DataCount = cpu_to_le16(count);
5508 pSMB->ParameterCount = cpu_to_le16(params);
5509 pSMB->TotalDataCount = pSMB->DataCount;
5510 pSMB->TotalParameterCount = pSMB->ParameterCount;
5511 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5512 pSMB->DataOffset = cpu_to_le16(offset);
5513 pSMB->Fid = fid;
5514 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5515 pSMB->Reserved4 = 0;
5516 inc_rfc1001_len(pSMB, byte_count);
5517 pSMB->ByteCount = cpu_to_le16(byte_count);
5518
5519 cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
5520
5521 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5522 cifs_small_buf_release(pSMB);
5523 if (rc)
5524 cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
5525 rc);
5526
5527
5528
5529
5530 return rc;
5531 }
5532
5533 int
5534 CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5535 const char *file_name,
5536 const struct cifs_unix_set_info_args *args,
5537 const struct nls_table *nls_codepage, int remap)
5538 {
5539 TRANSACTION2_SPI_REQ *pSMB = NULL;
5540 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5541 int name_len;
5542 int rc = 0;
5543 int bytes_returned = 0;
5544 FILE_UNIX_BASIC_INFO *data_offset;
5545 __u16 params, param_offset, offset, count, byte_count;
5546
5547 cifs_dbg(FYI, "In SetUID/GID/Mode\n");
5548 setPermsRetry:
5549 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5550 (void **) &pSMBr);
5551 if (rc)
5552 return rc;
5553
5554 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5555 name_len =
5556 cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
5557 PATH_MAX, nls_codepage, remap);
5558 name_len++;
5559 name_len *= 2;
5560 } else {
5561 name_len = copy_path_name(pSMB->FileName, file_name);
5562 }
5563
5564 params = 6 + name_len;
5565 count = sizeof(FILE_UNIX_BASIC_INFO);
5566 pSMB->MaxParameterCount = cpu_to_le16(2);
5567
5568 pSMB->MaxDataCount = cpu_to_le16(1000);
5569 pSMB->MaxSetupCount = 0;
5570 pSMB->Reserved = 0;
5571 pSMB->Flags = 0;
5572 pSMB->Timeout = 0;
5573 pSMB->Reserved2 = 0;
5574 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5575 InformationLevel) - 4;
5576 offset = param_offset + params;
5577
5578 data_offset = (FILE_UNIX_BASIC_INFO *)((char *) pSMB + offset + 4);
5579 memset(data_offset, 0, count);
5580 pSMB->DataOffset = cpu_to_le16(offset);
5581 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5582 pSMB->SetupCount = 1;
5583 pSMB->Reserved3 = 0;
5584 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5585 byte_count = 3 + params + count;
5586 pSMB->ParameterCount = cpu_to_le16(params);
5587 pSMB->DataCount = cpu_to_le16(count);
5588 pSMB->TotalParameterCount = pSMB->ParameterCount;
5589 pSMB->TotalDataCount = pSMB->DataCount;
5590 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5591 pSMB->Reserved4 = 0;
5592 inc_rfc1001_len(pSMB, byte_count);
5593
5594 cifs_fill_unix_set_info(data_offset, args);
5595
5596 pSMB->ByteCount = cpu_to_le16(byte_count);
5597 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5598 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5599 if (rc)
5600 cifs_dbg(FYI, "SetPathInfo (perms) returned %d\n", rc);
5601
5602 cifs_buf_release(pSMB);
5603 if (rc == -EAGAIN)
5604 goto setPermsRetry;
5605 return rc;
5606 }
5607
5608 #ifdef CONFIG_CIFS_XATTR
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618 ssize_t
5619 CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
5620 const unsigned char *searchName, const unsigned char *ea_name,
5621 char *EAData, size_t buf_size,
5622 struct cifs_sb_info *cifs_sb)
5623 {
5624
5625 TRANSACTION2_QPI_REQ *pSMB = NULL;
5626 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5627 int remap = cifs_remap(cifs_sb);
5628 struct nls_table *nls_codepage = cifs_sb->local_nls;
5629 int rc = 0;
5630 int bytes_returned;
5631 int list_len;
5632 struct fealist *ea_response_data;
5633 struct fea *temp_fea;
5634 char *temp_ptr;
5635 char *end_of_smb;
5636 __u16 params, byte_count, data_offset;
5637 unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
5638
5639 cifs_dbg(FYI, "In Query All EAs path %s\n", searchName);
5640 QAllEAsRetry:
5641 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5642 (void **) &pSMBr);
5643 if (rc)
5644 return rc;
5645
5646 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5647 list_len =
5648 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
5649 PATH_MAX, nls_codepage, remap);
5650 list_len++;
5651 list_len *= 2;
5652 } else {
5653 list_len = copy_path_name(pSMB->FileName, searchName);
5654 }
5655
5656 params = 2 + 4 + list_len ;
5657 pSMB->TotalDataCount = 0;
5658 pSMB->MaxParameterCount = cpu_to_le16(2);
5659
5660 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
5661 pSMB->MaxSetupCount = 0;
5662 pSMB->Reserved = 0;
5663 pSMB->Flags = 0;
5664 pSMB->Timeout = 0;
5665 pSMB->Reserved2 = 0;
5666 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5667 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5668 pSMB->DataCount = 0;
5669 pSMB->DataOffset = 0;
5670 pSMB->SetupCount = 1;
5671 pSMB->Reserved3 = 0;
5672 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5673 byte_count = params + 1 ;
5674 pSMB->TotalParameterCount = cpu_to_le16(params);
5675 pSMB->ParameterCount = pSMB->TotalParameterCount;
5676 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5677 pSMB->Reserved4 = 0;
5678 inc_rfc1001_len(pSMB, byte_count);
5679 pSMB->ByteCount = cpu_to_le16(byte_count);
5680
5681 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5682 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5683 if (rc) {
5684 cifs_dbg(FYI, "Send error in QueryAllEAs = %d\n", rc);
5685 goto QAllEAsOut;
5686 }
5687
5688
5689
5690
5691
5692
5693 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5694 if (rc || get_bcc(&pSMBr->hdr) < 4) {
5695 rc = -EIO;
5696 goto QAllEAsOut;
5697 }
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5708 ea_response_data = (struct fealist *)
5709 (((char *) &pSMBr->hdr.Protocol) + data_offset);
5710
5711 list_len = le32_to_cpu(ea_response_data->list_len);
5712 cifs_dbg(FYI, "ea length %d\n", list_len);
5713 if (list_len <= 8) {
5714 cifs_dbg(FYI, "empty EA list returned from server\n");
5715
5716 if (ea_name)
5717 rc = -ENODATA;
5718 goto QAllEAsOut;
5719 }
5720
5721
5722 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
5723 if ((char *)ea_response_data + list_len > end_of_smb) {
5724 cifs_dbg(FYI, "EA list appears to go beyond SMB\n");
5725 rc = -EIO;
5726 goto QAllEAsOut;
5727 }
5728
5729
5730 list_len -= 4;
5731 temp_fea = ea_response_data->list;
5732 temp_ptr = (char *)temp_fea;
5733 while (list_len > 0) {
5734 unsigned int name_len;
5735 __u16 value_len;
5736
5737 list_len -= 4;
5738 temp_ptr += 4;
5739
5740 if (list_len < 0) {
5741 cifs_dbg(FYI, "EA entry goes beyond length of list\n");
5742 rc = -EIO;
5743 goto QAllEAsOut;
5744 }
5745
5746 name_len = temp_fea->name_len;
5747 value_len = le16_to_cpu(temp_fea->value_len);
5748 list_len -= name_len + 1 + value_len;
5749 if (list_len < 0) {
5750 cifs_dbg(FYI, "EA entry goes beyond length of list\n");
5751 rc = -EIO;
5752 goto QAllEAsOut;
5753 }
5754
5755 if (ea_name) {
5756 if (ea_name_len == name_len &&
5757 memcmp(ea_name, temp_ptr, name_len) == 0) {
5758 temp_ptr += name_len + 1;
5759 rc = value_len;
5760 if (buf_size == 0)
5761 goto QAllEAsOut;
5762 if ((size_t)value_len > buf_size) {
5763 rc = -ERANGE;
5764 goto QAllEAsOut;
5765 }
5766 memcpy(EAData, temp_ptr, value_len);
5767 goto QAllEAsOut;
5768 }
5769 } else {
5770
5771 rc += (5 + 1 + name_len);
5772 if (rc < (int) buf_size) {
5773 memcpy(EAData, "user.", 5);
5774 EAData += 5;
5775 memcpy(EAData, temp_ptr, name_len);
5776 EAData += name_len;
5777
5778 *EAData = 0;
5779 ++EAData;
5780 } else if (buf_size == 0) {
5781
5782 } else {
5783
5784 rc = -ERANGE;
5785 break;
5786 }
5787 }
5788 temp_ptr += name_len + 1 + value_len;
5789 temp_fea = (struct fea *)temp_ptr;
5790 }
5791
5792
5793 if (ea_name)
5794 rc = -ENODATA;
5795
5796 QAllEAsOut:
5797 cifs_buf_release(pSMB);
5798 if (rc == -EAGAIN)
5799 goto QAllEAsRetry;
5800
5801 return (ssize_t)rc;
5802 }
5803
5804 int
5805 CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
5806 const char *fileName, const char *ea_name, const void *ea_value,
5807 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5808 struct cifs_sb_info *cifs_sb)
5809 {
5810 struct smb_com_transaction2_spi_req *pSMB = NULL;
5811 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5812 struct fealist *parm_data;
5813 int name_len;
5814 int rc = 0;
5815 int bytes_returned = 0;
5816 __u16 params, param_offset, byte_count, offset, count;
5817 int remap = cifs_remap(cifs_sb);
5818
5819 cifs_dbg(FYI, "In SetEA\n");
5820 SetEARetry:
5821 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5822 (void **) &pSMBr);
5823 if (rc)
5824 return rc;
5825
5826 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5827 name_len =
5828 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5829 PATH_MAX, nls_codepage, remap);
5830 name_len++;
5831 name_len *= 2;
5832 } else {
5833 name_len = copy_path_name(pSMB->FileName, fileName);
5834 }
5835
5836 params = 6 + name_len;
5837
5838
5839
5840
5841 if (ea_name == NULL)
5842 name_len = 0;
5843 else
5844 name_len = strnlen(ea_name, 255);
5845
5846 count = sizeof(*parm_data) + ea_value_len + name_len;
5847 pSMB->MaxParameterCount = cpu_to_le16(2);
5848
5849 pSMB->MaxDataCount = cpu_to_le16(1000);
5850 pSMB->MaxSetupCount = 0;
5851 pSMB->Reserved = 0;
5852 pSMB->Flags = 0;
5853 pSMB->Timeout = 0;
5854 pSMB->Reserved2 = 0;
5855 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5856 InformationLevel) - 4;
5857 offset = param_offset + params;
5858 pSMB->InformationLevel =
5859 cpu_to_le16(SMB_SET_FILE_EA);
5860
5861 parm_data = (void *)pSMB + offsetof(struct smb_hdr, Protocol) + offset;
5862 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5863 pSMB->DataOffset = cpu_to_le16(offset);
5864 pSMB->SetupCount = 1;
5865 pSMB->Reserved3 = 0;
5866 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5867 byte_count = 3 + params + count;
5868 pSMB->DataCount = cpu_to_le16(count);
5869 parm_data->list_len = cpu_to_le32(count);
5870 parm_data->list[0].EA_flags = 0;
5871
5872 parm_data->list[0].name_len = (__u8)name_len;
5873
5874 if (ea_name)
5875 strncpy(parm_data->list[0].name, ea_name, name_len);
5876 parm_data->list[0].name[name_len] = 0;
5877 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5878
5879
5880
5881
5882
5883
5884 if (ea_value_len)
5885 memcpy(parm_data->list[0].name+name_len+1,
5886 ea_value, ea_value_len);
5887
5888 pSMB->TotalDataCount = pSMB->DataCount;
5889 pSMB->ParameterCount = cpu_to_le16(params);
5890 pSMB->TotalParameterCount = pSMB->ParameterCount;
5891 pSMB->Reserved4 = 0;
5892 inc_rfc1001_len(pSMB, byte_count);
5893 pSMB->ByteCount = cpu_to_le16(byte_count);
5894 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5895 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5896 if (rc)
5897 cifs_dbg(FYI, "SetPathInfo (EA) returned %d\n", rc);
5898
5899 cifs_buf_release(pSMB);
5900
5901 if (rc == -EAGAIN)
5902 goto SetEARetry;
5903
5904 return rc;
5905 }
5906 #endif