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