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