Blame view

fs/cifs/cifssmb.c 192 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
  /*
   *   fs/cifs/cifssmb.c
   *
f19159dc5   Steve French   [CIFS] Cleanup va...
4
   *   Copyright (C) International Business Machines  Corp., 2002,2010
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
   *   Author(s): Steve French (sfrench@us.ibm.com)
   *
   *   Contains the routines for constructing the SMB PDUs themselves
   *
   *   This library is free software; you can redistribute it and/or modify
   *   it under the terms of the GNU Lesser General Public License as published
   *   by the Free Software Foundation; either version 2.1 of the License, or
   *   (at your option) any later version.
   *
   *   This library is distributed in the hope that it will be useful,
   *   but WITHOUT ANY WARRANTY; without even the implied warranty of
   *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
   *   the GNU Lesser General Public License for more details.
   *
   *   You should have received a copy of the GNU Lesser General Public License
   *   along with this library; if not, write to the Free Software
   *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
   */
  
   /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c   */
   /* These are mostly routines that operate on a pathname, or on a tree id     */
   /* (mounted volume), but there are eight handle based routines which must be */
2dd29d313   Steve French   [CIFS] New CIFS P...
27
28
   /* treated slightly differently for reconnection purposes since we never     */
   /* want to reuse a stale file handle and only the caller knows the file info */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
30
31
32
  
  #include <linux/fs.h>
  #include <linux/kernel.h>
  #include <linux/vfs.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
33
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
  #include <linux/posix_acl_xattr.h>
c28c89fc4   Jeff Layton   cifs: add cifs_as...
35
  #include <linux/pagemap.h>
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
36
37
  #include <linux/swap.h>
  #include <linux/task_io_accounting_ops.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
39
40
  #include <asm/uaccess.h>
  #include "cifspdu.h"
  #include "cifsglob.h"
d0d66c443   Shirish Pargaonkar   [CIFS] CIFS ACL s...
41
  #include "cifsacl.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
43
44
  #include "cifsproto.h"
  #include "cifs_unicode.h"
  #include "cifs_debug.h"
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
45
  #include "fscache.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
47
48
49
50
51
  
  #ifdef CONFIG_CIFS_POSIX
  static struct {
  	int index;
  	char *name;
  } protocols[] = {
3979877e5   Steve French   [CIFS] Support fo...
52
53
  #ifdef CONFIG_CIFS_WEAK_PW_HASH
  	{LANMAN_PROT, "\2LM1.2X002"},
9ac00b7d9   Steve French   [CIFS] Do not sen...
54
  	{LANMAN2_PROT, "\2LANMAN2.1"},
3979877e5   Steve French   [CIFS] Support fo...
55
  #endif /* weak password hashing for legacy clients */
50c2f7538   Steve French   [CIFS] whitespace...
56
  	{CIFS_PROT, "\2NT LM 0.12"},
3979877e5   Steve French   [CIFS] Support fo...
57
  	{POSIX_PROT, "\2POSIX 2"},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
59
60
61
62
63
64
  	{BAD_PROT, "\2"}
  };
  #else
  static struct {
  	int index;
  	char *name;
  } protocols[] = {
3979877e5   Steve French   [CIFS] Support fo...
65
66
  #ifdef CONFIG_CIFS_WEAK_PW_HASH
  	{LANMAN_PROT, "\2LM1.2X002"},
18f75ca0d   Steve French   [CIFS] Allow LANM...
67
  	{LANMAN2_PROT, "\2LANMAN2.1"},
3979877e5   Steve French   [CIFS] Support fo...
68
  #endif /* weak password hashing for legacy clients */
790fe579f   Steve French   [CIFS] more white...
69
  	{CIFS_PROT, "\2NT LM 0.12"},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
71
72
  	{BAD_PROT, "\2"}
  };
  #endif
3979877e5   Steve French   [CIFS] Support fo...
73
74
75
  /* define the number of elements in the cifs dialect array */
  #ifdef CONFIG_CIFS_POSIX
  #ifdef CONFIG_CIFS_WEAK_PW_HASH
9ac00b7d9   Steve French   [CIFS] Do not sen...
76
  #define CIFS_NUM_PROT 4
3979877e5   Steve French   [CIFS] Support fo...
77
78
79
80
81
  #else
  #define CIFS_NUM_PROT 2
  #endif /* CIFS_WEAK_PW_HASH */
  #else /* not posix */
  #ifdef CONFIG_CIFS_WEAK_PW_HASH
9ac00b7d9   Steve French   [CIFS] Do not sen...
82
  #define CIFS_NUM_PROT 3
3979877e5   Steve French   [CIFS] Support fo...
83
84
85
86
  #else
  #define CIFS_NUM_PROT 1
  #endif /* CONFIG_CIFS_WEAK_PW_HASH */
  #endif /* CIFS_POSIX */
aa24d1e96   Pavel Shilovsky   CIFS: Process rec...
87
88
89
90
91
92
  /*
   * Mark as invalid, all open files on tree connections since they
   * were closed when session to server was lost.
   */
  void
  cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93
94
  {
  	struct cifsFileInfo *open_file = NULL;
790fe579f   Steve French   [CIFS] more white...
95
96
  	struct list_head *tmp;
  	struct list_head *tmp1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97

aa24d1e96   Pavel Shilovsky   CIFS: Process rec...
98
  	/* list all files open on tree connection and mark them invalid */
4477288a1   Jeff Layton   cifs: convert Glo...
99
  	spin_lock(&cifs_file_list_lock);
aa24d1e96   Pavel Shilovsky   CIFS: Process rec...
100
  	list_for_each_safe(tmp, tmp1, &tcon->openFileList) {
790fe579f   Steve French   [CIFS] more white...
101
  		open_file = list_entry(tmp, struct cifsFileInfo, tlist);
ad8b15f0f   Steve French   [CIFS] list entry...
102
  		open_file->invalidHandle = true;
3bc303c25   Jeff Layton   cifs: convert opl...
103
  		open_file->oplock_break_cancelled = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
  	}
4477288a1   Jeff Layton   cifs: convert Glo...
105
  	spin_unlock(&cifs_file_list_lock);
aa24d1e96   Pavel Shilovsky   CIFS: Process rec...
106
107
108
109
  	/*
  	 * BB Add call to invalidate_inodes(sb) for all superblocks mounted
  	 * to this tcon.
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
  }
9162ab200   Jeff Layton   cifs: consolidate...
111
112
  /* reconnect the socket, tcon, and smb session if needed */
  static int
96daf2b09   Steve French   [CIFS] Rename thr...
113
  cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
9162ab200   Jeff Layton   cifs: consolidate...
114
  {
c4a5534a1   Jeff Layton   cifs: remove unne...
115
  	int rc;
96daf2b09   Steve French   [CIFS] Rename thr...
116
  	struct cifs_ses *ses;
9162ab200   Jeff Layton   cifs: consolidate...
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
  	struct TCP_Server_Info *server;
  	struct nls_table *nls_codepage;
  
  	/*
  	 * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
  	 * tcp and smb session status done differently for those three - in the
  	 * calling routine
  	 */
  	if (!tcon)
  		return 0;
  
  	ses = tcon->ses;
  	server = ses->server;
  
  	/*
  	 * only tree disconnect, open, and write, (and ulogoff which does not
  	 * have tcon) are allowed as we start force umount
  	 */
  	if (tcon->tidStatus == CifsExiting) {
  		if (smb_command != SMB_COM_WRITE_ANDX &&
  		    smb_command != SMB_COM_OPEN_ANDX &&
  		    smb_command != SMB_COM_TREE_DISCONNECT) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
139
140
141
  			cifs_dbg(FYI, "can not send cmd %d while umounting
  ",
  				 smb_command);
9162ab200   Jeff Layton   cifs: consolidate...
142
143
144
  			return -ENODEV;
  		}
  	}
9162ab200   Jeff Layton   cifs: consolidate...
145
146
147
148
149
150
  	/*
  	 * Give demultiplex thread up to 10 seconds to reconnect, should be
  	 * greater than cifs socket timeout which is 7 seconds
  	 */
  	while (server->tcpStatus == CifsNeedReconnect) {
  		wait_event_interruptible_timeout(server->response_q,
fd88ce931   Steve French   [CIFS] cifs: clar...
151
  			(server->tcpStatus != CifsNeedReconnect), 10 * HZ);
9162ab200   Jeff Layton   cifs: consolidate...
152

fd88ce931   Steve French   [CIFS] cifs: clar...
153
  		/* are we still trying to reconnect? */
9162ab200   Jeff Layton   cifs: consolidate...
154
155
156
157
158
159
160
161
  		if (server->tcpStatus != CifsNeedReconnect)
  			break;
  
  		/*
  		 * on "soft" mounts we wait once. Hard mounts keep
  		 * retrying until process is killed or server comes
  		 * back on-line
  		 */
d402539b8   Jeff Layton   cifs: remove chec...
162
  		if (!tcon->retry) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
163
164
  			cifs_dbg(FYI, "gave up waiting on reconnect in smb_init
  ");
9162ab200   Jeff Layton   cifs: consolidate...
165
166
167
168
169
170
171
172
173
174
175
176
177
  			return -EHOSTDOWN;
  		}
  	}
  
  	if (!ses->need_reconnect && !tcon->need_reconnect)
  		return 0;
  
  	nls_codepage = load_nls_default();
  
  	/*
  	 * need to prevent multiple threads trying to simultaneously
  	 * reconnect the same SMB session
  	 */
d7b619cf5   Steve French   [CIFS] pSesInfo->...
178
  	mutex_lock(&ses->session_mutex);
198b56827   Jeff Layton   cifs: break negot...
179
180
  	rc = cifs_negotiate_protocol(0, ses);
  	if (rc == 0 && ses->need_reconnect)
9162ab200   Jeff Layton   cifs: consolidate...
181
182
183
184
  		rc = cifs_setup_session(0, ses, nls_codepage);
  
  	/* do we need to reconnect tcon? */
  	if (rc || !tcon->need_reconnect) {
d7b619cf5   Steve French   [CIFS] pSesInfo->...
185
  		mutex_unlock(&ses->session_mutex);
9162ab200   Jeff Layton   cifs: consolidate...
186
187
  		goto out;
  	}
aa24d1e96   Pavel Shilovsky   CIFS: Process rec...
188
  	cifs_mark_open_files_invalid(tcon);
9162ab200   Jeff Layton   cifs: consolidate...
189
  	rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
d7b619cf5   Steve French   [CIFS] pSesInfo->...
190
  	mutex_unlock(&ses->session_mutex);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
191
192
  	cifs_dbg(FYI, "reconnect tcon rc = %d
  ", rc);
9162ab200   Jeff Layton   cifs: consolidate...
193
194
195
  
  	if (rc)
  		goto out;
9162ab200   Jeff Layton   cifs: consolidate...
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
  	atomic_inc(&tconInfoReconnectCount);
  
  	/* tell server Unix caps we support */
  	if (ses->capabilities & CAP_UNIX)
  		reset_cifs_unix_caps(0, tcon, NULL, NULL);
  
  	/*
  	 * Removed call to reopen open files here. It is safer (and faster) to
  	 * reopen files one at a time as needed in read and write.
  	 *
  	 * FIXME: what about file locks? don't we need to reclaim them ASAP?
  	 */
  
  out:
  	/*
  	 * Check if handle based operation so we know whether we can continue
  	 * or not without returning to caller to reset file handle
  	 */
  	switch (smb_command) {
  	case SMB_COM_READ_ANDX:
  	case SMB_COM_WRITE_ANDX:
  	case SMB_COM_CLOSE:
  	case SMB_COM_FIND_CLOSE2:
  	case SMB_COM_LOCKING_ANDX:
  		rc = -EAGAIN;
  	}
  
  	unload_nls(nls_codepage);
  	return rc;
  }
ad7a2926b   Steve French   [CIFS] reduce che...
226
227
228
  /* Allocate and return pointer to an SMB request buffer, and set basic
     SMB information in the SMB header.  If the return code is zero, this
     function must have filled in request_buf pointer */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
229
  static int
96daf2b09   Steve French   [CIFS] Rename thr...
230
  small_smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
ad7a2926b   Steve French   [CIFS] reduce che...
231
  		void **request_buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232
  {
f569599ae   Jeff Layton   cifs: prevent inf...
233
  	int rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234

9162ab200   Jeff Layton   cifs: consolidate...
235
  	rc = cifs_reconnect_tcon(tcon, smb_command);
790fe579f   Steve French   [CIFS] more white...
236
  	if (rc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237
238
239
240
241
242
243
  		return rc;
  
  	*request_buf = cifs_small_buf_get();
  	if (*request_buf == NULL) {
  		/* BB should we add a retry in here if not a writepage? */
  		return -ENOMEM;
  	}
63135e088   Steve French   [CIFS] More white...
244
  	header_assemble((struct smb_hdr *) *request_buf, smb_command,
c18c842b1   Steve French   [CIFS] Allow disa...
245
  			tcon, wct);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246

790fe579f   Steve French   [CIFS] more white...
247
248
  	if (tcon != NULL)
  		cifs_stats_inc(&tcon->num_smbs_sent);
a45443475   Steve French   CIFS: Reduce CONF...
249

f569599ae   Jeff Layton   cifs: prevent inf...
250
  	return 0;
5815449d1   Steve French   [CIFS] SessionSet...
251
  }
12b3b8ffb   Steve French   [CIFS] Cleanup NT...
252
  int
50c2f7538   Steve French   [CIFS] whitespace...
253
  small_smb_init_no_tc(const int smb_command, const int wct,
96daf2b09   Steve French   [CIFS] Rename thr...
254
  		     struct cifs_ses *ses, void **request_buf)
12b3b8ffb   Steve French   [CIFS] Cleanup NT...
255
256
  {
  	int rc;
50c2f7538   Steve French   [CIFS] whitespace...
257
  	struct smb_hdr *buffer;
12b3b8ffb   Steve French   [CIFS] Cleanup NT...
258

5815449d1   Steve French   [CIFS] SessionSet...
259
  	rc = small_smb_init(smb_command, wct, NULL, request_buf);
790fe579f   Steve French   [CIFS] more white...
260
  	if (rc)
12b3b8ffb   Steve French   [CIFS] Cleanup NT...
261
  		return rc;
04fdabe17   Steve French   [CIFS] fix compil...
262
  	buffer = (struct smb_hdr *)*request_buf;
882573606   Pavel Shilovsky   CIFS: Move get_ne...
263
  	buffer->Mid = get_next_mid(ses->server);
12b3b8ffb   Steve French   [CIFS] Cleanup NT...
264
265
  	if (ses->capabilities & CAP_UNICODE)
  		buffer->Flags2 |= SMBFLG2_UNICODE;
04fdabe17   Steve French   [CIFS] fix compil...
266
  	if (ses->capabilities & CAP_STATUS32)
12b3b8ffb   Steve French   [CIFS] Cleanup NT...
267
268
269
  		buffer->Flags2 |= SMBFLG2_ERR_STATUS;
  
  	/* uid, tid can stay at zero as set in header assemble */
50c2f7538   Steve French   [CIFS] whitespace...
270
  	/* BB add support for turning on the signing when
12b3b8ffb   Steve French   [CIFS] Cleanup NT...
271
272
273
274
  	this function is used after 1st of session setup requests */
  
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
275
276
277
  
  /* If the return code is zero, this function must fill in request_buf pointer */
  static int
96daf2b09   Steve French   [CIFS] Rename thr...
278
  __smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
f569599ae   Jeff Layton   cifs: prevent inf...
279
  			void **request_buf, void **response_buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
281
282
283
284
285
286
287
288
289
  	*request_buf = cifs_buf_get();
  	if (*request_buf == NULL) {
  		/* BB should we add a retry in here if not a writepage? */
  		return -ENOMEM;
  	}
      /* Although the original thought was we needed the response buf for  */
      /* potential retries of smb operations it turns out we can determine */
      /* from the mid flags when the request buffer can be resent without  */
      /* having to use a second distinct buffer for the response */
790fe579f   Steve French   [CIFS] more white...
290
  	if (response_buf)
50c2f7538   Steve French   [CIFS] whitespace...
291
  		*response_buf = *request_buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292
293
  
  	header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
ad7a2926b   Steve French   [CIFS] reduce che...
294
  			wct);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295

790fe579f   Steve French   [CIFS] more white...
296
297
  	if (tcon != NULL)
  		cifs_stats_inc(&tcon->num_smbs_sent);
a45443475   Steve French   CIFS: Reduce CONF...
298

f569599ae   Jeff Layton   cifs: prevent inf...
299
300
301
302
303
  	return 0;
  }
  
  /* If the return code is zero, this function must fill in request_buf pointer */
  static int
96daf2b09   Steve French   [CIFS] Rename thr...
304
  smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
f569599ae   Jeff Layton   cifs: prevent inf...
305
306
307
308
309
310
311
312
313
314
315
316
  	 void **request_buf, void **response_buf)
  {
  	int rc;
  
  	rc = cifs_reconnect_tcon(tcon, smb_command);
  	if (rc)
  		return rc;
  
  	return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
  }
  
  static int
96daf2b09   Steve French   [CIFS] Rename thr...
317
  smb_init_no_reconnect(int smb_command, int wct, struct cifs_tcon *tcon,
f569599ae   Jeff Layton   cifs: prevent inf...
318
319
320
321
322
323
  			void **request_buf, void **response_buf)
  {
  	if (tcon->ses->need_reconnect || tcon->need_reconnect)
  		return -EHOSTDOWN;
  
  	return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
324
  }
50c2f7538   Steve French   [CIFS] whitespace...
325
  static int validate_t2(struct smb_t2_rsp *pSMB)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
326
  {
12df83c9b   Jeff Layton   cifs: clean up un...
327
328
329
330
331
  	unsigned int total_size;
  
  	/* check for plausible wct */
  	if (pSMB->hdr.WordCount < 10)
  		goto vt2_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
332

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
333
  	/* check for parm and data offset going beyond end of smb */
12df83c9b   Jeff Layton   cifs: clean up un...
334
335
336
  	if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
  	    get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
  		goto vt2_err;
12df83c9b   Jeff Layton   cifs: clean up un...
337
338
339
  	total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
  	if (total_size >= 512)
  		goto vt2_err;
fd5707e1b   Jeff Layton   cifs: fix comment...
340
341
342
  	/* check that bcc is at least as big as parms + data, and that it is
  	 * less than negotiated smb buffer
  	 */
12df83c9b   Jeff Layton   cifs: clean up un...
343
344
345
346
347
348
349
  	total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
  	if (total_size > get_bcc(&pSMB->hdr) ||
  	    total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
  		goto vt2_err;
  
  	return 0;
  vt2_err:
50c2f7538   Steve French   [CIFS] whitespace...
350
  	cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351
  		sizeof(struct smb_t2_rsp) + 16);
12df83c9b   Jeff Layton   cifs: clean up un...
352
  	return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
353
  }
690c522fa   Jeff Layton   cifs: use get/put...
354

31d9e2bd5   Jeff Layton   cifs: break out d...
355
  static int
3f618223d   Jeff Layton   move sectype to t...
356
  decode_ext_sec_blob(struct cifs_ses *ses, NEGOTIATE_RSP *pSMBr)
31d9e2bd5   Jeff Layton   cifs: break out d...
357
358
359
360
  {
  	int	rc = 0;
  	u16	count;
  	char	*guid = pSMBr->u.extended_response.GUID;
3f618223d   Jeff Layton   move sectype to t...
361
  	struct TCP_Server_Info *server = ses->server;
31d9e2bd5   Jeff Layton   cifs: break out d...
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
  
  	count = get_bcc(&pSMBr->hdr);
  	if (count < SMB1_CLIENT_GUID_SIZE)
  		return -EIO;
  
  	spin_lock(&cifs_tcp_ses_lock);
  	if (server->srv_count > 1) {
  		spin_unlock(&cifs_tcp_ses_lock);
  		if (memcmp(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE) != 0) {
  			cifs_dbg(FYI, "server UID changed
  ");
  			memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
  		}
  	} else {
  		spin_unlock(&cifs_tcp_ses_lock);
  		memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
  	}
  
  	if (count == SMB1_CLIENT_GUID_SIZE) {
3f618223d   Jeff Layton   move sectype to t...
381
  		server->sec_ntlmssp = true;
31d9e2bd5   Jeff Layton   cifs: break out d...
382
383
384
385
386
387
  	} else {
  		count -= SMB1_CLIENT_GUID_SIZE;
  		rc = decode_negTokenInit(
  			pSMBr->u.extended_response.SecurityBlob, count, server);
  		if (rc != 1)
  			return -EINVAL;
31d9e2bd5   Jeff Layton   cifs: break out d...
388
389
390
391
  	}
  
  	return 0;
  }
9ddec5613   Jeff Layton   cifs: move handli...
392
  int
38d77c50b   Jeff Layton   cifs: track the e...
393
  cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required)
9ddec5613   Jeff Layton   cifs: move handli...
394
  {
50285882f   Jeff Layton   cifs: fix SMB2 si...
395
396
  	bool srv_sign_required = server->sec_mode & server->vals->signing_required;
  	bool srv_sign_enabled = server->sec_mode & server->vals->signing_enabled;
38d77c50b   Jeff Layton   cifs: track the e...
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
  	bool mnt_sign_enabled = global_secflags & CIFSSEC_MAY_SIGN;
  
  	/*
  	 * Is signing required by mnt options? If not then check
  	 * global_secflags to see if it is there.
  	 */
  	if (!mnt_sign_required)
  		mnt_sign_required = ((global_secflags & CIFSSEC_MUST_SIGN) ==
  						CIFSSEC_MUST_SIGN);
  
  	/*
  	 * If signing is required then it's automatically enabled too,
  	 * otherwise, check to see if the secflags allow it.
  	 */
  	mnt_sign_enabled = mnt_sign_required ? mnt_sign_required :
  				(global_secflags & CIFSSEC_MAY_SIGN);
  
  	/* If server requires signing, does client allow it? */
  	if (srv_sign_required) {
  		if (!mnt_sign_enabled) {
  			cifs_dbg(VFS, "Server requires signing, but it's disabled in SecurityFlags!");
  			return -ENOTSUPP;
9ddec5613   Jeff Layton   cifs: move handli...
419
  		}
38d77c50b   Jeff Layton   cifs: track the e...
420
421
422
423
424
425
426
427
428
429
  		server->sign = true;
  	}
  
  	/* If client requires signing, does server allow it? */
  	if (mnt_sign_required) {
  		if (!srv_sign_enabled) {
  			cifs_dbg(VFS, "Server does not support signing!");
  			return -ENOTSUPP;
  		}
  		server->sign = true;
9ddec5613   Jeff Layton   cifs: move handli...
430
431
432
433
  	}
  
  	return 0;
  }
2190eca1d   Jeff Layton   cifs: break out l...
434
435
  #ifdef CONFIG_CIFS_WEAK_PW_HASH
  static int
3f618223d   Jeff Layton   move sectype to t...
436
  decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
2190eca1d   Jeff Layton   cifs: break out l...
437
438
439
440
441
442
  {
  	__s16 tmp;
  	struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
  
  	if (server->dialect != LANMAN_PROT && server->dialect != LANMAN2_PROT)
  		return -EOPNOTSUPP;
2190eca1d   Jeff Layton   cifs: break out l...
443
444
445
446
447
448
  	server->sec_mode = le16_to_cpu(rsp->SecurityMode);
  	server->maxReq = min_t(unsigned int,
  			       le16_to_cpu(rsp->MaxMpxCount),
  			       cifs_max_pending);
  	set_credits(server, server->maxReq);
  	server->maxBuf = le16_to_cpu(rsp->MaxBufSize);
2190eca1d   Jeff Layton   cifs: break out l...
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
  	/* even though we do not use raw we might as well set this
  	accurately, in case we ever find a need for it */
  	if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
  		server->max_rw = 0xFF00;
  		server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
  	} else {
  		server->max_rw = 0;/* do not need to use raw anyway */
  		server->capabilities = CAP_MPX_MODE;
  	}
  	tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
  	if (tmp == -1) {
  		/* OS/2 often does not set timezone therefore
  		 * we must use server time to calc time zone.
  		 * Could deviate slightly from the right zone.
  		 * Smallest defined timezone difference is 15 minutes
  		 * (i.e. Nepal).  Rounding up/down is done to match
  		 * this requirement.
  		 */
  		int val, seconds, remain, result;
  		struct timespec ts, utc;
  		utc = CURRENT_TIME;
  		ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
  				    rsp->SrvTime.Time, 0);
  		cifs_dbg(FYI, "SrvTime %d sec since 1970 (utc: %d) diff: %d
  ",
  			 (int)ts.tv_sec, (int)utc.tv_sec,
  			 (int)(utc.tv_sec - ts.tv_sec));
  		val = (int)(utc.tv_sec - ts.tv_sec);
  		seconds = abs(val);
  		result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
  		remain = seconds % MIN_TZ_ADJ;
  		if (remain >= (MIN_TZ_ADJ / 2))
  			result += MIN_TZ_ADJ;
  		if (val < 0)
  			result = -result;
  		server->timeAdj = result;
  	} else {
  		server->timeAdj = (int)tmp;
  		server->timeAdj *= 60; /* also in seconds */
  	}
  	cifs_dbg(FYI, "server->timeAdj: %d seconds
  ", server->timeAdj);
  
  
  	/* BB get server time for time conversions and add
  	code to use it and timezone since this is not UTC */
  
  	if (rsp->EncryptionKeyLength ==
  			cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
  		memcpy(server->cryptkey, rsp->EncryptionKey,
  			CIFS_CRYPTO_KEY_SIZE);
  	} else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
  		return -EIO; /* need cryptkey unless plain text */
  	}
  
  	cifs_dbg(FYI, "LANMAN negotiated
  ");
  	return 0;
  }
  #else
  static inline int
3f618223d   Jeff Layton   move sectype to t...
510
  decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
2190eca1d   Jeff Layton   cifs: break out l...
511
512
513
514
515
516
  {
  	cifs_dbg(VFS, "mount failed, cifs module not built with CIFS_WEAK_PW_HASH support
  ");
  	return -EOPNOTSUPP;
  }
  #endif
9193400b6   Jeff Layton   cifs: factor out ...
517
  static bool
3f618223d   Jeff Layton   move sectype to t...
518
  should_set_ext_sec_flag(enum securityEnum sectype)
9193400b6   Jeff Layton   cifs: factor out ...
519
  {
3f618223d   Jeff Layton   move sectype to t...
520
521
522
  	switch (sectype) {
  	case RawNTLMSSP:
  	case Kerberos:
9193400b6   Jeff Layton   cifs: factor out ...
523
  		return true;
3f618223d   Jeff Layton   move sectype to t...
524
525
526
527
528
529
530
531
  	case Unspecified:
  		if (global_secflags &
  		    (CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP))
  			return true;
  		/* Fallthrough */
  	default:
  		return false;
  	}
9193400b6   Jeff Layton   cifs: factor out ...
532
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
533
  int
286170aa2   Pavel Shilovsky   CIFS: Move protoc...
534
  CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
535
536
537
538
539
  {
  	NEGOTIATE_REQ *pSMB;
  	NEGOTIATE_RSP *pSMBr;
  	int rc = 0;
  	int bytes_returned;
3979877e5   Steve French   [CIFS] Support fo...
540
  	int i;
3534b8508   Jeff Layton   cifs: throw a war...
541
  	struct TCP_Server_Info *server = ses->server;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
542
  	u16 count;
3534b8508   Jeff Layton   cifs: throw a war...
543
544
545
546
  	if (!server) {
  		WARN(1, "%s: server is NULL!
  ", __func__);
  		return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
547
  	}
3534b8508   Jeff Layton   cifs: throw a war...
548

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
549
550
551
552
  	rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
  		      (void **) &pSMB, (void **) &pSMBr);
  	if (rc)
  		return rc;
750d1151a   Steve French   [CIFS] Fix alloca...
553

882573606   Pavel Shilovsky   CIFS: Move get_ne...
554
  	pSMB->hdr.Mid = get_next_mid(server);
100c1ddc9   Yehuda Sadeh Weinraub   [CIFS] Missing fl...
555
  	pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
a013689dd   Steve French   [CIFS] Fix cifsd ...
556

3f618223d   Jeff Layton   move sectype to t...
557
  	if (should_set_ext_sec_flag(ses->sectype)) {
9193400b6   Jeff Layton   cifs: factor out ...
558
  		cifs_dbg(FYI, "Requesting extended security.");
ac6839246   Steve French   [CIFS] Allow raw ...
559
560
  		pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
  	}
50c2f7538   Steve French   [CIFS] whitespace...
561

3979877e5   Steve French   [CIFS] Support fo...
562
  	count = 0;
50c2f7538   Steve French   [CIFS] whitespace...
563
  	for (i = 0; i < CIFS_NUM_PROT; i++) {
3979877e5   Steve French   [CIFS] Support fo...
564
565
566
567
  		strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
  		count += strlen(protocols[i].name) + 1;
  		/* null at end of source and target buffers anyway */
  	}
be8e3b004   Steve French   consistently use ...
568
  	inc_rfc1001_len(pSMB, count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
569
570
571
572
  	pSMB->ByteCount = cpu_to_le16(count);
  
  	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
50c2f7538   Steve French   [CIFS] whitespace...
573
  	if (rc != 0)
254e55ed0   Steve French   CIFS] Support for...
574
  		goto neg_err_exit;
9bf67e516   Jeff Layton   cifs: save the di...
575
  	server->dialect = le16_to_cpu(pSMBr->DialectIndex);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
576
577
  	cifs_dbg(FYI, "Dialect: %d
  ", server->dialect);
254e55ed0   Steve French   CIFS] Support for...
578
  	/* Check wct = 1 error case */
9bf67e516   Jeff Layton   cifs: save the di...
579
  	if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) {
254e55ed0   Steve French   CIFS] Support for...
580
  		/* core returns wct = 1, but we do not ask for core - otherwise
50c2f7538   Steve French   [CIFS] whitespace...
581
  		small wct just comes when dialect index is -1 indicating we
254e55ed0   Steve French   CIFS] Support for...
582
583
584
  		could not negotiate a common dialect */
  		rc = -EOPNOTSUPP;
  		goto neg_err_exit;
790fe579f   Steve French   [CIFS] more white...
585
  	} else if (pSMBr->hdr.WordCount == 13) {
e598d1d8f   Jeff Layton   cifs: track the f...
586
  		server->negflavor = CIFS_NEGFLAVOR_LANMAN;
3f618223d   Jeff Layton   move sectype to t...
587
  		rc = decode_lanman_negprot_rsp(server, pSMBr);
9ddec5613   Jeff Layton   cifs: move handli...
588
  		goto signing_check;
790fe579f   Steve French   [CIFS] more white...
589
  	} else if (pSMBr->hdr.WordCount != 17) {
254e55ed0   Steve French   CIFS] Support for...
590
591
592
593
  		/* unknown wct */
  		rc = -EOPNOTSUPP;
  		goto neg_err_exit;
  	}
2190eca1d   Jeff Layton   cifs: break out l...
594
  	/* else wct == 17, NTLM or better */
96daf2b09   Steve French   [CIFS] Rename thr...
595
596
  	server->sec_mode = pSMBr->SecurityMode;
  	if ((server->sec_mode & SECMODE_USER) == 0)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
597
598
  		cifs_dbg(FYI, "share mode security
  ");
bdc4bf6e8   Steve French   [CIFS] Support fo...
599

254e55ed0   Steve French   CIFS] Support for...
600
601
  	/* one byte, so no need to convert this or EncryptionKeyLen from
  	   little endian */
10b9b98e4   Pavel Shilovsky   CIFS: Respect neg...
602
603
  	server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
  			       cifs_max_pending);
452757897   Pavel Shilovsky   CIFS: Move add/se...
604
  	set_credits(server, server->maxReq);
254e55ed0   Steve French   CIFS] Support for...
605
  	/* probably no need to store and check maxvcs */
c974befa4   Jeff Layton   cifs: untangle se...
606
  	server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
eca6acf91   Steve French   [CIFS] Fix multiu...
607
  	server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
608
609
  	cifs_dbg(NOISY, "Max buf = %d
  ", ses->server->maxBuf);
254e55ed0   Steve French   CIFS] Support for...
610
  	server->capabilities = le32_to_cpu(pSMBr->Capabilities);
b815f1e55   Steve French   [CIFS] Allow for ...
611
612
  	server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
  	server->timeAdj *= 60;
31d9e2bd5   Jeff Layton   cifs: break out d...
613

e598d1d8f   Jeff Layton   cifs: track the f...
614
615
  	if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
  		server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
d3ba50b17   Shirish Pargaonkar   NTLM auth and sig...
616
  		memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
254e55ed0   Steve French   CIFS] Support for...
617
  		       CIFS_CRYPTO_KEY_SIZE);
f291095f3   Noel Power   client MUST ignor...
618
619
  	} else if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
  			server->capabilities & CAP_EXTENDED_SECURITY) {
e598d1d8f   Jeff Layton   cifs: track the f...
620
  		server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
3f618223d   Jeff Layton   move sectype to t...
621
  		rc = decode_ext_sec_blob(ses, pSMBr);
e598d1d8f   Jeff Layton   cifs: track the f...
622
  	} else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
07cc6cf9e   Steve French   Fix extended secu...
623
  		rc = -EIO; /* no crypt key only if plain text pwd */
e598d1d8f   Jeff Layton   cifs: track the f...
624
625
  	} else {
  		server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
254e55ed0   Steve French   CIFS] Support for...
626
  		server->capabilities &= ~CAP_EXTENDED_SECURITY;
e598d1d8f   Jeff Layton   cifs: track the f...
627
  	}
254e55ed0   Steve French   CIFS] Support for...
628
629
  
  signing_check:
9ddec5613   Jeff Layton   cifs: move handli...
630
  	if (!rc)
38d77c50b   Jeff Layton   cifs: track the e...
631
  		rc = cifs_enable_signing(server, ses->sign);
50c2f7538   Steve French   [CIFS] whitespace...
632
  neg_err_exit:
4a6d87f1d   Steve French   [CIFS] Add missin...
633
  	cifs_buf_release(pSMB);
254e55ed0   Steve French   CIFS] Support for...
634

f96637be0   Joe Perches   [CIFS] cifs: Rena...
635
636
  	cifs_dbg(FYI, "negprot rc %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
637
638
639
640
  	return rc;
  }
  
  int
2e6e02ab6   Pavel Shilovsky   CIFS: Move protoc...
641
  CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
642
643
  {
  	struct smb_hdr *smb_buffer;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
644
  	int rc = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
645

f96637be0   Joe Perches   [CIFS] cifs: Rena...
646
647
  	cifs_dbg(FYI, "In tree disconnect
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
648

f1987b44f   Jeff Layton   cifs: reinstate s...
649
650
651
  	/* BB: do we need to check this? These should never be NULL. */
  	if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
  		return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
652

f1987b44f   Jeff Layton   cifs: reinstate s...
653
654
655
656
657
658
  	/*
  	 * No need to return error on this operation if tid invalidated and
  	 * closed on server already e.g. due to tcp session crashing. Also,
  	 * the tcon is no longer on the list, so no need to take lock before
  	 * checking this.
  	 */
268875b9d   Steve French   [CIFS] Do not sen...
659
  	if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
50c2f7538   Steve French   [CIFS] whitespace...
660
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
661

50c2f7538   Steve French   [CIFS] whitespace...
662
  	rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
09d1db5c6   Steve French   [PATCH] cifs: imp...
663
  			    (void **)&smb_buffer);
f1987b44f   Jeff Layton   cifs: reinstate s...
664
  	if (rc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
665
  		return rc;
133672efb   Steve French   [CIFS] Fix buffer...
666

792af7b05   Pavel Shilovsky   CIFS: Separate pr...
667
  	rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
668
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
669
670
  		cifs_dbg(FYI, "Tree disconnect failed %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
671

50c2f7538   Steve French   [CIFS] whitespace...
672
  	/* No need to return error on this operation if tid invalidated and
f1987b44f   Jeff Layton   cifs: reinstate s...
673
  	   closed on server already e.g. due to tcp session crashing */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
674
675
676
677
678
  	if (rc == -EAGAIN)
  		rc = 0;
  
  	return rc;
  }
766fdbb57   Jeff Layton   cifs: add ability...
679
680
681
682
683
684
685
686
687
688
689
  /*
   * This is a no-op for now. We're not really interested in the reply, but
   * rather in the fact that the server sent one and that server->lstrp
   * gets updated.
   *
   * FIXME: maybe we should consider checking that the reply matches request?
   */
  static void
  cifs_echo_callback(struct mid_q_entry *mid)
  {
  	struct TCP_Server_Info *server = mid->callback_data;
5fb4e288a   Christopher Oo   cifs: Fix use-aft...
690
  	mutex_lock(&server->srv_mutex);
766fdbb57   Jeff Layton   cifs: add ability...
691
  	DeleteMidQEntry(mid);
5fb4e288a   Christopher Oo   cifs: Fix use-aft...
692
  	mutex_unlock(&server->srv_mutex);
a891f0f89   Pavel Shilovsky   CIFS: Extend cred...
693
  	add_credits(server, 1, CIFS_ECHO_OP);
766fdbb57   Jeff Layton   cifs: add ability...
694
695
696
697
698
699
700
  }
  
  int
  CIFSSMBEcho(struct TCP_Server_Info *server)
  {
  	ECHO_REQ *smb;
  	int rc = 0;
fcc31cb6f   Jeff Layton   cifs: make cifs_s...
701
  	struct kvec iov;
fec344e3f   Jeff Layton   cifs: change cifs...
702
703
  	struct smb_rqst rqst = { .rq_iov = &iov,
  				 .rq_nvec = 1 };
766fdbb57   Jeff Layton   cifs: add ability...
704

f96637be0   Joe Perches   [CIFS] cifs: Rena...
705
706
  	cifs_dbg(FYI, "In echo request
  ");
766fdbb57   Jeff Layton   cifs: add ability...
707
708
709
710
711
712
  
  	rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
  	if (rc)
  		return rc;
  
  	/* set up echo request */
5443d130a   Steve French   various endian fi...
713
  	smb->hdr.Tid = 0xffff;
99d86c8f1   Jeff Layton   cifs: fix up CIFS...
714
715
  	smb->hdr.WordCount = 1;
  	put_unaligned_le16(1, &smb->EchoCount);
820a803ff   Jeff Layton   cifs: keep BCC in...
716
  	put_bcc(1, &smb->hdr);
766fdbb57   Jeff Layton   cifs: add ability...
717
  	smb->Data[0] = 'a';
be8e3b004   Steve French   consistently use ...
718
  	inc_rfc1001_len(smb, 3);
fcc31cb6f   Jeff Layton   cifs: make cifs_s...
719
720
  	iov.iov_base = smb;
  	iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
766fdbb57   Jeff Layton   cifs: add ability...
721

fec344e3f   Jeff Layton   cifs: change cifs...
722
  	rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback,
a891f0f89   Pavel Shilovsky   CIFS: Extend cred...
723
  			     server, CIFS_ASYNC_OP | CIFS_ECHO_OP);
766fdbb57   Jeff Layton   cifs: add ability...
724
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
725
726
  		cifs_dbg(FYI, "Echo request failed: %d
  ", rc);
766fdbb57   Jeff Layton   cifs: add ability...
727
728
729
730
731
  
  	cifs_small_buf_release(smb);
  
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
732
  int
58c45c58a   Pavel Shilovsky   CIFS: Move protoc...
733
  CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
734
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
735
736
  	LOGOFF_ANDX_REQ *pSMB;
  	int rc = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
737

f96637be0   Joe Perches   [CIFS] cifs: Rena...
738
739
  	cifs_dbg(FYI, "In SMBLogoff for session disconnect
  ");
3b7952109   Steve French   [CIFS] Fix cifs r...
740

14fbf50d6   Jeff Layton   cifs: reinstate s...
741
742
743
744
745
746
  	/*
  	 * BB: do we need to check validity of ses and server? They should
  	 * always be valid since we have an active reference. If not, that
  	 * should probably be a BUG()
  	 */
  	if (!ses || !ses->server)
3b7952109   Steve French   [CIFS] Fix cifs r...
747
  		return -EIO;
d7b619cf5   Steve French   [CIFS] pSesInfo->...
748
  	mutex_lock(&ses->session_mutex);
3b7952109   Steve French   [CIFS] Fix cifs r...
749
750
751
  	if (ses->need_reconnect)
  		goto session_already_dead; /* no need to send SMBlogoff if uid
  					      already closed due to reconnect */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
752
753
  	rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
  	if (rc) {
d7b619cf5   Steve French   [CIFS] pSesInfo->...
754
  		mutex_unlock(&ses->session_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
755
756
  		return rc;
  	}
882573606   Pavel Shilovsky   CIFS: Move get_ne...
757
  	pSMB->hdr.Mid = get_next_mid(ses->server);
1982c344f   Steve French   [CIFS] Ensure tha...
758

38d77c50b   Jeff Layton   cifs: track the e...
759
760
  	if (ses->server->sign)
  		pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
761
762
763
764
  
  	pSMB->hdr.Uid = ses->Suid;
  
  	pSMB->AndXCommand = 0xFF;
792af7b05   Pavel Shilovsky   CIFS: Separate pr...
765
  	rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, 0);
3b7952109   Steve French   [CIFS] Fix cifs r...
766
  session_already_dead:
d7b619cf5   Steve French   [CIFS] pSesInfo->...
767
  	mutex_unlock(&ses->session_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
768
769
  
  	/* if session dead then we do not need to do ulogoff,
50c2f7538   Steve French   [CIFS] whitespace...
770
  		since server closed smb session, no sense reporting
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
771
772
773
774
775
776
777
  		error */
  	if (rc == -EAGAIN)
  		rc = 0;
  	return rc;
  }
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
778
779
780
  CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
  		 const char *fileName, __u16 type,
  		 const struct nls_table *nls_codepage, int remap)
2d785a50a   Steve French   [CIFS] Add suppor...
781
782
783
784
785
786
787
788
  {
  	TRANSACTION2_SPI_REQ *pSMB = NULL;
  	TRANSACTION2_SPI_RSP *pSMBr = NULL;
  	struct unlink_psx_rq *pRqD;
  	int name_len;
  	int rc = 0;
  	int bytes_returned = 0;
  	__u16 params, param_offset, offset, byte_count;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
789
790
  	cifs_dbg(FYI, "In POSIX delete
  ");
2d785a50a   Steve French   [CIFS] Add suppor...
791
792
793
794
795
796
797
798
  PsxDelete:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		name_len =
acbbb76a2   Steve French   CIFS: Rename *UCS...
799
800
  		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
  				       PATH_MAX, nls_codepage, remap);
2d785a50a   Steve French   [CIFS] Add suppor...
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
  		name_len++;	/* trailing null */
  		name_len *= 2;
  	} else { /* BB add path length overrun check */
  		name_len = strnlen(fileName, PATH_MAX);
  		name_len++;	/* trailing null */
  		strncpy(pSMB->FileName, fileName, name_len);
  	}
  
  	params = 6 + name_len;
  	pSMB->MaxParameterCount = cpu_to_le16(2);
  	pSMB->MaxDataCount = 0; /* BB double check this with jra */
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  	pSMB->Flags = 0;
  	pSMB->Timeout = 0;
  	pSMB->Reserved2 = 0;
  	param_offset = offsetof(struct smb_com_transaction2_spi_req,
  				InformationLevel) - 4;
  	offset = param_offset + params;
  
  	/* Setup pointer to Request Data (inode type) */
  	pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
  	pRqD->type = cpu_to_le16(type);
  	pSMB->ParameterOffset = cpu_to_le16(param_offset);
  	pSMB->DataOffset = cpu_to_le16(offset);
  	pSMB->SetupCount = 1;
  	pSMB->Reserved3 = 0;
  	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
  	byte_count = 3 /* pad */  + params + sizeof(struct unlink_psx_rq);
  
  	pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
  	pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
  	pSMB->ParameterCount = cpu_to_le16(params);
  	pSMB->TotalParameterCount = pSMB->ParameterCount;
  	pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
  	pSMB->Reserved4 = 0;
be8e3b004   Steve French   consistently use ...
837
  	inc_rfc1001_len(pSMB, byte_count);
2d785a50a   Steve French   [CIFS] Add suppor...
838
839
840
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
ad7a2926b   Steve French   [CIFS] reduce che...
841
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
842
843
  		cifs_dbg(FYI, "Posix delete returned %d
  ", rc);
2d785a50a   Steve French   [CIFS] Add suppor...
844
  	cifs_buf_release(pSMB);
44c581866   Pavel Shilovsky   CIFS: Move clear/...
845
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
2d785a50a   Steve French   [CIFS] Add suppor...
846
847
848
849
850
851
852
853
  
  	if (rc == -EAGAIN)
  		goto PsxDelete;
  
  	return rc;
  }
  
  int
ed6875e0d   Pavel Shilovsky   CIFS: Move unlink...
854
855
  CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
  	       struct cifs_sb_info *cifs_sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
856
857
858
859
860
861
  {
  	DELETE_FILE_REQ *pSMB = NULL;
  	DELETE_FILE_RSP *pSMBr = NULL;
  	int rc = 0;
  	int bytes_returned;
  	int name_len;
2baa26825   Steve French   Remap reserved po...
862
  	int remap = cifs_remap(cifs_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
863
864
865
866
867
868
869
870
  
  DelFileRetry:
  	rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
ed6875e0d   Pavel Shilovsky   CIFS: Move unlink...
871
872
873
  		name_len = cifsConvertToUTF16((__le16 *) pSMB->fileName, name,
  					      PATH_MAX, cifs_sb->local_nls,
  					      remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
874
875
  		name_len++;	/* trailing null */
  		name_len *= 2;
09d1db5c6   Steve French   [PATCH] cifs: imp...
876
  	} else {		/* BB improve check for buffer overruns BB */
ed6875e0d   Pavel Shilovsky   CIFS: Move unlink...
877
  		name_len = strnlen(name, PATH_MAX);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
878
  		name_len++;	/* trailing null */
ed6875e0d   Pavel Shilovsky   CIFS: Move unlink...
879
  		strncpy(pSMB->fileName, name, name_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
880
881
882
883
  	}
  	pSMB->SearchAttributes =
  	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
  	pSMB->BufferFormat = 0x04;
be8e3b004   Steve French   consistently use ...
884
  	inc_rfc1001_len(pSMB, name_len + 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
885
886
887
  	pSMB->ByteCount = cpu_to_le16(name_len + 1);
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
44c581866   Pavel Shilovsky   CIFS: Move clear/...
888
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
ad7a2926b   Steve French   [CIFS] reduce che...
889
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
890
891
  		cifs_dbg(FYI, "Error in RMFile = %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
892
893
894
895
896
897
898
899
900
  
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto DelFileRetry;
  
  	return rc;
  }
  
  int
f958ca5d8   Pavel Shilovsky   CIFS: Move rmdir ...
901
902
  CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
  	     struct cifs_sb_info *cifs_sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
903
904
905
906
907
908
  {
  	DELETE_DIRECTORY_REQ *pSMB = NULL;
  	DELETE_DIRECTORY_RSP *pSMBr = NULL;
  	int rc = 0;
  	int bytes_returned;
  	int name_len;
2baa26825   Steve French   Remap reserved po...
909
  	int remap = cifs_remap(cifs_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
910

f96637be0   Joe Perches   [CIFS] cifs: Rena...
911
912
  	cifs_dbg(FYI, "In CIFSSMBRmDir
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
913
914
915
916
917
918
919
  RmDirRetry:
  	rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
f958ca5d8   Pavel Shilovsky   CIFS: Move rmdir ...
920
921
922
  		name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
  					      PATH_MAX, cifs_sb->local_nls,
  					      remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
923
924
  		name_len++;	/* trailing null */
  		name_len *= 2;
09d1db5c6   Steve French   [PATCH] cifs: imp...
925
  	} else {		/* BB improve check for buffer overruns BB */
f958ca5d8   Pavel Shilovsky   CIFS: Move rmdir ...
926
  		name_len = strnlen(name, PATH_MAX);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
927
  		name_len++;	/* trailing null */
f958ca5d8   Pavel Shilovsky   CIFS: Move rmdir ...
928
  		strncpy(pSMB->DirName, name, name_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
929
930
931
  	}
  
  	pSMB->BufferFormat = 0x04;
be8e3b004   Steve French   consistently use ...
932
  	inc_rfc1001_len(pSMB, name_len + 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
933
934
935
  	pSMB->ByteCount = cpu_to_le16(name_len + 1);
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
44c581866   Pavel Shilovsky   CIFS: Move clear/...
936
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_rmdirs);
ad7a2926b   Steve French   [CIFS] reduce che...
937
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
938
939
  		cifs_dbg(FYI, "Error in RMDir = %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
940
941
942
943
944
945
946
947
  
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto RmDirRetry;
  	return rc;
  }
  
  int
f436720e9   Pavel Shilovsky   CIFS: Separate pr...
948
949
  CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
  	     struct cifs_sb_info *cifs_sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
950
951
952
953
954
955
  {
  	int rc = 0;
  	CREATE_DIRECTORY_REQ *pSMB = NULL;
  	CREATE_DIRECTORY_RSP *pSMBr = NULL;
  	int bytes_returned;
  	int name_len;
2baa26825   Steve French   Remap reserved po...
956
  	int remap = cifs_remap(cifs_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
957

f96637be0   Joe Perches   [CIFS] cifs: Rena...
958
959
  	cifs_dbg(FYI, "In CIFSSMBMkDir
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
960
961
962
963
964
965
966
  MkDirRetry:
  	rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
acbbb76a2   Steve French   CIFS: Rename *UCS...
967
  		name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
f436720e9   Pavel Shilovsky   CIFS: Separate pr...
968
969
  					      PATH_MAX, cifs_sb->local_nls,
  					      remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
970
971
  		name_len++;	/* trailing null */
  		name_len *= 2;
09d1db5c6   Steve French   [PATCH] cifs: imp...
972
  	} else {		/* BB improve check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
973
974
975
976
977
978
  		name_len = strnlen(name, PATH_MAX);
  		name_len++;	/* trailing null */
  		strncpy(pSMB->DirName, name, name_len);
  	}
  
  	pSMB->BufferFormat = 0x04;
be8e3b004   Steve French   consistently use ...
979
  	inc_rfc1001_len(pSMB, name_len + 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
980
981
982
  	pSMB->ByteCount = cpu_to_le16(name_len + 1);
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
44c581866   Pavel Shilovsky   CIFS: Move clear/...
983
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_mkdirs);
ad7a2926b   Steve French   [CIFS] reduce che...
984
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
985
986
  		cifs_dbg(FYI, "Error in Mkdir = %d
  ", rc);
a5a2b489b   Steve French   [CIFS] Make CIFS ...
987

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
988
989
990
991
992
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto MkDirRetry;
  	return rc;
  }
2dd29d313   Steve French   [CIFS] New CIFS P...
993
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
994
995
996
997
998
  CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon,
  		__u32 posix_flags, __u64 mode, __u16 *netfid,
  		FILE_UNIX_BASIC_INFO *pRetData, __u32 *pOplock,
  		const char *name, const struct nls_table *nls_codepage,
  		int remap)
2dd29d313   Steve French   [CIFS] New CIFS P...
999
1000
1001
1002
1003
1004
  {
  	TRANSACTION2_SPI_REQ *pSMB = NULL;
  	TRANSACTION2_SPI_RSP *pSMBr = NULL;
  	int name_len;
  	int rc = 0;
  	int bytes_returned = 0;
2dd29d313   Steve French   [CIFS] New CIFS P...
1005
  	__u16 params, param_offset, offset, byte_count, count;
ad7a2926b   Steve French   [CIFS] reduce che...
1006
1007
  	OPEN_PSX_REQ *pdata;
  	OPEN_PSX_RSP *psx_rsp;
2dd29d313   Steve French   [CIFS] New CIFS P...
1008

f96637be0   Joe Perches   [CIFS] cifs: Rena...
1009
1010
  	cifs_dbg(FYI, "In POSIX Create
  ");
2dd29d313   Steve French   [CIFS] New CIFS P...
1011
1012
1013
1014
1015
1016
1017
1018
  PsxCreat:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		name_len =
acbbb76a2   Steve French   CIFS: Rename *UCS...
1019
1020
  		    cifsConvertToUTF16((__le16 *) pSMB->FileName, name,
  				       PATH_MAX, nls_codepage, remap);
2dd29d313   Steve French   [CIFS] New CIFS P...
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
  		name_len++;	/* trailing null */
  		name_len *= 2;
  	} else {	/* BB improve the check for buffer overruns BB */
  		name_len = strnlen(name, PATH_MAX);
  		name_len++;	/* trailing null */
  		strncpy(pSMB->FileName, name, name_len);
  	}
  
  	params = 6 + name_len;
  	count = sizeof(OPEN_PSX_REQ);
  	pSMB->MaxParameterCount = cpu_to_le16(2);
  	pSMB->MaxDataCount = cpu_to_le16(1000);	/* large enough */
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  	pSMB->Flags = 0;
  	pSMB->Timeout = 0;
  	pSMB->Reserved2 = 0;
  	param_offset = offsetof(struct smb_com_transaction2_spi_req,
50c2f7538   Steve French   [CIFS] whitespace...
1039
  				InformationLevel) - 4;
2dd29d313   Steve French   [CIFS] New CIFS P...
1040
  	offset = param_offset + params;
2dd29d313   Steve French   [CIFS] New CIFS P...
1041
  	pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
8f2376adf   Cyril Gorcunov   [CIFS] Fix endian...
1042
  	pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
2dd29d313   Steve French   [CIFS] New CIFS P...
1043
  	pdata->Permissions = cpu_to_le64(mode);
50c2f7538   Steve French   [CIFS] whitespace...
1044
  	pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
2dd29d313   Steve French   [CIFS] New CIFS P...
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
  	pdata->OpenFlags =  cpu_to_le32(*pOplock);
  	pSMB->ParameterOffset = cpu_to_le16(param_offset);
  	pSMB->DataOffset = cpu_to_le16(offset);
  	pSMB->SetupCount = 1;
  	pSMB->Reserved3 = 0;
  	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
  	byte_count = 3 /* pad */  + params + count;
  
  	pSMB->DataCount = cpu_to_le16(count);
  	pSMB->ParameterCount = cpu_to_le16(params);
  	pSMB->TotalDataCount = pSMB->DataCount;
  	pSMB->TotalParameterCount = pSMB->ParameterCount;
  	pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
  	pSMB->Reserved4 = 0;
be8e3b004   Steve French   consistently use ...
1059
  	inc_rfc1001_len(pSMB, byte_count);
2dd29d313   Steve French   [CIFS] New CIFS P...
1060
1061
1062
1063
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1064
1065
  		cifs_dbg(FYI, "Posix create returned %d
  ", rc);
2dd29d313   Steve French   [CIFS] New CIFS P...
1066
1067
  		goto psx_create_err;
  	}
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1068
1069
  	cifs_dbg(FYI, "copying inode info
  ");
2dd29d313   Steve French   [CIFS] New CIFS P...
1070
  	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
820a803ff   Jeff Layton   cifs: keep BCC in...
1071
  	if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
2dd29d313   Steve French   [CIFS] New CIFS P...
1072
1073
1074
1075
1076
  		rc = -EIO;	/* bad smb */
  		goto psx_create_err;
  	}
  
  	/* copy return information to pRetData */
50c2f7538   Steve French   [CIFS] whitespace...
1077
  	psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
2dd29d313   Steve French   [CIFS] New CIFS P...
1078
  			+ le16_to_cpu(pSMBr->t2.DataOffset));
50c2f7538   Steve French   [CIFS] whitespace...
1079

2dd29d313   Steve French   [CIFS] New CIFS P...
1080
  	*pOplock = le16_to_cpu(psx_rsp->OplockFlags);
790fe579f   Steve French   [CIFS] more white...
1081
  	if (netfid)
2dd29d313   Steve French   [CIFS] New CIFS P...
1082
1083
1084
  		*netfid = psx_rsp->Fid;   /* cifs fid stays in le */
  	/* Let caller know file was created so we can set the mode. */
  	/* Do we care about the CreateAction in any other cases? */
790fe579f   Steve French   [CIFS] more white...
1085
  	if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
2dd29d313   Steve French   [CIFS] New CIFS P...
1086
1087
  		*pOplock |= CIFS_CREATE_ACTION;
  	/* check to make sure response data is there */
8f2376adf   Cyril Gorcunov   [CIFS] Fix endian...
1088
1089
  	if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
  		pRetData->Type = cpu_to_le32(-1); /* unknown */
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1090
1091
  		cifs_dbg(NOISY, "unknown type
  ");
cbac3cba6   Steve French   [CIFS] New CIFS P...
1092
  	} else {
820a803ff   Jeff Layton   cifs: keep BCC in...
1093
  		if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
2dd29d313   Steve French   [CIFS] New CIFS P...
1094
  					+ sizeof(FILE_UNIX_BASIC_INFO)) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1095
1096
  			cifs_dbg(VFS, "Open response data too small
  ");
8f2376adf   Cyril Gorcunov   [CIFS] Fix endian...
1097
  			pRetData->Type = cpu_to_le32(-1);
2dd29d313   Steve French   [CIFS] New CIFS P...
1098
1099
  			goto psx_create_err;
  		}
50c2f7538   Steve French   [CIFS] whitespace...
1100
  		memcpy((char *) pRetData,
cbac3cba6   Steve French   [CIFS] New CIFS P...
1101
  			(char *)psx_rsp + sizeof(OPEN_PSX_RSP),
26f57364d   Steve French   [CIFS] formatting...
1102
  			sizeof(FILE_UNIX_BASIC_INFO));
2dd29d313   Steve French   [CIFS] New CIFS P...
1103
  	}
2dd29d313   Steve French   [CIFS] New CIFS P...
1104
1105
1106
  
  psx_create_err:
  	cifs_buf_release(pSMB);
65bc98b00   Steve French   [CIFS] Distinguis...
1107
  	if (posix_flags & SMB_O_DIRECTORY)
44c581866   Pavel Shilovsky   CIFS: Move clear/...
1108
  		cifs_stats_inc(&tcon->stats.cifs_stats.num_posixmkdirs);
65bc98b00   Steve French   [CIFS] Distinguis...
1109
  	else
44c581866   Pavel Shilovsky   CIFS: Move clear/...
1110
  		cifs_stats_inc(&tcon->stats.cifs_stats.num_posixopens);
2dd29d313   Steve French   [CIFS] New CIFS P...
1111
1112
1113
  
  	if (rc == -EAGAIN)
  		goto PsxCreat;
50c2f7538   Steve French   [CIFS] whitespace...
1114
  	return rc;
2dd29d313   Steve French   [CIFS] New CIFS P...
1115
  }
a9d02ad49   Steve French   [CIFS] Support fo...
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
  static __u16 convert_disposition(int disposition)
  {
  	__u16 ofun = 0;
  
  	switch (disposition) {
  		case FILE_SUPERSEDE:
  			ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
  			break;
  		case FILE_OPEN:
  			ofun = SMBOPEN_OAPPEND;
  			break;
  		case FILE_CREATE:
  			ofun = SMBOPEN_OCREATE;
  			break;
  		case FILE_OPEN_IF:
  			ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
  			break;
  		case FILE_OVERWRITE:
  			ofun = SMBOPEN_OTRUNC;
  			break;
  		case FILE_OVERWRITE_IF:
  			ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
  			break;
  		default:
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1140
1141
  			cifs_dbg(FYI, "unknown disposition %d
  ", disposition);
a9d02ad49   Steve French   [CIFS] Support fo...
1142
1143
1144
1145
  			ofun =  SMBOPEN_OAPPEND; /* regular open */
  	}
  	return ofun;
  }
35fc37d51   Jeff Layton   add function to c...
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
  static int
  access_flags_to_smbopen_mode(const int access_flags)
  {
  	int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
  
  	if (masked_flags == GENERIC_READ)
  		return SMBOPEN_READ;
  	else if (masked_flags == GENERIC_WRITE)
  		return SMBOPEN_WRITE;
  
  	/* just go for read/write */
  	return SMBOPEN_READWRITE;
  }
a9d02ad49   Steve French   [CIFS] Support fo...
1159
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1160
  SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
a9d02ad49   Steve French   [CIFS] Support fo...
1161
  	    const char *fileName, const int openDisposition,
ad7a2926b   Steve French   [CIFS] reduce che...
1162
1163
  	    const int access_flags, const int create_options, __u16 *netfid,
  	    int *pOplock, FILE_ALL_INFO *pfile_info,
a9d02ad49   Steve French   [CIFS] Support fo...
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
  	    const struct nls_table *nls_codepage, int remap)
  {
  	int rc = -EACCES;
  	OPENX_REQ *pSMB = NULL;
  	OPENX_RSP *pSMBr = NULL;
  	int bytes_returned;
  	int name_len;
  	__u16 count;
  
  OldOpenRetry:
  	rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	pSMB->AndXCommand = 0xFF;       /* none */
  
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		count = 1;      /* account for one byte pad to word boundary */
  		name_len =
acbbb76a2   Steve French   CIFS: Rename *UCS...
1184
1185
  		   cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
  				      fileName, PATH_MAX, nls_codepage, remap);
a9d02ad49   Steve French   [CIFS] Support fo...
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
  		name_len++;     /* trailing null */
  		name_len *= 2;
  	} else {                /* BB improve check for buffer overruns BB */
  		count = 0;      /* no pad */
  		name_len = strnlen(fileName, PATH_MAX);
  		name_len++;     /* trailing null */
  		strncpy(pSMB->fileName, fileName, name_len);
  	}
  	if (*pOplock & REQ_OPLOCK)
  		pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
26f57364d   Steve French   [CIFS] formatting...
1196
  	else if (*pOplock & REQ_BATCHOPLOCK)
a9d02ad49   Steve French   [CIFS] Support fo...
1197
  		pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
26f57364d   Steve French   [CIFS] formatting...
1198

a9d02ad49   Steve French   [CIFS] Support fo...
1199
  	pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
35fc37d51   Jeff Layton   add function to c...
1200
  	pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
a9d02ad49   Steve French   [CIFS] Support fo...
1201
1202
1203
1204
  	pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
  	/* set file as system file if special file such
  	   as fifo and server expecting SFU style and
  	   no Unix extensions */
790fe579f   Steve French   [CIFS] more white...
1205
1206
  	if (create_options & CREATE_OPTION_SPECIAL)
  		pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
ad7a2926b   Steve French   [CIFS] reduce che...
1207
1208
  	else /* BB FIXME BB */
  		pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
a9d02ad49   Steve French   [CIFS] Support fo...
1209

67750fb9e   Jeff Layton   [CIFS] when not u...
1210
1211
  	if (create_options & CREATE_OPTION_READONLY)
  		pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
a9d02ad49   Steve French   [CIFS] Support fo...
1212
1213
  
  	/* BB FIXME BB */
50c2f7538   Steve French   [CIFS] whitespace...
1214
1215
  /*	pSMB->CreateOptions = cpu_to_le32(create_options &
  						 CREATE_OPTIONS_MASK); */
a9d02ad49   Steve French   [CIFS] Support fo...
1216
  	/* BB FIXME END BB */
3e87d8039   Steve French   [CIFS] Add suppor...
1217
1218
  
  	pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
70ca734a1   Steve French   [CIFS] Various mi...
1219
  	pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
a9d02ad49   Steve French   [CIFS] Support fo...
1220
  	count += name_len;
be8e3b004   Steve French   consistently use ...
1221
  	inc_rfc1001_len(pSMB, count);
a9d02ad49   Steve French   [CIFS] Support fo...
1222
1223
1224
1225
  
  	pSMB->ByteCount = cpu_to_le16(count);
  	/* long_op set to 1 to allow for oplock break timeouts */
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7749981ec   Jeff Layton   cifs: remove code...
1226
  			(struct smb_hdr *)pSMBr, &bytes_returned, 0);
44c581866   Pavel Shilovsky   CIFS: Move clear/...
1227
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
a9d02ad49   Steve French   [CIFS] Support fo...
1228
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1229
1230
  		cifs_dbg(FYI, "Error in Open = %d
  ", rc);
a9d02ad49   Steve French   [CIFS] Support fo...
1231
1232
  	} else {
  	/* BB verify if wct == 15 */
582d21e5e   Steve French   [CIFS] cleanup ol...
1233
  /*		*pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
a9d02ad49   Steve French   [CIFS] Support fo...
1234
1235
1236
1237
1238
  
  		*netfid = pSMBr->Fid;   /* cifs fid stays in le */
  		/* Let caller know file was created so we can set the mode. */
  		/* Do we care about the CreateAction in any other cases? */
  	/* BB FIXME BB */
790fe579f   Steve French   [CIFS] more white...
1239
  /*		if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
a9d02ad49   Steve French   [CIFS] Support fo...
1240
1241
  			*pOplock |= CIFS_CREATE_ACTION; */
  	/* BB FIXME END */
790fe579f   Steve French   [CIFS] more white...
1242
  		if (pfile_info) {
a9d02ad49   Steve French   [CIFS] Support fo...
1243
1244
1245
1246
  			pfile_info->CreationTime = 0; /* BB convert CreateTime*/
  			pfile_info->LastAccessTime = 0; /* BB fixme */
  			pfile_info->LastWriteTime = 0; /* BB fixme */
  			pfile_info->ChangeTime = 0;  /* BB fixme */
70ca734a1   Steve French   [CIFS] Various mi...
1247
  			pfile_info->Attributes =
50c2f7538   Steve French   [CIFS] whitespace...
1248
  				cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
a9d02ad49   Steve French   [CIFS] Support fo...
1249
  			/* the file_info buf is endian converted by caller */
70ca734a1   Steve French   [CIFS] Various mi...
1250
1251
1252
  			pfile_info->AllocationSize =
  				cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
  			pfile_info->EndOfFile = pfile_info->AllocationSize;
a9d02ad49   Steve French   [CIFS] Support fo...
1253
  			pfile_info->NumberOfLinks = cpu_to_le32(1);
9a8165fce   Jeff Layton   cifs: track Delet...
1254
  			pfile_info->DeletePending = 0;
a9d02ad49   Steve French   [CIFS] Support fo...
1255
1256
1257
1258
1259
1260
1261
1262
  		}
  	}
  
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto OldOpenRetry;
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1263
  int
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1264
1265
  CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,
  	  FILE_ALL_INFO *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1266
1267
  {
  	int rc = -EACCES;
9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1268
1269
  	OPEN_REQ *req = NULL;
  	OPEN_RSP *rsp = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1270
1271
1272
  	int bytes_returned;
  	int name_len;
  	__u16 count;
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1273
1274
  	struct cifs_sb_info *cifs_sb = oparms->cifs_sb;
  	struct cifs_tcon *tcon = oparms->tcon;
2baa26825   Steve French   Remap reserved po...
1275
  	int remap = cifs_remap(cifs_sb);
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1276
1277
1278
1279
1280
  	const struct nls_table *nls = cifs_sb->local_nls;
  	int create_options = oparms->create_options;
  	int desired_access = oparms->desired_access;
  	int disposition = oparms->disposition;
  	const char *path = oparms->path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1281
1282
  
  openRetry:
9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1283
1284
  	rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **)&req,
  		      (void **)&rsp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1285
1286
  	if (rc)
  		return rc;
9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1287
1288
  	/* no commands go after this */
  	req->AndXCommand = 0xFF;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1289

9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1290
1291
1292
1293
1294
1295
1296
  	if (req->hdr.Flags2 & SMBFLG2_UNICODE) {
  		/* account for one byte pad to word boundary */
  		count = 1;
  		name_len = cifsConvertToUTF16((__le16 *)(req->fileName + 1),
  					      path, PATH_MAX, nls, remap);
  		/* trailing null */
  		name_len++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1297
  		name_len *= 2;
9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
  		req->NameLength = cpu_to_le16(name_len);
  	} else {
  		/* BB improve check for buffer overruns BB */
  		/* no pad */
  		count = 0;
  		name_len = strnlen(path, PATH_MAX);
  		/* trailing null */
  		name_len++;
  		req->NameLength = cpu_to_le16(name_len);
  		strncpy(req->fileName, path, name_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1308
  	}
9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
  
  	if (*oplock & REQ_OPLOCK)
  		req->OpenFlags = cpu_to_le32(REQ_OPLOCK);
  	else if (*oplock & REQ_BATCHOPLOCK)
  		req->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
  
  	req->DesiredAccess = cpu_to_le32(desired_access);
  	req->AllocationSize = 0;
  
  	/*
  	 * Set file as system file if special file such as fifo and server
  	 * expecting SFU style and no Unix extensions.
  	 */
790fe579f   Steve French   [CIFS] more white...
1322
  	if (create_options & CREATE_OPTION_SPECIAL)
9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1323
  		req->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
eda3c0298   Steve French   [CIFS] Add compat...
1324
  	else
9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1325
  		req->FileAttributes = cpu_to_le32(ATTR_NORMAL);
67750fb9e   Jeff Layton   [CIFS] when not u...
1326

9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1327
1328
1329
1330
  	/*
  	 * XP does not handle ATTR_POSIX_SEMANTICS but it helps speed up case
  	 * sensitive checks for other servers such as Samba.
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1331
  	if (tcon->ses->capabilities & CAP_UNIX)
9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1332
  		req->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1333

67750fb9e   Jeff Layton   [CIFS] when not u...
1334
  	if (create_options & CREATE_OPTION_READONLY)
9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1335
1336
1337
1338
1339
  		req->FileAttributes |= cpu_to_le32(ATTR_READONLY);
  
  	req->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
  	req->CreateDisposition = cpu_to_le32(disposition);
  	req->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
67750fb9e   Jeff Layton   [CIFS] when not u...
1340

09d1db5c6   Steve French   [PATCH] cifs: imp...
1341
  	/* BB Expirement with various impersonation levels and verify */
9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1342
1343
  	req->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
  	req->SecurityFlags = SECURITY_CONTEXT_TRACKING|SECURITY_EFFECTIVE_ONLY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1344
1345
  
  	count += name_len;
9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1346
  	inc_rfc1001_len(req, count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1347

9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1348
1349
1350
  	req->ByteCount = cpu_to_le16(count);
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)req,
  			 (struct smb_hdr *)rsp, &bytes_returned, 0);
44c581866   Pavel Shilovsky   CIFS: Move clear/...
1351
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1352
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1353
1354
  		cifs_dbg(FYI, "Error in Open = %d
  ", rc);
9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1355
1356
1357
1358
  		cifs_buf_release(req);
  		if (rc == -EAGAIN)
  			goto openRetry;
  		return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1359
  	}
a5a2b489b   Steve French   [CIFS] Make CIFS ...
1360

9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1361
1362
1363
  	/* 1 byte no need to le_to_cpu */
  	*oplock = rsp->OplockLevel;
  	/* cifs fid stays in le */
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1364
  	oparms->fid->netfid = rsp->Fid;
9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
  
  	/* Let caller know file was created so we can set the mode. */
  	/* Do we care about the CreateAction in any other cases? */
  	if (cpu_to_le32(FILE_CREATE) == rsp->CreateAction)
  		*oplock |= CIFS_CREATE_ACTION;
  
  	if (buf) {
  		/* copy from CreationTime to Attributes */
  		memcpy((char *)buf, (char *)&rsp->CreationTime, 36);
  		/* the file_info buf is endian converted by caller */
  		buf->AllocationSize = rsp->AllocationSize;
  		buf->EndOfFile = rsp->EndOfFile;
  		buf->NumberOfLinks = cpu_to_le32(1);
  		buf->DeletePending = 0;
  	}
  
  	cifs_buf_release(req);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1382
1383
  	return rc;
  }
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1384
1385
1386
1387
1388
  /*
   * Discard any remaining data in the current SMB. To do this, we borrow the
   * current bigbuf.
   */
  static int
6cc3b2423   Pavel Shilovsky   CIFS: Fix SMB2+ i...
1389
  discard_remaining_data(struct TCP_Server_Info *server)
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1390
  {
5ffef7bf1   Pavel Shilovsky   CIFS: Separate pr...
1391
  	unsigned int rfclen = get_rfc1002_length(server->smallbuf);
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1392
  	int remaining = rfclen + 4 - server->total_read;
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1393
1394
1395
1396
1397
1398
  
  	while (remaining > 0) {
  		int length;
  
  		length = cifs_read_from_socket(server, server->bigbuf,
  				min_t(unsigned int, remaining,
1887f6010   Pavel Shilovsky   CIFS: Move header...
1399
  				    CIFSMaxBufSize + MAX_HEADER_SIZE(server)));
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1400
1401
1402
1403
1404
  		if (length < 0)
  			return length;
  		server->total_read += length;
  		remaining -= length;
  	}
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1405
1406
  	return 0;
  }
6cc3b2423   Pavel Shilovsky   CIFS: Fix SMB2+ i...
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
  static int
  cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
  {
  	int length;
  	struct cifs_readdata *rdata = mid->callback_data;
  
  	length = discard_remaining_data(server);
  	dequeue_mid(mid, rdata->result);
  	return length;
  }
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
1417
  int
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1418
1419
1420
  cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
  {
  	int length, len;
8d5ce4d23   Jeff Layton   cifs: abstract ou...
1421
  	unsigned int data_offset, data_len;
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1422
  	struct cifs_readdata *rdata = mid->callback_data;
5ffef7bf1   Pavel Shilovsky   CIFS: Separate pr...
1423
1424
  	char *buf = server->smallbuf;
  	unsigned int buflen = get_rfc1002_length(buf) + 4;
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1425

f96637be0   Joe Perches   [CIFS] cifs: Rena...
1426
1427
1428
  	cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%u
  ",
  		 __func__, mid->mid, rdata->offset, rdata->bytes);
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1429
1430
1431
1432
1433
1434
  
  	/*
  	 * read the rest of READ_RSP header (sans Data array), or whatever we
  	 * can if there's not enough data. At this point, we've read down to
  	 * the Mid.
  	 */
eb3787111   Pavel Shilovsky   CIFS: Move protoc...
1435
  	len = min_t(unsigned int, buflen, server->vals->read_rsp_size) -
1887f6010   Pavel Shilovsky   CIFS: Move header...
1436
  							HEADER_SIZE(server) + 1;
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1437

a6137305a   Al Viro   cifs_readv_receiv...
1438
1439
  	length = cifs_read_from_socket(server,
  				       buf + HEADER_SIZE(server) - 1, len);
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1440
1441
1442
  	if (length < 0)
  		return length;
  	server->total_read += length;
6cc3b2423   Pavel Shilovsky   CIFS: Fix SMB2+ i...
1443
1444
1445
1446
1447
  	if (server->ops->is_status_pending &&
  	    server->ops->is_status_pending(buf, server, 0)) {
  		discard_remaining_data(server);
  		return -1;
  	}
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1448
  	/* Was the SMB read successful? */
eb3787111   Pavel Shilovsky   CIFS: Move protoc...
1449
  	rdata->result = server->ops->map_error(buf, false);
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1450
  	if (rdata->result != 0) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1451
1452
1453
  		cifs_dbg(FYI, "%s: server returned error %d
  ",
  			 __func__, rdata->result);
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1454
1455
1456
1457
  		return cifs_readv_discard(server, mid);
  	}
  
  	/* Is there enough to get to the rest of the READ_RSP header? */
eb3787111   Pavel Shilovsky   CIFS: Move protoc...
1458
  	if (server->total_read < server->vals->read_rsp_size) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1459
1460
1461
1462
  		cifs_dbg(FYI, "%s: server returned short header. got=%u expected=%zu
  ",
  			 __func__, server->total_read,
  			 server->vals->read_rsp_size);
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1463
1464
1465
  		rdata->result = -EIO;
  		return cifs_readv_discard(server, mid);
  	}
eb3787111   Pavel Shilovsky   CIFS: Move protoc...
1466
  	data_offset = server->ops->read_data_offset(buf) + 4;
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1467
1468
1469
1470
1471
1472
  	if (data_offset < server->total_read) {
  		/*
  		 * win2k8 sometimes sends an offset of 0 when the read
  		 * is beyond the EOF. Treat it as if the data starts just after
  		 * the header.
  		 */
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1473
1474
1475
  		cifs_dbg(FYI, "%s: data offset (%u) inside read response header
  ",
  			 __func__, data_offset);
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1476
1477
1478
  		data_offset = server->total_read;
  	} else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) {
  		/* data_offset is beyond the end of smallbuf */
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1479
1480
1481
  		cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf
  ",
  			 __func__, data_offset);
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1482
1483
1484
  		rdata->result = -EIO;
  		return cifs_readv_discard(server, mid);
  	}
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1485
1486
1487
  	cifs_dbg(FYI, "%s: total_read=%u data_offset=%u
  ",
  		 __func__, server->total_read, data_offset);
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1488
1489
1490
1491
  
  	len = data_offset - server->total_read;
  	if (len > 0) {
  		/* read any junk before data into the rest of smallbuf */
a6137305a   Al Viro   cifs_readv_receiv...
1492
1493
  		length = cifs_read_from_socket(server,
  					       buf + server->total_read, len);
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1494
1495
1496
1497
1498
1499
  		if (length < 0)
  			return length;
  		server->total_read += length;
  	}
  
  	/* set up first iov for signature check */
5819575ec   Jeff Layton   cifs: replace kve...
1500
1501
  	rdata->iov.iov_base = buf;
  	rdata->iov.iov_len = server->total_read;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1502
1503
1504
  	cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu
  ",
  		 rdata->iov.iov_base, rdata->iov.iov_len);
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1505
1506
  
  	/* how much data is in the response? */
eb3787111   Pavel Shilovsky   CIFS: Move protoc...
1507
  	data_len = server->ops->read_data_length(buf);
5ffef7bf1   Pavel Shilovsky   CIFS: Separate pr...
1508
  	if (data_offset + data_len > buflen) {
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1509
1510
1511
1512
  		/* data_len is corrupt -- discard frame */
  		rdata->result = -EIO;
  		return cifs_readv_discard(server, mid);
  	}
8321fec43   Jeff Layton   cifs: convert asy...
1513
1514
1515
  	length = rdata->read_into_pages(server, rdata, data_len);
  	if (length < 0)
  		return length;
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1516

8321fec43   Jeff Layton   cifs: convert asy...
1517
  	server->total_read += length;
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1518

f96637be0   Joe Perches   [CIFS] cifs: Rena...
1519
1520
1521
  	cifs_dbg(FYI, "total_read=%u buflen=%u remaining=%u
  ",
  		 server->total_read, buflen, data_len);
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1522
1523
  
  	/* discard anything left over */
5ffef7bf1   Pavel Shilovsky   CIFS: Separate pr...
1524
  	if (server->total_read < buflen)
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1525
1526
1527
1528
1529
1530
1531
  		return cifs_readv_discard(server, mid);
  
  	dequeue_mid(mid, false);
  	return length;
  }
  
  static void
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1532
1533
1534
1535
1536
  cifs_readv_callback(struct mid_q_entry *mid)
  {
  	struct cifs_readdata *rdata = mid->callback_data;
  	struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
  	struct TCP_Server_Info *server = tcon->ses->server;
5819575ec   Jeff Layton   cifs: replace kve...
1537
1538
  	struct smb_rqst rqst = { .rq_iov = &rdata->iov,
  				 .rq_nvec = 1,
8321fec43   Jeff Layton   cifs: convert asy...
1539
1540
1541
1542
  				 .rq_pages = rdata->pages,
  				 .rq_npages = rdata->nr_pages,
  				 .rq_pagesz = rdata->pagesz,
  				 .rq_tailsz = rdata->tailsz };
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1543

f96637be0   Joe Perches   [CIFS] cifs: Rena...
1544
1545
1546
1547
  	cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%u
  ",
  		 __func__, mid->mid, mid->mid_state, rdata->result,
  		 rdata->bytes);
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1548

7c9421e1a   Pavel Shilovsky   CIFS: Change mid_...
1549
  	switch (mid->mid_state) {
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1550
1551
  	case MID_RESPONSE_RECEIVED:
  		/* result already set, check signature */
38d77c50b   Jeff Layton   cifs: track the e...
1552
  		if (server->sign) {
985e4ff01   Steve French   cifs: print error...
1553
  			int rc = 0;
bf5ea0e2f   Jeff Layton   cifs: change sign...
1554
  			rc = cifs_verify_signature(&rqst, server,
0124cc451   Jeff Layton   cifs: store the r...
1555
  						  mid->sequence_number);
985e4ff01   Steve French   cifs: print error...
1556
  			if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1557
1558
1559
  				cifs_dbg(VFS, "SMB signature verification returned error = %d
  ",
  					 rc);
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1560
1561
  		}
  		/* FIXME: should this be counted toward the initiating task? */
34a54d617   Pavel Shilovsky   CIFS: Use separat...
1562
1563
  		task_io_account_read(rdata->got_bytes);
  		cifs_stats_bytes_read(tcon, rdata->got_bytes);
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1564
1565
1566
1567
  		break;
  	case MID_REQUEST_SUBMITTED:
  	case MID_RETRY_NEEDED:
  		rdata->result = -EAGAIN;
d913ed17f   Pavel Shilovsky   CIFS: Optimize ci...
1568
1569
1570
1571
1572
1573
  		if (server->sign && rdata->got_bytes)
  			/* reset bytes number since we can not check a sign */
  			rdata->got_bytes = 0;
  		/* FIXME: should this be counted toward the initiating task? */
  		task_io_account_read(rdata->got_bytes);
  		cifs_stats_bytes_read(tcon, rdata->got_bytes);
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1574
1575
1576
1577
  		break;
  	default:
  		rdata->result = -EIO;
  	}
da472fc84   Jeff Layton   cifs: add new cif...
1578
  	queue_work(cifsiod_wq, &rdata->work);
5fb4e288a   Christopher Oo   cifs: Fix use-aft...
1579
  	mutex_lock(&server->srv_mutex);
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1580
  	DeleteMidQEntry(mid);
5fb4e288a   Christopher Oo   cifs: Fix use-aft...
1581
  	mutex_unlock(&server->srv_mutex);
a891f0f89   Pavel Shilovsky   CIFS: Extend cred...
1582
  	add_credits(server, 1, 0);
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
  }
  
  /* cifs_async_readv - send an async write, and set up mid to handle result */
  int
  cifs_async_readv(struct cifs_readdata *rdata)
  {
  	int rc;
  	READ_REQ *smb = NULL;
  	int wct;
  	struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
5819575ec   Jeff Layton   cifs: replace kve...
1593
  	struct smb_rqst rqst = { .rq_iov = &rdata->iov,
fec344e3f   Jeff Layton   cifs: change cifs...
1594
  				 .rq_nvec = 1 };
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1595

f96637be0   Joe Perches   [CIFS] cifs: Rena...
1596
1597
1598
  	cifs_dbg(FYI, "%s: offset=%llu bytes=%u
  ",
  		 __func__, rdata->offset, rdata->bytes);
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
  
  	if (tcon->ses->capabilities & CAP_LARGE_FILES)
  		wct = 12;
  	else {
  		wct = 10; /* old style read */
  		if ((rdata->offset >> 32) > 0)  {
  			/* can not handle this big offset for old */
  			return -EIO;
  		}
  	}
  
  	rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
  	if (rc)
  		return rc;
  
  	smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid);
  	smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
  
  	smb->AndXCommand = 0xFF;	/* none */
4b4de76e3   Pavel Shilovsky   CIFS: Replace net...
1618
  	smb->Fid = rdata->cfile->fid.netfid;
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
  	smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
  	if (wct == 12)
  		smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
  	smb->Remaining = 0;
  	smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
  	smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
  	if (wct == 12)
  		smb->ByteCount = 0;
  	else {
  		/* old style read */
  		struct smb_com_readx_req *smbr =
  			(struct smb_com_readx_req *)smb;
  		smbr->ByteCount = 0;
  	}
  
  	/* 4 for RFC1001 length + 1 for BCC */
5819575ec   Jeff Layton   cifs: replace kve...
1635
1636
  	rdata->iov.iov_base = smb;
  	rdata->iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1637

6993f74a5   Jeff Layton   cifs: add refcoun...
1638
  	kref_get(&rdata->refcount);
fec344e3f   Jeff Layton   cifs: change cifs...
1639
1640
  	rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive,
  			     cifs_readv_callback, rdata, 0);
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1641
1642
  
  	if (rc == 0)
44c581866   Pavel Shilovsky   CIFS: Move clear/...
1643
  		cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
6993f74a5   Jeff Layton   cifs: add refcoun...
1644
1645
  	else
  		kref_put(&rdata->refcount, cifs_readdata_release);
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1646
1647
1648
1649
  
  	cifs_small_buf_release(smb);
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1650
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1651
1652
  CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
  	    unsigned int *nbytes, char **buf, int *pbuf_type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1653
1654
1655
1656
1657
  {
  	int rc = -EACCES;
  	READ_REQ *pSMB = NULL;
  	READ_RSP *pSMBr = NULL;
  	char *pReadData = NULL;
bfa0d75a1   Steve French   [CIFS] Add suppor...
1658
  	int wct;
ec637e3ff   Steve French   [CIFS] Avoid extr...
1659
1660
  	int resp_buf_type = 0;
  	struct kvec iov[1];
d4ffff1fa   Pavel Shilovsky   CIFS: Add rwpidfo...
1661
1662
1663
  	__u32 pid = io_parms->pid;
  	__u16 netfid = io_parms->netfid;
  	__u64 offset = io_parms->offset;
96daf2b09   Steve French   [CIFS] Rename thr...
1664
  	struct cifs_tcon *tcon = io_parms->tcon;
d4ffff1fa   Pavel Shilovsky   CIFS: Add rwpidfo...
1665
  	unsigned int count = io_parms->length;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1666

f96637be0   Joe Perches   [CIFS] cifs: Rena...
1667
1668
  	cifs_dbg(FYI, "Reading %d bytes on fid %d
  ", count, netfid);
790fe579f   Steve French   [CIFS] more white...
1669
  	if (tcon->ses->capabilities & CAP_LARGE_FILES)
bfa0d75a1   Steve French   [CIFS] Add suppor...
1670
  		wct = 12;
4c3130efd   Steve French   [CIFS] Cleanup: M...
1671
  	else {
bfa0d75a1   Steve French   [CIFS] Add suppor...
1672
  		wct = 10; /* old style read */
d4ffff1fa   Pavel Shilovsky   CIFS: Add rwpidfo...
1673
  		if ((offset >> 32) > 0)  {
4c3130efd   Steve French   [CIFS] Cleanup: M...
1674
1675
1676
1677
  			/* can not handle this big offset for old */
  			return -EIO;
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1678
1679
  
  	*nbytes = 0;
ec637e3ff   Steve French   [CIFS] Avoid extr...
1680
  	rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1681
1682
  	if (rc)
  		return rc;
d4ffff1fa   Pavel Shilovsky   CIFS: Add rwpidfo...
1683
1684
  	pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
  	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1685
1686
1687
  	/* tcon and ses pointer are checked in smb_init */
  	if (tcon->ses->server == NULL)
  		return -ECONNABORTED;
ec637e3ff   Steve French   [CIFS] Avoid extr...
1688
  	pSMB->AndXCommand = 0xFF;       /* none */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1689
  	pSMB->Fid = netfid;
d4ffff1fa   Pavel Shilovsky   CIFS: Add rwpidfo...
1690
  	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
790fe579f   Steve French   [CIFS] more white...
1691
  	if (wct == 12)
d4ffff1fa   Pavel Shilovsky   CIFS: Add rwpidfo...
1692
  		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
bfa0d75a1   Steve French   [CIFS] Add suppor...
1693

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1694
1695
1696
  	pSMB->Remaining = 0;
  	pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
  	pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
790fe579f   Steve French   [CIFS] more white...
1697
  	if (wct == 12)
bfa0d75a1   Steve French   [CIFS] Add suppor...
1698
1699
1700
  		pSMB->ByteCount = 0;  /* no need to do le conversion since 0 */
  	else {
  		/* old style read */
50c2f7538   Steve French   [CIFS] whitespace...
1701
  		struct smb_com_readx_req *pSMBW =
bfa0d75a1   Steve French   [CIFS] Add suppor...
1702
  			(struct smb_com_readx_req *)pSMB;
ec637e3ff   Steve French   [CIFS] Avoid extr...
1703
  		pSMBW->ByteCount = 0;
bfa0d75a1   Steve French   [CIFS] Add suppor...
1704
  	}
ec637e3ff   Steve French   [CIFS] Avoid extr...
1705
1706
  
  	iov[0].iov_base = (char *)pSMB;
be8e3b004   Steve French   consistently use ...
1707
  	iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
a761ac579   Steve French   [CIFS] log better...
1708
  	rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
7749981ec   Jeff Layton   cifs: remove code...
1709
  			 &resp_buf_type, CIFS_LOG_ERROR);
44c581866   Pavel Shilovsky   CIFS: Move clear/...
1710
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
ec637e3ff   Steve French   [CIFS] Avoid extr...
1711
  	pSMBr = (READ_RSP *)iov[0].iov_base;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1712
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1713
1714
  		cifs_dbg(VFS, "Send error in read = %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1715
1716
1717
1718
1719
1720
1721
  	} else {
  		int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
  		data_length = data_length << 16;
  		data_length += le16_to_cpu(pSMBr->DataLength);
  		*nbytes = data_length;
  
  		/*check that DataLength would not go beyond end of SMB */
ec637e3ff   Steve French   [CIFS] Avoid extr...
1722
  		if ((data_length > CIFSMaxBufSize)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1723
  				|| (data_length > count)) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1724
1725
  			cifs_dbg(FYI, "bad length %d for count %d
  ",
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1726
  				 data_length, count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1727
1728
1729
  			rc = -EIO;
  			*nbytes = 0;
  		} else {
ec637e3ff   Steve French   [CIFS] Avoid extr...
1730
  			pReadData = (char *) (&pSMBr->hdr.Protocol) +
26f57364d   Steve French   [CIFS] formatting...
1731
1732
  					le16_to_cpu(pSMBr->DataOffset);
  /*			if (rc = copy_to_user(buf, pReadData, data_length)) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1733
1734
  				cifs_dbg(VFS, "Faulting on read rc = %d
  ",rc);
50c2f7538   Steve French   [CIFS] whitespace...
1735
  				rc = -EFAULT;
26f57364d   Steve French   [CIFS] formatting...
1736
  			}*/ /* can not use copy_to_user when using page cache*/
790fe579f   Steve French   [CIFS] more white...
1737
  			if (*buf)
50c2f7538   Steve French   [CIFS] whitespace...
1738
  				memcpy(*buf, pReadData, data_length);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1739
1740
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1741

4b8f930ff   Steve French   [CIFS] Free small...
1742
  /*	cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
790fe579f   Steve French   [CIFS] more white...
1743
  	if (*buf) {
6d81ed1ec   Sachin Prabhu   cifs: replace cod...
1744
  		free_rsp_buf(resp_buf_type, iov[0].iov_base);
790fe579f   Steve French   [CIFS] more white...
1745
  	} else if (resp_buf_type != CIFS_NO_BUFFER) {
50c2f7538   Steve French   [CIFS] whitespace...
1746
1747
  		/* return buffer to caller to free */
  		*buf = iov[0].iov_base;
790fe579f   Steve French   [CIFS] more white...
1748
  		if (resp_buf_type == CIFS_SMALL_BUFFER)
ec637e3ff   Steve French   [CIFS] Avoid extr...
1749
  			*pbuf_type = CIFS_SMALL_BUFFER;
790fe579f   Steve French   [CIFS] more white...
1750
  		else if (resp_buf_type == CIFS_LARGE_BUFFER)
ec637e3ff   Steve French   [CIFS] Avoid extr...
1751
  			*pbuf_type = CIFS_LARGE_BUFFER;
6cec2aed8   Steve French   [PATCH] CIFS: CIF...
1752
  	} /* else no valid buffer on return - leave as null */
ec637e3ff   Steve French   [CIFS] Avoid extr...
1753
1754
  
  	/* Note: On -EAGAIN error only caller can retry on handle based calls
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1755
1756
1757
  		since file handle passed in no longer valid */
  	return rc;
  }
ec637e3ff   Steve French   [CIFS] Avoid extr...
1758

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1759
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1760
  CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
fa2989f44   Pavel Shilovsky   CIFS: Use pid sav...
1761
  	     unsigned int *nbytes, const char *buf,
50c2f7538   Steve French   [CIFS] whitespace...
1762
  	     const char __user *ubuf, const int long_op)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1763
1764
1765
1766
  {
  	int rc = -EACCES;
  	WRITE_REQ *pSMB = NULL;
  	WRITE_RSP *pSMBr = NULL;
1c9551878   Steve French   [CIFS] Add suppor...
1767
  	int bytes_returned, wct;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1768
1769
  	__u32 bytes_sent;
  	__u16 byte_count;
fa2989f44   Pavel Shilovsky   CIFS: Use pid sav...
1770
1771
1772
  	__u32 pid = io_parms->pid;
  	__u16 netfid = io_parms->netfid;
  	__u64 offset = io_parms->offset;
96daf2b09   Steve French   [CIFS] Rename thr...
1773
  	struct cifs_tcon *tcon = io_parms->tcon;
fa2989f44   Pavel Shilovsky   CIFS: Use pid sav...
1774
  	unsigned int count = io_parms->length;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1775

a24e2d7d8   Steve French   [CIFS] initialize...
1776
  	*nbytes = 0;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1777
1778
  	/* cifs_dbg(FYI, "write at %lld %d bytes
  ", offset, count);*/
790fe579f   Steve French   [CIFS] more white...
1779
  	if (tcon->ses == NULL)
1c9551878   Steve French   [CIFS] Add suppor...
1780
  		return -ECONNABORTED;
790fe579f   Steve French   [CIFS] more white...
1781
  	if (tcon->ses->capabilities & CAP_LARGE_FILES)
1c9551878   Steve French   [CIFS] Add suppor...
1782
  		wct = 14;
4c3130efd   Steve French   [CIFS] Cleanup: M...
1783
  	else {
1c9551878   Steve French   [CIFS] Add suppor...
1784
  		wct = 12;
4c3130efd   Steve French   [CIFS] Cleanup: M...
1785
1786
1787
1788
1789
  		if ((offset >> 32) > 0) {
  			/* can not handle big offset for old srv */
  			return -EIO;
  		}
  	}
1c9551878   Steve French   [CIFS] Add suppor...
1790
1791
  
  	rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1792
1793
1794
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
fa2989f44   Pavel Shilovsky   CIFS: Use pid sav...
1795
1796
1797
  
  	pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
  	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1798
1799
1800
1801
1802
1803
1804
  	/* tcon and ses pointer are checked in smb_init */
  	if (tcon->ses->server == NULL)
  		return -ECONNABORTED;
  
  	pSMB->AndXCommand = 0xFF;	/* none */
  	pSMB->Fid = netfid;
  	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
790fe579f   Steve French   [CIFS] more white...
1805
  	if (wct == 14)
1c9551878   Steve French   [CIFS] Add suppor...
1806
  		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
50c2f7538   Steve French   [CIFS] whitespace...
1807

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1808
1809
1810
  	pSMB->Reserved = 0xFFFFFFFF;
  	pSMB->WriteMode = 0;
  	pSMB->Remaining = 0;
50c2f7538   Steve French   [CIFS] whitespace...
1811
  	/* Can increase buffer size if buffer is big enough in some cases ie we
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1812
1813
1814
  	can send more if LARGE_WRITE_X capability returned by the server and if
  	our buffer is big enough or if we convert to iovecs on socket writes
  	and eliminate the copy to the CIFS buffer */
790fe579f   Steve French   [CIFS] more white...
1815
  	if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1816
1817
1818
1819
1820
1821
1822
1823
1824
  		bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
  	} else {
  		bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
  			 & ~0xFF;
  	}
  
  	if (bytes_sent > count)
  		bytes_sent = count;
  	pSMB->DataOffset =
50c2f7538   Steve French   [CIFS] whitespace...
1825
  		cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
790fe579f   Steve French   [CIFS] more white...
1826
  	if (buf)
61e748015   Steve French   [CIFS] various mi...
1827
  		memcpy(pSMB->Data, buf, bytes_sent);
790fe579f   Steve French   [CIFS] more white...
1828
1829
  	else if (ubuf) {
  		if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1830
1831
1832
  			cifs_buf_release(pSMB);
  			return -EFAULT;
  		}
e30dcf3a1   Steve French   [CIFS] Add suppor...
1833
  	} else if (count != 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1834
1835
1836
  		/* No buffer */
  		cifs_buf_release(pSMB);
  		return -EINVAL;
e30dcf3a1   Steve French   [CIFS] Add suppor...
1837
  	} /* else setting file size with write of zero bytes */
790fe579f   Steve French   [CIFS] more white...
1838
  	if (wct == 14)
e30dcf3a1   Steve French   [CIFS] Add suppor...
1839
  		byte_count = bytes_sent + 1; /* pad */
ad7a2926b   Steve French   [CIFS] reduce che...
1840
  	else /* wct == 12 */
e30dcf3a1   Steve French   [CIFS] Add suppor...
1841
  		byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
ad7a2926b   Steve French   [CIFS] reduce che...
1842

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1843
1844
  	pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
  	pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
be8e3b004   Steve French   consistently use ...
1845
  	inc_rfc1001_len(pSMB, byte_count);
1c9551878   Steve French   [CIFS] Add suppor...
1846

790fe579f   Steve French   [CIFS] more white...
1847
  	if (wct == 14)
1c9551878   Steve French   [CIFS] Add suppor...
1848
  		pSMB->ByteCount = cpu_to_le16(byte_count);
50c2f7538   Steve French   [CIFS] whitespace...
1849
1850
1851
  	else { /* old style write has byte count 4 bytes earlier
  		  so 4 bytes pad  */
  		struct smb_com_writex_req *pSMBW =
1c9551878   Steve French   [CIFS] Add suppor...
1852
1853
1854
  			(struct smb_com_writex_req *)pSMB;
  		pSMBW->ByteCount = cpu_to_le16(byte_count);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1855
1856
1857
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
44c581866   Pavel Shilovsky   CIFS: Move clear/...
1858
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1859
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1860
1861
  		cifs_dbg(FYI, "Send error in write = %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1862
1863
1864
1865
  	} else {
  		*nbytes = le16_to_cpu(pSMBr->CountHigh);
  		*nbytes = (*nbytes) << 16;
  		*nbytes += le16_to_cpu(pSMBr->Count);
6513a81e9   Suresh Jayaraman   cifs: Fix a kerne...
1866
1867
1868
1869
1870
1871
1872
1873
  
  		/*
  		 * Mask off high 16 bits when bytes written as returned by the
  		 * server is greater than bytes requested by the client. Some
  		 * OS/2 servers are known to set incorrect CountHigh values.
  		 */
  		if (*nbytes > count)
  			*nbytes &= 0xFFFF;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1874
1875
1876
  	}
  
  	cifs_buf_release(pSMB);
50c2f7538   Steve French   [CIFS] whitespace...
1877
  	/* Note: On -EAGAIN error only caller can retry on handle based calls
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1878
1879
1880
1881
  		since file handle passed in no longer valid */
  
  	return rc;
  }
c28c89fc4   Jeff Layton   cifs: add cifs_as...
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
  void
  cifs_writedata_release(struct kref *refcount)
  {
  	struct cifs_writedata *wdata = container_of(refcount,
  					struct cifs_writedata, refcount);
  
  	if (wdata->cfile)
  		cifsFileInfo_put(wdata->cfile);
  
  	kfree(wdata);
  }
  
  /*
   * Write failed with a retryable error. Resend the write request. It's also
   * possible that the page was redirtied so re-clean the page.
   */
  static void
  cifs_writev_requeue(struct cifs_writedata *wdata)
  {
7f6c50086   Pavel Shilovsky   CIFS: Fix cifs_wr...
1901
  	int i, rc = 0;
2b0143b5c   David Howells   VFS: normal files...
1902
  	struct inode *inode = d_inode(wdata->cfile->dentry);
c9de5c80d   Pavel Shilovsky   CIFS: Move async ...
1903
  	struct TCP_Server_Info *server;
7f6c50086   Pavel Shilovsky   CIFS: Fix cifs_wr...
1904
  	unsigned int rest_len;
c28c89fc4   Jeff Layton   cifs: add cifs_as...
1905

7f6c50086   Pavel Shilovsky   CIFS: Fix cifs_wr...
1906
1907
1908
  	server = tlink_tcon(wdata->cfile->tlink)->ses->server;
  	i = 0;
  	rest_len = wdata->bytes;
c28c89fc4   Jeff Layton   cifs: add cifs_as...
1909
  	do {
7f6c50086   Pavel Shilovsky   CIFS: Fix cifs_wr...
1910
1911
1912
1913
1914
  		struct cifs_writedata *wdata2;
  		unsigned int j, nr_pages, wsize, tailsz, cur_len;
  
  		wsize = server->ops->wp_retry_size(inode);
  		if (wsize < rest_len) {
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1915
  			nr_pages = wsize / PAGE_SIZE;
7f6c50086   Pavel Shilovsky   CIFS: Fix cifs_wr...
1916
1917
1918
1919
  			if (!nr_pages) {
  				rc = -ENOTSUPP;
  				break;
  			}
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1920
1921
  			cur_len = nr_pages * PAGE_SIZE;
  			tailsz = PAGE_SIZE;
7f6c50086   Pavel Shilovsky   CIFS: Fix cifs_wr...
1922
  		} else {
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1923
  			nr_pages = DIV_ROUND_UP(rest_len, PAGE_SIZE);
7f6c50086   Pavel Shilovsky   CIFS: Fix cifs_wr...
1924
  			cur_len = rest_len;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1925
  			tailsz = rest_len - (nr_pages - 1) * PAGE_SIZE;
7f6c50086   Pavel Shilovsky   CIFS: Fix cifs_wr...
1926
  		}
c28c89fc4   Jeff Layton   cifs: add cifs_as...
1927

7f6c50086   Pavel Shilovsky   CIFS: Fix cifs_wr...
1928
1929
1930
1931
  		wdata2 = cifs_writedata_alloc(nr_pages, cifs_writev_complete);
  		if (!wdata2) {
  			rc = -ENOMEM;
  			break;
c51bb0ea4   Ouyang Maochun   cifs: bugfix for ...
1932
  		}
7f6c50086   Pavel Shilovsky   CIFS: Fix cifs_wr...
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
  
  		for (j = 0; j < nr_pages; j++) {
  			wdata2->pages[j] = wdata->pages[i + j];
  			lock_page(wdata2->pages[j]);
  			clear_page_dirty_for_io(wdata2->pages[j]);
  		}
  
  		wdata2->sync_mode = wdata->sync_mode;
  		wdata2->nr_pages = nr_pages;
  		wdata2->offset = page_offset(wdata2->pages[0]);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1943
  		wdata2->pagesz = PAGE_SIZE;
7f6c50086   Pavel Shilovsky   CIFS: Fix cifs_wr...
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
  		wdata2->tailsz = tailsz;
  		wdata2->bytes = cur_len;
  
  		wdata2->cfile = find_writable_file(CIFS_I(inode), false);
  		if (!wdata2->cfile) {
  			cifs_dbg(VFS, "No writable handles for inode
  ");
  			rc = -EBADF;
  			break;
  		}
  		wdata2->pid = wdata2->cfile->pid;
  		rc = server->ops->async_writev(wdata2, cifs_writedata_release);
  
  		for (j = 0; j < nr_pages; j++) {
  			unlock_page(wdata2->pages[j]);
  			if (rc != 0 && rc != -EAGAIN) {
  				SetPageError(wdata2->pages[j]);
  				end_page_writeback(wdata2->pages[j]);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1962
  				put_page(wdata2->pages[j]);
7f6c50086   Pavel Shilovsky   CIFS: Fix cifs_wr...
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
  			}
  		}
  
  		if (rc) {
  			kref_put(&wdata2->refcount, cifs_writedata_release);
  			if (rc == -EAGAIN)
  				continue;
  			break;
  		}
  
  		rest_len -= cur_len;
  		i += nr_pages;
  	} while (i < wdata->nr_pages);
c28c89fc4   Jeff Layton   cifs: add cifs_as...
1976
1977
1978
1979
  
  	mapping_set_error(inode->i_mapping, rc);
  	kref_put(&wdata->refcount, cifs_writedata_release);
  }
c2e876400   Jeff Layton   cifs: allow calle...
1980
  void
c28c89fc4   Jeff Layton   cifs: add cifs_as...
1981
1982
1983
1984
  cifs_writev_complete(struct work_struct *work)
  {
  	struct cifs_writedata *wdata = container_of(work,
  						struct cifs_writedata, work);
2b0143b5c   David Howells   VFS: normal files...
1985
  	struct inode *inode = d_inode(wdata->cfile->dentry);
c28c89fc4   Jeff Layton   cifs: add cifs_as...
1986
1987
1988
  	int i = 0;
  
  	if (wdata->result == 0) {
597b027f6   Jeff Layton   cifs: call cifs_u...
1989
  		spin_lock(&inode->i_lock);
c28c89fc4   Jeff Layton   cifs: add cifs_as...
1990
  		cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
597b027f6   Jeff Layton   cifs: call cifs_u...
1991
  		spin_unlock(&inode->i_lock);
c28c89fc4   Jeff Layton   cifs: add cifs_as...
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
  		cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
  					 wdata->bytes);
  	} else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
  		return cifs_writev_requeue(wdata);
  
  	for (i = 0; i < wdata->nr_pages; i++) {
  		struct page *page = wdata->pages[i];
  		if (wdata->result == -EAGAIN)
  			__set_page_dirty_nobuffers(page);
  		else if (wdata->result < 0)
  			SetPageError(page);
  		end_page_writeback(page);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
2004
  		put_page(page);
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2005
2006
2007
2008
2009
2010
2011
  	}
  	if (wdata->result != -EAGAIN)
  		mapping_set_error(inode->i_mapping, wdata->result);
  	kref_put(&wdata->refcount, cifs_writedata_release);
  }
  
  struct cifs_writedata *
c2e876400   Jeff Layton   cifs: allow calle...
2012
  cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2013
2014
  {
  	struct cifs_writedata *wdata;
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2015
2016
  	/* writedata + number of page pointers */
  	wdata = kzalloc(sizeof(*wdata) +
26c8f0d60   Jeff Layton   cifs: use a flexa...
2017
  			sizeof(struct page *) * nr_pages, GFP_NOFS);
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2018
  	if (wdata != NULL) {
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2019
  		kref_init(&wdata->refcount);
da82f7e75   Jeff Layton   cifs: convert cif...
2020
2021
2022
  		INIT_LIST_HEAD(&wdata->list);
  		init_completion(&wdata->done);
  		INIT_WORK(&wdata->work, complete);
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2023
2024
2025
2026
2027
  	}
  	return wdata;
  }
  
  /*
7c9421e1a   Pavel Shilovsky   CIFS: Change mid_...
2028
   * Check the mid_state and signature on received buffer (if any), and queue the
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2029
2030
2031
2032
2033
2034
   * workqueue completion task.
   */
  static void
  cifs_writev_callback(struct mid_q_entry *mid)
  {
  	struct cifs_writedata *wdata = mid->callback_data;
96daf2b09   Steve French   [CIFS] Rename thr...
2035
  	struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
5fb4e288a   Christopher Oo   cifs: Fix use-aft...
2036
  	struct TCP_Server_Info *server = tcon->ses->server;
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2037
2038
  	unsigned int written;
  	WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
7c9421e1a   Pavel Shilovsky   CIFS: Change mid_...
2039
  	switch (mid->mid_state) {
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
  	case MID_RESPONSE_RECEIVED:
  		wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
  		if (wdata->result != 0)
  			break;
  
  		written = le16_to_cpu(smb->CountHigh);
  		written <<= 16;
  		written += le16_to_cpu(smb->Count);
  		/*
  		 * Mask off high 16 bits when bytes written as returned
  		 * by the server is greater than bytes requested by the
  		 * client. OS/2 servers are known to set incorrect
  		 * CountHigh values.
  		 */
  		if (written > wdata->bytes)
  			written &= 0xFFFF;
  
  		if (written < wdata->bytes)
  			wdata->result = -ENOSPC;
  		else
  			wdata->bytes = written;
  		break;
  	case MID_REQUEST_SUBMITTED:
  	case MID_RETRY_NEEDED:
  		wdata->result = -EAGAIN;
  		break;
  	default:
  		wdata->result = -EIO;
  		break;
  	}
da472fc84   Jeff Layton   cifs: add new cif...
2070
  	queue_work(cifsiod_wq, &wdata->work);
5fb4e288a   Christopher Oo   cifs: Fix use-aft...
2071
  	mutex_lock(&server->srv_mutex);
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2072
  	DeleteMidQEntry(mid);
5fb4e288a   Christopher Oo   cifs: Fix use-aft...
2073
  	mutex_unlock(&server->srv_mutex);
a891f0f89   Pavel Shilovsky   CIFS: Extend cred...
2074
  	add_credits(tcon->ses->server, 1, 0);
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2075
2076
2077
2078
  }
  
  /* cifs_async_writev - send an async write, and set up mid to handle result */
  int
4a5c80d7b   Steve French   [CIFS] clean up p...
2079
2080
  cifs_async_writev(struct cifs_writedata *wdata,
  		  void (*release)(struct kref *kref))
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2081
  {
eddb079de   Jeff Layton   cifs: convert asy...
2082
  	int rc = -EACCES;
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2083
2084
  	WRITE_REQ *smb = NULL;
  	int wct;
96daf2b09   Steve French   [CIFS] Rename thr...
2085
  	struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
eddb079de   Jeff Layton   cifs: convert asy...
2086
  	struct kvec iov;
fec344e3f   Jeff Layton   cifs: change cifs...
2087
  	struct smb_rqst rqst = { };
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
  
  	if (tcon->ses->capabilities & CAP_LARGE_FILES) {
  		wct = 14;
  	} else {
  		wct = 12;
  		if (wdata->offset >> 32 > 0) {
  			/* can not handle big offset for old srv */
  			return -EIO;
  		}
  	}
  
  	rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
  	if (rc)
  		goto async_writev_out;
fe5f5d2e9   Jeff Layton   cifs: add pid fie...
2102
2103
  	smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
  	smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
fa2989f44   Pavel Shilovsky   CIFS: Use pid sav...
2104

c28c89fc4   Jeff Layton   cifs: add cifs_as...
2105
  	smb->AndXCommand = 0xFF;	/* none */
4b4de76e3   Pavel Shilovsky   CIFS: Replace net...
2106
  	smb->Fid = wdata->cfile->fid.netfid;
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
  	smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
  	if (wct == 14)
  		smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
  	smb->Reserved = 0xFFFFFFFF;
  	smb->WriteMode = 0;
  	smb->Remaining = 0;
  
  	smb->DataOffset =
  	    cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
  
  	/* 4 for RFC1001 length + 1 for BCC */
eddb079de   Jeff Layton   cifs: convert asy...
2118
2119
  	iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
  	iov.iov_base = smb;
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2120

eddb079de   Jeff Layton   cifs: convert asy...
2121
2122
2123
2124
2125
2126
  	rqst.rq_iov = &iov;
  	rqst.rq_nvec = 1;
  	rqst.rq_pages = wdata->pages;
  	rqst.rq_npages = wdata->nr_pages;
  	rqst.rq_pagesz = wdata->pagesz;
  	rqst.rq_tailsz = wdata->tailsz;
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2127

f96637be0   Joe Perches   [CIFS] cifs: Rena...
2128
2129
2130
  	cifs_dbg(FYI, "async write at %llu %u bytes
  ",
  		 wdata->offset, wdata->bytes);
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
  
  	smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
  	smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
  
  	if (wct == 14) {
  		inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
  		put_bcc(wdata->bytes + 1, &smb->hdr);
  	} else {
  		/* wct == 12 */
  		struct smb_com_writex_req *smbw =
  				(struct smb_com_writex_req *)smb;
  		inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
  		put_bcc(wdata->bytes + 5, &smbw->hdr);
eddb079de   Jeff Layton   cifs: convert asy...
2144
  		iov.iov_len += 4; /* pad bigger by four bytes */
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2145
2146
2147
  	}
  
  	kref_get(&wdata->refcount);
fec344e3f   Jeff Layton   cifs: change cifs...
2148
2149
  	rc = cifs_call_async(tcon->ses->server, &rqst, NULL,
  				cifs_writev_callback, wdata, 0);
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2150
2151
  
  	if (rc == 0)
44c581866   Pavel Shilovsky   CIFS: Move clear/...
2152
  		cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2153
  	else
4a5c80d7b   Steve French   [CIFS] clean up p...
2154
  		kref_put(&wdata->refcount, release);
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2155

c28c89fc4   Jeff Layton   cifs: add cifs_as...
2156
2157
  async_writev_out:
  	cifs_small_buf_release(smb);
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2158
2159
  	return rc;
  }
d6e04ae64   Steve French   [CIFS] CIFS write...
2160
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2161
  CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
ba9ad7257   Pavel Shilovsky   CIFS: Move writep...
2162
  	      unsigned int *nbytes, struct kvec *iov, int n_vec)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2163
2164
2165
  {
  	int rc = -EACCES;
  	WRITE_REQ *pSMB = NULL;
ec637e3ff   Steve French   [CIFS] Avoid extr...
2166
  	int wct;
d6e04ae64   Steve French   [CIFS] CIFS write...
2167
  	int smb_hdr_len;
ec637e3ff   Steve French   [CIFS] Avoid extr...
2168
  	int resp_buf_type = 0;
fa2989f44   Pavel Shilovsky   CIFS: Use pid sav...
2169
2170
2171
  	__u32 pid = io_parms->pid;
  	__u16 netfid = io_parms->netfid;
  	__u64 offset = io_parms->offset;
96daf2b09   Steve French   [CIFS] Rename thr...
2172
  	struct cifs_tcon *tcon = io_parms->tcon;
fa2989f44   Pavel Shilovsky   CIFS: Use pid sav...
2173
  	unsigned int count = io_parms->length;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2174

fbec9ab95   Jeff Layton   cifs: vary timeou...
2175
  	*nbytes = 0;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2176
2177
  	cifs_dbg(FYI, "write2 at %lld %d bytes
  ", (long long)offset, count);
ff7feac96   Steve French   [CIFS] Fix endian...
2178

4c3130efd   Steve French   [CIFS] Cleanup: M...
2179
  	if (tcon->ses->capabilities & CAP_LARGE_FILES) {
8cc64c6ec   Steve French   [CIFS] Allow SMBW...
2180
  		wct = 14;
4c3130efd   Steve French   [CIFS] Cleanup: M...
2181
  	} else {
8cc64c6ec   Steve French   [CIFS] Allow SMBW...
2182
  		wct = 12;
4c3130efd   Steve French   [CIFS] Cleanup: M...
2183
2184
2185
2186
2187
  		if ((offset >> 32) > 0) {
  			/* can not handle big offset for old srv */
  			return -EIO;
  		}
  	}
8cc64c6ec   Steve French   [CIFS] Allow SMBW...
2188
  	rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2189
2190
  	if (rc)
  		return rc;
fa2989f44   Pavel Shilovsky   CIFS: Use pid sav...
2191
2192
2193
  
  	pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
  	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2194
2195
2196
  	/* tcon and ses pointer are checked in smb_init */
  	if (tcon->ses->server == NULL)
  		return -ECONNABORTED;
d6e04ae64   Steve French   [CIFS] CIFS write...
2197
  	pSMB->AndXCommand = 0xFF;	/* none */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2198
2199
  	pSMB->Fid = netfid;
  	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
790fe579f   Steve French   [CIFS] more white...
2200
  	if (wct == 14)
8cc64c6ec   Steve French   [CIFS] Allow SMBW...
2201
  		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2202
2203
2204
  	pSMB->Reserved = 0xFFFFFFFF;
  	pSMB->WriteMode = 0;
  	pSMB->Remaining = 0;
d6e04ae64   Steve French   [CIFS] CIFS write...
2205

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2206
  	pSMB->DataOffset =
50c2f7538   Steve French   [CIFS] whitespace...
2207
  	    cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2208

3e84469d0   Steve French   [CIFS] Add writep...
2209
2210
  	pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
  	pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
be8e3b004   Steve French   consistently use ...
2211
2212
  	/* header + 1 byte pad */
  	smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
790fe579f   Steve French   [CIFS] more white...
2213
  	if (wct == 14)
be8e3b004   Steve French   consistently use ...
2214
  		inc_rfc1001_len(pSMB, count + 1);
8cc64c6ec   Steve French   [CIFS] Allow SMBW...
2215
  	else /* wct == 12 */
be8e3b004   Steve French   consistently use ...
2216
  		inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
790fe579f   Steve French   [CIFS] more white...
2217
  	if (wct == 14)
8cc64c6ec   Steve French   [CIFS] Allow SMBW...
2218
2219
  		pSMB->ByteCount = cpu_to_le16(count + 1);
  	else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
50c2f7538   Steve French   [CIFS] whitespace...
2220
  		struct smb_com_writex_req *pSMBW =
8cc64c6ec   Steve French   [CIFS] Allow SMBW...
2221
2222
2223
  				(struct smb_com_writex_req *)pSMB;
  		pSMBW->ByteCount = cpu_to_le16(count + 5);
  	}
3e84469d0   Steve French   [CIFS] Add writep...
2224
  	iov[0].iov_base = pSMB;
790fe579f   Steve French   [CIFS] more white...
2225
  	if (wct == 14)
ec637e3ff   Steve French   [CIFS] Avoid extr...
2226
2227
2228
  		iov[0].iov_len = smb_hdr_len + 4;
  	else /* wct == 12 pad bigger by four bytes */
  		iov[0].iov_len = smb_hdr_len + 8;
50c2f7538   Steve French   [CIFS] whitespace...
2229

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2230

ba9ad7257   Pavel Shilovsky   CIFS: Move writep...
2231
  	rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, 0);
44c581866   Pavel Shilovsky   CIFS: Move clear/...
2232
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2233
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2234
2235
  		cifs_dbg(FYI, "Send error Write2 = %d
  ", rc);
790fe579f   Steve French   [CIFS] more white...
2236
  	} else if (resp_buf_type == 0) {
ec637e3ff   Steve French   [CIFS] Avoid extr...
2237
2238
  		/* presumably this can not happen, but best to be safe */
  		rc = -EIO;
d6e04ae64   Steve French   [CIFS] CIFS write...
2239
  	} else {
ad7a2926b   Steve French   [CIFS] reduce che...
2240
  		WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
d6e04ae64   Steve French   [CIFS] CIFS write...
2241
2242
2243
  		*nbytes = le16_to_cpu(pSMBr->CountHigh);
  		*nbytes = (*nbytes) << 16;
  		*nbytes += le16_to_cpu(pSMBr->Count);
6513a81e9   Suresh Jayaraman   cifs: Fix a kerne...
2244
2245
2246
2247
2248
2249
2250
2251
  
  		/*
  		 * Mask off high 16 bits when bytes written as returned by the
  		 * server is greater than bytes requested by the client. OS/2
  		 * servers are known to set incorrect CountHigh values.
  		 */
  		if (*nbytes > count)
  			*nbytes &= 0xFFFF;
50c2f7538   Steve French   [CIFS] whitespace...
2252
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2253

4b8f930ff   Steve French   [CIFS] Free small...
2254
  /*	cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
6d81ed1ec   Sachin Prabhu   cifs: replace cod...
2255
  	free_rsp_buf(resp_buf_type, iov[0].iov_base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2256

50c2f7538   Steve French   [CIFS] whitespace...
2257
  	/* Note: On -EAGAIN error only caller can retry on handle based calls
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2258
2259
2260
2261
  		since file handle passed in no longer valid */
  
  	return rc;
  }
d6e04ae64   Steve French   [CIFS] CIFS write...
2262

6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2263
2264
  int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
  	       const __u16 netfid, const __u8 lock_type, const __u32 num_unlock,
9ee305b70   Pavel Shilovsky   CIFS: Send as man...
2265
2266
2267
2268
2269
2270
2271
  	       const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
  {
  	int rc = 0;
  	LOCK_REQ *pSMB = NULL;
  	struct kvec iov[2];
  	int resp_buf_type;
  	__u16 count;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2272
2273
2274
  	cifs_dbg(FYI, "cifs_lockv num lock %d num unlock %d
  ",
  		 num_lock, num_unlock);
9ee305b70   Pavel Shilovsky   CIFS: Send as man...
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
  
  	rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
  	if (rc)
  		return rc;
  
  	pSMB->Timeout = 0;
  	pSMB->NumberOfLocks = cpu_to_le16(num_lock);
  	pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
  	pSMB->LockType = lock_type;
  	pSMB->AndXCommand = 0xFF; /* none */
  	pSMB->Fid = netfid; /* netfid stays le */
  
  	count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
  	inc_rfc1001_len(pSMB, count);
  	pSMB->ByteCount = cpu_to_le16(count);
  
  	iov[0].iov_base = (char *)pSMB;
  	iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
  			 (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
  	iov[1].iov_base = (char *)buf;
  	iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
44c581866   Pavel Shilovsky   CIFS: Move clear/...
2296
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
9ee305b70   Pavel Shilovsky   CIFS: Send as man...
2297
2298
  	rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP);
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2299
2300
  		cifs_dbg(FYI, "Send error in cifs_lockv = %d
  ", rc);
9ee305b70   Pavel Shilovsky   CIFS: Send as man...
2301
2302
2303
  
  	return rc;
  }
d6e04ae64   Steve French   [CIFS] CIFS write...
2304

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2305
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2306
  CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
03776f451   Pavel Shilovsky   CIFS: Simplify by...
2307
  	    const __u16 smb_file_id, const __u32 netpid, const __u64 len,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2308
  	    const __u64 offset, const __u32 numUnlock,
12fed00de   Pavel Shilovsky   CIFS: Fix oplock ...
2309
2310
  	    const __u32 numLock, const __u8 lockType,
  	    const bool waitFlag, const __u8 oplock_level)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2311
2312
2313
  {
  	int rc = 0;
  	LOCK_REQ *pSMB = NULL;
aaa9bbe03   Steve French   [CIFS] remove unu...
2314
  /*	LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2315
  	int bytes_returned;
a891f0f89   Pavel Shilovsky   CIFS: Extend cred...
2316
  	int flags = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2317
  	__u16 count;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2318
2319
2320
  	cifs_dbg(FYI, "CIFSSMBLock timeout %d numLock %d
  ",
  		 (int)waitFlag, numLock);
46810cbf3   Steve French   [PATCH] cifs: Eas...
2321
  	rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2322
2323
  	if (rc)
  		return rc;
790fe579f   Steve French   [CIFS] more white...
2324
  	if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
a891f0f89   Pavel Shilovsky   CIFS: Extend cred...
2325
2326
  		/* no response expected */
  		flags = CIFS_ASYNC_OP | CIFS_OBREAK_OP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2327
  		pSMB->Timeout = 0;
4b18f2a9c   Steve French   [CIFS] convert us...
2328
  	} else if (waitFlag) {
a891f0f89   Pavel Shilovsky   CIFS: Extend cred...
2329
  		flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2330
2331
2332
2333
2334
2335
2336
2337
  		pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
  	} else {
  		pSMB->Timeout = 0;
  	}
  
  	pSMB->NumberOfLocks = cpu_to_le16(numLock);
  	pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
  	pSMB->LockType = lockType;
12fed00de   Pavel Shilovsky   CIFS: Fix oplock ...
2338
  	pSMB->OplockLevel = oplock_level;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2339
2340
  	pSMB->AndXCommand = 0xFF;	/* none */
  	pSMB->Fid = smb_file_id; /* netfid stays le */
790fe579f   Steve French   [CIFS] more white...
2341
  	if ((numLock != 0) || (numUnlock != 0)) {
03776f451   Pavel Shilovsky   CIFS: Simplify by...
2342
  		pSMB->Locks[0].Pid = cpu_to_le16(netpid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
  		/* BB where to store pid high? */
  		pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
  		pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
  		pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
  		pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
  		count = sizeof(LOCKING_ANDX_RANGE);
  	} else {
  		/* oplock break */
  		count = 0;
  	}
be8e3b004   Steve French   consistently use ...
2353
  	inc_rfc1001_len(pSMB, count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2354
  	pSMB->ByteCount = cpu_to_le16(count);
7ee1af765   Jeremy Allison   [CIFS]
2355
2356
  	if (waitFlag) {
  		rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
aaa9bbe03   Steve French   [CIFS] remove unu...
2357
  			(struct smb_hdr *) pSMB, &bytes_returned);
133672efb   Steve French   [CIFS] Fix buffer...
2358
  		cifs_small_buf_release(pSMB);
7ee1af765   Jeremy Allison   [CIFS]
2359
  	} else {
a891f0f89   Pavel Shilovsky   CIFS: Extend cred...
2360
  		rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags);
133672efb   Steve French   [CIFS] Fix buffer...
2361
  		/* SMB buffer freed by function above */
7ee1af765   Jeremy Allison   [CIFS]
2362
  	}
44c581866   Pavel Shilovsky   CIFS: Move clear/...
2363
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
ad7a2926b   Steve French   [CIFS] reduce che...
2364
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2365
2366
  		cifs_dbg(FYI, "Send error in Lock = %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2367

50c2f7538   Steve French   [CIFS] whitespace...
2368
  	/* Note: On -EAGAIN error only caller can retry on handle based calls
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2369
2370
2371
2372
2373
  	since file handle passed in no longer valid */
  	return rc;
  }
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2374
  CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
c5fd363d7   Jeff Layton   cifs: move file_l...
2375
2376
2377
2378
  		const __u16 smb_file_id, const __u32 netpid,
  		const loff_t start_offset, const __u64 len,
  		struct file_lock *pLockData, const __u16 lock_type,
  		const bool waitFlag)
08547b036   Steve French   [CIFS] Add posix ...
2379
2380
2381
  {
  	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
  	struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
08547b036   Steve French   [CIFS] Add posix ...
2382
2383
  	struct cifs_posix_lock *parm_data;
  	int rc = 0;
3a5ff61c1   Steve French   [CIFS] Do not tim...
2384
  	int timeout = 0;
08547b036   Steve French   [CIFS] Add posix ...
2385
  	int bytes_returned = 0;
133672efb   Steve French   [CIFS] Fix buffer...
2386
  	int resp_buf_type = 0;
08547b036   Steve French   [CIFS] Add posix ...
2387
  	__u16 params, param_offset, offset, byte_count, count;
133672efb   Steve French   [CIFS] Fix buffer...
2388
  	struct kvec iov[1];
08547b036   Steve French   [CIFS] Add posix ...
2389

f96637be0   Joe Perches   [CIFS] cifs: Rena...
2390
2391
  	cifs_dbg(FYI, "Posix Lock
  ");
fc94cdb94   Steve French   [CIFS] Fix new PO...
2392

08547b036   Steve French   [CIFS] Add posix ...
2393
2394
2395
2396
2397
2398
  	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
  
  	if (rc)
  		return rc;
  
  	pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
50c2f7538   Steve French   [CIFS] whitespace...
2399
  	params = 6;
08547b036   Steve French   [CIFS] Add posix ...
2400
2401
2402
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  	pSMB->Flags = 0;
08547b036   Steve French   [CIFS] Add posix ...
2403
2404
2405
  	pSMB->Reserved2 = 0;
  	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
  	offset = param_offset + params;
08547b036   Steve French   [CIFS] Add posix ...
2406
2407
  	count = sizeof(struct cifs_posix_lock);
  	pSMB->MaxParameterCount = cpu_to_le16(2);
ad7a2926b   Steve French   [CIFS] reduce che...
2408
  	pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
08547b036   Steve French   [CIFS] Add posix ...
2409
2410
  	pSMB->SetupCount = 1;
  	pSMB->Reserved3 = 0;
c5fd363d7   Jeff Layton   cifs: move file_l...
2411
  	if (pLockData)
08547b036   Steve French   [CIFS] Add posix ...
2412
2413
2414
2415
2416
2417
2418
2419
2420
  		pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
  	else
  		pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
  	byte_count = 3 /* pad */  + params + count;
  	pSMB->DataCount = cpu_to_le16(count);
  	pSMB->ParameterCount = cpu_to_le16(params);
  	pSMB->TotalDataCount = pSMB->DataCount;
  	pSMB->TotalParameterCount = pSMB->ParameterCount;
  	pSMB->ParameterOffset = cpu_to_le16(param_offset);
50c2f7538   Steve French   [CIFS] whitespace...
2421
  	parm_data = (struct cifs_posix_lock *)
08547b036   Steve French   [CIFS] Add posix ...
2422
2423
2424
  			(((char *) &pSMB->hdr.Protocol) + offset);
  
  	parm_data->lock_type = cpu_to_le16(lock_type);
790fe579f   Steve French   [CIFS] more white...
2425
  	if (waitFlag) {
133672efb   Steve French   [CIFS] Fix buffer...
2426
  		timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
cec6815a1   Steve French   [CIFS] endian fix...
2427
  		parm_data->lock_flags = cpu_to_le16(1);
3a5ff61c1   Steve French   [CIFS] Do not tim...
2428
2429
2430
  		pSMB->Timeout = cpu_to_le32(-1);
  	} else
  		pSMB->Timeout = 0;
4f6bcec91   Pavel Shilovsky   CIFS: Implement c...
2431
  	parm_data->pid = cpu_to_le32(netpid);
c5fd363d7   Jeff Layton   cifs: move file_l...
2432
  	parm_data->start = cpu_to_le64(start_offset);
cec6815a1   Steve French   [CIFS] endian fix...
2433
  	parm_data->length = cpu_to_le64(len);  /* normalize negative numbers */
08547b036   Steve French   [CIFS] Add posix ...
2434
2435
  
  	pSMB->DataOffset = cpu_to_le16(offset);
f26282c9a   Steve French   [CIFS] Use correc...
2436
  	pSMB->Fid = smb_file_id;
08547b036   Steve French   [CIFS] Add posix ...
2437
2438
  	pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
  	pSMB->Reserved4 = 0;
be8e3b004   Steve French   consistently use ...
2439
  	inc_rfc1001_len(pSMB, byte_count);
08547b036   Steve French   [CIFS] Add posix ...
2440
  	pSMB->ByteCount = cpu_to_le16(byte_count);
7ee1af765   Jeremy Allison   [CIFS]
2441
2442
2443
2444
  	if (waitFlag) {
  		rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
  			(struct smb_hdr *) pSMBr, &bytes_returned);
  	} else {
133672efb   Steve French   [CIFS] Fix buffer...
2445
  		iov[0].iov_base = (char *)pSMB;
be8e3b004   Steve French   consistently use ...
2446
  		iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
133672efb   Steve French   [CIFS] Fix buffer...
2447
2448
2449
2450
2451
  		rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
  				&resp_buf_type, timeout);
  		pSMB = NULL; /* request buf already freed by SendReceive2. Do
  				not try to free it twice below on exit */
  		pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
7ee1af765   Jeremy Allison   [CIFS]
2452
  	}
08547b036   Steve French   [CIFS] Add posix ...
2453
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2454
2455
  		cifs_dbg(FYI, "Send error in Posix Lock = %d
  ", rc);
c5fd363d7   Jeff Layton   cifs: move file_l...
2456
  	} else if (pLockData) {
fc94cdb94   Steve French   [CIFS] Fix new PO...
2457
2458
2459
2460
  		/* lock structure can be returned on get */
  		__u16 data_offset;
  		__u16 data_count;
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
820a803ff   Jeff Layton   cifs: keep BCC in...
2461
  		if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
fc94cdb94   Steve French   [CIFS] Fix new PO...
2462
2463
2464
  			rc = -EIO;      /* bad smb */
  			goto plk_err_exit;
  		}
fc94cdb94   Steve French   [CIFS] Fix new PO...
2465
2466
  		data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
  		data_count  = le16_to_cpu(pSMBr->t2.DataCount);
790fe579f   Steve French   [CIFS] more white...
2467
  		if (data_count < sizeof(struct cifs_posix_lock)) {
fc94cdb94   Steve French   [CIFS] Fix new PO...
2468
2469
2470
2471
2472
  			rc = -EIO;
  			goto plk_err_exit;
  		}
  		parm_data = (struct cifs_posix_lock *)
  			((char *)&pSMBr->hdr.Protocol + data_offset);
bc09d141e   Fabian Frederick   fs/cifs: remove o...
2473
  		if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
fc94cdb94   Steve French   [CIFS] Fix new PO...
2474
  			pLockData->fl_type = F_UNLCK;
f05337c6a   Pavel Shilovsky   not overwriting f...
2475
2476
  		else {
  			if (parm_data->lock_type ==
bc09d141e   Fabian Frederick   fs/cifs: remove o...
2477
  					cpu_to_le16(CIFS_RDLCK))
f05337c6a   Pavel Shilovsky   not overwriting f...
2478
2479
  				pLockData->fl_type = F_RDLCK;
  			else if (parm_data->lock_type ==
bc09d141e   Fabian Frederick   fs/cifs: remove o...
2480
  					cpu_to_le16(CIFS_WRLCK))
f05337c6a   Pavel Shilovsky   not overwriting f...
2481
  				pLockData->fl_type = F_WRLCK;
5443d130a   Steve French   various endian fi...
2482
2483
2484
2485
  			pLockData->fl_start = le64_to_cpu(parm_data->start);
  			pLockData->fl_end = pLockData->fl_start +
  					le64_to_cpu(parm_data->length) - 1;
  			pLockData->fl_pid = le32_to_cpu(parm_data->pid);
f05337c6a   Pavel Shilovsky   not overwriting f...
2486
  		}
08547b036   Steve French   [CIFS] Add posix ...
2487
  	}
50c2f7538   Steve French   [CIFS] whitespace...
2488

fc94cdb94   Steve French   [CIFS] Fix new PO...
2489
  plk_err_exit:
08547b036   Steve French   [CIFS] Add posix ...
2490
2491
  	if (pSMB)
  		cifs_small_buf_release(pSMB);
6d81ed1ec   Sachin Prabhu   cifs: replace cod...
2492
  	free_rsp_buf(resp_buf_type, iov[0].iov_base);
133672efb   Steve French   [CIFS] Fix buffer...
2493

08547b036   Steve French   [CIFS] Add posix ...
2494
2495
2496
2497
2498
2499
2500
2501
  	/* Note: On -EAGAIN error only caller can retry on handle based calls
  	   since file handle passed in no longer valid */
  
  	return rc;
  }
  
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2502
  CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2503
2504
2505
  {
  	int rc = 0;
  	CLOSE_REQ *pSMB = NULL;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2506
2507
  	cifs_dbg(FYI, "In CIFSSMBClose
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2508
2509
2510
  
  /* do not retry on dead session on close */
  	rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
790fe579f   Steve French   [CIFS] more white...
2511
  	if (rc == -EAGAIN)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2512
2513
2514
  		return 0;
  	if (rc)
  		return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2515
  	pSMB->FileID = (__u16) smb_file_id;
b815f1e55   Steve French   [CIFS] Allow for ...
2516
  	pSMB->LastWriteTime = 0xFFFFFFFF;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2517
  	pSMB->ByteCount = 0;
792af7b05   Pavel Shilovsky   CIFS: Separate pr...
2518
  	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
44c581866   Pavel Shilovsky   CIFS: Move clear/...
2519
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_closes);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2520
  	if (rc) {
790fe579f   Steve French   [CIFS] more white...
2521
  		if (rc != -EINTR) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2522
  			/* EINTR is expected when user ctl-c to kill app */
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2523
2524
  			cifs_dbg(VFS, "Send error in Close = %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2525
2526
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2527
  	/* Since session is dead, file will be closed on server already */
790fe579f   Steve French   [CIFS] more white...
2528
  	if (rc == -EAGAIN)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2529
2530
2531
2532
2533
2534
  		rc = 0;
  
  	return rc;
  }
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2535
  CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
b298f2235   Steve French   [CIFS] Send SMB f...
2536
2537
2538
  {
  	int rc = 0;
  	FLUSH_REQ *pSMB = NULL;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2539
2540
  	cifs_dbg(FYI, "In CIFSSMBFlush
  ");
b298f2235   Steve French   [CIFS] Send SMB f...
2541
2542
2543
2544
2545
2546
2547
  
  	rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
  	if (rc)
  		return rc;
  
  	pSMB->FileID = (__u16) smb_file_id;
  	pSMB->ByteCount = 0;
792af7b05   Pavel Shilovsky   CIFS: Separate pr...
2548
  	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
44c581866   Pavel Shilovsky   CIFS: Move clear/...
2549
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);
b298f2235   Steve French   [CIFS] Send SMB f...
2550
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2551
2552
  		cifs_dbg(VFS, "Send error in Flush = %d
  ", rc);
b298f2235   Steve French   [CIFS] Send SMB f...
2553
2554
2555
2556
2557
  
  	return rc;
  }
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2558
  CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
2559
2560
  	      const char *from_name, const char *to_name,
  	      struct cifs_sb_info *cifs_sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2561
2562
2563
2564
2565
2566
2567
  {
  	int rc = 0;
  	RENAME_REQ *pSMB = NULL;
  	RENAME_RSP *pSMBr = NULL;
  	int bytes_returned;
  	int name_len, name_len2;
  	__u16 count;
2baa26825   Steve French   Remap reserved po...
2568
  	int remap = cifs_remap(cifs_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2569

f96637be0   Joe Perches   [CIFS] cifs: Rena...
2570
2571
  	cifs_dbg(FYI, "In CIFSSMBRename
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
  renameRetry:
  	rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	pSMB->BufferFormat = 0x04;
  	pSMB->SearchAttributes =
  	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
  			ATTR_DIRECTORY);
  
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
2584
2585
2586
  		name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
  					      from_name, PATH_MAX,
  					      cifs_sb->local_nls, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2587
2588
2589
2590
2591
2592
  		name_len++;	/* trailing null */
  		name_len *= 2;
  		pSMB->OldFileName[name_len] = 0x04;	/* pad */
  	/* protocol requires ASCII signature byte on Unicode string */
  		pSMB->OldFileName[name_len + 1] = 0x00;
  		name_len2 =
acbbb76a2   Steve French   CIFS: Rename *UCS...
2593
  		    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
2594
2595
  				       to_name, PATH_MAX, cifs_sb->local_nls,
  				       remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2596
2597
  		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
  		name_len2 *= 2;	/* convert to bytes */
50c2f7538   Steve French   [CIFS] whitespace...
2598
  	} else {	/* BB improve the check for buffer overruns BB */
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
2599
  		name_len = strnlen(from_name, PATH_MAX);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2600
  		name_len++;	/* trailing null */
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
2601
2602
  		strncpy(pSMB->OldFileName, from_name, name_len);
  		name_len2 = strnlen(to_name, PATH_MAX);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2603
2604
  		name_len2++;	/* trailing null */
  		pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
2605
  		strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2606
2607
2608
2609
2610
  		name_len2++;	/* trailing null */
  		name_len2++;	/* signature byte */
  	}
  
  	count = 1 /* 1st signature byte */  + name_len + name_len2;
be8e3b004   Steve French   consistently use ...
2611
  	inc_rfc1001_len(pSMB, count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2612
2613
2614
2615
  	pSMB->ByteCount = cpu_to_le16(count);
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
44c581866   Pavel Shilovsky   CIFS: Move clear/...
2616
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);
ad7a2926b   Steve French   [CIFS] reduce che...
2617
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2618
2619
  		cifs_dbg(FYI, "Send error in rename = %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2620

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2621
2622
2623
2624
2625
2626
2627
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto renameRetry;
  
  	return rc;
  }
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2628
  int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
391e57555   Jeff Layton   cifs: remove NULL...
2629
  		int netfid, const char *target_name,
50c2f7538   Steve French   [CIFS] whitespace...
2630
  		const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2631
2632
2633
  {
  	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
  	struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
50c2f7538   Steve French   [CIFS] whitespace...
2634
  	struct set_file_rename *rename_info;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2635
2636
2637
2638
2639
2640
  	char *data_offset;
  	char dummy_string[30];
  	int rc = 0;
  	int bytes_returned = 0;
  	int len_of_str;
  	__u16 params, param_offset, offset, count, byte_count;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2641
2642
  	cifs_dbg(FYI, "Rename to File by handle
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
  			(void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	params = 6;
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  	pSMB->Flags = 0;
  	pSMB->Timeout = 0;
  	pSMB->Reserved2 = 0;
  	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
  	offset = param_offset + params;
  
  	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
  	rename_info = (struct set_file_rename *) data_offset;
  	pSMB->MaxParameterCount = cpu_to_le16(2);
ad7a2926b   Steve French   [CIFS] reduce che...
2660
  	pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
  	pSMB->SetupCount = 1;
  	pSMB->Reserved3 = 0;
  	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
  	byte_count = 3 /* pad */  + params;
  	pSMB->ParameterCount = cpu_to_le16(params);
  	pSMB->TotalParameterCount = pSMB->ParameterCount;
  	pSMB->ParameterOffset = cpu_to_le16(param_offset);
  	pSMB->DataOffset = cpu_to_le16(offset);
  	/* construct random name ".cifs_tmp<inodenum><mid>" */
  	rename_info->overwrite = cpu_to_le32(1);
  	rename_info->root_fid  = 0;
  	/* unicode only call */
790fe579f   Steve French   [CIFS] more white...
2673
  	if (target_name == NULL) {
50c2f7538   Steve French   [CIFS] whitespace...
2674
  		sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
acbbb76a2   Steve French   CIFS: Rename *UCS...
2675
2676
  		len_of_str =
  			cifsConvertToUTF16((__le16 *)rename_info->target_name,
737b758c9   Steve French   [PATCH] cifs: cha...
2677
  					dummy_string, 24, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2678
  	} else {
acbbb76a2   Steve French   CIFS: Rename *UCS...
2679
2680
  		len_of_str =
  			cifsConvertToUTF16((__le16 *)rename_info->target_name,
50c2f7538   Steve French   [CIFS] whitespace...
2681
2682
  					target_name, PATH_MAX, nls_codepage,
  					remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2683
2684
  	}
  	rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
391e57555   Jeff Layton   cifs: remove NULL...
2685
  	count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2686
2687
2688
2689
2690
2691
2692
  	byte_count += count;
  	pSMB->DataCount = cpu_to_le16(count);
  	pSMB->TotalDataCount = pSMB->DataCount;
  	pSMB->Fid = netfid;
  	pSMB->InformationLevel =
  		cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
  	pSMB->Reserved4 = 0;
be8e3b004   Steve French   consistently use ...
2693
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2694
2695
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  	rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
50c2f7538   Steve French   [CIFS] whitespace...
2696
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
44c581866   Pavel Shilovsky   CIFS: Move clear/...
2697
  	cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);
ad7a2926b   Steve French   [CIFS] reduce che...
2698
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2699
2700
2701
  		cifs_dbg(FYI, "Send error in Rename (by file handle) = %d
  ",
  			 rc);
a5a2b489b   Steve French   [CIFS] Make CIFS ...
2702

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2703
2704
2705
2706
2707
2708
2709
2710
2711
  	cifs_buf_release(pSMB);
  
  	/* Note: On -EAGAIN error only caller can retry on handle based calls
  		since file handle passed in no longer valid */
  
  	return rc;
  }
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2712
2713
2714
  CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon,
  	    const char *fromName, const __u16 target_tid, const char *toName,
  	    const int flags, const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2715
2716
2717
2718
2719
2720
2721
  {
  	int rc = 0;
  	COPY_REQ *pSMB = NULL;
  	COPY_RSP *pSMBr = NULL;
  	int bytes_returned;
  	int name_len, name_len2;
  	__u16 count;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2722
2723
  	cifs_dbg(FYI, "In CIFSSMBCopy
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
  copyRetry:
  	rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
  			(void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	pSMB->BufferFormat = 0x04;
  	pSMB->Tid2 = target_tid;
  
  	pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
  
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
acbbb76a2   Steve French   CIFS: Rename *UCS...
2736
2737
2738
  		name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
  					      fromName, PATH_MAX, nls_codepage,
  					      remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2739
2740
2741
2742
2743
  		name_len++;     /* trailing null */
  		name_len *= 2;
  		pSMB->OldFileName[name_len] = 0x04;     /* pad */
  		/* protocol requires ASCII signature byte on Unicode string */
  		pSMB->OldFileName[name_len + 1] = 0x00;
50c2f7538   Steve French   [CIFS] whitespace...
2744
  		name_len2 =
acbbb76a2   Steve French   CIFS: Rename *UCS...
2745
2746
  		    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
  				       toName, PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2747
2748
  		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
  		name_len2 *= 2; /* convert to bytes */
50c2f7538   Steve French   [CIFS] whitespace...
2749
  	} else { 	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
  		name_len = strnlen(fromName, PATH_MAX);
  		name_len++;     /* trailing null */
  		strncpy(pSMB->OldFileName, fromName, name_len);
  		name_len2 = strnlen(toName, PATH_MAX);
  		name_len2++;    /* trailing null */
  		pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
  		strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
  		name_len2++;    /* trailing null */
  		name_len2++;    /* signature byte */
  	}
  
  	count = 1 /* 1st signature byte */  + name_len + name_len2;
be8e3b004   Steve French   consistently use ...
2762
  	inc_rfc1001_len(pSMB, count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2763
2764
2765
2766
2767
  	pSMB->ByteCount = cpu_to_le16(count);
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2768
2769
2770
  		cifs_dbg(FYI, "Send error in copy = %d with %d files copied
  ",
  			 rc, le16_to_cpu(pSMBr->CopyCount));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2771
  	}
0d817bc0d   Steve French   [CIFS] Remove red...
2772
  	cifs_buf_release(pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2773
2774
2775
2776
2777
2778
2779
2780
  
  	if (rc == -EAGAIN)
  		goto copyRetry;
  
  	return rc;
  }
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2781
  CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2782
  		      const char *fromName, const char *toName,
bc8ebdc4f   Nakajima Akira   Fix that several ...
2783
  		      const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2784
2785
2786
2787
2788
2789
2790
2791
2792
  {
  	TRANSACTION2_SPI_REQ *pSMB = NULL;
  	TRANSACTION2_SPI_RSP *pSMBr = NULL;
  	char *data_offset;
  	int name_len;
  	int name_len_target;
  	int rc = 0;
  	int bytes_returned = 0;
  	__u16 params, param_offset, offset, byte_count;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2793
2794
  	cifs_dbg(FYI, "In Symlink Unix style
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2795
2796
2797
2798
2799
2800
2801
2802
  createSymLinkRetry:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		name_len =
bc8ebdc4f   Nakajima Akira   Fix that several ...
2803
2804
2805
  		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fromName,
  				/* find define for this maxpathcomponent */
  					PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2806
2807
  		name_len++;	/* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
2808
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
  		name_len = strnlen(fromName, PATH_MAX);
  		name_len++;	/* trailing null */
  		strncpy(pSMB->FileName, fromName, name_len);
  	}
  	params = 6 + name_len;
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  	pSMB->Flags = 0;
  	pSMB->Timeout = 0;
  	pSMB->Reserved2 = 0;
  	param_offset = offsetof(struct smb_com_transaction2_spi_req,
50c2f7538   Steve French   [CIFS] whitespace...
2820
  				InformationLevel) - 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2821
2822
2823
2824
2825
  	offset = param_offset + params;
  
  	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		name_len_target =
bc8ebdc4f   Nakajima Akira   Fix that several ...
2826
2827
2828
  		    cifsConvertToUTF16((__le16 *) data_offset, toName,
  				/* find define for this maxpathcomponent */
  					PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2829
2830
  		name_len_target++;	/* trailing null */
  		name_len_target *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
2831
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
  		name_len_target = strnlen(toName, PATH_MAX);
  		name_len_target++;	/* trailing null */
  		strncpy(data_offset, toName, name_len_target);
  	}
  
  	pSMB->MaxParameterCount = cpu_to_le16(2);
  	/* BB find exact max on data count below from sess */
  	pSMB->MaxDataCount = cpu_to_le16(1000);
  	pSMB->SetupCount = 1;
  	pSMB->Reserved3 = 0;
  	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
  	byte_count = 3 /* pad */  + params + name_len_target;
  	pSMB->DataCount = cpu_to_le16(name_len_target);
  	pSMB->ParameterCount = cpu_to_le16(params);
  	pSMB->TotalDataCount = pSMB->DataCount;
  	pSMB->TotalParameterCount = pSMB->ParameterCount;
  	pSMB->ParameterOffset = cpu_to_le16(param_offset);
  	pSMB->DataOffset = cpu_to_le16(offset);
  	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
  	pSMB->Reserved4 = 0;
be8e3b004   Steve French   consistently use ...
2852
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2853
2854
2855
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
44c581866   Pavel Shilovsky   CIFS: Move clear/...
2856
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);
ad7a2926b   Steve French   [CIFS] reduce che...
2857
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2858
2859
2860
  		cifs_dbg(FYI, "Send error in SetPathInfo create symlink = %d
  ",
  			 rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2861

0d817bc0d   Steve French   [CIFS] Remove red...
2862
  	cifs_buf_release(pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2863
2864
2865
2866
2867
2868
2869
2870
  
  	if (rc == -EAGAIN)
  		goto createSymLinkRetry;
  
  	return rc;
  }
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2871
  CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2872
  		       const char *fromName, const char *toName,
737b758c9   Steve French   [PATCH] cifs: cha...
2873
  		       const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2874
2875
2876
2877
2878
2879
2880
2881
2882
  {
  	TRANSACTION2_SPI_REQ *pSMB = NULL;
  	TRANSACTION2_SPI_RSP *pSMBr = NULL;
  	char *data_offset;
  	int name_len;
  	int name_len_target;
  	int rc = 0;
  	int bytes_returned = 0;
  	__u16 params, param_offset, offset, byte_count;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2883
2884
  	cifs_dbg(FYI, "In Create Hard link Unix style
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2885
2886
2887
2888
2889
2890
2891
  createHardLinkRetry:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
acbbb76a2   Steve French   CIFS: Rename *UCS...
2892
2893
  		name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
  					      PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2894
2895
  		name_len++;	/* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
2896
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
  		name_len = strnlen(toName, PATH_MAX);
  		name_len++;	/* trailing null */
  		strncpy(pSMB->FileName, toName, name_len);
  	}
  	params = 6 + name_len;
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  	pSMB->Flags = 0;
  	pSMB->Timeout = 0;
  	pSMB->Reserved2 = 0;
  	param_offset = offsetof(struct smb_com_transaction2_spi_req,
50c2f7538   Steve French   [CIFS] whitespace...
2908
  				InformationLevel) - 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2909
2910
2911
2912
2913
  	offset = param_offset + params;
  
  	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		name_len_target =
acbbb76a2   Steve French   CIFS: Rename *UCS...
2914
2915
  		    cifsConvertToUTF16((__le16 *) data_offset, fromName,
  				       PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2916
2917
  		name_len_target++;	/* trailing null */
  		name_len_target *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
2918
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
  		name_len_target = strnlen(fromName, PATH_MAX);
  		name_len_target++;	/* trailing null */
  		strncpy(data_offset, fromName, name_len_target);
  	}
  
  	pSMB->MaxParameterCount = cpu_to_le16(2);
  	/* BB find exact max on data count below from sess*/
  	pSMB->MaxDataCount = cpu_to_le16(1000);
  	pSMB->SetupCount = 1;
  	pSMB->Reserved3 = 0;
  	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
  	byte_count = 3 /* pad */  + params + name_len_target;
  	pSMB->ParameterCount = cpu_to_le16(params);
  	pSMB->TotalParameterCount = pSMB->ParameterCount;
  	pSMB->DataCount = cpu_to_le16(name_len_target);
  	pSMB->TotalDataCount = pSMB->DataCount;
  	pSMB->ParameterOffset = cpu_to_le16(param_offset);
  	pSMB->DataOffset = cpu_to_le16(offset);
  	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
  	pSMB->Reserved4 = 0;
be8e3b004   Steve French   consistently use ...
2939
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2940
2941
2942
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
44c581866   Pavel Shilovsky   CIFS: Move clear/...
2943
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
ad7a2926b   Steve French   [CIFS] reduce che...
2944
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2945
2946
2947
  		cifs_dbg(FYI, "Send error in SetPathInfo (hard link) = %d
  ",
  			 rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2948
2949
2950
2951
2952
2953
2954
2955
2956
  
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto createHardLinkRetry;
  
  	return rc;
  }
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2957
  CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
d6e906f1b   Steve French   CIFS: Move hardli...
2958
2959
  		   const char *from_name, const char *to_name,
  		   struct cifs_sb_info *cifs_sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2960
2961
2962
2963
2964
2965
2966
  {
  	int rc = 0;
  	NT_RENAME_REQ *pSMB = NULL;
  	RENAME_RSP *pSMBr = NULL;
  	int bytes_returned;
  	int name_len, name_len2;
  	__u16 count;
2baa26825   Steve French   Remap reserved po...
2967
  	int remap = cifs_remap(cifs_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2968

f96637be0   Joe Perches   [CIFS] cifs: Rena...
2969
2970
  	cifs_dbg(FYI, "In CIFSCreateHardLink
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
  winCreateHardLinkRetry:
  
  	rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	pSMB->SearchAttributes =
  	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
  			ATTR_DIRECTORY);
  	pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
  	pSMB->ClusterCount = 0;
  
  	pSMB->BufferFormat = 0x04;
  
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		name_len =
d6e906f1b   Steve French   CIFS: Move hardli...
2988
2989
  		    cifsConvertToUTF16((__le16 *) pSMB->OldFileName, from_name,
  				       PATH_MAX, cifs_sb->local_nls, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2990
2991
  		name_len++;	/* trailing null */
  		name_len *= 2;
fcc7c09d9   Jeff Layton   cifs: fix buffer ...
2992
2993
2994
2995
  
  		/* protocol specifies ASCII buffer format (0x04) for unicode */
  		pSMB->OldFileName[name_len] = 0x04;
  		pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2996
  		name_len2 =
acbbb76a2   Steve French   CIFS: Rename *UCS...
2997
  		    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
d6e906f1b   Steve French   CIFS: Move hardli...
2998
2999
  				       to_name, PATH_MAX, cifs_sb->local_nls,
  				       remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3000
3001
  		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
  		name_len2 *= 2;	/* convert to bytes */
50c2f7538   Steve French   [CIFS] whitespace...
3002
  	} else {	/* BB improve the check for buffer overruns BB */
d6e906f1b   Steve French   CIFS: Move hardli...
3003
  		name_len = strnlen(from_name, PATH_MAX);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3004
  		name_len++;	/* trailing null */
d6e906f1b   Steve French   CIFS: Move hardli...
3005
3006
  		strncpy(pSMB->OldFileName, from_name, name_len);
  		name_len2 = strnlen(to_name, PATH_MAX);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3007
3008
  		name_len2++;	/* trailing null */
  		pSMB->OldFileName[name_len] = 0x04;	/* 2nd buffer format */
d6e906f1b   Steve French   CIFS: Move hardli...
3009
  		strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3010
3011
3012
3013
3014
  		name_len2++;	/* trailing null */
  		name_len2++;	/* signature byte */
  	}
  
  	count = 1 /* string type byte */  + name_len + name_len2;
be8e3b004   Steve French   consistently use ...
3015
  	inc_rfc1001_len(pSMB, count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3016
3017
3018
3019
  	pSMB->ByteCount = cpu_to_le16(count);
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
44c581866   Pavel Shilovsky   CIFS: Move clear/...
3020
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
ad7a2926b   Steve French   [CIFS] reduce che...
3021
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3022
3023
  		cifs_dbg(FYI, "Send error in hard link (NT rename) = %d
  ", rc);
ad7a2926b   Steve French   [CIFS] reduce che...
3024

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3025
3026
3027
3028
3029
3030
3031
3032
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto winCreateHardLinkRetry;
  
  	return rc;
  }
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
3033
  CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
460b96960   Jeff Layton   cifs: change CIFS...
3034
  			const unsigned char *searchName, char **symlinkinfo,
bc8ebdc4f   Nakajima Akira   Fix that several ...
3035
  			const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3036
3037
3038
3039
3040
3041
3042
3043
  {
  /* SMB_QUERY_FILE_UNIX_LINK */
  	TRANSACTION2_QPI_REQ *pSMB = NULL;
  	TRANSACTION2_QPI_RSP *pSMBr = NULL;
  	int rc = 0;
  	int bytes_returned;
  	int name_len;
  	__u16 params, byte_count;
460b96960   Jeff Layton   cifs: change CIFS...
3044
  	char *data_start;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3045

f96637be0   Joe Perches   [CIFS] cifs: Rena...
3046
3047
  	cifs_dbg(FYI, "In QPathSymLinkInfo (Unix) for path %s
  ", searchName);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3048
3049
3050
3051
3052
3053
3054
3055
3056
  
  querySymLinkRetry:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		name_len =
bc8ebdc4f   Nakajima Akira   Fix that several ...
3057
3058
3059
  			cifsConvertToUTF16((__le16 *) pSMB->FileName,
  					   searchName, PATH_MAX, nls_codepage,
  					   remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3060
3061
  		name_len++;	/* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
3062
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3063
3064
3065
3066
3067
3068
3069
3070
  		name_len = strnlen(searchName, PATH_MAX);
  		name_len++;	/* trailing null */
  		strncpy(pSMB->FileName, searchName, name_len);
  	}
  
  	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
  	pSMB->TotalDataCount = 0;
  	pSMB->MaxParameterCount = cpu_to_le16(2);
46a7574ca   Jeff Layton   cifs: fix artific...
3071
  	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3072
3073
3074
3075
3076
3077
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  	pSMB->Flags = 0;
  	pSMB->Timeout = 0;
  	pSMB->Reserved2 = 0;
  	pSMB->ParameterOffset = cpu_to_le16(offsetof(
50c2f7538   Steve French   [CIFS] whitespace...
3078
  	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
  	pSMB->DataCount = 0;
  	pSMB->DataOffset = 0;
  	pSMB->SetupCount = 1;
  	pSMB->Reserved3 = 0;
  	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
  	byte_count = params + 1 /* pad */ ;
  	pSMB->TotalParameterCount = cpu_to_le16(params);
  	pSMB->ParameterCount = pSMB->TotalParameterCount;
  	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
  	pSMB->Reserved4 = 0;
be8e3b004   Steve French   consistently use ...
3089
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3090
3091
3092
3093
3094
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3095
3096
  		cifs_dbg(FYI, "Send error in QuerySymLinkInfo = %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3097
3098
3099
3100
  	} else {
  		/* decode response */
  
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3101
  		/* BB also check enough total bytes returned */
820a803ff   Jeff Layton   cifs: keep BCC in...
3102
  		if (rc || get_bcc(&pSMBr->hdr) < 2)
460b96960   Jeff Layton   cifs: change CIFS...
3103
  			rc = -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3104
  		else {
0e0d2cf32   Steve French   [CIFS] Remove spa...
3105
  			bool is_unicode;
460b96960   Jeff Layton   cifs: change CIFS...
3106
3107
3108
3109
  			u16 count = le16_to_cpu(pSMBr->t2.DataCount);
  
  			data_start = ((char *) &pSMBr->hdr.Protocol) +
  					   le16_to_cpu(pSMBr->t2.DataOffset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3110

0e0d2cf32   Steve French   [CIFS] Remove spa...
3111
3112
3113
3114
  			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
  				is_unicode = true;
  			else
  				is_unicode = false;
737b758c9   Steve French   [PATCH] cifs: cha...
3115
  			/* BB FIXME investigate remapping reserved chars here */
acbbb76a2   Steve French   CIFS: Rename *UCS...
3116
3117
  			*symlinkinfo = cifs_strndup_from_utf16(data_start,
  					count, is_unicode, nls_codepage);
8b6427a2a   Jeff Layton   cifs: fix pointer...
3118
  			if (!*symlinkinfo)
460b96960   Jeff Layton   cifs: change CIFS...
3119
  				rc = -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3120
3121
3122
3123
3124
3125
3126
  		}
  	}
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto querySymLinkRetry;
  	return rc;
  }
c52a95545   Steve French   Don't compile in ...
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
  /*
   *	Recent Windows versions now create symlinks more frequently
   *	and they use the "reparse point" mechanism below.  We can of course
   *	do symlinks nicely to Samba and other servers which support the
   *	CIFS Unix Extensions and we can also do SFU symlinks and "client only"
   *	"MF" symlinks optionally, but for recent Windows we really need to
   *	reenable the code below and fix the cifs_symlink callers to handle this.
   *	In the interim this code has been moved to its own config option so
   *	it is not compiled in by default until callers fixed up and more tested.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3137
  int
d244bf2df   Pavel Shilovsky   CIFS: Implement f...
3138
3139
3140
  CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
  		    __u16 fid, char **symlinkinfo,
  		    const struct nls_table *nls_codepage)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3141
3142
3143
  {
  	int rc = 0;
  	int bytes_returned;
50c2f7538   Steve French   [CIFS] whitespace...
3144
3145
  	struct smb_com_transaction_ioctl_req *pSMB;
  	struct smb_com_transaction_ioctl_rsp *pSMBr;
d244bf2df   Pavel Shilovsky   CIFS: Implement f...
3146
3147
3148
  	bool is_unicode;
  	unsigned int sub_len;
  	char *sub_start;
c31f33071   Steve French   do not treat non-...
3149
3150
  	struct reparse_symlink_data *reparse_buf;
  	struct reparse_posix_data *posix_buf;
d244bf2df   Pavel Shilovsky   CIFS: Implement f...
3151
3152
3153
3154
3155
  	__u32 data_offset, data_count;
  	char *end_of_smb;
  
  	cifs_dbg(FYI, "In Windows reparse style QueryLink for fid %u
  ", fid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3156
3157
3158
3159
3160
3161
3162
3163
3164
  	rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	pSMB->TotalParameterCount = 0 ;
  	pSMB->TotalDataCount = 0;
  	pSMB->MaxParameterCount = cpu_to_le32(2);
  	/* BB find exact data count max from sess structure BB */
c974befa4   Jeff Layton   cifs: untangle se...
3165
  	pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
  	pSMB->MaxSetupCount = 4;
  	pSMB->Reserved = 0;
  	pSMB->ParameterOffset = 0;
  	pSMB->DataCount = 0;
  	pSMB->DataOffset = 0;
  	pSMB->SetupCount = 4;
  	pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
  	pSMB->ParameterCount = pSMB->TotalParameterCount;
  	pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
  	pSMB->IsFsctl = 1; /* FSCTL */
  	pSMB->IsRootFlag = 0;
  	pSMB->Fid = fid; /* file handle always le */
  	pSMB->ByteCount = 0;
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3183
3184
  		cifs_dbg(FYI, "Send error in QueryReparseLinkInfo = %d
  ", rc);
d244bf2df   Pavel Shilovsky   CIFS: Implement f...
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
  		goto qreparse_out;
  	}
  
  	data_offset = le32_to_cpu(pSMBr->DataOffset);
  	data_count = le32_to_cpu(pSMBr->DataCount);
  	if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
  		/* BB also check enough total bytes returned */
  		rc = -EIO;	/* bad smb */
  		goto qreparse_out;
  	}
  	if (!data_count || (data_count > 2048)) {
  		rc = -EIO;
  		cifs_dbg(FYI, "Invalid return data count on get reparse info ioctl
  ");
  		goto qreparse_out;
  	}
  	end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
c31f33071   Steve French   do not treat non-...
3202
  	reparse_buf = (struct reparse_symlink_data *)
d244bf2df   Pavel Shilovsky   CIFS: Implement f...
3203
3204
3205
3206
  				((char *)&pSMBr->hdr.Protocol + data_offset);
  	if ((char *)reparse_buf >= end_of_smb) {
  		rc = -EIO;
  		goto qreparse_out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3207
  	}
c31f33071   Steve French   do not treat non-...
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
  	if (reparse_buf->ReparseTag == cpu_to_le32(IO_REPARSE_TAG_NFS)) {
  		cifs_dbg(FYI, "NFS style reparse tag
  ");
  		posix_buf =  (struct reparse_posix_data *)reparse_buf;
  
  		if (posix_buf->InodeType != cpu_to_le64(NFS_SPECFILE_LNK)) {
  			cifs_dbg(FYI, "unsupported file type 0x%llx
  ",
  				 le64_to_cpu(posix_buf->InodeType));
  			rc = -EOPNOTSUPP;
  			goto qreparse_out;
  		}
  		is_unicode = true;
  		sub_len = le16_to_cpu(reparse_buf->ReparseDataLength);
  		if (posix_buf->PathBuffer + sub_len > end_of_smb) {
  			cifs_dbg(FYI, "reparse buf beyond SMB
  ");
  			rc = -EIO;
  			goto qreparse_out;
  		}
  		*symlinkinfo = cifs_strndup_from_utf16(posix_buf->PathBuffer,
  				sub_len, is_unicode, nls_codepage);
  		goto qreparse_out;
  	} else if (reparse_buf->ReparseTag !=
  			cpu_to_le32(IO_REPARSE_TAG_SYMLINK)) {
  		rc = -EOPNOTSUPP;
  		goto qreparse_out;
  	}
  
  	/* Reparse tag is NTFS symlink */
  	sub_start = le16_to_cpu(reparse_buf->SubstituteNameOffset) +
  				reparse_buf->PathBuffer;
  	sub_len = le16_to_cpu(reparse_buf->SubstituteNameLength);
  	if (sub_start + sub_len > end_of_smb) {
d244bf2df   Pavel Shilovsky   CIFS: Implement f...
3242
3243
3244
3245
3246
  		cifs_dbg(FYI, "reparse buf beyond SMB
  ");
  		rc = -EIO;
  		goto qreparse_out;
  	}
d244bf2df   Pavel Shilovsky   CIFS: Implement f...
3247
3248
3249
3250
  	if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
  		is_unicode = true;
  	else
  		is_unicode = false;
989c7e512   Steve French   [CIFS] remove che...
3251

d244bf2df   Pavel Shilovsky   CIFS: Implement f...
3252
3253
3254
3255
3256
  	/* BB FIXME investigate remapping reserved chars here */
  	*symlinkinfo = cifs_strndup_from_utf16(sub_start, sub_len, is_unicode,
  					       nls_codepage);
  	if (!*symlinkinfo)
  		rc = -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3257
  qreparse_out:
4a6d87f1d   Steve French   [CIFS] Add missin...
3258
  	cifs_buf_release(pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3259

d244bf2df   Pavel Shilovsky   CIFS: Implement f...
3260
3261
3262
3263
  	/*
  	 * Note: On -EAGAIN error only caller can retry on handle based calls
  	 * since file handle passed in no longer valid.
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3264
3265
  	return rc;
  }
c7f508a99   Steve French   Allow setting per...
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
  int
  CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
  		    __u16 fid)
  {
  	int rc = 0;
  	int bytes_returned;
  	struct smb_com_transaction_compr_ioctl_req *pSMB;
  	struct smb_com_transaction_ioctl_rsp *pSMBr;
  
  	cifs_dbg(FYI, "Set compression for %u
  ", fid);
  	rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	pSMB->compression_state = cpu_to_le16(COMPRESSION_FORMAT_DEFAULT);
  
  	pSMB->TotalParameterCount = 0;
bc09d141e   Fabian Frederick   fs/cifs: remove o...
3285
  	pSMB->TotalDataCount = cpu_to_le32(2);
c7f508a99   Steve French   Allow setting per...
3286
3287
3288
3289
3290
  	pSMB->MaxParameterCount = 0;
  	pSMB->MaxDataCount = 0;
  	pSMB->MaxSetupCount = 4;
  	pSMB->Reserved = 0;
  	pSMB->ParameterOffset = 0;
bc09d141e   Fabian Frederick   fs/cifs: remove o...
3291
  	pSMB->DataCount = cpu_to_le32(2);
c7f508a99   Steve French   Allow setting per...
3292
3293
3294
3295
  	pSMB->DataOffset =
  		cpu_to_le32(offsetof(struct smb_com_transaction_compr_ioctl_req,
  				compression_state) - 4);  /* 84 */
  	pSMB->SetupCount = 4;
bc09d141e   Fabian Frederick   fs/cifs: remove o...
3296
  	pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
c7f508a99   Steve French   Allow setting per...
3297
  	pSMB->ParameterCount = 0;
bc09d141e   Fabian Frederick   fs/cifs: remove o...
3298
  	pSMB->FunctionCode = cpu_to_le32(FSCTL_SET_COMPRESSION);
c7f508a99   Steve French   Allow setting per...
3299
3300
3301
3302
  	pSMB->IsFsctl = 1; /* FSCTL */
  	pSMB->IsRootFlag = 0;
  	pSMB->Fid = fid; /* file handle always le */
  	/* 3 byte pad, followed by 2 byte compress state */
bc09d141e   Fabian Frederick   fs/cifs: remove o...
3303
  	pSMB->ByteCount = cpu_to_le16(5);
c7f508a99   Steve French   Allow setting per...
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
  	inc_rfc1001_len(pSMB, 5);
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  	if (rc)
  		cifs_dbg(FYI, "Send error in SetCompression = %d
  ", rc);
  
  	cifs_buf_release(pSMB);
  
  	/*
  	 * Note: On -EAGAIN error only caller can retry on handle based calls
  	 * since file handle passed in no longer valid.
  	 */
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3320
3321
3322
  #ifdef CONFIG_CIFS_POSIX
  
  /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
50c2f7538   Steve French   [CIFS] whitespace...
3323
3324
  static void cifs_convert_ace(posix_acl_xattr_entry *ace,
  			     struct cifs_posix_ace *cifs_ace)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3325
3326
  {
  	/* u8 cifs fields do not need le conversion */
ff7feac96   Steve French   [CIFS] Fix endian...
3327
3328
3329
  	ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
  	ace->e_tag  = cpu_to_le16(cifs_ace->cifs_e_tag);
  	ace->e_id   = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3330
3331
3332
3333
3334
  /*
  	cifs_dbg(FYI, "perm %d tag %d id %d
  ",
  		 ace->e_perm, ace->e_tag, ace->e_id);
  */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3335
3336
3337
3338
3339
  
  	return;
  }
  
  /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
50c2f7538   Steve French   [CIFS] whitespace...
3340
3341
  static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
  			       const int acl_type, const int size_of_data_area)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3342
3343
3344
3345
  {
  	int size =  0;
  	int i;
  	__u16 count;
50c2f7538   Steve French   [CIFS] whitespace...
3346
3347
3348
  	struct cifs_posix_ace *pACE;
  	struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
  	posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3349
3350
3351
  
  	if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
  		return -EOPNOTSUPP;
45987e006   Andreas Gruenbacher   cifs: Check for e...
3352
  	if (acl_type == ACL_TYPE_ACCESS) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3353
3354
3355
3356
3357
  		count = le16_to_cpu(cifs_acl->access_entry_count);
  		pACE = &cifs_acl->ace_array[0];
  		size = sizeof(struct cifs_posix_acl);
  		size += sizeof(struct cifs_posix_ace) * count;
  		/* check if we would go beyond end of SMB */
790fe579f   Steve French   [CIFS] more white...
3358
  		if (size_of_data_area < size) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3359
3360
3361
  			cifs_dbg(FYI, "bad CIFS POSIX ACL size %d vs. %d
  ",
  				 size_of_data_area, size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3362
3363
  			return -EINVAL;
  		}
45987e006   Andreas Gruenbacher   cifs: Check for e...
3364
  	} else if (acl_type == ACL_TYPE_DEFAULT) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3365
3366
3367
3368
3369
3370
3371
3372
  		count = le16_to_cpu(cifs_acl->access_entry_count);
  		size = sizeof(struct cifs_posix_acl);
  		size += sizeof(struct cifs_posix_ace) * count;
  /* skip past access ACEs to get to default ACEs */
  		pACE = &cifs_acl->ace_array[count];
  		count = le16_to_cpu(cifs_acl->default_entry_count);
  		size += sizeof(struct cifs_posix_ace) * count;
  		/* check if we would go beyond end of SMB */
790fe579f   Steve French   [CIFS] more white...
3373
  		if (size_of_data_area < size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3374
3375
3376
3377
3378
3379
3380
  			return -EINVAL;
  	} else {
  		/* illegal type */
  		return -EINVAL;
  	}
  
  	size = posix_acl_xattr_size(count);
790fe579f   Steve French   [CIFS] more white...
3381
  	if ((buflen == 0) || (local_acl == NULL)) {
50c2f7538   Steve French   [CIFS] whitespace...
3382
  		/* used to query ACL EA size */
790fe579f   Steve French   [CIFS] more white...
3383
  	} else if (size > buflen) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3384
3385
  		return -ERANGE;
  	} else /* buffer big enough */ {
ff7feac96   Steve French   [CIFS] Fix endian...
3386
  		local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
50c2f7538   Steve French   [CIFS] whitespace...
3387
3388
3389
  		for (i = 0; i < count ; i++) {
  			cifs_convert_ace(&local_acl->a_entries[i], pACE);
  			pACE++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3390
3391
3392
3393
  		}
  	}
  	return size;
  }
50c2f7538   Steve French   [CIFS] whitespace...
3394
3395
  static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
  				     const posix_acl_xattr_entry *local_ace)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3396
3397
  {
  	__u16 rc = 0; /* 0 = ACL converted ok */
ff7feac96   Steve French   [CIFS] Fix endian...
3398
3399
  	cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
  	cifs_ace->cifs_e_tag =  le16_to_cpu(local_ace->e_tag);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3400
  	/* BB is there a better way to handle the large uid? */
790fe579f   Steve French   [CIFS] more white...
3401
  	if (local_ace->e_id == cpu_to_le32(-1)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3402
3403
  	/* Probably no need to le convert -1 on any arch but can not hurt */
  		cifs_ace->cifs_uid = cpu_to_le64(-1);
50c2f7538   Steve French   [CIFS] whitespace...
3404
  	} else
ff7feac96   Steve French   [CIFS] Fix endian...
3405
  		cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3406
3407
3408
3409
3410
  /*
  	cifs_dbg(FYI, "perm %d tag %d id %d
  ",
  		 ace->e_perm, ace->e_tag, ace->e_id);
  */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3411
3412
3413
3414
  	return rc;
  }
  
  /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
50c2f7538   Steve French   [CIFS] whitespace...
3415
3416
  static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
  			       const int buflen, const int acl_type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3417
3418
  {
  	__u16 rc = 0;
50c2f7538   Steve French   [CIFS] whitespace...
3419
3420
  	struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
  	posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3421
3422
  	int count;
  	int i;
790fe579f   Steve French   [CIFS] more white...
3423
  	if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3424
3425
3426
  		return 0;
  
  	count = posix_acl_xattr_count((size_t)buflen);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3427
3428
3429
  	cifs_dbg(FYI, "setting acl with %d entries from buf of length %d and version of %d
  ",
  		 count, buflen, le32_to_cpu(local_acl->a_version));
790fe579f   Steve French   [CIFS] more white...
3430
  	if (le32_to_cpu(local_acl->a_version) != 2) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3431
3432
3433
  		cifs_dbg(FYI, "unknown POSIX ACL version %d
  ",
  			 le32_to_cpu(local_acl->a_version));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3434
3435
3436
  		return 0;
  	}
  	cifs_acl->version = cpu_to_le16(1);
b1d933564   Steve French   setfacl removes p...
3437
  	if (acl_type == ACL_TYPE_ACCESS) {
ff7feac96   Steve French   [CIFS] Fix endian...
3438
  		cifs_acl->access_entry_count = cpu_to_le16(count);
bc09d141e   Fabian Frederick   fs/cifs: remove o...
3439
  		cifs_acl->default_entry_count = cpu_to_le16(0xFFFF);
b1d933564   Steve French   setfacl removes p...
3440
  	} else if (acl_type == ACL_TYPE_DEFAULT) {
ff7feac96   Steve French   [CIFS] Fix endian...
3441
  		cifs_acl->default_entry_count = cpu_to_le16(count);
bc09d141e   Fabian Frederick   fs/cifs: remove o...
3442
  		cifs_acl->access_entry_count = cpu_to_le16(0xFFFF);
b1d933564   Steve French   setfacl removes p...
3443
  	} else {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3444
3445
  		cifs_dbg(FYI, "unknown ACL type %d
  ", acl_type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3446
3447
  		return 0;
  	}
50c2f7538   Steve French   [CIFS] whitespace...
3448
  	for (i = 0; i < count; i++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3449
3450
  		rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
  					&local_acl->a_entries[i]);
790fe579f   Steve French   [CIFS] more white...
3451
  		if (rc != 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3452
3453
3454
3455
  			/* ACE not converted */
  			break;
  		}
  	}
790fe579f   Steve French   [CIFS] more white...
3456
  	if (rc == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3457
3458
3459
3460
3461
3462
3463
3464
  		rc = (__u16)(count * sizeof(struct cifs_posix_ace));
  		rc += sizeof(struct cifs_posix_acl);
  		/* BB add check to make sure ACL does not overflow SMB */
  	}
  	return rc;
  }
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
3465
  CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
50c2f7538   Steve French   [CIFS] whitespace...
3466
3467
3468
  		   const unsigned char *searchName,
  		   char *acl_inf, const int buflen, const int acl_type,
  		   const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3469
3470
3471
3472
3473
3474
3475
3476
  {
  /* SMB_QUERY_POSIX_ACL */
  	TRANSACTION2_QPI_REQ *pSMB = NULL;
  	TRANSACTION2_QPI_RSP *pSMBr = NULL;
  	int rc = 0;
  	int bytes_returned;
  	int name_len;
  	__u16 params, byte_count;
50c2f7538   Steve French   [CIFS] whitespace...
3477

f96637be0   Joe Perches   [CIFS] cifs: Rena...
3478
3479
  	cifs_dbg(FYI, "In GetPosixACL (Unix) for path %s
  ", searchName);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3480
3481
3482
3483
3484
3485
  
  queryAclRetry:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  		(void **) &pSMBr);
  	if (rc)
  		return rc;
50c2f7538   Steve French   [CIFS] whitespace...
3486

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3487
3488
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		name_len =
acbbb76a2   Steve French   CIFS: Rename *UCS...
3489
3490
3491
  			cifsConvertToUTF16((__le16 *) pSMB->FileName,
  					   searchName, PATH_MAX, nls_codepage,
  					   remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3492
3493
3494
3495
  		name_len++;     /* trailing null */
  		name_len *= 2;
  		pSMB->FileName[name_len] = 0;
  		pSMB->FileName[name_len+1] = 0;
50c2f7538   Steve French   [CIFS] whitespace...
3496
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3497
3498
3499
3500
3501
3502
3503
3504
  		name_len = strnlen(searchName, PATH_MAX);
  		name_len++;     /* trailing null */
  		strncpy(pSMB->FileName, searchName, name_len);
  	}
  
  	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
  	pSMB->TotalDataCount = 0;
  	pSMB->MaxParameterCount = cpu_to_le16(2);
50c2f7538   Steve French   [CIFS] whitespace...
3505
  	/* BB find exact max data count below from sess structure BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3506
3507
3508
3509
3510
3511
3512
  	pSMB->MaxDataCount = cpu_to_le16(4000);
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  	pSMB->Flags = 0;
  	pSMB->Timeout = 0;
  	pSMB->Reserved2 = 0;
  	pSMB->ParameterOffset = cpu_to_le16(
50c2f7538   Steve French   [CIFS] whitespace...
3513
3514
  		offsetof(struct smb_com_transaction2_qpi_req,
  			 InformationLevel) - 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
  	pSMB->DataCount = 0;
  	pSMB->DataOffset = 0;
  	pSMB->SetupCount = 1;
  	pSMB->Reserved3 = 0;
  	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
  	byte_count = params + 1 /* pad */ ;
  	pSMB->TotalParameterCount = cpu_to_le16(params);
  	pSMB->ParameterCount = pSMB->TotalParameterCount;
  	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
  	pSMB->Reserved4 = 0;
be8e3b004   Steve French   consistently use ...
3525
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3526
3527
3528
3529
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
44c581866   Pavel Shilovsky   CIFS: Move clear/...
3530
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3531
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3532
3533
  		cifs_dbg(FYI, "Send error in Query POSIX ACL = %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3534
3535
  	} else {
  		/* decode response */
50c2f7538   Steve French   [CIFS] whitespace...
3536

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3537
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3538
  		/* BB also check enough total bytes returned */
820a803ff   Jeff Layton   cifs: keep BCC in...
3539
  		if (rc || get_bcc(&pSMBr->hdr) < 2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3540
3541
3542
3543
3544
3545
  			rc = -EIO;      /* bad smb */
  		else {
  			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
  			__u16 count = le16_to_cpu(pSMBr->t2.DataCount);
  			rc = cifs_copy_posix_acl(acl_inf,
  				(char *)&pSMBr->hdr.Protocol+data_offset,
50c2f7538   Steve French   [CIFS] whitespace...
3546
  				buflen, acl_type, count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3547
3548
3549
3550
3551
3552
3553
3554
3555
  		}
  	}
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto queryAclRetry;
  	return rc;
  }
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
3556
  CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
50c2f7538   Steve French   [CIFS] whitespace...
3557
3558
3559
3560
  		   const unsigned char *fileName,
  		   const char *local_acl, const int buflen,
  		   const int acl_type,
  		   const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3561
3562
3563
3564
3565
3566
3567
3568
  {
  	struct smb_com_transaction2_spi_req *pSMB = NULL;
  	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
  	char *parm_data;
  	int name_len;
  	int rc = 0;
  	int bytes_returned = 0;
  	__u16 params, byte_count, data_count, param_offset, offset;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3569
3570
  	cifs_dbg(FYI, "In SetPosixACL (Unix) for path %s
  ", fileName);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3571
3572
  setAclRetry:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
50c2f7538   Steve French   [CIFS] whitespace...
3573
  		      (void **) &pSMBr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3574
3575
3576
3577
  	if (rc)
  		return rc;
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		name_len =
acbbb76a2   Steve French   CIFS: Rename *UCS...
3578
3579
  			cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
  					   PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3580
3581
  		name_len++;     /* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
3582
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3583
3584
3585
3586
3587
3588
  		name_len = strnlen(fileName, PATH_MAX);
  		name_len++;     /* trailing null */
  		strncpy(pSMB->FileName, fileName, name_len);
  	}
  	params = 6 + name_len;
  	pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5e   Steve French   [CIFS] cleanup ol...
3589
3590
  	/* BB find max SMB size from sess */
  	pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3591
3592
3593
3594
3595
3596
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  	pSMB->Flags = 0;
  	pSMB->Timeout = 0;
  	pSMB->Reserved2 = 0;
  	param_offset = offsetof(struct smb_com_transaction2_spi_req,
50c2f7538   Steve French   [CIFS] whitespace...
3597
  				InformationLevel) - 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3598
3599
3600
3601
3602
  	offset = param_offset + params;
  	parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
  	pSMB->ParameterOffset = cpu_to_le16(param_offset);
  
  	/* convert to on the wire format for POSIX ACL */
50c2f7538   Steve French   [CIFS] whitespace...
3603
  	data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3604

790fe579f   Steve French   [CIFS] more white...
3605
  	if (data_count == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
  		rc = -EOPNOTSUPP;
  		goto setACLerrorExit;
  	}
  	pSMB->DataOffset = cpu_to_le16(offset);
  	pSMB->SetupCount = 1;
  	pSMB->Reserved3 = 0;
  	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
  	pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
  	byte_count = 3 /* pad */  + params + data_count;
  	pSMB->DataCount = cpu_to_le16(data_count);
  	pSMB->TotalDataCount = pSMB->DataCount;
  	pSMB->ParameterCount = cpu_to_le16(params);
  	pSMB->TotalParameterCount = pSMB->ParameterCount;
  	pSMB->Reserved4 = 0;
be8e3b004   Steve French   consistently use ...
3620
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3621
3622
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
50c2f7538   Steve French   [CIFS] whitespace...
3623
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
ad7a2926b   Steve French   [CIFS] reduce che...
3624
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3625
3626
  		cifs_dbg(FYI, "Set POSIX ACL returned %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3627
3628
3629
3630
3631
3632
3633
  
  setACLerrorExit:
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto setAclRetry;
  	return rc;
  }
f654bac22   Steve French   [PATCH] cifs: add...
3634
3635
  /* BB fix tabs in this function FIXME BB */
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
3636
  CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
ad7a2926b   Steve French   [CIFS] reduce che...
3637
  	       const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
f654bac22   Steve French   [PATCH] cifs: add...
3638
  {
50c2f7538   Steve French   [CIFS] whitespace...
3639
3640
3641
3642
3643
  	int rc = 0;
  	struct smb_t2_qfi_req *pSMB = NULL;
  	struct smb_t2_qfi_rsp *pSMBr = NULL;
  	int bytes_returned;
  	__u16 params, byte_count;
f654bac22   Steve French   [PATCH] cifs: add...
3644

f96637be0   Joe Perches   [CIFS] cifs: Rena...
3645
3646
  	cifs_dbg(FYI, "In GetExtAttr
  ");
790fe579f   Steve French   [CIFS] more white...
3647
3648
  	if (tcon == NULL)
  		return -ENODEV;
f654bac22   Steve French   [PATCH] cifs: add...
3649
3650
  
  GetExtAttrRetry:
790fe579f   Steve French   [CIFS] more white...
3651
3652
3653
3654
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  			(void **) &pSMBr);
  	if (rc)
  		return rc;
f654bac22   Steve French   [PATCH] cifs: add...
3655

ad7a2926b   Steve French   [CIFS] reduce che...
3656
  	params = 2 /* level */ + 2 /* fid */;
790fe579f   Steve French   [CIFS] more white...
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
  	pSMB->t2.TotalDataCount = 0;
  	pSMB->t2.MaxParameterCount = cpu_to_le16(4);
  	/* BB find exact max data count below from sess structure BB */
  	pSMB->t2.MaxDataCount = cpu_to_le16(4000);
  	pSMB->t2.MaxSetupCount = 0;
  	pSMB->t2.Reserved = 0;
  	pSMB->t2.Flags = 0;
  	pSMB->t2.Timeout = 0;
  	pSMB->t2.Reserved2 = 0;
  	pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
  					       Fid) - 4);
  	pSMB->t2.DataCount = 0;
  	pSMB->t2.DataOffset = 0;
  	pSMB->t2.SetupCount = 1;
  	pSMB->t2.Reserved3 = 0;
  	pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
  	byte_count = params + 1 /* pad */ ;
  	pSMB->t2.TotalParameterCount = cpu_to_le16(params);
  	pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
  	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
  	pSMB->Pad = 0;
f654bac22   Steve French   [PATCH] cifs: add...
3678
  	pSMB->Fid = netfid;
be8e3b004   Steve French   consistently use ...
3679
  	inc_rfc1001_len(pSMB, byte_count);
790fe579f   Steve French   [CIFS] more white...
3680
3681
3682
3683
3684
  	pSMB->t2.ByteCount = cpu_to_le16(byte_count);
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3685
3686
  		cifs_dbg(FYI, "error %d in GetExtAttr
  ", rc);
790fe579f   Steve French   [CIFS] more white...
3687
3688
3689
  	} else {
  		/* decode response */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
790fe579f   Steve French   [CIFS] more white...
3690
  		/* BB also check enough total bytes returned */
820a803ff   Jeff Layton   cifs: keep BCC in...
3691
  		if (rc || get_bcc(&pSMBr->hdr) < 2)
790fe579f   Steve French   [CIFS] more white...
3692
3693
3694
3695
3696
3697
3698
3699
3700
  			/* If rc should we check for EOPNOSUPP and
  			   disable the srvino flag? or in caller? */
  			rc = -EIO;      /* bad smb */
  		else {
  			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
  			__u16 count = le16_to_cpu(pSMBr->t2.DataCount);
  			struct file_chattr_info *pfinfo;
  			/* BB Do we need a cast or hash here ? */
  			if (count != 16) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3701
3702
  				cifs_dbg(FYI, "Illegal size ret in GetExtAttr
  ");
790fe579f   Steve French   [CIFS] more white...
3703
3704
3705
3706
3707
3708
  				rc = -EIO;
  				goto GetExtAttrOut;
  			}
  			pfinfo = (struct file_chattr_info *)
  				 (data_offset + (char *) &pSMBr->hdr.Protocol);
  			*pExtAttrBits = le64_to_cpu(pfinfo->mode);
f654bac22   Steve French   [PATCH] cifs: add...
3709
  			*pMask = le64_to_cpu(pfinfo->mask);
790fe579f   Steve French   [CIFS] more white...
3710
3711
  		}
  	}
f654bac22   Steve French   [PATCH] cifs: add...
3712
  GetExtAttrOut:
790fe579f   Steve French   [CIFS] more white...
3713
3714
3715
3716
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto GetExtAttrRetry;
  	return rc;
f654bac22   Steve French   [PATCH] cifs: add...
3717
  }
f654bac22   Steve French   [PATCH] cifs: add...
3718
  #endif /* CONFIG_POSIX */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3719

79df1baee   Jeff Layton   cifs: fix use of ...
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
  #ifdef CONFIG_CIFS_ACL
  /*
   * Initialize NT TRANSACT SMB into small smb request buffer.  This assumes that
   * all NT TRANSACTS that we init here have total parm and data under about 400
   * bytes (to fit in small cifs buffer size), which is the case so far, it
   * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
   * returned setup area) and MaxParameterCount (returned parms size) must be set
   * by caller
   */
  static int
  smb_init_nttransact(const __u16 sub_command, const int setup_count,
96daf2b09   Steve French   [CIFS] Rename thr...
3731
  		   const int parm_len, struct cifs_tcon *tcon,
79df1baee   Jeff Layton   cifs: fix use of ...
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
  		   void **ret_buf)
  {
  	int rc;
  	__u32 temp_offset;
  	struct smb_com_ntransact_req *pSMB;
  
  	rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
  				(void **)&pSMB);
  	if (rc)
  		return rc;
  	*ret_buf = (void *)pSMB;
  	pSMB->Reserved = 0;
  	pSMB->TotalParameterCount = cpu_to_le32(parm_len);
  	pSMB->TotalDataCount  = 0;
c974befa4   Jeff Layton   cifs: untangle se...
3746
  	pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
79df1baee   Jeff Layton   cifs: fix use of ...
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
  	pSMB->ParameterCount = pSMB->TotalParameterCount;
  	pSMB->DataCount  = pSMB->TotalDataCount;
  	temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
  			(setup_count * 2) - 4 /* for rfc1001 length itself */;
  	pSMB->ParameterOffset = cpu_to_le32(temp_offset);
  	pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
  	pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
  	pSMB->SubCommand = cpu_to_le16(sub_command);
  	return 0;
  }
  
  static int
  validate_ntransact(char *buf, char **ppparm, char **ppdata,
  		   __u32 *pparmlen, __u32 *pdatalen)
  {
  	char *end_of_smb;
  	__u32 data_count, data_offset, parm_count, parm_offset;
  	struct smb_com_ntransact_rsp *pSMBr;
820a803ff   Jeff Layton   cifs: keep BCC in...
3765
  	u16 bcc;
79df1baee   Jeff Layton   cifs: fix use of ...
3766
3767
3768
3769
3770
3771
3772
3773
  
  	*pdatalen = 0;
  	*pparmlen = 0;
  
  	if (buf == NULL)
  		return -EINVAL;
  
  	pSMBr = (struct smb_com_ntransact_rsp *)buf;
820a803ff   Jeff Layton   cifs: keep BCC in...
3774
3775
  	bcc = get_bcc(&pSMBr->hdr);
  	end_of_smb = 2 /* sizeof byte count */ + bcc +
79df1baee   Jeff Layton   cifs: fix use of ...
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
  			(char *)&pSMBr->ByteCount;
  
  	data_offset = le32_to_cpu(pSMBr->DataOffset);
  	data_count = le32_to_cpu(pSMBr->DataCount);
  	parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
  	parm_count = le32_to_cpu(pSMBr->ParameterCount);
  
  	*ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
  	*ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
  
  	/* should we also check that parm and data areas do not overlap? */
  	if (*ppparm > end_of_smb) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3788
3789
  		cifs_dbg(FYI, "parms start after end of smb
  ");
79df1baee   Jeff Layton   cifs: fix use of ...
3790
3791
  		return -EINVAL;
  	} else if (parm_count + *ppparm > end_of_smb) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3792
3793
  		cifs_dbg(FYI, "parm end after end of smb
  ");
79df1baee   Jeff Layton   cifs: fix use of ...
3794
3795
  		return -EINVAL;
  	} else if (*ppdata > end_of_smb) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3796
3797
  		cifs_dbg(FYI, "data starts after end of smb
  ");
79df1baee   Jeff Layton   cifs: fix use of ...
3798
3799
  		return -EINVAL;
  	} else if (data_count + *ppdata > end_of_smb) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3800
3801
3802
3803
  		cifs_dbg(FYI, "data %p + count %d (%p) past smb end %p start %p
  ",
  			 *ppdata, data_count, (data_count + *ppdata),
  			 end_of_smb, pSMBr);
79df1baee   Jeff Layton   cifs: fix use of ...
3804
  		return -EINVAL;
820a803ff   Jeff Layton   cifs: keep BCC in...
3805
  	} else if (parm_count + data_count > bcc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3806
3807
  		cifs_dbg(FYI, "parm count and data count larger than SMB
  ");
79df1baee   Jeff Layton   cifs: fix use of ...
3808
3809
3810
3811
3812
3813
  		return -EINVAL;
  	}
  	*pdatalen = data_count;
  	*pparmlen = parm_count;
  	return 0;
  }
0a4b92c05   Steve French   [CIFS] Add worker...
3814
3815
  /* Get Security Descriptor (by handle) from remote server for a file or dir */
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
3816
  CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
630f3f0c4   Steve French   [CIFS] acl suppor...
3817
  		  struct cifs_ntsd **acl_inf, __u32 *pbuflen)
0a4b92c05   Steve French   [CIFS] Add worker...
3818
3819
3820
  {
  	int rc = 0;
  	int buf_type = 0;
ad7a2926b   Steve French   [CIFS] reduce che...
3821
  	QUERY_SEC_DESC_REQ *pSMB;
0a4b92c05   Steve French   [CIFS] Add worker...
3822
  	struct kvec iov[1];
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3823
3824
  	cifs_dbg(FYI, "GetCifsACL
  ");
0a4b92c05   Steve French   [CIFS] Add worker...
3825

630f3f0c4   Steve French   [CIFS] acl suppor...
3826
3827
  	*pbuflen = 0;
  	*acl_inf = NULL;
b9c7a2bb1   Steve French   [CIFS] ACL suppor...
3828
  	rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
0a4b92c05   Steve French   [CIFS] Add worker...
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
  			8 /* parm len */, tcon, (void **) &pSMB);
  	if (rc)
  		return rc;
  
  	pSMB->MaxParameterCount = cpu_to_le32(4);
  	/* BB TEST with big acls that might need to be e.g. larger than 16K */
  	pSMB->MaxSetupCount = 0;
  	pSMB->Fid = fid; /* file handle always le */
  	pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
  				     CIFS_ACL_DACL);
  	pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
be8e3b004   Steve French   consistently use ...
3840
  	inc_rfc1001_len(pSMB, 11);
0a4b92c05   Steve French   [CIFS] Add worker...
3841
  	iov[0].iov_base = (char *)pSMB;
be8e3b004   Steve French   consistently use ...
3842
  	iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
0a4b92c05   Steve French   [CIFS] Add worker...
3843

a761ac579   Steve French   [CIFS] log better...
3844
  	rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
7749981ec   Jeff Layton   cifs: remove code...
3845
  			 0);
44c581866   Pavel Shilovsky   CIFS: Move clear/...
3846
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
0a4b92c05   Steve French   [CIFS] Add worker...
3847
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3848
3849
  		cifs_dbg(FYI, "Send error in QuerySecDesc = %d
  ", rc);
0a4b92c05   Steve French   [CIFS] Add worker...
3850
  	} else {                /* decode response */
ad7a2926b   Steve French   [CIFS] reduce che...
3851
  		__le32 *parm;
630f3f0c4   Steve French   [CIFS] acl suppor...
3852
3853
  		__u32 parm_len;
  		__u32 acl_len;
50c2f7538   Steve French   [CIFS] whitespace...
3854
  		struct smb_com_ntransact_rsp *pSMBr;
630f3f0c4   Steve French   [CIFS] acl suppor...
3855
  		char *pdata;
0a4b92c05   Steve French   [CIFS] Add worker...
3856
3857
  
  /* validate_nttransact */
50c2f7538   Steve French   [CIFS] whitespace...
3858
  		rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
630f3f0c4   Steve French   [CIFS] acl suppor...
3859
  					&pdata, &parm_len, pbuflen);
790fe579f   Steve French   [CIFS] more white...
3860
  		if (rc)
0a4b92c05   Steve French   [CIFS] Add worker...
3861
3862
  			goto qsec_out;
  		pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3863
3864
3865
  		cifs_dbg(FYI, "smb %p parm %p data %p
  ",
  			 pSMBr, parm, *acl_inf);
0a4b92c05   Steve French   [CIFS] Add worker...
3866
3867
3868
  
  		if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
  			rc = -EIO;      /* bad smb */
630f3f0c4   Steve French   [CIFS] acl suppor...
3869
  			*pbuflen = 0;
0a4b92c05   Steve French   [CIFS] Add worker...
3870
3871
3872
3873
  			goto qsec_out;
  		}
  
  /* BB check that data area is minimum length and as big as acl_len */
af6f4612f   Steve French   [CIFS] Fix some e...
3874
  		acl_len = le32_to_cpu(*parm);
630f3f0c4   Steve French   [CIFS] acl suppor...
3875
  		if (acl_len != *pbuflen) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3876
3877
3878
  			cifs_dbg(VFS, "acl length %d does not match %d
  ",
  				 acl_len, *pbuflen);
630f3f0c4   Steve French   [CIFS] acl suppor...
3879
3880
3881
  			if (*pbuflen > acl_len)
  				*pbuflen = acl_len;
  		}
0a4b92c05   Steve French   [CIFS] Add worker...
3882

630f3f0c4   Steve French   [CIFS] acl suppor...
3883
3884
3885
3886
  		/* check if buffer is big enough for the acl
  		   header followed by the smallest SID */
  		if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
  		    (*pbuflen >= 64 * 1024)) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3887
3888
  			cifs_dbg(VFS, "bad acl length %d
  ", *pbuflen);
630f3f0c4   Steve French   [CIFS] acl suppor...
3889
3890
3891
  			rc = -EINVAL;
  			*pbuflen = 0;
  		} else {
f7f7c1850   Silviu-Mihai Popescu   fs: cifs: use kme...
3892
  			*acl_inf = kmemdup(pdata, *pbuflen, GFP_KERNEL);
630f3f0c4   Steve French   [CIFS] acl suppor...
3893
3894
3895
3896
  			if (*acl_inf == NULL) {
  				*pbuflen = 0;
  				rc = -ENOMEM;
  			}
630f3f0c4   Steve French   [CIFS] acl suppor...
3897
  		}
0a4b92c05   Steve French   [CIFS] Add worker...
3898
3899
  	}
  qsec_out:
6d81ed1ec   Sachin Prabhu   cifs: replace cod...
3900
  	free_rsp_buf(buf_type, iov[0].iov_base);
4b8f930ff   Steve French   [CIFS] Free small...
3901
  /*	cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
0a4b92c05   Steve French   [CIFS] Add worker...
3902
3903
  	return rc;
  }
97837582b   Steve French   [CIFS] Allow sett...
3904
3905
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
3906
  CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
a5ff37696   Shirish Pargaonkar   cifs: Call id to ...
3907
  			struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
97837582b   Steve French   [CIFS] Allow sett...
3908
3909
3910
3911
3912
  {
  	__u16 byte_count, param_count, data_count, param_offset, data_offset;
  	int rc = 0;
  	int bytes_returned = 0;
  	SET_SEC_DESC_REQ *pSMB = NULL;
b2a3ad9ca   Jeff Layton   cifs: silence com...
3913
  	void *pSMBr;
97837582b   Steve French   [CIFS] Allow sett...
3914
3915
  
  setCifsAclRetry:
b2a3ad9ca   Jeff Layton   cifs: silence com...
3916
  	rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
97837582b   Steve French   [CIFS] Allow sett...
3917
  	if (rc)
b2a3ad9ca   Jeff Layton   cifs: silence com...
3918
  		return rc;
97837582b   Steve French   [CIFS] Allow sett...
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
  
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  
  	param_count = 8;
  	param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
  	data_count = acllen;
  	data_offset = param_offset + param_count;
  	byte_count = 3 /* pad */  + param_count;
  
  	pSMB->DataCount = cpu_to_le32(data_count);
  	pSMB->TotalDataCount = pSMB->DataCount;
  	pSMB->MaxParameterCount = cpu_to_le32(4);
  	pSMB->MaxDataCount = cpu_to_le32(16384);
  	pSMB->ParameterCount = cpu_to_le32(param_count);
  	pSMB->ParameterOffset = cpu_to_le32(param_offset);
  	pSMB->TotalParameterCount = pSMB->ParameterCount;
  	pSMB->DataOffset = cpu_to_le32(data_offset);
  	pSMB->SetupCount = 0;
  	pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
  	pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
  
  	pSMB->Fid = fid; /* file handle always le */
  	pSMB->Reserved2 = 0;
a5ff37696   Shirish Pargaonkar   cifs: Call id to ...
3943
  	pSMB->AclFlags = cpu_to_le32(aclflag);
97837582b   Steve French   [CIFS] Allow sett...
3944
3945
  
  	if (pntsd && acllen) {
b2a3ad9ca   Jeff Layton   cifs: silence com...
3946
3947
  		memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
  				data_offset, pntsd, acllen);
be8e3b004   Steve French   consistently use ...
3948
  		inc_rfc1001_len(pSMB, byte_count + data_count);
97837582b   Steve French   [CIFS] Allow sett...
3949
  	} else
be8e3b004   Steve French   consistently use ...
3950
  		inc_rfc1001_len(pSMB, byte_count);
97837582b   Steve French   [CIFS] Allow sett...
3951
3952
3953
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3954
3955
3956
  	cifs_dbg(FYI, "SetCIFSACL bytes_returned: %d, rc: %d
  ",
  		 bytes_returned, rc);
97837582b   Steve French   [CIFS] Allow sett...
3957
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3958
3959
  		cifs_dbg(FYI, "Set CIFS ACL returned %d
  ", rc);
97837582b   Steve French   [CIFS] Allow sett...
3960
3961
3962
3963
3964
3965
3966
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto setCifsAclRetry;
  
  	return (rc);
  }
79df1baee   Jeff Layton   cifs: fix use of ...
3967
  #endif /* CONFIG_CIFS_ACL */
0a4b92c05   Steve French   [CIFS] Add worker...
3968

6b8edfe0f   Steve French   [CIFS] Support fo...
3969
3970
  /* Legacy Query Path Information call for lookup to old servers such
     as Win9x/WinME */
68889f269   Pavel Shilovsky   CIFS: Move is_pat...
3971
3972
3973
3974
  int
  SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
  		    const char *search_name, FILE_ALL_INFO *data,
  		    const struct nls_table *nls_codepage, int remap)
6b8edfe0f   Steve French   [CIFS] Support fo...
3975
  {
ad7a2926b   Steve French   [CIFS] reduce che...
3976
3977
  	QUERY_INFORMATION_REQ *pSMB;
  	QUERY_INFORMATION_RSP *pSMBr;
6b8edfe0f   Steve French   [CIFS] Support fo...
3978
3979
3980
  	int rc = 0;
  	int bytes_returned;
  	int name_len;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3981
3982
  	cifs_dbg(FYI, "In SMBQPath path %s
  ", search_name);
6b8edfe0f   Steve French   [CIFS] Support fo...
3983
3984
  QInfRetry:
  	rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
50c2f7538   Steve French   [CIFS] whitespace...
3985
  		      (void **) &pSMBr);
6b8edfe0f   Steve French   [CIFS] Support fo...
3986
3987
3988
3989
3990
  	if (rc)
  		return rc;
  
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		name_len =
acbbb76a2   Steve French   CIFS: Rename *UCS...
3991
  			cifsConvertToUTF16((__le16 *) pSMB->FileName,
68889f269   Pavel Shilovsky   CIFS: Move is_pat...
3992
  					   search_name, PATH_MAX, nls_codepage,
acbbb76a2   Steve French   CIFS: Rename *UCS...
3993
  					   remap);
6b8edfe0f   Steve French   [CIFS] Support fo...
3994
3995
  		name_len++;     /* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
3996
  	} else {
68889f269   Pavel Shilovsky   CIFS: Move is_pat...
3997
  		name_len = strnlen(search_name, PATH_MAX);
6b8edfe0f   Steve French   [CIFS] Support fo...
3998
  		name_len++;     /* trailing null */
68889f269   Pavel Shilovsky   CIFS: Move is_pat...
3999
  		strncpy(pSMB->FileName, search_name, name_len);
6b8edfe0f   Steve French   [CIFS] Support fo...
4000
4001
  	}
  	pSMB->BufferFormat = 0x04;
50c2f7538   Steve French   [CIFS] whitespace...
4002
  	name_len++; /* account for buffer type byte */
be8e3b004   Steve French   consistently use ...
4003
  	inc_rfc1001_len(pSMB, (__u16)name_len);
6b8edfe0f   Steve French   [CIFS] Support fo...
4004
4005
4006
  	pSMB->ByteCount = cpu_to_le16(name_len);
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
50c2f7538   Steve French   [CIFS] whitespace...
4007
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6b8edfe0f   Steve French   [CIFS] Support fo...
4008
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4009
4010
  		cifs_dbg(FYI, "Send error in QueryInfo = %d
  ", rc);
68889f269   Pavel Shilovsky   CIFS: Move is_pat...
4011
  	} else if (data) {
1bd5bbcb6   Steve French   [CIFS] Legacy tim...
4012
4013
  		struct timespec ts;
  		__u32 time = le32_to_cpu(pSMBr->last_write_time);
ad7a2926b   Steve French   [CIFS] reduce che...
4014
4015
  
  		/* decode response */
1bd5bbcb6   Steve French   [CIFS] Legacy tim...
4016
  		/* BB FIXME - add time zone adjustment BB */
68889f269   Pavel Shilovsky   CIFS: Move is_pat...
4017
  		memset(data, 0, sizeof(FILE_ALL_INFO));
1bd5bbcb6   Steve French   [CIFS] Legacy tim...
4018
4019
4020
  		ts.tv_nsec = 0;
  		ts.tv_sec = time;
  		/* decode time fields */
68889f269   Pavel Shilovsky   CIFS: Move is_pat...
4021
4022
4023
4024
  		data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
  		data->LastWriteTime = data->ChangeTime;
  		data->LastAccessTime = 0;
  		data->AllocationSize =
70ca734a1   Steve French   [CIFS] Various mi...
4025
  			cpu_to_le64(le32_to_cpu(pSMBr->size));
68889f269   Pavel Shilovsky   CIFS: Move is_pat...
4026
4027
  		data->EndOfFile = data->AllocationSize;
  		data->Attributes =
70ca734a1   Steve French   [CIFS] Various mi...
4028
  			cpu_to_le32(le16_to_cpu(pSMBr->attr));
6b8edfe0f   Steve French   [CIFS] Support fo...
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
  	} else
  		rc = -EIO; /* bad buffer passed in */
  
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto QInfRetry;
  
  	return rc;
  }
bcd5357f4   Jeff Layton   cifs: add a CIFSS...
4039
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
4040
  CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
bcd5357f4   Jeff Layton   cifs: add a CIFSS...
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
  		 u16 netfid, FILE_ALL_INFO *pFindData)
  {
  	struct smb_t2_qfi_req *pSMB = NULL;
  	struct smb_t2_qfi_rsp *pSMBr = NULL;
  	int rc = 0;
  	int bytes_returned;
  	__u16 params, byte_count;
  
  QFileInfoRetry:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	params = 2 /* level */ + 2 /* fid */;
  	pSMB->t2.TotalDataCount = 0;
  	pSMB->t2.MaxParameterCount = cpu_to_le16(4);
  	/* BB find exact max data count below from sess structure BB */
  	pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
  	pSMB->t2.MaxSetupCount = 0;
  	pSMB->t2.Reserved = 0;
  	pSMB->t2.Flags = 0;
  	pSMB->t2.Timeout = 0;
  	pSMB->t2.Reserved2 = 0;
  	pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
  					       Fid) - 4);
  	pSMB->t2.DataCount = 0;
  	pSMB->t2.DataOffset = 0;
  	pSMB->t2.SetupCount = 1;
  	pSMB->t2.Reserved3 = 0;
  	pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
  	byte_count = params + 1 /* pad */ ;
  	pSMB->t2.TotalParameterCount = cpu_to_le16(params);
  	pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
  	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
  	pSMB->Pad = 0;
  	pSMB->Fid = netfid;
be8e3b004   Steve French   consistently use ...
4078
  	inc_rfc1001_len(pSMB, byte_count);
7ac0febb8   David Disseldorp   cifs: fill TRANS2...
4079
  	pSMB->t2.ByteCount = cpu_to_le16(byte_count);
6b8edfe0f   Steve French   [CIFS] Support fo...
4080

bcd5357f4   Jeff Layton   cifs: add a CIFSS...
4081
4082
4083
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  	if (rc) {
ebcc943c1   Steve French   Add missing end o...
4084
  		cifs_dbg(FYI, "Send error in QFileInfo = %d", rc);
bcd5357f4   Jeff Layton   cifs: add a CIFSS...
4085
4086
  	} else {		/* decode response */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
6b8edfe0f   Steve French   [CIFS] Support fo...
4087

bcd5357f4   Jeff Layton   cifs: add a CIFSS...
4088
4089
  		if (rc) /* BB add auto retry on EOPNOTSUPP? */
  			rc = -EIO;
820a803ff   Jeff Layton   cifs: keep BCC in...
4090
  		else if (get_bcc(&pSMBr->hdr) < 40)
bcd5357f4   Jeff Layton   cifs: add a CIFSS...
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
  			rc = -EIO;	/* bad smb */
  		else if (pFindData) {
  			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
  			memcpy((char *) pFindData,
  			       (char *) &pSMBr->hdr.Protocol +
  			       data_offset, sizeof(FILE_ALL_INFO));
  		} else
  		    rc = -ENOMEM;
  	}
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto QFileInfoRetry;
6b8edfe0f   Steve French   [CIFS] Support fo...
4103

bcd5357f4   Jeff Layton   cifs: add a CIFSS...
4104
4105
  	return rc;
  }
6b8edfe0f   Steve French   [CIFS] Support fo...
4106

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4107
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
4108
  CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
68889f269   Pavel Shilovsky   CIFS: Move is_pat...
4109
  		 const char *search_name, FILE_ALL_INFO *data,
acf1a1b10   Steve French   [CIFS] Level 1 QP...
4110
  		 int legacy /* old style infolevel */,
737b758c9   Steve French   [PATCH] cifs: cha...
4111
  		 const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4112
  {
68889f269   Pavel Shilovsky   CIFS: Move is_pat...
4113
  	/* level 263 SMB_QUERY_FILE_ALL_INFO */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4114
4115
4116
4117
4118
4119
  	TRANSACTION2_QPI_REQ *pSMB = NULL;
  	TRANSACTION2_QPI_RSP *pSMBr = NULL;
  	int rc = 0;
  	int bytes_returned;
  	int name_len;
  	__u16 params, byte_count;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4120
4121
  	/* cifs_dbg(FYI, "In QPathInfo path %s
  ", search_name); */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4122
4123
4124
4125
4126
4127
4128
4129
  QPathInfoRetry:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		name_len =
68889f269   Pavel Shilovsky   CIFS: Move is_pat...
4130
  		    cifsConvertToUTF16((__le16 *) pSMB->FileName, search_name,
acbbb76a2   Steve French   CIFS: Rename *UCS...
4131
  				       PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4132
4133
  		name_len++;	/* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
4134
  	} else {	/* BB improve the check for buffer overruns BB */
68889f269   Pavel Shilovsky   CIFS: Move is_pat...
4135
  		name_len = strnlen(search_name, PATH_MAX);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4136
  		name_len++;	/* trailing null */
68889f269   Pavel Shilovsky   CIFS: Move is_pat...
4137
  		strncpy(pSMB->FileName, search_name, name_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4138
  	}
50c2f7538   Steve French   [CIFS] whitespace...
4139
  	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4140
4141
  	pSMB->TotalDataCount = 0;
  	pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5e   Steve French   [CIFS] cleanup ol...
4142
4143
  	/* BB find exact max SMB PDU from sess structure BB */
  	pSMB->MaxDataCount = cpu_to_le16(4000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4144
4145
4146
4147
4148
4149
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  	pSMB->Flags = 0;
  	pSMB->Timeout = 0;
  	pSMB->Reserved2 = 0;
  	pSMB->ParameterOffset = cpu_to_le16(offsetof(
50c2f7538   Steve French   [CIFS] whitespace...
4150
  	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4151
4152
4153
4154
4155
4156
4157
4158
  	pSMB->DataCount = 0;
  	pSMB->DataOffset = 0;
  	pSMB->SetupCount = 1;
  	pSMB->Reserved3 = 0;
  	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
  	byte_count = params + 1 /* pad */ ;
  	pSMB->TotalParameterCount = cpu_to_le16(params);
  	pSMB->ParameterCount = pSMB->TotalParameterCount;
790fe579f   Steve French   [CIFS] more white...
4159
  	if (legacy)
acf1a1b10   Steve French   [CIFS] Level 1 QP...
4160
4161
4162
  		pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
  	else
  		pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4163
  	pSMB->Reserved4 = 0;
be8e3b004   Steve French   consistently use ...
4164
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4165
4166
4167
4168
4169
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4170
4171
  		cifs_dbg(FYI, "Send error in QPathInfo = %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4172
4173
  	} else {		/* decode response */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
acf1a1b10   Steve French   [CIFS] Level 1 QP...
4174
4175
  		if (rc) /* BB add auto retry on EOPNOTSUPP? */
  			rc = -EIO;
820a803ff   Jeff Layton   cifs: keep BCC in...
4176
  		else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4177
  			rc = -EIO;	/* bad smb */
820a803ff   Jeff Layton   cifs: keep BCC in...
4178
  		else if (legacy && get_bcc(&pSMBr->hdr) < 24)
50c2f7538   Steve French   [CIFS] whitespace...
4179
4180
  			rc = -EIO;  /* 24 or 26 expected but we do not read
  					last field */
68889f269   Pavel Shilovsky   CIFS: Move is_pat...
4181
  		else if (data) {
acf1a1b10   Steve French   [CIFS] Level 1 QP...
4182
  			int size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4183
  			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
ad7a2926b   Steve French   [CIFS] reduce che...
4184

68889f269   Pavel Shilovsky   CIFS: Move is_pat...
4185
4186
4187
4188
4189
4190
  			/*
  			 * On legacy responses we do not read the last field,
  			 * EAsize, fortunately since it varies by subdialect and
  			 * also note it differs on Set vs Get, ie two bytes or 4
  			 * bytes depending but we don't care here.
  			 */
ad7a2926b   Steve French   [CIFS] reduce che...
4191
  			if (legacy)
acf1a1b10   Steve French   [CIFS] Level 1 QP...
4192
4193
4194
  				size = sizeof(FILE_INFO_STANDARD);
  			else
  				size = sizeof(FILE_ALL_INFO);
68889f269   Pavel Shilovsky   CIFS: Move is_pat...
4195
  			memcpy((char *) data, (char *) &pSMBr->hdr.Protocol +
acf1a1b10   Steve French   [CIFS] Level 1 QP...
4196
  			       data_offset, size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
  		} else
  		    rc = -ENOMEM;
  	}
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto QPathInfoRetry;
  
  	return rc;
  }
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
4208
  CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
c8634fd31   Jeff Layton   cifs: add a CIFSS...
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
  		 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
  {
  	struct smb_t2_qfi_req *pSMB = NULL;
  	struct smb_t2_qfi_rsp *pSMBr = NULL;
  	int rc = 0;
  	int bytes_returned;
  	__u16 params, byte_count;
  
  UnixQFileInfoRetry:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	params = 2 /* level */ + 2 /* fid */;
  	pSMB->t2.TotalDataCount = 0;
  	pSMB->t2.MaxParameterCount = cpu_to_le16(4);
  	/* BB find exact max data count below from sess structure BB */
  	pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
  	pSMB->t2.MaxSetupCount = 0;
  	pSMB->t2.Reserved = 0;
  	pSMB->t2.Flags = 0;
  	pSMB->t2.Timeout = 0;
  	pSMB->t2.Reserved2 = 0;
  	pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
  					       Fid) - 4);
  	pSMB->t2.DataCount = 0;
  	pSMB->t2.DataOffset = 0;
  	pSMB->t2.SetupCount = 1;
  	pSMB->t2.Reserved3 = 0;
  	pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
  	byte_count = params + 1 /* pad */ ;
  	pSMB->t2.TotalParameterCount = cpu_to_le16(params);
  	pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
  	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
  	pSMB->Pad = 0;
  	pSMB->Fid = netfid;
be8e3b004   Steve French   consistently use ...
4246
  	inc_rfc1001_len(pSMB, byte_count);
7ac0febb8   David Disseldorp   cifs: fill TRANS2...
4247
  	pSMB->t2.ByteCount = cpu_to_le16(byte_count);
c8634fd31   Jeff Layton   cifs: add a CIFSS...
4248
4249
4250
4251
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  	if (rc) {
ebcc943c1   Steve French   Add missing end o...
4252
  		cifs_dbg(FYI, "Send error in UnixQFileInfo = %d", rc);
c8634fd31   Jeff Layton   cifs: add a CIFSS...
4253
4254
  	} else {		/* decode response */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
820a803ff   Jeff Layton   cifs: keep BCC in...
4255
  		if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4256
4257
  			cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.
  ");
c8634fd31   Jeff Layton   cifs: add a CIFSS...
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
  			rc = -EIO;	/* bad smb */
  		} else {
  			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
  			memcpy((char *) pFindData,
  			       (char *) &pSMBr->hdr.Protocol +
  			       data_offset,
  			       sizeof(FILE_UNIX_BASIC_INFO));
  		}
  	}
  
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto UnixQFileInfoRetry;
  
  	return rc;
  }
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
4276
  CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4277
  		     const unsigned char *searchName,
582d21e5e   Steve French   [CIFS] cleanup ol...
4278
  		     FILE_UNIX_BASIC_INFO *pFindData,
737b758c9   Steve French   [PATCH] cifs: cha...
4279
  		     const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4280
4281
4282
4283
4284
4285
4286
4287
  {
  /* SMB_QUERY_FILE_UNIX_BASIC */
  	TRANSACTION2_QPI_REQ *pSMB = NULL;
  	TRANSACTION2_QPI_RSP *pSMBr = NULL;
  	int rc = 0;
  	int bytes_returned = 0;
  	int name_len;
  	__u16 params, byte_count;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4288
4289
  	cifs_dbg(FYI, "In QPathInfo (Unix) the path %s
  ", searchName);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4290
4291
4292
4293
4294
4295
4296
4297
  UnixQPathInfoRetry:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		name_len =
acbbb76a2   Steve French   CIFS: Rename *UCS...
4298
4299
  		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
  				       PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4300
4301
  		name_len++;	/* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
4302
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4303
4304
4305
4306
  		name_len = strnlen(searchName, PATH_MAX);
  		name_len++;	/* trailing null */
  		strncpy(pSMB->FileName, searchName, name_len);
  	}
50c2f7538   Steve French   [CIFS] whitespace...
4307
  	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4308
4309
4310
  	pSMB->TotalDataCount = 0;
  	pSMB->MaxParameterCount = cpu_to_le16(2);
  	/* BB find exact max SMB PDU from sess structure BB */
50c2f7538   Steve French   [CIFS] whitespace...
4311
  	pSMB->MaxDataCount = cpu_to_le16(4000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4312
4313
4314
4315
4316
4317
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  	pSMB->Flags = 0;
  	pSMB->Timeout = 0;
  	pSMB->Reserved2 = 0;
  	pSMB->ParameterOffset = cpu_to_le16(offsetof(
50c2f7538   Steve French   [CIFS] whitespace...
4318
  	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
  	pSMB->DataCount = 0;
  	pSMB->DataOffset = 0;
  	pSMB->SetupCount = 1;
  	pSMB->Reserved3 = 0;
  	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
  	byte_count = params + 1 /* pad */ ;
  	pSMB->TotalParameterCount = cpu_to_le16(params);
  	pSMB->ParameterCount = pSMB->TotalParameterCount;
  	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
  	pSMB->Reserved4 = 0;
be8e3b004   Steve French   consistently use ...
4329
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4330
4331
4332
4333
4334
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  	if (rc) {
ebcc943c1   Steve French   Add missing end o...
4335
  		cifs_dbg(FYI, "Send error in UnixQPathInfo = %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4336
4337
  	} else {		/* decode response */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
820a803ff   Jeff Layton   cifs: keep BCC in...
4338
  		if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4339
4340
  			cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4341
4342
4343
4344
4345
4346
  			rc = -EIO;	/* bad smb */
  		} else {
  			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
  			memcpy((char *) pFindData,
  			       (char *) &pSMBr->hdr.Protocol +
  			       data_offset,
630f3f0c4   Steve French   [CIFS] acl suppor...
4347
  			       sizeof(FILE_UNIX_BASIC_INFO));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4348
4349
4350
4351
4352
4353
4354
4355
  		}
  	}
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto UnixQPathInfoRetry;
  
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4356
4357
  /* xid, tcon, searchName and codepage are input parms, rest are returned */
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
4358
  CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
c052e2b42   Shirish Pargaonkar   cifs: obtain file...
4359
  	      const char *searchName, struct cifs_sb_info *cifs_sb,
2608bee74   Shirish Pargaonkar   cifs: Include bac...
4360
  	      __u16 *pnetfid, __u16 search_flags,
c052e2b42   Shirish Pargaonkar   cifs: obtain file...
4361
  	      struct cifs_search_info *psrch_inf, bool msearch)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4362
4363
4364
4365
  {
  /* level 257 SMB_ */
  	TRANSACTION2_FFIRST_REQ *pSMB = NULL;
  	TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
ad7a2926b   Steve French   [CIFS] reduce che...
4366
  	T2_FFIRST_RSP_PARMS *parms;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4367
4368
  	int rc = 0;
  	int bytes_returned = 0;
c052e2b42   Shirish Pargaonkar   cifs: obtain file...
4369
  	int name_len, remap;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4370
  	__u16 params, byte_count;
c052e2b42   Shirish Pargaonkar   cifs: obtain file...
4371
  	struct nls_table *nls_codepage;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4372

f96637be0   Joe Perches   [CIFS] cifs: Rena...
4373
4374
  	cifs_dbg(FYI, "In FindFirst for %s
  ", searchName);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4375
4376
4377
4378
4379
4380
  
  findFirstRetry:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
c052e2b42   Shirish Pargaonkar   cifs: obtain file...
4381
  	nls_codepage = cifs_sb->local_nls;
2baa26825   Steve French   Remap reserved po...
4382
  	remap = cifs_remap(cifs_sb);
c052e2b42   Shirish Pargaonkar   cifs: obtain file...
4383

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4384
4385
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		name_len =
acbbb76a2   Steve French   CIFS: Rename *UCS...
4386
4387
  		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
  				       PATH_MAX, nls_codepage, remap);
737b758c9   Steve French   [PATCH] cifs: cha...
4388
4389
4390
  		/* We can not add the asterik earlier in case
  		it got remapped to 0xF03A as if it were part of the
  		directory name instead of a wildcard */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4391
  		name_len *= 2;
c052e2b42   Shirish Pargaonkar   cifs: obtain file...
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
  		if (msearch) {
  			pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
  			pSMB->FileName[name_len+1] = 0;
  			pSMB->FileName[name_len+2] = '*';
  			pSMB->FileName[name_len+3] = 0;
  			name_len += 4; /* now the trailing null */
  			/* null terminate just in case */
  			pSMB->FileName[name_len] = 0;
  			pSMB->FileName[name_len+1] = 0;
  			name_len += 2;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4403
4404
  	} else {	/* BB add check for overrun of SMB buf BB */
  		name_len = strnlen(searchName, PATH_MAX);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4405
  /* BB fix here and in unicode clause above ie
790fe579f   Steve French   [CIFS] more white...
4406
  		if (name_len > buffersize-header)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4407
4408
  			free buffer exit; BB */
  		strncpy(pSMB->FileName, searchName, name_len);
c052e2b42   Shirish Pargaonkar   cifs: obtain file...
4409
4410
4411
4412
4413
4414
  		if (msearch) {
  			pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
  			pSMB->FileName[name_len+1] = '*';
  			pSMB->FileName[name_len+2] = 0;
  			name_len += 3;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4415
4416
4417
4418
4419
  	}
  
  	params = 12 + name_len /* includes null */ ;
  	pSMB->TotalDataCount = 0;	/* no EAs */
  	pSMB->MaxParameterCount = cpu_to_le16(10);
c974befa4   Jeff Layton   cifs: untangle se...
4420
  	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4421
4422
4423
4424
4425
4426
4427
4428
4429
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  	pSMB->Flags = 0;
  	pSMB->Timeout = 0;
  	pSMB->Reserved2 = 0;
  	byte_count = params + 1 /* pad */ ;
  	pSMB->TotalParameterCount = cpu_to_le16(params);
  	pSMB->ParameterCount = pSMB->TotalParameterCount;
  	pSMB->ParameterOffset = cpu_to_le16(
88274815f   Steve French   [CIFS] Fix two re...
4430
4431
  	      offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
  		- 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4432
4433
4434
4435
4436
4437
4438
4439
  	pSMB->DataCount = 0;
  	pSMB->DataOffset = 0;
  	pSMB->SetupCount = 1;	/* one byte, no need to make endian neutral */
  	pSMB->Reserved3 = 0;
  	pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
  	pSMB->SearchAttributes =
  	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
  			ATTR_DIRECTORY);
50c2f7538   Steve French   [CIFS] whitespace...
4440
  	pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
2608bee74   Shirish Pargaonkar   cifs: Include bac...
4441
  	pSMB->SearchFlags = cpu_to_le16(search_flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4442
4443
4444
4445
  	pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
  
  	/* BB what should we set StorageType to? Does it matter? BB */
  	pSMB->SearchStorageType = 0;
be8e3b004   Steve French   consistently use ...
4446
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4447
4448
4449
4450
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
44c581866   Pavel Shilovsky   CIFS: Move clear/...
4451
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_ffirst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4452

88274815f   Steve French   [CIFS] Fix two re...
4453
4454
  	if (rc) {/* BB add logic to retry regular search if Unix search
  			rejected unexpectedly by server */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4455
  		/* BB Add code to handle unsupported level rc */
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4456
4457
  		cifs_dbg(FYI, "Error in FindFirst = %d
  ", rc);
1982c344f   Steve French   [CIFS] Ensure tha...
4458

88274815f   Steve French   [CIFS] Fix two re...
4459
  		cifs_buf_release(pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4460
4461
4462
4463
4464
4465
4466
4467
  
  		/* BB eventually could optimize out free and realloc of buf */
  		/*    for this case */
  		if (rc == -EAGAIN)
  			goto findFirstRetry;
  	} else { /* decode response */
  		/* BB remember to free buffer if error BB */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
790fe579f   Steve French   [CIFS] more white...
4468
  		if (rc == 0) {
b77d753c4   Steve French   [CIFS] Check that...
4469
  			unsigned int lnoff;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4470
  			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4b18f2a9c   Steve French   [CIFS] convert us...
4471
  				psrch_inf->unicode = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4472
  			else
4b18f2a9c   Steve French   [CIFS] convert us...
4473
  				psrch_inf->unicode = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4474
4475
  
  			psrch_inf->ntwrk_buf_start = (char *)pSMBr;
d47d7c1a8   Steve French   [CIFS] CIFS readd...
4476
  			psrch_inf->smallBuf = 0;
50c2f7538   Steve French   [CIFS] whitespace...
4477
4478
  			psrch_inf->srch_entries_start =
  				(char *) &pSMBr->hdr.Protocol +
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4479
  					le16_to_cpu(pSMBr->t2.DataOffset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4480
4481
  			parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
  			       le16_to_cpu(pSMBr->t2.ParameterOffset));
790fe579f   Steve French   [CIFS] more white...
4482
  			if (parms->EndofSearch)
4b18f2a9c   Steve French   [CIFS] convert us...
4483
  				psrch_inf->endOfSearch = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4484
  			else
4b18f2a9c   Steve French   [CIFS] convert us...
4485
  				psrch_inf->endOfSearch = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4486

50c2f7538   Steve French   [CIFS] whitespace...
4487
4488
  			psrch_inf->entries_in_buffer =
  					le16_to_cpu(parms->SearchCount);
60808233f   Steve French   [CIFS] Readdir fi...
4489
  			psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4490
  				psrch_inf->entries_in_buffer;
b77d753c4   Steve French   [CIFS] Check that...
4491
  			lnoff = le16_to_cpu(parms->LastNameOffset);
c974befa4   Jeff Layton   cifs: untangle se...
4492
  			if (CIFSMaxBufSize < lnoff) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4493
4494
  				cifs_dbg(VFS, "ignoring corrupt resume name
  ");
b77d753c4   Steve French   [CIFS] Check that...
4495
4496
4497
  				psrch_inf->last_entry = NULL;
  				return rc;
  			}
0752f1522   Steve French   [CIFS] make sure ...
4498
  			psrch_inf->last_entry = psrch_inf->srch_entries_start +
b77d753c4   Steve French   [CIFS] Check that...
4499
  							lnoff;
c052e2b42   Shirish Pargaonkar   cifs: obtain file...
4500
4501
  			if (pnetfid)
  				*pnetfid = parms->SearchHandle;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4502
4503
4504
4505
4506
4507
4508
  		} else {
  			cifs_buf_release(pSMB);
  		}
  	}
  
  	return rc;
  }
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
4509
4510
4511
  int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
  		 __u16 searchHandle, __u16 search_flags,
  		 struct cifs_search_info *psrch_inf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4512
4513
4514
  {
  	TRANSACTION2_FNEXT_REQ *pSMB = NULL;
  	TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
ad7a2926b   Steve French   [CIFS] reduce che...
4515
  	T2_FNEXT_RSP_PARMS *parms;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4516
4517
  	char *response_data;
  	int rc = 0;
9438fabb7   Jeff Layton   cifs: fix possibl...
4518
4519
  	int bytes_returned;
  	unsigned int name_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4520
  	__u16 params, byte_count;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4521
4522
  	cifs_dbg(FYI, "In FindNext
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4523

4b18f2a9c   Steve French   [CIFS] convert us...
4524
  	if (psrch_inf->endOfSearch)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4525
4526
4527
4528
4529
4530
  		return -ENOENT;
  
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  		(void **) &pSMBr);
  	if (rc)
  		return rc;
50c2f7538   Steve French   [CIFS] whitespace...
4531
  	params = 14; /* includes 2 bytes of null string, converted to LE below*/
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4532
4533
4534
  	byte_count = 0;
  	pSMB->TotalDataCount = 0;       /* no EAs */
  	pSMB->MaxParameterCount = cpu_to_le16(8);
c974befa4   Jeff Layton   cifs: untangle se...
4535
  	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  	pSMB->Flags = 0;
  	pSMB->Timeout = 0;
  	pSMB->Reserved2 = 0;
  	pSMB->ParameterOffset =  cpu_to_le16(
  	      offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
  	pSMB->DataCount = 0;
  	pSMB->DataOffset = 0;
  	pSMB->SetupCount = 1;
  	pSMB->Reserved3 = 0;
  	pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
  	pSMB->SearchHandle = searchHandle;      /* always kept as le */
  	pSMB->SearchCount =
630f3f0c4   Steve French   [CIFS] acl suppor...
4550
  		cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4551
4552
  	pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
  	pSMB->ResumeKey = psrch_inf->resume_key;
2608bee74   Shirish Pargaonkar   cifs: Include bac...
4553
  	pSMB->SearchFlags = cpu_to_le16(search_flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4554
4555
4556
  
  	name_len = psrch_inf->resume_name_len;
  	params += name_len;
790fe579f   Steve French   [CIFS] more white...
4557
  	if (name_len < PATH_MAX) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4558
4559
  		memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
  		byte_count += name_len;
ef6724e32   Steve French   [CIFS] Fix missin...
4560
4561
4562
  		/* 14 byte parm len above enough for 2 byte null terminator */
  		pSMB->ResumeFileName[name_len] = 0;
  		pSMB->ResumeFileName[name_len+1] = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4563
4564
4565
4566
4567
4568
4569
  	} else {
  		rc = -EINVAL;
  		goto FNext2_err_exit;
  	}
  	byte_count = params + 1 /* pad */ ;
  	pSMB->TotalParameterCount = cpu_to_le16(params);
  	pSMB->ParameterCount = pSMB->TotalParameterCount;
be8e3b004   Steve French   consistently use ...
4570
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4571
  	pSMB->ByteCount = cpu_to_le16(byte_count);
50c2f7538   Steve French   [CIFS] whitespace...
4572

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4573
4574
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			(struct smb_hdr *) pSMBr, &bytes_returned, 0);
44c581866   Pavel Shilovsky   CIFS: Move clear/...
4575
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_fnext);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4576
4577
  	if (rc) {
  		if (rc == -EBADF) {
4b18f2a9c   Steve French   [CIFS] convert us...
4578
  			psrch_inf->endOfSearch = true;
6353450a2   Jeff Layton   fix memory leak i...
4579
  			cifs_buf_release(pSMB);
50c2f7538   Steve French   [CIFS] whitespace...
4580
  			rc = 0; /* search probably was closed at end of search*/
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4581
  		} else
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4582
4583
  			cifs_dbg(FYI, "FindNext returned = %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4584
4585
  	} else {                /* decode response */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
50c2f7538   Steve French   [CIFS] whitespace...
4586

790fe579f   Steve French   [CIFS] more white...
4587
  		if (rc == 0) {
b77d753c4   Steve French   [CIFS] Check that...
4588
  			unsigned int lnoff;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4589
4590
  			/* BB fixme add lock for file (srch_info) struct here */
  			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4b18f2a9c   Steve French   [CIFS] convert us...
4591
  				psrch_inf->unicode = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4592
  			else
4b18f2a9c   Steve French   [CIFS] convert us...
4593
  				psrch_inf->unicode = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4594
4595
4596
4597
4598
  			response_data = (char *) &pSMBr->hdr.Protocol +
  			       le16_to_cpu(pSMBr->t2.ParameterOffset);
  			parms = (T2_FNEXT_RSP_PARMS *)response_data;
  			response_data = (char *)&pSMBr->hdr.Protocol +
  				le16_to_cpu(pSMBr->t2.DataOffset);
790fe579f   Steve French   [CIFS] more white...
4599
  			if (psrch_inf->smallBuf)
d47d7c1a8   Steve French   [CIFS] CIFS readd...
4600
4601
4602
4603
  				cifs_small_buf_release(
  					psrch_inf->ntwrk_buf_start);
  			else
  				cifs_buf_release(psrch_inf->ntwrk_buf_start);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4604
4605
  			psrch_inf->srch_entries_start = response_data;
  			psrch_inf->ntwrk_buf_start = (char *)pSMB;
d47d7c1a8   Steve French   [CIFS] CIFS readd...
4606
  			psrch_inf->smallBuf = 0;
790fe579f   Steve French   [CIFS] more white...
4607
  			if (parms->EndofSearch)
4b18f2a9c   Steve French   [CIFS] convert us...
4608
  				psrch_inf->endOfSearch = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4609
  			else
4b18f2a9c   Steve French   [CIFS] convert us...
4610
  				psrch_inf->endOfSearch = false;
50c2f7538   Steve French   [CIFS] whitespace...
4611
4612
  			psrch_inf->entries_in_buffer =
  						le16_to_cpu(parms->SearchCount);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4613
4614
  			psrch_inf->index_of_last_entry +=
  				psrch_inf->entries_in_buffer;
b77d753c4   Steve French   [CIFS] Check that...
4615
  			lnoff = le16_to_cpu(parms->LastNameOffset);
c974befa4   Jeff Layton   cifs: untangle se...
4616
  			if (CIFSMaxBufSize < lnoff) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4617
4618
  				cifs_dbg(VFS, "ignoring corrupt resume name
  ");
b77d753c4   Steve French   [CIFS] Check that...
4619
4620
4621
4622
4623
  				psrch_inf->last_entry = NULL;
  				return rc;
  			} else
  				psrch_inf->last_entry =
  					psrch_inf->srch_entries_start + lnoff;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4624
4625
4626
  /*  cifs_dbg(FYI, "fnxt2 entries in buf %d index_of_last %d
  ",
      psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
  
  			/* BB fixme add unlock here */
  		}
  
  	}
  
  	/* BB On error, should we leave previous search buf (and count and
  	last entry fields) intact or free the previous one? */
  
  	/* Note: On -EAGAIN error only caller can retry on handle based calls
  	since file handle passed in no longer valid */
  FNext2_err_exit:
  	if (rc != 0)
  		cifs_buf_release(pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4641
4642
4643
4644
  	return rc;
  }
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
4645
  CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
50c2f7538   Steve French   [CIFS] whitespace...
4646
  	      const __u16 searchHandle)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4647
4648
4649
  {
  	int rc = 0;
  	FINDCLOSE_REQ *pSMB = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4650

f96637be0   Joe Perches   [CIFS] cifs: Rena...
4651
4652
  	cifs_dbg(FYI, "In CIFSSMBFindClose
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4653
4654
4655
4656
  	rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
  
  	/* no sense returning error if session restarted
  		as file handle has been closed */
790fe579f   Steve French   [CIFS] more white...
4657
  	if (rc == -EAGAIN)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4658
4659
4660
  		return 0;
  	if (rc)
  		return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4661
4662
  	pSMB->FileID = searchHandle;
  	pSMB->ByteCount = 0;
792af7b05   Pavel Shilovsky   CIFS: Separate pr...
4663
  	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
ad7a2926b   Steve French   [CIFS] reduce che...
4664
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4665
4666
  		cifs_dbg(VFS, "Send error in FindClose = %d
  ", rc);
ad7a2926b   Steve French   [CIFS] reduce che...
4667

44c581866   Pavel Shilovsky   CIFS: Move clear/...
4668
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_fclose);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4669
4670
4671
4672
4673
4674
4675
  
  	/* Since session is dead, search handle closed on server already */
  	if (rc == -EAGAIN)
  		rc = 0;
  
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4676
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
4677
  CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
1208ef1f7   Pavel Shilovsky   CIFS: Move query ...
4678
  		      const char *search_name, __u64 *inode_number,
50c2f7538   Steve French   [CIFS] whitespace...
4679
  		      const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4680
4681
4682
4683
4684
4685
  {
  	int rc = 0;
  	TRANSACTION2_QPI_REQ *pSMB = NULL;
  	TRANSACTION2_QPI_RSP *pSMBr = NULL;
  	int name_len, bytes_returned;
  	__u16 params, byte_count;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4686
4687
  	cifs_dbg(FYI, "In GetSrvInodeNum for %s
  ", search_name);
790fe579f   Steve French   [CIFS] more white...
4688
  	if (tcon == NULL)
50c2f7538   Steve French   [CIFS] whitespace...
4689
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4690
4691
4692
  
  GetInodeNumberRetry:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
50c2f7538   Steve French   [CIFS] whitespace...
4693
  		      (void **) &pSMBr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4694
4695
  	if (rc)
  		return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4696
4697
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		name_len =
acbbb76a2   Steve French   CIFS: Rename *UCS...
4698
  			cifsConvertToUTF16((__le16 *) pSMB->FileName,
1208ef1f7   Pavel Shilovsky   CIFS: Move query ...
4699
  					   search_name, PATH_MAX, nls_codepage,
acbbb76a2   Steve French   CIFS: Rename *UCS...
4700
  					   remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4701
4702
  		name_len++;     /* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
4703
  	} else {	/* BB improve the check for buffer overruns BB */
1208ef1f7   Pavel Shilovsky   CIFS: Move query ...
4704
  		name_len = strnlen(search_name, PATH_MAX);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4705
  		name_len++;     /* trailing null */
1208ef1f7   Pavel Shilovsky   CIFS: Move query ...
4706
  		strncpy(pSMB->FileName, search_name, name_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
  	}
  
  	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
  	pSMB->TotalDataCount = 0;
  	pSMB->MaxParameterCount = cpu_to_le16(2);
  	/* BB find exact max data count below from sess structure BB */
  	pSMB->MaxDataCount = cpu_to_le16(4000);
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  	pSMB->Flags = 0;
  	pSMB->Timeout = 0;
  	pSMB->Reserved2 = 0;
  	pSMB->ParameterOffset = cpu_to_le16(offsetof(
50c2f7538   Steve French   [CIFS] whitespace...
4720
  		struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
  	pSMB->DataCount = 0;
  	pSMB->DataOffset = 0;
  	pSMB->SetupCount = 1;
  	pSMB->Reserved3 = 0;
  	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
  	byte_count = params + 1 /* pad */ ;
  	pSMB->TotalParameterCount = cpu_to_le16(params);
  	pSMB->ParameterCount = pSMB->TotalParameterCount;
  	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
  	pSMB->Reserved4 = 0;
be8e3b004   Steve French   consistently use ...
4731
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4732
4733
4734
4735
4736
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4737
4738
  		cifs_dbg(FYI, "error %d in QueryInternalInfo
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4739
4740
4741
  	} else {
  		/* decode response */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4742
  		/* BB also check enough total bytes returned */
820a803ff   Jeff Layton   cifs: keep BCC in...
4743
  		if (rc || get_bcc(&pSMBr->hdr) < 2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4744
4745
4746
  			/* If rc should we check for EOPNOSUPP and
  			disable the srvino flag? or in caller? */
  			rc = -EIO;      /* bad smb */
50c2f7538   Steve French   [CIFS] whitespace...
4747
  		else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4748
4749
  			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
  			__u16 count = le16_to_cpu(pSMBr->t2.DataCount);
50c2f7538   Steve French   [CIFS] whitespace...
4750
  			struct file_internal_info *pfinfo;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4751
  			/* BB Do we need a cast or hash here ? */
790fe579f   Steve French   [CIFS] more white...
4752
  			if (count < 8) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4753
4754
  				cifs_dbg(FYI, "Illegal size ret in QryIntrnlInf
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4755
4756
4757
4758
4759
  				rc = -EIO;
  				goto GetInodeNumOut;
  			}
  			pfinfo = (struct file_internal_info *)
  				(data_offset + (char *) &pSMBr->hdr.Protocol);
85a6dac54   Steve French   [CIFS] Endian con...
4760
  			*inode_number = le64_to_cpu(pfinfo->UniqueId);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4761
4762
4763
4764
4765
4766
4767
4768
  		}
  	}
  GetInodeNumOut:
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto GetInodeNumberRetry;
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4769

fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4770
4771
4772
4773
4774
4775
4776
  /* parses DFS refferal V3 structure
   * caller is responsible for freeing target_nodes
   * returns:
   * 	on success - 0
   *	on failure - errno
   */
  static int
a1fe78f16   Steve French   [CIFS] Add missin...
4777
  parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4778
4779
  		unsigned int *num_of_nodes,
  		struct dfs_info3_param **target_nodes,
2c55608f2   Igor Mammedov   Fixed parsing of ...
4780
4781
  		const struct nls_table *nls_codepage, int remap,
  		const char *searchName)
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4782
4783
4784
4785
4786
  {
  	int i, rc = 0;
  	char *data_end;
  	bool is_unicode;
  	struct dfs_referral_level_3 *ref;
5ca33c6ac   Harvey Harrison   cifs: assorted en...
4787
4788
4789
4790
  	if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
  		is_unicode = true;
  	else
  		is_unicode = false;
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4791
4792
4793
  	*num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
  
  	if (*num_of_nodes < 1) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4794
4795
4796
  		cifs_dbg(VFS, "num_referrals: must be at least > 0, but we get num_referrals = %d
  ",
  			 *num_of_nodes);
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4797
  		rc = -EINVAL;
a1fe78f16   Steve French   [CIFS] Add missin...
4798
  		goto parse_DFS_referrals_exit;
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4799
4800
4801
  	}
  
  	ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
1d92cfd54   Al Viro   cifs endianness f...
4802
  	if (ref->VersionNumber != cpu_to_le16(3)) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4803
4804
4805
  		cifs_dbg(VFS, "Referrals of V%d version are not supported, should be V3
  ",
  			 le16_to_cpu(ref->VersionNumber));
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4806
  		rc = -EINVAL;
a1fe78f16   Steve French   [CIFS] Add missin...
4807
  		goto parse_DFS_referrals_exit;
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4808
4809
4810
4811
4812
  	}
  
  	/* get the upper boundary of the resp buffer */
  	data_end = (char *)(&(pSMBr->PathConsumed)) +
  				le16_to_cpu(pSMBr->t2.DataCount);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4813
4814
4815
  	cifs_dbg(FYI, "num_referrals: %d dfs flags: 0x%x ...
  ",
  		 *num_of_nodes, le32_to_cpu(pSMBr->DFSFlags));
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4816

f96637be0   Joe Perches   [CIFS] cifs: Rena...
4817
4818
  	*target_nodes = kcalloc(*num_of_nodes, sizeof(struct dfs_info3_param),
  				GFP_KERNEL);
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4819
  	if (*target_nodes == NULL) {
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4820
  		rc = -ENOMEM;
a1fe78f16   Steve French   [CIFS] Add missin...
4821
  		goto parse_DFS_referrals_exit;
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4822
  	}
3ad2f3fbb   Daniel Mack   tree-wide: Assort...
4823
  	/* collect necessary data from referrals */
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4824
4825
4826
4827
  	for (i = 0; i < *num_of_nodes; i++) {
  		char *temp;
  		int max_len;
  		struct dfs_info3_param *node = (*target_nodes)+i;
0e0d2cf32   Steve French   [CIFS] Remove spa...
4828
  		node->flags = le32_to_cpu(pSMBr->DFSFlags);
2c55608f2   Igor Mammedov   Fixed parsing of ...
4829
  		if (is_unicode) {
331c31351   Jeff Layton   cifs: fix buffer ...
4830
4831
  			__le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
  						GFP_KERNEL);
2920ee2b4   Steve French   [CIFS] potential ...
4832
4833
4834
4835
  			if (tmp == NULL) {
  				rc = -ENOMEM;
  				goto parse_DFS_referrals_exit;
  			}
acbbb76a2   Steve French   CIFS: Rename *UCS...
4836
4837
4838
  			cifsConvertToUTF16((__le16 *) tmp, searchName,
  					   PATH_MAX, nls_codepage, remap);
  			node->path_consumed = cifs_utf16_bytes(tmp,
69f801fca   Jeff Layton   cifs: add new fun...
4839
  					le16_to_cpu(pSMBr->PathConsumed),
2c55608f2   Igor Mammedov   Fixed parsing of ...
4840
4841
4842
4843
  					nls_codepage);
  			kfree(tmp);
  		} else
  			node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4844
4845
4846
4847
4848
4849
  		node->server_type = le16_to_cpu(ref->ServerType);
  		node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
  
  		/* copy DfsPath */
  		temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
  		max_len = data_end - temp;
acbbb76a2   Steve French   CIFS: Rename *UCS...
4850
4851
  		node->path_name = cifs_strndup_from_utf16(temp, max_len,
  						is_unicode, nls_codepage);
d8e2f53ac   Jeff Layton   cifs: fix error h...
4852
4853
  		if (!node->path_name) {
  			rc = -ENOMEM;
a1fe78f16   Steve French   [CIFS] Add missin...
4854
  			goto parse_DFS_referrals_exit;
066ce6899   Jeff Layton   cifs: rename cifs...
4855
  		}
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4856
4857
4858
4859
  
  		/* copy link target UNC */
  		temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
  		max_len = data_end - temp;
acbbb76a2   Steve French   CIFS: Rename *UCS...
4860
4861
  		node->node_name = cifs_strndup_from_utf16(temp, max_len,
  						is_unicode, nls_codepage);
d8f2799b1   Stefan Metzmacher   fs/cifs: fix pars...
4862
  		if (!node->node_name) {
d8e2f53ac   Jeff Layton   cifs: fix error h...
4863
  			rc = -ENOMEM;
d8f2799b1   Stefan Metzmacher   fs/cifs: fix pars...
4864
4865
4866
4867
  			goto parse_DFS_referrals_exit;
  		}
  
  		ref++;
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4868
  	}
a1fe78f16   Steve French   [CIFS] Add missin...
4869
  parse_DFS_referrals_exit:
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4870
4871
4872
4873
4874
4875
4876
  	if (rc) {
  		free_dfs_info_array(*target_nodes, *num_of_nodes);
  		*target_nodes = NULL;
  		*num_of_nodes = 0;
  	}
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4877
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
4878
  CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
b669f33ca   Pavel Shilovsky   CIFS: Move gettin...
4879
  		const char *search_name, struct dfs_info3_param **target_nodes,
c2cf07d59   Steve French   [CIFS] Finishup D...
4880
  		unsigned int *num_of_nodes,
737b758c9   Steve French   [PATCH] cifs: cha...
4881
  		const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4882
4883
4884
4885
  {
  /* TRANS2_GET_DFS_REFERRAL */
  	TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
  	TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4886
4887
4888
  	int rc = 0;
  	int bytes_returned;
  	int name_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4889
  	__u16 params, byte_count;
c2cf07d59   Steve French   [CIFS] Finishup D...
4890
4891
  	*num_of_nodes = 0;
  	*target_nodes = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4892

f96637be0   Joe Perches   [CIFS] cifs: Rena...
4893
4894
  	cifs_dbg(FYI, "In GetDFSRefer the path %s
  ", search_name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4895
4896
4897
4898
4899
4900
4901
  	if (ses == NULL)
  		return -ENODEV;
  getDFSRetry:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
50c2f7538   Steve French   [CIFS] whitespace...
4902
4903
  
  	/* server pointer checked in called function,
1982c344f   Steve French   [CIFS] Ensure tha...
4904
  	but should never be null here anyway */
882573606   Pavel Shilovsky   CIFS: Move get_ne...
4905
  	pSMB->hdr.Mid = get_next_mid(ses->server);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4906
4907
  	pSMB->hdr.Tid = ses->ipc_tid;
  	pSMB->hdr.Uid = ses->Suid;
26f57364d   Steve French   [CIFS] formatting...
4908
  	if (ses->capabilities & CAP_STATUS32)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4909
  		pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
26f57364d   Steve French   [CIFS] formatting...
4910
  	if (ses->capabilities & CAP_DFS)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4911
  		pSMB->hdr.Flags2 |= SMBFLG2_DFS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4912
4913
4914
4915
  
  	if (ses->capabilities & CAP_UNICODE) {
  		pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
  		name_len =
acbbb76a2   Steve French   CIFS: Rename *UCS...
4916
  		    cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
b669f33ca   Pavel Shilovsky   CIFS: Move gettin...
4917
  				       search_name, PATH_MAX, nls_codepage,
acbbb76a2   Steve French   CIFS: Rename *UCS...
4918
  				       remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4919
4920
  		name_len++;	/* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
4921
  	} else {	/* BB improve the check for buffer overruns BB */
b669f33ca   Pavel Shilovsky   CIFS: Move gettin...
4922
  		name_len = strnlen(search_name, PATH_MAX);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4923
  		name_len++;	/* trailing null */
b669f33ca   Pavel Shilovsky   CIFS: Move gettin...
4924
  		strncpy(pSMB->RequestFileName, search_name, name_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4925
  	}
65c3b205e   Dan Carpenter   CIFS: remove an u...
4926
  	if (ses->server->sign)
38d77c50b   Jeff Layton   cifs: track the e...
4927
  		pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1a4e15a04   Steve French   [CIFS] Missing fl...
4928

50c2f7538   Steve French   [CIFS] whitespace...
4929
  	pSMB->hdr.Uid = ses->Suid;
1a4e15a04   Steve French   [CIFS] Missing fl...
4930

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4931
4932
4933
4934
4935
  	params = 2 /* level */  + name_len /*includes null */ ;
  	pSMB->TotalDataCount = 0;
  	pSMB->DataCount = 0;
  	pSMB->DataOffset = 0;
  	pSMB->MaxParameterCount = 0;
582d21e5e   Steve French   [CIFS] cleanup ol...
4936
4937
  	/* BB find exact max SMB PDU from sess structure BB */
  	pSMB->MaxDataCount = cpu_to_le16(4000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4938
4939
4940
4941
4942
4943
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  	pSMB->Flags = 0;
  	pSMB->Timeout = 0;
  	pSMB->Reserved2 = 0;
  	pSMB->ParameterOffset = cpu_to_le16(offsetof(
50c2f7538   Steve French   [CIFS] whitespace...
4944
  	  struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4945
4946
4947
4948
4949
4950
4951
  	pSMB->SetupCount = 1;
  	pSMB->Reserved3 = 0;
  	pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
  	byte_count = params + 3 /* pad */ ;
  	pSMB->ParameterCount = cpu_to_le16(params);
  	pSMB->TotalParameterCount = pSMB->ParameterCount;
  	pSMB->MaxReferralLevel = cpu_to_le16(3);
be8e3b004   Steve French   consistently use ...
4952
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4953
4954
4955
4956
4957
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  
  	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4958
4959
  		cifs_dbg(FYI, "Send error in GetDFSRefer = %d
  ", rc);
c2cf07d59   Steve French   [CIFS] Finishup D...
4960
4961
4962
  		goto GetDFSRefExit;
  	}
  	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4963

c2cf07d59   Steve French   [CIFS] Finishup D...
4964
  	/* BB Also check if enough total bytes returned? */
820a803ff   Jeff Layton   cifs: keep BCC in...
4965
  	if (rc || get_bcc(&pSMBr->hdr) < 17) {
c2cf07d59   Steve French   [CIFS] Finishup D...
4966
  		rc = -EIO;      /* bad smb */
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4967
4968
  		goto GetDFSRefExit;
  	}
c2cf07d59   Steve French   [CIFS] Finishup D...
4969

f96637be0   Joe Perches   [CIFS] cifs: Rena...
4970
4971
4972
  	cifs_dbg(FYI, "Decoding GetDFSRefer response BCC: %d  Offset %d
  ",
  		 get_bcc(&pSMBr->hdr), le16_to_cpu(pSMBr->t2.DataOffset));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4973

fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4974
  	/* parse returned result into more usable form */
a1fe78f16   Steve French   [CIFS] Add missin...
4975
  	rc = parse_DFS_referrals(pSMBr, num_of_nodes,
2c55608f2   Igor Mammedov   Fixed parsing of ...
4976
  				 target_nodes, nls_codepage, remap,
b669f33ca   Pavel Shilovsky   CIFS: Move gettin...
4977
  				 search_name);
c2cf07d59   Steve French   [CIFS] Finishup D...
4978

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4979
  GetDFSRefExit:
0d817bc0d   Steve French   [CIFS] Remove red...
4980
  	cifs_buf_release(pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4981
4982
4983
4984
4985
4986
  
  	if (rc == -EAGAIN)
  		goto getDFSRetry;
  
  	return rc;
  }
209624388   Steve French   [CIFS] Add suppor...
4987
4988
  /* Query File System Info such as free space to old servers such as Win 9x */
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
4989
4990
  SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
  	      struct kstatfs *FSData)
209624388   Steve French   [CIFS] Add suppor...
4991
4992
4993
4994
4995
4996
4997
4998
  {
  /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
  	TRANSACTION2_QFSI_REQ *pSMB = NULL;
  	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
  	FILE_SYSTEM_ALLOC_INFO *response_data;
  	int rc = 0;
  	int bytes_returned = 0;
  	__u16 params, byte_count;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4999
5000
  	cifs_dbg(FYI, "OldQFSInfo
  ");
209624388   Steve French   [CIFS] Add suppor...
5001
5002
5003
5004
5005
  oldQFSInfoRetry:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  		(void **) &pSMBr);
  	if (rc)
  		return rc;
209624388   Steve French   [CIFS] Add suppor...
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
  
  	params = 2;     /* level */
  	pSMB->TotalDataCount = 0;
  	pSMB->MaxParameterCount = cpu_to_le16(2);
  	pSMB->MaxDataCount = cpu_to_le16(1000);
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  	pSMB->Flags = 0;
  	pSMB->Timeout = 0;
  	pSMB->Reserved2 = 0;
  	byte_count = params + 1 /* pad */ ;
  	pSMB->TotalParameterCount = cpu_to_le16(params);
  	pSMB->ParameterCount = pSMB->TotalParameterCount;
  	pSMB->ParameterOffset = cpu_to_le16(offsetof(
  	struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
  	pSMB->DataCount = 0;
  	pSMB->DataOffset = 0;
  	pSMB->SetupCount = 1;
  	pSMB->Reserved3 = 0;
  	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
  	pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
be8e3b004   Steve French   consistently use ...
5027
  	inc_rfc1001_len(pSMB, byte_count);
209624388   Steve French   [CIFS] Add suppor...
5028
5029
5030
5031
5032
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5033
5034
  		cifs_dbg(FYI, "Send error in QFSInfo = %d
  ", rc);
209624388   Steve French   [CIFS] Add suppor...
5035
5036
  	} else {                /* decode response */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
820a803ff   Jeff Layton   cifs: keep BCC in...
5037
  		if (rc || get_bcc(&pSMBr->hdr) < 18)
209624388   Steve French   [CIFS] Add suppor...
5038
5039
5040
  			rc = -EIO;      /* bad smb */
  		else {
  			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5041
5042
  			cifs_dbg(FYI, "qfsinf resp BCC: %d  Offset %d
  ",
820a803ff   Jeff Layton   cifs: keep BCC in...
5043
  				 get_bcc(&pSMBr->hdr), data_offset);
209624388   Steve French   [CIFS] Add suppor...
5044

50c2f7538   Steve French   [CIFS] whitespace...
5045
  			response_data = (FILE_SYSTEM_ALLOC_INFO *)
209624388   Steve French   [CIFS] Add suppor...
5046
5047
5048
5049
5050
5051
  				(((char *) &pSMBr->hdr.Protocol) + data_offset);
  			FSData->f_bsize =
  				le16_to_cpu(response_data->BytesPerSector) *
  				le32_to_cpu(response_data->
  					SectorsPerAllocationUnit);
  			FSData->f_blocks =
50c2f7538   Steve French   [CIFS] whitespace...
5052
  			       le32_to_cpu(response_data->TotalAllocationUnits);
209624388   Steve French   [CIFS] Add suppor...
5053
5054
  			FSData->f_bfree = FSData->f_bavail =
  				le32_to_cpu(response_data->FreeAllocationUnits);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5055
5056
5057
5058
5059
  			cifs_dbg(FYI, "Blocks: %lld  Free: %lld Block size %ld
  ",
  				 (unsigned long long)FSData->f_blocks,
  				 (unsigned long long)FSData->f_bfree,
  				 FSData->f_bsize);
209624388   Steve French   [CIFS] Add suppor...
5060
5061
5062
5063
5064
5065
5066
5067
5068
  		}
  	}
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto oldQFSInfoRetry;
  
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5069
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
5070
5071
  CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
  	       struct kstatfs *FSData)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5072
5073
5074
5075
5076
5077
5078
5079
  {
  /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
  	TRANSACTION2_QFSI_REQ *pSMB = NULL;
  	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
  	FILE_SYSTEM_INFO *response_data;
  	int rc = 0;
  	int bytes_returned = 0;
  	__u16 params, byte_count;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5080
5081
  	cifs_dbg(FYI, "In QFSInfo
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5082
5083
5084
5085
5086
5087
5088
5089
5090
  QFSInfoRetry:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	params = 2;	/* level */
  	pSMB->TotalDataCount = 0;
  	pSMB->MaxParameterCount = cpu_to_le16(2);
209624388   Steve French   [CIFS] Add suppor...
5091
  	pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5092
5093
5094
5095
5096
5097
5098
5099
5100
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  	pSMB->Flags = 0;
  	pSMB->Timeout = 0;
  	pSMB->Reserved2 = 0;
  	byte_count = params + 1 /* pad */ ;
  	pSMB->TotalParameterCount = cpu_to_le16(params);
  	pSMB->ParameterCount = pSMB->TotalParameterCount;
  	pSMB->ParameterOffset = cpu_to_le16(offsetof(
50c2f7538   Steve French   [CIFS] whitespace...
5101
  		struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5102
5103
5104
5105
5106
5107
  	pSMB->DataCount = 0;
  	pSMB->DataOffset = 0;
  	pSMB->SetupCount = 1;
  	pSMB->Reserved3 = 0;
  	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
  	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
be8e3b004   Steve French   consistently use ...
5108
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5109
5110
5111
5112
5113
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5114
5115
  		cifs_dbg(FYI, "Send error in QFSInfo = %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5116
  	} else {		/* decode response */
50c2f7538   Steve French   [CIFS] whitespace...
5117
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5118

820a803ff   Jeff Layton   cifs: keep BCC in...
5119
  		if (rc || get_bcc(&pSMBr->hdr) < 24)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5120
5121
5122
  			rc = -EIO;	/* bad smb */
  		else {
  			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
  
  			response_data =
  			    (FILE_SYSTEM_INFO
  			     *) (((char *) &pSMBr->hdr.Protocol) +
  				 data_offset);
  			FSData->f_bsize =
  			    le32_to_cpu(response_data->BytesPerSector) *
  			    le32_to_cpu(response_data->
  					SectorsPerAllocationUnit);
  			FSData->f_blocks =
  			    le64_to_cpu(response_data->TotalAllocationUnits);
  			FSData->f_bfree = FSData->f_bavail =
  			    le64_to_cpu(response_data->FreeAllocationUnits);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5136
5137
5138
5139
5140
  			cifs_dbg(FYI, "Blocks: %lld  Free: %lld Block size %ld
  ",
  				 (unsigned long long)FSData->f_blocks,
  				 (unsigned long long)FSData->f_bfree,
  				 FSData->f_bsize);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
  		}
  	}
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto QFSInfoRetry;
  
  	return rc;
  }
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
5152
  CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5153
5154
5155
5156
5157
5158
5159
5160
  {
  /* level 0x105  SMB_QUERY_FILE_SYSTEM_INFO */
  	TRANSACTION2_QFSI_REQ *pSMB = NULL;
  	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
  	FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
  	int rc = 0;
  	int bytes_returned = 0;
  	__u16 params, byte_count;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5161
5162
  	cifs_dbg(FYI, "In QFSAttributeInfo
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5163
5164
5165
5166
5167
5168
5169
5170
5171
  QFSAttributeRetry:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	params = 2;	/* level */
  	pSMB->TotalDataCount = 0;
  	pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5e   Steve French   [CIFS] cleanup ol...
5172
5173
  	/* BB find exact max SMB PDU from sess structure BB */
  	pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5174
5175
5176
5177
5178
5179
5180
5181
5182
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  	pSMB->Flags = 0;
  	pSMB->Timeout = 0;
  	pSMB->Reserved2 = 0;
  	byte_count = params + 1 /* pad */ ;
  	pSMB->TotalParameterCount = cpu_to_le16(params);
  	pSMB->ParameterCount = pSMB->TotalParameterCount;
  	pSMB->ParameterOffset = cpu_to_le16(offsetof(
50c2f7538   Steve French   [CIFS] whitespace...
5183
  		struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5184
5185
5186
5187
5188
5189
  	pSMB->DataCount = 0;
  	pSMB->DataOffset = 0;
  	pSMB->SetupCount = 1;
  	pSMB->Reserved3 = 0;
  	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
  	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
be8e3b004   Steve French   consistently use ...
5190
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5191
5192
5193
5194
5195
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5196
5197
  		cifs_dbg(VFS, "Send error in QFSAttributeInfo = %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5198
5199
  	} else {		/* decode response */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
820a803ff   Jeff Layton   cifs: keep BCC in...
5200
  		if (rc || get_bcc(&pSMBr->hdr) < 13) {
50c2f7538   Steve French   [CIFS] whitespace...
5201
  			/* BB also check if enough bytes returned */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5202
5203
5204
5205
5206
5207
5208
5209
  			rc = -EIO;	/* bad smb */
  		} else {
  			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
  			response_data =
  			    (FILE_SYSTEM_ATTRIBUTE_INFO
  			     *) (((char *) &pSMBr->hdr.Protocol) +
  				 data_offset);
  			memcpy(&tcon->fsAttrInfo, response_data,
26f57364d   Steve French   [CIFS] formatting...
5210
  			       sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
  		}
  	}
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto QFSAttributeRetry;
  
  	return rc;
  }
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
5222
  CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5223
5224
5225
5226
5227
5228
5229
5230
  {
  /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
  	TRANSACTION2_QFSI_REQ *pSMB = NULL;
  	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
  	FILE_SYSTEM_DEVICE_INFO *response_data;
  	int rc = 0;
  	int bytes_returned = 0;
  	__u16 params, byte_count;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5231
5232
  	cifs_dbg(FYI, "In QFSDeviceInfo
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5233
5234
5235
5236
5237
5238
5239
5240
5241
  QFSDeviceRetry:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	params = 2;	/* level */
  	pSMB->TotalDataCount = 0;
  	pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5e   Steve French   [CIFS] cleanup ol...
5242
5243
  	/* BB find exact max SMB PDU from sess structure BB */
  	pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5244
5245
5246
5247
5248
5249
5250
5251
5252
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  	pSMB->Flags = 0;
  	pSMB->Timeout = 0;
  	pSMB->Reserved2 = 0;
  	byte_count = params + 1 /* pad */ ;
  	pSMB->TotalParameterCount = cpu_to_le16(params);
  	pSMB->ParameterCount = pSMB->TotalParameterCount;
  	pSMB->ParameterOffset = cpu_to_le16(offsetof(
50c2f7538   Steve French   [CIFS] whitespace...
5253
  		struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5254
5255
5256
5257
5258
5259
5260
  
  	pSMB->DataCount = 0;
  	pSMB->DataOffset = 0;
  	pSMB->SetupCount = 1;
  	pSMB->Reserved3 = 0;
  	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
  	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
be8e3b004   Steve French   consistently use ...
5261
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5262
5263
5264
5265
5266
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5267
5268
  		cifs_dbg(FYI, "Send error in QFSDeviceInfo = %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5269
5270
  	} else {		/* decode response */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
820a803ff   Jeff Layton   cifs: keep BCC in...
5271
5272
  		if (rc || get_bcc(&pSMBr->hdr) <
  			  sizeof(FILE_SYSTEM_DEVICE_INFO))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5273
5274
5275
5276
  			rc = -EIO;	/* bad smb */
  		else {
  			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
  			response_data =
737b758c9   Steve French   [PATCH] cifs: cha...
5277
5278
  			    (FILE_SYSTEM_DEVICE_INFO *)
  				(((char *) &pSMBr->hdr.Protocol) +
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5279
5280
  				 data_offset);
  			memcpy(&tcon->fsDevInfo, response_data,
26f57364d   Steve French   [CIFS] formatting...
5281
  			       sizeof(FILE_SYSTEM_DEVICE_INFO));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
  		}
  	}
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto QFSDeviceRetry;
  
  	return rc;
  }
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
5293
  CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5294
5295
5296
5297
5298
5299
5300
5301
  {
  /* level 0x200  SMB_QUERY_CIFS_UNIX_INFO */
  	TRANSACTION2_QFSI_REQ *pSMB = NULL;
  	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
  	FILE_SYSTEM_UNIX_INFO *response_data;
  	int rc = 0;
  	int bytes_returned = 0;
  	__u16 params, byte_count;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5302
5303
  	cifs_dbg(FYI, "In QFSUnixInfo
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5304
  QFSUnixRetry:
f569599ae   Jeff Layton   cifs: prevent inf...
5305
5306
  	rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
  				   (void **) &pSMB, (void **) &pSMBr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5307
5308
5309
5310
5311
5312
5313
5314
  	if (rc)
  		return rc;
  
  	params = 2;	/* level */
  	pSMB->TotalDataCount = 0;
  	pSMB->DataCount = 0;
  	pSMB->DataOffset = 0;
  	pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5e   Steve French   [CIFS] cleanup ol...
5315
5316
  	/* BB find exact max SMB PDU from sess structure BB */
  	pSMB->MaxDataCount = cpu_to_le16(100);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5317
5318
5319
5320
5321
5322
5323
5324
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  	pSMB->Flags = 0;
  	pSMB->Timeout = 0;
  	pSMB->Reserved2 = 0;
  	byte_count = params + 1 /* pad */ ;
  	pSMB->ParameterCount = cpu_to_le16(params);
  	pSMB->TotalParameterCount = pSMB->ParameterCount;
50c2f7538   Steve French   [CIFS] whitespace...
5325
5326
  	pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
  			smb_com_transaction2_qfsi_req, InformationLevel) - 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5327
5328
5329
5330
  	pSMB->SetupCount = 1;
  	pSMB->Reserved3 = 0;
  	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
  	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
be8e3b004   Steve French   consistently use ...
5331
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5332
5333
5334
5335
5336
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5337
5338
  		cifs_dbg(VFS, "Send error in QFSUnixInfo = %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5339
5340
  	} else {		/* decode response */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
820a803ff   Jeff Layton   cifs: keep BCC in...
5341
  		if (rc || get_bcc(&pSMBr->hdr) < 13) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5342
5343
5344
5345
5346
5347
5348
5349
  			rc = -EIO;	/* bad smb */
  		} else {
  			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
  			response_data =
  			    (FILE_SYSTEM_UNIX_INFO
  			     *) (((char *) &pSMBr->hdr.Protocol) +
  				 data_offset);
  			memcpy(&tcon->fsUnixInfo, response_data,
26f57364d   Steve French   [CIFS] formatting...
5350
  			       sizeof(FILE_SYSTEM_UNIX_INFO));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
  		}
  	}
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto QFSUnixRetry;
  
  
  	return rc;
  }
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
5361
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
5362
  CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
5363
5364
5365
5366
5367
5368
5369
  {
  /* level 0x200  SMB_SET_CIFS_UNIX_INFO */
  	TRANSACTION2_SETFSI_REQ *pSMB = NULL;
  	TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
  	int rc = 0;
  	int bytes_returned = 0;
  	__u16 params, param_offset, offset, byte_count;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5370
5371
  	cifs_dbg(FYI, "In SETFSUnixInfo
  ");
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
5372
  SETFSUnixRetry:
f26282c9a   Steve French   [CIFS] Use correc...
5373
  	/* BB switch to small buf init to save memory */
f569599ae   Jeff Layton   cifs: prevent inf...
5374
5375
  	rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
  					(void **) &pSMB, (void **) &pSMBr);
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
5376
5377
5378
5379
5380
5381
5382
5383
5384
  	if (rc)
  		return rc;
  
  	params = 4;	/* 2 bytes zero followed by info level. */
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  	pSMB->Flags = 0;
  	pSMB->Timeout = 0;
  	pSMB->Reserved2 = 0;
50c2f7538   Steve French   [CIFS] whitespace...
5385
5386
  	param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
  				- 4;
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
5387
5388
5389
  	offset = param_offset + params;
  
  	pSMB->MaxParameterCount = cpu_to_le16(4);
582d21e5e   Steve French   [CIFS] cleanup ol...
5390
5391
  	/* BB find exact max SMB PDU from sess structure BB */
  	pSMB->MaxDataCount = cpu_to_le16(100);
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
  	pSMB->SetupCount = 1;
  	pSMB->Reserved3 = 0;
  	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
  	byte_count = 1 /* pad */ + params + 12;
  
  	pSMB->DataCount = cpu_to_le16(12);
  	pSMB->ParameterCount = cpu_to_le16(params);
  	pSMB->TotalDataCount = pSMB->DataCount;
  	pSMB->TotalParameterCount = pSMB->ParameterCount;
  	pSMB->ParameterOffset = cpu_to_le16(param_offset);
  	pSMB->DataOffset = cpu_to_le16(offset);
  
  	/* Params. */
  	pSMB->FileNum = 0;
  	pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
  
  	/* Data. */
  	pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
  	pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
  	pSMB->ClientUnixCap = cpu_to_le64(cap);
be8e3b004   Steve French   consistently use ...
5412
  	inc_rfc1001_len(pSMB, byte_count);
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
5413
5414
5415
5416
5417
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5418
5419
  		cifs_dbg(VFS, "Send error in SETFSUnixInfo = %d
  ", rc);
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
5420
5421
  	} else {		/* decode response */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
ad7a2926b   Steve French   [CIFS] reduce che...
5422
  		if (rc)
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
5423
  			rc = -EIO;	/* bad smb */
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
5424
5425
5426
5427
5428
5429
5430
5431
  	}
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto SETFSUnixRetry;
  
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5432
5433
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
5434
  CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
737b758c9   Steve French   [PATCH] cifs: cha...
5435
  		   struct kstatfs *FSData)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5436
5437
5438
5439
5440
5441
5442
5443
  {
  /* level 0x201  SMB_QUERY_CIFS_POSIX_INFO */
  	TRANSACTION2_QFSI_REQ *pSMB = NULL;
  	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
  	FILE_SYSTEM_POSIX_INFO *response_data;
  	int rc = 0;
  	int bytes_returned = 0;
  	__u16 params, byte_count;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5444
5445
  	cifs_dbg(FYI, "In QFSPosixInfo
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
  QFSPosixRetry:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	params = 2;	/* level */
  	pSMB->TotalDataCount = 0;
  	pSMB->DataCount = 0;
  	pSMB->DataOffset = 0;
  	pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5e   Steve French   [CIFS] cleanup ol...
5457
5458
  	/* BB find exact max SMB PDU from sess structure BB */
  	pSMB->MaxDataCount = cpu_to_le16(100);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5459
5460
5461
5462
5463
5464
5465
5466
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  	pSMB->Flags = 0;
  	pSMB->Timeout = 0;
  	pSMB->Reserved2 = 0;
  	byte_count = params + 1 /* pad */ ;
  	pSMB->ParameterCount = cpu_to_le16(params);
  	pSMB->TotalParameterCount = pSMB->ParameterCount;
50c2f7538   Steve French   [CIFS] whitespace...
5467
5468
  	pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
  			smb_com_transaction2_qfsi_req, InformationLevel) - 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5469
5470
5471
5472
  	pSMB->SetupCount = 1;
  	pSMB->Reserved3 = 0;
  	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
  	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
be8e3b004   Steve French   consistently use ...
5473
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5474
5475
5476
5477
5478
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5479
5480
  		cifs_dbg(FYI, "Send error in QFSUnixInfo = %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5481
5482
  	} else {		/* decode response */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
820a803ff   Jeff Layton   cifs: keep BCC in...
5483
  		if (rc || get_bcc(&pSMBr->hdr) < 13) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
  			rc = -EIO;	/* bad smb */
  		} else {
  			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
  			response_data =
  			    (FILE_SYSTEM_POSIX_INFO
  			     *) (((char *) &pSMBr->hdr.Protocol) +
  				 data_offset);
  			FSData->f_bsize =
  					le32_to_cpu(response_data->BlockSize);
  			FSData->f_blocks =
  					le64_to_cpu(response_data->TotalBlocks);
  			FSData->f_bfree =
  			    le64_to_cpu(response_data->BlocksAvail);
790fe579f   Steve French   [CIFS] more white...
5497
  			if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5498
5499
5500
  				FSData->f_bavail = FSData->f_bfree;
  			} else {
  				FSData->f_bavail =
50c2f7538   Steve French   [CIFS] whitespace...
5501
  				    le64_to_cpu(response_data->UserBlocksAvail);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5502
  			}
790fe579f   Steve French   [CIFS] more white...
5503
  			if (response_data->TotalFileNodes != cpu_to_le64(-1))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5504
  				FSData->f_files =
50c2f7538   Steve French   [CIFS] whitespace...
5505
  				     le64_to_cpu(response_data->TotalFileNodes);
790fe579f   Steve French   [CIFS] more white...
5506
  			if (response_data->FreeFileNodes != cpu_to_le64(-1))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5507
  				FSData->f_ffree =
50c2f7538   Steve French   [CIFS] whitespace...
5508
  				      le64_to_cpu(response_data->FreeFileNodes);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5509
5510
5511
5512
5513
5514
5515
5516
5517
  		}
  	}
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto QFSPosixRetry;
  
  	return rc;
  }
d14334181   Pavel Shilovsky   CIFS: Move set_fi...
5518
5519
5520
5521
5522
5523
  /*
   * We can not use write of zero bytes trick to set file size due to need for
   * large file support. Also note that this SetPathInfo is preferred to
   * SetFileInfo based method in next routine which is only needed to work around
   * a sharing violation bugin Samba which this routine can run into.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5524
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
5525
  CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
d14334181   Pavel Shilovsky   CIFS: Move set_fi...
5526
5527
  	      const char *file_name, __u64 size, struct cifs_sb_info *cifs_sb,
  	      bool set_allocation)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5528
5529
5530
5531
5532
5533
5534
  {
  	struct smb_com_transaction2_spi_req *pSMB = NULL;
  	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
  	struct file_end_of_file_info *parm_data;
  	int name_len;
  	int rc = 0;
  	int bytes_returned = 0;
2baa26825   Steve French   Remap reserved po...
5535
  	int remap = cifs_remap(cifs_sb);
d14334181   Pavel Shilovsky   CIFS: Move set_fi...
5536

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5537
  	__u16 params, byte_count, data_count, param_offset, offset;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5538
5539
  	cifs_dbg(FYI, "In SetEOF
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5540
5541
5542
5543
5544
5545
5546
5547
  SetEOFRetry:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		name_len =
d14334181   Pavel Shilovsky   CIFS: Move set_fi...
5548
5549
  		    cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
  				       PATH_MAX, cifs_sb->local_nls, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5550
5551
  		name_len++;	/* trailing null */
  		name_len *= 2;
3e87d8039   Steve French   [CIFS] Add suppor...
5552
  	} else {	/* BB improve the check for buffer overruns BB */
d14334181   Pavel Shilovsky   CIFS: Move set_fi...
5553
  		name_len = strnlen(file_name, PATH_MAX);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5554
  		name_len++;	/* trailing null */
d14334181   Pavel Shilovsky   CIFS: Move set_fi...
5555
  		strncpy(pSMB->FileName, file_name, name_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5556
5557
  	}
  	params = 6 + name_len;
26f57364d   Steve French   [CIFS] formatting...
5558
  	data_count = sizeof(struct file_end_of_file_info);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5559
  	pSMB->MaxParameterCount = cpu_to_le16(2);
3e87d8039   Steve French   [CIFS] Add suppor...
5560
  	pSMB->MaxDataCount = cpu_to_le16(4100);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5561
5562
5563
5564
5565
5566
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  	pSMB->Flags = 0;
  	pSMB->Timeout = 0;
  	pSMB->Reserved2 = 0;
  	param_offset = offsetof(struct smb_com_transaction2_spi_req,
50c2f7538   Steve French   [CIFS] whitespace...
5567
  				InformationLevel) - 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5568
  	offset = param_offset + params;
d14334181   Pavel Shilovsky   CIFS: Move set_fi...
5569
  	if (set_allocation) {
50c2f7538   Steve French   [CIFS] whitespace...
5570
5571
5572
5573
5574
5575
5576
  		if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
  			pSMB->InformationLevel =
  				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
  		else
  			pSMB->InformationLevel =
  				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
  	} else /* Set File Size */  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5577
5578
  	    if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
  		    pSMB->InformationLevel =
50c2f7538   Steve French   [CIFS] whitespace...
5579
  				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5580
5581
  	    else
  		    pSMB->InformationLevel =
50c2f7538   Steve French   [CIFS] whitespace...
5582
  				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
  	}
  
  	parm_data =
  	    (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
  				       offset);
  	pSMB->ParameterOffset = cpu_to_le16(param_offset);
  	pSMB->DataOffset = cpu_to_le16(offset);
  	pSMB->SetupCount = 1;
  	pSMB->Reserved3 = 0;
  	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
  	byte_count = 3 /* pad */  + params + data_count;
  	pSMB->DataCount = cpu_to_le16(data_count);
  	pSMB->TotalDataCount = pSMB->DataCount;
  	pSMB->ParameterCount = cpu_to_le16(params);
  	pSMB->TotalParameterCount = pSMB->ParameterCount;
  	pSMB->Reserved4 = 0;
be8e3b004   Steve French   consistently use ...
5599
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5600
5601
5602
5603
  	parm_data->FileSize = cpu_to_le64(size);
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
ad7a2926b   Steve French   [CIFS] reduce che...
5604
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5605
5606
  		cifs_dbg(FYI, "SetPathInfo (file size) returned %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
  
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto SetEOFRetry;
  
  	return rc;
  }
  
  int
d14334181   Pavel Shilovsky   CIFS: Move set_fi...
5617
5618
  CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
  		   struct cifsFileInfo *cfile, __u64 size, bool set_allocation)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5619
5620
  {
  	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5621
5622
  	struct file_end_of_file_info *parm_data;
  	int rc = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5623
  	__u16 params, param_offset, offset, byte_count, count;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5624
5625
5626
  	cifs_dbg(FYI, "SetFileSize (via SetFileInfo) %lld
  ",
  		 (long long)size);
cd63499cb   Steve French   [PATCH] cifs: Han...
5627
  	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5628
5629
  	if (rc)
  		return rc;
d14334181   Pavel Shilovsky   CIFS: Move set_fi...
5630
5631
  	pSMB->hdr.Pid = cpu_to_le16((__u16)cfile->pid);
  	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(cfile->pid >> 16));
50c2f7538   Steve French   [CIFS] whitespace...
5632

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5633
5634
5635
5636
5637
5638
5639
5640
  	params = 6;
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  	pSMB->Flags = 0;
  	pSMB->Timeout = 0;
  	pSMB->Reserved2 = 0;
  	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
  	offset = param_offset + params;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5641
5642
  	count = sizeof(struct file_end_of_file_info);
  	pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5e   Steve French   [CIFS] cleanup ol...
5643
5644
  	/* BB find exact max SMB PDU from sess structure BB */
  	pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
  	pSMB->SetupCount = 1;
  	pSMB->Reserved3 = 0;
  	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
  	byte_count = 3 /* pad */  + params + count;
  	pSMB->DataCount = cpu_to_le16(count);
  	pSMB->ParameterCount = cpu_to_le16(params);
  	pSMB->TotalDataCount = pSMB->DataCount;
  	pSMB->TotalParameterCount = pSMB->ParameterCount;
  	pSMB->ParameterOffset = cpu_to_le16(param_offset);
  	parm_data =
50c2f7538   Steve French   [CIFS] whitespace...
5655
5656
  		(struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
  				+ offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5657
5658
  	pSMB->DataOffset = cpu_to_le16(offset);
  	parm_data->FileSize = cpu_to_le64(size);
d14334181   Pavel Shilovsky   CIFS: Move set_fi...
5659
5660
  	pSMB->Fid = cfile->fid.netfid;
  	if (set_allocation) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5661
5662
5663
5664
5665
5666
  		if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
  			pSMB->InformationLevel =
  				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
  		else
  			pSMB->InformationLevel =
  				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
50c2f7538   Steve French   [CIFS] whitespace...
5667
  	} else /* Set File Size */  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5668
5669
  	    if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
  		    pSMB->InformationLevel =
50c2f7538   Steve French   [CIFS] whitespace...
5670
  				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5671
5672
  	    else
  		    pSMB->InformationLevel =
50c2f7538   Steve French   [CIFS] whitespace...
5673
  				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5674
5675
  	}
  	pSMB->Reserved4 = 0;
be8e3b004   Steve French   consistently use ...
5676
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5677
  	pSMB->ByteCount = cpu_to_le16(byte_count);
792af7b05   Pavel Shilovsky   CIFS: Separate pr...
5678
  	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5679
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5680
5681
5682
  		cifs_dbg(FYI, "Send error in SetFileInfo (SetFileSize) = %d
  ",
  			 rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5683
  	}
50c2f7538   Steve French   [CIFS] whitespace...
5684
  	/* Note: On -EAGAIN error only caller can retry on handle based calls
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5685
5686
5687
5688
  		since file handle passed in no longer valid */
  
  	return rc;
  }
50c2f7538   Steve French   [CIFS] whitespace...
5689
  /* Some legacy servers such as NT4 require that the file times be set on
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5690
5691
5692
5693
5694
5695
     an open handle, rather than by pathname - this is awkward due to
     potential access conflicts on the open, but it is unavoidable for these
     old servers since the only other choice is to go from 100 nanosecond DCE
     time and resort to the original setpathinfo level which takes the ancient
     DOS time format with 2 second granularity */
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
5696
  CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
2dd2dfa06   Jeff Layton   Rename CIFSSMBSet...
5697
  		    const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5698
5699
  {
  	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5700
5701
  	char *data_offset;
  	int rc = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5702
  	__u16 params, param_offset, offset, byte_count, count;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5703
5704
  	cifs_dbg(FYI, "Set Times (via SetFileInfo)
  ");
cd63499cb   Steve French   [PATCH] cifs: Han...
5705
  	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5706
5707
  	if (rc)
  		return rc;
2dd2dfa06   Jeff Layton   Rename CIFSSMBSet...
5708
5709
  	pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
  	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
50c2f7538   Steve French   [CIFS] whitespace...
5710

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5711
5712
5713
5714
5715
5716
5717
5718
  	params = 6;
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  	pSMB->Flags = 0;
  	pSMB->Timeout = 0;
  	pSMB->Reserved2 = 0;
  	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
  	offset = param_offset + params;
b2a3ad9ca   Jeff Layton   cifs: silence com...
5719
5720
  	data_offset = (char *)pSMB +
  			offsetof(struct smb_hdr, Protocol) + offset;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5721

26f57364d   Steve French   [CIFS] formatting...
5722
  	count = sizeof(FILE_BASIC_INFO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5723
  	pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5e   Steve French   [CIFS] cleanup ol...
5724
5725
  	/* BB find max SMB PDU from sess */
  	pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
  	pSMB->SetupCount = 1;
  	pSMB->Reserved3 = 0;
  	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
  	byte_count = 3 /* pad */  + params + count;
  	pSMB->DataCount = cpu_to_le16(count);
  	pSMB->ParameterCount = cpu_to_le16(params);
  	pSMB->TotalDataCount = pSMB->DataCount;
  	pSMB->TotalParameterCount = pSMB->ParameterCount;
  	pSMB->ParameterOffset = cpu_to_le16(param_offset);
  	pSMB->DataOffset = cpu_to_le16(offset);
  	pSMB->Fid = fid;
  	if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
  		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
  	else
  		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
  	pSMB->Reserved4 = 0;
be8e3b004   Steve French   consistently use ...
5742
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5743
  	pSMB->ByteCount = cpu_to_le16(byte_count);
50c2f7538   Steve French   [CIFS] whitespace...
5744
  	memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
792af7b05   Pavel Shilovsky   CIFS: Separate pr...
5745
  	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
ad7a2926b   Steve French   [CIFS] reduce che...
5746
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5747
5748
5749
  		cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d
  ",
  			 rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5750

50c2f7538   Steve French   [CIFS] whitespace...
5751
  	/* Note: On -EAGAIN error only caller can retry on handle based calls
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5752
5753
5754
5755
  		since file handle passed in no longer valid */
  
  	return rc;
  }
6d22f0989   Jeff Layton   cifs: add functio...
5756
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
5757
  CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
6d22f0989   Jeff Layton   cifs: add functio...
5758
5759
5760
5761
5762
5763
  			  bool delete_file, __u16 fid, __u32 pid_of_opener)
  {
  	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
  	char *data_offset;
  	int rc = 0;
  	__u16 params, param_offset, offset, byte_count, count;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5764
5765
  	cifs_dbg(FYI, "Set File Disposition (via SetFileInfo)
  ");
6d22f0989   Jeff Layton   cifs: add functio...
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
  	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
  
  	if (rc)
  		return rc;
  
  	pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
  	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
  
  	params = 6;
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  	pSMB->Flags = 0;
  	pSMB->Timeout = 0;
  	pSMB->Reserved2 = 0;
  	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
  	offset = param_offset + params;
  
  	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
  
  	count = 1;
  	pSMB->MaxParameterCount = cpu_to_le16(2);
  	/* BB find max SMB PDU from sess */
  	pSMB->MaxDataCount = cpu_to_le16(1000);
  	pSMB->SetupCount = 1;
  	pSMB->Reserved3 = 0;
  	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
  	byte_count = 3 /* pad */  + params + count;
  	pSMB->DataCount = cpu_to_le16(count);
  	pSMB->ParameterCount = cpu_to_le16(params);
  	pSMB->TotalDataCount = pSMB->DataCount;
  	pSMB->TotalParameterCount = pSMB->ParameterCount;
  	pSMB->ParameterOffset = cpu_to_le16(param_offset);
  	pSMB->DataOffset = cpu_to_le16(offset);
  	pSMB->Fid = fid;
  	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
  	pSMB->Reserved4 = 0;
be8e3b004   Steve French   consistently use ...
5802
  	inc_rfc1001_len(pSMB, byte_count);
6d22f0989   Jeff Layton   cifs: add functio...
5803
5804
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  	*data_offset = delete_file ? 1 : 0;
792af7b05   Pavel Shilovsky   CIFS: Separate pr...
5805
  	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
6d22f0989   Jeff Layton   cifs: add functio...
5806
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5807
5808
  		cifs_dbg(FYI, "Send error in SetFileDisposition = %d
  ", rc);
6d22f0989   Jeff Layton   cifs: add functio...
5809
5810
5811
  
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5812
5813
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
5814
  CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
6fc000e51   Jeff Layton   change CIFSSMBSet...
5815
5816
  		   const char *fileName, const FILE_BASIC_INFO *data,
  		   const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5817
5818
5819
5820
5821
5822
5823
5824
  {
  	TRANSACTION2_SPI_REQ *pSMB = NULL;
  	TRANSACTION2_SPI_RSP *pSMBr = NULL;
  	int name_len;
  	int rc = 0;
  	int bytes_returned = 0;
  	char *data_offset;
  	__u16 params, param_offset, offset, byte_count, count;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5825
5826
  	cifs_dbg(FYI, "In SetTimes
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5827
5828
5829
5830
5831
5832
5833
5834
5835
  
  SetTimesRetry:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		name_len =
acbbb76a2   Steve French   CIFS: Rename *UCS...
5836
5837
  		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
  				       PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5838
5839
  		name_len++;	/* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
5840
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5841
5842
5843
5844
5845
5846
  		name_len = strnlen(fileName, PATH_MAX);
  		name_len++;	/* trailing null */
  		strncpy(pSMB->FileName, fileName, name_len);
  	}
  
  	params = 6 + name_len;
26f57364d   Steve French   [CIFS] formatting...
5847
  	count = sizeof(FILE_BASIC_INFO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5848
  	pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5e   Steve French   [CIFS] cleanup ol...
5849
5850
  	/* BB find max SMB PDU from sess structure BB */
  	pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5851
5852
5853
5854
5855
5856
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  	pSMB->Flags = 0;
  	pSMB->Timeout = 0;
  	pSMB->Reserved2 = 0;
  	param_offset = offsetof(struct smb_com_transaction2_spi_req,
50c2f7538   Steve French   [CIFS] whitespace...
5857
  				InformationLevel) - 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
  	offset = param_offset + params;
  	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
  	pSMB->ParameterOffset = cpu_to_le16(param_offset);
  	pSMB->DataOffset = cpu_to_le16(offset);
  	pSMB->SetupCount = 1;
  	pSMB->Reserved3 = 0;
  	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
  	byte_count = 3 /* pad */  + params + count;
  
  	pSMB->DataCount = cpu_to_le16(count);
  	pSMB->ParameterCount = cpu_to_le16(params);
  	pSMB->TotalDataCount = pSMB->DataCount;
  	pSMB->TotalParameterCount = pSMB->ParameterCount;
  	if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
  		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
  	else
  		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
  	pSMB->Reserved4 = 0;
be8e3b004   Steve French   consistently use ...
5876
  	inc_rfc1001_len(pSMB, byte_count);
26f57364d   Steve French   [CIFS] formatting...
5877
  	memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5878
5879
5880
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
ad7a2926b   Steve French   [CIFS] reduce che...
5881
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5882
5883
  		cifs_dbg(FYI, "SetPathInfo (times) returned %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
  
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto SetTimesRetry;
  
  	return rc;
  }
  
  /* Can not be used to set time stamps yet (due to old DOS time format) */
  /* Can be used to set attributes */
  #if 0  /* Possibly not needed - since it turns out that strangely NT4 has a bug
  	  handling it anyway and NT4 was what we thought it would be needed for
  	  Do not delete it until we prove whether needed for Win9x though */
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
5899
  CIFSSMBSetAttrLegacy(unsigned int xid, struct cifs_tcon *tcon, char *fileName,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5900
5901
5902
5903
5904
5905
5906
  		__u16 dos_attrs, const struct nls_table *nls_codepage)
  {
  	SETATTR_REQ *pSMB = NULL;
  	SETATTR_RSP *pSMBr = NULL;
  	int rc = 0;
  	int bytes_returned;
  	int name_len;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5907
5908
  	cifs_dbg(FYI, "In SetAttrLegacy
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5909
5910
5911
5912
5913
5914
5915
5916
5917
  
  SetAttrLgcyRetry:
  	rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		name_len =
acbbb76a2   Steve French   CIFS: Rename *UCS...
5918
5919
  			ConvertToUTF16((__le16 *) pSMB->fileName, fileName,
  				       PATH_MAX, nls_codepage);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5920
5921
  		name_len++;     /* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
5922
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5923
5924
5925
5926
5927
5928
  		name_len = strnlen(fileName, PATH_MAX);
  		name_len++;     /* trailing null */
  		strncpy(pSMB->fileName, fileName, name_len);
  	}
  	pSMB->attr = cpu_to_le16(dos_attrs);
  	pSMB->BufferFormat = 0x04;
be8e3b004   Steve French   consistently use ...
5929
  	inc_rfc1001_len(pSMB, name_len + 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5930
5931
5932
  	pSMB->ByteCount = cpu_to_le16(name_len + 1);
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
ad7a2926b   Steve French   [CIFS] reduce che...
5933
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5934
5935
  		cifs_dbg(FYI, "Error in LegacySetAttr = %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5936
5937
5938
5939
5940
5941
5942
5943
5944
  
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto SetAttrLgcyRetry;
  
  	return rc;
  }
  #endif /* temporarily unneeded SetAttr legacy function */
654cf14ac   Jeff Layton   cifs: make a sepa...
5945
5946
5947
5948
  static void
  cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
  			const struct cifs_unix_set_info_args *args)
  {
49418b2c2   Eric W. Biederman   cifs: Modify stru...
5949
  	u64 uid = NO_CHANGE_64, gid = NO_CHANGE_64;
654cf14ac   Jeff Layton   cifs: make a sepa...
5950
  	u64 mode = args->mode;
49418b2c2   Eric W. Biederman   cifs: Modify stru...
5951
5952
5953
5954
  	if (uid_valid(args->uid))
  		uid = from_kuid(&init_user_ns, args->uid);
  	if (gid_valid(args->gid))
  		gid = from_kgid(&init_user_ns, args->gid);
654cf14ac   Jeff Layton   cifs: make a sepa...
5955
5956
5957
5958
  	/*
  	 * Samba server ignores set of file size to zero due to bugs in some
  	 * older clients, but we should be precise - we use SetFileSize to
  	 * set file size and do not want to truncate file size to zero
25985edce   Lucas De Marchi   Fix common misspe...
5959
  	 * accidentally as happened on one Samba server beta by putting
654cf14ac   Jeff Layton   cifs: make a sepa...
5960
5961
5962
5963
5964
5965
5966
  	 * zero instead of -1 here
  	 */
  	data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
  	data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
  	data_offset->LastStatusChange = cpu_to_le64(args->ctime);
  	data_offset->LastAccessTime = cpu_to_le64(args->atime);
  	data_offset->LastModificationTime = cpu_to_le64(args->mtime);
49418b2c2   Eric W. Biederman   cifs: Modify stru...
5967
5968
  	data_offset->Uid = cpu_to_le64(uid);
  	data_offset->Gid = cpu_to_le64(gid);
654cf14ac   Jeff Layton   cifs: make a sepa...
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
  	/* better to leave device as zero when it is  */
  	data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
  	data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
  	data_offset->Permissions = cpu_to_le64(mode);
  
  	if (S_ISREG(mode))
  		data_offset->Type = cpu_to_le32(UNIX_FILE);
  	else if (S_ISDIR(mode))
  		data_offset->Type = cpu_to_le32(UNIX_DIR);
  	else if (S_ISLNK(mode))
  		data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
  	else if (S_ISCHR(mode))
  		data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
  	else if (S_ISBLK(mode))
  		data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
  	else if (S_ISFIFO(mode))
  		data_offset->Type = cpu_to_le32(UNIX_FIFO);
  	else if (S_ISSOCK(mode))
  		data_offset->Type = cpu_to_le32(UNIX_SOCKET);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5989
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
5990
  CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
3bbeeb3c9   Jeff Layton   cifs: add and use...
5991
5992
5993
5994
  		       const struct cifs_unix_set_info_args *args,
  		       u16 fid, u32 pid_of_opener)
  {
  	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
b2a3ad9ca   Jeff Layton   cifs: silence com...
5995
  	char *data_offset;
3bbeeb3c9   Jeff Layton   cifs: add and use...
5996
5997
  	int rc = 0;
  	u16 params, param_offset, offset, byte_count, count;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5998
5999
  	cifs_dbg(FYI, "Set Unix Info (via SetFileInfo)
  ");
3bbeeb3c9   Jeff Layton   cifs: add and use...
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
  	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
  
  	if (rc)
  		return rc;
  
  	pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
  	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
  
  	params = 6;
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  	pSMB->Flags = 0;
  	pSMB->Timeout = 0;
  	pSMB->Reserved2 = 0;
  	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
  	offset = param_offset + params;
b2a3ad9ca   Jeff Layton   cifs: silence com...
6016
6017
  	data_offset = (char *)pSMB +
  			offsetof(struct smb_hdr, Protocol) + offset;
3bbeeb3c9   Jeff Layton   cifs: add and use...
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
  	count = sizeof(FILE_UNIX_BASIC_INFO);
  
  	pSMB->MaxParameterCount = cpu_to_le16(2);
  	/* BB find max SMB PDU from sess */
  	pSMB->MaxDataCount = cpu_to_le16(1000);
  	pSMB->SetupCount = 1;
  	pSMB->Reserved3 = 0;
  	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
  	byte_count = 3 /* pad */  + params + count;
  	pSMB->DataCount = cpu_to_le16(count);
  	pSMB->ParameterCount = cpu_to_le16(params);
  	pSMB->TotalDataCount = pSMB->DataCount;
  	pSMB->TotalParameterCount = pSMB->ParameterCount;
  	pSMB->ParameterOffset = cpu_to_le16(param_offset);
  	pSMB->DataOffset = cpu_to_le16(offset);
  	pSMB->Fid = fid;
  	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
  	pSMB->Reserved4 = 0;
be8e3b004   Steve French   consistently use ...
6036
  	inc_rfc1001_len(pSMB, byte_count);
3bbeeb3c9   Jeff Layton   cifs: add and use...
6037
  	pSMB->ByteCount = cpu_to_le16(byte_count);
b2a3ad9ca   Jeff Layton   cifs: silence com...
6038
  	cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
3bbeeb3c9   Jeff Layton   cifs: add and use...
6039

792af7b05   Pavel Shilovsky   CIFS: Separate pr...
6040
  	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
3bbeeb3c9   Jeff Layton   cifs: add and use...
6041
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
6042
6043
6044
  		cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d
  ",
  			 rc);
3bbeeb3c9   Jeff Layton   cifs: add and use...
6045
6046
6047
6048
6049
6050
6051
6052
  
  	/* Note: On -EAGAIN error only caller can retry on handle based calls
  		since file handle passed in no longer valid */
  
  	return rc;
  }
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
6053
  CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
6054
  		       const char *file_name,
01ea95e3b   Jeff Layton   cifs: rename CIFS...
6055
6056
  		       const struct cifs_unix_set_info_args *args,
  		       const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6057
6058
6059
6060
6061
6062
6063
6064
  {
  	TRANSACTION2_SPI_REQ *pSMB = NULL;
  	TRANSACTION2_SPI_RSP *pSMBr = NULL;
  	int name_len;
  	int rc = 0;
  	int bytes_returned = 0;
  	FILE_UNIX_BASIC_INFO *data_offset;
  	__u16 params, param_offset, offset, count, byte_count;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
6065
6066
  	cifs_dbg(FYI, "In SetUID/GID/Mode
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6067
6068
6069
6070
6071
6072
6073
6074
  setPermsRetry:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		name_len =
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
6075
  		    cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
acbbb76a2   Steve French   CIFS: Rename *UCS...
6076
  				       PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6077
6078
  		name_len++;	/* trailing null */
  		name_len *= 2;
3e87d8039   Steve French   [CIFS] Add suppor...
6079
  	} else {	/* BB improve the check for buffer overruns BB */
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
6080
  		name_len = strnlen(file_name, PATH_MAX);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6081
  		name_len++;	/* trailing null */
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
6082
  		strncpy(pSMB->FileName, file_name, name_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6083
6084
6085
  	}
  
  	params = 6 + name_len;
26f57364d   Steve French   [CIFS] formatting...
6086
  	count = sizeof(FILE_UNIX_BASIC_INFO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6087
  	pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5e   Steve French   [CIFS] cleanup ol...
6088
6089
  	/* BB find max SMB PDU from sess structure BB */
  	pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6090
6091
6092
6093
6094
6095
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  	pSMB->Flags = 0;
  	pSMB->Timeout = 0;
  	pSMB->Reserved2 = 0;
  	param_offset = offsetof(struct smb_com_transaction2_spi_req,
50c2f7538   Steve French   [CIFS] whitespace...
6096
  				InformationLevel) - 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
  	offset = param_offset + params;
  	data_offset =
  	    (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
  				      offset);
  	memset(data_offset, 0, count);
  	pSMB->DataOffset = cpu_to_le16(offset);
  	pSMB->ParameterOffset = cpu_to_le16(param_offset);
  	pSMB->SetupCount = 1;
  	pSMB->Reserved3 = 0;
  	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
  	byte_count = 3 /* pad */  + params + count;
  	pSMB->ParameterCount = cpu_to_le16(params);
  	pSMB->DataCount = cpu_to_le16(count);
  	pSMB->TotalParameterCount = pSMB->ParameterCount;
  	pSMB->TotalDataCount = pSMB->DataCount;
  	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
  	pSMB->Reserved4 = 0;
be8e3b004   Steve French   consistently use ...
6114
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6115

654cf14ac   Jeff Layton   cifs: make a sepa...
6116
  	cifs_fill_unix_set_info(data_offset, args);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6117
6118
6119
6120
  
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
ad7a2926b   Steve French   [CIFS] reduce che...
6121
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
6122
6123
  		cifs_dbg(FYI, "SetPathInfo (perms) returned %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6124

0d817bc0d   Steve French   [CIFS] Remove red...
6125
  	cifs_buf_release(pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6126
6127
6128
6129
  	if (rc == -EAGAIN)
  		goto setPermsRetry;
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6130
  #ifdef CONFIG_CIFS_XATTR
31c0519f7   Jeff Layton   cifs: merge CIFSS...
6131
6132
6133
6134
6135
6136
6137
6138
6139
  /*
   * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
   * function used by listxattr and getxattr type calls. When ea_name is set,
   * it looks for that attribute name and stuffs that value into the EAData
   * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
   * buffer. In both cases, the return value is either the length of the
   * resulting data or a negative error code. If EAData is a NULL pointer then
   * the data isn't copied to it, but the length is returned.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6140
  ssize_t
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
6141
  CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
31c0519f7   Jeff Layton   cifs: merge CIFSS...
6142
6143
6144
  		const unsigned char *searchName, const unsigned char *ea_name,
  		char *EAData, size_t buf_size,
  		const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6145
6146
6147
6148
6149
6150
  {
  		/* BB assumes one setup word */
  	TRANSACTION2_QPI_REQ *pSMB = NULL;
  	TRANSACTION2_QPI_RSP *pSMBr = NULL;
  	int rc = 0;
  	int bytes_returned;
6e462b9f2   Jeff Layton   cifs: rename name...
6151
  	int list_len;
f0d3868b7   Jeff Layton   cifs: clean up in...
6152
  	struct fealist *ea_response_data;
50c2f7538   Steve French   [CIFS] whitespace...
6153
6154
  	struct fea *temp_fea;
  	char *temp_ptr;
0cd126b50   Jeff Layton   cifs: verify leng...
6155
  	char *end_of_smb;
f0d3868b7   Jeff Layton   cifs: clean up in...
6156
  	__u16 params, byte_count, data_offset;
5980fc966   Jeff Layton   cifs: fix compile...
6157
  	unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6158

f96637be0   Joe Perches   [CIFS] cifs: Rena...
6159
6160
  	cifs_dbg(FYI, "In Query All EAs path %s
  ", searchName);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6161
6162
6163
6164
6165
6166
6167
  QAllEAsRetry:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6e462b9f2   Jeff Layton   cifs: rename name...
6168
  		list_len =
acbbb76a2   Steve French   CIFS: Rename *UCS...
6169
6170
  		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
  				       PATH_MAX, nls_codepage, remap);
6e462b9f2   Jeff Layton   cifs: rename name...
6171
6172
  		list_len++;	/* trailing null */
  		list_len *= 2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6173
  	} else {	/* BB improve the check for buffer overruns BB */
6e462b9f2   Jeff Layton   cifs: rename name...
6174
6175
6176
  		list_len = strnlen(searchName, PATH_MAX);
  		list_len++;	/* trailing null */
  		strncpy(pSMB->FileName, searchName, list_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6177
  	}
6e462b9f2   Jeff Layton   cifs: rename name...
6178
  	params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6179
6180
  	pSMB->TotalDataCount = 0;
  	pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5e   Steve French   [CIFS] cleanup ol...
6181
  	/* BB find exact max SMB PDU from sess structure BB */
e529614ad   Jeff Layton   cifs: increase ma...
6182
  	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6183
6184
6185
6186
6187
6188
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  	pSMB->Flags = 0;
  	pSMB->Timeout = 0;
  	pSMB->Reserved2 = 0;
  	pSMB->ParameterOffset = cpu_to_le16(offsetof(
50c2f7538   Steve French   [CIFS] whitespace...
6189
  	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
  	pSMB->DataCount = 0;
  	pSMB->DataOffset = 0;
  	pSMB->SetupCount = 1;
  	pSMB->Reserved3 = 0;
  	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
  	byte_count = params + 1 /* pad */ ;
  	pSMB->TotalParameterCount = cpu_to_le16(params);
  	pSMB->ParameterCount = pSMB->TotalParameterCount;
  	pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
  	pSMB->Reserved4 = 0;
be8e3b004   Steve French   consistently use ...
6200
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6201
6202
6203
6204
6205
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
6206
6207
  		cifs_dbg(FYI, "Send error in QueryAllEAs = %d
  ", rc);
f0d3868b7   Jeff Layton   cifs: clean up in...
6208
6209
  		goto QAllEAsOut;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6210

f0d3868b7   Jeff Layton   cifs: clean up in...
6211
6212
6213
6214
6215
6216
  
  	/* BB also check enough total bytes returned */
  	/* BB we need to improve the validity checking
  	of these trans2 responses */
  
  	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
820a803ff   Jeff Layton   cifs: keep BCC in...
6217
  	if (rc || get_bcc(&pSMBr->hdr) < 4) {
f0d3868b7   Jeff Layton   cifs: clean up in...
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
  		rc = -EIO;	/* bad smb */
  		goto QAllEAsOut;
  	}
  
  	/* check that length of list is not more than bcc */
  	/* check that each entry does not go beyond length
  	   of list */
  	/* check that each element of each entry does not
  	   go beyond end of list */
  	/* validate_trans2_offsets() */
  	/* BB check if start of smb + data_offset > &bcc+ bcc */
  
  	data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
  	ea_response_data = (struct fealist *)
  				(((char *) &pSMBr->hdr.Protocol) + data_offset);
6e462b9f2   Jeff Layton   cifs: rename name...
6233
  	list_len = le32_to_cpu(ea_response_data->list_len);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
6234
6235
  	cifs_dbg(FYI, "ea length %d
  ", list_len);
6e462b9f2   Jeff Layton   cifs: rename name...
6236
  	if (list_len <= 8) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
6237
6238
  		cifs_dbg(FYI, "empty EA list returned from server
  ");
60977fcc8   Steve French   Return correct er...
6239
6240
6241
  		/* didn't find the named attribute */
  		if (ea_name)
  			rc = -ENODATA;
f0d3868b7   Jeff Layton   cifs: clean up in...
6242
6243
  		goto QAllEAsOut;
  	}
0cd126b50   Jeff Layton   cifs: verify leng...
6244
  	/* make sure list_len doesn't go past end of SMB */
690c522fa   Jeff Layton   cifs: use get/put...
6245
  	end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
0cd126b50   Jeff Layton   cifs: verify leng...
6246
  	if ((char *)ea_response_data + list_len > end_of_smb) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
6247
6248
  		cifs_dbg(FYI, "EA list appears to go beyond SMB
  ");
0cd126b50   Jeff Layton   cifs: verify leng...
6249
6250
6251
  		rc = -EIO;
  		goto QAllEAsOut;
  	}
f0d3868b7   Jeff Layton   cifs: clean up in...
6252
  	/* account for ea list len */
6e462b9f2   Jeff Layton   cifs: rename name...
6253
  	list_len -= 4;
f0d3868b7   Jeff Layton   cifs: clean up in...
6254
6255
  	temp_fea = ea_response_data->list;
  	temp_ptr = (char *)temp_fea;
6e462b9f2   Jeff Layton   cifs: rename name...
6256
  	while (list_len > 0) {
122ca0076   Steve French   [CIFS] Use unsign...
6257
  		unsigned int name_len;
f0d3868b7   Jeff Layton   cifs: clean up in...
6258
  		__u16 value_len;
0cd126b50   Jeff Layton   cifs: verify leng...
6259

6e462b9f2   Jeff Layton   cifs: rename name...
6260
  		list_len -= 4;
f0d3868b7   Jeff Layton   cifs: clean up in...
6261
  		temp_ptr += 4;
0cd126b50   Jeff Layton   cifs: verify leng...
6262
6263
  		/* make sure we can read name_len and value_len */
  		if (list_len < 0) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
6264
6265
  			cifs_dbg(FYI, "EA entry goes beyond length of list
  ");
0cd126b50   Jeff Layton   cifs: verify leng...
6266
6267
6268
6269
6270
6271
6272
6273
  			rc = -EIO;
  			goto QAllEAsOut;
  		}
  
  		name_len = temp_fea->name_len;
  		value_len = le16_to_cpu(temp_fea->value_len);
  		list_len -= name_len + 1 + value_len;
  		if (list_len < 0) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
6274
6275
  			cifs_dbg(FYI, "EA entry goes beyond length of list
  ");
0cd126b50   Jeff Layton   cifs: verify leng...
6276
6277
6278
  			rc = -EIO;
  			goto QAllEAsOut;
  		}
31c0519f7   Jeff Layton   cifs: merge CIFSS...
6279
  		if (ea_name) {
91d065c47   Jeff Layton   cifs: fix name pa...
6280
  			if (ea_name_len == name_len &&
ac423446d   Jeff Layton   cifs: switch CIFS...
6281
  			    memcmp(ea_name, temp_ptr, name_len) == 0) {
31c0519f7   Jeff Layton   cifs: merge CIFSS...
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
  				temp_ptr += name_len + 1;
  				rc = value_len;
  				if (buf_size == 0)
  					goto QAllEAsOut;
  				if ((size_t)value_len > buf_size) {
  					rc = -ERANGE;
  					goto QAllEAsOut;
  				}
  				memcpy(EAData, temp_ptr, value_len);
  				goto QAllEAsOut;
  			}
f0d3868b7   Jeff Layton   cifs: clean up in...
6293
  		} else {
31c0519f7   Jeff Layton   cifs: merge CIFSS...
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
  			/* account for prefix user. and trailing null */
  			rc += (5 + 1 + name_len);
  			if (rc < (int) buf_size) {
  				memcpy(EAData, "user.", 5);
  				EAData += 5;
  				memcpy(EAData, temp_ptr, name_len);
  				EAData += name_len;
  				/* null terminate name */
  				*EAData = 0;
  				++EAData;
  			} else if (buf_size == 0) {
  				/* skip copy - calc size only */
  			} else {
  				/* stop before overrun buffer */
  				rc = -ERANGE;
  				break;
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6311
  		}
0cd126b50   Jeff Layton   cifs: verify leng...
6312
  		temp_ptr += name_len + 1 + value_len;
f0d3868b7   Jeff Layton   cifs: clean up in...
6313
  		temp_fea = (struct fea *)temp_ptr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6314
  	}
f0d3868b7   Jeff Layton   cifs: clean up in...
6315

31c0519f7   Jeff Layton   cifs: merge CIFSS...
6316
6317
6318
  	/* didn't find the named attribute */
  	if (ea_name)
  		rc = -ENODATA;
f0d3868b7   Jeff Layton   cifs: clean up in...
6319
  QAllEAsOut:
0d817bc0d   Steve French   [CIFS] Remove red...
6320
  	cifs_buf_release(pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6321
6322
6323
6324
6325
  	if (rc == -EAGAIN)
  		goto QAllEAsRetry;
  
  	return (ssize_t)rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6326
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
6327
6328
  CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
  	     const char *fileName, const char *ea_name, const void *ea_value,
50c2f7538   Steve French   [CIFS] whitespace...
6329
6330
  	     const __u16 ea_value_len, const struct nls_table *nls_codepage,
  	     int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6331
6332
6333
6334
6335
6336
6337
6338
  {
  	struct smb_com_transaction2_spi_req *pSMB = NULL;
  	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
  	struct fealist *parm_data;
  	int name_len;
  	int rc = 0;
  	int bytes_returned = 0;
  	__u16 params, param_offset, byte_count, offset, count;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
6339
6340
  	cifs_dbg(FYI, "In SetEA
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6341
6342
6343
6344
6345
6346
6347
6348
  SetEARetry:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		name_len =
acbbb76a2   Steve French   CIFS: Rename *UCS...
6349
6350
  		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
  				       PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6351
6352
  		name_len++;	/* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
6353
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
  		name_len = strnlen(fileName, PATH_MAX);
  		name_len++;	/* trailing null */
  		strncpy(pSMB->FileName, fileName, name_len);
  	}
  
  	params = 6 + name_len;
  
  	/* done calculating parms using name_len of file name,
  	now use name_len to calculate length of ea name
  	we are going to create in the inode xattrs */
790fe579f   Steve French   [CIFS] more white...
6364
  	if (ea_name == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6365
6366
  		name_len = 0;
  	else
50c2f7538   Steve French   [CIFS] whitespace...
6367
  		name_len = strnlen(ea_name, 255);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6368

dae5dbdbd   Steve French   [CIFS] fix SetEA ...
6369
  	count = sizeof(*parm_data) + ea_value_len + name_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6370
  	pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5e   Steve French   [CIFS] cleanup ol...
6371
6372
  	/* BB find max SMB PDU from sess */
  	pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6373
6374
6375
6376
6377
6378
  	pSMB->MaxSetupCount = 0;
  	pSMB->Reserved = 0;
  	pSMB->Flags = 0;
  	pSMB->Timeout = 0;
  	pSMB->Reserved2 = 0;
  	param_offset = offsetof(struct smb_com_transaction2_spi_req,
50c2f7538   Steve French   [CIFS] whitespace...
6379
  				InformationLevel) - 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
  	offset = param_offset + params;
  	pSMB->InformationLevel =
  		cpu_to_le16(SMB_SET_FILE_EA);
  
  	parm_data =
  		(struct fealist *) (((char *) &pSMB->hdr.Protocol) +
  				       offset);
  	pSMB->ParameterOffset = cpu_to_le16(param_offset);
  	pSMB->DataOffset = cpu_to_le16(offset);
  	pSMB->SetupCount = 1;
  	pSMB->Reserved3 = 0;
  	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
  	byte_count = 3 /* pad */  + params + count;
  	pSMB->DataCount = cpu_to_le16(count);
  	parm_data->list_len = cpu_to_le32(count);
  	parm_data->list[0].EA_flags = 0;
  	/* we checked above that name len is less than 255 */
53b3531bb   Alexey Dobriyan   [PATCH] s/;;/;/g
6397
  	parm_data->list[0].name_len = (__u8)name_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6398
  	/* EA names are always ASCII */
790fe579f   Steve French   [CIFS] more white...
6399
  	if (ea_name)
50c2f7538   Steve French   [CIFS] whitespace...
6400
  		strncpy(parm_data->list[0].name, ea_name, name_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6401
6402
6403
6404
  	parm_data->list[0].name[name_len] = 0;
  	parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
  	/* caller ensures that ea_value_len is less than 64K but
  	we need to ensure that it fits within the smb */
50c2f7538   Steve French   [CIFS] whitespace...
6405
6406
  	/*BB add length check to see if it would fit in
  	     negotiated SMB buffer size BB */
790fe579f   Steve French   [CIFS] more white...
6407
6408
  	/* if (ea_value_len > buffer_size - 512 (enough for header)) */
  	if (ea_value_len)
50c2f7538   Steve French   [CIFS] whitespace...
6409
6410
  		memcpy(parm_data->list[0].name+name_len+1,
  		       ea_value, ea_value_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6411
6412
6413
6414
6415
  
  	pSMB->TotalDataCount = pSMB->DataCount;
  	pSMB->ParameterCount = cpu_to_le16(params);
  	pSMB->TotalParameterCount = pSMB->ParameterCount;
  	pSMB->Reserved4 = 0;
be8e3b004   Steve French   consistently use ...
6416
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6417
6418
6419
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
ad7a2926b   Steve French   [CIFS] reduce che...
6420
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
6421
6422
  		cifs_dbg(FYI, "SetPathInfo (EA) returned %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6423
6424
6425
6426
6427
6428
6429
6430
  
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto SetEARetry;
  
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6431
  #endif
0eff0e267   Steve French   Remove unused CIF...
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
  
  #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* BB unused temporarily */
  /*
   *	Years ago the kernel added a "dnotify" function for Samba server,
   *	to allow network clients (such as Windows) to display updated
   *	lists of files in directory listings automatically when
   *	files are added by one user when another user has the
   *	same directory open on their desktop.  The Linux cifs kernel
   *	client hooked into the kernel side of this interface for
   *	the same reason, but ironically when the VFS moved from
   *	"dnotify" to "inotify" it became harder to plug in Linux
   *	network file system clients (the most obvious use case
   *	for notify interfaces is when multiple users can update
   *	the contents of the same directory - exactly what network
   *	file systems can do) although the server (Samba) could
   *	still use it.  For the short term we leave the worker
   *	function ifdeffed out (below) until inotify is fixed
   *	in the VFS to make it easier to plug in network file
   *	system clients.  If inotify turns out to be permanently
   *	incompatible for network fs clients, we could instead simply
   *	expose this config flag by adding a future cifs (and smb2) notify ioctl.
   */
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
6454
  int CIFSSMBNotify(const unsigned int xid, struct cifs_tcon *tcon,
0eff0e267   Steve French   Remove unused CIF...
6455
6456
6457
6458
6459
6460
6461
6462
6463
  		  const int notify_subdirs, const __u16 netfid,
  		  __u32 filter, struct file *pfile, int multishot,
  		  const struct nls_table *nls_codepage)
  {
  	int rc = 0;
  	struct smb_com_transaction_change_notify_req *pSMB = NULL;
  	struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
  	struct dir_notify_req *dnotify_req;
  	int bytes_returned;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
6464
6465
  	cifs_dbg(FYI, "In CIFSSMBNotify for file handle %d
  ", (int)netfid);
0eff0e267   Steve French   Remove unused CIF...
6466
6467
6468
6469
6470
6471
6472
6473
  	rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	pSMB->TotalParameterCount = 0 ;
  	pSMB->TotalDataCount = 0;
  	pSMB->MaxParameterCount = cpu_to_le32(2);
c974befa4   Jeff Layton   cifs: untangle se...
6474
  	pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
0eff0e267   Steve French   Remove unused CIF...
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489
6490
6491
6492
6493
  	pSMB->MaxSetupCount = 4;
  	pSMB->Reserved = 0;
  	pSMB->ParameterOffset = 0;
  	pSMB->DataCount = 0;
  	pSMB->DataOffset = 0;
  	pSMB->SetupCount = 4; /* single byte does not need le conversion */
  	pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
  	pSMB->ParameterCount = pSMB->TotalParameterCount;
  	if (notify_subdirs)
  		pSMB->WatchTree = 1; /* one byte - no le conversion needed */
  	pSMB->Reserved2 = 0;
  	pSMB->CompletionFilter = cpu_to_le32(filter);
  	pSMB->Fid = netfid; /* file handle always le */
  	pSMB->ByteCount = 0;
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *)pSMBr, &bytes_returned,
  			 CIFS_ASYNC_OP);
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
6494
6495
  		cifs_dbg(FYI, "Error in Notify = %d
  ", rc);
0eff0e267   Steve French   Remove unused CIF...
6496
6497
6498
6499
6500
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517
6518
6519
6520
6521
6522
  	} else {
  		/* Add file to outstanding requests */
  		/* BB change to kmem cache alloc */
  		dnotify_req = kmalloc(
  						sizeof(struct dir_notify_req),
  						 GFP_KERNEL);
  		if (dnotify_req) {
  			dnotify_req->Pid = pSMB->hdr.Pid;
  			dnotify_req->PidHigh = pSMB->hdr.PidHigh;
  			dnotify_req->Mid = pSMB->hdr.Mid;
  			dnotify_req->Tid = pSMB->hdr.Tid;
  			dnotify_req->Uid = pSMB->hdr.Uid;
  			dnotify_req->netfid = netfid;
  			dnotify_req->pfile = pfile;
  			dnotify_req->filter = filter;
  			dnotify_req->multishot = multishot;
  			spin_lock(&GlobalMid_Lock);
  			list_add_tail(&dnotify_req->lhead,
  					&GlobalDnotifyReqList);
  			spin_unlock(&GlobalMid_Lock);
  		} else
  			rc = -ENOMEM;
  	}
  	cifs_buf_release(pSMB);
  	return rc;
  }
  #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */