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 */
3afca265b   Steve French   Clarify locking o...
99
  	spin_lock(&tcon->open_file_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
  	}
3afca265b   Steve French   Clarify locking o...
105
  	spin_unlock(&tcon->open_file_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
  
  	pSMB->ByteCount = cpu_to_le16(count);
a9d02ad49   Steve French   [CIFS] Support fo...
1224
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7749981ec   Jeff Layton   cifs: remove code...
1225
  			(struct smb_hdr *)pSMBr, &bytes_returned, 0);
44c581866   Pavel Shilovsky   CIFS: Move clear/...
1226
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
a9d02ad49   Steve French   [CIFS] Support fo...
1227
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1228
1229
  		cifs_dbg(FYI, "Error in Open = %d
  ", rc);
a9d02ad49   Steve French   [CIFS] Support fo...
1230
1231
  	} else {
  	/* BB verify if wct == 15 */
582d21e5e   Steve French   [CIFS] cleanup ol...
1232
  /*		*pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
a9d02ad49   Steve French   [CIFS] Support fo...
1233
1234
1235
1236
1237
  
  		*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...
1238
  /*		if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
a9d02ad49   Steve French   [CIFS] Support fo...
1239
1240
  			*pOplock |= CIFS_CREATE_ACTION; */
  	/* BB FIXME END */
790fe579f   Steve French   [CIFS] more white...
1241
  		if (pfile_info) {
a9d02ad49   Steve French   [CIFS] Support fo...
1242
1243
1244
1245
  			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...
1246
  			pfile_info->Attributes =
50c2f7538   Steve French   [CIFS] whitespace...
1247
  				cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
a9d02ad49   Steve French   [CIFS] Support fo...
1248
  			/* the file_info buf is endian converted by caller */
70ca734a1   Steve French   [CIFS] Various mi...
1249
1250
1251
  			pfile_info->AllocationSize =
  				cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
  			pfile_info->EndOfFile = pfile_info->AllocationSize;
a9d02ad49   Steve French   [CIFS] Support fo...
1252
  			pfile_info->NumberOfLinks = cpu_to_le32(1);
9a8165fce   Jeff Layton   cifs: track Delet...
1253
  			pfile_info->DeletePending = 0;
a9d02ad49   Steve French   [CIFS] Support fo...
1254
1255
1256
1257
1258
1259
1260
1261
  		}
  	}
  
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto OldOpenRetry;
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1262
  int
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1263
1264
  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
1265
1266
  {
  	int rc = -EACCES;
9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1267
1268
  	OPEN_REQ *req = NULL;
  	OPEN_RSP *rsp = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1269
1270
1271
  	int bytes_returned;
  	int name_len;
  	__u16 count;
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1272
1273
  	struct cifs_sb_info *cifs_sb = oparms->cifs_sb;
  	struct cifs_tcon *tcon = oparms->tcon;
2baa26825   Steve French   Remap reserved po...
1274
  	int remap = cifs_remap(cifs_sb);
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1275
1276
1277
1278
1279
  	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
1280
1281
  
  openRetry:
9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1282
1283
  	rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **)&req,
  		      (void **)&rsp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1284
1285
  	if (rc)
  		return rc;
9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1286
1287
  	/* no commands go after this */
  	req->AndXCommand = 0xFF;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1288

9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1289
1290
1291
1292
1293
1294
1295
  	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
1296
  		name_len *= 2;
9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
  		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
1307
  	}
9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
  
  	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...
1321
  	if (create_options & CREATE_OPTION_SPECIAL)
9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1322
  		req->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
eda3c0298   Steve French   [CIFS] Add compat...
1323
  	else
9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1324
  		req->FileAttributes = cpu_to_le32(ATTR_NORMAL);
67750fb9e   Jeff Layton   [CIFS] when not u...
1325

9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1326
1327
1328
1329
  	/*
  	 * 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
1330
  	if (tcon->ses->capabilities & CAP_UNIX)
9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1331
  		req->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1332

67750fb9e   Jeff Layton   [CIFS] when not u...
1333
  	if (create_options & CREATE_OPTION_READONLY)
9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1334
1335
1336
1337
1338
  		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...
1339

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

9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1347
1348
1349
  	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/...
1350
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1351
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1352
1353
  		cifs_dbg(FYI, "Error in Open = %d
  ", rc);
9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1354
1355
1356
1357
  		cifs_buf_release(req);
  		if (rc == -EAGAIN)
  			goto openRetry;
  		return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1358
  	}
a5a2b489b   Steve French   [CIFS] Make CIFS ...
1359

9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1360
1361
1362
  	/* 1 byte no need to le_to_cpu */
  	*oplock = rsp->OplockLevel;
  	/* cifs fid stays in le */
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1363
  	oparms->fid->netfid = rsp->Fid;
9bf4fa01f   Pavel Shilovsky   CIFS: Cleanup CIF...
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
  
  	/* 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
1381
1382
  	return rc;
  }
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1383
1384
1385
1386
1387
  /*
   * 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...
1388
  discard_remaining_data(struct TCP_Server_Info *server)
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1389
  {
5ffef7bf1   Pavel Shilovsky   CIFS: Separate pr...
1390
  	unsigned int rfclen = get_rfc1002_length(server->smallbuf);
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1391
  	int remaining = rfclen + 4 - server->total_read;
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1392
1393
1394
1395
1396
1397
  
  	while (remaining > 0) {
  		int length;
  
  		length = cifs_read_from_socket(server, server->bigbuf,
  				min_t(unsigned int, remaining,
1887f6010   Pavel Shilovsky   CIFS: Move header...
1398
  				    CIFSMaxBufSize + MAX_HEADER_SIZE(server)));
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1399
1400
1401
1402
1403
  		if (length < 0)
  			return length;
  		server->total_read += length;
  		remaining -= length;
  	}
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1404
1405
  	return 0;
  }
6cc3b2423   Pavel Shilovsky   CIFS: Fix SMB2+ i...
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
  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...
1416
  int
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1417
1418
1419
  cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
  {
  	int length, len;
8d5ce4d23   Jeff Layton   cifs: abstract ou...
1420
  	unsigned int data_offset, data_len;
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1421
  	struct cifs_readdata *rdata = mid->callback_data;
5ffef7bf1   Pavel Shilovsky   CIFS: Separate pr...
1422
1423
  	char *buf = server->smallbuf;
  	unsigned int buflen = get_rfc1002_length(buf) + 4;
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1424

f96637be0   Joe Perches   [CIFS] cifs: Rena...
1425
1426
1427
  	cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%u
  ",
  		 __func__, mid->mid, rdata->offset, rdata->bytes);
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1428
1429
1430
1431
1432
1433
  
  	/*
  	 * 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...
1434
  	len = min_t(unsigned int, buflen, server->vals->read_rsp_size) -
1887f6010   Pavel Shilovsky   CIFS: Move header...
1435
  							HEADER_SIZE(server) + 1;
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1436

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

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

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

f96637be0   Joe Perches   [CIFS] cifs: Rena...
1543
1544
1545
1546
  	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...
1547

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

f96637be0   Joe Perches   [CIFS] cifs: Rena...
1595
1596
1597
  	cifs_dbg(FYI, "%s: offset=%llu bytes=%u
  ",
  		 __func__, rdata->offset, rdata->bytes);
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
  
  	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...
1617
  	smb->Fid = rdata->cfile->fid.netfid;
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
  	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...
1634
1635
  	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...
1636

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

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

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

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

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

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1806
1807
1808
  	pSMB->Reserved = 0xFFFFFFFF;
  	pSMB->WriteMode = 0;
  	pSMB->Remaining = 0;
50c2f7538   Steve French   [CIFS] whitespace...
1809
  	/* Can increase buffer size if buffer is big enough in some cases ie we
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1810
1811
1812
  	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...
1813
  	if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1814
1815
1816
1817
1818
1819
1820
1821
1822
  		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...
1823
  		cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
790fe579f   Steve French   [CIFS] more white...
1824
  	if (buf)
61e748015   Steve French   [CIFS] various mi...
1825
  		memcpy(pSMB->Data, buf, bytes_sent);
dbbab3257   Al Viro   cifs: get rid of ...
1826
  	else if (count != 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1827
1828
1829
  		/* No buffer */
  		cifs_buf_release(pSMB);
  		return -EINVAL;
e30dcf3a1   Steve French   [CIFS] Add suppor...
1830
  	} /* else setting file size with write of zero bytes */
790fe579f   Steve French   [CIFS] more white...
1831
  	if (wct == 14)
e30dcf3a1   Steve French   [CIFS] Add suppor...
1832
  		byte_count = bytes_sent + 1; /* pad */
ad7a2926b   Steve French   [CIFS] reduce che...
1833
  	else /* wct == 12 */
e30dcf3a1   Steve French   [CIFS] Add suppor...
1834
  		byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
ad7a2926b   Steve French   [CIFS] reduce che...
1835

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

790fe579f   Steve French   [CIFS] more white...
1840
  	if (wct == 14)
1c9551878   Steve French   [CIFS] Add suppor...
1841
  		pSMB->ByteCount = cpu_to_le16(byte_count);
50c2f7538   Steve French   [CIFS] whitespace...
1842
1843
1844
  	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...
1845
1846
1847
  			(struct smb_com_writex_req *)pSMB;
  		pSMBW->ByteCount = cpu_to_le16(byte_count);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1848
1849
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
dbbab3257   Al Viro   cifs: get rid of ...
1850
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
44c581866   Pavel Shilovsky   CIFS: Move clear/...
1851
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1852
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1853
1854
  		cifs_dbg(FYI, "Send error in write = %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1855
1856
1857
1858
  	} else {
  		*nbytes = le16_to_cpu(pSMBr->CountHigh);
  		*nbytes = (*nbytes) << 16;
  		*nbytes += le16_to_cpu(pSMBr->Count);
6513a81e9   Suresh Jayaraman   cifs: Fix a kerne...
1859
1860
1861
1862
1863
1864
1865
1866
  
  		/*
  		 * 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
1867
1868
1869
  	}
  
  	cifs_buf_release(pSMB);
50c2f7538   Steve French   [CIFS] whitespace...
1870
  	/* Note: On -EAGAIN error only caller can retry on handle based calls
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1871
1872
1873
1874
  		since file handle passed in no longer valid */
  
  	return rc;
  }
c28c89fc4   Jeff Layton   cifs: add cifs_as...
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
  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...
1894
  	int i, rc = 0;
2b0143b5c   David Howells   VFS: normal files...
1895
  	struct inode *inode = d_inode(wdata->cfile->dentry);
c9de5c80d   Pavel Shilovsky   CIFS: Move async ...
1896
  	struct TCP_Server_Info *server;
7f6c50086   Pavel Shilovsky   CIFS: Fix cifs_wr...
1897
  	unsigned int rest_len;
c28c89fc4   Jeff Layton   cifs: add cifs_as...
1898

7f6c50086   Pavel Shilovsky   CIFS: Fix cifs_wr...
1899
1900
1901
  	server = tlink_tcon(wdata->cfile->tlink)->ses->server;
  	i = 0;
  	rest_len = wdata->bytes;
c28c89fc4   Jeff Layton   cifs: add cifs_as...
1902
  	do {
7f6c50086   Pavel Shilovsky   CIFS: Fix cifs_wr...
1903
1904
1905
1906
1907
  		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...
1908
  			nr_pages = wsize / PAGE_SIZE;
7f6c50086   Pavel Shilovsky   CIFS: Fix cifs_wr...
1909
1910
1911
1912
  			if (!nr_pages) {
  				rc = -ENOTSUPP;
  				break;
  			}
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1913
1914
  			cur_len = nr_pages * PAGE_SIZE;
  			tailsz = PAGE_SIZE;
7f6c50086   Pavel Shilovsky   CIFS: Fix cifs_wr...
1915
  		} else {
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1916
  			nr_pages = DIV_ROUND_UP(rest_len, PAGE_SIZE);
7f6c50086   Pavel Shilovsky   CIFS: Fix cifs_wr...
1917
  			cur_len = rest_len;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1918
  			tailsz = rest_len - (nr_pages - 1) * PAGE_SIZE;
7f6c50086   Pavel Shilovsky   CIFS: Fix cifs_wr...
1919
  		}
c28c89fc4   Jeff Layton   cifs: add cifs_as...
1920

7f6c50086   Pavel Shilovsky   CIFS: Fix cifs_wr...
1921
1922
1923
1924
  		wdata2 = cifs_writedata_alloc(nr_pages, cifs_writev_complete);
  		if (!wdata2) {
  			rc = -ENOMEM;
  			break;
c51bb0ea4   Ouyang Maochun   cifs: bugfix for ...
1925
  		}
7f6c50086   Pavel Shilovsky   CIFS: Fix cifs_wr...
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
  
  		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...
1936
  		wdata2->pagesz = PAGE_SIZE;
7f6c50086   Pavel Shilovsky   CIFS: Fix cifs_wr...
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
  		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...
1955
  				put_page(wdata2->pages[j]);
7f6c50086   Pavel Shilovsky   CIFS: Fix cifs_wr...
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
  			}
  		}
  
  		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...
1969
1970
1971
1972
  
  	mapping_set_error(inode->i_mapping, rc);
  	kref_put(&wdata->refcount, cifs_writedata_release);
  }
c2e876400   Jeff Layton   cifs: allow calle...
1973
  void
