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