Merge with 2.5.75.
[linux-2.6/linux-mips.git] / fs / cifs / cifssmb.c
blob5761b8349297d75d77223dfd0b5bda8639dfba1e
1 /*
2 * fs/cifs/cifssmb.c
4 * Copyright (c) International Business Machines Corp., 2002
5 * Author(s): Steve French (sfrench@us.ibm.com)
7 * Contains the routines for constructing the SMB PDUs themselves
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
26 #include <linux/fs.h>
27 #include <linux/kernel.h>
28 #include <linux/vfs.h>
29 #include <asm/uaccess.h>
30 #include "cifspdu.h"
31 #include "cifsglob.h"
32 #include "cifsproto.h"
33 #include "cifs_unicode.h"
34 #include "cifs_debug.h"
36 static struct {
37 int index;
38 char *name;
39 } protocols[] = {
41 CIFS_PROT, "\2NT LM 0.12"}, {
42 BAD_PROT, "\2"}
45 int
46 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
47 void **request_buf /* returned */ ,
48 void **response_buf /* returned */ )
50 int rc = 0;
52 if(tcon && (tcon->tidStatus == CifsNeedReconnect)) {
53 rc = -EIO;
54 if(tcon->ses) {
55 struct nls_table *nls_codepage = load_nls_default();
56 if(tcon->ses->status == CifsNeedReconnect)
57 rc = setup_session(0, tcon->ses, nls_codepage);
58 if(!rc) {
59 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
60 nls_codepage);
61 cFYI(1, ("reconnect tcon rc = %d", rc));
62 if(!rc)
63 reopen_files(tcon,nls_codepage);
67 if(rc)
68 return rc;
70 *request_buf = buf_get();
71 if (request_buf == 0) {
72 return -ENOMEM;
74 /* Although the original thought was we needed the response buf for */
75 /* potential retries of smb operations it turns out we can determine */
76 /* from the mid flags when the request buffer can be resent without */
77 /* having to use a second distinct buffer for the response */
78 *response_buf = *request_buf;
80 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
81 wct /*wct */ );
82 return rc;
85 int
86 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
88 NEGOTIATE_REQ *pSMB;
89 NEGOTIATE_RSP *pSMBr;
90 int rc = 0;
91 int bytes_returned;
92 struct TCP_Server_Info * server;
94 if(ses->server)
95 server = ses->server;
96 else {
97 rc = -EIO;
98 return rc;
101 rc = smb_init(SMB_COM_NEGOTIATE, 0, 0 /* no tcon yet */ ,
102 (void **) &pSMB, (void **) &pSMBr);
103 if (rc)
104 return rc;
106 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
107 if (extended_security)
108 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
110 pSMB->ByteCount = strlen(protocols[0].name) + 1;
111 strncpy(pSMB->DialectsArray, protocols[0].name, 30);
112 /* null guaranteed to be at end of source and target buffers anyway */
114 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
115 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
117 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
118 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
119 if (rc == 0) {
120 server->secMode = pSMBr->SecurityMode;
121 server->secType = NTLM; /* BB override default for NTLMv2 or krb*/
122 /* one byte - no need to convert this or EncryptionKeyLen from le,*/
123 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
124 /* probably no need to store and check maxvcs */
125 server->maxBuf =
126 min(le32_to_cpu(pSMBr->MaxBufferSize),
127 (__u32) CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE);
128 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
129 cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
130 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
131 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
132 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
133 /* BB with UTC do we ever need to be using srvr timezone? */
134 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
135 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
136 CIFS_CRYPTO_KEY_SIZE);
137 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
138 && (pSMBr->EncryptionKeyLength == 0)) {
139 /* decode security blob */
140 } else
141 rc = -EIO;
143 /* BB might be helpful to save off the domain of server here */
145 if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) {
146 if (pSMBr->ByteCount < 16)
147 rc = -EIO;
148 else if (pSMBr->ByteCount == 16) {
149 server->secType = RawNTLMSSP;
150 if (server->socketUseCount.counter > 1) {
151 if (memcmp
152 (server->server_GUID,
153 pSMBr->u.extended_response.
154 GUID, 16) != 0) {
155 cFYI(1,
156 ("UID of server does not match previous connection to same ip address"));
157 memcpy(server->
158 server_GUID,
159 pSMBr->u.
160 extended_response.
161 GUID, 16);
163 } else
164 memcpy(server->server_GUID,
165 pSMBr->u.extended_response.
166 GUID, 16);
167 } else {
168 rc = decode_negTokenInit(pSMBr->u.
169 extended_response.
170 SecurityBlob,
171 pSMBr->ByteCount -
172 16, &server->secType);
175 } else
176 server->capabilities &= ~CAP_EXTENDED_SECURITY;
177 if(sign_CIFS_PDUs == FALSE) {
178 if(server->secMode & SECMODE_SIGN_REQUIRED)
179 cERROR(1,
180 ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
181 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
184 if (pSMB)
185 buf_release(pSMB);
186 return rc;
190 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
192 struct smb_hdr *smb_buffer;
193 struct smb_hdr *smb_buffer_response;
194 int rc = 0;
195 int length;
197 cFYI(1, ("In tree disconnect"));
199 * If last user of the connection and
200 * connection alive - disconnect it
201 * If this is the last connection on the server session disconnect it
202 * (and inside session disconnect we should check if tcp socket needs
203 * to be freed and kernel thread woken up).
205 if (tcon)
206 down(&tcon->tconSem);
207 else
208 return -EIO;
210 atomic_dec(&tcon->useCount);
211 if (atomic_read(&tcon->useCount) > 0) {
212 up(&tcon->tconSem);
213 return -EBUSY;
216 /* BB remove (from server) list of shares - but with smp safety BB */
217 /* BB is ses active - do we need to check here - but how? BB */
218 if((tcon->ses == 0) || (tcon->ses->server == 0)) {
219 up(&tcon->tconSem);
220 return -EIO;
223 rc = smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
224 (void **) &smb_buffer, (void **) &smb_buffer_response);
225 if (rc) {
226 up(&tcon->tconSem);
227 return rc;
229 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
230 &length, 0);
231 if (rc)
232 cFYI(1, (" Tree disconnect failed %d", rc));
234 if (smb_buffer)
235 buf_release(smb_buffer);
236 up(&tcon->tconSem);
237 return rc;
241 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
243 struct smb_hdr *smb_buffer_response;
244 LOGOFF_ANDX_REQ *pSMB;
245 int rc = 0;
246 int length;
248 cFYI(1, ("In SMBLogoff for session disconnect"));
250 if (ses)
251 down(&ses->sesSem); /* check this sem more places */
252 else
253 return -EIO;
255 atomic_dec(&ses->inUse);
256 if (atomic_read(&ses->inUse) > 0) {
257 up(&ses->sesSem);
258 return -EBUSY;
261 rc = smb_init(SMB_COM_LOGOFF_ANDX, 2, 0 /* no tcon anymore */,
262 (void **) &pSMB, (void **) &smb_buffer_response);
264 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
265 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
267 if (rc) {
268 up(&ses->sesSem);
269 return rc;
272 pSMB->hdr.Uid = ses->Suid;
274 pSMB->AndXCommand = 0xFF;
275 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
276 smb_buffer_response, &length, 0);
277 if (ses->server) {
278 atomic_dec(&ses->server->socketUseCount);
279 if (atomic_read(&ses->server->socketUseCount) == 0)
280 ses->server->tcpStatus = CifsExiting;
282 if (pSMB)
283 buf_release(pSMB);
284 up(&ses->sesSem);
285 return rc;
289 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
290 const char *fileName, const struct nls_table *nls_codepage)
292 DELETE_FILE_REQ *pSMB = NULL;
293 DELETE_FILE_RSP *pSMBr = NULL;
294 int rc = 0;
295 int bytes_returned;
296 int name_len;
298 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
299 (void **) &pSMBr);
300 if (rc)
301 return rc;
303 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
304 name_len =
305 cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, 530
306 /* find define for this maxpathcomponent */
307 , nls_codepage);
308 name_len++; /* trailing null */
309 name_len *= 2;
310 } else { /* BB improve the check for buffer overruns BB */
311 name_len = strnlen(fileName, 530);
312 name_len++; /* trailing null */
313 strncpy(pSMB->fileName, fileName, name_len);
315 pSMB->SearchAttributes =
316 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
317 pSMB->ByteCount = name_len + 1;
318 pSMB->BufferFormat = 0x04;
319 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
320 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
321 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
322 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
323 if (rc) {
324 cFYI(1, ("Error in RMFile = %d", rc));
326 if (pSMB)
327 buf_release(pSMB);
328 return rc;
332 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
333 const char *dirName, const struct nls_table *nls_codepage)
335 DELETE_DIRECTORY_REQ *pSMB = NULL;
336 DELETE_DIRECTORY_RSP *pSMBr = NULL;
337 int rc = 0;
338 int bytes_returned;
339 int name_len;
341 cFYI(1, ("In CIFSSMBRmDir"));
343 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
344 (void **) &pSMBr);
345 if (rc)
346 return rc;
348 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
349 name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, 530
350 /* find define for this maxpathcomponent */
351 , nls_codepage);
352 name_len++; /* trailing null */
353 name_len *= 2;
354 } else { /* BB improve the check for buffer overruns BB */
355 name_len = strnlen(dirName, 530);
356 name_len++; /* trailing null */
357 strncpy(pSMB->DirName, dirName, name_len);
360 pSMB->ByteCount = name_len + 1;
361 pSMB->BufferFormat = 0x04;
362 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
363 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
364 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
365 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
366 if (rc) {
367 cFYI(1, ("Error in RMDir = %d", rc));
369 if (pSMB)
370 buf_release(pSMB);
371 return rc;
375 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
376 const char *name, const struct nls_table *nls_codepage)
378 int rc = 0;
379 CREATE_DIRECTORY_REQ *pSMB = NULL;
380 CREATE_DIRECTORY_RSP *pSMBr = NULL;
381 int bytes_returned;
382 int name_len;
384 cFYI(1, ("In CIFSSMBMkDir"));
386 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
387 (void **) &pSMBr);
388 if (rc)
389 return rc;
391 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
392 name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, 530
393 /* find define for this maxpathcomponent */
394 , nls_codepage);
395 name_len++; /* trailing null */
396 name_len *= 2;
397 } else { /* BB improve the check for buffer overruns BB */
398 name_len = strnlen(name, 530);
399 name_len++; /* trailing null */
400 strncpy(pSMB->DirName, name, name_len);
403 pSMB->ByteCount = name_len + 1 /* for buf format */ ;
404 pSMB->BufferFormat = 0x04;
405 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
406 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
407 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
408 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
409 if (rc) {
410 cFYI(1, ("Error in Mkdir = %d", rc));
412 if (pSMB)
413 buf_release(pSMB);
415 return rc;
419 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
420 const char *fileName, const int openDisposition,
421 const int access_flags, const int create_options, __u16 * netfid,
422 int *pOplock, const struct nls_table *nls_codepage)
424 int rc = -EACCES;
425 OPEN_REQ *pSMB = NULL;
426 OPEN_RSP *pSMBr = NULL;
427 int bytes_returned;
428 int name_len;
430 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
431 (void **) &pSMBr);
432 if (rc)
433 return rc;
435 pSMB->AndXCommand = 0xFF; /* none */
437 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
438 pSMB->ByteCount = 1; /* account for one byte pad to word boundary */
439 name_len =
440 cifs_strtoUCS((wchar_t *) (pSMB->fileName + 1),
441 fileName, 530
442 /* find define for this maxpathcomponent */
443 , nls_codepage);
444 name_len++; /* trailing null */
445 name_len *= 2;
446 pSMB->NameLength = cpu_to_le16(name_len);
447 } else { /* BB improve the check for buffer overruns BB */
448 pSMB->ByteCount = 0; /* no pad */
449 name_len = strnlen(fileName, 530);
450 name_len++; /* trailing null */
451 pSMB->NameLength = cpu_to_le16(name_len);
452 strncpy(pSMB->fileName, fileName, name_len);
454 if (*pOplock & REQ_OPLOCK)
455 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
456 else if (*pOplock & REQ_BATCHOPLOCK) {
457 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
459 pSMB->DesiredAccess = cpu_to_le32(access_flags);
460 pSMB->AllocationSize = 0;
461 pSMB->FileAttributes = ATTR_NORMAL; /* XP does not handle ATTR_POSIX_SEMANTICS */
462 /*if ((omode & S_IWUGO) == 0)
463 pSMB->FileAttributes |= ATTR_READONLY;*/
464 /* Above line causes problems due to vfs splitting create into two
465 pieces - need to set mode after file created not while it is
466 being created */
467 pSMB->FileAttributes = cpu_to_le32(pSMB->FileAttributes);
468 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
469 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
470 pSMB->CreateOptions = cpu_to_le32(create_options);
471 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); /* BB ??*/
472 pSMB->SecurityFlags =
473 cpu_to_le32(SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY);
475 pSMB->ByteCount += name_len;
476 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
478 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
479 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
480 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
481 if (rc) {
482 cFYI(1, ("Error in Open = %d", rc));
483 } else {
484 *pOplock = pSMBr->OplockLevel; /* one byte no need to le_to_cpu */
485 *netfid = pSMBr->Fid; /* cifs fid stays in le */
486 /* Do we care about the CreateAction in any cases? */
488 /* BB add code to update inode file sizes from create response */
490 if (pSMB)
491 buf_release(pSMB);
493 return rc;
496 /* If no buffer passed in, then caller wants to do the copy
497 as in the case of readpages so the SMB buffer must be
498 freed by the caller */
501 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
502 const int netfid, const unsigned int count,
503 const __u64 lseek, unsigned int *nbytes, char **buf)
505 int rc = -EACCES;
506 READ_REQ *pSMB = NULL;
507 READ_RSP *pSMBr = NULL;
508 char *pReadData = NULL;
509 int bytes_returned;
511 *nbytes = 0;
512 rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
513 (void **) &pSMBr);
514 if (rc)
515 return rc;
517 pSMB->AndXCommand = 0xFF; /* none */
518 pSMB->Fid = netfid;
519 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
520 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
521 pSMB->Remaining = 0;
522 pSMB->MaxCount = cpu_to_le16(count);
523 pSMB->MaxCountHigh = 0;
524 pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */
526 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
527 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
528 if (rc) {
529 cERROR(1, ("Send error in read = %d", rc));
530 } else {
531 pSMBr->DataLength = le16_to_cpu(pSMBr->DataLength);
532 *nbytes = pSMBr->DataLength;
533 /*check that DataLength would not go beyond end of SMB */
534 if ((pSMBr->DataLength > CIFS_MAX_MSGSIZE)
535 || (pSMBr->DataLength > count)) {
536 cFYI(1,("bad length %d for count %d",pSMBr->DataLength,count));
537 rc = -EIO;
538 *nbytes = 0;
539 } else {
540 pReadData =
541 (char *) (&pSMBr->hdr.Protocol) +
542 le16_to_cpu(pSMBr->DataOffset);
543 /* if(rc = copy_to_user(buf, pReadData, pSMBr->DataLength)) {
544 cERROR(1,("Faulting on read rc = %d",rc));
545 rc = -EFAULT;
546 }*/ /* can not use copy_to_user when using page cache*/
547 if(*buf)
548 memcpy(*buf,pReadData,pSMBr->DataLength);
551 if (pSMB) {
552 if(*buf)
553 buf_release(pSMB);
554 else
555 *buf = (char *)pSMB;
557 return rc;
561 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
562 const int netfid, const unsigned int count,
563 const __u64 offset, unsigned int *nbytes, const char *buf,
564 const int long_op)
566 int rc = -EACCES;
567 WRITE_REQ *pSMB = NULL;
568 WRITE_RSP *pSMBr = NULL;
569 int bytes_returned;
571 rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
572 (void **) &pSMBr);
573 if (rc)
574 return rc;
576 pSMB->AndXCommand = 0xFF; /* none */
577 pSMB->Fid = netfid;
578 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
579 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
580 pSMB->Remaining = 0;
581 if (count > ((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00))
582 pSMB->DataLengthLow =
583 (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00;
584 else
585 pSMB->DataLengthLow = count;
586 pSMB->DataLengthHigh = 0;
587 pSMB->DataOffset =
588 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
590 memcpy(pSMB->Data,buf,pSMB->DataLengthLow);
592 pSMB->ByteCount += pSMB->DataLengthLow + 1 /* pad */ ;
593 pSMB->DataLengthLow = cpu_to_le16(pSMB->DataLengthLow);
594 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
595 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
597 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
598 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
599 if (rc) {
600 cERROR(1, ("Send error in write = %d", rc));
601 *nbytes = 0;
602 } else
603 *nbytes = le16_to_cpu(pSMBr->Count);
605 if (pSMB)
606 buf_release(pSMB);
608 return rc;
612 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
613 const __u16 smb_file_id, const __u64 len,
614 const __u64 offset, const __u32 numUnlock,
615 const __u32 numLock, const __u8 lockType, const int waitFlag)
617 int rc = 0;
618 LOCK_REQ *pSMB = NULL;
619 LOCK_RSP *pSMBr = NULL;
620 int bytes_returned;
622 cFYI(1, ("In CIFSSMBLock"));
624 rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB,
625 (void **) &pSMBr);
626 if (rc)
627 return rc;
629 pSMB->NumberOfLocks = cpu_to_le32(numLock);
630 pSMB->NumberOfUnlocks = cpu_to_le32(numUnlock);
631 pSMB->LockType = lockType;
632 pSMB->AndXCommand = 0xFF; /* none */
633 pSMB->Fid = smb_file_id; /* netfid stays le */
635 pSMB->Locks[0].Pid = cpu_to_le16(current->pid);
636 pSMB->Locks[0].Length = cpu_to_le64(len);
637 pSMB->Locks[0].Offset = cpu_to_le64(offset);
638 pSMB->ByteCount = sizeof (LOCKING_ANDX_RANGE);
639 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
640 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
642 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
643 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
645 if (rc) {
646 cERROR(1, ("Send error in Lock = %d", rc));
648 if (pSMB)
649 buf_release(pSMB);
651 return rc;
655 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
657 int rc = 0;
658 CLOSE_REQ *pSMB = NULL;
659 CLOSE_RSP *pSMBr = NULL;
660 int bytes_returned;
661 cFYI(1, ("In CIFSSMBClose"));
663 rc = smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB,
664 (void **) &pSMBr);
665 if (rc)
666 return rc;
668 pSMB->FileID = (__u16) smb_file_id;
669 pSMB->LastWriteTime = 0;
670 pSMB->ByteCount = 0;
671 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
672 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
673 if (rc) {
674 cERROR(1, ("Send error in Close = %d", rc));
676 if (pSMB)
677 buf_release(pSMB);
679 return rc;
683 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
684 const char *fromName, const char *toName,
685 const struct nls_table *nls_codepage)
687 int rc = 0;
688 RENAME_REQ *pSMB = NULL;
689 RENAME_RSP *pSMBr = NULL;
690 int bytes_returned;
691 int name_len, name_len2;
693 cFYI(1, ("In CIFSSMBRename"));
695 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
696 (void **) &pSMBr);
697 if (rc)
698 return rc;
700 pSMB->BufferFormat = 0x04;
701 pSMB->SearchAttributes =
702 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
703 ATTR_DIRECTORY);
705 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
706 name_len =
707 cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
708 /* find define for this maxpathcomponent */
709 , nls_codepage);
710 name_len++; /* trailing null */
711 name_len *= 2;
712 pSMB->OldFileName[name_len] = 0x04; /* pad */
713 /* protocol requires ASCII signature byte on Unicode string */
714 pSMB->OldFileName[name_len + 1] = 0x00;
715 name_len2 =
716 cifs_strtoUCS((wchar_t *) & pSMB->
717 OldFileName[name_len + 2], toName, 530,
718 nls_codepage);
719 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
720 name_len2 *= 2; /* convert to bytes */
721 } else { /* BB improve the check for buffer overruns BB */
722 name_len = strnlen(fromName, 530);
723 name_len++; /* trailing null */
724 strncpy(pSMB->OldFileName, fromName, name_len);
725 name_len2 = strnlen(toName, 530);
726 name_len2++; /* trailing null */
727 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
728 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
729 name_len2++; /* trailing null */
730 name_len2++; /* signature byte */
733 pSMB->ByteCount = 1 /* 1st signature byte */ + name_len + name_len2;
734 /* we could also set search attributes but not needed */
735 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
736 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
738 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
739 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
740 if (rc) {
741 cFYI(1, ("Send error in RMDir = %d", rc));
743 if (pSMB)
744 buf_release(pSMB);
746 return rc;
750 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
751 const char *fromName, const char *toName,
752 const struct nls_table *nls_codepage)
754 TRANSACTION2_SPI_REQ *pSMB = NULL;
755 TRANSACTION2_SPI_RSP *pSMBr = NULL;
756 char *data_offset;
757 int name_len;
758 int name_len_target;
759 int rc = 0;
760 int bytes_returned = 0;
762 cFYI(1, ("In Symlink Unix style"));
764 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
765 (void **) &pSMBr);
766 if (rc)
767 return rc;
769 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
770 name_len =
771 cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, 530
772 /* find define for this maxpathcomponent */
773 , nls_codepage);
774 name_len++; /* trailing null */
775 name_len *= 2;
777 } else { /* BB improve the check for buffer overruns BB */
778 name_len = strnlen(fromName, 530);
779 name_len++; /* trailing null */
780 strncpy(pSMB->FileName, fromName, name_len);
782 pSMB->ParameterCount = 6 + name_len;
783 pSMB->MaxSetupCount = 0;
784 pSMB->Reserved = 0;
785 pSMB->Flags = 0;
786 pSMB->Timeout = 0;
787 pSMB->Reserved2 = 0;
788 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
789 InformationLevel) - 4;
790 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
792 data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
793 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
794 name_len_target =
795 cifs_strtoUCS((wchar_t *) data_offset, toName, 530
796 /* find define for this maxpathcomponent */
797 , nls_codepage);
798 name_len_target++; /* trailing null */
799 name_len_target *= 2;
800 } else { /* BB improve the check for buffer overruns BB */
801 name_len_target = strnlen(toName, 530);
802 name_len_target++; /* trailing null */
803 strncpy(data_offset, toName, name_len_target);
806 pSMB->DataCount = name_len_target;
807 pSMB->MaxParameterCount = cpu_to_le16(2);
808 /* BB find exact max on data count below from sess */
809 pSMB->MaxDataCount = cpu_to_le16(1000);
810 pSMB->SetupCount = 1;
811 pSMB->Reserved3 = 0;
812 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
813 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
814 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
815 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
816 pSMB->TotalDataCount = pSMB->DataCount;
817 pSMB->TotalParameterCount = pSMB->ParameterCount;
818 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
819 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
820 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
821 pSMB->Reserved4 = 0;
822 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
823 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
824 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
825 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
826 if (rc) {
827 cFYI(1,
828 ("Send error in SetPathInfo (create symlink) = %d",
829 rc));
832 if (pSMB)
833 buf_release(pSMB);
834 return rc;
838 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
839 const char *fromName, const char *toName,
840 const struct nls_table *nls_codepage)
842 TRANSACTION2_SPI_REQ *pSMB = NULL;
843 TRANSACTION2_SPI_RSP *pSMBr = NULL;
844 char *data_offset;
845 int name_len;
846 int name_len_target;
847 int rc = 0;
848 int bytes_returned = 0;
850 cFYI(1, ("In Create Hard link Unix style"));
852 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
853 (void **) &pSMBr);
854 if (rc)
855 return rc;
857 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
858 name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, toName, 530
859 /* find define for this maxpathcomponent */
860 , nls_codepage);
861 name_len++; /* trailing null */
862 name_len *= 2;
864 } else { /* BB improve the check for buffer overruns BB */
865 name_len = strnlen(toName, 530);
866 name_len++; /* trailing null */
867 strncpy(pSMB->FileName, toName, name_len);
869 pSMB->ParameterCount = 6 + name_len;
870 pSMB->MaxSetupCount = 0;
871 pSMB->Reserved = 0;
872 pSMB->Flags = 0;
873 pSMB->Timeout = 0;
874 pSMB->Reserved2 = 0;
875 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
876 InformationLevel) - 4;
877 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
879 data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
880 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
881 name_len_target =
882 cifs_strtoUCS((wchar_t *) data_offset, fromName, 530
883 /* find define for this maxpathcomponent */
884 , nls_codepage);
885 name_len_target++; /* trailing null */
886 name_len_target *= 2;
887 } else { /* BB improve the check for buffer overruns BB */
888 name_len_target = strnlen(fromName, 530);
889 name_len_target++; /* trailing null */
890 strncpy(data_offset, fromName, name_len_target);
893 pSMB->DataCount = name_len_target;
894 pSMB->MaxParameterCount = cpu_to_le16(2);
895 /* BB find exact max on data count below from sess*/
896 pSMB->MaxDataCount = cpu_to_le16(1000);
897 pSMB->SetupCount = 1;
898 pSMB->Reserved3 = 0;
899 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
900 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
901 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
902 pSMB->TotalParameterCount = pSMB->ParameterCount;
903 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
904 pSMB->TotalDataCount = pSMB->DataCount;
905 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
906 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
907 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
908 pSMB->Reserved4 = 0;
909 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
910 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
911 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
912 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
913 if (rc) {
914 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
917 if (pSMB)
918 buf_release(pSMB);
919 return rc;
923 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
924 const char *fromName, const char *toName,
925 const struct nls_table *nls_codepage)
927 int rc = 0;
928 NT_RENAME_REQ *pSMB = NULL;
929 RENAME_RSP *pSMBr = NULL;
930 int bytes_returned;
931 int name_len, name_len2;
933 cFYI(1, ("In CIFSCreateHardLink"));
935 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
936 (void **) &pSMBr);
937 if (rc)
938 return rc;
940 pSMB->SearchAttributes =
941 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
942 ATTR_DIRECTORY);
943 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
944 pSMB->ClusterCount = 0;
946 pSMB->BufferFormat = 0x04;
948 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
949 name_len =
950 cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
951 /* find define for this maxpathcomponent */
952 , nls_codepage);
953 name_len++; /* trailing null */
954 name_len *= 2;
955 pSMB->OldFileName[name_len] = 0; /* pad */
956 pSMB->OldFileName[name_len + 1] = 0x04;
957 name_len2 =
958 cifs_strtoUCS((wchar_t *) & pSMB->
959 OldFileName[name_len + 2], toName, 530,
960 nls_codepage);
961 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
962 name_len2 *= 2; /* convert to bytes */
963 } else { /* BB improve the check for buffer overruns BB */
964 name_len = strnlen(fromName, 530);
965 name_len++; /* trailing null */
966 strncpy(pSMB->OldFileName, fromName, name_len);
967 name_len2 = strnlen(toName, 530);
968 name_len2++; /* trailing null */
969 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
970 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
971 name_len2++; /* trailing null */
972 name_len2++; /* signature byte */
975 pSMB->ByteCount = 1 /* string type byte */ + name_len + name_len2;
976 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
977 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
979 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
980 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
981 if (rc) {
982 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
984 if (pSMB)
985 buf_release(pSMB);
987 return rc;
991 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
992 const unsigned char *searchName,
993 char *symlinkinfo, const int buflen,
994 const struct nls_table *nls_codepage)
996 /* SMB_QUERY_FILE_UNIX_LINK */
997 TRANSACTION2_QPI_REQ *pSMB = NULL;
998 TRANSACTION2_QPI_RSP *pSMBr = NULL;
999 int rc = 0;
1000 int bytes_returned;
1001 int name_len;
1003 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
1004 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1005 (void **) &pSMBr);
1006 if (rc)
1007 return rc;
1009 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1010 name_len =
1011 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1012 /* find define for this maxpathcomponent */
1013 , nls_codepage);
1014 name_len++; /* trailing null */
1015 name_len *= 2;
1016 } else { /* BB improve the check for buffer overruns BB */
1017 name_len = strnlen(searchName, 530);
1018 name_len++; /* trailing null */
1019 strncpy(pSMB->FileName, searchName, name_len);
1022 pSMB->TotalParameterCount =
1023 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
1024 pSMB->TotalDataCount = 0;
1025 pSMB->MaxParameterCount = cpu_to_le16(2);
1026 /* BB find exact max data count below from sess structure BB */
1027 pSMB->MaxDataCount = cpu_to_le16(4000);
1028 pSMB->MaxSetupCount = 0;
1029 pSMB->Reserved = 0;
1030 pSMB->Flags = 0;
1031 pSMB->Timeout = 0;
1032 pSMB->Reserved2 = 0;
1033 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1034 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1035 pSMB->DataCount = 0;
1036 pSMB->DataOffset = 0;
1037 pSMB->SetupCount = 1;
1038 pSMB->Reserved3 = 0;
1039 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1040 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1041 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1042 pSMB->ParameterCount = pSMB->TotalParameterCount;
1043 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
1044 pSMB->Reserved4 = 0;
1045 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1046 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1048 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1049 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1050 if (rc) {
1051 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
1052 } else { /* decode response */
1053 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1054 pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
1055 if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
1056 /* BB also check enough total bytes returned */
1057 rc = -EIO; /* bad smb */
1058 else {
1059 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1060 name_len = UniStrnlen((wchar_t *) ((char *)
1061 &pSMBr->hdr.Protocol +pSMBr->DataOffset),
1062 min_t(const int, buflen,pSMBr->DataCount) / 2);
1063 cifs_strfromUCS_le(symlinkinfo,
1064 (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
1065 pSMBr->DataOffset),
1066 name_len, nls_codepage);
1067 } else {
1068 strncpy(symlinkinfo,
1069 (char *) &pSMBr->hdr.Protocol +
1070 pSMBr->DataOffset,
1071 min_t(const int, buflen, pSMBr->DataCount));
1073 symlinkinfo[buflen] = 0;
1074 /* just in case so calling code does not go off the end of buffer */
1077 if (pSMB)
1078 buf_release(pSMB);
1079 return rc;
1085 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1086 const unsigned char *searchName,
1087 char *symlinkinfo, const int buflen,__u16 fid,
1088 const struct nls_table *nls_codepage)
1090 int rc = 0;
1091 int bytes_returned;
1092 int name_len;
1093 struct smb_com_transaction_ioctl_req * pSMB;
1094 struct smb_com_transaction_ioctl_rsp * pSMBr;
1096 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
1097 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
1098 (void **) &pSMBr);
1099 if (rc)
1100 return rc;
1102 pSMB->TotalParameterCount = 0 ;
1103 pSMB->TotalDataCount = 0;
1104 pSMB->MaxParameterCount = cpu_to_le16(2);
1105 /* BB find exact data count max from sess structure BB */
1106 pSMB->MaxDataCount = cpu_to_le16(4000);
1107 pSMB->MaxSetupCount = 4;
1108 pSMB->Reserved = 0;
1109 pSMB->ParameterOffset = 0;
1110 pSMB->DataCount = 0;
1111 pSMB->DataOffset = 0;
1112 pSMB->SetupCount = 4;
1113 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
1114 pSMB->ParameterCount = pSMB->TotalParameterCount;
1115 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
1116 pSMB->IsFsctl = 1; /* FSCTL */
1117 pSMB->IsRootFlag = 0;
1118 pSMB->Fid = fid; /* file handle always le */
1119 pSMB->ByteCount = 0;
1121 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1122 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1123 if (rc) {
1124 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
1125 } else { /* decode response */
1126 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1127 pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
1128 if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
1129 /* BB also check enough total bytes returned */
1130 rc = -EIO; /* bad smb */
1131 else {
1132 if(pSMBr->DataCount && (pSMBr->DataCount < 2048)) {
1133 /* could also validate reparse tag && better check name length */
1134 struct reparse_data * reparse_buf = (struct reparse_data *)
1135 ((char *)&pSMBr->hdr.Protocol + pSMBr->DataOffset);
1136 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1137 name_len = UniStrnlen((wchar_t *)
1138 (reparse_buf->LinkNamesBuf +
1139 reparse_buf->TargetNameOffset),
1140 min(buflen/2, reparse_buf->TargetNameLen / 2));
1141 cifs_strfromUCS_le(symlinkinfo,
1142 (wchar_t *) (reparse_buf->LinkNamesBuf +
1143 reparse_buf->TargetNameOffset),
1144 name_len, nls_codepage);
1145 } else { /* ASCII names */
1146 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
1147 reparse_buf->TargetNameOffset,
1148 min_t(const int, buflen, reparse_buf->TargetNameLen));
1150 } else {
1151 rc = -EIO;
1152 cFYI(1,("Invalid return data count on get reparse info ioctl"));
1154 symlinkinfo[buflen] = 0; /* just in case so the caller
1155 does not go off the end of the buffer */
1156 cFYI(1,("readlink result - %s ",symlinkinfo));
1159 if (pSMB)
1160 buf_release(pSMB);
1161 return rc;
1165 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
1166 const unsigned char *searchName,
1167 FILE_ALL_INFO * pFindData,
1168 const struct nls_table *nls_codepage)
1170 /* level 263 SMB_QUERY_FILE_ALL_INFO */
1171 TRANSACTION2_QPI_REQ *pSMB = NULL;
1172 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1173 int rc = 0;
1174 int bytes_returned;
1175 int name_len;
1177 cFYI(1, ("In QPathInfo path %s", searchName));
1178 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1179 (void **) &pSMBr);
1180 if (rc)
1181 return rc;
1183 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1184 name_len =
1185 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1186 /* find define for this maxpathcomponent */
1187 , nls_codepage);
1188 name_len++; /* trailing null */
1189 name_len *= 2;
1190 } else { /* BB improve the check for buffer overruns BB */
1191 name_len = strnlen(searchName, 530);
1192 name_len++; /* trailing null */
1193 strncpy(pSMB->FileName, searchName, name_len);
1196 pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
1197 name_len /* includes null */ ;
1198 pSMB->TotalDataCount = 0;
1199 pSMB->MaxParameterCount = cpu_to_le16(2);
1200 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
1201 pSMB->MaxSetupCount = 0;
1202 pSMB->Reserved = 0;
1203 pSMB->Flags = 0;
1204 pSMB->Timeout = 0;
1205 pSMB->Reserved2 = 0;
1206 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1207 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1208 pSMB->DataCount = 0;
1209 pSMB->DataOffset = 0;
1210 pSMB->SetupCount = 1;
1211 pSMB->Reserved3 = 0;
1212 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1213 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1214 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1215 pSMB->ParameterCount = pSMB->TotalParameterCount;
1216 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
1217 pSMB->Reserved4 = 0;
1218 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1219 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1221 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1222 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1223 if (rc) {
1224 cFYI(1, ("Send error in QPathInfo = %d", rc));
1225 } else { /* decode response */
1226 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1227 /* BB also check enough total bytes returned */
1228 if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512))
1229 rc = -EIO; /* bad smb */
1230 else {
1231 memcpy((char *) pFindData,
1232 (char *) &pSMBr->hdr.Protocol +
1233 pSMBr->DataOffset, sizeof (FILE_ALL_INFO));
1236 if (pSMB)
1237 buf_release(pSMB);
1238 return rc;
1242 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
1243 const unsigned char *searchName,
1244 FILE_UNIX_BASIC_INFO * pFindData,
1245 const struct nls_table *nls_codepage)
1247 /* SMB_QUERY_FILE_UNIX_BASIC */
1248 TRANSACTION2_QPI_REQ *pSMB = NULL;
1249 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1250 int rc = 0;
1251 int bytes_returned;
1252 int name_len;
1254 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
1255 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1256 (void **) &pSMBr);
1257 if (rc)
1258 return rc;
1260 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1261 name_len =
1262 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1263 /* find define for this maxpathcomponent */
1264 , nls_codepage);
1265 name_len++; /* trailing null */
1266 name_len *= 2;
1267 } else { /* BB improve the check for buffer overruns BB */
1268 name_len = strnlen(searchName, 530);
1269 name_len++; /* trailing null */
1270 strncpy(pSMB->FileName, searchName, name_len);
1273 pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
1274 name_len /* includes null */ ;
1275 pSMB->TotalDataCount = 0;
1276 pSMB->MaxParameterCount = cpu_to_le16(2);
1277 /* BB find exact max SMB PDU from sess structure BB */
1278 pSMB->MaxDataCount = cpu_to_le16(4000);
1279 pSMB->MaxSetupCount = 0;
1280 pSMB->Reserved = 0;
1281 pSMB->Flags = 0;
1282 pSMB->Timeout = 0;
1283 pSMB->Reserved2 = 0;
1284 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1285 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1286 pSMB->DataCount = 0;
1287 pSMB->DataOffset = 0;
1288 pSMB->SetupCount = 1;
1289 pSMB->Reserved3 = 0;
1290 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1291 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1292 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1293 pSMB->ParameterCount = pSMB->TotalParameterCount;
1294 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1295 pSMB->Reserved4 = 0;
1296 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1297 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1299 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1300 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1301 if (rc) {
1302 cFYI(1, ("Send error in QPathInfo = %d", rc));
1303 } else { /* decode response */
1304 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1305 /* BB also check if enough total bytes returned */
1306 if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512))
1307 rc = -EIO; /* bad smb */
1308 else {
1309 memcpy((char *) pFindData,
1310 (char *) &pSMBr->hdr.Protocol +
1311 pSMBr->DataOffset,
1312 sizeof (FILE_UNIX_BASIC_INFO));
1315 if (pSMB)
1316 buf_release(pSMB);
1317 return rc;
1321 CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
1322 const char *searchName, FILE_ALL_INFO * findData,
1323 const struct nls_table *nls_codepage)
1325 /* level 257 SMB_ */
1326 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
1327 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
1328 int rc = 0;
1329 int bytes_returned;
1330 int name_len;
1332 cFYI(1, ("In FindUnique"));
1333 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1334 (void **) &pSMBr);
1335 if (rc)
1336 return rc;
1338 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1339 name_len =
1340 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1341 /* find define for this maxpathcomponent */
1342 , nls_codepage);
1343 name_len++; /* trailing null */
1344 name_len *= 2;
1345 } else { /* BB improve the check for buffer overruns BB */
1346 name_len = strnlen(searchName, 530);
1347 name_len++; /* trailing null */
1348 strncpy(pSMB->FileName, searchName, name_len);
1351 pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
1352 pSMB->TotalDataCount = 0; /* no EAs */
1353 pSMB->MaxParameterCount = cpu_to_le16(2);
1354 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
1355 pSMB->MaxSetupCount = 0;
1356 pSMB->Reserved = 0;
1357 pSMB->Flags = 0;
1358 pSMB->Timeout = 0;
1359 pSMB->Reserved2 = 0;
1360 pSMB->ParameterOffset = cpu_to_le16(
1361 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
1362 pSMB->DataCount = 0;
1363 pSMB->DataOffset = 0;
1364 pSMB->SetupCount = 1; /* one byte, no need to le convert */
1365 pSMB->Reserved3 = 0;
1366 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
1367 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1368 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalDataCount);
1369 pSMB->ParameterCount = pSMB->TotalParameterCount;
1370 pSMB->SearchAttributes =
1371 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1372 ATTR_DIRECTORY);
1373 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
1374 pSMB->SearchFlags = cpu_to_le16(1);
1375 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
1376 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
1377 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1378 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1380 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1381 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1383 if (rc) {
1384 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
1385 } else { /* decode response */
1387 /* BB fill in */
1389 if (pSMB)
1390 buf_release(pSMB);
1391 return rc;
1395 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
1396 const char *searchName, FILE_DIRECTORY_INFO * findData,
1397 T2_FFIRST_RSP_PARMS * findParms,
1398 const struct nls_table *nls_codepage, int *pUnicodeFlag,
1399 int *pUnixFlag)
1401 /* level 257 SMB_ */
1402 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
1403 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
1404 char *response_data;
1405 int rc = 0;
1406 int bytes_returned;
1407 int name_len;
1409 cFYI(1, ("In FindFirst"));
1410 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1411 (void **) &pSMBr);
1412 if (rc)
1413 return rc;
1415 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1416 name_len =
1417 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1418 /* find define for this maxpathcomponent */
1419 , nls_codepage);
1420 name_len++; /* trailing null */
1421 name_len *= 2;
1422 } else { /* BB improve the check for buffer overruns BB */
1423 name_len = strnlen(searchName, 530);
1424 name_len++; /* trailing null */
1425 strncpy(pSMB->FileName, searchName, name_len);
1428 pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
1429 pSMB->TotalDataCount = 0; /* no EAs */
1430 pSMB->MaxParameterCount = cpu_to_le16(10);
1431 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
1432 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
1433 pSMB->MaxSetupCount = 0;
1434 pSMB->Reserved = 0;
1435 pSMB->Flags = 0;
1436 pSMB->Timeout = 0;
1437 pSMB->Reserved2 = 0;
1438 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1439 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1440 pSMB->ParameterCount = pSMB->TotalParameterCount;
1441 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
1442 smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
1443 pSMB->DataCount = 0;
1444 pSMB->DataOffset = 0;
1445 pSMB->SetupCount = 1; /* one byte no need to make endian neutral */
1446 pSMB->Reserved3 = 0;
1447 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
1448 pSMB->SearchAttributes =
1449 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1450 ATTR_DIRECTORY);
1451 pSMB->SearchCount = cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO)); /* should this be shrunk even more ? */
1452 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
1454 /* test for Unix extensions */
1455 if (tcon->ses->capabilities & CAP_UNIX) {
1456 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
1457 *pUnixFlag = TRUE;
1458 } else {
1459 pSMB->InformationLevel =
1460 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
1461 *pUnixFlag = FALSE;
1463 pSMB->SearchStorageType = 0; /* BB what should we set this to? It is not clear if it matters BB */
1464 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1465 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1467 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1468 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1470 if (rc) { /* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
1471 cFYI(1, ("Error in FindFirst = %d", rc));
1472 } else { /* decode response */
1473 /* BB add safety checks for these memcpys */
1474 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
1475 *pUnicodeFlag = TRUE;
1476 else
1477 *pUnicodeFlag = FALSE;
1478 memcpy(findParms,
1479 (char *) &pSMBr->hdr.Protocol +
1480 le16_to_cpu(pSMBr->ParameterOffset),
1481 sizeof (T2_FFIRST_RSP_PARMS));
1482 /* search handle can stay LE and EAoffset not needed so not converted */
1483 findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
1484 findParms->LastNameOffset =
1485 le16_to_cpu(findParms->LastNameOffset);
1486 findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
1487 response_data =
1488 (char *) &pSMBr->hdr.Protocol +
1489 le16_to_cpu(pSMBr->DataOffset);
1490 memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
1492 if (pSMB)
1493 buf_release(pSMB);
1494 return rc;
1498 CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
1499 FILE_DIRECTORY_INFO * findData, T2_FNEXT_RSP_PARMS * findParms,
1500 const __u16 searchHandle, char * resume_file_name, int name_len,
1501 __u32 resume_key, int *pUnicodeFlag, int *pUnixFlag)
1503 /* level 257 SMB_ */
1504 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
1505 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
1506 char *response_data;
1507 int rc = 0;
1508 int bytes_returned;
1510 cFYI(1, ("In FindNext"));
1511 if(resume_file_name == NULL) {
1512 return -EIO;
1514 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1515 (void **) &pSMBr);
1516 if (rc)
1517 return rc;
1519 pSMB->TotalParameterCount = 14; /* includes 2 bytes of null string, converted to LE below */
1520 pSMB->TotalDataCount = 0; /* no EAs */
1521 pSMB->MaxParameterCount = cpu_to_le16(8);
1522 pSMB->MaxDataCount =
1523 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
1524 pSMB->MaxSetupCount = 0;
1525 pSMB->Reserved = 0;
1526 pSMB->Flags = 0;
1527 pSMB->Timeout = 0;
1528 pSMB->Reserved2 = 0;
1529 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1530 struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
1531 pSMB->DataCount = 0;
1532 pSMB->DataOffset = 0;
1533 pSMB->SetupCount = 1;
1534 pSMB->Reserved3 = 0;
1535 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
1536 pSMB->SearchHandle = searchHandle; /* always kept as le */
1537 findParms->SearchCount = 0; /* set to zero in case of error */
1538 pSMB->SearchCount =
1539 cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO));
1540 /* test for Unix extensions */
1541 if (tcon->ses->capabilities & CAP_UNIX) {
1542 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
1543 *pUnixFlag = TRUE;
1544 } else {
1545 pSMB->InformationLevel =
1546 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
1547 *pUnixFlag = FALSE;
1549 pSMB->ResumeKey = resume_key;
1550 pSMB->SearchFlags =
1551 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
1552 /* BB add check to make sure we do not cross end of smb */
1553 if(name_len < CIFS_MAX_MSGSIZE) {
1554 memcpy(pSMB->ResumeFileName, resume_file_name, name_len);
1555 pSMB->ByteCount += name_len;
1557 pSMB->TotalParameterCount += name_len;
1558 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1559 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1560 pSMB->ParameterCount = pSMB->TotalParameterCount;
1561 /* BB improve error handling here */
1562 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1563 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1565 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1566 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1568 if (rc) {
1569 if (rc == -EBADF)
1570 rc = 0; /* search probably was closed at end of search above */
1571 else
1572 cFYI(1, ("FindNext returned = %d", rc));
1573 } else { /* decode response */
1574 /* BB add safety checks for these memcpys */
1575 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
1576 *pUnicodeFlag = TRUE;
1577 else
1578 *pUnicodeFlag = FALSE;
1579 memcpy(findParms,
1580 (char *) &pSMBr->hdr.Protocol +
1581 le16_to_cpu(pSMBr->ParameterOffset),
1582 sizeof (T2_FNEXT_RSP_PARMS));
1583 findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
1584 findParms->LastNameOffset =
1585 le16_to_cpu(findParms->LastNameOffset);
1586 findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
1587 response_data =
1588 (char *) &pSMBr->hdr.Protocol +
1589 le16_to_cpu(pSMBr->DataOffset);
1590 memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
1592 if (pSMB)
1593 buf_release(pSMB);
1594 return rc;
1598 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
1600 int rc = 0;
1601 FINDCLOSE_REQ *pSMB = NULL;
1602 CLOSE_RSP *pSMBr = NULL;
1603 int bytes_returned;
1604 cFYI(1, ("In CIFSSMBFindClose"));
1606 rc = smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **) &pSMB,
1607 (void **) &pSMBr);
1608 if (rc)
1609 return rc;
1611 pSMB->FileID = searchHandle;
1612 pSMB->ByteCount = 0;
1613 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1614 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1615 if (rc) {
1616 cERROR(1, ("Send error in FindClose = %d", rc));
1618 if (pSMB)
1619 buf_release(pSMB);
1621 return rc;
1625 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
1626 const unsigned char *searchName,
1627 unsigned char **targetUNCs,
1628 unsigned int *number_of_UNC_in_array,
1629 const struct nls_table *nls_codepage)
1631 /* TRANS2_GET_DFS_REFERRAL */
1632 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
1633 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
1634 struct dfs_referral_level_3 * referrals = NULL;
1635 int rc = 0;
1636 int bytes_returned;
1637 int name_len;
1638 unsigned int i;
1639 char * temp;
1640 *number_of_UNC_in_array = 0;
1641 *targetUNCs = NULL;
1643 cFYI(1, ("In GetDFSRefer the path %s", searchName));
1644 if (ses == NULL)
1645 return -ENODEV;
1647 rc = smb_init(SMB_COM_TRANSACTION2, 15, 0, (void **) &pSMB,
1648 (void **) &pSMBr);
1649 if (rc)
1650 return rc;
1652 pSMB->hdr.Tid = ses->ipc_tid;
1653 pSMB->hdr.Uid = ses->Suid;
1654 if (ses->capabilities & CAP_STATUS32) {
1655 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
1657 if (ses->capabilities & CAP_DFS) {
1658 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
1661 if (ses->capabilities & CAP_UNICODE) {
1662 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
1663 name_len =
1664 cifs_strtoUCS((wchar_t *) pSMB->RequestFileName,
1665 searchName, 530
1666 /* find define for this maxpathcomponent */
1667 , nls_codepage);
1668 name_len++; /* trailing null */
1669 name_len *= 2;
1670 } else { /* BB improve the check for buffer overruns BB */
1671 name_len = strnlen(searchName, 530);
1672 name_len++; /* trailing null */
1673 strncpy(pSMB->RequestFileName, searchName, name_len);
1676 pSMB->ParameterCount = 2 /* level */ + name_len /*includes null */ ;
1677 pSMB->TotalDataCount = 0;
1678 pSMB->DataCount = 0;
1679 pSMB->DataOffset = 0;
1680 pSMB->MaxParameterCount = 0;
1681 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
1682 pSMB->MaxSetupCount = 0;
1683 pSMB->Reserved = 0;
1684 pSMB->Flags = 0;
1685 pSMB->Timeout = 0;
1686 pSMB->Reserved2 = 0;
1687 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1688 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
1689 pSMB->SetupCount = 1;
1690 pSMB->Reserved3 = 0;
1691 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
1692 pSMB->ByteCount = pSMB->ParameterCount + 3 /* pad */ ;
1693 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
1694 pSMB->TotalParameterCount = pSMB->ParameterCount;
1695 pSMB->MaxReferralLevel = cpu_to_le16(3);
1696 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1697 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1699 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
1700 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1701 if (rc) {
1702 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
1703 } else { /* decode response */
1704 /* BB Add logic to parse referrals here */
1705 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1706 pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
1707 cFYI(1,
1708 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
1709 pSMBr->ByteCount, pSMBr->DataOffset));
1710 if ((pSMBr->ByteCount < 17) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */
1711 rc = -EIO; /* bad smb */
1712 else {
1713 referrals =
1714 (struct dfs_referral_level_3 *)
1715 (8 /* sizeof start of data block */ +
1716 pSMBr->DataOffset +
1717 (char *) &pSMBr->hdr.Protocol);
1718 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",pSMBr->NumberOfReferrals,pSMBr->DFSFlags, referrals->ReferralSize,referrals->ServerType,referrals->ReferralFlags,referrals->TimeToLive));
1719 /* BB This field is actually two bytes in from start of
1720 data block so we could do safety check that DataBlock
1721 begins at address of pSMBr->NumberOfReferrals */
1722 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
1724 /* BB Fix below so can return more than one referral */
1725 if(*number_of_UNC_in_array > 1)
1726 *number_of_UNC_in_array = 1;
1728 /* get the length of the strings describing refs */
1729 name_len = 0;
1730 for(i=0;i<*number_of_UNC_in_array;i++) {
1731 /* make sure that DfsPathOffset not past end */
1732 referrals->DfsPathOffset = le16_to_cpu(referrals->DfsPathOffset);
1733 if(referrals->DfsPathOffset > pSMBr->DataCount) {
1734 /* if invalid referral, stop here and do
1735 not try to copy any more */
1736 *number_of_UNC_in_array = i;
1737 break;
1739 temp = ((char *)referrals) + referrals->DfsPathOffset;
1741 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1742 name_len += UniStrnlen((wchar_t *)temp,pSMBr->DataCount);
1743 } else {
1744 name_len += strnlen(temp,pSMBr->DataCount);
1746 referrals++;
1747 /* BB add check that referral pointer does not fall off end PDU */
1750 /* BB add check for name_len bigger than bcc */
1751 *targetUNCs =
1752 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
1753 /* copy the ref strings */
1754 referrals =
1755 (struct dfs_referral_level_3 *)
1756 (8 /* sizeof data hdr */ +
1757 pSMBr->DataOffset +
1758 (char *) &pSMBr->hdr.Protocol);
1760 for(i=0;i<*number_of_UNC_in_array;i++) {
1761 temp = ((char *)referrals) + referrals->DfsPathOffset;
1762 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1763 cifs_strfromUCS_le(*targetUNCs,
1764 (wchar_t *) temp, name_len, nls_codepage);
1765 } else {
1766 strncpy(*targetUNCs,temp,name_len);
1768 /* BB update target_uncs pointers */
1769 referrals++;
1771 temp = *targetUNCs;
1772 temp[name_len] = 0;
1776 if (pSMB)
1777 buf_release(pSMB);
1778 return rc;
1782 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
1783 struct kstatfs *FSData, const struct nls_table *nls_codepage)
1785 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
1786 TRANSACTION2_QFSI_REQ *pSMB = NULL;
1787 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
1788 FILE_SYSTEM_INFO *response_data;
1789 int rc = 0;
1790 int bytes_returned = 0;
1792 cFYI(1, ("In QFSInfo"));
1794 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1795 (void **) &pSMBr);
1796 if (rc)
1797 return rc;
1799 pSMB->TotalParameterCount = 2; /* level */
1800 pSMB->TotalDataCount = 0;
1801 pSMB->MaxParameterCount = cpu_to_le16(2);
1802 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
1803 pSMB->MaxSetupCount = 0;
1804 pSMB->Reserved = 0;
1805 pSMB->Flags = 0;
1806 pSMB->Timeout = 0;
1807 pSMB->Reserved2 = 0;
1808 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1809 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1810 pSMB->ParameterCount = pSMB->TotalParameterCount;
1811 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1812 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
1813 pSMB->DataCount = 0;
1814 pSMB->DataOffset = 0;
1815 pSMB->SetupCount = 1;
1816 pSMB->Reserved3 = 0;
1817 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
1818 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
1819 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1820 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1822 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1823 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1824 if (rc) {
1825 cERROR(1, ("Send error in QFSInfo = %d", rc));
1826 } else { /* decode response */
1827 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1828 cFYI(1,
1829 ("Decoding qfsinfo response. BCC: %d Offset %d",
1830 pSMBr->ByteCount, pSMBr->DataOffset));
1831 if ((pSMBr->ByteCount < 24) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */
1832 rc = -EIO; /* bad smb */
1833 else {
1834 response_data =
1835 (FILE_SYSTEM_INFO
1836 *) (((char *) &pSMBr->hdr.Protocol) +
1837 pSMBr->DataOffset);
1838 FSData->f_bsize =
1839 le32_to_cpu(response_data->BytesPerSector) *
1840 le32_to_cpu(response_data->
1841 SectorsPerAllocationUnit);
1842 FSData->f_blocks =
1843 le64_to_cpu(response_data->TotalAllocationUnits);
1844 FSData->f_bfree = FSData->f_bavail =
1845 le64_to_cpu(response_data->FreeAllocationUnits);
1846 cFYI(1,
1847 ("Blocks: %lld Free: %lld Block size %ld",
1848 (unsigned long long)FSData->f_blocks,
1849 (unsigned long long)FSData->f_bfree,
1850 FSData->f_bsize));
1853 if (pSMB)
1854 buf_release(pSMB);
1855 return rc;
1859 CIFSSMBQFSAttributeInfo(int xid, struct cifsTconInfo *tcon,
1860 const struct nls_table *nls_codepage)
1862 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
1863 TRANSACTION2_QFSI_REQ *pSMB = NULL;
1864 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
1865 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
1866 int rc = 0;
1867 int bytes_returned = 0;
1869 cFYI(1, ("In QFSAttributeInfo"));
1870 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1871 (void **) &pSMBr);
1872 if (rc)
1873 return rc;
1875 pSMB->TotalParameterCount = 2; /* level */
1876 pSMB->TotalDataCount = 0;
1877 pSMB->MaxParameterCount = cpu_to_le16(2);
1878 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
1879 pSMB->MaxSetupCount = 0;
1880 pSMB->Reserved = 0;
1881 pSMB->Flags = 0;
1882 pSMB->Timeout = 0;
1883 pSMB->Reserved2 = 0;
1884 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1885 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1886 pSMB->ParameterCount = pSMB->TotalParameterCount;
1887 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1888 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
1889 pSMB->DataCount = 0;
1890 pSMB->DataOffset = 0;
1891 pSMB->SetupCount = 1;
1892 pSMB->Reserved3 = 0;
1893 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
1894 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
1895 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1896 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1898 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1899 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1900 if (rc) {
1901 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
1902 } else { /* decode response */
1903 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1904 if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) { /* BB also check enough bytes returned */
1905 rc = -EIO; /* bad smb */
1906 } else {
1907 response_data =
1908 (FILE_SYSTEM_ATTRIBUTE_INFO
1909 *) (((char *) &pSMBr->hdr.Protocol) +
1910 pSMBr->DataOffset);
1911 memcpy(&tcon->fsAttrInfo, response_data,
1912 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
1915 if (pSMB)
1916 buf_release(pSMB);
1917 return rc;
1921 CIFSSMBQFSDeviceInfo(int xid, struct cifsTconInfo *tcon,
1922 const struct nls_table *nls_codepage)
1924 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
1925 TRANSACTION2_QFSI_REQ *pSMB = NULL;
1926 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
1927 FILE_SYSTEM_DEVICE_INFO *response_data;
1928 int rc = 0;
1929 int bytes_returned = 0;
1931 cFYI(1, ("In QFSDeviceInfo"));
1933 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1934 (void **) &pSMBr);
1935 if (rc)
1936 return rc;
1938 pSMB->TotalParameterCount = 2; /* level */
1939 pSMB->TotalDataCount = 0;
1940 pSMB->MaxParameterCount = cpu_to_le16(2);
1941 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
1942 pSMB->MaxSetupCount = 0;
1943 pSMB->Reserved = 0;
1944 pSMB->Flags = 0;
1945 pSMB->Timeout = 0;
1946 pSMB->Reserved2 = 0;
1947 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1948 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1949 pSMB->ParameterCount = pSMB->TotalParameterCount;
1950 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1951 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
1953 pSMB->DataCount = 0;
1954 pSMB->DataOffset = 0;
1955 pSMB->SetupCount = 1;
1956 pSMB->Reserved3 = 0;
1957 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
1958 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
1959 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1960 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1962 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1963 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1964 if (rc) {
1965 cERROR(1, ("Send error in QFSDeviceInfo = %d", rc));
1966 } else { /* decode response */
1967 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1968 if ((pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO))
1969 || (pSMBr->DataOffset > 512))
1970 rc = -EIO; /* bad smb */
1971 else {
1972 response_data =
1973 (FILE_SYSTEM_DEVICE_INFO
1974 *) (((char *) &pSMBr->hdr.Protocol) +
1975 pSMBr->DataOffset);
1976 memcpy(&tcon->fsDevInfo, response_data,
1977 sizeof (FILE_SYSTEM_DEVICE_INFO));
1980 if (pSMB)
1981 buf_release(pSMB);
1982 return rc;
1986 CIFSSMBQFSUnixInfo(int xid, struct cifsTconInfo *tcon,
1987 const struct nls_table *nls_codepage)
1989 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
1990 TRANSACTION2_QFSI_REQ *pSMB = NULL;
1991 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
1992 FILE_SYSTEM_UNIX_INFO *response_data;
1993 int rc = 0;
1994 int bytes_returned = 0;
1996 cFYI(1, ("In QFSUnixInfo"));
1997 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1998 (void **) &pSMBr);
1999 if (rc)
2000 return rc;
2002 pSMB->ParameterCount = 2; /* level */
2003 pSMB->TotalDataCount = 0;
2004 pSMB->DataCount = 0;
2005 pSMB->DataOffset = 0;
2006 pSMB->MaxParameterCount = cpu_to_le16(2);
2007 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
2008 pSMB->MaxSetupCount = 0;
2009 pSMB->Reserved = 0;
2010 pSMB->Flags = 0;
2011 pSMB->Timeout = 0;
2012 pSMB->Reserved2 = 0;
2013 pSMB->ByteCount = pSMB->ParameterCount + 1 /* pad */ ;
2014 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2015 pSMB->TotalParameterCount = pSMB->ParameterCount;
2016 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
2017 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
2018 pSMB->SetupCount = 1;
2019 pSMB->Reserved3 = 0;
2020 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
2021 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
2022 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2023 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2025 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2026 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2027 if (rc) {
2028 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
2029 } else { /* decode response */
2030 pSMBr->DataOffset = cpu_to_le16(pSMBr->DataOffset);
2031 if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) {
2032 rc = -EIO; /* bad smb */
2033 } else {
2034 response_data =
2035 (FILE_SYSTEM_UNIX_INFO
2036 *) (((char *) &pSMBr->hdr.Protocol) +
2037 pSMBr->DataOffset);
2038 memcpy(&tcon->fsUnixInfo, response_data,
2039 sizeof (FILE_SYSTEM_UNIX_INFO));
2042 if (pSMB)
2043 buf_release(pSMB);
2044 return rc;
2047 /* We can not use write of zero bytes trick to
2048 set file size due to need for large file support. Also note that
2049 this SetPathInfo is preferred to SetFileInfo based method in next
2050 routine which is only needed to work around a sharing violation bug
2051 in Samba which this routine can run into */
2054 CIFSSMBSetEOF(int xid, struct cifsTconInfo *tcon, char *fileName,
2055 __u64 size, int SetAllocation, const struct nls_table *nls_codepage)
2057 struct smb_com_transaction2_spi_req *pSMB = NULL;
2058 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2059 struct file_end_of_file_info *parm_data;
2060 int name_len;
2061 int rc = 0;
2062 int bytes_returned = 0;
2064 cFYI(1, ("In SetEOF"));
2066 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2067 (void **) &pSMBr);
2068 if (rc)
2069 return rc;
2071 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2072 name_len =
2073 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
2074 /* find define for this maxpathcomponent */
2075 , nls_codepage);
2076 name_len++; /* trailing null */
2077 name_len *= 2;
2078 } else { /* BB improve the check for buffer overruns BB */
2079 name_len = strnlen(fileName, 530);
2080 name_len++; /* trailing null */
2081 strncpy(pSMB->FileName, fileName, name_len);
2083 pSMB->ParameterCount = 6 + name_len;
2084 pSMB->DataCount = sizeof (struct file_end_of_file_info);
2085 pSMB->MaxParameterCount = cpu_to_le16(2);
2086 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2087 pSMB->MaxSetupCount = 0;
2088 pSMB->Reserved = 0;
2089 pSMB->Flags = 0;
2090 pSMB->Timeout = 0;
2091 pSMB->Reserved2 = 0;
2092 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
2093 InformationLevel) - 4;
2094 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
2095 if(SetAllocation) {
2096 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2097 pSMB->InformationLevel =
2098 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
2099 else
2100 pSMB->InformationLevel =
2101 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
2102 } else /* Set File Size */ {
2103 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2104 pSMB->InformationLevel =
2105 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
2106 else
2107 pSMB->InformationLevel =
2108 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
2111 parm_data =
2112 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
2113 pSMB->DataOffset);
2114 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
2115 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
2116 pSMB->SetupCount = 1;
2117 pSMB->Reserved3 = 0;
2118 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2119 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
2120 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
2121 pSMB->TotalDataCount = pSMB->DataCount;
2122 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2123 pSMB->TotalParameterCount = pSMB->ParameterCount;
2124 pSMB->Reserved4 = 0;
2125 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2126 parm_data->FileSize = cpu_to_le64(size);
2127 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2128 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2129 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2130 if (rc) {
2131 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
2134 if (pSMB)
2135 buf_release(pSMB);
2136 return rc;
2140 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
2141 __u16 fid, __u32 pid_of_opener, int SetAllocation)
2143 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2144 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2145 char *data_offset;
2146 struct file_end_of_file_info *parm_data;
2147 int rc = 0;
2148 int bytes_returned = 0;
2149 __u32 tmp;
2151 cFYI(1, ("SetFileSize (via SetFileInfo)"));
2153 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2154 (void **) &pSMBr);
2155 if (rc)
2156 return rc;
2158 tmp = cpu_to_le32(pid_of_opener); /* override pid of current process
2159 so network fid will be valid */
2160 pSMB->hdr.Pid = tmp & 0xFFFF;
2161 tmp >>= 16;
2162 pSMB->hdr.PidHigh = tmp & 0xFFFF;
2164 pSMB->ParameterCount = 6;
2165 pSMB->MaxSetupCount = 0;
2166 pSMB->Reserved = 0;
2167 pSMB->Flags = 0;
2168 pSMB->Timeout = 0;
2169 pSMB->Reserved2 = 0;
2170 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
2171 Fid) - 4;
2172 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
2174 data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
2176 pSMB->DataCount = sizeof(struct file_end_of_file_info);
2177 pSMB->MaxParameterCount = cpu_to_le16(2);
2178 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
2179 pSMB->SetupCount = 1;
2180 pSMB->Reserved3 = 0;
2181 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2182 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
2183 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
2184 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2185 pSMB->TotalDataCount = pSMB->DataCount;
2186 pSMB->TotalParameterCount = pSMB->ParameterCount;
2187 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
2188 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
2189 parm_data =
2190 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
2191 pSMB->DataOffset);
2192 parm_data->FileSize = size;
2193 pSMB->Fid = fid;
2194 if(SetAllocation) {
2195 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2196 pSMB->InformationLevel =
2197 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
2198 else
2199 pSMB->InformationLevel =
2200 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
2201 } else /* Set File Size */ {
2202 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2203 pSMB->InformationLevel =
2204 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
2205 else
2206 pSMB->InformationLevel =
2207 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
2209 pSMB->Reserved4 = 0;
2210 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2211 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2212 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2213 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2214 if (rc) {
2215 cFYI(1,
2216 ("Send error in SetFileInfo (SetFileSize) = %d",
2217 rc));
2220 if (pSMB)
2221 buf_release(pSMB);
2222 return rc;
2226 CIFSSMBSetTimes(int xid, struct cifsTconInfo *tcon, char *fileName,
2227 FILE_BASIC_INFO * data, const struct nls_table *nls_codepage)
2229 TRANSACTION2_SPI_REQ *pSMB = NULL;
2230 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2231 int name_len;
2232 int rc = 0;
2233 int bytes_returned = 0;
2234 char *data_offset;
2236 cFYI(1, ("In SetTimes"));
2238 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2239 (void **) &pSMBr);
2240 if (rc)
2241 return rc;
2243 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2244 name_len =
2245 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
2246 /* find define for this maxpathcomponent */
2247 , nls_codepage);
2248 name_len++; /* trailing null */
2249 name_len *= 2;
2250 } else { /* BB improve the check for buffer overruns BB */
2251 name_len = strnlen(fileName, 530);
2252 name_len++; /* trailing null */
2253 strncpy(pSMB->FileName, fileName, name_len);
2256 pSMB->ParameterCount = 6 + name_len;
2257 pSMB->DataCount = sizeof (FILE_BASIC_INFO);
2258 pSMB->MaxParameterCount = cpu_to_le16(2);
2259 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2260 pSMB->MaxSetupCount = 0;
2261 pSMB->Reserved = 0;
2262 pSMB->Flags = 0;
2263 pSMB->Timeout = 0;
2264 pSMB->Reserved2 = 0;
2265 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
2266 InformationLevel) - 4;
2267 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
2268 data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
2269 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
2270 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
2271 pSMB->SetupCount = 1;
2272 pSMB->Reserved3 = 0;
2273 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2274 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
2276 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
2277 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2278 pSMB->TotalDataCount = pSMB->DataCount;
2279 pSMB->TotalParameterCount = pSMB->ParameterCount;
2280 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2281 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
2282 else
2283 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
2284 pSMB->Reserved4 = 0;
2285 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2286 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
2287 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2288 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2289 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2290 if (rc) {
2291 cFYI(1, ("SetPathInfo (times) returned %d", rc));
2294 if (pSMB)
2295 buf_release(pSMB);
2296 return rc;
2300 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
2301 char *fileName, __u64 mode, __u64 uid, __u64 gid,
2302 const struct nls_table *nls_codepage)
2304 TRANSACTION2_SPI_REQ *pSMB = NULL;
2305 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2306 int name_len;
2307 int rc = 0;
2308 int bytes_returned = 0;
2309 FILE_UNIX_BASIC_INFO *data_offset;
2311 cFYI(1, ("In SetUID/GID/Mode"));
2313 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2314 (void **) &pSMBr);
2315 if (rc)
2316 return rc;
2318 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2319 name_len =
2320 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
2321 /* find define for this maxpathcomponent */
2322 , nls_codepage);
2323 name_len++; /* trailing null */
2324 name_len *= 2;
2325 } else { /* BB improve the check for buffer overruns BB */
2326 name_len = strnlen(fileName, 530);
2327 name_len++; /* trailing null */
2328 strncpy(pSMB->FileName, fileName, name_len);
2331 pSMB->ParameterCount = 6 + name_len;
2332 pSMB->DataCount = sizeof (FILE_UNIX_BASIC_INFO);
2333 pSMB->MaxParameterCount = cpu_to_le16(2);
2334 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2335 pSMB->MaxSetupCount = 0;
2336 pSMB->Reserved = 0;
2337 pSMB->Flags = 0;
2338 pSMB->Timeout = 0;
2339 pSMB->Reserved2 = 0;
2340 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
2341 InformationLevel) - 4;
2342 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
2343 data_offset =
2344 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
2345 pSMB->DataOffset);
2346 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
2347 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
2348 pSMB->SetupCount = 1;
2349 pSMB->Reserved3 = 0;
2350 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2351 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
2352 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2353 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
2354 pSMB->TotalParameterCount = pSMB->ParameterCount;
2355 pSMB->TotalDataCount = pSMB->DataCount;
2356 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
2357 pSMB->Reserved4 = 0;
2358 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2359 data_offset->Uid = cpu_to_le64(uid);
2360 data_offset->Gid = cpu_to_le64(gid);
2361 data_offset->Permissions = cpu_to_le64(mode);
2362 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2363 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2364 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2365 if (rc) {
2366 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
2369 if (pSMB)
2370 buf_release(pSMB);
2371 return rc;