c28c89fc4   Jeff Layton   cifs: add cifs_as...
1974
1975
1976
1977
  cifs_writev_complete(struct work_struct *work)
  {
  	struct cifs_writedata *wdata = container_of(work,
  						struct cifs_writedata, work);
2b0143b5c   David Howells   VFS: normal files...
1978
  	struct inode *inode = d_inode(wdata->cfile->dentry);
c28c89fc4   Jeff Layton   cifs: add cifs_as...
1979
1980
1981
  	int i = 0;
  
  	if (wdata->result == 0) {
597b027f6   Jeff Layton   cifs: call cifs_u...
1982
  		spin_lock(&inode->i_lock);
c28c89fc4   Jeff Layton   cifs: add cifs_as...
1983
  		cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
597b027f6   Jeff Layton   cifs: call cifs_u...
1984
  		spin_unlock(&inode->i_lock);
c28c89fc4   Jeff Layton   cifs: add cifs_as...
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
  		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...
1997
  		put_page(page);
c28c89fc4   Jeff Layton   cifs: add cifs_as...
1998
1999
2000
2001
2002
2003
2004
  	}
  	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...
2005
  cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2006
2007
  {
  	struct cifs_writedata *wdata;
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2008
2009
  	/* writedata + number of page pointers */
  	wdata = kzalloc(sizeof(*wdata) +
26c8f0d60   Jeff Layton   cifs: use a flexa...
2010
  			sizeof(struct page *) * nr_pages, GFP_NOFS);
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2011
  	if (wdata != NULL) {
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2012
  		kref_init(&wdata->refcount);
da82f7e75   Jeff Layton   cifs: convert cif...
2013
2014
2015
  		INIT_LIST_HEAD(&wdata->list);
  		init_completion(&wdata->done);
  		INIT_WORK(&wdata->work, complete);
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2016
2017
2018
2019
2020
  	}
  	return wdata;
  }
  
  /*
7c9421e1a   Pavel Shilovsky   CIFS: Change mid_...
2021
   * Check the mid_state and signature on received buffer (if any), and queue the
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2022
2023
2024
2025
2026
2027
   * 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...
2028
  	struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
5fb4e288a   Christopher Oo   cifs: Fix use-aft...
2029
  	struct TCP_Server_Info *server = tcon->ses->server;
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2030
2031
  	unsigned int written;
  	WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
7c9421e1a   Pavel Shilovsky   CIFS: Change mid_...
2032
  	switch (mid->mid_state) {
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
  	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...
2063
  	queue_work(cifsiod_wq, &wdata->work);
5fb4e288a   Christopher Oo   cifs: Fix use-aft...
2064
  	mutex_lock(&server->srv_mutex);
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2065
  	DeleteMidQEntry(mid);
5fb4e288a   Christopher Oo   cifs: Fix use-aft...
2066
  	mutex_unlock(&server->srv_mutex);
a891f0f89   Pavel Shilovsky   CIFS: Extend cred...
2067
  	add_credits(tcon->ses->server, 1, 0);
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2068
2069
2070
2071
  }
  
  /* cifs_async_writev - send an async write, and set up mid to handle result */
  int
4a5c80d7b   Steve French   [CIFS] clean up p...
2072
2073
  cifs_async_writev(struct cifs_writedata *wdata,
  		  void (*release)(struct kref *kref))
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2074
  {
eddb079de   Jeff Layton   cifs: convert asy...
2075
  	int rc = -EACCES;
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2076
2077
  	WRITE_REQ *smb = NULL;
  	int wct;
96daf2b09   Steve French   [CIFS] Rename thr...
2078
  	struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
eddb079de   Jeff Layton   cifs: convert asy...
2079
  	struct kvec iov;
fec344e3f   Jeff Layton   cifs: change cifs...
2080
  	struct smb_rqst rqst = { };
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
  
  	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...
2095
2096
  	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...
2097

c28c89fc4   Jeff Layton   cifs: add cifs_as...
2098
  	smb->AndXCommand = 0xFF;	/* none */
4b4de76e3   Pavel Shilovsky   CIFS: Replace net...
2099
  	smb->Fid = wdata->cfile->fid.netfid;
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
  	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...
2111
2112
  	iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
  	iov.iov_base = smb;
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2113

eddb079de   Jeff Layton   cifs: convert asy...
2114
2115
2116
2117
2118
2119
  	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...
2120

f96637be0   Joe Perches   [CIFS] cifs: Rena...
2121
2122
2123
  	cifs_dbg(FYI, "async write at %llu %u bytes
  ",
  		 wdata->offset, wdata->bytes);
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
  
  	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...
2137
  		iov.iov_len += 4; /* pad bigger by four bytes */
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2138
2139
2140
  	}
  
  	kref_get(&wdata->refcount);
fec344e3f   Jeff Layton   cifs: change cifs...
2141
2142
  	rc = cifs_call_async(tcon->ses->server, &rqst, NULL,
  				cifs_writev_callback, wdata, 0);
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2143
2144
  
  	if (rc == 0)
44c581866   Pavel Shilovsky   CIFS: Move clear/...
2145
  		cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2146
  	else
4a5c80d7b   Steve French   [CIFS] clean up p...
2147
  		kref_put(&wdata->refcount, release);
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2148

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

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

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

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

3e84469d0   Steve French   [CIFS] Add writep...
2202
2203
  	pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
  	pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
be8e3b004   Steve French   consistently use ...
2204
2205
  	/* header + 1 byte pad */
  	smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
790fe579f   Steve French   [CIFS] more white...
2206
  	if (wct == 14)
be8e3b004   Steve French   consistently use ...
2207
  		inc_rfc1001_len(pSMB, count + 1);
8cc64c6ec   Steve French   [CIFS] Allow SMBW...
2208
  	else /* wct == 12 */
be8e3b004   Steve French   consistently use ...
2209
  		inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
790fe579f   Steve French   [CIFS] more white...
2210
  	if (wct == 14)
8cc64c6ec   Steve French   [CIFS] Allow SMBW...
2211
2212
  		pSMB->ByteCount = cpu_to_le16(count + 1);
  	else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
50c2f7538   Steve French   [CIFS] whitespace...
2213
  		struct smb_com_writex_req *pSMBW =
8cc64c6ec   Steve French   [CIFS] Allow SMBW...
2214
2215
2216
  				(struct smb_com_writex_req *)pSMB;
  		pSMBW->ByteCount = cpu_to_le16(count + 5);
  	}
3e84469d0   Steve French   [CIFS] Add writep...
2217
  	iov[0].iov_base = pSMB;
790fe579f   Steve French   [CIFS] more white...
2218
  	if (wct == 14)
ec637e3ff   Steve French   [CIFS] Avoid extr...
2219
2220
2221
  		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...
2222

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2223

ba9ad7257   Pavel Shilovsky   CIFS: Move writep...
2224
  	rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, 0);
44c581866   Pavel Shilovsky   CIFS: Move clear/...
2225
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2226
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2227
2228
  		cifs_dbg(FYI, "Send error Write2 = %d
  ", rc);
790fe579f   Steve French   [CIFS] more white...
2229
  	} else if (resp_buf_type == 0) {
ec637e3ff   Steve French   [CIFS] Avoid extr...
2230
2231
  		/* presumably this can not happen, but best to be safe */
  		rc = -EIO;
d6e04ae64   Steve French   [CIFS] CIFS write...
2232
  	} else {
ad7a2926b   Steve French   [CIFS] reduce che...
2233
  		WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
d6e04ae64   Steve French   [CIFS] CIFS write...
2234
2235
2236
  		*nbytes = le16_to_cpu(pSMBr->CountHigh);
  		*nbytes = (*nbytes) << 16;
  		*nbytes += le16_to_cpu(pSMBr->Count);
6513a81e9   Suresh Jayaraman   cifs: Fix a kerne...
2237
2238
2239
2240
2241
2242
2243
2244
  
  		/*
  		 * 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...
2245
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2246

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

50c2f7538   Steve French   [CIFS] whitespace...
2250
  	/* Note: On -EAGAIN error only caller can retry on handle based calls
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2251
2252
2253
2254
  		since file handle passed in no longer valid */
  
  	return rc;
  }
d6e04ae64   Steve French   [CIFS] CIFS write...
2255

6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2256
2257
  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...
2258
2259
2260
2261
2262
2263
2264
  	       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...
2265
2266
2267
  	cifs_dbg(FYI, "cifs_lockv num lock %d num unlock %d
  ",
  		 num_lock, num_unlock);
9ee305b70   Pavel Shilovsky   CIFS: Send as man...
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
  
  	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/...
2289
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
9ee305b70   Pavel Shilovsky   CIFS: Send as man...
2290
2291
  	rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP);
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2292
2293
  		cifs_dbg(FYI, "Send error in cifs_lockv = %d
  ", rc);
9ee305b70   Pavel Shilovsky   CIFS: Send as man...
2294
2295
2296
  
  	return rc;
  }
d6e04ae64   Steve French   [CIFS] CIFS write...
2297

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

50c2f7538   Steve French   [CIFS] whitespace...
2361
  	/* Note: On -EAGAIN error only caller can retry on handle based calls
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2362
2363
2364
2365
2366
  	since file handle passed in no longer valid */
  	return rc;
  }
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2367
  CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
c5fd363d7   Jeff Layton   cifs: move file_l...
2368
2369
2370
2371
  		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 ...
2372
2373
2374
  {
  	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
  	struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
08547b036   Steve French   [CIFS] Add posix ...
2375
2376
  	struct cifs_posix_lock *parm_data;
  	int rc = 0;
3a5ff61c1   Steve French   [CIFS] Do not tim...
2377
  	int timeout = 0;
08547b036   Steve French   [CIFS] Add posix ...
2378
  	int bytes_returned = 0;
133672efb   Steve French   [CIFS] Fix buffer...
2379
  	int resp_buf_type = 0;
08547b036   Steve French   [CIFS] Add posix ...
2380
  	__u16 params, param_offset, offset, byte_count, count;
133672efb   Steve French   [CIFS] Fix buffer...
2381
  	struct kvec iov[1];
08547b036   Steve French   [CIFS] Add posix ...
2382

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

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

fc94cdb94   Steve French   [CIFS] Fix new PO...
2482
  plk_err_exit:
08547b036   Steve French   [CIFS] Add posix ...
2483
2484
  	if (pSMB)
  		cifs_small_buf_release(pSMB);
6d81ed1ec   Sachin Prabhu   cifs: replace cod...
2485
  	free_rsp_buf(resp_buf_type, iov[0].iov_base);
133672efb   Steve French   [CIFS] Fix buffer...
2486

08547b036   Steve French   [CIFS] Add posix ...
2487
2488
2489
2490
2491
2492
2493
2494
  	/* 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/...
2495
  CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2496
2497
2498
  {
  	int rc = 0;
  	CLOSE_REQ *pSMB = NULL;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2499
2500
  	cifs_dbg(FYI, "In CIFSSMBClose
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2501
2502
2503
  
  /* 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...
2504
  	if (rc == -EAGAIN)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2505
2506
2507
  		return 0;
  	if (rc)
  		return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2508
  	pSMB->FileID = (__u16) smb_file_id;
b815f1e55   Steve French   [CIFS] Allow for ...
2509
  	pSMB->LastWriteTime = 0xFFFFFFFF;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2510
  	pSMB->ByteCount = 0;
792af7b05   Pavel Shilovsky   CIFS: Separate pr...
2511
  	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
44c581866   Pavel Shilovsky   CIFS: Move clear/...
2512
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_closes);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2513
  	if (rc) {
790fe579f   Steve French   [CIFS] more white...
2514
  		if (rc != -EINTR) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2515
  			/* EINTR is expected when user ctl-c to kill app */
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2516
2517
  			cifs_dbg(VFS, "Send error in Close = %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2518
2519
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2520
  	/* Since session is dead, file will be closed on server already */
790fe579f   Steve French   [CIFS] more white...
2521
  	if (rc == -EAGAIN)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2522
2523
2524
2525
2526
2527
  		rc = 0;
  
  	return rc;
  }
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2528
  CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
b298f2235   Steve French   [CIFS] Send SMB f...
2529
2530
2531
  {
  	int rc = 0;
  	FLUSH_REQ *pSMB = NULL;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2532
2533
  	cifs_dbg(FYI, "In CIFSSMBFlush
  ");
b298f2235   Steve French   [CIFS] Send SMB f...
2534
2535
2536
2537
2538
2539
2540
  
  	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...
2541
  	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
44c581866   Pavel Shilovsky   CIFS: Move clear/...
2542
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);
b298f2235   Steve French   [CIFS] Send SMB f...
2543
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2544
2545
  		cifs_dbg(VFS, "Send error in Flush = %d
  ", rc);
b298f2235   Steve French   [CIFS] Send SMB f...
2546
2547
2548
2549
2550
  
  	return rc;
  }
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2551
  CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
2552
2553
  	      const char *from_name, const char *to_name,
  	      struct cifs_sb_info *cifs_sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2554
2555
2556
2557
2558
2559
2560
  {
  	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...
2561
  	int remap = cifs_remap(cifs_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2562

f96637be0   Joe Perches   [CIFS] cifs: Rena...
2563
2564
  	cifs_dbg(FYI, "In CIFSSMBRename
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
  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...
2577
2578
2579
  		name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
  					      from_name, PATH_MAX,
  					      cifs_sb->local_nls, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2580
2581
2582
2583
2584
2585
  		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...
2586
  		    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
2587
2588
  				       to_name, PATH_MAX, cifs_sb->local_nls,
  				       remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2589
2590
  		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
  		name_len2 *= 2;	/* convert to bytes */
50c2f7538   Steve French   [CIFS] whitespace...
2591
  	} else {	/* BB improve the check for buffer overruns BB */
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
2592
  		name_len = strnlen(from_name, PATH_MAX);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2593
  		name_len++;	/* trailing null */
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
2594
2595
  		strncpy(pSMB->OldFileName, from_name, name_len);
  		name_len2 = strnlen(to_name, PATH_MAX);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2596
2597
  		name_len2++;	/* trailing null */
  		pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
2598
  		strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2599
2600
2601
2602
2603
  		name_len2++;	/* trailing null */
  		name_len2++;	/* signature byte */
  	}
  
  	count = 1 /* 1st signature byte */  + name_len + name_len2;
be8e3b004   Steve French   consistently use ...
2604
  	inc_rfc1001_len(pSMB, count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2605
2606
2607
2608
  	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/...
2609
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);
ad7a2926b   Steve French   [CIFS] reduce che...
2610
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2611
2612
  		cifs_dbg(FYI, "Send error in rename = %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2613

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2614
2615
2616
2617
2618
2619
2620
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto renameRetry;
  
  	return rc;
  }
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2621
  int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
391e57555   Jeff Layton   cifs: remove NULL...
2622
  		int netfid, const char *target_name,
50c2f7538   Steve French   [CIFS] whitespace...
2623
  		const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2624
2625
2626
  {
  	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
  	struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
50c2f7538   Steve French   [CIFS] whitespace...
2627
  	struct set_file_rename *rename_info;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2628
2629
2630
2631
2632
2633
  	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...
2634
2635
  	cifs_dbg(FYI, "Rename to File by handle
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
  	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...
2653
  	pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
  	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...
2666
  	if (target_name == NULL) {
50c2f7538   Steve French   [CIFS] whitespace...
2667
  		sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
acbbb76a2   Steve French   CIFS: Rename *UCS...
2668
2669
  		len_of_str =
  			cifsConvertToUTF16((__le16 *)rename_info->target_name,
737b758c9   Steve French   [PATCH] cifs: cha...
2670
  					dummy_string, 24, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2671
  	} else {
acbbb76a2   Steve French   CIFS: Rename *UCS...
2672
2673
  		len_of_str =
  			cifsConvertToUTF16((__le16 *)rename_info->target_name,
50c2f7538   Steve French   [CIFS] whitespace...
2674
2675
  					target_name, PATH_MAX, nls_codepage,
  					remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2676
2677
  	}
  	rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
391e57555   Jeff Layton   cifs: remove NULL...
2678
  	count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2679
2680
2681
2682
2683
2684
2685
  	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 ...
2686
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2687
2688
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  	rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
50c2f7538   Steve French   [CIFS] whitespace...
2689
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
44c581866   Pavel Shilovsky   CIFS: Move clear/...
2690
  	cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);
ad7a2926b   Steve French   [CIFS] reduce che...
2691
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2692
2693
2694
  		cifs_dbg(FYI, "Send error in Rename (by file handle) = %d
  ",
  			 rc);
a5a2b489b   Steve French   [CIFS] Make CIFS ...
2695

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2696
2697
2698
2699
2700
2701
2702
2703
2704
  	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/...
2705
2706
2707
  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
2708
2709
2710
2711
2712
2713
2714
  {
  	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...
2715
2716
  	cifs_dbg(FYI, "In CIFSSMBCopy
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
  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...
2729
2730
2731
  		name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
  					      fromName, PATH_MAX, nls_codepage,
  					      remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2732
2733
2734
2735
2736
  		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...
2737
  		name_len2 =
acbbb76a2   Steve French   CIFS: Rename *UCS...
2738
2739
  		    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
  				       toName, PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2740
2741
  		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
  		name_len2 *= 2; /* convert to bytes */
50c2f7538   Steve French   [CIFS] whitespace...
2742
  	} else { 	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
  		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 ...
2755
  	inc_rfc1001_len(pSMB, count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2756
2757
2758
2759
2760
  	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...
2761
2762
2763
  		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
2764
  	}
0d817bc0d   Steve French   [CIFS] Remove red...
2765
  	cifs_buf_release(pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2766
2767
2768
2769
2770
2771
2772
2773
  
  	if (rc == -EAGAIN)
  		goto copyRetry;
  
  	return rc;
  }
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2774
  CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2775
  		      const char *fromName, const char *toName,
bc8ebdc4f   Nakajima Akira   Fix that several ...
2776
  		      const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2777
2778
2779
2780
2781
2782
2783
2784
2785
  {
  	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...
2786
2787
  	cifs_dbg(FYI, "In Symlink Unix style
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2788
2789
2790
2791
2792
2793
2794
2795
  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 ...
2796
2797
2798
  		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fromName,
  				/* find define for this maxpathcomponent */
  					PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2799
2800
  		name_len++;	/* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
2801
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
  		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...
2813
  				InformationLevel) - 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2814
2815
2816
2817
2818
  	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 ...
2819
2820
2821
  		    cifsConvertToUTF16((__le16 *) data_offset, toName,
  				/* find define for this maxpathcomponent */
  					PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2822
2823
  		name_len_target++;	/* trailing null */
  		name_len_target *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
2824
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
  		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 ...
2845
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2846
2847
2848
  	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/...
2849
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);
ad7a2926b   Steve French   [CIFS] reduce che...
2850
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2851
2852
2853
  		cifs_dbg(FYI, "Send error in SetPathInfo create symlink = %d
  ",
  			 rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2854

0d817bc0d   Steve French   [CIFS] Remove red...
2855
  	cifs_buf_release(pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2856
2857
2858
2859
2860
2861
2862
2863
  
  	if (rc == -EAGAIN)
  		goto createSymLinkRetry;
  
  	return rc;
  }
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2864
  CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2865
  		       const char *fromName, const char *toName,
737b758c9   Steve French   [PATCH] cifs: cha...
2866
  		       const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2867
2868
2869
2870
2871
2872
2873
2874
2875
  {
  	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...
2876
2877
  	cifs_dbg(FYI, "In Create Hard link Unix style
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2878
2879
2880
2881
2882
2883
2884
  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...
2885
2886
  		name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
  					      PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2887
2888
  		name_len++;	/* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
2889
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
  		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...
2901
  				InformationLevel) - 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2902
2903
2904
2905
2906
  	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...
2907
2908
  		    cifsConvertToUTF16((__le16 *) data_offset, fromName,
  				       PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2909
2910
  		name_len_target++;	/* trailing null */
  		name_len_target *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
2911
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
  		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 ...
2932
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2933
2934
2935
  	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/...
2936
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
ad7a2926b   Steve French   [CIFS] reduce che...
2937
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2938
2939
2940
  		cifs_dbg(FYI, "Send error in SetPathInfo (hard link) = %d
  ",
  			 rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2941
2942
2943
2944
2945
2946
2947
2948
2949
  
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto createHardLinkRetry;
  
  	return rc;
  }
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2950
  CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
d6e906f1b   Steve French   CIFS: Move hardli...
2951
2952
  		   const char *from_name, const char *to_name,
  		   struct cifs_sb_info *cifs_sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2953
2954
2955
2956
2957
2958
2959
  {
  	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...
2960
  	int remap = cifs_remap(cifs_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2961

f96637be0   Joe Perches   [CIFS] cifs: Rena...
2962
2963
  	cifs_dbg(FYI, "In CIFSCreateHardLink
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
  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...
2981
2982
  		    cifsConvertToUTF16((__le16 *) pSMB->OldFileName, from_name,
  				       PATH_MAX, cifs_sb->local_nls, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2983
2984
  		name_len++;	/* trailing null */
  		name_len *= 2;
fcc7c09d9   Jeff Layton   cifs: fix buffer ...
2985
2986
2987
2988
  
  		/* 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
2989
  		name_len2 =
acbbb76a2   Steve French   CIFS: Rename *UCS...
2990
  		    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
d6e906f1b   Steve French   CIFS: Move hardli...
2991
2992
  				       to_name, PATH_MAX, cifs_sb->local_nls,
  				       remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2993
2994
  		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
  		name_len2 *= 2;	/* convert to bytes */
50c2f7538   Steve French   [CIFS] whitespace...
2995
  	} else {	/* BB improve the check for buffer overruns BB */
d6e906f1b   Steve French   CIFS: Move hardli...
2996
  		name_len = strnlen(from_name, PATH_MAX);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2997
  		name_len++;	/* trailing null */
d6e906f1b   Steve French   CIFS: Move hardli...
2998
2999
  		strncpy(pSMB->OldFileName, from_name, name_len);
  		name_len2 = strnlen(to_name, PATH_MAX);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3000
3001
  		name_len2++;	/* trailing null */
  		pSMB->OldFileName[name_len] = 0x04;	/* 2nd buffer format */
d6e906f1b   Steve French   CIFS: Move hardli...
3002
  		strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3003
3004
3005
3006
3007
  		name_len2++;	/* trailing null */
  		name_len2++;	/* signature byte */
  	}
  
  	count = 1 /* string type byte */  + name_len + name_len2;
be8e3b004   Steve French   consistently use ...
3008
  	inc_rfc1001_len(pSMB, count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3009
3010
3011
3012
  	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/...
3013
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
ad7a2926b   Steve French   [CIFS] reduce che...
3014
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3015
3016
  		cifs_dbg(FYI, "Send error in hard link (NT rename) = %d
  ", rc);
ad7a2926b   Steve French   [CIFS] reduce che...
3017

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3018
3019
3020
3021
3022
3023
3024
3025
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto winCreateHardLinkRetry;
  
  	return rc;
  }
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
3026
  CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
460b96960   Jeff Layton   cifs: change CIFS...
3027
  			const unsigned char *searchName, char **symlinkinfo,
bc8ebdc4f   Nakajima Akira   Fix that several ...
3028
  			const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3029
3030
3031
3032
3033
3034
3035
3036
  {
  /* 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...
3037
  	char *data_start;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3038

f96637be0   Joe Perches   [CIFS] cifs: Rena...
3039
3040
  	cifs_dbg(FYI, "In QPathSymLinkInfo (Unix) for path %s
  ", searchName);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3041
3042
3043
3044
3045
3046
3047
3048
3049
  
  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 ...
3050
3051
3052
  			cifsConvertToUTF16((__le16 *) pSMB->FileName,
  					   searchName, PATH_MAX, nls_codepage,
  					   remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3053
3054
  		name_len++;	/* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
3055
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3056
3057
3058
3059
3060
3061
3062
3063
  		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...
3064
  	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3065
3066
3067
3068
3069
3070
  	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...
3071
  	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
  	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 ...
3082
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3083
3084
3085
3086
3087
  	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...
3088
3089
  		cifs_dbg(FYI, "Send error in QuerySymLinkInfo = %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3090
3091
3092
3093
  	} else {
  		/* decode response */
  
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3094
  		/* BB also check enough total bytes returned */
820a803ff   Jeff Layton   cifs: keep BCC in...
3095
  		if (rc || get_bcc(&pSMBr->hdr) < 2)
460b96960   Jeff Layton   cifs: change CIFS...
3096
  			rc = -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3097
  		else {
0e0d2cf32   Steve French   [CIFS] Remove spa...
3098
  			bool is_unicode;
460b96960   Jeff Layton   cifs: change CIFS...
3099
3100
3101
3102
  			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
3103

0e0d2cf32   Steve French   [CIFS] Remove spa...
3104
3105
3106
3107
  			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
  				is_unicode = true;
  			else
  				is_unicode = false;
737b758c9   Steve French   [PATCH] cifs: cha...
3108
  			/* BB FIXME investigate remapping reserved chars here */
acbbb76a2   Steve French   CIFS: Rename *UCS...
3109
3110
  			*symlinkinfo = cifs_strndup_from_utf16(data_start,
  					count, is_unicode, nls_codepage);
8b6427a2a   Jeff Layton   cifs: fix pointer...
3111
  			if (!*symlinkinfo)
460b96960   Jeff Layton   cifs: change CIFS...
3112
  				rc = -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3113
3114
3115
3116
3117
3118
3119
  		}
  	}
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto querySymLinkRetry;
  	return rc;
  }
c52a95545   Steve French   Don't compile in ...
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
  /*
   *	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
3130
  int
d244bf2df   Pavel Shilovsky   CIFS: Implement f...
3131
3132
3133
  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
3134
3135
3136
  {
  	int rc = 0;
  	int bytes_returned;
50c2f7538   Steve French   [CIFS] whitespace...
3137
3138
  	struct smb_com_transaction_ioctl_req *pSMB;
  	struct smb_com_transaction_ioctl_rsp *pSMBr;
d244bf2df   Pavel Shilovsky   CIFS: Implement f...
3139
3140
3141
  	bool is_unicode;
  	unsigned int sub_len;
  	char *sub_start;
c31f33071   Steve French   do not treat non-...
3142
3143
  	struct reparse_symlink_data *reparse_buf;
  	struct reparse_posix_data *posix_buf;
d244bf2df   Pavel Shilovsky   CIFS: Implement f...
3144
3145
3146
3147
3148
  	__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
3149
3150
3151
3152
3153
3154
3155
3156
3157
  	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...
3158
  	pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
  	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...
3176
3177
  		cifs_dbg(FYI, "Send error in QueryReparseLinkInfo = %d
  ", rc);
d244bf2df   Pavel Shilovsky   CIFS: Implement f...
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
  		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-...
3195
  	reparse_buf = (struct reparse_symlink_data *)
d244bf2df   Pavel Shilovsky   CIFS: Implement f...
3196
3197
3198
3199
  				((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
3200
  	}
c31f33071   Steve French   do not treat non-...
3201
3202
3203
3204
3205
3206
3207
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
  	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...
3235
3236
3237
3238
3239
  		cifs_dbg(FYI, "reparse buf beyond SMB
  ");
  		rc = -EIO;
  		goto qreparse_out;
  	}
d244bf2df   Pavel Shilovsky   CIFS: Implement f...
3240
3241
3242
3243
  	if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
  		is_unicode = true;
  	else
  		is_unicode = false;
989c7e512   Steve French   [CIFS] remove che...
3244

d244bf2df   Pavel Shilovsky   CIFS: Implement f...
3245
3246
3247
3248
3249
  	/* 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
3250
  qreparse_out:
4a6d87f1d   Steve French   [CIFS] Add missin...
3251
  	cifs_buf_release(pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3252

d244bf2df   Pavel Shilovsky   CIFS: Implement f...
3253
3254
3255
3256
  	/*
  	 * 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
3257
3258
  	return rc;
  }
c7f508a99   Steve French   Allow setting per...
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
  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...
3278
  	pSMB->TotalDataCount = cpu_to_le32(2);
c7f508a99   Steve French   Allow setting per...
3279
3280
3281
3282
3283
  	pSMB->MaxParameterCount = 0;
  	pSMB->MaxDataCount = 0;
  	pSMB->MaxSetupCount = 4;
  	pSMB->Reserved = 0;
  	pSMB->ParameterOffset = 0;
bc09d141e   Fabian Frederick   fs/cifs: remove o...
3284
  	pSMB->DataCount = cpu_to_le32(2);
c7f508a99   Steve French   Allow setting per...
3285
3286
3287
3288
  	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...
3289
  	pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
c7f508a99   Steve French   Allow setting per...
3290
  	pSMB->ParameterCount = 0;
bc09d141e   Fabian Frederick   fs/cifs: remove o...
3291
  	pSMB->FunctionCode = cpu_to_le32(FSCTL_SET_COMPRESSION);
c7f508a99   Steve French   Allow setting per...
3292
3293
3294
3295
  	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...
3296
  	pSMB->ByteCount = cpu_to_le16(5);
c7f508a99   Steve French   Allow setting per...
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
  	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
3313
3314
3315
  #ifdef CONFIG_CIFS_POSIX
  
  /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2211d5ba5   Andreas Gruenbacher   posix_acl: xattr ...
3316
  static void cifs_convert_ace(struct posix_acl_xattr_entry *ace,
50c2f7538   Steve French   [CIFS] whitespace...
3317
  			     struct cifs_posix_ace *cifs_ace)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3318
3319
  {
  	/* u8 cifs fields do not need le conversion */
ff7feac96   Steve French   [CIFS] Fix endian...
3320
3321
3322
  	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...
3323
3324
3325
3326
3327
  /*
  	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
3328
3329
3330
3331
3332
  
  	return;
  }
  
  /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
50c2f7538   Steve French   [CIFS] whitespace...
3333
3334
  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
3335
3336
3337
3338
  {
  	int size =  0;
  	int i;
  	__u16 count;
50c2f7538   Steve French   [CIFS] whitespace...
3339
3340
  	struct cifs_posix_ace *pACE;
  	struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2211d5ba5   Andreas Gruenbacher   posix_acl: xattr ...
3341
  	struct posix_acl_xattr_header *local_acl = (void *)trgt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3342
3343
3344
  
  	if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
  		return -EOPNOTSUPP;
45987e006   Andreas Gruenbacher   cifs: Check for e...
3345
  	if (acl_type == ACL_TYPE_ACCESS) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3346
3347
3348
3349
3350
  		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...
3351
  		if (size_of_data_area < size) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3352
3353
3354
  			cifs_dbg(FYI, "bad CIFS POSIX ACL size %d vs. %d
  ",
  				 size_of_data_area, size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3355
3356
  			return -EINVAL;
  		}
45987e006   Andreas Gruenbacher   cifs: Check for e...
3357
  	} else if (acl_type == ACL_TYPE_DEFAULT) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3358
3359
3360
3361
3362
3363
3364
3365
  		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...
3366
  		if (size_of_data_area < size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3367
3368
3369
3370
3371
3372
3373
  			return -EINVAL;
  	} else {
  		/* illegal type */
  		return -EINVAL;
  	}
  
  	size = posix_acl_xattr_size(count);
790fe579f   Steve French   [CIFS] more white...
3374
  	if ((buflen == 0) || (local_acl == NULL)) {
50c2f7538   Steve French   [CIFS] whitespace...
3375
  		/* used to query ACL EA size */
790fe579f   Steve French   [CIFS] more white...
3376
  	} else if (size > buflen) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3377
3378
  		return -ERANGE;
  	} else /* buffer big enough */ {
2211d5ba5   Andreas Gruenbacher   posix_acl: xattr ...
3379
  		struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
ff7feac96   Steve French   [CIFS] Fix endian...
3380
  		local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
50c2f7538   Steve French   [CIFS] whitespace...
3381
  		for (i = 0; i < count ; i++) {
2211d5ba5   Andreas Gruenbacher   posix_acl: xattr ...
3382
  			cifs_convert_ace(&ace[i], pACE);
50c2f7538   Steve French   [CIFS] whitespace...
3383
  			pACE++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3384
3385
3386
3387
  		}
  	}
  	return size;
  }
50c2f7538   Steve French   [CIFS] whitespace...
3388
  static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2211d5ba5   Andreas Gruenbacher   posix_acl: xattr ...
3389
  				     const struct posix_acl_xattr_entry *local_ace)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3390
3391
  {
  	__u16 rc = 0; /* 0 = ACL converted ok */
ff7feac96   Steve French   [CIFS] Fix endian...
3392
3393
  	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
3394
  	/* BB is there a better way to handle the large uid? */
790fe579f   Steve French   [CIFS] more white...
3395
  	if (local_ace->e_id == cpu_to_le32(-1)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3396
3397
  	/* 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...
3398
  	} else
ff7feac96   Steve French   [CIFS] Fix endian...
3399
  		cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3400
3401
3402
3403
3404
  /*
  	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
3405
3406
3407
3408
  	return rc;
  }
  
  /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
50c2f7538   Steve French   [CIFS] whitespace...
3409
3410
  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
3411
3412
  {
  	__u16 rc = 0;
50c2f7538   Steve French   [CIFS] whitespace...
3413
  	struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2211d5ba5   Andreas Gruenbacher   posix_acl: xattr ...
3414
  	struct posix_acl_xattr_header *local_acl = (void *)pACL;
ae9ebe7c4   Eryu Guan   CIFS: iterate ove...
3415
  	struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3416
3417
  	int count;
  	int i;
790fe579f   Steve French   [CIFS] more white...
3418
  	if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3419
3420
3421
  		return 0;
  
  	count = posix_acl_xattr_count((size_t)buflen);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3422
3423
3424
  	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...
3425
  	if (le32_to_cpu(local_acl->a_version) != 2) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3426
3427
3428
  		cifs_dbg(FYI, "unknown POSIX ACL version %d
  ",
  			 le32_to_cpu(local_acl->a_version));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3429
3430
3431
  		return 0;
  	}
  	cifs_acl->version = cpu_to_le16(1);
b1d933564   Steve French   setfacl removes p...
3432
  	if (acl_type == ACL_TYPE_ACCESS) {
ff7feac96   Steve French   [CIFS] Fix endian...
3433
  		cifs_acl->access_entry_count = cpu_to_le16(count);
bc09d141e   Fabian Frederick   fs/cifs: remove o...
3434
  		cifs_acl->default_entry_count = cpu_to_le16(0xFFFF);
b1d933564   Steve French   setfacl removes p...
3435
  	} else if (acl_type == ACL_TYPE_DEFAULT) {
ff7feac96   Steve French   [CIFS] Fix endian...
3436
  		cifs_acl->default_entry_count = cpu_to_le16(count);
bc09d141e   Fabian Frederick   fs/cifs: remove o...
3437
  		cifs_acl->access_entry_count = cpu_to_le16(0xFFFF);
b1d933564   Steve French   setfacl removes p...
3438
  	} else {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3439
3440
  		cifs_dbg(FYI, "unknown ACL type %d
  ", acl_type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3441
3442
  		return 0;
  	}
50c2f7538   Steve French   [CIFS] whitespace...
3443
  	for (i = 0; i < count; i++) {
ae9ebe7c4   Eryu Guan   CIFS: iterate ove...
3444
  		rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i], &ace[i]);
790fe579f   Steve French   [CIFS] more white...
3445
  		if (rc != 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3446
3447
3448
3449
  			/* ACE not converted */
  			break;
  		}
  	}
790fe579f   Steve French   [CIFS] more white...
3450
  	if (rc == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3451
3452
3453
3454
3455
3456
3457
3458
  		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/...
3459
  CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
50c2f7538   Steve French   [CIFS] whitespace...
3460
3461
3462
  		   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
3463
3464
3465
3466
3467
3468
3469
3470
  {
  /* 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...
3471

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3481
3482
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		name_len =
acbbb76a2   Steve French   CIFS: Rename *UCS...
3483
3484
3485
  			cifsConvertToUTF16((__le16 *) pSMB->FileName,
  					   searchName, PATH_MAX, nls_codepage,
  					   remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3486
3487
3488
3489
  		name_len++;     /* trailing null */
  		name_len *= 2;
  		pSMB->FileName[name_len] = 0;
  		pSMB->FileName[name_len+1] = 0;
50c2f7538   Steve French   [CIFS] whitespace...
3490
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3491
3492
3493
3494
3495
3496
3497
3498
  		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...
3499
  	/* BB find exact max data count below from sess structure BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3500
3501
3502
3503
3504
3505
3506
  	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...
3507
3508
  		offsetof(struct smb_com_transaction2_qpi_req,
  			 InformationLevel) - 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
  	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 ...
3519
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3520
3521
3522
3523
  	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/...
3524
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3525
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3526
3527
  		cifs_dbg(FYI, "Send error in Query POSIX ACL = %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3528
3529
  	} else {
  		/* decode response */
50c2f7538   Steve French   [CIFS] whitespace...
3530

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3531
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3532
  		/* BB also check enough total bytes returned */
820a803ff   Jeff Layton   cifs: keep BCC in...
3533
  		if (rc || get_bcc(&pSMBr->hdr) < 2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3534
3535
3536
3537
3538
3539
  			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...
3540
  				buflen, acl_type, count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3541
3542
3543
3544
3545
3546
3547
3548
3549
  		}
  	}
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto queryAclRetry;
  	return rc;
  }
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
3550
  CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
50c2f7538   Steve French   [CIFS] whitespace...
3551
3552
3553
3554
  		   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
3555
3556
3557
3558
3559
3560
3561
3562
  {
  	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...
3563
3564
  	cifs_dbg(FYI, "In SetPosixACL (Unix) for path %s
  ", fileName);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3565
3566
  setAclRetry:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
50c2f7538   Steve French   [CIFS] whitespace...
3567
  		      (void **) &pSMBr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3568
3569
3570
3571
  	if (rc)
  		return rc;
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		name_len =
acbbb76a2   Steve French   CIFS: Rename *UCS...
3572
3573
  			cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
  					   PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3574
3575
  		name_len++;     /* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
3576
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3577
3578
3579
3580
3581
3582
  		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...
3583
3584
  	/* BB find max SMB size from sess */
  	pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3585
3586
3587
3588
3589
3590
  	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...
3591
  				InformationLevel) - 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3592
3593
3594
3595
3596
  	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...
3597
  	data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3598

790fe579f   Steve French   [CIFS] more white...
3599
  	if (data_count == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
  		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 ...
3614
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3615
3616
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
50c2f7538   Steve French   [CIFS] whitespace...
3617
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
ad7a2926b   Steve French   [CIFS] reduce che...
3618
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3619
3620
  		cifs_dbg(FYI, "Set POSIX ACL returned %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3621
3622
3623
3624
3625
3626
3627
  
  setACLerrorExit:
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto setAclRetry;
  	return rc;
  }
f654bac22   Steve French   [PATCH] cifs: add...
3628
3629
  /* BB fix tabs in this function FIXME BB */
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
3630
  CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
ad7a2926b   Steve French   [CIFS] reduce che...
3631
  	       const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
f654bac22   Steve French   [PATCH] cifs: add...
3632
  {
50c2f7538   Steve French   [CIFS] whitespace...
3633
3634
3635
3636
3637
  	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...
3638

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

ad7a2926b   Steve French   [CIFS] reduce che...
3650
  	params = 2 /* level */ + 2 /* fid */;
790fe579f   Steve French   [CIFS] more white...
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
  	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...
3672
  	pSMB->Fid = netfid;
be8e3b004   Steve French   consistently use ...
3673
  	inc_rfc1001_len(pSMB, byte_count);
790fe579f   Steve French   [CIFS] more white...
3674
3675
3676
3677
3678
  	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...
3679
3680
  		cifs_dbg(FYI, "error %d in GetExtAttr
  ", rc);
790fe579f   Steve French   [CIFS] more white...
3681
3682
3683
  	} else {
  		/* decode response */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
790fe579f   Steve French   [CIFS] more white...
3684
  		/* BB also check enough total bytes returned */
820a803ff   Jeff Layton   cifs: keep BCC in...
3685
  		if (rc || get_bcc(&pSMBr->hdr) < 2)
790fe579f   Steve French   [CIFS] more white...
3686
3687
3688
3689
3690
3691
3692
3693
3694
  			/* 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...
3695
3696
  				cifs_dbg(FYI, "Illegal size ret in GetExtAttr
  ");
790fe579f   Steve French   [CIFS] more white...
3697
3698
3699
3700
3701
3702
  				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...
3703
  			*pMask = le64_to_cpu(pfinfo->mask);
790fe579f   Steve French   [CIFS] more white...
3704
3705
  		}
  	}
f654bac22   Steve French   [PATCH] cifs: add...
3706
  GetExtAttrOut:
790fe579f   Steve French   [CIFS] more white...
3707
3708
3709
3710
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto GetExtAttrRetry;
  	return rc;
f654bac22   Steve French   [PATCH] cifs: add...
3711
  }
f654bac22   Steve French   [PATCH] cifs: add...
3712
  #endif /* CONFIG_POSIX */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3713

79df1baee   Jeff Layton   cifs: fix use of ...
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
  #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...
3725
  		   const int parm_len, struct cifs_tcon *tcon,
79df1baee   Jeff Layton   cifs: fix use of ...
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
  		   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...
3740
  	pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
79df1baee   Jeff Layton   cifs: fix use of ...
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
  	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...
3759
  	u16 bcc;
79df1baee   Jeff Layton   cifs: fix use of ...
3760
3761
3762
3763
3764
3765
3766
3767
  
  	*pdatalen = 0;
  	*pparmlen = 0;
  
  	if (buf == NULL)
  		return -EINVAL;
  
  	pSMBr = (struct smb_com_ntransact_rsp *)buf;
820a803ff   Jeff Layton   cifs: keep BCC in...
3768
3769
  	bcc = get_bcc(&pSMBr->hdr);
  	end_of_smb = 2 /* sizeof byte count */ + bcc +
79df1baee   Jeff Layton   cifs: fix use of ...
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
  			(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...
3782
3783
  		cifs_dbg(FYI, "parms start after end of smb
  ");
79df1baee   Jeff Layton   cifs: fix use of ...
3784
3785
  		return -EINVAL;
  	} else if (parm_count + *ppparm > end_of_smb) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3786
3787
  		cifs_dbg(FYI, "parm end after end of smb
  ");
79df1baee   Jeff Layton   cifs: fix use of ...
3788
3789
  		return -EINVAL;
  	} else if (*ppdata > end_of_smb) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3790
3791
  		cifs_dbg(FYI, "data starts after end of smb
  ");
79df1baee   Jeff Layton   cifs: fix use of ...
3792
3793
  		return -EINVAL;
  	} else if (data_count + *ppdata > end_of_smb) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3794
3795
3796
3797
  		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 ...
3798
  		return -EINVAL;
820a803ff   Jeff Layton   cifs: keep BCC in...
3799
  	} else if (parm_count + data_count > bcc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3800
3801
  		cifs_dbg(FYI, "parm count and data count larger than SMB
  ");
79df1baee   Jeff Layton   cifs: fix use of ...
3802
3803
3804
3805
3806
3807
  		return -EINVAL;
  	}
  	*pdatalen = data_count;
  	*pparmlen = parm_count;
  	return 0;
  }
0a4b92c05   Steve French   [CIFS] Add worker...
3808
3809
  /* Get Security Descriptor (by handle) from remote server for a file or dir */
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
3810
  CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
630f3f0c4   Steve French   [CIFS] acl suppor...
3811
  		  struct cifs_ntsd **acl_inf, __u32 *pbuflen)
0a4b92c05   Steve French   [CIFS] Add worker...
3812
3813
3814
  {
  	int rc = 0;
  	int buf_type = 0;
ad7a2926b   Steve French   [CIFS] reduce che...
3815
  	QUERY_SEC_DESC_REQ *pSMB;
0a4b92c05   Steve French   [CIFS] Add worker...
3816
  	struct kvec iov[1];
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3817
3818
  	cifs_dbg(FYI, "GetCifsACL
  ");
0a4b92c05   Steve French   [CIFS] Add worker...
3819

630f3f0c4   Steve French   [CIFS] acl suppor...
3820
3821
  	*pbuflen = 0;
  	*acl_inf = NULL;
b9c7a2bb1   Steve French   [CIFS] ACL suppor...
3822
  	rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
0a4b92c05   Steve French   [CIFS] Add worker...
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
  			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 ...
3834
  	inc_rfc1001_len(pSMB, 11);
0a4b92c05   Steve French   [CIFS] Add worker...
3835
  	iov[0].iov_base = (char *)pSMB;
be8e3b004   Steve French   consistently use ...
3836
  	iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
0a4b92c05   Steve French   [CIFS] Add worker...
3837

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

630f3f0c4   Steve French   [CIFS] acl suppor...
3877
3878
3879
3880
  		/* 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...
3881
3882
  			cifs_dbg(VFS, "bad acl length %d
  ", *pbuflen);
630f3f0c4   Steve French   [CIFS] acl suppor...
3883
3884
3885
  			rc = -EINVAL;
  			*pbuflen = 0;
  		} else {
f7f7c1850   Silviu-Mihai Popescu   fs: cifs: use kme...
3886
  			*acl_inf = kmemdup(pdata, *pbuflen, GFP_KERNEL);
630f3f0c4   Steve French   [CIFS] acl suppor...
3887
3888
3889
3890
  			if (*acl_inf == NULL) {
  				*pbuflen = 0;
  				rc = -ENOMEM;
  			}
630f3f0c4   Steve French   [CIFS] acl suppor...
3891
  		}
0a4b92c05   Steve French   [CIFS] Add worker...
3892
3893
  	}
  qsec_out:
6d81ed1ec   Sachin Prabhu   cifs: replace cod...
3894
  	free_rsp_buf(buf_type, iov[0].iov_base);
4b8f930ff   Steve French   [CIFS] Free small...
3895
  /*	cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
0a4b92c05   Steve French   [CIFS] Add worker...
3896
3897
  	return rc;
  }
97837582b   Steve French   [CIFS] Allow sett...
3898
3899
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
3900
  CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
a5ff37696   Shirish Pargaonkar   cifs: Call id to ...
3901
  			struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
97837582b   Steve French   [CIFS] Allow sett...
3902
3903
3904
3905
3906
  {
  	__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...
3907
  	void *pSMBr;
97837582b   Steve French   [CIFS] Allow sett...
3908
3909
  
  setCifsAclRetry:
b2a3ad9ca   Jeff Layton   cifs: silence com...
3910
  	rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
97837582b   Steve French   [CIFS] Allow sett...
3911
  	if (rc)
b2a3ad9ca   Jeff Layton   cifs: silence com...
3912
  		return rc;
97837582b   Steve French   [CIFS] Allow sett...
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
  
  	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 ...
3937
  	pSMB->AclFlags = cpu_to_le32(aclflag);
97837582b   Steve French   [CIFS] Allow sett...
3938
3939
  
  	if (pntsd && acllen) {
b2a3ad9ca   Jeff Layton   cifs: silence com...
3940
3941
  		memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
  				data_offset, pntsd, acllen);
be8e3b004   Steve French   consistently use ...
3942
  		inc_rfc1001_len(pSMB, byte_count + data_count);
97837582b   Steve French   [CIFS] Allow sett...
3943
  	} else
be8e3b004   Steve French   consistently use ...
3944
  		inc_rfc1001_len(pSMB, byte_count);
97837582b   Steve French   [CIFS] Allow sett...
3945
3946
3947
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3948
3949
3950
  	cifs_dbg(FYI, "SetCIFSACL bytes_returned: %d, rc: %d
  ",
  		 bytes_returned, rc);
97837582b   Steve French   [CIFS] Allow sett...
3951
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3952
3953
  		cifs_dbg(FYI, "Set CIFS ACL returned %d
  ", rc);
97837582b   Steve French   [CIFS] Allow sett...
3954
3955
3956
3957
3958
3959
3960
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto setCifsAclRetry;
  
  	return (rc);
  }
79df1baee   Jeff Layton   cifs: fix use of ...
3961
  #endif /* CONFIG_CIFS_ACL */
0a4b92c05   Steve French   [CIFS] Add worker...
3962

6b8edfe0f   Steve French   [CIFS] Support fo...
3963
3964
  /* Legacy Query Path Information call for lookup to old servers such
     as Win9x/WinME */
68889f269   Pavel Shilovsky   CIFS: Move is_pat...
3965
3966
3967
3968
  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...
3969
  {
ad7a2926b   Steve French   [CIFS] reduce che...
3970
3971
  	QUERY_INFORMATION_REQ *pSMB;
  	QUERY_INFORMATION_RSP *pSMBr;
6b8edfe0f   Steve French   [CIFS] Support fo...
3972
3973
3974
  	int rc = 0;
  	int bytes_returned;
  	int name_len;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3975
3976
  	cifs_dbg(FYI, "In SMBQPath path %s
  ", search_name);
6b8edfe0f   Steve French   [CIFS] Support fo...
3977
3978
  QInfRetry:
  	rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
50c2f7538   Steve French   [CIFS] whitespace...
3979
  		      (void **) &pSMBr);
6b8edfe0f   Steve French   [CIFS] Support fo...
3980
3981
3982
3983
3984
  	if (rc)
  		return rc;
  
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		name_len =
acbbb76a2   Steve French   CIFS: Rename *UCS...
3985
  			cifsConvertToUTF16((__le16 *) pSMB->FileName,
68889f269   Pavel Shilovsky   CIFS: Move is_pat...
3986
  					   search_name, PATH_MAX, nls_codepage,
acbbb76a2   Steve French   CIFS: Rename *UCS...
3987
  					   remap);
6b8edfe0f   Steve French   [CIFS] Support fo...
3988
3989
  		name_len++;     /* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
3990
  	} else {
68889f269   Pavel Shilovsky   CIFS: Move is_pat...
3991
  		name_len = strnlen(search_name, PATH_MAX);
6b8edfe0f   Steve French   [CIFS] Support fo...
3992
  		name_len++;     /* trailing null */
68889f269   Pavel Shilovsky   CIFS: Move is_pat...
3993
  		strncpy(pSMB->FileName, search_name, name_len);
6b8edfe0f   Steve French   [CIFS] Support fo...
3994
3995
  	}
  	pSMB->BufferFormat = 0x04;
50c2f7538   Steve French   [CIFS] whitespace...
3996
  	name_len++; /* account for buffer type byte */
be8e3b004   Steve French   consistently use ...
3997
  	inc_rfc1001_len(pSMB, (__u16)name_len);
6b8edfe0f   Steve French   [CIFS] Support fo...
3998
3999
4000
  	pSMB->ByteCount = cpu_to_le16(name_len);
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
50c2f7538   Steve French   [CIFS] whitespace...
4001
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6b8edfe0f   Steve French   [CIFS] Support fo...
4002
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4003
4004
  		cifs_dbg(FYI, "Send error in QueryInfo = %d
  ", rc);
68889f269   Pavel Shilovsky   CIFS: Move is_pat...
4005
  	} else if (data) {
1bd5bbcb6   Steve French   [CIFS] Legacy tim...
4006
4007
  		struct timespec ts;
  		__u32 time = le32_to_cpu(pSMBr->last_write_time);
ad7a2926b   Steve French   [CIFS] reduce che...
4008
4009
  
  		/* decode response */
1bd5bbcb6   Steve French   [CIFS] Legacy tim...
4010
  		/* BB FIXME - add time zone adjustment BB */
68889f269   Pavel Shilovsky   CIFS: Move is_pat...
4011
  		memset(data, 0, sizeof(FILE_ALL_INFO));
1bd5bbcb6   Steve French   [CIFS] Legacy tim...
4012
4013
4014
  		ts.tv_nsec = 0;
  		ts.tv_sec = time;
  		/* decode time fields */
68889f269   Pavel Shilovsky   CIFS: Move is_pat...
4015
4016
4017
4018
  		data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
  		data->LastWriteTime = data->ChangeTime;
  		data->LastAccessTime = 0;
  		data->AllocationSize =
70ca734a1   Steve French   [CIFS] Various mi...
4019
  			cpu_to_le64(le32_to_cpu(pSMBr->size));
68889f269   Pavel Shilovsky   CIFS: Move is_pat...
4020
4021
  		data->EndOfFile = data->AllocationSize;
  		data->Attributes =
70ca734a1   Steve French   [CIFS] Various mi...
4022
  			cpu_to_le32(le16_to_cpu(pSMBr->attr));
6b8edfe0f   Steve French   [CIFS] Support fo...
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
  	} 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...
4033
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
4034
  CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
bcd5357f4   Jeff Layton   cifs: add a CIFSS...
4035
4036
4037
4038
4039
4040
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
  		 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 ...
4072
  	inc_rfc1001_len(pSMB, byte_count);
7ac0febb8   David Disseldorp   cifs: fill TRANS2...
4073
  	pSMB->t2.ByteCount = cpu_to_le16(byte_count);
6b8edfe0f   Steve French   [CIFS] Support fo...
4074

bcd5357f4   Jeff Layton   cifs: add a CIFSS...
4075
4076
4077
  	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...
4078
  		cifs_dbg(FYI, "Send error in QFileInfo = %d", rc);
bcd5357f4   Jeff Layton   cifs: add a CIFSS...
4079
4080
  	} else {		/* decode response */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
6b8edfe0f   Steve French   [CIFS] Support fo...
4081

bcd5357f4   Jeff Layton   cifs: add a CIFSS...
4082
4083
  		if (rc) /* BB add auto retry on EOPNOTSUPP? */
  			rc = -EIO;
820a803ff   Jeff Layton   cifs: keep BCC in...
4084
  		else if (get_bcc(&pSMBr->hdr) < 40)
bcd5357f4   Jeff Layton   cifs: add a CIFSS...
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
  			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...
4097

bcd5357f4   Jeff Layton   cifs: add a CIFSS...
4098
4099
  	return rc;
  }
6b8edfe0f   Steve French   [CIFS] Support fo...
4100

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

68889f269   Pavel Shilovsky   CIFS: Move is_pat...
4179
4180
4181
4182
4183
4184
  			/*
  			 * 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...
4185
  			if (legacy)
acf1a1b10   Steve French   [CIFS] Level 1 QP...
4186
4187
4188
  				size = sizeof(FILE_INFO_STANDARD);
  			else
  				size = sizeof(FILE_ALL_INFO);
68889f269   Pavel Shilovsky   CIFS: Move is_pat...
4189
  			memcpy((char *) data, (char *) &pSMBr->hdr.Protocol +
acf1a1b10   Steve French   [CIFS] Level 1 QP...
4190
  			       data_offset, size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
  		} else
  		    rc = -ENOMEM;
  	}
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto QPathInfoRetry;
  
  	return rc;
  }
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
4202
  CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
c8634fd31   Jeff Layton   cifs: add a CIFSS...
4203
4204
4205
4206
4207
4208
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
  		 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 ...
4240
  	inc_rfc1001_len(pSMB, byte_count);
7ac0febb8   David Disseldorp   cifs: fill TRANS2...
4241
  	pSMB->t2.ByteCount = cpu_to_le16(byte_count);
c8634fd31   Jeff Layton   cifs: add a CIFSS...
4242
4243
4244
4245
  
  	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...
4246
  		cifs_dbg(FYI, "Send error in UnixQFileInfo = %d", rc);
c8634fd31   Jeff Layton   cifs: add a CIFSS...
4247
4248
  	} else {		/* decode response */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
820a803ff   Jeff Layton   cifs: keep BCC in...
4249
  		if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4250
4251
  			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...
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
  			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/...
4270
  CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4271
  		     const unsigned char *searchName,
582d21e5e   Steve French   [CIFS] cleanup ol...
4272
  		     FILE_UNIX_BASIC_INFO *pFindData,
737b758c9   Steve French   [PATCH] cifs: cha...
4273
  		     const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4274
4275
4276
4277
4278
4279
4280
4281
  {
  /* 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...
4282
4283
  	cifs_dbg(FYI, "In QPathInfo (Unix) the path %s
  ", searchName);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4284
4285
4286
4287
4288
4289
4290
4291
  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...
4292
4293
  		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
  				       PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4294
4295
  		name_len++;	/* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
4296
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4297
4298
4299
4300
  		name_len = strnlen(searchName, PATH_MAX);
  		name_len++;	/* trailing null */
  		strncpy(pSMB->FileName, searchName, name_len);
  	}
50c2f7538   Steve French   [CIFS] whitespace...
4301
  	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4302
4303
4304
  	pSMB->TotalDataCount = 0;
  	pSMB->MaxParameterCount = cpu_to_le16(2);
  	/* BB find exact max SMB PDU from sess structure BB */
50c2f7538   Steve French   [CIFS] whitespace...
4305
  	pSMB->MaxDataCount = cpu_to_le16(4000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4306
4307
4308
4309
4310
4311
  	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...
4312
  	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
  	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 ...
4323
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4324
4325
4326
4327
4328
  	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...
4329
  		cifs_dbg(FYI, "Send error in UnixQPathInfo = %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4330
4331
  	} else {		/* decode response */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
820a803ff   Jeff Layton   cifs: keep BCC in...
4332
  		if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4333
4334
  			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
4335
4336
4337
4338
4339
4340
  			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...
4341
  			       sizeof(FILE_UNIX_BASIC_INFO));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4342
4343
4344
4345
4346
4347
4348
4349
  		}
  	}
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto UnixQPathInfoRetry;
  
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4350
4351
  /* xid, tcon, searchName and codepage are input parms, rest are returned */
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
4352
  CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
c052e2b42   Shirish Pargaonkar   cifs: obtain file...
4353
  	      const char *searchName, struct cifs_sb_info *cifs_sb,
2608bee74   Shirish Pargaonkar   cifs: Include bac...
4354
  	      __u16 *pnetfid, __u16 search_flags,
c052e2b42   Shirish Pargaonkar   cifs: obtain file...
4355
  	      struct cifs_search_info *psrch_inf, bool msearch)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4356
4357
4358
4359
  {
  /* level 257 SMB_ */
  	TRANSACTION2_FFIRST_REQ *pSMB = NULL;
  	TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
ad7a2926b   Steve French   [CIFS] reduce che...
4360
  	T2_FFIRST_RSP_PARMS *parms;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4361
4362
  	int rc = 0;
  	int bytes_returned = 0;
c052e2b42   Shirish Pargaonkar   cifs: obtain file...
4363
  	int name_len, remap;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4364
  	__u16 params, byte_count;
c052e2b42   Shirish Pargaonkar   cifs: obtain file...
4365
  	struct nls_table *nls_codepage;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4366

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4378
4379
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		name_len =
acbbb76a2   Steve French   CIFS: Rename *UCS...
4380
4381
  		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
  				       PATH_MAX, nls_codepage, remap);
737b758c9   Steve French   [PATCH] cifs: cha...
4382
4383
4384
  		/* 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
4385
  		name_len *= 2;
c052e2b42   Shirish Pargaonkar   cifs: obtain file...
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
  		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
4397
4398
  	} else {	/* BB add check for overrun of SMB buf BB */
  		name_len = strnlen(searchName, PATH_MAX);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4399
  /* BB fix here and in unicode clause above ie
790fe579f   Steve French   [CIFS] more white...
4400
  		if (name_len > buffersize-header)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4401
4402
  			free buffer exit; BB */
  		strncpy(pSMB->FileName, searchName, name_len);
c052e2b42   Shirish Pargaonkar   cifs: obtain file...
4403
4404
4405
4406
4407
4408
  		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
4409
4410
4411
4412
4413
  	}
  
  	params = 12 + name_len /* includes null */ ;
  	pSMB->TotalDataCount = 0;	/* no EAs */
  	pSMB->MaxParameterCount = cpu_to_le16(10);
c974befa4   Jeff Layton   cifs: untangle se...
4414
  	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4415
4416
4417
4418
4419
4420
4421
4422
4423
  	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...
4424
4425
  	      offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
  		- 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4426
4427
4428
4429
4430
4431
4432
4433
  	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...
4434
  	pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
2608bee74   Shirish Pargaonkar   cifs: Include bac...
4435
  	pSMB->SearchFlags = cpu_to_le16(search_flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4436
4437
4438
4439
  	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 ...
4440
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4441
4442
4443
4444
  	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/...
4445
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_ffirst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4446

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

88274815f   Steve French   [CIFS] Fix two re...
4453
  		cifs_buf_release(pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4454
4455
4456
4457
4458
4459
4460
4461
  
  		/* 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...
4462
  		if (rc == 0) {
b77d753c4   Steve French   [CIFS] Check that...
4463
  			unsigned int lnoff;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4464
  			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4b18f2a9c   Steve French   [CIFS] convert us...
4465
  				psrch_inf->unicode = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4466
  			else
4b18f2a9c   Steve French   [CIFS] convert us...
4467
  				psrch_inf->unicode = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4468
4469
  
  			psrch_inf->ntwrk_buf_start = (char *)pSMBr;
d47d7c1a8   Steve French   [CIFS] CIFS readd...
4470
  			psrch_inf->smallBuf = 0;
50c2f7538   Steve French   [CIFS] whitespace...
4471
4472
  			psrch_inf->srch_entries_start =
  				(char *) &pSMBr->hdr.Protocol +
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4473
  					le16_to_cpu(pSMBr->t2.DataOffset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4474
4475
  			parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
  			       le16_to_cpu(pSMBr->t2.ParameterOffset));
790fe579f   Steve French   [CIFS] more white...
4476
  			if (parms->EndofSearch)
4b18f2a9c   Steve French   [CIFS] convert us...
4477
  				psrch_inf->endOfSearch = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4478
  			else
4b18f2a9c   Steve French   [CIFS] convert us...
4479
  				psrch_inf->endOfSearch = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4480

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

4b18f2a9c   Steve French   [CIFS] convert us...
4518
  	if (psrch_inf->endOfSearch)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4519
4520
4521
4522
4523
4524
  		return -ENOENT;
  
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  		(void **) &pSMBr);
  	if (rc)
  		return rc;
50c2f7538   Steve French   [CIFS] whitespace...
4525
  	params = 14; /* includes 2 bytes of null string, converted to LE below*/
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4526
4527
4528
  	byte_count = 0;
  	pSMB->TotalDataCount = 0;       /* no EAs */
  	pSMB->MaxParameterCount = cpu_to_le16(8);
c974befa4   Jeff Layton   cifs: untangle se...
4529
  	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
  	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...
4544
  		cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4545
4546
  	pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
  	pSMB->ResumeKey = psrch_inf->resume_key;
2608bee74   Shirish Pargaonkar   cifs: Include bac...
4547
  	pSMB->SearchFlags = cpu_to_le16(search_flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4548
4549
4550
  
  	name_len = psrch_inf->resume_name_len;
  	params += name_len;
790fe579f   Steve French   [CIFS] more white...
4551
  	if (name_len < PATH_MAX) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4552
4553
  		memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
  		byte_count += name_len;
ef6724e32   Steve French   [CIFS] Fix missin...
4554
4555
4556
  		/* 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
4557
4558
4559
4560
4561
4562
4563
  	} 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 ...
4564
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4565
  	pSMB->ByteCount = cpu_to_le16(byte_count);
50c2f7538   Steve French   [CIFS] whitespace...
4566

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

790fe579f   Steve French   [CIFS] more white...
4581
  		if (rc == 0) {
b77d753c4   Steve French   [CIFS] Check that...
4582
  			unsigned int lnoff;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4583
4584
  			/* BB fixme add lock for file (srch_info) struct here */
  			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4b18f2a9c   Steve French   [CIFS] convert us...
4585
  				psrch_inf->unicode = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4586
  			else
4b18f2a9c   Steve French   [CIFS] convert us...
4587
  				psrch_inf->unicode = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4588
4589
4590
4591
4592
  			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...
4593
  			if (psrch_inf->smallBuf)
d47d7c1a8   Steve French   [CIFS] CIFS readd...
4594
4595
4596
4597
  				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
4598
4599
  			psrch_inf->srch_entries_start = response_data;
  			psrch_inf->ntwrk_buf_start = (char *)pSMB;
d47d7c1a8   Steve French   [CIFS] CIFS readd...
4600
  			psrch_inf->smallBuf = 0;
790fe579f   Steve French   [CIFS] more white...
4601
  			if (parms->EndofSearch)
4b18f2a9c   Steve French   [CIFS] convert us...
4602
  				psrch_inf->endOfSearch = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4603
  			else
4b18f2a9c   Steve French   [CIFS] convert us...
4604
  				psrch_inf->endOfSearch = false;
50c2f7538   Steve French   [CIFS] whitespace...
4605
4606
  			psrch_inf->entries_in_buffer =
  						le16_to_cpu(parms->SearchCount);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4607
4608
  			psrch_inf->index_of_last_entry +=
  				psrch_inf->entries_in_buffer;
b77d753c4   Steve French   [CIFS] Check that...
4609
  			lnoff = le16_to_cpu(parms->LastNameOffset);
c974befa4   Jeff Layton   cifs: untangle se...
4610
  			if (CIFSMaxBufSize < lnoff) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4611
4612
  				cifs_dbg(VFS, "ignoring corrupt resume name
  ");
b77d753c4   Steve French   [CIFS] Check that...
4613
4614
4615
4616
4617
  				psrch_inf->last_entry = NULL;
  				return rc;
  			} else
  				psrch_inf->last_entry =
  					psrch_inf->srch_entries_start + lnoff;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4618
4619
4620
  /*  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
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
  
  			/* 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
4635
4636
4637
4638
  	return rc;
  }
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
4639
  CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
50c2f7538   Steve French   [CIFS] whitespace...
4640
  	      const __u16 searchHandle)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4641
4642
4643
  {
  	int rc = 0;
  	FINDCLOSE_REQ *pSMB = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4644

f96637be0   Joe Perches   [CIFS] cifs: Rena...
4645
4646
  	cifs_dbg(FYI, "In CIFSSMBFindClose
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4647
4648
4649
4650
  	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...
4651
  	if (rc == -EAGAIN)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4652
4653
4654
  		return 0;
  	if (rc)
  		return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4655
4656
  	pSMB->FileID = searchHandle;
  	pSMB->ByteCount = 0;
792af7b05   Pavel Shilovsky   CIFS: Separate pr...
4657
  	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
ad7a2926b   Steve French   [CIFS] reduce che...
4658
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4659
4660
  		cifs_dbg(VFS, "Send error in FindClose = %d
  ", rc);
ad7a2926b   Steve French   [CIFS] reduce che...
4661

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

fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4764
4765
4766
4767
4768
4769
4770
  /* 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...
4771
  parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4772
4773
  		unsigned int *num_of_nodes,
  		struct dfs_info3_param **target_nodes,
2c55608f2   Igor Mammedov   Fixed parsing of ...
4774
4775
  		const struct nls_table *nls_codepage, int remap,
  		const char *searchName)
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4776
4777
4778
4779
4780
  {
  	int i, rc = 0;
  	char *data_end;
  	bool is_unicode;
  	struct dfs_referral_level_3 *ref;
5ca33c6ac   Harvey Harrison   cifs: assorted en...
4781
4782
4783
4784
  	if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
  		is_unicode = true;
  	else
  		is_unicode = false;
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4785
4786
4787
  	*num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
  
  	if (*num_of_nodes < 1) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4788
4789
4790
  		cifs_dbg(VFS, "num_referrals: must be at least > 0, but we get num_referrals = %d
  ",
  			 *num_of_nodes);
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4791
  		rc = -EINVAL;
a1fe78f16   Steve French   [CIFS] Add missin...
4792
  		goto parse_DFS_referrals_exit;
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4793
4794
4795
  	}
  
  	ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
1d92cfd54   Al Viro   cifs endianness f...
4796
  	if (ref->VersionNumber != cpu_to_le16(3)) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4797
4798
4799
  		cifs_dbg(VFS, "Referrals of V%d version are not supported, should be V3
  ",
  			 le16_to_cpu(ref->VersionNumber));
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4800
  		rc = -EINVAL;
a1fe78f16   Steve French   [CIFS] Add missin...
4801
  		goto parse_DFS_referrals_exit;
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4802
4803
4804
4805
4806
  	}
  
  	/* 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...
4807
4808
4809
  	cifs_dbg(FYI, "num_referrals: %d dfs flags: 0x%x ...
  ",
  		 *num_of_nodes, le32_to_cpu(pSMBr->DFSFlags));
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4810

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

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

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4925
4926
4927
4928
4929
  	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...
4930
4931
  	/* BB find exact max SMB PDU from sess structure BB */
  	pSMB->MaxDataCount = cpu_to_le16(4000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4932
4933
4934
4935
4936
4937
  	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...
4938
  	  struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4939
4940
4941
4942
4943
4944
4945
  	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 ...
4946
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4947
4948
4949
4950
4951
  	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...
4952
4953
  		cifs_dbg(FYI, "Send error in GetDFSRefer = %d
  ", rc);
c2cf07d59   Steve French   [CIFS] Finishup D...
4954
4955
4956
  		goto GetDFSRefExit;
  	}
  	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4957

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

f96637be0   Joe Perches   [CIFS] cifs: Rena...
4964
4965
4966
  	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
4967

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4973
  GetDFSRefExit:
0d817bc0d   Steve French   [CIFS] Remove red...
4974
  	cifs_buf_release(pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4975
4976
4977
4978
4979
4980
  
  	if (rc == -EAGAIN)
  		goto getDFSRetry;
  
  	return rc;
  }
209624388   Steve French   [CIFS] Add suppor...
4981
4982
  /* Query File System Info such as free space to old servers such as Win 9x */
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
4983
4984
  SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
  	      struct kstatfs *FSData)
209624388   Steve French   [CIFS] Add suppor...
4985
4986
4987
4988
4989
4990
4991
4992
  {
  /* 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...
4993
4994
  	cifs_dbg(FYI, "OldQFSInfo
  ");
209624388   Steve French   [CIFS] Add suppor...
4995
4996
4997
4998
4999
  oldQFSInfoRetry:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  		(void **) &pSMBr);
  	if (rc)
  		return rc;
209624388   Steve French   [CIFS] Add suppor...
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
  
  	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 ...
5021
  	inc_rfc1001_len(pSMB, byte_count);
209624388   Steve French   [CIFS] Add suppor...
5022
5023
5024
5025
5026
  	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...
5027
5028
  		cifs_dbg(FYI, "Send error in QFSInfo = %d
  ", rc);
209624388   Steve French   [CIFS] Add suppor...
5029
5030
  	} else {                /* decode response */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
820a803ff   Jeff Layton   cifs: keep BCC in...
5031
  		if (rc || get_bcc(&pSMBr->hdr) < 18)
209624388   Steve French   [CIFS] Add suppor...
5032
5033
5034
  			rc = -EIO;      /* bad smb */
  		else {
  			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5035
5036
  			cifs_dbg(FYI, "qfsinf resp BCC: %d  Offset %d
  ",
820a803ff   Jeff Layton   cifs: keep BCC in...
5037
  				 get_bcc(&pSMBr->hdr), data_offset);
209624388   Steve French   [CIFS] Add suppor...
5038

50c2f7538   Steve French   [CIFS] whitespace...
5039
  			response_data = (FILE_SYSTEM_ALLOC_INFO *)
209624388   Steve French   [CIFS] Add suppor...
5040
5041
5042
5043
5044
5045
  				(((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...
5046
  			       le32_to_cpu(response_data->TotalAllocationUnits);
209624388   Steve French   [CIFS] Add suppor...
5047
5048
  			FSData->f_bfree = FSData->f_bavail =
  				le32_to_cpu(response_data->FreeAllocationUnits);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5049
5050
5051
5052
5053
  			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...
5054
5055
5056
5057
5058
5059
5060
5061
5062
  		}
  	}
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto oldQFSInfoRetry;
  
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5063
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
5064
5065
  CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
  	       struct kstatfs *FSData)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5066
5067
5068
5069
5070
5071
5072
5073
  {
  /* 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...
5074
5075
  	cifs_dbg(FYI, "In QFSInfo
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5076
5077
5078
5079
5080
5081
5082
5083
5084
  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...
5085
  	pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5086
5087
5088
5089
5090
5091
5092
5093
5094
  	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...
5095
  		struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5096
5097
5098
5099
5100
5101
  	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 ...
5102
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5103
5104
5105
5106
5107
  	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...
5108
5109
  		cifs_dbg(FYI, "Send error in QFSInfo = %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5110
  	} else {		/* decode response */
50c2f7538   Steve French   [CIFS] whitespace...
5111
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5112

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5531
  	__u16 params, byte_count, data_count, param_offset, offset;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5532
5533
  	cifs_dbg(FYI, "In SetEOF
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5534
5535
5536
5537
5538
5539
5540
5541
  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...
5542
5543
  		    cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
  				       PATH_MAX, cifs_sb->local_nls, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5544
5545
  		name_len++;	/* trailing null */
  		name_len *= 2;
3e87d8039   Steve French   [CIFS] Add suppor...
5546
  	} else {	/* BB improve the check for buffer overruns BB */
d14334181   Pavel Shilovsky   CIFS: Move set_fi...
5547
  		name_len = strnlen(file_name, PATH_MAX);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5548
  		name_len++;	/* trailing null */
d14334181   Pavel Shilovsky   CIFS: Move set_fi...
5549
  		strncpy(pSMB->FileName, file_name, name_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5550
5551
  	}
  	params = 6 + name_len;
26f57364d   Steve French   [CIFS] formatting...
5552
  	data_count = sizeof(struct file_end_of_file_info);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5553
  	pSMB->MaxParameterCount = cpu_to_le16(2);
3e87d8039   Steve French   [CIFS] Add suppor...
5554
  	pSMB->MaxDataCount = cpu_to_le16(4100);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5555
5556
5557
5558
5559
5560
  	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...
5561
  				InformationLevel) - 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5562
  	offset = param_offset + params;
d14334181   Pavel Shilovsky   CIFS: Move set_fi...
5563
  	if (set_allocation) {
50c2f7538   Steve French   [CIFS] whitespace...
5564
5565
5566
5567
5568
5569
5570
  		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
5571
5572
  	    if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
  		    pSMB->InformationLevel =
50c2f7538   Steve French   [CIFS] whitespace...
5573
  				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5574
5575
  	    else
  		    pSMB->InformationLevel =
50c2f7538   Steve French   [CIFS] whitespace...
5576
  				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
  	}
  
  	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 ...
5593
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5594
5595
5596
5597
  	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...
5598
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5599
5600
  		cifs_dbg(FYI, "SetPathInfo (file size) returned %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
  
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto SetEOFRetry;
  
  	return rc;
  }
  
  int
d14334181   Pavel Shilovsky   CIFS: Move set_fi...
5611
5612
  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
5613
5614
  {
  	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5615
5616
  	struct file_end_of_file_info *parm_data;
  	int rc = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5617
  	__u16 params, param_offset, offset, byte_count, count;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5618
5619
5620
  	cifs_dbg(FYI, "SetFileSize (via SetFileInfo) %lld
  ",
  		 (long long)size);
cd63499cb   Steve French   [PATCH] cifs: Han...
5621
  	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5622
5623
  	if (rc)
  		return rc;
d14334181   Pavel Shilovsky   CIFS: Move set_fi...
5624
5625
  	pSMB->hdr.Pid = cpu_to_le16((__u16)cfile->pid);
  	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(cfile->pid >> 16));
50c2f7538   Steve French   [CIFS] whitespace...
5626

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5627
5628
5629
5630
5631
5632
5633
5634
  	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
5635
5636
  	count = sizeof(struct file_end_of_file_info);
  	pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5e   Steve French   [CIFS] cleanup ol...
5637
5638
  	/* BB find exact max SMB PDU from sess structure BB */
  	pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
  	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...
5649
5650
  		(struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
  				+ offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5651
5652
  	pSMB->DataOffset = cpu_to_le16(offset);
  	parm_data->FileSize = cpu_to_le64(size);
d14334181   Pavel Shilovsky   CIFS: Move set_fi...
5653
5654
  	pSMB->Fid = cfile->fid.netfid;
  	if (set_allocation) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5655
5656
5657
5658
5659
5660
  		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...
5661
  	} else /* Set File Size */  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5662
5663
  	    if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
  		    pSMB->InformationLevel =
50c2f7538   Steve French   [CIFS] whitespace...
5664
  				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5665
5666
  	    else
  		    pSMB->InformationLevel =
50c2f7538   Steve French   [CIFS] whitespace...
5667
  				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5668
5669
  	}
  	pSMB->Reserved4 = 0;
be8e3b004   Steve French   consistently use ...
5670
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5671
  	pSMB->ByteCount = cpu_to_le16(byte_count);
792af7b05   Pavel Shilovsky   CIFS: Separate pr...
5672
  	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5673
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5674
5675
5676
  		cifs_dbg(FYI, "Send error in SetFileInfo (SetFileSize) = %d
  ",
  			 rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5677
  	}
50c2f7538   Steve French   [CIFS] whitespace...
5678
  	/* Note: On -EAGAIN error only caller can retry on handle based calls
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5679
5680
5681
5682
  		since file handle passed in no longer valid */
  
  	return rc;
  }
50c2f7538   Steve French   [CIFS] whitespace...
5683
  /* Some legacy servers such as NT4 require that the file times be set on
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5684
5685
5686
5687
5688
5689
     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/...
5690
  CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
2dd2dfa06   Jeff Layton   Rename CIFSSMBSet...
5691
  		    const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5692
5693
  {
  	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5694
5695
  	char *data_offset;
  	int rc = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5696
  	__u16 params, param_offset, offset, byte_count, count;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5697
5698
  	cifs_dbg(FYI, "Set Times (via SetFileInfo)
  ");
cd63499cb   Steve French   [PATCH] cifs: Han...
5699
  	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5700
5701
  	if (rc)
  		return rc;
2dd2dfa06   Jeff Layton   Rename CIFSSMBSet...
5702
5703
  	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...
5704

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5705
5706
5707
5708
5709
5710
5711
5712
  	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...
5713
5714
  	data_offset = (char *)pSMB +
  			offsetof(struct smb_hdr, Protocol) + offset;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5715

26f57364d   Steve French   [CIFS] formatting...
5716
  	count = sizeof(FILE_BASIC_INFO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5717
  	pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5e   Steve French   [CIFS] cleanup ol...
5718
5719
  	/* BB find max SMB PDU from sess */
  	pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
  	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 ...
5736
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5737
  	pSMB->ByteCount = cpu_to_le16(byte_count);
50c2f7538   Steve French   [CIFS] whitespace...
5738
  	memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
792af7b05   Pavel Shilovsky   CIFS: Separate pr...
5739
  	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
ad7a2926b   Steve French   [CIFS] reduce che...
5740
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5741
5742
5743
  		cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d
  ",
  			 rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5744

50c2f7538   Steve French   [CIFS] whitespace...
5745
  	/* Note: On -EAGAIN error only caller can retry on handle based calls
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5746
5747
5748
5749
  		since file handle passed in no longer valid */
  
  	return rc;
  }
6d22f0989   Jeff Layton   cifs: add functio...
5750
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
5751
  CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
6d22f0989   Jeff Layton   cifs: add functio...
5752
5753
5754
5755
5756
5757
  			  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...
5758
5759
  	cifs_dbg(FYI, "Set File Disposition (via SetFileInfo)
  ");
6d22f0989   Jeff Layton   cifs: add functio...
5760
5761
5762
5763
5764
5765
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
  	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 ...
5796
  	inc_rfc1001_len(pSMB, byte_count);
6d22f0989   Jeff Layton   cifs: add functio...
5797
5798
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  	*data_offset = delete_file ? 1 : 0;
792af7b05   Pavel Shilovsky   CIFS: Separate pr...
5799
  	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
6d22f0989   Jeff Layton   cifs: add functio...
5800
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5801
5802
  		cifs_dbg(FYI, "Send error in SetFileDisposition = %d
  ", rc);
6d22f0989   Jeff Layton   cifs: add functio...
5803
5804
5805
  
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5806
5807
  
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
5808
  CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
6fc000e51   Jeff Layton   change CIFSSMBSet...
5809
5810
  		   const char *fileName, const FILE_BASIC_INFO *data,
  		   const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5811
5812
5813
5814
5815
5816
5817
5818
  {
  	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...
5819
5820
  	cifs_dbg(FYI, "In SetTimes
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5821
5822
5823
5824
5825
5826
5827
5828
5829
  
  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...
5830
5831
  		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
  				       PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5832
5833
  		name_len++;	/* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
5834
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5835
5836
5837
5838
5839
5840
  		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...
5841
  	count = sizeof(FILE_BASIC_INFO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5842
  	pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5e   Steve French   [CIFS] cleanup ol...
5843
5844
  	/* BB find max SMB PDU from sess structure BB */
  	pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5845
5846
5847
5848
5849
5850
  	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...
5851
  				InformationLevel) - 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
  	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 ...
5870
  	inc_rfc1001_len(pSMB, byte_count);
26f57364d   Steve French   [CIFS] formatting...
5871
  	memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5872
5873
5874
  	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...
5875
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5876
5877
  		cifs_dbg(FYI, "SetPathInfo (times) returned %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
  
  	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/...
5893
  CIFSSMBSetAttrLegacy(unsigned int xid, struct cifs_tcon *tcon, char *fileName,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5894
5895
5896
5897
5898
5899
5900
  		__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...
5901
5902
  	cifs_dbg(FYI, "In SetAttrLegacy
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5903
5904
5905
5906
5907
5908
5909
5910
5911
  
  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...
5912
5913
  			ConvertToUTF16((__le16 *) pSMB->fileName, fileName,
  				       PATH_MAX, nls_codepage);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5914
5915
  		name_len++;     /* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
5916
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5917
5918
5919
5920
5921
5922
  		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 ...
5923
  	inc_rfc1001_len(pSMB, name_len + 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5924
5925
5926
  	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...
5927
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5928
5929
  		cifs_dbg(FYI, "Error in LegacySetAttr = %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5930
5931
5932
5933
5934
5935
5936
5937
5938
  
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto SetAttrLgcyRetry;
  
  	return rc;
  }
  #endif /* temporarily unneeded SetAttr legacy function */
654cf14ac   Jeff Layton   cifs: make a sepa...
5939
5940
5941
5942
  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...
5943
  	u64 uid = NO_CHANGE_64, gid = NO_CHANGE_64;
654cf14ac   Jeff Layton   cifs: make a sepa...
5944
  	u64 mode = args->mode;
49418b2c2   Eric W. Biederman   cifs: Modify stru...
5945
5946
5947
5948
  	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...
5949
5950
5951
5952
  	/*
  	 * 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...
5953
  	 * accidentally as happened on one Samba server beta by putting
654cf14ac   Jeff Layton   cifs: make a sepa...
5954
5955
5956
5957
5958
5959
5960
  	 * 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...
5961
5962
  	data_offset->Uid = cpu_to_le64(uid);
  	data_offset->Gid = cpu_to_le64(gid);
654cf14ac   Jeff Layton   cifs: make a sepa...
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
  	/* 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
5983
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
5984
  CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
3bbeeb3c9   Jeff Layton   cifs: add and use...
5985
5986
5987
5988
  		       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...
5989
  	char *data_offset;
3bbeeb3c9   Jeff Layton   cifs: add and use...
5990
5991
  	int rc = 0;
  	u16 params, param_offset, offset, byte_count, count;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
5992
5993
  	cifs_dbg(FYI, "Set Unix Info (via SetFileInfo)
  ");
3bbeeb3c9   Jeff Layton   cifs: add and use...
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
  	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...
6010
6011
  	data_offset = (char *)pSMB +
  			offsetof(struct smb_hdr, Protocol) + offset;
3bbeeb3c9   Jeff Layton   cifs: add and use...
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
  	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 ...
6030
  	inc_rfc1001_len(pSMB, byte_count);
3bbeeb3c9   Jeff Layton   cifs: add and use...
6031
  	pSMB->ByteCount = cpu_to_le16(byte_count);
b2a3ad9ca   Jeff Layton   cifs: silence com...
6032
  	cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
3bbeeb3c9   Jeff Layton   cifs: add and use...
6033

792af7b05   Pavel Shilovsky   CIFS: Separate pr...
6034
  	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
3bbeeb3c9   Jeff Layton   cifs: add and use...
6035
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
6036
6037
6038
  		cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d
  ",
  			 rc);
3bbeeb3c9   Jeff Layton   cifs: add and use...
6039
6040
6041
6042
6043
6044
6045
6046
  
  	/* 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/...
6047
  CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
6048
  		       const char *file_name,
01ea95e3b   Jeff Layton   cifs: rename CIFS...
6049
6050
  		       const struct cifs_unix_set_info_args *args,
  		       const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6051
6052
6053
6054
6055
6056
6057
6058
  {
  	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...
6059
6060
  	cifs_dbg(FYI, "In SetUID/GID/Mode
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6061
6062
6063
6064
6065
6066
6067
6068
  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...
6069
  		    cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
acbbb76a2   Steve French   CIFS: Rename *UCS...
6070
  				       PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6071
6072
  		name_len++;	/* trailing null */
  		name_len *= 2;
3e87d8039   Steve French   [CIFS] Add suppor...
6073
  	} else {	/* BB improve the check for buffer overruns BB */
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
6074
  		name_len = strnlen(file_name, PATH_MAX);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6075
  		name_len++;	/* trailing null */
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
6076
  		strncpy(pSMB->FileName, file_name, name_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6077
6078
6079
  	}
  
  	params = 6 + name_len;
26f57364d   Steve French   [CIFS] formatting...
6080
  	count = sizeof(FILE_UNIX_BASIC_INFO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6081
  	pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5e   Steve French   [CIFS] cleanup ol...
6082
6083
  	/* BB find max SMB PDU from sess structure BB */
  	pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6084
6085
6086
6087
6088
6089
  	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...
6090
  				InformationLevel) - 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
  	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 ...
6108
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6109

654cf14ac   Jeff Layton   cifs: make a sepa...
6110
  	cifs_fill_unix_set_info(data_offset, args);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6111
6112
6113
6114
  
  	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...
6115
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
6116
6117
  		cifs_dbg(FYI, "SetPathInfo (perms) returned %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6118

0d817bc0d   Steve French   [CIFS] Remove red...
6119
  	cifs_buf_release(pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6120
6121
6122
6123
  	if (rc == -EAGAIN)
  		goto setPermsRetry;
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6124
  #ifdef CONFIG_CIFS_XATTR
31c0519f7   Jeff Layton   cifs: merge CIFSS...
6125
6126
6127
6128
6129
6130
6131
6132
6133
  /*
   * 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
6134
  ssize_t
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
6135
  CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
31c0519f7   Jeff Layton   cifs: merge CIFSS...
6136
6137
6138
  		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
6139
6140
6141
6142
6143
6144
  {
  		/* 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...
6145
  	int list_len;
f0d3868b7   Jeff Layton   cifs: clean up in...
6146
  	struct fealist *ea_response_data;
50c2f7538   Steve French   [CIFS] whitespace...
6147
6148
  	struct fea *temp_fea;
  	char *temp_ptr;
0cd126b50   Jeff Layton   cifs: verify leng...
6149
  	char *end_of_smb;
f0d3868b7   Jeff Layton   cifs: clean up in...
6150
  	__u16 params, byte_count, data_offset;
5980fc966   Jeff Layton   cifs: fix compile...
6151
  	unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6152

f96637be0   Joe Perches   [CIFS] cifs: Rena...
6153
6154
  	cifs_dbg(FYI, "In Query All EAs path %s
  ", searchName);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6155
6156
6157
6158
6159
6160
6161
  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...
6162
  		list_len =
acbbb76a2   Steve French   CIFS: Rename *UCS...
6163
6164
  		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
  				       PATH_MAX, nls_codepage, remap);
6e462b9f2   Jeff Layton   cifs: rename name...
6165
6166
  		list_len++;	/* trailing null */
  		list_len *= 2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6167
  	} else {	/* BB improve the check for buffer overruns BB */
6e462b9f2   Jeff Layton   cifs: rename name...
6168
6169
6170
  		list_len = strnlen(searchName, PATH_MAX);
  		list_len++;	/* trailing null */
  		strncpy(pSMB->FileName, searchName, list_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6171
  	}
6e462b9f2   Jeff Layton   cifs: rename name...
6172
  	params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6173
6174
  	pSMB->TotalDataCount = 0;
  	pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5e   Steve French   [CIFS] cleanup ol...
6175
  	/* BB find exact max SMB PDU from sess structure BB */
e529614ad   Jeff Layton   cifs: increase ma...
6176
  	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6177
6178
6179
6180
6181
6182
  	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...
6183
  	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
  	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 ...
6194
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6195
6196
6197
6198
6199
  	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...
6200
6201
  		cifs_dbg(FYI, "Send error in QueryAllEAs = %d
  ", rc);
f0d3868b7   Jeff Layton   cifs: clean up in...
6202
6203
  		goto QAllEAsOut;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6204

f0d3868b7   Jeff Layton   cifs: clean up in...
6205
6206
6207
6208
6209
6210
  
  	/* 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...
6211
  	if (rc || get_bcc(&pSMBr->hdr) < 4) {
f0d3868b7   Jeff Layton   cifs: clean up in...
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
  		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...
6227
  	list_len = le32_to_cpu(ea_response_data->list_len);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
6228
6229
  	cifs_dbg(FYI, "ea length %d
  ", list_len);
6e462b9f2   Jeff Layton   cifs: rename name...
6230
  	if (list_len <= 8) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
6231
6232
  		cifs_dbg(FYI, "empty EA list returned from server
  ");
60977fcc8   Steve French   Return correct er...
6233
6234
6235
  		/* didn't find the named attribute */
  		if (ea_name)
  			rc = -ENODATA;
f0d3868b7   Jeff Layton   cifs: clean up in...
6236
6237
  		goto QAllEAsOut;
  	}
0cd126b50   Jeff Layton   cifs: verify leng...
6238
  	/* make sure list_len doesn't go past end of SMB */
690c522fa   Jeff Layton   cifs: use get/put...
6239
  	end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
0cd126b50   Jeff Layton   cifs: verify leng...
6240
  	if ((char *)ea_response_data + list_len > end_of_smb) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
6241
6242
  		cifs_dbg(FYI, "EA list appears to go beyond SMB
  ");
0cd126b50   Jeff Layton   cifs: verify leng...
6243
6244
6245
  		rc = -EIO;
  		goto QAllEAsOut;
  	}
f0d3868b7   Jeff Layton   cifs: clean up in...
6246
  	/* account for ea list len */
6e462b9f2   Jeff Layton   cifs: rename name...
6247
  	list_len -= 4;
f0d3868b7   Jeff Layton   cifs: clean up in...
6248
6249
  	temp_fea = ea_response_data->list;
  	temp_ptr = (char *)temp_fea;
6e462b9f2   Jeff Layton   cifs: rename name...
6250
  	while (list_len > 0) {
122ca0076   Steve French   [CIFS] Use unsign...
6251
  		unsigned int name_len;
f0d3868b7   Jeff Layton   cifs: clean up in...
6252
  		__u16 value_len;
0cd126b50   Jeff Layton   cifs: verify leng...
6253

6e462b9f2   Jeff Layton   cifs: rename name...
6254
  		list_len -= 4;
f0d3868b7   Jeff Layton   cifs: clean up in...
6255
  		temp_ptr += 4;
0cd126b50   Jeff Layton   cifs: verify leng...
6256
6257
  		/* make sure we can read name_len and value_len */
  		if (list_len < 0) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
6258
6259
  			cifs_dbg(FYI, "EA entry goes beyond length of list
  ");
0cd126b50   Jeff Layton   cifs: verify leng...
6260
6261
6262
6263
6264
6265
6266
6267
  			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...
6268
6269
  			cifs_dbg(FYI, "EA entry goes beyond length of list
  ");
0cd126b50   Jeff Layton   cifs: verify leng...
6270
6271
6272
  			rc = -EIO;
  			goto QAllEAsOut;
  		}
31c0519f7   Jeff Layton   cifs: merge CIFSS...
6273
  		if (ea_name) {
91d065c47   Jeff Layton   cifs: fix name pa...
6274
  			if (ea_name_len == name_len &&
ac423446d   Jeff Layton   cifs: switch CIFS...
6275
  			    memcmp(ea_name, temp_ptr, name_len) == 0) {
31c0519f7   Jeff Layton   cifs: merge CIFSS...
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
  				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...
6287
  		} else {
31c0519f7   Jeff Layton   cifs: merge CIFSS...
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
  			/* 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
6305
  		}
0cd126b50   Jeff Layton   cifs: verify leng...
6306
  		temp_ptr += name_len + 1 + value_len;
f0d3868b7   Jeff Layton   cifs: clean up in...
6307
  		temp_fea = (struct fea *)temp_ptr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6308
  	}
f0d3868b7   Jeff Layton   cifs: clean up in...
6309

31c0519f7   Jeff Layton   cifs: merge CIFSS...
6310
6311
6312
  	/* didn't find the named attribute */
  	if (ea_name)
  		rc = -ENODATA;
f0d3868b7   Jeff Layton   cifs: clean up in...
6313
  QAllEAsOut:
0d817bc0d   Steve French   [CIFS] Remove red...
6314
  	cifs_buf_release(pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6315
6316
6317
6318
6319
  	if (rc == -EAGAIN)
  		goto QAllEAsRetry;
  
  	return (ssize_t)rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6320
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
6321
6322
  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...
6323
6324
  	     const __u16 ea_value_len, const struct nls_table *nls_codepage,
  	     int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6325
6326
6327
6328
6329
6330
6331
6332
  {
  	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...
6333
6334
  	cifs_dbg(FYI, "In SetEA
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6335
6336
6337
6338
6339
6340
6341
6342
  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...
6343
6344
  		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
  				       PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6345
6346
  		name_len++;	/* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
6347
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
  		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...
6358
  	if (ea_name == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6359
6360
  		name_len = 0;
  	else
50c2f7538   Steve French   [CIFS] whitespace...
6361
  		name_len = strnlen(ea_name, 255);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6362

dae5dbdbd   Steve French   [CIFS] fix SetEA ...
6363
  	count = sizeof(*parm_data) + ea_value_len + name_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6364
  	pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5e   Steve French   [CIFS] cleanup ol...
6365
6366
  	/* BB find max SMB PDU from sess */
  	pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6367
6368
6369
6370
6371
6372
  	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...
6373
  				InformationLevel) - 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
  	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
6391
  	parm_data->list[0].name_len = (__u8)name_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6392
  	/* EA names are always ASCII */
790fe579f   Steve French   [CIFS] more white...
6393
  	if (ea_name)
50c2f7538   Steve French   [CIFS] whitespace...
6394
  		strncpy(parm_data->list[0].name, ea_name, name_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6395
6396
6397
6398
  	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...
6399
6400
  	/*BB add length check to see if it would fit in
  	     negotiated SMB buffer size BB */
790fe579f   Steve French   [CIFS] more white...
6401
6402
  	/* if (ea_value_len > buffer_size - 512 (enough for header)) */
  	if (ea_value_len)
50c2f7538   Steve French   [CIFS] whitespace...
6403
6404
  		memcpy(parm_data->list[0].name+name_len+1,
  		       ea_value, ea_value_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6405
6406
6407
6408
6409
  
  	pSMB->TotalDataCount = pSMB->DataCount;
  	pSMB->ParameterCount = cpu_to_le16(params);
  	pSMB->TotalParameterCount = pSMB->ParameterCount;
  	pSMB->Reserved4 = 0;
be8e3b004   Steve French   consistently use ...
6410
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6411
6412
6413
  	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...
6414
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
6415
6416
  		cifs_dbg(FYI, "SetPathInfo (EA) returned %d
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6417
6418
6419
6420
6421
6422
6423
6424
  
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto SetEARetry;
  
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6425
  #endif
0eff0e267   Steve French   Remove unused CIF...
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
  
  #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/...
6448
  int CIFSSMBNotify(const unsigned int xid, struct cifs_tcon *tcon,
0eff0e267   Steve French   Remove unused CIF...
6449
6450
6451
6452
6453
6454
6455
6456
6457
  		  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...
6458
6459
  	cifs_dbg(FYI, "In CIFSSMBNotify for file handle %d
  ", (int)netfid);
0eff0e267   Steve French   Remove unused CIF...
6460
6461
6462
6463
6464
6465
6466
6467
  	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...
6468
  	pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
0eff0e267   Steve French   Remove unused CIF...
6469
6470
6471
6472
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
  	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...
6488
6489
  		cifs_dbg(FYI, "Error in Notify = %d
  ", rc);
0eff0e267   Steve French   Remove unused CIF...
6490
6491
6492
6493
6494
6495
6496
6497
6498
6499
6500
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
  	} 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 */