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