1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30#include <linux/fs.h>
31#include <linux/kernel.h>
32#include <linux/vfs.h>
33#include <linux/posix_acl_xattr.h>
34#include <asm/uaccess.h>
35#include "cifspdu.h"
36#include "cifsglob.h"
37#include "cifsproto.h"
38#include "cifs_unicode.h"
39#include "cifs_debug.h"
40
41#ifdef CONFIG_CIFS_POSIX
42static struct {
43 int index;
44 char *name;
45} protocols[] = {
46 {CIFS_PROT, "\2NT LM 0.12"},
47 {CIFS_PROT, "\2POSIX 2"},
48 {BAD_PROT, "\2"}
49};
50#else
51static struct {
52 int index;
53 char *name;
54} protocols[] = {
55 {CIFS_PROT, "\2NT LM 0.12"},
56 {BAD_PROT, "\2"}
57};
58#endif
59
60
61
62
63static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
64{
65 struct cifsFileInfo *open_file = NULL;
66 struct list_head * tmp;
67 struct list_head * tmp1;
68
69
70 write_lock(&GlobalSMBSeslock);
71 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
72 open_file = list_entry(tmp,struct cifsFileInfo, tlist);
73 if(open_file) {
74 open_file->invalidHandle = TRUE;
75 }
76 }
77 write_unlock(&GlobalSMBSeslock);
78
79}
80
81static int
82small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
83 void **request_buf )
84{
85 int rc = 0;
86
87
88
89
90 if(tcon) {
91 if((tcon->ses) && (tcon->ses->server)){
92 struct nls_table *nls_codepage;
93
94
95
96 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
97 wait_event_interruptible_timeout(tcon->ses->server->response_q,
98 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
99 if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
100
101 if((tcon->retry == FALSE) ||
102 (tcon->ses->status == CifsExiting)) {
103 cFYI(1,("gave up waiting on reconnect in smb_init"));
104 return -EHOSTDOWN;
105 }
106
107 } else
108 break;
109
110 }
111
112 nls_codepage = load_nls_default();
113
114
115 down(&tcon->ses->sesSem);
116 if(tcon->ses->status == CifsNeedReconnect)
117 rc = cifs_setup_session(0, tcon->ses, nls_codepage);
118 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
119 mark_open_files_invalid(tcon);
120 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
121 nls_codepage);
122 up(&tcon->ses->sesSem);
123 if(rc == 0)
124 atomic_inc(&tconInfoReconnectCount);
125
126 cFYI(1, ("reconnect tcon rc = %d", rc));
127
128
129
130
131
132
133
134 switch(smb_command) {
135 case SMB_COM_READ_ANDX:
136 case SMB_COM_WRITE_ANDX:
137 case SMB_COM_CLOSE:
138 case SMB_COM_FIND_CLOSE2:
139 case SMB_COM_LOCKING_ANDX: {
140 unload_nls(nls_codepage);
141 return -EAGAIN;
142 }
143 }
144 } else {
145 up(&tcon->ses->sesSem);
146 }
147 unload_nls(nls_codepage);
148
149 } else {
150 return -EIO;
151 }
152 }
153 if(rc)
154 return rc;
155
156 *request_buf = cifs_small_buf_get();
157 if (*request_buf == 0) {
158
159 return -ENOMEM;
160 }
161
162 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
163
164#ifdef CONFIG_CIFS_STATS
165 if(tcon != NULL) {
166 atomic_inc(&tcon->num_smbs_sent);
167 }
168#endif
169 return rc;
170}
171
172static int
173smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
174 void **request_buf ,
175 void **response_buf )
176{
177 int rc = 0;
178
179
180
181
182 if(tcon) {
183 if((tcon->ses) && (tcon->ses->server)){
184 struct nls_table *nls_codepage;
185
186
187
188 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
189 wait_event_interruptible_timeout(tcon->ses->server->response_q,
190 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
191 if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
192
193 if((tcon->retry == FALSE) ||
194 (tcon->ses->status == CifsExiting)) {
195 cFYI(1,("gave up waiting on reconnect in smb_init"));
196 return -EHOSTDOWN;
197 }
198
199 } else
200 break;
201
202 }
203
204 nls_codepage = load_nls_default();
205
206
207 down(&tcon->ses->sesSem);
208 if(tcon->ses->status == CifsNeedReconnect)
209 rc = cifs_setup_session(0, tcon->ses, nls_codepage);
210 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
211 mark_open_files_invalid(tcon);
212 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
213 nls_codepage);
214 up(&tcon->ses->sesSem);
215 if(rc == 0)
216 atomic_inc(&tconInfoReconnectCount);
217
218 cFYI(1, ("reconnect tcon rc = %d", rc));
219
220
221
222
223
224
225
226 switch(smb_command) {
227 case SMB_COM_READ_ANDX:
228 case SMB_COM_WRITE_ANDX:
229 case SMB_COM_CLOSE:
230 case SMB_COM_FIND_CLOSE2:
231 case SMB_COM_LOCKING_ANDX: {
232 unload_nls(nls_codepage);
233 return -EAGAIN;
234 }
235 }
236 } else {
237 up(&tcon->ses->sesSem);
238 }
239 unload_nls(nls_codepage);
240
241 } else {
242 return -EIO;
243 }
244 }
245 if(rc)
246 return rc;
247
248 *request_buf = cifs_buf_get();
249 if (*request_buf == 0) {
250
251 return -ENOMEM;
252 }
253
254
255
256
257 *response_buf = *request_buf;
258
259 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
260 wct );
261
262#ifdef CONFIG_CIFS_STATS
263 if(tcon != NULL) {
264 atomic_inc(&tcon->num_smbs_sent);
265 }
266#endif
267 return rc;
268}
269
270static int validate_t2(struct smb_t2_rsp * pSMB)
271{
272 int rc = -EINVAL;
273 int total_size;
274 char * pBCC;
275
276
277
278 if(pSMB->hdr.WordCount >= 10) {
279 if((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
280 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
281
282
283 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
284 if(total_size < 512) {
285 total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
286
287 pBCC = (pSMB->hdr.WordCount * 2) + sizeof(struct smb_hdr) +
288 (char *)pSMB;
289 if((total_size <= (*(u16 *)pBCC)) &&
290 (total_size <
291 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
292 return 0;
293 }
294
295 }
296 }
297 }
298 cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB,
299 sizeof(struct smb_t2_rsp) + 16);
300 return rc;
301}
302int
303CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
304{
305 NEGOTIATE_REQ *pSMB;
306 NEGOTIATE_RSP *pSMBr;
307 int rc = 0;
308 int bytes_returned;
309 struct TCP_Server_Info * server;
310 u16 count;
311
312 if(ses->server)
313 server = ses->server;
314 else {
315 rc = -EIO;
316 return rc;
317 }
318 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL ,
319 (void **) &pSMB, (void **) &pSMBr);
320 if (rc)
321 return rc;
322
323 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
324 if (extended_security)
325 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
326
327 count = strlen(protocols[0].name) + 1;
328 strncpy(pSMB->DialectsArray, protocols[0].name, 30);
329
330
331 pSMB->hdr.smb_buf_length += count;
332 pSMB->ByteCount = cpu_to_le16(count);
333
334 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
335 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
336 if (rc == 0) {
337 server->secMode = pSMBr->SecurityMode;
338 server->secType = NTLM;
339
340 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
341
342 server->maxBuf =
343 min(le32_to_cpu(pSMBr->MaxBufferSize),
344 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
345 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
346 cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
347 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
348 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
349 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
350
351 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
352 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
353 CIFS_CRYPTO_KEY_SIZE);
354 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
355 && (pSMBr->EncryptionKeyLength == 0)) {
356
357 } else
358 rc = -EIO;
359
360
361
362 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
363 (server->capabilities & CAP_EXTENDED_SECURITY)) {
364 count = pSMBr->ByteCount;
365 if (count < 16)
366 rc = -EIO;
367 else if (count == 16) {
368 server->secType = RawNTLMSSP;
369 if (server->socketUseCount.counter > 1) {
370 if (memcmp
371 (server->server_GUID,
372 pSMBr->u.extended_response.
373 GUID, 16) != 0) {
374 cFYI(1,
375 ("UID of server does not match previous connection to same ip address"));
376 memcpy(server->
377 server_GUID,
378 pSMBr->u.
379 extended_response.
380 GUID, 16);
381 }
382 } else
383 memcpy(server->server_GUID,
384 pSMBr->u.extended_response.
385 GUID, 16);
386 } else {
387 rc = decode_negTokenInit(pSMBr->u.
388 extended_response.
389 SecurityBlob,
390 count - 16,
391 &server->secType);
392 if(rc == 1) {
393
394 rc = -EOPNOTSUPP;
395 } else {
396 rc = -EINVAL;
397 }
398 }
399 } else
400 server->capabilities &= ~CAP_EXTENDED_SECURITY;
401 if(sign_CIFS_PDUs == FALSE) {
402 if(server->secMode & SECMODE_SIGN_REQUIRED)
403 cERROR(1,
404 ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
405 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
406 } else if(sign_CIFS_PDUs == 1) {
407 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
408 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
409 }
410
411 }
412 if (pSMB)
413 cifs_buf_release(pSMB);
414 return rc;
415}
416
417int
418CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
419{
420 struct smb_hdr *smb_buffer;
421 struct smb_hdr *smb_buffer_response;
422 int rc = 0;
423 int length;
424
425 cFYI(1, ("In tree disconnect"));
426
427
428
429
430
431
432
433 if (tcon)
434 down(&tcon->tconSem);
435 else
436 return -EIO;
437
438 atomic_dec(&tcon->useCount);
439 if (atomic_read(&tcon->useCount) > 0) {
440 up(&tcon->tconSem);
441 return -EBUSY;
442 }
443
444
445
446 if(tcon->tidStatus == CifsNeedReconnect) {
447 up(&tcon->tconSem);
448 return 0;
449 }
450
451 if((tcon->ses == 0) || (tcon->ses->server == 0)) {
452 up(&tcon->tconSem);
453 return -EIO;
454 }
455 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon, (void **)&smb_buffer);
456 if (rc) {
457 up(&tcon->tconSem);
458 return rc;
459 } else {
460 smb_buffer_response = smb_buffer;
461 }
462 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
463 &length, 0);
464 if (rc)
465 cFYI(1, (" Tree disconnect failed %d", rc));
466
467 if (smb_buffer)
468 cifs_small_buf_release(smb_buffer);
469 up(&tcon->tconSem);
470
471
472
473 if (rc == -EAGAIN)
474 rc = 0;
475
476 return rc;
477}
478
479int
480CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
481{
482 struct smb_hdr *smb_buffer_response;
483 LOGOFF_ANDX_REQ *pSMB;
484 int rc = 0;
485 int length;
486
487 cFYI(1, ("In SMBLogoff for session disconnect"));
488 if (ses)
489 down(&ses->sesSem);
490 else
491 return -EIO;
492
493 atomic_dec(&ses->inUse);
494 if (atomic_read(&ses->inUse) > 0) {
495 up(&ses->sesSem);
496 return -EBUSY;
497 }
498 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
499 smb_buffer_response = (struct smb_hdr *)pSMB;
500
501 if(ses->server) {
502 if(ses->server->secMode &
503 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
504 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
505 }
506
507 if (rc) {
508 up(&ses->sesSem);
509 return rc;
510 }
511
512 pSMB->hdr.Uid = ses->Suid;
513
514 pSMB->AndXCommand = 0xFF;
515 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
516 smb_buffer_response, &length, 0);
517 if (ses->server) {
518 atomic_dec(&ses->server->socketUseCount);
519 if (atomic_read(&ses->server->socketUseCount) == 0) {
520 spin_lock(&GlobalMid_Lock);
521 ses->server->tcpStatus = CifsExiting;
522 spin_unlock(&GlobalMid_Lock);
523 rc = -ESHUTDOWN;
524 }
525 }
526 if (pSMB)
527 cifs_small_buf_release(pSMB);
528 up(&ses->sesSem);
529
530
531
532
533 if (rc == -EAGAIN)
534 rc = 0;
535 return rc;
536}
537
538int
539CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
540 const char *fileName, const struct nls_table *nls_codepage)
541{
542 DELETE_FILE_REQ *pSMB = NULL;
543 DELETE_FILE_RSP *pSMBr = NULL;
544 int rc = 0;
545 int bytes_returned;
546 int name_len;
547
548DelFileRetry:
549 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
550 (void **) &pSMBr);
551 if (rc)
552 return rc;
553
554 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
555 name_len =
556 cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, PATH_MAX
557
558 , nls_codepage);
559 name_len++;
560 name_len *= 2;
561 } else {
562 name_len = strnlen(fileName, PATH_MAX);
563 name_len++;
564 strncpy(pSMB->fileName, fileName, name_len);
565 }
566 pSMB->SearchAttributes =
567 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
568 pSMB->BufferFormat = 0x04;
569 pSMB->hdr.smb_buf_length += name_len + 1;
570 pSMB->ByteCount = cpu_to_le16(name_len + 1);
571 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
572 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
573 if (rc) {
574 cFYI(1, ("Error in RMFile = %d", rc));
575 }
576#ifdef CONFIG_CIFS_STATS
577 else {
578 atomic_inc(&tcon->num_deletes);
579 }
580#endif
581
582 if (pSMB)
583 cifs_buf_release(pSMB);
584 if (rc == -EAGAIN)
585 goto DelFileRetry;
586
587 return rc;
588}
589
590int
591CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
592 const char *dirName, const struct nls_table *nls_codepage)
593{
594 DELETE_DIRECTORY_REQ *pSMB = NULL;
595 DELETE_DIRECTORY_RSP *pSMBr = NULL;
596 int rc = 0;
597 int bytes_returned;
598 int name_len;
599
600 cFYI(1, ("In CIFSSMBRmDir"));
601RmDirRetry:
602 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
603 (void **) &pSMBr);
604 if (rc)
605 return rc;
606
607 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
608 name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, PATH_MAX
609
610 , nls_codepage);
611 name_len++;
612 name_len *= 2;
613 } else {
614 name_len = strnlen(dirName, PATH_MAX);
615 name_len++;
616 strncpy(pSMB->DirName, dirName, name_len);
617 }
618
619 pSMB->BufferFormat = 0x04;
620 pSMB->hdr.smb_buf_length += name_len + 1;
621 pSMB->ByteCount = cpu_to_le16(name_len + 1);
622 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
623 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
624 if (rc) {
625 cFYI(1, ("Error in RMDir = %d", rc));
626 }
627#ifdef CONFIG_CIFS_STATS
628 else {
629 atomic_inc(&tcon->num_rmdirs);
630 }
631#endif
632
633 if (pSMB)
634 cifs_buf_release(pSMB);
635 if (rc == -EAGAIN)
636 goto RmDirRetry;
637 return rc;
638}
639
640int
641CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
642 const char *name, const struct nls_table *nls_codepage)
643{
644 int rc = 0;
645 CREATE_DIRECTORY_REQ *pSMB = NULL;
646 CREATE_DIRECTORY_RSP *pSMBr = NULL;
647 int bytes_returned;
648 int name_len;
649
650 cFYI(1, ("In CIFSSMBMkDir"));
651MkDirRetry:
652 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
653 (void **) &pSMBr);
654 if (rc)
655 return rc;
656
657 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
658 name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, PATH_MAX
659
660 , nls_codepage);
661 name_len++;
662 name_len *= 2;
663 } else {
664 name_len = strnlen(name, PATH_MAX);
665 name_len++;
666 strncpy(pSMB->DirName, name, name_len);
667 }
668
669 pSMB->BufferFormat = 0x04;
670 pSMB->hdr.smb_buf_length += name_len + 1;
671 pSMB->ByteCount = cpu_to_le16(name_len + 1);
672 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
673 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
674 if (rc) {
675 cFYI(1, ("Error in Mkdir = %d", rc));
676 }
677#ifdef CONFIG_CIFS_STATS
678 else {
679 atomic_inc(&tcon->num_mkdirs);
680 }
681#endif
682 if (pSMB)
683 cifs_buf_release(pSMB);
684 if (rc == -EAGAIN)
685 goto MkDirRetry;
686 return rc;
687}
688
689int
690CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
691 const char *fileName, const int openDisposition,
692 const int access_flags, const int create_options, __u16 * netfid,
693 int *pOplock, FILE_ALL_INFO * pfile_info,
694 const struct nls_table *nls_codepage)
695{
696 int rc = -EACCES;
697 OPEN_REQ *pSMB = NULL;
698 OPEN_RSP *pSMBr = NULL;
699 int bytes_returned;
700 int name_len;
701 __u16 count;
702
703openRetry:
704 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
705 (void **) &pSMBr);
706 if (rc)
707 return rc;
708
709 pSMB->AndXCommand = 0xFF;
710
711 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
712 count = 1;
713 name_len =
714 cifs_strtoUCS((wchar_t *) (pSMB->fileName + 1),
715 fileName, PATH_MAX
716
717 , nls_codepage);
718 name_len++;
719 name_len *= 2;
720 pSMB->NameLength = cpu_to_le16(name_len);
721 } else {
722 count = 0;
723 name_len = strnlen(fileName, PATH_MAX);
724 name_len++;
725 pSMB->NameLength = cpu_to_le16(name_len);
726 strncpy(pSMB->fileName, fileName, name_len);
727 }
728 if (*pOplock & REQ_OPLOCK)
729 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
730 else if (*pOplock & REQ_BATCHOPLOCK) {
731 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
732 }
733 pSMB->DesiredAccess = cpu_to_le32(access_flags);
734 pSMB->AllocationSize = 0;
735 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
736
737
738
739 if (tcon->ses->capabilities & CAP_UNIX)
740 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
741
742
743
744
745
746
747 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
748 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
749 pSMB->CreateOptions = cpu_to_le32(create_options);
750 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
751 pSMB->SecurityFlags =
752 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
753
754 count += name_len;
755 pSMB->hdr.smb_buf_length += count;
756
757 pSMB->ByteCount = cpu_to_le16(count);
758
759 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
760 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
761 if (rc) {
762 cFYI(1, ("Error in Open = %d", rc));
763 } else {
764 *pOplock = pSMBr->OplockLevel;
765 *netfid = pSMBr->Fid;
766
767
768 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
769 *pOplock |= CIFS_CREATE_ACTION;
770 if(pfile_info) {
771 memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
772 36 );
773
774 pfile_info->AllocationSize = pSMBr->AllocationSize;
775 pfile_info->EndOfFile = pSMBr->EndOfFile;
776 pfile_info->NumberOfLinks = cpu_to_le32(1);
777 }
778
779#ifdef CONFIG_CIFS_STATS
780 atomic_inc(&tcon->num_opens);
781#endif
782 }
783 if (pSMB)
784 cifs_buf_release(pSMB);
785 if (rc == -EAGAIN)
786 goto openRetry;
787 return rc;
788}
789
790
791
792
793
794int
795CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
796 const int netfid, const unsigned int count,
797 const __u64 lseek, unsigned int *nbytes, char **buf)
798{
799 int rc = -EACCES;
800 READ_REQ *pSMB = NULL;
801 READ_RSP *pSMBr = NULL;
802 char *pReadData = NULL;
803 int bytes_returned;
804
805 *nbytes = 0;
806 rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
807 (void **) &pSMBr);
808 if (rc)
809 return rc;
810
811
812 if (tcon->ses->server == NULL)
813 return -ECONNABORTED;
814
815 pSMB->AndXCommand = 0xFF;
816 pSMB->Fid = netfid;
817 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
818 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
819 pSMB->Remaining = 0;
820 pSMB->MaxCount = cpu_to_le16(count);
821 pSMB->MaxCountHigh = 0;
822 pSMB->ByteCount = 0;
823
824 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
825 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
826 if (rc) {
827 cERROR(1, ("Send error in read = %d", rc));
828 } else {
829 __u16 data_length = le16_to_cpu(pSMBr->DataLength);
830 *nbytes = data_length;
831
832 if ((data_length > CIFSMaxBufSize)
833 || (data_length > count)) {
834 cFYI(1,("bad length %d for count %d",data_length,count));
835 rc = -EIO;
836 *nbytes = 0;
837 } else {
838 pReadData =
839 (char *) (&pSMBr->hdr.Protocol) +
840 le16_to_cpu(pSMBr->DataOffset);
841
842
843
844
845 if(*buf)
846 memcpy(*buf,pReadData,data_length);
847 }
848 }
849 if (pSMB) {
850 if(*buf)
851 cifs_buf_release(pSMB);
852 else
853 *buf = (char *)pSMB;
854 }
855
856
857
858 return rc;
859}
860
861int
862CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
863 const int netfid, const unsigned int count,
864 const __u64 offset, unsigned int *nbytes, const char *buf,
865 const char __user * ubuf, const int long_op)
866{
867 int rc = -EACCES;
868 WRITE_REQ *pSMB = NULL;
869 WRITE_RSP *pSMBr = NULL;
870 int bytes_returned;
871 unsigned bytes_sent;
872 __u16 byte_count;
873
874 rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
875 (void **) &pSMBr);
876 if (rc)
877 return rc;
878
879 if (tcon->ses->server == NULL)
880 return -ECONNABORTED;
881
882 pSMB->AndXCommand = 0xFF;
883 pSMB->Fid = netfid;
884 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
885 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
886 pSMB->Reserved = 0xFFFFFFFF;
887 pSMB->WriteMode = 0;
888 pSMB->Remaining = 0;
889
890
891
892
893 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF;
894 if (bytes_sent > count)
895 bytes_sent = count;
896 pSMB->DataLengthHigh = 0;
897 pSMB->DataOffset =
898 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
899 if(buf)
900 memcpy(pSMB->Data,buf,bytes_sent);
901 else if(ubuf)
902 copy_from_user(pSMB->Data,ubuf,bytes_sent);
903 else {
904
905 if(pSMB)
906 cifs_buf_release(pSMB);
907 return -EINVAL;
908 }
909
910 byte_count = bytes_sent + 1 ;
911 pSMB->DataLengthLow = cpu_to_le16(bytes_sent);
912 pSMB->DataLengthHigh = 0;
913 pSMB->hdr.smb_buf_length += byte_count;
914 pSMB->ByteCount = cpu_to_le16(byte_count);
915
916 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
917 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
918 if (rc) {
919 cFYI(1, ("Send error in write = %d", rc));
920 *nbytes = 0;
921 } else
922 *nbytes = le16_to_cpu(pSMBr->Count);
923
924 if (pSMB)
925 cifs_buf_release(pSMB);
926
927
928
929
930 return rc;
931}
932
933#ifdef CONFIG_CIFS_EXPERIMENTAL
934int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
935 const int netfid, const unsigned int count,
936 const __u64 offset, unsigned int *nbytes, const char __user *buf,
937 const int long_op)
938{
939 int rc = -EACCES;
940 WRITE_REQ *pSMB = NULL;
941 WRITE_RSP *pSMBr = NULL;
942
943 unsigned bytes_sent;
944 __u16 byte_count;
945
946 rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB);
947 pSMBr = (WRITE_RSP *)pSMB;
948
949 if (rc)
950 return rc;
951
952 if (tcon->ses->server == NULL)
953 return -ECONNABORTED;
954
955 pSMB->AndXCommand = 0xFF;
956 pSMB->Fid = netfid;
957 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
958 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
959 pSMB->Reserved = 0xFFFFFFFF;
960 pSMB->WriteMode = 0;
961 pSMB->Remaining = 0;
962 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF;
963 if (bytes_sent > count)
964 bytes_sent = count;
965 pSMB->DataLengthHigh = 0;
966 pSMB->DataOffset =
967 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
968
969 byte_count = bytes_sent + 1 ;
970 pSMB->DataLengthLow = cpu_to_le16(bytes_sent);
971 pSMB->DataLengthHigh = 0;
972 pSMB->hdr.smb_buf_length += byte_count;
973 pSMB->ByteCount = cpu_to_le16(byte_count);
974
975
976
977 if (rc) {
978 cFYI(1, ("Send error in write2 (large write) = %d", rc));
979 *nbytes = 0;
980 } else
981 *nbytes = le16_to_cpu(pSMBr->Count);
982
983 if (pSMB)
984 cifs_small_buf_release(pSMB);
985
986
987
988
989 return rc;
990}
991#endif
992
993int
994CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
995 const __u16 smb_file_id, const __u64 len,
996 const __u64 offset, const __u32 numUnlock,
997 const __u32 numLock, const __u8 lockType, const int waitFlag)
998{
999 int rc = 0;
1000 LOCK_REQ *pSMB = NULL;
1001 LOCK_RSP *pSMBr = NULL;
1002 int bytes_returned;
1003 int timeout = 0;
1004 __u16 count;
1005
1006 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
1007 rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB,
1008 (void **) &pSMBr);
1009 if (rc)
1010 return rc;
1011
1012 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1013 timeout = -1;
1014 pSMB->Timeout = 0;
1015 } else if (waitFlag == TRUE) {
1016 timeout = 3;
1017 pSMB->Timeout = cpu_to_le32(-1);
1018 } else {
1019 pSMB->Timeout = 0;
1020 }
1021
1022 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1023 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1024 pSMB->LockType = lockType;
1025 pSMB->AndXCommand = 0xFF;
1026 pSMB->Fid = smb_file_id;
1027
1028 if((numLock != 0) || (numUnlock != 0)) {
1029 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1030
1031 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1032 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1033 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1034 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1035 count = sizeof(LOCKING_ANDX_RANGE);
1036 } else {
1037
1038 count = 0;
1039 }
1040 pSMB->hdr.smb_buf_length += count;
1041 pSMB->ByteCount = cpu_to_le16(count);
1042
1043 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1044 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1045
1046 if (rc) {
1047 cFYI(1, ("Send error in Lock = %d", rc));
1048 }
1049 if (pSMB)
1050 cifs_buf_release(pSMB);
1051
1052
1053
1054 return rc;
1055}
1056
1057int
1058CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1059{
1060 int rc = 0;
1061 CLOSE_REQ *pSMB = NULL;
1062 CLOSE_RSP *pSMBr = NULL;
1063 int bytes_returned;
1064 cFYI(1, ("In CIFSSMBClose"));
1065
1066
1067 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1068 pSMBr = (CLOSE_RSP *)pSMB;
1069 if(rc == -EAGAIN)
1070 return 0;
1071 if (rc)
1072 return rc;
1073
1074 pSMB->FileID = (__u16) smb_file_id;
1075 pSMB->LastWriteTime = 0;
1076 pSMB->ByteCount = 0;
1077 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1078 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1079 if (rc) {
1080 if(rc!=-EINTR) {
1081
1082 cERROR(1, ("Send error in Close = %d", rc));
1083 }
1084 }
1085
1086 if (pSMB)
1087 cifs_small_buf_release(pSMB);
1088
1089
1090 if(rc == -EAGAIN)
1091 rc = 0;
1092
1093 return rc;
1094}
1095
1096int
1097CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1098 const char *fromName, const char *toName,
1099 const struct nls_table *nls_codepage)
1100{
1101 int rc = 0;
1102 RENAME_REQ *pSMB = NULL;
1103 RENAME_RSP *pSMBr = NULL;
1104 int bytes_returned;
1105 int name_len, name_len2;
1106 __u16 count;
1107
1108 cFYI(1, ("In CIFSSMBRename"));
1109renameRetry:
1110 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1111 (void **) &pSMBr);
1112 if (rc)
1113 return rc;
1114
1115 pSMB->BufferFormat = 0x04;
1116 pSMB->SearchAttributes =
1117 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1118 ATTR_DIRECTORY);
1119
1120 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1121 name_len =
1122 cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, PATH_MAX
1123
1124 , nls_codepage);
1125 name_len++;
1126 name_len *= 2;
1127 pSMB->OldFileName[name_len] = 0x04;
1128
1129 pSMB->OldFileName[name_len + 1] = 0x00;
1130 name_len2 =
1131 cifs_strtoUCS((wchar_t *) & pSMB->
1132 OldFileName[name_len + 2], toName, PATH_MAX,
1133 nls_codepage);
1134 name_len2 += 1 + 1 ;
1135 name_len2 *= 2;
1136 } else {
1137 name_len = strnlen(fromName, PATH_MAX);
1138 name_len++;
1139 strncpy(pSMB->OldFileName, fromName, name_len);
1140 name_len2 = strnlen(toName, PATH_MAX);
1141 name_len2++;
1142 pSMB->OldFileName[name_len] = 0x04;
1143 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1144 name_len2++;
1145 name_len2++;
1146 }
1147
1148 count = 1 + name_len + name_len2;
1149 pSMB->hdr.smb_buf_length += count;
1150 pSMB->ByteCount = cpu_to_le16(count);
1151
1152 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1153 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1154 if (rc) {
1155 cFYI(1, ("Send error in rename = %d", rc));
1156 }
1157
1158#ifdef CONFIG_CIFS_STATS
1159 else {
1160 atomic_inc(&tcon->num_renames);
1161 }
1162#endif
1163
1164 if (pSMB)
1165 cifs_buf_release(pSMB);
1166
1167 if (rc == -EAGAIN)
1168 goto renameRetry;
1169
1170 return rc;
1171}
1172
1173int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1174 int netfid, char * target_name, const struct nls_table * nls_codepage)
1175{
1176 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1177 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1178 struct set_file_rename * rename_info;
1179 char *data_offset;
1180 char dummy_string[30];
1181 int rc = 0;
1182 int bytes_returned = 0;
1183 int len_of_str;
1184 __u16 params, param_offset, offset, count, byte_count;
1185
1186 cFYI(1, ("Rename to File by handle"));
1187 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1188 (void **) &pSMBr);
1189 if (rc)
1190 return rc;
1191
1192 params = 6;
1193 pSMB->MaxSetupCount = 0;
1194 pSMB->Reserved = 0;
1195 pSMB->Flags = 0;
1196 pSMB->Timeout = 0;
1197 pSMB->Reserved2 = 0;
1198 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1199 offset = param_offset + params;
1200
1201 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1202 rename_info = (struct set_file_rename *) data_offset;
1203 pSMB->MaxParameterCount = cpu_to_le16(2);
1204 pSMB->MaxDataCount = cpu_to_le16(1000);
1205 pSMB->SetupCount = 1;
1206 pSMB->Reserved3 = 0;
1207 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1208 byte_count = 3 + params;
1209 pSMB->ParameterCount = cpu_to_le16(params);
1210 pSMB->TotalParameterCount = pSMB->ParameterCount;
1211 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1212 pSMB->DataOffset = cpu_to_le16(offset);
1213
1214 rename_info->overwrite = cpu_to_le32(1);
1215 rename_info->root_fid = 0;
1216
1217 if(target_name == NULL) {
1218 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1219 len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, dummy_string, 24, nls_codepage);
1220 } else {
1221 len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, PATH_MAX, nls_codepage);
1222 }
1223 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1224 count = 12 + (2 * len_of_str) + 2;
1225 byte_count += count;
1226 pSMB->DataCount = cpu_to_le16(count);
1227 pSMB->TotalDataCount = pSMB->DataCount;
1228 pSMB->Fid = netfid;
1229 pSMB->InformationLevel =
1230 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1231 pSMB->Reserved4 = 0;
1232 pSMB->hdr.smb_buf_length += byte_count;
1233 pSMB->ByteCount = cpu_to_le16(byte_count);
1234 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1235 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1236 if (rc) {
1237 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1238 }
1239#ifdef CONFIG_CIFS_STATS
1240 else {
1241 atomic_inc(&pTcon->num_t2renames);
1242 }
1243#endif
1244 if (pSMB)
1245 cifs_buf_release(pSMB);
1246
1247
1248
1249
1250 return rc;
1251}
1252
1253int
1254CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1255 const __u16 target_tid, const char *toName, const int flags,
1256 const struct nls_table *nls_codepage)
1257{
1258 int rc = 0;
1259 COPY_REQ *pSMB = NULL;
1260 COPY_RSP *pSMBr = NULL;
1261 int bytes_returned;
1262 int name_len, name_len2;
1263 __u16 count;
1264
1265 cFYI(1, ("In CIFSSMBCopy"));
1266copyRetry:
1267 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1268 (void **) &pSMBr);
1269 if (rc)
1270 return rc;
1271
1272 pSMB->BufferFormat = 0x04;
1273 pSMB->Tid2 = target_tid;
1274
1275 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1276
1277 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1278 name_len = cifs_strtoUCS((wchar_t *) pSMB->OldFileName,
1279 fromName,
1280 PATH_MAX ,
1281 nls_codepage);
1282 name_len++;
1283 name_len *= 2;
1284 pSMB->OldFileName[name_len] = 0x04;
1285
1286 pSMB->OldFileName[name_len + 1] = 0x00;
1287 name_len2 = cifs_strtoUCS((wchar_t *) & pSMB->
1288 OldFileName[name_len + 2], toName, PATH_MAX,
1289 nls_codepage);
1290 name_len2 += 1 + 1 ;
1291 name_len2 *= 2;
1292 } else {
1293 name_len = strnlen(fromName, PATH_MAX);
1294 name_len++;
1295 strncpy(pSMB->OldFileName, fromName, name_len);
1296 name_len2 = strnlen(toName, PATH_MAX);
1297 name_len2++;
1298 pSMB->OldFileName[name_len] = 0x04;
1299 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1300 name_len2++;
1301 name_len2++;
1302 }
1303
1304 count = 1 + name_len + name_len2;
1305 pSMB->hdr.smb_buf_length += count;
1306 pSMB->ByteCount = cpu_to_le16(count);
1307
1308 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1309 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1310 if (rc) {
1311 cFYI(1, ("Send error in copy = %d with %d files copied",
1312 rc, le16_to_cpu(pSMBr->CopyCount)));
1313 }
1314 if (pSMB)
1315 cifs_buf_release(pSMB);
1316
1317 if (rc == -EAGAIN)
1318 goto copyRetry;
1319
1320 return rc;
1321}
1322
1323int
1324CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1325 const char *fromName, const char *toName,
1326 const struct nls_table *nls_codepage)
1327{
1328 TRANSACTION2_SPI_REQ *pSMB = NULL;
1329 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1330 char *data_offset;
1331 int name_len;
1332 int name_len_target;
1333 int rc = 0;
1334 int bytes_returned = 0;
1335 __u16 params, param_offset, offset, byte_count;
1336
1337 cFYI(1, ("In Symlink Unix style"));
1338createSymLinkRetry:
1339 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1340 (void **) &pSMBr);
1341 if (rc)
1342 return rc;
1343
1344 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1345 name_len =
1346 cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, PATH_MAX
1347
1348 , nls_codepage);
1349 name_len++;
1350 name_len *= 2;
1351
1352 } else {
1353 name_len = strnlen(fromName, PATH_MAX);
1354 name_len++;
1355 strncpy(pSMB->FileName, fromName, name_len);
1356 }
1357 params = 6 + name_len;
1358 pSMB->MaxSetupCount = 0;
1359 pSMB->Reserved = 0;
1360 pSMB->Flags = 0;
1361 pSMB->Timeout = 0;
1362 pSMB->Reserved2 = 0;
1363 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1364 InformationLevel) - 4;
1365 offset = param_offset + params;
1366
1367 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1368 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1369 name_len_target =
1370 cifs_strtoUCS((wchar_t *) data_offset, toName, PATH_MAX
1371
1372 , nls_codepage);
1373 name_len_target++;
1374 name_len_target *= 2;
1375 } else {
1376 name_len_target = strnlen(toName, PATH_MAX);
1377 name_len_target++;
1378 strncpy(data_offset, toName, name_len_target);
1379 }
1380
1381 pSMB->MaxParameterCount = cpu_to_le16(2);
1382
1383 pSMB->MaxDataCount = cpu_to_le16(1000);
1384 pSMB->SetupCount = 1;
1385 pSMB->Reserved3 = 0;
1386 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1387 byte_count = 3 + params + name_len_target;
1388 pSMB->DataCount = cpu_to_le16(name_len_target);
1389 pSMB->ParameterCount = cpu_to_le16(params);
1390 pSMB->TotalDataCount = pSMB->DataCount;
1391 pSMB->TotalParameterCount = pSMB->ParameterCount;
1392 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1393 pSMB->DataOffset = cpu_to_le16(offset);
1394 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1395 pSMB->Reserved4 = 0;
1396 pSMB->hdr.smb_buf_length += byte_count;
1397 pSMB->ByteCount = cpu_to_le16(byte_count);
1398 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1399 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1400 if (rc) {
1401 cFYI(1,
1402 ("Send error in SetPathInfo (create symlink) = %d",
1403 rc));
1404 }
1405
1406 if (pSMB)
1407 cifs_buf_release(pSMB);
1408
1409 if (rc == -EAGAIN)
1410 goto createSymLinkRetry;
1411
1412 return rc;
1413}
1414
1415int
1416CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1417 const char *fromName, const char *toName,
1418 const struct nls_table *nls_codepage)
1419{
1420 TRANSACTION2_SPI_REQ *pSMB = NULL;
1421 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1422 char *data_offset;
1423 int name_len;
1424 int name_len_target;
1425 int rc = 0;
1426 int bytes_returned = 0;
1427 __u16 params, param_offset, offset, byte_count;
1428
1429 cFYI(1, ("In Create Hard link Unix style"));
1430createHardLinkRetry:
1431 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1432 (void **) &pSMBr);
1433 if (rc)
1434 return rc;
1435
1436 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1437 name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, toName, PATH_MAX
1438
1439 , nls_codepage);
1440 name_len++;
1441 name_len *= 2;
1442
1443 } else {
1444 name_len = strnlen(toName, PATH_MAX);
1445 name_len++;
1446 strncpy(pSMB->FileName, toName, name_len);
1447 }
1448 params = 6 + name_len;
1449 pSMB->MaxSetupCount = 0;
1450 pSMB->Reserved = 0;
1451 pSMB->Flags = 0;
1452 pSMB->Timeout = 0;
1453 pSMB->Reserved2 = 0;
1454 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1455 InformationLevel) - 4;
1456 offset = param_offset + params;
1457
1458 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1459 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1460 name_len_target =
1461 cifs_strtoUCS((wchar_t *) data_offset, fromName, PATH_MAX
1462
1463 , nls_codepage);
1464 name_len_target++;
1465 name_len_target *= 2;
1466 } else {
1467 name_len_target = strnlen(fromName, PATH_MAX);
1468 name_len_target++;
1469 strncpy(data_offset, fromName, name_len_target);
1470 }
1471
1472 pSMB->MaxParameterCount = cpu_to_le16(2);
1473
1474 pSMB->MaxDataCount = cpu_to_le16(1000);
1475 pSMB->SetupCount = 1;
1476 pSMB->Reserved3 = 0;
1477 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1478 byte_count = 3 + params + name_len_target;
1479 pSMB->ParameterCount = cpu_to_le16(params);
1480 pSMB->TotalParameterCount = pSMB->ParameterCount;
1481 pSMB->DataCount = cpu_to_le16(name_len_target);
1482 pSMB->TotalDataCount = pSMB->DataCount;
1483 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1484 pSMB->DataOffset = cpu_to_le16(offset);
1485 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
1486 pSMB->Reserved4 = 0;
1487 pSMB->hdr.smb_buf_length += byte_count;
1488 pSMB->ByteCount = cpu_to_le16(byte_count);
1489 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1490 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1491 if (rc) {
1492 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1493 }
1494
1495 if (pSMB)
1496 cifs_buf_release(pSMB);
1497 if (rc == -EAGAIN)
1498 goto createHardLinkRetry;
1499
1500 return rc;
1501}
1502
1503int
1504CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1505 const char *fromName, const char *toName,
1506 const struct nls_table *nls_codepage)
1507{
1508 int rc = 0;
1509 NT_RENAME_REQ *pSMB = NULL;
1510 RENAME_RSP *pSMBr = NULL;
1511 int bytes_returned;
1512 int name_len, name_len2;
1513 __u16 count;
1514
1515 cFYI(1, ("In CIFSCreateHardLink"));
1516winCreateHardLinkRetry:
1517
1518 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
1519 (void **) &pSMBr);
1520 if (rc)
1521 return rc;
1522
1523 pSMB->SearchAttributes =
1524 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1525 ATTR_DIRECTORY);
1526 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
1527 pSMB->ClusterCount = 0;
1528
1529 pSMB->BufferFormat = 0x04;
1530
1531 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1532 name_len =
1533 cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, PATH_MAX
1534
1535 , nls_codepage);
1536 name_len++;
1537 name_len *= 2;
1538 pSMB->OldFileName[name_len] = 0;
1539 pSMB->OldFileName[name_len + 1] = 0x04;
1540 name_len2 =
1541 cifs_strtoUCS((wchar_t *) & pSMB->
1542 OldFileName[name_len + 2], toName, PATH_MAX,
1543 nls_codepage);
1544 name_len2 += 1 + 1 ;
1545 name_len2 *= 2;
1546 } else {
1547 name_len = strnlen(fromName, PATH_MAX);
1548 name_len++;
1549 strncpy(pSMB->OldFileName, fromName, name_len);
1550 name_len2 = strnlen(toName, PATH_MAX);
1551 name_len2++;
1552 pSMB->OldFileName[name_len] = 0x04;
1553 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1554 name_len2++;
1555 name_len2++;
1556 }
1557
1558 count = 1 + name_len + name_len2;
1559 pSMB->hdr.smb_buf_length += count;
1560 pSMB->ByteCount = cpu_to_le16(count);
1561
1562 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1563 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1564 if (rc) {
1565 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1566 }
1567 if (pSMB)
1568 cifs_buf_release(pSMB);
1569 if (rc == -EAGAIN)
1570 goto winCreateHardLinkRetry;
1571
1572 return rc;
1573}
1574
1575int
1576CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
1577 const unsigned char *searchName,
1578 char *symlinkinfo, const int buflen,
1579 const struct nls_table *nls_codepage)
1580{
1581
1582 TRANSACTION2_QPI_REQ *pSMB = NULL;
1583 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1584 int rc = 0;
1585 int bytes_returned;
1586 int name_len;
1587 __u16 params, byte_count;
1588
1589 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
1590
1591querySymLinkRetry:
1592 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1593 (void **) &pSMBr);
1594 if (rc)
1595 return rc;
1596
1597 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1598 name_len =
1599 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
1600
1601 , nls_codepage);
1602 name_len++;
1603 name_len *= 2;
1604 } else {
1605 name_len = strnlen(searchName, PATH_MAX);
1606 name_len++;
1607 strncpy(pSMB->FileName, searchName, name_len);
1608 }
1609
1610 params = 2 + 4 + name_len ;
1611 pSMB->TotalDataCount = 0;
1612 pSMB->MaxParameterCount = cpu_to_le16(2);
1613
1614 pSMB->MaxDataCount = cpu_to_le16(4000);
1615 pSMB->MaxSetupCount = 0;
1616 pSMB->Reserved = 0;
1617 pSMB->Flags = 0;
1618 pSMB->Timeout = 0;
1619 pSMB->Reserved2 = 0;
1620 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1621 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1622 pSMB->DataCount = 0;
1623 pSMB->DataOffset = 0;
1624 pSMB->SetupCount = 1;
1625 pSMB->Reserved3 = 0;
1626 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1627 byte_count = params + 1 ;
1628 pSMB->TotalParameterCount = cpu_to_le16(params);
1629 pSMB->ParameterCount = pSMB->TotalParameterCount;
1630 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
1631 pSMB->Reserved4 = 0;
1632 pSMB->hdr.smb_buf_length += byte_count;
1633 pSMB->ByteCount = cpu_to_le16(byte_count);
1634
1635 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1636 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1637 if (rc) {
1638 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
1639 } else {
1640
1641
1642 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1643 if (rc || (pSMBr->ByteCount < 2))
1644
1645 rc = -EIO;
1646 else {
1647 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1648 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
1649
1650 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1651 name_len = UniStrnlen((wchar_t *) ((char *)
1652 &pSMBr->hdr.Protocol +data_offset),
1653 min_t(const int, buflen,count) / 2);
1654 cifs_strfromUCS_le(symlinkinfo,
1655 (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
1656 data_offset),
1657 name_len, nls_codepage);
1658 } else {
1659 strncpy(symlinkinfo,
1660 (char *) &pSMBr->hdr.Protocol +
1661 data_offset,
1662 min_t(const int, buflen, count));
1663 }
1664 symlinkinfo[buflen] = 0;
1665
1666 }
1667 }
1668 if (pSMB)
1669 cifs_buf_release(pSMB);
1670 if (rc == -EAGAIN)
1671 goto querySymLinkRetry;
1672 return rc;
1673}
1674
1675
1676
1677int
1678CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1679 const unsigned char *searchName,
1680 char *symlinkinfo, const int buflen,__u16 fid,
1681 const struct nls_table *nls_codepage)
1682{
1683 int rc = 0;
1684 int bytes_returned;
1685 int name_len;
1686 struct smb_com_transaction_ioctl_req * pSMB;
1687 struct smb_com_transaction_ioctl_rsp * pSMBr;
1688
1689 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
1690 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
1691 (void **) &pSMBr);
1692 if (rc)
1693 return rc;
1694
1695 pSMB->TotalParameterCount = 0 ;
1696 pSMB->TotalDataCount = 0;
1697 pSMB->MaxParameterCount = cpu_to_le32(2);
1698
1699 pSMB->MaxDataCount = cpu_to_le32(4000);
1700 pSMB->MaxSetupCount = 4;
1701 pSMB->Reserved = 0;
1702 pSMB->ParameterOffset = 0;
1703 pSMB->DataCount = 0;
1704 pSMB->DataOffset = 0;
1705 pSMB->SetupCount = 4;
1706 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
1707 pSMB->ParameterCount = pSMB->TotalParameterCount;
1708 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
1709 pSMB->IsFsctl = 1;
1710 pSMB->IsRootFlag = 0;
1711 pSMB->Fid = fid;
1712 pSMB->ByteCount = 0;
1713
1714 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1715 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1716 if (rc) {
1717 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
1718 } else {
1719 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
1720 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
1721 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
1722
1723 rc = -EIO;
1724 else {
1725 if(data_count && (data_count < 2048)) {
1726
1727 struct reparse_data * reparse_buf = (struct reparse_data *)
1728 ((char *)&pSMBr->hdr.Protocol + data_offset);
1729 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1730 name_len = UniStrnlen((wchar_t *)
1731 (reparse_buf->LinkNamesBuf +
1732 reparse_buf->TargetNameOffset),
1733 min(buflen/2, reparse_buf->TargetNameLen / 2));
1734 cifs_strfromUCS_le(symlinkinfo,
1735 (wchar_t *) (reparse_buf->LinkNamesBuf +
1736 reparse_buf->TargetNameOffset),
1737 name_len, nls_codepage);
1738 } else {
1739 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
1740 reparse_buf->TargetNameOffset,
1741 min_t(const int, buflen, reparse_buf->TargetNameLen));
1742 }
1743 } else {
1744 rc = -EIO;
1745 cFYI(1,("Invalid return data count on get reparse info ioctl"));
1746 }
1747 symlinkinfo[buflen] = 0;
1748
1749 cFYI(1,("readlink result - %s ",symlinkinfo));
1750 }
1751 }
1752 if (pSMB)
1753 cifs_buf_release(pSMB);
1754
1755
1756
1757
1758 return rc;
1759}
1760
1761#ifdef CONFIG_CIFS_POSIX
1762
1763
1764static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
1765{
1766
1767 ace->e_perm = (__u16)cifs_ace->cifs_e_perm;
1768 ace->e_tag = (__u16)cifs_ace->cifs_e_tag;
1769 ace->e_id = (__u32)le64_to_cpu(cifs_ace->cifs_uid);
1770
1771
1772 return;
1773}
1774
1775
1776static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,const int acl_type,const int size_of_data_area)
1777{
1778 int size = 0;
1779 int i;
1780 __u16 count;
1781 struct cifs_posix_ace * pACE;
1782 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
1783 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
1784
1785 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
1786 return -EOPNOTSUPP;
1787
1788 if(acl_type & ACL_TYPE_ACCESS) {
1789 count = le16_to_cpu(cifs_acl->access_entry_count);
1790 pACE = &cifs_acl->ace_array[0];
1791 size = sizeof(struct cifs_posix_acl);
1792 size += sizeof(struct cifs_posix_ace) * count;
1793
1794 if(size_of_data_area < size) {
1795 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
1796 return -EINVAL;
1797 }
1798 } else if(acl_type & ACL_TYPE_DEFAULT) {
1799 count = le16_to_cpu(cifs_acl->access_entry_count);
1800 size = sizeof(struct cifs_posix_acl);
1801 size += sizeof(struct cifs_posix_ace) * count;
1802
1803 pACE = &cifs_acl->ace_array[count];
1804 count = le16_to_cpu(cifs_acl->default_entry_count);
1805 size += sizeof(struct cifs_posix_ace) * count;
1806
1807 if(size_of_data_area < size)
1808 return -EINVAL;
1809 } else {
1810
1811 return -EINVAL;
1812 }
1813
1814 size = posix_acl_xattr_size(count);
1815 if((buflen == 0) || (local_acl == NULL)) {
1816
1817 } else if(size > buflen) {
1818 return -ERANGE;
1819 } else {
1820 local_acl->a_version = POSIX_ACL_XATTR_VERSION;
1821 for(i = 0;i < count ;i++) {
1822 cifs_convert_ace(&local_acl->a_entries[i],pACE);
1823 pACE ++;
1824 }
1825 }
1826 return size;
1827}
1828
1829__u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
1830 const posix_acl_xattr_entry * local_ace)
1831{
1832 __u16 rc = 0;
1833
1834 cifs_ace->cifs_e_perm = (__u8)cpu_to_le16(local_ace->e_perm);
1835 cifs_ace->cifs_e_tag = (__u8)cpu_to_le16(local_ace->e_tag);
1836
1837 if(local_ace->e_id == -1) {
1838
1839 cifs_ace->cifs_uid = cpu_to_le64(-1);
1840 } else
1841 cifs_ace->cifs_uid = (__u64)cpu_to_le32(local_ace->e_id);
1842
1843 return rc;
1844}
1845
1846
1847__u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
1848 const int acl_type)
1849{
1850 __u16 rc = 0;
1851 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
1852 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
1853 int count;
1854 int i;
1855
1856 if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
1857 return 0;
1858
1859 count = posix_acl_xattr_count((size_t)buflen);
1860 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
1861 count,buflen,local_acl->a_version));
1862 if(local_acl->a_version != 2) {
1863 cFYI(1,("unknown POSIX ACL version %d",local_acl->a_version));
1864 return 0;
1865 }
1866 cifs_acl->version = cpu_to_le16(1);
1867 if(acl_type == ACL_TYPE_ACCESS)
1868 cifs_acl->access_entry_count = count;
1869 else if(acl_type == ACL_TYPE_DEFAULT)
1870 cifs_acl->default_entry_count = count;
1871 else {
1872 cFYI(1,("unknown ACL type %d",acl_type));
1873 return 0;
1874 }
1875 for(i=0;i<count;i++) {
1876 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
1877 &local_acl->a_entries[i]);
1878 if(rc != 0) {
1879
1880 break;
1881 }
1882 }
1883 if(rc == 0) {
1884 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
1885 rc += sizeof(struct cifs_posix_acl);
1886
1887 }
1888 return rc;
1889}
1890
1891int
1892CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
1893 const unsigned char *searchName,
1894 char *acl_inf, const int buflen, const int acl_type,
1895 const struct nls_table *nls_codepage)
1896{
1897
1898 TRANSACTION2_QPI_REQ *pSMB = NULL;
1899 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1900 int rc = 0;
1901 int bytes_returned;
1902 int name_len;
1903 __u16 params, byte_count;
1904
1905 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
1906
1907queryAclRetry:
1908 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1909 (void **) &pSMBr);
1910 if (rc)
1911 return rc;
1912
1913 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1914 name_len =
1915 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
1916
1917 , nls_codepage);
1918 name_len++;
1919 name_len *= 2;
1920 pSMB->FileName[name_len] = 0;
1921 pSMB->FileName[name_len+1] = 0;
1922 } else {
1923 name_len = strnlen(searchName, PATH_MAX );
1924 name_len++;
1925 strncpy(pSMB->FileName, searchName, name_len);
1926 }
1927
1928 params = 2 + 4 + name_len ;
1929 pSMB->TotalDataCount = 0;
1930 pSMB->MaxParameterCount = cpu_to_le16(2);
1931
1932 pSMB->MaxDataCount = cpu_to_le16(4000);
1933 pSMB->MaxSetupCount = 0;
1934 pSMB->Reserved = 0;
1935 pSMB->Flags = 0;
1936 pSMB->Timeout = 0;
1937 pSMB->Reserved2 = 0;
1938 pSMB->ParameterOffset = cpu_to_le16(
1939 offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1940 pSMB->DataCount = 0;
1941 pSMB->DataOffset = 0;
1942 pSMB->SetupCount = 1;
1943 pSMB->Reserved3 = 0;
1944 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1945 byte_count = params + 1 ;
1946 pSMB->TotalParameterCount = cpu_to_le16(params);
1947 pSMB->ParameterCount = pSMB->TotalParameterCount;
1948 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
1949 pSMB->Reserved4 = 0;
1950 pSMB->hdr.smb_buf_length += byte_count;
1951 pSMB->ByteCount = cpu_to_le16(byte_count);
1952
1953 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1954 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1955 if (rc) {
1956 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
1957 } else {
1958
1959
1960 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1961 if (rc || (pSMBr->ByteCount < 2))
1962
1963 rc = -EIO;
1964 else {
1965 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1966 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
1967 rc = cifs_copy_posix_acl(acl_inf,
1968 (char *)&pSMBr->hdr.Protocol+data_offset,
1969 buflen,acl_type,count);
1970 }
1971 }
1972 if (pSMB)
1973 cifs_buf_release(pSMB);
1974 if (rc == -EAGAIN)
1975 goto queryAclRetry;
1976 return rc;
1977}
1978
1979int
1980CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
1981 const unsigned char *fileName,
1982 const char *local_acl, const int buflen, const int acl_type,
1983 const struct nls_table *nls_codepage)
1984{
1985 struct smb_com_transaction2_spi_req *pSMB = NULL;
1986 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
1987 char *parm_data;
1988 int name_len;
1989 int rc = 0;
1990 int bytes_returned = 0;
1991 __u16 params, byte_count, data_count, param_offset, offset;
1992
1993 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
1994setAclRetry:
1995 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1996 (void **) &pSMBr);
1997 if (rc)
1998 return rc;
1999 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2000 name_len =
2001 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
2002
2003 , nls_codepage);
2004 name_len++;
2005 name_len *= 2;
2006 } else {
2007 name_len = strnlen(fileName, PATH_MAX);
2008 name_len++;
2009 strncpy(pSMB->FileName, fileName, name_len);
2010 }
2011 params = 6 + name_len;
2012 pSMB->MaxParameterCount = cpu_to_le16(2);
2013 pSMB->MaxDataCount = cpu_to_le16(1000);
2014 pSMB->MaxSetupCount = 0;
2015 pSMB->Reserved = 0;
2016 pSMB->Flags = 0;
2017 pSMB->Timeout = 0;
2018 pSMB->Reserved2 = 0;
2019 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2020 InformationLevel) - 4;
2021 offset = param_offset + params;
2022 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2023 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2024
2025
2026 data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
2027
2028 if(data_count == 0) {
2029 rc = -EOPNOTSUPP;
2030 goto setACLerrorExit;
2031 }
2032 pSMB->DataOffset = cpu_to_le16(offset);
2033 pSMB->SetupCount = 1;
2034 pSMB->Reserved3 = 0;
2035 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2036 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2037 byte_count = 3 + params + data_count;
2038 pSMB->DataCount = cpu_to_le16(data_count);
2039 pSMB->TotalDataCount = pSMB->DataCount;
2040 pSMB->ParameterCount = cpu_to_le16(params);
2041 pSMB->TotalParameterCount = pSMB->ParameterCount;
2042 pSMB->Reserved4 = 0;
2043 pSMB->hdr.smb_buf_length += byte_count;
2044 pSMB->ByteCount = cpu_to_le16(byte_count);
2045 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2046 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2047 if (rc) {
2048 cFYI(1, ("Set POSIX ACL returned %d", rc));
2049 }
2050
2051setACLerrorExit:
2052 if (pSMB)
2053 cifs_buf_release(pSMB);
2054 if (rc == -EAGAIN)
2055 goto setAclRetry;
2056 return rc;
2057}
2058
2059#endif
2060
2061int
2062CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2063 const unsigned char *searchName,
2064 FILE_ALL_INFO * pFindData,
2065 const struct nls_table *nls_codepage)
2066{
2067
2068 TRANSACTION2_QPI_REQ *pSMB = NULL;
2069 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2070 int rc = 0;
2071 int bytes_returned;
2072 int name_len;
2073 __u16 params, byte_count;
2074
2075
2076QPathInfoRetry:
2077 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2078 (void **) &pSMBr);
2079 if (rc)
2080 return rc;
2081
2082 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2083 name_len =
2084 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
2085
2086 , nls_codepage);
2087 name_len++;
2088 name_len *= 2;
2089 } else {
2090 name_len = strnlen(searchName, PATH_MAX);
2091 name_len++;
2092 strncpy(pSMB->FileName, searchName, name_len);
2093 }
2094
2095 params = 2 + 4 + name_len ;
2096 pSMB->TotalDataCount = 0;
2097 pSMB->MaxParameterCount = cpu_to_le16(2);
2098 pSMB->MaxDataCount = cpu_to_le16(4000);
2099 pSMB->MaxSetupCount = 0;
2100 pSMB->Reserved = 0;
2101 pSMB->Flags = 0;
2102 pSMB->Timeout = 0;
2103 pSMB->Reserved2 = 0;
2104 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2105 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2106 pSMB->DataCount = 0;
2107 pSMB->DataOffset = 0;
2108 pSMB->SetupCount = 1;
2109 pSMB->Reserved3 = 0;
2110 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2111 byte_count = params + 1 ;
2112 pSMB->TotalParameterCount = cpu_to_le16(params);
2113 pSMB->ParameterCount = pSMB->TotalParameterCount;
2114 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
2115 pSMB->Reserved4 = 0;
2116 pSMB->hdr.smb_buf_length += byte_count;
2117 pSMB->ByteCount = cpu_to_le16(byte_count);
2118
2119 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2120 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2121 if (rc) {
2122 cFYI(1, ("Send error in QPathInfo = %d", rc));
2123 } else {
2124 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2125
2126 if (rc || (pSMBr->ByteCount < 40))
2127 rc = -EIO;
2128 else if (pFindData){
2129 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2130 memcpy((char *) pFindData,
2131 (char *) &pSMBr->hdr.Protocol +
2132 data_offset, sizeof (FILE_ALL_INFO));
2133 } else
2134 rc = -ENOMEM;
2135 }
2136 if (pSMB)
2137 cifs_buf_release(pSMB);
2138 if (rc == -EAGAIN)
2139 goto QPathInfoRetry;
2140
2141 return rc;
2142}
2143
2144int
2145CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
2146 const unsigned char *searchName,
2147 FILE_UNIX_BASIC_INFO * pFindData,
2148 const struct nls_table *nls_codepage)
2149{
2150
2151 TRANSACTION2_QPI_REQ *pSMB = NULL;
2152 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2153 int rc = 0;
2154 int bytes_returned = 0;
2155 int name_len;
2156 __u16 params, byte_count;
2157
2158 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
2159UnixQPathInfoRetry:
2160 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2161 (void **) &pSMBr);
2162 if (rc)
2163 return rc;
2164
2165 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2166 name_len =
2167 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
2168
2169 , nls_codepage);
2170 name_len++;
2171 name_len *= 2;
2172 } else {
2173 name_len = strnlen(searchName, PATH_MAX);
2174 name_len++;
2175 strncpy(pSMB->FileName, searchName, name_len);
2176 }
2177
2178 params = 2 + 4 + name_len ;
2179 pSMB->TotalDataCount = 0;
2180 pSMB->MaxParameterCount = cpu_to_le16(2);
2181
2182 pSMB->MaxDataCount = cpu_to_le16(4000);
2183 pSMB->MaxSetupCount = 0;
2184 pSMB->Reserved = 0;
2185 pSMB->Flags = 0;
2186 pSMB->Timeout = 0;
2187 pSMB->Reserved2 = 0;
2188 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2189 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2190 pSMB->DataCount = 0;
2191 pSMB->DataOffset = 0;
2192 pSMB->SetupCount = 1;
2193 pSMB->Reserved3 = 0;
2194 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2195 byte_count = params + 1 ;
2196 pSMB->TotalParameterCount = cpu_to_le16(params);
2197 pSMB->ParameterCount = pSMB->TotalParameterCount;
2198 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
2199 pSMB->Reserved4 = 0;
2200 pSMB->hdr.smb_buf_length += byte_count;
2201 pSMB->ByteCount = cpu_to_le16(byte_count);
2202
2203 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2204 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2205 if (rc) {
2206 cFYI(1, ("Send error in QPathInfo = %d", rc));
2207 } else {
2208 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2209
2210 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
2211 rc = -EIO;
2212 } else {
2213 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2214 memcpy((char *) pFindData,
2215 (char *) &pSMBr->hdr.Protocol +
2216 data_offset,
2217 sizeof (FILE_UNIX_BASIC_INFO));
2218 }
2219 }
2220 if (pSMB)
2221 cifs_buf_release(pSMB);
2222 if (rc == -EAGAIN)
2223 goto UnixQPathInfoRetry;
2224
2225 return rc;
2226}
2227
2228#ifdef CONFIG_CIFS_EXPERIMENTAL
2229int
2230CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
2231 const char *searchName, FILE_ALL_INFO * findData,
2232 const struct nls_table *nls_codepage)
2233{
2234
2235 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2236 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2237 int rc = 0;
2238 int bytes_returned;
2239 int name_len;
2240 __u16 params, byte_count;
2241
2242 cFYI(1, ("In FindUnique"));
2243findUniqueRetry:
2244 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2245 (void **) &pSMBr);
2246 if (rc)
2247 return rc;
2248
2249 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2250 name_len =
2251 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
2252
2253 , nls_codepage);
2254 name_len++;
2255 name_len *= 2;
2256 } else {
2257 name_len = strnlen(searchName, PATH_MAX);
2258 name_len++;
2259 strncpy(pSMB->FileName, searchName, name_len);
2260 }
2261
2262 params = 12 + name_len ;
2263 pSMB->TotalDataCount = 0;
2264 pSMB->MaxParameterCount = cpu_to_le16(2);
2265 pSMB->MaxDataCount = cpu_to_le16(4000);
2266 pSMB->MaxSetupCount = 0;
2267 pSMB->Reserved = 0;
2268 pSMB->Flags = 0;
2269 pSMB->Timeout = 0;
2270 pSMB->Reserved2 = 0;
2271 pSMB->ParameterOffset = cpu_to_le16(
2272 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
2273 pSMB->DataCount = 0;
2274 pSMB->DataOffset = 0;
2275 pSMB->SetupCount = 1;
2276 pSMB->Reserved3 = 0;
2277 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2278 byte_count = params + 1 ;
2279 pSMB->TotalParameterCount = cpu_to_le16(params);
2280 pSMB->ParameterCount = pSMB->TotalParameterCount;
2281 pSMB->SearchAttributes =
2282 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2283 ATTR_DIRECTORY);
2284 pSMB->SearchCount = cpu_to_le16(16);
2285 pSMB->SearchFlags = cpu_to_le16(1);
2286 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2287 pSMB->SearchStorageType = 0;
2288 pSMB->hdr.smb_buf_length += byte_count;
2289 pSMB->ByteCount = cpu_to_le16(byte_count);
2290
2291 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2292 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2293
2294 if (rc) {
2295 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
2296 } else {
2297
2298
2299 }
2300 if (pSMB)
2301 cifs_buf_release(pSMB);
2302 if (rc == -EAGAIN)
2303 goto findUniqueRetry;
2304
2305 return rc;
2306}
2307#endif
2308
2309int
2310CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
2311 const char *searchName, FILE_DIRECTORY_INFO * findData,
2312 T2_FFIRST_RSP_PARMS * findParms,
2313 const struct nls_table *nls_codepage, int *pUnicodeFlag,
2314 int *pUnixFlag)
2315{
2316
2317 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2318 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2319 char *response_data;
2320 int rc = 0;
2321 int bytes_returned;
2322 int name_len;
2323 __u16 params, byte_count;
2324
2325 cFYI(1, ("In FindFirst"));
2326findFirstRetry:
2327 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2328 (void **) &pSMBr);
2329 if (rc)
2330 return rc;
2331
2332 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2333 name_len =
2334 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
2335
2336 , nls_codepage);
2337 name_len++;
2338 name_len *= 2;
2339 } else {
2340 name_len = strnlen(searchName, PATH_MAX);
2341 name_len++;
2342 strncpy(pSMB->FileName, searchName, name_len);
2343 }
2344
2345 params = 12 + name_len ;
2346 pSMB->TotalDataCount = 0;
2347 pSMB->MaxParameterCount = cpu_to_le16(10);
2348 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
2349 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2350 pSMB->MaxSetupCount = 0;
2351 pSMB->Reserved = 0;
2352 pSMB->Flags = 0;
2353 pSMB->Timeout = 0;
2354 pSMB->Reserved2 = 0;
2355 byte_count = params + 1 ;
2356 pSMB->TotalParameterCount = cpu_to_le16(params);
2357 pSMB->ParameterCount = pSMB->TotalParameterCount;
2358 pSMB->ParameterOffset = cpu_to_le16(
2359 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
2360 pSMB->DataCount = 0;
2361 pSMB->DataOffset = 0;
2362 pSMB->SetupCount = 1;
2363 pSMB->Reserved3 = 0;
2364 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2365 pSMB->SearchAttributes =
2366 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2367 ATTR_DIRECTORY);
2368 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_DIRECTORY_INFO));
2369 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
2370
2371
2372 if (tcon->ses->capabilities & CAP_UNIX) {
2373 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
2374 *pUnixFlag = TRUE;
2375 } else {
2376 pSMB->InformationLevel =
2377 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2378 *pUnixFlag = FALSE;
2379 }
2380 pSMB->SearchStorageType = 0;
2381 pSMB->hdr.smb_buf_length += byte_count;
2382 pSMB->ByteCount = cpu_to_le16(byte_count);
2383
2384 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2385 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2386
2387 if (rc) {
2388 cFYI(1, ("Error in FindFirst = %d", rc));
2389 } else {
2390 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2391 if(!rc) {
2392
2393
2394 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2395 *pUnicodeFlag = TRUE;
2396 else
2397 *pUnicodeFlag = FALSE;
2398 memcpy(findParms,
2399 (char *) &pSMBr->hdr.Protocol +
2400 le16_to_cpu(pSMBr->t2.ParameterOffset),
2401 sizeof (T2_FFIRST_RSP_PARMS));
2402 response_data =
2403 (char *) &pSMBr->hdr.Protocol +
2404 le16_to_cpu(pSMBr->t2.DataOffset);
2405 memcpy(findData, response_data,
2406 le16_to_cpu(pSMBr->t2.DataCount));
2407 }
2408 }
2409 if (pSMB)
2410 cifs_buf_release(pSMB);
2411
2412 if (rc == -EAGAIN)
2413 goto findFirstRetry;
2414
2415 return rc;
2416}
2417
2418
2419int
2420CIFSFindFirst2(const int xid, struct cifsTconInfo *tcon,
2421 const char *searchName,
2422 const struct nls_table *nls_codepage,
2423 __u16 * pnetfid,
2424 struct cifs_search_info * psrch_inf)
2425{
2426
2427 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2428 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2429 T2_FFIRST_RSP_PARMS * parms;
2430 int rc = 0;
2431 int bytes_returned = 0;
2432 int name_len;
2433 __u16 params, byte_count;
2434
2435 cFYI(1, ("In FindFirst2"));
2436
2437findFirst2Retry:
2438 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2439 (void **) &pSMBr);
2440 if (rc)
2441 return rc;
2442
2443 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2444 name_len =
2445 cifs_strtoUCS((wchar_t *) pSMB->FileName,searchName,
2446 PATH_MAX, nls_codepage);
2447 name_len++;
2448 name_len *= 2;
2449 pSMB->FileName[name_len] = 0;
2450 pSMB->FileName[name_len+1] = 0;
2451 } else {
2452 name_len = strnlen(searchName, PATH_MAX);
2453 name_len++;
2454
2455
2456
2457 strncpy(pSMB->FileName, searchName, name_len);
2458 pSMB->FileName[name_len] = 0;
2459 }
2460
2461 params = 12 + name_len ;
2462 pSMB->TotalDataCount = 0;
2463 pSMB->MaxParameterCount = cpu_to_le16(10);
2464 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
2465 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2466 pSMB->MaxSetupCount = 0;
2467 pSMB->Reserved = 0;
2468 pSMB->Flags = 0;
2469 pSMB->Timeout = 0;
2470 pSMB->Reserved2 = 0;
2471 byte_count = params + 1 ;
2472 pSMB->TotalParameterCount = cpu_to_le16(params);
2473 pSMB->ParameterCount = pSMB->TotalParameterCount;
2474 pSMB->ParameterOffset = cpu_to_le16(
2475 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
2476 pSMB->DataCount = 0;
2477 pSMB->DataOffset = 0;
2478 pSMB->SetupCount = 1;
2479 pSMB->Reserved3 = 0;
2480 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2481 pSMB->SearchAttributes =
2482 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2483 ATTR_DIRECTORY);
2484 pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
2485 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
2486 CIFS_SEARCH_RETURN_RESUME);
2487 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2488
2489
2490 pSMB->SearchStorageType = 0;
2491 pSMB->hdr.smb_buf_length += byte_count;
2492 pSMB->ByteCount = cpu_to_le16(byte_count);
2493
2494 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2495 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2496
2497 if (rc) {
2498
2499 cFYI(1, ("Error in FindFirst = %d", rc));
2500
2501 if (pSMB)
2502 cifs_buf_release(pSMB);
2503
2504
2505
2506 if (rc == -EAGAIN)
2507 goto findFirst2Retry;
2508 } else {
2509
2510 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2511 if(rc == 0) {
2512 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2513 psrch_inf->unicode = TRUE;
2514 else
2515 psrch_inf->unicode = FALSE;
2516
2517 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
2518 psrch_inf->srch_entries_start =
2519 (char *) &pSMBr->hdr.Protocol +
2520 le16_to_cpu(pSMBr->t2.DataOffset);
2521
2522 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
2523 le16_to_cpu(pSMBr->t2.ParameterOffset));
2524
2525 if(parms->EndofSearch)
2526 psrch_inf->endOfSearch = TRUE;
2527 else
2528 psrch_inf->endOfSearch = FALSE;
2529
2530 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2531 psrch_inf->index_of_last_entry =
2532 psrch_inf->entries_in_buffer;
2533
2534 *pnetfid = parms->SearchHandle;
2535 } else {
2536 if(pSMB)
2537 cifs_buf_release(pSMB);
2538 }
2539 }
2540
2541 return rc;
2542}
2543
2544int CIFSFindNext2(const int xid, struct cifsTconInfo *tcon,
2545 __u16 searchHandle, struct cifs_search_info * psrch_inf)
2546{
2547 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
2548 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
2549 T2_FNEXT_RSP_PARMS * parms;
2550 char *response_data;
2551 int rc = 0;
2552 int bytes_returned, name_len;
2553 __u16 params, byte_count;
2554
2555 cFYI(1, ("In FindNext2"));
2556
2557 if(psrch_inf->endOfSearch == TRUE)
2558 return -ENOENT;
2559
2560 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2561 (void **) &pSMBr);
2562 if (rc)
2563 return rc;
2564
2565 params = 14;
2566 byte_count = 0;
2567 pSMB->TotalDataCount = 0;
2568 pSMB->MaxParameterCount = cpu_to_le16(8);
2569 pSMB->MaxDataCount =
2570 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2571 pSMB->MaxSetupCount = 0;
2572 pSMB->Reserved = 0;
2573 pSMB->Flags = 0;
2574 pSMB->Timeout = 0;
2575 pSMB->Reserved2 = 0;
2576 pSMB->ParameterOffset = cpu_to_le16(
2577 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
2578 pSMB->DataCount = 0;
2579 pSMB->DataOffset = 0;
2580 pSMB->SetupCount = 1;
2581 pSMB->Reserved3 = 0;
2582 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
2583 pSMB->SearchHandle = searchHandle;
2584 pSMB->SearchCount =
2585 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2596 pSMB->ResumeKey = psrch_inf->resume_key;
2597 pSMB->SearchFlags =
2598 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
2599
2600 name_len = psrch_inf->resume_name_len;
2601 params += name_len;
2602 if(name_len < PATH_MAX) {
2603 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
2604 byte_count += name_len;
2605 } else {
2606 rc = -EINVAL;
2607 goto FNext2_err_exit;
2608 }
2609 byte_count = params + 1 ;
2610 pSMB->TotalParameterCount = cpu_to_le16(params);
2611 pSMB->ParameterCount = pSMB->TotalParameterCount;
2612 pSMB->hdr.smb_buf_length += byte_count;
2613 pSMB->ByteCount = cpu_to_le16(byte_count);
2614
2615 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2616 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2617
2618 if (rc) {
2619 if (rc == -EBADF) {
2620 psrch_inf->endOfSearch = TRUE;
2621 rc = 0;
2622 } else
2623 cFYI(1, ("FindNext returned = %d", rc));
2624 } else {
2625 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2626
2627 if(rc == 0) {
2628
2629 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2630 psrch_inf->unicode = TRUE;
2631 else
2632 psrch_inf->unicode = FALSE;
2633 response_data = (char *) &pSMBr->hdr.Protocol +
2634 le16_to_cpu(pSMBr->t2.ParameterOffset);
2635 parms = (T2_FNEXT_RSP_PARMS *)response_data;
2636 response_data = (char *)&pSMBr->hdr.Protocol +
2637 le16_to_cpu(pSMBr->t2.DataOffset);
2638 cifs_buf_release(psrch_inf->ntwrk_buf_start);
2639 psrch_inf->srch_entries_start = response_data;
2640 psrch_inf->ntwrk_buf_start = (char *)pSMB;
2641 if(parms->EndofSearch)
2642 psrch_inf->endOfSearch = TRUE;
2643 else
2644 psrch_inf->endOfSearch = FALSE;
2645
2646 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2647 psrch_inf->index_of_last_entry +=
2648 psrch_inf->entries_in_buffer;
2649
2650
2651
2652 }
2653
2654 }
2655
2656
2657
2658
2659
2660
2661FNext2_err_exit:
2662 if ((rc != 0) && pSMB)
2663 cifs_buf_release(pSMB);
2664
2665 return rc;
2666}
2667
2668int
2669CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
2670 FILE_DIRECTORY_INFO * findData, T2_FNEXT_RSP_PARMS * findParms,
2671 const __u16 searchHandle, char * resume_file_name, int name_len,
2672 __u32 resume_key, int *pUnicodeFlag, int *pUnixFlag)
2673{
2674
2675 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
2676 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
2677 char *response_data;
2678 int rc = 0;
2679 int bytes_returned;
2680 __u16 params, byte_count;
2681
2682 cFYI(1, ("In FindNext"));
2683
2684 if(resume_file_name == NULL) {
2685 return -EIO;
2686 }
2687 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2688 (void **) &pSMBr);
2689 if (rc)
2690 return rc;
2691
2692 params = 14;
2693 byte_count = 0;
2694 pSMB->TotalDataCount = 0;
2695 pSMB->MaxParameterCount = cpu_to_le16(8);
2696 pSMB->MaxDataCount =
2697 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2698 pSMB->MaxSetupCount = 0;
2699 pSMB->Reserved = 0;
2700 pSMB->Flags = 0;
2701 pSMB->Timeout = 0;
2702 pSMB->Reserved2 = 0;
2703 pSMB->ParameterOffset = cpu_to_le16(
2704 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
2705 pSMB->DataCount = 0;
2706 pSMB->DataOffset = 0;
2707 pSMB->SetupCount = 1;
2708 pSMB->Reserved3 = 0;
2709 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
2710 pSMB->SearchHandle = searchHandle;
2711 findParms->SearchCount = 0;
2712 pSMB->SearchCount =
2713 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
2714
2715 if (tcon->ses->capabilities & CAP_UNIX) {
2716 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
2717 *pUnixFlag = TRUE;
2718 } else {
2719 pSMB->InformationLevel =
2720 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2721 *pUnixFlag = FALSE;
2722 }
2723 pSMB->ResumeKey = resume_key;
2724 pSMB->SearchFlags =
2725 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
2726
2727 if(name_len < PATH_MAX) {
2728 memcpy(pSMB->ResumeFileName, resume_file_name, name_len);
2729 byte_count += name_len;
2730 }
2731 params += name_len;
2732 byte_count = params + 1 ;
2733 pSMB->TotalParameterCount = cpu_to_le16(params);
2734 pSMB->ParameterCount = pSMB->TotalParameterCount;
2735
2736 pSMB->hdr.smb_buf_length += byte_count;
2737 pSMB->ByteCount = cpu_to_le16(byte_count);
2738
2739 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2740 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2741
2742 if (rc) {
2743 if (rc == -EBADF)
2744 rc = 0;
2745 else
2746 cFYI(1, ("FindNext returned = %d", rc));
2747 } else {
2748 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2749
2750
2751 if(rc == 0) {
2752 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2753 *pUnicodeFlag = TRUE;
2754 else
2755 *pUnicodeFlag = FALSE;
2756 memcpy(findParms,
2757 (char *) &pSMBr->hdr.Protocol +
2758 le16_to_cpu(pSMBr->t2.ParameterOffset),
2759 sizeof (T2_FNEXT_RSP_PARMS));
2760 response_data =
2761 (char *) &pSMBr->hdr.Protocol +
2762 le16_to_cpu(pSMBr->t2.DataOffset);
2763 memcpy(findData,response_data,le16_to_cpu(pSMBr->t2.DataCount));
2764 }
2765 }
2766 if (pSMB)
2767 cifs_buf_release(pSMB);
2768
2769
2770
2771
2772 return rc;
2773}
2774
2775int
2776CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
2777{
2778 int rc = 0;
2779 FINDCLOSE_REQ *pSMB = NULL;
2780 CLOSE_RSP *pSMBr = NULL;
2781 int bytes_returned;
2782
2783 cFYI(1, ("In CIFSSMBFindClose"));
2784 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
2785 pSMBr = (CLOSE_RSP *)pSMB;
2786
2787
2788 if(rc == -EAGAIN)
2789 return 0;
2790 if (rc)
2791 return rc;
2792
2793 pSMB->FileID = searchHandle;
2794 pSMB->ByteCount = 0;
2795 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2796 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2797 if (rc) {
2798 cERROR(1, ("Send error in FindClose = %d", rc));
2799 }
2800 if (pSMB)
2801 cifs_small_buf_release(pSMB);
2802
2803
2804 if (rc == -EAGAIN)
2805 rc = 0;
2806
2807 return rc;
2808}
2809
2810#ifdef CONFIG_CIFS_EXPERIMENTAL
2811int
2812CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
2813 const unsigned char *searchName,
2814 __u64 * inode_number,
2815 const struct nls_table *nls_codepage)
2816{
2817 int rc = 0;
2818 TRANSACTION2_QPI_REQ *pSMB = NULL;
2819 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2820
2821 cFYI(1,("In GetSrvInodeNumber for %s",searchName));
2822 if(tcon == NULL)
2823 return -ENODEV;
2824
2825 cFYI(1, ("In QPathInfo path %s", searchName));
2826GetInodeNumberRetry:
2827 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2828 (void **) &pSMBr);
2829 if (rc)
2830 return rc;
2831
2832
2833
2834 if (pSMB)
2835 cifs_buf_release(pSMB);
2836
2837 if (rc == -EAGAIN)
2838 goto GetInodeNumberRetry;
2839 return rc;
2840}
2841#endif
2842
2843int
2844CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
2845 const unsigned char *searchName,
2846 unsigned char **targetUNCs,
2847 unsigned int *number_of_UNC_in_array,
2848 const struct nls_table *nls_codepage)
2849{
2850
2851 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
2852 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
2853 struct dfs_referral_level_3 * referrals = NULL;
2854 int rc = 0;
2855 int bytes_returned;
2856 int name_len;
2857 unsigned int i;
2858 char * temp;
2859 __u16 params, byte_count;
2860 *number_of_UNC_in_array = 0;
2861 *targetUNCs = NULL;
2862
2863 cFYI(1, ("In GetDFSRefer the path %s", searchName));
2864 if (ses == NULL)
2865 return -ENODEV;
2866getDFSRetry:
2867 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
2868 (void **) &pSMBr);
2869 if (rc)
2870 return rc;
2871
2872 pSMB->hdr.Tid = ses->ipc_tid;
2873 pSMB->hdr.Uid = ses->Suid;
2874 if (ses->capabilities & CAP_STATUS32) {
2875 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
2876 }
2877 if (ses->capabilities & CAP_DFS) {
2878 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
2879 }
2880
2881 if (ses->capabilities & CAP_UNICODE) {
2882 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
2883 name_len =
2884 cifs_strtoUCS((wchar_t *) pSMB->RequestFileName,
2885 searchName, PATH_MAX
2886
2887 , nls_codepage);
2888 name_len++;
2889 name_len *= 2;
2890 } else {
2891 name_len = strnlen(searchName, PATH_MAX);
2892 name_len++;
2893 strncpy(pSMB->RequestFileName, searchName, name_len);
2894 }
2895
2896 params = 2 + name_len ;
2897 pSMB->TotalDataCount = 0;
2898 pSMB->DataCount = 0;
2899 pSMB->DataOffset = 0;
2900 pSMB->MaxParameterCount = 0;
2901 pSMB->MaxDataCount = cpu_to_le16(4000);
2902 pSMB->MaxSetupCount = 0;
2903 pSMB->Reserved = 0;
2904 pSMB->Flags = 0;
2905 pSMB->Timeout = 0;
2906 pSMB->Reserved2 = 0;
2907 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2908 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
2909 pSMB->SetupCount = 1;
2910 pSMB->Reserved3 = 0;
2911 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
2912 byte_count = params + 3 ;
2913 pSMB->ParameterCount = cpu_to_le16(params);
2914 pSMB->TotalParameterCount = pSMB->ParameterCount;
2915 pSMB->MaxReferralLevel = cpu_to_le16(3);
2916 pSMB->hdr.smb_buf_length += byte_count;
2917 pSMB->ByteCount = cpu_to_le16(byte_count);
2918
2919 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
2920 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2921 if (rc) {
2922 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
2923 } else {
2924
2925 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2926
2927 if (rc || (pSMBr->ByteCount < 17))
2928 rc = -EIO;
2929 else {
2930 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2931 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
2932
2933 cFYI(1,
2934 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
2935 pSMBr->ByteCount, data_offset));
2936 referrals =
2937 (struct dfs_referral_level_3 *)
2938 (8 +
2939 data_offset +
2940 (char *) &pSMBr->hdr.Protocol);
2941 cFYI(1,("num_referrals: %d dfs flags: 0x%x ... \nfor referral one refer size: 0x%x srv type: 0x%x refer flags: 0x%x ttl: 0x%x",
2942 le16_to_cpu(pSMBr->NumberOfReferrals),le16_to_cpu(pSMBr->DFSFlags), le16_to_cpu(referrals->ReferralSize),le16_to_cpu(referrals->ServerType),le16_to_cpu(referrals->ReferralFlags),le16_to_cpu(referrals->TimeToLive)));
2943
2944
2945
2946 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
2947
2948
2949 if(*number_of_UNC_in_array > 1)
2950 *number_of_UNC_in_array = 1;
2951
2952
2953 name_len = 0;
2954 for(i=0;i<*number_of_UNC_in_array;i++) {
2955
2956 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
2957 if (offset > data_count) {
2958
2959
2960 *number_of_UNC_in_array = i;
2961 break;
2962 }
2963 temp = ((char *)referrals) + offset;
2964
2965 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2966 name_len += UniStrnlen((wchar_t *)temp,data_count);
2967 } else {
2968 name_len += strnlen(temp,data_count);
2969 }
2970 referrals++;
2971
2972
2973 }
2974
2975 *targetUNCs =
2976 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
2977 if(*targetUNCs == NULL) {
2978 rc = -ENOMEM;
2979 goto GetDFSRefExit;
2980 }
2981
2982 referrals =
2983 (struct dfs_referral_level_3 *)
2984 (8 +
2985 data_offset +
2986 (char *) &pSMBr->hdr.Protocol);
2987
2988 for(i=0;i<*number_of_UNC_in_array;i++) {
2989 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
2990 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2991 cifs_strfromUCS_le(*targetUNCs,
2992 (wchar_t *) temp, name_len, nls_codepage);
2993 } else {
2994 strncpy(*targetUNCs,temp,name_len);
2995 }
2996
2997 referrals++;
2998 }
2999 temp = *targetUNCs;
3000 temp[name_len] = 0;
3001 }
3002
3003 }
3004GetDFSRefExit:
3005 if (pSMB)
3006 cifs_buf_release(pSMB);
3007
3008 if (rc == -EAGAIN)
3009 goto getDFSRetry;
3010
3011 return rc;
3012}
3013
3014int
3015CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
3016 struct kstatfs *FSData, const struct nls_table *nls_codepage)
3017{
3018
3019 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3020 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3021 FILE_SYSTEM_INFO *response_data;
3022 int rc = 0;
3023 int bytes_returned = 0;
3024 __u16 params, byte_count;
3025
3026 cFYI(1, ("In QFSInfo"));
3027QFSInfoRetry:
3028 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3029 (void **) &pSMBr);
3030 if (rc)
3031 return rc;
3032
3033 params = 2;
3034 pSMB->TotalDataCount = 0;
3035 pSMB->MaxParameterCount = cpu_to_le16(2);
3036 pSMB->MaxDataCount = cpu_to_le16(1000);
3037 pSMB->MaxSetupCount = 0;
3038 pSMB->Reserved = 0;
3039 pSMB->Flags = 0;
3040 pSMB->Timeout = 0;
3041 pSMB->Reserved2 = 0;
3042 byte_count = params + 1 ;
3043 pSMB->TotalParameterCount = cpu_to_le16(params);
3044 pSMB->ParameterCount = pSMB->TotalParameterCount;
3045 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3046 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3047 pSMB->DataCount = 0;
3048 pSMB->DataOffset = 0;
3049 pSMB->SetupCount = 1;
3050 pSMB->Reserved3 = 0;
3051 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3052 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
3053 pSMB->hdr.smb_buf_length += byte_count;
3054 pSMB->ByteCount = cpu_to_le16(byte_count);
3055
3056 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3057 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3058 if (rc) {
3059 cERROR(1, ("Send error in QFSInfo = %d", rc));
3060 } else {
3061 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3062
3063 if (rc || (pSMBr->ByteCount < 24))
3064 rc = -EIO;
3065 else {
3066 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3067 cFYI(1,
3068 ("Decoding qfsinfo response. BCC: %d Offset %d",
3069 pSMBr->ByteCount, data_offset));
3070
3071 response_data =
3072 (FILE_SYSTEM_INFO
3073 *) (((char *) &pSMBr->hdr.Protocol) +
3074 data_offset);
3075 FSData->f_bsize =
3076 le32_to_cpu(response_data->BytesPerSector) *
3077 le32_to_cpu(response_data->
3078 SectorsPerAllocationUnit);
3079 FSData->f_blocks =
3080 le64_to_cpu(response_data->TotalAllocationUnits);
3081 FSData->f_bfree = FSData->f_bavail =
3082 le64_to_cpu(response_data->FreeAllocationUnits);
3083 cFYI(1,
3084 ("Blocks: %lld Free: %lld Block size %ld",
3085 (unsigned long long)FSData->f_blocks,
3086 (unsigned long long)FSData->f_bfree,
3087 FSData->f_bsize));
3088 }
3089 }
3090 if (pSMB)
3091 cifs_buf_release(pSMB);
3092
3093 if (rc == -EAGAIN)
3094 goto QFSInfoRetry;
3095
3096 return rc;
3097}
3098
3099int
3100CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon,
3101 const struct nls_table *nls_codepage)
3102{
3103
3104 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3105 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3106 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
3107 int rc = 0;
3108 int bytes_returned = 0;
3109 __u16 params, byte_count;
3110
3111 cFYI(1, ("In QFSAttributeInfo"));
3112QFSAttributeRetry:
3113 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3114 (void **) &pSMBr);
3115 if (rc)
3116 return rc;
3117
3118 params = 2;
3119 pSMB->TotalDataCount = 0;
3120 pSMB->MaxParameterCount = cpu_to_le16(2);
3121 pSMB->MaxDataCount = cpu_to_le16(1000);
3122 pSMB->MaxSetupCount = 0;
3123 pSMB->Reserved = 0;
3124 pSMB->Flags = 0;
3125 pSMB->Timeout = 0;
3126 pSMB->Reserved2 = 0;
3127 byte_count = params + 1 ;
3128 pSMB->TotalParameterCount = cpu_to_le16(params);
3129 pSMB->ParameterCount = pSMB->TotalParameterCount;
3130 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3131 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3132 pSMB->DataCount = 0;
3133 pSMB->DataOffset = 0;
3134 pSMB->SetupCount = 1;
3135 pSMB->Reserved3 = 0;
3136 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3137 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
3138 pSMB->hdr.smb_buf_length += byte_count;
3139 pSMB->ByteCount = cpu_to_le16(byte_count);
3140
3141 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3142 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3143 if (rc) {
3144 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
3145 } else {
3146 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3147
3148 if (rc || (pSMBr->ByteCount < 13)) {
3149 rc = -EIO;
3150 } else {
3151 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3152 response_data =
3153 (FILE_SYSTEM_ATTRIBUTE_INFO
3154 *) (((char *) &pSMBr->hdr.Protocol) +
3155 data_offset);
3156 memcpy(&tcon->fsAttrInfo, response_data,
3157 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
3158 }
3159 }
3160 if (pSMB)
3161 cifs_buf_release(pSMB);
3162
3163 if (rc == -EAGAIN)
3164 goto QFSAttributeRetry;
3165
3166 return rc;
3167}
3168
3169int
3170CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon,
3171 const struct nls_table *nls_codepage)
3172{
3173
3174 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3175 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3176 FILE_SYSTEM_DEVICE_INFO *response_data;
3177 int rc = 0;
3178 int bytes_returned = 0;
3179 __u16 params, byte_count;
3180
3181 cFYI(1, ("In QFSDeviceInfo"));
3182QFSDeviceRetry:
3183 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3184 (void **) &pSMBr);
3185 if (rc)
3186 return rc;
3187
3188 params = 2;
3189 pSMB->TotalDataCount = 0;
3190 pSMB->MaxParameterCount = cpu_to_le16(2);
3191 pSMB->MaxDataCount = cpu_to_le16(1000);
3192 pSMB->MaxSetupCount = 0;
3193 pSMB->Reserved = 0;
3194 pSMB->Flags = 0;
3195 pSMB->Timeout = 0;
3196 pSMB->Reserved2 = 0;
3197 byte_count = params + 1 ;
3198 pSMB->TotalParameterCount = cpu_to_le16(params);
3199 pSMB->ParameterCount = pSMB->TotalParameterCount;
3200 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3201 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3202
3203 pSMB->DataCount = 0;
3204 pSMB->DataOffset = 0;
3205 pSMB->SetupCount = 1;
3206 pSMB->Reserved3 = 0;
3207 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3208 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
3209 pSMB->hdr.smb_buf_length += byte_count;
3210 pSMB->ByteCount = cpu_to_le16(byte_count);
3211
3212 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3213 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3214 if (rc) {
3215 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
3216 } else {
3217 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3218
3219 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
3220 rc = -EIO;
3221 else {
3222 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3223 response_data =
3224 (FILE_SYSTEM_DEVICE_INFO
3225 *) (((char *) &pSMBr->hdr.Protocol) +
3226 data_offset);
3227 memcpy(&tcon->fsDevInfo, response_data,
3228 sizeof (FILE_SYSTEM_DEVICE_INFO));
3229 }
3230 }
3231 if (pSMB)
3232 cifs_buf_release(pSMB);
3233
3234 if (rc == -EAGAIN)
3235 goto QFSDeviceRetry;
3236
3237 return rc;
3238}
3239
3240int
3241CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
3242 const struct nls_table *nls_codepage)
3243{
3244
3245 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3246 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3247 FILE_SYSTEM_UNIX_INFO *response_data;
3248 int rc = 0;
3249 int bytes_returned = 0;
3250 __u16 params, byte_count;
3251
3252 cFYI(1, ("In QFSUnixInfo"));
3253QFSUnixRetry:
3254 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3255 (void **) &pSMBr);
3256 if (rc)
3257 return rc;
3258
3259 params = 2;
3260 pSMB->TotalDataCount = 0;
3261 pSMB->DataCount = 0;
3262 pSMB->DataOffset = 0;
3263 pSMB->MaxParameterCount = cpu_to_le16(2);
3264 pSMB->MaxDataCount = cpu_to_le16(100);
3265 pSMB->MaxSetupCount = 0;
3266 pSMB->Reserved = 0;
3267 pSMB->Flags = 0;
3268 pSMB->Timeout = 0;
3269 pSMB->Reserved2 = 0;
3270 byte_count = params + 1 ;
3271 pSMB->ParameterCount = cpu_to_le16(params);
3272 pSMB->TotalParameterCount = pSMB->ParameterCount;
3273 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3274 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3275 pSMB->SetupCount = 1;
3276 pSMB->Reserved3 = 0;
3277 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3278 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
3279 pSMB->hdr.smb_buf_length += byte_count;
3280 pSMB->ByteCount = cpu_to_le16(byte_count);
3281
3282 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3283 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3284 if (rc) {
3285 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
3286 } else {
3287 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3288
3289 if (rc || (pSMBr->ByteCount < 13)) {
3290 rc = -EIO;
3291 } else {
3292 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3293 response_data =
3294 (FILE_SYSTEM_UNIX_INFO
3295 *) (((char *) &pSMBr->hdr.Protocol) +
3296 data_offset);
3297 memcpy(&tcon->fsUnixInfo, response_data,
3298 sizeof (FILE_SYSTEM_UNIX_INFO));
3299 }
3300 }
3301 if (pSMB)
3302 cifs_buf_release(pSMB);
3303
3304 if (rc == -EAGAIN)
3305 goto QFSUnixRetry;
3306
3307
3308 return rc;
3309}
3310
3311
3312
3313
3314
3315
3316
3317int
3318CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3319 __u64 size, int SetAllocation, const struct nls_table *nls_codepage)
3320{
3321 struct smb_com_transaction2_spi_req *pSMB = NULL;
3322 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3323 struct file_end_of_file_info *parm_data;
3324 int name_len;
3325 int rc = 0;
3326 int bytes_returned = 0;
3327 __u16 params, byte_count, data_count, param_offset, offset;
3328
3329 cFYI(1, ("In SetEOF"));
3330SetEOFRetry:
3331 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3332 (void **) &pSMBr);
3333 if (rc)
3334 return rc;
3335
3336 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3337 name_len =
3338 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
3339
3340 , nls_codepage);
3341 name_len++;
3342 name_len *= 2;
3343 } else {
3344 name_len = strnlen(fileName, PATH_MAX);
3345 name_len++;
3346 strncpy(pSMB->FileName, fileName, name_len);
3347 }
3348 params = 6 + name_len;
3349 data_count = sizeof (struct file_end_of_file_info);
3350 pSMB->MaxParameterCount = cpu_to_le16(2);
3351 pSMB->MaxDataCount = cpu_to_le16(1000);
3352 pSMB->MaxSetupCount = 0;
3353 pSMB->Reserved = 0;
3354 pSMB->Flags = 0;
3355 pSMB->Timeout = 0;
3356 pSMB->Reserved2 = 0;
3357 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3358 InformationLevel) - 4;
3359 offset = param_offset + params;
3360 if(SetAllocation) {
3361 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3362 pSMB->InformationLevel =
3363 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3364 else
3365 pSMB->InformationLevel =
3366 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3367 } else {
3368 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3369 pSMB->InformationLevel =
3370 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3371 else
3372 pSMB->InformationLevel =
3373 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3374 }
3375
3376 parm_data =
3377 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3378 offset);
3379 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3380 pSMB->DataOffset = cpu_to_le16(offset);
3381 pSMB->SetupCount = 1;
3382 pSMB->Reserved3 = 0;
3383 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3384 byte_count = 3 + params + data_count;
3385 pSMB->DataCount = cpu_to_le16(data_count);
3386 pSMB->TotalDataCount = pSMB->DataCount;
3387 pSMB->ParameterCount = cpu_to_le16(params);
3388 pSMB->TotalParameterCount = pSMB->ParameterCount;
3389 pSMB->Reserved4 = 0;
3390 pSMB->hdr.smb_buf_length += byte_count;
3391 parm_data->FileSize = cpu_to_le64(size);
3392 pSMB->ByteCount = cpu_to_le16(byte_count);
3393 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3394 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3395 if (rc) {
3396 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
3397 }
3398
3399 if (pSMB)
3400 cifs_buf_release(pSMB);
3401
3402 if (rc == -EAGAIN)
3403 goto SetEOFRetry;
3404
3405 return rc;
3406}
3407
3408int
3409CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
3410 __u16 fid, __u32 pid_of_opener, int SetAllocation)
3411{
3412 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3413 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3414 char *data_offset;
3415 struct file_end_of_file_info *parm_data;
3416 int rc = 0;
3417 int bytes_returned = 0;
3418 __u16 params, param_offset, offset, byte_count, count;
3419
3420 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
3421 (long long)size));
3422 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3423 (void **) &pSMBr);
3424 if (rc)
3425 return rc;
3426
3427 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3428 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
3429
3430 params = 6;
3431 pSMB->MaxSetupCount = 0;
3432 pSMB->Reserved = 0;
3433 pSMB->Flags = 0;
3434 pSMB->Timeout = 0;
3435 pSMB->Reserved2 = 0;
3436 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3437 offset = param_offset + params;
3438
3439 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3440
3441 count = sizeof(struct file_end_of_file_info);
3442 pSMB->MaxParameterCount = cpu_to_le16(2);
3443 pSMB->MaxDataCount = cpu_to_le16(1000);
3444 pSMB->SetupCount = 1;
3445 pSMB->Reserved3 = 0;
3446 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3447 byte_count = 3 + params + count;
3448 pSMB->DataCount = cpu_to_le16(count);
3449 pSMB->ParameterCount = cpu_to_le16(params);
3450 pSMB->TotalDataCount = pSMB->DataCount;
3451 pSMB->TotalParameterCount = pSMB->ParameterCount;
3452 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3453 parm_data =
3454 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3455 offset);
3456 pSMB->DataOffset = cpu_to_le16(offset);
3457 parm_data->FileSize = cpu_to_le64(size);
3458 pSMB->Fid = fid;
3459 if(SetAllocation) {
3460 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3461 pSMB->InformationLevel =
3462 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3463 else
3464 pSMB->InformationLevel =
3465 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3466 } else {
3467 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3468 pSMB->InformationLevel =
3469 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3470 else
3471 pSMB->InformationLevel =
3472 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3473 }
3474 pSMB->Reserved4 = 0;
3475 pSMB->hdr.smb_buf_length += byte_count;
3476 pSMB->ByteCount = cpu_to_le16(byte_count);
3477 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3478 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3479 if (rc) {
3480 cFYI(1,
3481 ("Send error in SetFileInfo (SetFileSize) = %d",
3482 rc));
3483 }
3484
3485 if (pSMB)
3486 cifs_buf_release(pSMB);
3487
3488
3489
3490
3491 return rc;
3492}
3493
3494int
3495CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3496 const FILE_BASIC_INFO * data,
3497 const struct nls_table *nls_codepage)
3498{
3499 TRANSACTION2_SPI_REQ *pSMB = NULL;
3500 TRANSACTION2_SPI_RSP *pSMBr = NULL;
3501 int name_len;
3502 int rc = 0;
3503 int bytes_returned = 0;
3504 char *data_offset;
3505 __u16 params, param_offset, offset, byte_count, count;
3506
3507 cFYI(1, ("In SetTimes"));
3508
3509SetTimesRetry:
3510 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3511 (void **) &pSMBr);
3512 if (rc)
3513 return rc;
3514
3515 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3516 name_len =
3517 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
3518
3519 , nls_codepage);
3520 name_len++;
3521 name_len *= 2;
3522 } else {
3523 name_len = strnlen(fileName, PATH_MAX);
3524 name_len++;
3525 strncpy(pSMB->FileName, fileName, name_len);
3526 }
3527
3528 params = 6 + name_len;
3529 count = sizeof (FILE_BASIC_INFO);
3530 pSMB->MaxParameterCount = cpu_to_le16(2);
3531 pSMB->MaxDataCount = cpu_to_le16(1000);
3532 pSMB->MaxSetupCount = 0;
3533 pSMB->Reserved = 0;
3534 pSMB->Flags = 0;
3535 pSMB->Timeout = 0;
3536 pSMB->Reserved2 = 0;
3537 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3538 InformationLevel) - 4;
3539 offset = param_offset + params;
3540 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3541 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3542 pSMB->DataOffset = cpu_to_le16(offset);
3543 pSMB->SetupCount = 1;
3544 pSMB->Reserved3 = 0;
3545 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3546 byte_count = 3 + params + count;
3547
3548 pSMB->DataCount = cpu_to_le16(count);
3549 pSMB->ParameterCount = cpu_to_le16(params);
3550 pSMB->TotalDataCount = pSMB->DataCount;
3551 pSMB->TotalParameterCount = pSMB->ParameterCount;
3552 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3553 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
3554 else
3555 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
3556 pSMB->Reserved4 = 0;
3557 pSMB->hdr.smb_buf_length += byte_count;
3558 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
3559 pSMB->ByteCount = cpu_to_le16(byte_count);
3560 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3561 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3562 if (rc) {
3563 cFYI(1, ("SetPathInfo (times) returned %d", rc));
3564 }
3565
3566 if (pSMB)
3567 cifs_buf_release(pSMB);
3568
3569 if (rc == -EAGAIN)
3570 goto SetTimesRetry;
3571
3572 return rc;
3573}
3574
3575int
3576CIFSSMBSetTimesLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
3577 FILE_INFO_STANDARD * data, const struct nls_table *nls_codepage)
3578{
3579 TRANSACTION2_SPI_REQ *pSMB = NULL;
3580 TRANSACTION2_SPI_RSP *pSMBr = NULL;
3581 int name_len;
3582 int rc = 0;
3583 int bytes_returned = 0;
3584 char *data_offset;
3585 __u16 params, param_offset, count, offset, byte_count;
3586
3587 cFYI(1, ("In SetTimesLegacy"));
3588
3589SetTimesRetryLegacy:
3590 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3591 (void **) &pSMBr);
3592 if (rc)
3593 return rc;
3594
3595 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3596 name_len =
3597 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
3598
3599 , nls_codepage);
3600 name_len++;
3601 name_len *= 2;
3602 } else {
3603 name_len = strnlen(fileName, PATH_MAX);
3604 name_len++;
3605 strncpy(pSMB->FileName, fileName, name_len);
3606 }
3607
3608
3609 params = 6 + name_len;
3610 count = sizeof (FILE_INFO_STANDARD);
3611 pSMB->MaxParameterCount = cpu_to_le16(2);
3612 pSMB->MaxDataCount = cpu_to_le16(1000);
3613 pSMB->MaxSetupCount = 0;
3614 pSMB->Reserved = 0;
3615 pSMB->Flags = 0;
3616 pSMB->Timeout = 0;
3617 pSMB->Reserved2 = 0;
3618 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3619 InformationLevel) - 4;
3620 offset = param_offset + params;
3621 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3622 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3623 pSMB->DataOffset = cpu_to_le16(offset);
3624 pSMB->SetupCount = 1;
3625 pSMB->Reserved3 = 0;
3626 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3627 byte_count = 3 + params + count;
3628
3629 pSMB->DataCount = cpu_to_le16(count);
3630 pSMB->ParameterCount = cpu_to_le16(params);
3631 pSMB->TotalDataCount = pSMB->DataCount;
3632 pSMB->TotalParameterCount = pSMB->ParameterCount;
3633 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3634 pSMB->Reserved4 = 0;
3635 pSMB->hdr.smb_buf_length += byte_count;
3636 memcpy(data_offset, data, sizeof (FILE_INFO_STANDARD));
3637 pSMB->ByteCount = cpu_to_le16(byte_count);
3638 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3639 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3640 if (rc) {
3641 cFYI(1, ("SetPathInfo (times legacy) returned %d", rc));
3642 }
3643
3644 if (pSMB)
3645 cifs_buf_release(pSMB);
3646
3647 if (rc == -EAGAIN)
3648 goto SetTimesRetryLegacy;
3649
3650 return rc;
3651}
3652
3653int
3654CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
3655 char *fileName, __u64 mode, __u64 uid, __u64 gid,
3656 dev_t device, const struct nls_table *nls_codepage)
3657{
3658 TRANSACTION2_SPI_REQ *pSMB = NULL;
3659 TRANSACTION2_SPI_RSP *pSMBr = NULL;
3660 int name_len;
3661 int rc = 0;
3662 int bytes_returned = 0;
3663 FILE_UNIX_BASIC_INFO *data_offset;
3664 __u16 params, param_offset, offset, count, byte_count;
3665
3666 cFYI(1, ("In SetUID/GID/Mode"));
3667setPermsRetry:
3668 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3669 (void **) &pSMBr);
3670 if (rc)
3671 return rc;
3672
3673 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3674 name_len =
3675 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
3676
3677 , nls_codepage);
3678 name_len++;
3679 name_len *= 2;
3680 } else {
3681 name_len = strnlen(fileName, PATH_MAX);
3682 name_len++;
3683 strncpy(pSMB->FileName, fileName, name_len);
3684 }
3685
3686 params = 6 + name_len;
3687 count = sizeof (FILE_UNIX_BASIC_INFO);
3688 pSMB->MaxParameterCount = cpu_to_le16(2);
3689 pSMB->MaxDataCount = cpu_to_le16(1000);
3690 pSMB->MaxSetupCount = 0;
3691 pSMB->Reserved = 0;
3692 pSMB->Flags = 0;
3693 pSMB->Timeout = 0;
3694 pSMB->Reserved2 = 0;
3695 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3696 InformationLevel) - 4;
3697 offset = param_offset + params;
3698 data_offset =
3699 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
3700 offset);
3701 memset(data_offset, 0, count);
3702 pSMB->DataOffset = cpu_to_le16(offset);
3703 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3704 pSMB->SetupCount = 1;
3705 pSMB->Reserved3 = 0;
3706 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3707 byte_count = 3 + params + count;
3708 pSMB->ParameterCount = cpu_to_le16(params);
3709 pSMB->DataCount = cpu_to_le16(count);
3710 pSMB->TotalParameterCount = pSMB->ParameterCount;
3711 pSMB->TotalDataCount = pSMB->DataCount;
3712 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
3713 pSMB->Reserved4 = 0;
3714 pSMB->hdr.smb_buf_length += byte_count;
3715 data_offset->Uid = cpu_to_le64(uid);
3716 data_offset->Gid = cpu_to_le64(gid);
3717
3718 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
3719 data_offset->DevMinor = cpu_to_le64(MINOR(device));
3720 data_offset->Permissions = cpu_to_le64(mode);
3721
3722 if(S_ISREG(mode))
3723 data_offset->Type = cpu_to_le32(UNIX_FILE);
3724 else if(S_ISDIR(mode))
3725 data_offset->Type = cpu_to_le32(UNIX_DIR);
3726 else if(S_ISLNK(mode))
3727 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
3728 else if(S_ISCHR(mode))
3729 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
3730 else if(S_ISBLK(mode))
3731 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
3732 else if(S_ISFIFO(mode))
3733 data_offset->Type = cpu_to_le32(UNIX_FIFO);
3734 else if(S_ISSOCK(mode))
3735 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
3736
3737
3738 pSMB->ByteCount = cpu_to_le16(byte_count);
3739 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3740 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3741 if (rc) {
3742 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
3743 }
3744
3745 if (pSMB)
3746 cifs_buf_release(pSMB);
3747 if (rc == -EAGAIN)
3748 goto setPermsRetry;
3749 return rc;
3750}
3751
3752int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
3753 const int notify_subdirs, const __u16 netfid,
3754 __u32 filter, const struct nls_table *nls_codepage)
3755{
3756 int rc = 0;
3757 struct smb_com_transaction_change_notify_req * pSMB = NULL;
3758 struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
3759 int bytes_returned;
3760
3761 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
3762 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3763 (void **) &pSMBr);
3764 if (rc)
3765 return rc;
3766
3767 pSMB->TotalParameterCount = 0 ;
3768 pSMB->TotalDataCount = 0;
3769 pSMB->MaxParameterCount = cpu_to_le32(2);
3770
3771 pSMB->MaxDataCount = 0;
3772 pSMB->MaxSetupCount = 4;
3773 pSMB->Reserved = 0;
3774 pSMB->ParameterOffset = 0;
3775 pSMB->DataCount = 0;
3776 pSMB->DataOffset = 0;
3777 pSMB->SetupCount = 4;
3778 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
3779 pSMB->ParameterCount = pSMB->TotalParameterCount;
3780 if(notify_subdirs)
3781 pSMB->WatchTree = 1;
3782 pSMB->Reserved2 = 0;
3783 pSMB->CompletionFilter = cpu_to_le32(filter);
3784 pSMB->Fid = netfid;
3785 pSMB->ByteCount = 0;
3786
3787 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3788 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
3789 if (rc) {
3790 cFYI(1, ("Error in Notify = %d", rc));
3791 }
3792 if (pSMB)
3793 cifs_buf_release(pSMB);
3794
3795
3796 return rc;
3797}
3798#ifdef CONFIG_CIFS_XATTR
3799ssize_t
3800CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
3801 const unsigned char *searchName,
3802 char * EAData, size_t buf_size,
3803 const struct nls_table *nls_codepage)
3804{
3805
3806 TRANSACTION2_QPI_REQ *pSMB = NULL;
3807 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3808 int rc = 0;
3809 int bytes_returned;
3810 int name_len;
3811 struct fea * temp_fea;
3812 char * temp_ptr;
3813 __u16 params, byte_count;
3814
3815 cFYI(1, ("In Query All EAs path %s", searchName));
3816QAllEAsRetry:
3817 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3818 (void **) &pSMBr);
3819 if (rc)
3820 return rc;
3821
3822 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3823 name_len =
3824 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
3825
3826 , nls_codepage);
3827 name_len++;
3828 name_len *= 2;
3829 } else {
3830 name_len = strnlen(searchName, PATH_MAX);
3831 name_len++;
3832 strncpy(pSMB->FileName, searchName, name_len);
3833 }
3834
3835 params = 2 + 4 + name_len ;
3836 pSMB->TotalDataCount = 0;
3837 pSMB->MaxParameterCount = cpu_to_le16(2);
3838 pSMB->MaxDataCount = cpu_to_le16(4000);
3839 pSMB->MaxSetupCount = 0;
3840 pSMB->Reserved = 0;
3841 pSMB->Flags = 0;
3842 pSMB->Timeout = 0;
3843 pSMB->Reserved2 = 0;
3844 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3845 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3846 pSMB->DataCount = 0;
3847 pSMB->DataOffset = 0;
3848 pSMB->SetupCount = 1;
3849 pSMB->Reserved3 = 0;
3850 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3851 byte_count = params + 1 ;
3852 pSMB->TotalParameterCount = cpu_to_le16(params);
3853 pSMB->ParameterCount = pSMB->TotalParameterCount;
3854 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
3855 pSMB->Reserved4 = 0;
3856 pSMB->hdr.smb_buf_length += byte_count;
3857 pSMB->ByteCount = cpu_to_le16(byte_count);
3858
3859 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3860 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3861 if (rc) {
3862 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
3863 } else {
3864 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3865
3866
3867
3868
3869 if (rc || (pSMBr->ByteCount < 4))
3870 rc = -EIO;
3871
3872
3873
3874
3875 else {
3876
3877
3878
3879
3880
3881 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3882 struct fealist * ea_response_data;
3883 rc = 0;
3884
3885
3886 ea_response_data = (struct fealist *)
3887 (((char *) &pSMBr->hdr.Protocol) +
3888 data_offset);
3889 name_len = le32_to_cpu(ea_response_data->list_len);
3890 cFYI(1,("ea length %d", name_len));
3891 if(name_len <= 8) {
3892
3893 cFYI(1,("empty EA list returned from server"));
3894 } else {
3895
3896 name_len -= 4;
3897 temp_fea = ea_response_data->list;
3898 temp_ptr = (char *)temp_fea;
3899 while(name_len > 0) {
3900 __u16 value_len;
3901 name_len -= 4;
3902 temp_ptr += 4;
3903 rc += temp_fea->name_len;
3904
3905 rc = rc + 5 + 1;
3906 if(rc<(int)buf_size) {
3907 memcpy(EAData,"user.",5);
3908 EAData+=5;
3909 memcpy(EAData,temp_ptr,temp_fea->name_len);
3910 EAData+=temp_fea->name_len;
3911
3912 *EAData = 0;
3913 EAData = EAData + 1;
3914 } else if(buf_size == 0) {
3915
3916 } else {
3917
3918 rc = -ERANGE;
3919 break;
3920 }
3921 name_len -= temp_fea->name_len;
3922 temp_ptr += temp_fea->name_len;
3923
3924 name_len--;
3925 temp_ptr++;
3926 value_len = le16_to_cpu(temp_fea->value_len);
3927 name_len -= value_len;
3928 temp_ptr += value_len;
3929
3930
3931
3932 temp_fea = (struct fea *)temp_ptr;
3933 }
3934 }
3935 }
3936 }
3937 if (pSMB)
3938 cifs_buf_release(pSMB);
3939 if (rc == -EAGAIN)
3940 goto QAllEAsRetry;
3941
3942 return (ssize_t)rc;
3943}
3944
3945ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
3946 const unsigned char * searchName,const unsigned char * ea_name,
3947 unsigned char * ea_value, size_t buf_size,
3948 const struct nls_table *nls_codepage)
3949{
3950 TRANSACTION2_QPI_REQ *pSMB = NULL;
3951 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3952 int rc = 0;
3953 int bytes_returned;
3954 int name_len;
3955 struct fea * temp_fea;
3956 char * temp_ptr;
3957 __u16 params, byte_count;
3958
3959 cFYI(1, ("In Query EA path %s", searchName));
3960QEARetry:
3961 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3962 (void **) &pSMBr);
3963 if (rc)
3964 return rc;
3965
3966 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3967 name_len =
3968 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
3969
3970 , nls_codepage);
3971 name_len++;
3972 name_len *= 2;
3973 } else {
3974 name_len = strnlen(searchName, PATH_MAX);
3975 name_len++;
3976 strncpy(pSMB->FileName, searchName, name_len);
3977 }
3978
3979 params = 2 + 4 + name_len ;
3980 pSMB->TotalDataCount = 0;
3981 pSMB->MaxParameterCount = cpu_to_le16(2);
3982 pSMB->MaxDataCount = cpu_to_le16(4000);
3983 pSMB->MaxSetupCount = 0;
3984 pSMB->Reserved = 0;
3985 pSMB->Flags = 0;
3986 pSMB->Timeout = 0;
3987 pSMB->Reserved2 = 0;
3988 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3989 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3990 pSMB->DataCount = 0;
3991 pSMB->DataOffset = 0;
3992 pSMB->SetupCount = 1;
3993 pSMB->Reserved3 = 0;
3994 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3995 byte_count = params + 1 ;
3996 pSMB->TotalParameterCount = cpu_to_le16(params);
3997 pSMB->ParameterCount = pSMB->TotalParameterCount;
3998 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
3999 pSMB->Reserved4 = 0;
4000 pSMB->hdr.smb_buf_length += byte_count;
4001 pSMB->ByteCount = cpu_to_le16(byte_count);
4002
4003 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4004 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4005 if (rc) {
4006 cFYI(1, ("Send error in Query EA = %d", rc));
4007 } else {
4008 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4009
4010
4011
4012
4013 if (rc || (pSMBr->ByteCount < 4))
4014 rc = -EIO;
4015
4016
4017
4018
4019 else {
4020
4021
4022
4023
4024
4025 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4026 struct fealist * ea_response_data;
4027 rc = -ENODATA;
4028
4029
4030 ea_response_data = (struct fealist *)
4031 (((char *) &pSMBr->hdr.Protocol) +
4032 data_offset);
4033 name_len = le32_to_cpu(ea_response_data->list_len);
4034 cFYI(1,("ea length %d", name_len));
4035 if(name_len <= 8) {
4036
4037 cFYI(1,("empty EA list returned from server"));
4038 } else {
4039
4040 name_len -= 4;
4041 temp_fea = ea_response_data->list;
4042 temp_ptr = (char *)temp_fea;
4043
4044
4045 while(name_len > 0) {
4046 __u16 value_len;
4047 name_len -= 4;
4048 temp_ptr += 4;
4049 value_len = le16_to_cpu(temp_fea->value_len);
4050
4051
4052 if(memcmp(temp_fea->name,ea_name,
4053 temp_fea->name_len) == 0) {
4054
4055 rc = value_len;
4056
4057 if(rc<=(int)buf_size) {
4058 memcpy(ea_value,
4059 temp_fea->name+temp_fea->name_len+1,
4060 rc);
4061
4062
4063 } else if(buf_size == 0) {
4064
4065 } else {
4066
4067 rc = -ERANGE;
4068 }
4069 break;
4070 }
4071 name_len -= temp_fea->name_len;
4072 temp_ptr += temp_fea->name_len;
4073
4074 name_len--;
4075 temp_ptr++;
4076 name_len -= value_len;
4077 temp_ptr += value_len;
4078
4079
4080 temp_fea = (struct fea *)temp_ptr;
4081 }
4082 }
4083 }
4084 }
4085 if (pSMB)
4086 cifs_buf_release(pSMB);
4087 if (rc == -EAGAIN)
4088 goto QEARetry;
4089
4090 return (ssize_t)rc;
4091}
4092
4093int
4094CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4095 const char * ea_name, const void * ea_value,
4096 const __u16 ea_value_len, const struct nls_table *nls_codepage)
4097{
4098 struct smb_com_transaction2_spi_req *pSMB = NULL;
4099 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4100 struct fealist *parm_data;
4101 int name_len;
4102 int rc = 0;
4103 int bytes_returned = 0;
4104 __u16 params, param_offset, byte_count, offset, count;
4105
4106 cFYI(1, ("In SetEA"));
4107SetEARetry:
4108 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4109 (void **) &pSMBr);
4110 if (rc)
4111 return rc;
4112
4113 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4114 name_len =
4115 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
4116
4117 , nls_codepage);
4118 name_len++;
4119 name_len *= 2;
4120 } else {
4121 name_len = strnlen(fileName, PATH_MAX);
4122 name_len++;
4123 strncpy(pSMB->FileName, fileName, name_len);
4124 }
4125
4126 params = 6 + name_len;
4127
4128
4129
4130
4131 if(ea_name == NULL)
4132 name_len = 0;
4133 else
4134 name_len = strnlen(ea_name,255);
4135
4136 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
4137 pSMB->MaxParameterCount = cpu_to_le16(2);
4138 pSMB->MaxDataCount = cpu_to_le16(1000);
4139 pSMB->MaxSetupCount = 0;
4140 pSMB->Reserved = 0;
4141 pSMB->Flags = 0;
4142 pSMB->Timeout = 0;
4143 pSMB->Reserved2 = 0;
4144 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4145 InformationLevel) - 4;
4146 offset = param_offset + params;
4147 pSMB->InformationLevel =
4148 cpu_to_le16(SMB_SET_FILE_EA);
4149
4150 parm_data =
4151 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
4152 offset);
4153 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4154 pSMB->DataOffset = cpu_to_le16(offset);
4155 pSMB->SetupCount = 1;
4156 pSMB->Reserved3 = 0;
4157 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4158 byte_count = 3 + params + count;
4159 pSMB->DataCount = cpu_to_le16(count);
4160 parm_data->list_len = cpu_to_le32(count);
4161 parm_data->list[0].EA_flags = 0;
4162
4163 parm_data->list[0].name_len = (__u8)name_len;;
4164
4165 strncpy(parm_data->list[0].name,ea_name,name_len);
4166 parm_data->list[0].name[name_len] = 0;
4167 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
4168
4169
4170
4171
4172
4173 if(ea_value_len)
4174 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
4175
4176 pSMB->TotalDataCount = pSMB->DataCount;
4177 pSMB->ParameterCount = cpu_to_le16(params);
4178 pSMB->TotalParameterCount = pSMB->ParameterCount;
4179 pSMB->Reserved4 = 0;
4180 pSMB->hdr.smb_buf_length += byte_count;
4181 pSMB->ByteCount = cpu_to_le16(byte_count);
4182 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4183 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4184 if (rc) {
4185 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
4186 }
4187
4188 if (pSMB)
4189 cifs_buf_release(pSMB);
4190
4191 if (rc == -EAGAIN)
4192 goto SetEARetry;
4193
4194 return rc;
4195}
4196
4197#endif
4198