cifs: double lock in cifs_reconnect_tcon()
[linux-2.6-block.git] / fs / cifs / cifssmb.c
CommitLineData
929be906 1// SPDX-License-Identifier: LGPL-2.1
1da177e4 2/*
1da177e4 3 *
f19159dc 4 * Copyright (C) International Business Machines Corp., 2002,2010
1da177e4
LT
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * Contains the routines for constructing the SMB PDUs themselves
8 *
1da177e4
LT
9 */
10
11 /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
12 /* These are mostly routines that operate on a pathname, or on a tree id */
13 /* (mounted volume), but there are eight handle based routines which must be */
2dd29d31
SF
14 /* treated slightly differently for reconnection purposes since we never */
15 /* want to reuse a stale file handle and only the caller knows the file info */
1da177e4
LT
16
17#include <linux/fs.h>
5970e15d 18#include <linux/filelock.h>
1da177e4
LT
19#include <linux/kernel.h>
20#include <linux/vfs.h>
5a0e3ad6 21#include <linux/slab.h>
1da177e4 22#include <linux/posix_acl_xattr.h>
c28c89fc 23#include <linux/pagemap.h>
e28bc5b1
JL
24#include <linux/swap.h>
25#include <linux/task_io_accounting_ops.h>
7c0f6ba6 26#include <linux/uaccess.h>
1da177e4 27#include "cifspdu.h"
d08089f6 28#include "cifsfs.h"
1da177e4 29#include "cifsglob.h"
d0d66c44 30#include "cifsacl.h"
1da177e4
LT
31#include "cifsproto.h"
32#include "cifs_unicode.h"
33#include "cifs_debug.h"
e28bc5b1 34#include "fscache.h"
db223a59 35#include "smbdirect.h"
08744015
PA
36#ifdef CONFIG_CIFS_DFS_UPCALL
37#include "dfs_cache.h"
38#endif
1da177e4
LT
39
40#ifdef CONFIG_CIFS_POSIX
41static struct {
42 int index;
43 char *name;
44} protocols[] = {
50c2f753 45 {CIFS_PROT, "\2NT LM 0.12"},
3979877e 46 {POSIX_PROT, "\2POSIX 2"},
1da177e4
LT
47 {BAD_PROT, "\2"}
48};
49#else
50static struct {
51 int index;
52 char *name;
53} protocols[] = {
790fe579 54 {CIFS_PROT, "\2NT LM 0.12"},
1da177e4
LT
55 {BAD_PROT, "\2"}
56};
57#endif
58
3979877e
SF
59/* define the number of elements in the cifs dialect array */
60#ifdef CONFIG_CIFS_POSIX
3979877e 61#define CIFS_NUM_PROT 2
3979877e 62#else /* not posix */
3979877e 63#define CIFS_NUM_PROT 1
3979877e
SF
64#endif /* CIFS_POSIX */
65
1da177e4 66
9162ab20
JL
67/* reconnect the socket, tcon, and smb session if needed */
68static int
96daf2b0 69cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
9162ab20 70{
c4a5534a 71 int rc;
96daf2b0 72 struct cifs_ses *ses;
9162ab20 73 struct TCP_Server_Info *server;
6cc041e9 74 struct nls_table *nls_codepage = NULL;
9162ab20
JL
75
76 /*
77 * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
78 * tcp and smb session status done differently for those three - in the
79 * calling routine
80 */
81 if (!tcon)
82 return 0;
83
84 ses = tcon->ses;
85 server = ses->server;
86
87 /*
88 * only tree disconnect, open, and write, (and ulogoff which does not
491eafce 89 * have tcon) are allowed as we start umount
9162ab20 90 */
d7d7a66a 91 spin_lock(&tcon->tc_lock);
fdf59eb5 92 if (tcon->status == TID_EXITING) {
491eafce 93 if (smb_command != SMB_COM_TREE_DISCONNECT) {
d7d7a66a 94 spin_unlock(&tcon->tc_lock);
f96637be
JP
95 cifs_dbg(FYI, "can not send cmd %d while umounting\n",
96 smb_command);
9162ab20
JL
97 return -ENODEV;
98 }
99 }
d7d7a66a 100 spin_unlock(&tcon->tc_lock);
9162ab20 101
6cc041e9 102again:
1bcd548d
PA
103 rc = cifs_wait_for_server_reconnect(server, tcon->retry);
104 if (rc)
105 return rc;
9162ab20 106
d1a931ce
SP
107 spin_lock(&ses->chan_lock);
108 if (!cifs_chan_needs_reconnect(ses, server) && !tcon->need_reconnect) {
109 spin_unlock(&ses->chan_lock);
9162ab20 110 return 0;
d1a931ce
SP
111 }
112 spin_unlock(&ses->chan_lock);
9162ab20 113
6cc041e9 114 mutex_lock(&ses->session_mutex);
76e75270
SC
115 /*
116 * Recheck after acquire mutex. If another thread is negotiating
117 * and the server never sends an answer the socket will be closed
118 * and tcpStatus set to reconnect.
119 */
d7d7a66a 120 spin_lock(&server->srv_lock);
76e75270 121 if (server->tcpStatus == CifsNeedReconnect) {
d7d7a66a 122 spin_unlock(&server->srv_lock);
4f5d5b33 123 mutex_unlock(&ses->session_mutex);
6cc041e9
PA
124
125 if (tcon->retry)
126 goto again;
76e75270 127 rc = -EHOSTDOWN;
76e75270
SC
128 goto out;
129 }
d7d7a66a 130 spin_unlock(&server->srv_lock);
76e75270 131
6cc041e9
PA
132 nls_codepage = load_nls_default();
133
d1a931ce
SP
134 /*
135 * need to prevent multiple threads trying to simultaneously
136 * reconnect the same SMB session
137 */
6cc041e9 138 spin_lock(&ses->ses_lock);
d1a931ce 139 spin_lock(&ses->chan_lock);
6cc041e9
PA
140 if (!cifs_chan_needs_reconnect(ses, server) &&
141 ses->ses_status == SES_GOOD) {
d1a931ce 142 spin_unlock(&ses->chan_lock);
6cc041e9 143 spin_unlock(&ses->ses_lock);
f486ef8e
SP
144
145 /* this means that we only need to tree connect */
d1a931ce
SP
146 if (tcon->need_reconnect)
147 goto skip_sess_setup;
148
6cc041e9 149 mutex_unlock(&ses->session_mutex);
d1a931ce
SP
150 goto out;
151 }
152 spin_unlock(&ses->chan_lock);
6cc041e9 153 spin_unlock(&ses->ses_lock);
d1a931ce 154
f486ef8e 155 rc = cifs_negotiate_protocol(0, ses, server);
d1a931ce 156 if (!rc)
f486ef8e 157 rc = cifs_setup_session(0, ses, server, nls_codepage);
9162ab20
JL
158
159 /* do we need to reconnect tcon? */
160 if (rc || !tcon->need_reconnect) {
d7b619cf 161 mutex_unlock(&ses->session_mutex);
9162ab20
JL
162 goto out;
163 }
164
d1a931ce 165skip_sess_setup:
aa24d1e9 166 cifs_mark_open_files_invalid(tcon);
565674d6 167 rc = cifs_tree_connect(0, tcon, nls_codepage);
d7b619cf 168 mutex_unlock(&ses->session_mutex);
f96637be 169 cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
9162ab20 170
c318e6c2 171 if (rc) {
a0a3036b 172 pr_warn_once("reconnect tcon failed rc = %d\n", rc);
9162ab20 173 goto out;
c318e6c2 174 }
9162ab20 175
9162ab20
JL
176 atomic_inc(&tconInfoReconnectCount);
177
178 /* tell server Unix caps we support */
864138cb 179 if (cap_unix(ses))
9162ab20
JL
180 reset_cifs_unix_caps(0, tcon, NULL, NULL);
181
182 /*
183 * Removed call to reopen open files here. It is safer (and faster) to
184 * reopen files one at a time as needed in read and write.
185 *
186 * FIXME: what about file locks? don't we need to reclaim them ASAP?
187 */
188
189out:
190 /*
191 * Check if handle based operation so we know whether we can continue
192 * or not without returning to caller to reset file handle
193 */
194 switch (smb_command) {
195 case SMB_COM_READ_ANDX:
196 case SMB_COM_WRITE_ANDX:
197 case SMB_COM_CLOSE:
198 case SMB_COM_FIND_CLOSE2:
199 case SMB_COM_LOCKING_ANDX:
200 rc = -EAGAIN;
201 }
202
203 unload_nls(nls_codepage);
204 return rc;
205}
206
ad7a2926
SF
207/* Allocate and return pointer to an SMB request buffer, and set basic
208 SMB information in the SMB header. If the return code is zero, this
209 function must have filled in request_buf pointer */
1da177e4 210static int
96daf2b0 211small_smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
ad7a2926 212 void **request_buf)
1da177e4 213{
f569599a 214 int rc;
1da177e4 215
9162ab20 216 rc = cifs_reconnect_tcon(tcon, smb_command);
790fe579 217 if (rc)
1da177e4
LT
218 return rc;
219
220 *request_buf = cifs_small_buf_get();
221 if (*request_buf == NULL) {
222 /* BB should we add a retry in here if not a writepage? */
223 return -ENOMEM;
224 }
225
63135e08 226 header_assemble((struct smb_hdr *) *request_buf, smb_command,
c18c842b 227 tcon, wct);
1da177e4 228
790fe579
SF
229 if (tcon != NULL)
230 cifs_stats_inc(&tcon->num_smbs_sent);
a4544347 231
f569599a 232 return 0;
5815449d
SF
233}
234
12b3b8ff 235int
50c2f753 236small_smb_init_no_tc(const int smb_command, const int wct,
96daf2b0 237 struct cifs_ses *ses, void **request_buf)
12b3b8ff
SF
238{
239 int rc;
50c2f753 240 struct smb_hdr *buffer;
12b3b8ff 241
5815449d 242 rc = small_smb_init(smb_command, wct, NULL, request_buf);
790fe579 243 if (rc)
12b3b8ff
SF
244 return rc;
245
04fdabe1 246 buffer = (struct smb_hdr *)*request_buf;
88257360 247 buffer->Mid = get_next_mid(ses->server);
12b3b8ff
SF
248 if (ses->capabilities & CAP_UNICODE)
249 buffer->Flags2 |= SMBFLG2_UNICODE;
04fdabe1 250 if (ses->capabilities & CAP_STATUS32)
12b3b8ff
SF
251 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
252
253 /* uid, tid can stay at zero as set in header assemble */
254
50c2f753 255 /* BB add support for turning on the signing when
12b3b8ff
SF
256 this function is used after 1st of session setup requests */
257
258 return rc;
259}
1da177e4
LT
260
261/* If the return code is zero, this function must fill in request_buf pointer */
262static int
96daf2b0 263__smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
f569599a 264 void **request_buf, void **response_buf)
1da177e4 265{
1da177e4
LT
266 *request_buf = cifs_buf_get();
267 if (*request_buf == NULL) {
268 /* BB should we add a retry in here if not a writepage? */
269 return -ENOMEM;
270 }
271 /* Although the original thought was we needed the response buf for */
272 /* potential retries of smb operations it turns out we can determine */
273 /* from the mid flags when the request buffer can be resent without */
274 /* having to use a second distinct buffer for the response */
790fe579 275 if (response_buf)
50c2f753 276 *response_buf = *request_buf;
1da177e4
LT
277
278 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
ad7a2926 279 wct);
1da177e4 280
790fe579
SF
281 if (tcon != NULL)
282 cifs_stats_inc(&tcon->num_smbs_sent);
a4544347 283
f569599a
JL
284 return 0;
285}
286
287/* If the return code is zero, this function must fill in request_buf pointer */
288static int
96daf2b0 289smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
f569599a
JL
290 void **request_buf, void **response_buf)
291{
292 int rc;
293
294 rc = cifs_reconnect_tcon(tcon, smb_command);
295 if (rc)
296 return rc;
297
298 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
299}
300
301static int
96daf2b0 302smb_init_no_reconnect(int smb_command, int wct, struct cifs_tcon *tcon,
f569599a
JL
303 void **request_buf, void **response_buf)
304{
d1a931ce
SP
305 spin_lock(&tcon->ses->chan_lock);
306 if (cifs_chan_needs_reconnect(tcon->ses, tcon->ses->server) ||
307 tcon->need_reconnect) {
308 spin_unlock(&tcon->ses->chan_lock);
f569599a 309 return -EHOSTDOWN;
d1a931ce
SP
310 }
311 spin_unlock(&tcon->ses->chan_lock);
f569599a
JL
312
313 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
1da177e4
LT
314}
315
50c2f753 316static int validate_t2(struct smb_t2_rsp *pSMB)
1da177e4 317{
12df83c9
JL
318 unsigned int total_size;
319
320 /* check for plausible wct */
321 if (pSMB->hdr.WordCount < 10)
322 goto vt2_err;
1da177e4 323
1da177e4 324 /* check for parm and data offset going beyond end of smb */
12df83c9
JL
325 if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
326 get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
327 goto vt2_err;
328
12df83c9
JL
329 total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
330 if (total_size >= 512)
331 goto vt2_err;
332
fd5707e1
JL
333 /* check that bcc is at least as big as parms + data, and that it is
334 * less than negotiated smb buffer
335 */
12df83c9
JL
336 total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
337 if (total_size > get_bcc(&pSMB->hdr) ||
338 total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
339 goto vt2_err;
340
341 return 0;
342vt2_err:
50c2f753 343 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
1da177e4 344 sizeof(struct smb_t2_rsp) + 16);
12df83c9 345 return -EINVAL;
1da177e4 346}
690c522f 347
31d9e2bd 348static int
3f618223 349decode_ext_sec_blob(struct cifs_ses *ses, NEGOTIATE_RSP *pSMBr)
31d9e2bd
JL
350{
351 int rc = 0;
352 u16 count;
353 char *guid = pSMBr->u.extended_response.GUID;
3f618223 354 struct TCP_Server_Info *server = ses->server;
31d9e2bd
JL
355
356 count = get_bcc(&pSMBr->hdr);
357 if (count < SMB1_CLIENT_GUID_SIZE)
358 return -EIO;
359
360 spin_lock(&cifs_tcp_ses_lock);
361 if (server->srv_count > 1) {
362 spin_unlock(&cifs_tcp_ses_lock);
363 if (memcmp(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE) != 0) {
364 cifs_dbg(FYI, "server UID changed\n");
365 memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
366 }
367 } else {
368 spin_unlock(&cifs_tcp_ses_lock);
369 memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
370 }
371
372 if (count == SMB1_CLIENT_GUID_SIZE) {
3f618223 373 server->sec_ntlmssp = true;
31d9e2bd
JL
374 } else {
375 count -= SMB1_CLIENT_GUID_SIZE;
376 rc = decode_negTokenInit(
377 pSMBr->u.extended_response.SecurityBlob, count, server);
378 if (rc != 1)
379 return -EINVAL;
31d9e2bd
JL
380 }
381
382 return 0;
383}
384
9193400b 385static bool
3f618223 386should_set_ext_sec_flag(enum securityEnum sectype)
9193400b 387{
3f618223
JL
388 switch (sectype) {
389 case RawNTLMSSP:
390 case Kerberos:
9193400b 391 return true;
3f618223
JL
392 case Unspecified:
393 if (global_secflags &
394 (CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP))
395 return true;
df561f66 396 fallthrough;
3f618223
JL
397 default:
398 return false;
399 }
9193400b
JL
400}
401
1da177e4 402int
f486ef8e
SP
403CIFSSMBNegotiate(const unsigned int xid,
404 struct cifs_ses *ses,
405 struct TCP_Server_Info *server)
1da177e4
LT
406{
407 NEGOTIATE_REQ *pSMB;
408 NEGOTIATE_RSP *pSMBr;
409 int rc = 0;
410 int bytes_returned;
3979877e 411 int i;
1da177e4
LT
412 u16 count;
413
3534b850
JL
414 if (!server) {
415 WARN(1, "%s: server is NULL!\n", __func__);
416 return -EIO;
1da177e4 417 }
3534b850 418
1da177e4
LT
419 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
420 (void **) &pSMB, (void **) &pSMBr);
421 if (rc)
422 return rc;
750d1151 423
88257360 424 pSMB->hdr.Mid = get_next_mid(server);
100c1ddc 425 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
a013689d 426
3f618223 427 if (should_set_ext_sec_flag(ses->sectype)) {
a0a3036b 428 cifs_dbg(FYI, "Requesting extended security\n");
ac683924
SF
429 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
430 }
50c2f753 431
3979877e 432 count = 0;
bcfb84a9
SR
433 /*
434 * We know that all the name entries in the protocols array
435 * are short (< 16 bytes anyway) and are NUL terminated.
436 */
50c2f753 437 for (i = 0; i < CIFS_NUM_PROT; i++) {
bcfb84a9
SR
438 size_t len = strlen(protocols[i].name) + 1;
439
943deb60 440 memcpy(&pSMB->DialectsArray[count], protocols[i].name, len);
bcfb84a9 441 count += len;
3979877e 442 }
be8e3b00 443 inc_rfc1001_len(pSMB, count);
1da177e4
LT
444 pSMB->ByteCount = cpu_to_le16(count);
445
446 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
447 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
50c2f753 448 if (rc != 0)
254e55ed
SF
449 goto neg_err_exit;
450
9bf67e51 451 server->dialect = le16_to_cpu(pSMBr->DialectIndex);
f96637be 452 cifs_dbg(FYI, "Dialect: %d\n", server->dialect);
254e55ed 453 /* Check wct = 1 error case */
76a3c92e 454 if ((pSMBr->hdr.WordCount <= 13) || (server->dialect == BAD_PROT)) {
254e55ed 455 /* core returns wct = 1, but we do not ask for core - otherwise
50c2f753 456 small wct just comes when dialect index is -1 indicating we
254e55ed
SF
457 could not negotiate a common dialect */
458 rc = -EOPNOTSUPP;
459 goto neg_err_exit;
790fe579 460 } else if (pSMBr->hdr.WordCount != 17) {
254e55ed
SF
461 /* unknown wct */
462 rc = -EOPNOTSUPP;
463 goto neg_err_exit;
464 }
2190eca1
JL
465 /* else wct == 17, NTLM or better */
466
96daf2b0
SF
467 server->sec_mode = pSMBr->SecurityMode;
468 if ((server->sec_mode & SECMODE_USER) == 0)
f96637be 469 cifs_dbg(FYI, "share mode security\n");
bdc4bf6e 470
254e55ed
SF
471 /* one byte, so no need to convert this or EncryptionKeyLen from
472 little endian */
10b9b98e
PS
473 server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
474 cifs_max_pending);
45275789 475 set_credits(server, server->maxReq);
254e55ed 476 /* probably no need to store and check maxvcs */
c974befa 477 server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
704528d8 478 /* set up max_read for readahead check */
1f641d94 479 server->max_read = server->maxBuf;
eca6acf9 480 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
f96637be 481 cifs_dbg(NOISY, "Max buf = %d\n", ses->server->maxBuf);
254e55ed 482 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
b815f1e5
SF
483 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
484 server->timeAdj *= 60;
31d9e2bd 485
e598d1d8
JL
486 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
487 server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
d3ba50b1 488 memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
254e55ed 489 CIFS_CRYPTO_KEY_SIZE);
f291095f
NP
490 } else if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
491 server->capabilities & CAP_EXTENDED_SECURITY) {
e598d1d8 492 server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
3f618223 493 rc = decode_ext_sec_blob(ses, pSMBr);
e598d1d8 494 } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
07cc6cf9 495 rc = -EIO; /* no crypt key only if plain text pwd */
e598d1d8
JL
496 } else {
497 server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
254e55ed 498 server->capabilities &= ~CAP_EXTENDED_SECURITY;
e598d1d8 499 }
254e55ed 500
9ddec561 501 if (!rc)
38d77c50 502 rc = cifs_enable_signing(server, ses->sign);
50c2f753 503neg_err_exit:
4a6d87f1 504 cifs_buf_release(pSMB);
254e55ed 505
f96637be 506 cifs_dbg(FYI, "negprot rc %d\n", rc);
1da177e4
LT
507 return rc;
508}
509
510int
2e6e02ab 511CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon)
1da177e4
LT
512{
513 struct smb_hdr *smb_buffer;
1da177e4 514 int rc = 0;
1da177e4 515
f96637be 516 cifs_dbg(FYI, "In tree disconnect\n");
1da177e4 517
f1987b44
JL
518 /* BB: do we need to check this? These should never be NULL. */
519 if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
520 return -EIO;
1da177e4 521
f1987b44
JL
522 /*
523 * No need to return error on this operation if tid invalidated and
524 * closed on server already e.g. due to tcp session crashing. Also,
525 * the tcon is no longer on the list, so no need to take lock before
526 * checking this.
527 */
d1a931ce
SP
528 spin_lock(&tcon->ses->chan_lock);
529 if ((tcon->need_reconnect) || CIFS_ALL_CHANS_NEED_RECONNECT(tcon->ses)) {
530 spin_unlock(&tcon->ses->chan_lock);
531 return -EIO;
532 }
533 spin_unlock(&tcon->ses->chan_lock);
1da177e4 534
50c2f753 535 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
09d1db5c 536 (void **)&smb_buffer);
f1987b44 537 if (rc)
1da177e4 538 return rc;
133672ef 539
792af7b0 540 rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, 0);
da502f7d 541 cifs_small_buf_release(smb_buffer);
1da177e4 542 if (rc)
f96637be 543 cifs_dbg(FYI, "Tree disconnect failed %d\n", rc);
1da177e4 544
50c2f753 545 /* No need to return error on this operation if tid invalidated and
f1987b44 546 closed on server already e.g. due to tcp session crashing */
1da177e4
LT
547 if (rc == -EAGAIN)
548 rc = 0;
549
550 return rc;
551}
552
766fdbb5
JL
553/*
554 * This is a no-op for now. We're not really interested in the reply, but
555 * rather in the fact that the server sent one and that server->lstrp
556 * gets updated.
557 *
558 * FIXME: maybe we should consider checking that the reply matches request?
559 */
560static void
561cifs_echo_callback(struct mid_q_entry *mid)
562{
563 struct TCP_Server_Info *server = mid->callback_data;
34f4deb7 564 struct cifs_credits credits = { .value = 1, .instance = 0 };
766fdbb5 565
70f08f91 566 release_mid(mid);
34f4deb7 567 add_credits(server, &credits, CIFS_ECHO_OP);
766fdbb5
JL
568}
569
570int
571CIFSSMBEcho(struct TCP_Server_Info *server)
572{
573 ECHO_REQ *smb;
574 int rc = 0;
738f9de5
PS
575 struct kvec iov[2];
576 struct smb_rqst rqst = { .rq_iov = iov,
577 .rq_nvec = 2 };
766fdbb5 578
f96637be 579 cifs_dbg(FYI, "In echo request\n");
766fdbb5
JL
580
581 rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
582 if (rc)
583 return rc;
584
26c9cb66
SF
585 if (server->capabilities & CAP_UNICODE)
586 smb->hdr.Flags2 |= SMBFLG2_UNICODE;
587
766fdbb5 588 /* set up echo request */
5443d130 589 smb->hdr.Tid = 0xffff;
99d86c8f
JL
590 smb->hdr.WordCount = 1;
591 put_unaligned_le16(1, &smb->EchoCount);
820a803f 592 put_bcc(1, &smb->hdr);
766fdbb5 593 smb->Data[0] = 'a';
be8e3b00 594 inc_rfc1001_len(smb, 3);
738f9de5
PS
595
596 iov[0].iov_len = 4;
597 iov[0].iov_base = smb;
598 iov[1].iov_len = get_rfc1002_length(smb);
599 iov[1].iov_base = (char *)smb + 4;
766fdbb5 600
9b7c18a2 601 rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback, NULL,
392e1c5d 602 server, CIFS_NON_BLOCKING | CIFS_ECHO_OP, NULL);
766fdbb5 603 if (rc)
f96637be 604 cifs_dbg(FYI, "Echo request failed: %d\n", rc);
766fdbb5
JL
605
606 cifs_small_buf_release(smb);
607
608 return rc;
609}
610
1da177e4 611int
58c45c58 612CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses)
1da177e4 613{
1da177e4
LT
614 LOGOFF_ANDX_REQ *pSMB;
615 int rc = 0;
1da177e4 616
f96637be 617 cifs_dbg(FYI, "In SMBLogoff for session disconnect\n");
3b795210 618
14fbf50d
JL
619 /*
620 * BB: do we need to check validity of ses and server? They should
621 * always be valid since we have an active reference. If not, that
622 * should probably be a BUG()
623 */
624 if (!ses || !ses->server)
3b795210
SF
625 return -EIO;
626
d7b619cf 627 mutex_lock(&ses->session_mutex);
d1a931ce
SP
628 spin_lock(&ses->chan_lock);
629 if (CIFS_ALL_CHANS_NEED_RECONNECT(ses)) {
630 spin_unlock(&ses->chan_lock);
3b795210
SF
631 goto session_already_dead; /* no need to send SMBlogoff if uid
632 already closed due to reconnect */
d1a931ce
SP
633 }
634 spin_unlock(&ses->chan_lock);
635
1da177e4
LT
636 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
637 if (rc) {
d7b619cf 638 mutex_unlock(&ses->session_mutex);
1da177e4
LT
639 return rc;
640 }
641
88257360 642 pSMB->hdr.Mid = get_next_mid(ses->server);
1982c344 643
38d77c50
JL
644 if (ses->server->sign)
645 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1da177e4
LT
646
647 pSMB->hdr.Uid = ses->Suid;
648
649 pSMB->AndXCommand = 0xFF;
792af7b0 650 rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, 0);
da502f7d 651 cifs_small_buf_release(pSMB);
3b795210 652session_already_dead:
d7b619cf 653 mutex_unlock(&ses->session_mutex);
1da177e4
LT
654
655 /* if session dead then we do not need to do ulogoff,
50c2f753 656 since server closed smb session, no sense reporting
1da177e4
LT
657 error */
658 if (rc == -EAGAIN)
659 rc = 0;
660 return rc;
661}
662
2d785a50 663int
6d5786a3
PS
664CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
665 const char *fileName, __u16 type,
666 const struct nls_table *nls_codepage, int remap)
2d785a50
SF
667{
668 TRANSACTION2_SPI_REQ *pSMB = NULL;
669 TRANSACTION2_SPI_RSP *pSMBr = NULL;
670 struct unlink_psx_rq *pRqD;
671 int name_len;
672 int rc = 0;
673 int bytes_returned = 0;
674 __u16 params, param_offset, offset, byte_count;
675
f96637be 676 cifs_dbg(FYI, "In POSIX delete\n");
2d785a50
SF
677PsxDelete:
678 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
679 (void **) &pSMBr);
680 if (rc)
681 return rc;
682
683 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
684 name_len =
acbbb76a
SF
685 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
686 PATH_MAX, nls_codepage, remap);
2d785a50
SF
687 name_len++; /* trailing null */
688 name_len *= 2;
340625e6
RS
689 } else {
690 name_len = copy_path_name(pSMB->FileName, fileName);
2d785a50
SF
691 }
692
693 params = 6 + name_len;
694 pSMB->MaxParameterCount = cpu_to_le16(2);
695 pSMB->MaxDataCount = 0; /* BB double check this with jra */
696 pSMB->MaxSetupCount = 0;
697 pSMB->Reserved = 0;
698 pSMB->Flags = 0;
699 pSMB->Timeout = 0;
700 pSMB->Reserved2 = 0;
701 param_offset = offsetof(struct smb_com_transaction2_spi_req,
702 InformationLevel) - 4;
703 offset = param_offset + params;
704
7b09d4e0
SF
705 /* Setup pointer to Request Data (inode type).
706 * Note that SMB offsets are from the beginning of SMB which is 4 bytes
707 * in, after RFC1001 field
708 */
709 pRqD = (struct unlink_psx_rq *)((char *)(pSMB) + offset + 4);
2d785a50
SF
710 pRqD->type = cpu_to_le16(type);
711 pSMB->ParameterOffset = cpu_to_le16(param_offset);
712 pSMB->DataOffset = cpu_to_le16(offset);
713 pSMB->SetupCount = 1;
714 pSMB->Reserved3 = 0;
715 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
716 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
717
718 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
719 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
720 pSMB->ParameterCount = cpu_to_le16(params);
721 pSMB->TotalParameterCount = pSMB->ParameterCount;
722 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
723 pSMB->Reserved4 = 0;
be8e3b00 724 inc_rfc1001_len(pSMB, byte_count);
2d785a50
SF
725 pSMB->ByteCount = cpu_to_le16(byte_count);
726 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
727 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
ad7a2926 728 if (rc)
f96637be 729 cifs_dbg(FYI, "Posix delete returned %d\n", rc);
2d785a50
SF
730 cifs_buf_release(pSMB);
731
44c58186 732 cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
2d785a50
SF
733
734 if (rc == -EAGAIN)
735 goto PsxDelete;
736
737 return rc;
738}
739
1da177e4 740int
ed6875e0
PS
741CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
742 struct cifs_sb_info *cifs_sb)
1da177e4
LT
743{
744 DELETE_FILE_REQ *pSMB = NULL;
745 DELETE_FILE_RSP *pSMBr = NULL;
746 int rc = 0;
747 int bytes_returned;
748 int name_len;
2baa2682 749 int remap = cifs_remap(cifs_sb);
1da177e4
LT
750
751DelFileRetry:
752 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
753 (void **) &pSMBr);
754 if (rc)
755 return rc;
756
757 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
ed6875e0
PS
758 name_len = cifsConvertToUTF16((__le16 *) pSMB->fileName, name,
759 PATH_MAX, cifs_sb->local_nls,
760 remap);
1da177e4
LT
761 name_len++; /* trailing null */
762 name_len *= 2;
340625e6
RS
763 } else {
764 name_len = copy_path_name(pSMB->fileName, name);
1da177e4
LT
765 }
766 pSMB->SearchAttributes =
767 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
768 pSMB->BufferFormat = 0x04;
be8e3b00 769 inc_rfc1001_len(pSMB, name_len + 1);
1da177e4
LT
770 pSMB->ByteCount = cpu_to_le16(name_len + 1);
771 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
772 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
44c58186 773 cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
ad7a2926 774 if (rc)
f96637be 775 cifs_dbg(FYI, "Error in RMFile = %d\n", rc);
1da177e4
LT
776
777 cifs_buf_release(pSMB);
778 if (rc == -EAGAIN)
779 goto DelFileRetry;
780
781 return rc;
782}
783
784int
f958ca5d
PS
785CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
786 struct cifs_sb_info *cifs_sb)
1da177e4
LT
787{
788 DELETE_DIRECTORY_REQ *pSMB = NULL;
789 DELETE_DIRECTORY_RSP *pSMBr = NULL;
790 int rc = 0;
791 int bytes_returned;
792 int name_len;
2baa2682 793 int remap = cifs_remap(cifs_sb);
1da177e4 794
f96637be 795 cifs_dbg(FYI, "In CIFSSMBRmDir\n");
1da177e4
LT
796RmDirRetry:
797 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
798 (void **) &pSMBr);
799 if (rc)
800 return rc;
801
802 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
f958ca5d
PS
803 name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
804 PATH_MAX, cifs_sb->local_nls,
805 remap);
1da177e4
LT
806 name_len++; /* trailing null */
807 name_len *= 2;
340625e6
RS
808 } else {
809 name_len = copy_path_name(pSMB->DirName, name);
1da177e4
LT
810 }
811
812 pSMB->BufferFormat = 0x04;
be8e3b00 813 inc_rfc1001_len(pSMB, name_len + 1);
1da177e4
LT
814 pSMB->ByteCount = cpu_to_le16(name_len + 1);
815 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
816 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
44c58186 817 cifs_stats_inc(&tcon->stats.cifs_stats.num_rmdirs);
ad7a2926 818 if (rc)
f96637be 819 cifs_dbg(FYI, "Error in RMDir = %d\n", rc);
1da177e4
LT
820
821 cifs_buf_release(pSMB);
822 if (rc == -EAGAIN)
823 goto RmDirRetry;
824 return rc;
825}
826
827int
c3ca78e2
SF
828CIFSSMBMkDir(const unsigned int xid, struct inode *inode, umode_t mode,
829 struct cifs_tcon *tcon, const char *name,
f436720e 830 struct cifs_sb_info *cifs_sb)
1da177e4
LT
831{
832 int rc = 0;
833 CREATE_DIRECTORY_REQ *pSMB = NULL;
834 CREATE_DIRECTORY_RSP *pSMBr = NULL;
835 int bytes_returned;
836 int name_len;
2baa2682 837 int remap = cifs_remap(cifs_sb);
1da177e4 838
f96637be 839 cifs_dbg(FYI, "In CIFSSMBMkDir\n");
1da177e4
LT
840MkDirRetry:
841 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
842 (void **) &pSMBr);
843 if (rc)
844 return rc;
845
846 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
acbbb76a 847 name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
f436720e
PS
848 PATH_MAX, cifs_sb->local_nls,
849 remap);
1da177e4
LT
850 name_len++; /* trailing null */
851 name_len *= 2;
340625e6
RS
852 } else {
853 name_len = copy_path_name(pSMB->DirName, name);
1da177e4
LT
854 }
855
856 pSMB->BufferFormat = 0x04;
be8e3b00 857 inc_rfc1001_len(pSMB, name_len + 1);
1da177e4
LT
858 pSMB->ByteCount = cpu_to_le16(name_len + 1);
859 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
860 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
44c58186 861 cifs_stats_inc(&tcon->stats.cifs_stats.num_mkdirs);
ad7a2926 862 if (rc)
f96637be 863 cifs_dbg(FYI, "Error in Mkdir = %d\n", rc);
a5a2b489 864
1da177e4
LT
865 cifs_buf_release(pSMB);
866 if (rc == -EAGAIN)
867 goto MkDirRetry;
868 return rc;
869}
870
2dd29d31 871int
6d5786a3
PS
872CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon,
873 __u32 posix_flags, __u64 mode, __u16 *netfid,
874 FILE_UNIX_BASIC_INFO *pRetData, __u32 *pOplock,
875 const char *name, const struct nls_table *nls_codepage,
876 int remap)
2dd29d31
SF
877{
878 TRANSACTION2_SPI_REQ *pSMB = NULL;
879 TRANSACTION2_SPI_RSP *pSMBr = NULL;
880 int name_len;
881 int rc = 0;
882 int bytes_returned = 0;
2dd29d31 883 __u16 params, param_offset, offset, byte_count, count;
ad7a2926
SF
884 OPEN_PSX_REQ *pdata;
885 OPEN_PSX_RSP *psx_rsp;
2dd29d31 886
f96637be 887 cifs_dbg(FYI, "In POSIX Create\n");
2dd29d31
SF
888PsxCreat:
889 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
890 (void **) &pSMBr);
891 if (rc)
892 return rc;
893
894 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
895 name_len =
acbbb76a
SF
896 cifsConvertToUTF16((__le16 *) pSMB->FileName, name,
897 PATH_MAX, nls_codepage, remap);
2dd29d31
SF
898 name_len++; /* trailing null */
899 name_len *= 2;
340625e6
RS
900 } else {
901 name_len = copy_path_name(pSMB->FileName, name);
2dd29d31
SF
902 }
903
904 params = 6 + name_len;
905 count = sizeof(OPEN_PSX_REQ);
906 pSMB->MaxParameterCount = cpu_to_le16(2);
907 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
908 pSMB->MaxSetupCount = 0;
909 pSMB->Reserved = 0;
910 pSMB->Flags = 0;
911 pSMB->Timeout = 0;
912 pSMB->Reserved2 = 0;
913 param_offset = offsetof(struct smb_com_transaction2_spi_req,
50c2f753 914 InformationLevel) - 4;
2dd29d31 915 offset = param_offset + params;
21a64910
SF
916 /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
917 pdata = (OPEN_PSX_REQ *)((char *)(pSMB) + offset + 4);
8f2376ad 918 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
2dd29d31 919 pdata->Permissions = cpu_to_le64(mode);
50c2f753 920 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
2dd29d31
SF
921 pdata->OpenFlags = cpu_to_le32(*pOplock);
922 pSMB->ParameterOffset = cpu_to_le16(param_offset);
923 pSMB->DataOffset = cpu_to_le16(offset);
924 pSMB->SetupCount = 1;
925 pSMB->Reserved3 = 0;
926 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
927 byte_count = 3 /* pad */ + params + count;
928
929 pSMB->DataCount = cpu_to_le16(count);
930 pSMB->ParameterCount = cpu_to_le16(params);
931 pSMB->TotalDataCount = pSMB->DataCount;
932 pSMB->TotalParameterCount = pSMB->ParameterCount;
933 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
934 pSMB->Reserved4 = 0;
be8e3b00 935 inc_rfc1001_len(pSMB, byte_count);
2dd29d31
SF
936 pSMB->ByteCount = cpu_to_le16(byte_count);
937 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
938 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
939 if (rc) {
f96637be 940 cifs_dbg(FYI, "Posix create returned %d\n", rc);
2dd29d31
SF
941 goto psx_create_err;
942 }
943
f96637be 944 cifs_dbg(FYI, "copying inode info\n");
2dd29d31
SF
945 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
946
820a803f 947 if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
2dd29d31
SF
948 rc = -EIO; /* bad smb */
949 goto psx_create_err;
950 }
951
952 /* copy return information to pRetData */
50c2f753 953 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
2dd29d31 954 + le16_to_cpu(pSMBr->t2.DataOffset));
50c2f753 955
2dd29d31 956 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
790fe579 957 if (netfid)
2dd29d31
SF
958 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
959 /* Let caller know file was created so we can set the mode. */
960 /* Do we care about the CreateAction in any other cases? */
790fe579 961 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
2dd29d31
SF
962 *pOplock |= CIFS_CREATE_ACTION;
963 /* check to make sure response data is there */
8f2376ad
CG
964 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
965 pRetData->Type = cpu_to_le32(-1); /* unknown */
f96637be 966 cifs_dbg(NOISY, "unknown type\n");
cbac3cba 967 } else {
820a803f 968 if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
2dd29d31 969 + sizeof(FILE_UNIX_BASIC_INFO)) {
f96637be 970 cifs_dbg(VFS, "Open response data too small\n");
8f2376ad 971 pRetData->Type = cpu_to_le32(-1);
2dd29d31
SF
972 goto psx_create_err;
973 }
50c2f753 974 memcpy((char *) pRetData,
cbac3cba 975 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
26f57364 976 sizeof(FILE_UNIX_BASIC_INFO));
2dd29d31 977 }
2dd29d31
SF
978
979psx_create_err:
980 cifs_buf_release(pSMB);
981
65bc98b0 982 if (posix_flags & SMB_O_DIRECTORY)
44c58186 983 cifs_stats_inc(&tcon->stats.cifs_stats.num_posixmkdirs);
65bc98b0 984 else
44c58186 985 cifs_stats_inc(&tcon->stats.cifs_stats.num_posixopens);
2dd29d31
SF
986
987 if (rc == -EAGAIN)
988 goto PsxCreat;
989
50c2f753 990 return rc;
2dd29d31
SF
991}
992
a9d02ad4
SF
993static __u16 convert_disposition(int disposition)
994{
995 __u16 ofun = 0;
996
997 switch (disposition) {
998 case FILE_SUPERSEDE:
999 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1000 break;
1001 case FILE_OPEN:
1002 ofun = SMBOPEN_OAPPEND;
1003 break;
1004 case FILE_CREATE:
1005 ofun = SMBOPEN_OCREATE;
1006 break;
1007 case FILE_OPEN_IF:
1008 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1009 break;
1010 case FILE_OVERWRITE:
1011 ofun = SMBOPEN_OTRUNC;
1012 break;
1013 case FILE_OVERWRITE_IF:
1014 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1015 break;
1016 default:
f96637be 1017 cifs_dbg(FYI, "unknown disposition %d\n", disposition);
a9d02ad4
SF
1018 ofun = SMBOPEN_OAPPEND; /* regular open */
1019 }
1020 return ofun;
1021}
1022
35fc37d5
JL
1023static int
1024access_flags_to_smbopen_mode(const int access_flags)
1025{
1026 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1027
1028 if (masked_flags == GENERIC_READ)
1029 return SMBOPEN_READ;
1030 else if (masked_flags == GENERIC_WRITE)
1031 return SMBOPEN_WRITE;
1032
1033 /* just go for read/write */
1034 return SMBOPEN_READWRITE;
1035}
1036
a9d02ad4 1037int
6d5786a3 1038SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
a9d02ad4 1039 const char *fileName, const int openDisposition,
ad7a2926
SF
1040 const int access_flags, const int create_options, __u16 *netfid,
1041 int *pOplock, FILE_ALL_INFO *pfile_info,
a9d02ad4
SF
1042 const struct nls_table *nls_codepage, int remap)
1043{
032e091d 1044 int rc;
a9d02ad4
SF
1045 OPENX_REQ *pSMB = NULL;
1046 OPENX_RSP *pSMBr = NULL;
1047 int bytes_returned;
1048 int name_len;
1049 __u16 count;
1050
1051OldOpenRetry:
1052 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1053 (void **) &pSMBr);
1054 if (rc)
1055 return rc;
1056
1057 pSMB->AndXCommand = 0xFF; /* none */
1058
1059 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1060 count = 1; /* account for one byte pad to word boundary */
1061 name_len =
acbbb76a
SF
1062 cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1063 fileName, PATH_MAX, nls_codepage, remap);
a9d02ad4
SF
1064 name_len++; /* trailing null */
1065 name_len *= 2;
340625e6 1066 } else {
a9d02ad4 1067 count = 0; /* no pad */
340625e6 1068 name_len = copy_path_name(pSMB->fileName, fileName);
a9d02ad4
SF
1069 }
1070 if (*pOplock & REQ_OPLOCK)
1071 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
26f57364 1072 else if (*pOplock & REQ_BATCHOPLOCK)
a9d02ad4 1073 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
26f57364 1074
a9d02ad4 1075 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
35fc37d5 1076 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
a9d02ad4
SF
1077 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1078 /* set file as system file if special file such
1079 as fifo and server expecting SFU style and
1080 no Unix extensions */
1081
790fe579
SF
1082 if (create_options & CREATE_OPTION_SPECIAL)
1083 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
ad7a2926
SF
1084 else /* BB FIXME BB */
1085 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
a9d02ad4 1086
67750fb9
JL
1087 if (create_options & CREATE_OPTION_READONLY)
1088 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
a9d02ad4
SF
1089
1090 /* BB FIXME BB */
50c2f753
SF
1091/* pSMB->CreateOptions = cpu_to_le32(create_options &
1092 CREATE_OPTIONS_MASK); */
a9d02ad4 1093 /* BB FIXME END BB */
3e87d803
SF
1094
1095 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
70ca734a 1096 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
a9d02ad4 1097 count += name_len;
be8e3b00 1098 inc_rfc1001_len(pSMB, count);
a9d02ad4
SF
1099
1100 pSMB->ByteCount = cpu_to_le16(count);
a9d02ad4 1101 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7749981e 1102 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
44c58186 1103 cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
a9d02ad4 1104 if (rc) {
f96637be 1105 cifs_dbg(FYI, "Error in Open = %d\n", rc);
a9d02ad4
SF
1106 } else {
1107 /* BB verify if wct == 15 */
1108
582d21e5 1109/* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
a9d02ad4
SF
1110
1111 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1112 /* Let caller know file was created so we can set the mode. */
1113 /* Do we care about the CreateAction in any other cases? */
1114 /* BB FIXME BB */
790fe579 1115/* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
a9d02ad4
SF
1116 *pOplock |= CIFS_CREATE_ACTION; */
1117 /* BB FIXME END */
1118
790fe579 1119 if (pfile_info) {
a9d02ad4
SF
1120 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1121 pfile_info->LastAccessTime = 0; /* BB fixme */
1122 pfile_info->LastWriteTime = 0; /* BB fixme */
1123 pfile_info->ChangeTime = 0; /* BB fixme */
70ca734a 1124 pfile_info->Attributes =
50c2f753 1125 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
a9d02ad4 1126 /* the file_info buf is endian converted by caller */
70ca734a
SF
1127 pfile_info->AllocationSize =
1128 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1129 pfile_info->EndOfFile = pfile_info->AllocationSize;
a9d02ad4 1130 pfile_info->NumberOfLinks = cpu_to_le32(1);
9a8165fc 1131 pfile_info->DeletePending = 0;
a9d02ad4
SF
1132 }
1133 }
1134
1135 cifs_buf_release(pSMB);
1136 if (rc == -EAGAIN)
1137 goto OldOpenRetry;
1138 return rc;
1139}
1140
1da177e4 1141int
d81b8a40
PS
1142CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,
1143 FILE_ALL_INFO *buf)
1da177e4 1144{
1afdea4f 1145 int rc;
9bf4fa01
PS
1146 OPEN_REQ *req = NULL;
1147 OPEN_RSP *rsp = NULL;
1da177e4
LT
1148 int bytes_returned;
1149 int name_len;
1150 __u16 count;
d81b8a40
PS
1151 struct cifs_sb_info *cifs_sb = oparms->cifs_sb;
1152 struct cifs_tcon *tcon = oparms->tcon;
2baa2682 1153 int remap = cifs_remap(cifs_sb);
d81b8a40
PS
1154 const struct nls_table *nls = cifs_sb->local_nls;
1155 int create_options = oparms->create_options;
1156 int desired_access = oparms->desired_access;
1157 int disposition = oparms->disposition;
1158 const char *path = oparms->path;
1da177e4
LT
1159
1160openRetry:
9bf4fa01
PS
1161 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **)&req,
1162 (void **)&rsp);
1da177e4
LT
1163 if (rc)
1164 return rc;
1165
9bf4fa01
PS
1166 /* no commands go after this */
1167 req->AndXCommand = 0xFF;
1da177e4 1168
9bf4fa01
PS
1169 if (req->hdr.Flags2 & SMBFLG2_UNICODE) {
1170 /* account for one byte pad to word boundary */
1171 count = 1;
1172 name_len = cifsConvertToUTF16((__le16 *)(req->fileName + 1),
1173 path, PATH_MAX, nls, remap);
1174 /* trailing null */
1175 name_len++;
1da177e4 1176 name_len *= 2;
9bf4fa01
PS
1177 req->NameLength = cpu_to_le16(name_len);
1178 } else {
1179 /* BB improve check for buffer overruns BB */
1180 /* no pad */
1181 count = 0;
340625e6 1182 name_len = copy_path_name(req->fileName, path);
9bf4fa01 1183 req->NameLength = cpu_to_le16(name_len);
1da177e4 1184 }
9bf4fa01
PS
1185
1186 if (*oplock & REQ_OPLOCK)
1187 req->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1188 else if (*oplock & REQ_BATCHOPLOCK)
1189 req->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1190
1191 req->DesiredAccess = cpu_to_le32(desired_access);
1192 req->AllocationSize = 0;
1193
1194 /*
1195 * Set file as system file if special file such as fifo and server
1196 * expecting SFU style and no Unix extensions.
1197 */
790fe579 1198 if (create_options & CREATE_OPTION_SPECIAL)
9bf4fa01 1199 req->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
eda3c029 1200 else
9bf4fa01 1201 req->FileAttributes = cpu_to_le32(ATTR_NORMAL);
67750fb9 1202
9bf4fa01
PS
1203 /*
1204 * XP does not handle ATTR_POSIX_SEMANTICS but it helps speed up case
1205 * sensitive checks for other servers such as Samba.
1206 */
1da177e4 1207 if (tcon->ses->capabilities & CAP_UNIX)
9bf4fa01 1208 req->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1da177e4 1209
67750fb9 1210 if (create_options & CREATE_OPTION_READONLY)
9bf4fa01
PS
1211 req->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1212
1213 req->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1214 req->CreateDisposition = cpu_to_le32(disposition);
1215 req->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
67750fb9 1216
09d1db5c 1217 /* BB Expirement with various impersonation levels and verify */
9bf4fa01
PS
1218 req->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1219 req->SecurityFlags = SECURITY_CONTEXT_TRACKING|SECURITY_EFFECTIVE_ONLY;
1da177e4
LT
1220
1221 count += name_len;
9bf4fa01 1222 inc_rfc1001_len(req, count);
1da177e4 1223
9bf4fa01
PS
1224 req->ByteCount = cpu_to_le16(count);
1225 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)req,
1226 (struct smb_hdr *)rsp, &bytes_returned, 0);
44c58186 1227 cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1da177e4 1228 if (rc) {
f96637be 1229 cifs_dbg(FYI, "Error in Open = %d\n", rc);
9bf4fa01
PS
1230 cifs_buf_release(req);
1231 if (rc == -EAGAIN)
1232 goto openRetry;
1233 return rc;
1da177e4 1234 }
a5a2b489 1235
9bf4fa01
PS
1236 /* 1 byte no need to le_to_cpu */
1237 *oplock = rsp->OplockLevel;
1238 /* cifs fid stays in le */
d81b8a40 1239 oparms->fid->netfid = rsp->Fid;
86f740f2 1240 oparms->fid->access = desired_access;
9bf4fa01
PS
1241
1242 /* Let caller know file was created so we can set the mode. */
1243 /* Do we care about the CreateAction in any other cases? */
1244 if (cpu_to_le32(FILE_CREATE) == rsp->CreateAction)
1245 *oplock |= CIFS_CREATE_ACTION;
1246
1247 if (buf) {
1248 /* copy from CreationTime to Attributes */
1249 memcpy((char *)buf, (char *)&rsp->CreationTime, 36);
1250 /* the file_info buf is endian converted by caller */
1251 buf->AllocationSize = rsp->AllocationSize;
1252 buf->EndOfFile = rsp->EndOfFile;
1253 buf->NumberOfLinks = cpu_to_le32(1);
1254 buf->DeletePending = 0;
1255 }
1256
1257 cifs_buf_release(req);
1da177e4
LT
1258 return rc;
1259}
1260
e28bc5b1
JL
1261static void
1262cifs_readv_callback(struct mid_q_entry *mid)
1263{
1264 struct cifs_readdata *rdata = mid->callback_data;
1265 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1266 struct TCP_Server_Info *server = tcon->ses->server;
738f9de5
PS
1267 struct smb_rqst rqst = { .rq_iov = rdata->iov,
1268 .rq_nvec = 2,
d08089f6
DH
1269 .rq_iter_size = iov_iter_count(&rdata->iter),
1270 .rq_iter = rdata->iter };
34f4deb7 1271 struct cifs_credits credits = { .value = 1, .instance = 0 };
e28bc5b1 1272
f96637be
JP
1273 cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%u\n",
1274 __func__, mid->mid, mid->mid_state, rdata->result,
1275 rdata->bytes);
e28bc5b1 1276
7c9421e1 1277 switch (mid->mid_state) {
e28bc5b1
JL
1278 case MID_RESPONSE_RECEIVED:
1279 /* result already set, check signature */
38d77c50 1280 if (server->sign) {
985e4ff0
SF
1281 int rc = 0;
1282
bf5ea0e2 1283 rc = cifs_verify_signature(&rqst, server,
0124cc45 1284 mid->sequence_number);
985e4ff0 1285 if (rc)
f96637be
JP
1286 cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
1287 rc);
e28bc5b1
JL
1288 }
1289 /* FIXME: should this be counted toward the initiating task? */
34a54d61
PS
1290 task_io_account_read(rdata->got_bytes);
1291 cifs_stats_bytes_read(tcon, rdata->got_bytes);
e28bc5b1
JL
1292 break;
1293 case MID_REQUEST_SUBMITTED:
1294 case MID_RETRY_NEEDED:
1295 rdata->result = -EAGAIN;
d913ed17
PS
1296 if (server->sign && rdata->got_bytes)
1297 /* reset bytes number since we can not check a sign */
1298 rdata->got_bytes = 0;
1299 /* FIXME: should this be counted toward the initiating task? */
1300 task_io_account_read(rdata->got_bytes);
1301 cifs_stats_bytes_read(tcon, rdata->got_bytes);
e28bc5b1
JL
1302 break;
1303 default:
1304 rdata->result = -EIO;
1305 }
1306
da472fc8 1307 queue_work(cifsiod_wq, &rdata->work);
70f08f91 1308 release_mid(mid);
34f4deb7 1309 add_credits(server, &credits, 0);
e28bc5b1
JL
1310}
1311
1312/* cifs_async_readv - send an async write, and set up mid to handle result */
1313int
1314cifs_async_readv(struct cifs_readdata *rdata)
1315{
1316 int rc;
1317 READ_REQ *smb = NULL;
1318 int wct;
1319 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
738f9de5
PS
1320 struct smb_rqst rqst = { .rq_iov = rdata->iov,
1321 .rq_nvec = 2 };
e28bc5b1 1322
f96637be
JP
1323 cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n",
1324 __func__, rdata->offset, rdata->bytes);
e28bc5b1
JL
1325
1326 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1327 wct = 12;
1328 else {
1329 wct = 10; /* old style read */
1330 if ((rdata->offset >> 32) > 0) {
1331 /* can not handle this big offset for old */
1332 return -EIO;
1333 }
1334 }
1335
1336 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
1337 if (rc)
1338 return rc;
1339
1340 smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid);
1341 smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
1342
1343 smb->AndXCommand = 0xFF; /* none */
4b4de76e 1344 smb->Fid = rdata->cfile->fid.netfid;
e28bc5b1
JL
1345 smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
1346 if (wct == 12)
1347 smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
1348 smb->Remaining = 0;
1349 smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
1350 smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
1351 if (wct == 12)
1352 smb->ByteCount = 0;
1353 else {
1354 /* old style read */
1355 struct smb_com_readx_req *smbr =
1356 (struct smb_com_readx_req *)smb;
1357 smbr->ByteCount = 0;
1358 }
1359
1360 /* 4 for RFC1001 length + 1 for BCC */
738f9de5
PS
1361 rdata->iov[0].iov_base = smb;
1362 rdata->iov[0].iov_len = 4;
1363 rdata->iov[1].iov_base = (char *)smb + 4;
1364 rdata->iov[1].iov_len = get_rfc1002_length(smb);
e28bc5b1 1365
6993f74a 1366 kref_get(&rdata->refcount);
fec344e3 1367 rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive,
3349c3a7 1368 cifs_readv_callback, NULL, rdata, 0, NULL);
e28bc5b1
JL
1369
1370 if (rc == 0)
44c58186 1371 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
6993f74a
JL
1372 else
1373 kref_put(&rdata->refcount, cifs_readdata_release);
e28bc5b1
JL
1374
1375 cifs_small_buf_release(smb);
1376 return rc;
1377}
1378
1da177e4 1379int
6d5786a3
PS
1380CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
1381 unsigned int *nbytes, char **buf, int *pbuf_type)
1da177e4
LT
1382{
1383 int rc = -EACCES;
1384 READ_REQ *pSMB = NULL;
1385 READ_RSP *pSMBr = NULL;
1386 char *pReadData = NULL;
bfa0d75a 1387 int wct;
ec637e3f
SF
1388 int resp_buf_type = 0;
1389 struct kvec iov[1];
da502f7d 1390 struct kvec rsp_iov;
d4ffff1f
PS
1391 __u32 pid = io_parms->pid;
1392 __u16 netfid = io_parms->netfid;
1393 __u64 offset = io_parms->offset;
96daf2b0 1394 struct cifs_tcon *tcon = io_parms->tcon;
d4ffff1f 1395 unsigned int count = io_parms->length;
1da177e4 1396
f96637be 1397 cifs_dbg(FYI, "Reading %d bytes on fid %d\n", count, netfid);
790fe579 1398 if (tcon->ses->capabilities & CAP_LARGE_FILES)
bfa0d75a 1399 wct = 12;
4c3130ef 1400 else {
bfa0d75a 1401 wct = 10; /* old style read */
d4ffff1f 1402 if ((offset >> 32) > 0) {
4c3130ef
SF
1403 /* can not handle this big offset for old */
1404 return -EIO;
1405 }
1406 }
1da177e4
LT
1407
1408 *nbytes = 0;
ec637e3f 1409 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1da177e4
LT
1410 if (rc)
1411 return rc;
1412
d4ffff1f
PS
1413 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1414 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1415
1da177e4
LT
1416 /* tcon and ses pointer are checked in smb_init */
1417 if (tcon->ses->server == NULL)
1418 return -ECONNABORTED;
1419
ec637e3f 1420 pSMB->AndXCommand = 0xFF; /* none */
1da177e4 1421 pSMB->Fid = netfid;
d4ffff1f 1422 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
790fe579 1423 if (wct == 12)
d4ffff1f 1424 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
bfa0d75a 1425
1da177e4
LT
1426 pSMB->Remaining = 0;
1427 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1428 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
790fe579 1429 if (wct == 12)
bfa0d75a
SF
1430 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1431 else {
1432 /* old style read */
50c2f753 1433 struct smb_com_readx_req *pSMBW =
bfa0d75a 1434 (struct smb_com_readx_req *)pSMB;
ec637e3f 1435 pSMBW->ByteCount = 0;
bfa0d75a 1436 }
ec637e3f
SF
1437
1438 iov[0].iov_base = (char *)pSMB;
be8e3b00 1439 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
da502f7d
PS
1440 rc = SendReceive2(xid, tcon->ses, iov, 1, &resp_buf_type,
1441 CIFS_LOG_ERROR, &rsp_iov);
1442 cifs_small_buf_release(pSMB);
44c58186 1443 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
da502f7d 1444 pSMBr = (READ_RSP *)rsp_iov.iov_base;
1da177e4 1445 if (rc) {
f96637be 1446 cifs_dbg(VFS, "Send error in read = %d\n", rc);
1da177e4
LT
1447 } else {
1448 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1449 data_length = data_length << 16;
1450 data_length += le16_to_cpu(pSMBr->DataLength);
1451 *nbytes = data_length;
1452
1453 /*check that DataLength would not go beyond end of SMB */
ec637e3f 1454 if ((data_length > CIFSMaxBufSize)
1da177e4 1455 || (data_length > count)) {
f96637be 1456 cifs_dbg(FYI, "bad length %d for count %d\n",
b6b38f70 1457 data_length, count);
1da177e4
LT
1458 rc = -EIO;
1459 *nbytes = 0;
1460 } else {
ec637e3f 1461 pReadData = (char *) (&pSMBr->hdr.Protocol) +
26f57364
SF
1462 le16_to_cpu(pSMBr->DataOffset);
1463/* if (rc = copy_to_user(buf, pReadData, data_length)) {
f96637be 1464 cifs_dbg(VFS, "Faulting on read rc = %d\n",rc);
50c2f753 1465 rc = -EFAULT;
26f57364 1466 }*/ /* can not use copy_to_user when using page cache*/
790fe579 1467 if (*buf)
50c2f753 1468 memcpy(*buf, pReadData, data_length);
1da177e4
LT
1469 }
1470 }
1da177e4 1471
790fe579 1472 if (*buf) {
da502f7d 1473 free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
790fe579 1474 } else if (resp_buf_type != CIFS_NO_BUFFER) {
50c2f753 1475 /* return buffer to caller to free */
da502f7d 1476 *buf = rsp_iov.iov_base;
790fe579 1477 if (resp_buf_type == CIFS_SMALL_BUFFER)
ec637e3f 1478 *pbuf_type = CIFS_SMALL_BUFFER;
790fe579 1479 else if (resp_buf_type == CIFS_LARGE_BUFFER)
ec637e3f 1480 *pbuf_type = CIFS_LARGE_BUFFER;
6cec2aed 1481 } /* else no valid buffer on return - leave as null */
ec637e3f
SF
1482
1483 /* Note: On -EAGAIN error only caller can retry on handle based calls
1da177e4
LT
1484 since file handle passed in no longer valid */
1485 return rc;
1486}
1487
ec637e3f 1488
1da177e4 1489int
6d5786a3 1490CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
dbbab325 1491 unsigned int *nbytes, const char *buf)
1da177e4
LT
1492{
1493 int rc = -EACCES;
1494 WRITE_REQ *pSMB = NULL;
1495 WRITE_RSP *pSMBr = NULL;
1c955187 1496 int bytes_returned, wct;
1da177e4
LT
1497 __u32 bytes_sent;
1498 __u16 byte_count;
fa2989f4
PS
1499 __u32 pid = io_parms->pid;
1500 __u16 netfid = io_parms->netfid;
1501 __u64 offset = io_parms->offset;
96daf2b0 1502 struct cifs_tcon *tcon = io_parms->tcon;
fa2989f4 1503 unsigned int count = io_parms->length;
1da177e4 1504
a24e2d7d
SF
1505 *nbytes = 0;
1506
f96637be 1507 /* cifs_dbg(FYI, "write at %lld %d bytes\n", offset, count);*/
790fe579 1508 if (tcon->ses == NULL)
1c955187
SF
1509 return -ECONNABORTED;
1510
790fe579 1511 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1c955187 1512 wct = 14;
4c3130ef 1513 else {
1c955187 1514 wct = 12;
4c3130ef
SF
1515 if ((offset >> 32) > 0) {
1516 /* can not handle big offset for old srv */
1517 return -EIO;
1518 }
1519 }
1c955187
SF
1520
1521 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1da177e4
LT
1522 (void **) &pSMBr);
1523 if (rc)
1524 return rc;
fa2989f4
PS
1525
1526 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1527 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1528
1da177e4
LT
1529 /* tcon and ses pointer are checked in smb_init */
1530 if (tcon->ses->server == NULL)
1531 return -ECONNABORTED;
1532
1533 pSMB->AndXCommand = 0xFF; /* none */
1534 pSMB->Fid = netfid;
1535 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
790fe579 1536 if (wct == 14)
1c955187 1537 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
50c2f753 1538
1da177e4
LT
1539 pSMB->Reserved = 0xFFFFFFFF;
1540 pSMB->WriteMode = 0;
1541 pSMB->Remaining = 0;
1542
50c2f753 1543 /* Can increase buffer size if buffer is big enough in some cases ie we
1da177e4
LT
1544 can send more if LARGE_WRITE_X capability returned by the server and if
1545 our buffer is big enough or if we convert to iovecs on socket writes
1546 and eliminate the copy to the CIFS buffer */
790fe579 1547 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1da177e4
LT
1548 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1549 } else {
1550 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1551 & ~0xFF;
1552 }
1553
1554 if (bytes_sent > count)
1555 bytes_sent = count;
1556 pSMB->DataOffset =
50c2f753 1557 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
790fe579 1558 if (buf)
61e74801 1559 memcpy(pSMB->Data, buf, bytes_sent);
dbbab325 1560 else if (count != 0) {
1da177e4
LT
1561 /* No buffer */
1562 cifs_buf_release(pSMB);
1563 return -EINVAL;
e30dcf3a 1564 } /* else setting file size with write of zero bytes */
790fe579 1565 if (wct == 14)
e30dcf3a 1566 byte_count = bytes_sent + 1; /* pad */
ad7a2926 1567 else /* wct == 12 */
e30dcf3a 1568 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
ad7a2926 1569
1da177e4
LT
1570 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1571 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
be8e3b00 1572 inc_rfc1001_len(pSMB, byte_count);
1c955187 1573
790fe579 1574 if (wct == 14)
1c955187 1575 pSMB->ByteCount = cpu_to_le16(byte_count);
50c2f753
SF
1576 else { /* old style write has byte count 4 bytes earlier
1577 so 4 bytes pad */
1578 struct smb_com_writex_req *pSMBW =
1c955187
SF
1579 (struct smb_com_writex_req *)pSMB;
1580 pSMBW->ByteCount = cpu_to_le16(byte_count);
1581 }
1da177e4
LT
1582
1583 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
dbbab325 1584 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
44c58186 1585 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1da177e4 1586 if (rc) {
f96637be 1587 cifs_dbg(FYI, "Send error in write = %d\n", rc);
1da177e4
LT
1588 } else {
1589 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1590 *nbytes = (*nbytes) << 16;
1591 *nbytes += le16_to_cpu(pSMBr->Count);
6513a81e
SJ
1592
1593 /*
1594 * Mask off high 16 bits when bytes written as returned by the
1595 * server is greater than bytes requested by the client. Some
1596 * OS/2 servers are known to set incorrect CountHigh values.
1597 */
1598 if (*nbytes > count)
1599 *nbytes &= 0xFFFF;
1da177e4
LT
1600 }
1601
1602 cifs_buf_release(pSMB);
1603
50c2f753 1604 /* Note: On -EAGAIN error only caller can retry on handle based calls
1da177e4
LT
1605 since file handle passed in no longer valid */
1606
1607 return rc;
1608}
1609
c28c89fc 1610/*
7c9421e1 1611 * Check the mid_state and signature on received buffer (if any), and queue the
c28c89fc
JL
1612 * workqueue completion task.
1613 */
1614static void
1615cifs_writev_callback(struct mid_q_entry *mid)
1616{
1617 struct cifs_writedata *wdata = mid->callback_data;
96daf2b0 1618 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
c28c89fc
JL
1619 unsigned int written;
1620 WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
34f4deb7 1621 struct cifs_credits credits = { .value = 1, .instance = 0 };
c28c89fc 1622
7c9421e1 1623 switch (mid->mid_state) {
c28c89fc
JL
1624 case MID_RESPONSE_RECEIVED:
1625 wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
1626 if (wdata->result != 0)
1627 break;
1628
1629 written = le16_to_cpu(smb->CountHigh);
1630 written <<= 16;
1631 written += le16_to_cpu(smb->Count);
1632 /*
1633 * Mask off high 16 bits when bytes written as returned
1634 * by the server is greater than bytes requested by the
1635 * client. OS/2 servers are known to set incorrect
1636 * CountHigh values.
1637 */
1638 if (written > wdata->bytes)
1639 written &= 0xFFFF;
1640
1641 if (written < wdata->bytes)
1642 wdata->result = -ENOSPC;
1643 else
1644 wdata->bytes = written;
1645 break;
1646 case MID_REQUEST_SUBMITTED:
1647 case MID_RETRY_NEEDED:
1648 wdata->result = -EAGAIN;
1649 break;
1650 default:
1651 wdata->result = -EIO;
1652 break;
1653 }
1654
da472fc8 1655 queue_work(cifsiod_wq, &wdata->work);
70f08f91 1656 release_mid(mid);
34f4deb7 1657 add_credits(tcon->ses->server, &credits, 0);
c28c89fc
JL
1658}
1659
1660/* cifs_async_writev - send an async write, and set up mid to handle result */
1661int
4a5c80d7
SF
1662cifs_async_writev(struct cifs_writedata *wdata,
1663 void (*release)(struct kref *kref))
c28c89fc 1664{
eddb079d 1665 int rc = -EACCES;
c28c89fc
JL
1666 WRITE_REQ *smb = NULL;
1667 int wct;
96daf2b0 1668 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
738f9de5 1669 struct kvec iov[2];
fec344e3 1670 struct smb_rqst rqst = { };
c28c89fc
JL
1671
1672 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1673 wct = 14;
1674 } else {
1675 wct = 12;
1676 if (wdata->offset >> 32 > 0) {
1677 /* can not handle big offset for old srv */
1678 return -EIO;
1679 }
1680 }
1681
1682 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
1683 if (rc)
1684 goto async_writev_out;
1685
fe5f5d2e
JL
1686 smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
1687 smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
fa2989f4 1688
c28c89fc 1689 smb->AndXCommand = 0xFF; /* none */
4b4de76e 1690 smb->Fid = wdata->cfile->fid.netfid;
c28c89fc
JL
1691 smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
1692 if (wct == 14)
1693 smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
1694 smb->Reserved = 0xFFFFFFFF;
1695 smb->WriteMode = 0;
1696 smb->Remaining = 0;
1697
1698 smb->DataOffset =
1699 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1700
1701 /* 4 for RFC1001 length + 1 for BCC */
738f9de5
PS
1702 iov[0].iov_len = 4;
1703 iov[0].iov_base = smb;
1704 iov[1].iov_len = get_rfc1002_length(smb) + 1;
1705 iov[1].iov_base = (char *)smb + 4;
c28c89fc 1706
738f9de5
PS
1707 rqst.rq_iov = iov;
1708 rqst.rq_nvec = 2;
d08089f6
DH
1709 rqst.rq_iter = wdata->iter;
1710 rqst.rq_iter_size = iov_iter_count(&wdata->iter);
c28c89fc 1711
f96637be
JP
1712 cifs_dbg(FYI, "async write at %llu %u bytes\n",
1713 wdata->offset, wdata->bytes);
c28c89fc
JL
1714
1715 smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
1716 smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
1717
1718 if (wct == 14) {
1719 inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
1720 put_bcc(wdata->bytes + 1, &smb->hdr);
1721 } else {
1722 /* wct == 12 */
1723 struct smb_com_writex_req *smbw =
1724 (struct smb_com_writex_req *)smb;
1725 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
1726 put_bcc(wdata->bytes + 5, &smbw->hdr);
738f9de5 1727 iov[1].iov_len += 4; /* pad bigger by four bytes */
c28c89fc
JL
1728 }
1729
1730 kref_get(&wdata->refcount);
fec344e3 1731 rc = cifs_call_async(tcon->ses->server, &rqst, NULL,
3349c3a7 1732 cifs_writev_callback, NULL, wdata, 0, NULL);
c28c89fc
JL
1733
1734 if (rc == 0)
44c58186 1735 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
c28c89fc 1736 else
4a5c80d7 1737 kref_put(&wdata->refcount, release);
c28c89fc 1738
c28c89fc
JL
1739async_writev_out:
1740 cifs_small_buf_release(smb);
c28c89fc
JL
1741 return rc;
1742}
1743
d6e04ae6 1744int
6d5786a3 1745CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
ba9ad725 1746 unsigned int *nbytes, struct kvec *iov, int n_vec)
1da177e4 1747{
136a5dc3 1748 int rc;
1da177e4 1749 WRITE_REQ *pSMB = NULL;
ec637e3f 1750 int wct;
d6e04ae6 1751 int smb_hdr_len;
ec637e3f 1752 int resp_buf_type = 0;
fa2989f4
PS
1753 __u32 pid = io_parms->pid;
1754 __u16 netfid = io_parms->netfid;
1755 __u64 offset = io_parms->offset;
96daf2b0 1756 struct cifs_tcon *tcon = io_parms->tcon;
fa2989f4 1757 unsigned int count = io_parms->length;
da502f7d 1758 struct kvec rsp_iov;
1da177e4 1759
fbec9ab9
JL
1760 *nbytes = 0;
1761
f96637be 1762 cifs_dbg(FYI, "write2 at %lld %d bytes\n", (long long)offset, count);
ff7feac9 1763
4c3130ef 1764 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
8cc64c6e 1765 wct = 14;
4c3130ef 1766 } else {
8cc64c6e 1767 wct = 12;
4c3130ef
SF
1768 if ((offset >> 32) > 0) {
1769 /* can not handle big offset for old srv */
1770 return -EIO;
1771 }
1772 }
8cc64c6e 1773 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1da177e4
LT
1774 if (rc)
1775 return rc;
fa2989f4
PS
1776
1777 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1778 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1779
1da177e4
LT
1780 /* tcon and ses pointer are checked in smb_init */
1781 if (tcon->ses->server == NULL)
1782 return -ECONNABORTED;
1783
d6e04ae6 1784 pSMB->AndXCommand = 0xFF; /* none */
1da177e4
LT
1785 pSMB->Fid = netfid;
1786 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
790fe579 1787 if (wct == 14)
8cc64c6e 1788 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1da177e4
LT
1789 pSMB->Reserved = 0xFFFFFFFF;
1790 pSMB->WriteMode = 0;
1791 pSMB->Remaining = 0;
d6e04ae6 1792
1da177e4 1793 pSMB->DataOffset =
50c2f753 1794 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1da177e4 1795
3e84469d
SF
1796 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1797 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
be8e3b00
SF
1798 /* header + 1 byte pad */
1799 smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
790fe579 1800 if (wct == 14)
be8e3b00 1801 inc_rfc1001_len(pSMB, count + 1);
8cc64c6e 1802 else /* wct == 12 */
be8e3b00 1803 inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
790fe579 1804 if (wct == 14)
8cc64c6e
SF
1805 pSMB->ByteCount = cpu_to_le16(count + 1);
1806 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
50c2f753 1807 struct smb_com_writex_req *pSMBW =
8cc64c6e
SF
1808 (struct smb_com_writex_req *)pSMB;
1809 pSMBW->ByteCount = cpu_to_le16(count + 5);
1810 }
3e84469d 1811 iov[0].iov_base = pSMB;
790fe579 1812 if (wct == 14)
ec637e3f
SF
1813 iov[0].iov_len = smb_hdr_len + 4;
1814 else /* wct == 12 pad bigger by four bytes */
1815 iov[0].iov_len = smb_hdr_len + 8;
50c2f753 1816
da502f7d
PS
1817 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, 0,
1818 &rsp_iov);
1819 cifs_small_buf_release(pSMB);
44c58186 1820 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1da177e4 1821 if (rc) {
f96637be 1822 cifs_dbg(FYI, "Send error Write2 = %d\n", rc);
790fe579 1823 } else if (resp_buf_type == 0) {
ec637e3f
SF
1824 /* presumably this can not happen, but best to be safe */
1825 rc = -EIO;
d6e04ae6 1826 } else {
da502f7d 1827 WRITE_RSP *pSMBr = (WRITE_RSP *)rsp_iov.iov_base;
d6e04ae6
SF
1828 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1829 *nbytes = (*nbytes) << 16;
1830 *nbytes += le16_to_cpu(pSMBr->Count);
6513a81e
SJ
1831
1832 /*
1833 * Mask off high 16 bits when bytes written as returned by the
1834 * server is greater than bytes requested by the client. OS/2
1835 * servers are known to set incorrect CountHigh values.
1836 */
1837 if (*nbytes > count)
1838 *nbytes &= 0xFFFF;
50c2f753 1839 }
1da177e4 1840
da502f7d 1841 free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
1da177e4 1842
50c2f753 1843 /* Note: On -EAGAIN error only caller can retry on handle based calls
1da177e4
LT
1844 since file handle passed in no longer valid */
1845
1846 return rc;
1847}
d6e04ae6 1848
6d5786a3
PS
1849int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
1850 const __u16 netfid, const __u8 lock_type, const __u32 num_unlock,
9ee305b7
PS
1851 const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
1852{
1853 int rc = 0;
1854 LOCK_REQ *pSMB = NULL;
1855 struct kvec iov[2];
da502f7d 1856 struct kvec rsp_iov;
9ee305b7
PS
1857 int resp_buf_type;
1858 __u16 count;
1859
f96637be
JP
1860 cifs_dbg(FYI, "cifs_lockv num lock %d num unlock %d\n",
1861 num_lock, num_unlock);
9ee305b7
PS
1862
1863 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1864 if (rc)
1865 return rc;
1866
1867 pSMB->Timeout = 0;
1868 pSMB->NumberOfLocks = cpu_to_le16(num_lock);
1869 pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
1870 pSMB->LockType = lock_type;
1871 pSMB->AndXCommand = 0xFF; /* none */
1872 pSMB->Fid = netfid; /* netfid stays le */
1873
1874 count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
1875 inc_rfc1001_len(pSMB, count);
1876 pSMB->ByteCount = cpu_to_le16(count);
1877
1878 iov[0].iov_base = (char *)pSMB;
1879 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
1880 (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
1881 iov[1].iov_base = (char *)buf;
1882 iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
1883
44c58186 1884 cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
392e1c5d
RS
1885 rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type,
1886 CIFS_NO_RSP_BUF, &rsp_iov);
da502f7d 1887 cifs_small_buf_release(pSMB);
9ee305b7 1888 if (rc)
f96637be 1889 cifs_dbg(FYI, "Send error in cifs_lockv = %d\n", rc);
9ee305b7
PS
1890
1891 return rc;
1892}
d6e04ae6 1893
1da177e4 1894int
6d5786a3 1895CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
03776f45 1896 const __u16 smb_file_id, const __u32 netpid, const __u64 len,
1da177e4 1897 const __u64 offset, const __u32 numUnlock,
12fed00d
PS
1898 const __u32 numLock, const __u8 lockType,
1899 const bool waitFlag, const __u8 oplock_level)
1da177e4
LT
1900{
1901 int rc = 0;
1902 LOCK_REQ *pSMB = NULL;
aaa9bbe0 1903/* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1da177e4 1904 int bytes_returned;
a891f0f8 1905 int flags = 0;
1da177e4
LT
1906 __u16 count;
1907
f96637be
JP
1908 cifs_dbg(FYI, "CIFSSMBLock timeout %d numLock %d\n",
1909 (int)waitFlag, numLock);
46810cbf
SF
1910 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1911
1da177e4
LT
1912 if (rc)
1913 return rc;
1914
790fe579 1915 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
a891f0f8 1916 /* no response expected */
392e1c5d 1917 flags = CIFS_NO_SRV_RSP | CIFS_NON_BLOCKING | CIFS_OBREAK_OP;
1da177e4 1918 pSMB->Timeout = 0;
4b18f2a9 1919 } else if (waitFlag) {
a891f0f8 1920 flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1da177e4
LT
1921 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1922 } else {
1923 pSMB->Timeout = 0;
1924 }
1925
1926 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1927 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1928 pSMB->LockType = lockType;
12fed00d 1929 pSMB->OplockLevel = oplock_level;
1da177e4
LT
1930 pSMB->AndXCommand = 0xFF; /* none */
1931 pSMB->Fid = smb_file_id; /* netfid stays le */
1932
790fe579 1933 if ((numLock != 0) || (numUnlock != 0)) {
03776f45 1934 pSMB->Locks[0].Pid = cpu_to_le16(netpid);
1da177e4
LT
1935 /* BB where to store pid high? */
1936 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1937 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1938 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1939 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1940 count = sizeof(LOCKING_ANDX_RANGE);
1941 } else {
1942 /* oplock break */
1943 count = 0;
1944 }
be8e3b00 1945 inc_rfc1001_len(pSMB, count);
1da177e4
LT
1946 pSMB->ByteCount = cpu_to_le16(count);
1947
da502f7d 1948 if (waitFlag)
7ee1af76 1949 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
aaa9bbe0 1950 (struct smb_hdr *) pSMB, &bytes_returned);
da502f7d 1951 else
a891f0f8 1952 rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags);
da502f7d 1953 cifs_small_buf_release(pSMB);
44c58186 1954 cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
ad7a2926 1955 if (rc)
f96637be 1956 cifs_dbg(FYI, "Send error in Lock = %d\n", rc);
1da177e4 1957
50c2f753 1958 /* Note: On -EAGAIN error only caller can retry on handle based calls
1da177e4
LT
1959 since file handle passed in no longer valid */
1960 return rc;
1961}
1962
08547b03 1963int
6d5786a3 1964CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
c5fd363d
JL
1965 const __u16 smb_file_id, const __u32 netpid,
1966 const loff_t start_offset, const __u64 len,
1967 struct file_lock *pLockData, const __u16 lock_type,
1968 const bool waitFlag)
08547b03
SF
1969{
1970 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1971 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
08547b03
SF
1972 struct cifs_posix_lock *parm_data;
1973 int rc = 0;
3a5ff61c 1974 int timeout = 0;
08547b03 1975 int bytes_returned = 0;
133672ef 1976 int resp_buf_type = 0;
08547b03 1977 __u16 params, param_offset, offset, byte_count, count;
133672ef 1978 struct kvec iov[1];
da502f7d 1979 struct kvec rsp_iov;
08547b03 1980
f96637be 1981 cifs_dbg(FYI, "Posix Lock\n");
fc94cdb9 1982
08547b03
SF
1983 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1984
1985 if (rc)
1986 return rc;
1987
1988 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1989
50c2f753 1990 params = 6;
08547b03
SF
1991 pSMB->MaxSetupCount = 0;
1992 pSMB->Reserved = 0;
1993 pSMB->Flags = 0;
08547b03
SF
1994 pSMB->Reserved2 = 0;
1995 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1996 offset = param_offset + params;
1997
08547b03
SF
1998 count = sizeof(struct cifs_posix_lock);
1999 pSMB->MaxParameterCount = cpu_to_le16(2);
ad7a2926 2000 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
08547b03
SF
2001 pSMB->SetupCount = 1;
2002 pSMB->Reserved3 = 0;
c5fd363d 2003 if (pLockData)
08547b03
SF
2004 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2005 else
2006 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2007 byte_count = 3 /* pad */ + params + count;
2008 pSMB->DataCount = cpu_to_le16(count);
2009 pSMB->ParameterCount = cpu_to_le16(params);
2010 pSMB->TotalDataCount = pSMB->DataCount;
2011 pSMB->TotalParameterCount = pSMB->ParameterCount;
2012 pSMB->ParameterOffset = cpu_to_le16(param_offset);
d4dc277c 2013 /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
50c2f753 2014 parm_data = (struct cifs_posix_lock *)
d4dc277c 2015 (((char *)pSMB) + offset + 4);
08547b03
SF
2016
2017 parm_data->lock_type = cpu_to_le16(lock_type);
790fe579 2018 if (waitFlag) {
133672ef 2019 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
cec6815a 2020 parm_data->lock_flags = cpu_to_le16(1);
3a5ff61c
SF
2021 pSMB->Timeout = cpu_to_le32(-1);
2022 } else
2023 pSMB->Timeout = 0;
2024
4f6bcec9 2025 parm_data->pid = cpu_to_le32(netpid);
c5fd363d 2026 parm_data->start = cpu_to_le64(start_offset);
cec6815a 2027 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
08547b03
SF
2028
2029 pSMB->DataOffset = cpu_to_le16(offset);
f26282c9 2030 pSMB->Fid = smb_file_id;
08547b03
SF
2031 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2032 pSMB->Reserved4 = 0;
be8e3b00 2033 inc_rfc1001_len(pSMB, byte_count);
08547b03 2034 pSMB->ByteCount = cpu_to_le16(byte_count);
7ee1af76
JA
2035 if (waitFlag) {
2036 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2037 (struct smb_hdr *) pSMBr, &bytes_returned);
2038 } else {
133672ef 2039 iov[0].iov_base = (char *)pSMB;
be8e3b00 2040 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
133672ef 2041 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
da502f7d
PS
2042 &resp_buf_type, timeout, &rsp_iov);
2043 pSMBr = (struct smb_com_transaction2_sfi_rsp *)rsp_iov.iov_base;
7ee1af76 2044 }
da502f7d 2045 cifs_small_buf_release(pSMB);
7ee1af76 2046
08547b03 2047 if (rc) {
f96637be 2048 cifs_dbg(FYI, "Send error in Posix Lock = %d\n", rc);
c5fd363d 2049 } else if (pLockData) {
fc94cdb9
SF
2050 /* lock structure can be returned on get */
2051 __u16 data_offset;
2052 __u16 data_count;
2053 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2054
820a803f 2055 if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
fc94cdb9
SF
2056 rc = -EIO; /* bad smb */
2057 goto plk_err_exit;
2058 }
fc94cdb9
SF
2059 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2060 data_count = le16_to_cpu(pSMBr->t2.DataCount);
790fe579 2061 if (data_count < sizeof(struct cifs_posix_lock)) {
fc94cdb9
SF
2062 rc = -EIO;
2063 goto plk_err_exit;
2064 }
2065 parm_data = (struct cifs_posix_lock *)
2066 ((char *)&pSMBr->hdr.Protocol + data_offset);
bc09d141 2067 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
fc94cdb9 2068 pLockData->fl_type = F_UNLCK;
f05337c6
PS
2069 else {
2070 if (parm_data->lock_type ==
bc09d141 2071 cpu_to_le16(CIFS_RDLCK))
f05337c6
PS
2072 pLockData->fl_type = F_RDLCK;
2073 else if (parm_data->lock_type ==
bc09d141 2074 cpu_to_le16(CIFS_WRLCK))
f05337c6
PS
2075 pLockData->fl_type = F_WRLCK;
2076
5443d130
SF
2077 pLockData->fl_start = le64_to_cpu(parm_data->start);
2078 pLockData->fl_end = pLockData->fl_start +
d80c6984
PA
2079 (le64_to_cpu(parm_data->length) ?
2080 le64_to_cpu(parm_data->length) - 1 : 0);
9d5b86ac 2081 pLockData->fl_pid = -le32_to_cpu(parm_data->pid);
f05337c6 2082 }
08547b03 2083 }
50c2f753 2084
fc94cdb9 2085plk_err_exit:
da502f7d 2086 free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
133672ef 2087
08547b03
SF
2088 /* Note: On -EAGAIN error only caller can retry on handle based calls
2089 since file handle passed in no longer valid */
2090
2091 return rc;
2092}
2093
2094
1da177e4 2095int
6d5786a3 2096CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
1da177e4
LT
2097{
2098 int rc = 0;
2099 CLOSE_REQ *pSMB = NULL;
f96637be 2100 cifs_dbg(FYI, "In CIFSSMBClose\n");
1da177e4
LT
2101
2102/* do not retry on dead session on close */
2103 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
790fe579 2104 if (rc == -EAGAIN)
1da177e4
LT
2105 return 0;
2106 if (rc)
2107 return rc;
2108
1da177e4 2109 pSMB->FileID = (__u16) smb_file_id;
b815f1e5 2110 pSMB->LastWriteTime = 0xFFFFFFFF;
1da177e4 2111 pSMB->ByteCount = 0;
792af7b0 2112 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
da502f7d 2113 cifs_small_buf_release(pSMB);
44c58186 2114 cifs_stats_inc(&tcon->stats.cifs_stats.num_closes);
1da177e4 2115 if (rc) {
790fe579 2116 if (rc != -EINTR) {
1da177e4 2117 /* EINTR is expected when user ctl-c to kill app */
f96637be 2118 cifs_dbg(VFS, "Send error in Close = %d\n", rc);
1da177e4
LT
2119 }
2120 }
2121
1da177e4 2122 /* Since session is dead, file will be closed on server already */
790fe579 2123 if (rc == -EAGAIN)
1da177e4
LT
2124 rc = 0;
2125
2126 return rc;
2127}
2128
b298f223 2129int
6d5786a3 2130CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
b298f223
SF
2131{
2132 int rc = 0;
2133 FLUSH_REQ *pSMB = NULL;
f96637be 2134 cifs_dbg(FYI, "In CIFSSMBFlush\n");
b298f223
SF
2135
2136 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2137 if (rc)
2138 return rc;
2139
2140 pSMB->FileID = (__u16) smb_file_id;
2141 pSMB->ByteCount = 0;
792af7b0 2142 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
da502f7d 2143 cifs_small_buf_release(pSMB);
44c58186 2144 cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);
b298f223 2145 if (rc)
f96637be 2146 cifs_dbg(VFS, "Send error in Flush = %d\n", rc);
b298f223
SF
2147
2148 return rc;
2149}
2150
1da177e4 2151int
6d5786a3 2152CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
8ceb9843
PS
2153 const char *from_name, const char *to_name,
2154 struct cifs_sb_info *cifs_sb)
1da177e4
LT
2155{
2156 int rc = 0;
2157 RENAME_REQ *pSMB = NULL;
2158 RENAME_RSP *pSMBr = NULL;
2159 int bytes_returned;
2160 int name_len, name_len2;
2161 __u16 count;
2baa2682 2162 int remap = cifs_remap(cifs_sb);
1da177e4 2163
f96637be 2164 cifs_dbg(FYI, "In CIFSSMBRename\n");
1da177e4
LT
2165renameRetry:
2166 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2167 (void **) &pSMBr);
2168 if (rc)
2169 return rc;
2170
2171 pSMB->BufferFormat = 0x04;
2172 pSMB->SearchAttributes =
2173 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2174 ATTR_DIRECTORY);
2175
2176 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
8ceb9843
PS
2177 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2178 from_name, PATH_MAX,
2179 cifs_sb->local_nls, remap);
1da177e4
LT
2180 name_len++; /* trailing null */
2181 name_len *= 2;
2182 pSMB->OldFileName[name_len] = 0x04; /* pad */
2183 /* protocol requires ASCII signature byte on Unicode string */
2184 pSMB->OldFileName[name_len + 1] = 0x00;
2185 name_len2 =
acbbb76a 2186 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
8ceb9843
PS
2187 to_name, PATH_MAX, cifs_sb->local_nls,
2188 remap);
1da177e4
LT
2189 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2190 name_len2 *= 2; /* convert to bytes */
340625e6
RS
2191 } else {
2192 name_len = copy_path_name(pSMB->OldFileName, from_name);
2193 name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
1da177e4 2194 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1da177e4
LT
2195 name_len2++; /* signature byte */
2196 }
2197
2198 count = 1 /* 1st signature byte */ + name_len + name_len2;
be8e3b00 2199 inc_rfc1001_len(pSMB, count);
1da177e4
LT
2200 pSMB->ByteCount = cpu_to_le16(count);
2201
2202 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2203 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
44c58186 2204 cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);
ad7a2926 2205 if (rc)
f96637be 2206 cifs_dbg(FYI, "Send error in rename = %d\n", rc);
1da177e4 2207
1da177e4
LT
2208 cifs_buf_release(pSMB);
2209
2210 if (rc == -EAGAIN)
2211 goto renameRetry;
2212
2213 return rc;
2214}
2215
6d5786a3 2216int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
391e5755 2217 int netfid, const char *target_name,
50c2f753 2218 const struct nls_table *nls_codepage, int remap)
1da177e4
LT
2219{
2220 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2221 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
50c2f753 2222 struct set_file_rename *rename_info;
1da177e4
LT
2223 char *data_offset;
2224 char dummy_string[30];
2225 int rc = 0;
2226 int bytes_returned = 0;
2227 int len_of_str;
2228 __u16 params, param_offset, offset, count, byte_count;
2229
f96637be 2230 cifs_dbg(FYI, "Rename to File by handle\n");
1da177e4
LT
2231 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2232 (void **) &pSMBr);
2233 if (rc)
2234 return rc;
2235
2236 params = 6;
2237 pSMB->MaxSetupCount = 0;
2238 pSMB->Reserved = 0;
2239 pSMB->Flags = 0;
2240 pSMB->Timeout = 0;
2241 pSMB->Reserved2 = 0;
2242 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2243 offset = param_offset + params;
2244
f371793d
SF
2245 /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
2246 data_offset = (char *)(pSMB) + offset + 4;
1da177e4
LT
2247 rename_info = (struct set_file_rename *) data_offset;
2248 pSMB->MaxParameterCount = cpu_to_le16(2);
ad7a2926 2249 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1da177e4
LT
2250 pSMB->SetupCount = 1;
2251 pSMB->Reserved3 = 0;
2252 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2253 byte_count = 3 /* pad */ + params;
2254 pSMB->ParameterCount = cpu_to_le16(params);
2255 pSMB->TotalParameterCount = pSMB->ParameterCount;
2256 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2257 pSMB->DataOffset = cpu_to_le16(offset);
2258 /* construct random name ".cifs_tmp<inodenum><mid>" */
2259 rename_info->overwrite = cpu_to_le32(1);
2260 rename_info->root_fid = 0;
2261 /* unicode only call */
790fe579 2262 if (target_name == NULL) {
50c2f753 2263 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
acbbb76a
SF
2264 len_of_str =
2265 cifsConvertToUTF16((__le16 *)rename_info->target_name,
737b758c 2266 dummy_string, 24, nls_codepage, remap);
1da177e4 2267 } else {
acbbb76a
SF
2268 len_of_str =
2269 cifsConvertToUTF16((__le16 *)rename_info->target_name,
50c2f753
SF
2270 target_name, PATH_MAX, nls_codepage,
2271 remap);
1da177e4
LT
2272 }
2273 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
d7173623 2274 count = sizeof(struct set_file_rename) + (2 * len_of_str);
1da177e4
LT
2275 byte_count += count;
2276 pSMB->DataCount = cpu_to_le16(count);
2277 pSMB->TotalDataCount = pSMB->DataCount;
2278 pSMB->Fid = netfid;
2279 pSMB->InformationLevel =
2280 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2281 pSMB->Reserved4 = 0;
be8e3b00 2282 inc_rfc1001_len(pSMB, byte_count);
1da177e4
LT
2283 pSMB->ByteCount = cpu_to_le16(byte_count);
2284 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
50c2f753 2285 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
44c58186 2286 cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);
ad7a2926 2287 if (rc)
f96637be
JP
2288 cifs_dbg(FYI, "Send error in Rename (by file handle) = %d\n",
2289 rc);
a5a2b489 2290
1da177e4
LT
2291 cifs_buf_release(pSMB);
2292
2293 /* Note: On -EAGAIN error only caller can retry on handle based calls
2294 since file handle passed in no longer valid */
2295
2296 return rc;
2297}
2298
2299int
6d5786a3
PS
2300CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon,
2301 const char *fromName, const __u16 target_tid, const char *toName,
2302 const int flags, const struct nls_table *nls_codepage, int remap)
1da177e4
LT
2303{
2304 int rc = 0;
2305 COPY_REQ *pSMB = NULL;
2306 COPY_RSP *pSMBr = NULL;
2307 int bytes_returned;
2308 int name_len, name_len2;
2309 __u16 count;
2310
f96637be 2311 cifs_dbg(FYI, "In CIFSSMBCopy\n");
1da177e4
LT
2312copyRetry:
2313 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2314 (void **) &pSMBr);
2315 if (rc)
2316 return rc;
2317
2318 pSMB->BufferFormat = 0x04;
2319 pSMB->Tid2 = target_tid;
2320
2321 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2322
2323 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
acbbb76a
SF
2324 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2325 fromName, PATH_MAX, nls_codepage,
2326 remap);
1da177e4
LT
2327 name_len++; /* trailing null */
2328 name_len *= 2;
2329 pSMB->OldFileName[name_len] = 0x04; /* pad */
2330 /* protocol requires ASCII signature byte on Unicode string */
2331 pSMB->OldFileName[name_len + 1] = 0x00;
50c2f753 2332 name_len2 =
acbbb76a
SF
2333 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2334 toName, PATH_MAX, nls_codepage, remap);
1da177e4
LT
2335 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2336 name_len2 *= 2; /* convert to bytes */
340625e6
RS
2337 } else {
2338 name_len = copy_path_name(pSMB->OldFileName, fromName);
1da177e4 2339 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
340625e6 2340 name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, toName);
1da177e4
LT
2341 name_len2++; /* signature byte */
2342 }
2343
2344 count = 1 /* 1st signature byte */ + name_len + name_len2;
be8e3b00 2345 inc_rfc1001_len(pSMB, count);
1da177e4
LT
2346 pSMB->ByteCount = cpu_to_le16(count);
2347
2348 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2349 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2350 if (rc) {
f96637be
JP
2351 cifs_dbg(FYI, "Send error in copy = %d with %d files copied\n",
2352 rc, le16_to_cpu(pSMBr->CopyCount));
1da177e4 2353 }
0d817bc0 2354 cifs_buf_release(pSMB);
1da177e4
LT
2355
2356 if (rc == -EAGAIN)
2357 goto copyRetry;
2358
2359 return rc;
2360}
2361
2362int
6d5786a3 2363CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
1da177e4 2364 const char *fromName, const char *toName,
bc8ebdc4 2365 const struct nls_table *nls_codepage, int remap)
1da177e4
LT
2366{
2367 TRANSACTION2_SPI_REQ *pSMB = NULL;
2368 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2369 char *data_offset;
2370 int name_len;
2371 int name_len_target;
2372 int rc = 0;
2373 int bytes_returned = 0;
2374 __u16 params, param_offset, offset, byte_count;
2375
f96637be 2376 cifs_dbg(FYI, "In Symlink Unix style\n");
1da177e4
LT
2377createSymLinkRetry:
2378 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2379 (void **) &pSMBr);
2380 if (rc)
2381 return rc;
2382
2383 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2384 name_len =
bc8ebdc4
NA
2385 cifsConvertToUTF16((__le16 *) pSMB->FileName, fromName,
2386 /* find define for this maxpathcomponent */
2387 PATH_MAX, nls_codepage, remap);
1da177e4
LT
2388 name_len++; /* trailing null */
2389 name_len *= 2;
2390
340625e6
RS
2391 } else {
2392 name_len = copy_path_name(pSMB->FileName, fromName);
1da177e4
LT
2393 }
2394 params = 6 + name_len;
2395 pSMB->MaxSetupCount = 0;
2396 pSMB->Reserved = 0;
2397 pSMB->Flags = 0;
2398 pSMB->Timeout = 0;
2399 pSMB->Reserved2 = 0;
2400 param_offset = offsetof(struct smb_com_transaction2_spi_req,
50c2f753 2401 InformationLevel) - 4;
1da177e4
LT
2402 offset = param_offset + params;
2403
ded2d99c
SF
2404 /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
2405 data_offset = (char *)pSMB + offset + 4;
1da177e4
LT
2406 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2407 name_len_target =
bc8ebdc4
NA
2408 cifsConvertToUTF16((__le16 *) data_offset, toName,
2409 /* find define for this maxpathcomponent */
2410 PATH_MAX, nls_codepage, remap);
1da177e4
LT
2411 name_len_target++; /* trailing null */
2412 name_len_target *= 2;
340625e6
RS
2413 } else {
2414 name_len_target = copy_path_name(data_offset, toName);
1da177e4
LT
2415 }
2416
2417 pSMB->MaxParameterCount = cpu_to_le16(2);
2418 /* BB find exact max on data count below from sess */
2419 pSMB->MaxDataCount = cpu_to_le16(1000);
2420 pSMB->SetupCount = 1;
2421 pSMB->Reserved3 = 0;
2422 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2423 byte_count = 3 /* pad */ + params + name_len_target;
2424 pSMB->DataCount = cpu_to_le16(name_len_target);
2425 pSMB->ParameterCount = cpu_to_le16(params);
2426 pSMB->TotalDataCount = pSMB->DataCount;
2427 pSMB->TotalParameterCount = pSMB->ParameterCount;
2428 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2429 pSMB->DataOffset = cpu_to_le16(offset);
2430 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2431 pSMB->Reserved4 = 0;
be8e3b00 2432 inc_rfc1001_len(pSMB, byte_count);
1da177e4
LT
2433 pSMB->ByteCount = cpu_to_le16(byte_count);
2434 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2435 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
44c58186 2436 cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);
ad7a2926 2437 if (rc)
f96637be
JP
2438 cifs_dbg(FYI, "Send error in SetPathInfo create symlink = %d\n",
2439 rc);
1da177e4 2440
0d817bc0 2441 cifs_buf_release(pSMB);
1da177e4
LT
2442
2443 if (rc == -EAGAIN)
2444 goto createSymLinkRetry;
2445
2446 return rc;
2447}
2448
2449int
6d5786a3 2450CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
1da177e4 2451 const char *fromName, const char *toName,
737b758c 2452 const struct nls_table *nls_codepage, int remap)
1da177e4
LT
2453{
2454 TRANSACTION2_SPI_REQ *pSMB = NULL;
2455 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2456 char *data_offset;
2457 int name_len;
2458 int name_len_target;
2459 int rc = 0;
2460 int bytes_returned = 0;
2461 __u16 params, param_offset, offset, byte_count;
2462
f96637be 2463 cifs_dbg(FYI, "In Create Hard link Unix style\n");
1da177e4
LT
2464createHardLinkRetry:
2465 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2466 (void **) &pSMBr);
2467 if (rc)
2468 return rc;
2469
2470 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
acbbb76a
SF
2471 name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
2472 PATH_MAX, nls_codepage, remap);
1da177e4
LT
2473 name_len++; /* trailing null */
2474 name_len *= 2;
2475
340625e6
RS
2476 } else {
2477 name_len = copy_path_name(pSMB->FileName, toName);
1da177e4
LT
2478 }
2479 params = 6 + name_len;
2480 pSMB->MaxSetupCount = 0;
2481 pSMB->Reserved = 0;
2482 pSMB->Flags = 0;
2483 pSMB->Timeout = 0;
2484 pSMB->Reserved2 = 0;
2485 param_offset = offsetof(struct smb_com_transaction2_spi_req,
50c2f753 2486 InformationLevel) - 4;
1da177e4
LT
2487 offset = param_offset + params;
2488
819f916c
SF
2489 /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
2490 data_offset = (char *)pSMB + offset + 4;
1da177e4
LT
2491 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2492 name_len_target =
acbbb76a
SF
2493 cifsConvertToUTF16((__le16 *) data_offset, fromName,
2494 PATH_MAX, nls_codepage, remap);
1da177e4
LT
2495 name_len_target++; /* trailing null */
2496 name_len_target *= 2;
340625e6
RS
2497 } else {
2498 name_len_target = copy_path_name(data_offset, fromName);
1da177e4
LT
2499 }
2500
2501 pSMB->MaxParameterCount = cpu_to_le16(2);
2502 /* BB find exact max on data count below from sess*/
2503 pSMB->MaxDataCount = cpu_to_le16(1000);
2504 pSMB->SetupCount = 1;
2505 pSMB->Reserved3 = 0;
2506 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2507 byte_count = 3 /* pad */ + params + name_len_target;
2508 pSMB->ParameterCount = cpu_to_le16(params);
2509 pSMB->TotalParameterCount = pSMB->ParameterCount;
2510 pSMB->DataCount = cpu_to_le16(name_len_target);
2511 pSMB->TotalDataCount = pSMB->DataCount;
2512 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2513 pSMB->DataOffset = cpu_to_le16(offset);
2514 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2515 pSMB->Reserved4 = 0;
be8e3b00 2516 inc_rfc1001_len(pSMB, byte_count);
1da177e4
LT
2517 pSMB->ByteCount = cpu_to_le16(byte_count);
2518 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2519 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
44c58186 2520 cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
ad7a2926 2521 if (rc)
f96637be
JP
2522 cifs_dbg(FYI, "Send error in SetPathInfo (hard link) = %d\n",
2523 rc);
1da177e4
LT
2524
2525 cifs_buf_release(pSMB);
2526 if (rc == -EAGAIN)
2527 goto createHardLinkRetry;
2528
2529 return rc;
2530}
2531
2532int
6d5786a3 2533CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
d6e906f1
SF
2534 const char *from_name, const char *to_name,
2535 struct cifs_sb_info *cifs_sb)
1da177e4
LT
2536{
2537 int rc = 0;
2538 NT_RENAME_REQ *pSMB = NULL;
2539 RENAME_RSP *pSMBr = NULL;
2540 int bytes_returned;
2541 int name_len, name_len2;
2542 __u16 count;
2baa2682 2543 int remap = cifs_remap(cifs_sb);
1da177e4 2544
f96637be 2545 cifs_dbg(FYI, "In CIFSCreateHardLink\n");
1da177e4
LT
2546winCreateHardLinkRetry:
2547
2548 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2549 (void **) &pSMBr);
2550 if (rc)
2551 return rc;
2552
2553 pSMB->SearchAttributes =
2554 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2555 ATTR_DIRECTORY);
2556 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2557 pSMB->ClusterCount = 0;
2558
2559 pSMB->BufferFormat = 0x04;
2560
2561 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2562 name_len =
d6e906f1
SF
2563 cifsConvertToUTF16((__le16 *) pSMB->OldFileName, from_name,
2564 PATH_MAX, cifs_sb->local_nls, remap);
1da177e4
LT
2565 name_len++; /* trailing null */
2566 name_len *= 2;
fcc7c09d
JL
2567
2568 /* protocol specifies ASCII buffer format (0x04) for unicode */
2569 pSMB->OldFileName[name_len] = 0x04;
2570 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
1da177e4 2571 name_len2 =
acbbb76a 2572 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
d6e906f1
SF
2573 to_name, PATH_MAX, cifs_sb->local_nls,
2574 remap);
1da177e4
LT
2575 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2576 name_len2 *= 2; /* convert to bytes */
340625e6
RS
2577 } else {
2578 name_len = copy_path_name(pSMB->OldFileName, from_name);
1da177e4 2579 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
340625e6 2580 name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
1da177e4
LT
2581 name_len2++; /* signature byte */
2582 }
2583
2584 count = 1 /* string type byte */ + name_len + name_len2;
be8e3b00 2585 inc_rfc1001_len(pSMB, count);
1da177e4
LT
2586 pSMB->ByteCount = cpu_to_le16(count);
2587
2588 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2589 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
44c58186 2590 cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
ad7a2926 2591 if (rc)
f96637be 2592 cifs_dbg(FYI, "Send error in hard link (NT rename) = %d\n", rc);
ad7a2926 2593
1da177e4
LT
2594 cifs_buf_release(pSMB);
2595 if (rc == -EAGAIN)
2596 goto winCreateHardLinkRetry;
2597
2598 return rc;
2599}
2600
2601int
6d5786a3 2602CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
460b9696 2603 const unsigned char *searchName, char **symlinkinfo,
bc8ebdc4 2604 const struct nls_table *nls_codepage, int remap)
1da177e4
LT
2605{
2606/* SMB_QUERY_FILE_UNIX_LINK */
2607 TRANSACTION2_QPI_REQ *pSMB = NULL;
2608 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2609 int rc = 0;
2610 int bytes_returned;
2611 int name_len;
2612 __u16 params, byte_count;
460b9696 2613 char *data_start;
1da177e4 2614
f96637be 2615 cifs_dbg(FYI, "In QPathSymLinkInfo (Unix) for path %s\n", searchName);
1da177e4
LT
2616
2617querySymLinkRetry:
2618 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2619 (void **) &pSMBr);
2620 if (rc)
2621 return rc;
2622
2623 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2624 name_len =
bc8ebdc4
NA
2625 cifsConvertToUTF16((__le16 *) pSMB->FileName,
2626 searchName, PATH_MAX, nls_codepage,
2627 remap);
1da177e4
LT
2628 name_len++; /* trailing null */
2629 name_len *= 2;
340625e6
RS
2630 } else {
2631 name_len = copy_path_name(pSMB->FileName, searchName);
1da177e4
LT
2632 }
2633
2634 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2635 pSMB->TotalDataCount = 0;
2636 pSMB->MaxParameterCount = cpu_to_le16(2);
46a7574c 2637 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
1da177e4
LT
2638 pSMB->MaxSetupCount = 0;
2639 pSMB->Reserved = 0;
2640 pSMB->Flags = 0;
2641 pSMB->Timeout = 0;
2642 pSMB->Reserved2 = 0;
2643 pSMB->ParameterOffset = cpu_to_le16(offsetof(
50c2f753 2644 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
1da177e4
LT
2645 pSMB->DataCount = 0;
2646 pSMB->DataOffset = 0;
2647 pSMB->SetupCount = 1;
2648 pSMB->Reserved3 = 0;
2649 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2650 byte_count = params + 1 /* pad */ ;
2651 pSMB->TotalParameterCount = cpu_to_le16(params);
2652 pSMB->ParameterCount = pSMB->TotalParameterCount;
2653 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2654 pSMB->Reserved4 = 0;
be8e3b00 2655 inc_rfc1001_len(pSMB, byte_count);
1da177e4
LT
2656 pSMB->ByteCount = cpu_to_le16(byte_count);
2657
2658 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2659 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2660 if (rc) {
f96637be 2661 cifs_dbg(FYI, "Send error in QuerySymLinkInfo = %d\n", rc);
1da177e4
LT
2662 } else {
2663 /* decode response */
2664
2665 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1da177e4 2666 /* BB also check enough total bytes returned */
820a803f 2667 if (rc || get_bcc(&pSMBr->hdr) < 2)
460b9696 2668 rc = -EIO;
1da177e4 2669 else {
0e0d2cf3 2670 bool is_unicode;
460b9696
JL
2671 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2672
2673 data_start = ((char *) &pSMBr->hdr.Protocol) +
2674 le16_to_cpu(pSMBr->t2.DataOffset);
1da177e4 2675
0e0d2cf3
SF
2676 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2677 is_unicode = true;
2678 else
2679 is_unicode = false;
2680
737b758c 2681 /* BB FIXME investigate remapping reserved chars here */
acbbb76a
SF
2682 *symlinkinfo = cifs_strndup_from_utf16(data_start,
2683 count, is_unicode, nls_codepage);
8b6427a2 2684 if (!*symlinkinfo)
460b9696 2685 rc = -ENOMEM;
1da177e4
LT
2686 }
2687 }
2688 cifs_buf_release(pSMB);
2689 if (rc == -EAGAIN)
2690 goto querySymLinkRetry;
2691 return rc;
2692}
2693
c52a9554
SF
2694/*
2695 * Recent Windows versions now create symlinks more frequently
2696 * and they use the "reparse point" mechanism below. We can of course
2697 * do symlinks nicely to Samba and other servers which support the
2698 * CIFS Unix Extensions and we can also do SFU symlinks and "client only"
2699 * "MF" symlinks optionally, but for recent Windows we really need to
2700 * reenable the code below and fix the cifs_symlink callers to handle this.
2701 * In the interim this code has been moved to its own config option so
2702 * it is not compiled in by default until callers fixed up and more tested.
2703 */
1da177e4 2704int
d244bf2d
PS
2705CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
2706 __u16 fid, char **symlinkinfo,
2707 const struct nls_table *nls_codepage)
1da177e4
LT
2708{
2709 int rc = 0;
2710 int bytes_returned;
50c2f753
SF
2711 struct smb_com_transaction_ioctl_req *pSMB;
2712 struct smb_com_transaction_ioctl_rsp *pSMBr;
d244bf2d
PS
2713 bool is_unicode;
2714 unsigned int sub_len;
2715 char *sub_start;
c31f3307
SF
2716 struct reparse_symlink_data *reparse_buf;
2717 struct reparse_posix_data *posix_buf;
d244bf2d
PS
2718 __u32 data_offset, data_count;
2719 char *end_of_smb;
2720
2721 cifs_dbg(FYI, "In Windows reparse style QueryLink for fid %u\n", fid);
1da177e4
LT
2722 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2723 (void **) &pSMBr);
2724 if (rc)
2725 return rc;
2726
2727 pSMB->TotalParameterCount = 0 ;
2728 pSMB->TotalDataCount = 0;
2729 pSMB->MaxParameterCount = cpu_to_le32(2);
2730 /* BB find exact data count max from sess structure BB */
c974befa 2731 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
1da177e4
LT
2732 pSMB->MaxSetupCount = 4;
2733 pSMB->Reserved = 0;
2734 pSMB->ParameterOffset = 0;
2735 pSMB->DataCount = 0;
2736 pSMB->DataOffset = 0;
2737 pSMB->SetupCount = 4;
2738 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2739 pSMB->ParameterCount = pSMB->TotalParameterCount;
2740 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2741 pSMB->IsFsctl = 1; /* FSCTL */
2742 pSMB->IsRootFlag = 0;
2743 pSMB->Fid = fid; /* file handle always le */
2744 pSMB->ByteCount = 0;
2745
2746 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2747 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2748 if (rc) {
f96637be 2749 cifs_dbg(FYI, "Send error in QueryReparseLinkInfo = %d\n", rc);
d244bf2d
PS
2750 goto qreparse_out;
2751 }
2752
2753 data_offset = le32_to_cpu(pSMBr->DataOffset);
2754 data_count = le32_to_cpu(pSMBr->DataCount);
2755 if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
2756 /* BB also check enough total bytes returned */
2757 rc = -EIO; /* bad smb */
2758 goto qreparse_out;
2759 }
2760 if (!data_count || (data_count > 2048)) {
2761 rc = -EIO;
2762 cifs_dbg(FYI, "Invalid return data count on get reparse info ioctl\n");
2763 goto qreparse_out;
2764 }
2765 end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
c31f3307 2766 reparse_buf = (struct reparse_symlink_data *)
d244bf2d
PS
2767 ((char *)&pSMBr->hdr.Protocol + data_offset);
2768 if ((char *)reparse_buf >= end_of_smb) {
2769 rc = -EIO;
2770 goto qreparse_out;
1da177e4 2771 }
c31f3307
SF
2772 if (reparse_buf->ReparseTag == cpu_to_le32(IO_REPARSE_TAG_NFS)) {
2773 cifs_dbg(FYI, "NFS style reparse tag\n");
2774 posix_buf = (struct reparse_posix_data *)reparse_buf;
2775
2776 if (posix_buf->InodeType != cpu_to_le64(NFS_SPECFILE_LNK)) {
2777 cifs_dbg(FYI, "unsupported file type 0x%llx\n",
2778 le64_to_cpu(posix_buf->InodeType));
2779 rc = -EOPNOTSUPP;
2780 goto qreparse_out;
2781 }
2782 is_unicode = true;
2783 sub_len = le16_to_cpu(reparse_buf->ReparseDataLength);
2784 if (posix_buf->PathBuffer + sub_len > end_of_smb) {
2785 cifs_dbg(FYI, "reparse buf beyond SMB\n");
2786 rc = -EIO;
2787 goto qreparse_out;
2788 }
2789 *symlinkinfo = cifs_strndup_from_utf16(posix_buf->PathBuffer,
2790 sub_len, is_unicode, nls_codepage);
2791 goto qreparse_out;
2792 } else if (reparse_buf->ReparseTag !=
2793 cpu_to_le32(IO_REPARSE_TAG_SYMLINK)) {
2794 rc = -EOPNOTSUPP;
2795 goto qreparse_out;
2796 }
2797
2798 /* Reparse tag is NTFS symlink */
2799 sub_start = le16_to_cpu(reparse_buf->SubstituteNameOffset) +
2800 reparse_buf->PathBuffer;
2801 sub_len = le16_to_cpu(reparse_buf->SubstituteNameLength);
2802 if (sub_start + sub_len > end_of_smb) {
d244bf2d
PS
2803 cifs_dbg(FYI, "reparse buf beyond SMB\n");
2804 rc = -EIO;
2805 goto qreparse_out;
2806 }
d244bf2d
PS
2807 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2808 is_unicode = true;
2809 else
2810 is_unicode = false;
989c7e51 2811
d244bf2d
PS
2812 /* BB FIXME investigate remapping reserved chars here */
2813 *symlinkinfo = cifs_strndup_from_utf16(sub_start, sub_len, is_unicode,
2814 nls_codepage);
2815 if (!*symlinkinfo)
2816 rc = -ENOMEM;
1da177e4 2817qreparse_out:
4a6d87f1 2818 cifs_buf_release(pSMB);
1da177e4 2819
d244bf2d
PS
2820 /*
2821 * Note: On -EAGAIN error only caller can retry on handle based calls
2822 * since file handle passed in no longer valid.
2823 */
1da177e4
LT
2824 return rc;
2825}
2826
c7f508a9
SF
2827int
2828CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
2829 __u16 fid)
2830{
2831 int rc = 0;
2832 int bytes_returned;
2833 struct smb_com_transaction_compr_ioctl_req *pSMB;
2834 struct smb_com_transaction_ioctl_rsp *pSMBr;
2835
2836 cifs_dbg(FYI, "Set compression for %u\n", fid);
2837 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2838 (void **) &pSMBr);
2839 if (rc)
2840 return rc;
2841
2842 pSMB->compression_state = cpu_to_le16(COMPRESSION_FORMAT_DEFAULT);
2843
2844 pSMB->TotalParameterCount = 0;
bc09d141 2845 pSMB->TotalDataCount = cpu_to_le32(2);
c7f508a9
SF
2846 pSMB->MaxParameterCount = 0;
2847 pSMB->MaxDataCount = 0;
2848 pSMB->MaxSetupCount = 4;
2849 pSMB->Reserved = 0;
2850 pSMB->ParameterOffset = 0;
bc09d141 2851 pSMB->DataCount = cpu_to_le32(2);
c7f508a9
SF
2852 pSMB->DataOffset =
2853 cpu_to_le32(offsetof(struct smb_com_transaction_compr_ioctl_req,
2854 compression_state) - 4); /* 84 */
2855 pSMB->SetupCount = 4;
bc09d141 2856 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
c7f508a9 2857 pSMB->ParameterCount = 0;
bc09d141 2858 pSMB->FunctionCode = cpu_to_le32(FSCTL_SET_COMPRESSION);
c7f508a9
SF
2859 pSMB->IsFsctl = 1; /* FSCTL */
2860 pSMB->IsRootFlag = 0;
2861 pSMB->Fid = fid; /* file handle always le */
2862 /* 3 byte pad, followed by 2 byte compress state */
bc09d141 2863 pSMB->ByteCount = cpu_to_le16(5);
c7f508a9
SF
2864 inc_rfc1001_len(pSMB, 5);
2865
2866 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2867 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2868 if (rc)
2869 cifs_dbg(FYI, "Send error in SetCompression = %d\n", rc);
2870
2871 cifs_buf_release(pSMB);
2872
2873 /*
2874 * Note: On -EAGAIN error only caller can retry on handle based calls
2875 * since file handle passed in no longer valid.
2876 */
2877 return rc;
2878}
2879
2880
1da177e4
LT
2881#ifdef CONFIG_CIFS_POSIX
2882
bd9684b0
CB
2883#ifdef CONFIG_FS_POSIX_ACL
2884/**
2885 * cifs_init_posix_acl - convert ACL from cifs to POSIX ACL format
2886 * @ace: POSIX ACL entry to store converted ACL into
2887 * @cifs_ace: ACL in cifs format
2888 *
2889 * Convert an Access Control Entry from wire format to local POSIX xattr
2890 * format.
2891 *
2892 * Note that the @cifs_uid member is used to store both {g,u}id_t.
2893 */
2894static void cifs_init_posix_acl(struct posix_acl_entry *ace,
2895 struct cifs_posix_ace *cifs_ace)
2896{
2897 /* u8 cifs fields do not need le conversion */
2898 ace->e_perm = cifs_ace->cifs_e_perm;
2899 ace->e_tag = cifs_ace->cifs_e_tag;
2900
2901 switch (ace->e_tag) {
2902 case ACL_USER:
2903 ace->e_uid = make_kuid(&init_user_ns,
2904 le64_to_cpu(cifs_ace->cifs_uid));
2905 break;
2906 case ACL_GROUP:
2907 ace->e_gid = make_kgid(&init_user_ns,
2908 le64_to_cpu(cifs_ace->cifs_uid));
2909 break;
2910 }
2911 return;
2912}
2913
2914/**
2915 * cifs_to_posix_acl - copy cifs ACL format to POSIX ACL format
2916 * @acl: ACLs returned in POSIX ACL format
2917 * @src: ACLs in cifs format
2918 * @acl_type: type of POSIX ACL requested
2919 * @size_of_data_area: size of SMB we got
2920 *
2921 * This function converts ACLs from cifs format to POSIX ACL format.
2922 * If @acl is NULL then the size of the buffer required to store POSIX ACLs in
2923 * their uapi format is returned.
2924 */
2925static int cifs_to_posix_acl(struct posix_acl **acl, char *src,
2926 const int acl_type, const int size_of_data_area)
2927{
2928 int size = 0;
2929 __u16 count;
2930 struct cifs_posix_ace *pACE;
2931 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2932 struct posix_acl *kacl = NULL;
2933 struct posix_acl_entry *pa, *pe;
2934
2935 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2936 return -EOPNOTSUPP;
2937
2938 if (acl_type == ACL_TYPE_ACCESS) {
2939 count = le16_to_cpu(cifs_acl->access_entry_count);
2940 pACE = &cifs_acl->ace_array[0];
2941 size = sizeof(struct cifs_posix_acl);
2942 size += sizeof(struct cifs_posix_ace) * count;
2943 /* check if we would go beyond end of SMB */
2944 if (size_of_data_area < size) {
2945 cifs_dbg(FYI, "bad CIFS POSIX ACL size %d vs. %d\n",
2946 size_of_data_area, size);
2947 return -EINVAL;
2948 }
2949 } else if (acl_type == ACL_TYPE_DEFAULT) {
2950 count = le16_to_cpu(cifs_acl->access_entry_count);
2951 size = sizeof(struct cifs_posix_acl);
2952 size += sizeof(struct cifs_posix_ace) * count;
2953 /* skip past access ACEs to get to default ACEs */
2954 pACE = &cifs_acl->ace_array[count];
2955 count = le16_to_cpu(cifs_acl->default_entry_count);
2956 size += sizeof(struct cifs_posix_ace) * count;
2957 /* check if we would go beyond end of SMB */
2958 if (size_of_data_area < size)
2959 return -EINVAL;
2960 } else {
2961 /* illegal type */
2962 return -EINVAL;
2963 }
2964
2965 /* Allocate number of POSIX ACLs to store in VFS format. */
2966 kacl = posix_acl_alloc(count, GFP_NOFS);
2967 if (!kacl)
2968 return -ENOMEM;
2969
2970 FOREACH_ACL_ENTRY(pa, kacl, pe) {
2971 cifs_init_posix_acl(pa, pACE);
2972 pACE++;
2973 }
2974
2975 *acl = kacl;
2976 return 0;
2977}
2978
dc1af4c4
CB
2979/**
2980 * cifs_init_ace - convert ACL entry from POSIX ACL to cifs format
2981 * @cifs_ace: the cifs ACL entry to store into
2982 * @local_ace: the POSIX ACL entry to convert
2983 */
2984static void cifs_init_ace(struct cifs_posix_ace *cifs_ace,
2985 const struct posix_acl_entry *local_ace)
2986{
2987 cifs_ace->cifs_e_perm = local_ace->e_perm;
2988 cifs_ace->cifs_e_tag = local_ace->e_tag;
2989
2990 switch (local_ace->e_tag) {
2991 case ACL_USER:
2992 cifs_ace->cifs_uid =
2993 cpu_to_le64(from_kuid(&init_user_ns, local_ace->e_uid));
2994 break;
2995 case ACL_GROUP:
2996 cifs_ace->cifs_uid =
2997 cpu_to_le64(from_kgid(&init_user_ns, local_ace->e_gid));
2998 break;
2999 default:
3000 cifs_ace->cifs_uid = cpu_to_le64(-1);
3001 }
3002}
3003
3004/**
3005 * posix_acl_to_cifs - convert ACLs from POSIX ACL to cifs format
3006 * @parm_data: ACLs in cifs format to conver to
3007 * @acl: ACLs in POSIX ACL format to convert from
3008 * @acl_type: the type of POSIX ACLs stored in @acl
3009 *
3010 * Return: the number cifs ACL entries after conversion
3011 */
3012static __u16 posix_acl_to_cifs(char *parm_data, const struct posix_acl *acl,
3013 const int acl_type)
3014{
3015 __u16 rc = 0;
3016 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
3017 const struct posix_acl_entry *pa, *pe;
3018 int count;
3019 int i = 0;
3020
3021 if ((acl == NULL) || (cifs_acl == NULL))
3022 return 0;
3023
3024 count = acl->a_count;
3025 cifs_dbg(FYI, "setting acl with %d entries\n", count);
3026
3027 /*
3028 * Note that the uapi POSIX ACL version is verified by the VFS and is
3029 * independent of the cifs ACL version. Changing the POSIX ACL version
3030 * is a uapi change and if it's changed we will pass down the POSIX ACL
3031 * version in struct posix_acl from the VFS. For now there's really
3032 * only one that all filesystems know how to deal with.
3033 */
3034 cifs_acl->version = cpu_to_le16(1);
3035 if (acl_type == ACL_TYPE_ACCESS) {
3036 cifs_acl->access_entry_count = cpu_to_le16(count);
3037 cifs_acl->default_entry_count = cpu_to_le16(0xFFFF);
3038 } else if (acl_type == ACL_TYPE_DEFAULT) {
3039 cifs_acl->default_entry_count = cpu_to_le16(count);
3040 cifs_acl->access_entry_count = cpu_to_le16(0xFFFF);
3041 } else {
3042 cifs_dbg(FYI, "unknown ACL type %d\n", acl_type);
3043 return 0;
3044 }
3045 FOREACH_ACL_ENTRY(pa, acl, pe) {
3046 cifs_init_ace(&cifs_acl->ace_array[i++], pa);
3047 }
3048 if (rc == 0) {
3049 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3050 rc += sizeof(struct cifs_posix_acl);
3051 /* BB add check to make sure ACL does not overflow SMB */
3052 }
3053 return rc;
3054}
3055
bd9684b0
CB
3056int cifs_do_get_acl(const unsigned int xid, struct cifs_tcon *tcon,
3057 const unsigned char *searchName, struct posix_acl **acl,
3058 const int acl_type, const struct nls_table *nls_codepage,
3059 int remap)
3060{
3061/* SMB_QUERY_POSIX_ACL */
3062 TRANSACTION2_QPI_REQ *pSMB = NULL;
3063 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3064 int rc = 0;
3065 int bytes_returned;
3066 int name_len;
3067 __u16 params, byte_count;
3068
3069 cifs_dbg(FYI, "In GetPosixACL (Unix) for path %s\n", searchName);
3070
3071queryAclRetry:
3072 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3073 (void **) &pSMBr);
3074 if (rc)
3075 return rc;
3076
3077 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3078 name_len =
3079 cifsConvertToUTF16((__le16 *) pSMB->FileName,
3080 searchName, PATH_MAX, nls_codepage,
3081 remap);
3082 name_len++; /* trailing null */
3083 name_len *= 2;
3084 pSMB->FileName[name_len] = 0;
3085 pSMB->FileName[name_len+1] = 0;
3086 } else {
3087 name_len = copy_path_name(pSMB->FileName, searchName);
3088 }
3089
3090 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3091 pSMB->TotalDataCount = 0;
3092 pSMB->MaxParameterCount = cpu_to_le16(2);
3093 /* BB find exact max data count below from sess structure BB */
3094 pSMB->MaxDataCount = cpu_to_le16(4000);
3095 pSMB->MaxSetupCount = 0;
3096 pSMB->Reserved = 0;
3097 pSMB->Flags = 0;
3098 pSMB->Timeout = 0;
3099 pSMB->Reserved2 = 0;
3100 pSMB->ParameterOffset = cpu_to_le16(
3101 offsetof(struct smb_com_transaction2_qpi_req,
3102 InformationLevel) - 4);
3103 pSMB->DataCount = 0;
3104 pSMB->DataOffset = 0;
3105 pSMB->SetupCount = 1;
3106 pSMB->Reserved3 = 0;
3107 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3108 byte_count = params + 1 /* pad */ ;
3109 pSMB->TotalParameterCount = cpu_to_le16(params);
3110 pSMB->ParameterCount = pSMB->TotalParameterCount;
3111 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3112 pSMB->Reserved4 = 0;
3113 inc_rfc1001_len(pSMB, byte_count);
3114 pSMB->ByteCount = cpu_to_le16(byte_count);
3115
3116 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3117 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3118 cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3119 if (rc) {
3120 cifs_dbg(FYI, "Send error in Query POSIX ACL = %d\n", rc);
3121 } else {
3122 /* decode response */
3123
3124 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3125 /* BB also check enough total bytes returned */
3126 if (rc || get_bcc(&pSMBr->hdr) < 2)
3127 rc = -EIO; /* bad smb */
3128 else {
3129 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3130 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3131 rc = cifs_to_posix_acl(acl,
3132 (char *)&pSMBr->hdr.Protocol+data_offset,
3133 acl_type, count);
3134 }
3135 }
3136 cifs_buf_release(pSMB);
3137 /*
3138 * The else branch after SendReceive() doesn't return EAGAIN so if we
3139 * allocated @acl in cifs_to_posix_acl() we are guaranteed to return
3140 * here and don't leak POSIX ACLs.
3141 */
3142 if (rc == -EAGAIN)
3143 goto queryAclRetry;
3144 return rc;
3145}
dc1af4c4
CB
3146
3147int cifs_do_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
3148 const unsigned char *fileName, const struct posix_acl *acl,
3149 const int acl_type, const struct nls_table *nls_codepage,
3150 int remap)
3151{
3152 struct smb_com_transaction2_spi_req *pSMB = NULL;
3153 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3154 char *parm_data;
3155 int name_len;
3156 int rc = 0;
3157 int bytes_returned = 0;
3158 __u16 params, byte_count, data_count, param_offset, offset;
3159
3160 cifs_dbg(FYI, "In SetPosixACL (Unix) for path %s\n", fileName);
3161setAclRetry:
3162 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3163 (void **) &pSMBr);
3164 if (rc)
3165 return rc;
3166 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3167 name_len =
3168 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
3169 PATH_MAX, nls_codepage, remap);
3170 name_len++; /* trailing null */
3171 name_len *= 2;
3172 } else {
3173 name_len = copy_path_name(pSMB->FileName, fileName);
3174 }
3175 params = 6 + name_len;
3176 pSMB->MaxParameterCount = cpu_to_le16(2);
3177 /* BB find max SMB size from sess */
3178 pSMB->MaxDataCount = cpu_to_le16(1000);
3179 pSMB->MaxSetupCount = 0;
3180 pSMB->Reserved = 0;
3181 pSMB->Flags = 0;
3182 pSMB->Timeout = 0;
3183 pSMB->Reserved2 = 0;
3184 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3185 InformationLevel) - 4;
3186 offset = param_offset + params;
3187 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3188 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3189
3190 /* convert to on the wire format for POSIX ACL */
3191 data_count = posix_acl_to_cifs(parm_data, acl, acl_type);
3192
3193 if (data_count == 0) {
3194 rc = -EOPNOTSUPP;
3195 goto setACLerrorExit;
3196 }
3197 pSMB->DataOffset = cpu_to_le16(offset);
3198 pSMB->SetupCount = 1;
3199 pSMB->Reserved3 = 0;
3200 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3201 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3202 byte_count = 3 /* pad */ + params + data_count;
3203 pSMB->DataCount = cpu_to_le16(data_count);
3204 pSMB->TotalDataCount = pSMB->DataCount;
3205 pSMB->ParameterCount = cpu_to_le16(params);
3206 pSMB->TotalParameterCount = pSMB->ParameterCount;
3207 pSMB->Reserved4 = 0;
3208 inc_rfc1001_len(pSMB, byte_count);
3209 pSMB->ByteCount = cpu_to_le16(byte_count);
3210 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3211 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3212 if (rc)
3213 cifs_dbg(FYI, "Set POSIX ACL returned %d\n", rc);
3214
3215setACLerrorExit:
3216 cifs_buf_release(pSMB);
3217 if (rc == -EAGAIN)
3218 goto setAclRetry;
3219 return rc;
3220}
bd9684b0
CB
3221#else
3222int cifs_do_get_acl(const unsigned int xid, struct cifs_tcon *tcon,
3223 const unsigned char *searchName, struct posix_acl **acl,
3224 const int acl_type, const struct nls_table *nls_codepage,
3225 int remap)
3226{
3227 return -EOPNOTSUPP;
3228}
dc1af4c4
CB
3229
3230int cifs_do_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
3231 const unsigned char *fileName, const struct posix_acl *acl,
3232 const int acl_type, const struct nls_table *nls_codepage,
3233 int remap)
3234{
3235 return -EOPNOTSUPP;
3236}
bd9684b0
CB
3237#endif /* CONFIG_FS_POSIX_ACL */
3238
f654bac2 3239int
6d5786a3 3240CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
ad7a2926 3241 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
f654bac2 3242{
50c2f753
SF
3243 int rc = 0;
3244 struct smb_t2_qfi_req *pSMB = NULL;
3245 struct smb_t2_qfi_rsp *pSMBr = NULL;
3246 int bytes_returned;
3247 __u16 params, byte_count;
f654bac2 3248
f96637be 3249 cifs_dbg(FYI, "In GetExtAttr\n");
790fe579
SF
3250 if (tcon == NULL)
3251 return -ENODEV;
f654bac2
SF
3252
3253GetExtAttrRetry:
790fe579 3254 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
fb157ed2 3255 (void **) &pSMBr);
790fe579
SF
3256 if (rc)
3257 return rc;
f654bac2 3258
ad7a2926 3259 params = 2 /* level */ + 2 /* fid */;
790fe579
SF
3260 pSMB->t2.TotalDataCount = 0;
3261 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3262 /* BB find exact max data count below from sess structure BB */
3263 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3264 pSMB->t2.MaxSetupCount = 0;
3265 pSMB->t2.Reserved = 0;
3266 pSMB->t2.Flags = 0;
3267 pSMB->t2.Timeout = 0;
3268 pSMB->t2.Reserved2 = 0;
3269 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3270 Fid) - 4);
3271 pSMB->t2.DataCount = 0;
3272 pSMB->t2.DataOffset = 0;
3273 pSMB->t2.SetupCount = 1;
3274 pSMB->t2.Reserved3 = 0;
3275 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3276 byte_count = params + 1 /* pad */ ;
3277 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3278 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3279 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3280 pSMB->Pad = 0;
f654bac2 3281 pSMB->Fid = netfid;
be8e3b00 3282 inc_rfc1001_len(pSMB, byte_count);
790fe579
SF
3283 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3284
3285 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3286 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3287 if (rc) {
f96637be 3288 cifs_dbg(FYI, "error %d in GetExtAttr\n", rc);
790fe579
SF
3289 } else {
3290 /* decode response */
3291 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
790fe579 3292 /* BB also check enough total bytes returned */
820a803f 3293 if (rc || get_bcc(&pSMBr->hdr) < 2)
790fe579
SF
3294 /* If rc should we check for EOPNOSUPP and
3295 disable the srvino flag? or in caller? */
3296 rc = -EIO; /* bad smb */
3297 else {
3298 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3299 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3300 struct file_chattr_info *pfinfo;
fb157ed2 3301
790fe579 3302 if (count != 16) {
a0a3036b 3303 cifs_dbg(FYI, "Invalid size ret in GetExtAttr\n");
790fe579
SF
3304 rc = -EIO;
3305 goto GetExtAttrOut;
3306 }
3307 pfinfo = (struct file_chattr_info *)
3308 (data_offset + (char *) &pSMBr->hdr.Protocol);
3309 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
f654bac2 3310 *pMask = le64_to_cpu(pfinfo->mask);
790fe579
SF
3311 }
3312 }
f654bac2 3313GetExtAttrOut:
790fe579
SF
3314 cifs_buf_release(pSMB);
3315 if (rc == -EAGAIN)
3316 goto GetExtAttrRetry;
3317 return rc;
f654bac2
SF
3318}
3319
f654bac2 3320#endif /* CONFIG_POSIX */
1da177e4 3321
79df1bae
JL
3322/*
3323 * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that
3324 * all NT TRANSACTS that we init here have total parm and data under about 400
3325 * bytes (to fit in small cifs buffer size), which is the case so far, it
3326 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3327 * returned setup area) and MaxParameterCount (returned parms size) must be set
3328 * by caller
3329 */
3330static int
3331smb_init_nttransact(const __u16 sub_command, const int setup_count,
96daf2b0 3332 const int parm_len, struct cifs_tcon *tcon,
79df1bae
JL
3333 void **ret_buf)
3334{
3335 int rc;
3336 __u32 temp_offset;
3337 struct smb_com_ntransact_req *pSMB;
3338
3339 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3340 (void **)&pSMB);
3341 if (rc)
3342 return rc;
3343 *ret_buf = (void *)pSMB;
3344 pSMB->Reserved = 0;
3345 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3346 pSMB->TotalDataCount = 0;
c974befa 3347 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
79df1bae
JL
3348 pSMB->ParameterCount = pSMB->TotalParameterCount;
3349 pSMB->DataCount = pSMB->TotalDataCount;
3350 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3351 (setup_count * 2) - 4 /* for rfc1001 length itself */;
3352 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3353 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3354 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3355 pSMB->SubCommand = cpu_to_le16(sub_command);
3356 return 0;
3357}
3358
3359static int
3360validate_ntransact(char *buf, char **ppparm, char **ppdata,
3361 __u32 *pparmlen, __u32 *pdatalen)
3362{
3363 char *end_of_smb;
3364 __u32 data_count, data_offset, parm_count, parm_offset;
3365 struct smb_com_ntransact_rsp *pSMBr;
820a803f 3366 u16 bcc;
79df1bae
JL
3367
3368 *pdatalen = 0;
3369 *pparmlen = 0;
3370
3371 if (buf == NULL)
3372 return -EINVAL;
3373
3374 pSMBr = (struct smb_com_ntransact_rsp *)buf;
3375
820a803f
JL
3376 bcc = get_bcc(&pSMBr->hdr);
3377 end_of_smb = 2 /* sizeof byte count */ + bcc +
79df1bae
JL
3378 (char *)&pSMBr->ByteCount;
3379
3380 data_offset = le32_to_cpu(pSMBr->DataOffset);
3381 data_count = le32_to_cpu(pSMBr->DataCount);
3382 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3383 parm_count = le32_to_cpu(pSMBr->ParameterCount);
3384
3385 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3386 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3387
3388 /* should we also check that parm and data areas do not overlap? */
3389 if (*ppparm > end_of_smb) {
f96637be 3390 cifs_dbg(FYI, "parms start after end of smb\n");
79df1bae
JL
3391 return -EINVAL;
3392 } else if (parm_count + *ppparm > end_of_smb) {
f96637be 3393 cifs_dbg(FYI, "parm end after end of smb\n");
79df1bae
JL
3394 return -EINVAL;
3395 } else if (*ppdata > end_of_smb) {
f96637be 3396 cifs_dbg(FYI, "data starts after end of smb\n");
79df1bae
JL
3397 return -EINVAL;
3398 } else if (data_count + *ppdata > end_of_smb) {
f96637be
JP
3399 cifs_dbg(FYI, "data %p + count %d (%p) past smb end %p start %p\n",
3400 *ppdata, data_count, (data_count + *ppdata),
3401 end_of_smb, pSMBr);
79df1bae 3402 return -EINVAL;
820a803f 3403 } else if (parm_count + data_count > bcc) {
f96637be 3404 cifs_dbg(FYI, "parm count and data count larger than SMB\n");
79df1bae
JL
3405 return -EINVAL;
3406 }
3407 *pdatalen = data_count;
3408 *pparmlen = parm_count;
3409 return 0;
3410}
3411
0a4b92c0
SF
3412/* Get Security Descriptor (by handle) from remote server for a file or dir */
3413int
6d5786a3 3414CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
630f3f0c 3415 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
0a4b92c0
SF
3416{
3417 int rc = 0;
3418 int buf_type = 0;
ad7a2926 3419 QUERY_SEC_DESC_REQ *pSMB;
0a4b92c0 3420 struct kvec iov[1];
da502f7d 3421 struct kvec rsp_iov;
0a4b92c0 3422
f96637be 3423 cifs_dbg(FYI, "GetCifsACL\n");
0a4b92c0 3424
630f3f0c
SF
3425 *pbuflen = 0;
3426 *acl_inf = NULL;
3427
b9c7a2bb 3428 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
0a4b92c0
SF
3429 8 /* parm len */, tcon, (void **) &pSMB);
3430 if (rc)
3431 return rc;
3432
3433 pSMB->MaxParameterCount = cpu_to_le32(4);
3434 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3435 pSMB->MaxSetupCount = 0;
3436 pSMB->Fid = fid; /* file handle always le */
3437 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3438 CIFS_ACL_DACL);
3439 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
be8e3b00 3440 inc_rfc1001_len(pSMB, 11);
0a4b92c0 3441 iov[0].iov_base = (char *)pSMB;
be8e3b00 3442 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
0a4b92c0 3443
a761ac57 3444 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
da502f7d
PS
3445 0, &rsp_iov);
3446 cifs_small_buf_release(pSMB);
44c58186 3447 cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
0a4b92c0 3448 if (rc) {
f96637be 3449 cifs_dbg(FYI, "Send error in QuerySecDesc = %d\n", rc);
0a4b92c0 3450 } else { /* decode response */
ad7a2926 3451 __le32 *parm;
630f3f0c
SF
3452 __u32 parm_len;
3453 __u32 acl_len;
50c2f753 3454 struct smb_com_ntransact_rsp *pSMBr;
630f3f0c 3455 char *pdata;
0a4b92c0
SF
3456
3457/* validate_nttransact */
da502f7d 3458 rc = validate_ntransact(rsp_iov.iov_base, (char **)&parm,
630f3f0c 3459 &pdata, &parm_len, pbuflen);
790fe579 3460 if (rc)
0a4b92c0 3461 goto qsec_out;
da502f7d 3462 pSMBr = (struct smb_com_ntransact_rsp *)rsp_iov.iov_base;
0a4b92c0 3463
f96637be
JP
3464 cifs_dbg(FYI, "smb %p parm %p data %p\n",
3465 pSMBr, parm, *acl_inf);
0a4b92c0
SF
3466
3467 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3468 rc = -EIO; /* bad smb */
630f3f0c 3469 *pbuflen = 0;
0a4b92c0
SF
3470 goto qsec_out;
3471 }
3472
3473/* BB check that data area is minimum length and as big as acl_len */
3474
af6f4612 3475 acl_len = le32_to_cpu(*parm);
630f3f0c 3476 if (acl_len != *pbuflen) {
f96637be
JP
3477 cifs_dbg(VFS, "acl length %d does not match %d\n",
3478 acl_len, *pbuflen);
630f3f0c
SF
3479 if (*pbuflen > acl_len)
3480 *pbuflen = acl_len;
3481 }
0a4b92c0 3482
630f3f0c
SF
3483 /* check if buffer is big enough for the acl
3484 header followed by the smallest SID */
3485 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3486 (*pbuflen >= 64 * 1024)) {
f96637be 3487 cifs_dbg(VFS, "bad acl length %d\n", *pbuflen);
630f3f0c
SF
3488 rc = -EINVAL;
3489 *pbuflen = 0;
3490 } else {
f7f7c185 3491 *acl_inf = kmemdup(pdata, *pbuflen, GFP_KERNEL);
630f3f0c
SF
3492 if (*acl_inf == NULL) {
3493 *pbuflen = 0;
3494 rc = -ENOMEM;
3495 }
630f3f0c 3496 }
0a4b92c0
SF
3497 }
3498qsec_out:
da502f7d 3499 free_rsp_buf(buf_type, rsp_iov.iov_base);
0a4b92c0
SF
3500 return rc;
3501}
97837582
SF
3502
3503int
6d5786a3 3504CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
a5ff3769 3505 struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
97837582
SF
3506{
3507 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3508 int rc = 0;
3509 int bytes_returned = 0;
3510 SET_SEC_DESC_REQ *pSMB = NULL;
b2a3ad9c 3511 void *pSMBr;
97837582
SF
3512
3513setCifsAclRetry:
b2a3ad9c 3514 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
97837582 3515 if (rc)
b2a3ad9c 3516 return rc;
97837582
SF
3517
3518 pSMB->MaxSetupCount = 0;
3519 pSMB->Reserved = 0;
3520
3521 param_count = 8;
3522 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3523 data_count = acllen;
3524 data_offset = param_offset + param_count;
3525 byte_count = 3 /* pad */ + param_count;
3526
3527 pSMB->DataCount = cpu_to_le32(data_count);
3528 pSMB->TotalDataCount = pSMB->DataCount;
3529 pSMB->MaxParameterCount = cpu_to_le32(4);
3530 pSMB->MaxDataCount = cpu_to_le32(16384);
3531 pSMB->ParameterCount = cpu_to_le32(param_count);
3532 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3533 pSMB->TotalParameterCount = pSMB->ParameterCount;
3534 pSMB->DataOffset = cpu_to_le32(data_offset);
3535 pSMB->SetupCount = 0;
3536 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3537 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3538
3539 pSMB->Fid = fid; /* file handle always le */
3540 pSMB->Reserved2 = 0;
a5ff3769 3541 pSMB->AclFlags = cpu_to_le32(aclflag);
97837582
SF
3542
3543 if (pntsd && acllen) {
b2a3ad9c
JL
3544 memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
3545 data_offset, pntsd, acllen);
be8e3b00 3546 inc_rfc1001_len(pSMB, byte_count + data_count);
97837582 3547 } else
be8e3b00 3548 inc_rfc1001_len(pSMB, byte_count);
97837582
SF
3549
3550 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3551 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3552
f96637be
JP
3553 cifs_dbg(FYI, "SetCIFSACL bytes_returned: %d, rc: %d\n",
3554 bytes_returned, rc);
97837582 3555 if (rc)
f96637be 3556 cifs_dbg(FYI, "Set CIFS ACL returned %d\n", rc);
97837582
SF
3557 cifs_buf_release(pSMB);
3558
3559 if (rc == -EAGAIN)
3560 goto setCifsAclRetry;
3561
3562 return (rc);
3563}
3564
0a4b92c0 3565
6b8edfe0
SF
3566/* Legacy Query Path Information call for lookup to old servers such
3567 as Win9x/WinME */
68889f26
PS
3568int
3569SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
3570 const char *search_name, FILE_ALL_INFO *data,
3571 const struct nls_table *nls_codepage, int remap)
6b8edfe0 3572{
ad7a2926
SF
3573 QUERY_INFORMATION_REQ *pSMB;
3574 QUERY_INFORMATION_RSP *pSMBr;
6b8edfe0
SF
3575 int rc = 0;
3576 int bytes_returned;
3577 int name_len;
3578
f96637be 3579 cifs_dbg(FYI, "In SMBQPath path %s\n", search_name);
6b8edfe0
SF
3580QInfRetry:
3581 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
50c2f753 3582 (void **) &pSMBr);
6b8edfe0
SF
3583 if (rc)
3584 return rc;
3585
3586 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3587 name_len =
acbbb76a 3588 cifsConvertToUTF16((__le16 *) pSMB->FileName,
68889f26 3589 search_name, PATH_MAX, nls_codepage,
acbbb76a 3590 remap);
6b8edfe0
SF
3591 name_len++; /* trailing null */
3592 name_len *= 2;
50c2f753 3593 } else {
340625e6 3594 name_len = copy_path_name(pSMB->FileName, search_name);
6b8edfe0
SF
3595 }
3596 pSMB->BufferFormat = 0x04;
50c2f753 3597 name_len++; /* account for buffer type byte */
be8e3b00 3598 inc_rfc1001_len(pSMB, (__u16)name_len);
6b8edfe0
SF
3599 pSMB->ByteCount = cpu_to_le16(name_len);
3600
3601 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
50c2f753 3602 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6b8edfe0 3603 if (rc) {
f96637be 3604 cifs_dbg(FYI, "Send error in QueryInfo = %d\n", rc);
68889f26 3605 } else if (data) {
95390201 3606 struct timespec64 ts;
1bd5bbcb 3607 __u32 time = le32_to_cpu(pSMBr->last_write_time);
ad7a2926
SF
3608
3609 /* decode response */
1bd5bbcb 3610 /* BB FIXME - add time zone adjustment BB */
68889f26 3611 memset(data, 0, sizeof(FILE_ALL_INFO));
1bd5bbcb
SF
3612 ts.tv_nsec = 0;
3613 ts.tv_sec = time;
3614 /* decode time fields */
68889f26
PS
3615 data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3616 data->LastWriteTime = data->ChangeTime;
3617 data->LastAccessTime = 0;
3618 data->AllocationSize =
70ca734a 3619 cpu_to_le64(le32_to_cpu(pSMBr->size));
68889f26
PS
3620 data->EndOfFile = data->AllocationSize;
3621 data->Attributes =
70ca734a 3622 cpu_to_le32(le16_to_cpu(pSMBr->attr));
6b8edfe0
SF
3623 } else
3624 rc = -EIO; /* bad buffer passed in */
3625
3626 cifs_buf_release(pSMB);
3627
3628 if (rc == -EAGAIN)
3629 goto QInfRetry;
3630
3631 return rc;
3632}
3633
bcd5357f 3634int
6d5786a3 3635CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
bcd5357f
JL
3636 u16 netfid, FILE_ALL_INFO *pFindData)
3637{
3638 struct smb_t2_qfi_req *pSMB = NULL;
3639 struct smb_t2_qfi_rsp *pSMBr = NULL;
3640 int rc = 0;
3641 int bytes_returned;
3642 __u16 params, byte_count;
3643
3644QFileInfoRetry:
3645 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3646 (void **) &pSMBr);
3647 if (rc)
3648 return rc;
3649
3650 params = 2 /* level */ + 2 /* fid */;
3651 pSMB->t2.TotalDataCount = 0;
3652 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3653 /* BB find exact max data count below from sess structure BB */
3654 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3655 pSMB->t2.MaxSetupCount = 0;
3656 pSMB->t2.Reserved = 0;
3657 pSMB->t2.Flags = 0;
3658 pSMB->t2.Timeout = 0;
3659 pSMB->t2.Reserved2 = 0;
3660 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3661 Fid) - 4);
3662 pSMB->t2.DataCount = 0;
3663 pSMB->t2.DataOffset = 0;
3664 pSMB->t2.SetupCount = 1;
3665 pSMB->t2.Reserved3 = 0;
3666 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3667 byte_count = params + 1 /* pad */ ;
3668 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3669 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3670 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3671 pSMB->Pad = 0;
3672 pSMB->Fid = netfid;
be8e3b00 3673 inc_rfc1001_len(pSMB, byte_count);
7ac0febb 3674 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
6b8edfe0 3675
bcd5357f
JL
3676 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3677 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3678 if (rc) {
a0a3036b 3679 cifs_dbg(FYI, "Send error in QFileInfo = %d\n", rc);
bcd5357f
JL
3680 } else { /* decode response */
3681 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
6b8edfe0 3682
bcd5357f
JL
3683 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3684 rc = -EIO;
820a803f 3685 else if (get_bcc(&pSMBr->hdr) < 40)
bcd5357f
JL
3686 rc = -EIO; /* bad smb */
3687 else if (pFindData) {
3688 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3689 memcpy((char *) pFindData,
3690 (char *) &pSMBr->hdr.Protocol +
3691 data_offset, sizeof(FILE_ALL_INFO));
3692 } else
3693 rc = -ENOMEM;
3694 }
3695 cifs_buf_release(pSMB);
3696 if (rc == -EAGAIN)
3697 goto QFileInfoRetry;
6b8edfe0 3698
bcd5357f
JL
3699 return rc;
3700}
6b8edfe0 3701
1da177e4 3702int
6d5786a3 3703CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
68889f26 3704 const char *search_name, FILE_ALL_INFO *data,
acf1a1b1 3705 int legacy /* old style infolevel */,
737b758c 3706 const struct nls_table *nls_codepage, int remap)
1da177e4 3707{
68889f26 3708 /* level 263 SMB_QUERY_FILE_ALL_INFO */
1da177e4
LT
3709 TRANSACTION2_QPI_REQ *pSMB = NULL;
3710 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3711 int rc = 0;
3712 int bytes_returned;
3713 int name_len;
3714 __u16 params, byte_count;
3715
f96637be 3716 /* cifs_dbg(FYI, "In QPathInfo path %s\n", search_name); */
1da177e4
LT
3717QPathInfoRetry:
3718 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3719 (void **) &pSMBr);
3720 if (rc)
3721 return rc;
3722
3723 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3724 name_len =
68889f26 3725 cifsConvertToUTF16((__le16 *) pSMB->FileName, search_name,
acbbb76a 3726 PATH_MAX, nls_codepage, remap);
1da177e4
LT
3727 name_len++; /* trailing null */
3728 name_len *= 2;
340625e6
RS
3729 } else {
3730 name_len = copy_path_name(pSMB->FileName, search_name);
1da177e4
LT
3731 }
3732
50c2f753 3733 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
1da177e4
LT
3734 pSMB->TotalDataCount = 0;
3735 pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5
SF
3736 /* BB find exact max SMB PDU from sess structure BB */
3737 pSMB->MaxDataCount = cpu_to_le16(4000);
1da177e4
LT
3738 pSMB->MaxSetupCount = 0;
3739 pSMB->Reserved = 0;
3740 pSMB->Flags = 0;
3741 pSMB->Timeout = 0;
3742 pSMB->Reserved2 = 0;
3743 pSMB->ParameterOffset = cpu_to_le16(offsetof(
50c2f753 3744 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
1da177e4
LT
3745 pSMB->DataCount = 0;
3746 pSMB->DataOffset = 0;
3747 pSMB->SetupCount = 1;
3748 pSMB->Reserved3 = 0;
3749 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3750 byte_count = params + 1 /* pad */ ;
3751 pSMB->TotalParameterCount = cpu_to_le16(params);
3752 pSMB->ParameterCount = pSMB->TotalParameterCount;
790fe579 3753 if (legacy)
acf1a1b1
SF
3754 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3755 else
3756 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
1da177e4 3757 pSMB->Reserved4 = 0;
be8e3b00 3758 inc_rfc1001_len(pSMB, byte_count);
1da177e4
LT
3759 pSMB->ByteCount = cpu_to_le16(byte_count);
3760
3761 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3762 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3763 if (rc) {
f96637be 3764 cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
1da177e4
LT
3765 } else { /* decode response */
3766 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3767
acf1a1b1
SF
3768 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3769 rc = -EIO;
820a803f 3770 else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
1da177e4 3771 rc = -EIO; /* bad smb */
820a803f 3772 else if (legacy && get_bcc(&pSMBr->hdr) < 24)
50c2f753
SF
3773 rc = -EIO; /* 24 or 26 expected but we do not read
3774 last field */
68889f26 3775 else if (data) {
acf1a1b1 3776 int size;
1da177e4 3777 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
ad7a2926 3778
68889f26
PS
3779 /*
3780 * On legacy responses we do not read the last field,
3781 * EAsize, fortunately since it varies by subdialect and
3782 * also note it differs on Set vs Get, ie two bytes or 4
3783 * bytes depending but we don't care here.
3784 */
ad7a2926 3785 if (legacy)
acf1a1b1
SF
3786 size = sizeof(FILE_INFO_STANDARD);
3787 else
3788 size = sizeof(FILE_ALL_INFO);
68889f26 3789 memcpy((char *) data, (char *) &pSMBr->hdr.Protocol +
acf1a1b1 3790 data_offset, size);
1da177e4
LT
3791 } else
3792 rc = -ENOMEM;
3793 }
3794 cifs_buf_release(pSMB);
3795 if (rc == -EAGAIN)
3796 goto QPathInfoRetry;
3797
3798 return rc;
3799}
3800
c8634fd3 3801int
6d5786a3 3802CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
c8634fd3
JL
3803 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
3804{
3805 struct smb_t2_qfi_req *pSMB = NULL;
3806 struct smb_t2_qfi_rsp *pSMBr = NULL;
3807 int rc = 0;
3808 int bytes_returned;
3809 __u16 params, byte_count;
3810
3811UnixQFileInfoRetry:
3812 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3813 (void **) &pSMBr);
3814 if (rc)
3815 return rc;
3816
3817 params = 2 /* level */ + 2 /* fid */;
3818 pSMB->t2.TotalDataCount = 0;
3819 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3820 /* BB find exact max data count below from sess structure BB */
3821 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3822 pSMB->t2.MaxSetupCount = 0;
3823 pSMB->t2.Reserved = 0;
3824 pSMB->t2.Flags = 0;
3825 pSMB->t2.Timeout = 0;
3826 pSMB->t2.Reserved2 = 0;
3827 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3828 Fid) - 4);
3829 pSMB->t2.DataCount = 0;
3830 pSMB->t2.DataOffset = 0;
3831 pSMB->t2.SetupCount = 1;
3832 pSMB->t2.Reserved3 = 0;
3833 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3834 byte_count = params + 1 /* pad */ ;
3835 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3836 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3837 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3838 pSMB->Pad = 0;
3839 pSMB->Fid = netfid;
be8e3b00 3840 inc_rfc1001_len(pSMB, byte_count);
7ac0febb 3841 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
c8634fd3
JL
3842
3843 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3844 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3845 if (rc) {
a0a3036b 3846 cifs_dbg(FYI, "Send error in UnixQFileInfo = %d\n", rc);
c8634fd3
JL
3847 } else { /* decode response */
3848 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3849
820a803f 3850 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
f96637be 3851 cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
c8634fd3
JL
3852 rc = -EIO; /* bad smb */
3853 } else {
3854 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3855 memcpy((char *) pFindData,
3856 (char *) &pSMBr->hdr.Protocol +
3857 data_offset,
3858 sizeof(FILE_UNIX_BASIC_INFO));
3859 }
3860 }
3861
3862 cifs_buf_release(pSMB);
3863 if (rc == -EAGAIN)
3864 goto UnixQFileInfoRetry;
3865
3866 return rc;
3867}
3868
1da177e4 3869int
6d5786a3 3870CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
1da177e4 3871 const unsigned char *searchName,
582d21e5 3872 FILE_UNIX_BASIC_INFO *pFindData,
737b758c 3873 const struct nls_table *nls_codepage, int remap)
1da177e4
LT
3874{
3875/* SMB_QUERY_FILE_UNIX_BASIC */
3876 TRANSACTION2_QPI_REQ *pSMB = NULL;
3877 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3878 int rc = 0;
3879 int bytes_returned = 0;
3880 int name_len;
3881 __u16 params, byte_count;
3882
f96637be 3883 cifs_dbg(FYI, "In QPathInfo (Unix) the path %s\n", searchName);
1da177e4
LT
3884UnixQPathInfoRetry:
3885 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3886 (void **) &pSMBr);
3887 if (rc)
3888 return rc;
3889
3890 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3891 name_len =
acbbb76a
SF
3892 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
3893 PATH_MAX, nls_codepage, remap);
1da177e4
LT
3894 name_len++; /* trailing null */
3895 name_len *= 2;
340625e6
RS
3896 } else {
3897 name_len = copy_path_name(pSMB->FileName, searchName);
1da177e4
LT
3898 }
3899
50c2f753 3900 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
1da177e4
LT
3901 pSMB->TotalDataCount = 0;
3902 pSMB->MaxParameterCount = cpu_to_le16(2);
3903 /* BB find exact max SMB PDU from sess structure BB */
50c2f753 3904 pSMB->MaxDataCount = cpu_to_le16(4000);
1da177e4
LT
3905 pSMB->MaxSetupCount = 0;
3906 pSMB->Reserved = 0;
3907 pSMB->Flags = 0;
3908 pSMB->Timeout = 0;
3909 pSMB->Reserved2 = 0;
3910 pSMB->ParameterOffset = cpu_to_le16(offsetof(
50c2f753 3911 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
1da177e4
LT
3912 pSMB->DataCount = 0;
3913 pSMB->DataOffset = 0;
3914 pSMB->SetupCount = 1;
3915 pSMB->Reserved3 = 0;
3916 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3917 byte_count = params + 1 /* pad */ ;
3918 pSMB->TotalParameterCount = cpu_to_le16(params);
3919 pSMB->ParameterCount = pSMB->TotalParameterCount;
3920 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3921 pSMB->Reserved4 = 0;
be8e3b00 3922 inc_rfc1001_len(pSMB, byte_count);
1da177e4
LT
3923 pSMB->ByteCount = cpu_to_le16(byte_count);
3924
3925 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3926 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3927 if (rc) {
a0a3036b 3928 cifs_dbg(FYI, "Send error in UnixQPathInfo = %d\n", rc);
1da177e4
LT
3929 } else { /* decode response */
3930 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3931
820a803f 3932 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
f96637be 3933 cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
1da177e4
LT
3934 rc = -EIO; /* bad smb */
3935 } else {
3936 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3937 memcpy((char *) pFindData,
3938 (char *) &pSMBr->hdr.Protocol +
3939 data_offset,
630f3f0c 3940 sizeof(FILE_UNIX_BASIC_INFO));
1da177e4
LT
3941 }
3942 }
3943 cifs_buf_release(pSMB);
3944 if (rc == -EAGAIN)
3945 goto UnixQPathInfoRetry;
3946
3947 return rc;
3948}
3949
1da177e4
LT
3950/* xid, tcon, searchName and codepage are input parms, rest are returned */
3951int
6d5786a3 3952CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
c052e2b4 3953 const char *searchName, struct cifs_sb_info *cifs_sb,
2608bee7 3954 __u16 *pnetfid, __u16 search_flags,
c052e2b4 3955 struct cifs_search_info *psrch_inf, bool msearch)
1da177e4
LT
3956{
3957/* level 257 SMB_ */
3958 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3959 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
ad7a2926 3960 T2_FFIRST_RSP_PARMS *parms;
1da177e4
LT
3961 int rc = 0;
3962 int bytes_returned = 0;
c052e2b4 3963 int name_len, remap;
1da177e4 3964 __u16 params, byte_count;
c052e2b4 3965 struct nls_table *nls_codepage;
1da177e4 3966
f96637be 3967 cifs_dbg(FYI, "In FindFirst for %s\n", searchName);
1da177e4
LT
3968
3969findFirstRetry:
3970 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3971 (void **) &pSMBr);
3972 if (rc)
3973 return rc;
3974
c052e2b4 3975 nls_codepage = cifs_sb->local_nls;
2baa2682 3976 remap = cifs_remap(cifs_sb);
c052e2b4 3977
1da177e4
LT
3978 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3979 name_len =
acbbb76a
SF
3980 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
3981 PATH_MAX, nls_codepage, remap);
737b758c
SF
3982 /* We can not add the asterik earlier in case
3983 it got remapped to 0xF03A as if it were part of the
3984 directory name instead of a wildcard */
1da177e4 3985 name_len *= 2;
c052e2b4
SP
3986 if (msearch) {
3987 pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
3988 pSMB->FileName[name_len+1] = 0;
3989 pSMB->FileName[name_len+2] = '*';
3990 pSMB->FileName[name_len+3] = 0;
3991 name_len += 4; /* now the trailing null */
3992 /* null terminate just in case */
3993 pSMB->FileName[name_len] = 0;
3994 pSMB->FileName[name_len+1] = 0;
3995 name_len += 2;
3996 }
340625e6
RS
3997 } else {
3998 name_len = copy_path_name(pSMB->FileName, searchName);
c052e2b4 3999 if (msearch) {
340625e6
RS
4000 if (WARN_ON_ONCE(name_len > PATH_MAX-2))
4001 name_len = PATH_MAX-2;
4002 /* overwrite nul byte */
4003 pSMB->FileName[name_len-1] = CIFS_DIR_SEP(cifs_sb);
4004 pSMB->FileName[name_len] = '*';
4005 pSMB->FileName[name_len+1] = 0;
4006 name_len += 2;
c052e2b4 4007 }
1da177e4
LT
4008 }
4009
4010 params = 12 + name_len /* includes null */ ;
4011 pSMB->TotalDataCount = 0; /* no EAs */
4012 pSMB->MaxParameterCount = cpu_to_le16(10);
c974befa 4013 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
1da177e4
LT
4014 pSMB->MaxSetupCount = 0;
4015 pSMB->Reserved = 0;
4016 pSMB->Flags = 0;
4017 pSMB->Timeout = 0;
4018 pSMB->Reserved2 = 0;
4019 byte_count = params + 1 /* pad */ ;
4020 pSMB->TotalParameterCount = cpu_to_le16(params);
4021 pSMB->ParameterCount = pSMB->TotalParameterCount;
4022 pSMB->ParameterOffset = cpu_to_le16(
88274815
SF
4023 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
4024 - 4);
1da177e4
LT
4025 pSMB->DataCount = 0;
4026 pSMB->DataOffset = 0;
4027 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
4028 pSMB->Reserved3 = 0;
4029 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4030 pSMB->SearchAttributes =
4031 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4032 ATTR_DIRECTORY);
50c2f753 4033 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
2608bee7 4034 pSMB->SearchFlags = cpu_to_le16(search_flags);
1da177e4
LT
4035 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4036
4037 /* BB what should we set StorageType to? Does it matter? BB */
4038 pSMB->SearchStorageType = 0;
be8e3b00 4039 inc_rfc1001_len(pSMB, byte_count);
1da177e4
LT
4040 pSMB->ByteCount = cpu_to_le16(byte_count);
4041
4042 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4043 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
44c58186 4044 cifs_stats_inc(&tcon->stats.cifs_stats.num_ffirst);
1da177e4 4045
88274815
SF
4046 if (rc) {/* BB add logic to retry regular search if Unix search
4047 rejected unexpectedly by server */
1da177e4 4048 /* BB Add code to handle unsupported level rc */
f96637be 4049 cifs_dbg(FYI, "Error in FindFirst = %d\n", rc);
1982c344 4050
88274815 4051 cifs_buf_release(pSMB);
1da177e4
LT
4052
4053 /* BB eventually could optimize out free and realloc of buf */
4054 /* for this case */
4055 if (rc == -EAGAIN)
4056 goto findFirstRetry;
4057 } else { /* decode response */
4058 /* BB remember to free buffer if error BB */
4059 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
790fe579 4060 if (rc == 0) {
b77d753c
SF
4061 unsigned int lnoff;
4062
1da177e4 4063 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4b18f2a9 4064 psrch_inf->unicode = true;
1da177e4 4065 else
4b18f2a9 4066 psrch_inf->unicode = false;
1da177e4
LT
4067
4068 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
01d1bd76 4069 psrch_inf->smallBuf = false;
50c2f753
SF
4070 psrch_inf->srch_entries_start =
4071 (char *) &pSMBr->hdr.Protocol +
1da177e4 4072 le16_to_cpu(pSMBr->t2.DataOffset);
1da177e4
LT
4073 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
4074 le16_to_cpu(pSMBr->t2.ParameterOffset));
4075
790fe579 4076 if (parms->EndofSearch)
4b18f2a9 4077 psrch_inf->endOfSearch = true;
1da177e4 4078 else
4b18f2a9 4079 psrch_inf->endOfSearch = false;
1da177e4 4080
50c2f753
SF
4081 psrch_inf->entries_in_buffer =
4082 le16_to_cpu(parms->SearchCount);
60808233 4083 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
1da177e4 4084 psrch_inf->entries_in_buffer;
b77d753c 4085 lnoff = le16_to_cpu(parms->LastNameOffset);
c974befa 4086 if (CIFSMaxBufSize < lnoff) {
f96637be 4087 cifs_dbg(VFS, "ignoring corrupt resume name\n");
b77d753c
SF
4088 psrch_inf->last_entry = NULL;
4089 return rc;
4090 }
4091
0752f152 4092 psrch_inf->last_entry = psrch_inf->srch_entries_start +
b77d753c
SF
4093 lnoff;
4094
c052e2b4
SP
4095 if (pnetfid)
4096 *pnetfid = parms->SearchHandle;
1da177e4
LT
4097 } else {
4098 cifs_buf_release(pSMB);
4099 }
4100 }
4101
4102 return rc;
4103}
4104
6d5786a3
PS
4105int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
4106 __u16 searchHandle, __u16 search_flags,
4107 struct cifs_search_info *psrch_inf)
1da177e4
LT
4108{
4109 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4110 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
ad7a2926 4111 T2_FNEXT_RSP_PARMS *parms;
1da177e4
LT
4112 char *response_data;
4113 int rc = 0;
9438fabb
JL
4114 int bytes_returned;
4115 unsigned int name_len;
1da177e4
LT
4116 __u16 params, byte_count;
4117
f96637be 4118 cifs_dbg(FYI, "In FindNext\n");
1da177e4 4119
4b18f2a9 4120 if (psrch_inf->endOfSearch)
1da177e4
LT
4121 return -ENOENT;
4122
4123 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4124 (void **) &pSMBr);
4125 if (rc)
4126 return rc;
4127
50c2f753 4128 params = 14; /* includes 2 bytes of null string, converted to LE below*/
1da177e4
LT
4129 byte_count = 0;
4130 pSMB->TotalDataCount = 0; /* no EAs */
4131 pSMB->MaxParameterCount = cpu_to_le16(8);
c974befa 4132 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
1da177e4
LT
4133 pSMB->MaxSetupCount = 0;
4134 pSMB->Reserved = 0;
4135 pSMB->Flags = 0;
4136 pSMB->Timeout = 0;
4137 pSMB->Reserved2 = 0;
4138 pSMB->ParameterOffset = cpu_to_le16(
4139 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4140 pSMB->DataCount = 0;
4141 pSMB->DataOffset = 0;
4142 pSMB->SetupCount = 1;
4143 pSMB->Reserved3 = 0;
4144 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4145 pSMB->SearchHandle = searchHandle; /* always kept as le */
4146 pSMB->SearchCount =
630f3f0c 4147 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
1da177e4
LT
4148 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4149 pSMB->ResumeKey = psrch_inf->resume_key;
2608bee7 4150 pSMB->SearchFlags = cpu_to_le16(search_flags);
1da177e4
LT
4151
4152 name_len = psrch_inf->resume_name_len;
4153 params += name_len;
790fe579 4154 if (name_len < PATH_MAX) {
1da177e4
LT
4155 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4156 byte_count += name_len;
ef6724e3
SF
4157 /* 14 byte parm len above enough for 2 byte null terminator */
4158 pSMB->ResumeFileName[name_len] = 0;
4159 pSMB->ResumeFileName[name_len+1] = 0;
1da177e4
LT
4160 } else {
4161 rc = -EINVAL;
4162 goto FNext2_err_exit;
4163 }
4164 byte_count = params + 1 /* pad */ ;
4165 pSMB->TotalParameterCount = cpu_to_le16(params);
4166 pSMB->ParameterCount = pSMB->TotalParameterCount;
be8e3b00 4167 inc_rfc1001_len(pSMB, byte_count);
1da177e4 4168 pSMB->ByteCount = cpu_to_le16(byte_count);
50c2f753 4169
1da177e4
LT
4170 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4171 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
44c58186 4172 cifs_stats_inc(&tcon->stats.cifs_stats.num_fnext);
1da177e4
LT
4173 if (rc) {
4174 if (rc == -EBADF) {
4b18f2a9 4175 psrch_inf->endOfSearch = true;
6353450a 4176 cifs_buf_release(pSMB);
50c2f753 4177 rc = 0; /* search probably was closed at end of search*/
1da177e4 4178 } else
f96637be 4179 cifs_dbg(FYI, "FindNext returned = %d\n", rc);
1da177e4
LT
4180 } else { /* decode response */
4181 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
50c2f753 4182
790fe579 4183 if (rc == 0) {
b77d753c
SF
4184 unsigned int lnoff;
4185
1da177e4
LT
4186 /* BB fixme add lock for file (srch_info) struct here */
4187 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4b18f2a9 4188 psrch_inf->unicode = true;
1da177e4 4189 else
4b18f2a9 4190 psrch_inf->unicode = false;
1da177e4
LT
4191 response_data = (char *) &pSMBr->hdr.Protocol +
4192 le16_to_cpu(pSMBr->t2.ParameterOffset);
4193 parms = (T2_FNEXT_RSP_PARMS *)response_data;
4194 response_data = (char *)&pSMBr->hdr.Protocol +
4195 le16_to_cpu(pSMBr->t2.DataOffset);
790fe579 4196 if (psrch_inf->smallBuf)
d47d7c1a
SF
4197 cifs_small_buf_release(
4198 psrch_inf->ntwrk_buf_start);
4199 else
4200 cifs_buf_release(psrch_inf->ntwrk_buf_start);
1da177e4
LT
4201 psrch_inf->srch_entries_start = response_data;
4202 psrch_inf->ntwrk_buf_start = (char *)pSMB;
01d1bd76 4203 psrch_inf->smallBuf = false;
790fe579 4204 if (parms->EndofSearch)
4b18f2a9 4205 psrch_inf->endOfSearch = true;
1da177e4 4206 else
4b18f2a9 4207 psrch_inf->endOfSearch = false;
50c2f753
SF
4208 psrch_inf->entries_in_buffer =
4209 le16_to_cpu(parms->SearchCount);
1da177e4
LT
4210 psrch_inf->index_of_last_entry +=
4211 psrch_inf->entries_in_buffer;
b77d753c 4212 lnoff = le16_to_cpu(parms->LastNameOffset);
c974befa 4213 if (CIFSMaxBufSize < lnoff) {
f96637be 4214 cifs_dbg(VFS, "ignoring corrupt resume name\n");
b77d753c
SF
4215 psrch_inf->last_entry = NULL;
4216 return rc;
4217 } else
4218 psrch_inf->last_entry =
4219 psrch_inf->srch_entries_start + lnoff;
4220
f96637be
JP
4221/* cifs_dbg(FYI, "fnxt2 entries in buf %d index_of_last %d\n",
4222 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
1da177e4
LT
4223
4224 /* BB fixme add unlock here */
4225 }
4226
4227 }
4228
4229 /* BB On error, should we leave previous search buf (and count and
4230 last entry fields) intact or free the previous one? */
4231
4232 /* Note: On -EAGAIN error only caller can retry on handle based calls
4233 since file handle passed in no longer valid */
4234FNext2_err_exit:
4235 if (rc != 0)
4236 cifs_buf_release(pSMB);
1da177e4
LT
4237 return rc;
4238}
4239
4240int
6d5786a3 4241CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
50c2f753 4242 const __u16 searchHandle)
1da177e4
LT
4243{
4244 int rc = 0;
4245 FINDCLOSE_REQ *pSMB = NULL;
1da177e4 4246
f96637be 4247 cifs_dbg(FYI, "In CIFSSMBFindClose\n");
1da177e4
LT
4248 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4249
4250 /* no sense returning error if session restarted
4251 as file handle has been closed */
790fe579 4252 if (rc == -EAGAIN)
1da177e4
LT
4253 return 0;
4254 if (rc)
4255 return rc;
4256
1da177e4
LT
4257 pSMB->FileID = searchHandle;
4258 pSMB->ByteCount = 0;
792af7b0 4259 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
da502f7d 4260 cifs_small_buf_release(pSMB);
ad7a2926 4261 if (rc)
f96637be 4262 cifs_dbg(VFS, "Send error in FindClose = %d\n", rc);
ad7a2926 4263
44c58186 4264 cifs_stats_inc(&tcon->stats.cifs_stats.num_fclose);
1da177e4
LT
4265
4266 /* Since session is dead, search handle closed on server already */
4267 if (rc == -EAGAIN)
4268 rc = 0;
4269
4270 return rc;
4271}
4272
1da177e4 4273int
6d5786a3 4274CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
1208ef1f 4275 const char *search_name, __u64 *inode_number,
50c2f753 4276 const struct nls_table *nls_codepage, int remap)
1da177e4
LT
4277{
4278 int rc = 0;
4279 TRANSACTION2_QPI_REQ *pSMB = NULL;
4280 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4281 int name_len, bytes_returned;
4282 __u16 params, byte_count;
4283
f96637be 4284 cifs_dbg(FYI, "In GetSrvInodeNum for %s\n", search_name);
790fe579 4285 if (tcon == NULL)
50c2f753 4286 return -ENODEV;
1da177e4
LT
4287
4288GetInodeNumberRetry:
4289 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
50c2f753 4290 (void **) &pSMBr);
1da177e4
LT
4291 if (rc)
4292 return rc;
4293
1da177e4
LT
4294 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4295 name_len =
acbbb76a 4296 cifsConvertToUTF16((__le16 *) pSMB->FileName,
1208ef1f 4297 search_name, PATH_MAX, nls_codepage,
acbbb76a 4298 remap);
1da177e4
LT
4299 name_len++; /* trailing null */
4300 name_len *= 2;
340625e6
RS
4301 } else {
4302 name_len = copy_path_name(pSMB->FileName, search_name);
1da177e4
LT
4303 }
4304
4305 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
4306 pSMB->TotalDataCount = 0;
4307 pSMB->MaxParameterCount = cpu_to_le16(2);
4308 /* BB find exact max data count below from sess structure BB */
4309 pSMB->MaxDataCount = cpu_to_le16(4000);
4310 pSMB->MaxSetupCount = 0;
4311 pSMB->Reserved = 0;
4312 pSMB->Flags = 0;
4313 pSMB->Timeout = 0;
4314 pSMB->Reserved2 = 0;
4315 pSMB->ParameterOffset = cpu_to_le16(offsetof(
50c2f753 4316 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
1da177e4
LT
4317 pSMB->DataCount = 0;
4318 pSMB->DataOffset = 0;
4319 pSMB->SetupCount = 1;
4320 pSMB->Reserved3 = 0;
4321 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4322 byte_count = params + 1 /* pad */ ;
4323 pSMB->TotalParameterCount = cpu_to_le16(params);
4324 pSMB->ParameterCount = pSMB->TotalParameterCount;
4325 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4326 pSMB->Reserved4 = 0;
be8e3b00 4327 inc_rfc1001_len(pSMB, byte_count);
1da177e4
LT
4328 pSMB->ByteCount = cpu_to_le16(byte_count);
4329
4330 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4331 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4332 if (rc) {
f96637be 4333 cifs_dbg(FYI, "error %d in QueryInternalInfo\n", rc);
1da177e4
LT
4334 } else {
4335 /* decode response */
4336 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1da177e4 4337 /* BB also check enough total bytes returned */
820a803f 4338 if (rc || get_bcc(&pSMBr->hdr) < 2)
1da177e4
LT
4339 /* If rc should we check for EOPNOSUPP and
4340 disable the srvino flag? or in caller? */
4341 rc = -EIO; /* bad smb */
50c2f753 4342 else {
1da177e4
LT
4343 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4344 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
50c2f753 4345 struct file_internal_info *pfinfo;
1da177e4 4346 /* BB Do we need a cast or hash here ? */
790fe579 4347 if (count < 8) {
a0a3036b 4348 cifs_dbg(FYI, "Invalid size ret in QryIntrnlInf\n");
1da177e4
LT
4349 rc = -EIO;
4350 goto GetInodeNumOut;
4351 }
4352 pfinfo = (struct file_internal_info *)
4353 (data_offset + (char *) &pSMBr->hdr.Protocol);
85a6dac5 4354 *inode_number = le64_to_cpu(pfinfo->UniqueId);
1da177e4
LT
4355 }
4356 }
4357GetInodeNumOut:
4358 cifs_buf_release(pSMB);
4359 if (rc == -EAGAIN)
4360 goto GetInodeNumberRetry;
4361 return rc;
4362}
1da177e4
LT
4363
4364int
6d5786a3 4365CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
b669f33c 4366 const char *search_name, struct dfs_info3_param **target_nodes,
c2cf07d5 4367 unsigned int *num_of_nodes,
737b758c 4368 const struct nls_table *nls_codepage, int remap)
1da177e4
LT
4369{
4370/* TRANS2_GET_DFS_REFERRAL */
4371 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4372 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
1da177e4
LT
4373 int rc = 0;
4374 int bytes_returned;
4375 int name_len;
1da177e4 4376 __u16 params, byte_count;
c2cf07d5
SF
4377 *num_of_nodes = 0;
4378 *target_nodes = NULL;
1da177e4 4379
f96637be 4380 cifs_dbg(FYI, "In GetDFSRefer the path %s\n", search_name);
b327a717 4381 if (ses == NULL || ses->tcon_ipc == NULL)
1da177e4 4382 return -ENODEV;
b327a717 4383
1da177e4 4384getDFSRetry:
09ba47b4
PA
4385 /*
4386 * Use smb_init_no_reconnect() instead of smb_init() as
4387 * CIFSGetDFSRefer() may be called from cifs_reconnect_tcon() and thus
4388 * causing an infinite recursion.
4389 */
4390 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, ses->tcon_ipc,
4391 (void **)&pSMB, (void **)&pSMBr);
1da177e4
LT
4392 if (rc)
4393 return rc;
50c2f753
SF
4394
4395 /* server pointer checked in called function,
1982c344 4396 but should never be null here anyway */
88257360 4397 pSMB->hdr.Mid = get_next_mid(ses->server);
b327a717 4398 pSMB->hdr.Tid = ses->tcon_ipc->tid;
1da177e4 4399 pSMB->hdr.Uid = ses->Suid;
26f57364 4400 if (ses->capabilities & CAP_STATUS32)
1da177e4 4401 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
26f57364 4402 if (ses->capabilities & CAP_DFS)
1da177e4 4403 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
1da177e4
LT
4404
4405 if (ses->capabilities & CAP_UNICODE) {
4406 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4407 name_len =
acbbb76a 4408 cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
b669f33c 4409 search_name, PATH_MAX, nls_codepage,
acbbb76a 4410 remap);
1da177e4
LT
4411 name_len++; /* trailing null */
4412 name_len *= 2;
50c2f753 4413 } else { /* BB improve the check for buffer overruns BB */
340625e6 4414 name_len = copy_path_name(pSMB->RequestFileName, search_name);
1da177e4
LT
4415 }
4416
65c3b205 4417 if (ses->server->sign)
38d77c50 4418 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1a4e15a0 4419
50c2f753 4420 pSMB->hdr.Uid = ses->Suid;
1a4e15a0 4421
1da177e4
LT
4422 params = 2 /* level */ + name_len /*includes null */ ;
4423 pSMB->TotalDataCount = 0;
4424 pSMB->DataCount = 0;
4425 pSMB->DataOffset = 0;
4426 pSMB->MaxParameterCount = 0;
582d21e5
SF
4427 /* BB find exact max SMB PDU from sess structure BB */
4428 pSMB->MaxDataCount = cpu_to_le16(4000);
1da177e4
LT
4429 pSMB->MaxSetupCount = 0;
4430 pSMB->Reserved = 0;
4431 pSMB->Flags = 0;
4432 pSMB->Timeout = 0;
4433 pSMB->Reserved2 = 0;
4434 pSMB->ParameterOffset = cpu_to_le16(offsetof(
50c2f753 4435 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
1da177e4
LT
4436 pSMB->SetupCount = 1;
4437 pSMB->Reserved3 = 0;
4438 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4439 byte_count = params + 3 /* pad */ ;
4440 pSMB->ParameterCount = cpu_to_le16(params);
4441 pSMB->TotalParameterCount = pSMB->ParameterCount;
4442 pSMB->MaxReferralLevel = cpu_to_le16(3);
be8e3b00 4443 inc_rfc1001_len(pSMB, byte_count);
1da177e4
LT
4444 pSMB->ByteCount = cpu_to_le16(byte_count);
4445
4446 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4447 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4448 if (rc) {
f96637be 4449 cifs_dbg(FYI, "Send error in GetDFSRefer = %d\n", rc);
c2cf07d5
SF
4450 goto GetDFSRefExit;
4451 }
4452 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1da177e4 4453
c2cf07d5 4454 /* BB Also check if enough total bytes returned? */
820a803f 4455 if (rc || get_bcc(&pSMBr->hdr) < 17) {
c2cf07d5 4456 rc = -EIO; /* bad smb */
fec4585f
IM
4457 goto GetDFSRefExit;
4458 }
c2cf07d5 4459
f96637be
JP
4460 cifs_dbg(FYI, "Decoding GetDFSRefer response BCC: %d Offset %d\n",
4461 get_bcc(&pSMBr->hdr), le16_to_cpu(pSMBr->t2.DataOffset));
1da177e4 4462
fec4585f 4463 /* parse returned result into more usable form */
4ecce920
AA
4464 rc = parse_dfs_referrals(&pSMBr->dfs_data,
4465 le16_to_cpu(pSMBr->t2.DataCount),
4466 num_of_nodes, target_nodes, nls_codepage,
4467 remap, search_name,
284316dd 4468 (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) != 0);
c2cf07d5 4469
1da177e4 4470GetDFSRefExit:
0d817bc0 4471 cifs_buf_release(pSMB);
1da177e4
LT
4472
4473 if (rc == -EAGAIN)
4474 goto getDFSRetry;
4475
4476 return rc;
4477}
4478
20962438
SF
4479/* Query File System Info such as free space to old servers such as Win 9x */
4480int
6d5786a3
PS
4481SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4482 struct kstatfs *FSData)
20962438
SF
4483{
4484/* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4485 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4486 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4487 FILE_SYSTEM_ALLOC_INFO *response_data;
4488 int rc = 0;
4489 int bytes_returned = 0;
4490 __u16 params, byte_count;
4491
f96637be 4492 cifs_dbg(FYI, "OldQFSInfo\n");
20962438
SF
4493oldQFSInfoRetry:
4494 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4495 (void **) &pSMBr);
4496 if (rc)
4497 return rc;
20962438
SF
4498
4499 params = 2; /* level */
4500 pSMB->TotalDataCount = 0;
4501 pSMB->MaxParameterCount = cpu_to_le16(2);
4502 pSMB->MaxDataCount = cpu_to_le16(1000);
4503 pSMB->MaxSetupCount = 0;
4504 pSMB->Reserved = 0;
4505 pSMB->Flags = 0;
4506 pSMB->Timeout = 0;
4507 pSMB->Reserved2 = 0;
4508 byte_count = params + 1 /* pad */ ;
4509 pSMB->TotalParameterCount = cpu_to_le16(params);
4510 pSMB->ParameterCount = pSMB->TotalParameterCount;
4511 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4512 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4513 pSMB->DataCount = 0;
4514 pSMB->DataOffset = 0;
4515 pSMB->SetupCount = 1;
4516 pSMB->Reserved3 = 0;
4517 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4518 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
be8e3b00 4519 inc_rfc1001_len(pSMB, byte_count);
20962438
SF
4520 pSMB->ByteCount = cpu_to_le16(byte_count);
4521
4522 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4523 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4524 if (rc) {
f96637be 4525 cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
20962438
SF
4526 } else { /* decode response */
4527 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4528
820a803f 4529 if (rc || get_bcc(&pSMBr->hdr) < 18)
20962438
SF
4530 rc = -EIO; /* bad smb */
4531 else {
4532 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
f96637be 4533 cifs_dbg(FYI, "qfsinf resp BCC: %d Offset %d\n",
820a803f 4534 get_bcc(&pSMBr->hdr), data_offset);
20962438 4535
50c2f753 4536 response_data = (FILE_SYSTEM_ALLOC_INFO *)
20962438
SF
4537 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4538 FSData->f_bsize =
4539 le16_to_cpu(response_data->BytesPerSector) *
4540 le32_to_cpu(response_data->
4541 SectorsPerAllocationUnit);
5a519bea
SF
4542 /*
4543 * much prefer larger but if server doesn't report
4544 * a valid size than 4K is a reasonable minimum
4545 */
4546 if (FSData->f_bsize < 512)
4547 FSData->f_bsize = 4096;
4548
20962438 4549 FSData->f_blocks =
50c2f753 4550 le32_to_cpu(response_data->TotalAllocationUnits);
20962438
SF
4551 FSData->f_bfree = FSData->f_bavail =
4552 le32_to_cpu(response_data->FreeAllocationUnits);
f96637be
JP
4553 cifs_dbg(FYI, "Blocks: %lld Free: %lld Block size %ld\n",
4554 (unsigned long long)FSData->f_blocks,
4555 (unsigned long long)FSData->f_bfree,
4556 FSData->f_bsize);
20962438
SF
4557 }
4558 }
4559 cifs_buf_release(pSMB);
4560
4561 if (rc == -EAGAIN)
4562 goto oldQFSInfoRetry;
4563
4564 return rc;
4565}
4566
1da177e4 4567int
6d5786a3
PS
4568CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4569 struct kstatfs *FSData)
1da177e4
LT
4570{
4571/* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4572 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4573 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4574 FILE_SYSTEM_INFO *response_data;
4575 int rc = 0;
4576 int bytes_returned = 0;
4577 __u16 params, byte_count;
4578
f96637be 4579 cifs_dbg(FYI, "In QFSInfo\n");
1da177e4
LT
4580QFSInfoRetry:
4581 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4582 (void **) &pSMBr);
4583 if (rc)
4584 return rc;
4585
4586 params = 2; /* level */
4587 pSMB->TotalDataCount = 0;
4588 pSMB->MaxParameterCount = cpu_to_le16(2);
20962438 4589 pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4
LT
4590 pSMB->MaxSetupCount = 0;
4591 pSMB->Reserved = 0;
4592 pSMB->Flags = 0;
4593 pSMB->Timeout = 0;
4594 pSMB->Reserved2 = 0;
4595 byte_count = params + 1 /* pad */ ;
4596 pSMB->TotalParameterCount = cpu_to_le16(params);
4597 pSMB->ParameterCount = pSMB->TotalParameterCount;
4598 pSMB->ParameterOffset = cpu_to_le16(offsetof(
50c2f753 4599 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
1da177e4
LT
4600 pSMB->DataCount = 0;
4601 pSMB->DataOffset = 0;
4602 pSMB->SetupCount = 1;
4603 pSMB->Reserved3 = 0;
4604 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4605 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
be8e3b00 4606 inc_rfc1001_len(pSMB, byte_count);
1da177e4
LT
4607 pSMB->ByteCount = cpu_to_le16(byte_count);
4608
4609 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4610 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4611 if (rc) {
f96637be 4612 cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
1da177e4 4613 } else { /* decode response */
50c2f753 4614 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1da177e4 4615
820a803f 4616 if (rc || get_bcc(&pSMBr->hdr) < 24)
1da177e4
LT
4617 rc = -EIO; /* bad smb */
4618 else {
4619 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1da177e4
LT
4620
4621 response_data =
4622 (FILE_SYSTEM_INFO
4623 *) (((char *) &pSMBr->hdr.Protocol) +
4624 data_offset);
4625 FSData->f_bsize =
4626 le32_to_cpu(response_data->BytesPerSector) *
4627 le32_to_cpu(response_data->
4628 SectorsPerAllocationUnit);
5a519bea
SF
4629 /*
4630 * much prefer larger but if server doesn't report
4631 * a valid size than 4K is a reasonable minimum
4632 */
4633 if (FSData->f_bsize < 512)
4634 FSData->f_bsize = 4096;
4635
1da177e4
LT
4636 FSData->f_blocks =
4637 le64_to_cpu(response_data->TotalAllocationUnits);
4638 FSData->f_bfree = FSData->f_bavail =
4639 le64_to_cpu(response_data->FreeAllocationUnits);
f96637be
JP
4640 cifs_dbg(FYI, "Blocks: %lld Free: %lld Block size %ld\n",
4641 (unsigned long long)FSData->f_blocks,
4642 (unsigned long long)FSData->f_bfree,
4643 FSData->f_bsize);
1da177e4
LT
4644 }
4645 }
4646 cifs_buf_release(pSMB);
4647
4648 if (rc == -EAGAIN)
4649 goto QFSInfoRetry;
4650
4651 return rc;
4652}
4653
4654int
6d5786a3 4655CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)
1da177e4
LT
4656{
4657/* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4658 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4659 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4660 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4661 int rc = 0;
4662 int bytes_returned = 0;
4663 __u16 params, byte_count;
4664
f96637be 4665 cifs_dbg(FYI, "In QFSAttributeInfo\n");
1da177e4
LT
4666QFSAttributeRetry:
4667 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4668 (void **) &pSMBr);
4669 if (rc)
4670 return rc;
4671
4672 params = 2; /* level */
4673 pSMB->TotalDataCount = 0;
4674 pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5
SF
4675 /* BB find exact max SMB PDU from sess structure BB */
4676 pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4
LT
4677 pSMB->MaxSetupCount = 0;
4678 pSMB->Reserved = 0;
4679 pSMB->Flags = 0;
4680 pSMB->Timeout = 0;
4681 pSMB->Reserved2 = 0;
4682 byte_count = params + 1 /* pad */ ;
4683 pSMB->TotalParameterCount = cpu_to_le16(params);
4684 pSMB->ParameterCount = pSMB->TotalParameterCount;
4685 pSMB->ParameterOffset = cpu_to_le16(offsetof(
50c2f753 4686 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
1da177e4
LT
4687 pSMB->DataCount = 0;
4688 pSMB->DataOffset = 0;
4689 pSMB->SetupCount = 1;
4690 pSMB->Reserved3 = 0;
4691 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4692 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
be8e3b00 4693 inc_rfc1001_len(pSMB, byte_count);
1da177e4
LT
4694 pSMB->ByteCount = cpu_to_le16(byte_count);
4695
4696 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4697 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4698 if (rc) {
f96637be 4699 cifs_dbg(VFS, "Send error in QFSAttributeInfo = %d\n", rc);
1da177e4
LT
4700 } else { /* decode response */
4701 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4702
820a803f 4703 if (rc || get_bcc(&pSMBr->hdr) < 13) {
50c2f753 4704 /* BB also check if enough bytes returned */
1da177e4
LT
4705 rc = -EIO; /* bad smb */
4706 } else {
4707 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4708 response_data =
4709 (FILE_SYSTEM_ATTRIBUTE_INFO
4710 *) (((char *) &pSMBr->hdr.Protocol) +
4711 data_offset);
4712 memcpy(&tcon->fsAttrInfo, response_data,
26f57364 4713 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
1da177e4
LT
4714 }
4715 }
4716 cifs_buf_release(pSMB);
4717
4718 if (rc == -EAGAIN)
4719 goto QFSAttributeRetry;
4720
4721 return rc;
4722}
4723
4724int
6d5786a3 4725CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)
1da177e4
LT
4726{
4727/* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4728 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4729 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4730 FILE_SYSTEM_DEVICE_INFO *response_data;
4731 int rc = 0;
4732 int bytes_returned = 0;
4733 __u16 params, byte_count;
4734
f96637be 4735 cifs_dbg(FYI, "In QFSDeviceInfo\n");
1da177e4
LT
4736QFSDeviceRetry:
4737 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4738 (void **) &pSMBr);
4739 if (rc)
4740 return rc;
4741
4742 params = 2; /* level */
4743 pSMB->TotalDataCount = 0;
4744 pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5
SF
4745 /* BB find exact max SMB PDU from sess structure BB */
4746 pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4
LT
4747 pSMB->MaxSetupCount = 0;
4748 pSMB->Reserved = 0;
4749 pSMB->Flags = 0;
4750 pSMB->Timeout = 0;
4751 pSMB->Reserved2 = 0;
4752 byte_count = params + 1 /* pad */ ;
4753 pSMB->TotalParameterCount = cpu_to_le16(params);
4754 pSMB->ParameterCount = pSMB->TotalParameterCount;
4755 pSMB->ParameterOffset = cpu_to_le16(offsetof(
50c2f753 4756 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
1da177e4
LT
4757
4758 pSMB->DataCount = 0;
4759 pSMB->DataOffset = 0;
4760 pSMB->SetupCount = 1;
4761 pSMB->Reserved3 = 0;
4762 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4763 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
be8e3b00 4764 inc_rfc1001_len(pSMB, byte_count);
1da177e4
LT
4765 pSMB->ByteCount = cpu_to_le16(byte_count);
4766
4767 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4768 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4769 if (rc) {
f96637be 4770 cifs_dbg(FYI, "Send error in QFSDeviceInfo = %d\n", rc);
1da177e4
LT
4771 } else { /* decode response */
4772 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4773
820a803f
JL
4774 if (rc || get_bcc(&pSMBr->hdr) <
4775 sizeof(FILE_SYSTEM_DEVICE_INFO))
1da177e4
LT
4776 rc = -EIO; /* bad smb */
4777 else {
4778 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4779 response_data =
737b758c
SF
4780 (FILE_SYSTEM_DEVICE_INFO *)
4781 (((char *) &pSMBr->hdr.Protocol) +
1da177e4
LT
4782 data_offset);
4783 memcpy(&tcon->fsDevInfo, response_data,
26f57364 4784 sizeof(FILE_SYSTEM_DEVICE_INFO));
1da177e4
LT
4785 }
4786 }
4787 cifs_buf_release(pSMB);
4788
4789 if (rc == -EAGAIN)
4790 goto QFSDeviceRetry;
4791
4792 return rc;
4793}
4794
4795int
6d5786a3 4796CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)
1da177e4
LT
4797{
4798/* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4799 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4800 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4801 FILE_SYSTEM_UNIX_INFO *response_data;
4802 int rc = 0;
4803 int bytes_returned = 0;
4804 __u16 params, byte_count;
4805
f96637be 4806 cifs_dbg(FYI, "In QFSUnixInfo\n");
1da177e4 4807QFSUnixRetry:
f569599a
JL
4808 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
4809 (void **) &pSMB, (void **) &pSMBr);
1da177e4
LT
4810 if (rc)
4811 return rc;
4812
4813 params = 2; /* level */
4814 pSMB->TotalDataCount = 0;
4815 pSMB->DataCount = 0;
4816 pSMB->DataOffset = 0;
4817 pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5
SF
4818 /* BB find exact max SMB PDU from sess structure BB */
4819 pSMB->MaxDataCount = cpu_to_le16(100);
1da177e4
LT
4820 pSMB->MaxSetupCount = 0;
4821 pSMB->Reserved = 0;
4822 pSMB->Flags = 0;
4823 pSMB->Timeout = 0;
4824 pSMB->Reserved2 = 0;
4825 byte_count = params + 1 /* pad */ ;
4826 pSMB->ParameterCount = cpu_to_le16(params);
4827 pSMB->TotalParameterCount = pSMB->ParameterCount;
50c2f753
SF
4828 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4829 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
1da177e4
LT
4830 pSMB->SetupCount = 1;
4831 pSMB->Reserved3 = 0;
4832 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4833 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
be8e3b00 4834 inc_rfc1001_len(pSMB, byte_count);
1da177e4
LT
4835 pSMB->ByteCount = cpu_to_le16(byte_count);
4836
4837 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4838 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4839 if (rc) {
f96637be 4840 cifs_dbg(VFS, "Send error in QFSUnixInfo = %d\n", rc);
1da177e4
LT
4841 } else { /* decode response */
4842 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4843
820a803f 4844 if (rc || get_bcc(&pSMBr->hdr) < 13) {
1da177e4
LT
4845 rc = -EIO; /* bad smb */
4846 } else {
4847 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4848 response_data =
4849 (FILE_SYSTEM_UNIX_INFO
4850 *) (((char *) &pSMBr->hdr.Protocol) +
4851 data_offset);
4852 memcpy(&tcon->fsUnixInfo, response_data,
26f57364 4853 sizeof(FILE_SYSTEM_UNIX_INFO));
1da177e4
LT
4854 }
4855 }
4856 cifs_buf_release(pSMB);
4857
4858 if (rc == -EAGAIN)
4859 goto QFSUnixRetry;
4860
4861
4862 return rc;
4863}
4864
ac67055e 4865int
6d5786a3 4866CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)
ac67055e
JA
4867{
4868/* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4869 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4870 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4871 int rc = 0;
4872 int bytes_returned = 0;
4873 __u16 params, param_offset, offset, byte_count;
4874
f96637be 4875 cifs_dbg(FYI, "In SETFSUnixInfo\n");
ac67055e 4876SETFSUnixRetry:
f26282c9 4877 /* BB switch to small buf init to save memory */
f569599a
JL
4878 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
4879 (void **) &pSMB, (void **) &pSMBr);
ac67055e
JA
4880 if (rc)
4881 return rc;
4882
4883 params = 4; /* 2 bytes zero followed by info level. */
4884 pSMB->MaxSetupCount = 0;
4885 pSMB->Reserved = 0;
4886 pSMB->Flags = 0;
4887 pSMB->Timeout = 0;
4888 pSMB->Reserved2 = 0;
50c2f753
SF
4889 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4890 - 4;
ac67055e
JA
4891 offset = param_offset + params;
4892
4893 pSMB->MaxParameterCount = cpu_to_le16(4);
582d21e5
SF
4894 /* BB find exact max SMB PDU from sess structure BB */
4895 pSMB->MaxDataCount = cpu_to_le16(100);
ac67055e
JA
4896 pSMB->SetupCount = 1;
4897 pSMB->Reserved3 = 0;
4898 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4899 byte_count = 1 /* pad */ + params + 12;
4900
4901 pSMB->DataCount = cpu_to_le16(12);
4902 pSMB->ParameterCount = cpu_to_le16(params);
4903 pSMB->TotalDataCount = pSMB->DataCount;
4904 pSMB->TotalParameterCount = pSMB->ParameterCount;
4905 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4906 pSMB->DataOffset = cpu_to_le16(offset);
4907
4908 /* Params. */
4909 pSMB->FileNum = 0;
4910 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4911
4912 /* Data. */
4913 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4914 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4915 pSMB->ClientUnixCap = cpu_to_le64(cap);
4916
be8e3b00 4917 inc_rfc1001_len(pSMB, byte_count);
ac67055e
JA
4918 pSMB->ByteCount = cpu_to_le16(byte_count);
4919
4920 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4921 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4922 if (rc) {
f96637be 4923 cifs_dbg(VFS, "Send error in SETFSUnixInfo = %d\n", rc);
ac67055e
JA
4924 } else { /* decode response */
4925 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
ad7a2926 4926 if (rc)
ac67055e 4927 rc = -EIO; /* bad smb */
ac67055e
JA
4928 }
4929 cifs_buf_release(pSMB);
4930
4931 if (rc == -EAGAIN)
4932 goto SETFSUnixRetry;
4933
4934 return rc;
4935}
4936
4937
1da177e4
LT
4938
4939int
6d5786a3 4940CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
737b758c 4941 struct kstatfs *FSData)
1da177e4
LT
4942{
4943/* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4944 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4945 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4946 FILE_SYSTEM_POSIX_INFO *response_data;
4947 int rc = 0;
4948 int bytes_returned = 0;
4949 __u16 params, byte_count;
4950
f96637be 4951 cifs_dbg(FYI, "In QFSPosixInfo\n");
1da177e4
LT
4952QFSPosixRetry:
4953 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4954 (void **) &pSMBr);
4955 if (rc)
4956 return rc;
4957
4958 params = 2; /* level */
4959 pSMB->TotalDataCount = 0;
4960 pSMB->DataCount = 0;
4961 pSMB->DataOffset = 0;
4962 pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5
SF
4963 /* BB find exact max SMB PDU from sess structure BB */
4964 pSMB->MaxDataCount = cpu_to_le16(100);
1da177e4
LT
4965 pSMB->MaxSetupCount = 0;
4966 pSMB->Reserved = 0;
4967 pSMB->Flags = 0;
4968 pSMB->Timeout = 0;
4969 pSMB->Reserved2 = 0;
4970 byte_count = params + 1 /* pad */ ;
4971 pSMB->ParameterCount = cpu_to_le16(params);
4972 pSMB->TotalParameterCount = pSMB->ParameterCount;
50c2f753
SF
4973 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4974 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
1da177e4
LT
4975 pSMB->SetupCount = 1;
4976 pSMB->Reserved3 = 0;
4977 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4978 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
be8e3b00 4979 inc_rfc1001_len(pSMB, byte_count);
1da177e4
LT
4980 pSMB->ByteCount = cpu_to_le16(byte_count);
4981
4982 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4983 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4984 if (rc) {
f96637be 4985 cifs_dbg(FYI, "Send error in QFSUnixInfo = %d\n", rc);
1da177e4
LT
4986 } else { /* decode response */
4987 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4988
820a803f 4989 if (rc || get_bcc(&pSMBr->hdr) < 13) {
1da177e4
LT
4990 rc = -EIO; /* bad smb */
4991 } else {
4992 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4993 response_data =
4994 (FILE_SYSTEM_POSIX_INFO
4995 *) (((char *) &pSMBr->hdr.Protocol) +
4996 data_offset);
4997 FSData->f_bsize =
4998 le32_to_cpu(response_data->BlockSize);
5a519bea
SF
4999 /*
5000 * much prefer larger but if server doesn't report
5001 * a valid size than 4K is a reasonable minimum
5002 */
5003 if (FSData->f_bsize < 512)
5004 FSData->f_bsize = 4096;
5005
1da177e4
LT
5006 FSData->f_blocks =
5007 le64_to_cpu(response_data->TotalBlocks);
5008 FSData->f_bfree =
5009 le64_to_cpu(response_data->BlocksAvail);
790fe579 5010 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
1da177e4
LT
5011 FSData->f_bavail = FSData->f_bfree;
5012 } else {
5013 FSData->f_bavail =
50c2f753 5014 le64_to_cpu(response_data->UserBlocksAvail);
1da177e4 5015 }
790fe579 5016 if (response_data->TotalFileNodes != cpu_to_le64(-1))
1da177e4 5017 FSData->f_files =
50c2f753 5018 le64_to_cpu(response_data->TotalFileNodes);
790fe579 5019 if (response_data->FreeFileNodes != cpu_to_le64(-1))
1da177e4 5020 FSData->f_ffree =
50c2f753 5021 le64_to_cpu(response_data->FreeFileNodes);
1da177e4
LT
5022 }
5023 }
5024 cifs_buf_release(pSMB);
5025
5026 if (rc == -EAGAIN)
5027 goto QFSPosixRetry;
5028
5029 return rc;
5030}
5031
5032
d1433418
PS
5033/*
5034 * We can not use write of zero bytes trick to set file size due to need for
5035 * large file support. Also note that this SetPathInfo is preferred to
5036 * SetFileInfo based method in next routine which is only needed to work around
5037 * a sharing violation bugin Samba which this routine can run into.
5038 */
1da177e4 5039int
6d5786a3 5040CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
d1433418
PS
5041 const char *file_name, __u64 size, struct cifs_sb_info *cifs_sb,
5042 bool set_allocation)
1da177e4
LT
5043{
5044 struct smb_com_transaction2_spi_req *pSMB = NULL;
5045 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5046 struct file_end_of_file_info *parm_data;
5047 int name_len;
5048 int rc = 0;
5049 int bytes_returned = 0;
2baa2682 5050 int remap = cifs_remap(cifs_sb);
d1433418 5051
1da177e4
LT
5052 __u16 params, byte_count, data_count, param_offset, offset;
5053
f96637be 5054 cifs_dbg(FYI, "In SetEOF\n");
1da177e4
LT
5055SetEOFRetry:
5056 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5057 (void **) &pSMBr);
5058 if (rc)
5059 return rc;
5060
5061 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5062 name_len =
d1433418
PS
5063 cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
5064 PATH_MAX, cifs_sb->local_nls, remap);
1da177e4
LT
5065 name_len++; /* trailing null */
5066 name_len *= 2;
340625e6
RS
5067 } else {
5068 name_len = copy_path_name(pSMB->FileName, file_name);
1da177e4
LT
5069 }
5070 params = 6 + name_len;
26f57364 5071 data_count = sizeof(struct file_end_of_file_info);
1da177e4 5072 pSMB->MaxParameterCount = cpu_to_le16(2);
3e87d803 5073 pSMB->MaxDataCount = cpu_to_le16(4100);
1da177e4
LT
5074 pSMB->MaxSetupCount = 0;
5075 pSMB->Reserved = 0;
5076 pSMB->Flags = 0;
5077 pSMB->Timeout = 0;
5078 pSMB->Reserved2 = 0;
5079 param_offset = offsetof(struct smb_com_transaction2_spi_req,
50c2f753 5080 InformationLevel) - 4;
1da177e4 5081 offset = param_offset + params;
d1433418 5082 if (set_allocation) {
50c2f753
SF
5083 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5084 pSMB->InformationLevel =
5085 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5086 else
5087 pSMB->InformationLevel =
5088 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5089 } else /* Set File Size */ {
1da177e4
LT
5090 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5091 pSMB->InformationLevel =
50c2f753 5092 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
1da177e4
LT
5093 else
5094 pSMB->InformationLevel =
50c2f753 5095 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
1da177e4
LT
5096 }
5097
5098 parm_data =
5099 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5100 offset);
5101 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5102 pSMB->DataOffset = cpu_to_le16(offset);
5103 pSMB->SetupCount = 1;
5104 pSMB->Reserved3 = 0;
5105 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5106 byte_count = 3 /* pad */ + params + data_count;
5107 pSMB->DataCount = cpu_to_le16(data_count);
5108 pSMB->TotalDataCount = pSMB->DataCount;
5109 pSMB->ParameterCount = cpu_to_le16(params);
5110 pSMB->TotalParameterCount = pSMB->ParameterCount;
5111 pSMB->Reserved4 = 0;
be8e3b00 5112 inc_rfc1001_len(pSMB, byte_count);
1da177e4
LT
5113 parm_data->FileSize = cpu_to_le64(size);
5114 pSMB->ByteCount = cpu_to_le16(byte_count);
5115 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5116 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
ad7a2926 5117 if (rc)
f96637be 5118 cifs_dbg(FYI, "SetPathInfo (file size) returned %d\n", rc);
1da177e4
LT
5119
5120 cifs_buf_release(pSMB);
5121
5122 if (rc == -EAGAIN)
5123 goto SetEOFRetry;
5124
5125 return rc;
5126}
5127
5128int
d1433418
PS
5129CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
5130 struct cifsFileInfo *cfile, __u64 size, bool set_allocation)
1da177e4
LT
5131{
5132 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1da177e4
LT
5133 struct file_end_of_file_info *parm_data;
5134 int rc = 0;
1da177e4
LT
5135 __u16 params, param_offset, offset, byte_count, count;
5136
f96637be
JP
5137 cifs_dbg(FYI, "SetFileSize (via SetFileInfo) %lld\n",
5138 (long long)size);
cd63499c
SF
5139 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5140
1da177e4
LT
5141 if (rc)
5142 return rc;
5143
d1433418
PS
5144 pSMB->hdr.Pid = cpu_to_le16((__u16)cfile->pid);
5145 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(cfile->pid >> 16));
50c2f753 5146
1da177e4
LT
5147 params = 6;
5148 pSMB->MaxSetupCount = 0;
5149 pSMB->Reserved = 0;
5150 pSMB->Flags = 0;
5151 pSMB->Timeout = 0;
5152 pSMB->Reserved2 = 0;
5153 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5154 offset = param_offset + params;
5155
1da177e4
LT
5156 count = sizeof(struct file_end_of_file_info);
5157 pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5
SF
5158 /* BB find exact max SMB PDU from sess structure BB */
5159 pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4
LT
5160 pSMB->SetupCount = 1;
5161 pSMB->Reserved3 = 0;
5162 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5163 byte_count = 3 /* pad */ + params + count;
5164 pSMB->DataCount = cpu_to_le16(count);
5165 pSMB->ParameterCount = cpu_to_le16(params);
5166 pSMB->TotalDataCount = pSMB->DataCount;
5167 pSMB->TotalParameterCount = pSMB->ParameterCount;
5168 pSMB->ParameterOffset = cpu_to_le16(param_offset);
e3973ea3 5169 /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
1da177e4 5170 parm_data =
e3973ea3 5171 (struct file_end_of_file_info *)(((char *)pSMB) + offset + 4);
1da177e4
LT
5172 pSMB->DataOffset = cpu_to_le16(offset);
5173 parm_data->FileSize = cpu_to_le64(size);
d1433418
PS
5174 pSMB->Fid = cfile->fid.netfid;
5175 if (set_allocation) {
1da177e4
LT
5176 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5177 pSMB->InformationLevel =
5178 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5179 else
5180 pSMB->InformationLevel =
5181 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
50c2f753 5182 } else /* Set File Size */ {
1da177e4
LT
5183 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5184 pSMB->InformationLevel =
50c2f753 5185 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
1da177e4
LT
5186 else
5187 pSMB->InformationLevel =
50c2f753 5188 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
1da177e4
LT
5189 }
5190 pSMB->Reserved4 = 0;
be8e3b00 5191 inc_rfc1001_len(pSMB, byte_count);
1da177e4 5192 pSMB->ByteCount = cpu_to_le16(byte_count);
792af7b0 5193 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
da502f7d 5194 cifs_small_buf_release(pSMB);
1da177e4 5195 if (rc) {
f96637be
JP
5196 cifs_dbg(FYI, "Send error in SetFileInfo (SetFileSize) = %d\n",
5197 rc);
1da177e4
LT
5198 }
5199
50c2f753 5200 /* Note: On -EAGAIN error only caller can retry on handle based calls
1da177e4
LT
5201 since file handle passed in no longer valid */
5202
5203 return rc;
5204}
5205
50c2f753 5206/* Some legacy servers such as NT4 require that the file times be set on
1da177e4
LT
5207 an open handle, rather than by pathname - this is awkward due to
5208 potential access conflicts on the open, but it is unavoidable for these
5209 old servers since the only other choice is to go from 100 nanosecond DCE
5210 time and resort to the original setpathinfo level which takes the ancient
5211 DOS time format with 2 second granularity */
5212int
6d5786a3 5213CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
2dd2dfa0 5214 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
1da177e4
LT
5215{
5216 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1da177e4
LT
5217 char *data_offset;
5218 int rc = 0;
1da177e4
LT
5219 __u16 params, param_offset, offset, byte_count, count;
5220
f96637be 5221 cifs_dbg(FYI, "Set Times (via SetFileInfo)\n");
cd63499c
SF
5222 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5223
1da177e4
LT
5224 if (rc)
5225 return rc;
5226
2dd2dfa0
JL
5227 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5228 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
50c2f753 5229
1da177e4
LT
5230 params = 6;
5231 pSMB->MaxSetupCount = 0;
5232 pSMB->Reserved = 0;
5233 pSMB->Flags = 0;
5234 pSMB->Timeout = 0;
5235 pSMB->Reserved2 = 0;
5236 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5237 offset = param_offset + params;
5238
b2a3ad9c
JL
5239 data_offset = (char *)pSMB +
5240 offsetof(struct smb_hdr, Protocol) + offset;
1da177e4 5241
26f57364 5242 count = sizeof(FILE_BASIC_INFO);
1da177e4 5243 pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5
SF
5244 /* BB find max SMB PDU from sess */
5245 pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4
LT
5246 pSMB->SetupCount = 1;
5247 pSMB->Reserved3 = 0;
5248 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5249 byte_count = 3 /* pad */ + params + count;
5250 pSMB->DataCount = cpu_to_le16(count);
5251 pSMB->ParameterCount = cpu_to_le16(params);
5252 pSMB->TotalDataCount = pSMB->DataCount;
5253 pSMB->TotalParameterCount = pSMB->ParameterCount;
5254 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5255 pSMB->DataOffset = cpu_to_le16(offset);
5256 pSMB->Fid = fid;
5257 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5258 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5259 else
5260 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5261 pSMB->Reserved4 = 0;
be8e3b00 5262 inc_rfc1001_len(pSMB, byte_count);
1da177e4 5263 pSMB->ByteCount = cpu_to_le16(byte_count);
50c2f753 5264 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
792af7b0 5265 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
da502f7d 5266 cifs_small_buf_release(pSMB);
ad7a2926 5267 if (rc)
f96637be
JP
5268 cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
5269 rc);
1da177e4 5270
50c2f753 5271 /* Note: On -EAGAIN error only caller can retry on handle based calls
1da177e4
LT
5272 since file handle passed in no longer valid */
5273
5274 return rc;
5275}
5276
6d22f098 5277int
6d5786a3 5278CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
6d22f098
JL
5279 bool delete_file, __u16 fid, __u32 pid_of_opener)
5280{
5281 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5282 char *data_offset;
5283 int rc = 0;
5284 __u16 params, param_offset, offset, byte_count, count;
5285
f96637be 5286 cifs_dbg(FYI, "Set File Disposition (via SetFileInfo)\n");
6d22f098
JL
5287 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5288
5289 if (rc)
5290 return rc;
5291
5292 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5293 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5294
5295 params = 6;
5296 pSMB->MaxSetupCount = 0;
5297 pSMB->Reserved = 0;
5298 pSMB->Flags = 0;
5299 pSMB->Timeout = 0;
5300 pSMB->Reserved2 = 0;
5301 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5302 offset = param_offset + params;
5303
2a780e8b
SF
5304 /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
5305 data_offset = (char *)(pSMB) + offset + 4;
6d22f098
JL
5306
5307 count = 1;
5308 pSMB->MaxParameterCount = cpu_to_le16(2);
5309 /* BB find max SMB PDU from sess */
5310 pSMB->MaxDataCount = cpu_to_le16(1000);
5311 pSMB->SetupCount = 1;
5312 pSMB->Reserved3 = 0;
5313 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5314 byte_count = 3 /* pad */ + params + count;
5315 pSMB->DataCount = cpu_to_le16(count);
5316 pSMB->ParameterCount = cpu_to_le16(params);
5317 pSMB->TotalDataCount = pSMB->DataCount;
5318 pSMB->TotalParameterCount = pSMB->ParameterCount;
5319 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5320 pSMB->DataOffset = cpu_to_le16(offset);
5321 pSMB->Fid = fid;
5322 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5323 pSMB->Reserved4 = 0;
be8e3b00 5324 inc_rfc1001_len(pSMB, byte_count);
6d22f098
JL
5325 pSMB->ByteCount = cpu_to_le16(byte_count);
5326 *data_offset = delete_file ? 1 : 0;
792af7b0 5327 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
da502f7d 5328 cifs_small_buf_release(pSMB);
6d22f098 5329 if (rc)
f96637be 5330 cifs_dbg(FYI, "Send error in SetFileDisposition = %d\n", rc);
6d22f098
JL
5331
5332 return rc;
5333}
1da177e4 5334
8e408fc9
RS
5335static int
5336CIFSSMBSetPathInfoFB(const unsigned int xid, struct cifs_tcon *tcon,
5337 const char *fileName, const FILE_BASIC_INFO *data,
5338 const struct nls_table *nls_codepage,
5339 struct cifs_sb_info *cifs_sb)
5340{
5341 int oplock = 0;
5342 struct cifs_open_parms oparms;
5343 struct cifs_fid fid;
5344 int rc;
5345
de036dca
VL
5346 oparms = (struct cifs_open_parms) {
5347 .tcon = tcon,
5348 .cifs_sb = cifs_sb,
5349 .desired_access = GENERIC_WRITE,
5350 .create_options = cifs_create_options(cifs_sb, 0),
5351 .disposition = FILE_OPEN,
5352 .path = fileName,
5353 .fid = &fid,
5354 };
8e408fc9
RS
5355
5356 rc = CIFS_open(xid, &oparms, &oplock, NULL);
5357 if (rc)
5358 goto out;
5359
5360 rc = CIFSSMBSetFileInfo(xid, tcon, data, fid.netfid, current->tgid);
5361 CIFSSMBClose(xid, tcon, fid.netfid);
5362out:
5363
5364 return rc;
5365}
5366
1da177e4 5367int
6d5786a3 5368CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
6fc000e5 5369 const char *fileName, const FILE_BASIC_INFO *data,
8e408fc9
RS
5370 const struct nls_table *nls_codepage,
5371 struct cifs_sb_info *cifs_sb)
1da177e4
LT
5372{
5373 TRANSACTION2_SPI_REQ *pSMB = NULL;
5374 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5375 int name_len;
5376 int rc = 0;
5377 int bytes_returned = 0;
5378 char *data_offset;
5379 __u16 params, param_offset, offset, byte_count, count;
8e408fc9 5380 int remap = cifs_remap(cifs_sb);
1da177e4 5381
f96637be 5382 cifs_dbg(FYI, "In SetTimes\n");
1da177e4
LT
5383
5384SetTimesRetry:
5385 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5386 (void **) &pSMBr);
5387 if (rc)
5388 return rc;
5389
5390 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5391 name_len =
acbbb76a
SF
5392 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5393 PATH_MAX, nls_codepage, remap);
1da177e4
LT
5394 name_len++; /* trailing null */
5395 name_len *= 2;
340625e6
RS
5396 } else {
5397 name_len = copy_path_name(pSMB->FileName, fileName);
1da177e4
LT
5398 }
5399
5400 params = 6 + name_len;
26f57364 5401 count = sizeof(FILE_BASIC_INFO);
1da177e4 5402 pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5
SF
5403 /* BB find max SMB PDU from sess structure BB */
5404 pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4
LT
5405 pSMB->MaxSetupCount = 0;
5406 pSMB->Reserved = 0;
5407 pSMB->Flags = 0;
5408 pSMB->Timeout = 0;
5409 pSMB->Reserved2 = 0;
5410 param_offset = offsetof(struct smb_com_transaction2_spi_req,
50c2f753 5411 InformationLevel) - 4;
1da177e4
LT
5412 offset = param_offset + params;
5413 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5414 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5415 pSMB->DataOffset = cpu_to_le16(offset);
5416 pSMB->SetupCount = 1;
5417 pSMB->Reserved3 = 0;
5418 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5419 byte_count = 3 /* pad */ + params + count;
5420
5421 pSMB->DataCount = cpu_to_le16(count);
5422 pSMB->ParameterCount = cpu_to_le16(params);
5423 pSMB->TotalDataCount = pSMB->DataCount;
5424 pSMB->TotalParameterCount = pSMB->ParameterCount;
5425 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5426 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5427 else
5428 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5429 pSMB->Reserved4 = 0;
be8e3b00 5430 inc_rfc1001_len(pSMB, byte_count);
26f57364 5431 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
1da177e4
LT
5432 pSMB->ByteCount = cpu_to_le16(byte_count);
5433 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5434 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
ad7a2926 5435 if (rc)
f96637be 5436 cifs_dbg(FYI, "SetPathInfo (times) returned %d\n", rc);
1da177e4
LT
5437
5438 cifs_buf_release(pSMB);
5439
5440 if (rc == -EAGAIN)
5441 goto SetTimesRetry;
5442
8e408fc9
RS
5443 if (rc == -EOPNOTSUPP)
5444 return CIFSSMBSetPathInfoFB(xid, tcon, fileName, data,
5445 nls_codepage, cifs_sb);
5446
1da177e4
LT
5447 return rc;
5448}
5449
654cf14a
JL
5450static void
5451cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5452 const struct cifs_unix_set_info_args *args)
5453{
49418b2c 5454 u64 uid = NO_CHANGE_64, gid = NO_CHANGE_64;
654cf14a
JL
5455 u64 mode = args->mode;
5456
49418b2c
EB
5457 if (uid_valid(args->uid))
5458 uid = from_kuid(&init_user_ns, args->uid);
5459 if (gid_valid(args->gid))
5460 gid = from_kgid(&init_user_ns, args->gid);
5461
654cf14a
JL
5462 /*
5463 * Samba server ignores set of file size to zero due to bugs in some
5464 * older clients, but we should be precise - we use SetFileSize to
5465 * set file size and do not want to truncate file size to zero
25985edc 5466 * accidentally as happened on one Samba server beta by putting
654cf14a
JL
5467 * zero instead of -1 here
5468 */
5469 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5470 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5471 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5472 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5473 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
49418b2c
EB
5474 data_offset->Uid = cpu_to_le64(uid);
5475 data_offset->Gid = cpu_to_le64(gid);
654cf14a
JL
5476 /* better to leave device as zero when it is */
5477 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5478 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5479 data_offset->Permissions = cpu_to_le64(mode);
5480
5481 if (S_ISREG(mode))
5482 data_offset->Type = cpu_to_le32(UNIX_FILE);
5483 else if (S_ISDIR(mode))
5484 data_offset->Type = cpu_to_le32(UNIX_DIR);
5485 else if (S_ISLNK(mode))
5486 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5487 else if (S_ISCHR(mode))
5488 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5489 else if (S_ISBLK(mode))
5490 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5491 else if (S_ISFIFO(mode))
5492 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5493 else if (S_ISSOCK(mode))
5494 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5495}
5496
3bbeeb3c 5497int
6d5786a3 5498CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
3bbeeb3c
JL
5499 const struct cifs_unix_set_info_args *args,
5500 u16 fid, u32 pid_of_opener)
5501{
5502 struct smb_com_transaction2_sfi_req *pSMB = NULL;
b2a3ad9c 5503 char *data_offset;
3bbeeb3c
JL
5504 int rc = 0;
5505 u16 params, param_offset, offset, byte_count, count;
5506
f96637be 5507 cifs_dbg(FYI, "Set Unix Info (via SetFileInfo)\n");
3bbeeb3c
JL
5508 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5509
5510 if (rc)
5511 return rc;
5512
5513 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5514 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5515
5516 params = 6;
5517 pSMB->MaxSetupCount = 0;
5518 pSMB->Reserved = 0;
5519 pSMB->Flags = 0;
5520 pSMB->Timeout = 0;
5521 pSMB->Reserved2 = 0;
5522 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5523 offset = param_offset + params;
5524
b2a3ad9c
JL
5525 data_offset = (char *)pSMB +
5526 offsetof(struct smb_hdr, Protocol) + offset;
5527
3bbeeb3c
JL
5528 count = sizeof(FILE_UNIX_BASIC_INFO);
5529
5530 pSMB->MaxParameterCount = cpu_to_le16(2);
5531 /* BB find max SMB PDU from sess */
5532 pSMB->MaxDataCount = cpu_to_le16(1000);
5533 pSMB->SetupCount = 1;
5534 pSMB->Reserved3 = 0;
5535 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5536 byte_count = 3 /* pad */ + params + count;
5537 pSMB->DataCount = cpu_to_le16(count);
5538 pSMB->ParameterCount = cpu_to_le16(params);
5539 pSMB->TotalDataCount = pSMB->DataCount;
5540 pSMB->TotalParameterCount = pSMB->ParameterCount;
5541 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5542 pSMB->DataOffset = cpu_to_le16(offset);
5543 pSMB->Fid = fid;
5544 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5545 pSMB->Reserved4 = 0;
be8e3b00 5546 inc_rfc1001_len(pSMB, byte_count);
3bbeeb3c
JL
5547 pSMB->ByteCount = cpu_to_le16(byte_count);
5548
b2a3ad9c 5549 cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
3bbeeb3c 5550
792af7b0 5551 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
da502f7d 5552 cifs_small_buf_release(pSMB);
3bbeeb3c 5553 if (rc)
f96637be
JP
5554 cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
5555 rc);
3bbeeb3c
JL
5556
5557 /* Note: On -EAGAIN error only caller can retry on handle based calls
5558 since file handle passed in no longer valid */
5559
5560 return rc;
5561}
5562
1da177e4 5563int
6d5786a3 5564CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
ff691e96 5565 const char *file_name,
01ea95e3
JL
5566 const struct cifs_unix_set_info_args *args,
5567 const struct nls_table *nls_codepage, int remap)
1da177e4
LT
5568{
5569 TRANSACTION2_SPI_REQ *pSMB = NULL;
5570 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5571 int name_len;
5572 int rc = 0;
5573 int bytes_returned = 0;
5574 FILE_UNIX_BASIC_INFO *data_offset;
5575 __u16 params, param_offset, offset, count, byte_count;
5576
f96637be 5577 cifs_dbg(FYI, "In SetUID/GID/Mode\n");
1da177e4
LT
5578setPermsRetry:
5579 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5580 (void **) &pSMBr);
5581 if (rc)
5582 return rc;
5583
5584 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5585 name_len =
ff691e96 5586 cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
acbbb76a 5587 PATH_MAX, nls_codepage, remap);
1da177e4
LT
5588 name_len++; /* trailing null */
5589 name_len *= 2;
340625e6
RS
5590 } else {
5591 name_len = copy_path_name(pSMB->FileName, file_name);
1da177e4
LT
5592 }
5593
5594 params = 6 + name_len;
26f57364 5595 count = sizeof(FILE_UNIX_BASIC_INFO);
1da177e4 5596 pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5
SF
5597 /* BB find max SMB PDU from sess structure BB */
5598 pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4
LT
5599 pSMB->MaxSetupCount = 0;
5600 pSMB->Reserved = 0;
5601 pSMB->Flags = 0;
5602 pSMB->Timeout = 0;
5603 pSMB->Reserved2 = 0;
5604 param_offset = offsetof(struct smb_com_transaction2_spi_req,
50c2f753 5605 InformationLevel) - 4;
1da177e4 5606 offset = param_offset + params;
b019e118
SF
5607 /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
5608 data_offset = (FILE_UNIX_BASIC_INFO *)((char *) pSMB + offset + 4);
1da177e4
LT
5609 memset(data_offset, 0, count);
5610 pSMB->DataOffset = cpu_to_le16(offset);
5611 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5612 pSMB->SetupCount = 1;
5613 pSMB->Reserved3 = 0;
5614 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5615 byte_count = 3 /* pad */ + params + count;
5616 pSMB->ParameterCount = cpu_to_le16(params);
5617 pSMB->DataCount = cpu_to_le16(count);
5618 pSMB->TotalParameterCount = pSMB->ParameterCount;
5619 pSMB->TotalDataCount = pSMB->DataCount;
5620 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5621 pSMB->Reserved4 = 0;
be8e3b00 5622 inc_rfc1001_len(pSMB, byte_count);
1da177e4 5623
654cf14a 5624 cifs_fill_unix_set_info(data_offset, args);
1da177e4
LT
5625
5626 pSMB->ByteCount = cpu_to_le16(byte_count);
5627 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5628 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
ad7a2926 5629 if (rc)
f96637be 5630 cifs_dbg(FYI, "SetPathInfo (perms) returned %d\n", rc);
1da177e4 5631
0d817bc0 5632 cifs_buf_release(pSMB);
1da177e4
LT
5633 if (rc == -EAGAIN)
5634 goto setPermsRetry;
5635 return rc;
5636}
5637
1da177e4 5638#ifdef CONFIG_CIFS_XATTR
31c0519f
JL
5639/*
5640 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
5641 * function used by listxattr and getxattr type calls. When ea_name is set,
5642 * it looks for that attribute name and stuffs that value into the EAData
5643 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
5644 * buffer. In both cases, the return value is either the length of the
5645 * resulting data or a negative error code. If EAData is a NULL pointer then
5646 * the data isn't copied to it, but the length is returned.
5647 */
1da177e4 5648ssize_t
6d5786a3 5649CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
31c0519f
JL
5650 const unsigned char *searchName, const unsigned char *ea_name,
5651 char *EAData, size_t buf_size,
67b4c889 5652 struct cifs_sb_info *cifs_sb)
1da177e4
LT
5653{
5654 /* BB assumes one setup word */
5655 TRANSACTION2_QPI_REQ *pSMB = NULL;
5656 TRANSACTION2_QPI_RSP *pSMBr = NULL;
67b4c889
SF
5657 int remap = cifs_remap(cifs_sb);
5658 struct nls_table *nls_codepage = cifs_sb->local_nls;
1da177e4
LT
5659 int rc = 0;
5660 int bytes_returned;
6e462b9f 5661 int list_len;
f0d3868b 5662 struct fealist *ea_response_data;
50c2f753
SF
5663 struct fea *temp_fea;
5664 char *temp_ptr;
0cd126b5 5665 char *end_of_smb;
f0d3868b 5666 __u16 params, byte_count, data_offset;
5980fc96 5667 unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
1da177e4 5668
f96637be 5669 cifs_dbg(FYI, "In Query All EAs path %s\n", searchName);
1da177e4
LT
5670QAllEAsRetry:
5671 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5672 (void **) &pSMBr);
5673 if (rc)
5674 return rc;
5675
5676 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6e462b9f 5677 list_len =
acbbb76a
SF
5678 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
5679 PATH_MAX, nls_codepage, remap);
6e462b9f
JL
5680 list_len++; /* trailing null */
5681 list_len *= 2;
340625e6
RS
5682 } else {
5683 list_len = copy_path_name(pSMB->FileName, searchName);
1da177e4
LT
5684 }
5685
6e462b9f 5686 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
1da177e4
LT
5687 pSMB->TotalDataCount = 0;
5688 pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5 5689 /* BB find exact max SMB PDU from sess structure BB */
e529614a 5690 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
1da177e4
LT
5691 pSMB->MaxSetupCount = 0;
5692 pSMB->Reserved = 0;
5693 pSMB->Flags = 0;
5694 pSMB->Timeout = 0;
5695 pSMB->Reserved2 = 0;
5696 pSMB->ParameterOffset = cpu_to_le16(offsetof(
50c2f753 5697 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
1da177e4
LT
5698 pSMB->DataCount = 0;
5699 pSMB->DataOffset = 0;
5700 pSMB->SetupCount = 1;
5701 pSMB->Reserved3 = 0;
5702 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5703 byte_count = params + 1 /* pad */ ;
5704 pSMB->TotalParameterCount = cpu_to_le16(params);
5705 pSMB->ParameterCount = pSMB->TotalParameterCount;
5706 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5707 pSMB->Reserved4 = 0;
be8e3b00 5708 inc_rfc1001_len(pSMB, byte_count);
1da177e4
LT
5709 pSMB->ByteCount = cpu_to_le16(byte_count);
5710
5711 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5712 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5713 if (rc) {
f96637be 5714 cifs_dbg(FYI, "Send error in QueryAllEAs = %d\n", rc);
f0d3868b
JL
5715 goto QAllEAsOut;
5716 }
1da177e4 5717
f0d3868b
JL
5718
5719 /* BB also check enough total bytes returned */
5720 /* BB we need to improve the validity checking
5721 of these trans2 responses */
5722
5723 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
820a803f 5724 if (rc || get_bcc(&pSMBr->hdr) < 4) {
f0d3868b
JL
5725 rc = -EIO; /* bad smb */
5726 goto QAllEAsOut;
5727 }
5728
5729 /* check that length of list is not more than bcc */
5730 /* check that each entry does not go beyond length
5731 of list */
5732 /* check that each element of each entry does not
5733 go beyond end of list */
5734 /* validate_trans2_offsets() */
5735 /* BB check if start of smb + data_offset > &bcc+ bcc */
5736
5737 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5738 ea_response_data = (struct fealist *)
5739 (((char *) &pSMBr->hdr.Protocol) + data_offset);
5740
6e462b9f 5741 list_len = le32_to_cpu(ea_response_data->list_len);
f96637be 5742 cifs_dbg(FYI, "ea length %d\n", list_len);
6e462b9f 5743 if (list_len <= 8) {
f96637be 5744 cifs_dbg(FYI, "empty EA list returned from server\n");
60977fcc
SF
5745 /* didn't find the named attribute */
5746 if (ea_name)
5747 rc = -ENODATA;
f0d3868b
JL
5748 goto QAllEAsOut;
5749 }
5750
0cd126b5 5751 /* make sure list_len doesn't go past end of SMB */
690c522f 5752 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
0cd126b5 5753 if ((char *)ea_response_data + list_len > end_of_smb) {
f96637be 5754 cifs_dbg(FYI, "EA list appears to go beyond SMB\n");
0cd126b5
JL
5755 rc = -EIO;
5756 goto QAllEAsOut;
5757 }
5758
f0d3868b 5759 /* account for ea list len */
6e462b9f 5760 list_len -= 4;
398d5843 5761 temp_fea = &ea_response_data->list;
f0d3868b 5762 temp_ptr = (char *)temp_fea;
6e462b9f 5763 while (list_len > 0) {
122ca007 5764 unsigned int name_len;
f0d3868b 5765 __u16 value_len;
0cd126b5 5766
6e462b9f 5767 list_len -= 4;
f0d3868b 5768 temp_ptr += 4;
0cd126b5
JL
5769 /* make sure we can read name_len and value_len */
5770 if (list_len < 0) {
f96637be 5771 cifs_dbg(FYI, "EA entry goes beyond length of list\n");
0cd126b5
JL
5772 rc = -EIO;
5773 goto QAllEAsOut;
5774 }
5775
5776 name_len = temp_fea->name_len;
5777 value_len = le16_to_cpu(temp_fea->value_len);
5778 list_len -= name_len + 1 + value_len;
5779 if (list_len < 0) {
f96637be 5780 cifs_dbg(FYI, "EA entry goes beyond length of list\n");
0cd126b5
JL
5781 rc = -EIO;
5782 goto QAllEAsOut;
5783 }
5784
31c0519f 5785 if (ea_name) {
91d065c4 5786 if (ea_name_len == name_len &&
ac423446 5787 memcmp(ea_name, temp_ptr, name_len) == 0) {
31c0519f
JL
5788 temp_ptr += name_len + 1;
5789 rc = value_len;
5790 if (buf_size == 0)
5791 goto QAllEAsOut;
5792 if ((size_t)value_len > buf_size) {
5793 rc = -ERANGE;
5794 goto QAllEAsOut;
5795 }
5796 memcpy(EAData, temp_ptr, value_len);
5797 goto QAllEAsOut;
5798 }
f0d3868b 5799 } else {
31c0519f
JL
5800 /* account for prefix user. and trailing null */
5801 rc += (5 + 1 + name_len);
5802 if (rc < (int) buf_size) {
5803 memcpy(EAData, "user.", 5);
5804 EAData += 5;
5805 memcpy(EAData, temp_ptr, name_len);
5806 EAData += name_len;
5807 /* null terminate name */
5808 *EAData = 0;
5809 ++EAData;
5810 } else if (buf_size == 0) {
5811 /* skip copy - calc size only */
5812 } else {
5813 /* stop before overrun buffer */
5814 rc = -ERANGE;
5815 break;
5816 }
1da177e4 5817 }
0cd126b5 5818 temp_ptr += name_len + 1 + value_len;
f0d3868b 5819 temp_fea = (struct fea *)temp_ptr;
1da177e4 5820 }
f0d3868b 5821
31c0519f
JL
5822 /* didn't find the named attribute */
5823 if (ea_name)
5824 rc = -ENODATA;
5825
f0d3868b 5826QAllEAsOut:
0d817bc0 5827 cifs_buf_release(pSMB);
1da177e4
LT
5828 if (rc == -EAGAIN)
5829 goto QAllEAsRetry;
5830
5831 return (ssize_t)rc;
5832}
5833
1da177e4 5834int
6d5786a3
PS
5835CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
5836 const char *fileName, const char *ea_name, const void *ea_value,
50c2f753 5837 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5517554e 5838 struct cifs_sb_info *cifs_sb)
1da177e4
LT
5839{
5840 struct smb_com_transaction2_spi_req *pSMB = NULL;
5841 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5842 struct fealist *parm_data;
5843 int name_len;
5844 int rc = 0;
5845 int bytes_returned = 0;
5846 __u16 params, param_offset, byte_count, offset, count;
5517554e 5847 int remap = cifs_remap(cifs_sb);
1da177e4 5848
f96637be 5849 cifs_dbg(FYI, "In SetEA\n");
1da177e4
LT
5850SetEARetry:
5851 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5852 (void **) &pSMBr);
5853 if (rc)
5854 return rc;
5855
5856 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5857 name_len =
acbbb76a
SF
5858 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5859 PATH_MAX, nls_codepage, remap);
1da177e4
LT
5860 name_len++; /* trailing null */
5861 name_len *= 2;
340625e6
RS
5862 } else {
5863 name_len = copy_path_name(pSMB->FileName, fileName);
1da177e4
LT
5864 }
5865
5866 params = 6 + name_len;
5867
5868 /* done calculating parms using name_len of file name,
5869 now use name_len to calculate length of ea name
5870 we are going to create in the inode xattrs */
790fe579 5871 if (ea_name == NULL)
1da177e4
LT
5872 name_len = 0;
5873 else
50c2f753 5874 name_len = strnlen(ea_name, 255);
1da177e4 5875
398d5843 5876 count = sizeof(*parm_data) + 1 + ea_value_len + name_len;
1da177e4 5877 pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5
SF
5878 /* BB find max SMB PDU from sess */
5879 pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4
LT
5880 pSMB->MaxSetupCount = 0;
5881 pSMB->Reserved = 0;
5882 pSMB->Flags = 0;
5883 pSMB->Timeout = 0;
5884 pSMB->Reserved2 = 0;
5885 param_offset = offsetof(struct smb_com_transaction2_spi_req,
50c2f753 5886 InformationLevel) - 4;
1da177e4
LT
5887 offset = param_offset + params;
5888 pSMB->InformationLevel =
5889 cpu_to_le16(SMB_SET_FILE_EA);
5890
ade7db99 5891 parm_data = (void *)pSMB + offsetof(struct smb_hdr, Protocol) + offset;
1da177e4
LT
5892 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5893 pSMB->DataOffset = cpu_to_le16(offset);
5894 pSMB->SetupCount = 1;
5895 pSMB->Reserved3 = 0;
5896 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5897 byte_count = 3 /* pad */ + params + count;
5898 pSMB->DataCount = cpu_to_le16(count);
5899 parm_data->list_len = cpu_to_le32(count);
398d5843 5900 parm_data->list.EA_flags = 0;
1da177e4 5901 /* we checked above that name len is less than 255 */
398d5843 5902 parm_data->list.name_len = (__u8)name_len;
1da177e4 5903 /* EA names are always ASCII */
790fe579 5904 if (ea_name)
398d5843
KC
5905 strncpy(parm_data->list.name, ea_name, name_len);
5906 parm_data->list.name[name_len] = '\0';
5907 parm_data->list.value_len = cpu_to_le16(ea_value_len);
1da177e4
LT
5908 /* caller ensures that ea_value_len is less than 64K but
5909 we need to ensure that it fits within the smb */
5910
50c2f753
SF
5911 /*BB add length check to see if it would fit in
5912 negotiated SMB buffer size BB */
790fe579
SF
5913 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5914 if (ea_value_len)
398d5843 5915 memcpy(parm_data->list.name + name_len + 1,
50c2f753 5916 ea_value, ea_value_len);
1da177e4
LT
5917
5918 pSMB->TotalDataCount = pSMB->DataCount;
5919 pSMB->ParameterCount = cpu_to_le16(params);
5920 pSMB->TotalParameterCount = pSMB->ParameterCount;
5921 pSMB->Reserved4 = 0;
be8e3b00 5922 inc_rfc1001_len(pSMB, byte_count);
1da177e4
LT
5923 pSMB->ByteCount = cpu_to_le16(byte_count);
5924 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5925 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
ad7a2926 5926 if (rc)
f96637be 5927 cifs_dbg(FYI, "SetPathInfo (EA) returned %d\n", rc);
1da177e4
LT
5928
5929 cifs_buf_release(pSMB);
5930
5931 if (rc == -EAGAIN)
5932 goto SetEARetry;
5933
5934 return rc;
5935}
1da177e4 5936#endif