initial commit with v2.6.9
[linux-2.6.9-moxart.git] / fs / cifs / cifssmb.c
blob8e17185383f02151a33de605dcc835ef0eb09b36
1 /*
2 * fs/cifs/cifssmb.c
4 * Copyright (C) International Business Machines Corp., 2002,2003
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 */
25 /* These are mostly routines that operate on a pathname, or on a tree id */
26 /* (mounted volume), but there are eight handle based routines which must be */
27 /* treated slightly different for reconnection purposes since we never want */
28 /* to reuse a stale file handle and the caller knows the file handle */
30 #include <linux/fs.h>
31 #include <linux/kernel.h>
32 #include <linux/vfs.h>
33 #include <asm/uaccess.h>
34 #include "cifspdu.h"
35 #include "cifsglob.h"
36 #include "cifsproto.h"
37 #include "cifs_unicode.h"
38 #include "cifs_debug.h"
40 #ifdef CONFIG_CIFS_POSIX
41 static struct {
42 int index;
43 char *name;
44 } protocols[] = {
45 {CIFS_PROT, "\2NT LM 0.12"},
46 {CIFS_PROT, "\2POSIX 2"},
47 {BAD_PROT, "\2"}
49 #else
50 static struct {
51 int index;
52 char *name;
53 } protocols[] = {
54 {CIFS_PROT, "\2NT LM 0.12"},
55 {BAD_PROT, "\2"}
57 #endif
60 /* Mark as invalid, all open files on tree connections since they
61 were closed when session to server was lost */
62 static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
64 struct cifsFileInfo *open_file = NULL;
65 struct list_head * tmp;
66 struct list_head * tmp1;
68 /* list all files open on tree connection and mark them invalid */
69 write_lock(&GlobalSMBSeslock);
70 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
71 open_file = list_entry(tmp,struct cifsFileInfo, tlist);
72 if(open_file) {
73 open_file->invalidHandle = TRUE;
76 write_unlock(&GlobalSMBSeslock);
77 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted to this tcon */
80 static int
81 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
82 void **request_buf /* returned */ ,
83 void **response_buf /* returned */ )
85 int rc = 0;
87 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
88 check for tcp and smb session status done differently
89 for those three - in the calling routine */
90 if(tcon) {
91 if((tcon->ses) && (tcon->ses->server)){
92 struct nls_table *nls_codepage;
93 /* Give Demultiplex thread up to 10 seconds to
94 reconnect, should be greater than cifs socket
95 timeout which is 7 seconds */
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 /* on "soft" mounts we wait once */
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 } /* else "hard" mount - keep retrying until
106 process is killed or server comes back up */
107 } else /* TCP session is reestablished now */
108 break;
112 nls_codepage = load_nls_default();
113 /* need to prevent multiple threads trying to
114 simultaneously reconnect the same SMB session */
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);
126 cFYI(1, ("reconnect tcon rc = %d", rc));
127 /* Removed call to reopen open files here -
128 it is safer (and faster) to reopen files
129 one at a time as needed in read and write */
131 /* Check if handle based operation so we
132 know whether we can continue or not without
133 returning to caller to reset file handle */
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;
144 } else {
145 up(&tcon->ses->sesSem);
147 unload_nls(nls_codepage);
149 } else {
150 return -EIO;
153 if(rc)
154 return rc;
156 *request_buf = cifs_buf_get();
157 if (*request_buf == 0) {
158 /* BB should we add a retry in here if not a writepage? */
159 return -ENOMEM;
161 /* Although the original thought was we needed the response buf for */
162 /* potential retries of smb operations it turns out we can determine */
163 /* from the mid flags when the request buffer can be resent without */
164 /* having to use a second distinct buffer for the response */
165 *response_buf = *request_buf;
167 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
168 wct /*wct */ );
170 #ifdef CONFIG_CIFS_STATS
171 if(tcon != NULL) {
172 atomic_inc(&tcon->num_smbs_sent);
174 #endif
175 return rc;
179 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
181 NEGOTIATE_REQ *pSMB;
182 NEGOTIATE_RSP *pSMBr;
183 int rc = 0;
184 int bytes_returned;
185 struct TCP_Server_Info * server;
186 u16 count;
188 if(ses->server)
189 server = ses->server;
190 else {
191 rc = -EIO;
192 return rc;
194 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
195 (void **) &pSMB, (void **) &pSMBr);
196 if (rc)
197 return rc;
199 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
200 if (extended_security)
201 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
203 count = strlen(protocols[0].name) + 1;
204 strncpy(pSMB->DialectsArray, protocols[0].name, 30);
205 /* null guaranteed to be at end of source and target buffers anyway */
207 pSMB->hdr.smb_buf_length += count;
208 pSMB->ByteCount = cpu_to_le16(count);
210 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
211 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
212 if (rc == 0) {
213 server->secMode = pSMBr->SecurityMode;
214 server->secType = NTLM; /* BB override default for NTLMv2 or krb*/
215 /* one byte - no need to convert this or EncryptionKeyLen from le,*/
216 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
217 /* probably no need to store and check maxvcs */
218 server->maxBuf =
219 min(le32_to_cpu(pSMBr->MaxBufferSize),
220 (__u32) CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE);
221 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
222 cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
223 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
224 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
225 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
226 /* BB with UTC do we ever need to be using srvr timezone? */
227 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
228 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
229 CIFS_CRYPTO_KEY_SIZE);
230 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
231 && (pSMBr->EncryptionKeyLength == 0)) {
232 /* decode security blob */
233 } else
234 rc = -EIO;
236 /* BB might be helpful to save off the domain of server here */
238 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
239 (server->capabilities & CAP_EXTENDED_SECURITY)) {
240 count = pSMBr->ByteCount;
241 if (count < 16)
242 rc = -EIO;
243 else if (count == 16) {
244 server->secType = RawNTLMSSP;
245 if (server->socketUseCount.counter > 1) {
246 if (memcmp
247 (server->server_GUID,
248 pSMBr->u.extended_response.
249 GUID, 16) != 0) {
250 cFYI(1,
251 ("UID of server does not match previous connection to same ip address"));
252 memcpy(server->
253 server_GUID,
254 pSMBr->u.
255 extended_response.
256 GUID, 16);
258 } else
259 memcpy(server->server_GUID,
260 pSMBr->u.extended_response.
261 GUID, 16);
262 } else {
263 rc = decode_negTokenInit(pSMBr->u.
264 extended_response.
265 SecurityBlob,
266 count - 16,
267 &server->secType);
269 } else
270 server->capabilities &= ~CAP_EXTENDED_SECURITY;
271 if(sign_CIFS_PDUs == FALSE) {
272 if(server->secMode & SECMODE_SIGN_REQUIRED)
273 cERROR(1,
274 ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
275 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
276 } else if(sign_CIFS_PDUs == 1) {
277 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
278 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
282 if (pSMB)
283 cifs_buf_release(pSMB);
284 return rc;
288 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
290 struct smb_hdr *smb_buffer;
291 struct smb_hdr *smb_buffer_response;
292 int rc = 0;
293 int length;
295 cFYI(1, ("In tree disconnect"));
297 * If last user of the connection and
298 * connection alive - disconnect it
299 * If this is the last connection on the server session disconnect it
300 * (and inside session disconnect we should check if tcp socket needs
301 * to be freed and kernel thread woken up).
303 if (tcon)
304 down(&tcon->tconSem);
305 else
306 return -EIO;
308 atomic_dec(&tcon->useCount);
309 if (atomic_read(&tcon->useCount) > 0) {
310 up(&tcon->tconSem);
311 return -EBUSY;
314 /* No need to return error on this operation if tid invalidated and
315 closed on server already e.g. due to tcp session crashing */
316 if(tcon->tidStatus == CifsNeedReconnect) {
317 up(&tcon->tconSem);
318 return 0;
321 if((tcon->ses == 0) || (tcon->ses->server == 0)) {
322 up(&tcon->tconSem);
323 return -EIO;
326 rc = smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
327 (void **) &smb_buffer, (void **) &smb_buffer_response);
328 if (rc) {
329 up(&tcon->tconSem);
330 return rc;
332 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
333 &length, 0);
334 if (rc)
335 cFYI(1, (" Tree disconnect failed %d", rc));
337 if (smb_buffer)
338 cifs_buf_release(smb_buffer);
339 up(&tcon->tconSem);
341 /* No need to return error on this operation if tid invalidated and
342 closed on server already e.g. due to tcp session crashing */
343 if (rc == -EAGAIN)
344 rc = 0;
346 return rc;
350 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
352 struct smb_hdr *smb_buffer_response;
353 LOGOFF_ANDX_REQ *pSMB;
354 int rc = 0;
355 int length;
357 cFYI(1, ("In SMBLogoff for session disconnect"));
358 if (ses)
359 down(&ses->sesSem);
360 else
361 return -EIO;
363 atomic_dec(&ses->inUse);
364 if (atomic_read(&ses->inUse) > 0) {
365 up(&ses->sesSem);
366 return -EBUSY;
369 rc = smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL /* no tcon anymore */,
370 (void **) &pSMB, (void **) &smb_buffer_response);
372 if(ses->server) {
373 if(ses->server->secMode &
374 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
375 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
378 if (rc) {
379 up(&ses->sesSem);
380 return rc;
383 pSMB->hdr.Uid = ses->Suid;
385 pSMB->AndXCommand = 0xFF;
386 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
387 smb_buffer_response, &length, 0);
388 if (ses->server) {
389 atomic_dec(&ses->server->socketUseCount);
390 if (atomic_read(&ses->server->socketUseCount) == 0) {
391 spin_lock(&GlobalMid_Lock);
392 ses->server->tcpStatus = CifsExiting;
393 spin_unlock(&GlobalMid_Lock);
394 rc = -ESHUTDOWN;
397 if (pSMB)
398 cifs_buf_release(pSMB);
399 up(&ses->sesSem);
401 /* if session dead then we do not need to do ulogoff,
402 since server closed smb session, no sense reporting
403 error */
404 if (rc == -EAGAIN)
405 rc = 0;
406 return rc;
410 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
411 const char *fileName, const struct nls_table *nls_codepage)
413 DELETE_FILE_REQ *pSMB = NULL;
414 DELETE_FILE_RSP *pSMBr = NULL;
415 int rc = 0;
416 int bytes_returned;
417 int name_len;
419 DelFileRetry:
420 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
421 (void **) &pSMBr);
422 if (rc)
423 return rc;
425 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
426 name_len =
427 cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, 530
428 /* find define for this maxpathcomponent */
429 , nls_codepage);
430 name_len++; /* trailing null */
431 name_len *= 2;
432 } else { /* BB improve the check for buffer overruns BB */
433 name_len = strnlen(fileName, 530);
434 name_len++; /* trailing null */
435 strncpy(pSMB->fileName, fileName, name_len);
437 pSMB->SearchAttributes =
438 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
439 pSMB->BufferFormat = 0x04;
440 pSMB->hdr.smb_buf_length += name_len + 1;
441 pSMB->ByteCount = cpu_to_le16(name_len + 1);
442 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
443 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
444 if (rc) {
445 cFYI(1, ("Error in RMFile = %d", rc));
447 #ifdef CONFIG_CIFS_STATS
448 else {
449 atomic_inc(&tcon->num_deletes);
451 #endif
453 if (pSMB)
454 cifs_buf_release(pSMB);
455 if (rc == -EAGAIN)
456 goto DelFileRetry;
458 return rc;
462 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
463 const char *dirName, const struct nls_table *nls_codepage)
465 DELETE_DIRECTORY_REQ *pSMB = NULL;
466 DELETE_DIRECTORY_RSP *pSMBr = NULL;
467 int rc = 0;
468 int bytes_returned;
469 int name_len;
471 cFYI(1, ("In CIFSSMBRmDir"));
472 RmDirRetry:
473 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
474 (void **) &pSMBr);
475 if (rc)
476 return rc;
478 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
479 name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, 530
480 /* find define for this maxpathcomponent */
481 , nls_codepage);
482 name_len++; /* trailing null */
483 name_len *= 2;
484 } else { /* BB improve the check for buffer overruns BB */
485 name_len = strnlen(dirName, 530);
486 name_len++; /* trailing null */
487 strncpy(pSMB->DirName, dirName, name_len);
490 pSMB->BufferFormat = 0x04;
491 pSMB->hdr.smb_buf_length += name_len + 1;
492 pSMB->ByteCount = cpu_to_le16(name_len + 1);
493 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
494 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
495 if (rc) {
496 cFYI(1, ("Error in RMDir = %d", rc));
498 #ifdef CONFIG_CIFS_STATS
499 else {
500 atomic_inc(&tcon->num_rmdirs);
502 #endif
504 if (pSMB)
505 cifs_buf_release(pSMB);
506 if (rc == -EAGAIN)
507 goto RmDirRetry;
508 return rc;
512 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
513 const char *name, const struct nls_table *nls_codepage)
515 int rc = 0;
516 CREATE_DIRECTORY_REQ *pSMB = NULL;
517 CREATE_DIRECTORY_RSP *pSMBr = NULL;
518 int bytes_returned;
519 int name_len;
521 cFYI(1, ("In CIFSSMBMkDir"));
522 MkDirRetry:
523 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
524 (void **) &pSMBr);
525 if (rc)
526 return rc;
528 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
529 name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, 530
530 /* find define for this maxpathcomponent */
531 , nls_codepage);
532 name_len++; /* trailing null */
533 name_len *= 2;
534 } else { /* BB improve the check for buffer overruns BB */
535 name_len = strnlen(name, 530);
536 name_len++; /* trailing null */
537 strncpy(pSMB->DirName, name, name_len);
540 pSMB->BufferFormat = 0x04;
541 pSMB->hdr.smb_buf_length += name_len + 1;
542 pSMB->ByteCount = cpu_to_le16(name_len + 1);
543 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
544 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
545 if (rc) {
546 cFYI(1, ("Error in Mkdir = %d", rc));
548 #ifdef CONFIG_CIFS_STATS
549 else {
550 atomic_inc(&tcon->num_mkdirs);
552 #endif
553 if (pSMB)
554 cifs_buf_release(pSMB);
555 if (rc == -EAGAIN)
556 goto MkDirRetry;
557 return rc;
561 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
562 const char *fileName, const int openDisposition,
563 const int access_flags, const int create_options, __u16 * netfid,
564 int *pOplock, FILE_ALL_INFO * pfile_info,
565 const struct nls_table *nls_codepage)
567 int rc = -EACCES;
568 OPEN_REQ *pSMB = NULL;
569 OPEN_RSP *pSMBr = NULL;
570 int bytes_returned;
571 int name_len;
572 __u16 count;
574 openRetry:
575 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
576 (void **) &pSMBr);
577 if (rc)
578 return rc;
580 pSMB->AndXCommand = 0xFF; /* none */
582 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
583 count = 1; /* account for one byte pad to word boundary */
584 name_len =
585 cifs_strtoUCS((wchar_t *) (pSMB->fileName + 1),
586 fileName, 530
587 /* find define for this maxpathcomponent */
588 , nls_codepage);
589 name_len++; /* trailing null */
590 name_len *= 2;
591 pSMB->NameLength = cpu_to_le16(name_len);
592 } else { /* BB improve the check for buffer overruns BB */
593 count = 0; /* no pad */
594 name_len = strnlen(fileName, 530);
595 name_len++; /* trailing null */
596 pSMB->NameLength = cpu_to_le16(name_len);
597 strncpy(pSMB->fileName, fileName, name_len);
599 if (*pOplock & REQ_OPLOCK)
600 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
601 else if (*pOplock & REQ_BATCHOPLOCK) {
602 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
604 pSMB->DesiredAccess = cpu_to_le32(access_flags);
605 pSMB->AllocationSize = 0;
606 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
607 /* XP does not handle ATTR_POSIX_SEMANTICS */
608 /* but it helps speed up case sensitive checks for other
609 servers such as Samba */
610 if (tcon->ses->capabilities & CAP_UNIX)
611 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
613 /* if ((omode & S_IWUGO) == 0)
614 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
615 /* Above line causes problems due to vfs splitting create into two
616 pieces - need to set mode after file created not while it is
617 being created */
618 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
619 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
620 pSMB->CreateOptions = cpu_to_le32(create_options);
621 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); /* BB ??*/
622 pSMB->SecurityFlags =
623 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
625 count += name_len;
626 pSMB->hdr.smb_buf_length += count;
628 pSMB->ByteCount = cpu_to_le16(count);
629 /* long_op set to 1 to allow for oplock break timeouts */
630 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
631 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
632 if (rc) {
633 cFYI(1, ("Error in Open = %d", rc));
634 } else {
635 *pOplock = pSMBr->OplockLevel; /* one byte no need to le_to_cpu */
636 *netfid = pSMBr->Fid; /* cifs fid stays in le */
637 /* Let caller know file was created so we can set the mode. */
638 /* Do we care about the CreateAction in any other cases? */
639 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
640 *pOplock |= CIFS_CREATE_ACTION;
641 if(pfile_info) {
642 memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
643 36 /* CreationTime to Attributes */);
644 /* the file_info buf is endian converted by caller */
645 pfile_info->AllocationSize = pSMBr->AllocationSize;
646 pfile_info->EndOfFile = pSMBr->EndOfFile;
647 pfile_info->NumberOfLinks = cpu_to_le32(1);
650 #ifdef CONFIG_CIFS_STATS
651 atomic_inc(&tcon->num_opens);
652 #endif
654 if (pSMB)
655 cifs_buf_release(pSMB);
656 if (rc == -EAGAIN)
657 goto openRetry;
658 return rc;
661 /* If no buffer passed in, then caller wants to do the copy
662 as in the case of readpages so the SMB buffer must be
663 freed by the caller */
666 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
667 const int netfid, const unsigned int count,
668 const __u64 lseek, unsigned int *nbytes, char **buf)
670 int rc = -EACCES;
671 READ_REQ *pSMB = NULL;
672 READ_RSP *pSMBr = NULL;
673 char *pReadData = NULL;
674 int bytes_returned;
676 *nbytes = 0;
677 rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
678 (void **) &pSMBr);
679 if (rc)
680 return rc;
682 /* tcon and ses pointer are checked in smb_init */
683 if (tcon->ses->server == NULL)
684 return -ECONNABORTED;
686 pSMB->AndXCommand = 0xFF; /* none */
687 pSMB->Fid = netfid;
688 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
689 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
690 pSMB->Remaining = 0;
691 pSMB->MaxCount = cpu_to_le16(count);
692 pSMB->MaxCountHigh = 0;
693 pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */
695 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
696 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
697 if (rc) {
698 cERROR(1, ("Send error in read = %d", rc));
699 } else {
700 __u16 data_length = le16_to_cpu(pSMBr->DataLength);
701 *nbytes = data_length;
702 /*check that DataLength would not go beyond end of SMB */
703 if ((data_length > CIFS_MAX_MSGSIZE)
704 || (data_length > count)) {
705 cFYI(1,("bad length %d for count %d",data_length,count));
706 rc = -EIO;
707 *nbytes = 0;
708 } else {
709 pReadData =
710 (char *) (&pSMBr->hdr.Protocol) +
711 le16_to_cpu(pSMBr->DataOffset);
712 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
713 cERROR(1,("Faulting on read rc = %d",rc));
714 rc = -EFAULT;
715 }*/ /* can not use copy_to_user when using page cache*/
716 if(*buf)
717 memcpy(*buf,pReadData,data_length);
720 if (pSMB) {
721 if(*buf)
722 cifs_buf_release(pSMB);
723 else
724 *buf = (char *)pSMB;
727 /* Note: On -EAGAIN error only caller can retry on handle based calls
728 since file handle passed in no longer valid */
729 return rc;
733 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
734 const int netfid, const unsigned int count,
735 const __u64 offset, unsigned int *nbytes, const char *buf,
736 const int long_op)
738 int rc = -EACCES;
739 WRITE_REQ *pSMB = NULL;
740 WRITE_RSP *pSMBr = NULL;
741 int bytes_returned;
742 unsigned bytes_sent;
743 __u16 byte_count;
745 rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
746 (void **) &pSMBr);
747 if (rc)
748 return rc;
749 /* tcon and ses pointer are checked in smb_init */
750 if (tcon->ses->server == NULL)
751 return -ECONNABORTED;
753 pSMB->AndXCommand = 0xFF; /* none */
754 pSMB->Fid = netfid;
755 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
756 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
757 pSMB->Remaining = 0;
758 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF;
759 if (bytes_sent > count)
760 bytes_sent = count;
761 pSMB->DataLengthHigh = 0;
762 pSMB->DataOffset =
763 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
765 memcpy(pSMB->Data,buf,bytes_sent);
767 byte_count = bytes_sent + 1 /* pad */ ;
768 pSMB->DataLengthLow = cpu_to_le16(bytes_sent);
769 pSMB->DataLengthHigh = 0;
770 pSMB->hdr.smb_buf_length += byte_count;
771 pSMB->ByteCount = cpu_to_le16(byte_count);
773 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
774 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
775 if (rc) {
776 cFYI(1, ("Send error in write = %d", rc));
777 *nbytes = 0;
778 } else
779 *nbytes = le16_to_cpu(pSMBr->Count);
781 if (pSMB)
782 cifs_buf_release(pSMB);
784 /* Note: On -EAGAIN error only caller can retry on handle based calls
785 since file handle passed in no longer valid */
787 return rc;
791 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
792 const __u16 smb_file_id, const __u64 len,
793 const __u64 offset, const __u32 numUnlock,
794 const __u32 numLock, const __u8 lockType, const int waitFlag)
796 int rc = 0;
797 LOCK_REQ *pSMB = NULL;
798 LOCK_RSP *pSMBr = NULL;
799 int bytes_returned;
800 int timeout = 0;
801 __u16 count;
803 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
804 rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB,
805 (void **) &pSMBr);
806 if (rc)
807 return rc;
809 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
810 timeout = -1; /* no response expected */
811 pSMB->Timeout = 0;
812 } else if (waitFlag == TRUE) {
813 timeout = 3; /* blocking operation, no timeout */
814 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
815 } else {
816 pSMB->Timeout = 0;
819 pSMB->NumberOfLocks = cpu_to_le16(numLock);
820 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
821 pSMB->LockType = lockType;
822 pSMB->AndXCommand = 0xFF; /* none */
823 pSMB->Fid = smb_file_id; /* netfid stays le */
825 if((numLock != 0) || (numUnlock != 0)) {
826 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
827 /* BB where to store pid high? */
828 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
829 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
830 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
831 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
832 count = sizeof(LOCKING_ANDX_RANGE);
833 } else {
834 /* oplock break */
835 count = 0;
837 pSMB->hdr.smb_buf_length += count;
838 pSMB->ByteCount = cpu_to_le16(count);
840 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
841 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
843 if (rc) {
844 cFYI(1, ("Send error in Lock = %d", rc));
846 if (pSMB)
847 cifs_buf_release(pSMB);
849 /* Note: On -EAGAIN error only caller can retry on handle based calls
850 since file handle passed in no longer valid */
851 return rc;
855 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
857 int rc = 0;
858 CLOSE_REQ *pSMB = NULL;
859 CLOSE_RSP *pSMBr = NULL;
860 int bytes_returned;
861 cFYI(1, ("In CIFSSMBClose"));
863 /* do not retry on dead session on close */
864 rc = smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB,
865 (void **) &pSMBr);
866 if(rc == -EAGAIN)
867 return 0;
868 if (rc)
869 return rc;
871 pSMB->FileID = (__u16) smb_file_id;
872 pSMB->LastWriteTime = 0;
873 pSMB->ByteCount = 0;
874 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
875 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
876 if (rc) {
877 if(rc!=-EINTR) {
878 /* EINTR is expected when user ctl-c to kill app */
879 cERROR(1, ("Send error in Close = %d", rc));
882 if (pSMB)
883 cifs_buf_release(pSMB);
885 /* Since session is dead, file will be closed on server already */
886 if(rc == -EAGAIN)
887 rc = 0;
889 return rc;
893 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
894 const char *fromName, const char *toName,
895 const struct nls_table *nls_codepage)
897 int rc = 0;
898 RENAME_REQ *pSMB = NULL;
899 RENAME_RSP *pSMBr = NULL;
900 int bytes_returned;
901 int name_len, name_len2;
902 __u16 count;
904 cFYI(1, ("In CIFSSMBRename"));
905 renameRetry:
906 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
907 (void **) &pSMBr);
908 if (rc)
909 return rc;
911 pSMB->BufferFormat = 0x04;
912 pSMB->SearchAttributes =
913 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
914 ATTR_DIRECTORY);
916 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
917 name_len =
918 cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
919 /* find define for this maxpathcomponent */
920 , nls_codepage);
921 name_len++; /* trailing null */
922 name_len *= 2;
923 pSMB->OldFileName[name_len] = 0x04; /* pad */
924 /* protocol requires ASCII signature byte on Unicode string */
925 pSMB->OldFileName[name_len + 1] = 0x00;
926 name_len2 =
927 cifs_strtoUCS((wchar_t *) & pSMB->
928 OldFileName[name_len + 2], toName, 530,
929 nls_codepage);
930 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
931 name_len2 *= 2; /* convert to bytes */
932 } else { /* BB improve the check for buffer overruns BB */
933 name_len = strnlen(fromName, 530);
934 name_len++; /* trailing null */
935 strncpy(pSMB->OldFileName, fromName, name_len);
936 name_len2 = strnlen(toName, 530);
937 name_len2++; /* trailing null */
938 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
939 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
940 name_len2++; /* trailing null */
941 name_len2++; /* signature byte */
944 count = 1 /* 1st signature byte */ + name_len + name_len2;
945 pSMB->hdr.smb_buf_length += count;
946 pSMB->ByteCount = cpu_to_le16(count);
948 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
949 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
950 if (rc) {
951 cFYI(1, ("Send error in rename = %d", rc));
954 #ifdef CONFIG_CIFS_STATS
955 else {
956 atomic_inc(&tcon->num_renames);
958 #endif
960 if (pSMB)
961 cifs_buf_release(pSMB);
963 if (rc == -EAGAIN)
964 goto renameRetry;
966 return rc;
969 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
970 int netfid, char * target_name, const struct nls_table * nls_codepage)
972 struct smb_com_transaction2_sfi_req *pSMB = NULL;
973 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
974 struct set_file_rename * rename_info;
975 char *data_offset;
976 char dummy_string[30];
977 int rc = 0;
978 int bytes_returned = 0;
979 int len_of_str;
980 __u16 params, param_offset, offset, count, byte_count;
982 cFYI(1, ("Rename to File by handle"));
983 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
984 (void **) &pSMBr);
985 if (rc)
986 return rc;
988 params = 6;
989 pSMB->MaxSetupCount = 0;
990 pSMB->Reserved = 0;
991 pSMB->Flags = 0;
992 pSMB->Timeout = 0;
993 pSMB->Reserved2 = 0;
994 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
995 offset = param_offset + params;
997 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
998 rename_info = (struct set_file_rename *) data_offset;
999 pSMB->MaxParameterCount = cpu_to_le16(2);
1000 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1001 pSMB->SetupCount = 1;
1002 pSMB->Reserved3 = 0;
1003 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1004 byte_count = 3 /* pad */ + params;
1005 pSMB->ParameterCount = cpu_to_le16(params);
1006 pSMB->TotalParameterCount = pSMB->ParameterCount;
1007 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1008 pSMB->DataOffset = cpu_to_le16(offset);
1009 /* construct random name ".cifs_tmp<inodenum><mid>" */
1010 rename_info->overwrite = cpu_to_le32(1);
1011 rename_info->root_fid = 0;
1012 /* unicode only call */
1013 if(target_name == NULL) {
1014 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1015 len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, dummy_string, 24, nls_codepage);
1016 } else {
1017 len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, 530, nls_codepage);
1019 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1020 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1021 byte_count += count;
1022 pSMB->DataCount = cpu_to_le16(count);
1023 pSMB->TotalDataCount = pSMB->DataCount;
1024 pSMB->Fid = netfid;
1025 pSMB->InformationLevel =
1026 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1027 pSMB->Reserved4 = 0;
1028 pSMB->hdr.smb_buf_length += byte_count;
1029 pSMB->ByteCount = cpu_to_le16(byte_count);
1030 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1031 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1032 if (rc) {
1033 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1035 #ifdef CONFIG_CIFS_STATS
1036 else {
1037 atomic_inc(&pTcon->num_t2renames);
1039 #endif
1040 if (pSMB)
1041 cifs_buf_release(pSMB);
1043 /* Note: On -EAGAIN error only caller can retry on handle based calls
1044 since file handle passed in no longer valid */
1046 return rc;
1050 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1051 const __u16 target_tid, const char *toName, const int flags,
1052 const struct nls_table *nls_codepage)
1054 int rc = 0;
1055 COPY_REQ *pSMB = NULL;
1056 COPY_RSP *pSMBr = NULL;
1057 int bytes_returned;
1058 int name_len, name_len2;
1059 __u16 count;
1061 cFYI(1, ("In CIFSSMBCopy"));
1062 copyRetry:
1063 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1064 (void **) &pSMBr);
1065 if (rc)
1066 return rc;
1068 pSMB->BufferFormat = 0x04;
1069 pSMB->Tid2 = target_tid;
1071 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1073 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1074 name_len = cifs_strtoUCS((wchar_t *) pSMB->OldFileName,
1075 fromName,
1076 530 /* find define for this maxpathcomponent */,
1077 nls_codepage);
1078 name_len++; /* trailing null */
1079 name_len *= 2;
1080 pSMB->OldFileName[name_len] = 0x04; /* pad */
1081 /* protocol requires ASCII signature byte on Unicode string */
1082 pSMB->OldFileName[name_len + 1] = 0x00;
1083 name_len2 = cifs_strtoUCS((wchar_t *) & pSMB->
1084 OldFileName[name_len + 2], toName, 530,
1085 nls_codepage);
1086 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1087 name_len2 *= 2; /* convert to bytes */
1088 } else { /* BB improve the check for buffer overruns BB */
1089 name_len = strnlen(fromName, 530);
1090 name_len++; /* trailing null */
1091 strncpy(pSMB->OldFileName, fromName, name_len);
1092 name_len2 = strnlen(toName, 530);
1093 name_len2++; /* trailing null */
1094 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1095 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1096 name_len2++; /* trailing null */
1097 name_len2++; /* signature byte */
1100 count = 1 /* 1st signature byte */ + name_len + name_len2;
1101 pSMB->hdr.smb_buf_length += count;
1102 pSMB->ByteCount = cpu_to_le16(count);
1104 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1105 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1106 if (rc) {
1107 cFYI(1, ("Send error in copy = %d with %d files copied",
1108 rc, le16_to_cpu(pSMBr->CopyCount)));
1110 if (pSMB)
1111 cifs_buf_release(pSMB);
1113 if (rc == -EAGAIN)
1114 goto copyRetry;
1116 return rc;
1120 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1121 const char *fromName, const char *toName,
1122 const struct nls_table *nls_codepage)
1124 TRANSACTION2_SPI_REQ *pSMB = NULL;
1125 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1126 char *data_offset;
1127 int name_len;
1128 int name_len_target;
1129 int rc = 0;
1130 int bytes_returned = 0;
1131 __u16 params, param_offset, offset, byte_count;
1133 cFYI(1, ("In Symlink Unix style"));
1134 createSymLinkRetry:
1135 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1136 (void **) &pSMBr);
1137 if (rc)
1138 return rc;
1140 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1141 name_len =
1142 cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, 530
1143 /* find define for this maxpathcomponent */
1144 , nls_codepage);
1145 name_len++; /* trailing null */
1146 name_len *= 2;
1148 } else { /* BB improve the check for buffer overruns BB */
1149 name_len = strnlen(fromName, 530);
1150 name_len++; /* trailing null */
1151 strncpy(pSMB->FileName, fromName, name_len);
1153 params = 6 + name_len;
1154 pSMB->MaxSetupCount = 0;
1155 pSMB->Reserved = 0;
1156 pSMB->Flags = 0;
1157 pSMB->Timeout = 0;
1158 pSMB->Reserved2 = 0;
1159 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1160 InformationLevel) - 4;
1161 offset = param_offset + params;
1163 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1164 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1165 name_len_target =
1166 cifs_strtoUCS((wchar_t *) data_offset, toName, 530
1167 /* find define for this maxpathcomponent */
1168 , nls_codepage);
1169 name_len_target++; /* trailing null */
1170 name_len_target *= 2;
1171 } else { /* BB improve the check for buffer overruns BB */
1172 name_len_target = strnlen(toName, 530);
1173 name_len_target++; /* trailing null */
1174 strncpy(data_offset, toName, name_len_target);
1177 pSMB->MaxParameterCount = cpu_to_le16(2);
1178 /* BB find exact max on data count below from sess */
1179 pSMB->MaxDataCount = cpu_to_le16(1000);
1180 pSMB->SetupCount = 1;
1181 pSMB->Reserved3 = 0;
1182 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1183 byte_count = 3 /* pad */ + params + name_len_target;
1184 pSMB->DataCount = cpu_to_le16(name_len_target);
1185 pSMB->ParameterCount = cpu_to_le16(params);
1186 pSMB->TotalDataCount = pSMB->DataCount;
1187 pSMB->TotalParameterCount = pSMB->ParameterCount;
1188 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1189 pSMB->DataOffset = cpu_to_le16(offset);
1190 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1191 pSMB->Reserved4 = 0;
1192 pSMB->hdr.smb_buf_length += byte_count;
1193 pSMB->ByteCount = cpu_to_le16(byte_count);
1194 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1195 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1196 if (rc) {
1197 cFYI(1,
1198 ("Send error in SetPathInfo (create symlink) = %d",
1199 rc));
1202 if (pSMB)
1203 cifs_buf_release(pSMB);
1205 if (rc == -EAGAIN)
1206 goto createSymLinkRetry;
1208 return rc;
1212 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1213 const char *fromName, const char *toName,
1214 const struct nls_table *nls_codepage)
1216 TRANSACTION2_SPI_REQ *pSMB = NULL;
1217 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1218 char *data_offset;
1219 int name_len;
1220 int name_len_target;
1221 int rc = 0;
1222 int bytes_returned = 0;
1223 __u16 params, param_offset, offset, byte_count;
1225 cFYI(1, ("In Create Hard link Unix style"));
1226 createHardLinkRetry:
1227 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1228 (void **) &pSMBr);
1229 if (rc)
1230 return rc;
1232 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1233 name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, toName, 530
1234 /* find define for this maxpathcomponent */
1235 , nls_codepage);
1236 name_len++; /* trailing null */
1237 name_len *= 2;
1239 } else { /* BB improve the check for buffer overruns BB */
1240 name_len = strnlen(toName, 530);
1241 name_len++; /* trailing null */
1242 strncpy(pSMB->FileName, toName, name_len);
1244 params = 6 + name_len;
1245 pSMB->MaxSetupCount = 0;
1246 pSMB->Reserved = 0;
1247 pSMB->Flags = 0;
1248 pSMB->Timeout = 0;
1249 pSMB->Reserved2 = 0;
1250 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1251 InformationLevel) - 4;
1252 offset = param_offset + params;
1254 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1255 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1256 name_len_target =
1257 cifs_strtoUCS((wchar_t *) data_offset, fromName, 530
1258 /* find define for this maxpathcomponent */
1259 , nls_codepage);
1260 name_len_target++; /* trailing null */
1261 name_len_target *= 2;
1262 } else { /* BB improve the check for buffer overruns BB */
1263 name_len_target = strnlen(fromName, 530);
1264 name_len_target++; /* trailing null */
1265 strncpy(data_offset, fromName, name_len_target);
1268 pSMB->MaxParameterCount = cpu_to_le16(2);
1269 /* BB find exact max on data count below from sess*/
1270 pSMB->MaxDataCount = cpu_to_le16(1000);
1271 pSMB->SetupCount = 1;
1272 pSMB->Reserved3 = 0;
1273 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1274 byte_count = 3 /* pad */ + params + name_len_target;
1275 pSMB->ParameterCount = cpu_to_le16(params);
1276 pSMB->TotalParameterCount = pSMB->ParameterCount;
1277 pSMB->DataCount = cpu_to_le16(name_len_target);
1278 pSMB->TotalDataCount = pSMB->DataCount;
1279 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1280 pSMB->DataOffset = cpu_to_le16(offset);
1281 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
1282 pSMB->Reserved4 = 0;
1283 pSMB->hdr.smb_buf_length += byte_count;
1284 pSMB->ByteCount = cpu_to_le16(byte_count);
1285 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1286 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1287 if (rc) {
1288 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1291 if (pSMB)
1292 cifs_buf_release(pSMB);
1293 if (rc == -EAGAIN)
1294 goto createHardLinkRetry;
1296 return rc;
1300 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1301 const char *fromName, const char *toName,
1302 const struct nls_table *nls_codepage)
1304 int rc = 0;
1305 NT_RENAME_REQ *pSMB = NULL;
1306 RENAME_RSP *pSMBr = NULL;
1307 int bytes_returned;
1308 int name_len, name_len2;
1309 __u16 count;
1311 cFYI(1, ("In CIFSCreateHardLink"));
1312 winCreateHardLinkRetry:
1314 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
1315 (void **) &pSMBr);
1316 if (rc)
1317 return rc;
1319 pSMB->SearchAttributes =
1320 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1321 ATTR_DIRECTORY);
1322 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
1323 pSMB->ClusterCount = 0;
1325 pSMB->BufferFormat = 0x04;
1327 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1328 name_len =
1329 cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
1330 /* find define for this maxpathcomponent */
1331 , nls_codepage);
1332 name_len++; /* trailing null */
1333 name_len *= 2;
1334 pSMB->OldFileName[name_len] = 0; /* pad */
1335 pSMB->OldFileName[name_len + 1] = 0x04;
1336 name_len2 =
1337 cifs_strtoUCS((wchar_t *) & pSMB->
1338 OldFileName[name_len + 2], toName, 530,
1339 nls_codepage);
1340 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1341 name_len2 *= 2; /* convert to bytes */
1342 } else { /* BB improve the check for buffer overruns BB */
1343 name_len = strnlen(fromName, 530);
1344 name_len++; /* trailing null */
1345 strncpy(pSMB->OldFileName, fromName, name_len);
1346 name_len2 = strnlen(toName, 530);
1347 name_len2++; /* trailing null */
1348 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1349 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1350 name_len2++; /* trailing null */
1351 name_len2++; /* signature byte */
1354 count = 1 /* string type byte */ + name_len + name_len2;
1355 pSMB->hdr.smb_buf_length += count;
1356 pSMB->ByteCount = cpu_to_le16(count);
1358 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1359 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1360 if (rc) {
1361 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1363 if (pSMB)
1364 cifs_buf_release(pSMB);
1365 if (rc == -EAGAIN)
1366 goto winCreateHardLinkRetry;
1368 return rc;
1372 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
1373 const unsigned char *searchName,
1374 char *symlinkinfo, const int buflen,
1375 const struct nls_table *nls_codepage)
1377 /* SMB_QUERY_FILE_UNIX_LINK */
1378 TRANSACTION2_QPI_REQ *pSMB = NULL;
1379 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1380 int rc = 0;
1381 int bytes_returned;
1382 int name_len;
1383 __u16 params, byte_count;
1385 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
1387 querySymLinkRetry:
1388 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1389 (void **) &pSMBr);
1390 if (rc)
1391 return rc;
1393 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1394 name_len =
1395 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1396 /* find define for this maxpathcomponent */
1397 , nls_codepage);
1398 name_len++; /* trailing null */
1399 name_len *= 2;
1400 } else { /* BB improve the check for buffer overruns BB */
1401 name_len = strnlen(searchName, 530);
1402 name_len++; /* trailing null */
1403 strncpy(pSMB->FileName, searchName, name_len);
1406 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
1407 pSMB->TotalDataCount = 0;
1408 pSMB->MaxParameterCount = cpu_to_le16(2);
1409 /* BB find exact max data count below from sess structure BB */
1410 pSMB->MaxDataCount = cpu_to_le16(4000);
1411 pSMB->MaxSetupCount = 0;
1412 pSMB->Reserved = 0;
1413 pSMB->Flags = 0;
1414 pSMB->Timeout = 0;
1415 pSMB->Reserved2 = 0;
1416 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1417 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1418 pSMB->DataCount = 0;
1419 pSMB->DataOffset = 0;
1420 pSMB->SetupCount = 1;
1421 pSMB->Reserved3 = 0;
1422 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1423 byte_count = params + 1 /* pad */ ;
1424 pSMB->TotalParameterCount = cpu_to_le16(params);
1425 pSMB->ParameterCount = pSMB->TotalParameterCount;
1426 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
1427 pSMB->Reserved4 = 0;
1428 pSMB->hdr.smb_buf_length += byte_count;
1429 pSMB->ByteCount = cpu_to_le16(byte_count);
1431 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1432 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1433 if (rc) {
1434 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
1435 } else { /* decode response */
1436 __u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
1437 __u16 count = le16_to_cpu(pSMBr->DataCount);
1438 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
1439 /* BB also check enough total bytes returned */
1440 rc = -EIO; /* bad smb */
1441 else {
1442 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1443 name_len = UniStrnlen((wchar_t *) ((char *)
1444 &pSMBr->hdr.Protocol +data_offset),
1445 min_t(const int, buflen,count) / 2);
1446 cifs_strfromUCS_le(symlinkinfo,
1447 (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
1448 data_offset),
1449 name_len, nls_codepage);
1450 } else {
1451 strncpy(symlinkinfo,
1452 (char *) &pSMBr->hdr.Protocol +
1453 data_offset,
1454 min_t(const int, buflen, count));
1456 symlinkinfo[buflen] = 0;
1457 /* just in case so calling code does not go off the end of buffer */
1460 if (pSMB)
1461 cifs_buf_release(pSMB);
1462 if (rc == -EAGAIN)
1463 goto querySymLinkRetry;
1464 return rc;
1470 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1471 const unsigned char *searchName,
1472 char *symlinkinfo, const int buflen,__u16 fid,
1473 const struct nls_table *nls_codepage)
1475 int rc = 0;
1476 int bytes_returned;
1477 int name_len;
1478 struct smb_com_transaction_ioctl_req * pSMB;
1479 struct smb_com_transaction_ioctl_rsp * pSMBr;
1481 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
1482 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
1483 (void **) &pSMBr);
1484 if (rc)
1485 return rc;
1487 pSMB->TotalParameterCount = 0 ;
1488 pSMB->TotalDataCount = 0;
1489 pSMB->MaxParameterCount = cpu_to_le32(2);
1490 /* BB find exact data count max from sess structure BB */
1491 pSMB->MaxDataCount = cpu_to_le32(4000);
1492 pSMB->MaxSetupCount = 4;
1493 pSMB->Reserved = 0;
1494 pSMB->ParameterOffset = 0;
1495 pSMB->DataCount = 0;
1496 pSMB->DataOffset = 0;
1497 pSMB->SetupCount = 4;
1498 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
1499 pSMB->ParameterCount = pSMB->TotalParameterCount;
1500 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
1501 pSMB->IsFsctl = 1; /* FSCTL */
1502 pSMB->IsRootFlag = 0;
1503 pSMB->Fid = fid; /* file handle always le */
1504 pSMB->ByteCount = 0;
1506 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1507 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1508 if (rc) {
1509 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
1510 } else { /* decode response */
1511 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
1512 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
1513 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
1514 /* BB also check enough total bytes returned */
1515 rc = -EIO; /* bad smb */
1516 else {
1517 if(data_count && (data_count < 2048)) {
1518 /* could also validate reparse tag && better check name length */
1519 struct reparse_data * reparse_buf = (struct reparse_data *)
1520 ((char *)&pSMBr->hdr.Protocol + data_offset);
1521 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1522 name_len = UniStrnlen((wchar_t *)
1523 (reparse_buf->LinkNamesBuf +
1524 reparse_buf->TargetNameOffset),
1525 min(buflen/2, reparse_buf->TargetNameLen / 2));
1526 cifs_strfromUCS_le(symlinkinfo,
1527 (wchar_t *) (reparse_buf->LinkNamesBuf +
1528 reparse_buf->TargetNameOffset),
1529 name_len, nls_codepage);
1530 } else { /* ASCII names */
1531 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
1532 reparse_buf->TargetNameOffset,
1533 min_t(const int, buflen, reparse_buf->TargetNameLen));
1535 } else {
1536 rc = -EIO;
1537 cFYI(1,("Invalid return data count on get reparse info ioctl"));
1539 symlinkinfo[buflen] = 0; /* just in case so the caller
1540 does not go off the end of the buffer */
1541 cFYI(1,("readlink result - %s ",symlinkinfo));
1544 if (pSMB)
1545 cifs_buf_release(pSMB);
1547 /* Note: On -EAGAIN error only caller can retry on handle based calls
1548 since file handle passed in no longer valid */
1550 return rc;
1554 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
1555 const unsigned char *searchName,
1556 FILE_ALL_INFO * pFindData,
1557 const struct nls_table *nls_codepage)
1559 /* level 263 SMB_QUERY_FILE_ALL_INFO */
1560 TRANSACTION2_QPI_REQ *pSMB = NULL;
1561 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1562 int rc = 0;
1563 int bytes_returned;
1564 int name_len;
1565 __u16 params, byte_count;
1567 cFYI(1, ("In QPathInfo path %s", searchName));
1568 QPathInfoRetry:
1569 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1570 (void **) &pSMBr);
1571 if (rc)
1572 return rc;
1574 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1575 name_len =
1576 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1577 /* find define for this maxpathcomponent */
1578 , nls_codepage);
1579 name_len++; /* trailing null */
1580 name_len *= 2;
1581 } else { /* BB improve the check for buffer overruns BB */
1582 name_len = strnlen(searchName, 530);
1583 name_len++; /* trailing null */
1584 strncpy(pSMB->FileName, searchName, name_len);
1587 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
1588 pSMB->TotalDataCount = 0;
1589 pSMB->MaxParameterCount = cpu_to_le16(2);
1590 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
1591 pSMB->MaxSetupCount = 0;
1592 pSMB->Reserved = 0;
1593 pSMB->Flags = 0;
1594 pSMB->Timeout = 0;
1595 pSMB->Reserved2 = 0;
1596 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1597 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1598 pSMB->DataCount = 0;
1599 pSMB->DataOffset = 0;
1600 pSMB->SetupCount = 1;
1601 pSMB->Reserved3 = 0;
1602 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1603 byte_count = params + 1 /* pad */ ;
1604 pSMB->TotalParameterCount = cpu_to_le16(params);
1605 pSMB->ParameterCount = pSMB->TotalParameterCount;
1606 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
1607 pSMB->Reserved4 = 0;
1608 pSMB->hdr.smb_buf_length += byte_count;
1609 pSMB->ByteCount = cpu_to_le16(byte_count);
1611 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1612 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1613 if (rc) {
1614 cFYI(1, ("Send error in QPathInfo = %d", rc));
1615 } else { /* decode response */
1616 __u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
1617 /* BB also check enough total bytes returned */
1618 /* BB we need to improve the validity checking
1619 of these trans2 responses */
1620 if ((pSMBr->ByteCount < 40) || (data_offset > 512))
1621 rc = -EIO; /* bad smb */
1622 else if (pFindData){
1623 memcpy((char *) pFindData,
1624 (char *) &pSMBr->hdr.Protocol +
1625 data_offset, sizeof (FILE_ALL_INFO));
1626 } else
1627 rc = -ENOMEM;
1629 if (pSMB)
1630 cifs_buf_release(pSMB);
1631 if (rc == -EAGAIN)
1632 goto QPathInfoRetry;
1634 return rc;
1638 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
1639 const unsigned char *searchName,
1640 FILE_UNIX_BASIC_INFO * pFindData,
1641 const struct nls_table *nls_codepage)
1643 /* SMB_QUERY_FILE_UNIX_BASIC */
1644 TRANSACTION2_QPI_REQ *pSMB = NULL;
1645 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1646 int rc = 0;
1647 int bytes_returned = 0;
1648 int name_len;
1649 __u16 params, byte_count;
1651 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
1652 UnixQPathInfoRetry:
1653 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1654 (void **) &pSMBr);
1655 if (rc)
1656 return rc;
1658 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1659 name_len =
1660 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1661 /* find define for this maxpathcomponent */
1662 , nls_codepage);
1663 name_len++; /* trailing null */
1664 name_len *= 2;
1665 } else { /* BB improve the check for buffer overruns BB */
1666 name_len = strnlen(searchName, 530);
1667 name_len++; /* trailing null */
1668 strncpy(pSMB->FileName, searchName, name_len);
1671 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
1672 pSMB->TotalDataCount = 0;
1673 pSMB->MaxParameterCount = cpu_to_le16(2);
1674 /* BB find exact max SMB PDU from sess structure BB */
1675 pSMB->MaxDataCount = cpu_to_le16(4000);
1676 pSMB->MaxSetupCount = 0;
1677 pSMB->Reserved = 0;
1678 pSMB->Flags = 0;
1679 pSMB->Timeout = 0;
1680 pSMB->Reserved2 = 0;
1681 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1682 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1683 pSMB->DataCount = 0;
1684 pSMB->DataOffset = 0;
1685 pSMB->SetupCount = 1;
1686 pSMB->Reserved3 = 0;
1687 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1688 byte_count = params + 1 /* pad */ ;
1689 pSMB->TotalParameterCount = cpu_to_le16(params);
1690 pSMB->ParameterCount = pSMB->TotalParameterCount;
1691 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1692 pSMB->Reserved4 = 0;
1693 pSMB->hdr.smb_buf_length += byte_count;
1694 pSMB->ByteCount = cpu_to_le16(byte_count);
1696 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1697 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1698 if (rc) {
1699 cFYI(1, ("Send error in QPathInfo = %d", rc));
1700 } else { /* decode response */
1701 __u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
1702 /* BB also check if enough total bytes returned */
1703 if ((pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO)) ||
1704 (data_offset > 512) ||
1705 (data_offset < sizeof(struct smb_hdr))) {
1706 cFYI(1,("UnixQPathinfo invalid data offset %d bytes returned %d",
1707 (int)data_offset,bytes_returned));
1708 rc = -EIO; /* bad smb */
1709 } else {
1710 memcpy((char *) pFindData,
1711 (char *) &pSMBr->hdr.Protocol +
1712 data_offset,
1713 sizeof (FILE_UNIX_BASIC_INFO));
1716 if (pSMB)
1717 cifs_buf_release(pSMB);
1718 if (rc == -EAGAIN)
1719 goto UnixQPathInfoRetry;
1721 return rc;
1725 CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
1726 const char *searchName, FILE_ALL_INFO * findData,
1727 const struct nls_table *nls_codepage)
1729 /* level 257 SMB_ */
1730 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
1731 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
1732 int rc = 0;
1733 int bytes_returned;
1734 int name_len;
1735 __u16 params, byte_count;
1737 cFYI(1, ("In FindUnique"));
1738 findUniqueRetry:
1739 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1740 (void **) &pSMBr);
1741 if (rc)
1742 return rc;
1744 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1745 name_len =
1746 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1747 /* find define for this maxpathcomponent */
1748 , nls_codepage);
1749 name_len++; /* trailing null */
1750 name_len *= 2;
1751 } else { /* BB improve the check for buffer overruns BB */
1752 name_len = strnlen(searchName, 530);
1753 name_len++; /* trailing null */
1754 strncpy(pSMB->FileName, searchName, name_len);
1757 params = 12 + name_len /* includes null */ ;
1758 pSMB->TotalDataCount = 0; /* no EAs */
1759 pSMB->MaxParameterCount = cpu_to_le16(2);
1760 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
1761 pSMB->MaxSetupCount = 0;
1762 pSMB->Reserved = 0;
1763 pSMB->Flags = 0;
1764 pSMB->Timeout = 0;
1765 pSMB->Reserved2 = 0;
1766 pSMB->ParameterOffset = cpu_to_le16(
1767 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
1768 pSMB->DataCount = 0;
1769 pSMB->DataOffset = 0;
1770 pSMB->SetupCount = 1; /* one byte, no need to le convert */
1771 pSMB->Reserved3 = 0;
1772 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
1773 byte_count = params + 1 /* pad */ ;
1774 pSMB->TotalParameterCount = cpu_to_le16(params);
1775 pSMB->ParameterCount = pSMB->TotalParameterCount;
1776 pSMB->SearchAttributes =
1777 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1778 ATTR_DIRECTORY);
1779 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
1780 pSMB->SearchFlags = cpu_to_le16(1);
1781 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
1782 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
1783 pSMB->hdr.smb_buf_length += byte_count;
1784 pSMB->ByteCount = cpu_to_le16(byte_count);
1786 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1787 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1789 if (rc) {
1790 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
1791 } else { /* decode response */
1793 /* BB fill in */
1795 if (pSMB)
1796 cifs_buf_release(pSMB);
1797 if (rc == -EAGAIN)
1798 goto findUniqueRetry;
1800 return rc;
1804 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
1805 const char *searchName, FILE_DIRECTORY_INFO * findData,
1806 T2_FFIRST_RSP_PARMS * findParms,
1807 const struct nls_table *nls_codepage, int *pUnicodeFlag,
1808 int *pUnixFlag)
1810 /* level 257 SMB_ */
1811 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
1812 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
1813 char *response_data;
1814 int rc = 0;
1815 int bytes_returned;
1816 int name_len;
1817 __u16 params, byte_count;
1819 cFYI(1, ("In FindFirst"));
1820 findFirstRetry:
1821 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1822 (void **) &pSMBr);
1823 if (rc)
1824 return rc;
1826 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1827 name_len =
1828 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1829 /* find define for this maxpathcomponent */
1830 , nls_codepage);
1831 name_len++; /* trailing null */
1832 name_len *= 2;
1833 } else { /* BB improve the check for buffer overruns BB */
1834 name_len = strnlen(searchName, 530);
1835 name_len++; /* trailing null */
1836 strncpy(pSMB->FileName, searchName, name_len);
1839 params = 12 + name_len /* includes null */ ;
1840 pSMB->TotalDataCount = 0; /* no EAs */
1841 pSMB->MaxParameterCount = cpu_to_le16(10);
1842 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
1843 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
1844 pSMB->MaxSetupCount = 0;
1845 pSMB->Reserved = 0;
1846 pSMB->Flags = 0;
1847 pSMB->Timeout = 0;
1848 pSMB->Reserved2 = 0;
1849 byte_count = params + 1 /* pad */ ;
1850 pSMB->TotalParameterCount = cpu_to_le16(params);
1851 pSMB->ParameterCount = pSMB->TotalParameterCount;
1852 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
1853 smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
1854 pSMB->DataCount = 0;
1855 pSMB->DataOffset = 0;
1856 pSMB->SetupCount = 1; /* one byte no need to make endian neutral */
1857 pSMB->Reserved3 = 0;
1858 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
1859 pSMB->SearchAttributes =
1860 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1861 ATTR_DIRECTORY);
1862 pSMB->SearchCount = cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO)); /* should this be shrunk even more ? */
1863 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
1865 /* test for Unix extensions */
1866 if (tcon->ses->capabilities & CAP_UNIX) {
1867 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
1868 *pUnixFlag = TRUE;
1869 } else {
1870 pSMB->InformationLevel =
1871 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
1872 *pUnixFlag = FALSE;
1874 pSMB->SearchStorageType = 0; /* BB what should we set this to? It is not clear if it matters BB */
1875 pSMB->hdr.smb_buf_length += byte_count;
1876 pSMB->ByteCount = cpu_to_le16(byte_count);
1878 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1879 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1881 if (rc) { /* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
1882 cFYI(1, ("Error in FindFirst = %d", rc));
1883 } else { /* decode response */
1884 /* BB add safety checks for these memcpys */
1885 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
1886 *pUnicodeFlag = TRUE;
1887 else
1888 *pUnicodeFlag = FALSE;
1889 memcpy(findParms,
1890 (char *) &pSMBr->hdr.Protocol +
1891 le16_to_cpu(pSMBr->ParameterOffset),
1892 sizeof (T2_FFIRST_RSP_PARMS));
1893 response_data =
1894 (char *) &pSMBr->hdr.Protocol +
1895 le16_to_cpu(pSMBr->DataOffset);
1896 memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
1898 if (pSMB)
1899 cifs_buf_release(pSMB);
1901 if (rc == -EAGAIN)
1902 goto findFirstRetry;
1904 return rc;
1908 CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
1909 FILE_DIRECTORY_INFO * findData, T2_FNEXT_RSP_PARMS * findParms,
1910 const __u16 searchHandle, char * resume_file_name, int name_len,
1911 __u32 resume_key, int *pUnicodeFlag, int *pUnixFlag)
1913 /* level 257 SMB_ */
1914 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
1915 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
1916 char *response_data;
1917 int rc = 0;
1918 int bytes_returned;
1919 __u16 params, byte_count;
1921 cFYI(1, ("In FindNext"));
1923 if(resume_file_name == NULL) {
1924 return -EIO;
1926 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1927 (void **) &pSMBr);
1928 if (rc)
1929 return rc;
1931 params = 14; /* includes 2 bytes of null string, converted to LE below */
1932 byte_count = 0;
1933 pSMB->TotalDataCount = 0; /* no EAs */
1934 pSMB->MaxParameterCount = cpu_to_le16(8);
1935 pSMB->MaxDataCount =
1936 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
1937 pSMB->MaxSetupCount = 0;
1938 pSMB->Reserved = 0;
1939 pSMB->Flags = 0;
1940 pSMB->Timeout = 0;
1941 pSMB->Reserved2 = 0;
1942 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1943 struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
1944 pSMB->DataCount = 0;
1945 pSMB->DataOffset = 0;
1946 pSMB->SetupCount = 1;
1947 pSMB->Reserved3 = 0;
1948 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
1949 pSMB->SearchHandle = searchHandle; /* always kept as le */
1950 findParms->SearchCount = 0; /* set to zero in case of error */
1951 pSMB->SearchCount =
1952 cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO));
1953 /* test for Unix extensions */
1954 if (tcon->ses->capabilities & CAP_UNIX) {
1955 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
1956 *pUnixFlag = TRUE;
1957 } else {
1958 pSMB->InformationLevel =
1959 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
1960 *pUnixFlag = FALSE;
1962 pSMB->ResumeKey = resume_key;
1963 pSMB->SearchFlags =
1964 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
1965 /* BB add check to make sure we do not cross end of smb */
1966 if(name_len < CIFS_MAX_MSGSIZE) {
1967 memcpy(pSMB->ResumeFileName, resume_file_name, name_len);
1968 byte_count += name_len;
1970 params += name_len;
1971 byte_count = params + 1 /* pad */ ;
1972 pSMB->TotalParameterCount = cpu_to_le16(params);
1973 pSMB->ParameterCount = pSMB->TotalParameterCount;
1974 /* BB improve error handling here */
1975 pSMB->hdr.smb_buf_length += byte_count;
1976 pSMB->ByteCount = cpu_to_le16(byte_count);
1978 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1979 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1981 if (rc) {
1982 if (rc == -EBADF)
1983 rc = 0; /* search probably was closed at end of search above */
1984 else
1985 cFYI(1, ("FindNext returned = %d", rc));
1986 } else { /* decode response */
1987 /* BB add safety checks for these memcpys */
1988 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
1989 *pUnicodeFlag = TRUE;
1990 else
1991 *pUnicodeFlag = FALSE;
1992 memcpy(findParms,
1993 (char *) &pSMBr->hdr.Protocol +
1994 le16_to_cpu(pSMBr->ParameterOffset),
1995 sizeof (T2_FNEXT_RSP_PARMS));
1996 response_data =
1997 (char *) &pSMBr->hdr.Protocol +
1998 le16_to_cpu(pSMBr->DataOffset);
1999 memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
2001 if (pSMB)
2002 cifs_buf_release(pSMB);
2004 /* Note: On -EAGAIN error only caller can retry on handle based calls
2005 since file handle passed in no longer valid */
2007 return rc;
2011 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
2013 int rc = 0;
2014 FINDCLOSE_REQ *pSMB = NULL;
2015 CLOSE_RSP *pSMBr = NULL;
2016 int bytes_returned;
2018 cFYI(1, ("In CIFSSMBFindClose"));
2019 rc = smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **) &pSMB,
2020 (void **) &pSMBr);
2021 /* no sense returning error if session restarted
2022 file handle has been closed */
2023 if(rc == -EAGAIN)
2024 return 0;
2025 if (rc)
2026 return rc;
2028 pSMB->FileID = searchHandle;
2029 pSMB->ByteCount = 0;
2030 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2031 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2032 if (rc) {
2033 cERROR(1, ("Send error in FindClose = %d", rc));
2035 if (pSMB)
2036 cifs_buf_release(pSMB);
2038 /* Since session is dead, search handle closed on server already */
2039 if (rc == -EAGAIN)
2040 rc = 0;
2042 return rc;
2046 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
2047 const unsigned char *searchName,
2048 unsigned char **targetUNCs,
2049 unsigned int *number_of_UNC_in_array,
2050 const struct nls_table *nls_codepage)
2052 /* TRANS2_GET_DFS_REFERRAL */
2053 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
2054 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
2055 struct dfs_referral_level_3 * referrals = NULL;
2056 int rc = 0;
2057 int bytes_returned;
2058 int name_len;
2059 unsigned int i;
2060 char * temp;
2061 __u16 params, byte_count;
2062 *number_of_UNC_in_array = 0;
2063 *targetUNCs = NULL;
2065 cFYI(1, ("In GetDFSRefer the path %s", searchName));
2066 if (ses == NULL)
2067 return -ENODEV;
2068 getDFSRetry:
2069 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
2070 (void **) &pSMBr);
2071 if (rc)
2072 return rc;
2074 pSMB->hdr.Tid = ses->ipc_tid;
2075 pSMB->hdr.Uid = ses->Suid;
2076 if (ses->capabilities & CAP_STATUS32) {
2077 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
2079 if (ses->capabilities & CAP_DFS) {
2080 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
2083 if (ses->capabilities & CAP_UNICODE) {
2084 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
2085 name_len =
2086 cifs_strtoUCS((wchar_t *) pSMB->RequestFileName,
2087 searchName, 530
2088 /* find define for this maxpathcomponent */
2089 , nls_codepage);
2090 name_len++; /* trailing null */
2091 name_len *= 2;
2092 } else { /* BB improve the check for buffer overruns BB */
2093 name_len = strnlen(searchName, 530);
2094 name_len++; /* trailing null */
2095 strncpy(pSMB->RequestFileName, searchName, name_len);
2098 params = 2 /* level */ + name_len /*includes null */ ;
2099 pSMB->TotalDataCount = 0;
2100 pSMB->DataCount = 0;
2101 pSMB->DataOffset = 0;
2102 pSMB->MaxParameterCount = 0;
2103 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2104 pSMB->MaxSetupCount = 0;
2105 pSMB->Reserved = 0;
2106 pSMB->Flags = 0;
2107 pSMB->Timeout = 0;
2108 pSMB->Reserved2 = 0;
2109 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2110 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
2111 pSMB->SetupCount = 1;
2112 pSMB->Reserved3 = 0;
2113 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
2114 byte_count = params + 3 /* pad */ ;
2115 pSMB->ParameterCount = cpu_to_le16(params);
2116 pSMB->TotalParameterCount = pSMB->ParameterCount;
2117 pSMB->MaxReferralLevel = cpu_to_le16(3);
2118 pSMB->hdr.smb_buf_length += byte_count;
2119 pSMB->ByteCount = cpu_to_le16(byte_count);
2121 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
2122 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2123 if (rc) {
2124 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
2125 } else { /* decode response */
2126 /* BB Add logic to parse referrals here */
2127 __u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
2128 __u16 data_count = le16_to_cpu(pSMBr->DataCount);
2129 cFYI(1,
2130 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
2131 pSMBr->ByteCount, data_offset));
2132 if ((pSMBr->ByteCount < 17) || (data_offset > 512)) /* BB also check enough total bytes returned */
2133 rc = -EIO; /* bad smb */
2134 else {
2135 referrals =
2136 (struct dfs_referral_level_3 *)
2137 (8 /* sizeof start of data block */ +
2138 data_offset +
2139 (char *) &pSMBr->hdr.Protocol);
2140 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",
2141 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)));
2142 /* BB This field is actually two bytes in from start of
2143 data block so we could do safety check that DataBlock
2144 begins at address of pSMBr->NumberOfReferrals */
2145 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
2147 /* BB Fix below so can return more than one referral */
2148 if(*number_of_UNC_in_array > 1)
2149 *number_of_UNC_in_array = 1;
2151 /* get the length of the strings describing refs */
2152 name_len = 0;
2153 for(i=0;i<*number_of_UNC_in_array;i++) {
2154 /* make sure that DfsPathOffset not past end */
2155 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
2156 if (offset > data_count) {
2157 /* if invalid referral, stop here and do
2158 not try to copy any more */
2159 *number_of_UNC_in_array = i;
2160 break;
2162 temp = ((char *)referrals) + offset;
2164 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2165 name_len += UniStrnlen((wchar_t *)temp,data_count);
2166 } else {
2167 name_len += strnlen(temp,data_count);
2169 referrals++;
2170 /* BB add check that referral pointer does not fall off end PDU */
2173 /* BB add check for name_len bigger than bcc */
2174 *targetUNCs =
2175 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
2176 if(*targetUNCs == NULL) {
2177 rc = -ENOMEM;
2178 goto GetDFSRefExit;
2180 /* copy the ref strings */
2181 referrals =
2182 (struct dfs_referral_level_3 *)
2183 (8 /* sizeof data hdr */ +
2184 data_offset +
2185 (char *) &pSMBr->hdr.Protocol);
2187 for(i=0;i<*number_of_UNC_in_array;i++) {
2188 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
2189 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2190 cifs_strfromUCS_le(*targetUNCs,
2191 (wchar_t *) temp, name_len, nls_codepage);
2192 } else {
2193 strncpy(*targetUNCs,temp,name_len);
2195 /* BB update target_uncs pointers */
2196 referrals++;
2198 temp = *targetUNCs;
2199 temp[name_len] = 0;
2203 GetDFSRefExit:
2204 if (pSMB)
2205 cifs_buf_release(pSMB);
2207 if (rc == -EAGAIN)
2208 goto getDFSRetry;
2210 return rc;
2214 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
2215 struct kstatfs *FSData, const struct nls_table *nls_codepage)
2217 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
2218 TRANSACTION2_QFSI_REQ *pSMB = NULL;
2219 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
2220 FILE_SYSTEM_INFO *response_data;
2221 int rc = 0;
2222 int bytes_returned = 0;
2223 __u16 params, byte_count;
2225 cFYI(1, ("In QFSInfo"));
2226 QFSInfoRetry:
2227 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2228 (void **) &pSMBr);
2229 if (rc)
2230 return rc;
2232 params = 2; /* level */
2233 pSMB->TotalDataCount = 0;
2234 pSMB->MaxParameterCount = cpu_to_le16(2);
2235 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2236 pSMB->MaxSetupCount = 0;
2237 pSMB->Reserved = 0;
2238 pSMB->Flags = 0;
2239 pSMB->Timeout = 0;
2240 pSMB->Reserved2 = 0;
2241 byte_count = params + 1 /* pad */ ;
2242 pSMB->TotalParameterCount = cpu_to_le16(params);
2243 pSMB->ParameterCount = pSMB->TotalParameterCount;
2244 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2245 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
2246 pSMB->DataCount = 0;
2247 pSMB->DataOffset = 0;
2248 pSMB->SetupCount = 1;
2249 pSMB->Reserved3 = 0;
2250 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
2251 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
2252 pSMB->hdr.smb_buf_length += byte_count;
2253 pSMB->ByteCount = cpu_to_le16(byte_count);
2255 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2256 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2257 if (rc) {
2258 cERROR(1, ("Send error in QFSInfo = %d", rc));
2259 } else { /* decode response */
2260 __u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
2261 cFYI(1,
2262 ("Decoding qfsinfo response. BCC: %d Offset %d",
2263 pSMBr->ByteCount, data_offset));
2264 if ((pSMBr->ByteCount < 24) || (data_offset > 512)) /* BB also check enough total bytes returned */
2265 rc = -EIO; /* bad smb */
2266 else {
2267 response_data =
2268 (FILE_SYSTEM_INFO
2269 *) (((char *) &pSMBr->hdr.Protocol) +
2270 data_offset);
2271 FSData->f_bsize =
2272 le32_to_cpu(response_data->BytesPerSector) *
2273 le32_to_cpu(response_data->
2274 SectorsPerAllocationUnit);
2275 FSData->f_blocks =
2276 le64_to_cpu(response_data->TotalAllocationUnits);
2277 FSData->f_bfree = FSData->f_bavail =
2278 le64_to_cpu(response_data->FreeAllocationUnits);
2279 cFYI(1,
2280 ("Blocks: %lld Free: %lld Block size %ld",
2281 (unsigned long long)FSData->f_blocks,
2282 (unsigned long long)FSData->f_bfree,
2283 FSData->f_bsize));
2286 if (pSMB)
2287 cifs_buf_release(pSMB);
2289 if (rc == -EAGAIN)
2290 goto QFSInfoRetry;
2292 return rc;
2296 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon,
2297 const struct nls_table *nls_codepage)
2299 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
2300 TRANSACTION2_QFSI_REQ *pSMB = NULL;
2301 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
2302 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
2303 int rc = 0;
2304 int bytes_returned = 0;
2305 __u16 params, byte_count;
2307 cFYI(1, ("In QFSAttributeInfo"));
2308 QFSAttributeRetry:
2309 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2310 (void **) &pSMBr);
2311 if (rc)
2312 return rc;
2314 params = 2; /* level */
2315 pSMB->TotalDataCount = 0;
2316 pSMB->MaxParameterCount = cpu_to_le16(2);
2317 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2318 pSMB->MaxSetupCount = 0;
2319 pSMB->Reserved = 0;
2320 pSMB->Flags = 0;
2321 pSMB->Timeout = 0;
2322 pSMB->Reserved2 = 0;
2323 byte_count = params + 1 /* pad */ ;
2324 pSMB->TotalParameterCount = cpu_to_le16(params);
2325 pSMB->ParameterCount = pSMB->TotalParameterCount;
2326 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2327 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
2328 pSMB->DataCount = 0;
2329 pSMB->DataOffset = 0;
2330 pSMB->SetupCount = 1;
2331 pSMB->Reserved3 = 0;
2332 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
2333 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
2334 pSMB->hdr.smb_buf_length += byte_count;
2335 pSMB->ByteCount = cpu_to_le16(byte_count);
2337 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2338 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2339 if (rc) {
2340 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
2341 } else { /* decode response */
2342 __u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
2343 if ((pSMBr->ByteCount < 13) || (data_offset > 512)) { /* BB also check enough bytes returned */
2344 rc = -EIO; /* bad smb */
2345 } else {
2346 response_data =
2347 (FILE_SYSTEM_ATTRIBUTE_INFO
2348 *) (((char *) &pSMBr->hdr.Protocol) +
2349 data_offset);
2350 memcpy(&tcon->fsAttrInfo, response_data,
2351 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
2354 if (pSMB)
2355 cifs_buf_release(pSMB);
2357 if (rc == -EAGAIN)
2358 goto QFSAttributeRetry;
2360 return rc;
2364 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon,
2365 const struct nls_table *nls_codepage)
2367 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
2368 TRANSACTION2_QFSI_REQ *pSMB = NULL;
2369 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
2370 FILE_SYSTEM_DEVICE_INFO *response_data;
2371 int rc = 0;
2372 int bytes_returned = 0;
2373 __u16 params, byte_count;
2375 cFYI(1, ("In QFSDeviceInfo"));
2376 QFSDeviceRetry:
2377 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2378 (void **) &pSMBr);
2379 if (rc)
2380 return rc;
2382 params = 2; /* level */
2383 pSMB->TotalDataCount = 0;
2384 pSMB->MaxParameterCount = cpu_to_le16(2);
2385 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2386 pSMB->MaxSetupCount = 0;
2387 pSMB->Reserved = 0;
2388 pSMB->Flags = 0;
2389 pSMB->Timeout = 0;
2390 pSMB->Reserved2 = 0;
2391 byte_count = params + 1 /* pad */ ;
2392 pSMB->TotalParameterCount = cpu_to_le16(params);
2393 pSMB->ParameterCount = pSMB->TotalParameterCount;
2394 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2395 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
2397 pSMB->DataCount = 0;
2398 pSMB->DataOffset = 0;
2399 pSMB->SetupCount = 1;
2400 pSMB->Reserved3 = 0;
2401 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
2402 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
2403 pSMB->hdr.smb_buf_length += byte_count;
2404 pSMB->ByteCount = cpu_to_le16(byte_count);
2406 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2407 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2408 if (rc) {
2409 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
2410 } else { /* decode response */
2411 __u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
2412 if ((pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO))
2413 || (data_offset > 512))
2414 rc = -EIO; /* bad smb */
2415 else {
2416 response_data =
2417 (FILE_SYSTEM_DEVICE_INFO
2418 *) (((char *) &pSMBr->hdr.Protocol) +
2419 data_offset);
2420 memcpy(&tcon->fsDevInfo, response_data,
2421 sizeof (FILE_SYSTEM_DEVICE_INFO));
2424 if (pSMB)
2425 cifs_buf_release(pSMB);
2427 if (rc == -EAGAIN)
2428 goto QFSDeviceRetry;
2430 return rc;
2434 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
2435 const struct nls_table *nls_codepage)
2437 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
2438 TRANSACTION2_QFSI_REQ *pSMB = NULL;
2439 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
2440 FILE_SYSTEM_UNIX_INFO *response_data;
2441 int rc = 0;
2442 int bytes_returned = 0;
2443 __u16 params, byte_count;
2445 cFYI(1, ("In QFSUnixInfo"));
2446 QFSUnixRetry:
2447 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2448 (void **) &pSMBr);
2449 if (rc)
2450 return rc;
2452 params = 2; /* level */
2453 pSMB->TotalDataCount = 0;
2454 pSMB->DataCount = 0;
2455 pSMB->DataOffset = 0;
2456 pSMB->MaxParameterCount = cpu_to_le16(2);
2457 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
2458 pSMB->MaxSetupCount = 0;
2459 pSMB->Reserved = 0;
2460 pSMB->Flags = 0;
2461 pSMB->Timeout = 0;
2462 pSMB->Reserved2 = 0;
2463 byte_count = params + 1 /* pad */ ;
2464 pSMB->ParameterCount = cpu_to_le16(params);
2465 pSMB->TotalParameterCount = pSMB->ParameterCount;
2466 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
2467 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
2468 pSMB->SetupCount = 1;
2469 pSMB->Reserved3 = 0;
2470 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
2471 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
2472 pSMB->hdr.smb_buf_length += byte_count;
2473 pSMB->ByteCount = cpu_to_le16(byte_count);
2475 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2476 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2477 if (rc) {
2478 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
2479 } else { /* decode response */
2480 __u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
2481 if ((pSMBr->ByteCount < 13) || (data_offset > 512)) {
2482 rc = -EIO; /* bad smb */
2483 } else {
2484 response_data =
2485 (FILE_SYSTEM_UNIX_INFO
2486 *) (((char *) &pSMBr->hdr.Protocol) +
2487 data_offset);
2488 memcpy(&tcon->fsUnixInfo, response_data,
2489 sizeof (FILE_SYSTEM_UNIX_INFO));
2492 if (pSMB)
2493 cifs_buf_release(pSMB);
2495 if (rc == -EAGAIN)
2496 goto QFSUnixRetry;
2499 return rc;
2502 /* We can not use write of zero bytes trick to
2503 set file size due to need for large file support. Also note that
2504 this SetPathInfo is preferred to SetFileInfo based method in next
2505 routine which is only needed to work around a sharing violation bug
2506 in Samba which this routine can run into */
2509 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
2510 __u64 size, int SetAllocation, const struct nls_table *nls_codepage)
2512 struct smb_com_transaction2_spi_req *pSMB = NULL;
2513 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2514 struct file_end_of_file_info *parm_data;
2515 int name_len;
2516 int rc = 0;
2517 int bytes_returned = 0;
2518 __u16 params, byte_count, data_count, param_offset, offset;
2520 cFYI(1, ("In SetEOF"));
2521 SetEOFRetry:
2522 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2523 (void **) &pSMBr);
2524 if (rc)
2525 return rc;
2527 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2528 name_len =
2529 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
2530 /* find define for this maxpathcomponent */
2531 , nls_codepage);
2532 name_len++; /* trailing null */
2533 name_len *= 2;
2534 } else { /* BB improve the check for buffer overruns BB */
2535 name_len = strnlen(fileName, 530);
2536 name_len++; /* trailing null */
2537 strncpy(pSMB->FileName, fileName, name_len);
2539 params = 6 + name_len;
2540 data_count = sizeof (struct file_end_of_file_info);
2541 pSMB->MaxParameterCount = cpu_to_le16(2);
2542 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2543 pSMB->MaxSetupCount = 0;
2544 pSMB->Reserved = 0;
2545 pSMB->Flags = 0;
2546 pSMB->Timeout = 0;
2547 pSMB->Reserved2 = 0;
2548 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2549 InformationLevel) - 4;
2550 offset = param_offset + params;
2551 if(SetAllocation) {
2552 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2553 pSMB->InformationLevel =
2554 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
2555 else
2556 pSMB->InformationLevel =
2557 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
2558 } else /* Set File Size */ {
2559 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2560 pSMB->InformationLevel =
2561 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
2562 else
2563 pSMB->InformationLevel =
2564 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
2567 parm_data =
2568 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
2569 offset);
2570 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2571 pSMB->DataOffset = cpu_to_le16(offset);
2572 pSMB->SetupCount = 1;
2573 pSMB->Reserved3 = 0;
2574 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2575 byte_count = 3 /* pad */ + params + data_count;
2576 pSMB->DataCount = cpu_to_le16(data_count);
2577 pSMB->TotalDataCount = pSMB->DataCount;
2578 pSMB->ParameterCount = cpu_to_le16(params);
2579 pSMB->TotalParameterCount = pSMB->ParameterCount;
2580 pSMB->Reserved4 = 0;
2581 pSMB->hdr.smb_buf_length += byte_count;
2582 parm_data->FileSize = cpu_to_le64(size);
2583 pSMB->ByteCount = cpu_to_le16(byte_count);
2584 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2585 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2586 if (rc) {
2587 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
2590 if (pSMB)
2591 cifs_buf_release(pSMB);
2593 if (rc == -EAGAIN)
2594 goto SetEOFRetry;
2596 return rc;
2600 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
2601 __u16 fid, __u32 pid_of_opener, int SetAllocation)
2603 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2604 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2605 char *data_offset;
2606 struct file_end_of_file_info *parm_data;
2607 int rc = 0;
2608 int bytes_returned = 0;
2609 __u16 params, param_offset, offset, byte_count, count;
2611 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
2612 (long long)size));
2613 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2614 (void **) &pSMBr);
2615 if (rc)
2616 return rc;
2618 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
2619 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
2621 params = 6;
2622 pSMB->MaxSetupCount = 0;
2623 pSMB->Reserved = 0;
2624 pSMB->Flags = 0;
2625 pSMB->Timeout = 0;
2626 pSMB->Reserved2 = 0;
2627 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2628 offset = param_offset + params;
2630 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2632 count = sizeof(struct file_end_of_file_info);
2633 pSMB->MaxParameterCount = cpu_to_le16(2);
2634 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
2635 pSMB->SetupCount = 1;
2636 pSMB->Reserved3 = 0;
2637 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2638 byte_count = 3 /* pad */ + params + count;
2639 pSMB->DataCount = cpu_to_le16(count);
2640 pSMB->ParameterCount = cpu_to_le16(params);
2641 pSMB->TotalDataCount = pSMB->DataCount;
2642 pSMB->TotalParameterCount = pSMB->ParameterCount;
2643 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2644 parm_data =
2645 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
2646 offset);
2647 pSMB->DataOffset = cpu_to_le16(offset);
2648 parm_data->FileSize = cpu_to_le64(size);
2649 pSMB->Fid = fid;
2650 if(SetAllocation) {
2651 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2652 pSMB->InformationLevel =
2653 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
2654 else
2655 pSMB->InformationLevel =
2656 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
2657 } else /* Set File Size */ {
2658 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2659 pSMB->InformationLevel =
2660 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
2661 else
2662 pSMB->InformationLevel =
2663 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
2665 pSMB->Reserved4 = 0;
2666 pSMB->hdr.smb_buf_length += byte_count;
2667 pSMB->ByteCount = cpu_to_le16(byte_count);
2668 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2669 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2670 if (rc) {
2671 cFYI(1,
2672 ("Send error in SetFileInfo (SetFileSize) = %d",
2673 rc));
2676 if (pSMB)
2677 cifs_buf_release(pSMB);
2679 /* Note: On -EAGAIN error only caller can retry on handle based calls
2680 since file handle passed in no longer valid */
2682 return rc;
2686 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
2687 const FILE_BASIC_INFO * data,
2688 const struct nls_table *nls_codepage)
2690 TRANSACTION2_SPI_REQ *pSMB = NULL;
2691 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2692 int name_len;
2693 int rc = 0;
2694 int bytes_returned = 0;
2695 char *data_offset;
2696 __u16 params, param_offset, offset, byte_count, count;
2698 cFYI(1, ("In SetTimes"));
2700 SetTimesRetry:
2701 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2702 (void **) &pSMBr);
2703 if (rc)
2704 return rc;
2706 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2707 name_len =
2708 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
2709 /* find define for this maxpathcomponent */
2710 , nls_codepage);
2711 name_len++; /* trailing null */
2712 name_len *= 2;
2713 } else { /* BB improve the check for buffer overruns BB */
2714 name_len = strnlen(fileName, 530);
2715 name_len++; /* trailing null */
2716 strncpy(pSMB->FileName, fileName, name_len);
2719 params = 6 + name_len;
2720 count = sizeof (FILE_BASIC_INFO);
2721 pSMB->MaxParameterCount = cpu_to_le16(2);
2722 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2723 pSMB->MaxSetupCount = 0;
2724 pSMB->Reserved = 0;
2725 pSMB->Flags = 0;
2726 pSMB->Timeout = 0;
2727 pSMB->Reserved2 = 0;
2728 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2729 InformationLevel) - 4;
2730 offset = param_offset + params;
2731 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2732 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2733 pSMB->DataOffset = cpu_to_le16(offset);
2734 pSMB->SetupCount = 1;
2735 pSMB->Reserved3 = 0;
2736 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2737 byte_count = 3 /* pad */ + params + count;
2739 pSMB->DataCount = cpu_to_le16(count);
2740 pSMB->ParameterCount = cpu_to_le16(params);
2741 pSMB->TotalDataCount = pSMB->DataCount;
2742 pSMB->TotalParameterCount = pSMB->ParameterCount;
2743 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2744 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
2745 else
2746 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
2747 pSMB->Reserved4 = 0;
2748 pSMB->hdr.smb_buf_length += byte_count;
2749 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
2750 pSMB->ByteCount = cpu_to_le16(byte_count);
2751 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2752 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2753 if (rc) {
2754 cFYI(1, ("SetPathInfo (times) returned %d", rc));
2757 if (pSMB)
2758 cifs_buf_release(pSMB);
2760 if (rc == -EAGAIN)
2761 goto SetTimesRetry;
2763 return rc;
2767 CIFSSMBSetTimesLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
2768 FILE_INFO_STANDARD * data, const struct nls_table *nls_codepage)
2770 TRANSACTION2_SPI_REQ *pSMB = NULL;
2771 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2772 int name_len;
2773 int rc = 0;
2774 int bytes_returned = 0;
2775 char *data_offset;
2776 __u16 params, param_offset, count, offset, byte_count;
2778 cFYI(1, ("In SetTimesLegacy"));
2780 SetTimesRetryLegacy:
2781 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2782 (void **) &pSMBr);
2783 if (rc)
2784 return rc;
2786 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2787 name_len =
2788 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
2789 /* find define for this maxpathcomponent */
2790 , nls_codepage);
2791 name_len++; /* trailing null */
2792 name_len *= 2;
2793 } else { /* BB improve the check for buffer overruns BB */
2794 name_len = strnlen(fileName, 530);
2795 name_len++; /* trailing null */
2796 strncpy(pSMB->FileName, fileName, name_len);
2798 /* BB fixme - we have to map to FILE_STANDARD_INFO (level 1 info
2799 in parent function, from the better and ususal FILE_BASIC_INFO */
2800 params = 6 + name_len;
2801 count = sizeof (FILE_INFO_STANDARD);
2802 pSMB->MaxParameterCount = cpu_to_le16(2);
2803 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2804 pSMB->MaxSetupCount = 0;
2805 pSMB->Reserved = 0;
2806 pSMB->Flags = 0;
2807 pSMB->Timeout = 0;
2808 pSMB->Reserved2 = 0;
2809 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2810 InformationLevel) - 4;
2811 offset = param_offset + params;
2812 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2813 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2814 pSMB->DataOffset = cpu_to_le16(offset);
2815 pSMB->SetupCount = 1;
2816 pSMB->Reserved3 = 0;
2817 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2818 byte_count = 3 /* pad */ + params + count;
2820 pSMB->DataCount = cpu_to_le16(count);
2821 pSMB->ParameterCount = cpu_to_le16(params);
2822 pSMB->TotalDataCount = pSMB->DataCount;
2823 pSMB->TotalParameterCount = pSMB->ParameterCount;
2824 /* I doubt that passthrough levels apply to this old
2825 preNT info level */
2826 /* if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2827 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
2828 else*/
2829 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
2830 pSMB->Reserved4 = 0;
2831 pSMB->hdr.smb_buf_length += byte_count;
2832 memcpy(data_offset, data, sizeof (FILE_INFO_STANDARD));
2833 pSMB->ByteCount = cpu_to_le16(byte_count);
2834 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2835 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2836 if (rc) {
2837 cFYI(1, ("SetPathInfo (times legacy) returned %d", rc));
2840 if (pSMB)
2841 cifs_buf_release(pSMB);
2843 if (rc == -EAGAIN)
2844 goto SetTimesRetryLegacy;
2846 return rc;
2850 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
2851 char *fileName, __u64 mode, __u64 uid, __u64 gid,
2852 dev_t device, const struct nls_table *nls_codepage)
2854 TRANSACTION2_SPI_REQ *pSMB = NULL;
2855 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2856 int name_len;
2857 int rc = 0;
2858 int bytes_returned = 0;
2859 FILE_UNIX_BASIC_INFO *data_offset;
2860 __u16 params, param_offset, offset, count, byte_count;
2862 cFYI(1, ("In SetUID/GID/Mode"));
2863 setPermsRetry:
2864 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2865 (void **) &pSMBr);
2866 if (rc)
2867 return rc;
2869 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2870 name_len =
2871 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
2872 /* find define for this maxpathcomponent */
2873 , nls_codepage);
2874 name_len++; /* trailing null */
2875 name_len *= 2;
2876 } else { /* BB improve the check for buffer overruns BB */
2877 name_len = strnlen(fileName, 530);
2878 name_len++; /* trailing null */
2879 strncpy(pSMB->FileName, fileName, name_len);
2882 params = 6 + name_len;
2883 count = sizeof (FILE_UNIX_BASIC_INFO);
2884 pSMB->MaxParameterCount = cpu_to_le16(2);
2885 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2886 pSMB->MaxSetupCount = 0;
2887 pSMB->Reserved = 0;
2888 pSMB->Flags = 0;
2889 pSMB->Timeout = 0;
2890 pSMB->Reserved2 = 0;
2891 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2892 InformationLevel) - 4;
2893 offset = param_offset + params;
2894 data_offset =
2895 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
2896 offset);
2897 pSMB->DataOffset = cpu_to_le16(offset);
2898 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2899 pSMB->SetupCount = 1;
2900 pSMB->Reserved3 = 0;
2901 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2902 byte_count = 3 /* pad */ + params + count;
2903 pSMB->ParameterCount = cpu_to_le16(params);
2904 pSMB->DataCount = cpu_to_le16(count);
2905 pSMB->TotalParameterCount = pSMB->ParameterCount;
2906 pSMB->TotalDataCount = pSMB->DataCount;
2907 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
2908 pSMB->Reserved4 = 0;
2909 pSMB->hdr.smb_buf_length += byte_count;
2910 data_offset->Uid = cpu_to_le64(uid);
2911 data_offset->Gid = cpu_to_le64(gid);
2912 /* better to leave device as zero when it is */
2913 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
2914 data_offset->DevMinor = cpu_to_le64(MINOR(device));
2915 data_offset->Permissions = cpu_to_le64(mode);
2917 if(S_ISREG(mode))
2918 data_offset->Type = cpu_to_le32(UNIX_FILE);
2919 else if(S_ISDIR(mode))
2920 data_offset->Type = cpu_to_le32(UNIX_DIR);
2921 else if(S_ISLNK(mode))
2922 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
2923 else if(S_ISCHR(mode))
2924 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
2925 else if(S_ISBLK(mode))
2926 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
2927 else if(S_ISFIFO(mode))
2928 data_offset->Type = cpu_to_le32(UNIX_FIFO);
2929 else if(S_ISSOCK(mode))
2930 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
2933 pSMB->ByteCount = cpu_to_le16(byte_count);
2934 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2935 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2936 if (rc) {
2937 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
2940 if (pSMB)
2941 cifs_buf_release(pSMB);
2942 if (rc == -EAGAIN)
2943 goto setPermsRetry;
2944 return rc;
2947 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
2948 const int notify_subdirs, const __u16 netfid,
2949 __u32 filter, const struct nls_table *nls_codepage)
2951 int rc = 0;
2952 struct smb_com_transaction_change_notify_req * pSMB = NULL;
2953 struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
2954 int bytes_returned;
2956 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
2957 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2958 (void **) &pSMBr);
2959 if (rc)
2960 return rc;
2962 pSMB->TotalParameterCount = 0 ;
2963 pSMB->TotalDataCount = 0;
2964 pSMB->MaxParameterCount = cpu_to_le32(2);
2965 /* BB find exact data count max from sess structure BB */
2966 pSMB->MaxDataCount = 0; /* same in little endian or be */
2967 pSMB->MaxSetupCount = 4;
2968 pSMB->Reserved = 0;
2969 pSMB->ParameterOffset = 0;
2970 pSMB->DataCount = 0;
2971 pSMB->DataOffset = 0;
2972 pSMB->SetupCount = 4; /* single byte does not need le conversion */
2973 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
2974 pSMB->ParameterCount = pSMB->TotalParameterCount;
2975 if(notify_subdirs)
2976 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
2977 pSMB->Reserved2 = 0;
2978 pSMB->CompletionFilter = cpu_to_le32(filter);
2979 pSMB->Fid = netfid; /* file handle always le */
2980 pSMB->ByteCount = 0;
2982 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2983 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2984 if (rc) {
2985 cFYI(1, ("Error in Notify = %d", rc));
2987 if (pSMB)
2988 cifs_buf_release(pSMB);
2989 /* if (rc == -EAGAIN)
2990 goto NotifyRetry; */
2991 return rc;
2993 #ifdef CONFIG_CIFS_XATTR
2994 ssize_t
2995 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
2996 const unsigned char *searchName,
2997 char * EAData, size_t buf_size,
2998 const struct nls_table *nls_codepage)
3000 /* BB assumes one setup word */
3001 TRANSACTION2_QPI_REQ *pSMB = NULL;
3002 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3003 int rc = 0;
3004 int bytes_returned;
3005 int name_len;
3006 struct fea * temp_fea;
3007 char * temp_ptr;
3008 __u16 params, byte_count;
3010 cFYI(1, ("In Query All EAs path %s", searchName));
3011 QAllEAsRetry:
3012 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3013 (void **) &pSMBr);
3014 if (rc)
3015 return rc;
3017 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3018 name_len =
3019 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
3020 /* find define for this maxpathcomponent */
3021 , nls_codepage);
3022 name_len++; /* trailing null */
3023 name_len *= 2;
3024 } else { /* BB improve the check for buffer overruns BB */
3025 name_len = strnlen(searchName, 530);
3026 name_len++; /* trailing null */
3027 strncpy(pSMB->FileName, searchName, name_len);
3030 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
3031 pSMB->TotalDataCount = 0;
3032 pSMB->MaxParameterCount = cpu_to_le16(2);
3033 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3034 pSMB->MaxSetupCount = 0;
3035 pSMB->Reserved = 0;
3036 pSMB->Flags = 0;
3037 pSMB->Timeout = 0;
3038 pSMB->Reserved2 = 0;
3039 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3040 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3041 pSMB->DataCount = 0;
3042 pSMB->DataOffset = 0;
3043 pSMB->SetupCount = 1;
3044 pSMB->Reserved3 = 0;
3045 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3046 byte_count = params + 1 /* pad */ ;
3047 pSMB->TotalParameterCount = cpu_to_le16(params);
3048 pSMB->ParameterCount = pSMB->TotalParameterCount;
3049 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
3050 pSMB->Reserved4 = 0;
3051 pSMB->hdr.smb_buf_length += byte_count;
3052 pSMB->ByteCount = cpu_to_le16(byte_count);
3054 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3055 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3056 if (rc) {
3057 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
3058 } else { /* decode response */
3059 __u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
3060 /* BB also check enough total bytes returned */
3061 /* BB we need to improve the validity checking
3062 of these trans2 responses */
3063 if ((pSMBr->ByteCount < 4) || (data_offset > 512))
3064 rc = -EIO; /* bad smb */
3065 /* else if (pFindData){
3066 memcpy((char *) pFindData,
3067 (char *) &pSMBr->hdr.Protocol +
3068 data_offset, kl);
3069 }*/ else {
3070 /* check that length of list is not more than bcc */
3071 /* check that each entry does not go beyond length
3072 of list */
3073 /* check that each element of each entry does not
3074 go beyond end of list */
3075 struct fealist * ea_response_data;
3076 rc = 0;
3077 /* validate_trans2_offsets() */
3078 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
3079 ea_response_data = (struct fealist *)
3080 (((char *) &pSMBr->hdr.Protocol) +
3081 data_offset);
3082 name_len = le32_to_cpu(ea_response_data->list_len);
3083 cFYI(1,("ea length %d", name_len));
3084 if(name_len <= 8) {
3085 /* returned EA size zeroed at top of function */
3086 cFYI(1,("empty EA list returned from server"));
3087 } else {
3088 /* account for ea list len */
3089 name_len -= 4;
3090 temp_fea = ea_response_data->list;
3091 temp_ptr = (char *)temp_fea;
3092 while(name_len > 0) {
3093 __u16 value_len;
3094 name_len -= 4;
3095 temp_ptr += 4;
3096 rc += temp_fea->name_len;
3097 /* account for prefix user. and trailing null */
3098 rc = rc + 5 + 1;
3099 if(rc<(int)buf_size) {
3100 memcpy(EAData,"user.",5);
3101 EAData+=5;
3102 memcpy(EAData,temp_ptr,temp_fea->name_len);
3103 EAData+=temp_fea->name_len;
3104 /* null terminate name */
3105 *EAData = 0;
3106 EAData = EAData + 1;
3107 } else if(buf_size == 0) {
3108 /* skip copy - calc size only */
3109 } else {
3110 /* stop before overrun buffer */
3111 rc = -ERANGE;
3112 break;
3114 name_len -= temp_fea->name_len;
3115 temp_ptr += temp_fea->name_len;
3116 /* account for trailing null */
3117 name_len--;
3118 temp_ptr++;
3119 value_len = le16_to_cpu(temp_fea->value_len);
3120 name_len -= value_len;
3121 temp_ptr += value_len;
3122 /* BB check that temp_ptr is still within smb BB*/
3123 /* no trailing null to account for in value len */
3124 /* go on to next EA */
3125 temp_fea = (struct fea *)temp_ptr;
3130 if (pSMB)
3131 cifs_buf_release(pSMB);
3132 if (rc == -EAGAIN)
3133 goto QAllEAsRetry;
3135 return (ssize_t)rc;
3138 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
3139 const unsigned char * searchName,const unsigned char * ea_name,
3140 unsigned char * ea_value, size_t buf_size,
3141 const struct nls_table *nls_codepage)
3143 TRANSACTION2_QPI_REQ *pSMB = NULL;
3144 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3145 int rc = 0;
3146 int bytes_returned;
3147 int name_len;
3148 struct fea * temp_fea;
3149 char * temp_ptr;
3150 __u16 params, byte_count;
3152 cFYI(1, ("In Query EA path %s", searchName));
3153 QEARetry:
3154 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3155 (void **) &pSMBr);
3156 if (rc)
3157 return rc;
3159 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3160 name_len =
3161 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
3162 /* find define for this maxpathcomponent */
3163 , nls_codepage);
3164 name_len++; /* trailing null */
3165 name_len *= 2;
3166 } else { /* BB improve the check for buffer overruns BB */
3167 name_len = strnlen(searchName, 530);
3168 name_len++; /* trailing null */
3169 strncpy(pSMB->FileName, searchName, name_len);
3172 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
3173 pSMB->TotalDataCount = 0;
3174 pSMB->MaxParameterCount = cpu_to_le16(2);
3175 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3176 pSMB->MaxSetupCount = 0;
3177 pSMB->Reserved = 0;
3178 pSMB->Flags = 0;
3179 pSMB->Timeout = 0;
3180 pSMB->Reserved2 = 0;
3181 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3182 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3183 pSMB->DataCount = 0;
3184 pSMB->DataOffset = 0;
3185 pSMB->SetupCount = 1;
3186 pSMB->Reserved3 = 0;
3187 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3188 byte_count = params + 1 /* pad */ ;
3189 pSMB->TotalParameterCount = cpu_to_le16(params);
3190 pSMB->ParameterCount = pSMB->TotalParameterCount;
3191 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
3192 pSMB->Reserved4 = 0;
3193 pSMB->hdr.smb_buf_length += byte_count;
3194 pSMB->ByteCount = cpu_to_le16(byte_count);
3196 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3197 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3198 if (rc) {
3199 cFYI(1, ("Send error in Query EA = %d", rc));
3200 } else { /* decode response */
3201 __u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
3202 /* BB also check enough total bytes returned */
3203 /* BB we need to improve the validity checking
3204 of these trans2 responses */
3205 if ((pSMBr->ByteCount < 4) || (data_offset > 512))
3206 rc = -EIO; /* bad smb */
3207 /* else if (pFindData){
3208 memcpy((char *) pFindData,
3209 (char *) &pSMBr->hdr.Protocol +
3210 data_offset, kl);
3211 }*/ else {
3212 /* check that length of list is not more than bcc */
3213 /* check that each entry does not go beyond length
3214 of list */
3215 /* check that each element of each entry does not
3216 go beyond end of list */
3217 struct fealist * ea_response_data;
3218 rc = -ENOENT;
3219 /* validate_trans2_offsets() */
3220 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
3221 ea_response_data = (struct fealist *)
3222 (((char *) &pSMBr->hdr.Protocol) +
3223 data_offset);
3224 name_len = le32_to_cpu(ea_response_data->list_len);
3225 cFYI(1,("ea length %d", name_len));
3226 if(name_len <= 8) {
3227 /* returned EA size zeroed at top of function */
3228 cFYI(1,("empty EA list returned from server"));
3229 } else {
3230 /* account for ea list len */
3231 name_len -= 4;
3232 temp_fea = ea_response_data->list;
3233 temp_ptr = (char *)temp_fea;
3234 /* loop through checking if we have a matching
3235 name and then return the associated value */
3236 while(name_len > 0) {
3237 __u16 value_len;
3238 name_len -= 4;
3239 temp_ptr += 4;
3240 value_len = le16_to_cpu(temp_fea->value_len);
3241 /* BB validate that value_len falls within SMB,
3242 even though maximum for name_len is 255 */
3243 if(memcmp(temp_fea->name,ea_name,
3244 temp_fea->name_len) == 0) {
3245 /* found a match */
3246 rc = value_len;
3247 /* account for prefix user. and trailing null */
3248 if(rc<=(int)buf_size) {
3249 memcpy(ea_value,
3250 temp_fea->name+temp_fea->name_len+1,
3251 rc);
3252 /* ea values, unlike ea names,
3253 are not null terminated */
3254 } else if(buf_size == 0) {
3255 /* skip copy - calc size only */
3256 } else {
3257 /* stop before overrun buffer */
3258 rc = -ERANGE;
3260 break;
3262 name_len -= temp_fea->name_len;
3263 temp_ptr += temp_fea->name_len;
3264 /* account for trailing null */
3265 name_len--;
3266 temp_ptr++;
3267 name_len -= value_len;
3268 temp_ptr += value_len;
3269 /* no trailing null to account for in value len */
3270 /* go on to next EA */
3271 temp_fea = (struct fea *)temp_ptr;
3276 if (pSMB)
3277 cifs_buf_release(pSMB);
3278 if (rc == -EAGAIN)
3279 goto QEARetry;
3281 return (ssize_t)rc;
3285 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3286 const char * ea_name, const void * ea_value,
3287 const __u16 ea_value_len, const struct nls_table *nls_codepage)
3289 struct smb_com_transaction2_spi_req *pSMB = NULL;
3290 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3291 struct fealist *parm_data;
3292 int name_len;
3293 int rc = 0;
3294 int bytes_returned = 0;
3295 __u16 params, param_offset, byte_count, offset, count;
3297 cFYI(1, ("In SetEA"));
3298 SetEARetry:
3299 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3300 (void **) &pSMBr);
3301 if (rc)
3302 return rc;
3304 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3305 name_len =
3306 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
3307 /* find define for this maxpathcomponent */
3308 , nls_codepage);
3309 name_len++; /* trailing null */
3310 name_len *= 2;
3311 } else { /* BB improve the check for buffer overruns BB */
3312 name_len = strnlen(fileName, 530);
3313 name_len++; /* trailing null */
3314 strncpy(pSMB->FileName, fileName, name_len);
3317 params = 6 + name_len;
3319 /* done calculating parms using name_len of file name,
3320 now use name_len to calculate length of ea name
3321 we are going to create in the inode xattrs */
3322 if(ea_name == NULL)
3323 name_len = 0;
3324 else
3325 name_len = strnlen(ea_name,255);
3327 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
3328 pSMB->MaxParameterCount = cpu_to_le16(2);
3329 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
3330 pSMB->MaxSetupCount = 0;
3331 pSMB->Reserved = 0;
3332 pSMB->Flags = 0;
3333 pSMB->Timeout = 0;
3334 pSMB->Reserved2 = 0;
3335 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3336 InformationLevel) - 4;
3337 offset = param_offset + params;
3338 pSMB->InformationLevel =
3339 cpu_to_le16(SMB_SET_FILE_EA);
3341 parm_data =
3342 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
3343 offset);
3344 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3345 pSMB->DataOffset = cpu_to_le16(offset);
3346 pSMB->SetupCount = 1;
3347 pSMB->Reserved3 = 0;
3348 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3349 byte_count = 3 /* pad */ + params + count;
3350 pSMB->DataCount = cpu_to_le16(count);
3351 parm_data->list_len = cpu_to_le32(count);
3352 parm_data->list[0].EA_flags = 0;
3353 /* we checked above that name len is less than 255 */
3354 parm_data->list[0].name_len = (__u8)name_len;;
3355 /* EA names are always ASCII */
3356 strncpy(parm_data->list[0].name,ea_name,name_len);
3357 parm_data->list[0].name[name_len] = 0;
3358 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
3359 /* caller ensures that ea_value_len is less than 64K but
3360 we need to ensure that it fits within the smb */
3362 /*BB add length check that it would fit in negotiated SMB buffer size BB */
3363 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
3364 if(ea_value_len)
3365 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
3367 pSMB->TotalDataCount = pSMB->DataCount;
3368 pSMB->ParameterCount = cpu_to_le16(params);
3369 pSMB->TotalParameterCount = pSMB->ParameterCount;
3370 pSMB->Reserved4 = 0;
3371 pSMB->hdr.smb_buf_length += byte_count;
3372 pSMB->ByteCount = cpu_to_le16(byte_count);
3373 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3374 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3375 if (rc) {
3376 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
3379 if (pSMB)
3380 cifs_buf_release(pSMB);
3382 if (rc == -EAGAIN)
3383 goto SetEARetry;
3385 return rc;
3388 #endif