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