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