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