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