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