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