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