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