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(rsp->SrvTime.Date,
528 rsp->SrvTime.Time, 0);
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 = RawNTLMSSP;
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) || (tcon->ses->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 if (posix_flags & SMB_O_DIRECTORY)
1117 cifs_stats_inc(&tcon->num_posixmkdirs);
1118 else
1119 cifs_stats_inc(&tcon->num_posixopens);
1120
1121 if (rc == -EAGAIN)
1122 goto PsxCreat;
1123
1124 return rc;
1125}
1126
1127static __u16 convert_disposition(int disposition)
1128{
1129 __u16 ofun = 0;
1130
1131 switch (disposition) {
1132 case FILE_SUPERSEDE:
1133 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1134 break;
1135 case FILE_OPEN:
1136 ofun = SMBOPEN_OAPPEND;
1137 break;
1138 case FILE_CREATE:
1139 ofun = SMBOPEN_OCREATE;
1140 break;
1141 case FILE_OPEN_IF:
1142 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1143 break;
1144 case FILE_OVERWRITE:
1145 ofun = SMBOPEN_OTRUNC;
1146 break;
1147 case FILE_OVERWRITE_IF:
1148 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1149 break;
1150 default:
1151 cFYI(1, ("unknown disposition %d", disposition));
1152 ofun = SMBOPEN_OAPPEND;
1153 }
1154 return ofun;
1155}
1156
1157static int
1158access_flags_to_smbopen_mode(const int access_flags)
1159{
1160 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1161
1162 if (masked_flags == GENERIC_READ)
1163 return SMBOPEN_READ;
1164 else if (masked_flags == GENERIC_WRITE)
1165 return SMBOPEN_WRITE;
1166
1167
1168 return SMBOPEN_READWRITE;
1169}
1170
1171int
1172SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1173 const char *fileName, const int openDisposition,
1174 const int access_flags, const int create_options, __u16 *netfid,
1175 int *pOplock, FILE_ALL_INFO *pfile_info,
1176 const struct nls_table *nls_codepage, int remap)
1177{
1178 int rc = -EACCES;
1179 OPENX_REQ *pSMB = NULL;
1180 OPENX_RSP *pSMBr = NULL;
1181 int bytes_returned;
1182 int name_len;
1183 __u16 count;
1184
1185OldOpenRetry:
1186 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1187 (void **) &pSMBr);
1188 if (rc)
1189 return rc;
1190
1191 pSMB->AndXCommand = 0xFF;
1192
1193 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1194 count = 1;
1195 name_len =
1196 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1197 fileName, PATH_MAX, nls_codepage, remap);
1198 name_len++;
1199 name_len *= 2;
1200 } else {
1201 count = 0;
1202 name_len = strnlen(fileName, PATH_MAX);
1203 name_len++;
1204 strncpy(pSMB->fileName, fileName, name_len);
1205 }
1206 if (*pOplock & REQ_OPLOCK)
1207 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1208 else if (*pOplock & REQ_BATCHOPLOCK)
1209 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1210
1211 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1212 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1213 pSMB->Mode |= cpu_to_le16(0x40);
1214
1215
1216
1217
1218 if (create_options & CREATE_OPTION_SPECIAL)
1219 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1220 else
1221 pSMB->FileAttributes = cpu_to_le16(0);
1222
1223 if (create_options & CREATE_OPTION_READONLY)
1224 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1225
1226
1227
1228
1229
1230
1231 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1232 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1233 count += name_len;
1234 pSMB->hdr.smb_buf_length += count;
1235
1236 pSMB->ByteCount = cpu_to_le16(count);
1237
1238 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1239 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1240 cifs_stats_inc(&tcon->num_opens);
1241 if (rc) {
1242 cFYI(1, ("Error in Open = %d", rc));
1243 } else {
1244
1245
1246
1247
1248 *netfid = pSMBr->Fid;
1249
1250
1251
1252
1253
1254
1255
1256 if (pfile_info) {
1257 pfile_info->CreationTime = 0;
1258 pfile_info->LastAccessTime = 0;
1259 pfile_info->LastWriteTime = 0;
1260 pfile_info->ChangeTime = 0;
1261 pfile_info->Attributes =
1262 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1263
1264 pfile_info->AllocationSize =
1265 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1266 pfile_info->EndOfFile = pfile_info->AllocationSize;
1267 pfile_info->NumberOfLinks = cpu_to_le32(1);
1268 pfile_info->DeletePending = 0;
1269 }
1270 }
1271
1272 cifs_buf_release(pSMB);
1273 if (rc == -EAGAIN)
1274 goto OldOpenRetry;
1275 return rc;
1276}
1277
1278int
1279CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1280 const char *fileName, const int openDisposition,
1281 const int access_flags, const int create_options, __u16 *netfid,
1282 int *pOplock, FILE_ALL_INFO *pfile_info,
1283 const struct nls_table *nls_codepage, int remap)
1284{
1285 int rc = -EACCES;
1286 OPEN_REQ *pSMB = NULL;
1287 OPEN_RSP *pSMBr = NULL;
1288 int bytes_returned;
1289 int name_len;
1290 __u16 count;
1291
1292openRetry:
1293 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1294 (void **) &pSMBr);
1295 if (rc)
1296 return rc;
1297
1298 pSMB->AndXCommand = 0xFF;
1299
1300 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1301 count = 1;
1302 name_len =
1303 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1304 fileName, PATH_MAX, nls_codepage, remap);
1305 name_len++;
1306 name_len *= 2;
1307 pSMB->NameLength = cpu_to_le16(name_len);
1308 } else {
1309 count = 0;
1310 name_len = strnlen(fileName, PATH_MAX);
1311 name_len++;
1312 pSMB->NameLength = cpu_to_le16(name_len);
1313 strncpy(pSMB->fileName, fileName, name_len);
1314 }
1315 if (*pOplock & REQ_OPLOCK)
1316 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1317 else if (*pOplock & REQ_BATCHOPLOCK)
1318 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1319 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1320 pSMB->AllocationSize = 0;
1321
1322
1323
1324 if (create_options & CREATE_OPTION_SPECIAL)
1325 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1326 else
1327 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1328
1329
1330
1331
1332 if (tcon->ses->capabilities & CAP_UNIX)
1333 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1334
1335 if (create_options & CREATE_OPTION_READONLY)
1336 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1337
1338 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1339 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1340 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1341
1342 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1343 pSMB->SecurityFlags =
1344 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1345
1346 count += name_len;
1347 pSMB->hdr.smb_buf_length += count;
1348
1349 pSMB->ByteCount = cpu_to_le16(count);
1350
1351 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1352 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1353 cifs_stats_inc(&tcon->num_opens);
1354 if (rc) {
1355 cFYI(1, ("Error in Open = %d", rc));
1356 } else {
1357 *pOplock = pSMBr->OplockLevel;
1358 *netfid = pSMBr->Fid;
1359
1360
1361 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1362 *pOplock |= CIFS_CREATE_ACTION;
1363 if (pfile_info) {
1364 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1365 36 );
1366
1367 pfile_info->AllocationSize = pSMBr->AllocationSize;
1368 pfile_info->EndOfFile = pSMBr->EndOfFile;
1369 pfile_info->NumberOfLinks = cpu_to_le32(1);
1370 pfile_info->DeletePending = 0;
1371 }
1372 }
1373
1374 cifs_buf_release(pSMB);
1375 if (rc == -EAGAIN)
1376 goto openRetry;
1377 return rc;
1378}
1379
1380int
1381CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1382 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1383 char **buf, int *pbuf_type)
1384{
1385 int rc = -EACCES;
1386 READ_REQ *pSMB = NULL;
1387 READ_RSP *pSMBr = NULL;
1388 char *pReadData = NULL;
1389 int wct;
1390 int resp_buf_type = 0;
1391 struct kvec iov[1];
1392
1393 cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
1394 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1395 wct = 12;
1396 else {
1397 wct = 10;
1398 if ((lseek >> 32) > 0) {
1399
1400 return -EIO;
1401 }
1402 }
1403
1404 *nbytes = 0;
1405 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1406 if (rc)
1407 return rc;
1408
1409
1410 if (tcon->ses->server == NULL)
1411 return -ECONNABORTED;
1412
1413 pSMB->AndXCommand = 0xFF;
1414 pSMB->Fid = netfid;
1415 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1416 if (wct == 12)
1417 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1418
1419 pSMB->Remaining = 0;
1420 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1421 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1422 if (wct == 12)
1423 pSMB->ByteCount = 0;
1424 else {
1425
1426 struct smb_com_readx_req *pSMBW =
1427 (struct smb_com_readx_req *)pSMB;
1428 pSMBW->ByteCount = 0;
1429 }
1430
1431 iov[0].iov_base = (char *)pSMB;
1432 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1433 rc = SendReceive2(xid, tcon->ses, iov, 1 ,
1434 &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR);
1435 cifs_stats_inc(&tcon->num_reads);
1436 pSMBr = (READ_RSP *)iov[0].iov_base;
1437 if (rc) {
1438 cERROR(1, ("Send error in read = %d", rc));
1439 } else {
1440 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1441 data_length = data_length << 16;
1442 data_length += le16_to_cpu(pSMBr->DataLength);
1443 *nbytes = data_length;
1444
1445
1446 if ((data_length > CIFSMaxBufSize)
1447 || (data_length > count)) {
1448 cFYI(1, ("bad length %d for count %d",
1449 data_length, count));
1450 rc = -EIO;
1451 *nbytes = 0;
1452 } else {
1453 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1454 le16_to_cpu(pSMBr->DataOffset);
1455
1456
1457
1458
1459 if (*buf)
1460 memcpy(*buf, pReadData, data_length);
1461 }
1462 }
1463
1464
1465 if (*buf) {
1466 if (resp_buf_type == CIFS_SMALL_BUFFER)
1467 cifs_small_buf_release(iov[0].iov_base);
1468 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1469 cifs_buf_release(iov[0].iov_base);
1470 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1471
1472 *buf = iov[0].iov_base;
1473 if (resp_buf_type == CIFS_SMALL_BUFFER)
1474 *pbuf_type = CIFS_SMALL_BUFFER;
1475 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1476 *pbuf_type = CIFS_LARGE_BUFFER;
1477 }
1478
1479
1480
1481 return rc;
1482}
1483
1484
1485int
1486CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1487 const int netfid, const unsigned int count,
1488 const __u64 offset, unsigned int *nbytes, const char *buf,
1489 const char __user *ubuf, const int long_op)
1490{
1491 int rc = -EACCES;
1492 WRITE_REQ *pSMB = NULL;
1493 WRITE_RSP *pSMBr = NULL;
1494 int bytes_returned, wct;
1495 __u32 bytes_sent;
1496 __u16 byte_count;
1497
1498
1499 if (tcon->ses == NULL)
1500 return -ECONNABORTED;
1501
1502 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1503 wct = 14;
1504 else {
1505 wct = 12;
1506 if ((offset >> 32) > 0) {
1507
1508 return -EIO;
1509 }
1510 }
1511
1512 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1513 (void **) &pSMBr);
1514 if (rc)
1515 return rc;
1516
1517 if (tcon->ses->server == NULL)
1518 return -ECONNABORTED;
1519
1520 pSMB->AndXCommand = 0xFF;
1521 pSMB->Fid = netfid;
1522 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1523 if (wct == 14)
1524 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1525
1526 pSMB->Reserved = 0xFFFFFFFF;
1527 pSMB->WriteMode = 0;
1528 pSMB->Remaining = 0;
1529
1530
1531
1532
1533
1534 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1535 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1536 } else {
1537 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1538 & ~0xFF;
1539 }
1540
1541 if (bytes_sent > count)
1542 bytes_sent = count;
1543 pSMB->DataOffset =
1544 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1545 if (buf)
1546 memcpy(pSMB->Data, buf, bytes_sent);
1547 else if (ubuf) {
1548 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1549 cifs_buf_release(pSMB);
1550 return -EFAULT;
1551 }
1552 } else if (count != 0) {
1553
1554 cifs_buf_release(pSMB);
1555 return -EINVAL;
1556 }
1557 if (wct == 14)
1558 byte_count = bytes_sent + 1;
1559 else
1560 byte_count = bytes_sent + 5;
1561
1562 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1563 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1564 pSMB->hdr.smb_buf_length += byte_count;
1565
1566 if (wct == 14)
1567 pSMB->ByteCount = cpu_to_le16(byte_count);
1568 else {
1569
1570 struct smb_com_writex_req *pSMBW =
1571 (struct smb_com_writex_req *)pSMB;
1572 pSMBW->ByteCount = cpu_to_le16(byte_count);
1573 }
1574
1575 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1576 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1577 cifs_stats_inc(&tcon->num_writes);
1578 if (rc) {
1579 cFYI(1, ("Send error in write = %d", rc));
1580 *nbytes = 0;
1581 } else {
1582 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1583 *nbytes = (*nbytes) << 16;
1584 *nbytes += le16_to_cpu(pSMBr->Count);
1585 }
1586
1587 cifs_buf_release(pSMB);
1588
1589
1590
1591
1592 return rc;
1593}
1594
1595int
1596CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1597 const int netfid, const unsigned int count,
1598 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1599 int n_vec, const int long_op)
1600{
1601 int rc = -EACCES;
1602 WRITE_REQ *pSMB = NULL;
1603 int wct;
1604 int smb_hdr_len;
1605 int resp_buf_type = 0;
1606
1607 *nbytes = 0;
1608
1609 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1610
1611 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1612 wct = 14;
1613 } else {
1614 wct = 12;
1615 if ((offset >> 32) > 0) {
1616
1617 return -EIO;
1618 }
1619 }
1620 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1621 if (rc)
1622 return rc;
1623
1624 if (tcon->ses->server == NULL)
1625 return -ECONNABORTED;
1626
1627 pSMB->AndXCommand = 0xFF;
1628 pSMB->Fid = netfid;
1629 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1630 if (wct == 14)
1631 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1632 pSMB->Reserved = 0xFFFFFFFF;
1633 pSMB->WriteMode = 0;
1634 pSMB->Remaining = 0;
1635
1636 pSMB->DataOffset =
1637 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1638
1639 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1640 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1641 smb_hdr_len = pSMB->hdr.smb_buf_length + 1;
1642 if (wct == 14)
1643 pSMB->hdr.smb_buf_length += count+1;
1644 else
1645 pSMB->hdr.smb_buf_length += count+5;
1646 if (wct == 14)
1647 pSMB->ByteCount = cpu_to_le16(count + 1);
1648 else {
1649 struct smb_com_writex_req *pSMBW =
1650 (struct smb_com_writex_req *)pSMB;
1651 pSMBW->ByteCount = cpu_to_le16(count + 5);
1652 }
1653 iov[0].iov_base = pSMB;
1654 if (wct == 14)
1655 iov[0].iov_len = smb_hdr_len + 4;
1656 else
1657 iov[0].iov_len = smb_hdr_len + 8;
1658
1659
1660 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1661 long_op);
1662 cifs_stats_inc(&tcon->num_writes);
1663 if (rc) {
1664 cFYI(1, ("Send error Write2 = %d", rc));
1665 } else if (resp_buf_type == 0) {
1666
1667 rc = -EIO;
1668 } else {
1669 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
1670 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1671 *nbytes = (*nbytes) << 16;
1672 *nbytes += le16_to_cpu(pSMBr->Count);
1673 }
1674
1675
1676 if (resp_buf_type == CIFS_SMALL_BUFFER)
1677 cifs_small_buf_release(iov[0].iov_base);
1678 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1679 cifs_buf_release(iov[0].iov_base);
1680
1681
1682
1683
1684 return rc;
1685}
1686
1687
1688int
1689CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1690 const __u16 smb_file_id, const __u64 len,
1691 const __u64 offset, const __u32 numUnlock,
1692 const __u32 numLock, const __u8 lockType, const bool waitFlag)
1693{
1694 int rc = 0;
1695 LOCK_REQ *pSMB = NULL;
1696
1697 int bytes_returned;
1698 int timeout = 0;
1699 __u16 count;
1700
1701 cFYI(1, ("CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock));
1702 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1703
1704 if (rc)
1705 return rc;
1706
1707 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1708 timeout = CIFS_ASYNC_OP;
1709 pSMB->Timeout = 0;
1710 } else if (waitFlag) {
1711 timeout = CIFS_BLOCKING_OP;
1712 pSMB->Timeout = cpu_to_le32(-1);
1713 } else {
1714 pSMB->Timeout = 0;
1715 }
1716
1717 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1718 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1719 pSMB->LockType = lockType;
1720 pSMB->AndXCommand = 0xFF;
1721 pSMB->Fid = smb_file_id;
1722
1723 if ((numLock != 0) || (numUnlock != 0)) {
1724 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1725
1726 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1727 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1728 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1729 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1730 count = sizeof(LOCKING_ANDX_RANGE);
1731 } else {
1732
1733 count = 0;
1734 }
1735 pSMB->hdr.smb_buf_length += count;
1736 pSMB->ByteCount = cpu_to_le16(count);
1737
1738 if (waitFlag) {
1739 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1740 (struct smb_hdr *) pSMB, &bytes_returned);
1741 cifs_small_buf_release(pSMB);
1742 } else {
1743 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
1744 timeout);
1745
1746 }
1747 cifs_stats_inc(&tcon->num_locks);
1748 if (rc)
1749 cFYI(1, ("Send error in Lock = %d", rc));
1750
1751
1752
1753 return rc;
1754}
1755
1756int
1757CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1758 const __u16 smb_file_id, const int get_flag, const __u64 len,
1759 struct file_lock *pLockData, const __u16 lock_type,
1760 const bool waitFlag)
1761{
1762 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1763 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1764 struct cifs_posix_lock *parm_data;
1765 int rc = 0;
1766 int timeout = 0;
1767 int bytes_returned = 0;
1768 int resp_buf_type = 0;
1769 __u16 params, param_offset, offset, byte_count, count;
1770 struct kvec iov[1];
1771
1772 cFYI(1, ("Posix Lock"));
1773
1774 if (pLockData == NULL)
1775 return -EINVAL;
1776
1777 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1778
1779 if (rc)
1780 return rc;
1781
1782 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1783
1784 params = 6;
1785 pSMB->MaxSetupCount = 0;
1786 pSMB->Reserved = 0;
1787 pSMB->Flags = 0;
1788 pSMB->Reserved2 = 0;
1789 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1790 offset = param_offset + params;
1791
1792 count = sizeof(struct cifs_posix_lock);
1793 pSMB->MaxParameterCount = cpu_to_le16(2);
1794 pSMB->MaxDataCount = cpu_to_le16(1000);
1795 pSMB->SetupCount = 1;
1796 pSMB->Reserved3 = 0;
1797 if (get_flag)
1798 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1799 else
1800 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1801 byte_count = 3 + params + count;
1802 pSMB->DataCount = cpu_to_le16(count);
1803 pSMB->ParameterCount = cpu_to_le16(params);
1804 pSMB->TotalDataCount = pSMB->DataCount;
1805 pSMB->TotalParameterCount = pSMB->ParameterCount;
1806 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1807 parm_data = (struct cifs_posix_lock *)
1808 (((char *) &pSMB->hdr.Protocol) + offset);
1809
1810 parm_data->lock_type = cpu_to_le16(lock_type);
1811 if (waitFlag) {
1812 timeout = CIFS_BLOCKING_OP;
1813 parm_data->lock_flags = cpu_to_le16(1);
1814 pSMB->Timeout = cpu_to_le32(-1);
1815 } else
1816 pSMB->Timeout = 0;
1817
1818 parm_data->pid = cpu_to_le32(current->tgid);
1819 parm_data->start = cpu_to_le64(pLockData->fl_start);
1820 parm_data->length = cpu_to_le64(len);
1821
1822 pSMB->DataOffset = cpu_to_le16(offset);
1823 pSMB->Fid = smb_file_id;
1824 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1825 pSMB->Reserved4 = 0;
1826 pSMB->hdr.smb_buf_length += byte_count;
1827 pSMB->ByteCount = cpu_to_le16(byte_count);
1828 if (waitFlag) {
1829 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1830 (struct smb_hdr *) pSMBr, &bytes_returned);
1831 } else {
1832 iov[0].iov_base = (char *)pSMB;
1833 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1834 rc = SendReceive2(xid, tcon->ses, iov, 1 ,
1835 &resp_buf_type, timeout);
1836 pSMB = NULL;
1837
1838 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
1839 }
1840
1841 if (rc) {
1842 cFYI(1, ("Send error in Posix Lock = %d", rc));
1843 } else if (get_flag) {
1844
1845 __u16 data_offset;
1846 __u16 data_count;
1847 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1848
1849 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1850 rc = -EIO;
1851 goto plk_err_exit;
1852 }
1853 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1854 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1855 if (data_count < sizeof(struct cifs_posix_lock)) {
1856 rc = -EIO;
1857 goto plk_err_exit;
1858 }
1859 parm_data = (struct cifs_posix_lock *)
1860 ((char *)&pSMBr->hdr.Protocol + data_offset);
1861 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1862 pLockData->fl_type = F_UNLCK;
1863 }
1864
1865plk_err_exit:
1866 if (pSMB)
1867 cifs_small_buf_release(pSMB);
1868
1869 if (resp_buf_type == CIFS_SMALL_BUFFER)
1870 cifs_small_buf_release(iov[0].iov_base);
1871 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1872 cifs_buf_release(iov[0].iov_base);
1873
1874
1875
1876
1877 return rc;
1878}
1879
1880
1881int
1882CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1883{
1884 int rc = 0;
1885 CLOSE_REQ *pSMB = NULL;
1886 cFYI(1, ("In CIFSSMBClose"));
1887
1888
1889 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1890 if (rc == -EAGAIN)
1891 return 0;
1892 if (rc)
1893 return rc;
1894
1895 pSMB->FileID = (__u16) smb_file_id;
1896 pSMB->LastWriteTime = 0xFFFFFFFF;
1897 pSMB->ByteCount = 0;
1898 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1899 cifs_stats_inc(&tcon->num_closes);
1900 if (rc) {
1901 if (rc != -EINTR) {
1902
1903 cERROR(1, ("Send error in Close = %d", rc));
1904 }
1905 }
1906
1907
1908 if (rc == -EAGAIN)
1909 rc = 0;
1910
1911 return rc;
1912}
1913
1914int
1915CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1916{
1917 int rc = 0;
1918 FLUSH_REQ *pSMB = NULL;
1919 cFYI(1, ("In CIFSSMBFlush"));
1920
1921 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
1922 if (rc)
1923 return rc;
1924
1925 pSMB->FileID = (__u16) smb_file_id;
1926 pSMB->ByteCount = 0;
1927 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1928 cifs_stats_inc(&tcon->num_flushes);
1929 if (rc)
1930 cERROR(1, ("Send error in Flush = %d", rc));
1931
1932 return rc;
1933}
1934
1935int
1936CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1937 const char *fromName, const char *toName,
1938 const struct nls_table *nls_codepage, int remap)
1939{
1940 int rc = 0;
1941 RENAME_REQ *pSMB = NULL;
1942 RENAME_RSP *pSMBr = NULL;
1943 int bytes_returned;
1944 int name_len, name_len2;
1945 __u16 count;
1946
1947 cFYI(1, ("In CIFSSMBRename"));
1948renameRetry:
1949 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1950 (void **) &pSMBr);
1951 if (rc)
1952 return rc;
1953
1954 pSMB->BufferFormat = 0x04;
1955 pSMB->SearchAttributes =
1956 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1957 ATTR_DIRECTORY);
1958
1959 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1960 name_len =
1961 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1962 PATH_MAX, nls_codepage, remap);
1963 name_len++;
1964 name_len *= 2;
1965 pSMB->OldFileName[name_len] = 0x04;
1966
1967 pSMB->OldFileName[name_len + 1] = 0x00;
1968 name_len2 =
1969 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1970 toName, PATH_MAX, nls_codepage, remap);
1971 name_len2 += 1 + 1 ;
1972 name_len2 *= 2;
1973 } else {
1974 name_len = strnlen(fromName, PATH_MAX);
1975 name_len++;
1976 strncpy(pSMB->OldFileName, fromName, name_len);
1977 name_len2 = strnlen(toName, PATH_MAX);
1978 name_len2++;
1979 pSMB->OldFileName[name_len] = 0x04;
1980 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1981 name_len2++;
1982 name_len2++;
1983 }
1984
1985 count = 1 + name_len + name_len2;
1986 pSMB->hdr.smb_buf_length += count;
1987 pSMB->ByteCount = cpu_to_le16(count);
1988
1989 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1990 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1991 cifs_stats_inc(&tcon->num_renames);
1992 if (rc)
1993 cFYI(1, ("Send error in rename = %d", rc));
1994
1995 cifs_buf_release(pSMB);
1996
1997 if (rc == -EAGAIN)
1998 goto renameRetry;
1999
2000 return rc;
2001}
2002
2003int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
2004 int netfid, const char *target_name,
2005 const struct nls_table *nls_codepage, int remap)
2006{
2007 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2008 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2009 struct set_file_rename *rename_info;
2010 char *data_offset;
2011 char dummy_string[30];
2012 int rc = 0;
2013 int bytes_returned = 0;
2014 int len_of_str;
2015 __u16 params, param_offset, offset, count, byte_count;
2016
2017 cFYI(1, ("Rename to File by handle"));
2018 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2019 (void **) &pSMBr);
2020 if (rc)
2021 return rc;
2022
2023 params = 6;
2024 pSMB->MaxSetupCount = 0;
2025 pSMB->Reserved = 0;
2026 pSMB->Flags = 0;
2027 pSMB->Timeout = 0;
2028 pSMB->Reserved2 = 0;
2029 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2030 offset = param_offset + params;
2031
2032 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2033 rename_info = (struct set_file_rename *) data_offset;
2034 pSMB->MaxParameterCount = cpu_to_le16(2);
2035 pSMB->MaxDataCount = cpu_to_le16(1000);
2036 pSMB->SetupCount = 1;
2037 pSMB->Reserved3 = 0;
2038 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2039 byte_count = 3 + params;
2040 pSMB->ParameterCount = cpu_to_le16(params);
2041 pSMB->TotalParameterCount = pSMB->ParameterCount;
2042 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2043 pSMB->DataOffset = cpu_to_le16(offset);
2044
2045 rename_info->overwrite = cpu_to_le32(1);
2046 rename_info->root_fid = 0;
2047
2048 if (target_name == NULL) {
2049 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2050 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2051 dummy_string, 24, nls_codepage, remap);
2052 } else {
2053 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2054 target_name, PATH_MAX, nls_codepage,
2055 remap);
2056 }
2057 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2058 count = 12 + (2 * len_of_str);
2059 byte_count += count;
2060 pSMB->DataCount = cpu_to_le16(count);
2061 pSMB->TotalDataCount = pSMB->DataCount;
2062 pSMB->Fid = netfid;
2063 pSMB->InformationLevel =
2064 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2065 pSMB->Reserved4 = 0;
2066 pSMB->hdr.smb_buf_length += byte_count;
2067 pSMB->ByteCount = cpu_to_le16(byte_count);
2068 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2069 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2070 cifs_stats_inc(&pTcon->num_t2renames);
2071 if (rc)
2072 cFYI(1, ("Send error in Rename (by file handle) = %d", rc));
2073
2074 cifs_buf_release(pSMB);
2075
2076
2077
2078
2079 return rc;
2080}
2081
2082int
2083CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2084 const __u16 target_tid, const char *toName, const int flags,
2085 const struct nls_table *nls_codepage, int remap)
2086{
2087 int rc = 0;
2088 COPY_REQ *pSMB = NULL;
2089 COPY_RSP *pSMBr = NULL;
2090 int bytes_returned;
2091 int name_len, name_len2;
2092 __u16 count;
2093
2094 cFYI(1, ("In CIFSSMBCopy"));
2095copyRetry:
2096 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2097 (void **) &pSMBr);
2098 if (rc)
2099 return rc;
2100
2101 pSMB->BufferFormat = 0x04;
2102 pSMB->Tid2 = target_tid;
2103
2104 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2105
2106 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2107 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2108 fromName, PATH_MAX, nls_codepage,
2109 remap);
2110 name_len++;
2111 name_len *= 2;
2112 pSMB->OldFileName[name_len] = 0x04;
2113
2114 pSMB->OldFileName[name_len + 1] = 0x00;
2115 name_len2 =
2116 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2117 toName, PATH_MAX, nls_codepage, remap);
2118 name_len2 += 1 + 1 ;
2119 name_len2 *= 2;
2120 } else {
2121 name_len = strnlen(fromName, PATH_MAX);
2122 name_len++;
2123 strncpy(pSMB->OldFileName, fromName, name_len);
2124 name_len2 = strnlen(toName, PATH_MAX);
2125 name_len2++;
2126 pSMB->OldFileName[name_len] = 0x04;
2127 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2128 name_len2++;
2129 name_len2++;
2130 }
2131
2132 count = 1 + name_len + name_len2;
2133 pSMB->hdr.smb_buf_length += count;
2134 pSMB->ByteCount = cpu_to_le16(count);
2135
2136 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2137 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2138 if (rc) {
2139 cFYI(1, ("Send error in copy = %d with %d files copied",
2140 rc, le16_to_cpu(pSMBr->CopyCount)));
2141 }
2142 cifs_buf_release(pSMB);
2143
2144 if (rc == -EAGAIN)
2145 goto copyRetry;
2146
2147 return rc;
2148}
2149
2150int
2151CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2152 const char *fromName, const char *toName,
2153 const struct nls_table *nls_codepage)
2154{
2155 TRANSACTION2_SPI_REQ *pSMB = NULL;
2156 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2157 char *data_offset;
2158 int name_len;
2159 int name_len_target;
2160 int rc = 0;
2161 int bytes_returned = 0;
2162 __u16 params, param_offset, offset, byte_count;
2163
2164 cFYI(1, ("In Symlink Unix style"));
2165createSymLinkRetry:
2166 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2167 (void **) &pSMBr);
2168 if (rc)
2169 return rc;
2170
2171 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2172 name_len =
2173 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2174
2175 , nls_codepage);
2176 name_len++;
2177 name_len *= 2;
2178
2179 } else {
2180 name_len = strnlen(fromName, PATH_MAX);
2181 name_len++;
2182 strncpy(pSMB->FileName, fromName, name_len);
2183 }
2184 params = 6 + name_len;
2185 pSMB->MaxSetupCount = 0;
2186 pSMB->Reserved = 0;
2187 pSMB->Flags = 0;
2188 pSMB->Timeout = 0;
2189 pSMB->Reserved2 = 0;
2190 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2191 InformationLevel) - 4;
2192 offset = param_offset + params;
2193
2194 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2195 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2196 name_len_target =
2197 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2198
2199 , nls_codepage);
2200 name_len_target++;
2201 name_len_target *= 2;
2202 } else {
2203 name_len_target = strnlen(toName, PATH_MAX);
2204 name_len_target++;
2205 strncpy(data_offset, toName, name_len_target);
2206 }
2207
2208 pSMB->MaxParameterCount = cpu_to_le16(2);
2209
2210 pSMB->MaxDataCount = cpu_to_le16(1000);
2211 pSMB->SetupCount = 1;
2212 pSMB->Reserved3 = 0;
2213 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2214 byte_count = 3 + params + name_len_target;
2215 pSMB->DataCount = cpu_to_le16(name_len_target);
2216 pSMB->ParameterCount = cpu_to_le16(params);
2217 pSMB->TotalDataCount = pSMB->DataCount;
2218 pSMB->TotalParameterCount = pSMB->ParameterCount;
2219 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2220 pSMB->DataOffset = cpu_to_le16(offset);
2221 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2222 pSMB->Reserved4 = 0;
2223 pSMB->hdr.smb_buf_length += byte_count;
2224 pSMB->ByteCount = cpu_to_le16(byte_count);
2225 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2226 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2227 cifs_stats_inc(&tcon->num_symlinks);
2228 if (rc)
2229 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc));
2230
2231 cifs_buf_release(pSMB);
2232
2233 if (rc == -EAGAIN)
2234 goto createSymLinkRetry;
2235
2236 return rc;
2237}
2238
2239int
2240CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2241 const char *fromName, const char *toName,
2242 const struct nls_table *nls_codepage, int remap)
2243{
2244 TRANSACTION2_SPI_REQ *pSMB = NULL;
2245 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2246 char *data_offset;
2247 int name_len;
2248 int name_len_target;
2249 int rc = 0;
2250 int bytes_returned = 0;
2251 __u16 params, param_offset, offset, byte_count;
2252
2253 cFYI(1, ("In Create Hard link Unix style"));
2254createHardLinkRetry:
2255 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2256 (void **) &pSMBr);
2257 if (rc)
2258 return rc;
2259
2260 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2261 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2262 PATH_MAX, nls_codepage, remap);
2263 name_len++;
2264 name_len *= 2;
2265
2266 } else {
2267 name_len = strnlen(toName, PATH_MAX);
2268 name_len++;
2269 strncpy(pSMB->FileName, toName, name_len);
2270 }
2271 params = 6 + name_len;
2272 pSMB->MaxSetupCount = 0;
2273 pSMB->Reserved = 0;
2274 pSMB->Flags = 0;
2275 pSMB->Timeout = 0;
2276 pSMB->Reserved2 = 0;
2277 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2278 InformationLevel) - 4;
2279 offset = param_offset + params;
2280
2281 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2282 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2283 name_len_target =
2284 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2285 nls_codepage, remap);
2286 name_len_target++;
2287 name_len_target *= 2;
2288 } else {
2289 name_len_target = strnlen(fromName, PATH_MAX);
2290 name_len_target++;
2291 strncpy(data_offset, fromName, name_len_target);
2292 }
2293
2294 pSMB->MaxParameterCount = cpu_to_le16(2);
2295
2296 pSMB->MaxDataCount = cpu_to_le16(1000);
2297 pSMB->SetupCount = 1;
2298 pSMB->Reserved3 = 0;
2299 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2300 byte_count = 3 + params + name_len_target;
2301 pSMB->ParameterCount = cpu_to_le16(params);
2302 pSMB->TotalParameterCount = pSMB->ParameterCount;
2303 pSMB->DataCount = cpu_to_le16(name_len_target);
2304 pSMB->TotalDataCount = pSMB->DataCount;
2305 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2306 pSMB->DataOffset = cpu_to_le16(offset);
2307 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2308 pSMB->Reserved4 = 0;
2309 pSMB->hdr.smb_buf_length += byte_count;
2310 pSMB->ByteCount = cpu_to_le16(byte_count);
2311 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2312 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2313 cifs_stats_inc(&tcon->num_hardlinks);
2314 if (rc)
2315 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2316
2317 cifs_buf_release(pSMB);
2318 if (rc == -EAGAIN)
2319 goto createHardLinkRetry;
2320
2321 return rc;
2322}
2323
2324int
2325CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2326 const char *fromName, const char *toName,
2327 const struct nls_table *nls_codepage, int remap)
2328{
2329 int rc = 0;
2330 NT_RENAME_REQ *pSMB = NULL;
2331 RENAME_RSP *pSMBr = NULL;
2332 int bytes_returned;
2333 int name_len, name_len2;
2334 __u16 count;
2335
2336 cFYI(1, ("In CIFSCreateHardLink"));
2337winCreateHardLinkRetry:
2338
2339 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2340 (void **) &pSMBr);
2341 if (rc)
2342 return rc;
2343
2344 pSMB->SearchAttributes =
2345 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2346 ATTR_DIRECTORY);
2347 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2348 pSMB->ClusterCount = 0;
2349
2350 pSMB->BufferFormat = 0x04;
2351
2352 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2353 name_len =
2354 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2355 PATH_MAX, nls_codepage, remap);
2356 name_len++;
2357 name_len *= 2;
2358
2359
2360 pSMB->OldFileName[name_len] = 0x04;
2361 pSMB->OldFileName[name_len + 1] = 0x00;
2362 name_len2 =
2363 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2364 toName, PATH_MAX, nls_codepage, remap);
2365 name_len2 += 1 + 1 ;
2366 name_len2 *= 2;
2367 } else {
2368 name_len = strnlen(fromName, PATH_MAX);
2369 name_len++;
2370 strncpy(pSMB->OldFileName, fromName, name_len);
2371 name_len2 = strnlen(toName, PATH_MAX);
2372 name_len2++;
2373 pSMB->OldFileName[name_len] = 0x04;
2374 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2375 name_len2++;
2376 name_len2++;
2377 }
2378
2379 count = 1 + name_len + name_len2;
2380 pSMB->hdr.smb_buf_length += count;
2381 pSMB->ByteCount = cpu_to_le16(count);
2382
2383 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2384 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2385 cifs_stats_inc(&tcon->num_hardlinks);
2386 if (rc)
2387 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2388
2389 cifs_buf_release(pSMB);
2390 if (rc == -EAGAIN)
2391 goto winCreateHardLinkRetry;
2392
2393 return rc;
2394}
2395
2396int
2397CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2398 const unsigned char *searchName, char **symlinkinfo,
2399 const struct nls_table *nls_codepage)
2400{
2401
2402 TRANSACTION2_QPI_REQ *pSMB = NULL;
2403 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2404 int rc = 0;
2405 int bytes_returned;
2406 int name_len;
2407 __u16 params, byte_count;
2408 char *data_start;
2409
2410 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2411
2412querySymLinkRetry:
2413 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2414 (void **) &pSMBr);
2415 if (rc)
2416 return rc;
2417
2418 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2419 name_len =
2420 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2421 PATH_MAX, nls_codepage);
2422 name_len++;
2423 name_len *= 2;
2424 } else {
2425 name_len = strnlen(searchName, PATH_MAX);
2426 name_len++;
2427 strncpy(pSMB->FileName, searchName, name_len);
2428 }
2429
2430 params = 2 + 4 + name_len ;
2431 pSMB->TotalDataCount = 0;
2432 pSMB->MaxParameterCount = cpu_to_le16(2);
2433 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
2434 pSMB->MaxSetupCount = 0;
2435 pSMB->Reserved = 0;
2436 pSMB->Flags = 0;
2437 pSMB->Timeout = 0;
2438 pSMB->Reserved2 = 0;
2439 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2440 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2441 pSMB->DataCount = 0;
2442 pSMB->DataOffset = 0;
2443 pSMB->SetupCount = 1;
2444 pSMB->Reserved3 = 0;
2445 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2446 byte_count = params + 1 ;
2447 pSMB->TotalParameterCount = cpu_to_le16(params);
2448 pSMB->ParameterCount = pSMB->TotalParameterCount;
2449 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2450 pSMB->Reserved4 = 0;
2451 pSMB->hdr.smb_buf_length += byte_count;
2452 pSMB->ByteCount = cpu_to_le16(byte_count);
2453
2454 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2455 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2456 if (rc) {
2457 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2458 } else {
2459
2460
2461 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2462
2463 if (rc || (pSMBr->ByteCount < 2))
2464 rc = -EIO;
2465 else {
2466 bool is_unicode;
2467 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2468
2469 data_start = ((char *) &pSMBr->hdr.Protocol) +
2470 le16_to_cpu(pSMBr->t2.DataOffset);
2471
2472 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2473 is_unicode = true;
2474 else
2475 is_unicode = false;
2476
2477
2478 *symlinkinfo = cifs_strndup_from_ucs(data_start, count,
2479 is_unicode, nls_codepage);
2480 if (!*symlinkinfo)
2481 rc = -ENOMEM;
2482 }
2483 }
2484 cifs_buf_release(pSMB);
2485 if (rc == -EAGAIN)
2486 goto querySymLinkRetry;
2487 return rc;
2488}
2489
2490#ifdef CONFIG_CIFS_EXPERIMENTAL
2491
2492
2493
2494
2495
2496
2497
2498static int
2499smb_init_nttransact(const __u16 sub_command, const int setup_count,
2500 const int parm_len, struct cifsTconInfo *tcon,
2501 void **ret_buf)
2502{
2503 int rc;
2504 __u32 temp_offset;
2505 struct smb_com_ntransact_req *pSMB;
2506
2507 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2508 (void **)&pSMB);
2509 if (rc)
2510 return rc;
2511 *ret_buf = (void *)pSMB;
2512 pSMB->Reserved = 0;
2513 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2514 pSMB->TotalDataCount = 0;
2515 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2516 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2517 pSMB->ParameterCount = pSMB->TotalParameterCount;
2518 pSMB->DataCount = pSMB->TotalDataCount;
2519 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2520 (setup_count * 2) - 4 ;
2521 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2522 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2523 pSMB->SetupCount = setup_count;
2524 pSMB->SubCommand = cpu_to_le16(sub_command);
2525 return 0;
2526}
2527
2528static int
2529validate_ntransact(char *buf, char **ppparm, char **ppdata,
2530 __u32 *pparmlen, __u32 *pdatalen)
2531{
2532 char *end_of_smb;
2533 __u32 data_count, data_offset, parm_count, parm_offset;
2534 struct smb_com_ntransact_rsp *pSMBr;
2535
2536 *pdatalen = 0;
2537 *pparmlen = 0;
2538
2539 if (buf == NULL)
2540 return -EINVAL;
2541
2542 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2543
2544
2545 end_of_smb = 2 + pSMBr->ByteCount +
2546 (char *)&pSMBr->ByteCount;
2547
2548 data_offset = le32_to_cpu(pSMBr->DataOffset);
2549 data_count = le32_to_cpu(pSMBr->DataCount);
2550 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2551 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2552
2553 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2554 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2555
2556
2557 if (*ppparm > end_of_smb) {
2558 cFYI(1, ("parms start after end of smb"));
2559 return -EINVAL;
2560 } else if (parm_count + *ppparm > end_of_smb) {
2561 cFYI(1, ("parm end after end of smb"));
2562 return -EINVAL;
2563 } else if (*ppdata > end_of_smb) {
2564 cFYI(1, ("data starts after end of smb"));
2565 return -EINVAL;
2566 } else if (data_count + *ppdata > end_of_smb) {
2567 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2568 *ppdata, data_count, (data_count + *ppdata),
2569 end_of_smb, pSMBr));
2570 return -EINVAL;
2571 } else if (parm_count + data_count > pSMBr->ByteCount) {
2572 cFYI(1, ("parm count and data count larger than SMB"));
2573 return -EINVAL;
2574 }
2575 *pdatalen = data_count;
2576 *pparmlen = parm_count;
2577 return 0;
2578}
2579
2580int
2581CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2582 const unsigned char *searchName,
2583 char *symlinkinfo, const int buflen, __u16 fid,
2584 const struct nls_table *nls_codepage)
2585{
2586 int rc = 0;
2587 int bytes_returned;
2588 struct smb_com_transaction_ioctl_req *pSMB;
2589 struct smb_com_transaction_ioctl_rsp *pSMBr;
2590
2591 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2592 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2593 (void **) &pSMBr);
2594 if (rc)
2595 return rc;
2596
2597 pSMB->TotalParameterCount = 0 ;
2598 pSMB->TotalDataCount = 0;
2599 pSMB->MaxParameterCount = cpu_to_le32(2);
2600
2601 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2602 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2603 pSMB->MaxSetupCount = 4;
2604 pSMB->Reserved = 0;
2605 pSMB->ParameterOffset = 0;
2606 pSMB->DataCount = 0;
2607 pSMB->DataOffset = 0;
2608 pSMB->SetupCount = 4;
2609 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2610 pSMB->ParameterCount = pSMB->TotalParameterCount;
2611 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2612 pSMB->IsFsctl = 1;
2613 pSMB->IsRootFlag = 0;
2614 pSMB->Fid = fid;
2615 pSMB->ByteCount = 0;
2616
2617 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2618 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2619 if (rc) {
2620 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2621 } else {
2622 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2623 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2624 if ((pSMBr->ByteCount < 2) || (data_offset > 512)) {
2625
2626 rc = -EIO;
2627 goto qreparse_out;
2628 }
2629 if (data_count && (data_count < 2048)) {
2630 char *end_of_smb = 2 +
2631 pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
2632
2633 struct reparse_data *reparse_buf =
2634 (struct reparse_data *)
2635 ((char *)&pSMBr->hdr.Protocol
2636 + data_offset);
2637 if ((char *)reparse_buf >= end_of_smb) {
2638 rc = -EIO;
2639 goto qreparse_out;
2640 }
2641 if ((reparse_buf->LinkNamesBuf +
2642 reparse_buf->TargetNameOffset +
2643 reparse_buf->TargetNameLen) > end_of_smb) {
2644 cFYI(1, ("reparse buf beyond SMB"));
2645 rc = -EIO;
2646 goto qreparse_out;
2647 }
2648
2649 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2650 cifs_from_ucs2(symlinkinfo, (__le16 *)
2651 (reparse_buf->LinkNamesBuf +
2652 reparse_buf->TargetNameOffset),
2653 buflen,
2654 reparse_buf->TargetNameLen,
2655 nls_codepage, 0);
2656 } else {
2657 strncpy(symlinkinfo,
2658 reparse_buf->LinkNamesBuf +
2659 reparse_buf->TargetNameOffset,
2660 min_t(const int, buflen,
2661 reparse_buf->TargetNameLen));
2662 }
2663 } else {
2664 rc = -EIO;
2665 cFYI(1, ("Invalid return data count on "
2666 "get reparse info ioctl"));
2667 }
2668 symlinkinfo[buflen] = 0;
2669
2670 cFYI(1, ("readlink result - %s", symlinkinfo));
2671 }
2672
2673qreparse_out:
2674 cifs_buf_release(pSMB);
2675
2676
2677
2678
2679 return rc;
2680}
2681#endif
2682
2683#ifdef CONFIG_CIFS_POSIX
2684
2685
2686static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2687 struct cifs_posix_ace *cifs_ace)
2688{
2689
2690 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2691 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2692 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2693
2694
2695 return;
2696}
2697
2698
2699static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2700 const int acl_type, const int size_of_data_area)
2701{
2702 int size = 0;
2703 int i;
2704 __u16 count;
2705 struct cifs_posix_ace *pACE;
2706 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2707 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2708
2709 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2710 return -EOPNOTSUPP;
2711
2712 if (acl_type & ACL_TYPE_ACCESS) {
2713 count = le16_to_cpu(cifs_acl->access_entry_count);
2714 pACE = &cifs_acl->ace_array[0];
2715 size = sizeof(struct cifs_posix_acl);
2716 size += sizeof(struct cifs_posix_ace) * count;
2717
2718 if (size_of_data_area < size) {
2719 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2720 size_of_data_area, size));
2721 return -EINVAL;
2722 }
2723 } else if (acl_type & ACL_TYPE_DEFAULT) {
2724 count = le16_to_cpu(cifs_acl->access_entry_count);
2725 size = sizeof(struct cifs_posix_acl);
2726 size += sizeof(struct cifs_posix_ace) * count;
2727
2728 pACE = &cifs_acl->ace_array[count];
2729 count = le16_to_cpu(cifs_acl->default_entry_count);
2730 size += sizeof(struct cifs_posix_ace) * count;
2731
2732 if (size_of_data_area < size)
2733 return -EINVAL;
2734 } else {
2735
2736 return -EINVAL;
2737 }
2738
2739 size = posix_acl_xattr_size(count);
2740 if ((buflen == 0) || (local_acl == NULL)) {
2741
2742 } else if (size > buflen) {
2743 return -ERANGE;
2744 } else {
2745 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2746 for (i = 0; i < count ; i++) {
2747 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2748 pACE++;
2749 }
2750 }
2751 return size;
2752}
2753
2754static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2755 const posix_acl_xattr_entry *local_ace)
2756{
2757 __u16 rc = 0;
2758
2759 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2760 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2761
2762 if (local_ace->e_id == cpu_to_le32(-1)) {
2763
2764 cifs_ace->cifs_uid = cpu_to_le64(-1);
2765 } else
2766 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2767
2768 return rc;
2769}
2770
2771
2772static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2773 const int buflen, const int acl_type)
2774{
2775 __u16 rc = 0;
2776 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2777 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2778 int count;
2779 int i;
2780
2781 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2782 return 0;
2783
2784 count = posix_acl_xattr_count((size_t)buflen);
2785 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2786 "version of %d",
2787 count, buflen, le32_to_cpu(local_acl->a_version)));
2788 if (le32_to_cpu(local_acl->a_version) != 2) {
2789 cFYI(1, ("unknown POSIX ACL version %d",
2790 le32_to_cpu(local_acl->a_version)));
2791 return 0;
2792 }
2793 cifs_acl->version = cpu_to_le16(1);
2794 if (acl_type == ACL_TYPE_ACCESS)
2795 cifs_acl->access_entry_count = cpu_to_le16(count);
2796 else if (acl_type == ACL_TYPE_DEFAULT)
2797 cifs_acl->default_entry_count = cpu_to_le16(count);
2798 else {
2799 cFYI(1, ("unknown ACL type %d", acl_type));
2800 return 0;
2801 }
2802 for (i = 0; i < count; i++) {
2803 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2804 &local_acl->a_entries[i]);
2805 if (rc != 0) {
2806
2807 break;
2808 }
2809 }
2810 if (rc == 0) {
2811 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2812 rc += sizeof(struct cifs_posix_acl);
2813
2814 }
2815 return rc;
2816}
2817
2818int
2819CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2820 const unsigned char *searchName,
2821 char *acl_inf, const int buflen, const int acl_type,
2822 const struct nls_table *nls_codepage, int remap)
2823{
2824
2825 TRANSACTION2_QPI_REQ *pSMB = NULL;
2826 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2827 int rc = 0;
2828 int bytes_returned;
2829 int name_len;
2830 __u16 params, byte_count;
2831
2832 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2833
2834queryAclRetry:
2835 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2836 (void **) &pSMBr);
2837 if (rc)
2838 return rc;
2839
2840 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2841 name_len =
2842 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2843 PATH_MAX, nls_codepage, remap);
2844 name_len++;
2845 name_len *= 2;
2846 pSMB->FileName[name_len] = 0;
2847 pSMB->FileName[name_len+1] = 0;
2848 } else {
2849 name_len = strnlen(searchName, PATH_MAX);
2850 name_len++;
2851 strncpy(pSMB->FileName, searchName, name_len);
2852 }
2853
2854 params = 2 + 4 + name_len ;
2855 pSMB->TotalDataCount = 0;
2856 pSMB->MaxParameterCount = cpu_to_le16(2);
2857
2858 pSMB->MaxDataCount = cpu_to_le16(4000);
2859 pSMB->MaxSetupCount = 0;
2860 pSMB->Reserved = 0;
2861 pSMB->Flags = 0;
2862 pSMB->Timeout = 0;
2863 pSMB->Reserved2 = 0;
2864 pSMB->ParameterOffset = cpu_to_le16(
2865 offsetof(struct smb_com_transaction2_qpi_req,
2866 InformationLevel) - 4);
2867 pSMB->DataCount = 0;
2868 pSMB->DataOffset = 0;
2869 pSMB->SetupCount = 1;
2870 pSMB->Reserved3 = 0;
2871 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2872 byte_count = params + 1 ;
2873 pSMB->TotalParameterCount = cpu_to_le16(params);
2874 pSMB->ParameterCount = pSMB->TotalParameterCount;
2875 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2876 pSMB->Reserved4 = 0;
2877 pSMB->hdr.smb_buf_length += byte_count;
2878 pSMB->ByteCount = cpu_to_le16(byte_count);
2879
2880 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2881 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2882 cifs_stats_inc(&tcon->num_acl_get);
2883 if (rc) {
2884 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2885 } else {
2886
2887
2888 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2889 if (rc || (pSMBr->ByteCount < 2))
2890
2891 rc = -EIO;
2892 else {
2893 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2894 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2895 rc = cifs_copy_posix_acl(acl_inf,
2896 (char *)&pSMBr->hdr.Protocol+data_offset,
2897 buflen, acl_type, count);
2898 }
2899 }
2900 cifs_buf_release(pSMB);
2901 if (rc == -EAGAIN)
2902 goto queryAclRetry;
2903 return rc;
2904}
2905
2906int
2907CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2908 const unsigned char *fileName,
2909 const char *local_acl, const int buflen,
2910 const int acl_type,
2911 const struct nls_table *nls_codepage, int remap)
2912{
2913 struct smb_com_transaction2_spi_req *pSMB = NULL;
2914 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2915 char *parm_data;
2916 int name_len;
2917 int rc = 0;
2918 int bytes_returned = 0;
2919 __u16 params, byte_count, data_count, param_offset, offset;
2920
2921 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2922setAclRetry:
2923 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2924 (void **) &pSMBr);
2925 if (rc)
2926 return rc;
2927 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2928 name_len =
2929 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2930 PATH_MAX, nls_codepage, remap);
2931 name_len++;
2932 name_len *= 2;
2933 } else {
2934 name_len = strnlen(fileName, PATH_MAX);
2935 name_len++;
2936 strncpy(pSMB->FileName, fileName, name_len);
2937 }
2938 params = 6 + name_len;
2939 pSMB->MaxParameterCount = cpu_to_le16(2);
2940
2941 pSMB->MaxDataCount = cpu_to_le16(1000);
2942 pSMB->MaxSetupCount = 0;
2943 pSMB->Reserved = 0;
2944 pSMB->Flags = 0;
2945 pSMB->Timeout = 0;
2946 pSMB->Reserved2 = 0;
2947 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2948 InformationLevel) - 4;
2949 offset = param_offset + params;
2950 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2951 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2952
2953
2954 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2955
2956 if (data_count == 0) {
2957 rc = -EOPNOTSUPP;
2958 goto setACLerrorExit;
2959 }
2960 pSMB->DataOffset = cpu_to_le16(offset);
2961 pSMB->SetupCount = 1;
2962 pSMB->Reserved3 = 0;
2963 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2964 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2965 byte_count = 3 + params + data_count;
2966 pSMB->DataCount = cpu_to_le16(data_count);
2967 pSMB->TotalDataCount = pSMB->DataCount;
2968 pSMB->ParameterCount = cpu_to_le16(params);
2969 pSMB->TotalParameterCount = pSMB->ParameterCount;
2970 pSMB->Reserved4 = 0;
2971 pSMB->hdr.smb_buf_length += byte_count;
2972 pSMB->ByteCount = cpu_to_le16(byte_count);
2973 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2974 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2975 if (rc)
2976 cFYI(1, ("Set POSIX ACL returned %d", rc));
2977
2978setACLerrorExit:
2979 cifs_buf_release(pSMB);
2980 if (rc == -EAGAIN)
2981 goto setAclRetry;
2982 return rc;
2983}
2984
2985
2986int
2987CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2988 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
2989{
2990 int rc = 0;
2991 struct smb_t2_qfi_req *pSMB = NULL;
2992 struct smb_t2_qfi_rsp *pSMBr = NULL;
2993 int bytes_returned;
2994 __u16 params, byte_count;
2995
2996 cFYI(1, ("In GetExtAttr"));
2997 if (tcon == NULL)
2998 return -ENODEV;
2999
3000GetExtAttrRetry:
3001 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3002 (void **) &pSMBr);
3003 if (rc)
3004 return rc;
3005
3006 params = 2 + 2 ;
3007 pSMB->t2.TotalDataCount = 0;
3008 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3009
3010 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3011 pSMB->t2.MaxSetupCount = 0;
3012 pSMB->t2.Reserved = 0;
3013 pSMB->t2.Flags = 0;
3014 pSMB->t2.Timeout = 0;
3015 pSMB->t2.Reserved2 = 0;
3016 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3017 Fid) - 4);
3018 pSMB->t2.DataCount = 0;
3019 pSMB->t2.DataOffset = 0;
3020 pSMB->t2.SetupCount = 1;
3021 pSMB->t2.Reserved3 = 0;
3022 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3023 byte_count = params + 1 ;
3024 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3025 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3026 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3027 pSMB->Pad = 0;
3028 pSMB->Fid = netfid;
3029 pSMB->hdr.smb_buf_length += byte_count;
3030 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3031
3032 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3033 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3034 if (rc) {
3035 cFYI(1, ("error %d in GetExtAttr", rc));
3036 } else {
3037
3038 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3039 if (rc || (pSMBr->ByteCount < 2))
3040
3041
3042
3043 rc = -EIO;
3044 else {
3045 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3046 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3047 struct file_chattr_info *pfinfo;
3048
3049 if (count != 16) {
3050 cFYI(1, ("Illegal size ret in GetExtAttr"));
3051 rc = -EIO;
3052 goto GetExtAttrOut;
3053 }
3054 pfinfo = (struct file_chattr_info *)
3055 (data_offset + (char *) &pSMBr->hdr.Protocol);
3056 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3057 *pMask = le64_to_cpu(pfinfo->mask);
3058 }
3059 }
3060GetExtAttrOut:
3061 cifs_buf_release(pSMB);
3062 if (rc == -EAGAIN)
3063 goto GetExtAttrRetry;
3064 return rc;
3065}
3066
3067#endif
3068
3069#ifdef CONFIG_CIFS_EXPERIMENTAL
3070
3071int
3072CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3073 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3074{
3075 int rc = 0;
3076 int buf_type = 0;
3077 QUERY_SEC_DESC_REQ *pSMB;
3078 struct kvec iov[1];
3079
3080 cFYI(1, ("GetCifsACL"));
3081
3082 *pbuflen = 0;
3083 *acl_inf = NULL;
3084
3085 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3086 8 , tcon, (void **) &pSMB);
3087 if (rc)
3088 return rc;
3089
3090 pSMB->MaxParameterCount = cpu_to_le32(4);
3091
3092 pSMB->MaxSetupCount = 0;
3093 pSMB->Fid = fid;
3094 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3095 CIFS_ACL_DACL);
3096 pSMB->ByteCount = cpu_to_le16(11);
3097 pSMB->hdr.smb_buf_length += 11;
3098 iov[0].iov_base = (char *)pSMB;
3099 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3100
3101 rc = SendReceive2(xid, tcon->ses, iov, 1 , &buf_type,
3102 CIFS_STD_OP);
3103 cifs_stats_inc(&tcon->num_acl_get);
3104 if (rc) {
3105 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3106 } else {
3107 __le32 *parm;
3108 __u32 parm_len;
3109 __u32 acl_len;
3110 struct smb_com_ntransact_rsp *pSMBr;
3111 char *pdata;
3112
3113
3114 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3115 &pdata, &parm_len, pbuflen);
3116 if (rc)
3117 goto qsec_out;
3118 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3119
3120 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
3121
3122 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3123 rc = -EIO;
3124 *pbuflen = 0;
3125 goto qsec_out;
3126 }
3127
3128
3129
3130 acl_len = le32_to_cpu(*parm);
3131 if (acl_len != *pbuflen) {
3132 cERROR(1, ("acl length %d does not match %d",
3133 acl_len, *pbuflen));
3134 if (*pbuflen > acl_len)
3135 *pbuflen = acl_len;
3136 }
3137
3138
3139
3140 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3141 (*pbuflen >= 64 * 1024)) {
3142 cERROR(1, ("bad acl length %d", *pbuflen));
3143 rc = -EINVAL;
3144 *pbuflen = 0;
3145 } else {
3146 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3147 if (*acl_inf == NULL) {
3148 *pbuflen = 0;
3149 rc = -ENOMEM;
3150 }
3151 memcpy(*acl_inf, pdata, *pbuflen);
3152 }
3153 }
3154qsec_out:
3155 if (buf_type == CIFS_SMALL_BUFFER)
3156 cifs_small_buf_release(iov[0].iov_base);
3157 else if (buf_type == CIFS_LARGE_BUFFER)
3158 cifs_buf_release(iov[0].iov_base);
3159
3160 return rc;
3161}
3162
3163int
3164CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3165 struct cifs_ntsd *pntsd, __u32 acllen)
3166{
3167 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3168 int rc = 0;
3169 int bytes_returned = 0;
3170 SET_SEC_DESC_REQ *pSMB = NULL;
3171 NTRANSACT_RSP *pSMBr = NULL;
3172
3173setCifsAclRetry:
3174 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3175 (void **) &pSMBr);
3176 if (rc)
3177 return (rc);
3178
3179 pSMB->MaxSetupCount = 0;
3180 pSMB->Reserved = 0;
3181
3182 param_count = 8;
3183 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3184 data_count = acllen;
3185 data_offset = param_offset + param_count;
3186 byte_count = 3 + param_count;
3187
3188 pSMB->DataCount = cpu_to_le32(data_count);
3189 pSMB->TotalDataCount = pSMB->DataCount;
3190 pSMB->MaxParameterCount = cpu_to_le32(4);
3191 pSMB->MaxDataCount = cpu_to_le32(16384);
3192 pSMB->ParameterCount = cpu_to_le32(param_count);
3193 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3194 pSMB->TotalParameterCount = pSMB->ParameterCount;
3195 pSMB->DataOffset = cpu_to_le32(data_offset);
3196 pSMB->SetupCount = 0;
3197 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3198 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3199
3200 pSMB->Fid = fid;
3201 pSMB->Reserved2 = 0;
3202 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3203
3204 if (pntsd && acllen) {
3205 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3206 (char *) pntsd,
3207 acllen);
3208 pSMB->hdr.smb_buf_length += (byte_count + data_count);
3209
3210 } else
3211 pSMB->hdr.smb_buf_length += byte_count;
3212
3213 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3214 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3215
3216 cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc));
3217 if (rc)
3218 cFYI(1, ("Set CIFS ACL returned %d", rc));
3219 cifs_buf_release(pSMB);
3220
3221 if (rc == -EAGAIN)
3222 goto setCifsAclRetry;
3223
3224 return (rc);
3225}
3226
3227#endif
3228
3229
3230
3231int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3232 const unsigned char *searchName,
3233 FILE_ALL_INFO *pFinfo,
3234 const struct nls_table *nls_codepage, int remap)
3235{
3236 QUERY_INFORMATION_REQ *pSMB;
3237 QUERY_INFORMATION_RSP *pSMBr;
3238 int rc = 0;
3239 int bytes_returned;
3240 int name_len;
3241
3242 cFYI(1, ("In SMBQPath path %s", searchName));
3243QInfRetry:
3244 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3245 (void **) &pSMBr);
3246 if (rc)
3247 return rc;
3248
3249 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3250 name_len =
3251 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3252 PATH_MAX, nls_codepage, remap);
3253 name_len++;
3254 name_len *= 2;
3255 } else {
3256 name_len = strnlen(searchName, PATH_MAX);
3257 name_len++;
3258 strncpy(pSMB->FileName, searchName, name_len);
3259 }
3260 pSMB->BufferFormat = 0x04;
3261 name_len++;
3262 pSMB->hdr.smb_buf_length += (__u16) name_len;
3263 pSMB->ByteCount = cpu_to_le16(name_len);
3264
3265 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3266 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3267 if (rc) {
3268 cFYI(1, ("Send error in QueryInfo = %d", rc));
3269 } else if (pFinfo) {
3270 struct timespec ts;
3271 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3272
3273
3274
3275 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3276 ts.tv_nsec = 0;
3277 ts.tv_sec = time;
3278
3279 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3280 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3281 pFinfo->LastAccessTime = 0;
3282 pFinfo->AllocationSize =
3283 cpu_to_le64(le32_to_cpu(pSMBr->size));
3284 pFinfo->EndOfFile = pFinfo->AllocationSize;
3285 pFinfo->Attributes =
3286 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3287 } else
3288 rc = -EIO;
3289
3290 cifs_buf_release(pSMB);
3291
3292 if (rc == -EAGAIN)
3293 goto QInfRetry;
3294
3295 return rc;
3296}
3297
3298
3299
3300
3301int
3302CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3303 const unsigned char *searchName,
3304 FILE_ALL_INFO *pFindData,
3305 int legacy ,
3306 const struct nls_table *nls_codepage, int remap)
3307{
3308
3309 TRANSACTION2_QPI_REQ *pSMB = NULL;
3310 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3311 int rc = 0;
3312 int bytes_returned;
3313 int name_len;
3314 __u16 params, byte_count;
3315
3316
3317QPathInfoRetry:
3318 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3319 (void **) &pSMBr);
3320 if (rc)
3321 return rc;
3322
3323 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3324 name_len =
3325 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3326 PATH_MAX, nls_codepage, remap);
3327 name_len++;
3328 name_len *= 2;
3329 } else {
3330 name_len = strnlen(searchName, PATH_MAX);
3331 name_len++;
3332 strncpy(pSMB->FileName, searchName, name_len);
3333 }
3334
3335 params = 2 + 4 + name_len ;
3336 pSMB->TotalDataCount = 0;
3337 pSMB->MaxParameterCount = cpu_to_le16(2);
3338
3339 pSMB->MaxDataCount = cpu_to_le16(4000);
3340 pSMB->MaxSetupCount = 0;
3341 pSMB->Reserved = 0;
3342 pSMB->Flags = 0;
3343 pSMB->Timeout = 0;
3344 pSMB->Reserved2 = 0;
3345 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3346 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3347 pSMB->DataCount = 0;
3348 pSMB->DataOffset = 0;
3349 pSMB->SetupCount = 1;
3350 pSMB->Reserved3 = 0;
3351 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3352 byte_count = params + 1 ;
3353 pSMB->TotalParameterCount = cpu_to_le16(params);
3354 pSMB->ParameterCount = pSMB->TotalParameterCount;
3355 if (legacy)
3356 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3357 else
3358 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3359 pSMB->Reserved4 = 0;
3360 pSMB->hdr.smb_buf_length += byte_count;
3361 pSMB->ByteCount = cpu_to_le16(byte_count);
3362
3363 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3364 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3365 if (rc) {
3366 cFYI(1, ("Send error in QPathInfo = %d", rc));
3367 } else {
3368 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3369
3370 if (rc)
3371 rc = -EIO;
3372 else if (!legacy && (pSMBr->ByteCount < 40))
3373 rc = -EIO;
3374 else if (legacy && (pSMBr->ByteCount < 24))
3375 rc = -EIO;
3376
3377 else if (pFindData) {
3378 int size;
3379 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3380
3381
3382
3383
3384
3385 if (legacy)
3386 size = sizeof(FILE_INFO_STANDARD);
3387 else
3388 size = sizeof(FILE_ALL_INFO);
3389 memcpy((char *) pFindData,
3390 (char *) &pSMBr->hdr.Protocol +
3391 data_offset, size);
3392 } else
3393 rc = -ENOMEM;
3394 }
3395 cifs_buf_release(pSMB);
3396 if (rc == -EAGAIN)
3397 goto QPathInfoRetry;
3398
3399 return rc;
3400}
3401
3402int
3403CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3404 const unsigned char *searchName,
3405 FILE_UNIX_BASIC_INFO *pFindData,
3406 const struct nls_table *nls_codepage, int remap)
3407{
3408
3409 TRANSACTION2_QPI_REQ *pSMB = NULL;
3410 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3411 int rc = 0;
3412 int bytes_returned = 0;
3413 int name_len;
3414 __u16 params, byte_count;
3415
3416 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3417UnixQPathInfoRetry:
3418 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3419 (void **) &pSMBr);
3420 if (rc)
3421 return rc;
3422
3423 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3424 name_len =
3425 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3426 PATH_MAX, nls_codepage, remap);
3427 name_len++;
3428 name_len *= 2;
3429 } else {
3430 name_len = strnlen(searchName, PATH_MAX);
3431 name_len++;
3432 strncpy(pSMB->FileName, searchName, name_len);
3433 }
3434
3435 params = 2 + 4 + name_len ;
3436 pSMB->TotalDataCount = 0;
3437 pSMB->MaxParameterCount = cpu_to_le16(2);
3438
3439 pSMB->MaxDataCount = cpu_to_le16(4000);
3440 pSMB->MaxSetupCount = 0;
3441 pSMB->Reserved = 0;
3442 pSMB->Flags = 0;
3443 pSMB->Timeout = 0;
3444 pSMB->Reserved2 = 0;
3445 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3446 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3447 pSMB->DataCount = 0;
3448 pSMB->DataOffset = 0;
3449 pSMB->SetupCount = 1;
3450 pSMB->Reserved3 = 0;
3451 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3452 byte_count = params + 1 ;
3453 pSMB->TotalParameterCount = cpu_to_le16(params);
3454 pSMB->ParameterCount = pSMB->TotalParameterCount;
3455 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3456 pSMB->Reserved4 = 0;
3457 pSMB->hdr.smb_buf_length += byte_count;
3458 pSMB->ByteCount = cpu_to_le16(byte_count);
3459
3460 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3461 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3462 if (rc) {
3463 cFYI(1, ("Send error in QPathInfo = %d", rc));
3464 } else {
3465 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3466
3467 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3468 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3469 "Unix Extensions can be disabled on mount "
3470 "by specifying the nosfu mount option."));
3471 rc = -EIO;
3472 } else {
3473 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3474 memcpy((char *) pFindData,
3475 (char *) &pSMBr->hdr.Protocol +
3476 data_offset,
3477 sizeof(FILE_UNIX_BASIC_INFO));
3478 }
3479 }
3480 cifs_buf_release(pSMB);
3481 if (rc == -EAGAIN)
3482 goto UnixQPathInfoRetry;
3483
3484 return rc;
3485}
3486
3487
3488int
3489CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3490 const char *searchName,
3491 const struct nls_table *nls_codepage,
3492 __u16 *pnetfid,
3493 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3494{
3495
3496 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3497 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3498 T2_FFIRST_RSP_PARMS *parms;
3499 int rc = 0;
3500 int bytes_returned = 0;
3501 int name_len;
3502 __u16 params, byte_count;
3503
3504 cFYI(1, ("In FindFirst for %s", searchName));
3505
3506findFirstRetry:
3507 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3508 (void **) &pSMBr);
3509 if (rc)
3510 return rc;
3511
3512 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3513 name_len =
3514 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3515 PATH_MAX, nls_codepage, remap);
3516
3517
3518
3519 name_len *= 2;
3520 pSMB->FileName[name_len] = dirsep;
3521 pSMB->FileName[name_len+1] = 0;
3522 pSMB->FileName[name_len+2] = '*';
3523 pSMB->FileName[name_len+3] = 0;
3524 name_len += 4;
3525 pSMB->FileName[name_len] = 0;
3526 pSMB->FileName[name_len+1] = 0;
3527 name_len += 2;
3528 } else {
3529 name_len = strnlen(searchName, PATH_MAX);
3530
3531
3532
3533 strncpy(pSMB->FileName, searchName, name_len);
3534 pSMB->FileName[name_len] = dirsep;
3535 pSMB->FileName[name_len+1] = '*';
3536 pSMB->FileName[name_len+2] = 0;
3537 name_len += 3;
3538 }
3539
3540 params = 12 + name_len ;
3541 pSMB->TotalDataCount = 0;
3542 pSMB->MaxParameterCount = cpu_to_le16(10);
3543 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3544 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3545 pSMB->MaxSetupCount = 0;
3546 pSMB->Reserved = 0;
3547 pSMB->Flags = 0;
3548 pSMB->Timeout = 0;
3549 pSMB->Reserved2 = 0;
3550 byte_count = params + 1 ;
3551 pSMB->TotalParameterCount = cpu_to_le16(params);
3552 pSMB->ParameterCount = pSMB->TotalParameterCount;
3553 pSMB->ParameterOffset = cpu_to_le16(
3554 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3555 - 4);
3556 pSMB->DataCount = 0;
3557 pSMB->DataOffset = 0;
3558 pSMB->SetupCount = 1;
3559 pSMB->Reserved3 = 0;
3560 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3561 pSMB->SearchAttributes =
3562 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3563 ATTR_DIRECTORY);
3564 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3565 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3566 CIFS_SEARCH_RETURN_RESUME);
3567 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3568
3569
3570 pSMB->SearchStorageType = 0;
3571 pSMB->hdr.smb_buf_length += byte_count;
3572 pSMB->ByteCount = cpu_to_le16(byte_count);
3573
3574 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3575 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3576 cifs_stats_inc(&tcon->num_ffirst);
3577
3578 if (rc) {
3579
3580
3581 cFYI(1, ("Error in FindFirst = %d", rc));
3582
3583 cifs_buf_release(pSMB);
3584
3585
3586
3587 if (rc == -EAGAIN)
3588 goto findFirstRetry;
3589 } else {
3590
3591 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3592 if (rc == 0) {
3593 unsigned int lnoff;
3594
3595 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3596 psrch_inf->unicode = true;
3597 else
3598 psrch_inf->unicode = false;
3599
3600 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3601 psrch_inf->smallBuf = 0;
3602 psrch_inf->srch_entries_start =
3603 (char *) &pSMBr->hdr.Protocol +
3604 le16_to_cpu(pSMBr->t2.DataOffset);
3605 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3606 le16_to_cpu(pSMBr->t2.ParameterOffset));
3607
3608 if (parms->EndofSearch)
3609 psrch_inf->endOfSearch = true;
3610 else
3611 psrch_inf->endOfSearch = false;
3612
3613 psrch_inf->entries_in_buffer =
3614 le16_to_cpu(parms->SearchCount);
3615 psrch_inf->index_of_last_entry = 2 +
3616 psrch_inf->entries_in_buffer;
3617 lnoff = le16_to_cpu(parms->LastNameOffset);
3618 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3619 lnoff) {
3620 cERROR(1, ("ignoring corrupt resume name"));
3621 psrch_inf->last_entry = NULL;
3622 return rc;
3623 }
3624
3625 psrch_inf->last_entry = psrch_inf->srch_entries_start +
3626 lnoff;
3627
3628 *pnetfid = parms->SearchHandle;
3629 } else {
3630 cifs_buf_release(pSMB);
3631 }
3632 }
3633
3634 return rc;
3635}
3636
3637int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3638 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3639{
3640 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3641 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3642 T2_FNEXT_RSP_PARMS *parms;
3643 char *response_data;
3644 int rc = 0;
3645 int bytes_returned, name_len;
3646 __u16 params, byte_count;
3647
3648 cFYI(1, ("In FindNext"));
3649
3650 if (psrch_inf->endOfSearch)
3651 return -ENOENT;
3652
3653 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3654 (void **) &pSMBr);
3655 if (rc)
3656 return rc;
3657
3658 params = 14;
3659 byte_count = 0;
3660 pSMB->TotalDataCount = 0;
3661 pSMB->MaxParameterCount = cpu_to_le16(8);
3662 pSMB->MaxDataCount =
3663 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3664 0xFFFFFF00);
3665 pSMB->MaxSetupCount = 0;
3666 pSMB->Reserved = 0;
3667 pSMB->Flags = 0;
3668 pSMB->Timeout = 0;
3669 pSMB->Reserved2 = 0;
3670 pSMB->ParameterOffset = cpu_to_le16(
3671 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3672 pSMB->DataCount = 0;
3673 pSMB->DataOffset = 0;
3674 pSMB->SetupCount = 1;
3675 pSMB->Reserved3 = 0;
3676 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3677 pSMB->SearchHandle = searchHandle;
3678 pSMB->SearchCount =
3679 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3680 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3681 pSMB->ResumeKey = psrch_inf->resume_key;
3682 pSMB->SearchFlags =
3683 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3684
3685 name_len = psrch_inf->resume_name_len;
3686 params += name_len;
3687 if (name_len < PATH_MAX) {
3688 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3689 byte_count += name_len;
3690
3691 pSMB->ResumeFileName[name_len] = 0;
3692 pSMB->ResumeFileName[name_len+1] = 0;
3693 } else {
3694 rc = -EINVAL;
3695 goto FNext2_err_exit;
3696 }
3697 byte_count = params + 1 ;
3698 pSMB->TotalParameterCount = cpu_to_le16(params);
3699 pSMB->ParameterCount = pSMB->TotalParameterCount;
3700 pSMB->hdr.smb_buf_length += byte_count;
3701 pSMB->ByteCount = cpu_to_le16(byte_count);
3702
3703 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3704 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3705 cifs_stats_inc(&tcon->num_fnext);
3706 if (rc) {
3707 if (rc == -EBADF) {
3708 psrch_inf->endOfSearch = true;
3709 cifs_buf_release(pSMB);
3710 rc = 0;
3711 } else
3712 cFYI(1, ("FindNext returned = %d", rc));
3713 } else {
3714 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3715
3716 if (rc == 0) {
3717 unsigned int lnoff;
3718
3719
3720 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3721 psrch_inf->unicode = true;
3722 else
3723 psrch_inf->unicode = false;
3724 response_data = (char *) &pSMBr->hdr.Protocol +
3725 le16_to_cpu(pSMBr->t2.ParameterOffset);
3726 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3727 response_data = (char *)&pSMBr->hdr.Protocol +
3728 le16_to_cpu(pSMBr->t2.DataOffset);
3729 if (psrch_inf->smallBuf)
3730 cifs_small_buf_release(
3731 psrch_inf->ntwrk_buf_start);
3732 else
3733 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3734 psrch_inf->srch_entries_start = response_data;
3735 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3736 psrch_inf->smallBuf = 0;
3737 if (parms->EndofSearch)
3738 psrch_inf->endOfSearch = true;
3739 else
3740 psrch_inf->endOfSearch = false;
3741 psrch_inf->entries_in_buffer =
3742 le16_to_cpu(parms->SearchCount);
3743 psrch_inf->index_of_last_entry +=
3744 psrch_inf->entries_in_buffer;
3745 lnoff = le16_to_cpu(parms->LastNameOffset);
3746 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3747 lnoff) {
3748 cERROR(1, ("ignoring corrupt resume name"));
3749 psrch_inf->last_entry = NULL;
3750 return rc;
3751 } else
3752 psrch_inf->last_entry =
3753 psrch_inf->srch_entries_start + lnoff;
3754
3755
3756
3757
3758
3759 }
3760
3761 }
3762
3763
3764
3765
3766
3767
3768FNext2_err_exit:
3769 if (rc != 0)
3770 cifs_buf_release(pSMB);
3771 return rc;
3772}
3773
3774int
3775CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3776 const __u16 searchHandle)
3777{
3778 int rc = 0;
3779 FINDCLOSE_REQ *pSMB = NULL;
3780
3781 cFYI(1, ("In CIFSSMBFindClose"));
3782 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3783
3784
3785
3786 if (rc == -EAGAIN)
3787 return 0;
3788 if (rc)
3789 return rc;
3790
3791 pSMB->FileID = searchHandle;
3792 pSMB->ByteCount = 0;
3793 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3794 if (rc)
3795 cERROR(1, ("Send error in FindClose = %d", rc));
3796
3797 cifs_stats_inc(&tcon->num_fclose);
3798
3799
3800 if (rc == -EAGAIN)
3801 rc = 0;
3802
3803 return rc;
3804}
3805
3806int
3807CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3808 const unsigned char *searchName,
3809 __u64 *inode_number,
3810 const struct nls_table *nls_codepage, int remap)
3811{
3812 int rc = 0;
3813 TRANSACTION2_QPI_REQ *pSMB = NULL;
3814 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3815 int name_len, bytes_returned;
3816 __u16 params, byte_count;
3817
3818 cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3819 if (tcon == NULL)
3820 return -ENODEV;
3821
3822GetInodeNumberRetry:
3823 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3824 (void **) &pSMBr);
3825 if (rc)
3826 return rc;
3827
3828 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3829 name_len =
3830 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3831 PATH_MAX, nls_codepage, remap);
3832 name_len++;
3833 name_len *= 2;
3834 } else {
3835 name_len = strnlen(searchName, PATH_MAX);
3836 name_len++;
3837 strncpy(pSMB->FileName, searchName, name_len);
3838 }
3839
3840 params = 2 + 4 + name_len ;
3841 pSMB->TotalDataCount = 0;
3842 pSMB->MaxParameterCount = cpu_to_le16(2);
3843
3844 pSMB->MaxDataCount = cpu_to_le16(4000);
3845 pSMB->MaxSetupCount = 0;
3846 pSMB->Reserved = 0;
3847 pSMB->Flags = 0;
3848 pSMB->Timeout = 0;
3849 pSMB->Reserved2 = 0;
3850 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3851 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3852 pSMB->DataCount = 0;
3853 pSMB->DataOffset = 0;
3854 pSMB->SetupCount = 1;
3855 pSMB->Reserved3 = 0;
3856 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3857 byte_count = params + 1 ;
3858 pSMB->TotalParameterCount = cpu_to_le16(params);
3859 pSMB->ParameterCount = pSMB->TotalParameterCount;
3860 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3861 pSMB->Reserved4 = 0;
3862 pSMB->hdr.smb_buf_length += byte_count;
3863 pSMB->ByteCount = cpu_to_le16(byte_count);
3864
3865 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3866 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3867 if (rc) {
3868 cFYI(1, ("error %d in QueryInternalInfo", rc));
3869 } else {
3870
3871 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3872 if (rc || (pSMBr->ByteCount < 2))
3873
3874
3875
3876 rc = -EIO;
3877 else {
3878 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3879 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3880 struct file_internal_info *pfinfo;
3881
3882 if (count < 8) {
3883 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3884 rc = -EIO;
3885 goto GetInodeNumOut;
3886 }
3887 pfinfo = (struct file_internal_info *)
3888 (data_offset + (char *) &pSMBr->hdr.Protocol);
3889 *inode_number = le64_to_cpu(pfinfo->UniqueId);
3890 }
3891 }
3892GetInodeNumOut:
3893 cifs_buf_release(pSMB);
3894 if (rc == -EAGAIN)
3895 goto GetInodeNumberRetry;
3896 return rc;
3897}
3898
3899
3900
3901
3902
3903
3904
3905static int
3906parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
3907 unsigned int *num_of_nodes,
3908 struct dfs_info3_param **target_nodes,
3909 const struct nls_table *nls_codepage, int remap,
3910 const char *searchName)
3911{
3912 int i, rc = 0;
3913 char *data_end;
3914 bool is_unicode;
3915 struct dfs_referral_level_3 *ref;
3916
3917 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3918 is_unicode = true;
3919 else
3920 is_unicode = false;
3921 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
3922
3923 if (*num_of_nodes < 1) {
3924 cERROR(1, ("num_referrals: must be at least > 0,"
3925 "but we get num_referrals = %d\n", *num_of_nodes));
3926 rc = -EINVAL;
3927 goto parse_DFS_referrals_exit;
3928 }
3929
3930 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
3931 if (ref->VersionNumber != cpu_to_le16(3)) {
3932 cERROR(1, ("Referrals of V%d version are not supported,"
3933 "should be V3", le16_to_cpu(ref->VersionNumber)));
3934 rc = -EINVAL;
3935 goto parse_DFS_referrals_exit;
3936 }
3937
3938
3939 data_end = (char *)(&(pSMBr->PathConsumed)) +
3940 le16_to_cpu(pSMBr->t2.DataCount);
3941
3942 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
3943 *num_of_nodes,
3944 le32_to_cpu(pSMBr->DFSFlags)));
3945
3946 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
3947 *num_of_nodes, GFP_KERNEL);
3948 if (*target_nodes == NULL) {
3949 cERROR(1, ("Failed to allocate buffer for target_nodes\n"));
3950 rc = -ENOMEM;
3951 goto parse_DFS_referrals_exit;
3952 }
3953
3954
3955 for (i = 0; i < *num_of_nodes; i++) {
3956 char *temp;
3957 int max_len;
3958 struct dfs_info3_param *node = (*target_nodes)+i;
3959
3960 node->flags = le32_to_cpu(pSMBr->DFSFlags);
3961 if (is_unicode) {
3962 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
3963 GFP_KERNEL);
3964 cifsConvertToUCS((__le16 *) tmp, searchName,
3965 PATH_MAX, nls_codepage, remap);
3966 node->path_consumed = cifs_ucs2_bytes(tmp,
3967 le16_to_cpu(pSMBr->PathConsumed),
3968 nls_codepage);
3969 kfree(tmp);
3970 } else
3971 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
3972
3973 node->server_type = le16_to_cpu(ref->ServerType);
3974 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
3975
3976
3977 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
3978 max_len = data_end - temp;
3979 node->path_name = cifs_strndup_from_ucs(temp, max_len,
3980 is_unicode, nls_codepage);
3981 if (!node->path_name) {
3982 rc = -ENOMEM;
3983 goto parse_DFS_referrals_exit;
3984 }
3985
3986
3987 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
3988 max_len = data_end - temp;
3989 node->node_name = cifs_strndup_from_ucs(temp, max_len,
3990 is_unicode, nls_codepage);
3991 if (!node->node_name)
3992 rc = -ENOMEM;
3993 }
3994
3995parse_DFS_referrals_exit:
3996 if (rc) {
3997 free_dfs_info_array(*target_nodes, *num_of_nodes);
3998 *target_nodes = NULL;
3999 *num_of_nodes = 0;
4000 }
4001 return rc;
4002}
4003
4004int
4005CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
4006 const unsigned char *searchName,
4007 struct dfs_info3_param **target_nodes,
4008 unsigned int *num_of_nodes,
4009 const struct nls_table *nls_codepage, int remap)
4010{
4011
4012 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4013 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4014 int rc = 0;
4015 int bytes_returned;
4016 int name_len;
4017 __u16 params, byte_count;
4018 *num_of_nodes = 0;
4019 *target_nodes = NULL;
4020
4021 cFYI(1, ("In GetDFSRefer the path %s", searchName));
4022 if (ses == NULL)
4023 return -ENODEV;
4024getDFSRetry:
4025 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4026 (void **) &pSMBr);
4027 if (rc)
4028 return rc;
4029
4030
4031
4032 pSMB->hdr.Mid = GetNextMid(ses->server);
4033 pSMB->hdr.Tid = ses->ipc_tid;
4034 pSMB->hdr.Uid = ses->Suid;
4035 if (ses->capabilities & CAP_STATUS32)
4036 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4037 if (ses->capabilities & CAP_DFS)
4038 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4039
4040 if (ses->capabilities & CAP_UNICODE) {
4041 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4042 name_len =
4043 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4044 searchName, PATH_MAX, nls_codepage, remap);
4045 name_len++;
4046 name_len *= 2;
4047 } else {
4048 name_len = strnlen(searchName, PATH_MAX);
4049 name_len++;
4050 strncpy(pSMB->RequestFileName, searchName, name_len);
4051 }
4052
4053 if (ses->server) {
4054 if (ses->server->secMode &
4055 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4056 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4057 }
4058
4059 pSMB->hdr.Uid = ses->Suid;
4060
4061 params = 2 + name_len ;
4062 pSMB->TotalDataCount = 0;
4063 pSMB->DataCount = 0;
4064 pSMB->DataOffset = 0;
4065 pSMB->MaxParameterCount = 0;
4066
4067 pSMB->MaxDataCount = cpu_to_le16(4000);
4068 pSMB->MaxSetupCount = 0;
4069 pSMB->Reserved = 0;
4070 pSMB->Flags = 0;
4071 pSMB->Timeout = 0;
4072 pSMB->Reserved2 = 0;
4073 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4074 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4075 pSMB->SetupCount = 1;
4076 pSMB->Reserved3 = 0;
4077 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4078 byte_count = params + 3 ;
4079 pSMB->ParameterCount = cpu_to_le16(params);
4080 pSMB->TotalParameterCount = pSMB->ParameterCount;
4081 pSMB->MaxReferralLevel = cpu_to_le16(3);
4082 pSMB->hdr.smb_buf_length += byte_count;
4083 pSMB->ByteCount = cpu_to_le16(byte_count);
4084
4085 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4086 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4087 if (rc) {
4088 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
4089 goto GetDFSRefExit;
4090 }
4091 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4092
4093
4094 if (rc || (pSMBr->ByteCount < 17)) {
4095 rc = -EIO;
4096 goto GetDFSRefExit;
4097 }
4098
4099 cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d",
4100 pSMBr->ByteCount,
4101 le16_to_cpu(pSMBr->t2.DataOffset)));
4102
4103
4104 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4105 target_nodes, nls_codepage, remap,
4106 searchName);
4107
4108GetDFSRefExit:
4109 cifs_buf_release(pSMB);
4110
4111 if (rc == -EAGAIN)
4112 goto getDFSRetry;
4113
4114 return rc;
4115}
4116
4117
4118int
4119SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4120{
4121
4122 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4123 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4124 FILE_SYSTEM_ALLOC_INFO *response_data;
4125 int rc = 0;
4126 int bytes_returned = 0;
4127 __u16 params, byte_count;
4128
4129 cFYI(1, ("OldQFSInfo"));
4130oldQFSInfoRetry:
4131 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4132 (void **) &pSMBr);
4133 if (rc)
4134 return rc;
4135
4136 params = 2;
4137 pSMB->TotalDataCount = 0;
4138 pSMB->MaxParameterCount = cpu_to_le16(2);
4139 pSMB->MaxDataCount = cpu_to_le16(1000);
4140 pSMB->MaxSetupCount = 0;
4141 pSMB->Reserved = 0;
4142 pSMB->Flags = 0;
4143 pSMB->Timeout = 0;
4144 pSMB->Reserved2 = 0;
4145 byte_count = params + 1 ;
4146 pSMB->TotalParameterCount = cpu_to_le16(params);
4147 pSMB->ParameterCount = pSMB->TotalParameterCount;
4148 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4149 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4150 pSMB->DataCount = 0;
4151 pSMB->DataOffset = 0;
4152 pSMB->SetupCount = 1;
4153 pSMB->Reserved3 = 0;
4154 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4155 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4156 pSMB->hdr.smb_buf_length += byte_count;
4157 pSMB->ByteCount = cpu_to_le16(byte_count);
4158
4159 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4160 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4161 if (rc) {
4162 cFYI(1, ("Send error in QFSInfo = %d", rc));
4163 } else {
4164 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4165
4166 if (rc || (pSMBr->ByteCount < 18))
4167 rc = -EIO;
4168 else {
4169 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4170 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4171 pSMBr->ByteCount, data_offset));
4172
4173 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4174 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4175 FSData->f_bsize =
4176 le16_to_cpu(response_data->BytesPerSector) *
4177 le32_to_cpu(response_data->
4178 SectorsPerAllocationUnit);
4179 FSData->f_blocks =
4180 le32_to_cpu(response_data->TotalAllocationUnits);
4181 FSData->f_bfree = FSData->f_bavail =
4182 le32_to_cpu(response_data->FreeAllocationUnits);
4183 cFYI(1,
4184 ("Blocks: %lld Free: %lld Block size %ld",
4185 (unsigned long long)FSData->f_blocks,
4186 (unsigned long long)FSData->f_bfree,
4187 FSData->f_bsize));
4188 }
4189 }
4190 cifs_buf_release(pSMB);
4191
4192 if (rc == -EAGAIN)
4193 goto oldQFSInfoRetry;
4194
4195 return rc;
4196}
4197
4198int
4199CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4200{
4201
4202 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4203 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4204 FILE_SYSTEM_INFO *response_data;
4205 int rc = 0;
4206 int bytes_returned = 0;
4207 __u16 params, byte_count;
4208
4209 cFYI(1, ("In QFSInfo"));
4210QFSInfoRetry:
4211 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4212 (void **) &pSMBr);
4213 if (rc)
4214 return rc;
4215
4216 params = 2;
4217 pSMB->TotalDataCount = 0;
4218 pSMB->MaxParameterCount = cpu_to_le16(2);
4219 pSMB->MaxDataCount = cpu_to_le16(1000);
4220 pSMB->MaxSetupCount = 0;
4221 pSMB->Reserved = 0;
4222 pSMB->Flags = 0;
4223 pSMB->Timeout = 0;
4224 pSMB->Reserved2 = 0;
4225 byte_count = params + 1 ;
4226 pSMB->TotalParameterCount = cpu_to_le16(params);
4227 pSMB->ParameterCount = pSMB->TotalParameterCount;
4228 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4229 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4230 pSMB->DataCount = 0;
4231 pSMB->DataOffset = 0;
4232 pSMB->SetupCount = 1;
4233 pSMB->Reserved3 = 0;
4234 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4235 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4236 pSMB->hdr.smb_buf_length += byte_count;
4237 pSMB->ByteCount = cpu_to_le16(byte_count);
4238
4239 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4240 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4241 if (rc) {
4242 cFYI(1, ("Send error in QFSInfo = %d", rc));
4243 } else {
4244 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4245
4246 if (rc || (pSMBr->ByteCount < 24))
4247 rc = -EIO;
4248 else {
4249 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4250
4251 response_data =
4252 (FILE_SYSTEM_INFO
4253 *) (((char *) &pSMBr->hdr.Protocol) +
4254 data_offset);
4255 FSData->f_bsize =
4256 le32_to_cpu(response_data->BytesPerSector) *
4257 le32_to_cpu(response_data->
4258 SectorsPerAllocationUnit);
4259 FSData->f_blocks =
4260 le64_to_cpu(response_data->TotalAllocationUnits);
4261 FSData->f_bfree = FSData->f_bavail =
4262 le64_to_cpu(response_data->FreeAllocationUnits);
4263 cFYI(1,
4264 ("Blocks: %lld Free: %lld Block size %ld",
4265 (unsigned long long)FSData->f_blocks,
4266 (unsigned long long)FSData->f_bfree,
4267 FSData->f_bsize));
4268 }
4269 }
4270 cifs_buf_release(pSMB);
4271
4272 if (rc == -EAGAIN)
4273 goto QFSInfoRetry;
4274
4275 return rc;
4276}
4277
4278int
4279CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4280{
4281
4282 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4283 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4284 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4285 int rc = 0;
4286 int bytes_returned = 0;
4287 __u16 params, byte_count;
4288
4289 cFYI(1, ("In QFSAttributeInfo"));
4290QFSAttributeRetry:
4291 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4292 (void **) &pSMBr);
4293 if (rc)
4294 return rc;
4295
4296 params = 2;
4297 pSMB->TotalDataCount = 0;
4298 pSMB->MaxParameterCount = cpu_to_le16(2);
4299
4300 pSMB->MaxDataCount = cpu_to_le16(1000);
4301 pSMB->MaxSetupCount = 0;
4302 pSMB->Reserved = 0;
4303 pSMB->Flags = 0;
4304 pSMB->Timeout = 0;
4305 pSMB->Reserved2 = 0;
4306 byte_count = params + 1 ;
4307 pSMB->TotalParameterCount = cpu_to_le16(params);
4308 pSMB->ParameterCount = pSMB->TotalParameterCount;
4309 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4310 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4311 pSMB->DataCount = 0;
4312 pSMB->DataOffset = 0;
4313 pSMB->SetupCount = 1;
4314 pSMB->Reserved3 = 0;
4315 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4316 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4317 pSMB->hdr.smb_buf_length += byte_count;
4318 pSMB->ByteCount = cpu_to_le16(byte_count);
4319
4320 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4321 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4322 if (rc) {
4323 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4324 } else {
4325 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4326
4327 if (rc || (pSMBr->ByteCount < 13)) {
4328
4329 rc = -EIO;
4330 } else {
4331 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4332 response_data =
4333 (FILE_SYSTEM_ATTRIBUTE_INFO
4334 *) (((char *) &pSMBr->hdr.Protocol) +
4335 data_offset);
4336 memcpy(&tcon->fsAttrInfo, response_data,
4337 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4338 }
4339 }
4340 cifs_buf_release(pSMB);
4341
4342 if (rc == -EAGAIN)
4343 goto QFSAttributeRetry;
4344
4345 return rc;
4346}
4347
4348int
4349CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4350{
4351
4352 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4353 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4354 FILE_SYSTEM_DEVICE_INFO *response_data;
4355 int rc = 0;
4356 int bytes_returned = 0;
4357 __u16 params, byte_count;
4358
4359 cFYI(1, ("In QFSDeviceInfo"));
4360QFSDeviceRetry:
4361 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4362 (void **) &pSMBr);
4363 if (rc)
4364 return rc;
4365
4366 params = 2;
4367 pSMB->TotalDataCount = 0;
4368 pSMB->MaxParameterCount = cpu_to_le16(2);
4369
4370 pSMB->MaxDataCount = cpu_to_le16(1000);
4371 pSMB->MaxSetupCount = 0;
4372 pSMB->Reserved = 0;
4373 pSMB->Flags = 0;
4374 pSMB->Timeout = 0;
4375 pSMB->Reserved2 = 0;
4376 byte_count = params + 1 ;
4377 pSMB->TotalParameterCount = cpu_to_le16(params);
4378 pSMB->ParameterCount = pSMB->TotalParameterCount;
4379 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4380 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4381
4382 pSMB->DataCount = 0;
4383 pSMB->DataOffset = 0;
4384 pSMB->SetupCount = 1;
4385 pSMB->Reserved3 = 0;
4386 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4387 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4388 pSMB->hdr.smb_buf_length += byte_count;
4389 pSMB->ByteCount = cpu_to_le16(byte_count);
4390
4391 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4392 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4393 if (rc) {
4394 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4395 } else {
4396 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4397
4398 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4399 rc = -EIO;
4400 else {
4401 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4402 response_data =
4403 (FILE_SYSTEM_DEVICE_INFO *)
4404 (((char *) &pSMBr->hdr.Protocol) +
4405 data_offset);
4406 memcpy(&tcon->fsDevInfo, response_data,
4407 sizeof(FILE_SYSTEM_DEVICE_INFO));
4408 }
4409 }
4410 cifs_buf_release(pSMB);
4411
4412 if (rc == -EAGAIN)
4413 goto QFSDeviceRetry;
4414
4415 return rc;
4416}
4417
4418int
4419CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4420{
4421
4422 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4423 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4424 FILE_SYSTEM_UNIX_INFO *response_data;
4425 int rc = 0;
4426 int bytes_returned = 0;
4427 __u16 params, byte_count;
4428
4429 cFYI(1, ("In QFSUnixInfo"));
4430QFSUnixRetry:
4431 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4432 (void **) &pSMBr);
4433 if (rc)
4434 return rc;
4435
4436 params = 2;
4437 pSMB->TotalDataCount = 0;
4438 pSMB->DataCount = 0;
4439 pSMB->DataOffset = 0;
4440 pSMB->MaxParameterCount = cpu_to_le16(2);
4441
4442 pSMB->MaxDataCount = cpu_to_le16(100);
4443 pSMB->MaxSetupCount = 0;
4444 pSMB->Reserved = 0;
4445 pSMB->Flags = 0;
4446 pSMB->Timeout = 0;
4447 pSMB->Reserved2 = 0;
4448 byte_count = params + 1 ;
4449 pSMB->ParameterCount = cpu_to_le16(params);
4450 pSMB->TotalParameterCount = pSMB->ParameterCount;
4451 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4452 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4453 pSMB->SetupCount = 1;
4454 pSMB->Reserved3 = 0;
4455 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4456 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4457 pSMB->hdr.smb_buf_length += byte_count;
4458 pSMB->ByteCount = cpu_to_le16(byte_count);
4459
4460 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4461 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4462 if (rc) {
4463 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4464 } else {
4465 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4466
4467 if (rc || (pSMBr->ByteCount < 13)) {
4468 rc = -EIO;
4469 } else {
4470 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4471 response_data =
4472 (FILE_SYSTEM_UNIX_INFO
4473 *) (((char *) &pSMBr->hdr.Protocol) +
4474 data_offset);
4475 memcpy(&tcon->fsUnixInfo, response_data,
4476 sizeof(FILE_SYSTEM_UNIX_INFO));
4477 }
4478 }
4479 cifs_buf_release(pSMB);
4480
4481 if (rc == -EAGAIN)
4482 goto QFSUnixRetry;
4483
4484
4485 return rc;
4486}
4487
4488int
4489CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4490{
4491
4492 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4493 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4494 int rc = 0;
4495 int bytes_returned = 0;
4496 __u16 params, param_offset, offset, byte_count;
4497
4498 cFYI(1, ("In SETFSUnixInfo"));
4499SETFSUnixRetry:
4500
4501 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4502 (void **) &pSMBr);
4503 if (rc)
4504 return rc;
4505
4506 params = 4;
4507 pSMB->MaxSetupCount = 0;
4508 pSMB->Reserved = 0;
4509 pSMB->Flags = 0;
4510 pSMB->Timeout = 0;
4511 pSMB->Reserved2 = 0;
4512 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4513 - 4;
4514 offset = param_offset + params;
4515
4516 pSMB->MaxParameterCount = cpu_to_le16(4);
4517
4518 pSMB->MaxDataCount = cpu_to_le16(100);
4519 pSMB->SetupCount = 1;
4520 pSMB->Reserved3 = 0;
4521 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4522 byte_count = 1 + params + 12;
4523
4524 pSMB->DataCount = cpu_to_le16(12);
4525 pSMB->ParameterCount = cpu_to_le16(params);
4526 pSMB->TotalDataCount = pSMB->DataCount;
4527 pSMB->TotalParameterCount = pSMB->ParameterCount;
4528 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4529 pSMB->DataOffset = cpu_to_le16(offset);
4530
4531
4532 pSMB->FileNum = 0;
4533 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4534
4535
4536 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4537 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4538 pSMB->ClientUnixCap = cpu_to_le64(cap);
4539
4540 pSMB->hdr.smb_buf_length += byte_count;
4541 pSMB->ByteCount = cpu_to_le16(byte_count);
4542
4543 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4544 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4545 if (rc) {
4546 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4547 } else {
4548 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4549 if (rc)
4550 rc = -EIO;
4551 }
4552 cifs_buf_release(pSMB);
4553
4554 if (rc == -EAGAIN)
4555 goto SETFSUnixRetry;
4556
4557 return rc;
4558}
4559
4560
4561
4562int
4563CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4564 struct kstatfs *FSData)
4565{
4566
4567 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4568 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4569 FILE_SYSTEM_POSIX_INFO *response_data;
4570 int rc = 0;
4571 int bytes_returned = 0;
4572 __u16 params, byte_count;
4573
4574 cFYI(1, ("In QFSPosixInfo"));
4575QFSPosixRetry:
4576 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4577 (void **) &pSMBr);
4578 if (rc)
4579 return rc;
4580
4581 params = 2;
4582 pSMB->TotalDataCount = 0;
4583 pSMB->DataCount = 0;
4584 pSMB->DataOffset = 0;
4585 pSMB->MaxParameterCount = cpu_to_le16(2);
4586
4587 pSMB->MaxDataCount = cpu_to_le16(100);
4588 pSMB->MaxSetupCount = 0;
4589 pSMB->Reserved = 0;
4590 pSMB->Flags = 0;
4591 pSMB->Timeout = 0;
4592 pSMB->Reserved2 = 0;
4593 byte_count = params + 1 ;
4594 pSMB->ParameterCount = cpu_to_le16(params);
4595 pSMB->TotalParameterCount = pSMB->ParameterCount;
4596 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4597 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4598 pSMB->SetupCount = 1;
4599 pSMB->Reserved3 = 0;
4600 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4601 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4602 pSMB->hdr.smb_buf_length += byte_count;
4603 pSMB->ByteCount = cpu_to_le16(byte_count);
4604
4605 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4606 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4607 if (rc) {
4608 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4609 } else {
4610 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4611
4612 if (rc || (pSMBr->ByteCount < 13)) {
4613 rc = -EIO;
4614 } else {
4615 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4616 response_data =
4617 (FILE_SYSTEM_POSIX_INFO
4618 *) (((char *) &pSMBr->hdr.Protocol) +
4619 data_offset);
4620 FSData->f_bsize =
4621 le32_to_cpu(response_data->BlockSize);
4622 FSData->f_blocks =
4623 le64_to_cpu(response_data->TotalBlocks);
4624 FSData->f_bfree =
4625 le64_to_cpu(response_data->BlocksAvail);
4626 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4627 FSData->f_bavail = FSData->f_bfree;
4628 } else {
4629 FSData->f_bavail =
4630 le64_to_cpu(response_data->UserBlocksAvail);
4631 }
4632 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4633 FSData->f_files =
4634 le64_to_cpu(response_data->TotalFileNodes);
4635 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4636 FSData->f_ffree =
4637 le64_to_cpu(response_data->FreeFileNodes);
4638 }
4639 }
4640 cifs_buf_release(pSMB);
4641
4642 if (rc == -EAGAIN)
4643 goto QFSPosixRetry;
4644
4645 return rc;
4646}
4647
4648
4649
4650
4651
4652
4653
4654
4655int
4656CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4657 __u64 size, bool SetAllocation,
4658 const struct nls_table *nls_codepage, int remap)
4659{
4660 struct smb_com_transaction2_spi_req *pSMB = NULL;
4661 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4662 struct file_end_of_file_info *parm_data;
4663 int name_len;
4664 int rc = 0;
4665 int bytes_returned = 0;
4666 __u16 params, byte_count, data_count, param_offset, offset;
4667
4668 cFYI(1, ("In SetEOF"));
4669SetEOFRetry:
4670 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4671 (void **) &pSMBr);
4672 if (rc)
4673 return rc;
4674
4675 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4676 name_len =
4677 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4678 PATH_MAX, nls_codepage, remap);
4679 name_len++;
4680 name_len *= 2;
4681 } else {
4682 name_len = strnlen(fileName, PATH_MAX);
4683 name_len++;
4684 strncpy(pSMB->FileName, fileName, name_len);
4685 }
4686 params = 6 + name_len;
4687 data_count = sizeof(struct file_end_of_file_info);
4688 pSMB->MaxParameterCount = cpu_to_le16(2);
4689 pSMB->MaxDataCount = cpu_to_le16(4100);
4690 pSMB->MaxSetupCount = 0;
4691 pSMB->Reserved = 0;
4692 pSMB->Flags = 0;
4693 pSMB->Timeout = 0;
4694 pSMB->Reserved2 = 0;
4695 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4696 InformationLevel) - 4;
4697 offset = param_offset + params;
4698 if (SetAllocation) {
4699 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4700 pSMB->InformationLevel =
4701 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4702 else
4703 pSMB->InformationLevel =
4704 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4705 } else {
4706 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4707 pSMB->InformationLevel =
4708 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4709 else
4710 pSMB->InformationLevel =
4711 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4712 }
4713
4714 parm_data =
4715 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4716 offset);
4717 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4718 pSMB->DataOffset = cpu_to_le16(offset);
4719 pSMB->SetupCount = 1;
4720 pSMB->Reserved3 = 0;
4721 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4722 byte_count = 3 + params + data_count;
4723 pSMB->DataCount = cpu_to_le16(data_count);
4724 pSMB->TotalDataCount = pSMB->DataCount;
4725 pSMB->ParameterCount = cpu_to_le16(params);
4726 pSMB->TotalParameterCount = pSMB->ParameterCount;
4727 pSMB->Reserved4 = 0;
4728 pSMB->hdr.smb_buf_length += byte_count;
4729 parm_data->FileSize = cpu_to_le64(size);
4730 pSMB->ByteCount = cpu_to_le16(byte_count);
4731 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4732 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4733 if (rc)
4734 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4735
4736 cifs_buf_release(pSMB);
4737
4738 if (rc == -EAGAIN)
4739 goto SetEOFRetry;
4740
4741 return rc;
4742}
4743
4744int
4745CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4746 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4747{
4748 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4749 char *data_offset;
4750 struct file_end_of_file_info *parm_data;
4751 int rc = 0;
4752 __u16 params, param_offset, offset, byte_count, count;
4753
4754 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4755 (long long)size));
4756 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4757
4758 if (rc)
4759 return rc;
4760
4761 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4762 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4763
4764 params = 6;
4765 pSMB->MaxSetupCount = 0;
4766 pSMB->Reserved = 0;
4767 pSMB->Flags = 0;
4768 pSMB->Timeout = 0;
4769 pSMB->Reserved2 = 0;
4770 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4771 offset = param_offset + params;
4772
4773 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4774
4775 count = sizeof(struct file_end_of_file_info);
4776 pSMB->MaxParameterCount = cpu_to_le16(2);
4777
4778 pSMB->MaxDataCount = cpu_to_le16(1000);
4779 pSMB->SetupCount = 1;
4780 pSMB->Reserved3 = 0;
4781 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4782 byte_count = 3 + params + count;
4783 pSMB->DataCount = cpu_to_le16(count);
4784 pSMB->ParameterCount = cpu_to_le16(params);
4785 pSMB->TotalDataCount = pSMB->DataCount;
4786 pSMB->TotalParameterCount = pSMB->ParameterCount;
4787 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4788 parm_data =
4789 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4790 + offset);
4791 pSMB->DataOffset = cpu_to_le16(offset);
4792 parm_data->FileSize = cpu_to_le64(size);
4793 pSMB->Fid = fid;
4794 if (SetAllocation) {
4795 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4796 pSMB->InformationLevel =
4797 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4798 else
4799 pSMB->InformationLevel =
4800 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4801 } else {
4802 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4803 pSMB->InformationLevel =
4804 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4805 else
4806 pSMB->InformationLevel =
4807 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4808 }
4809 pSMB->Reserved4 = 0;
4810 pSMB->hdr.smb_buf_length += byte_count;
4811 pSMB->ByteCount = cpu_to_le16(byte_count);
4812 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4813 if (rc) {
4814 cFYI(1,
4815 ("Send error in SetFileInfo (SetFileSize) = %d",
4816 rc));
4817 }
4818
4819
4820
4821
4822 return rc;
4823}
4824
4825
4826
4827
4828
4829
4830
4831int
4832CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
4833 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
4834{
4835 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4836 char *data_offset;
4837 int rc = 0;
4838 __u16 params, param_offset, offset, byte_count, count;
4839
4840 cFYI(1, ("Set Times (via SetFileInfo)"));
4841 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4842
4843 if (rc)
4844 return rc;
4845
4846 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4847 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4848
4849 params = 6;
4850 pSMB->MaxSetupCount = 0;
4851 pSMB->Reserved = 0;
4852 pSMB->Flags = 0;
4853 pSMB->Timeout = 0;
4854 pSMB->Reserved2 = 0;
4855 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4856 offset = param_offset + params;
4857
4858 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4859
4860 count = sizeof(FILE_BASIC_INFO);
4861 pSMB->MaxParameterCount = cpu_to_le16(2);
4862
4863 pSMB->MaxDataCount = cpu_to_le16(1000);
4864 pSMB->SetupCount = 1;
4865 pSMB->Reserved3 = 0;
4866 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4867 byte_count = 3 + params + count;
4868 pSMB->DataCount = cpu_to_le16(count);
4869 pSMB->ParameterCount = cpu_to_le16(params);
4870 pSMB->TotalDataCount = pSMB->DataCount;
4871 pSMB->TotalParameterCount = pSMB->ParameterCount;
4872 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4873 pSMB->DataOffset = cpu_to_le16(offset);
4874 pSMB->Fid = fid;
4875 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4876 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4877 else
4878 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4879 pSMB->Reserved4 = 0;
4880 pSMB->hdr.smb_buf_length += byte_count;
4881 pSMB->ByteCount = cpu_to_le16(byte_count);
4882 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4883 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4884 if (rc)
4885 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4886
4887
4888
4889
4890 return rc;
4891}
4892
4893int
4894CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
4895 bool delete_file, __u16 fid, __u32 pid_of_opener)
4896{
4897 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4898 char *data_offset;
4899 int rc = 0;
4900 __u16 params, param_offset, offset, byte_count, count;
4901
4902 cFYI(1, ("Set File Disposition (via SetFileInfo)"));
4903 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4904
4905 if (rc)
4906 return rc;
4907
4908 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4909 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4910
4911 params = 6;
4912 pSMB->MaxSetupCount = 0;
4913 pSMB->Reserved = 0;
4914 pSMB->Flags = 0;
4915 pSMB->Timeout = 0;
4916 pSMB->Reserved2 = 0;
4917 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4918 offset = param_offset + params;
4919
4920 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4921
4922 count = 1;
4923 pSMB->MaxParameterCount = cpu_to_le16(2);
4924
4925 pSMB->MaxDataCount = cpu_to_le16(1000);
4926 pSMB->SetupCount = 1;
4927 pSMB->Reserved3 = 0;
4928 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4929 byte_count = 3 + params + count;
4930 pSMB->DataCount = cpu_to_le16(count);
4931 pSMB->ParameterCount = cpu_to_le16(params);
4932 pSMB->TotalDataCount = pSMB->DataCount;
4933 pSMB->TotalParameterCount = pSMB->ParameterCount;
4934 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4935 pSMB->DataOffset = cpu_to_le16(offset);
4936 pSMB->Fid = fid;
4937 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
4938 pSMB->Reserved4 = 0;
4939 pSMB->hdr.smb_buf_length += byte_count;
4940 pSMB->ByteCount = cpu_to_le16(byte_count);
4941 *data_offset = delete_file ? 1 : 0;
4942 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4943 if (rc)
4944 cFYI(1, ("Send error in SetFileDisposition = %d", rc));
4945
4946 return rc;
4947}
4948
4949int
4950CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
4951 const char *fileName, const FILE_BASIC_INFO *data,
4952 const struct nls_table *nls_codepage, int remap)
4953{
4954 TRANSACTION2_SPI_REQ *pSMB = NULL;
4955 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4956 int name_len;
4957 int rc = 0;
4958 int bytes_returned = 0;
4959 char *data_offset;
4960 __u16 params, param_offset, offset, byte_count, count;
4961
4962 cFYI(1, ("In SetTimes"));
4963
4964SetTimesRetry:
4965 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4966 (void **) &pSMBr);
4967 if (rc)
4968 return rc;
4969
4970 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4971 name_len =
4972 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4973 PATH_MAX, nls_codepage, remap);
4974 name_len++;
4975 name_len *= 2;
4976 } else {
4977 name_len = strnlen(fileName, PATH_MAX);
4978 name_len++;
4979 strncpy(pSMB->FileName, fileName, name_len);
4980 }
4981
4982 params = 6 + name_len;
4983 count = sizeof(FILE_BASIC_INFO);
4984 pSMB->MaxParameterCount = cpu_to_le16(2);
4985
4986 pSMB->MaxDataCount = cpu_to_le16(1000);
4987 pSMB->MaxSetupCount = 0;
4988 pSMB->Reserved = 0;
4989 pSMB->Flags = 0;
4990 pSMB->Timeout = 0;
4991 pSMB->Reserved2 = 0;
4992 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4993 InformationLevel) - 4;
4994 offset = param_offset + params;
4995 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4996 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4997 pSMB->DataOffset = cpu_to_le16(offset);
4998 pSMB->SetupCount = 1;
4999 pSMB->Reserved3 = 0;
5000 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5001 byte_count = 3 + params + count;
5002
5003 pSMB->DataCount = cpu_to_le16(count);
5004 pSMB->ParameterCount = cpu_to_le16(params);
5005 pSMB->TotalDataCount = pSMB->DataCount;
5006 pSMB->TotalParameterCount = pSMB->ParameterCount;
5007 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5008 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5009 else
5010 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5011 pSMB->Reserved4 = 0;
5012 pSMB->hdr.smb_buf_length += byte_count;
5013 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5014 pSMB->ByteCount = cpu_to_le16(byte_count);
5015 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5016 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5017 if (rc)
5018 cFYI(1, ("SetPathInfo (times) returned %d", rc));
5019
5020 cifs_buf_release(pSMB);
5021
5022 if (rc == -EAGAIN)
5023 goto SetTimesRetry;
5024
5025 return rc;
5026}
5027
5028
5029
5030#if 0
5031
5032
5033int
5034CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
5035 __u16 dos_attrs, const struct nls_table *nls_codepage)
5036{
5037 SETATTR_REQ *pSMB = NULL;
5038 SETATTR_RSP *pSMBr = NULL;
5039 int rc = 0;
5040 int bytes_returned;
5041 int name_len;
5042
5043 cFYI(1, ("In SetAttrLegacy"));
5044
5045SetAttrLgcyRetry:
5046 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5047 (void **) &pSMBr);
5048 if (rc)
5049 return rc;
5050
5051 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5052 name_len =
5053 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5054 PATH_MAX, nls_codepage);
5055 name_len++;
5056 name_len *= 2;
5057 } else {
5058