]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - fs/cifs/cifssmb.c
[CIFS] Readpages and readir performance improvements - eliminate extra
[mirror_ubuntu-bionic-kernel.git] / fs / cifs / cifssmb.c
1 /*
2 * fs/cifs/cifssmb.c
3 *
4 * Copyright (C) International Business Machines Corp., 2002,2005
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * Contains the routines for constructing the SMB PDUs themselves
8 *
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.
13 *
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.
18 *
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
22 */
23
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 */
29
30 #include <linux/fs.h>
31 #include <linux/kernel.h>
32 #include <linux/vfs.h>
33 #include <linux/posix_acl_xattr.h>
34 #include <asm/uaccess.h>
35 #include "cifspdu.h"
36 #include "cifsglob.h"
37 #include "cifsproto.h"
38 #include "cifs_unicode.h"
39 #include "cifs_debug.h"
40
41 #ifdef CONFIG_CIFS_POSIX
42 static struct {
43 int index;
44 char *name;
45 } protocols[] = {
46 {CIFS_PROT, "\2NT LM 0.12"},
47 {CIFS_PROT, "\2POSIX 2"},
48 {BAD_PROT, "\2"}
49 };
50 #else
51 static struct {
52 int index;
53 char *name;
54 } protocols[] = {
55 {CIFS_PROT, "\2NT LM 0.12"},
56 {BAD_PROT, "\2"}
57 };
58 #endif
59
60
61 /* Mark as invalid, all open files on tree connections since they
62 were closed when session to server was lost */
63 static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
64 {
65 struct cifsFileInfo *open_file = NULL;
66 struct list_head * tmp;
67 struct list_head * tmp1;
68
69 /* list all files open on tree connection and mark them invalid */
70 write_lock(&GlobalSMBSeslock);
71 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
72 open_file = list_entry(tmp,struct cifsFileInfo, tlist);
73 if(open_file) {
74 open_file->invalidHandle = TRUE;
75 }
76 }
77 write_unlock(&GlobalSMBSeslock);
78 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
79 to this tcon */
80 }
81
82 /* If the return code is zero, this function must fill in request_buf pointer */
83 static int
84 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
85 void **request_buf /* returned */)
86 {
87 int rc = 0;
88
89 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
90 check for tcp and smb session status done differently
91 for those three - in the calling routine */
92 if(tcon) {
93 if(tcon->tidStatus == CifsExiting) {
94 /* only tree disconnect, open, and write,
95 (and ulogoff which does not have tcon)
96 are allowed as we start force umount */
97 if((smb_command != SMB_COM_WRITE_ANDX) &&
98 (smb_command != SMB_COM_OPEN_ANDX) &&
99 (smb_command != SMB_COM_TREE_DISCONNECT)) {
100 cFYI(1,("can not send cmd %d while umounting",
101 smb_command));
102 return -ENODEV;
103 }
104 }
105 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
106 (tcon->ses->server)){
107 struct nls_table *nls_codepage;
108 /* Give Demultiplex thread up to 10 seconds to
109 reconnect, should be greater than cifs socket
110 timeout which is 7 seconds */
111 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
112 wait_event_interruptible_timeout(tcon->ses->server->response_q,
113 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
114 if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
115 /* on "soft" mounts we wait once */
116 if((tcon->retry == FALSE) ||
117 (tcon->ses->status == CifsExiting)) {
118 cFYI(1,("gave up waiting on reconnect in smb_init"));
119 return -EHOSTDOWN;
120 } /* else "hard" mount - keep retrying
121 until process is killed or server
122 comes back on-line */
123 } else /* TCP session is reestablished now */
124 break;
125
126 }
127
128 nls_codepage = load_nls_default();
129 /* need to prevent multiple threads trying to
130 simultaneously reconnect the same SMB session */
131 down(&tcon->ses->sesSem);
132 if(tcon->ses->status == CifsNeedReconnect)
133 rc = cifs_setup_session(0, tcon->ses,
134 nls_codepage);
135 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
136 mark_open_files_invalid(tcon);
137 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon
138 , nls_codepage);
139 up(&tcon->ses->sesSem);
140 /* BB FIXME add code to check if wsize needs
141 update due to negotiated smb buffer size
142 shrinking */
143 if(rc == 0)
144 atomic_inc(&tconInfoReconnectCount);
145
146 cFYI(1, ("reconnect tcon rc = %d", rc));
147 /* Removed call to reopen open files here -
148 it is safer (and faster) to reopen files
149 one at a time as needed in read and write */
150
151 /* Check if handle based operation so we
152 know whether we can continue or not without
153 returning to caller to reset file handle */
154 switch(smb_command) {
155 case SMB_COM_READ_ANDX:
156 case SMB_COM_WRITE_ANDX:
157 case SMB_COM_CLOSE:
158 case SMB_COM_FIND_CLOSE2:
159 case SMB_COM_LOCKING_ANDX: {
160 unload_nls(nls_codepage);
161 return -EAGAIN;
162 }
163 }
164 } else {
165 up(&tcon->ses->sesSem);
166 }
167 unload_nls(nls_codepage);
168
169 } else {
170 return -EIO;
171 }
172 }
173 if(rc)
174 return rc;
175
176 *request_buf = cifs_small_buf_get();
177 if (*request_buf == NULL) {
178 /* BB should we add a retry in here if not a writepage? */
179 return -ENOMEM;
180 }
181
182 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
183
184 if(tcon != NULL)
185 cifs_stats_inc(&tcon->num_smbs_sent);
186
187 return rc;
188 }
189
190 /* If the return code is zero, this function must fill in request_buf pointer */
191 static int
192 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
193 void **request_buf /* returned */ ,
194 void **response_buf /* returned */ )
195 {
196 int rc = 0;
197
198 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
199 check for tcp and smb session status done differently
200 for those three - in the calling routine */
201 if(tcon) {
202 if(tcon->tidStatus == CifsExiting) {
203 /* only tree disconnect, open, and write,
204 (and ulogoff which does not have tcon)
205 are allowed as we start force umount */
206 if((smb_command != SMB_COM_WRITE_ANDX) &&
207 (smb_command != SMB_COM_OPEN_ANDX) &&
208 (smb_command != SMB_COM_TREE_DISCONNECT)) {
209 cFYI(1,("can not send cmd %d while umounting",
210 smb_command));
211 return -ENODEV;
212 }
213 }
214
215 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
216 (tcon->ses->server)){
217 struct nls_table *nls_codepage;
218 /* Give Demultiplex thread up to 10 seconds to
219 reconnect, should be greater than cifs socket
220 timeout which is 7 seconds */
221 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
222 wait_event_interruptible_timeout(tcon->ses->server->response_q,
223 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
224 if(tcon->ses->server->tcpStatus ==
225 CifsNeedReconnect) {
226 /* on "soft" mounts we wait once */
227 if((tcon->retry == FALSE) ||
228 (tcon->ses->status == CifsExiting)) {
229 cFYI(1,("gave up waiting on reconnect in smb_init"));
230 return -EHOSTDOWN;
231 } /* else "hard" mount - keep retrying
232 until process is killed or server
233 comes on-line */
234 } else /* TCP session is reestablished now */
235 break;
236
237 }
238
239 nls_codepage = load_nls_default();
240 /* need to prevent multiple threads trying to
241 simultaneously reconnect the same SMB session */
242 down(&tcon->ses->sesSem);
243 if(tcon->ses->status == CifsNeedReconnect)
244 rc = cifs_setup_session(0, tcon->ses,
245 nls_codepage);
246 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
247 mark_open_files_invalid(tcon);
248 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
249 tcon, nls_codepage);
250 up(&tcon->ses->sesSem);
251 /* BB FIXME add code to check if wsize needs
252 update due to negotiated smb buffer size
253 shrinking */
254 if(rc == 0)
255 atomic_inc(&tconInfoReconnectCount);
256
257 cFYI(1, ("reconnect tcon rc = %d", rc));
258 /* Removed call to reopen open files here -
259 it is safer (and faster) to reopen files
260 one at a time as needed in read and write */
261
262 /* Check if handle based operation so we
263 know whether we can continue or not without
264 returning to caller to reset file handle */
265 switch(smb_command) {
266 case SMB_COM_READ_ANDX:
267 case SMB_COM_WRITE_ANDX:
268 case SMB_COM_CLOSE:
269 case SMB_COM_FIND_CLOSE2:
270 case SMB_COM_LOCKING_ANDX: {
271 unload_nls(nls_codepage);
272 return -EAGAIN;
273 }
274 }
275 } else {
276 up(&tcon->ses->sesSem);
277 }
278 unload_nls(nls_codepage);
279
280 } else {
281 return -EIO;
282 }
283 }
284 if(rc)
285 return rc;
286
287 *request_buf = cifs_buf_get();
288 if (*request_buf == NULL) {
289 /* BB should we add a retry in here if not a writepage? */
290 return -ENOMEM;
291 }
292 /* Although the original thought was we needed the response buf for */
293 /* potential retries of smb operations it turns out we can determine */
294 /* from the mid flags when the request buffer can be resent without */
295 /* having to use a second distinct buffer for the response */
296 *response_buf = *request_buf;
297
298 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
299 wct /*wct */ );
300
301 if(tcon != NULL)
302 cifs_stats_inc(&tcon->num_smbs_sent);
303
304 return rc;
305 }
306
307 static int validate_t2(struct smb_t2_rsp * pSMB)
308 {
309 int rc = -EINVAL;
310 int total_size;
311 char * pBCC;
312
313 /* check for plausible wct, bcc and t2 data and parm sizes */
314 /* check for parm and data offset going beyond end of smb */
315 if(pSMB->hdr.WordCount >= 10) {
316 if((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
317 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
318 /* check that bcc is at least as big as parms + data */
319 /* check that bcc is less than negotiated smb buffer */
320 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
321 if(total_size < 512) {
322 total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
323 /* BCC le converted in SendReceive */
324 pBCC = (pSMB->hdr.WordCount * 2) +
325 sizeof(struct smb_hdr) +
326 (char *)pSMB;
327 if((total_size <= (*(u16 *)pBCC)) &&
328 (total_size <
329 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
330 return 0;
331 }
332
333 }
334 }
335 }
336 cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB,
337 sizeof(struct smb_t2_rsp) + 16);
338 return rc;
339 }
340 int
341 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
342 {
343 NEGOTIATE_REQ *pSMB;
344 NEGOTIATE_RSP *pSMBr;
345 int rc = 0;
346 int bytes_returned;
347 struct TCP_Server_Info * server;
348 u16 count;
349
350 if(ses->server)
351 server = ses->server;
352 else {
353 rc = -EIO;
354 return rc;
355 }
356 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
357 (void **) &pSMB, (void **) &pSMBr);
358 if (rc)
359 return rc;
360 pSMB->hdr.Mid = GetNextMid(server);
361 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
362 if (extended_security)
363 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
364
365 count = strlen(protocols[0].name) + 1;
366 strncpy(pSMB->DialectsArray, protocols[0].name, 30);
367 /* null guaranteed to be at end of source and target buffers anyway */
368
369 pSMB->hdr.smb_buf_length += count;
370 pSMB->ByteCount = cpu_to_le16(count);
371
372 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
373 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
374 if (rc == 0) {
375 server->secMode = pSMBr->SecurityMode;
376 server->secType = NTLM; /* BB override default for
377 NTLMv2 or kerberos v5 */
378 /* one byte - no need to convert this or EncryptionKeyLen
379 from little endian */
380 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
381 /* probably no need to store and check maxvcs */
382 server->maxBuf =
383 min(le32_to_cpu(pSMBr->MaxBufferSize),
384 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
385 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
386 cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
387 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
388 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
389 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
390 /* BB with UTC do we ever need to be using srvr timezone? */
391 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
392 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
393 CIFS_CRYPTO_KEY_SIZE);
394 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
395 && (pSMBr->EncryptionKeyLength == 0)) {
396 /* decode security blob */
397 } else
398 rc = -EIO;
399
400 /* BB might be helpful to save off the domain of server here */
401
402 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
403 (server->capabilities & CAP_EXTENDED_SECURITY)) {
404 count = pSMBr->ByteCount;
405 if (count < 16)
406 rc = -EIO;
407 else if (count == 16) {
408 server->secType = RawNTLMSSP;
409 if (server->socketUseCount.counter > 1) {
410 if (memcmp
411 (server->server_GUID,
412 pSMBr->u.extended_response.
413 GUID, 16) != 0) {
414 cFYI(1,
415 ("UID of server does not match previous connection to same ip address"));
416 memcpy(server->
417 server_GUID,
418 pSMBr->u.
419 extended_response.
420 GUID, 16);
421 }
422 } else
423 memcpy(server->server_GUID,
424 pSMBr->u.extended_response.
425 GUID, 16);
426 } else {
427 rc = decode_negTokenInit(pSMBr->u.
428 extended_response.
429 SecurityBlob,
430 count - 16,
431 &server->secType);
432 if(rc == 1) {
433 /* BB Need to fill struct for sessetup here */
434 rc = -EOPNOTSUPP;
435 } else {
436 rc = -EINVAL;
437 }
438 }
439 } else
440 server->capabilities &= ~CAP_EXTENDED_SECURITY;
441 if(sign_CIFS_PDUs == FALSE) {
442 if(server->secMode & SECMODE_SIGN_REQUIRED)
443 cERROR(1,
444 ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
445 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
446 } else if(sign_CIFS_PDUs == 1) {
447 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
448 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
449 }
450
451 }
452
453 cifs_buf_release(pSMB);
454 return rc;
455 }
456
457 int
458 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
459 {
460 struct smb_hdr *smb_buffer;
461 struct smb_hdr *smb_buffer_response; /* BB removeme BB */
462 int rc = 0;
463 int length;
464
465 cFYI(1, ("In tree disconnect"));
466 /*
467 * If last user of the connection and
468 * connection alive - disconnect it
469 * If this is the last connection on the server session disconnect it
470 * (and inside session disconnect we should check if tcp socket needs
471 * to be freed and kernel thread woken up).
472 */
473 if (tcon)
474 down(&tcon->tconSem);
475 else
476 return -EIO;
477
478 atomic_dec(&tcon->useCount);
479 if (atomic_read(&tcon->useCount) > 0) {
480 up(&tcon->tconSem);
481 return -EBUSY;
482 }
483
484 /* No need to return error on this operation if tid invalidated and
485 closed on server already e.g. due to tcp session crashing */
486 if(tcon->tidStatus == CifsNeedReconnect) {
487 up(&tcon->tconSem);
488 return 0;
489 }
490
491 if((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
492 up(&tcon->tconSem);
493 return -EIO;
494 }
495 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
496 (void **)&smb_buffer);
497 if (rc) {
498 up(&tcon->tconSem);
499 return rc;
500 } else {
501 smb_buffer_response = smb_buffer; /* BB removeme BB */
502 }
503 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
504 &length, 0);
505 if (rc)
506 cFYI(1, ("Tree disconnect failed %d", rc));
507
508 if (smb_buffer)
509 cifs_small_buf_release(smb_buffer);
510 up(&tcon->tconSem);
511
512 /* No need to return error on this operation if tid invalidated and
513 closed on server already e.g. due to tcp session crashing */
514 if (rc == -EAGAIN)
515 rc = 0;
516
517 return rc;
518 }
519
520 int
521 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
522 {
523 struct smb_hdr *smb_buffer_response;
524 LOGOFF_ANDX_REQ *pSMB;
525 int rc = 0;
526 int length;
527
528 cFYI(1, ("In SMBLogoff for session disconnect"));
529 if (ses)
530 down(&ses->sesSem);
531 else
532 return -EIO;
533
534 atomic_dec(&ses->inUse);
535 if (atomic_read(&ses->inUse) > 0) {
536 up(&ses->sesSem);
537 return -EBUSY;
538 }
539 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
540 if (rc) {
541 up(&ses->sesSem);
542 return rc;
543 }
544
545 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
546
547 if(ses->server) {
548 pSMB->hdr.Mid = GetNextMid(ses->server);
549
550 if(ses->server->secMode &
551 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
552 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
553 }
554
555 pSMB->hdr.Uid = ses->Suid;
556
557 pSMB->AndXCommand = 0xFF;
558 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
559 smb_buffer_response, &length, 0);
560 if (ses->server) {
561 atomic_dec(&ses->server->socketUseCount);
562 if (atomic_read(&ses->server->socketUseCount) == 0) {
563 spin_lock(&GlobalMid_Lock);
564 ses->server->tcpStatus = CifsExiting;
565 spin_unlock(&GlobalMid_Lock);
566 rc = -ESHUTDOWN;
567 }
568 }
569 up(&ses->sesSem);
570 cifs_small_buf_release(pSMB);
571
572 /* if session dead then we do not need to do ulogoff,
573 since server closed smb session, no sense reporting
574 error */
575 if (rc == -EAGAIN)
576 rc = 0;
577 return rc;
578 }
579
580 int
581 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
582 const struct nls_table *nls_codepage, int remap)
583 {
584 DELETE_FILE_REQ *pSMB = NULL;
585 DELETE_FILE_RSP *pSMBr = NULL;
586 int rc = 0;
587 int bytes_returned;
588 int name_len;
589
590 DelFileRetry:
591 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
592 (void **) &pSMBr);
593 if (rc)
594 return rc;
595
596 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
597 name_len =
598 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
599 PATH_MAX, nls_codepage, remap);
600 name_len++; /* trailing null */
601 name_len *= 2;
602 } else { /* BB improve check for buffer overruns BB */
603 name_len = strnlen(fileName, PATH_MAX);
604 name_len++; /* trailing null */
605 strncpy(pSMB->fileName, fileName, name_len);
606 }
607 pSMB->SearchAttributes =
608 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
609 pSMB->BufferFormat = 0x04;
610 pSMB->hdr.smb_buf_length += name_len + 1;
611 pSMB->ByteCount = cpu_to_le16(name_len + 1);
612 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
613 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
614 cifs_stats_inc(&tcon->num_deletes);
615 if (rc) {
616 cFYI(1, ("Error in RMFile = %d", rc));
617 }
618
619 cifs_buf_release(pSMB);
620 if (rc == -EAGAIN)
621 goto DelFileRetry;
622
623 return rc;
624 }
625
626 int
627 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
628 const struct nls_table *nls_codepage, int remap)
629 {
630 DELETE_DIRECTORY_REQ *pSMB = NULL;
631 DELETE_DIRECTORY_RSP *pSMBr = NULL;
632 int rc = 0;
633 int bytes_returned;
634 int name_len;
635
636 cFYI(1, ("In CIFSSMBRmDir"));
637 RmDirRetry:
638 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
639 (void **) &pSMBr);
640 if (rc)
641 return rc;
642
643 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
644 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
645 PATH_MAX, nls_codepage, remap);
646 name_len++; /* trailing null */
647 name_len *= 2;
648 } else { /* BB improve check for buffer overruns BB */
649 name_len = strnlen(dirName, PATH_MAX);
650 name_len++; /* trailing null */
651 strncpy(pSMB->DirName, dirName, name_len);
652 }
653
654 pSMB->BufferFormat = 0x04;
655 pSMB->hdr.smb_buf_length += name_len + 1;
656 pSMB->ByteCount = cpu_to_le16(name_len + 1);
657 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
658 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
659 cifs_stats_inc(&tcon->num_rmdirs);
660 if (rc) {
661 cFYI(1, ("Error in RMDir = %d", rc));
662 }
663
664 cifs_buf_release(pSMB);
665 if (rc == -EAGAIN)
666 goto RmDirRetry;
667 return rc;
668 }
669
670 int
671 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
672 const char *name, const struct nls_table *nls_codepage, int remap)
673 {
674 int rc = 0;
675 CREATE_DIRECTORY_REQ *pSMB = NULL;
676 CREATE_DIRECTORY_RSP *pSMBr = NULL;
677 int bytes_returned;
678 int name_len;
679
680 cFYI(1, ("In CIFSSMBMkDir"));
681 MkDirRetry:
682 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
683 (void **) &pSMBr);
684 if (rc)
685 return rc;
686
687 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
688 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
689 PATH_MAX, nls_codepage, remap);
690 name_len++; /* trailing null */
691 name_len *= 2;
692 } else { /* BB improve check for buffer overruns BB */
693 name_len = strnlen(name, PATH_MAX);
694 name_len++; /* trailing null */
695 strncpy(pSMB->DirName, name, name_len);
696 }
697
698 pSMB->BufferFormat = 0x04;
699 pSMB->hdr.smb_buf_length += name_len + 1;
700 pSMB->ByteCount = cpu_to_le16(name_len + 1);
701 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
702 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
703 cifs_stats_inc(&tcon->num_mkdirs);
704 if (rc) {
705 cFYI(1, ("Error in Mkdir = %d", rc));
706 }
707
708 cifs_buf_release(pSMB);
709 if (rc == -EAGAIN)
710 goto MkDirRetry;
711 return rc;
712 }
713
714 static __u16 convert_disposition(int disposition)
715 {
716 __u16 ofun = 0;
717
718 switch (disposition) {
719 case FILE_SUPERSEDE:
720 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
721 break;
722 case FILE_OPEN:
723 ofun = SMBOPEN_OAPPEND;
724 break;
725 case FILE_CREATE:
726 ofun = SMBOPEN_OCREATE;
727 break;
728 case FILE_OPEN_IF:
729 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
730 break;
731 case FILE_OVERWRITE:
732 ofun = SMBOPEN_OTRUNC;
733 break;
734 case FILE_OVERWRITE_IF:
735 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
736 break;
737 default:
738 cFYI(1,("unknown disposition %d",disposition));
739 ofun = SMBOPEN_OAPPEND; /* regular open */
740 }
741 return ofun;
742 }
743
744 int
745 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
746 const char *fileName, const int openDisposition,
747 const int access_flags, const int create_options, __u16 * netfid,
748 int *pOplock, FILE_ALL_INFO * pfile_info,
749 const struct nls_table *nls_codepage, int remap)
750 {
751 int rc = -EACCES;
752 OPENX_REQ *pSMB = NULL;
753 OPENX_RSP *pSMBr = NULL;
754 int bytes_returned;
755 int name_len;
756 __u16 count;
757
758 OldOpenRetry:
759 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
760 (void **) &pSMBr);
761 if (rc)
762 return rc;
763
764 pSMB->AndXCommand = 0xFF; /* none */
765
766 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
767 count = 1; /* account for one byte pad to word boundary */
768 name_len =
769 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
770 fileName, PATH_MAX, nls_codepage, remap);
771 name_len++; /* trailing null */
772 name_len *= 2;
773 } else { /* BB improve check for buffer overruns BB */
774 count = 0; /* no pad */
775 name_len = strnlen(fileName, PATH_MAX);
776 name_len++; /* trailing null */
777 strncpy(pSMB->fileName, fileName, name_len);
778 }
779 if (*pOplock & REQ_OPLOCK)
780 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
781 else if (*pOplock & REQ_BATCHOPLOCK) {
782 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
783 }
784 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
785 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
786 /* 0 = read
787 1 = write
788 2 = rw
789 3 = execute
790 */
791 pSMB->Mode = cpu_to_le16(2);
792 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
793 /* set file as system file if special file such
794 as fifo and server expecting SFU style and
795 no Unix extensions */
796
797 if(create_options & CREATE_OPTION_SPECIAL)
798 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
799 else
800 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
801
802 /* if ((omode & S_IWUGO) == 0)
803 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
804 /* Above line causes problems due to vfs splitting create into two
805 pieces - need to set mode after file created not while it is
806 being created */
807
808 /* BB FIXME BB */
809 /* pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); */
810 /* BB FIXME END BB */
811
812 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
813 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
814 count += name_len;
815 pSMB->hdr.smb_buf_length += count;
816
817 pSMB->ByteCount = cpu_to_le16(count);
818 /* long_op set to 1 to allow for oplock break timeouts */
819 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
820 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
821 cifs_stats_inc(&tcon->num_opens);
822 if (rc) {
823 cFYI(1, ("Error in Open = %d", rc));
824 } else {
825 /* BB verify if wct == 15 */
826
827 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
828
829 *netfid = pSMBr->Fid; /* cifs fid stays in le */
830 /* Let caller know file was created so we can set the mode. */
831 /* Do we care about the CreateAction in any other cases? */
832 /* BB FIXME BB */
833 /* if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
834 *pOplock |= CIFS_CREATE_ACTION; */
835 /* BB FIXME END */
836
837 if(pfile_info) {
838 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
839 pfile_info->LastAccessTime = 0; /* BB fixme */
840 pfile_info->LastWriteTime = 0; /* BB fixme */
841 pfile_info->ChangeTime = 0; /* BB fixme */
842 pfile_info->Attributes =
843 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
844 /* the file_info buf is endian converted by caller */
845 pfile_info->AllocationSize =
846 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
847 pfile_info->EndOfFile = pfile_info->AllocationSize;
848 pfile_info->NumberOfLinks = cpu_to_le32(1);
849 }
850 }
851
852 cifs_buf_release(pSMB);
853 if (rc == -EAGAIN)
854 goto OldOpenRetry;
855 return rc;
856 }
857
858 int
859 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
860 const char *fileName, const int openDisposition,
861 const int access_flags, const int create_options, __u16 * netfid,
862 int *pOplock, FILE_ALL_INFO * pfile_info,
863 const struct nls_table *nls_codepage, int remap)
864 {
865 int rc = -EACCES;
866 OPEN_REQ *pSMB = NULL;
867 OPEN_RSP *pSMBr = NULL;
868 int bytes_returned;
869 int name_len;
870 __u16 count;
871
872 openRetry:
873 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
874 (void **) &pSMBr);
875 if (rc)
876 return rc;
877
878 pSMB->AndXCommand = 0xFF; /* none */
879
880 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
881 count = 1; /* account for one byte pad to word boundary */
882 name_len =
883 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
884 fileName, PATH_MAX, nls_codepage, remap);
885 name_len++; /* trailing null */
886 name_len *= 2;
887 pSMB->NameLength = cpu_to_le16(name_len);
888 } else { /* BB improve check for buffer overruns BB */
889 count = 0; /* no pad */
890 name_len = strnlen(fileName, PATH_MAX);
891 name_len++; /* trailing null */
892 pSMB->NameLength = cpu_to_le16(name_len);
893 strncpy(pSMB->fileName, fileName, name_len);
894 }
895 if (*pOplock & REQ_OPLOCK)
896 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
897 else if (*pOplock & REQ_BATCHOPLOCK) {
898 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
899 }
900 pSMB->DesiredAccess = cpu_to_le32(access_flags);
901 pSMB->AllocationSize = 0;
902 /* set file as system file if special file such
903 as fifo and server expecting SFU style and
904 no Unix extensions */
905 if(create_options & CREATE_OPTION_SPECIAL)
906 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
907 else
908 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
909 /* XP does not handle ATTR_POSIX_SEMANTICS */
910 /* but it helps speed up case sensitive checks for other
911 servers such as Samba */
912 if (tcon->ses->capabilities & CAP_UNIX)
913 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
914
915 /* if ((omode & S_IWUGO) == 0)
916 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
917 /* Above line causes problems due to vfs splitting create into two
918 pieces - need to set mode after file created not while it is
919 being created */
920 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
921 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
922 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
923 /* BB Expirement with various impersonation levels and verify */
924 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
925 pSMB->SecurityFlags =
926 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
927
928 count += name_len;
929 pSMB->hdr.smb_buf_length += count;
930
931 pSMB->ByteCount = cpu_to_le16(count);
932 /* long_op set to 1 to allow for oplock break timeouts */
933 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
934 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
935 cifs_stats_inc(&tcon->num_opens);
936 if (rc) {
937 cFYI(1, ("Error in Open = %d", rc));
938 } else {
939 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
940 *netfid = pSMBr->Fid; /* cifs fid stays in le */
941 /* Let caller know file was created so we can set the mode. */
942 /* Do we care about the CreateAction in any other cases? */
943 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
944 *pOplock |= CIFS_CREATE_ACTION;
945 if(pfile_info) {
946 memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
947 36 /* CreationTime to Attributes */);
948 /* the file_info buf is endian converted by caller */
949 pfile_info->AllocationSize = pSMBr->AllocationSize;
950 pfile_info->EndOfFile = pSMBr->EndOfFile;
951 pfile_info->NumberOfLinks = cpu_to_le32(1);
952 }
953 }
954
955 cifs_buf_release(pSMB);
956 if (rc == -EAGAIN)
957 goto openRetry;
958 return rc;
959 }
960
961 /* If no buffer passed in, then caller wants to do the copy
962 as in the case of readpages so the SMB buffer must be
963 freed by the caller */
964
965 int
966 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
967 const int netfid, const unsigned int count,
968 const __u64 lseek, unsigned int *nbytes, char **buf)
969 {
970 int rc = -EACCES;
971 READ_REQ *pSMB = NULL;
972 READ_RSP *pSMBr = NULL;
973 char *pReadData = NULL;
974 int bytes_returned;
975 int wct;
976
977 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
978 if(tcon->ses->capabilities & CAP_LARGE_FILES)
979 wct = 12;
980 else
981 wct = 10; /* old style read */
982
983 *nbytes = 0;
984 rc = smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB,
985 (void **) &pSMBr);
986 if (rc)
987 return rc;
988
989 /* tcon and ses pointer are checked in smb_init */
990 if (tcon->ses->server == NULL)
991 return -ECONNABORTED;
992
993 pSMB->AndXCommand = 0xFF; /* none */
994 pSMB->Fid = netfid;
995 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
996 if(wct == 12)
997 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
998 else if((lseek >> 32) > 0) /* can not handle this big offset for old */
999 return -EIO;
1000
1001 pSMB->Remaining = 0;
1002 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1003 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1004 if(wct == 12)
1005 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1006 else {
1007 /* old style read */
1008 struct smb_com_readx_req * pSMBW =
1009 (struct smb_com_readx_req *)pSMB;
1010 pSMBW->ByteCount = 0;
1011 }
1012
1013 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1014 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1015 cifs_stats_inc(&tcon->num_reads);
1016 if (rc) {
1017 cERROR(1, ("Send error in read = %d", rc));
1018 } else {
1019 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1020 data_length = data_length << 16;
1021 data_length += le16_to_cpu(pSMBr->DataLength);
1022 *nbytes = data_length;
1023
1024 /*check that DataLength would not go beyond end of SMB */
1025 if ((data_length > CIFSMaxBufSize)
1026 || (data_length > count)) {
1027 cFYI(1,("bad length %d for count %d",data_length,count));
1028 rc = -EIO;
1029 *nbytes = 0;
1030 } else {
1031 pReadData =
1032 (char *) (&pSMBr->hdr.Protocol) +
1033 le16_to_cpu(pSMBr->DataOffset);
1034 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
1035 cERROR(1,("Faulting on read rc = %d",rc));
1036 rc = -EFAULT;
1037 }*/ /* can not use copy_to_user when using page cache*/
1038 if(*buf)
1039 memcpy(*buf,pReadData,data_length);
1040 }
1041 }
1042 if(*buf)
1043 cifs_buf_release(pSMB);
1044 else
1045 *buf = (char *)pSMB;
1046
1047 /* Note: On -EAGAIN error only caller can retry on handle based calls
1048 since file handle passed in no longer valid */
1049 return rc;
1050 }
1051
1052 int
1053 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1054 const int netfid, const unsigned int count,
1055 const __u64 offset, unsigned int *nbytes, const char *buf,
1056 const char __user * ubuf, const int long_op)
1057 {
1058 int rc = -EACCES;
1059 WRITE_REQ *pSMB = NULL;
1060 WRITE_RSP *pSMBr = NULL;
1061 int bytes_returned, wct;
1062 __u32 bytes_sent;
1063 __u16 byte_count;
1064
1065 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1066 if(tcon->ses == NULL)
1067 return -ECONNABORTED;
1068
1069 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1070 wct = 14;
1071 else
1072 wct = 12;
1073
1074 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1075 (void **) &pSMBr);
1076 if (rc)
1077 return rc;
1078 /* tcon and ses pointer are checked in smb_init */
1079 if (tcon->ses->server == NULL)
1080 return -ECONNABORTED;
1081
1082 pSMB->AndXCommand = 0xFF; /* none */
1083 pSMB->Fid = netfid;
1084 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1085 if(wct == 14)
1086 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1087 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1088 return -EIO;
1089
1090 pSMB->Reserved = 0xFFFFFFFF;
1091 pSMB->WriteMode = 0;
1092 pSMB->Remaining = 0;
1093
1094 /* Can increase buffer size if buffer is big enough in some cases - ie we
1095 can send more if LARGE_WRITE_X capability returned by the server and if
1096 our buffer is big enough or if we convert to iovecs on socket writes
1097 and eliminate the copy to the CIFS buffer */
1098 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1099 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1100 } else {
1101 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1102 & ~0xFF;
1103 }
1104
1105 if (bytes_sent > count)
1106 bytes_sent = count;
1107 pSMB->DataOffset =
1108 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1109 if(buf)
1110 memcpy(pSMB->Data,buf,bytes_sent);
1111 else if(ubuf) {
1112 if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) {
1113 cifs_buf_release(pSMB);
1114 return -EFAULT;
1115 }
1116 } else if (count != 0) {
1117 /* No buffer */
1118 cifs_buf_release(pSMB);
1119 return -EINVAL;
1120 } /* else setting file size with write of zero bytes */
1121 if(wct == 14)
1122 byte_count = bytes_sent + 1; /* pad */
1123 else /* wct == 12 */ {
1124 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1125 }
1126 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1127 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1128 pSMB->hdr.smb_buf_length += byte_count;
1129
1130 if(wct == 14)
1131 pSMB->ByteCount = cpu_to_le16(byte_count);
1132 else { /* old style write has byte count 4 bytes earlier so 4 bytes pad */
1133 struct smb_com_writex_req * pSMBW =
1134 (struct smb_com_writex_req *)pSMB;
1135 pSMBW->ByteCount = cpu_to_le16(byte_count);
1136 }
1137
1138 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1139 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1140 cifs_stats_inc(&tcon->num_writes);
1141 if (rc) {
1142 cFYI(1, ("Send error in write = %d", rc));
1143 *nbytes = 0;
1144 } else {
1145 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1146 *nbytes = (*nbytes) << 16;
1147 *nbytes += le16_to_cpu(pSMBr->Count);
1148 }
1149
1150 cifs_buf_release(pSMB);
1151
1152 /* Note: On -EAGAIN error only caller can retry on handle based calls
1153 since file handle passed in no longer valid */
1154
1155 return rc;
1156 }
1157
1158 int
1159 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1160 const int netfid, const unsigned int count,
1161 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1162 int n_vec, const int long_op)
1163 {
1164 int rc = -EACCES;
1165 WRITE_REQ *pSMB = NULL;
1166 int bytes_returned, wct;
1167 int smb_hdr_len;
1168
1169 /* BB removeme BB */
1170 cFYI(1,("write2 at %lld %d bytes", (long long)offset, count));
1171
1172 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1173 wct = 14;
1174 else
1175 wct = 12;
1176 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1177 if (rc)
1178 return rc;
1179 /* tcon and ses pointer are checked in smb_init */
1180 if (tcon->ses->server == NULL)
1181 return -ECONNABORTED;
1182
1183 pSMB->AndXCommand = 0xFF; /* none */
1184 pSMB->Fid = netfid;
1185 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1186 if(wct == 14)
1187 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1188 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1189 return -EIO;
1190 pSMB->Reserved = 0xFFFFFFFF;
1191 pSMB->WriteMode = 0;
1192 pSMB->Remaining = 0;
1193
1194 pSMB->DataOffset =
1195 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1196
1197 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1198 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1199 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1200 if(wct == 14)
1201 pSMB->hdr.smb_buf_length += count+1;
1202 else /* wct == 12 */
1203 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1204 if(wct == 14)
1205 pSMB->ByteCount = cpu_to_le16(count + 1);
1206 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1207 struct smb_com_writex_req * pSMBW =
1208 (struct smb_com_writex_req *)pSMB;
1209 pSMBW->ByteCount = cpu_to_le16(count + 5);
1210 }
1211 iov[0].iov_base = pSMB;
1212 iov[0].iov_len = smb_hdr_len + 4;
1213
1214 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &bytes_returned,
1215 long_op);
1216 cifs_stats_inc(&tcon->num_writes);
1217 if (rc) {
1218 cFYI(1, ("Send error Write2 = %d", rc));
1219 *nbytes = 0;
1220 } else {
1221 WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB;
1222 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1223 *nbytes = (*nbytes) << 16;
1224 *nbytes += le16_to_cpu(pSMBr->Count);
1225 }
1226
1227 cifs_small_buf_release(pSMB);
1228
1229 /* Note: On -EAGAIN error only caller can retry on handle based calls
1230 since file handle passed in no longer valid */
1231
1232 return rc;
1233 }
1234
1235
1236 int
1237 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1238 const __u16 smb_file_id, const __u64 len,
1239 const __u64 offset, const __u32 numUnlock,
1240 const __u32 numLock, const __u8 lockType, const int waitFlag)
1241 {
1242 int rc = 0;
1243 LOCK_REQ *pSMB = NULL;
1244 LOCK_RSP *pSMBr = NULL;
1245 int bytes_returned;
1246 int timeout = 0;
1247 __u16 count;
1248
1249 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
1250 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1251
1252 if (rc)
1253 return rc;
1254
1255 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1256
1257 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1258 timeout = -1; /* no response expected */
1259 pSMB->Timeout = 0;
1260 } else if (waitFlag == TRUE) {
1261 timeout = 3; /* blocking operation, no timeout */
1262 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1263 } else {
1264 pSMB->Timeout = 0;
1265 }
1266
1267 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1268 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1269 pSMB->LockType = lockType;
1270 pSMB->AndXCommand = 0xFF; /* none */
1271 pSMB->Fid = smb_file_id; /* netfid stays le */
1272
1273 if((numLock != 0) || (numUnlock != 0)) {
1274 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1275 /* BB where to store pid high? */
1276 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1277 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1278 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1279 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1280 count = sizeof(LOCKING_ANDX_RANGE);
1281 } else {
1282 /* oplock break */
1283 count = 0;
1284 }
1285 pSMB->hdr.smb_buf_length += count;
1286 pSMB->ByteCount = cpu_to_le16(count);
1287
1288 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1289 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1290 cifs_stats_inc(&tcon->num_locks);
1291 if (rc) {
1292 cFYI(1, ("Send error in Lock = %d", rc));
1293 }
1294 cifs_small_buf_release(pSMB);
1295
1296 /* Note: On -EAGAIN error only caller can retry on handle based calls
1297 since file handle passed in no longer valid */
1298 return rc;
1299 }
1300
1301 int
1302 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1303 {
1304 int rc = 0;
1305 CLOSE_REQ *pSMB = NULL;
1306 CLOSE_RSP *pSMBr = NULL;
1307 int bytes_returned;
1308 cFYI(1, ("In CIFSSMBClose"));
1309
1310 /* do not retry on dead session on close */
1311 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1312 if(rc == -EAGAIN)
1313 return 0;
1314 if (rc)
1315 return rc;
1316
1317 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1318
1319 pSMB->FileID = (__u16) smb_file_id;
1320 pSMB->LastWriteTime = 0;
1321 pSMB->ByteCount = 0;
1322 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1323 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1324 cifs_stats_inc(&tcon->num_closes);
1325 if (rc) {
1326 if(rc!=-EINTR) {
1327 /* EINTR is expected when user ctl-c to kill app */
1328 cERROR(1, ("Send error in Close = %d", rc));
1329 }
1330 }
1331
1332 cifs_small_buf_release(pSMB);
1333
1334 /* Since session is dead, file will be closed on server already */
1335 if(rc == -EAGAIN)
1336 rc = 0;
1337
1338 return rc;
1339 }
1340
1341 int
1342 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1343 const char *fromName, const char *toName,
1344 const struct nls_table *nls_codepage, int remap)
1345 {
1346 int rc = 0;
1347 RENAME_REQ *pSMB = NULL;
1348 RENAME_RSP *pSMBr = NULL;
1349 int bytes_returned;
1350 int name_len, name_len2;
1351 __u16 count;
1352
1353 cFYI(1, ("In CIFSSMBRename"));
1354 renameRetry:
1355 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1356 (void **) &pSMBr);
1357 if (rc)
1358 return rc;
1359
1360 pSMB->BufferFormat = 0x04;
1361 pSMB->SearchAttributes =
1362 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1363 ATTR_DIRECTORY);
1364
1365 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1366 name_len =
1367 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1368 PATH_MAX, nls_codepage, remap);
1369 name_len++; /* trailing null */
1370 name_len *= 2;
1371 pSMB->OldFileName[name_len] = 0x04; /* pad */
1372 /* protocol requires ASCII signature byte on Unicode string */
1373 pSMB->OldFileName[name_len + 1] = 0x00;
1374 name_len2 =
1375 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1376 toName, PATH_MAX, nls_codepage, remap);
1377 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1378 name_len2 *= 2; /* convert to bytes */
1379 } else { /* BB improve the check for buffer overruns BB */
1380 name_len = strnlen(fromName, PATH_MAX);
1381 name_len++; /* trailing null */
1382 strncpy(pSMB->OldFileName, fromName, name_len);
1383 name_len2 = strnlen(toName, PATH_MAX);
1384 name_len2++; /* trailing null */
1385 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1386 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1387 name_len2++; /* trailing null */
1388 name_len2++; /* signature byte */
1389 }
1390
1391 count = 1 /* 1st signature byte */ + name_len + name_len2;
1392 pSMB->hdr.smb_buf_length += count;
1393 pSMB->ByteCount = cpu_to_le16(count);
1394
1395 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1396 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1397 cifs_stats_inc(&tcon->num_renames);
1398 if (rc) {
1399 cFYI(1, ("Send error in rename = %d", rc));
1400 }
1401
1402 cifs_buf_release(pSMB);
1403
1404 if (rc == -EAGAIN)
1405 goto renameRetry;
1406
1407 return rc;
1408 }
1409
1410 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1411 int netfid, char * target_name,
1412 const struct nls_table * nls_codepage, int remap)
1413 {
1414 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1415 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1416 struct set_file_rename * rename_info;
1417 char *data_offset;
1418 char dummy_string[30];
1419 int rc = 0;
1420 int bytes_returned = 0;
1421 int len_of_str;
1422 __u16 params, param_offset, offset, count, byte_count;
1423
1424 cFYI(1, ("Rename to File by handle"));
1425 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1426 (void **) &pSMBr);
1427 if (rc)
1428 return rc;
1429
1430 params = 6;
1431 pSMB->MaxSetupCount = 0;
1432 pSMB->Reserved = 0;
1433 pSMB->Flags = 0;
1434 pSMB->Timeout = 0;
1435 pSMB->Reserved2 = 0;
1436 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1437 offset = param_offset + params;
1438
1439 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1440 rename_info = (struct set_file_rename *) data_offset;
1441 pSMB->MaxParameterCount = cpu_to_le16(2);
1442 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1443 pSMB->SetupCount = 1;
1444 pSMB->Reserved3 = 0;
1445 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1446 byte_count = 3 /* pad */ + params;
1447 pSMB->ParameterCount = cpu_to_le16(params);
1448 pSMB->TotalParameterCount = pSMB->ParameterCount;
1449 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1450 pSMB->DataOffset = cpu_to_le16(offset);
1451 /* construct random name ".cifs_tmp<inodenum><mid>" */
1452 rename_info->overwrite = cpu_to_le32(1);
1453 rename_info->root_fid = 0;
1454 /* unicode only call */
1455 if(target_name == NULL) {
1456 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1457 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1458 dummy_string, 24, nls_codepage, remap);
1459 } else {
1460 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1461 target_name, PATH_MAX, nls_codepage, remap);
1462 }
1463 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1464 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1465 byte_count += count;
1466 pSMB->DataCount = cpu_to_le16(count);
1467 pSMB->TotalDataCount = pSMB->DataCount;
1468 pSMB->Fid = netfid;
1469 pSMB->InformationLevel =
1470 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1471 pSMB->Reserved4 = 0;
1472 pSMB->hdr.smb_buf_length += byte_count;
1473 pSMB->ByteCount = cpu_to_le16(byte_count);
1474 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1475 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1476 cifs_stats_inc(&pTcon->num_t2renames);
1477 if (rc) {
1478 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1479 }
1480
1481 cifs_buf_release(pSMB);
1482
1483 /* Note: On -EAGAIN error only caller can retry on handle based calls
1484 since file handle passed in no longer valid */
1485
1486 return rc;
1487 }
1488
1489 int
1490 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1491 const __u16 target_tid, const char *toName, const int flags,
1492 const struct nls_table *nls_codepage, int remap)
1493 {
1494 int rc = 0;
1495 COPY_REQ *pSMB = NULL;
1496 COPY_RSP *pSMBr = NULL;
1497 int bytes_returned;
1498 int name_len, name_len2;
1499 __u16 count;
1500
1501 cFYI(1, ("In CIFSSMBCopy"));
1502 copyRetry:
1503 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1504 (void **) &pSMBr);
1505 if (rc)
1506 return rc;
1507
1508 pSMB->BufferFormat = 0x04;
1509 pSMB->Tid2 = target_tid;
1510
1511 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1512
1513 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1514 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
1515 fromName, PATH_MAX, nls_codepage,
1516 remap);
1517 name_len++; /* trailing null */
1518 name_len *= 2;
1519 pSMB->OldFileName[name_len] = 0x04; /* pad */
1520 /* protocol requires ASCII signature byte on Unicode string */
1521 pSMB->OldFileName[name_len + 1] = 0x00;
1522 name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1523 toName, PATH_MAX, nls_codepage, remap);
1524 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1525 name_len2 *= 2; /* convert to bytes */
1526 } else { /* BB improve the check for buffer overruns BB */
1527 name_len = strnlen(fromName, PATH_MAX);
1528 name_len++; /* trailing null */
1529 strncpy(pSMB->OldFileName, fromName, name_len);
1530 name_len2 = strnlen(toName, PATH_MAX);
1531 name_len2++; /* trailing null */
1532 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1533 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1534 name_len2++; /* trailing null */
1535 name_len2++; /* signature byte */
1536 }
1537
1538 count = 1 /* 1st signature byte */ + name_len + name_len2;
1539 pSMB->hdr.smb_buf_length += count;
1540 pSMB->ByteCount = cpu_to_le16(count);
1541
1542 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1543 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1544 if (rc) {
1545 cFYI(1, ("Send error in copy = %d with %d files copied",
1546 rc, le16_to_cpu(pSMBr->CopyCount)));
1547 }
1548 if (pSMB)
1549 cifs_buf_release(pSMB);
1550
1551 if (rc == -EAGAIN)
1552 goto copyRetry;
1553
1554 return rc;
1555 }
1556
1557 int
1558 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1559 const char *fromName, const char *toName,
1560 const struct nls_table *nls_codepage)
1561 {
1562 TRANSACTION2_SPI_REQ *pSMB = NULL;
1563 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1564 char *data_offset;
1565 int name_len;
1566 int name_len_target;
1567 int rc = 0;
1568 int bytes_returned = 0;
1569 __u16 params, param_offset, offset, byte_count;
1570
1571 cFYI(1, ("In Symlink Unix style"));
1572 createSymLinkRetry:
1573 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1574 (void **) &pSMBr);
1575 if (rc)
1576 return rc;
1577
1578 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1579 name_len =
1580 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
1581 /* find define for this maxpathcomponent */
1582 , nls_codepage);
1583 name_len++; /* trailing null */
1584 name_len *= 2;
1585
1586 } else { /* BB improve the check for buffer overruns BB */
1587 name_len = strnlen(fromName, PATH_MAX);
1588 name_len++; /* trailing null */
1589 strncpy(pSMB->FileName, fromName, name_len);
1590 }
1591 params = 6 + name_len;
1592 pSMB->MaxSetupCount = 0;
1593 pSMB->Reserved = 0;
1594 pSMB->Flags = 0;
1595 pSMB->Timeout = 0;
1596 pSMB->Reserved2 = 0;
1597 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1598 InformationLevel) - 4;
1599 offset = param_offset + params;
1600
1601 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1602 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1603 name_len_target =
1604 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
1605 /* find define for this maxpathcomponent */
1606 , nls_codepage);
1607 name_len_target++; /* trailing null */
1608 name_len_target *= 2;
1609 } else { /* BB improve the check for buffer overruns BB */
1610 name_len_target = strnlen(toName, PATH_MAX);
1611 name_len_target++; /* trailing null */
1612 strncpy(data_offset, toName, name_len_target);
1613 }
1614
1615 pSMB->MaxParameterCount = cpu_to_le16(2);
1616 /* BB find exact max on data count below from sess */
1617 pSMB->MaxDataCount = cpu_to_le16(1000);
1618 pSMB->SetupCount = 1;
1619 pSMB->Reserved3 = 0;
1620 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1621 byte_count = 3 /* pad */ + params + name_len_target;
1622 pSMB->DataCount = cpu_to_le16(name_len_target);
1623 pSMB->ParameterCount = cpu_to_le16(params);
1624 pSMB->TotalDataCount = pSMB->DataCount;
1625 pSMB->TotalParameterCount = pSMB->ParameterCount;
1626 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1627 pSMB->DataOffset = cpu_to_le16(offset);
1628 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1629 pSMB->Reserved4 = 0;
1630 pSMB->hdr.smb_buf_length += byte_count;
1631 pSMB->ByteCount = cpu_to_le16(byte_count);
1632 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1633 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1634 cifs_stats_inc(&tcon->num_symlinks);
1635 if (rc) {
1636 cFYI(1,
1637 ("Send error in SetPathInfo (create symlink) = %d",
1638 rc));
1639 }
1640
1641 if (pSMB)
1642 cifs_buf_release(pSMB);
1643
1644 if (rc == -EAGAIN)
1645 goto createSymLinkRetry;
1646
1647 return rc;
1648 }
1649
1650 int
1651 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1652 const char *fromName, const char *toName,
1653 const struct nls_table *nls_codepage, int remap)
1654 {
1655 TRANSACTION2_SPI_REQ *pSMB = NULL;
1656 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1657 char *data_offset;
1658 int name_len;
1659 int name_len_target;
1660 int rc = 0;
1661 int bytes_returned = 0;
1662 __u16 params, param_offset, offset, byte_count;
1663
1664 cFYI(1, ("In Create Hard link Unix style"));
1665 createHardLinkRetry:
1666 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1667 (void **) &pSMBr);
1668 if (rc)
1669 return rc;
1670
1671 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1672 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
1673 PATH_MAX, nls_codepage, remap);
1674 name_len++; /* trailing null */
1675 name_len *= 2;
1676
1677 } else { /* BB improve the check for buffer overruns BB */
1678 name_len = strnlen(toName, PATH_MAX);
1679 name_len++; /* trailing null */
1680 strncpy(pSMB->FileName, toName, name_len);
1681 }
1682 params = 6 + name_len;
1683 pSMB->MaxSetupCount = 0;
1684 pSMB->Reserved = 0;
1685 pSMB->Flags = 0;
1686 pSMB->Timeout = 0;
1687 pSMB->Reserved2 = 0;
1688 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1689 InformationLevel) - 4;
1690 offset = param_offset + params;
1691
1692 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1693 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1694 name_len_target =
1695 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
1696 nls_codepage, remap);
1697 name_len_target++; /* trailing null */
1698 name_len_target *= 2;
1699 } else { /* BB improve the check for buffer overruns BB */
1700 name_len_target = strnlen(fromName, PATH_MAX);
1701 name_len_target++; /* trailing null */
1702 strncpy(data_offset, fromName, name_len_target);
1703 }
1704
1705 pSMB->MaxParameterCount = cpu_to_le16(2);
1706 /* BB find exact max on data count below from sess*/
1707 pSMB->MaxDataCount = cpu_to_le16(1000);
1708 pSMB->SetupCount = 1;
1709 pSMB->Reserved3 = 0;
1710 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1711 byte_count = 3 /* pad */ + params + name_len_target;
1712 pSMB->ParameterCount = cpu_to_le16(params);
1713 pSMB->TotalParameterCount = pSMB->ParameterCount;
1714 pSMB->DataCount = cpu_to_le16(name_len_target);
1715 pSMB->TotalDataCount = pSMB->DataCount;
1716 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1717 pSMB->DataOffset = cpu_to_le16(offset);
1718 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
1719 pSMB->Reserved4 = 0;
1720 pSMB->hdr.smb_buf_length += byte_count;
1721 pSMB->ByteCount = cpu_to_le16(byte_count);
1722 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1723 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1724 cifs_stats_inc(&tcon->num_hardlinks);
1725 if (rc) {
1726 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1727 }
1728
1729 cifs_buf_release(pSMB);
1730 if (rc == -EAGAIN)
1731 goto createHardLinkRetry;
1732
1733 return rc;
1734 }
1735
1736 int
1737 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1738 const char *fromName, const char *toName,
1739 const struct nls_table *nls_codepage, int remap)
1740 {
1741 int rc = 0;
1742 NT_RENAME_REQ *pSMB = NULL;
1743 RENAME_RSP *pSMBr = NULL;
1744 int bytes_returned;
1745 int name_len, name_len2;
1746 __u16 count;
1747
1748 cFYI(1, ("In CIFSCreateHardLink"));
1749 winCreateHardLinkRetry:
1750
1751 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
1752 (void **) &pSMBr);
1753 if (rc)
1754 return rc;
1755
1756 pSMB->SearchAttributes =
1757 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1758 ATTR_DIRECTORY);
1759 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
1760 pSMB->ClusterCount = 0;
1761
1762 pSMB->BufferFormat = 0x04;
1763
1764 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1765 name_len =
1766 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1767 PATH_MAX, nls_codepage, remap);
1768 name_len++; /* trailing null */
1769 name_len *= 2;
1770 pSMB->OldFileName[name_len] = 0; /* pad */
1771 pSMB->OldFileName[name_len + 1] = 0x04;
1772 name_len2 =
1773 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1774 toName, PATH_MAX, nls_codepage, remap);
1775 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1776 name_len2 *= 2; /* convert to bytes */
1777 } else { /* BB improve the check for buffer overruns BB */
1778 name_len = strnlen(fromName, PATH_MAX);
1779 name_len++; /* trailing null */
1780 strncpy(pSMB->OldFileName, fromName, name_len);
1781 name_len2 = strnlen(toName, PATH_MAX);
1782 name_len2++; /* trailing null */
1783 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1784 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1785 name_len2++; /* trailing null */
1786 name_len2++; /* signature byte */
1787 }
1788
1789 count = 1 /* string type byte */ + name_len + name_len2;
1790 pSMB->hdr.smb_buf_length += count;
1791 pSMB->ByteCount = cpu_to_le16(count);
1792
1793 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1794 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1795 cifs_stats_inc(&tcon->num_hardlinks);
1796 if (rc) {
1797 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1798 }
1799 cifs_buf_release(pSMB);
1800 if (rc == -EAGAIN)
1801 goto winCreateHardLinkRetry;
1802
1803 return rc;
1804 }
1805
1806 int
1807 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
1808 const unsigned char *searchName,
1809 char *symlinkinfo, const int buflen,
1810 const struct nls_table *nls_codepage)
1811 {
1812 /* SMB_QUERY_FILE_UNIX_LINK */
1813 TRANSACTION2_QPI_REQ *pSMB = NULL;
1814 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1815 int rc = 0;
1816 int bytes_returned;
1817 int name_len;
1818 __u16 params, byte_count;
1819
1820 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
1821
1822 querySymLinkRetry:
1823 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1824 (void **) &pSMBr);
1825 if (rc)
1826 return rc;
1827
1828 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1829 name_len =
1830 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
1831 /* find define for this maxpathcomponent */
1832 , nls_codepage);
1833 name_len++; /* trailing null */
1834 name_len *= 2;
1835 } else { /* BB improve the check for buffer overruns BB */
1836 name_len = strnlen(searchName, PATH_MAX);
1837 name_len++; /* trailing null */
1838 strncpy(pSMB->FileName, searchName, name_len);
1839 }
1840
1841 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
1842 pSMB->TotalDataCount = 0;
1843 pSMB->MaxParameterCount = cpu_to_le16(2);
1844 /* BB find exact max data count below from sess structure BB */
1845 pSMB->MaxDataCount = cpu_to_le16(4000);
1846 pSMB->MaxSetupCount = 0;
1847 pSMB->Reserved = 0;
1848 pSMB->Flags = 0;
1849 pSMB->Timeout = 0;
1850 pSMB->Reserved2 = 0;
1851 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1852 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1853 pSMB->DataCount = 0;
1854 pSMB->DataOffset = 0;
1855 pSMB->SetupCount = 1;
1856 pSMB->Reserved3 = 0;
1857 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1858 byte_count = params + 1 /* pad */ ;
1859 pSMB->TotalParameterCount = cpu_to_le16(params);
1860 pSMB->ParameterCount = pSMB->TotalParameterCount;
1861 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
1862 pSMB->Reserved4 = 0;
1863 pSMB->hdr.smb_buf_length += byte_count;
1864 pSMB->ByteCount = cpu_to_le16(byte_count);
1865
1866 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1867 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1868 if (rc) {
1869 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
1870 } else {
1871 /* decode response */
1872
1873 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1874 if (rc || (pSMBr->ByteCount < 2))
1875 /* BB also check enough total bytes returned */
1876 rc = -EIO; /* bad smb */
1877 else {
1878 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1879 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
1880
1881 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1882 name_len = UniStrnlen((wchar_t *) ((char *)
1883 &pSMBr->hdr.Protocol +data_offset),
1884 min_t(const int, buflen,count) / 2);
1885 /* BB FIXME investigate remapping reserved chars here */
1886 cifs_strfromUCS_le(symlinkinfo,
1887 (__le16 *) ((char *)&pSMBr->hdr.Protocol +
1888 data_offset),
1889 name_len, nls_codepage);
1890 } else {
1891 strncpy(symlinkinfo,
1892 (char *) &pSMBr->hdr.Protocol +
1893 data_offset,
1894 min_t(const int, buflen, count));
1895 }
1896 symlinkinfo[buflen] = 0;
1897 /* just in case so calling code does not go off the end of buffer */
1898 }
1899 }
1900 cifs_buf_release(pSMB);
1901 if (rc == -EAGAIN)
1902 goto querySymLinkRetry;
1903 return rc;
1904 }
1905
1906 int
1907 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1908 const unsigned char *searchName,
1909 char *symlinkinfo, const int buflen,__u16 fid,
1910 const struct nls_table *nls_codepage)
1911 {
1912 int rc = 0;
1913 int bytes_returned;
1914 int name_len;
1915 struct smb_com_transaction_ioctl_req * pSMB;
1916 struct smb_com_transaction_ioctl_rsp * pSMBr;
1917
1918 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
1919 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
1920 (void **) &pSMBr);
1921 if (rc)
1922 return rc;
1923
1924 pSMB->TotalParameterCount = 0 ;
1925 pSMB->TotalDataCount = 0;
1926 pSMB->MaxParameterCount = cpu_to_le32(2);
1927 /* BB find exact data count max from sess structure BB */
1928 pSMB->MaxDataCount = cpu_to_le32(4000);
1929 pSMB->MaxSetupCount = 4;
1930 pSMB->Reserved = 0;
1931 pSMB->ParameterOffset = 0;
1932 pSMB->DataCount = 0;
1933 pSMB->DataOffset = 0;
1934 pSMB->SetupCount = 4;
1935 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
1936 pSMB->ParameterCount = pSMB->TotalParameterCount;
1937 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
1938 pSMB->IsFsctl = 1; /* FSCTL */
1939 pSMB->IsRootFlag = 0;
1940 pSMB->Fid = fid; /* file handle always le */
1941 pSMB->ByteCount = 0;
1942
1943 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1944 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1945 if (rc) {
1946 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
1947 } else { /* decode response */
1948 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
1949 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
1950 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
1951 /* BB also check enough total bytes returned */
1952 rc = -EIO; /* bad smb */
1953 else {
1954 if(data_count && (data_count < 2048)) {
1955 char * end_of_smb = pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
1956
1957 struct reparse_data * reparse_buf = (struct reparse_data *)
1958 ((char *)&pSMBr->hdr.Protocol + data_offset);
1959 if((char*)reparse_buf >= end_of_smb) {
1960 rc = -EIO;
1961 goto qreparse_out;
1962 }
1963 if((reparse_buf->LinkNamesBuf +
1964 reparse_buf->TargetNameOffset +
1965 reparse_buf->TargetNameLen) >
1966 end_of_smb) {
1967 cFYI(1,("reparse buf extended beyond SMB"));
1968 rc = -EIO;
1969 goto qreparse_out;
1970 }
1971
1972 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1973 name_len = UniStrnlen((wchar_t *)
1974 (reparse_buf->LinkNamesBuf +
1975 reparse_buf->TargetNameOffset),
1976 min(buflen/2, reparse_buf->TargetNameLen / 2));
1977 cifs_strfromUCS_le(symlinkinfo,
1978 (__le16 *) (reparse_buf->LinkNamesBuf +
1979 reparse_buf->TargetNameOffset),
1980 name_len, nls_codepage);
1981 } else { /* ASCII names */
1982 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
1983 reparse_buf->TargetNameOffset,
1984 min_t(const int, buflen, reparse_buf->TargetNameLen));
1985 }
1986 } else {
1987 rc = -EIO;
1988 cFYI(1,("Invalid return data count on get reparse info ioctl"));
1989 }
1990 symlinkinfo[buflen] = 0; /* just in case so the caller
1991 does not go off the end of the buffer */
1992 cFYI(1,("readlink result - %s ",symlinkinfo));
1993 }
1994 }
1995 qreparse_out:
1996 cifs_buf_release(pSMB);
1997
1998 /* Note: On -EAGAIN error only caller can retry on handle based calls
1999 since file handle passed in no longer valid */
2000
2001 return rc;
2002 }
2003
2004 #ifdef CONFIG_CIFS_POSIX
2005
2006 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2007 static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
2008 {
2009 /* u8 cifs fields do not need le conversion */
2010 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2011 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2012 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2013 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2014
2015 return;
2016 }
2017
2018 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2019 static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
2020 const int acl_type,const int size_of_data_area)
2021 {
2022 int size = 0;
2023 int i;
2024 __u16 count;
2025 struct cifs_posix_ace * pACE;
2026 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
2027 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
2028
2029 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2030 return -EOPNOTSUPP;
2031
2032 if(acl_type & ACL_TYPE_ACCESS) {
2033 count = le16_to_cpu(cifs_acl->access_entry_count);
2034 pACE = &cifs_acl->ace_array[0];
2035 size = sizeof(struct cifs_posix_acl);
2036 size += sizeof(struct cifs_posix_ace) * count;
2037 /* check if we would go beyond end of SMB */
2038 if(size_of_data_area < size) {
2039 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
2040 return -EINVAL;
2041 }
2042 } else if(acl_type & ACL_TYPE_DEFAULT) {
2043 count = le16_to_cpu(cifs_acl->access_entry_count);
2044 size = sizeof(struct cifs_posix_acl);
2045 size += sizeof(struct cifs_posix_ace) * count;
2046 /* skip past access ACEs to get to default ACEs */
2047 pACE = &cifs_acl->ace_array[count];
2048 count = le16_to_cpu(cifs_acl->default_entry_count);
2049 size += sizeof(struct cifs_posix_ace) * count;
2050 /* check if we would go beyond end of SMB */
2051 if(size_of_data_area < size)
2052 return -EINVAL;
2053 } else {
2054 /* illegal type */
2055 return -EINVAL;
2056 }
2057
2058 size = posix_acl_xattr_size(count);
2059 if((buflen == 0) || (local_acl == NULL)) {
2060 /* used to query ACL EA size */
2061 } else if(size > buflen) {
2062 return -ERANGE;
2063 } else /* buffer big enough */ {
2064 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2065 for(i = 0;i < count ;i++) {
2066 cifs_convert_ace(&local_acl->a_entries[i],pACE);
2067 pACE ++;
2068 }
2069 }
2070 return size;
2071 }
2072
2073 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
2074 const posix_acl_xattr_entry * local_ace)
2075 {
2076 __u16 rc = 0; /* 0 = ACL converted ok */
2077
2078 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2079 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2080 /* BB is there a better way to handle the large uid? */
2081 if(local_ace->e_id == cpu_to_le32(-1)) {
2082 /* Probably no need to le convert -1 on any arch but can not hurt */
2083 cifs_ace->cifs_uid = cpu_to_le64(-1);
2084 } else
2085 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2086 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2087 return rc;
2088 }
2089
2090 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2091 static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
2092 const int acl_type)
2093 {
2094 __u16 rc = 0;
2095 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
2096 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
2097 int count;
2098 int i;
2099
2100 if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2101 return 0;
2102
2103 count = posix_acl_xattr_count((size_t)buflen);
2104 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
2105 count, buflen, le32_to_cpu(local_acl->a_version)));
2106 if(le32_to_cpu(local_acl->a_version) != 2) {
2107 cFYI(1,("unknown POSIX ACL version %d",
2108 le32_to_cpu(local_acl->a_version)));
2109 return 0;
2110 }
2111 cifs_acl->version = cpu_to_le16(1);
2112 if(acl_type == ACL_TYPE_ACCESS)
2113 cifs_acl->access_entry_count = cpu_to_le16(count);
2114 else if(acl_type == ACL_TYPE_DEFAULT)
2115 cifs_acl->default_entry_count = cpu_to_le16(count);
2116 else {
2117 cFYI(1,("unknown ACL type %d",acl_type));
2118 return 0;
2119 }
2120 for(i=0;i<count;i++) {
2121 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2122 &local_acl->a_entries[i]);
2123 if(rc != 0) {
2124 /* ACE not converted */
2125 break;
2126 }
2127 }
2128 if(rc == 0) {
2129 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2130 rc += sizeof(struct cifs_posix_acl);
2131 /* BB add check to make sure ACL does not overflow SMB */
2132 }
2133 return rc;
2134 }
2135
2136 int
2137 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2138 const unsigned char *searchName,
2139 char *acl_inf, const int buflen, const int acl_type,
2140 const struct nls_table *nls_codepage, int remap)
2141 {
2142 /* SMB_QUERY_POSIX_ACL */
2143 TRANSACTION2_QPI_REQ *pSMB = NULL;
2144 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2145 int rc = 0;
2146 int bytes_returned;
2147 int name_len;
2148 __u16 params, byte_count;
2149
2150 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2151
2152 queryAclRetry:
2153 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2154 (void **) &pSMBr);
2155 if (rc)
2156 return rc;
2157
2158 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2159 name_len =
2160 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2161 PATH_MAX, nls_codepage, remap);
2162 name_len++; /* trailing null */
2163 name_len *= 2;
2164 pSMB->FileName[name_len] = 0;
2165 pSMB->FileName[name_len+1] = 0;
2166 } else { /* BB improve the check for buffer overruns BB */
2167 name_len = strnlen(searchName, PATH_MAX);
2168 name_len++; /* trailing null */
2169 strncpy(pSMB->FileName, searchName, name_len);
2170 }
2171
2172 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2173 pSMB->TotalDataCount = 0;
2174 pSMB->MaxParameterCount = cpu_to_le16(2);
2175 /* BB find exact max data count below from sess structure BB */
2176 pSMB->MaxDataCount = cpu_to_le16(4000);
2177 pSMB->MaxSetupCount = 0;
2178 pSMB->Reserved = 0;
2179 pSMB->Flags = 0;
2180 pSMB->Timeout = 0;
2181 pSMB->Reserved2 = 0;
2182 pSMB->ParameterOffset = cpu_to_le16(
2183 offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2184 pSMB->DataCount = 0;
2185 pSMB->DataOffset = 0;
2186 pSMB->SetupCount = 1;
2187 pSMB->Reserved3 = 0;
2188 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2189 byte_count = params + 1 /* pad */ ;
2190 pSMB->TotalParameterCount = cpu_to_le16(params);
2191 pSMB->ParameterCount = pSMB->TotalParameterCount;
2192 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2193 pSMB->Reserved4 = 0;
2194 pSMB->hdr.smb_buf_length += byte_count;
2195 pSMB->ByteCount = cpu_to_le16(byte_count);
2196
2197 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2198 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2199 if (rc) {
2200 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2201 } else {
2202 /* decode response */
2203
2204 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2205 if (rc || (pSMBr->ByteCount < 2))
2206 /* BB also check enough total bytes returned */
2207 rc = -EIO; /* bad smb */
2208 else {
2209 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2210 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2211 rc = cifs_copy_posix_acl(acl_inf,
2212 (char *)&pSMBr->hdr.Protocol+data_offset,
2213 buflen,acl_type,count);
2214 }
2215 }
2216 cifs_buf_release(pSMB);
2217 if (rc == -EAGAIN)
2218 goto queryAclRetry;
2219 return rc;
2220 }
2221
2222 int
2223 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2224 const unsigned char *fileName,
2225 const char *local_acl, const int buflen,
2226 const int acl_type,
2227 const struct nls_table *nls_codepage, int remap)
2228 {
2229 struct smb_com_transaction2_spi_req *pSMB = NULL;
2230 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2231 char *parm_data;
2232 int name_len;
2233 int rc = 0;
2234 int bytes_returned = 0;
2235 __u16 params, byte_count, data_count, param_offset, offset;
2236
2237 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2238 setAclRetry:
2239 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2240 (void **) &pSMBr);
2241 if (rc)
2242 return rc;
2243 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2244 name_len =
2245 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2246 PATH_MAX, nls_codepage, remap);
2247 name_len++; /* trailing null */
2248 name_len *= 2;
2249 } else { /* BB improve the check for buffer overruns BB */
2250 name_len = strnlen(fileName, PATH_MAX);
2251 name_len++; /* trailing null */
2252 strncpy(pSMB->FileName, fileName, name_len);
2253 }
2254 params = 6 + name_len;
2255 pSMB->MaxParameterCount = cpu_to_le16(2);
2256 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2257 pSMB->MaxSetupCount = 0;
2258 pSMB->Reserved = 0;
2259 pSMB->Flags = 0;
2260 pSMB->Timeout = 0;
2261 pSMB->Reserved2 = 0;
2262 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2263 InformationLevel) - 4;
2264 offset = param_offset + params;
2265 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2266 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2267
2268 /* convert to on the wire format for POSIX ACL */
2269 data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
2270
2271 if(data_count == 0) {
2272 rc = -EOPNOTSUPP;
2273 goto setACLerrorExit;
2274 }
2275 pSMB->DataOffset = cpu_to_le16(offset);
2276 pSMB->SetupCount = 1;
2277 pSMB->Reserved3 = 0;
2278 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2279 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2280 byte_count = 3 /* pad */ + params + data_count;
2281 pSMB->DataCount = cpu_to_le16(data_count);
2282 pSMB->TotalDataCount = pSMB->DataCount;
2283 pSMB->ParameterCount = cpu_to_le16(params);
2284 pSMB->TotalParameterCount = pSMB->ParameterCount;
2285 pSMB->Reserved4 = 0;
2286 pSMB->hdr.smb_buf_length += byte_count;
2287 pSMB->ByteCount = cpu_to_le16(byte_count);
2288 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2289 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2290 if (rc) {
2291 cFYI(1, ("Set POSIX ACL returned %d", rc));
2292 }
2293
2294 setACLerrorExit:
2295 cifs_buf_release(pSMB);
2296 if (rc == -EAGAIN)
2297 goto setAclRetry;
2298 return rc;
2299 }
2300
2301 /* BB fix tabs in this function FIXME BB */
2302 int
2303 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2304 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2305 {
2306 int rc = 0;
2307 struct smb_t2_qfi_req *pSMB = NULL;
2308 struct smb_t2_qfi_rsp *pSMBr = NULL;
2309 int bytes_returned;
2310 __u16 params, byte_count;
2311
2312 cFYI(1,("In GetExtAttr"));
2313 if(tcon == NULL)
2314 return -ENODEV;
2315
2316 GetExtAttrRetry:
2317 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2318 (void **) &pSMBr);
2319 if (rc)
2320 return rc;
2321
2322 params = 2 /* level */ +2 /* fid */;
2323 pSMB->t2.TotalDataCount = 0;
2324 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2325 /* BB find exact max data count below from sess structure BB */
2326 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2327 pSMB->t2.MaxSetupCount = 0;
2328 pSMB->t2.Reserved = 0;
2329 pSMB->t2.Flags = 0;
2330 pSMB->t2.Timeout = 0;
2331 pSMB->t2.Reserved2 = 0;
2332 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2333 Fid) - 4);
2334 pSMB->t2.DataCount = 0;
2335 pSMB->t2.DataOffset = 0;
2336 pSMB->t2.SetupCount = 1;
2337 pSMB->t2.Reserved3 = 0;
2338 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2339 byte_count = params + 1 /* pad */ ;
2340 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2341 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2342 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2343 pSMB->Pad = 0;
2344 pSMB->Fid = netfid;
2345 pSMB->hdr.smb_buf_length += byte_count;
2346 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2347
2348 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2349 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2350 if (rc) {
2351 cFYI(1, ("error %d in GetExtAttr", rc));
2352 } else {
2353 /* decode response */
2354 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2355 if (rc || (pSMBr->ByteCount < 2))
2356 /* BB also check enough total bytes returned */
2357 /* If rc should we check for EOPNOSUPP and
2358 disable the srvino flag? or in caller? */
2359 rc = -EIO; /* bad smb */
2360 else {
2361 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2362 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2363 struct file_chattr_info * pfinfo;
2364 /* BB Do we need a cast or hash here ? */
2365 if(count != 16) {
2366 cFYI(1, ("Illegal size ret in GetExtAttr"));
2367 rc = -EIO;
2368 goto GetExtAttrOut;
2369 }
2370 pfinfo = (struct file_chattr_info *)
2371 (data_offset + (char *) &pSMBr->hdr.Protocol);
2372 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2373 *pMask = le64_to_cpu(pfinfo->mask);
2374 }
2375 }
2376 GetExtAttrOut:
2377 cifs_buf_release(pSMB);
2378 if (rc == -EAGAIN)
2379 goto GetExtAttrRetry;
2380 return rc;
2381 }
2382
2383
2384 #endif /* CONFIG_POSIX */
2385
2386 /* Legacy Query Path Information call for lookup to old servers such
2387 as Win9x/WinME */
2388 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
2389 const unsigned char *searchName,
2390 FILE_ALL_INFO * pFinfo,
2391 const struct nls_table *nls_codepage, int remap)
2392 {
2393 QUERY_INFORMATION_REQ * pSMB;
2394 QUERY_INFORMATION_RSP * pSMBr;
2395 int rc = 0;
2396 int bytes_returned;
2397 int name_len;
2398
2399 cFYI(1, ("In SMBQPath path %s", searchName));
2400 QInfRetry:
2401 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
2402 (void **) &pSMBr);
2403 if (rc)
2404 return rc;
2405
2406 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2407 name_len =
2408 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2409 PATH_MAX, nls_codepage, remap);
2410 name_len++; /* trailing null */
2411 name_len *= 2;
2412 } else {
2413 name_len = strnlen(searchName, PATH_MAX);
2414 name_len++; /* trailing null */
2415 strncpy(pSMB->FileName, searchName, name_len);
2416 }
2417 pSMB->BufferFormat = 0x04;
2418 name_len++; /* account for buffer type byte */
2419 pSMB->hdr.smb_buf_length += (__u16) name_len;
2420 pSMB->ByteCount = cpu_to_le16(name_len);
2421
2422 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2423 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2424 if (rc) {
2425 cFYI(1, ("Send error in QueryInfo = %d", rc));
2426 } else if (pFinfo) { /* decode response */
2427 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
2428 pFinfo->AllocationSize =
2429 cpu_to_le64(le32_to_cpu(pSMBr->size));
2430 pFinfo->EndOfFile = pFinfo->AllocationSize;
2431 pFinfo->Attributes =
2432 cpu_to_le32(le16_to_cpu(pSMBr->attr));
2433 } else
2434 rc = -EIO; /* bad buffer passed in */
2435
2436 cifs_buf_release(pSMB);
2437
2438 if (rc == -EAGAIN)
2439 goto QInfRetry;
2440
2441 return rc;
2442 }
2443
2444
2445
2446
2447 int
2448 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2449 const unsigned char *searchName,
2450 FILE_ALL_INFO * pFindData,
2451 const struct nls_table *nls_codepage, int remap)
2452 {
2453 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2454 TRANSACTION2_QPI_REQ *pSMB = NULL;
2455 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2456 int rc = 0;
2457 int bytes_returned;
2458 int name_len;
2459 __u16 params, byte_count;
2460
2461 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2462 QPathInfoRetry:
2463 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2464 (void **) &pSMBr);
2465 if (rc)
2466 return rc;
2467
2468 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2469 name_len =
2470 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2471 PATH_MAX, nls_codepage, remap);
2472 name_len++; /* trailing null */
2473 name_len *= 2;
2474 } else { /* BB improve the check for buffer overruns BB */
2475 name_len = strnlen(searchName, PATH_MAX);
2476 name_len++; /* trailing null */
2477 strncpy(pSMB->FileName, searchName, name_len);
2478 }
2479
2480 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2481 pSMB->TotalDataCount = 0;
2482 pSMB->MaxParameterCount = cpu_to_le16(2);
2483 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2484 pSMB->MaxSetupCount = 0;
2485 pSMB->Reserved = 0;
2486 pSMB->Flags = 0;
2487 pSMB->Timeout = 0;
2488 pSMB->Reserved2 = 0;
2489 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2490 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2491 pSMB->DataCount = 0;
2492 pSMB->DataOffset = 0;
2493 pSMB->SetupCount = 1;
2494 pSMB->Reserved3 = 0;
2495 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2496 byte_count = params + 1 /* pad */ ;
2497 pSMB->TotalParameterCount = cpu_to_le16(params);
2498 pSMB->ParameterCount = pSMB->TotalParameterCount;
2499 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
2500 pSMB->Reserved4 = 0;
2501 pSMB->hdr.smb_buf_length += byte_count;
2502 pSMB->ByteCount = cpu_to_le16(byte_count);
2503
2504 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2505 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2506 if (rc) {
2507 cFYI(1, ("Send error in QPathInfo = %d", rc));
2508 } else { /* decode response */
2509 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2510
2511 if (rc || (pSMBr->ByteCount < 40))
2512 rc = -EIO; /* bad smb */
2513 else if (pFindData){
2514 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2515 memcpy((char *) pFindData,
2516 (char *) &pSMBr->hdr.Protocol +
2517 data_offset, sizeof (FILE_ALL_INFO));
2518 } else
2519 rc = -ENOMEM;
2520 }
2521 cifs_buf_release(pSMB);
2522 if (rc == -EAGAIN)
2523 goto QPathInfoRetry;
2524
2525 return rc;
2526 }
2527
2528 int
2529 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
2530 const unsigned char *searchName,
2531 FILE_UNIX_BASIC_INFO * pFindData,
2532 const struct nls_table *nls_codepage, int remap)
2533 {
2534 /* SMB_QUERY_FILE_UNIX_BASIC */
2535 TRANSACTION2_QPI_REQ *pSMB = NULL;
2536 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2537 int rc = 0;
2538 int bytes_returned = 0;
2539 int name_len;
2540 __u16 params, byte_count;
2541
2542 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
2543 UnixQPathInfoRetry:
2544 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2545 (void **) &pSMBr);
2546 if (rc)
2547 return rc;
2548
2549 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2550 name_len =
2551 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2552 PATH_MAX, nls_codepage, remap);
2553 name_len++; /* trailing null */
2554 name_len *= 2;
2555 } else { /* BB improve the check for buffer overruns BB */
2556 name_len = strnlen(searchName, PATH_MAX);
2557 name_len++; /* trailing null */
2558 strncpy(pSMB->FileName, searchName, name_len);
2559 }
2560
2561 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2562 pSMB->TotalDataCount = 0;
2563 pSMB->MaxParameterCount = cpu_to_le16(2);
2564 /* BB find exact max SMB PDU from sess structure BB */
2565 pSMB->MaxDataCount = cpu_to_le16(4000);
2566 pSMB->MaxSetupCount = 0;
2567 pSMB->Reserved = 0;
2568 pSMB->Flags = 0;
2569 pSMB->Timeout = 0;
2570 pSMB->Reserved2 = 0;
2571 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2572 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2573 pSMB->DataCount = 0;
2574 pSMB->DataOffset = 0;
2575 pSMB->SetupCount = 1;
2576 pSMB->Reserved3 = 0;
2577 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2578 byte_count = params + 1 /* pad */ ;
2579 pSMB->TotalParameterCount = cpu_to_le16(params);
2580 pSMB->ParameterCount = pSMB->TotalParameterCount;
2581 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
2582 pSMB->Reserved4 = 0;
2583 pSMB->hdr.smb_buf_length += byte_count;
2584 pSMB->ByteCount = cpu_to_le16(byte_count);
2585
2586 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2587 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2588 if (rc) {
2589 cFYI(1, ("Send error in QPathInfo = %d", rc));
2590 } else { /* decode response */
2591 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2592
2593 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
2594 rc = -EIO; /* bad smb */
2595 } else {
2596 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2597 memcpy((char *) pFindData,
2598 (char *) &pSMBr->hdr.Protocol +
2599 data_offset,
2600 sizeof (FILE_UNIX_BASIC_INFO));
2601 }
2602 }
2603 cifs_buf_release(pSMB);
2604 if (rc == -EAGAIN)
2605 goto UnixQPathInfoRetry;
2606
2607 return rc;
2608 }
2609
2610 #if 0 /* function unused at present */
2611 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
2612 const char *searchName, FILE_ALL_INFO * findData,
2613 const struct nls_table *nls_codepage)
2614 {
2615 /* level 257 SMB_ */
2616 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2617 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2618 int rc = 0;
2619 int bytes_returned;
2620 int name_len;
2621 __u16 params, byte_count;
2622
2623 cFYI(1, ("In FindUnique"));
2624 findUniqueRetry:
2625 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2626 (void **) &pSMBr);
2627 if (rc)
2628 return rc;
2629
2630 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2631 name_len =
2632 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
2633 /* find define for this maxpathcomponent */
2634 , nls_codepage);
2635 name_len++; /* trailing null */
2636 name_len *= 2;
2637 } else { /* BB improve the check for buffer overruns BB */
2638 name_len = strnlen(searchName, PATH_MAX);
2639 name_len++; /* trailing null */
2640 strncpy(pSMB->FileName, searchName, name_len);
2641 }
2642
2643 params = 12 + name_len /* includes null */ ;
2644 pSMB->TotalDataCount = 0; /* no EAs */
2645 pSMB->MaxParameterCount = cpu_to_le16(2);
2646 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2647 pSMB->MaxSetupCount = 0;
2648 pSMB->Reserved = 0;
2649 pSMB->Flags = 0;
2650 pSMB->Timeout = 0;
2651 pSMB->Reserved2 = 0;
2652 pSMB->ParameterOffset = cpu_to_le16(
2653 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
2654 pSMB->DataCount = 0;
2655 pSMB->DataOffset = 0;
2656 pSMB->SetupCount = 1; /* one byte, no need to le convert */
2657 pSMB->Reserved3 = 0;
2658 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2659 byte_count = params + 1 /* pad */ ;
2660 pSMB->TotalParameterCount = cpu_to_le16(params);
2661 pSMB->ParameterCount = pSMB->TotalParameterCount;
2662 pSMB->SearchAttributes =
2663 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2664 ATTR_DIRECTORY);
2665 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
2666 pSMB->SearchFlags = cpu_to_le16(1);
2667 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2668 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
2669 pSMB->hdr.smb_buf_length += byte_count;
2670 pSMB->ByteCount = cpu_to_le16(byte_count);
2671
2672 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2673 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2674
2675 if (rc) {
2676 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
2677 } else { /* decode response */
2678 cifs_stats_inc(&tcon->num_ffirst);
2679 /* BB fill in */
2680 }
2681
2682 cifs_buf_release(pSMB);
2683 if (rc == -EAGAIN)
2684 goto findUniqueRetry;
2685
2686 return rc;
2687 }
2688 #endif /* end unused (temporarily) function */
2689
2690 /* xid, tcon, searchName and codepage are input parms, rest are returned */
2691 int
2692 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
2693 const char *searchName,
2694 const struct nls_table *nls_codepage,
2695 __u16 * pnetfid,
2696 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
2697 {
2698 /* level 257 SMB_ */
2699 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2700 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2701 T2_FFIRST_RSP_PARMS * parms;
2702 int rc = 0;
2703 int bytes_returned = 0;
2704 int name_len;
2705 __u16 params, byte_count;
2706
2707 cFYI(1, ("In FindFirst for %s",searchName));
2708
2709 findFirstRetry:
2710 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2711 (void **) &pSMBr);
2712 if (rc)
2713 return rc;
2714
2715 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2716 name_len =
2717 cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
2718 PATH_MAX, nls_codepage, remap);
2719 /* We can not add the asterik earlier in case
2720 it got remapped to 0xF03A as if it were part of the
2721 directory name instead of a wildcard */
2722 name_len *= 2;
2723 pSMB->FileName[name_len] = dirsep;
2724 pSMB->FileName[name_len+1] = 0;
2725 pSMB->FileName[name_len+2] = '*';
2726 pSMB->FileName[name_len+3] = 0;
2727 name_len += 4; /* now the trailing null */
2728 pSMB->FileName[name_len] = 0; /* null terminate just in case */
2729 pSMB->FileName[name_len+1] = 0;
2730 name_len += 2;
2731 } else { /* BB add check for overrun of SMB buf BB */
2732 name_len = strnlen(searchName, PATH_MAX);
2733 /* BB fix here and in unicode clause above ie
2734 if(name_len > buffersize-header)
2735 free buffer exit; BB */
2736 strncpy(pSMB->FileName, searchName, name_len);
2737 pSMB->FileName[name_len] = dirsep;
2738 pSMB->FileName[name_len+1] = '*';
2739 pSMB->FileName[name_len+2] = 0;
2740 name_len += 3;
2741 }
2742
2743 params = 12 + name_len /* includes null */ ;
2744 pSMB->TotalDataCount = 0; /* no EAs */
2745 pSMB->MaxParameterCount = cpu_to_le16(10);
2746 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
2747 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2748 pSMB->MaxSetupCount = 0;
2749 pSMB->Reserved = 0;
2750 pSMB->Flags = 0;
2751 pSMB->Timeout = 0;
2752 pSMB->Reserved2 = 0;
2753 byte_count = params + 1 /* pad */ ;
2754 pSMB->TotalParameterCount = cpu_to_le16(params);
2755 pSMB->ParameterCount = pSMB->TotalParameterCount;
2756 pSMB->ParameterOffset = cpu_to_le16(
2757 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
2758 pSMB->DataCount = 0;
2759 pSMB->DataOffset = 0;
2760 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
2761 pSMB->Reserved3 = 0;
2762 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2763 pSMB->SearchAttributes =
2764 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2765 ATTR_DIRECTORY);
2766 pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
2767 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
2768 CIFS_SEARCH_RETURN_RESUME);
2769 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2770
2771 /* BB what should we set StorageType to? Does it matter? BB */
2772 pSMB->SearchStorageType = 0;
2773 pSMB->hdr.smb_buf_length += byte_count;
2774 pSMB->ByteCount = cpu_to_le16(byte_count);
2775
2776 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2777 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2778 cifs_stats_inc(&tcon->num_ffirst);
2779
2780 if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
2781 /* BB Add code to handle unsupported level rc */
2782 cFYI(1, ("Error in FindFirst = %d", rc));
2783
2784 if (pSMB)
2785 cifs_buf_release(pSMB);
2786
2787 /* BB eventually could optimize out free and realloc of buf */
2788 /* for this case */
2789 if (rc == -EAGAIN)
2790 goto findFirstRetry;
2791 } else { /* decode response */
2792 /* BB remember to free buffer if error BB */
2793 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2794 if(rc == 0) {
2795 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2796 psrch_inf->unicode = TRUE;
2797 else
2798 psrch_inf->unicode = FALSE;
2799
2800 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
2801 psrch_inf->srch_entries_start =
2802 (char *) &pSMBr->hdr.Protocol +
2803 le16_to_cpu(pSMBr->t2.DataOffset);
2804 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
2805 le16_to_cpu(pSMBr->t2.ParameterOffset));
2806
2807 if(parms->EndofSearch)
2808 psrch_inf->endOfSearch = TRUE;
2809 else
2810 psrch_inf->endOfSearch = FALSE;
2811
2812 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2813 psrch_inf->index_of_last_entry =
2814 psrch_inf->entries_in_buffer;
2815 *pnetfid = parms->SearchHandle;
2816 } else {
2817 cifs_buf_release(pSMB);
2818 }
2819 }
2820
2821 return rc;
2822 }
2823
2824 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
2825 __u16 searchHandle, struct cifs_search_info * psrch_inf)
2826 {
2827 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
2828 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
2829 T2_FNEXT_RSP_PARMS * parms;
2830 char *response_data;
2831 int rc = 0;
2832 int bytes_returned, name_len;
2833 __u16 params, byte_count;
2834
2835 cFYI(1, ("In FindNext"));
2836
2837 if(psrch_inf->endOfSearch == TRUE)
2838 return -ENOENT;
2839
2840 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2841 (void **) &pSMBr);
2842 if (rc)
2843 return rc;
2844
2845 params = 14; /* includes 2 bytes of null string, converted to LE below */
2846 byte_count = 0;
2847 pSMB->TotalDataCount = 0; /* no EAs */
2848 pSMB->MaxParameterCount = cpu_to_le16(8);
2849 pSMB->MaxDataCount =
2850 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2851 pSMB->MaxSetupCount = 0;
2852 pSMB->Reserved = 0;
2853 pSMB->Flags = 0;
2854 pSMB->Timeout = 0;
2855 pSMB->Reserved2 = 0;
2856 pSMB->ParameterOffset = cpu_to_le16(
2857 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
2858 pSMB->DataCount = 0;
2859 pSMB->DataOffset = 0;
2860 pSMB->SetupCount = 1;
2861 pSMB->Reserved3 = 0;
2862 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
2863 pSMB->SearchHandle = searchHandle; /* always kept as le */
2864 pSMB->SearchCount =
2865 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
2866 /* test for Unix extensions */
2867 /* if (tcon->ses->capabilities & CAP_UNIX) {
2868 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
2869 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
2870 } else {
2871 pSMB->InformationLevel =
2872 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2873 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
2874 } */
2875 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2876 pSMB->ResumeKey = psrch_inf->resume_key;
2877 pSMB->SearchFlags =
2878 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
2879
2880 name_len = psrch_inf->resume_name_len;
2881 params += name_len;
2882 if(name_len < PATH_MAX) {
2883 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
2884 byte_count += name_len;
2885 /* 14 byte parm len above enough for 2 byte null terminator */
2886 pSMB->ResumeFileName[name_len] = 0;
2887 pSMB->ResumeFileName[name_len+1] = 0;
2888 } else {
2889 rc = -EINVAL;
2890 goto FNext2_err_exit;
2891 }
2892 byte_count = params + 1 /* pad */ ;
2893 pSMB->TotalParameterCount = cpu_to_le16(params);
2894 pSMB->ParameterCount = pSMB->TotalParameterCount;
2895 pSMB->hdr.smb_buf_length += byte_count;
2896 pSMB->ByteCount = cpu_to_le16(byte_count);
2897
2898 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2899 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2900 cifs_stats_inc(&tcon->num_fnext);
2901 if (rc) {
2902 if (rc == -EBADF) {
2903 psrch_inf->endOfSearch = TRUE;
2904 rc = 0; /* search probably was closed at end of search above */
2905 } else
2906 cFYI(1, ("FindNext returned = %d", rc));
2907 } else { /* decode response */
2908 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2909
2910 if(rc == 0) {
2911 /* BB fixme add lock for file (srch_info) struct here */
2912 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2913 psrch_inf->unicode = TRUE;
2914 else
2915 psrch_inf->unicode = FALSE;
2916 response_data = (char *) &pSMBr->hdr.Protocol +
2917 le16_to_cpu(pSMBr->t2.ParameterOffset);
2918 parms = (T2_FNEXT_RSP_PARMS *)response_data;
2919 response_data = (char *)&pSMBr->hdr.Protocol +
2920 le16_to_cpu(pSMBr->t2.DataOffset);
2921 cifs_buf_release(psrch_inf->ntwrk_buf_start);
2922 psrch_inf->srch_entries_start = response_data;
2923 psrch_inf->ntwrk_buf_start = (char *)pSMB;
2924 if(parms->EndofSearch)
2925 psrch_inf->endOfSearch = TRUE;
2926 else
2927 psrch_inf->endOfSearch = FALSE;
2928
2929 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2930 psrch_inf->index_of_last_entry +=
2931 psrch_inf->entries_in_buffer;
2932 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
2933
2934 /* BB fixme add unlock here */
2935 }
2936
2937 }
2938
2939 /* BB On error, should we leave previous search buf (and count and
2940 last entry fields) intact or free the previous one? */
2941
2942 /* Note: On -EAGAIN error only caller can retry on handle based calls
2943 since file handle passed in no longer valid */
2944 FNext2_err_exit:
2945 if (rc != 0)
2946 cifs_buf_release(pSMB);
2947
2948 return rc;
2949 }
2950
2951 int
2952 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
2953 {
2954 int rc = 0;
2955 FINDCLOSE_REQ *pSMB = NULL;
2956 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
2957 int bytes_returned;
2958
2959 cFYI(1, ("In CIFSSMBFindClose"));
2960 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
2961
2962 /* no sense returning error if session restarted
2963 as file handle has been closed */
2964 if(rc == -EAGAIN)
2965 return 0;
2966 if (rc)
2967 return rc;
2968
2969 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
2970 pSMB->FileID = searchHandle;
2971 pSMB->ByteCount = 0;
2972 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2973 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2974 if (rc) {
2975 cERROR(1, ("Send error in FindClose = %d", rc));
2976 }
2977 cifs_stats_inc(&tcon->num_fclose);
2978 cifs_small_buf_release(pSMB);
2979
2980 /* Since session is dead, search handle closed on server already */
2981 if (rc == -EAGAIN)
2982 rc = 0;
2983
2984 return rc;
2985 }
2986
2987 int
2988 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
2989 const unsigned char *searchName,
2990 __u64 * inode_number,
2991 const struct nls_table *nls_codepage, int remap)
2992 {
2993 int rc = 0;
2994 TRANSACTION2_QPI_REQ *pSMB = NULL;
2995 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2996 int name_len, bytes_returned;
2997 __u16 params, byte_count;
2998
2999 cFYI(1,("In GetSrvInodeNum for %s",searchName));
3000 if(tcon == NULL)
3001 return -ENODEV;
3002
3003 GetInodeNumberRetry:
3004 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3005 (void **) &pSMBr);
3006 if (rc)
3007 return rc;
3008
3009
3010 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3011 name_len =
3012 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3013 PATH_MAX,nls_codepage, remap);
3014 name_len++; /* trailing null */
3015 name_len *= 2;
3016 } else { /* BB improve the check for buffer overruns BB */
3017 name_len = strnlen(searchName, PATH_MAX);
3018 name_len++; /* trailing null */
3019 strncpy(pSMB->FileName, searchName, name_len);
3020 }
3021
3022 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3023 pSMB->TotalDataCount = 0;
3024 pSMB->MaxParameterCount = cpu_to_le16(2);
3025 /* BB find exact max data count below from sess structure BB */
3026 pSMB->MaxDataCount = cpu_to_le16(4000);
3027 pSMB->MaxSetupCount = 0;
3028 pSMB->Reserved = 0;
3029 pSMB->Flags = 0;
3030 pSMB->Timeout = 0;
3031 pSMB->Reserved2 = 0;
3032 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3033 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3034 pSMB->DataCount = 0;
3035 pSMB->DataOffset = 0;
3036 pSMB->SetupCount = 1;
3037 pSMB->Reserved3 = 0;
3038 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3039 byte_count = params + 1 /* pad */ ;
3040 pSMB->TotalParameterCount = cpu_to_le16(params);
3041 pSMB->ParameterCount = pSMB->TotalParameterCount;
3042 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3043 pSMB->Reserved4 = 0;
3044 pSMB->hdr.smb_buf_length += byte_count;
3045 pSMB->ByteCount = cpu_to_le16(byte_count);
3046
3047 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3048 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3049 if (rc) {
3050 cFYI(1, ("error %d in QueryInternalInfo", rc));
3051 } else {
3052 /* decode response */
3053 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3054 if (rc || (pSMBr->ByteCount < 2))
3055 /* BB also check enough total bytes returned */
3056 /* If rc should we check for EOPNOSUPP and
3057 disable the srvino flag? or in caller? */
3058 rc = -EIO; /* bad smb */
3059 else {
3060 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3061 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3062 struct file_internal_info * pfinfo;
3063 /* BB Do we need a cast or hash here ? */
3064 if(count < 8) {
3065 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3066 rc = -EIO;
3067 goto GetInodeNumOut;
3068 }
3069 pfinfo = (struct file_internal_info *)
3070 (data_offset + (char *) &pSMBr->hdr.Protocol);
3071 *inode_number = pfinfo->UniqueId;
3072 }
3073 }
3074 GetInodeNumOut:
3075 cifs_buf_release(pSMB);
3076 if (rc == -EAGAIN)
3077 goto GetInodeNumberRetry;
3078 return rc;
3079 }
3080
3081 int
3082 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3083 const unsigned char *searchName,
3084 unsigned char **targetUNCs,
3085 unsigned int *number_of_UNC_in_array,
3086 const struct nls_table *nls_codepage, int remap)
3087 {
3088 /* TRANS2_GET_DFS_REFERRAL */
3089 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3090 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3091 struct dfs_referral_level_3 * referrals = NULL;
3092 int rc = 0;
3093 int bytes_returned;
3094 int name_len;
3095 unsigned int i;
3096 char * temp;
3097 __u16 params, byte_count;
3098 *number_of_UNC_in_array = 0;
3099 *targetUNCs = NULL;
3100
3101 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3102 if (ses == NULL)
3103 return -ENODEV;
3104 getDFSRetry:
3105 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3106 (void **) &pSMBr);
3107 if (rc)
3108 return rc;
3109
3110 /* server pointer checked in called function,
3111 but should never be null here anyway */
3112 pSMB->hdr.Mid = GetNextMid(ses->server);
3113 pSMB->hdr.Tid = ses->ipc_tid;
3114 pSMB->hdr.Uid = ses->Suid;
3115 if (ses->capabilities & CAP_STATUS32) {
3116 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3117 }
3118 if (ses->capabilities & CAP_DFS) {
3119 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3120 }
3121
3122 if (ses->capabilities & CAP_UNICODE) {
3123 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3124 name_len =
3125 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3126 searchName, PATH_MAX, nls_codepage, remap);
3127 name_len++; /* trailing null */
3128 name_len *= 2;
3129 } else { /* BB improve the check for buffer overruns BB */
3130 name_len = strnlen(searchName, PATH_MAX);
3131 name_len++; /* trailing null */
3132 strncpy(pSMB->RequestFileName, searchName, name_len);
3133 }
3134
3135 params = 2 /* level */ + name_len /*includes null */ ;
3136 pSMB->TotalDataCount = 0;
3137 pSMB->DataCount = 0;
3138 pSMB->DataOffset = 0;
3139 pSMB->MaxParameterCount = 0;
3140 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3141 pSMB->MaxSetupCount = 0;
3142 pSMB->Reserved = 0;
3143 pSMB->Flags = 0;
3144 pSMB->Timeout = 0;
3145 pSMB->Reserved2 = 0;
3146 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3147 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3148 pSMB->SetupCount = 1;
3149 pSMB->Reserved3 = 0;
3150 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3151 byte_count = params + 3 /* pad */ ;
3152 pSMB->ParameterCount = cpu_to_le16(params);
3153 pSMB->TotalParameterCount = pSMB->ParameterCount;
3154 pSMB->MaxReferralLevel = cpu_to_le16(3);
3155 pSMB->hdr.smb_buf_length += byte_count;
3156 pSMB->ByteCount = cpu_to_le16(byte_count);
3157
3158 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3159 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3160 if (rc) {
3161 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3162 } else { /* decode response */
3163 /* BB Add logic to parse referrals here */
3164 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3165
3166 if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
3167 rc = -EIO; /* bad smb */
3168 else {
3169 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3170 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3171
3172 cFYI(1,
3173 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
3174 pSMBr->ByteCount, data_offset));
3175 referrals =
3176 (struct dfs_referral_level_3 *)
3177 (8 /* sizeof start of data block */ +
3178 data_offset +
3179 (char *) &pSMBr->hdr.Protocol);
3180 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",
3181 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)));
3182 /* BB This field is actually two bytes in from start of
3183 data block so we could do safety check that DataBlock
3184 begins at address of pSMBr->NumberOfReferrals */
3185 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
3186
3187 /* BB Fix below so can return more than one referral */
3188 if(*number_of_UNC_in_array > 1)
3189 *number_of_UNC_in_array = 1;
3190
3191 /* get the length of the strings describing refs */
3192 name_len = 0;
3193 for(i=0;i<*number_of_UNC_in_array;i++) {
3194 /* make sure that DfsPathOffset not past end */
3195 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
3196 if (offset > data_count) {
3197 /* if invalid referral, stop here and do
3198 not try to copy any more */
3199 *number_of_UNC_in_array = i;
3200 break;
3201 }
3202 temp = ((char *)referrals) + offset;
3203
3204 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3205 name_len += UniStrnlen((wchar_t *)temp,data_count);
3206 } else {
3207 name_len += strnlen(temp,data_count);
3208 }
3209 referrals++;
3210 /* BB add check that referral pointer does not fall off end PDU */
3211
3212 }
3213 /* BB add check for name_len bigger than bcc */
3214 *targetUNCs =
3215 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
3216 if(*targetUNCs == NULL) {
3217 rc = -ENOMEM;
3218 goto GetDFSRefExit;
3219 }
3220 /* copy the ref strings */
3221 referrals =
3222 (struct dfs_referral_level_3 *)
3223 (8 /* sizeof data hdr */ +
3224 data_offset +
3225 (char *) &pSMBr->hdr.Protocol);
3226
3227 for(i=0;i<*number_of_UNC_in_array;i++) {
3228 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
3229 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3230 cifs_strfromUCS_le(*targetUNCs,
3231 (__le16 *) temp, name_len, nls_codepage);
3232 } else {
3233 strncpy(*targetUNCs,temp,name_len);
3234 }
3235 /* BB update target_uncs pointers */
3236 referrals++;
3237 }
3238 temp = *targetUNCs;
3239 temp[name_len] = 0;
3240 }
3241
3242 }
3243 GetDFSRefExit:
3244 if (pSMB)
3245 cifs_buf_release(pSMB);
3246
3247 if (rc == -EAGAIN)
3248 goto getDFSRetry;
3249
3250 return rc;
3251 }
3252
3253 /* Query File System Info such as free space to old servers such as Win 9x */
3254 int
3255 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3256 {
3257 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
3258 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3259 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3260 FILE_SYSTEM_ALLOC_INFO *response_data;
3261 int rc = 0;
3262 int bytes_returned = 0;
3263 __u16 params, byte_count;
3264
3265 cFYI(1, ("OldQFSInfo"));
3266 oldQFSInfoRetry:
3267 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3268 (void **) &pSMBr);
3269 if (rc)
3270 return rc;
3271 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3272 (void **) &pSMBr);
3273 if (rc)
3274 return rc;
3275
3276 params = 2; /* level */
3277 pSMB->TotalDataCount = 0;
3278 pSMB->MaxParameterCount = cpu_to_le16(2);
3279 pSMB->MaxDataCount = cpu_to_le16(1000);
3280 pSMB->MaxSetupCount = 0;
3281 pSMB->Reserved = 0;
3282 pSMB->Flags = 0;
3283 pSMB->Timeout = 0;
3284 pSMB->Reserved2 = 0;
3285 byte_count = params + 1 /* pad */ ;
3286 pSMB->TotalParameterCount = cpu_to_le16(params);
3287 pSMB->ParameterCount = pSMB->TotalParameterCount;
3288 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3289 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3290 pSMB->DataCount = 0;
3291 pSMB->DataOffset = 0;
3292 pSMB->SetupCount = 1;
3293 pSMB->Reserved3 = 0;
3294 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3295 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
3296 pSMB->hdr.smb_buf_length += byte_count;
3297 pSMB->ByteCount = cpu_to_le16(byte_count);
3298
3299 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3300 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3301 if (rc) {
3302 cFYI(1, ("Send error in QFSInfo = %d", rc));
3303 } else { /* decode response */
3304 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3305
3306 if (rc || (pSMBr->ByteCount < 18))
3307 rc = -EIO; /* bad smb */
3308 else {
3309 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3310 cFYI(1,("qfsinf resp BCC: %d Offset %d",
3311 pSMBr->ByteCount, data_offset));
3312
3313 response_data =
3314 (FILE_SYSTEM_ALLOC_INFO *)
3315 (((char *) &pSMBr->hdr.Protocol) + data_offset);
3316 FSData->f_bsize =
3317 le16_to_cpu(response_data->BytesPerSector) *
3318 le32_to_cpu(response_data->
3319 SectorsPerAllocationUnit);
3320 FSData->f_blocks =
3321 le32_to_cpu(response_data->TotalAllocationUnits);
3322 FSData->f_bfree = FSData->f_bavail =
3323 le32_to_cpu(response_data->FreeAllocationUnits);
3324 cFYI(1,
3325 ("Blocks: %lld Free: %lld Block size %ld",
3326 (unsigned long long)FSData->f_blocks,
3327 (unsigned long long)FSData->f_bfree,
3328 FSData->f_bsize));
3329 }
3330 }
3331 cifs_buf_release(pSMB);
3332
3333 if (rc == -EAGAIN)
3334 goto oldQFSInfoRetry;
3335
3336 return rc;
3337 }
3338
3339 int
3340 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3341 {
3342 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
3343 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3344 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3345 FILE_SYSTEM_INFO *response_data;
3346 int rc = 0;
3347 int bytes_returned = 0;
3348 __u16 params, byte_count;
3349
3350 cFYI(1, ("In QFSInfo"));
3351 QFSInfoRetry:
3352 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3353 (void **) &pSMBr);
3354 if (rc)
3355 return rc;
3356
3357 params = 2; /* level */
3358 pSMB->TotalDataCount = 0;
3359 pSMB->MaxParameterCount = cpu_to_le16(2);
3360 pSMB->MaxDataCount = cpu_to_le16(1000);
3361 pSMB->MaxSetupCount = 0;
3362 pSMB->Reserved = 0;
3363 pSMB->Flags = 0;
3364 pSMB->Timeout = 0;
3365 pSMB->Reserved2 = 0;
3366 byte_count = params + 1 /* pad */ ;
3367 pSMB->TotalParameterCount = cpu_to_le16(params);
3368 pSMB->ParameterCount = pSMB->TotalParameterCount;
3369 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3370 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3371 pSMB->DataCount = 0;
3372 pSMB->DataOffset = 0;
3373 pSMB->SetupCount = 1;
3374 pSMB->Reserved3 = 0;
3375 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3376 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
3377 pSMB->hdr.smb_buf_length += byte_count;
3378 pSMB->ByteCount = cpu_to_le16(byte_count);
3379
3380 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3381 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3382 if (rc) {
3383 cFYI(1, ("Send error in QFSInfo = %d", rc));
3384 } else { /* decode response */
3385 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3386
3387 if (rc || (pSMBr->ByteCount < 24))
3388 rc = -EIO; /* bad smb */
3389 else {
3390 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3391
3392 response_data =
3393 (FILE_SYSTEM_INFO
3394 *) (((char *) &pSMBr->hdr.Protocol) +
3395 data_offset);
3396 FSData->f_bsize =
3397 le32_to_cpu(response_data->BytesPerSector) *
3398 le32_to_cpu(response_data->
3399 SectorsPerAllocationUnit);
3400 FSData->f_blocks =
3401 le64_to_cpu(response_data->TotalAllocationUnits);
3402 FSData->f_bfree = FSData->f_bavail =
3403 le64_to_cpu(response_data->FreeAllocationUnits);
3404 cFYI(1,
3405 ("Blocks: %lld Free: %lld Block size %ld",
3406 (unsigned long long)FSData->f_blocks,
3407 (unsigned long long)FSData->f_bfree,
3408 FSData->f_bsize));
3409 }
3410 }
3411 cifs_buf_release(pSMB);
3412
3413 if (rc == -EAGAIN)
3414 goto QFSInfoRetry;
3415
3416 return rc;
3417 }
3418
3419 int
3420 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
3421 {
3422 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3423 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3424 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3425 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
3426 int rc = 0;
3427 int bytes_returned = 0;
3428 __u16 params, byte_count;
3429
3430 cFYI(1, ("In QFSAttributeInfo"));
3431 QFSAttributeRetry:
3432 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3433 (void **) &pSMBr);
3434 if (rc)
3435 return rc;
3436
3437 params = 2; /* level */
3438 pSMB->TotalDataCount = 0;
3439 pSMB->MaxParameterCount = cpu_to_le16(2);
3440 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3441 pSMB->MaxSetupCount = 0;
3442 pSMB->Reserved = 0;
3443 pSMB->Flags = 0;
3444 pSMB->Timeout = 0;
3445 pSMB->Reserved2 = 0;
3446 byte_count = params + 1 /* pad */ ;
3447 pSMB->TotalParameterCount = cpu_to_le16(params);
3448 pSMB->ParameterCount = pSMB->TotalParameterCount;
3449 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3450 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3451 pSMB->DataCount = 0;
3452 pSMB->DataOffset = 0;
3453 pSMB->SetupCount = 1;
3454 pSMB->Reserved3 = 0;
3455 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3456 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
3457 pSMB->hdr.smb_buf_length += byte_count;
3458 pSMB->ByteCount = cpu_to_le16(byte_count);
3459
3460 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3461 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3462 if (rc) {
3463 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
3464 } else { /* decode response */
3465 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3466
3467 if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
3468 rc = -EIO; /* bad smb */
3469 } else {
3470 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3471 response_data =
3472 (FILE_SYSTEM_ATTRIBUTE_INFO
3473 *) (((char *) &pSMBr->hdr.Protocol) +
3474 data_offset);
3475 memcpy(&tcon->fsAttrInfo, response_data,
3476 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
3477 }
3478 }
3479 cifs_buf_release(pSMB);
3480
3481 if (rc == -EAGAIN)
3482 goto QFSAttributeRetry;
3483
3484 return rc;
3485 }
3486
3487 int
3488 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
3489 {
3490 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3491 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3492 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3493 FILE_SYSTEM_DEVICE_INFO *response_data;
3494 int rc = 0;
3495 int bytes_returned = 0;
3496 __u16 params, byte_count;
3497
3498 cFYI(1, ("In QFSDeviceInfo"));
3499 QFSDeviceRetry:
3500 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3501 (void **) &pSMBr);
3502 if (rc)
3503 return rc;
3504
3505 params = 2; /* level */
3506 pSMB->TotalDataCount = 0;
3507 pSMB->MaxParameterCount = cpu_to_le16(2);
3508 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3509 pSMB->MaxSetupCount = 0;
3510 pSMB->Reserved = 0;
3511 pSMB->Flags = 0;
3512 pSMB->Timeout = 0;
3513 pSMB->Reserved2 = 0;
3514 byte_count = params + 1 /* pad */ ;
3515 pSMB->TotalParameterCount = cpu_to_le16(params);
3516 pSMB->ParameterCount = pSMB->TotalParameterCount;
3517 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3518 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3519
3520 pSMB->DataCount = 0;
3521 pSMB->DataOffset = 0;
3522 pSMB->SetupCount = 1;
3523 pSMB->Reserved3 = 0;
3524 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3525 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
3526 pSMB->hdr.smb_buf_length += byte_count;
3527 pSMB->ByteCount = cpu_to_le16(byte_count);
3528
3529 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3530 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3531 if (rc) {
3532 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
3533 } else { /* decode response */
3534 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3535
3536 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
3537 rc = -EIO; /* bad smb */
3538 else {
3539 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3540 response_data =
3541 (FILE_SYSTEM_DEVICE_INFO *)
3542 (((char *) &pSMBr->hdr.Protocol) +
3543 data_offset);
3544 memcpy(&tcon->fsDevInfo, response_data,
3545 sizeof (FILE_SYSTEM_DEVICE_INFO));
3546 }
3547 }
3548 cifs_buf_release(pSMB);
3549
3550 if (rc == -EAGAIN)
3551 goto QFSDeviceRetry;
3552
3553 return rc;
3554 }
3555
3556 int
3557 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
3558 {
3559 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
3560 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3561 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3562 FILE_SYSTEM_UNIX_INFO *response_data;
3563 int rc = 0;
3564 int bytes_returned = 0;
3565 __u16 params, byte_count;
3566
3567 cFYI(1, ("In QFSUnixInfo"));
3568 QFSUnixRetry:
3569 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3570 (void **) &pSMBr);
3571 if (rc)
3572 return rc;
3573
3574 params = 2; /* level */
3575 pSMB->TotalDataCount = 0;
3576 pSMB->DataCount = 0;
3577 pSMB->DataOffset = 0;
3578 pSMB->MaxParameterCount = cpu_to_le16(2);
3579 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3580 pSMB->MaxSetupCount = 0;
3581 pSMB->Reserved = 0;
3582 pSMB->Flags = 0;
3583 pSMB->Timeout = 0;
3584 pSMB->Reserved2 = 0;
3585 byte_count = params + 1 /* pad */ ;
3586 pSMB->ParameterCount = cpu_to_le16(params);
3587 pSMB->TotalParameterCount = pSMB->ParameterCount;
3588 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3589 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3590 pSMB->SetupCount = 1;
3591 pSMB->Reserved3 = 0;
3592 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3593 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
3594 pSMB->hdr.smb_buf_length += byte_count;
3595 pSMB->ByteCount = cpu_to_le16(byte_count);
3596
3597 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3598 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3599 if (rc) {
3600 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
3601 } else { /* decode response */
3602 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3603
3604 if (rc || (pSMBr->ByteCount < 13)) {
3605 rc = -EIO; /* bad smb */
3606 } else {
3607 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3608 response_data =
3609 (FILE_SYSTEM_UNIX_INFO
3610 *) (((char *) &pSMBr->hdr.Protocol) +
3611 data_offset);
3612 memcpy(&tcon->fsUnixInfo, response_data,
3613 sizeof (FILE_SYSTEM_UNIX_INFO));
3614 }
3615 }
3616 cifs_buf_release(pSMB);
3617
3618 if (rc == -EAGAIN)
3619 goto QFSUnixRetry;
3620
3621
3622 return rc;
3623 }
3624
3625 int
3626 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
3627 {
3628 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
3629 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
3630 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
3631 int rc = 0;
3632 int bytes_returned = 0;
3633 __u16 params, param_offset, offset, byte_count;
3634
3635 cFYI(1, ("In SETFSUnixInfo"));
3636 SETFSUnixRetry:
3637 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3638 (void **) &pSMBr);
3639 if (rc)
3640 return rc;
3641
3642 params = 4; /* 2 bytes zero followed by info level. */
3643 pSMB->MaxSetupCount = 0;
3644 pSMB->Reserved = 0;
3645 pSMB->Flags = 0;
3646 pSMB->Timeout = 0;
3647 pSMB->Reserved2 = 0;
3648 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
3649 offset = param_offset + params;
3650
3651 pSMB->MaxParameterCount = cpu_to_le16(4);
3652 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3653 pSMB->SetupCount = 1;
3654 pSMB->Reserved3 = 0;
3655 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
3656 byte_count = 1 /* pad */ + params + 12;
3657
3658 pSMB->DataCount = cpu_to_le16(12);
3659 pSMB->ParameterCount = cpu_to_le16(params);
3660 pSMB->TotalDataCount = pSMB->DataCount;
3661 pSMB->TotalParameterCount = pSMB->ParameterCount;
3662 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3663 pSMB->DataOffset = cpu_to_le16(offset);
3664
3665 /* Params. */
3666 pSMB->FileNum = 0;
3667 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
3668
3669 /* Data. */
3670 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
3671 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
3672 pSMB->ClientUnixCap = cpu_to_le64(cap);
3673
3674 pSMB->hdr.smb_buf_length += byte_count;
3675 pSMB->ByteCount = cpu_to_le16(byte_count);
3676
3677 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3678 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3679 if (rc) {
3680 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
3681 } else { /* decode response */
3682 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3683 if (rc) {
3684 rc = -EIO; /* bad smb */
3685 }
3686 }
3687 cifs_buf_release(pSMB);
3688
3689 if (rc == -EAGAIN)
3690 goto SETFSUnixRetry;
3691
3692 return rc;
3693 }
3694
3695
3696
3697 int
3698 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
3699 struct kstatfs *FSData)
3700 {
3701 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
3702 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3703 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3704 FILE_SYSTEM_POSIX_INFO *response_data;
3705 int rc = 0;
3706 int bytes_returned = 0;
3707 __u16 params, byte_count;
3708
3709 cFYI(1, ("In QFSPosixInfo"));
3710 QFSPosixRetry:
3711 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3712 (void **) &pSMBr);
3713 if (rc)
3714 return rc;
3715
3716 params = 2; /* level */
3717 pSMB->TotalDataCount = 0;
3718 pSMB->DataCount = 0;
3719 pSMB->DataOffset = 0;
3720 pSMB->MaxParameterCount = cpu_to_le16(2);
3721 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3722 pSMB->MaxSetupCount = 0;
3723 pSMB->Reserved = 0;
3724 pSMB->Flags = 0;
3725 pSMB->Timeout = 0;
3726 pSMB->Reserved2 = 0;
3727 byte_count = params + 1 /* pad */ ;
3728 pSMB->ParameterCount = cpu_to_le16(params);
3729 pSMB->TotalParameterCount = pSMB->ParameterCount;
3730 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3731 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3732 pSMB->SetupCount = 1;
3733 pSMB->Reserved3 = 0;
3734 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3735 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
3736 pSMB->hdr.smb_buf_length += byte_count;
3737 pSMB->ByteCount = cpu_to_le16(byte_count);
3738
3739 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3740 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3741 if (rc) {
3742 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
3743 } else { /* decode response */
3744 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3745
3746 if (rc || (pSMBr->ByteCount < 13)) {
3747 rc = -EIO; /* bad smb */
3748 } else {
3749 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3750 response_data =
3751 (FILE_SYSTEM_POSIX_INFO
3752 *) (((char *) &pSMBr->hdr.Protocol) +
3753 data_offset);
3754 FSData->f_bsize =
3755 le32_to_cpu(response_data->BlockSize);
3756 FSData->f_blocks =
3757 le64_to_cpu(response_data->TotalBlocks);
3758 FSData->f_bfree =
3759 le64_to_cpu(response_data->BlocksAvail);
3760 if(response_data->UserBlocksAvail == cpu_to_le64(-1)) {
3761 FSData->f_bavail = FSData->f_bfree;
3762 } else {
3763 FSData->f_bavail =
3764 le64_to_cpu(response_data->UserBlocksAvail);
3765 }
3766 if(response_data->TotalFileNodes != cpu_to_le64(-1))
3767 FSData->f_files =
3768 le64_to_cpu(response_data->TotalFileNodes);
3769 if(response_data->FreeFileNodes != cpu_to_le64(-1))
3770 FSData->f_ffree =
3771 le64_to_cpu(response_data->FreeFileNodes);
3772 }
3773 }
3774 cifs_buf_release(pSMB);
3775
3776 if (rc == -EAGAIN)
3777 goto QFSPosixRetry;
3778
3779 return rc;
3780 }
3781
3782
3783 /* We can not use write of zero bytes trick to
3784 set file size due to need for large file support. Also note that
3785 this SetPathInfo is preferred to SetFileInfo based method in next
3786 routine which is only needed to work around a sharing violation bug
3787 in Samba which this routine can run into */
3788
3789 int
3790 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3791 __u64 size, int SetAllocation,
3792 const struct nls_table *nls_codepage, int remap)
3793 {
3794 struct smb_com_transaction2_spi_req *pSMB = NULL;
3795 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3796 struct file_end_of_file_info *parm_data;
3797 int name_len;
3798 int rc = 0;
3799 int bytes_returned = 0;
3800 __u16 params, byte_count, data_count, param_offset, offset;
3801
3802 cFYI(1, ("In SetEOF"));
3803 SetEOFRetry:
3804 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3805 (void **) &pSMBr);
3806 if (rc)
3807 return rc;
3808
3809 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3810 name_len =
3811 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3812 PATH_MAX, nls_codepage, remap);
3813 name_len++; /* trailing null */
3814 name_len *= 2;
3815 } else { /* BB improve the check for buffer overruns BB */
3816 name_len = strnlen(fileName, PATH_MAX);
3817 name_len++; /* trailing null */
3818 strncpy(pSMB->FileName, fileName, name_len);
3819 }
3820 params = 6 + name_len;
3821 data_count = sizeof (struct file_end_of_file_info);
3822 pSMB->MaxParameterCount = cpu_to_le16(2);
3823 pSMB->MaxDataCount = cpu_to_le16(4100);
3824 pSMB->MaxSetupCount = 0;
3825 pSMB->Reserved = 0;
3826 pSMB->Flags = 0;
3827 pSMB->Timeout = 0;
3828 pSMB->Reserved2 = 0;
3829 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3830 InformationLevel) - 4;
3831 offset = param_offset + params;
3832 if(SetAllocation) {
3833 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3834 pSMB->InformationLevel =
3835 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3836 else
3837 pSMB->InformationLevel =
3838 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3839 } else /* Set File Size */ {
3840 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3841 pSMB->InformationLevel =
3842 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3843 else
3844 pSMB->InformationLevel =
3845 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3846 }
3847
3848 parm_data =
3849 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3850 offset);
3851 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3852 pSMB->DataOffset = cpu_to_le16(offset);
3853 pSMB->SetupCount = 1;
3854 pSMB->Reserved3 = 0;
3855 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3856 byte_count = 3 /* pad */ + params + data_count;
3857 pSMB->DataCount = cpu_to_le16(data_count);
3858 pSMB->TotalDataCount = pSMB->DataCount;
3859 pSMB->ParameterCount = cpu_to_le16(params);
3860 pSMB->TotalParameterCount = pSMB->ParameterCount;
3861 pSMB->Reserved4 = 0;
3862 pSMB->hdr.smb_buf_length += byte_count;
3863 parm_data->FileSize = cpu_to_le64(size);
3864 pSMB->ByteCount = cpu_to_le16(byte_count);
3865 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3866 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3867 if (rc) {
3868 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
3869 }
3870
3871 cifs_buf_release(pSMB);
3872
3873 if (rc == -EAGAIN)
3874 goto SetEOFRetry;
3875
3876 return rc;
3877 }
3878
3879 int
3880 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
3881 __u16 fid, __u32 pid_of_opener, int SetAllocation)
3882 {
3883 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3884 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3885 char *data_offset;
3886 struct file_end_of_file_info *parm_data;
3887 int rc = 0;
3888 int bytes_returned = 0;
3889 __u16 params, param_offset, offset, byte_count, count;
3890
3891 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
3892 (long long)size));
3893 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3894
3895 if (rc)
3896 return rc;
3897
3898 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3899
3900 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3901 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
3902
3903 params = 6;
3904 pSMB->MaxSetupCount = 0;
3905 pSMB->Reserved = 0;
3906 pSMB->Flags = 0;
3907 pSMB->Timeout = 0;
3908 pSMB->Reserved2 = 0;
3909 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3910 offset = param_offset + params;
3911
3912 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3913
3914 count = sizeof(struct file_end_of_file_info);
3915 pSMB->MaxParameterCount = cpu_to_le16(2);
3916 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3917 pSMB->SetupCount = 1;
3918 pSMB->Reserved3 = 0;
3919 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3920 byte_count = 3 /* pad */ + params + count;
3921 pSMB->DataCount = cpu_to_le16(count);
3922 pSMB->ParameterCount = cpu_to_le16(params);
3923 pSMB->TotalDataCount = pSMB->DataCount;
3924 pSMB->TotalParameterCount = pSMB->ParameterCount;
3925 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3926 parm_data =
3927 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3928 offset);
3929 pSMB->DataOffset = cpu_to_le16(offset);
3930 parm_data->FileSize = cpu_to_le64(size);
3931 pSMB->Fid = fid;
3932 if(SetAllocation) {
3933 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3934 pSMB->InformationLevel =
3935 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3936 else
3937 pSMB->InformationLevel =
3938 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3939 } else /* Set File Size */ {
3940 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3941 pSMB->InformationLevel =
3942 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3943 else
3944 pSMB->InformationLevel =
3945 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3946 }
3947 pSMB->Reserved4 = 0;
3948 pSMB->hdr.smb_buf_length += byte_count;
3949 pSMB->ByteCount = cpu_to_le16(byte_count);
3950 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3951 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3952 if (rc) {
3953 cFYI(1,
3954 ("Send error in SetFileInfo (SetFileSize) = %d",
3955 rc));
3956 }
3957
3958 if (pSMB)
3959 cifs_small_buf_release(pSMB);
3960
3961 /* Note: On -EAGAIN error only caller can retry on handle based calls
3962 since file handle passed in no longer valid */
3963
3964 return rc;
3965 }
3966
3967 /* Some legacy servers such as NT4 require that the file times be set on
3968 an open handle, rather than by pathname - this is awkward due to
3969 potential access conflicts on the open, but it is unavoidable for these
3970 old servers since the only other choice is to go from 100 nanosecond DCE
3971 time and resort to the original setpathinfo level which takes the ancient
3972 DOS time format with 2 second granularity */
3973 int
3974 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
3975 __u16 fid)
3976 {
3977 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3978 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3979 char *data_offset;
3980 int rc = 0;
3981 int bytes_returned = 0;
3982 __u16 params, param_offset, offset, byte_count, count;
3983
3984 cFYI(1, ("Set Times (via SetFileInfo)"));
3985 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3986
3987 if (rc)
3988 return rc;
3989
3990 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3991
3992 /* At this point there is no need to override the current pid
3993 with the pid of the opener, but that could change if we someday
3994 use an existing handle (rather than opening one on the fly) */
3995 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3996 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
3997
3998 params = 6;
3999 pSMB->MaxSetupCount = 0;
4000 pSMB->Reserved = 0;
4001 pSMB->Flags = 0;
4002 pSMB->Timeout = 0;
4003 pSMB->Reserved2 = 0;
4004 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4005 offset = param_offset + params;
4006
4007 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4008
4009 count = sizeof (FILE_BASIC_INFO);
4010 pSMB->MaxParameterCount = cpu_to_le16(2);
4011 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4012 pSMB->SetupCount = 1;
4013 pSMB->Reserved3 = 0;
4014 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4015 byte_count = 3 /* pad */ + params + count;
4016 pSMB->DataCount = cpu_to_le16(count);
4017 pSMB->ParameterCount = cpu_to_le16(params);
4018 pSMB->TotalDataCount = pSMB->DataCount;
4019 pSMB->TotalParameterCount = pSMB->ParameterCount;
4020 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4021 pSMB->DataOffset = cpu_to_le16(offset);
4022 pSMB->Fid = fid;
4023 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4024 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4025 else
4026 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4027 pSMB->Reserved4 = 0;
4028 pSMB->hdr.smb_buf_length += byte_count;
4029 pSMB->ByteCount = cpu_to_le16(byte_count);
4030 memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
4031 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4032 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4033 if (rc) {
4034 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
4035 }
4036
4037 cifs_small_buf_release(pSMB);
4038
4039 /* Note: On -EAGAIN error only caller can retry on handle based calls
4040 since file handle passed in no longer valid */
4041
4042 return rc;
4043 }
4044
4045
4046 int
4047 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4048 const FILE_BASIC_INFO * data,
4049 const struct nls_table *nls_codepage, int remap)
4050 {
4051 TRANSACTION2_SPI_REQ *pSMB = NULL;
4052 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4053 int name_len;
4054 int rc = 0;
4055 int bytes_returned = 0;
4056 char *data_offset;
4057 __u16 params, param_offset, offset, byte_count, count;
4058
4059 cFYI(1, ("In SetTimes"));
4060
4061 SetTimesRetry:
4062 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4063 (void **) &pSMBr);
4064 if (rc)
4065 return rc;
4066
4067 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4068 name_len =
4069 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4070 PATH_MAX, nls_codepage, remap);
4071 name_len++; /* trailing null */
4072 name_len *= 2;
4073 } else { /* BB improve the check for buffer overruns BB */
4074 name_len = strnlen(fileName, PATH_MAX);
4075 name_len++; /* trailing null */
4076 strncpy(pSMB->FileName, fileName, name_len);
4077 }
4078
4079 params = 6 + name_len;
4080 count = sizeof (FILE_BASIC_INFO);
4081 pSMB->MaxParameterCount = cpu_to_le16(2);
4082 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4083 pSMB->MaxSetupCount = 0;
4084 pSMB->Reserved = 0;
4085 pSMB->Flags = 0;
4086 pSMB->Timeout = 0;
4087 pSMB->Reserved2 = 0;
4088 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4089 InformationLevel) - 4;
4090 offset = param_offset + params;
4091 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4092 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4093 pSMB->DataOffset = cpu_to_le16(offset);
4094 pSMB->SetupCount = 1;
4095 pSMB->Reserved3 = 0;
4096 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4097 byte_count = 3 /* pad */ + params + count;
4098
4099 pSMB->DataCount = cpu_to_le16(count);
4100 pSMB->ParameterCount = cpu_to_le16(params);
4101 pSMB->TotalDataCount = pSMB->DataCount;
4102 pSMB->TotalParameterCount = pSMB->ParameterCount;
4103 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4104 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4105 else
4106 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4107 pSMB->Reserved4 = 0;
4108 pSMB->hdr.smb_buf_length += byte_count;
4109 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
4110 pSMB->ByteCount = cpu_to_le16(byte_count);
4111 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4112 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4113 if (rc) {
4114 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4115 }
4116
4117 cifs_buf_release(pSMB);
4118
4119 if (rc == -EAGAIN)
4120 goto SetTimesRetry;
4121
4122 return rc;
4123 }
4124
4125 /* Can not be used to set time stamps yet (due to old DOS time format) */
4126 /* Can be used to set attributes */
4127 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4128 handling it anyway and NT4 was what we thought it would be needed for
4129 Do not delete it until we prove whether needed for Win9x though */
4130 int
4131 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4132 __u16 dos_attrs, const struct nls_table *nls_codepage)
4133 {
4134 SETATTR_REQ *pSMB = NULL;
4135 SETATTR_RSP *pSMBr = NULL;
4136 int rc = 0;
4137 int bytes_returned;
4138 int name_len;
4139
4140 cFYI(1, ("In SetAttrLegacy"));
4141
4142 SetAttrLgcyRetry:
4143 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4144 (void **) &pSMBr);
4145 if (rc)
4146 return rc;
4147
4148 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4149 name_len =
4150 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4151 PATH_MAX, nls_codepage);
4152 name_len++; /* trailing null */
4153 name_len *= 2;
4154 } else { /* BB improve the check for buffer overruns BB */
4155 name_len = strnlen(fileName, PATH_MAX);
4156 name_len++; /* trailing null */
4157 strncpy(pSMB->fileName, fileName, name_len);
4158 }
4159 pSMB->attr = cpu_to_le16(dos_attrs);
4160 pSMB->BufferFormat = 0x04;
4161 pSMB->hdr.smb_buf_length += name_len + 1;
4162 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4163 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4164 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4165 if (rc) {
4166 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4167 }
4168
4169 cifs_buf_release(pSMB);
4170
4171 if (rc == -EAGAIN)
4172 goto SetAttrLgcyRetry;
4173
4174 return rc;
4175 }
4176 #endif /* temporarily unneeded SetAttr legacy function */
4177
4178 int
4179 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4180 char *fileName, __u64 mode, __u64 uid, __u64 gid,
4181 dev_t device, const struct nls_table *nls_codepage,
4182 int remap)
4183 {
4184 TRANSACTION2_SPI_REQ *pSMB = NULL;
4185 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4186 int name_len;
4187 int rc = 0;
4188 int bytes_returned = 0;
4189 FILE_UNIX_BASIC_INFO *data_offset;
4190 __u16 params, param_offset, offset, count, byte_count;
4191
4192 cFYI(1, ("In SetUID/GID/Mode"));
4193 setPermsRetry:
4194 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4195 (void **) &pSMBr);
4196 if (rc)
4197 return rc;
4198
4199 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4200 name_len =
4201 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4202 PATH_MAX, nls_codepage, remap);
4203 name_len++; /* trailing null */
4204 name_len *= 2;
4205 } else { /* BB improve the check for buffer overruns BB */
4206 name_len = strnlen(fileName, PATH_MAX);
4207 name_len++; /* trailing null */
4208 strncpy(pSMB->FileName, fileName, name_len);
4209 }
4210
4211 params = 6 + name_len;
4212 count = sizeof (FILE_UNIX_BASIC_INFO);
4213 pSMB->MaxParameterCount = cpu_to_le16(2);
4214 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4215 pSMB->MaxSetupCount = 0;
4216 pSMB->Reserved = 0;
4217 pSMB->Flags = 0;
4218 pSMB->Timeout = 0;
4219 pSMB->Reserved2 = 0;
4220 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4221 InformationLevel) - 4;
4222 offset = param_offset + params;
4223 data_offset =
4224 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
4225 offset);
4226 memset(data_offset, 0, count);
4227 pSMB->DataOffset = cpu_to_le16(offset);
4228 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4229 pSMB->SetupCount = 1;
4230 pSMB->Reserved3 = 0;
4231 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4232 byte_count = 3 /* pad */ + params + count;
4233 pSMB->ParameterCount = cpu_to_le16(params);
4234 pSMB->DataCount = cpu_to_le16(count);
4235 pSMB->TotalParameterCount = pSMB->ParameterCount;
4236 pSMB->TotalDataCount = pSMB->DataCount;
4237 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
4238 pSMB->Reserved4 = 0;
4239 pSMB->hdr.smb_buf_length += byte_count;
4240 data_offset->Uid = cpu_to_le64(uid);
4241 data_offset->Gid = cpu_to_le64(gid);
4242 /* better to leave device as zero when it is */
4243 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
4244 data_offset->DevMinor = cpu_to_le64(MINOR(device));
4245 data_offset->Permissions = cpu_to_le64(mode);
4246
4247 if(S_ISREG(mode))
4248 data_offset->Type = cpu_to_le32(UNIX_FILE);
4249 else if(S_ISDIR(mode))
4250 data_offset->Type = cpu_to_le32(UNIX_DIR);
4251 else if(S_ISLNK(mode))
4252 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
4253 else if(S_ISCHR(mode))
4254 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
4255 else if(S_ISBLK(mode))
4256 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
4257 else if(S_ISFIFO(mode))
4258 data_offset->Type = cpu_to_le32(UNIX_FIFO);
4259 else if(S_ISSOCK(mode))
4260 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
4261
4262
4263 pSMB->ByteCount = cpu_to_le16(byte_count);
4264 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4265 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4266 if (rc) {
4267 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
4268 }
4269
4270 if (pSMB)
4271 cifs_buf_release(pSMB);
4272 if (rc == -EAGAIN)
4273 goto setPermsRetry;
4274 return rc;
4275 }
4276
4277 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
4278 const int notify_subdirs, const __u16 netfid,
4279 __u32 filter, struct file * pfile, int multishot,
4280 const struct nls_table *nls_codepage)
4281 {
4282 int rc = 0;
4283 struct smb_com_transaction_change_notify_req * pSMB = NULL;
4284 struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
4285 struct dir_notify_req *dnotify_req;
4286 int bytes_returned;
4287
4288 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
4289 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
4290 (void **) &pSMBr);
4291 if (rc)
4292 return rc;
4293
4294 pSMB->TotalParameterCount = 0 ;
4295 pSMB->TotalDataCount = 0;
4296 pSMB->MaxParameterCount = cpu_to_le32(2);
4297 /* BB find exact data count max from sess structure BB */
4298 pSMB->MaxDataCount = 0; /* same in little endian or be */
4299 pSMB->MaxSetupCount = 4;
4300 pSMB->Reserved = 0;
4301 pSMB->ParameterOffset = 0;
4302 pSMB->DataCount = 0;
4303 pSMB->DataOffset = 0;
4304 pSMB->SetupCount = 4; /* single byte does not need le conversion */
4305 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
4306 pSMB->ParameterCount = pSMB->TotalParameterCount;
4307 if(notify_subdirs)
4308 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
4309 pSMB->Reserved2 = 0;
4310 pSMB->CompletionFilter = cpu_to_le32(filter);
4311 pSMB->Fid = netfid; /* file handle always le */
4312 pSMB->ByteCount = 0;
4313
4314 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4315 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
4316 if (rc) {
4317 cFYI(1, ("Error in Notify = %d", rc));
4318 } else {
4319 /* Add file to outstanding requests */
4320 /* BB change to kmem cache alloc */
4321 dnotify_req = (struct dir_notify_req *) kmalloc(
4322 sizeof(struct dir_notify_req),
4323 GFP_KERNEL);
4324 if(dnotify_req) {
4325 dnotify_req->Pid = pSMB->hdr.Pid;
4326 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
4327 dnotify_req->Mid = pSMB->hdr.Mid;
4328 dnotify_req->Tid = pSMB->hdr.Tid;
4329 dnotify_req->Uid = pSMB->hdr.Uid;
4330 dnotify_req->netfid = netfid;
4331 dnotify_req->pfile = pfile;
4332 dnotify_req->filter = filter;
4333 dnotify_req->multishot = multishot;
4334 spin_lock(&GlobalMid_Lock);
4335 list_add_tail(&dnotify_req->lhead,
4336 &GlobalDnotifyReqList);
4337 spin_unlock(&GlobalMid_Lock);
4338 } else
4339 rc = -ENOMEM;
4340 }
4341 cifs_buf_release(pSMB);
4342 return rc;
4343 }
4344 #ifdef CONFIG_CIFS_XATTR
4345 ssize_t
4346 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
4347 const unsigned char *searchName,
4348 char * EAData, size_t buf_size,
4349 const struct nls_table *nls_codepage, int remap)
4350 {
4351 /* BB assumes one setup word */
4352 TRANSACTION2_QPI_REQ *pSMB = NULL;
4353 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4354 int rc = 0;
4355 int bytes_returned;
4356 int name_len;
4357 struct fea * temp_fea;
4358 char * temp_ptr;
4359 __u16 params, byte_count;
4360
4361 cFYI(1, ("In Query All EAs path %s", searchName));
4362 QAllEAsRetry:
4363 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4364 (void **) &pSMBr);
4365 if (rc)
4366 return rc;
4367
4368 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4369 name_len =
4370 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4371 PATH_MAX, nls_codepage, remap);
4372 name_len++; /* trailing null */
4373 name_len *= 2;
4374 } else { /* BB improve the check for buffer overruns BB */
4375 name_len = strnlen(searchName, PATH_MAX);
4376 name_len++; /* trailing null */
4377 strncpy(pSMB->FileName, searchName, name_len);
4378 }
4379
4380 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4381 pSMB->TotalDataCount = 0;
4382 pSMB->MaxParameterCount = cpu_to_le16(2);
4383 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4384 pSMB->MaxSetupCount = 0;
4385 pSMB->Reserved = 0;
4386 pSMB->Flags = 0;
4387 pSMB->Timeout = 0;
4388 pSMB->Reserved2 = 0;
4389 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4390 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4391 pSMB->DataCount = 0;
4392 pSMB->DataOffset = 0;
4393 pSMB->SetupCount = 1;
4394 pSMB->Reserved3 = 0;
4395 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4396 byte_count = params + 1 /* pad */ ;
4397 pSMB->TotalParameterCount = cpu_to_le16(params);
4398 pSMB->ParameterCount = pSMB->TotalParameterCount;
4399 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4400 pSMB->Reserved4 = 0;
4401 pSMB->hdr.smb_buf_length += byte_count;
4402 pSMB->ByteCount = cpu_to_le16(byte_count);
4403
4404 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4405 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4406 if (rc) {
4407 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
4408 } else { /* decode response */
4409 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4410
4411 /* BB also check enough total bytes returned */
4412 /* BB we need to improve the validity checking
4413 of these trans2 responses */
4414 if (rc || (pSMBr->ByteCount < 4))
4415 rc = -EIO; /* bad smb */
4416 /* else if (pFindData){
4417 memcpy((char *) pFindData,
4418 (char *) &pSMBr->hdr.Protocol +
4419 data_offset, kl);
4420 }*/ else {
4421 /* check that length of list is not more than bcc */
4422 /* check that each entry does not go beyond length
4423 of list */
4424 /* check that each element of each entry does not
4425 go beyond end of list */
4426 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4427 struct fealist * ea_response_data;
4428 rc = 0;
4429 /* validate_trans2_offsets() */
4430 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4431 ea_response_data = (struct fealist *)
4432 (((char *) &pSMBr->hdr.Protocol) +
4433 data_offset);
4434 name_len = le32_to_cpu(ea_response_data->list_len);
4435 cFYI(1,("ea length %d", name_len));
4436 if(name_len <= 8) {
4437 /* returned EA size zeroed at top of function */
4438 cFYI(1,("empty EA list returned from server"));
4439 } else {
4440 /* account for ea list len */
4441 name_len -= 4;
4442 temp_fea = ea_response_data->list;
4443 temp_ptr = (char *)temp_fea;
4444 while(name_len > 0) {
4445 __u16 value_len;
4446 name_len -= 4;
4447 temp_ptr += 4;
4448 rc += temp_fea->name_len;
4449 /* account for prefix user. and trailing null */
4450 rc = rc + 5 + 1;
4451 if(rc<(int)buf_size) {
4452 memcpy(EAData,"user.",5);
4453 EAData+=5;
4454 memcpy(EAData,temp_ptr,temp_fea->name_len);
4455 EAData+=temp_fea->name_len;
4456 /* null terminate name */
4457 *EAData = 0;
4458 EAData = EAData + 1;
4459 } else if(buf_size == 0) {
4460 /* skip copy - calc size only */
4461 } else {
4462 /* stop before overrun buffer */
4463 rc = -ERANGE;
4464 break;
4465 }
4466 name_len -= temp_fea->name_len;
4467 temp_ptr += temp_fea->name_len;
4468 /* account for trailing null */
4469 name_len--;
4470 temp_ptr++;
4471 value_len = le16_to_cpu(temp_fea->value_len);
4472 name_len -= value_len;
4473 temp_ptr += value_len;
4474 /* BB check that temp_ptr is still within smb BB*/
4475 /* no trailing null to account for in value len */
4476 /* go on to next EA */
4477 temp_fea = (struct fea *)temp_ptr;
4478 }
4479 }
4480 }
4481 }
4482 if (pSMB)
4483 cifs_buf_release(pSMB);
4484 if (rc == -EAGAIN)
4485 goto QAllEAsRetry;
4486
4487 return (ssize_t)rc;
4488 }
4489
4490 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
4491 const unsigned char * searchName,const unsigned char * ea_name,
4492 unsigned char * ea_value, size_t buf_size,
4493 const struct nls_table *nls_codepage, int remap)
4494 {
4495 TRANSACTION2_QPI_REQ *pSMB = NULL;
4496 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4497 int rc = 0;
4498 int bytes_returned;
4499 int name_len;
4500 struct fea * temp_fea;
4501 char * temp_ptr;
4502 __u16 params, byte_count;
4503
4504 cFYI(1, ("In Query EA path %s", searchName));
4505 QEARetry:
4506 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4507 (void **) &pSMBr);
4508 if (rc)
4509 return rc;
4510
4511 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4512 name_len =
4513 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4514 PATH_MAX, nls_codepage, remap);
4515 name_len++; /* trailing null */
4516 name_len *= 2;
4517 } else { /* BB improve the check for buffer overruns BB */
4518 name_len = strnlen(searchName, PATH_MAX);
4519 name_len++; /* trailing null */
4520 strncpy(pSMB->FileName, searchName, name_len);
4521 }
4522
4523 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4524 pSMB->TotalDataCount = 0;
4525 pSMB->MaxParameterCount = cpu_to_le16(2);
4526 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4527 pSMB->MaxSetupCount = 0;
4528 pSMB->Reserved = 0;
4529 pSMB->Flags = 0;
4530 pSMB->Timeout = 0;
4531 pSMB->Reserved2 = 0;
4532 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4533 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4534 pSMB->DataCount = 0;
4535 pSMB->DataOffset = 0;
4536 pSMB->SetupCount = 1;
4537 pSMB->Reserved3 = 0;
4538 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4539 byte_count = params + 1 /* pad */ ;
4540 pSMB->TotalParameterCount = cpu_to_le16(params);
4541 pSMB->ParameterCount = pSMB->TotalParameterCount;
4542 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4543 pSMB->Reserved4 = 0;
4544 pSMB->hdr.smb_buf_length += byte_count;
4545 pSMB->ByteCount = cpu_to_le16(byte_count);
4546
4547 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4548 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4549 if (rc) {
4550 cFYI(1, ("Send error in Query EA = %d", rc));
4551 } else { /* decode response */
4552 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4553
4554 /* BB also check enough total bytes returned */
4555 /* BB we need to improve the validity checking
4556 of these trans2 responses */
4557 if (rc || (pSMBr->ByteCount < 4))
4558 rc = -EIO; /* bad smb */
4559 /* else if (pFindData){
4560 memcpy((char *) pFindData,
4561 (char *) &pSMBr->hdr.Protocol +
4562 data_offset, kl);
4563 }*/ else {
4564 /* check that length of list is not more than bcc */
4565 /* check that each entry does not go beyond length
4566 of list */
4567 /* check that each element of each entry does not
4568 go beyond end of list */
4569 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4570 struct fealist * ea_response_data;
4571 rc = -ENODATA;
4572 /* validate_trans2_offsets() */
4573 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4574 ea_response_data = (struct fealist *)
4575 (((char *) &pSMBr->hdr.Protocol) +
4576 data_offset);
4577 name_len = le32_to_cpu(ea_response_data->list_len);
4578 cFYI(1,("ea length %d", name_len));
4579 if(name_len <= 8) {
4580 /* returned EA size zeroed at top of function */
4581 cFYI(1,("empty EA list returned from server"));
4582 } else {
4583 /* account for ea list len */
4584 name_len -= 4;
4585 temp_fea = ea_response_data->list;
4586 temp_ptr = (char *)temp_fea;
4587 /* loop through checking if we have a matching
4588 name and then return the associated value */
4589 while(name_len > 0) {
4590 __u16 value_len;
4591 name_len -= 4;
4592 temp_ptr += 4;
4593 value_len = le16_to_cpu(temp_fea->value_len);
4594 /* BB validate that value_len falls within SMB,
4595 even though maximum for name_len is 255 */
4596 if(memcmp(temp_fea->name,ea_name,
4597 temp_fea->name_len) == 0) {
4598 /* found a match */
4599 rc = value_len;
4600 /* account for prefix user. and trailing null */
4601 if(rc<=(int)buf_size) {
4602 memcpy(ea_value,
4603 temp_fea->name+temp_fea->name_len+1,
4604 rc);
4605 /* ea values, unlike ea names,
4606 are not null terminated */
4607 } else if(buf_size == 0) {
4608 /* skip copy - calc size only */
4609 } else {
4610 /* stop before overrun buffer */
4611 rc = -ERANGE;
4612 }
4613 break;
4614 }
4615 name_len -= temp_fea->name_len;
4616 temp_ptr += temp_fea->name_len;
4617 /* account for trailing null */
4618 name_len--;
4619 temp_ptr++;
4620 name_len -= value_len;
4621 temp_ptr += value_len;
4622 /* no trailing null to account for in value len */
4623 /* go on to next EA */
4624 temp_fea = (struct fea *)temp_ptr;
4625 }
4626 }
4627 }
4628 }
4629 if (pSMB)
4630 cifs_buf_release(pSMB);
4631 if (rc == -EAGAIN)
4632 goto QEARetry;
4633
4634 return (ssize_t)rc;
4635 }
4636
4637 int
4638 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4639 const char * ea_name, const void * ea_value,
4640 const __u16 ea_value_len, const struct nls_table *nls_codepage,
4641 int remap)
4642 {
4643 struct smb_com_transaction2_spi_req *pSMB = NULL;
4644 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4645 struct fealist *parm_data;
4646 int name_len;
4647 int rc = 0;
4648 int bytes_returned = 0;
4649 __u16 params, param_offset, byte_count, offset, count;
4650
4651 cFYI(1, ("In SetEA"));
4652 SetEARetry:
4653 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4654 (void **) &pSMBr);
4655 if (rc)
4656 return rc;
4657
4658 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4659 name_len =
4660 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4661 PATH_MAX, nls_codepage, remap);
4662 name_len++; /* trailing null */
4663 name_len *= 2;
4664 } else { /* BB improve the check for buffer overruns BB */
4665 name_len = strnlen(fileName, PATH_MAX);
4666 name_len++; /* trailing null */
4667 strncpy(pSMB->FileName, fileName, name_len);
4668 }
4669
4670 params = 6 + name_len;
4671
4672 /* done calculating parms using name_len of file name,
4673 now use name_len to calculate length of ea name
4674 we are going to create in the inode xattrs */
4675 if(ea_name == NULL)
4676 name_len = 0;
4677 else
4678 name_len = strnlen(ea_name,255);
4679
4680 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
4681 pSMB->MaxParameterCount = cpu_to_le16(2);
4682 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
4683 pSMB->MaxSetupCount = 0;
4684 pSMB->Reserved = 0;
4685 pSMB->Flags = 0;
4686 pSMB->Timeout = 0;
4687 pSMB->Reserved2 = 0;
4688 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4689 InformationLevel) - 4;
4690 offset = param_offset + params;
4691 pSMB->InformationLevel =
4692 cpu_to_le16(SMB_SET_FILE_EA);
4693
4694 parm_data =
4695 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
4696 offset);
4697 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4698 pSMB->DataOffset = cpu_to_le16(offset);
4699 pSMB->SetupCount = 1;
4700 pSMB->Reserved3 = 0;
4701 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4702 byte_count = 3 /* pad */ + params + count;
4703 pSMB->DataCount = cpu_to_le16(count);
4704 parm_data->list_len = cpu_to_le32(count);
4705 parm_data->list[0].EA_flags = 0;
4706 /* we checked above that name len is less than 255 */
4707 parm_data->list[0].name_len = (__u8)name_len;;
4708 /* EA names are always ASCII */
4709 if(ea_name)
4710 strncpy(parm_data->list[0].name,ea_name,name_len);
4711 parm_data->list[0].name[name_len] = 0;
4712 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
4713 /* caller ensures that ea_value_len is less than 64K but
4714 we need to ensure that it fits within the smb */
4715
4716 /*BB add length check that it would fit in negotiated SMB buffer size BB */
4717 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
4718 if(ea_value_len)
4719 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
4720
4721 pSMB->TotalDataCount = pSMB->DataCount;
4722 pSMB->ParameterCount = cpu_to_le16(params);
4723 pSMB->TotalParameterCount = pSMB->ParameterCount;
4724 pSMB->Reserved4 = 0;
4725 pSMB->hdr.smb_buf_length += byte_count;
4726 pSMB->ByteCount = cpu_to_le16(byte_count);
4727 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4728 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4729 if (rc) {
4730 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
4731 }
4732
4733 cifs_buf_release(pSMB);
4734
4735 if (rc == -EAGAIN)
4736 goto SetEARetry;
4737
4738 return rc;
4739 }
4740
4741 #endif