1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#include <linux/fs.h>
18#include <linux/kernel.h>
19#include <linux/vfs.h>
20#include <linux/slab.h>
21#include <linux/posix_acl_xattr.h>
22#include <linux/pagemap.h>
23#include <linux/swap.h>
24#include <linux/task_io_accounting_ops.h>
25#include <linux/uaccess.h>
26#include "cifspdu.h"
27#include "cifsglob.h"
28#include "cifsacl.h"
29#include "cifsproto.h"
30#include "cifs_unicode.h"
31#include "cifs_debug.h"
32#include "smb2proto.h"
33#include "fscache.h"
34#include "smbdirect.h"
35#ifdef CONFIG_CIFS_DFS_UPCALL
36#include "dfs_cache.h"
37#endif
38
39#ifdef CONFIG_CIFS_POSIX
40static struct {
41 int index;
42 char *name;
43} protocols[] = {
44 {CIFS_PROT, "\2NT LM 0.12"},
45 {POSIX_PROT, "\2POSIX 2"},
46 {BAD_PROT, "\2"}
47};
48#else
49static struct {
50 int index;
51 char *name;
52} protocols[] = {
53 {CIFS_PROT, "\2NT LM 0.12"},
54 {BAD_PROT, "\2"}
55};
56#endif
57
58
59#ifdef CONFIG_CIFS_POSIX
60#define CIFS_NUM_PROT 2
61#else
62#define CIFS_NUM_PROT 1
63#endif
64
65
66
67
68
69void
70cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
71{
72 struct cifsFileInfo *open_file = NULL;
73 struct list_head *tmp;
74 struct list_head *tmp1;
75
76
77 spin_lock(&tcon->open_file_lock);
78 list_for_each_safe(tmp, tmp1, &tcon->openFileList) {
79 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
80 open_file->invalidHandle = true;
81 open_file->oplock_break_cancelled = true;
82 }
83 spin_unlock(&tcon->open_file_lock);
84
85 mutex_lock(&tcon->crfid.fid_mutex);
86 tcon->crfid.is_valid = false;
87
88 close_cached_dir_lease_locked(&tcon->crfid);
89 memset(tcon->crfid.fid, 0, sizeof(struct cifs_fid));
90 mutex_unlock(&tcon->crfid.fid_mutex);
91
92
93
94
95
96}
97
98
99static int
100cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
101{
102 int rc;
103 struct cifs_ses *ses;
104 struct TCP_Server_Info *server;
105 struct nls_table *nls_codepage;
106 int retries;
107
108
109
110
111
112
113 if (!tcon)
114 return 0;
115
116 ses = tcon->ses;
117 server = ses->server;
118
119
120
121
122
123 if (tcon->tidStatus == CifsExiting) {
124 if (smb_command != SMB_COM_WRITE_ANDX &&
125 smb_command != SMB_COM_OPEN_ANDX &&
126 smb_command != SMB_COM_TREE_DISCONNECT) {
127 cifs_dbg(FYI, "can not send cmd %d while umounting\n",
128 smb_command);
129 return -ENODEV;
130 }
131 }
132
133 retries = server->nr_targets;
134
135
136
137
138
139
140 while (server->tcpStatus == CifsNeedReconnect) {
141 rc = wait_event_interruptible_timeout(server->response_q,
142 (server->tcpStatus != CifsNeedReconnect),
143 10 * HZ);
144 if (rc < 0) {
145 cifs_dbg(FYI, "%s: aborting reconnect due to a received signal by the process\n",
146 __func__);
147 return -ERESTARTSYS;
148 }
149
150
151 if (server->tcpStatus != CifsNeedReconnect)
152 break;
153
154 if (retries && --retries)
155 continue;
156
157
158
159
160
161
162 if (!tcon->retry) {
163 cifs_dbg(FYI, "gave up waiting on reconnect in smb_init\n");
164 return -EHOSTDOWN;
165 }
166 retries = server->nr_targets;
167 }
168
169 if (!ses->need_reconnect && !tcon->need_reconnect)
170 return 0;
171
172 nls_codepage = load_nls_default();
173
174
175
176
177
178 mutex_lock(&ses->session_mutex);
179
180
181
182
183
184
185 if (server->tcpStatus == CifsNeedReconnect) {
186 rc = -EHOSTDOWN;
187 mutex_unlock(&ses->session_mutex);
188 goto out;
189 }
190
191 rc = cifs_negotiate_protocol(0, ses);
192 if (rc == 0 && ses->need_reconnect)
193 rc = cifs_setup_session(0, ses, nls_codepage);
194
195
196 if (rc || !tcon->need_reconnect) {
197 mutex_unlock(&ses->session_mutex);
198 goto out;
199 }
200
201 cifs_mark_open_files_invalid(tcon);
202 rc = cifs_tree_connect(0, tcon, nls_codepage);
203 mutex_unlock(&ses->session_mutex);
204 cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
205
206 if (rc) {
207 pr_warn_once("reconnect tcon failed rc = %d\n", rc);
208 goto out;
209 }
210
211 atomic_inc(&tconInfoReconnectCount);
212
213
214 if (cap_unix(ses))
215 reset_cifs_unix_caps(0, tcon, NULL, NULL);
216
217
218
219
220
221
222
223
224out:
225
226
227
228
229 switch (smb_command) {
230 case SMB_COM_READ_ANDX:
231 case SMB_COM_WRITE_ANDX:
232 case SMB_COM_CLOSE:
233 case SMB_COM_FIND_CLOSE2:
234 case SMB_COM_LOCKING_ANDX:
235 rc = -EAGAIN;
236 }
237
238 unload_nls(nls_codepage);
239 return rc;
240}
241
242
243
244
245static int
246small_smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
247 void **request_buf)
248{
249 int rc;
250
251 rc = cifs_reconnect_tcon(tcon, smb_command);
252 if (rc)
253 return rc;
254
255 *request_buf = cifs_small_buf_get();
256 if (*request_buf == NULL) {
257
258 return -ENOMEM;
259 }
260
261 header_assemble((struct smb_hdr *) *request_buf, smb_command,
262 tcon, wct);
263
264 if (tcon != NULL)
265 cifs_stats_inc(&tcon->num_smbs_sent);
266
267 return 0;
268}
269
270int
271small_smb_init_no_tc(const int smb_command, const int wct,
272 struct cifs_ses *ses, void **request_buf)
273{
274 int rc;
275 struct smb_hdr *buffer;
276
277 rc = small_smb_init(smb_command, wct, NULL, request_buf);
278 if (rc)
279 return rc;
280
281 buffer = (struct smb_hdr *)*request_buf;
282 buffer->Mid = get_next_mid(ses->server);
283 if (ses->capabilities & CAP_UNICODE)
284 buffer->Flags2 |= SMBFLG2_UNICODE;
285 if (ses->capabilities & CAP_STATUS32)
286 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
287
288
289
290
291
292
293 return rc;
294}
295
296
297static int
298__smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
299 void **request_buf, void **response_buf)
300{
301 *request_buf = cifs_buf_get();
302 if (*request_buf == NULL) {
303
304 return -ENOMEM;
305 }
306
307
308
309
310 if (response_buf)
311 *response_buf = *request_buf;
312
313 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
314 wct);
315
316 if (tcon != NULL)
317 cifs_stats_inc(&tcon->num_smbs_sent);
318
319 return 0;
320}
321
322
323static int
324smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
325 void **request_buf, void **response_buf)
326{
327 int rc;
328
329 rc = cifs_reconnect_tcon(tcon, smb_command);
330 if (rc)
331 return rc;
332
333 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
334}
335
336static int
337smb_init_no_reconnect(int smb_command, int wct, struct cifs_tcon *tcon,
338 void **request_buf, void **response_buf)
339{
340 if (tcon->ses->need_reconnect || tcon->need_reconnect)
341 return -EHOSTDOWN;
342
343 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
344}
345
346static int validate_t2(struct smb_t2_rsp *pSMB)
347{
348 unsigned int total_size;
349
350
351 if (pSMB->hdr.WordCount < 10)
352 goto vt2_err;
353
354
355 if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
356 get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
357 goto vt2_err;
358
359 total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
360 if (total_size >= 512)
361 goto vt2_err;
362
363
364
365
366 total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
367 if (total_size > get_bcc(&pSMB->hdr) ||
368 total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
369 goto vt2_err;
370
371 return 0;
372vt2_err:
373 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
374 sizeof(struct smb_t2_rsp) + 16);
375 return -EINVAL;
376}
377
378static int
379decode_ext_sec_blob(struct cifs_ses *ses, NEGOTIATE_RSP *pSMBr)
380{
381 int rc = 0;
382 u16 count;
383 char *guid = pSMBr->u.extended_response.GUID;
384 struct TCP_Server_Info *server = ses->server;
385
386 count = get_bcc(&pSMBr->hdr);
387 if (count < SMB1_CLIENT_GUID_SIZE)
388 return -EIO;
389
390 spin_lock(&cifs_tcp_ses_lock);
391 if (server->srv_count > 1) {
392 spin_unlock(&cifs_tcp_ses_lock);
393 if (memcmp(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE) != 0) {
394 cifs_dbg(FYI, "server UID changed\n");
395 memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
396 }
397 } else {
398 spin_unlock(&cifs_tcp_ses_lock);
399 memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
400 }
401
402 if (count == SMB1_CLIENT_GUID_SIZE) {
403 server->sec_ntlmssp = true;
404 } else {
405 count -= SMB1_CLIENT_GUID_SIZE;
406 rc = decode_negTokenInit(
407 pSMBr->u.extended_response.SecurityBlob, count, server);
408 if (rc != 1)
409 return -EINVAL;
410 }
411
412 return 0;
413}
414
415int
416cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required)
417{
418 bool srv_sign_required = server->sec_mode & server->vals->signing_required;
419 bool srv_sign_enabled = server->sec_mode & server->vals->signing_enabled;
420 bool mnt_sign_enabled = global_secflags & CIFSSEC_MAY_SIGN;
421
422
423
424
425
426 if (!mnt_sign_required)
427 mnt_sign_required = ((global_secflags & CIFSSEC_MUST_SIGN) ==
428 CIFSSEC_MUST_SIGN);
429
430
431
432
433
434 mnt_sign_enabled = mnt_sign_required ? mnt_sign_required :
435 (global_secflags & CIFSSEC_MAY_SIGN);
436
437
438 if (srv_sign_required) {
439 if (!mnt_sign_enabled) {
440 cifs_dbg(VFS, "Server requires signing, but it's disabled in SecurityFlags!\n");
441 return -ENOTSUPP;
442 }
443 server->sign = true;
444 }
445
446
447 if (mnt_sign_required) {
448 if (!srv_sign_enabled) {
449 cifs_dbg(VFS, "Server does not support signing!\n");
450 return -ENOTSUPP;
451 }
452 server->sign = true;
453 }
454
455 if (cifs_rdma_enabled(server) && server->sign)
456 cifs_dbg(VFS, "Signing is enabled, and RDMA read/write will be disabled\n");
457
458 return 0;
459}
460
461static bool
462should_set_ext_sec_flag(enum securityEnum sectype)
463{
464 switch (sectype) {
465 case RawNTLMSSP:
466 case Kerberos:
467 return true;
468 case Unspecified:
469 if (global_secflags &
470 (CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP))
471 return true;
472 fallthrough;
473 default:
474 return false;
475 }
476}
477
478int
479CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
480{
481 NEGOTIATE_REQ *pSMB;
482 NEGOTIATE_RSP *pSMBr;
483 int rc = 0;
484 int bytes_returned;
485 int i;
486 struct TCP_Server_Info *server = ses->server;
487 u16 count;
488
489 if (!server) {
490 WARN(1, "%s: server is NULL!\n", __func__);
491 return -EIO;
492 }
493
494 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL ,
495 (void **) &pSMB, (void **) &pSMBr);
496 if (rc)
497 return rc;
498
499 pSMB->hdr.Mid = get_next_mid(server);
500 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
501
502 if (should_set_ext_sec_flag(ses->sectype)) {
503 cifs_dbg(FYI, "Requesting extended security\n");
504 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
505 }
506
507 count = 0;
508
509
510
511
512 for (i = 0; i < CIFS_NUM_PROT; i++) {
513 size_t len = strlen(protocols[i].name) + 1;
514
515 memcpy(pSMB->DialectsArray+count, protocols[i].name, len);
516 count += len;
517 }
518 inc_rfc1001_len(pSMB, count);
519 pSMB->ByteCount = cpu_to_le16(count);
520
521 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
522 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
523 if (rc != 0)
524 goto neg_err_exit;
525
526 server->dialect = le16_to_cpu(pSMBr->DialectIndex);
527 cifs_dbg(FYI, "Dialect: %d\n", server->dialect);
528
529 if ((pSMBr->hdr.WordCount <= 13) || (server->dialect == BAD_PROT)) {
530
531
532
533 rc = -EOPNOTSUPP;
534 goto neg_err_exit;
535 } else if (pSMBr->hdr.WordCount != 17) {
536
537 rc = -EOPNOTSUPP;
538 goto neg_err_exit;
539 }
540
541
542 server->sec_mode = pSMBr->SecurityMode;
543 if ((server->sec_mode & SECMODE_USER) == 0)
544 cifs_dbg(FYI, "share mode security\n");
545
546
547
548 server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
549 cifs_max_pending);
550 set_credits(server, server->maxReq);
551
552 server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
553
554 server->max_read = server->maxBuf;
555 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
556 cifs_dbg(NOISY, "Max buf = %d\n", ses->server->maxBuf);
557 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
558 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
559 server->timeAdj *= 60;
560
561 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
562 server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
563 memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
564 CIFS_CRYPTO_KEY_SIZE);
565 } else if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
566 server->capabilities & CAP_EXTENDED_SECURITY) {
567 server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
568 rc = decode_ext_sec_blob(ses, pSMBr);
569 } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
570 rc = -EIO;
571 } else {
572 server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
573 server->capabilities &= ~CAP_EXTENDED_SECURITY;
574 }
575
576 if (!rc)
577 rc = cifs_enable_signing(server, ses->sign);
578neg_err_exit:
579 cifs_buf_release(pSMB);
580
581 cifs_dbg(FYI, "negprot rc %d\n", rc);
582 return rc;
583}
584
585int
586CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon)
587{
588 struct smb_hdr *smb_buffer;
589 int rc = 0;
590
591 cifs_dbg(FYI, "In tree disconnect\n");
592
593
594 if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
595 return -EIO;
596
597
598
599
600
601
602
603 if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
604 return 0;
605
606 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
607 (void **)&smb_buffer);
608 if (rc)
609 return rc;
610
611 rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, 0);
612 cifs_small_buf_release(smb_buffer);
613 if (rc)
614 cifs_dbg(FYI, "Tree disconnect failed %d\n", rc);
615
616
617
618 if (rc == -EAGAIN)
619 rc = 0;
620
621 return rc;
622}
623
624
625
626
627
628
629
630
631static void
632cifs_echo_callback(struct mid_q_entry *mid)
633{
634 struct TCP_Server_Info *server = mid->callback_data;
635 struct cifs_credits credits = { .value = 1, .instance = 0 };
636
637 DeleteMidQEntry(mid);
638 add_credits(server, &credits, CIFS_ECHO_OP);
639}
640
641int
642CIFSSMBEcho(struct TCP_Server_Info *server)
643{
644 ECHO_REQ *smb;
645 int rc = 0;
646 struct kvec iov[2];
647 struct smb_rqst rqst = { .rq_iov = iov,
648 .rq_nvec = 2 };
649
650 cifs_dbg(FYI, "In echo request\n");
651
652 rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
653 if (rc)
654 return rc;
655
656 if (server->capabilities & CAP_UNICODE)
657 smb->hdr.Flags2 |= SMBFLG2_UNICODE;
658
659
660 smb->hdr.Tid = 0xffff;
661 smb->hdr.WordCount = 1;
662 put_unaligned_le16(1, &smb->EchoCount);
663 put_bcc(1, &smb->hdr);
664 smb->Data[0] = 'a';
665 inc_rfc1001_len(smb, 3);
666
667 iov[0].iov_len = 4;
668 iov[0].iov_base = smb;
669 iov[1].iov_len = get_rfc1002_length(smb);
670 iov[1].iov_base = (char *)smb + 4;
671
672 rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback, NULL,
673 server, CIFS_NON_BLOCKING | CIFS_ECHO_OP, NULL);
674 if (rc)
675 cifs_dbg(FYI, "Echo request failed: %d\n", rc);
676
677 cifs_small_buf_release(smb);
678
679 return rc;
680}
681
682int
683CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses)
684{
685 LOGOFF_ANDX_REQ *pSMB;
686 int rc = 0;
687
688 cifs_dbg(FYI, "In SMBLogoff for session disconnect\n");
689
690
691
692
693
694
695 if (!ses || !ses->server)
696 return -EIO;
697
698 mutex_lock(&ses->session_mutex);
699 if (ses->need_reconnect)
700 goto session_already_dead;
701
702 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
703 if (rc) {
704 mutex_unlock(&ses->session_mutex);
705 return rc;
706 }
707
708 pSMB->hdr.Mid = get_next_mid(ses->server);
709
710 if (ses->server->sign)
711 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
712
713 pSMB->hdr.Uid = ses->Suid;
714
715 pSMB->AndXCommand = 0xFF;
716 rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, 0);
717 cifs_small_buf_release(pSMB);
718session_already_dead:
719 mutex_unlock(&ses->session_mutex);
720
721
722
723
724 if (rc == -EAGAIN)
725 rc = 0;
726 return rc;
727}
728
729int
730CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
731 const char *fileName, __u16 type,
732 const struct nls_table *nls_codepage, int remap)
733{
734 TRANSACTION2_SPI_REQ *pSMB = NULL;
735 TRANSACTION2_SPI_RSP *pSMBr = NULL;
736 struct unlink_psx_rq *pRqD;
737 int name_len;
738 int rc = 0;
739 int bytes_returned = 0;
740 __u16 params, param_offset, offset, byte_count;
741
742 cifs_dbg(FYI, "In POSIX delete\n");
743PsxDelete:
744 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
745 (void **) &pSMBr);
746 if (rc)
747 return rc;
748
749 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
750 name_len =
751 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
752 PATH_MAX, nls_codepage, remap);
753 name_len++;
754 name_len *= 2;
755 } else {
756 name_len = copy_path_name(pSMB->FileName, fileName);
757 }
758
759 params = 6 + name_len;
760 pSMB->MaxParameterCount = cpu_to_le16(2);
761 pSMB->MaxDataCount = 0;
762 pSMB->MaxSetupCount = 0;
763 pSMB->Reserved = 0;
764 pSMB->Flags = 0;
765 pSMB->Timeout = 0;
766 pSMB->Reserved2 = 0;
767 param_offset = offsetof(struct smb_com_transaction2_spi_req,
768 InformationLevel) - 4;
769 offset = param_offset + params;
770
771
772
773
774
775 pRqD = (struct unlink_psx_rq *)((char *)(pSMB) + offset + 4);
776 pRqD->type = cpu_to_le16(type);
777 pSMB->ParameterOffset = cpu_to_le16(param_offset);
778 pSMB->DataOffset = cpu_to_le16(offset);
779 pSMB->SetupCount = 1;
780 pSMB->Reserved3 = 0;
781 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
782 byte_count = 3 + params + sizeof(struct unlink_psx_rq);
783
784 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
785 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
786 pSMB->ParameterCount = cpu_to_le16(params);
787 pSMB->TotalParameterCount = pSMB->ParameterCount;
788 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
789 pSMB->Reserved4 = 0;
790 inc_rfc1001_len(pSMB, byte_count);
791 pSMB->ByteCount = cpu_to_le16(byte_count);
792 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
793 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
794 if (rc)
795 cifs_dbg(FYI, "Posix delete returned %d\n", rc);
796 cifs_buf_release(pSMB);
797
798 cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
799
800 if (rc == -EAGAIN)
801 goto PsxDelete;
802
803 return rc;
804}
805
806int
807CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
808 struct cifs_sb_info *cifs_sb)
809{
810 DELETE_FILE_REQ *pSMB = NULL;
811 DELETE_FILE_RSP *pSMBr = NULL;
812 int rc = 0;
813 int bytes_returned;
814 int name_len;
815 int remap = cifs_remap(cifs_sb);
816
817DelFileRetry:
818 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
819 (void **) &pSMBr);
820 if (rc)
821 return rc;
822
823 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
824 name_len = cifsConvertToUTF16((__le16 *) pSMB->fileName, name,
825 PATH_MAX, cifs_sb->local_nls,
826 remap);
827 name_len++;
828 name_len *= 2;
829 } else {
830 name_len = copy_path_name(pSMB->fileName, name);
831 }
832 pSMB->SearchAttributes =
833 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
834 pSMB->BufferFormat = 0x04;
835 inc_rfc1001_len(pSMB, name_len + 1);
836 pSMB->ByteCount = cpu_to_le16(name_len + 1);
837 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
838 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
839 cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
840 if (rc)
841 cifs_dbg(FYI, "Error in RMFile = %d\n", rc);
842
843 cifs_buf_release(pSMB);
844 if (rc == -EAGAIN)
845 goto DelFileRetry;
846
847 return rc;
848}
849
850int
851CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
852 struct cifs_sb_info *cifs_sb)
853{
854 DELETE_DIRECTORY_REQ *pSMB = NULL;
855 DELETE_DIRECTORY_RSP *pSMBr = NULL;
856 int rc = 0;
857 int bytes_returned;
858 int name_len;
859 int remap = cifs_remap(cifs_sb);
860
861 cifs_dbg(FYI, "In CIFSSMBRmDir\n");
862RmDirRetry:
863 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
864 (void **) &pSMBr);
865 if (rc)
866 return rc;
867
868 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
869 name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
870 PATH_MAX, cifs_sb->local_nls,
871 remap);
872 name_len++;
873 name_len *= 2;
874 } else {
875 name_len = copy_path_name(pSMB->DirName, name);
876 }
877
878 pSMB->BufferFormat = 0x04;
879 inc_rfc1001_len(pSMB, name_len + 1);
880 pSMB->ByteCount = cpu_to_le16(name_len + 1);
881 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
882 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
883 cifs_stats_inc(&tcon->stats.cifs_stats.num_rmdirs);
884 if (rc)
885 cifs_dbg(FYI, "Error in RMDir = %d\n", rc);
886
887 cifs_buf_release(pSMB);
888 if (rc == -EAGAIN)
889 goto RmDirRetry;
890 return rc;
891}
892
893int
894CIFSSMBMkDir(const unsigned int xid, struct inode *inode, umode_t mode,
895 struct cifs_tcon *tcon, const char *name,
896 struct cifs_sb_info *cifs_sb)
897{
898 int rc = 0;
899 CREATE_DIRECTORY_REQ *pSMB = NULL;
900 CREATE_DIRECTORY_RSP *pSMBr = NULL;
901 int bytes_returned;
902 int name_len;
903 int remap = cifs_remap(cifs_sb);
904
905 cifs_dbg(FYI, "In CIFSSMBMkDir\n");
906MkDirRetry:
907 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
908 (void **) &pSMBr);
909 if (rc)
910 return rc;
911
912 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
913 name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
914 PATH_MAX, cifs_sb->local_nls,
915 remap);
916 name_len++;
917 name_len *= 2;
918 } else {
919 name_len = copy_path_name(pSMB->DirName, name);
920 }
921
922 pSMB->BufferFormat = 0x04;
923 inc_rfc1001_len(pSMB, name_len + 1);
924 pSMB->ByteCount = cpu_to_le16(name_len + 1);
925 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
926 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
927 cifs_stats_inc(&tcon->stats.cifs_stats.num_mkdirs);
928 if (rc)
929 cifs_dbg(FYI, "Error in Mkdir = %d\n", rc);
930
931 cifs_buf_release(pSMB);
932 if (rc == -EAGAIN)
933 goto MkDirRetry;
934 return rc;
935}
936
937int
938CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon,
939 __u32 posix_flags, __u64 mode, __u16 *netfid,
940 FILE_UNIX_BASIC_INFO *pRetData, __u32 *pOplock,
941 const char *name, const struct nls_table *nls_codepage,
942 int remap)
943{
944 TRANSACTION2_SPI_REQ *pSMB = NULL;
945 TRANSACTION2_SPI_RSP *pSMBr = NULL;
946 int name_len;
947 int rc = 0;
948 int bytes_returned = 0;
949 __u16 params, param_offset, offset, byte_count, count;
950 OPEN_PSX_REQ *pdata;
951 OPEN_PSX_RSP *psx_rsp;
952
953 cifs_dbg(FYI, "In POSIX Create\n");
954PsxCreat:
955 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
956 (void **) &pSMBr);
957 if (rc)
958 return rc;
959
960 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
961 name_len =
962 cifsConvertToUTF16((__le16 *) pSMB->FileName, name,
963 PATH_MAX, nls_codepage, remap);
964 name_len++;
965 name_len *= 2;
966 } else {
967 name_len = copy_path_name(pSMB->FileName, name);
968 }
969
970 params = 6 + name_len;
971 count = sizeof(OPEN_PSX_REQ);
972 pSMB->MaxParameterCount = cpu_to_le16(2);
973 pSMB->MaxDataCount = cpu_to_le16(1000);
974 pSMB->MaxSetupCount = 0;
975 pSMB->Reserved = 0;
976 pSMB->Flags = 0;
977 pSMB->Timeout = 0;
978 pSMB->Reserved2 = 0;
979 param_offset = offsetof(struct smb_com_transaction2_spi_req,
980 InformationLevel) - 4;
981 offset = param_offset + params;
982
983 pdata = (OPEN_PSX_REQ *)((char *)(pSMB) + offset + 4);
984 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
985 pdata->Permissions = cpu_to_le64(mode);
986 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
987 pdata->OpenFlags = cpu_to_le32(*pOplock);
988 pSMB->ParameterOffset = cpu_to_le16(param_offset);
989 pSMB->DataOffset = cpu_to_le16(offset);
990 pSMB->SetupCount = 1;
991 pSMB->Reserved3 = 0;
992 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
993 byte_count = 3 + params + count;
994
995 pSMB->DataCount = cpu_to_le16(count);
996 pSMB->ParameterCount = cpu_to_le16(params);
997 pSMB->TotalDataCount = pSMB->DataCount;
998 pSMB->TotalParameterCount = pSMB->ParameterCount;
999 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1000 pSMB->Reserved4 = 0;
1001 inc_rfc1001_len(pSMB, byte_count);
1002 pSMB->ByteCount = cpu_to_le16(byte_count);
1003 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1004 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1005 if (rc) {
1006 cifs_dbg(FYI, "Posix create returned %d\n", rc);
1007 goto psx_create_err;
1008 }
1009
1010 cifs_dbg(FYI, "copying inode info\n");
1011 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1012
1013 if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
1014 rc = -EIO;
1015 goto psx_create_err;
1016 }
1017
1018
1019 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1020 + le16_to_cpu(pSMBr->t2.DataOffset));
1021
1022 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1023 if (netfid)
1024 *netfid = psx_rsp->Fid;
1025
1026
1027 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1028 *pOplock |= CIFS_CREATE_ACTION;
1029
1030 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1031 pRetData->Type = cpu_to_le32(-1);
1032 cifs_dbg(NOISY, "unknown type\n");
1033 } else {
1034 if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
1035 + sizeof(FILE_UNIX_BASIC_INFO)) {
1036 cifs_dbg(VFS, "Open response data too small\n");
1037 pRetData->Type = cpu_to_le32(-1);
1038 goto psx_create_err;
1039 }
1040 memcpy((char *) pRetData,
1041 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1042 sizeof(FILE_UNIX_BASIC_INFO));
1043 }
1044
1045psx_create_err:
1046 cifs_buf_release(pSMB);
1047
1048 if (posix_flags & SMB_O_DIRECTORY)
1049 cifs_stats_inc(&tcon->stats.cifs_stats.num_posixmkdirs);
1050 else
1051 cifs_stats_inc(&tcon->stats.cifs_stats.num_posixopens);
1052
1053 if (rc == -EAGAIN)
1054 goto PsxCreat;
1055
1056 return rc;
1057}
1058
1059static __u16 convert_disposition(int disposition)
1060{
1061 __u16 ofun = 0;
1062
1063 switch (disposition) {
1064 case FILE_SUPERSEDE:
1065 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1066 break;
1067 case FILE_OPEN:
1068 ofun = SMBOPEN_OAPPEND;
1069 break;
1070 case FILE_CREATE:
1071 ofun = SMBOPEN_OCREATE;
1072 break;
1073 case FILE_OPEN_IF:
1074 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1075 break;
1076 case FILE_OVERWRITE:
1077 ofun = SMBOPEN_OTRUNC;
1078 break;
1079 case FILE_OVERWRITE_IF:
1080 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1081 break;
1082 default:
1083 cifs_dbg(FYI, "unknown disposition %d\n", disposition);
1084 ofun = SMBOPEN_OAPPEND;
1085 }
1086 return ofun;
1087}
1088
1089static int
1090access_flags_to_smbopen_mode(const int access_flags)
1091{
1092 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1093
1094 if (masked_flags == GENERIC_READ)
1095 return SMBOPEN_READ;
1096 else if (masked_flags == GENERIC_WRITE)
1097 return SMBOPEN_WRITE;
1098
1099
1100 return SMBOPEN_READWRITE;
1101}
1102
1103int
1104SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
1105 const char *fileName, const int openDisposition,
1106 const int access_flags, const int create_options, __u16 *netfid,
1107 int *pOplock, FILE_ALL_INFO *pfile_info,
1108 const struct nls_table *nls_codepage, int remap)
1109{
1110 int rc;
1111 OPENX_REQ *pSMB = NULL;
1112 OPENX_RSP *pSMBr = NULL;
1113 int bytes_returned;
1114 int name_len;
1115 __u16 count;
1116
1117OldOpenRetry:
1118 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1119 (void **) &pSMBr);
1120 if (rc)
1121 return rc;
1122
1123 pSMB->AndXCommand = 0xFF;
1124
1125 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1126 count = 1;
1127 name_len =
1128 cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1129 fileName, PATH_MAX, nls_codepage, remap);
1130 name_len++;
1131 name_len *= 2;
1132 } else {
1133 count = 0;
1134 name_len = copy_path_name(pSMB->fileName, fileName);
1135 }
1136 if (*pOplock & REQ_OPLOCK)
1137 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1138 else if (*pOplock & REQ_BATCHOPLOCK)
1139 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1140
1141 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1142 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1143 pSMB->Mode |= cpu_to_le16(0x40);
1144
1145
1146
1147
1148 if (create_options & CREATE_OPTION_SPECIAL)
1149 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1150 else
1151 pSMB->FileAttributes = cpu_to_le16(0);
1152
1153 if (create_options & CREATE_OPTION_READONLY)
1154 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1155
1156
1157
1158
1159
1160
1161 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1162 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1163 count += name_len;
1164 inc_rfc1001_len(pSMB, count);
1165
1166 pSMB->ByteCount = cpu_to_le16(count);
1167 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1168 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1169 cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1170 if (rc) {
1171 cifs_dbg(FYI, "Error in Open = %d\n", rc);
1172 } else {
1173
1174
1175
1176
1177 *netfid = pSMBr->Fid;
1178
1179
1180
1181
1182
1183
1184
1185 if (pfile_info) {
1186 pfile_info->CreationTime = 0;
1187 pfile_info->LastAccessTime = 0;
1188 pfile_info->LastWriteTime = 0;
1189 pfile_info->ChangeTime = 0;
1190 pfile_info->Attributes =
1191 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1192
1193 pfile_info->AllocationSize =
1194 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1195 pfile_info->EndOfFile = pfile_info->AllocationSize;
1196 pfile_info->NumberOfLinks = cpu_to_le32(1);
1197 pfile_info->DeletePending = 0;
1198 }
1199 }
1200
1201 cifs_buf_release(pSMB);
1202 if (rc == -EAGAIN)
1203 goto OldOpenRetry;
1204 return rc;
1205}
1206
1207int
1208CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,
1209 FILE_ALL_INFO *buf)
1210{
1211 int rc;
1212 OPEN_REQ *req = NULL;
1213 OPEN_RSP *rsp = NULL;
1214 int bytes_returned;
1215 int name_len;
1216 __u16 count;
1217 struct cifs_sb_info *cifs_sb = oparms->cifs_sb;
1218 struct cifs_tcon *tcon = oparms->tcon;
1219 int remap = cifs_remap(cifs_sb);
1220 const struct nls_table *nls = cifs_sb->local_nls;
1221 int create_options = oparms->create_options;
1222 int desired_access = oparms->desired_access;
1223 int disposition = oparms->disposition;
1224 const char *path = oparms->path;
1225
1226openRetry:
1227 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **)&req,
1228 (void **)&rsp);
1229 if (rc)
1230 return rc;
1231
1232
1233 req->AndXCommand = 0xFF;
1234
1235 if (req->hdr.Flags2 & SMBFLG2_UNICODE) {
1236
1237 count = 1;
1238 name_len = cifsConvertToUTF16((__le16 *)(req->fileName + 1),
1239 path, PATH_MAX, nls, remap);
1240
1241 name_len++;
1242 name_len *= 2;
1243 req->NameLength = cpu_to_le16(name_len);
1244 } else {
1245
1246
1247 count = 0;
1248 name_len = copy_path_name(req->fileName, path);
1249 req->NameLength = cpu_to_le16(name_len);
1250 }
1251
1252 if (*oplock & REQ_OPLOCK)
1253 req->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1254 else if (*oplock & REQ_BATCHOPLOCK)
1255 req->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1256
1257 req->DesiredAccess = cpu_to_le32(desired_access);
1258 req->AllocationSize = 0;
1259
1260
1261
1262
1263
1264 if (create_options & CREATE_OPTION_SPECIAL)
1265 req->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1266 else
1267 req->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1268
1269
1270
1271
1272
1273 if (tcon->ses->capabilities & CAP_UNIX)
1274 req->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1275
1276 if (create_options & CREATE_OPTION_READONLY)
1277 req->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1278
1279 req->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1280 req->CreateDisposition = cpu_to_le32(disposition);
1281 req->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1282
1283
1284 req->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1285 req->SecurityFlags = SECURITY_CONTEXT_TRACKING|SECURITY_EFFECTIVE_ONLY;
1286
1287 count += name_len;
1288 inc_rfc1001_len(req, count);
1289
1290 req->ByteCount = cpu_to_le16(count);
1291 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)req,
1292 (struct smb_hdr *)rsp, &bytes_returned, 0);
1293 cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1294 if (rc) {
1295 cifs_dbg(FYI, "Error in Open = %d\n", rc);
1296 cifs_buf_release(req);
1297 if (rc == -EAGAIN)
1298 goto openRetry;
1299 return rc;
1300 }
1301
1302
1303 *oplock = rsp->OplockLevel;
1304
1305 oparms->fid->netfid = rsp->Fid;
1306 oparms->fid->access = desired_access;
1307
1308
1309
1310 if (cpu_to_le32(FILE_CREATE) == rsp->CreateAction)
1311 *oplock |= CIFS_CREATE_ACTION;
1312
1313 if (buf) {
1314
1315 memcpy((char *)buf, (char *)&rsp->CreationTime, 36);
1316
1317 buf->AllocationSize = rsp->AllocationSize;
1318 buf->EndOfFile = rsp->EndOfFile;
1319 buf->NumberOfLinks = cpu_to_le32(1);
1320 buf->DeletePending = 0;
1321 }
1322
1323 cifs_buf_release(req);
1324 return rc;
1325}
1326
1327
1328
1329
1330
1331int
1332cifs_discard_remaining_data(struct TCP_Server_Info *server)
1333{
1334 unsigned int rfclen = server->pdu_size;
1335 int remaining = rfclen + server->vals->header_preamble_size -
1336 server->total_read;
1337
1338 while (remaining > 0) {
1339 int length;
1340
1341 length = cifs_discard_from_socket(server,
1342 min_t(size_t, remaining,
1343 CIFSMaxBufSize + MAX_HEADER_SIZE(server)));
1344 if (length < 0)
1345 return length;
1346 server->total_read += length;
1347 remaining -= length;
1348 }
1349
1350 return 0;
1351}
1352
1353static int
1354__cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid,
1355 bool malformed)
1356{
1357 int length;
1358
1359 length = cifs_discard_remaining_data(server);
1360 dequeue_mid(mid, malformed);
1361 mid->resp_buf = server->smallbuf;
1362 server->smallbuf = NULL;
1363 return length;
1364}
1365
1366static int
1367cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1368{
1369 struct cifs_readdata *rdata = mid->callback_data;
1370
1371 return __cifs_readv_discard(server, mid, rdata->result);
1372}
1373
1374int
1375cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1376{
1377 int length, len;
1378 unsigned int data_offset, data_len;
1379 struct cifs_readdata *rdata = mid->callback_data;
1380 char *buf = server->smallbuf;
1381 unsigned int buflen = server->pdu_size +
1382 server->vals->header_preamble_size;
1383 bool use_rdma_mr = false;
1384
1385 cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%u\n",
1386 __func__, mid->mid, rdata->offset, rdata->bytes);
1387
1388
1389
1390
1391
1392
1393 len = min_t(unsigned int, buflen, server->vals->read_rsp_size) -
1394 HEADER_SIZE(server) + 1;
1395
1396 length = cifs_read_from_socket(server,
1397 buf + HEADER_SIZE(server) - 1, len);
1398 if (length < 0)
1399 return length;
1400 server->total_read += length;
1401
1402 if (server->ops->is_session_expired &&
1403 server->ops->is_session_expired(buf)) {
1404 cifs_reconnect(server);
1405 return -1;
1406 }
1407
1408 if (server->ops->is_status_pending &&
1409 server->ops->is_status_pending(buf, server)) {
1410 cifs_discard_remaining_data(server);
1411 return -1;
1412 }
1413
1414
1415 rdata->iov[0].iov_base = buf;
1416 rdata->iov[0].iov_len = server->vals->header_preamble_size;
1417 rdata->iov[1].iov_base = buf + server->vals->header_preamble_size;
1418 rdata->iov[1].iov_len =
1419 server->total_read - server->vals->header_preamble_size;
1420 cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
1421 rdata->iov[0].iov_base, rdata->iov[0].iov_len);
1422 cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n",
1423 rdata->iov[1].iov_base, rdata->iov[1].iov_len);
1424
1425
1426 rdata->result = server->ops->map_error(buf, false);
1427 if (rdata->result != 0) {
1428 cifs_dbg(FYI, "%s: server returned error %d\n",
1429 __func__, rdata->result);
1430
1431 return __cifs_readv_discard(server, mid, false);
1432 }
1433
1434
1435 if (server->total_read < server->vals->read_rsp_size) {
1436 cifs_dbg(FYI, "%s: server returned short header. got=%u expected=%zu\n",
1437 __func__, server->total_read,
1438 server->vals->read_rsp_size);
1439 rdata->result = -EIO;
1440 return cifs_readv_discard(server, mid);
1441 }
1442
1443 data_offset = server->ops->read_data_offset(buf) +
1444 server->vals->header_preamble_size;
1445 if (data_offset < server->total_read) {
1446
1447
1448
1449
1450
1451 cifs_dbg(FYI, "%s: data offset (%u) inside read response header\n",
1452 __func__, data_offset);
1453 data_offset = server->total_read;
1454 } else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) {
1455
1456 cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n",
1457 __func__, data_offset);
1458 rdata->result = -EIO;
1459 return cifs_readv_discard(server, mid);
1460 }
1461
1462 cifs_dbg(FYI, "%s: total_read=%u data_offset=%u\n",
1463 __func__, server->total_read, data_offset);
1464
1465 len = data_offset - server->total_read;
1466 if (len > 0) {
1467
1468 length = cifs_read_from_socket(server,
1469 buf + server->total_read, len);
1470 if (length < 0)
1471 return length;
1472 server->total_read += length;
1473 }
1474
1475
1476#ifdef CONFIG_CIFS_SMB_DIRECT
1477 use_rdma_mr = rdata->mr;
1478#endif
1479 data_len = server->ops->read_data_length(buf, use_rdma_mr);
1480 if (!use_rdma_mr && (data_offset + data_len > buflen)) {
1481
1482 rdata->result = -EIO;
1483 return cifs_readv_discard(server, mid);
1484 }
1485
1486 length = rdata->read_into_pages(server, rdata, data_len);
1487 if (length < 0)
1488 return length;
1489
1490 server->total_read += length;
1491
1492 cifs_dbg(FYI, "total_read=%u buflen=%u remaining=%u\n",
1493 server->total_read, buflen, data_len);
1494
1495
1496 if (server->total_read < buflen)
1497 return cifs_readv_discard(server, mid);
1498
1499 dequeue_mid(mid, false);
1500 mid->resp_buf = server->smallbuf;
1501 server->smallbuf = NULL;
1502 return length;
1503}
1504
1505static void
1506cifs_readv_callback(struct mid_q_entry *mid)
1507{
1508 struct cifs_readdata *rdata = mid->callback_data;
1509 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1510 struct TCP_Server_Info *server = tcon->ses->server;
1511 struct smb_rqst rqst = { .rq_iov = rdata->iov,
1512 .rq_nvec = 2,
1513 .rq_pages = rdata->pages,
1514 .rq_offset = rdata->page_offset,
1515 .rq_npages = rdata->nr_pages,
1516 .rq_pagesz = rdata->pagesz,
1517 .rq_tailsz = rdata->tailsz };
1518 struct cifs_credits credits = { .value = 1, .instance = 0 };
1519
1520 cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%u\n",
1521 __func__, mid->mid, mid->mid_state, rdata->result,
1522 rdata->bytes);
1523
1524 switch (mid->mid_state) {
1525 case MID_RESPONSE_RECEIVED:
1526
1527 if (server->sign) {
1528 int rc = 0;
1529
1530 rc = cifs_verify_signature(&rqst, server,
1531 mid->sequence_number);
1532 if (rc)
1533 cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
1534 rc);
1535 }
1536
1537 task_io_account_read(rdata->got_bytes);
1538 cifs_stats_bytes_read(tcon, rdata->got_bytes);
1539 break;
1540 case MID_REQUEST_SUBMITTED:
1541 case MID_RETRY_NEEDED:
1542 rdata->result = -EAGAIN;
1543 if (server->sign && rdata->got_bytes)
1544
1545 rdata->got_bytes = 0;
1546
1547 task_io_account_read(rdata->got_bytes);
1548 cifs_stats_bytes_read(tcon, rdata->got_bytes);
1549 break;
1550 default:
1551 rdata->result = -EIO;
1552 }
1553
1554 queue_work(cifsiod_wq, &rdata->work);
1555 DeleteMidQEntry(mid);
1556 add_credits(server, &credits, 0);
1557}
1558
1559
1560int
1561cifs_async_readv(struct cifs_readdata *rdata)
1562{
1563 int rc;
1564 READ_REQ *smb = NULL;
1565 int wct;
1566 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1567 struct smb_rqst rqst = { .rq_iov = rdata->iov,
1568 .rq_nvec = 2 };
1569
1570 cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n",
1571 __func__, rdata->offset, rdata->bytes);
1572
1573 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1574 wct = 12;
1575 else {
1576 wct = 10;
1577 if ((rdata->offset >> 32) > 0) {
1578
1579 return -EIO;
1580 }
1581 }
1582
1583 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
1584 if (rc)
1585 return rc;
1586
1587 smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid);
1588 smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
1589
1590 smb->AndXCommand = 0xFF;
1591 smb->Fid = rdata->cfile->fid.netfid;
1592 smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
1593 if (wct == 12)
1594 smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
1595 smb->Remaining = 0;
1596 smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
1597 smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
1598 if (wct == 12)
1599 smb->ByteCount = 0;
1600 else {
1601
1602 struct smb_com_readx_req *smbr =
1603 (struct smb_com_readx_req *)smb;
1604 smbr->ByteCount = 0;
1605 }
1606
1607
1608 rdata->iov[0].iov_base = smb;
1609 rdata->iov[0].iov_len = 4;
1610 rdata->iov[1].iov_base = (char *)smb + 4;
1611 rdata->iov[1].iov_len = get_rfc1002_length(smb);
1612
1613 kref_get(&rdata->refcount);
1614 rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive,
1615 cifs_readv_callback, NULL, rdata, 0, NULL);
1616
1617 if (rc == 0)
1618 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1619 else
1620 kref_put(&rdata->refcount, cifs_readdata_release);
1621
1622 cifs_small_buf_release(smb);
1623 return rc;
1624}
1625
1626int
1627CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
1628 unsigned int *nbytes, char **buf, int *pbuf_type)
1629{
1630 int rc = -EACCES;
1631 READ_REQ *pSMB = NULL;
1632 READ_RSP *pSMBr = NULL;
1633 char *pReadData = NULL;
1634 int wct;
1635 int resp_buf_type = 0;
1636 struct kvec iov[1];
1637 struct kvec rsp_iov;
1638 __u32 pid = io_parms->pid;
1639 __u16 netfid = io_parms->netfid;
1640 __u64 offset = io_parms->offset;
1641 struct cifs_tcon *tcon = io_parms->tcon;
1642 unsigned int count = io_parms->length;
1643
1644 cifs_dbg(FYI, "Reading %d bytes on fid %d\n", count, netfid);
1645 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1646 wct = 12;
1647 else {
1648 wct = 10;
1649 if ((offset >> 32) > 0) {
1650
1651 return -EIO;
1652 }
1653 }
1654
1655 *nbytes = 0;
1656 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1657 if (rc)
1658 return rc;
1659
1660 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1661 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1662
1663
1664 if (tcon->ses->server == NULL)
1665 return -ECONNABORTED;
1666
1667 pSMB->AndXCommand = 0xFF;
1668 pSMB->Fid = netfid;
1669 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1670 if (wct == 12)
1671 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1672
1673 pSMB->Remaining = 0;
1674 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1675 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1676 if (wct == 12)
1677 pSMB->ByteCount = 0;
1678 else {
1679
1680 struct smb_com_readx_req *pSMBW =
1681 (struct smb_com_readx_req *)pSMB;
1682 pSMBW->ByteCount = 0;
1683 }
1684
1685 iov[0].iov_base = (char *)pSMB;
1686 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1687 rc = SendReceive2(xid, tcon->ses, iov, 1, &resp_buf_type,
1688 CIFS_LOG_ERROR, &rsp_iov);
1689 cifs_small_buf_release(pSMB);
1690 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1691 pSMBr = (READ_RSP *)rsp_iov.iov_base;
1692 if (rc) {
1693 cifs_dbg(VFS, "Send error in read = %d\n", rc);
1694 } else {
1695 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1696 data_length = data_length << 16;
1697 data_length += le16_to_cpu(pSMBr->DataLength);
1698 *nbytes = data_length;
1699
1700
1701 if ((data_length > CIFSMaxBufSize)
1702 || (data_length > count)) {
1703 cifs_dbg(FYI, "bad length %d for count %d\n",
1704 data_length, count);
1705 rc = -EIO;
1706 *nbytes = 0;
1707 } else {
1708 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1709 le16_to_cpu(pSMBr->DataOffset);
1710
1711
1712
1713
1714 if (*buf)
1715 memcpy(*buf, pReadData, data_length);
1716 }
1717 }
1718
1719 if (*buf) {
1720 free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
1721 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1722
1723 *buf = rsp_iov.iov_base;
1724 if (resp_buf_type == CIFS_SMALL_BUFFER)
1725 *pbuf_type = CIFS_SMALL_BUFFER;
1726 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1727 *pbuf_type = CIFS_LARGE_BUFFER;
1728 }
1729
1730
1731
1732 return rc;
1733}
1734
1735
1736int
1737CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
1738 unsigned int *nbytes, const char *buf)
1739{
1740 int rc = -EACCES;
1741 WRITE_REQ *pSMB = NULL;
1742 WRITE_RSP *pSMBr = NULL;
1743 int bytes_returned, wct;
1744 __u32 bytes_sent;
1745 __u16 byte_count;
1746 __u32 pid = io_parms->pid;
1747 __u16 netfid = io_parms->netfid;
1748 __u64 offset = io_parms->offset;
1749 struct cifs_tcon *tcon = io_parms->tcon;
1750 unsigned int count = io_parms->length;
1751
1752 *nbytes = 0;
1753
1754
1755 if (tcon->ses == NULL)
1756 return -ECONNABORTED;
1757
1758 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1759 wct = 14;
1760 else {
1761 wct = 12;
1762 if ((offset >> 32) > 0) {
1763
1764 return -EIO;
1765 }
1766 }
1767
1768 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1769 (void **) &pSMBr);
1770 if (rc)
1771 return rc;
1772
1773 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1774 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1775
1776
1777 if (tcon->ses->server == NULL)
1778 return -ECONNABORTED;
1779
1780 pSMB->AndXCommand = 0xFF;
1781 pSMB->Fid = netfid;
1782 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1783 if (wct == 14)
1784 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1785
1786 pSMB->Reserved = 0xFFFFFFFF;
1787 pSMB->WriteMode = 0;
1788 pSMB->Remaining = 0;
1789
1790
1791
1792
1793
1794 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1795 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1796 } else {
1797 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1798 & ~0xFF;
1799 }
1800
1801 if (bytes_sent > count)
1802 bytes_sent = count;
1803 pSMB->DataOffset =
1804 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1805 if (buf)
1806 memcpy(pSMB->Data, buf, bytes_sent);
1807 else if (count != 0) {
1808
1809 cifs_buf_release(pSMB);
1810 return -EINVAL;
1811 }
1812 if (wct == 14)
1813 byte_count = bytes_sent + 1;
1814 else
1815 byte_count = bytes_sent + 5;
1816
1817 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1818 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1819 inc_rfc1001_len(pSMB, byte_count);
1820
1821 if (wct == 14)
1822 pSMB->ByteCount = cpu_to_le16(byte_count);
1823 else {
1824
1825 struct smb_com_writex_req *pSMBW =
1826 (struct smb_com_writex_req *)pSMB;
1827 pSMBW->ByteCount = cpu_to_le16(byte_count);
1828 }
1829
1830 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1831 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1832 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1833 if (rc) {
1834 cifs_dbg(FYI, "Send error in write = %d\n", rc);
1835 } else {
1836 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1837 *nbytes = (*nbytes) << 16;
1838 *nbytes += le16_to_cpu(pSMBr->Count);
1839
1840
1841
1842
1843
1844
1845 if (*nbytes > count)
1846 *nbytes &= 0xFFFF;
1847 }
1848
1849 cifs_buf_release(pSMB);
1850
1851
1852
1853
1854 return rc;
1855}
1856
1857void
1858cifs_writedata_release(struct kref *refcount)
1859{
1860 struct cifs_writedata *wdata = container_of(refcount,
1861 struct cifs_writedata, refcount);
1862#ifdef CONFIG_CIFS_SMB_DIRECT
1863 if (wdata->mr) {
1864 smbd_deregister_mr(wdata->mr);
1865 wdata->mr = NULL;
1866 }
1867#endif
1868
1869 if (wdata->cfile)
1870 cifsFileInfo_put(wdata->cfile);
1871
1872 kvfree(wdata->pages);
1873 kfree(wdata);
1874}
1875
1876
1877
1878
1879
1880static void
1881cifs_writev_requeue(struct cifs_writedata *wdata)
1882{
1883 int i, rc = 0;
1884 struct inode *inode = d_inode(wdata->cfile->dentry);
1885 struct TCP_Server_Info *server;
1886 unsigned int rest_len;
1887
1888 server = tlink_tcon(wdata->cfile->tlink)->ses->server;
1889 i = 0;
1890 rest_len = wdata->bytes;
1891 do {
1892 struct cifs_writedata *wdata2;
1893 unsigned int j, nr_pages, wsize, tailsz, cur_len;
1894
1895 wsize = server->ops->wp_retry_size(inode);
1896 if (wsize < rest_len) {
1897 nr_pages = wsize / PAGE_SIZE;
1898 if (!nr_pages) {
1899 rc = -ENOTSUPP;
1900 break;
1901 }
1902 cur_len = nr_pages * PAGE_SIZE;
1903 tailsz = PAGE_SIZE;
1904 } else {
1905 nr_pages = DIV_ROUND_UP(rest_len, PAGE_SIZE);
1906 cur_len = rest_len;
1907 tailsz = rest_len - (nr_pages - 1) * PAGE_SIZE;
1908 }
1909
1910 wdata2 = cifs_writedata_alloc(nr_pages, cifs_writev_complete);
1911 if (!wdata2) {
1912 rc = -ENOMEM;
1913 break;
1914 }
1915
1916 for (j = 0; j < nr_pages; j++) {
1917 wdata2->pages[j] = wdata->pages[i + j];
1918 lock_page(wdata2->pages[j]);
1919 clear_page_dirty_for_io(wdata2->pages[j]);
1920 }
1921
1922 wdata2->sync_mode = wdata->sync_mode;
1923 wdata2->nr_pages = nr_pages;
1924 wdata2->offset = page_offset(wdata2->pages[0]);
1925 wdata2->pagesz = PAGE_SIZE;
1926 wdata2->tailsz = tailsz;
1927 wdata2->bytes = cur_len;
1928
1929 rc = cifs_get_writable_file(CIFS_I(inode), FIND_WR_ANY,
1930 &wdata2->cfile);
1931 if (!wdata2->cfile) {
1932 cifs_dbg(VFS, "No writable handle to retry writepages rc=%d\n",
1933 rc);
1934 if (!is_retryable_error(rc))
1935 rc = -EBADF;
1936 } else {
1937 wdata2->pid = wdata2->cfile->pid;
1938 rc = server->ops->async_writev(wdata2,
1939 cifs_writedata_release);
1940 }
1941
1942 for (j = 0; j < nr_pages; j++) {
1943 unlock_page(wdata2->pages[j]);
1944 if (rc != 0 && !is_retryable_error(rc)) {
1945 SetPageError(wdata2->pages[j]);
1946 end_page_writeback(wdata2->pages[j]);
1947 put_page(wdata2->pages[j]);
1948 }
1949 }
1950
1951 kref_put(&wdata2->refcount, cifs_writedata_release);
1952 if (rc) {
1953 if (is_retryable_error(rc))
1954 continue;
1955 i += nr_pages;
1956 break;
1957 }
1958
1959 rest_len -= cur_len;
1960 i += nr_pages;
1961 } while (i < wdata->nr_pages);
1962
1963
1964 for (; i < wdata->nr_pages; i++) {
1965 SetPageError(wdata->pages[i]);
1966 end_page_writeback(wdata->pages[i]);
1967 put_page(wdata->pages[i]);
1968 }
1969
1970 if (rc != 0 && !is_retryable_error(rc))
1971 mapping_set_error(inode->i_mapping, rc);
1972 kref_put(&wdata->refcount, cifs_writedata_release);
1973}
1974
1975void
1976cifs_writev_complete(struct work_struct *work)
1977{
1978 struct cifs_writedata *wdata = container_of(work,
1979 struct cifs_writedata, work);
1980 struct inode *inode = d_inode(wdata->cfile->dentry);
1981 int i = 0;
1982
1983 if (wdata->result == 0) {
1984 spin_lock(&inode->i_lock);
1985 cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
1986 spin_unlock(&inode->i_lock);
1987 cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
1988 wdata->bytes);
1989 } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
1990 return cifs_writev_requeue(wdata);
1991
1992 for (i = 0; i < wdata->nr_pages; i++) {
1993 struct page *page = wdata->pages[i];
1994 if (wdata->result == -EAGAIN)
1995 __set_page_dirty_nobuffers(page);
1996 else if (wdata->result < 0)
1997 SetPageError(page);
1998 end_page_writeback(page);
1999 cifs_readpage_to_fscache(inode, page);
2000 put_page(page);
2001 }
2002 if (wdata->result != -EAGAIN)
2003 mapping_set_error(inode->i_mapping, wdata->result);
2004 kref_put(&wdata->refcount, cifs_writedata_release);
2005}
2006
2007struct cifs_writedata *
2008cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
2009{
2010 struct page **pages =
2011 kcalloc(nr_pages, sizeof(struct page *), GFP_NOFS);
2012 if (pages)
2013 return cifs_writedata_direct_alloc(pages, complete);
2014
2015 return NULL;
2016}
2017
2018struct cifs_writedata *
2019cifs_writedata_direct_alloc(struct page **pages, work_func_t complete)
2020{
2021 struct cifs_writedata *wdata;
2022
2023 wdata = kzalloc(sizeof(*wdata), GFP_NOFS);
2024 if (wdata != NULL) {
2025 wdata->pages = pages;
2026 kref_init(&wdata->refcount);
2027 INIT_LIST_HEAD(&wdata->list);
2028 init_completion(&wdata->done);
2029 INIT_WORK(&wdata->work, complete);
2030 }
2031 return wdata;
2032}
2033
2034
2035
2036
2037
2038static void
2039cifs_writev_callback(struct mid_q_entry *mid)
2040{
2041 struct cifs_writedata *wdata = mid->callback_data;
2042 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2043 unsigned int written;
2044 WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
2045 struct cifs_credits credits = { .value = 1, .instance = 0 };
2046
2047 switch (mid->mid_state) {
2048 case MID_RESPONSE_RECEIVED:
2049 wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
2050 if (wdata->result != 0)
2051 break;
2052
2053 written = le16_to_cpu(smb->CountHigh);
2054 written <<= 16;
2055 written += le16_to_cpu(smb->Count);
2056
2057
2058
2059
2060
2061
2062 if (written > wdata->bytes)
2063 written &= 0xFFFF;
2064
2065 if (written < wdata->bytes)
2066 wdata->result = -ENOSPC;
2067 else
2068 wdata->bytes = written;
2069 break;
2070 case MID_REQUEST_SUBMITTED:
2071 case MID_RETRY_NEEDED:
2072 wdata->result = -EAGAIN;
2073 break;
2074 default:
2075 wdata->result = -EIO;
2076 break;
2077 }
2078
2079 queue_work(cifsiod_wq, &wdata->work);
2080 DeleteMidQEntry(mid);
2081 add_credits(tcon->ses->server, &credits, 0);
2082}
2083
2084
2085int
2086cifs_async_writev(struct cifs_writedata *wdata,
2087 void (*release)(struct kref *kref))
2088{
2089 int rc = -EACCES;
2090 WRITE_REQ *smb = NULL;
2091 int wct;
2092 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2093 struct kvec iov[2];
2094 struct smb_rqst rqst = { };
2095
2096 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2097 wct = 14;
2098 } else {
2099 wct = 12;
2100 if (wdata->offset >> 32 > 0) {
2101
2102 return -EIO;
2103 }
2104 }
2105
2106 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
2107 if (rc)
2108 goto async_writev_out;
2109
2110 smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
2111 smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
2112
2113 smb->AndXCommand = 0xFF;
2114 smb->Fid = wdata->cfile->fid.netfid;
2115 smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
2116 if (wct == 14)
2117 smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
2118 smb->Reserved = 0xFFFFFFFF;
2119 smb->WriteMode = 0;
2120 smb->Remaining = 0;
2121
2122 smb->DataOffset =
2123 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2124
2125
2126 iov[0].iov_len = 4;
2127 iov[0].iov_base = smb;
2128 iov[1].iov_len = get_rfc1002_length(smb) + 1;
2129 iov[1].iov_base = (char *)smb + 4;
2130
2131 rqst.rq_iov = iov;
2132 rqst.rq_nvec = 2;
2133 rqst.rq_pages = wdata->pages;
2134 rqst.rq_offset = wdata->page_offset;
2135 rqst.rq_npages = wdata->nr_pages;
2136 rqst.rq_pagesz = wdata->pagesz;
2137 rqst.rq_tailsz = wdata->tailsz;
2138
2139 cifs_dbg(FYI, "async write at %llu %u bytes\n",
2140 wdata->offset, wdata->bytes);
2141
2142 smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
2143 smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
2144
2145 if (wct == 14) {
2146 inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
2147 put_bcc(wdata->bytes + 1, &smb->hdr);
2148 } else {
2149
2150 struct smb_com_writex_req *smbw =
2151 (struct smb_com_writex_req *)smb;
2152 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
2153 put_bcc(wdata->bytes + 5, &smbw->hdr);
2154 iov[1].iov_len += 4;
2155 }
2156
2157 kref_get(&wdata->refcount);
2158 rc = cifs_call_async(tcon->ses->server, &rqst, NULL,
2159 cifs_writev_callback, NULL, wdata, 0, NULL);
2160
2161 if (rc == 0)
2162 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2163 else
2164 kref_put(&wdata->refcount, release);
2165
2166async_writev_out:
2167 cifs_small_buf_release(smb);
2168 return rc;
2169}
2170
2171int
2172CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
2173 unsigned int *nbytes, struct kvec *iov, int n_vec)
2174{
2175 int rc;
2176 WRITE_REQ *pSMB = NULL;
2177 int wct;
2178 int smb_hdr_len;
2179 int resp_buf_type = 0;
2180 __u32 pid = io_parms->pid;
2181 __u16 netfid = io_parms->netfid;
2182 __u64 offset = io_parms->offset;
2183 struct cifs_tcon *tcon = io_parms->tcon;
2184 unsigned int count = io_parms->length;
2185 struct kvec rsp_iov;
2186
2187 *nbytes = 0;
2188
2189 cifs_dbg(FYI, "write2 at %lld %d bytes\n", (long long)offset, count);
2190
2191 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2192 wct = 14;
2193 } else {
2194 wct = 12;
2195 if ((offset >> 32) > 0) {
2196
2197 return -EIO;
2198 }
2199 }
2200 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
2201 if (rc)
2202 return rc;
2203
2204 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
2205 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
2206
2207
2208 if (tcon->ses->server == NULL)
2209 return -ECONNABORTED;
2210
2211 pSMB->AndXCommand = 0xFF;
2212 pSMB->Fid = netfid;
2213 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
2214 if (wct == 14)
2215 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
2216 pSMB->Reserved = 0xFFFFFFFF;
2217 pSMB->WriteMode = 0;
2218 pSMB->Remaining = 0;
2219
2220 pSMB->DataOffset =
2221 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2222
2223 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
2224 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
2225
2226 smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
2227 if (wct == 14)
2228 inc_rfc1001_len(pSMB, count + 1);
2229 else
2230 inc_rfc1001_len(pSMB, count + 5);
2231 if (wct == 14)
2232 pSMB->ByteCount = cpu_to_le16(count + 1);
2233 else {
2234 struct smb_com_writex_req *pSMBW =
2235 (struct smb_com_writex_req *)pSMB;
2236 pSMBW->ByteCount = cpu_to_le16(count + 5);
2237 }
2238 iov[0].iov_base = pSMB;
2239 if (wct == 14)
2240 iov[0].iov_len = smb_hdr_len + 4;
2241 else
2242 iov[0].iov_len = smb_hdr_len + 8;
2243
2244 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, 0,
2245 &rsp_iov);
2246 cifs_small_buf_release(pSMB);
2247 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2248 if (rc) {
2249 cifs_dbg(FYI, "Send error Write2 = %d\n", rc);
2250 } else if (resp_buf_type == 0) {
2251
2252 rc = -EIO;
2253 } else {
2254 WRITE_RSP *pSMBr = (WRITE_RSP *)rsp_iov.iov_base;
2255 *nbytes = le16_to_cpu(pSMBr->CountHigh);
2256 *nbytes = (*nbytes) << 16;
2257 *nbytes += le16_to_cpu(pSMBr->Count);
2258
2259
2260
2261
2262
2263
2264 if (*nbytes > count)
2265 *nbytes &= 0xFFFF;
2266 }
2267
2268 free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
2269
2270
2271
2272
2273 return rc;
2274}
2275
2276int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
2277 const __u16 netfid, const __u8 lock_type, const __u32 num_unlock,
2278 const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
2279{
2280 int rc = 0;
2281 LOCK_REQ *pSMB = NULL;
2282 struct kvec iov[2];
2283 struct kvec rsp_iov;
2284 int resp_buf_type;
2285 __u16 count;
2286
2287 cifs_dbg(FYI, "cifs_lockv num lock %d num unlock %d\n",
2288 num_lock, num_unlock);
2289
2290 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2291 if (rc)
2292 return rc;
2293
2294 pSMB->Timeout = 0;
2295 pSMB->NumberOfLocks = cpu_to_le16(num_lock);
2296 pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
2297 pSMB->LockType = lock_type;
2298 pSMB->AndXCommand = 0xFF;
2299 pSMB->Fid = netfid;
2300
2301 count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2302 inc_rfc1001_len(pSMB, count);
2303 pSMB->ByteCount = cpu_to_le16(count);
2304
2305 iov[0].iov_base = (char *)pSMB;
2306 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
2307 (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2308 iov[1].iov_base = (char *)buf;
2309 iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2310
2311 cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2312 rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type,
2313 CIFS_NO_RSP_BUF, &rsp_iov);
2314 cifs_small_buf_release(pSMB);
2315 if (rc)
2316 cifs_dbg(FYI, "Send error in cifs_lockv = %d\n", rc);
2317
2318 return rc;
2319}
2320
2321int
2322CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
2323 const __u16 smb_file_id, const __u32 netpid, const __u64 len,
2324 const __u64 offset, const __u32 numUnlock,
2325 const __u32 numLock, const __u8 lockType,
2326 const bool waitFlag, const __u8 oplock_level)
2327{
2328 int rc = 0;
2329 LOCK_REQ *pSMB = NULL;
2330
2331 int bytes_returned;
2332 int flags = 0;
2333 __u16 count;
2334
2335 cifs_dbg(FYI, "CIFSSMBLock timeout %d numLock %d\n",
2336 (int)waitFlag, numLock);
2337 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2338
2339 if (rc)
2340 return rc;
2341
2342 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
2343
2344 flags = CIFS_NO_SRV_RSP | CIFS_NON_BLOCKING | CIFS_OBREAK_OP;
2345 pSMB->Timeout = 0;
2346 } else if (waitFlag) {
2347 flags = CIFS_BLOCKING_OP;
2348 pSMB->Timeout = cpu_to_le32(-1);
2349 } else {
2350 pSMB->Timeout = 0;
2351 }
2352
2353 pSMB->NumberOfLocks = cpu_to_le16(numLock);
2354 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
2355 pSMB->LockType = lockType;
2356 pSMB->OplockLevel = oplock_level;
2357 pSMB->AndXCommand = 0xFF;
2358 pSMB->Fid = smb_file_id;
2359
2360 if ((numLock != 0) || (numUnlock != 0)) {
2361 pSMB->Locks[0].Pid = cpu_to_le16(netpid);
2362
2363 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
2364 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
2365 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
2366 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
2367 count = sizeof(LOCKING_ANDX_RANGE);
2368 } else {
2369
2370 count = 0;
2371 }
2372 inc_rfc1001_len(pSMB, count);
2373 pSMB->ByteCount = cpu_to_le16(count);
2374
2375 if (waitFlag)
2376 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2377 (struct smb_hdr *) pSMB, &bytes_returned);
2378 else
2379 rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags);
2380 cifs_small_buf_release(pSMB);
2381 cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2382 if (rc)
2383 cifs_dbg(FYI, "Send error in Lock = %d\n", rc);
2384
2385
2386
2387 return rc;
2388}
2389
2390int
2391CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
2392 const __u16 smb_file_id, const __u32 netpid,
2393 const loff_t start_offset, const __u64 len,
2394 struct file_lock *pLockData, const __u16 lock_type,
2395 const bool waitFlag)
2396{
2397 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2398 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2399 struct cifs_posix_lock *parm_data;
2400 int rc = 0;
2401 int timeout = 0;
2402 int bytes_returned = 0;
2403 int resp_buf_type = 0;
2404 __u16 params, param_offset, offset, byte_count, count;
2405 struct kvec iov[1];
2406 struct kvec rsp_iov;
2407
2408 cifs_dbg(FYI, "Posix Lock\n");
2409
2410 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2411
2412 if (rc)
2413 return rc;
2414
2415 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2416
2417 params = 6;
2418 pSMB->MaxSetupCount = 0;
2419 pSMB->Reserved = 0;
2420 pSMB->Flags = 0;
2421 pSMB->Reserved2 = 0;
2422 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2423 offset = param_offset + params;
2424
2425 count = sizeof(struct cifs_posix_lock);
2426 pSMB->MaxParameterCount = cpu_to_le16(2);
2427 pSMB->MaxDataCount = cpu_to_le16(1000);
2428 pSMB->SetupCount = 1;
2429 pSMB->Reserved3 = 0;
2430 if (pLockData)
2431 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2432 else
2433 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2434 byte_count = 3 + params + count;
2435 pSMB->DataCount = cpu_to_le16(count);
2436 pSMB->ParameterCount = cpu_to_le16(params);
2437 pSMB->TotalDataCount = pSMB->DataCount;
2438 pSMB->TotalParameterCount = pSMB->ParameterCount;
2439 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2440
2441 parm_data = (struct cifs_posix_lock *)
2442 (((char *)pSMB) + offset + 4);
2443
2444 parm_data->lock_type = cpu_to_le16(lock_type);
2445 if (waitFlag) {
2446 timeout = CIFS_BLOCKING_OP;
2447 parm_data->lock_flags = cpu_to_le16(1);
2448 pSMB->Timeout = cpu_to_le32(-1);
2449 } else
2450 pSMB->Timeout = 0;
2451
2452 parm_data->pid = cpu_to_le32(netpid);
2453 parm_data->start = cpu_to_le64(start_offset);
2454 parm_data->length = cpu_to_le64(len);
2455
2456 pSMB->DataOffset = cpu_to_le16(offset);
2457 pSMB->Fid = smb_file_id;
2458 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2459 pSMB->Reserved4 = 0;
2460 inc_rfc1001_len(pSMB, byte_count);
2461 pSMB->ByteCount = cpu_to_le16(byte_count);
2462 if (waitFlag) {
2463 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2464 (struct smb_hdr *) pSMBr, &bytes_returned);
2465 } else {
2466 iov[0].iov_base = (char *)pSMB;
2467 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2468 rc = SendReceive2(xid, tcon->ses, iov, 1 ,
2469 &resp_buf_type, timeout, &rsp_iov);
2470 pSMBr = (struct smb_com_transaction2_sfi_rsp *)rsp_iov.iov_base;
2471 }
2472 cifs_small_buf_release(pSMB);
2473
2474 if (rc) {
2475 cifs_dbg(FYI, "Send error in Posix Lock = %d\n", rc);
2476 } else if (pLockData) {
2477
2478 __u16 data_offset;
2479 __u16 data_count;
2480 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2481
2482 if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2483 rc = -EIO;
2484 goto plk_err_exit;
2485 }
2486 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2487 data_count = le16_to_cpu(pSMBr->t2.DataCount);
2488 if (data_count < sizeof(struct cifs_posix_lock)) {
2489 rc = -EIO;
2490 goto plk_err_exit;
2491 }
2492 parm_data = (struct cifs_posix_lock *)
2493 ((char *)&pSMBr->hdr.Protocol + data_offset);
2494 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
2495 pLockData->fl_type = F_UNLCK;
2496 else {
2497 if (parm_data->lock_type ==
2498 cpu_to_le16(CIFS_RDLCK))
2499 pLockData->fl_type = F_RDLCK;
2500 else if (parm_data->lock_type ==
2501 cpu_to_le16(CIFS_WRLCK))
2502 pLockData->fl_type = F_WRLCK;
2503
2504 pLockData->fl_start = le64_to_cpu(parm_data->start);
2505 pLockData->fl_end = pLockData->fl_start +
2506 le64_to_cpu(parm_data->length) - 1;
2507 pLockData->fl_pid = -le32_to_cpu(parm_data->pid);
2508 }
2509 }
2510
2511plk_err_exit:
2512 free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
2513
2514
2515
2516
2517 return rc;
2518}
2519
2520
2521int
2522CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2523{
2524 int rc = 0;
2525 CLOSE_REQ *pSMB = NULL;
2526 cifs_dbg(FYI, "In CIFSSMBClose\n");
2527
2528
2529 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2530 if (rc == -EAGAIN)
2531 return 0;
2532 if (rc)
2533 return rc;
2534
2535 pSMB->FileID = (__u16) smb_file_id;
2536 pSMB->LastWriteTime = 0xFFFFFFFF;
2537 pSMB->ByteCount = 0;
2538 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2539 cifs_small_buf_release(pSMB);
2540 cifs_stats_inc(&tcon->stats.cifs_stats.num_closes);
2541 if (rc) {
2542 if (rc != -EINTR) {
2543
2544 cifs_dbg(VFS, "Send error in Close = %d\n", rc);
2545 }
2546 }
2547
2548
2549 if (rc == -EAGAIN)
2550 rc = 0;
2551
2552 return rc;
2553}
2554
2555int
2556CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2557{
2558 int rc = 0;
2559 FLUSH_REQ *pSMB = NULL;
2560 cifs_dbg(FYI, "In CIFSSMBFlush\n");
2561
2562 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2563 if (rc)
2564 return rc;
2565
2566 pSMB->FileID = (__u16) smb_file_id;
2567 pSMB->ByteCount = 0;
2568 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2569 cifs_small_buf_release(pSMB);
2570 cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);
2571 if (rc)
2572 cifs_dbg(VFS, "Send error in Flush = %d\n", rc);
2573
2574 return rc;
2575}
2576
2577int
2578CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
2579 const char *from_name, const char *to_name,
2580 struct cifs_sb_info *cifs_sb)
2581{
2582 int rc = 0;
2583 RENAME_REQ *pSMB = NULL;
2584 RENAME_RSP *pSMBr = NULL;
2585 int bytes_returned;
2586 int name_len, name_len2;
2587 __u16 count;
2588 int remap = cifs_remap(cifs_sb);
2589
2590 cifs_dbg(FYI, "In CIFSSMBRename\n");
2591renameRetry:
2592 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2593 (void **) &pSMBr);
2594 if (rc)
2595 return rc;
2596
2597 pSMB->BufferFormat = 0x04;
2598 pSMB->SearchAttributes =
2599 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2600 ATTR_DIRECTORY);
2601
2602 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2603 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2604 from_name, PATH_MAX,
2605 cifs_sb->local_nls, remap);
2606 name_len++;
2607 name_len *= 2;
2608 pSMB->OldFileName[name_len] = 0x04;
2609
2610 pSMB->OldFileName[name_len + 1] = 0x00;
2611 name_len2 =
2612 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2613 to_name, PATH_MAX, cifs_sb->local_nls,
2614 remap);
2615 name_len2 += 1 + 1 ;
2616 name_len2 *= 2;
2617 } else {
2618 name_len = copy_path_name(pSMB->OldFileName, from_name);
2619 name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
2620 pSMB->OldFileName[name_len] = 0x04;
2621 name_len2++;
2622 }
2623
2624 count = 1 + name_len + name_len2;
2625 inc_rfc1001_len(pSMB, count);
2626 pSMB->ByteCount = cpu_to_le16(count);
2627
2628 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2629 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2630 cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);
2631 if (rc)
2632 cifs_dbg(FYI, "Send error in rename = %d\n", rc);
2633
2634 cifs_buf_release(pSMB);
2635
2636 if (rc == -EAGAIN)
2637 goto renameRetry;
2638
2639 return rc;
2640}
2641
2642int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
2643 int netfid, const char *target_name,
2644 const struct nls_table *nls_codepage, int remap)
2645{
2646 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2647 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2648 struct set_file_rename *rename_info;
2649 char *data_offset;
2650 char dummy_string[30];
2651 int rc = 0;
2652 int bytes_returned = 0;
2653 int len_of_str;
2654 __u16 params, param_offset, offset, count, byte_count;
2655
2656 cifs_dbg(FYI, "Rename to File by handle\n");
2657 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2658 (void **) &pSMBr);
2659 if (rc)
2660 return rc;
2661
2662 params = 6;
2663 pSMB->MaxSetupCount = 0;
2664 pSMB->Reserved = 0;
2665 pSMB->Flags = 0;
2666 pSMB->Timeout = 0;
2667 pSMB->Reserved2 = 0;
2668 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2669 offset = param_offset + params;
2670
2671
2672 data_offset = (char *)(pSMB) + offset + 4;
2673 rename_info = (struct set_file_rename *) data_offset;
2674 pSMB->MaxParameterCount = cpu_to_le16(2);
2675 pSMB->MaxDataCount = cpu_to_le16(1000);
2676 pSMB->SetupCount = 1;
2677 pSMB->Reserved3 = 0;
2678 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2679 byte_count = 3 + params;
2680 pSMB->ParameterCount = cpu_to_le16(params);
2681 pSMB->TotalParameterCount = pSMB->ParameterCount;
2682 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2683 pSMB->DataOffset = cpu_to_le16(offset);
2684
2685 rename_info->overwrite = cpu_to_le32(1);
2686 rename_info->root_fid = 0;
2687
2688 if (target_name == NULL) {
2689 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2690 len_of_str =
2691 cifsConvertToUTF16((__le16 *)rename_info->target_name,
2692 dummy_string, 24, nls_codepage, remap);
2693 } else {
2694 len_of_str =
2695 cifsConvertToUTF16((__le16 *)rename_info->target_name,
2696 target_name, PATH_MAX, nls_codepage,
2697 remap);
2698 }
2699 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2700 count = 12 + (2 * len_of_str);
2701 byte_count += count;
2702 pSMB->DataCount = cpu_to_le16(count);
2703 pSMB->TotalDataCount = pSMB->DataCount;
2704 pSMB->Fid = netfid;
2705 pSMB->InformationLevel =
2706 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2707 pSMB->Reserved4 = 0;
2708 inc_rfc1001_len(pSMB, byte_count);
2709 pSMB->ByteCount = cpu_to_le16(byte_count);
2710 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2711 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2712 cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);
2713 if (rc)
2714 cifs_dbg(FYI, "Send error in Rename (by file handle) = %d\n",
2715 rc);
2716
2717 cifs_buf_release(pSMB);
2718
2719
2720
2721
2722 return rc;
2723}
2724
2725int
2726CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon,
2727 const char *fromName, const __u16 target_tid, const char *toName,
2728 const int flags, const struct nls_table *nls_codepage, int remap)
2729{
2730 int rc = 0;
2731 COPY_REQ *pSMB = NULL;
2732 COPY_RSP *pSMBr = NULL;
2733 int bytes_returned;
2734 int name_len, name_len2;
2735 __u16 count;
2736
2737 cifs_dbg(FYI, "In CIFSSMBCopy\n");
2738copyRetry:
2739 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2740 (void **) &pSMBr);
2741 if (rc)
2742 return rc;
2743
2744 pSMB->BufferFormat = 0x04;
2745 pSMB->Tid2 = target_tid;
2746
2747 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2748
2749 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2750 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2751 fromName, PATH_MAX, nls_codepage,
2752 remap);
2753 name_len++;
2754 name_len *= 2;
2755 pSMB->OldFileName[name_len] = 0x04;
2756
2757 pSMB->OldFileName[name_len + 1] = 0x00;
2758 name_len2 =
2759 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2760 toName, PATH_MAX, nls_codepage, remap);
2761 name_len2 += 1 + 1 ;
2762 name_len2 *= 2;
2763 } else {
2764 name_len = copy_path_name(pSMB->OldFileName, fromName);
2765 pSMB->OldFileName[name_len] = 0x04;
2766 name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, toName);
2767 name_len2++;
2768 }
2769
2770 count = 1 + name_len + name_len2;
2771 inc_rfc1001_len(pSMB, count);
2772 pSMB->ByteCount = cpu_to_le16(count);
2773
2774 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2775 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2776 if (rc) {
2777 cifs_dbg(FYI, "Send error in copy = %d with %d files copied\n",
2778 rc, le16_to_cpu(pSMBr->CopyCount));
2779 }
2780 cifs_buf_release(pSMB);
2781
2782 if (rc == -EAGAIN)
2783 goto copyRetry;
2784
2785 return rc;
2786}
2787
2788int
2789CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
2790 const char *fromName, const char *toName,
2791 const struct nls_table *nls_codepage, int remap)
2792{
2793 TRANSACTION2_SPI_REQ *pSMB = NULL;
2794 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2795 char *data_offset;
2796 int name_len;
2797 int name_len_target;
2798 int rc = 0;
2799 int bytes_returned = 0;
2800 __u16 params, param_offset, offset, byte_count;
2801
2802 cifs_dbg(FYI, "In Symlink Unix style\n");
2803createSymLinkRetry:
2804 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2805 (void **) &pSMBr);
2806 if (rc)
2807 return rc;
2808
2809 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2810 name_len =
2811 cifsConvertToUTF16((__le16 *) pSMB->FileName, fromName,
2812
2813 PATH_MAX, nls_codepage, remap);
2814 name_len++;
2815 name_len *= 2;
2816
2817 } else {
2818 name_len = copy_path_name(pSMB->FileName, fromName);
2819 }
2820 params = 6 + name_len;
2821 pSMB->MaxSetupCount = 0;
2822 pSMB->Reserved = 0;
2823 pSMB->Flags = 0;
2824 pSMB->Timeout = 0;
2825 pSMB->Reserved2 = 0;
2826 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2827 InformationLevel) - 4;
2828 offset = param_offset + params;
2829
2830
2831 data_offset = (char *)pSMB + offset + 4;
2832 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2833 name_len_target =
2834 cifsConvertToUTF16((__le16 *) data_offset, toName,
2835
2836 PATH_MAX, nls_codepage, remap);
2837 name_len_target++;
2838 name_len_target *= 2;
2839 } else {
2840 name_len_target = copy_path_name(data_offset, toName);
2841 }
2842
2843 pSMB->MaxParameterCount = cpu_to_le16(2);
2844
2845 pSMB->MaxDataCount = cpu_to_le16(1000);
2846 pSMB->SetupCount = 1;
2847 pSMB->Reserved3 = 0;
2848 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2849 byte_count = 3 + params + name_len_target;
2850 pSMB->DataCount = cpu_to_le16(name_len_target);
2851 pSMB->ParameterCount = cpu_to_le16(params);
2852 pSMB->TotalDataCount = pSMB->DataCount;
2853 pSMB->TotalParameterCount = pSMB->ParameterCount;
2854 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2855 pSMB->DataOffset = cpu_to_le16(offset);
2856 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2857 pSMB->Reserved4 = 0;
2858 inc_rfc1001_len(pSMB, byte_count);
2859 pSMB->ByteCount = cpu_to_le16(byte_count);
2860 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2861 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2862 cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);
2863 if (rc)
2864 cifs_dbg(FYI, "Send error in SetPathInfo create symlink = %d\n",
2865 rc);
2866
2867 cifs_buf_release(pSMB);
2868
2869 if (rc == -EAGAIN)
2870 goto createSymLinkRetry;
2871
2872 return rc;
2873}
2874
2875int
2876CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2877 const char *fromName, const char *toName,
2878 const struct nls_table *nls_codepage, int remap)
2879{
2880 TRANSACTION2_SPI_REQ *pSMB = NULL;
2881 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2882 char *data_offset;
2883 int name_len;
2884 int name_len_target;
2885 int rc = 0;
2886 int bytes_returned = 0;
2887 __u16 params, param_offset, offset, byte_count;
2888
2889 cifs_dbg(FYI, "In Create Hard link Unix style\n");
2890createHardLinkRetry:
2891 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2892 (void **) &pSMBr);
2893 if (rc)
2894 return rc;
2895
2896 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2897 name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
2898 PATH_MAX, nls_codepage, remap);
2899 name_len++;
2900 name_len *= 2;
2901
2902 } else {
2903 name_len = copy_path_name(pSMB->FileName, toName);
2904 }
2905 params = 6 + name_len;
2906 pSMB->MaxSetupCount = 0;
2907 pSMB->Reserved = 0;
2908 pSMB->Flags = 0;
2909 pSMB->Timeout = 0;
2910 pSMB->Reserved2 = 0;
2911 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2912 InformationLevel) - 4;
2913 offset = param_offset + params;
2914
2915
2916 data_offset = (char *)pSMB + offset + 4;
2917 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2918 name_len_target =
2919 cifsConvertToUTF16((__le16 *) data_offset, fromName,
2920 PATH_MAX, nls_codepage, remap);
2921 name_len_target++;
2922 name_len_target *= 2;
2923 } else {
2924 name_len_target = copy_path_name(data_offset, fromName);
2925 }
2926
2927 pSMB->MaxParameterCount = cpu_to_le16(2);
2928
2929 pSMB->MaxDataCount = cpu_to_le16(1000);
2930 pSMB->SetupCount = 1;
2931 pSMB->Reserved3 = 0;
2932 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2933 byte_count = 3 + params + name_len_target;
2934 pSMB->ParameterCount = cpu_to_le16(params);
2935 pSMB->TotalParameterCount = pSMB->ParameterCount;
2936 pSMB->DataCount = cpu_to_le16(name_len_target);
2937 pSMB->TotalDataCount = pSMB->DataCount;
2938 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2939 pSMB->DataOffset = cpu_to_le16(offset);
2940 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2941 pSMB->Reserved4 = 0;
2942 inc_rfc1001_len(pSMB, byte_count);
2943 pSMB->ByteCount = cpu_to_le16(byte_count);
2944 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2945 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2946 cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
2947 if (rc)
2948 cifs_dbg(FYI, "Send error in SetPathInfo (hard link) = %d\n",
2949 rc);
2950
2951 cifs_buf_release(pSMB);
2952 if (rc == -EAGAIN)
2953 goto createHardLinkRetry;
2954
2955 return rc;
2956}
2957
2958int
2959CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2960 const char *from_name, const char *to_name,
2961 struct cifs_sb_info *cifs_sb)
2962{
2963 int rc = 0;
2964 NT_RENAME_REQ *pSMB = NULL;
2965 RENAME_RSP *pSMBr = NULL;
2966 int bytes_returned;
2967 int name_len, name_len2;
2968 __u16 count;
2969 int remap = cifs_remap(cifs_sb);
2970
2971 cifs_dbg(FYI, "In CIFSCreateHardLink\n");
2972winCreateHardLinkRetry:
2973
2974 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2975 (void **) &pSMBr);
2976 if (rc)
2977 return rc;
2978
2979 pSMB->SearchAttributes =
2980 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2981 ATTR_DIRECTORY);
2982 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2983 pSMB->ClusterCount = 0;
2984
2985 pSMB->BufferFormat = 0x04;
2986
2987 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2988 name_len =
2989 cifsConvertToUTF16((__le16 *) pSMB->OldFileName, from_name,
2990 PATH_MAX, cifs_sb->local_nls, remap);
2991 name_len++;
2992 name_len *= 2;
2993
2994
2995 pSMB->OldFileName[name_len] = 0x04;
2996 pSMB->OldFileName[name_len + 1] = 0x00;
2997 name_len2 =
2998 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2999 to_name, PATH_MAX, cifs_sb->local_nls,
3000 remap);
3001 name_len2 += 1 + 1 ;
3002 name_len2 *= 2;
3003 } else {
3004 name_len = copy_path_name(pSMB->OldFileName, from_name);
3005 pSMB->OldFileName[name_len] = 0x04;
3006 name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
3007 name_len2++;
3008 }
3009
3010 count = 1 + name_len + name_len2;
3011 inc_rfc1001_len(pSMB, count);
3012 pSMB->ByteCount = cpu_to_le16(count);
3013
3014 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3015 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3016 cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
3017 if (rc)
3018 cifs_dbg(FYI, "Send error in hard link (NT rename) = %d\n", rc);
3019
3020 cifs_buf_release(pSMB);
3021 if (rc == -EAGAIN)
3022 goto winCreateHardLinkRetry;
3023
3024 return rc;
3025}
3026
3027int
3028CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
3029 const unsigned char *searchName, char **symlinkinfo,
3030 const struct nls_table *nls_codepage, int remap)
3031{
3032
3033 TRANSACTION2_QPI_REQ *pSMB = NULL;
3034 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3035 int rc = 0;
3036 int bytes_returned;
3037 int name_len;
3038 __u16 params, byte_count;
3039 char *data_start;
3040
3041 cifs_dbg(FYI, "In QPathSymLinkInfo (Unix) for path %s\n", searchName);
3042
3043querySymLinkRetry:
3044 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3045 (void **) &pSMBr);
3046 if (rc)
3047 return rc;
3048
3049 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3050 name_len =
3051 cifsConvertToUTF16((__le16 *) pSMB->FileName,
3052 searchName, PATH_MAX, nls_codepage,
3053 remap);
3054 name_len++;
3055 name_len *= 2;
3056 } else {
3057 name_len = copy_path_name(pSMB->FileName, searchName);
3058 }
3059
3060 params = 2 + 4 + name_len ;
3061 pSMB->TotalDataCount = 0;
3062 pSMB->MaxParameterCount = cpu_to_le16(2);
3063 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3064 pSMB->MaxSetupCount = 0;
3065 pSMB->Reserved = 0;
3066 pSMB->Flags = 0;
3067 pSMB->Timeout = 0;
3068 pSMB->Reserved2 = 0;
3069 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3070 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3071 pSMB->DataCount = 0;
3072 pSMB->DataOffset = 0;
3073 pSMB->SetupCount = 1;
3074 pSMB->Reserved3 = 0;
3075 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3076 byte_count = params + 1 ;
3077 pSMB->TotalParameterCount = cpu_to_le16(params);
3078 pSMB->ParameterCount = pSMB->TotalParameterCount;
3079 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
3080 pSMB->Reserved4 = 0;
3081 inc_rfc1001_len(pSMB, byte_count);
3082 pSMB->ByteCount = cpu_to_le16(byte_count);
3083
3084 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3085 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3086 if (rc) {
3087 cifs_dbg(FYI, "Send error in QuerySymLinkInfo = %d\n", rc);
3088 } else {
3089
3090
3091 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3092
3093 if (rc || get_bcc(&pSMBr->hdr) < 2)
3094 rc = -EIO;
3095 else {
3096 bool is_unicode;
3097 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3098
3099 data_start = ((char *) &pSMBr->hdr.Protocol) +
3100 le16_to_cpu(pSMBr->t2.DataOffset);
3101
3102 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3103 is_unicode = true;
3104 else
3105 is_unicode = false;
3106
3107
3108 *symlinkinfo = cifs_strndup_from_utf16(data_start,
3109 count, is_unicode, nls_codepage);
3110 if (!*symlinkinfo)
3111 rc = -ENOMEM;
3112 }
3113 }
3114 cifs_buf_release(pSMB);
3115 if (rc == -EAGAIN)
3116 goto querySymLinkRetry;
3117 return rc;
3118}
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130int
3131CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
3132 __u16 fid, char **symlinkinfo,
3133 const struct nls_table *nls_codepage)
3134{
3135 int rc = 0;
3136 int bytes_returned;
3137 struct smb_com_transaction_ioctl_req *pSMB;
3138 struct smb_com_transaction_ioctl_rsp *pSMBr;
3139 bool is_unicode;
3140 unsigned int sub_len;
3141 char *sub_start;
3142 struct reparse_symlink_data *reparse_buf;
3143 struct reparse_posix_data *posix_buf;
3144 __u32 data_offset, data_count;
3145 char *end_of_smb;
3146
3147 cifs_dbg(FYI, "In Windows reparse style QueryLink for fid %u\n", fid);
3148 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3149 (void **) &pSMBr);
3150 if (rc)
3151 return rc;
3152
3153 pSMB->TotalParameterCount = 0 ;
3154 pSMB->TotalDataCount = 0;
3155 pSMB->MaxParameterCount = cpu_to_le32(2);
3156
3157 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3158 pSMB->MaxSetupCount = 4;
3159 pSMB->Reserved = 0;
3160 pSMB->ParameterOffset = 0;
3161 pSMB->DataCount = 0;
3162 pSMB->DataOffset = 0;
3163 pSMB->SetupCount = 4;
3164 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3165 pSMB->ParameterCount = pSMB->TotalParameterCount;
3166 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
3167 pSMB->IsFsctl = 1;
3168 pSMB->IsRootFlag = 0;
3169 pSMB->Fid = fid;
3170 pSMB->ByteCount = 0;
3171
3172 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3173 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3174 if (rc) {
3175 cifs_dbg(FYI, "Send error in QueryReparseLinkInfo = %d\n", rc);
3176 goto qreparse_out;
3177 }
3178
3179 data_offset = le32_to_cpu(pSMBr->DataOffset);
3180 data_count = le32_to_cpu(pSMBr->DataCount);
3181 if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
3182
3183 rc = -EIO;
3184 goto qreparse_out;
3185 }
3186 if (!data_count || (data_count > 2048)) {
3187 rc = -EIO;
3188 cifs_dbg(FYI, "Invalid return data count on get reparse info ioctl\n");
3189 goto qreparse_out;
3190 }
3191 end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
3192 reparse_buf = (struct reparse_symlink_data *)
3193 ((char *)&pSMBr->hdr.Protocol + data_offset);
3194 if ((char *)reparse_buf >= end_of_smb) {
3195 rc = -EIO;
3196 goto qreparse_out;
3197 }
3198 if (reparse_buf->ReparseTag == cpu_to_le32(IO_REPARSE_TAG_NFS)) {
3199 cifs_dbg(FYI, "NFS style reparse tag\n");
3200 posix_buf = (struct reparse_posix_data *)reparse_buf;
3201
3202 if (posix_buf->InodeType != cpu_to_le64(NFS_SPECFILE_LNK)) {
3203 cifs_dbg(FYI, "unsupported file type 0x%llx\n",
3204 le64_to_cpu(posix_buf->InodeType));
3205 rc = -EOPNOTSUPP;
3206 goto qreparse_out;
3207 }
3208 is_unicode = true;
3209 sub_len = le16_to_cpu(reparse_buf->ReparseDataLength);
3210 if (posix_buf->PathBuffer + sub_len > end_of_smb) {
3211 cifs_dbg(FYI, "reparse buf beyond SMB\n");
3212 rc = -EIO;
3213 goto qreparse_out;
3214 }
3215 *symlinkinfo = cifs_strndup_from_utf16(posix_buf->PathBuffer,
3216 sub_len, is_unicode, nls_codepage);
3217 goto qreparse_out;
3218 } else if (reparse_buf->ReparseTag !=
3219 cpu_to_le32(IO_REPARSE_TAG_SYMLINK)) {
3220 rc = -EOPNOTSUPP;
3221 goto qreparse_out;
3222 }
3223
3224
3225 sub_start = le16_to_cpu(reparse_buf->SubstituteNameOffset) +
3226 reparse_buf->PathBuffer;
3227 sub_len = le16_to_cpu(reparse_buf->SubstituteNameLength);
3228 if (sub_start + sub_len > end_of_smb) {
3229 cifs_dbg(FYI, "reparse buf beyond SMB\n");
3230 rc = -EIO;
3231 goto qreparse_out;
3232 }
3233 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3234 is_unicode = true;
3235 else
3236 is_unicode = false;
3237
3238
3239 *symlinkinfo = cifs_strndup_from_utf16(sub_start, sub_len, is_unicode,
3240 nls_codepage);
3241 if (!*symlinkinfo)
3242 rc = -ENOMEM;
3243qreparse_out:
3244 cifs_buf_release(pSMB);
3245
3246
3247
3248
3249
3250 return rc;
3251}
3252
3253int
3254CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
3255 __u16 fid)
3256{
3257 int rc = 0;
3258 int bytes_returned;
3259 struct smb_com_transaction_compr_ioctl_req *pSMB;
3260 struct smb_com_transaction_ioctl_rsp *pSMBr;
3261
3262 cifs_dbg(FYI, "Set compression for %u\n", fid);
3263 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3264 (void **) &pSMBr);
3265 if (rc)
3266 return rc;
3267
3268 pSMB->compression_state = cpu_to_le16(COMPRESSION_FORMAT_DEFAULT);
3269
3270 pSMB->TotalParameterCount = 0;
3271 pSMB->TotalDataCount = cpu_to_le32(2);
3272 pSMB->MaxParameterCount = 0;
3273 pSMB->MaxDataCount = 0;
3274 pSMB->MaxSetupCount = 4;
3275 pSMB->Reserved = 0;
3276 pSMB->ParameterOffset = 0;
3277 pSMB->DataCount = cpu_to_le32(2);
3278 pSMB->DataOffset =
3279 cpu_to_le32(offsetof(struct smb_com_transaction_compr_ioctl_req,
3280 compression_state) - 4);
3281 pSMB->SetupCount = 4;
3282 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3283 pSMB->ParameterCount = 0;
3284 pSMB->FunctionCode = cpu_to_le32(FSCTL_SET_COMPRESSION);
3285 pSMB->IsFsctl = 1;
3286 pSMB->IsRootFlag = 0;
3287 pSMB->Fid = fid;
3288
3289 pSMB->ByteCount = cpu_to_le16(5);
3290 inc_rfc1001_len(pSMB, 5);
3291
3292 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3293 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3294 if (rc)
3295 cifs_dbg(FYI, "Send error in SetCompression = %d\n", rc);
3296
3297 cifs_buf_release(pSMB);
3298
3299
3300
3301
3302
3303 return rc;
3304}
3305
3306
3307#ifdef CONFIG_CIFS_POSIX
3308
3309
3310static void cifs_convert_ace(struct posix_acl_xattr_entry *ace,
3311 struct cifs_posix_ace *cifs_ace)
3312{
3313
3314 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
3315 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
3316 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
3317
3318
3319
3320
3321
3322 return;
3323}
3324
3325
3326static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
3327 const int acl_type, const int size_of_data_area)
3328{
3329 int size = 0;
3330 int i;
3331 __u16 count;
3332 struct cifs_posix_ace *pACE;
3333 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
3334 struct posix_acl_xattr_header *local_acl = (void *)trgt;
3335
3336 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
3337 return -EOPNOTSUPP;
3338
3339 if (acl_type == ACL_TYPE_ACCESS) {
3340 count = le16_to_cpu(cifs_acl->access_entry_count);
3341 pACE = &cifs_acl->ace_array[0];
3342 size = sizeof(struct cifs_posix_acl);
3343 size += sizeof(struct cifs_posix_ace) * count;
3344
3345 if (size_of_data_area < size) {
3346 cifs_dbg(FYI, "bad CIFS POSIX ACL size %d vs. %d\n",
3347 size_of_data_area, size);
3348 return -EINVAL;
3349 }
3350 } else if (acl_type == ACL_TYPE_DEFAULT) {
3351 count = le16_to_cpu(cifs_acl->access_entry_count);
3352 size = sizeof(struct cifs_posix_acl);
3353 size += sizeof(struct cifs_posix_ace) * count;
3354
3355 pACE = &cifs_acl->ace_array[count];
3356 count = le16_to_cpu(cifs_acl->default_entry_count);
3357 size += sizeof(struct cifs_posix_ace) * count;
3358
3359 if (size_of_data_area < size)
3360 return -EINVAL;
3361 } else {
3362
3363 return -EINVAL;
3364 }
3365
3366 size = posix_acl_xattr_size(count);
3367 if ((buflen == 0) || (local_acl == NULL)) {
3368
3369 } else if (size > buflen) {
3370 return -ERANGE;
3371 } else {
3372 struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
3373
3374 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
3375 for (i = 0; i < count ; i++) {
3376 cifs_convert_ace(&ace[i], pACE);
3377 pACE++;
3378 }
3379 }
3380 return size;
3381}
3382
3383static void convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
3384 const struct posix_acl_xattr_entry *local_ace)
3385{
3386 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
3387 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
3388
3389 if (local_ace->e_id == cpu_to_le32(-1)) {
3390
3391 cifs_ace->cifs_uid = cpu_to_le64(-1);
3392 } else
3393 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
3394
3395
3396
3397
3398}
3399
3400
3401static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
3402 const int buflen, const int acl_type)
3403{
3404 __u16 rc = 0;
3405 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
3406 struct posix_acl_xattr_header *local_acl = (void *)pACL;
3407 struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
3408 int count;
3409 int i;
3410
3411 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
3412 return 0;
3413
3414 count = posix_acl_xattr_count((size_t)buflen);
3415 cifs_dbg(FYI, "setting acl with %d entries from buf of length %d and version of %d\n",
3416 count, buflen, le32_to_cpu(local_acl->a_version));
3417 if (le32_to_cpu(local_acl->a_version) != 2) {
3418 cifs_dbg(FYI, "unknown POSIX ACL version %d\n",
3419 le32_to_cpu(local_acl->a_version));
3420 return 0;
3421 }
3422 cifs_acl->version = cpu_to_le16(1);
3423 if (acl_type == ACL_TYPE_ACCESS) {
3424 cifs_acl->access_entry_count = cpu_to_le16(count);
3425 cifs_acl->default_entry_count = cpu_to_le16(0xFFFF);
3426 } else if (acl_type == ACL_TYPE_DEFAULT) {
3427 cifs_acl->default_entry_count = cpu_to_le16(count);
3428 cifs_acl->access_entry_count = cpu_to_le16(0xFFFF);
3429 } else {
3430 cifs_dbg(FYI, "unknown ACL type %d\n", acl_type);
3431 return 0;
3432 }
3433 for (i = 0; i < count; i++)
3434 convert_ace_to_cifs_ace(&cifs_acl->ace_array[i], &ace[i]);
3435 if (rc == 0) {
3436 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3437 rc += sizeof(struct cifs_posix_acl);
3438
3439 }
3440 return rc;
3441}
3442
3443int
3444CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3445 const unsigned char *searchName,
3446 char *acl_inf, const int buflen, const int acl_type,
3447 const struct nls_table *nls_codepage, int remap)
3448{
3449
3450 TRANSACTION2_QPI_REQ *pSMB = NULL;
3451 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3452 int rc = 0;
3453 int bytes_returned;
3454 int name_len;
3455 __u16 params, byte_count;
3456
3457 cifs_dbg(FYI, "In GetPosixACL (Unix) for path %s\n", searchName);
3458
3459queryAclRetry:
3460 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3461 (void **) &pSMBr);
3462 if (rc)
3463 return rc;
3464
3465 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3466 name_len =
3467 cifsConvertToUTF16((__le16 *) pSMB->FileName,
3468 searchName, PATH_MAX, nls_codepage,
3469 remap);
3470 name_len++;
3471 name_len *= 2;
3472 pSMB->FileName[name_len] = 0;
3473 pSMB->FileName[name_len+1] = 0;
3474 } else {
3475 name_len = copy_path_name(pSMB->FileName, searchName);
3476 }
3477
3478 params = 2 + 4 + name_len ;
3479 pSMB->TotalDataCount = 0;
3480 pSMB->MaxParameterCount = cpu_to_le16(2);
3481
3482 pSMB->MaxDataCount = cpu_to_le16(4000);
3483 pSMB->MaxSetupCount = 0;
3484 pSMB->Reserved = 0;
3485 pSMB->Flags = 0;
3486 pSMB->Timeout = 0;
3487 pSMB->Reserved2 = 0;
3488 pSMB->ParameterOffset = cpu_to_le16(
3489 offsetof(struct smb_com_transaction2_qpi_req,
3490 InformationLevel) - 4);
3491 pSMB->DataCount = 0;
3492 pSMB->DataOffset = 0;
3493 pSMB->SetupCount = 1;
3494 pSMB->Reserved3 = 0;
3495 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3496 byte_count = params + 1 ;
3497 pSMB->TotalParameterCount = cpu_to_le16(params);
3498 pSMB->ParameterCount = pSMB->TotalParameterCount;
3499 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3500 pSMB->Reserved4 = 0;
3501 inc_rfc1001_len(pSMB, byte_count);
3502 pSMB->ByteCount = cpu_to_le16(byte_count);
3503
3504 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3505 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3506 cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3507 if (rc) {
3508 cifs_dbg(FYI, "Send error in Query POSIX ACL = %d\n", rc);
3509 } else {
3510
3511
3512 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3513
3514 if (rc || get_bcc(&pSMBr->hdr) < 2)
3515 rc = -EIO;
3516 else {
3517 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3518 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3519 rc = cifs_copy_posix_acl(acl_inf,
3520 (char *)&pSMBr->hdr.Protocol+data_offset,
3521 buflen, acl_type, count);
3522 }
3523 }
3524 cifs_buf_release(pSMB);
3525 if (rc == -EAGAIN)
3526 goto queryAclRetry;
3527 return rc;
3528}
3529
3530int
3531CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3532 const unsigned char *fileName,
3533 const char *local_acl, const int buflen,
3534 const int acl_type,
3535 const struct nls_table *nls_codepage, int remap)
3536{
3537 struct smb_com_transaction2_spi_req *pSMB = NULL;
3538 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3539 char *parm_data;
3540 int name_len;
3541 int rc = 0;
3542 int bytes_returned = 0;
3543 __u16 params, byte_count, data_count, param_offset, offset;
3544
3545 cifs_dbg(FYI, "In SetPosixACL (Unix) for path %s\n", fileName);
3546setAclRetry:
3547 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3548 (void **) &pSMBr);
3549 if (rc)
3550 return rc;
3551 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3552 name_len =
3553 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
3554 PATH_MAX, nls_codepage, remap);
3555 name_len++;
3556 name_len *= 2;
3557 } else {
3558 name_len = copy_path_name(pSMB->FileName, fileName);
3559 }
3560 params = 6 + name_len;
3561 pSMB->MaxParameterCount = cpu_to_le16(2);
3562
3563 pSMB->MaxDataCount = cpu_to_le16(1000);
3564 pSMB->MaxSetupCount = 0;
3565 pSMB->Reserved = 0;
3566 pSMB->Flags = 0;
3567 pSMB->Timeout = 0;
3568 pSMB->Reserved2 = 0;
3569 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3570 InformationLevel) - 4;
3571 offset = param_offset + params;
3572 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3573 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3574
3575
3576 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
3577
3578 if (data_count == 0) {
3579 rc = -EOPNOTSUPP;
3580 goto setACLerrorExit;
3581 }
3582 pSMB->DataOffset = cpu_to_le16(offset);
3583 pSMB->SetupCount = 1;
3584 pSMB->Reserved3 = 0;
3585 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3586 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3587 byte_count = 3 + params + data_count;
3588 pSMB->DataCount = cpu_to_le16(data_count);
3589 pSMB->TotalDataCount = pSMB->DataCount;
3590 pSMB->ParameterCount = cpu_to_le16(params);
3591 pSMB->TotalParameterCount = pSMB->ParameterCount;
3592 pSMB->Reserved4 = 0;
3593 inc_rfc1001_len(pSMB, byte_count);
3594 pSMB->ByteCount = cpu_to_le16(byte_count);
3595 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3596 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3597 if (rc)
3598 cifs_dbg(FYI, "Set POSIX ACL returned %d\n", rc);
3599
3600setACLerrorExit:
3601 cifs_buf_release(pSMB);
3602 if (rc == -EAGAIN)
3603 goto setAclRetry;
3604 return rc;
3605}
3606
3607
3608int
3609CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
3610 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3611{
3612 int rc = 0;
3613 struct smb_t2_qfi_req *pSMB = NULL;
3614 struct smb_t2_qfi_rsp *pSMBr = NULL;
3615 int bytes_returned;
3616 __u16 params, byte_count;
3617
3618 cifs_dbg(FYI, "In GetExtAttr\n");
3619 if (tcon == NULL)
3620 return -ENODEV;
3621
3622GetExtAttrRetry:
3623 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3624 (void **) &pSMBr);
3625 if (rc)
3626 return rc;
3627
3628 params = 2 + 2 ;
3629 pSMB->t2.TotalDataCount = 0;
3630 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3631
3632 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3633 pSMB->t2.MaxSetupCount = 0;
3634 pSMB->t2.Reserved = 0;
3635 pSMB->t2.Flags = 0;
3636 pSMB->t2.Timeout = 0;
3637 pSMB->t2.Reserved2 = 0;
3638 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3639 Fid) - 4);
3640 pSMB->t2.DataCount = 0;
3641 pSMB->t2.DataOffset = 0;
3642 pSMB->t2.SetupCount = 1;
3643 pSMB->t2.Reserved3 = 0;
3644 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3645 byte_count = params + 1 ;
3646 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3647 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3648 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3649 pSMB->Pad = 0;
3650 pSMB->Fid = netfid;
3651 inc_rfc1001_len(pSMB, byte_count);
3652 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3653
3654 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3655 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3656 if (rc) {
3657 cifs_dbg(FYI, "error %d in GetExtAttr\n", rc);
3658 } else {
3659
3660 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3661
3662 if (rc || get_bcc(&pSMBr->hdr) < 2)
3663
3664
3665 rc = -EIO;
3666 else {
3667 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3668 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3669 struct file_chattr_info *pfinfo;
3670
3671 if (count != 16) {
3672 cifs_dbg(FYI, "Invalid size ret in GetExtAttr\n");
3673 rc = -EIO;
3674 goto GetExtAttrOut;
3675 }
3676 pfinfo = (struct file_chattr_info *)
3677 (data_offset + (char *) &pSMBr->hdr.Protocol);
3678 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3679 *pMask = le64_to_cpu(pfinfo->mask);
3680 }
3681 }
3682GetExtAttrOut:
3683 cifs_buf_release(pSMB);
3684 if (rc == -EAGAIN)
3685 goto GetExtAttrRetry;
3686 return rc;
3687}
3688
3689#endif
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699static int
3700smb_init_nttransact(const __u16 sub_command, const int setup_count,
3701 const int parm_len, struct cifs_tcon *tcon,
3702 void **ret_buf)
3703{
3704 int rc;
3705 __u32 temp_offset;
3706 struct smb_com_ntransact_req *pSMB;
3707
3708 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3709 (void **)&pSMB);
3710 if (rc)
3711 return rc;
3712 *ret_buf = (void *)pSMB;
3713 pSMB->Reserved = 0;
3714 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3715 pSMB->TotalDataCount = 0;
3716 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3717 pSMB->ParameterCount = pSMB->TotalParameterCount;
3718 pSMB->DataCount = pSMB->TotalDataCount;
3719 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3720 (setup_count * 2) - 4 ;
3721 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3722 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3723 pSMB->SetupCount = setup_count;
3724 pSMB->SubCommand = cpu_to_le16(sub_command);
3725 return 0;
3726}
3727
3728static int
3729validate_ntransact(char *buf, char **ppparm, char **ppdata,
3730 __u32 *pparmlen, __u32 *pdatalen)
3731{
3732 char *end_of_smb;
3733 __u32 data_count, data_offset, parm_count, parm_offset;
3734 struct smb_com_ntransact_rsp *pSMBr;
3735 u16 bcc;
3736
3737 *pdatalen = 0;
3738 *pparmlen = 0;
3739
3740 if (buf == NULL)
3741 return -EINVAL;
3742
3743 pSMBr = (struct smb_com_ntransact_rsp *)buf;
3744
3745 bcc = get_bcc(&pSMBr->hdr);
3746 end_of_smb = 2 + bcc +
3747 (char *)&pSMBr->ByteCount;
3748
3749 data_offset = le32_to_cpu(pSMBr->DataOffset);
3750 data_count = le32_to_cpu(pSMBr->DataCount);
3751 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3752 parm_count = le32_to_cpu(pSMBr->ParameterCount);
3753
3754 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3755 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3756
3757
3758 if (*ppparm > end_of_smb) {
3759 cifs_dbg(FYI, "parms start after end of smb\n");
3760 return -EINVAL;
3761 } else if (parm_count + *ppparm > end_of_smb) {
3762 cifs_dbg(FYI, "parm end after end of smb\n");
3763 return -EINVAL;
3764 } else if (*ppdata > end_of_smb) {
3765 cifs_dbg(FYI, "data starts after end of smb\n");
3766 return -EINVAL;
3767 } else if (data_count + *ppdata > end_of_smb) {
3768 cifs_dbg(FYI, "data %p + count %d (%p) past smb end %p start %p\n",
3769 *ppdata, data_count, (data_count + *ppdata),
3770 end_of_smb, pSMBr);
3771 return -EINVAL;
3772 } else if (parm_count + data_count > bcc) {
3773 cifs_dbg(FYI, "parm count and data count larger than SMB\n");
3774 return -EINVAL;
3775 }
3776 *pdatalen = data_count;
3777 *pparmlen = parm_count;
3778 return 0;
3779}
3780
3781
3782int
3783CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3784 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3785{
3786 int rc = 0;
3787 int buf_type = 0;
3788 QUERY_SEC_DESC_REQ *pSMB;
3789 struct kvec iov[1];
3790 struct kvec rsp_iov;
3791
3792 cifs_dbg(FYI, "GetCifsACL\n");
3793
3794 *pbuflen = 0;
3795 *acl_inf = NULL;
3796
3797 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3798 8 , tcon, (void **) &pSMB);
3799 if (rc)
3800 return rc;
3801
3802 pSMB->MaxParameterCount = cpu_to_le32(4);
3803
3804 pSMB->MaxSetupCount = 0;
3805 pSMB->Fid = fid;
3806 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3807 CIFS_ACL_DACL);
3808 pSMB->ByteCount = cpu_to_le16(11);
3809 inc_rfc1001_len(pSMB, 11);
3810 iov[0].iov_base = (char *)pSMB;
3811 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3812
3813 rc = SendReceive2(xid, tcon->ses, iov, 1 , &buf_type,
3814 0, &rsp_iov);
3815 cifs_small_buf_release(pSMB);
3816 cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3817 if (rc) {
3818 cifs_dbg(FYI, "Send error in QuerySecDesc = %d\n", rc);
3819 } else {
3820 __le32 *parm;
3821 __u32 parm_len;
3822 __u32 acl_len;
3823 struct smb_com_ntransact_rsp *pSMBr;
3824 char *pdata;
3825
3826
3827 rc = validate_ntransact(rsp_iov.iov_base, (char **)&parm,
3828 &pdata, &parm_len, pbuflen);
3829 if (rc)
3830 goto qsec_out;
3831 pSMBr = (struct smb_com_ntransact_rsp *)rsp_iov.iov_base;
3832
3833 cifs_dbg(FYI, "smb %p parm %p data %p\n",
3834 pSMBr, parm, *acl_inf);
3835
3836 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3837 rc = -EIO;
3838 *pbuflen = 0;
3839 goto qsec_out;
3840 }
3841
3842
3843
3844 acl_len = le32_to_cpu(*parm);
3845 if (acl_len != *pbuflen) {
3846 cifs_dbg(VFS, "acl length %d does not match %d\n",
3847 acl_len, *pbuflen);
3848 if (*pbuflen > acl_len)
3849 *pbuflen = acl_len;
3850 }
3851
3852
3853
3854 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3855 (*pbuflen >= 64 * 1024)) {
3856 cifs_dbg(VFS, "bad acl length %d\n", *pbuflen);
3857 rc = -EINVAL;
3858 *pbuflen = 0;
3859 } else {
3860 *acl_inf = kmemdup(pdata, *pbuflen, GFP_KERNEL);
3861 if (*acl_inf == NULL) {
3862 *pbuflen = 0;
3863 rc = -ENOMEM;
3864 }
3865 }
3866 }
3867qsec_out:
3868 free_rsp_buf(buf_type, rsp_iov.iov_base);
3869 return rc;
3870}
3871
3872int
3873CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3874 struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
3875{
3876 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3877 int rc = 0;
3878 int bytes_returned = 0;
3879 SET_SEC_DESC_REQ *pSMB = NULL;
3880 void *pSMBr;
3881
3882setCifsAclRetry:
3883 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
3884 if (rc)
3885 return rc;
3886
3887 pSMB->MaxSetupCount = 0;
3888 pSMB->Reserved = 0;
3889
3890 param_count = 8;
3891 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3892 data_count = acllen;
3893 data_offset = param_offset + param_count;
3894 byte_count = 3 + param_count;
3895
3896 pSMB->DataCount = cpu_to_le32(data_count);
3897 pSMB->TotalDataCount = pSMB->DataCount;
3898 pSMB->MaxParameterCount = cpu_to_le32(4);
3899 pSMB->MaxDataCount = cpu_to_le32(16384);
3900 pSMB->ParameterCount = cpu_to_le32(param_count);
3901 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3902 pSMB->TotalParameterCount = pSMB->ParameterCount;
3903 pSMB->DataOffset = cpu_to_le32(data_offset);
3904 pSMB->SetupCount = 0;
3905 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3906 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3907
3908 pSMB->Fid = fid;
3909 pSMB->Reserved2 = 0;
3910 pSMB->AclFlags = cpu_to_le32(aclflag);
3911
3912 if (pntsd && acllen) {
3913 memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
3914 data_offset, pntsd, acllen);
3915 inc_rfc1001_len(pSMB, byte_count + data_count);
3916 } else
3917 inc_rfc1001_len(pSMB, byte_count);
3918
3919 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3920 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3921
3922 cifs_dbg(FYI, "SetCIFSACL bytes_returned: %d, rc: %d\n",
3923 bytes_returned, rc);
3924 if (rc)
3925 cifs_dbg(FYI, "Set CIFS ACL returned %d\n", rc);
3926 cifs_buf_release(pSMB);
3927
3928 if (rc == -EAGAIN)
3929 goto setCifsAclRetry;
3930
3931 return (rc);
3932}
3933
3934
3935
3936
3937int
3938SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
3939 const char *search_name, FILE_ALL_INFO *data,
3940 const struct nls_table *nls_codepage, int remap)
3941{
3942 QUERY_INFORMATION_REQ *pSMB;
3943 QUERY_INFORMATION_RSP *pSMBr;
3944 int rc = 0;
3945 int bytes_returned;
3946 int name_len;
3947
3948 cifs_dbg(FYI, "In SMBQPath path %s\n", search_name);
3949QInfRetry:
3950 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3951 (void **) &pSMBr);
3952 if (rc)
3953 return rc;
3954
3955 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3956 name_len =
3957 cifsConvertToUTF16((__le16 *) pSMB->FileName,
3958 search_name, PATH_MAX, nls_codepage,
3959 remap);
3960 name_len++;
3961 name_len *= 2;
3962 } else {
3963 name_len = copy_path_name(pSMB->FileName, search_name);
3964 }
3965 pSMB->BufferFormat = 0x04;
3966 name_len++;
3967 inc_rfc1001_len(pSMB, (__u16)name_len);
3968 pSMB->ByteCount = cpu_to_le16(name_len);
3969
3970 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3971 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3972 if (rc) {
3973 cifs_dbg(FYI, "Send error in QueryInfo = %d\n", rc);
3974 } else if (data) {
3975 struct timespec64 ts;
3976 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3977
3978
3979
3980 memset(data, 0, sizeof(FILE_ALL_INFO));
3981 ts.tv_nsec = 0;
3982 ts.tv_sec = time;
3983
3984 data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3985 data->LastWriteTime = data->ChangeTime;
3986 data->LastAccessTime = 0;
3987 data->AllocationSize =
3988 cpu_to_le64(le32_to_cpu(pSMBr->size));
3989 data->EndOfFile = data->AllocationSize;
3990 data->Attributes =
3991 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3992 } else
3993 rc = -EIO;
3994
3995 cifs_buf_release(pSMB);
3996
3997 if (rc == -EAGAIN)
3998 goto QInfRetry;
3999
4000 return rc;
4001}
4002
4003int
4004CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
4005 u16 netfid, FILE_ALL_INFO *pFindData)
4006{
4007 struct smb_t2_qfi_req *pSMB = NULL;
4008 struct smb_t2_qfi_rsp *pSMBr = NULL;
4009 int rc = 0;
4010 int bytes_returned;
4011 __u16 params, byte_count;
4012
4013QFileInfoRetry:
4014 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4015 (void **) &pSMBr);
4016 if (rc)
4017 return rc;
4018
4019 params = 2 + 2 ;
4020 pSMB->t2.TotalDataCount = 0;
4021 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4022
4023 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4024 pSMB->t2.MaxSetupCount = 0;
4025 pSMB->t2.Reserved = 0;
4026 pSMB->t2.Flags = 0;
4027 pSMB->t2.Timeout = 0;
4028 pSMB->t2.Reserved2 = 0;
4029 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4030 Fid) - 4);
4031 pSMB->t2.DataCount = 0;
4032 pSMB->t2.DataOffset = 0;
4033 pSMB->t2.SetupCount = 1;
4034 pSMB->t2.Reserved3 = 0;
4035 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4036 byte_count = params + 1 ;
4037 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4038 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4039 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4040 pSMB->Pad = 0;
4041 pSMB->Fid = netfid;
4042 inc_rfc1001_len(pSMB, byte_count);
4043 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
4044
4045 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4046 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4047 if (rc) {
4048 cifs_dbg(FYI, "Send error in QFileInfo = %d\n", rc);
4049 } else {
4050 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4051
4052 if (rc)
4053 rc = -EIO;
4054 else if (get_bcc(&pSMBr->hdr) < 40)
4055 rc = -EIO;
4056 else if (pFindData) {
4057 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4058 memcpy((char *) pFindData,
4059 (char *) &pSMBr->hdr.Protocol +
4060 data_offset, sizeof(FILE_ALL_INFO));
4061 } else
4062 rc = -ENOMEM;
4063 }
4064 cifs_buf_release(pSMB);
4065 if (rc == -EAGAIN)
4066 goto QFileInfoRetry;
4067
4068 return rc;
4069}
4070
4071int
4072CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4073 const char *search_name, FILE_ALL_INFO *data,
4074 int legacy ,
4075 const struct nls_table *nls_codepage, int remap)
4076{
4077
4078 TRANSACTION2_QPI_REQ *pSMB = NULL;
4079 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4080 int rc = 0;
4081 int bytes_returned;
4082 int name_len;
4083 __u16 params, byte_count;
4084
4085
4086QPathInfoRetry:
4087 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4088 (void **) &pSMBr);
4089 if (rc)
4090 return rc;
4091
4092 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4093 name_len =
4094 cifsConvertToUTF16((__le16 *) pSMB->FileName, search_name,
4095 PATH_MAX, nls_codepage, remap);
4096 name_len++;
4097 name_len *= 2;
4098 } else {
4099 name_len = copy_path_name(pSMB->FileName, search_name);
4100 }
4101
4102 params = 2 + 4 + name_len ;
4103 pSMB->TotalDataCount = 0;
4104 pSMB->MaxParameterCount = cpu_to_le16(2);
4105
4106 pSMB->MaxDataCount = cpu_to_le16(4000);
4107 pSMB->MaxSetupCount = 0;
4108 pSMB->Reserved = 0;
4109 pSMB->Flags = 0;
4110 pSMB->Timeout = 0;
4111 pSMB->Reserved2 = 0;
4112 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4113 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4114 pSMB->DataCount = 0;
4115 pSMB->DataOffset = 0;
4116 pSMB->SetupCount = 1;
4117 pSMB->Reserved3 = 0;
4118 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4119 byte_count = params + 1 ;
4120 pSMB->TotalParameterCount = cpu_to_le16(params);
4121 pSMB->ParameterCount = pSMB->TotalParameterCount;
4122 if (legacy)
4123 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
4124 else
4125 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4126 pSMB->Reserved4 = 0;
4127 inc_rfc1001_len(pSMB, byte_count);
4128 pSMB->ByteCount = cpu_to_le16(byte_count);
4129
4130 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4131 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4132 if (rc) {
4133 cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
4134 } else {
4135 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4136
4137 if (rc)
4138 rc = -EIO;
4139 else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
4140 rc = -EIO;
4141 else if (legacy && get_bcc(&pSMBr->hdr) < 24)
4142 rc = -EIO;
4143
4144 else if (data) {
4145 int size;
4146 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4147
4148
4149
4150
4151
4152
4153
4154 if (legacy)
4155 size = sizeof(FILE_INFO_STANDARD);
4156 else
4157 size = sizeof(FILE_ALL_INFO);
4158 memcpy((char *) data, (char *) &pSMBr->hdr.Protocol +
4159 data_offset, size);
4160 } else
4161 rc = -ENOMEM;
4162 }
4163 cifs_buf_release(pSMB);
4164 if (rc == -EAGAIN)
4165 goto QPathInfoRetry;
4166
4167 return rc;
4168}
4169
4170int
4171CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
4172 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
4173{
4174 struct smb_t2_qfi_req *pSMB = NULL;
4175 struct smb_t2_qfi_rsp *pSMBr = NULL;
4176 int rc = 0;
4177 int bytes_returned;
4178 __u16 params, byte_count;
4179
4180UnixQFileInfoRetry:
4181 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4182 (void **) &pSMBr);
4183 if (rc)
4184 return rc;
4185
4186 params = 2 + 2 ;
4187 pSMB->t2.TotalDataCount = 0;
4188 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4189
4190 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4191 pSMB->t2.MaxSetupCount = 0;
4192 pSMB->t2.Reserved = 0;
4193 pSMB->t2.Flags = 0;
4194 pSMB->t2.Timeout = 0;
4195 pSMB->t2.Reserved2 = 0;
4196 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4197 Fid) - 4);
4198 pSMB->t2.DataCount = 0;
4199 pSMB->t2.DataOffset = 0;
4200 pSMB->t2.SetupCount = 1;
4201 pSMB->t2.Reserved3 = 0;
4202 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4203 byte_count = params + 1 ;
4204 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4205 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4206 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4207 pSMB->Pad = 0;
4208 pSMB->Fid = netfid;
4209 inc_rfc1001_len(pSMB, byte_count);
4210 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
4211
4212 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4213 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4214 if (rc) {
4215 cifs_dbg(FYI, "Send error in UnixQFileInfo = %d\n", rc);
4216 } else {
4217 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4218
4219 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4220 cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
4221 rc = -EIO;
4222 } else {
4223 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4224 memcpy((char *) pFindData,
4225 (char *) &pSMBr->hdr.Protocol +
4226 data_offset,
4227 sizeof(FILE_UNIX_BASIC_INFO));
4228 }
4229 }
4230
4231 cifs_buf_release(pSMB);
4232 if (rc == -EAGAIN)
4233 goto UnixQFileInfoRetry;
4234
4235 return rc;
4236}
4237
4238int
4239CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4240 const unsigned char *searchName,
4241 FILE_UNIX_BASIC_INFO *pFindData,
4242 const struct nls_table *nls_codepage, int remap)
4243{
4244
4245 TRANSACTION2_QPI_REQ *pSMB = NULL;
4246 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4247 int rc = 0;
4248 int bytes_returned = 0;
4249 int name_len;
4250 __u16 params, byte_count;
4251
4252 cifs_dbg(FYI, "In QPathInfo (Unix) the path %s\n", searchName);
4253UnixQPathInfoRetry:
4254 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4255 (void **) &pSMBr);
4256 if (rc)
4257 return rc;
4258
4259 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4260 name_len =
4261 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4262 PATH_MAX, nls_codepage, remap);
4263 name_len++;
4264 name_len *= 2;
4265 } else {
4266 name_len = copy_path_name(pSMB->FileName, searchName);
4267 }
4268
4269 params = 2 + 4 + name_len ;
4270 pSMB->TotalDataCount = 0;
4271 pSMB->MaxParameterCount = cpu_to_le16(2);
4272
4273 pSMB->MaxDataCount = cpu_to_le16(4000);
4274 pSMB->MaxSetupCount = 0;
4275 pSMB->Reserved = 0;
4276 pSMB->Flags = 0;
4277 pSMB->Timeout = 0;
4278 pSMB->Reserved2 = 0;
4279 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4280 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4281 pSMB->DataCount = 0;
4282 pSMB->DataOffset = 0;
4283 pSMB->SetupCount = 1;
4284 pSMB->Reserved3 = 0;
4285 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4286 byte_count = params + 1 ;
4287 pSMB->TotalParameterCount = cpu_to_le16(params);
4288 pSMB->ParameterCount = pSMB->TotalParameterCount;
4289 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4290 pSMB->Reserved4 = 0;
4291 inc_rfc1001_len(pSMB, byte_count);
4292 pSMB->ByteCount = cpu_to_le16(byte_count);
4293
4294 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4295 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4296 if (rc) {
4297 cifs_dbg(FYI, "Send error in UnixQPathInfo = %d\n", rc);
4298 } else {
4299 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4300
4301 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4302 cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
4303 rc = -EIO;
4304 } else {
4305 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4306 memcpy((char *) pFindData,
4307 (char *) &pSMBr->hdr.Protocol +
4308 data_offset,
4309 sizeof(FILE_UNIX_BASIC_INFO));
4310 }
4311 }
4312 cifs_buf_release(pSMB);
4313 if (rc == -EAGAIN)
4314 goto UnixQPathInfoRetry;
4315
4316 return rc;
4317}
4318
4319
4320int
4321CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
4322 const char *searchName, struct cifs_sb_info *cifs_sb,
4323 __u16 *pnetfid, __u16 search_flags,
4324 struct cifs_search_info *psrch_inf, bool msearch)
4325{
4326
4327 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
4328 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
4329 T2_FFIRST_RSP_PARMS *parms;
4330 int rc = 0;
4331 int bytes_returned = 0;
4332 int name_len, remap;
4333 __u16 params, byte_count;
4334 struct nls_table *nls_codepage;
4335
4336 cifs_dbg(FYI, "In FindFirst for %s\n", searchName);
4337
4338findFirstRetry:
4339 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4340 (void **) &pSMBr);
4341 if (rc)
4342 return rc;
4343
4344 nls_codepage = cifs_sb->local_nls;
4345 remap = cifs_remap(cifs_sb);
4346
4347 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4348 name_len =
4349 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4350 PATH_MAX, nls_codepage, remap);
4351
4352
4353
4354 name_len *= 2;
4355 if (msearch) {
4356 pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
4357 pSMB->FileName[name_len+1] = 0;
4358 pSMB->FileName[name_len+2] = '*';
4359 pSMB->FileName[name_len+3] = 0;
4360 name_len += 4;
4361
4362 pSMB->FileName[name_len] = 0;
4363 pSMB->FileName[name_len+1] = 0;
4364 name_len += 2;
4365 }
4366 } else {
4367 name_len = copy_path_name(pSMB->FileName, searchName);
4368 if (msearch) {
4369 if (WARN_ON_ONCE(name_len > PATH_MAX-2))
4370 name_len = PATH_MAX-2;
4371
4372 pSMB->FileName[name_len-1] = CIFS_DIR_SEP(cifs_sb);
4373 pSMB->FileName[name_len] = '*';
4374 pSMB->FileName[name_len+1] = 0;
4375 name_len += 2;
4376 }
4377 }
4378
4379 params = 12 + name_len ;
4380 pSMB->TotalDataCount = 0;
4381 pSMB->MaxParameterCount = cpu_to_le16(10);
4382 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4383 pSMB->MaxSetupCount = 0;
4384 pSMB->Reserved = 0;
4385 pSMB->Flags = 0;
4386 pSMB->Timeout = 0;
4387 pSMB->Reserved2 = 0;
4388 byte_count = params + 1 ;
4389 pSMB->TotalParameterCount = cpu_to_le16(params);
4390 pSMB->ParameterCount = pSMB->TotalParameterCount;
4391 pSMB->ParameterOffset = cpu_to_le16(
4392 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
4393 - 4);
4394 pSMB->DataCount = 0;
4395 pSMB->DataOffset = 0;
4396 pSMB->SetupCount = 1;
4397 pSMB->Reserved3 = 0;
4398 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4399 pSMB->SearchAttributes =
4400 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4401 ATTR_DIRECTORY);
4402 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
4403 pSMB->SearchFlags = cpu_to_le16(search_flags);
4404 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4405
4406
4407 pSMB->SearchStorageType = 0;
4408 inc_rfc1001_len(pSMB, byte_count);
4409 pSMB->ByteCount = cpu_to_le16(byte_count);
4410
4411 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4412 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4413 cifs_stats_inc(&tcon->stats.cifs_stats.num_ffirst);
4414
4415 if (rc) {
4416
4417
4418 cifs_dbg(FYI, "Error in FindFirst = %d\n", rc);
4419
4420 cifs_buf_release(pSMB);
4421
4422
4423
4424 if (rc == -EAGAIN)
4425 goto findFirstRetry;
4426 } else {
4427
4428 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4429 if (rc == 0) {
4430 unsigned int lnoff;
4431
4432 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4433 psrch_inf->unicode = true;
4434 else
4435 psrch_inf->unicode = false;
4436
4437 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4438 psrch_inf->smallBuf = false;
4439 psrch_inf->srch_entries_start =
4440 (char *) &pSMBr->hdr.Protocol +
4441 le16_to_cpu(pSMBr->t2.DataOffset);
4442 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
4443 le16_to_cpu(pSMBr->t2.ParameterOffset));
4444
4445 if (parms->EndofSearch)
4446 psrch_inf->endOfSearch = true;
4447 else
4448 psrch_inf->endOfSearch = false;
4449
4450 psrch_inf->entries_in_buffer =
4451 le16_to_cpu(parms->SearchCount);
4452 psrch_inf->index_of_last_entry = 2 +
4453 psrch_inf->entries_in_buffer;
4454 lnoff = le16_to_cpu(parms->LastNameOffset);
4455 if (CIFSMaxBufSize < lnoff) {
4456 cifs_dbg(VFS, "ignoring corrupt resume name\n");
4457 psrch_inf->last_entry = NULL;
4458 return rc;
4459 }
4460
4461 psrch_inf->last_entry = psrch_inf->srch_entries_start +
4462 lnoff;
4463
4464 if (pnetfid)
4465 *pnetfid = parms->SearchHandle;
4466 } else {
4467 cifs_buf_release(pSMB);
4468 }
4469 }
4470
4471 return rc;
4472}
4473
4474int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
4475 __u16 searchHandle, __u16 search_flags,
4476 struct cifs_search_info *psrch_inf)
4477{
4478 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4479 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4480 T2_FNEXT_RSP_PARMS *parms;
4481 char *response_data;
4482 int rc = 0;
4483 int bytes_returned;
4484 unsigned int name_len;
4485 __u16 params, byte_count;
4486
4487 cifs_dbg(FYI, "In FindNext\n");
4488
4489 if (psrch_inf->endOfSearch)
4490 return -ENOENT;
4491
4492 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4493 (void **) &pSMBr);
4494 if (rc)
4495 return rc;
4496
4497 params = 14;
4498 byte_count = 0;
4499 pSMB->TotalDataCount = 0;
4500 pSMB->MaxParameterCount = cpu_to_le16(8);
4501 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4502 pSMB->MaxSetupCount = 0;
4503 pSMB->Reserved = 0;
4504 pSMB->Flags = 0;
4505 pSMB->Timeout = 0;
4506 pSMB->Reserved2 = 0;
4507 pSMB->ParameterOffset = cpu_to_le16(
4508 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4509 pSMB->DataCount = 0;
4510 pSMB->DataOffset = 0;
4511 pSMB->SetupCount = 1;
4512 pSMB->Reserved3 = 0;
4513 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4514 pSMB->SearchHandle = searchHandle;
4515 pSMB->SearchCount =
4516 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4517 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4518 pSMB->ResumeKey = psrch_inf->resume_key;
4519 pSMB->SearchFlags = cpu_to_le16(search_flags);
4520
4521 name_len = psrch_inf->resume_name_len;
4522 params += name_len;
4523 if (name_len < PATH_MAX) {
4524 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4525 byte_count += name_len;
4526
4527 pSMB->ResumeFileName[name_len] = 0;
4528 pSMB->ResumeFileName[name_len+1] = 0;
4529 } else {
4530 rc = -EINVAL;
4531 goto FNext2_err_exit;
4532 }
4533 byte_count = params + 1 ;
4534 pSMB->TotalParameterCount = cpu_to_le16(params);
4535 pSMB->ParameterCount = pSMB->TotalParameterCount;
4536 inc_rfc1001_len(pSMB, byte_count);
4537 pSMB->ByteCount = cpu_to_le16(byte_count);
4538
4539 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4540 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4541 cifs_stats_inc(&tcon->stats.cifs_stats.num_fnext);
4542 if (rc) {
4543 if (rc == -EBADF) {
4544 psrch_inf->endOfSearch = true;
4545 cifs_buf_release(pSMB);
4546 rc = 0;
4547 } else
4548 cifs_dbg(FYI, "FindNext returned = %d\n", rc);
4549 } else {
4550 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4551
4552 if (rc == 0) {
4553 unsigned int lnoff;
4554
4555
4556 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4557 psrch_inf->unicode = true;
4558 else
4559 psrch_inf->unicode = false;
4560 response_data = (char *) &pSMBr->hdr.Protocol +
4561 le16_to_cpu(pSMBr->t2.ParameterOffset);
4562 parms = (T2_FNEXT_RSP_PARMS *)response_data;
4563 response_data = (char *)&pSMBr->hdr.Protocol +
4564 le16_to_cpu(pSMBr->t2.DataOffset);
4565 if (psrch_inf->smallBuf)
4566 cifs_small_buf_release(
4567 psrch_inf->ntwrk_buf_start);
4568 else
4569 cifs_buf_release(psrch_inf->ntwrk_buf_start);
4570 psrch_inf->srch_entries_start = response_data;
4571 psrch_inf->ntwrk_buf_start = (char *)pSMB;
4572 psrch_inf->smallBuf = false;
4573 if (parms->EndofSearch)
4574 psrch_inf->endOfSearch = true;
4575 else
4576 psrch_inf->endOfSearch = false;
4577 psrch_inf->entries_in_buffer =
4578 le16_to_cpu(parms->SearchCount);
4579 psrch_inf->index_of_last_entry +=
4580 psrch_inf->entries_in_buffer;
4581 lnoff = le16_to_cpu(parms->LastNameOffset);
4582 if (CIFSMaxBufSize < lnoff) {
4583 cifs_dbg(VFS, "ignoring corrupt resume name\n");
4584 psrch_inf->last_entry = NULL;
4585 return rc;
4586 } else
4587 psrch_inf->last_entry =
4588 psrch_inf->srch_entries_start + lnoff;
4589
4590
4591
4592
4593
4594 }
4595
4596 }
4597
4598
4599
4600
4601
4602
4603FNext2_err_exit:
4604 if (rc != 0)
4605 cifs_buf_release(pSMB);
4606 return rc;
4607}
4608
4609int
4610CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
4611 const __u16 searchHandle)
4612{
4613 int rc = 0;
4614 FINDCLOSE_REQ *pSMB = NULL;
4615
4616 cifs_dbg(FYI, "In CIFSSMBFindClose\n");
4617 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4618
4619
4620
4621 if (rc == -EAGAIN)
4622 return 0;
4623 if (rc)
4624 return rc;
4625
4626 pSMB->FileID = searchHandle;
4627 pSMB->ByteCount = 0;
4628 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
4629 cifs_small_buf_release(pSMB);
4630 if (rc)
4631 cifs_dbg(VFS, "Send error in FindClose = %d\n", rc);
4632
4633 cifs_stats_inc(&tcon->stats.cifs_stats.num_fclose);
4634
4635
4636 if (rc == -EAGAIN)
4637 rc = 0;
4638
4639 return rc;
4640}
4641
4642int
4643CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
4644 const char *search_name, __u64 *inode_number,
4645 const struct nls_table *nls_codepage, int remap)
4646{
4647 int rc = 0;
4648 TRANSACTION2_QPI_REQ *pSMB = NULL;
4649 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4650 int name_len, bytes_returned;
4651 __u16 params, byte_count;
4652
4653 cifs_dbg(FYI, "In GetSrvInodeNum for %s\n", search_name);
4654 if (tcon == NULL)
4655 return -ENODEV;
4656
4657GetInodeNumberRetry:
4658 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4659 (void **) &pSMBr);
4660 if (rc)
4661 return rc;
4662
4663 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4664 name_len =
4665 cifsConvertToUTF16((__le16 *) pSMB->FileName,
4666 search_name, PATH_MAX, nls_codepage,
4667 remap);
4668 name_len++;
4669 name_len *= 2;
4670 } else {
4671 name_len = copy_path_name(pSMB->FileName, search_name);
4672 }
4673
4674 params = 2 + 4 + name_len ;
4675 pSMB->TotalDataCount = 0;
4676 pSMB->MaxParameterCount = cpu_to_le16(2);
4677
4678 pSMB->MaxDataCount = cpu_to_le16(4000);
4679 pSMB->MaxSetupCount = 0;
4680 pSMB->Reserved = 0;
4681 pSMB->Flags = 0;
4682 pSMB->Timeout = 0;
4683 pSMB->Reserved2 = 0;
4684 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4685 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4686 pSMB->DataCount = 0;
4687 pSMB->DataOffset = 0;
4688 pSMB->SetupCount = 1;
4689 pSMB->Reserved3 = 0;
4690 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4691 byte_count = params + 1 ;
4692 pSMB->TotalParameterCount = cpu_to_le16(params);
4693 pSMB->ParameterCount = pSMB->TotalParameterCount;
4694 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4695 pSMB->Reserved4 = 0;
4696 inc_rfc1001_len(pSMB, byte_count);
4697 pSMB->ByteCount = cpu_to_le16(byte_count);
4698
4699 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4700 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4701 if (rc) {
4702 cifs_dbg(FYI, "error %d in QueryInternalInfo\n", rc);
4703 } else {
4704
4705 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4706
4707 if (rc || get_bcc(&pSMBr->hdr) < 2)
4708
4709
4710 rc = -EIO;
4711 else {
4712 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4713 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4714 struct file_internal_info *pfinfo;
4715
4716 if (count < 8) {
4717 cifs_dbg(FYI, "Invalid size ret in QryIntrnlInf\n");
4718 rc = -EIO;
4719 goto GetInodeNumOut;
4720 }
4721 pfinfo = (struct file_internal_info *)
4722 (data_offset + (char *) &pSMBr->hdr.Protocol);
4723 *inode_number = le64_to_cpu(pfinfo->UniqueId);
4724 }
4725 }
4726GetInodeNumOut:
4727 cifs_buf_release(pSMB);
4728 if (rc == -EAGAIN)
4729 goto GetInodeNumberRetry;
4730 return rc;
4731}
4732
4733int
4734CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
4735 const char *search_name, struct dfs_info3_param **target_nodes,
4736 unsigned int *num_of_nodes,
4737 const struct nls_table *nls_codepage, int remap)
4738{
4739
4740 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4741 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4742 int rc = 0;
4743 int bytes_returned;
4744 int name_len;
4745 __u16 params, byte_count;
4746 *num_of_nodes = 0;
4747 *target_nodes = NULL;
4748
4749 cifs_dbg(FYI, "In GetDFSRefer the path %s\n", search_name);
4750 if (ses == NULL || ses->tcon_ipc == NULL)
4751 return -ENODEV;
4752
4753getDFSRetry:
4754 rc = smb_init(SMB_COM_TRANSACTION2, 15, ses->tcon_ipc, (void **) &pSMB,
4755 (void **) &pSMBr);
4756 if (rc)
4757 return rc;
4758
4759
4760
4761 pSMB->hdr.Mid = get_next_mid(ses->server);
4762 pSMB->hdr.Tid = ses->tcon_ipc->tid;
4763 pSMB->hdr.Uid = ses->Suid;
4764 if (ses->capabilities & CAP_STATUS32)
4765 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4766 if (ses->capabilities & CAP_DFS)
4767 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4768
4769 if (ses->capabilities & CAP_UNICODE) {
4770 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4771 name_len =
4772 cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
4773 search_name, PATH_MAX, nls_codepage,
4774 remap);
4775 name_len++;
4776 name_len *= 2;
4777 } else {
4778 name_len = copy_path_name(pSMB->RequestFileName, search_name);
4779 }
4780
4781 if (ses->server->sign)
4782 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4783
4784 pSMB->hdr.Uid = ses->Suid;
4785
4786 params = 2 + name_len ;
4787 pSMB->TotalDataCount = 0;
4788 pSMB->DataCount = 0;
4789 pSMB->DataOffset = 0;
4790 pSMB->MaxParameterCount = 0;
4791
4792 pSMB->MaxDataCount = cpu_to_le16(4000);
4793 pSMB->MaxSetupCount = 0;
4794 pSMB->Reserved = 0;
4795 pSMB->Flags = 0;
4796 pSMB->Timeout = 0;
4797 pSMB->Reserved2 = 0;
4798 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4799 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4800 pSMB->SetupCount = 1;
4801 pSMB->Reserved3 = 0;
4802 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4803 byte_count = params + 3 ;
4804 pSMB->ParameterCount = cpu_to_le16(params);
4805 pSMB->TotalParameterCount = pSMB->ParameterCount;
4806 pSMB->MaxReferralLevel = cpu_to_le16(3);
4807 inc_rfc1001_len(pSMB, byte_count);
4808 pSMB->ByteCount = cpu_to_le16(byte_count);
4809
4810 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4811 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4812 if (rc) {
4813 cifs_dbg(FYI, "Send error in GetDFSRefer = %d\n", rc);
4814 goto GetDFSRefExit;
4815 }
4816 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4817
4818
4819 if (rc || get_bcc(&pSMBr->hdr) < 17) {
4820 rc = -EIO;
4821 goto GetDFSRefExit;
4822 }
4823
4824 cifs_dbg(FYI, "Decoding GetDFSRefer response BCC: %d Offset %d\n",
4825 get_bcc(&pSMBr->hdr), le16_to_cpu(pSMBr->t2.DataOffset));
4826
4827
4828 rc = parse_dfs_referrals(&pSMBr->dfs_data,
4829 le16_to_cpu(pSMBr->t2.DataCount),
4830 num_of_nodes, target_nodes, nls_codepage,
4831 remap, search_name,
4832 (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) != 0);
4833
4834GetDFSRefExit:
4835 cifs_buf_release(pSMB);
4836
4837 if (rc == -EAGAIN)
4838 goto getDFSRetry;
4839
4840 return rc;
4841}
4842
4843
4844int
4845SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4846 struct kstatfs *FSData)
4847{
4848
4849 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4850 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4851 FILE_SYSTEM_ALLOC_INFO *response_data;
4852 int rc = 0;
4853 int bytes_returned = 0;
4854 __u16 params, byte_count;
4855
4856 cifs_dbg(FYI, "OldQFSInfo\n");
4857oldQFSInfoRetry:
4858 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4859 (void **) &pSMBr);
4860 if (rc)
4861 return rc;
4862
4863 params = 2;
4864 pSMB->TotalDataCount = 0;
4865 pSMB->MaxParameterCount = cpu_to_le16(2);
4866 pSMB->MaxDataCount = cpu_to_le16(1000);
4867 pSMB->MaxSetupCount = 0;
4868 pSMB->Reserved = 0;
4869 pSMB->Flags = 0;
4870 pSMB->Timeout = 0;
4871 pSMB->Reserved2 = 0;
4872 byte_count = params + 1 ;
4873 pSMB->TotalParameterCount = cpu_to_le16(params);
4874 pSMB->ParameterCount = pSMB->TotalParameterCount;
4875 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4876 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4877 pSMB->DataCount = 0;
4878 pSMB->DataOffset = 0;
4879 pSMB->SetupCount = 1;
4880 pSMB->Reserved3 = 0;
4881 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4882 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4883 inc_rfc1001_len(pSMB, byte_count);
4884 pSMB->ByteCount = cpu_to_le16(byte_count);
4885
4886 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4887 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4888 if (rc) {
4889 cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
4890 } else {
4891 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4892
4893 if (rc || get_bcc(&pSMBr->hdr) < 18)
4894 rc = -EIO;
4895 else {
4896 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4897 cifs_dbg(FYI, "qfsinf resp BCC: %d Offset %d\n",
4898 get_bcc(&pSMBr->hdr), data_offset);
4899
4900 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4901 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4902 FSData->f_bsize =
4903 le16_to_cpu(response_data->BytesPerSector) *
4904 le32_to_cpu(response_data->
4905 SectorsPerAllocationUnit);
4906
4907
4908
4909
4910 if (FSData->f_bsize < 512)
4911 FSData->f_bsize = 4096;
4912
4913 FSData->f_blocks =
4914 le32_to_cpu(response_data->TotalAllocationUnits);
4915 FSData->f_bfree = FSData->f_bavail =
4916 le32_to_cpu(response_data->FreeAllocationUnits);
4917 cifs_dbg(FYI, "Blocks: %lld Free: %lld Block size %ld\n",
4918 (unsigned long long)FSData->f_blocks,
4919 (unsigned long long)FSData->f_bfree,
4920 FSData->f_bsize);
4921 }
4922 }
4923 cifs_buf_release(pSMB);
4924
4925 if (rc == -EAGAIN)
4926 goto oldQFSInfoRetry;
4927
4928 return rc;
4929}
4930
4931int
4932CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4933 struct kstatfs *FSData)
4934{
4935
4936 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4937 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4938 FILE_SYSTEM_INFO *response_data;
4939 int rc = 0;
4940 int bytes_returned = 0;
4941 __u16 params, byte_count;
4942
4943 cifs_dbg(FYI, "In QFSInfo\n");
4944QFSInfoRetry:
4945 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4946 (void **) &pSMBr);
4947 if (rc)
4948 return rc;
4949
4950 params = 2;
4951 pSMB->TotalDataCount = 0;
4952 pSMB->MaxParameterCount = cpu_to_le16(2);
4953 pSMB->MaxDataCount = cpu_to_le16(1000);
4954 pSMB->MaxSetupCount = 0;
4955 pSMB->Reserved = 0;
4956 pSMB->Flags = 0;
4957 pSMB->Timeout = 0;
4958 pSMB->Reserved2 = 0;
4959 byte_count = params + 1 ;
4960 pSMB->TotalParameterCount = cpu_to_le16(params);
4961 pSMB->ParameterCount = pSMB->TotalParameterCount;
4962 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4963 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4964 pSMB->DataCount = 0;
4965 pSMB->DataOffset = 0;
4966 pSMB->SetupCount = 1;
4967 pSMB->Reserved3 = 0;
4968 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4969 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4970 inc_rfc1001_len(pSMB, byte_count);
4971 pSMB->ByteCount = cpu_to_le16(byte_count);
4972
4973 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4974 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4975 if (rc) {
4976 cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
4977 } else {
4978 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4979
4980 if (rc || get_bcc(&pSMBr->hdr) < 24)
4981 rc = -EIO;
4982 else {
4983 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4984
4985 response_data =
4986 (FILE_SYSTEM_INFO
4987 *) (((char *) &pSMBr->hdr.Protocol) +
4988 data_offset);
4989 FSData->f_bsize =
4990 le32_to_cpu(response_data->BytesPerSector) *
4991 le32_to_cpu(response_data->
4992 SectorsPerAllocationUnit);
4993
4994
4995
4996
4997 if (FSData->f_bsize < 512)
4998 FSData->f_bsize = 4096;
4999
5000 FSData->f_blocks =
5001 le64_to_cpu(response_data->TotalAllocationUnits);
5002 FSData->f_bfree = FSData->f_bavail =
5003 le64_to_cpu(response_data->FreeAllocationUnits);
5004 cifs_dbg(FYI, "Blocks: %lld Free: %lld Block size %ld\n",
5005 (unsigned long long)FSData->f_blocks,
5006 (unsigned long long)FSData->f_bfree,
5007 FSData->f_bsize);
5008 }
5009 }
5010 cifs_buf_release(pSMB);
5011
5012 if (rc == -EAGAIN)
5013 goto QFSInfoRetry;
5014
5015 return rc;
5016}
5017
5018int
5019CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)
5020{
5021
5022 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5023 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5024 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
5025 int rc = 0;
5026 int bytes_returned = 0;
5027 __u16 params, byte_count;
5028
5029 cifs_dbg(FYI, "In QFSAttributeInfo\n");
5030QFSAttributeRetry:
5031 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5032 (void **) &pSMBr);
5033 if (rc)
5034 return rc;
5035
5036 params = 2;
5037 pSMB->TotalDataCount = 0;
5038 pSMB->MaxParameterCount = cpu_to_le16(2);
5039
5040 pSMB->MaxDataCount = cpu_to_le16(1000);
5041 pSMB->MaxSetupCount = 0;
5042 pSMB->Reserved = 0;
5043 pSMB->Flags = 0;
5044 pSMB->Timeout = 0;
5045 pSMB->Reserved2 = 0;
5046 byte_count = params + 1 ;
5047 pSMB->TotalParameterCount = cpu_to_le16(params);
5048 pSMB->ParameterCount = pSMB->TotalParameterCount;
5049 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5050 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5051 pSMB->DataCount = 0;
5052 pSMB->DataOffset = 0;
5053 pSMB->SetupCount = 1;
5054 pSMB->Reserved3 = 0;
5055 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5056 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
5057 inc_rfc1001_len(pSMB, byte_count);
5058 pSMB->ByteCount = cpu_to_le16(byte_count);
5059
5060 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5061 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5062 if (rc) {
5063 cifs_dbg(VFS, "Send error in QFSAttributeInfo = %d\n", rc);
5064 } else {
5065 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5066
5067 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5068
5069 rc = -EIO;
5070 } else {
5071 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5072 response_data =
5073 (FILE_SYSTEM_ATTRIBUTE_INFO
5074 *) (((char *) &pSMBr->hdr.Protocol) +
5075 data_offset);
5076 memcpy(&tcon->fsAttrInfo, response_data,
5077 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
5078 }
5079 }
5080 cifs_buf_release(pSMB);
5081
5082 if (rc == -EAGAIN)
5083 goto QFSAttributeRetry;
5084
5085 return rc;
5086}
5087
5088int
5089CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)
5090{
5091
5092 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5093 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5094 FILE_SYSTEM_DEVICE_INFO *response_data;
5095 int rc = 0;
5096 int bytes_returned = 0;
5097 __u16 params, byte_count;
5098
5099 cifs_dbg(FYI, "In QFSDeviceInfo\n");
5100QFSDeviceRetry:
5101 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5102 (void **) &pSMBr);
5103 if (rc)
5104 return rc;
5105
5106 params = 2;
5107 pSMB->TotalDataCount = 0;
5108 pSMB->MaxParameterCount = cpu_to_le16(2);
5109
5110 pSMB->MaxDataCount = cpu_to_le16(1000);
5111 pSMB->MaxSetupCount = 0;
5112 pSMB->Reserved = 0;
5113 pSMB->Flags = 0;
5114 pSMB->Timeout = 0;
5115 pSMB->Reserved2 = 0;
5116 byte_count = params + 1 ;
5117 pSMB->TotalParameterCount = cpu_to_le16(params);
5118 pSMB->ParameterCount = pSMB->TotalParameterCount;
5119 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5120 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5121
5122 pSMB->DataCount = 0;
5123 pSMB->DataOffset = 0;
5124 pSMB->SetupCount = 1;
5125 pSMB->Reserved3 = 0;
5126 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5127 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
5128 inc_rfc1001_len(pSMB, byte_count);
5129 pSMB->ByteCount = cpu_to_le16(byte_count);
5130
5131 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5132 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5133 if (rc) {
5134 cifs_dbg(FYI, "Send error in QFSDeviceInfo = %d\n", rc);
5135 } else {
5136 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5137
5138 if (rc || get_bcc(&pSMBr->hdr) <
5139 sizeof(FILE_SYSTEM_DEVICE_INFO))
5140 rc = -EIO;
5141 else {
5142 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5143 response_data =
5144 (FILE_SYSTEM_DEVICE_INFO *)
5145 (((char *) &pSMBr->hdr.Protocol) +
5146 data_offset);
5147 memcpy(&tcon->fsDevInfo, response_data,
5148 sizeof(FILE_SYSTEM_DEVICE_INFO));
5149 }
5150 }
5151 cifs_buf_release(pSMB);
5152
5153 if (rc == -EAGAIN)
5154 goto QFSDeviceRetry;
5155
5156 return rc;
5157}
5158
5159int
5160CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)
5161{
5162
5163 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5164 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5165 FILE_SYSTEM_UNIX_INFO *response_data;
5166 int rc = 0;
5167 int bytes_returned = 0;
5168 __u16 params, byte_count;
5169
5170 cifs_dbg(FYI, "In QFSUnixInfo\n");
5171QFSUnixRetry:
5172 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5173 (void **) &pSMB, (void **) &pSMBr);
5174 if (rc)
5175 return rc;
5176
5177 params = 2;
5178 pSMB->TotalDataCount = 0;
5179 pSMB->DataCount = 0;
5180 pSMB->DataOffset = 0;
5181 pSMB->MaxParameterCount = cpu_to_le16(2);
5182
5183 pSMB->MaxDataCount = cpu_to_le16(100);
5184 pSMB->MaxSetupCount = 0;
5185 pSMB->Reserved = 0;
5186 pSMB->Flags = 0;
5187 pSMB->Timeout = 0;
5188 pSMB->Reserved2 = 0;
5189 byte_count = params + 1 ;
5190 pSMB->ParameterCount = cpu_to_le16(params);
5191 pSMB->TotalParameterCount = pSMB->ParameterCount;
5192 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5193 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5194 pSMB->SetupCount = 1;
5195 pSMB->Reserved3 = 0;
5196 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5197 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
5198 inc_rfc1001_len(pSMB, byte_count);
5199 pSMB->ByteCount = cpu_to_le16(byte_count);
5200
5201 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5202 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5203 if (rc) {
5204 cifs_dbg(VFS, "Send error in QFSUnixInfo = %d\n", rc);
5205 } else {
5206 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5207
5208 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5209 rc = -EIO;
5210 } else {
5211 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5212 response_data =
5213 (FILE_SYSTEM_UNIX_INFO
5214 *) (((char *) &pSMBr->hdr.Protocol) +
5215 data_offset);
5216 memcpy(&tcon->fsUnixInfo, response_data,
5217 sizeof(FILE_SYSTEM_UNIX_INFO));
5218 }
5219 }
5220 cifs_buf_release(pSMB);
5221
5222 if (rc == -EAGAIN)
5223 goto QFSUnixRetry;
5224
5225
5226 return rc;
5227}
5228
5229int
5230CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)
5231{
5232
5233 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
5234 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
5235 int rc = 0;
5236 int bytes_returned = 0;
5237 __u16 params, param_offset, offset, byte_count;
5238
5239 cifs_dbg(FYI, "In SETFSUnixInfo\n");
5240SETFSUnixRetry:
5241
5242 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5243 (void **) &pSMB, (void **) &pSMBr);
5244 if (rc)
5245 return rc;
5246
5247 params = 4;
5248 pSMB->MaxSetupCount = 0;
5249 pSMB->Reserved = 0;
5250 pSMB->Flags = 0;
5251 pSMB->Timeout = 0;
5252 pSMB->Reserved2 = 0;
5253 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
5254 - 4;
5255 offset = param_offset + params;
5256
5257 pSMB->MaxParameterCount = cpu_to_le16(4);
5258
5259 pSMB->MaxDataCount = cpu_to_le16(100);
5260 pSMB->SetupCount = 1;
5261 pSMB->Reserved3 = 0;
5262 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
5263 byte_count = 1 + params + 12;
5264
5265 pSMB->DataCount = cpu_to_le16(12);
5266 pSMB->ParameterCount = cpu_to_le16(params);
5267 pSMB->TotalDataCount = pSMB->DataCount;
5268 pSMB->TotalParameterCount = pSMB->ParameterCount;
5269 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5270 pSMB->DataOffset = cpu_to_le16(offset);
5271
5272
5273 pSMB->FileNum = 0;
5274 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
5275
5276
5277 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
5278 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
5279 pSMB->ClientUnixCap = cpu_to_le64(cap);
5280
5281 inc_rfc1001_len(pSMB, byte_count);
5282 pSMB->ByteCount = cpu_to_le16(byte_count);
5283
5284 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5285 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5286 if (rc) {
5287 cifs_dbg(VFS, "Send error in SETFSUnixInfo = %d\n", rc);
5288 } else {
5289 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5290 if (rc)
5291 rc = -EIO;
5292 }
5293 cifs_buf_release(pSMB);
5294
5295 if (rc == -EAGAIN)
5296 goto SETFSUnixRetry;
5297
5298 return rc;
5299}
5300
5301
5302
5303int
5304CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
5305 struct kstatfs *FSData)
5306{
5307
5308 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5309 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5310 FILE_SYSTEM_POSIX_INFO *response_data;
5311 int rc = 0;
5312 int bytes_returned = 0;
5313 __u16 params, byte_count;
5314
5315 cifs_dbg(FYI, "In QFSPosixInfo\n");
5316QFSPosixRetry:
5317 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5318 (void **) &pSMBr);
5319 if (rc)
5320 return rc;
5321
5322 params = 2;
5323 pSMB->TotalDataCount = 0;
5324 pSMB->DataCount = 0;
5325 pSMB->DataOffset = 0;
5326 pSMB->MaxParameterCount = cpu_to_le16(2);
5327
5328 pSMB->MaxDataCount = cpu_to_le16(100);
5329 pSMB->MaxSetupCount = 0;
5330 pSMB->Reserved = 0;
5331 pSMB->Flags = 0;
5332 pSMB->Timeout = 0;
5333 pSMB->Reserved2 = 0;
5334 byte_count = params + 1 ;
5335 pSMB->ParameterCount = cpu_to_le16(params);
5336 pSMB->TotalParameterCount = pSMB->ParameterCount;
5337 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5338 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5339 pSMB->SetupCount = 1;
5340 pSMB->Reserved3 = 0;
5341 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5342 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5343 inc_rfc1001_len(pSMB, byte_count);
5344 pSMB->ByteCount = cpu_to_le16(byte_count);
5345
5346 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5347 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5348 if (rc) {
5349 cifs_dbg(FYI, "Send error in QFSUnixInfo = %d\n", rc);
5350 } else {
5351 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5352
5353 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5354 rc = -EIO;
5355 } else {
5356 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5357 response_data =
5358 (FILE_SYSTEM_POSIX_INFO
5359 *) (((char *) &pSMBr->hdr.Protocol) +
5360 data_offset);
5361 FSData->f_bsize =
5362 le32_to_cpu(response_data->BlockSize);
5363
5364
5365
5366
5367 if (FSData->f_bsize < 512)
5368 FSData->f_bsize = 4096;
5369
5370 FSData->f_blocks =
5371 le64_to_cpu(response_data->TotalBlocks);
5372 FSData->f_bfree =
5373 le64_to_cpu(response_data->BlocksAvail);
5374 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5375 FSData->f_bavail = FSData->f_bfree;
5376 } else {
5377 FSData->f_bavail =
5378 le64_to_cpu(response_data->UserBlocksAvail);
5379 }
5380 if (response_data->TotalFileNodes != cpu_to_le64(-1))
5381 FSData->f_files =
5382 le64_to_cpu(response_data->TotalFileNodes);
5383 if (response_data->FreeFileNodes != cpu_to_le64(-1))
5384 FSData->f_ffree =
5385 le64_to_cpu(response_data->FreeFileNodes);
5386 }
5387 }
5388 cifs_buf_release(pSMB);
5389
5390 if (rc == -EAGAIN)
5391 goto QFSPosixRetry;
5392
5393 return rc;
5394}
5395
5396
5397
5398
5399
5400
5401
5402
5403int
5404CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
5405 const char *file_name, __u64 size, struct cifs_sb_info *cifs_sb,
5406 bool set_allocation)
5407{
5408 struct smb_com_transaction2_spi_req *pSMB = NULL;
5409 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5410 struct file_end_of_file_info *parm_data;
5411 int name_len;
5412 int rc = 0;
5413 int bytes_returned = 0;
5414 int remap = cifs_remap(cifs_sb);
5415
5416 __u16 params, byte_count, data_count, param_offset, offset;
5417
5418 cifs_dbg(FYI, "In SetEOF\n");
5419SetEOFRetry:
5420 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5421 (void **) &pSMBr);
5422 if (rc)
5423 return rc;
5424
5425 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5426 name_len =
5427 cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
5428 PATH_MAX, cifs_sb->local_nls, remap);
5429 name_len++;
5430 name_len *= 2;
5431 } else {
5432 name_len = copy_path_name(pSMB->FileName, file_name);
5433 }
5434 params = 6 + name_len;
5435 data_count = sizeof(struct file_end_of_file_info);
5436 pSMB->MaxParameterCount = cpu_to_le16(2);
5437 pSMB->MaxDataCount = cpu_to_le16(4100);
5438 pSMB->MaxSetupCount = 0;
5439 pSMB->Reserved = 0;
5440 pSMB->Flags = 0;
5441 pSMB->Timeout = 0;
5442 pSMB->Reserved2 = 0;
5443 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5444 InformationLevel) - 4;
5445 offset = param_offset + params;
5446 if (set_allocation) {
5447 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5448 pSMB->InformationLevel =
5449 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5450 else
5451 pSMB->InformationLevel =
5452 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5453 } else {
5454 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5455 pSMB->InformationLevel =
5456 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5457 else
5458 pSMB->InformationLevel =
5459 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5460 }
5461
5462 parm_data =
5463 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5464 offset);
5465 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5466 pSMB->DataOffset = cpu_to_le16(offset);
5467 pSMB->SetupCount = 1;
5468 pSMB->Reserved3 = 0;
5469 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5470 byte_count = 3 + params + data_count;
5471 pSMB->DataCount = cpu_to_le16(data_count);
5472 pSMB->TotalDataCount = pSMB->DataCount;
5473 pSMB->ParameterCount = cpu_to_le16(params);
5474 pSMB->TotalParameterCount = pSMB->ParameterCount;
5475 pSMB->Reserved4 = 0;
5476 inc_rfc1001_len(pSMB, byte_count);
5477 parm_data->FileSize = cpu_to_le64(size);
5478 pSMB->ByteCount = cpu_to_le16(byte_count);
5479 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5480 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5481 if (rc)
5482 cifs_dbg(FYI, "SetPathInfo (file size) returned %d\n", rc);
5483
5484 cifs_buf_release(pSMB);
5485
5486 if (rc == -EAGAIN)
5487 goto SetEOFRetry;
5488
5489 return rc;
5490}
5491
5492int
5493CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
5494 struct cifsFileInfo *cfile, __u64 size, bool set_allocation)
5495{
5496 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5497 struct file_end_of_file_info *parm_data;
5498 int rc = 0;
5499 __u16 params, param_offset, offset, byte_count, count;
5500
5501 cifs_dbg(FYI, "SetFileSize (via SetFileInfo) %lld\n",
5502 (long long)size);
5503 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5504
5505 if (rc)
5506 return rc;
5507
5508 pSMB->hdr.Pid = cpu_to_le16((__u16)cfile->pid);
5509 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(cfile->pid >> 16));
5510
5511 params = 6;
5512 pSMB->MaxSetupCount = 0;
5513 pSMB->Reserved = 0;
5514 pSMB->Flags = 0;
5515 pSMB->Timeout = 0;
5516 pSMB->Reserved2 = 0;
5517 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5518 offset = param_offset + params;
5519
5520 count = sizeof(struct file_end_of_file_info);
5521 pSMB->MaxParameterCount = cpu_to_le16(2);
5522
5523 pSMB->MaxDataCount = cpu_to_le16(1000);
5524 pSMB->SetupCount = 1;
5525 pSMB->Reserved3 = 0;
5526 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5527 byte_count = 3 + params + count;
5528 pSMB->DataCount = cpu_to_le16(count);
5529 pSMB->ParameterCount = cpu_to_le16(params);
5530 pSMB->TotalDataCount = pSMB->DataCount;
5531 pSMB->TotalParameterCount = pSMB->ParameterCount;
5532 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5533
5534 parm_data =
5535 (struct file_end_of_file_info *)(((char *)pSMB) + offset + 4);
5536 pSMB->DataOffset = cpu_to_le16(offset);
5537 parm_data->FileSize = cpu_to_le64(size);
5538 pSMB->Fid = cfile->fid.netfid;
5539 if (set_allocation) {
5540 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5541 pSMB->InformationLevel =
5542 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5543 else
5544 pSMB->InformationLevel =
5545 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5546 } else {
5547 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5548 pSMB->InformationLevel =
5549 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5550 else
5551 pSMB->InformationLevel =
5552 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5553 }
5554 pSMB->Reserved4 = 0;
5555 inc_rfc1001_len(pSMB, byte_count);
5556 pSMB->ByteCount = cpu_to_le16(byte_count);
5557 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5558 cifs_small_buf_release(pSMB);
5559 if (rc) {
5560 cifs_dbg(FYI, "Send error in SetFileInfo (SetFileSize) = %d\n",
5561 rc);
5562 }
5563
5564
5565
5566
5567 return rc;
5568}
5569
5570
5571
5572
5573
5574
5575
5576int
5577CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5578 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5579{
5580 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5581 char *data_offset;
5582 int rc = 0;
5583 __u16 params, param_offset, offset, byte_count, count;
5584
5585 cifs_dbg(FYI, "Set Times (via SetFileInfo)\n");
5586 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5587
5588 if (rc)
5589 return rc;
5590
5591 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5592 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5593
5594 params = 6;
5595 pSMB->MaxSetupCount = 0;
5596 pSMB->Reserved = 0;
5597 pSMB->Flags = 0;
5598 pSMB->Timeout = 0;
5599 pSMB->Reserved2 = 0;
5600 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5601 offset = param_offset + params;
5602
5603 data_offset = (char *)pSMB +
5604 offsetof(struct smb_hdr, Protocol) + offset;
5605
5606 count = sizeof(FILE_BASIC_INFO);
5607 pSMB->MaxParameterCount = cpu_to_le16(2);
5608
5609 pSMB->MaxDataCount = cpu_to_le16(1000);
5610 pSMB->SetupCount = 1;
5611 pSMB->Reserved3 = 0;
5612 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5613 byte_count = 3 + params + count;
5614 pSMB->DataCount = cpu_to_le16(count);
5615 pSMB->ParameterCount = cpu_to_le16(params);
5616 pSMB->TotalDataCount = pSMB->DataCount;
5617 pSMB->TotalParameterCount = pSMB->ParameterCount;
5618 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5619 pSMB->DataOffset = cpu_to_le16(offset);
5620 pSMB->Fid = fid;
5621 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5622 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5623 else
5624 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5625 pSMB->Reserved4 = 0;
5626 inc_rfc1001_len(pSMB, byte_count);
5627 pSMB->ByteCount = cpu_to_le16(byte_count);
5628 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5629 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5630 cifs_small_buf_release(pSMB);
5631 if (rc)
5632 cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
5633 rc);
5634
5635
5636
5637
5638 return rc;
5639}
5640
5641int
5642CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
5643 bool delete_file, __u16 fid, __u32 pid_of_opener)
5644{
5645 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5646 char *data_offset;
5647 int rc = 0;
5648 __u16 params, param_offset, offset, byte_count, count;
5649
5650 cifs_dbg(FYI, "Set File Disposition (via SetFileInfo)\n");
5651 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5652
5653 if (rc)
5654 return rc;
5655
5656 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5657 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5658
5659 params = 6;
5660 pSMB->MaxSetupCount = 0;
5661 pSMB->Reserved = 0;
5662 pSMB->Flags = 0;
5663 pSMB->Timeout = 0;
5664 pSMB->Reserved2 = 0;
5665 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5666 offset = param_offset + params;
5667
5668
5669 data_offset = (char *)(pSMB) + offset + 4;
5670
5671 count = 1;
5672 pSMB->MaxParameterCount = cpu_to_le16(2);
5673
5674 pSMB->MaxDataCount = cpu_to_le16(1000);
5675 pSMB->SetupCount = 1;
5676 pSMB->Reserved3 = 0;
5677 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5678 byte_count = 3 + params + count;
5679 pSMB->DataCount = cpu_to_le16(count);
5680 pSMB->ParameterCount = cpu_to_le16(params);
5681 pSMB->TotalDataCount = pSMB->DataCount;
5682 pSMB->TotalParameterCount = pSMB->ParameterCount;
5683 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5684 pSMB->DataOffset = cpu_to_le16(offset);
5685 pSMB->Fid = fid;
5686 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5687 pSMB->Reserved4 = 0;
5688 inc_rfc1001_len(pSMB, byte_count);
5689 pSMB->ByteCount = cpu_to_le16(byte_count);
5690 *data_offset = delete_file ? 1 : 0;
5691 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5692 cifs_small_buf_release(pSMB);
5693 if (rc)
5694 cifs_dbg(FYI, "Send error in SetFileDisposition = %d\n", rc);
5695
5696 return rc;
5697}
5698
5699static int
5700CIFSSMBSetPathInfoFB(const unsigned int xid, struct cifs_tcon *tcon,
5701 const char *fileName, const FILE_BASIC_INFO *data,
5702 const struct nls_table *nls_codepage,
5703 struct cifs_sb_info *cifs_sb)
5704{
5705 int oplock = 0;
5706 struct cifs_open_parms oparms;
5707 struct cifs_fid fid;
5708 int rc;
5709
5710 oparms.tcon = tcon;
5711 oparms.cifs_sb = cifs_sb;
5712 oparms.desired_access = GENERIC_WRITE;
5713 oparms.create_options = cifs_create_options(cifs_sb, 0);
5714 oparms.disposition = FILE_OPEN;
5715 oparms.path = fileName;
5716 oparms.fid = &fid;
5717 oparms.reconnect = false;
5718
5719 rc = CIFS_open(xid, &oparms, &oplock, NULL);
5720 if (rc)
5721 goto out;
5722
5723 rc = CIFSSMBSetFileInfo(xid, tcon, data, fid.netfid, current->tgid);
5724 CIFSSMBClose(xid, tcon, fid.netfid);
5725out:
5726
5727 return rc;
5728}
5729
5730int
5731CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5732 const char *fileName, const FILE_BASIC_INFO *data,
5733 const struct nls_table *nls_codepage,
5734 struct cifs_sb_info *cifs_sb)
5735{
5736 TRANSACTION2_SPI_REQ *pSMB = NULL;
5737 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5738 int name_len;
5739 int rc = 0;
5740 int bytes_returned = 0;
5741 char *data_offset;
5742 __u16 params, param_offset, offset, byte_count, count;
5743 int remap = cifs_remap(cifs_sb);
5744
5745 cifs_dbg(FYI, "In SetTimes\n");
5746
5747SetTimesRetry:
5748 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5749 (void **) &pSMBr);
5750 if (rc)
5751 return rc;
5752
5753 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5754 name_len =
5755 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5756 PATH_MAX, nls_codepage, remap);
5757 name_len++;
5758 name_len *= 2;
5759 } else {
5760 name_len = copy_path_name(pSMB->FileName, fileName);
5761 }
5762
5763 params = 6 + name_len;
5764 count = sizeof(FILE_BASIC_INFO);
5765 pSMB->MaxParameterCount = cpu_to_le16(2);
5766
5767 pSMB->MaxDataCount = cpu_to_le16(1000);
5768 pSMB->MaxSetupCount = 0;
5769 pSMB->Reserved = 0;
5770 pSMB->Flags = 0;
5771 pSMB->Timeout = 0;
5772 pSMB->Reserved2 = 0;
5773 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5774 InformationLevel) - 4;
5775 offset = param_offset + params;
5776 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5777 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5778 pSMB->DataOffset = cpu_to_le16(offset);
5779 pSMB->SetupCount = 1;
5780 pSMB->Reserved3 = 0;
5781 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5782 byte_count = 3 + params + count;
5783
5784 pSMB->DataCount = cpu_to_le16(count);
5785 pSMB->ParameterCount = cpu_to_le16(params);
5786 pSMB->TotalDataCount = pSMB->DataCount;
5787 pSMB->TotalParameterCount = pSMB->ParameterCount;
5788 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5789 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5790 else
5791 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5792 pSMB->Reserved4 = 0;
5793 inc_rfc1001_len(pSMB, byte_count);
5794 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5795 pSMB->ByteCount = cpu_to_le16(byte_count);
5796 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5797 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5798 if (rc)
5799 cifs_dbg(FYI, "SetPathInfo (times) returned %d\n", rc);
5800
5801 cifs_buf_release(pSMB);
5802
5803 if (rc == -EAGAIN)
5804 goto SetTimesRetry;
5805
5806 if (rc == -EOPNOTSUPP)
5807 return CIFSSMBSetPathInfoFB(xid, tcon, fileName, data,
5808 nls_codepage, cifs_sb);
5809
5810 return rc;
5811}
5812
5813static void
5814cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5815 const struct cifs_unix_set_info_args *args)
5816{
5817 u64 uid = NO_CHANGE_64, gid = NO_CHANGE_64;
5818 u64 mode = args->mode;
5819
5820 if (uid_valid(args->uid))
5821 uid = from_kuid(&init_user_ns, args->uid);
5822 if (gid_valid(args->gid))
5823 gid = from_kgid(&init_user_ns, args->gid);
5824
5825
5826
5827
5828
5829
5830
5831
5832 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5833 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5834 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5835 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5836 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5837 data_offset->Uid = cpu_to_le64(uid);
5838 data_offset->Gid = cpu_to_le64(gid);
5839
5840 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5841 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5842 data_offset->Permissions = cpu_to_le64(mode);
5843
5844 if (S_ISREG(mode))
5845 data_offset->Type = cpu_to_le32(UNIX_FILE);
5846 else if (S_ISDIR(mode))
5847 data_offset->Type = cpu_to_le32(UNIX_DIR);
5848 else if (S_ISLNK(mode))
5849 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5850 else if (S_ISCHR(mode))
5851 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5852 else if (S_ISBLK(mode))
5853 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5854 else if (S_ISFIFO(mode))
5855 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5856 else if (S_ISSOCK(mode))
5857 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5858}
5859
5860int
5861CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5862 const struct cifs_unix_set_info_args *args,
5863 u16 fid, u32 pid_of_opener)
5864{
5865 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5866 char *data_offset;
5867 int rc = 0;
5868 u16 params, param_offset, offset, byte_count, count;
5869
5870 cifs_dbg(FYI, "Set Unix Info (via SetFileInfo)\n");
5871 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5872
5873 if (rc)
5874 return rc;
5875
5876 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5877 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5878
5879 params = 6;
5880 pSMB->MaxSetupCount = 0;
5881 pSMB->Reserved = 0;
5882 pSMB->Flags = 0;
5883 pSMB->Timeout = 0;
5884 pSMB->Reserved2 = 0;
5885 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5886 offset = param_offset + params;
5887
5888 data_offset = (char *)pSMB +
5889 offsetof(struct smb_hdr, Protocol) + offset;
5890
5891 count = sizeof(FILE_UNIX_BASIC_INFO);
5892
5893 pSMB->MaxParameterCount = cpu_to_le16(2);
5894
5895 pSMB->MaxDataCount = cpu_to_le16(1000);
5896 pSMB->SetupCount = 1;
5897 pSMB->Reserved3 = 0;
5898 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5899 byte_count = 3 + params + count;
5900 pSMB->DataCount = cpu_to_le16(count);
5901 pSMB->ParameterCount = cpu_to_le16(params);
5902 pSMB->TotalDataCount = pSMB->DataCount;
5903 pSMB->TotalParameterCount = pSMB->ParameterCount;
5904 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5905 pSMB->DataOffset = cpu_to_le16(offset);
5906 pSMB->Fid = fid;
5907 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5908 pSMB->Reserved4 = 0;
5909 inc_rfc1001_len(pSMB, byte_count);
5910 pSMB->ByteCount = cpu_to_le16(byte_count);
5911
5912 cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
5913
5914 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5915 cifs_small_buf_release(pSMB);
5916 if (rc)
5917 cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
5918 rc);
5919
5920
5921
5922
5923 return rc;
5924}
5925
5926int
5927CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5928 const char *file_name,
5929 const struct cifs_unix_set_info_args *args,
5930 const struct nls_table *nls_codepage, int remap)
5931{
5932 TRANSACTION2_SPI_REQ *pSMB = NULL;
5933 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5934 int name_len;
5935 int rc = 0;
5936 int bytes_returned = 0;
5937 FILE_UNIX_BASIC_INFO *data_offset;
5938 __u16 params, param_offset, offset, count, byte_count;
5939
5940 cifs_dbg(FYI, "In SetUID/GID/Mode\n");
5941setPermsRetry:
5942 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5943 (void **) &pSMBr);
5944 if (rc)
5945 return rc;
5946
5947 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5948 name_len =
5949 cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
5950 PATH_MAX, nls_codepage, remap);
5951 name_len++;
5952 name_len *= 2;
5953 } else {
5954 name_len = copy_path_name(pSMB->FileName, file_name);
5955 }
5956
5957 params = 6 + name_len;
5958 count = sizeof(FILE_UNIX_BASIC_INFO);
5959 pSMB->MaxParameterCount = cpu_to_le16(2);
5960
5961 pSMB->MaxDataCount = cpu_to_le16(1000);
5962 pSMB->MaxSetupCount = 0;
5963 pSMB->Reserved = 0;
5964 pSMB->Flags = 0;
5965 pSMB->Timeout = 0;
5966 pSMB->Reserved2 = 0;
5967 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5968 InformationLevel) - 4;
5969 offset = param_offset + params;
5970
5971 data_offset = (FILE_UNIX_BASIC_INFO *)((char *) pSMB + offset + 4);
5972 memset(data_offset, 0, count);
5973 pSMB->DataOffset = cpu_to_le16(offset);
5974 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5975 pSMB->SetupCount = 1;
5976 pSMB->Reserved3 = 0;
5977 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5978 byte_count = 3 + params + count;
5979 pSMB->ParameterCount = cpu_to_le16(params);
5980 pSMB->DataCount = cpu_to_le16(count);
5981 pSMB->TotalParameterCount = pSMB->ParameterCount;
5982 pSMB->TotalDataCount = pSMB->DataCount;
5983 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5984 pSMB->Reserved4 = 0;
5985 inc_rfc1001_len(pSMB, byte_count);
5986
5987 cifs_fill_unix_set_info(data_offset, args);
5988
5989 pSMB->ByteCount = cpu_to_le16(byte_count);
5990 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5991 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5992 if (rc)
5993 cifs_dbg(FYI, "SetPathInfo (perms) returned %d\n", rc);
5994
5995 cifs_buf_release(pSMB);
5996 if (rc == -EAGAIN)
5997 goto setPermsRetry;
5998 return rc;
5999}
6000
6001#ifdef CONFIG_CIFS_XATTR
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011ssize_t
6012CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
6013 const unsigned char *searchName, const unsigned char *ea_name,
6014 char *EAData, size_t buf_size,
6015 struct cifs_sb_info *cifs_sb)
6016{
6017
6018 TRANSACTION2_QPI_REQ *pSMB = NULL;
6019 TRANSACTION2_QPI_RSP *pSMBr = NULL;
6020 int remap = cifs_remap(cifs_sb);
6021 struct nls_table *nls_codepage = cifs_sb->local_nls;
6022 int rc = 0;
6023 int bytes_returned;
6024 int list_len;
6025 struct fealist *ea_response_data;
6026 struct fea *temp_fea;
6027 char *temp_ptr;
6028 char *end_of_smb;
6029 __u16 params, byte_count, data_offset;
6030 unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
6031
6032 cifs_dbg(FYI, "In Query All EAs path %s\n", searchName);
6033QAllEAsRetry:
6034 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6035 (void **) &pSMBr);
6036 if (rc)
6037 return rc;
6038
6039 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6040 list_len =
6041 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
6042 PATH_MAX, nls_codepage, remap);
6043 list_len++;
6044 list_len *= 2;
6045 } else {
6046 list_len = copy_path_name(pSMB->FileName, searchName);
6047 }
6048
6049 params = 2 + 4 + list_len ;
6050 pSMB->TotalDataCount = 0;
6051 pSMB->MaxParameterCount = cpu_to_le16(2);
6052
6053 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
6054 pSMB->MaxSetupCount = 0;
6055 pSMB->Reserved = 0;
6056 pSMB->Flags = 0;
6057 pSMB->Timeout = 0;
6058 pSMB->Reserved2 = 0;
6059 pSMB->ParameterOffset = cpu_to_le16(offsetof(
6060 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
6061 pSMB->DataCount = 0;
6062 pSMB->DataOffset = 0;
6063 pSMB->SetupCount = 1;
6064 pSMB->Reserved3 = 0;
6065 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
6066 byte_count = params + 1 ;
6067 pSMB->TotalParameterCount = cpu_to_le16(params);
6068 pSMB->ParameterCount = pSMB->TotalParameterCount;
6069 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
6070 pSMB->Reserved4 = 0;
6071 inc_rfc1001_len(pSMB, byte_count);
6072 pSMB->ByteCount = cpu_to_le16(byte_count);
6073
6074 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6075 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6076 if (rc) {
6077 cifs_dbg(FYI, "Send error in QueryAllEAs = %d\n", rc);
6078 goto QAllEAsOut;
6079 }
6080
6081
6082
6083
6084
6085
6086 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
6087 if (rc || get_bcc(&pSMBr->hdr) < 4) {
6088 rc = -EIO;
6089 goto QAllEAsOut;
6090 }
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
6101 ea_response_data = (struct fealist *)
6102 (((char *) &pSMBr->hdr.Protocol) + data_offset);
6103
6104 list_len = le32_to_cpu(ea_response_data->list_len);
6105 cifs_dbg(FYI, "ea length %d\n", list_len);
6106 if (list_len <= 8) {
6107 cifs_dbg(FYI, "empty EA list returned from server\n");
6108
6109 if (ea_name)
6110 rc = -ENODATA;
6111 goto QAllEAsOut;
6112 }
6113
6114
6115 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
6116 if ((char *)ea_response_data + list_len > end_of_smb) {
6117 cifs_dbg(FYI, "EA list appears to go beyond SMB\n");
6118 rc = -EIO;
6119 goto QAllEAsOut;
6120 }
6121
6122
6123 list_len -= 4;
6124 temp_fea = ea_response_data->list;
6125 temp_ptr = (char *)temp_fea;
6126 while (list_len > 0) {
6127 unsigned int name_len;
6128 __u16 value_len;
6129
6130 list_len -= 4;
6131 temp_ptr += 4;
6132
6133 if (list_len < 0) {
6134 cifs_dbg(FYI, "EA entry goes beyond length of list\n");
6135 rc = -EIO;
6136 goto QAllEAsOut;
6137 }
6138
6139 name_len = temp_fea->name_len;
6140 value_len = le16_to_cpu(temp_fea->value_len);
6141 list_len -= name_len + 1 + value_len;
6142 if (list_len < 0) {
6143 cifs_dbg(FYI, "EA entry goes beyond length of list\n");
6144 rc = -EIO;
6145 goto QAllEAsOut;
6146 }
6147
6148 if (ea_name) {
6149 if (ea_name_len == name_len &&
6150 memcmp(ea_name, temp_ptr, name_len) == 0) {
6151 temp_ptr += name_len + 1;
6152 rc = value_len;
6153 if (buf_size == 0)
6154 goto QAllEAsOut;
6155 if ((size_t)value_len > buf_size) {
6156 rc = -ERANGE;
6157 goto QAllEAsOut;
6158 }
6159 memcpy(EAData, temp_ptr, value_len);
6160 goto QAllEAsOut;
6161 }
6162 } else {
6163
6164 rc += (5 + 1 + name_len);
6165 if (rc < (int) buf_size) {
6166 memcpy(EAData, "user.", 5);
6167 EAData += 5;
6168 memcpy(EAData, temp_ptr, name_len);
6169 EAData += name_len;
6170
6171 *EAData = 0;
6172 ++EAData;
6173 } else if (buf_size == 0) {
6174
6175 } else {
6176
6177 rc = -ERANGE;
6178 break;
6179 }
6180 }
6181 temp_ptr += name_len + 1 + value_len;
6182 temp_fea = (struct fea *)temp_ptr;
6183 }
6184
6185
6186 if (ea_name)
6187 rc = -ENODATA;
6188
6189QAllEAsOut:
6190 cifs_buf_release(pSMB);
6191 if (rc == -EAGAIN)
6192 goto QAllEAsRetry;
6193
6194 return (ssize_t)rc;
6195}
6196
6197int
6198CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
6199 const char *fileName, const char *ea_name, const void *ea_value,
6200 const __u16 ea_value_len, const struct nls_table *nls_codepage,
6201 struct cifs_sb_info *cifs_sb)
6202{
6203 struct smb_com_transaction2_spi_req *pSMB = NULL;
6204 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
6205 struct fealist *parm_data;
6206 int name_len;
6207 int rc = 0;
6208 int bytes_returned = 0;
6209 __u16 params, param_offset, byte_count, offset, count;
6210 int remap = cifs_remap(cifs_sb);
6211
6212 cifs_dbg(FYI, "In SetEA\n");
6213SetEARetry:
6214 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6215 (void **) &pSMBr);
6216 if (rc)
6217 return rc;
6218
6219 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6220 name_len =
6221 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
6222 PATH_MAX, nls_codepage, remap);
6223 name_len++;
6224 name_len *= 2;
6225 } else {
6226 name_len = copy_path_name(pSMB->FileName, fileName);
6227 }
6228
6229 params = 6 + name_len;
6230
6231
6232
6233
6234 if (ea_name == NULL)
6235 name_len = 0;
6236 else
6237 name_len = strnlen(ea_name, 255);
6238
6239 count = sizeof(*parm_data) + ea_value_len + name_len;
6240 pSMB->MaxParameterCount = cpu_to_le16(2);
6241
6242 pSMB->MaxDataCount = cpu_to_le16(1000);
6243 pSMB->MaxSetupCount = 0;
6244 pSMB->Reserved = 0;
6245 pSMB->Flags = 0;
6246 pSMB->Timeout = 0;
6247 pSMB->Reserved2 = 0;
6248 param_offset = offsetof(struct smb_com_transaction2_spi_req,
6249 InformationLevel) - 4;
6250 offset = param_offset + params;
6251 pSMB->InformationLevel =
6252 cpu_to_le16(SMB_SET_FILE_EA);
6253
6254 parm_data = (void *)pSMB + offsetof(struct smb_hdr, Protocol) + offset;
6255 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6256 pSMB->DataOffset = cpu_to_le16(offset);
6257 pSMB->SetupCount = 1;
6258 pSMB->Reserved3 = 0;
6259 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6260 byte_count = 3 + params + count;
6261 pSMB->DataCount = cpu_to_le16(count);
6262 parm_data->list_len = cpu_to_le32(count);
6263 parm_data->list[0].EA_flags = 0;
6264
6265 parm_data->list[0].name_len = (__u8)name_len;
6266
6267 if (ea_name)
6268 strncpy(parm_data->list[0].name, ea_name, name_len);
6269 parm_data->list[0].name[name_len] = 0;
6270 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
6271
6272
6273
6274
6275
6276
6277 if (ea_value_len)
6278 memcpy(parm_data->list[0].name+name_len+1,
6279 ea_value, ea_value_len);
6280
6281 pSMB->TotalDataCount = pSMB->DataCount;
6282 pSMB->ParameterCount = cpu_to_le16(params);
6283 pSMB->TotalParameterCount = pSMB->ParameterCount;
6284 pSMB->Reserved4 = 0;
6285 inc_rfc1001_len(pSMB, byte_count);
6286 pSMB->ByteCount = cpu_to_le16(byte_count);
6287 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6288 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6289 if (rc)
6290 cifs_dbg(FYI, "SetPathInfo (EA) returned %d\n", rc);
6291
6292 cifs_buf_release(pSMB);
6293
6294 if (rc == -EAGAIN)
6295 goto SetEARetry;
6296
6297 return rc;
6298}
6299#endif
6300