Blame view

fs/cifs/cifssmb.c 190 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 */
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
87
88
  /* Forward declarations */
  static void cifs_readv_complete(struct work_struct *work);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
90
  /* Mark as invalid, all open files on tree connections since they
     were closed when session to server was lost */
96daf2b09   Steve French   [CIFS] Rename thr...
91
  static void mark_open_files_invalid(struct cifs_tcon *pTcon)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
93
  {
  	struct cifsFileInfo *open_file = NULL;
790fe579f   Steve French   [CIFS] more white...
94
95
  	struct list_head *tmp;
  	struct list_head *tmp1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
97
  
  /* list all files open on tree connection and mark them invalid */
4477288a1   Jeff Layton   cifs: convert Glo...
98
  	spin_lock(&cifs_file_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99
  	list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
790fe579f   Steve French   [CIFS] more white...
100
  		open_file = list_entry(tmp, struct cifsFileInfo, tlist);
ad8b15f0f   Steve French   [CIFS] list entry...
101
  		open_file->invalidHandle = true;
3bc303c25   Jeff Layton   cifs: convert opl...
102
  		open_file->oplock_break_cancelled = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
  	}
4477288a1   Jeff Layton   cifs: convert Glo...
104
  	spin_unlock(&cifs_file_list_lock);
09d1db5c6   Steve French   [PATCH] cifs: imp...
105
106
  	/* BB Add call to invalidate_inodes(sb) for all superblocks mounted
  	   to this tcon */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
  }
9162ab200   Jeff Layton   cifs: consolidate...
108
109
  /* reconnect the socket, tcon, and smb session if needed */
  static int
96daf2b09   Steve French   [CIFS] Rename thr...
110
  cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
9162ab200   Jeff Layton   cifs: consolidate...
111
  {
c4a5534a1   Jeff Layton   cifs: remove unne...
112
  	int rc;
96daf2b09   Steve French   [CIFS] Rename thr...
113
  	struct cifs_ses *ses;
9162ab200   Jeff Layton   cifs: consolidate...
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
  	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) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
136
137
  			cFYI(1, "can not send cmd %d while umounting",
  				smb_command);
9162ab200   Jeff Layton   cifs: consolidate...
138
139
140
  			return -ENODEV;
  		}
  	}
9162ab200   Jeff Layton   cifs: consolidate...
141
142
143
144
145
146
  	/*
  	 * 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...
147
  			(server->tcpStatus != CifsNeedReconnect), 10 * HZ);
9162ab200   Jeff Layton   cifs: consolidate...
148

fd88ce931   Steve French   [CIFS] cifs: clar...
149
  		/* are we still trying to reconnect? */
9162ab200   Jeff Layton   cifs: consolidate...
150
151
152
153
154
155
156
157
  		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...
158
  		if (!tcon->retry) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
159
  			cFYI(1, "gave up waiting on reconnect in smb_init");
9162ab200   Jeff Layton   cifs: consolidate...
160
161
162
163
164
165
166
167
168
169
170
171
172
  			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->...
173
  	mutex_lock(&ses->session_mutex);
198b56827   Jeff Layton   cifs: break negot...
174
175
  	rc = cifs_negotiate_protocol(0, ses);
  	if (rc == 0 && ses->need_reconnect)
9162ab200   Jeff Layton   cifs: consolidate...
176
177
178
179
  		rc = cifs_setup_session(0, ses, nls_codepage);
  
  	/* do we need to reconnect tcon? */
  	if (rc || !tcon->need_reconnect) {
d7b619cf5   Steve French   [CIFS] pSesInfo->...
180
  		mutex_unlock(&ses->session_mutex);
9162ab200   Jeff Layton   cifs: consolidate...
181
182
183
184
185
  		goto out;
  	}
  
  	mark_open_files_invalid(tcon);
  	rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
d7b619cf5   Steve French   [CIFS] pSesInfo->...
186
  	mutex_unlock(&ses->session_mutex);
b6b38f704   Joe Perches   [CIFS] Neaten cER...
187
  	cFYI(1, "reconnect tcon rc = %d", rc);
9162ab200   Jeff Layton   cifs: consolidate...
188
189
190
191
192
193
194
195
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
  
  	if (rc)
  		goto out;
  
  	/*
  	 * FIXME: check if wsize needs updated due to negotiated smb buffer
  	 * 	  size shrinking
  	 */
  	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;
12b3b8ffb   Steve French   [CIFS] Cleanup NT...
263
264
265
  	buffer->Mid = GetNextMid(ses->server);
  	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

be8e3b004   Steve French   consistently use ...
355
356
357
358
359
360
  static inline void inc_rfc1001_len(void *pSMB, int count)
  {
  	struct smb_hdr *hdr = (struct smb_hdr *)pSMB;
  
  	be32_add_cpu(&hdr->smb_buf_length, count);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
361
  int
96daf2b09   Steve French   [CIFS] Rename thr...
362
  CIFSSMBNegotiate(unsigned int xid, struct cifs_ses *ses)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
363
364
365
366
367
  {
  	NEGOTIATE_REQ *pSMB;
  	NEGOTIATE_RSP *pSMBr;
  	int rc = 0;
  	int bytes_returned;
3979877e5   Steve French   [CIFS] Support fo...
368
  	int i;
50c2f7538   Steve French   [CIFS] whitespace...
369
  	struct TCP_Server_Info *server;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
  	u16 count;
750d1151a   Steve French   [CIFS] Fix alloca...
371
  	unsigned int secFlags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
372

790fe579f   Steve French   [CIFS] more white...
373
  	if (ses->server)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
374
375
376
377
378
379
380
381
382
  		server = ses->server;
  	else {
  		rc = -EIO;
  		return rc;
  	}
  	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...
383
384
  
  	/* if any of auth flags (ie not sign or seal) are overriden use them */
790fe579f   Steve French   [CIFS] more white...
385
  	if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
762e5ab77   Steve French   [CIFS] Fix sign m...
386
  		secFlags = ses->overrideSecFlg;  /* BB FIXME fix sign flags? */
750d1151a   Steve French   [CIFS] Fix alloca...
387
  	else /* if override flags set only sign/seal OR them with global auth */
04912d6a2   Jeff Layton   cifs: rename "ext...
388
  		secFlags = global_secflags | ses->overrideSecFlg;
750d1151a   Steve French   [CIFS] Fix alloca...
389

b6b38f704   Joe Perches   [CIFS] Neaten cER...
390
  	cFYI(1, "secFlags 0x%x", secFlags);
f40c56285   Steve French   [CIFS] Fix authen...
391

1982c344f   Steve French   [CIFS] Ensure tha...
392
  	pSMB->hdr.Mid = GetNextMid(server);
100c1ddc9   Yehuda Sadeh Weinraub   [CIFS] Missing fl...
393
  	pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
a013689dd   Steve French   [CIFS] Fix cifsd ...
394

100c1ddc9   Yehuda Sadeh Weinraub   [CIFS] Missing fl...
395
  	if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
254e55ed0   Steve French   CIFS] Support for...
396
  		pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
a013689dd   Steve French   [CIFS] Fix cifsd ...
397
  	else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
398
  		cFYI(1, "Kerberos only mechanism, enable extended security");
a013689dd   Steve French   [CIFS] Fix cifsd ...
399
  		pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
b4d6fcf13   Jeff Layton   cifs: move "ntlms...
400
  	} else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
ac6839246   Steve French   [CIFS] Allow raw ...
401
402
  		pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
  	else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
403
  		cFYI(1, "NTLMSSP only mechanism, enable extended security");
ac6839246   Steve French   [CIFS] Allow raw ...
404
405
  		pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
  	}
50c2f7538   Steve French   [CIFS] whitespace...
406

3979877e5   Steve French   [CIFS] Support fo...
407
  	count = 0;
50c2f7538   Steve French   [CIFS] whitespace...
408
  	for (i = 0; i < CIFS_NUM_PROT; i++) {
3979877e5   Steve French   [CIFS] Support fo...
409
410
411
412
  		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 ...
413
  	inc_rfc1001_len(pSMB, count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
414
415
416
417
  	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...
418
  	if (rc != 0)
254e55ed0   Steve French   CIFS] Support for...
419
  		goto neg_err_exit;
9bf67e516   Jeff Layton   cifs: save the di...
420
421
  	server->dialect = le16_to_cpu(pSMBr->DialectIndex);
  	cFYI(1, "Dialect: %d", server->dialect);
254e55ed0   Steve French   CIFS] Support for...
422
  	/* Check wct = 1 error case */
9bf67e516   Jeff Layton   cifs: save the di...
423
  	if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) {
254e55ed0   Steve French   CIFS] Support for...
424
  		/* core returns wct = 1, but we do not ask for core - otherwise
50c2f7538   Steve French   [CIFS] whitespace...
425
  		small wct just comes when dialect index is -1 indicating we
254e55ed0   Steve French   CIFS] Support for...
426
427
428
  		could not negotiate a common dialect */
  		rc = -EOPNOTSUPP;
  		goto neg_err_exit;
50c2f7538   Steve French   [CIFS] whitespace...
429
  #ifdef CONFIG_CIFS_WEAK_PW_HASH
790fe579f   Steve French   [CIFS] more white...
430
  	} else if ((pSMBr->hdr.WordCount == 13)
9bf67e516   Jeff Layton   cifs: save the di...
431
432
  			&& ((server->dialect == LANMAN_PROT)
  				|| (server->dialect == LANMAN2_PROT))) {
b815f1e55   Steve French   [CIFS] Allow for ...
433
  		__s16 tmp;
50c2f7538   Steve French   [CIFS] whitespace...
434
  		struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
254e55ed0   Steve French   CIFS] Support for...
435

790fe579f   Steve French   [CIFS] more white...
436
  		if ((secFlags & CIFSSEC_MAY_LANMAN) ||
750d1151a   Steve French   [CIFS] Fix alloca...
437
  			(secFlags & CIFSSEC_MAY_PLNTXT))
254e55ed0   Steve French   CIFS] Support for...
438
439
  			server->secType = LANMAN;
  		else {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
440
441
  			cERROR(1, "mount failed weak security disabled"
  				   " in /proc/fs/cifs/SecurityFlags");
3979877e5   Steve French   [CIFS] Support fo...
442
443
  			rc = -EOPNOTSUPP;
  			goto neg_err_exit;
50c2f7538   Steve French   [CIFS] whitespace...
444
  		}
96daf2b09   Steve French   [CIFS] Rename thr...
445
  		server->sec_mode = (__u8)le16_to_cpu(rsp->SecurityMode);
254e55ed0   Steve French   CIFS] Support for...
446
  		server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
c974befa4   Jeff Layton   cifs: untangle se...
447
  		server->maxBuf = le16_to_cpu(rsp->MaxBufSize);
eca6acf91   Steve French   [CIFS] Fix multiu...
448
  		server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
254e55ed0   Steve French   CIFS] Support for...
449
450
  		/* even though we do not use raw we might as well set this
  		accurately, in case we ever find a need for it */
790fe579f   Steve French   [CIFS] more white...
451
  		if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
eca6acf91   Steve French   [CIFS] Fix multiu...
452
  			server->max_rw = 0xFF00;
254e55ed0   Steve French   CIFS] Support for...
453
454
  			server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
  		} else {
eca6acf91   Steve French   [CIFS] Fix multiu...
455
  			server->max_rw = 0;/* do not need to use raw anyway */
254e55ed0   Steve French   CIFS] Support for...
456
457
  			server->capabilities = CAP_MPX_MODE;
  		}
b815f1e55   Steve French   [CIFS] Allow for ...
458
  		tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
1a70d6529   Steve French   [CIFS] Fix compil...
459
  		if (tmp == -1) {
25ee4a98c   Steve French   [CIFS] Handle leg...
460
461
  			/* OS/2 often does not set timezone therefore
  			 * we must use server time to calc time zone.
b815f1e55   Steve French   [CIFS] Allow for ...
462
463
464
465
  			 * 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.
25ee4a98c   Steve French   [CIFS] Handle leg...
466
  			 */
b815f1e55   Steve French   [CIFS] Allow for ...
467
  			int val, seconds, remain, result;
25ee4a98c   Steve French   [CIFS] Handle leg...
468
469
  			struct timespec ts, utc;
  			utc = CURRENT_TIME;
c4a2c08db   Jeff Layton   cifs: make cnvrtD...
470
471
  			ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
  					    rsp->SrvTime.Time, 0);
b6b38f704   Joe Perches   [CIFS] Neaten cER...
472
  			cFYI(1, "SrvTime %d sec since 1970 (utc: %d) diff: %d",
50c2f7538   Steve French   [CIFS] whitespace...
473
  				(int)ts.tv_sec, (int)utc.tv_sec,
b6b38f704   Joe Perches   [CIFS] Neaten cER...
474
  				(int)(utc.tv_sec - ts.tv_sec));
b815f1e55   Steve French   [CIFS] Allow for ...
475
  			val = (int)(utc.tv_sec - ts.tv_sec);
8594c15ad   Andre Haupt   [CIFS][KJ] use ab...
476
  			seconds = abs(val);
947a50679   Steve French   [CIFS] Fix typo
477
  			result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
b815f1e55   Steve French   [CIFS] Allow for ...
478
  			remain = seconds % MIN_TZ_ADJ;
790fe579f   Steve French   [CIFS] more white...
479
  			if (remain >= (MIN_TZ_ADJ / 2))
b815f1e55   Steve French   [CIFS] Allow for ...
480
  				result += MIN_TZ_ADJ;
790fe579f   Steve French   [CIFS] more white...
481
  			if (val < 0)
ad7a2926b   Steve French   [CIFS] reduce che...
482
  				result = -result;
b815f1e55   Steve French   [CIFS] Allow for ...
483
  			server->timeAdj = result;
25ee4a98c   Steve French   [CIFS] Handle leg...
484
  		} else {
b815f1e55   Steve French   [CIFS] Allow for ...
485
486
  			server->timeAdj = (int)tmp;
  			server->timeAdj *= 60; /* also in seconds */
25ee4a98c   Steve French   [CIFS] Handle leg...
487
  		}
b6b38f704   Joe Perches   [CIFS] Neaten cER...
488
  		cFYI(1, "server->timeAdj: %d seconds", server->timeAdj);
25ee4a98c   Steve French   [CIFS] Handle leg...
489

3979877e5   Steve French   [CIFS] Support fo...
490

254e55ed0   Steve French   CIFS] Support for...
491
  		/* BB get server time for time conversions and add
50c2f7538   Steve French   [CIFS] whitespace...
492
  		code to use it and timezone since this is not UTC */
3979877e5   Steve French   [CIFS] Support fo...
493

50c2f7538   Steve French   [CIFS] whitespace...
494
  		if (rsp->EncryptionKeyLength ==
25ee4a98c   Steve French   [CIFS] Handle leg...
495
  				cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
d3ba50b17   Shirish Pargaonkar   NTLM auth and sig...
496
  			memcpy(ses->server->cryptkey, rsp->EncryptionKey,
254e55ed0   Steve French   CIFS] Support for...
497
  				CIFS_CRYPTO_KEY_SIZE);
96daf2b09   Steve French   [CIFS] Rename thr...
498
  		} else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
254e55ed0   Steve French   CIFS] Support for...
499
500
501
  			rc = -EIO; /* need cryptkey unless plain text */
  			goto neg_err_exit;
  		}
3979877e5   Steve French   [CIFS] Support fo...
502

f19159dc5   Steve French   [CIFS] Cleanup va...
503
  		cFYI(1, "LANMAN negotiated");
254e55ed0   Steve French   CIFS] Support for...
504
505
506
  		/* we will not end up setting signing flags - as no signing
  		was in LANMAN and server did not return the flags on */
  		goto signing_check;
7c7b25bc8   Steve French   [CIFS] Support fo...
507
  #else /* weak security disabled */
790fe579f   Steve French   [CIFS] more white...
508
  	} else if (pSMBr->hdr.WordCount == 13) {
f19159dc5   Steve French   [CIFS] Cleanup va...
509
510
  		cERROR(1, "mount failed, cifs module not built "
  			  "with CIFS_WEAK_PW_HASH support");
8212cf758   Dan Carpenter   cifs: trivial whi...
511
  		rc = -EOPNOTSUPP;
7c7b25bc8   Steve French   [CIFS] Support fo...
512
  #endif /* WEAK_PW_HASH */
254e55ed0   Steve French   CIFS] Support for...
513
  		goto neg_err_exit;
790fe579f   Steve French   [CIFS] more white...
514
  	} else if (pSMBr->hdr.WordCount != 17) {
254e55ed0   Steve French   CIFS] Support for...
515
516
517
518
519
  		/* unknown wct */
  		rc = -EOPNOTSUPP;
  		goto neg_err_exit;
  	}
  	/* else wct == 17 NTLM */
96daf2b09   Steve French   [CIFS] Rename thr...
520
521
  	server->sec_mode = pSMBr->SecurityMode;
  	if ((server->sec_mode & SECMODE_USER) == 0)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
522
  		cFYI(1, "share mode security");
bdc4bf6e8   Steve French   [CIFS] Support fo...
523

96daf2b09   Steve French   [CIFS] Rename thr...
524
  	if ((server->sec_mode & SECMODE_PW_ENCRYPT) == 0)
bdc4bf6e8   Steve French   [CIFS] Support fo...
525
  #ifdef CONFIG_CIFS_WEAK_PW_HASH
750d1151a   Steve French   [CIFS] Fix alloca...
526
  		if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
bdc4bf6e8   Steve French   [CIFS] Support fo...
527
  #endif /* CIFS_WEAK_PW_HASH */
b6b38f704   Joe Perches   [CIFS] Neaten cER...
528
529
  			cERROR(1, "Server requests plain text password"
  				  " but client support disabled");
9312f6754   Steve French   [CIFS] Fix mask s...
530

790fe579f   Steve French   [CIFS] more white...
531
  	if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
254e55ed0   Steve French   CIFS] Support for...
532
  		server->secType = NTLMv2;
790fe579f   Steve French   [CIFS] more white...
533
  	else if (secFlags & CIFSSEC_MAY_NTLM)
254e55ed0   Steve French   CIFS] Support for...
534
  		server->secType = NTLM;
790fe579f   Steve French   [CIFS] more white...
535
  	else if (secFlags & CIFSSEC_MAY_NTLMV2)
f40c56285   Steve French   [CIFS] Fix authen...
536
  		server->secType = NTLMv2;
a013689dd   Steve French   [CIFS] Fix cifsd ...
537
538
  	else if (secFlags & CIFSSEC_MAY_KRB5)
  		server->secType = Kerberos;
ac6839246   Steve French   [CIFS] Allow raw ...
539
  	else if (secFlags & CIFSSEC_MAY_NTLMSSP)
f46c7234e   Steve French   [CIFS] cleanup as...
540
  		server->secType = RawNTLMSSP;
a013689dd   Steve French   [CIFS] Fix cifsd ...
541
542
  	else if (secFlags & CIFSSEC_MAY_LANMAN)
  		server->secType = LANMAN;
a013689dd   Steve French   [CIFS] Fix cifsd ...
543
544
  	else {
  		rc = -EOPNOTSUPP;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
545
  		cERROR(1, "Invalid security type");
a013689dd   Steve French   [CIFS] Fix cifsd ...
546
547
548
  		goto neg_err_exit;
  	}
  	/* else ... any others ...? */
254e55ed0   Steve French   CIFS] Support for...
549
550
551
552
553
  
  	/* one byte, so no need to convert this or EncryptionKeyLen from
  	   little endian */
  	server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
  	/* probably no need to store and check maxvcs */
c974befa4   Jeff Layton   cifs: untangle se...
554
  	server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
eca6acf91   Steve French   [CIFS] Fix multiu...
555
  	server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
b6b38f704   Joe Perches   [CIFS] Neaten cER...
556
  	cFYI(DBG2, "Max buf = %d", ses->server->maxBuf);
254e55ed0   Steve French   CIFS] Support for...
557
  	server->capabilities = le32_to_cpu(pSMBr->Capabilities);
b815f1e55   Steve French   [CIFS] Allow for ...
558
559
  	server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
  	server->timeAdj *= 60;
254e55ed0   Steve French   CIFS] Support for...
560
  	if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
d3ba50b17   Shirish Pargaonkar   NTLM auth and sig...
561
  		memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
254e55ed0   Steve French   CIFS] Support for...
562
  		       CIFS_CRYPTO_KEY_SIZE);
07cc6cf9e   Steve French   Fix extended secu...
563
564
565
  	} else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
  			server->capabilities & CAP_EXTENDED_SECURITY) &&
  				(pSMBr->EncryptionKeyLength == 0)) {
254e55ed0   Steve French   CIFS] Support for...
566
  		/* decode security blob */
820a803ff   Jeff Layton   cifs: keep BCC in...
567
  		count = get_bcc(&pSMBr->hdr);
e187e44eb   Jeff Layton   [CIFS] parse serv...
568
  		if (count < 16) {
254e55ed0   Steve French   CIFS] Support for...
569
  			rc = -EIO;
e187e44eb   Jeff Layton   [CIFS] parse serv...
570
571
  			goto neg_err_exit;
  		}
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
572
  		spin_lock(&cifs_tcp_ses_lock);
e7ddee903   Jeff Layton   cifs: disable sha...
573
  		if (server->srv_count > 1) {
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
574
  			spin_unlock(&cifs_tcp_ses_lock);
e187e44eb   Jeff Layton   [CIFS] parse serv...
575
576
577
  			if (memcmp(server->server_GUID,
  				   pSMBr->u.extended_response.
  				   GUID, 16) != 0) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
578
  				cFYI(1, "server UID changed");
254e55ed0   Steve French   CIFS] Support for...
579
  				memcpy(server->server_GUID,
e187e44eb   Jeff Layton   [CIFS] parse serv...
580
581
582
  					pSMBr->u.extended_response.GUID,
  					16);
  			}
e7ddee903   Jeff Layton   cifs: disable sha...
583
  		} else {
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
584
  			spin_unlock(&cifs_tcp_ses_lock);
e187e44eb   Jeff Layton   [CIFS] parse serv...
585
586
  			memcpy(server->server_GUID,
  			       pSMBr->u.extended_response.GUID, 16);
e7ddee903   Jeff Layton   cifs: disable sha...
587
  		}
e187e44eb   Jeff Layton   [CIFS] parse serv...
588
589
590
  
  		if (count == 16) {
  			server->secType = RawNTLMSSP;
254e55ed0   Steve French   CIFS] Support for...
591
592
  		} else {
  			rc = decode_negTokenInit(pSMBr->u.extended_response.
26efa0bac   Jeff Layton   cifs: have decode...
593
594
  						 SecurityBlob, count - 16,
  						 server);
ef571cadd   Shirish Pargaonkar   [CIFS] Fix warnin...
595
  			if (rc == 1)
e545937a5   Jeff Layton   [CIFS] add OIDs f...
596
  				rc = 0;
ef571cadd   Shirish Pargaonkar   [CIFS] Fix warnin...
597
  			else
254e55ed0   Steve French   CIFS] Support for...
598
  				rc = -EINVAL;
2b149f119   Shirish Pargaonkar   cifs NTLMv2/NTLMS...
599
600
601
602
603
604
605
606
607
  			if (server->secType == Kerberos) {
  				if (!server->sec_kerberos &&
  						!server->sec_mskerberos)
  					rc = -EOPNOTSUPP;
  			} else if (server->secType == RawNTLMSSP) {
  				if (!server->sec_ntlmssp)
  					rc = -EOPNOTSUPP;
  			} else
  					rc = -EOPNOTSUPP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
608
  		}
96daf2b09   Steve French   [CIFS] Rename thr...
609
  	} else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
07cc6cf9e   Steve French   Fix extended secu...
610
611
  		rc = -EIO; /* no crypt key only if plain text pwd */
  		goto neg_err_exit;
254e55ed0   Steve French   CIFS] Support for...
612
613
  	} else
  		server->capabilities &= ~CAP_EXTENDED_SECURITY;
6344a423e   Steve French   [CIFS] fix minor ...
614
  #ifdef CONFIG_CIFS_WEAK_PW_HASH
254e55ed0   Steve French   CIFS] Support for...
615
  signing_check:
6344a423e   Steve French   [CIFS] fix minor ...
616
  #endif
762e5ab77   Steve French   [CIFS] Fix sign m...
617
618
619
  	if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
  		/* MUST_SIGN already includes the MAY_SIGN FLAG
  		   so if this is zero it means that signing is disabled */
b6b38f704   Joe Perches   [CIFS] Neaten cER...
620
  		cFYI(1, "Signing disabled");
96daf2b09   Steve French   [CIFS] Rename thr...
621
  		if (server->sec_mode & SECMODE_SIGN_REQUIRED) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
622
  			cERROR(1, "Server requires "
7111d2144   Jeff Layton   [CIFS]
623
  				   "packet signing to be enabled in "
b6b38f704   Joe Perches   [CIFS] Neaten cER...
624
  				   "/proc/fs/cifs/SecurityFlags.");
abb63d6c3   Steve French   [CIFS] Return bet...
625
626
  			rc = -EOPNOTSUPP;
  		}
96daf2b09   Steve French   [CIFS] Rename thr...
627
  		server->sec_mode &=
254e55ed0   Steve French   CIFS] Support for...
628
  			~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
762e5ab77   Steve French   [CIFS] Fix sign m...
629
630
  	} else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
  		/* signing required */
b6b38f704   Joe Perches   [CIFS] Neaten cER...
631
  		cFYI(1, "Must sign - secFlags 0x%x", secFlags);
96daf2b09   Steve French   [CIFS] Rename thr...
632
  		if ((server->sec_mode &
762e5ab77   Steve French   [CIFS] Fix sign m...
633
  			(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
634
  			cERROR(1, "signing required but server lacks support");
38c10a1dd   Jeff   [CIFS] Mount shou...
635
  			rc = -EOPNOTSUPP;
762e5ab77   Steve French   [CIFS] Fix sign m...
636
  		} else
96daf2b09   Steve French   [CIFS] Rename thr...
637
  			server->sec_mode |= SECMODE_SIGN_REQUIRED;
762e5ab77   Steve French   [CIFS] Fix sign m...
638
639
  	} else {
  		/* signing optional ie CIFSSEC_MAY_SIGN */
96daf2b09   Steve French   [CIFS] Rename thr...
640
641
  		if ((server->sec_mode & SECMODE_SIGN_REQUIRED) == 0)
  			server->sec_mode &=
254e55ed0   Steve French   CIFS] Support for...
642
  				~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
643
  	}
50c2f7538   Steve French   [CIFS] whitespace...
644
645
  
  neg_err_exit:
4a6d87f1d   Steve French   [CIFS] Add missin...
646
  	cifs_buf_release(pSMB);
254e55ed0   Steve French   CIFS] Support for...
647

b6b38f704   Joe Perches   [CIFS] Neaten cER...
648
  	cFYI(1, "negprot rc %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
649
650
651
652
  	return rc;
  }
  
  int
96daf2b09   Steve French   [CIFS] Rename thr...
653
  CIFSSMBTDis(const int xid, struct cifs_tcon *tcon)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
654
655
  {
  	struct smb_hdr *smb_buffer;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
656
  	int rc = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
657

b6b38f704   Joe Perches   [CIFS] Neaten cER...
658
  	cFYI(1, "In tree disconnect");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
659

f1987b44f   Jeff Layton   cifs: reinstate s...
660
661
662
  	/* 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
663

f1987b44f   Jeff Layton   cifs: reinstate s...
664
665
666
667
668
669
  	/*
  	 * 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...
670
  	if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
50c2f7538   Steve French   [CIFS] whitespace...
671
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
672

50c2f7538   Steve French   [CIFS] whitespace...
673
  	rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
09d1db5c6   Steve French   [PATCH] cifs: imp...
674
  			    (void **)&smb_buffer);
f1987b44f   Jeff Layton   cifs: reinstate s...
675
  	if (rc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
676
  		return rc;
133672efb   Steve French   [CIFS] Fix buffer...
677
678
  
  	rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
679
  	if (rc)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
680
  		cFYI(1, "Tree disconnect failed %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
681

50c2f7538   Steve French   [CIFS] whitespace...
682
  	/* No need to return error on this operation if tid invalidated and
f1987b44f   Jeff Layton   cifs: reinstate s...
683
  	   closed on server already e.g. due to tcp session crashing */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
684
685
686
687
688
  	if (rc == -EAGAIN)
  		rc = 0;
  
  	return rc;
  }
766fdbb57   Jeff Layton   cifs: add ability...
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
  /*
   * 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;
  
  	DeleteMidQEntry(mid);
  	atomic_dec(&server->inFlight);
  	wake_up(&server->request_q);
  }
  
  int
  CIFSSMBEcho(struct TCP_Server_Info *server)
  {
  	ECHO_REQ *smb;
  	int rc = 0;
fcc31cb6f   Jeff Layton   cifs: make cifs_s...
711
  	struct kvec iov;
766fdbb57   Jeff Layton   cifs: add ability...
712
713
714
715
716
717
718
719
  
  	cFYI(1, "In echo request");
  
  	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...
720
  	smb->hdr.Tid = 0xffff;
99d86c8f1   Jeff Layton   cifs: fix up CIFS...
721
722
  	smb->hdr.WordCount = 1;
  	put_unaligned_le16(1, &smb->EchoCount);
820a803ff   Jeff Layton   cifs: keep BCC in...
723
  	put_bcc(1, &smb->hdr);
766fdbb57   Jeff Layton   cifs: add ability...
724
  	smb->Data[0] = 'a';
be8e3b004   Steve French   consistently use ...
725
  	inc_rfc1001_len(smb, 3);
fcc31cb6f   Jeff Layton   cifs: make cifs_s...
726
727
  	iov.iov_base = smb;
  	iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
766fdbb57   Jeff Layton   cifs: add ability...
728

44d22d846   Jeff Layton   cifs: add a callb...
729
730
  	rc = cifs_call_async(server, &iov, 1, NULL, cifs_echo_callback,
  			     server, true);
766fdbb57   Jeff Layton   cifs: add ability...
731
732
733
734
735
736
737
  	if (rc)
  		cFYI(1, "Echo request failed: %d", rc);
  
  	cifs_small_buf_release(smb);
  
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
738
  int
96daf2b09   Steve French   [CIFS] Rename thr...
739
  CIFSSMBLogoff(const int xid, struct cifs_ses *ses)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
740
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
741
742
  	LOGOFF_ANDX_REQ *pSMB;
  	int rc = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
743

b6b38f704   Joe Perches   [CIFS] Neaten cER...
744
  	cFYI(1, "In SMBLogoff for session disconnect");
3b7952109   Steve French   [CIFS] Fix cifs r...
745

14fbf50d6   Jeff Layton   cifs: reinstate s...
746
747
748
749
750
751
  	/*
  	 * 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...
752
  		return -EIO;
d7b619cf5   Steve French   [CIFS] pSesInfo->...
753
  	mutex_lock(&ses->session_mutex);
3b7952109   Steve French   [CIFS] Fix cifs r...
754
755
756
  	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
757
758
  	rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
  	if (rc) {
d7b619cf5   Steve French   [CIFS] pSesInfo->...
759
  		mutex_unlock(&ses->session_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
760
761
  		return rc;
  	}
3b7952109   Steve French   [CIFS] Fix cifs r...
762
  	pSMB->hdr.Mid = GetNextMid(ses->server);
1982c344f   Steve French   [CIFS] Ensure tha...
763

96daf2b09   Steve French   [CIFS] Rename thr...
764
  	if (ses->server->sec_mode &
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
765
766
  		   (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
  			pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
767
768
769
770
  
  	pSMB->hdr.Uid = ses->Suid;
  
  	pSMB->AndXCommand = 0xFF;
133672efb   Steve French   [CIFS] Fix buffer...
771
  	rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
3b7952109   Steve French   [CIFS] Fix cifs r...
772
  session_already_dead:
d7b619cf5   Steve French   [CIFS] pSesInfo->...
773
  	mutex_unlock(&ses->session_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
774
775
  
  	/* if session dead then we do not need to do ulogoff,
50c2f7538   Steve French   [CIFS] whitespace...
776
  		since server closed smb session, no sense reporting
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
777
778
779
780
781
782
783
  		error */
  	if (rc == -EAGAIN)
  		rc = 0;
  	return rc;
  }
  
  int
96daf2b09   Steve French   [CIFS] Rename thr...
784
  CIFSPOSIXDelFile(const int xid, struct cifs_tcon *tcon, const char *fileName,
2d785a50a   Steve French   [CIFS] Add suppor...
785
786
787
788
789
790
791
792
793
  		 __u16 type, const struct nls_table *nls_codepage, int remap)
  {
  	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;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
794
  	cFYI(1, "In POSIX delete");
2d785a50a   Steve French   [CIFS] Add suppor...
795
796
797
798
799
800
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
837
838
839
840
  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 =
  		    cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
  				     PATH_MAX, nls_codepage, remap);
  		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 ...
841
  	inc_rfc1001_len(pSMB, byte_count);
2d785a50a   Steve French   [CIFS] Add suppor...
842
843
844
  	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...
845
  	if (rc)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
846
  		cFYI(1, "Posix delete returned %d", rc);
2d785a50a   Steve French   [CIFS] Add suppor...
847
848
849
850
851
852
853
854
855
856
857
  	cifs_buf_release(pSMB);
  
  	cifs_stats_inc(&tcon->num_deletes);
  
  	if (rc == -EAGAIN)
  		goto PsxDelete;
  
  	return rc;
  }
  
  int
96daf2b09   Steve French   [CIFS] Rename thr...
858
  CIFSSMBDelFile(const int xid, struct cifs_tcon *tcon, const char *fileName,
737b758c9   Steve French   [PATCH] cifs: cha...
859
  	       const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
  {
  	DELETE_FILE_REQ *pSMB = NULL;
  	DELETE_FILE_RSP *pSMBr = NULL;
  	int rc = 0;
  	int bytes_returned;
  	int name_len;
  
  DelFileRetry:
  	rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		name_len =
50c2f7538   Steve French   [CIFS] whitespace...
875
  		    cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
737b758c9   Steve French   [PATCH] cifs: cha...
876
  				     PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
877
878
  		name_len++;	/* trailing null */
  		name_len *= 2;
09d1db5c6   Steve French   [PATCH] cifs: imp...
879
  	} else {		/* BB improve check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
880
881
882
883
884
885
886
  		name_len = strnlen(fileName, PATH_MAX);
  		name_len++;	/* trailing null */
  		strncpy(pSMB->fileName, fileName, name_len);
  	}
  	pSMB->SearchAttributes =
  	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
  	pSMB->BufferFormat = 0x04;
be8e3b004   Steve French   consistently use ...
887
  	inc_rfc1001_len(pSMB, name_len + 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
888
889
890
  	pSMB->ByteCount = cpu_to_le16(name_len + 1);
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
a45443475   Steve French   CIFS: Reduce CONF...
891
  	cifs_stats_inc(&tcon->num_deletes);
ad7a2926b   Steve French   [CIFS] reduce che...
892
  	if (rc)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
893
  		cFYI(1, "Error in RMFile = %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
894
895
896
897
898
899
900
901
902
  
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto DelFileRetry;
  
  	return rc;
  }
  
  int
96daf2b09   Steve French   [CIFS] Rename thr...
903
  CIFSSMBRmDir(const int xid, struct cifs_tcon *tcon, const char *dirName,
737b758c9   Steve French   [PATCH] cifs: cha...
904
  	     const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
905
906
907
908
909
910
  {
  	DELETE_DIRECTORY_REQ *pSMB = NULL;
  	DELETE_DIRECTORY_RSP *pSMBr = NULL;
  	int rc = 0;
  	int bytes_returned;
  	int name_len;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
911
  	cFYI(1, "In CIFSSMBRmDir");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
912
913
914
915
916
917
918
  RmDirRetry:
  	rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
737b758c9   Steve French   [PATCH] cifs: cha...
919
920
  		name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
  					 PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
921
922
  		name_len++;	/* trailing null */
  		name_len *= 2;
09d1db5c6   Steve French   [PATCH] cifs: imp...
923
  	} else {		/* BB improve check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
924
925
926
927
928
929
  		name_len = strnlen(dirName, PATH_MAX);
  		name_len++;	/* trailing null */
  		strncpy(pSMB->DirName, dirName, name_len);
  	}
  
  	pSMB->BufferFormat = 0x04;
be8e3b004   Steve French   consistently use ...
930
  	inc_rfc1001_len(pSMB, name_len + 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
931
932
933
  	pSMB->ByteCount = cpu_to_le16(name_len + 1);
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
a45443475   Steve French   CIFS: Reduce CONF...
934
  	cifs_stats_inc(&tcon->num_rmdirs);
ad7a2926b   Steve French   [CIFS] reduce che...
935
  	if (rc)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
936
  		cFYI(1, "Error in RMDir = %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
937
938
939
940
941
942
943
944
  
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto RmDirRetry;
  	return rc;
  }
  
  int
96daf2b09   Steve French   [CIFS] Rename thr...
945
  CIFSSMBMkDir(const int xid, struct cifs_tcon *tcon,
737b758c9   Steve French   [PATCH] cifs: cha...
946
  	     const char *name, const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
947
948
949
950
951
952
  {
  	int rc = 0;
  	CREATE_DIRECTORY_REQ *pSMB = NULL;
  	CREATE_DIRECTORY_RSP *pSMBr = NULL;
  	int bytes_returned;
  	int name_len;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
953
  	cFYI(1, "In CIFSSMBMkDir");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
954
955
956
957
958
959
960
  MkDirRetry:
  	rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
50c2f7538   Steve French   [CIFS] whitespace...
961
  		name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
737b758c9   Steve French   [PATCH] cifs: cha...
962
  					    PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
963
964
  		name_len++;	/* trailing null */
  		name_len *= 2;
09d1db5c6   Steve French   [PATCH] cifs: imp...
965
  	} else {		/* BB improve check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
966
967
968
969
970
971
  		name_len = strnlen(name, PATH_MAX);
  		name_len++;	/* trailing null */
  		strncpy(pSMB->DirName, name, name_len);
  	}
  
  	pSMB->BufferFormat = 0x04;
be8e3b004   Steve French   consistently use ...
972
  	inc_rfc1001_len(pSMB, name_len + 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
973
974
975
  	pSMB->ByteCount = cpu_to_le16(name_len + 1);
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
a45443475   Steve French   CIFS: Reduce CONF...
976
  	cifs_stats_inc(&tcon->num_mkdirs);
ad7a2926b   Steve French   [CIFS] reduce che...
977
  	if (rc)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
978
  		cFYI(1, "Error in Mkdir = %d", rc);
a5a2b489b   Steve French   [CIFS] Make CIFS ...
979

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
980
981
982
983
984
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto MkDirRetry;
  	return rc;
  }
2dd29d313   Steve French   [CIFS] New CIFS P...
985
  int
96daf2b09   Steve French   [CIFS] Rename thr...
986
  CIFSPOSIXCreate(const int xid, struct cifs_tcon *tcon, __u32 posix_flags,
ad7a2926b   Steve French   [CIFS] reduce che...
987
  		__u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData,
50c2f7538   Steve French   [CIFS] whitespace...
988
  		__u32 *pOplock, const char *name,
2dd29d313   Steve French   [CIFS] New CIFS P...
989
990
991
992
993
994
995
  		const struct nls_table *nls_codepage, int remap)
  {
  	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...
996
  	__u16 params, param_offset, offset, byte_count, count;
ad7a2926b   Steve French   [CIFS] reduce che...
997
998
  	OPEN_PSX_REQ *pdata;
  	OPEN_PSX_RSP *psx_rsp;
2dd29d313   Steve French   [CIFS] New CIFS P...
999

b6b38f704   Joe Perches   [CIFS] Neaten cER...
1000
  	cFYI(1, "In POSIX Create");
2dd29d313   Steve French   [CIFS] New CIFS P...
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
  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 =
  		    cifsConvertToUCS((__le16 *) pSMB->FileName, name,
  				     PATH_MAX, nls_codepage, remap);
  		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...
1029
  				InformationLevel) - 4;
2dd29d313   Steve French   [CIFS] New CIFS P...
1030
  	offset = param_offset + params;
2dd29d313   Steve French   [CIFS] New CIFS P...
1031
  	pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
8f2376adf   Cyril Gorcunov   [CIFS] Fix endian...
1032
  	pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
2dd29d313   Steve French   [CIFS] New CIFS P...
1033
  	pdata->Permissions = cpu_to_le64(mode);
50c2f7538   Steve French   [CIFS] whitespace...
1034
  	pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
2dd29d313   Steve French   [CIFS] New CIFS P...
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
  	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 ...
1049
  	inc_rfc1001_len(pSMB, byte_count);
2dd29d313   Steve French   [CIFS] New CIFS P...
1050
1051
1052
1053
  	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) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1054
  		cFYI(1, "Posix create returned %d", rc);
2dd29d313   Steve French   [CIFS] New CIFS P...
1055
1056
  		goto psx_create_err;
  	}
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1057
  	cFYI(1, "copying inode info");
2dd29d313   Steve French   [CIFS] New CIFS P...
1058
  	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
820a803ff   Jeff Layton   cifs: keep BCC in...
1059
  	if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
2dd29d313   Steve French   [CIFS] New CIFS P...
1060
1061
1062
1063
1064
  		rc = -EIO;	/* bad smb */
  		goto psx_create_err;
  	}
  
  	/* copy return information to pRetData */
50c2f7538   Steve French   [CIFS] whitespace...
1065
  	psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
2dd29d313   Steve French   [CIFS] New CIFS P...
1066
  			+ le16_to_cpu(pSMBr->t2.DataOffset));
50c2f7538   Steve French   [CIFS] whitespace...
1067

2dd29d313   Steve French   [CIFS] New CIFS P...
1068
  	*pOplock = le16_to_cpu(psx_rsp->OplockFlags);
790fe579f   Steve French   [CIFS] more white...
1069
  	if (netfid)
2dd29d313   Steve French   [CIFS] New CIFS P...
1070
1071
1072
  		*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...
1073
  	if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
2dd29d313   Steve French   [CIFS] New CIFS P...
1074
1075
  		*pOplock |= CIFS_CREATE_ACTION;
  	/* check to make sure response data is there */
8f2376adf   Cyril Gorcunov   [CIFS] Fix endian...
1076
1077
  	if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
  		pRetData->Type = cpu_to_le32(-1); /* unknown */
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1078
  		cFYI(DBG2, "unknown type");
cbac3cba6   Steve French   [CIFS] New CIFS P...
1079
  	} else {
820a803ff   Jeff Layton   cifs: keep BCC in...
1080
  		if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
2dd29d313   Steve French   [CIFS] New CIFS P...
1081
  					+ sizeof(FILE_UNIX_BASIC_INFO)) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1082
  			cERROR(1, "Open response data too small");
8f2376adf   Cyril Gorcunov   [CIFS] Fix endian...
1083
  			pRetData->Type = cpu_to_le32(-1);
2dd29d313   Steve French   [CIFS] New CIFS P...
1084
1085
  			goto psx_create_err;
  		}
50c2f7538   Steve French   [CIFS] whitespace...
1086
  		memcpy((char *) pRetData,
cbac3cba6   Steve French   [CIFS] New CIFS P...
1087
  			(char *)psx_rsp + sizeof(OPEN_PSX_RSP),
26f57364d   Steve French   [CIFS] formatting...
1088
  			sizeof(FILE_UNIX_BASIC_INFO));
2dd29d313   Steve French   [CIFS] New CIFS P...
1089
  	}
2dd29d313   Steve French   [CIFS] New CIFS P...
1090
1091
1092
  
  psx_create_err:
  	cifs_buf_release(pSMB);
65bc98b00   Steve French   [CIFS] Distinguis...
1093
1094
1095
1096
  	if (posix_flags & SMB_O_DIRECTORY)
  		cifs_stats_inc(&tcon->num_posixmkdirs);
  	else
  		cifs_stats_inc(&tcon->num_posixopens);
2dd29d313   Steve French   [CIFS] New CIFS P...
1097
1098
1099
  
  	if (rc == -EAGAIN)
  		goto PsxCreat;
50c2f7538   Steve French   [CIFS] whitespace...
1100
  	return rc;
2dd29d313   Steve French   [CIFS] New CIFS P...
1101
  }
a9d02ad49   Steve French   [CIFS] Support fo...
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
  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:
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1126
  			cFYI(1, "unknown disposition %d", disposition);
a9d02ad49   Steve French   [CIFS] Support fo...
1127
1128
1129
1130
  			ofun =  SMBOPEN_OAPPEND; /* regular open */
  	}
  	return ofun;
  }
35fc37d51   Jeff Layton   add function to c...
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
  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...
1144
  int
96daf2b09   Steve French   [CIFS] Rename thr...
1145
  SMBLegacyOpen(const int xid, struct cifs_tcon *tcon,
a9d02ad49   Steve French   [CIFS] Support fo...
1146
  	    const char *fileName, const int openDisposition,
ad7a2926b   Steve French   [CIFS] reduce che...
1147
1148
  	    const int access_flags, const int create_options, __u16 *netfid,
  	    int *pOplock, FILE_ALL_INFO *pfile_info,
a9d02ad49   Steve French   [CIFS] Support fo...
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
  	    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 =
  		   cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
  				    fileName, PATH_MAX, nls_codepage, remap);
  		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...
1181
  	else if (*pOplock & REQ_BATCHOPLOCK)
a9d02ad49   Steve French   [CIFS] Support fo...
1182
  		pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
26f57364d   Steve French   [CIFS] formatting...
1183

a9d02ad49   Steve French   [CIFS] Support fo...
1184
  	pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
35fc37d51   Jeff Layton   add function to c...
1185
  	pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
a9d02ad49   Steve French   [CIFS] Support fo...
1186
1187
1188
1189
  	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...
1190
1191
  	if (create_options & CREATE_OPTION_SPECIAL)
  		pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
ad7a2926b   Steve French   [CIFS] reduce che...
1192
1193
  	else /* BB FIXME BB */
  		pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
a9d02ad49   Steve French   [CIFS] Support fo...
1194

67750fb9e   Jeff Layton   [CIFS] when not u...
1195
1196
  	if (create_options & CREATE_OPTION_READONLY)
  		pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
a9d02ad49   Steve French   [CIFS] Support fo...
1197
1198
  
  	/* BB FIXME BB */
50c2f7538   Steve French   [CIFS] whitespace...
1199
1200
  /*	pSMB->CreateOptions = cpu_to_le32(create_options &
  						 CREATE_OPTIONS_MASK); */
a9d02ad49   Steve French   [CIFS] Support fo...
1201
  	/* BB FIXME END BB */
3e87d8039   Steve French   [CIFS] Add suppor...
1202
1203
  
  	pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
70ca734a1   Steve French   [CIFS] Various mi...
1204
  	pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
a9d02ad49   Steve French   [CIFS] Support fo...
1205
  	count += name_len;
be8e3b004   Steve French   consistently use ...
1206
  	inc_rfc1001_len(pSMB, count);
a9d02ad49   Steve French   [CIFS] Support fo...
1207
1208
1209
1210
  
  	pSMB->ByteCount = cpu_to_le16(count);
  	/* long_op set to 1 to allow for oplock break timeouts */
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7749981ec   Jeff Layton   cifs: remove code...
1211
  			(struct smb_hdr *)pSMBr, &bytes_returned, 0);
a9d02ad49   Steve French   [CIFS] Support fo...
1212
1213
  	cifs_stats_inc(&tcon->num_opens);
  	if (rc) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1214
  		cFYI(1, "Error in Open = %d", rc);
a9d02ad49   Steve French   [CIFS] Support fo...
1215
1216
  	} else {
  	/* BB verify if wct == 15 */
582d21e5e   Steve French   [CIFS] cleanup ol...
1217
  /*		*pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
a9d02ad49   Steve French   [CIFS] Support fo...
1218
1219
1220
1221
1222
  
  		*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...
1223
  /*		if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
a9d02ad49   Steve French   [CIFS] Support fo...
1224
1225
  			*pOplock |= CIFS_CREATE_ACTION; */
  	/* BB FIXME END */
790fe579f   Steve French   [CIFS] more white...
1226
  		if (pfile_info) {
a9d02ad49   Steve French   [CIFS] Support fo...
1227
1228
1229
1230
  			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...
1231
  			pfile_info->Attributes =
50c2f7538   Steve French   [CIFS] whitespace...
1232
  				cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
a9d02ad49   Steve French   [CIFS] Support fo...
1233
  			/* the file_info buf is endian converted by caller */
70ca734a1   Steve French   [CIFS] Various mi...
1234
1235
1236
  			pfile_info->AllocationSize =
  				cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
  			pfile_info->EndOfFile = pfile_info->AllocationSize;
a9d02ad49   Steve French   [CIFS] Support fo...
1237
  			pfile_info->NumberOfLinks = cpu_to_le32(1);
9a8165fce   Jeff Layton   cifs: track Delet...
1238
  			pfile_info->DeletePending = 0;
a9d02ad49   Steve French   [CIFS] Support fo...
1239
1240
1241
1242
1243
1244
1245
1246
  		}
  	}
  
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto OldOpenRetry;
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1247
  int
96daf2b09   Steve French   [CIFS] Rename thr...
1248
  CIFSSMBOpen(const int xid, struct cifs_tcon *tcon,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1249
  	    const char *fileName, const int openDisposition,
ad7a2926b   Steve French   [CIFS] reduce che...
1250
1251
  	    const int access_flags, const int create_options, __u16 *netfid,
  	    int *pOplock, FILE_ALL_INFO *pfile_info,
737b758c9   Steve French   [PATCH] cifs: cha...
1252
  	    const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
  {
  	int rc = -EACCES;
  	OPEN_REQ *pSMB = NULL;
  	OPEN_RSP *pSMBr = NULL;
  	int bytes_returned;
  	int name_len;
  	__u16 count;
  
  openRetry:
  	rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, 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 =
b1a45695b   Steve French   [CIFS] fix casts ...
1272
  		    cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
737b758c9   Steve French   [PATCH] cifs: cha...
1273
  				     fileName, PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1274
1275
1276
  		name_len++;	/* trailing null */
  		name_len *= 2;
  		pSMB->NameLength = cpu_to_le16(name_len);
09d1db5c6   Steve French   [PATCH] cifs: imp...
1277
  	} else {		/* BB improve check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1278
1279
1280
1281
1282
1283
1284
1285
  		count = 0;	/* no pad */
  		name_len = strnlen(fileName, PATH_MAX);
  		name_len++;	/* trailing null */
  		pSMB->NameLength = cpu_to_le16(name_len);
  		strncpy(pSMB->fileName, fileName, name_len);
  	}
  	if (*pOplock & REQ_OPLOCK)
  		pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
26f57364d   Steve French   [CIFS] formatting...
1286
  	else if (*pOplock & REQ_BATCHOPLOCK)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1287
  		pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1288
1289
  	pSMB->DesiredAccess = cpu_to_le32(access_flags);
  	pSMB->AllocationSize = 0;
eda3c0298   Steve French   [CIFS] Add compat...
1290
1291
1292
  	/* 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...
1293
  	if (create_options & CREATE_OPTION_SPECIAL)
eda3c0298   Steve French   [CIFS] Add compat...
1294
1295
1296
  		pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
  	else
  		pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
67750fb9e   Jeff Layton   [CIFS] when not u...
1297

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1298
1299
1300
1301
1302
  	/* XP does not handle ATTR_POSIX_SEMANTICS */
  	/* but it helps speed up case sensitive checks for other
  	servers such as Samba */
  	if (tcon->ses->capabilities & CAP_UNIX)
  		pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
67750fb9e   Jeff Layton   [CIFS] when not u...
1303
1304
  	if (create_options & CREATE_OPTION_READONLY)
  		pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1305
1306
  	pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
  	pSMB->CreateDisposition = cpu_to_le32(openDisposition);
eda3c0298   Steve French   [CIFS] Add compat...
1307
  	pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
09d1db5c6   Steve French   [PATCH] cifs: imp...
1308
1309
  	/* BB Expirement with various impersonation levels and verify */
  	pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1310
1311
1312
1313
  	pSMB->SecurityFlags =
  	    SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
  
  	count += name_len;
be8e3b004   Steve French   consistently use ...
1314
  	inc_rfc1001_len(pSMB, count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1315
1316
1317
1318
  
  	pSMB->ByteCount = cpu_to_le16(count);
  	/* long_op set to 1 to allow for oplock break timeouts */
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7749981ec   Jeff Layton   cifs: remove code...
1319
  			(struct smb_hdr *)pSMBr, &bytes_returned, 0);
a45443475   Steve French   CIFS: Reduce CONF...
1320
  	cifs_stats_inc(&tcon->num_opens);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1321
  	if (rc) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1322
  		cFYI(1, "Error in Open = %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1323
  	} else {
09d1db5c6   Steve French   [PATCH] cifs: imp...
1324
  		*pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1325
1326
1327
  		*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? */
790fe579f   Steve French   [CIFS] more white...
1328
  		if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
50c2f7538   Steve French   [CIFS] whitespace...
1329
  			*pOplock |= CIFS_CREATE_ACTION;
790fe579f   Steve French   [CIFS] more white...
1330
  		if (pfile_info) {
61e748015   Steve French   [CIFS] various mi...
1331
1332
1333
1334
1335
1336
1337
  			memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
  				36 /* CreationTime to Attributes */);
  			/* the file_info buf is endian converted by caller */
  			pfile_info->AllocationSize = pSMBr->AllocationSize;
  			pfile_info->EndOfFile = pSMBr->EndOfFile;
  			pfile_info->NumberOfLinks = cpu_to_le32(1);
  			pfile_info->DeletePending = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1338
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1339
  	}
a5a2b489b   Steve French   [CIFS] Make CIFS ...
1340

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1341
1342
1343
1344
1345
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto openRetry;
  	return rc;
  }
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
  struct cifs_readdata *
  cifs_readdata_alloc(unsigned int nr_pages)
  {
  	struct cifs_readdata *rdata;
  
  	/* readdata + 1 kvec for each page */
  	rdata = kzalloc(sizeof(*rdata) +
  			sizeof(struct kvec) * nr_pages, GFP_KERNEL);
  	if (rdata != NULL) {
  		INIT_WORK(&rdata->work, cifs_readv_complete);
  		INIT_LIST_HEAD(&rdata->pages);
  	}
  	return rdata;
  }
  
  void
  cifs_readdata_free(struct cifs_readdata *rdata)
  {
  	cifsFileInfo_put(rdata->cfile);
  	kfree(rdata);
  }
  
  /*
   * Discard any remaining data in the current SMB. To do this, we borrow the
   * current bigbuf.
   */
  static int
  cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
  {
  	READ_RSP *rsp = (READ_RSP *)server->smallbuf;
  	unsigned int rfclen = be32_to_cpu(rsp->hdr.smb_buf_length);
  	int remaining = rfclen + 4 - server->total_read;
  	struct cifs_readdata *rdata = mid->callback_data;
  
  	while (remaining > 0) {
  		int length;
  
  		length = cifs_read_from_socket(server, server->bigbuf,
  				min_t(unsigned int, remaining,
  					CIFSMaxBufSize + MAX_CIFS_HDR_SIZE));
  		if (length < 0)
  			return length;
  		server->total_read += length;
  		remaining -= length;
  	}
  
  	dequeue_mid(mid, rdata->result);
  	return 0;
  }
  
  static int
  cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
  {
  	int length, len;
  	unsigned int data_offset, remaining, data_len;
  	struct cifs_readdata *rdata = mid->callback_data;
  	READ_RSP *rsp = (READ_RSP *)server->smallbuf;
  	unsigned int rfclen = be32_to_cpu(rsp->hdr.smb_buf_length) + 4;
  	u64 eof;
  	pgoff_t eof_index;
  	struct page *page, *tpage;
  
  	cFYI(1, "%s: mid=%u offset=%llu bytes=%u", __func__,
  		mid->mid, rdata->offset, rdata->bytes);
  
  	/*
  	 * 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.
  	 */
  	len = min_t(unsigned int, rfclen, sizeof(*rsp)) -
  			sizeof(struct smb_hdr) + 1;
  
  	rdata->iov[0].iov_base = server->smallbuf + sizeof(struct smb_hdr) - 1;
  	rdata->iov[0].iov_len = len;
  
  	length = cifs_readv_from_socket(server, rdata->iov, 1, len);
  	if (length < 0)
  		return length;
  	server->total_read += length;
  
  	/* Was the SMB read successful? */
  	rdata->result = map_smb_to_linux_error(&rsp->hdr, false);
  	if (rdata->result != 0) {
  		cFYI(1, "%s: server returned error %d", __func__,
  			rdata->result);
  		return cifs_readv_discard(server, mid);
  	}
  
  	/* Is there enough to get to the rest of the READ_RSP header? */
  	if (server->total_read < sizeof(READ_RSP)) {
  		cFYI(1, "%s: server returned short header. got=%u expected=%zu",
  			__func__, server->total_read, sizeof(READ_RSP));
  		rdata->result = -EIO;
  		return cifs_readv_discard(server, mid);
  	}
  
  	data_offset = le16_to_cpu(rsp->DataOffset) + 4;
  	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.
  		 */
  		cFYI(1, "%s: data offset (%u) inside read response header",
  			__func__, data_offset);
  		data_offset = server->total_read;
  	} else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) {
  		/* data_offset is beyond the end of smallbuf */
  		cFYI(1, "%s: data offset (%u) beyond end of smallbuf",
  			__func__, data_offset);
  		rdata->result = -EIO;
  		return cifs_readv_discard(server, mid);
  	}
  
  	cFYI(1, "%s: total_read=%u data_offset=%u", __func__,
  		server->total_read, data_offset);
  
  	len = data_offset - server->total_read;
  	if (len > 0) {
  		/* read any junk before data into the rest of smallbuf */
  		rdata->iov[0].iov_base = server->smallbuf + server->total_read;
  		rdata->iov[0].iov_len = len;
  		length = cifs_readv_from_socket(server, rdata->iov, 1, len);
  		if (length < 0)
  			return length;
  		server->total_read += length;
  	}
  
  	/* set up first iov for signature check */
  	rdata->iov[0].iov_base = server->smallbuf;
  	rdata->iov[0].iov_len = server->total_read;
  	cFYI(1, "0: iov_base=%p iov_len=%zu",
  		rdata->iov[0].iov_base, rdata->iov[0].iov_len);
  
  	/* how much data is in the response? */
  	data_len = le16_to_cpu(rsp->DataLengthHigh) << 16;
  	data_len += le16_to_cpu(rsp->DataLength);
  	if (data_offset + data_len > rfclen) {
  		/* data_len is corrupt -- discard frame */
  		rdata->result = -EIO;
  		return cifs_readv_discard(server, mid);
  	}
  
  	/* marshal up the page array */
  	len = 0;
  	remaining = data_len;
  	rdata->nr_iov = 1;
  
  	/* determine the eof that the server (probably) has */
  	eof = CIFS_I(rdata->mapping->host)->server_eof;
  	eof_index = eof ? (eof - 1) >> PAGE_CACHE_SHIFT : 0;
  	cFYI(1, "eof=%llu eof_index=%lu", eof, eof_index);
  
  	list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
  		if (remaining >= PAGE_CACHE_SIZE) {
  			/* enough data to fill the page */
  			rdata->iov[rdata->nr_iov].iov_base = kmap(page);
  			rdata->iov[rdata->nr_iov].iov_len = PAGE_CACHE_SIZE;
  			cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
  				rdata->nr_iov, page->index,
  				rdata->iov[rdata->nr_iov].iov_base,
  				rdata->iov[rdata->nr_iov].iov_len);
  			++rdata->nr_iov;
  			len += PAGE_CACHE_SIZE;
  			remaining -= PAGE_CACHE_SIZE;
  		} else if (remaining > 0) {
  			/* enough for partial page, fill and zero the rest */
  			rdata->iov[rdata->nr_iov].iov_base = kmap(page);
  			rdata->iov[rdata->nr_iov].iov_len = remaining;
  			cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
  				rdata->nr_iov, page->index,
  				rdata->iov[rdata->nr_iov].iov_base,
  				rdata->iov[rdata->nr_iov].iov_len);
  			memset(rdata->iov[rdata->nr_iov].iov_base + remaining,
  				'\0', PAGE_CACHE_SIZE - remaining);
  			++rdata->nr_iov;
  			len += remaining;
  			remaining = 0;
  		} else if (page->index > eof_index) {
  			/*
  			 * The VFS will not try to do readahead past the
  			 * i_size, but it's possible that we have outstanding
  			 * writes with gaps in the middle and the i_size hasn't
  			 * caught up yet. Populate those with zeroed out pages
  			 * to prevent the VFS from repeatedly attempting to
  			 * fill them until the writes are flushed.
  			 */
  			zero_user(page, 0, PAGE_CACHE_SIZE);
  			list_del(&page->lru);
  			lru_cache_add_file(page);
  			flush_dcache_page(page);
  			SetPageUptodate(page);
  			unlock_page(page);
  			page_cache_release(page);
  		} else {
  			/* no need to hold page hostage */
  			list_del(&page->lru);
  			lru_cache_add_file(page);
  			unlock_page(page);
  			page_cache_release(page);
  		}
  	}
  
  	/* issue the read if we have any iovecs left to fill */
  	if (rdata->nr_iov > 1) {
  		length = cifs_readv_from_socket(server, &rdata->iov[1],
  						rdata->nr_iov - 1, len);
  		if (length < 0)
  			return length;
  		server->total_read += length;
  	} else {
  		length = 0;
  	}
  
  	rdata->bytes = length;
  
  	cFYI(1, "total_read=%u rfclen=%u remaining=%u", server->total_read,
  		rfclen, remaining);
  
  	/* discard anything left over */
  	if (server->total_read < rfclen)
  		return cifs_readv_discard(server, mid);
  
  	dequeue_mid(mid, false);
  	return length;
  }
  
  static void
  cifs_readv_complete(struct work_struct *work)
  {
  	struct cifs_readdata *rdata = container_of(work,
  						struct cifs_readdata, work);
  	struct page *page, *tpage;
  
  	list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
  		list_del(&page->lru);
  		lru_cache_add_file(page);
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1584
1585
  
  		if (rdata->result == 0) {
a2d6b6cac   Pavel Shilovsky   CIFS: Fix error h...
1586
  			kunmap(page);
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
  			flush_dcache_page(page);
  			SetPageUptodate(page);
  		}
  
  		unlock_page(page);
  
  		if (rdata->result == 0)
  			cifs_readpage_to_fscache(rdata->mapping->host, page);
  
  		page_cache_release(page);
  	}
  	cifs_readdata_free(rdata);
  }
  
  static void
  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;
  
  	cFYI(1, "%s: mid=%u state=%d result=%d bytes=%u", __func__,
  		mid->mid, mid->midState, rdata->result, rdata->bytes);
  
  	switch (mid->midState) {
  	case MID_RESPONSE_RECEIVED:
  		/* result already set, check signature */
  		if (server->sec_mode &
  		    (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
  			if (cifs_verify_signature(rdata->iov, rdata->nr_iov,
  					  server, mid->sequence_number + 1))
  				cERROR(1, "Unexpected SMB signature");
  		}
  		/* FIXME: should this be counted toward the initiating task? */
  		task_io_account_read(rdata->bytes);
  		cifs_stats_bytes_read(tcon, rdata->bytes);
  		break;
  	case MID_REQUEST_SUBMITTED:
  	case MID_RETRY_NEEDED:
  		rdata->result = -EAGAIN;
  		break;
  	default:
  		rdata->result = -EIO;
  	}
  
  	queue_work(system_nrt_wq, &rdata->work);
  	DeleteMidQEntry(mid);
  	atomic_dec(&server->inFlight);
  	wake_up(&server->request_q);
  }
  
  /* 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);
  
  	cFYI(1, "%s: offset=%llu bytes=%u", __func__,
  		rdata->offset, rdata->bytes);
  
  	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 */
  	smb->Fid = rdata->cfile->netfid;
  	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 */
  	rdata->iov[0].iov_base = smb;
  	rdata->iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
  
  	rc = cifs_call_async(tcon->ses->server, rdata->iov, 1,
  			     cifs_readv_receive, cifs_readv_callback,
  			     rdata, false);
  
  	if (rc == 0)
  		cifs_stats_inc(&tcon->num_reads);
  
  	cifs_small_buf_release(smb);
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1698
  int
d4ffff1fa   Pavel Shilovsky   CIFS: Add rwpidfo...
1699
  CIFSSMBRead(const int xid, struct cifs_io_parms *io_parms, unsigned int *nbytes,
50c2f7538   Steve French   [CIFS] whitespace...
1700
  	    char **buf, int *pbuf_type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1701
1702
1703
1704
1705
  {
  	int rc = -EACCES;
  	READ_REQ *pSMB = NULL;
  	READ_RSP *pSMBr = NULL;
  	char *pReadData = NULL;
bfa0d75a1   Steve French   [CIFS] Add suppor...
1706
  	int wct;
ec637e3ff   Steve French   [CIFS] Avoid extr...
1707
1708
  	int resp_buf_type = 0;
  	struct kvec iov[1];
d4ffff1fa   Pavel Shilovsky   CIFS: Add rwpidfo...
1709
1710
1711
  	__u32 pid = io_parms->pid;
  	__u16 netfid = io_parms->netfid;
  	__u64 offset = io_parms->offset;
96daf2b09   Steve French   [CIFS] Rename thr...
1712
  	struct cifs_tcon *tcon = io_parms->tcon;
d4ffff1fa   Pavel Shilovsky   CIFS: Add rwpidfo...
1713
  	unsigned int count = io_parms->length;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1714

b6b38f704   Joe Perches   [CIFS] Neaten cER...
1715
  	cFYI(1, "Reading %d bytes on fid %d", count, netfid);
790fe579f   Steve French   [CIFS] more white...
1716
  	if (tcon->ses->capabilities & CAP_LARGE_FILES)
bfa0d75a1   Steve French   [CIFS] Add suppor...
1717
  		wct = 12;
4c3130efd   Steve French   [CIFS] Cleanup: M...
1718
  	else {
bfa0d75a1   Steve French   [CIFS] Add suppor...
1719
  		wct = 10; /* old style read */
d4ffff1fa   Pavel Shilovsky   CIFS: Add rwpidfo...
1720
  		if ((offset >> 32) > 0)  {
4c3130efd   Steve French   [CIFS] Cleanup: M...
1721
1722
1723
1724
  			/* can not handle this big offset for old */
  			return -EIO;
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1725
1726
  
  	*nbytes = 0;
ec637e3ff   Steve French   [CIFS] Avoid extr...
1727
  	rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1728
1729
  	if (rc)
  		return rc;
d4ffff1fa   Pavel Shilovsky   CIFS: Add rwpidfo...
1730
1731
  	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
1732
1733
1734
  	/* tcon and ses pointer are checked in smb_init */
  	if (tcon->ses->server == NULL)
  		return -ECONNABORTED;
ec637e3ff   Steve French   [CIFS] Avoid extr...
1735
  	pSMB->AndXCommand = 0xFF;       /* none */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1736
  	pSMB->Fid = netfid;
d4ffff1fa   Pavel Shilovsky   CIFS: Add rwpidfo...
1737
  	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
790fe579f   Steve French   [CIFS] more white...
1738
  	if (wct == 12)
d4ffff1fa   Pavel Shilovsky   CIFS: Add rwpidfo...
1739
  		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
bfa0d75a1   Steve French   [CIFS] Add suppor...
1740

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1741
1742
1743
  	pSMB->Remaining = 0;
  	pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
  	pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
790fe579f   Steve French   [CIFS] more white...
1744
  	if (wct == 12)
bfa0d75a1   Steve French   [CIFS] Add suppor...
1745
1746
1747
  		pSMB->ByteCount = 0;  /* no need to do le conversion since 0 */
  	else {
  		/* old style read */
50c2f7538   Steve French   [CIFS] whitespace...
1748
  		struct smb_com_readx_req *pSMBW =
bfa0d75a1   Steve French   [CIFS] Add suppor...
1749
  			(struct smb_com_readx_req *)pSMB;
ec637e3ff   Steve French   [CIFS] Avoid extr...
1750
  		pSMBW->ByteCount = 0;
bfa0d75a1   Steve French   [CIFS] Add suppor...
1751
  	}
ec637e3ff   Steve French   [CIFS] Avoid extr...
1752
1753
  
  	iov[0].iov_base = (char *)pSMB;
be8e3b004   Steve French   consistently use ...
1754
  	iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
a761ac579   Steve French   [CIFS] log better...
1755
  	rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
7749981ec   Jeff Layton   cifs: remove code...
1756
  			 &resp_buf_type, CIFS_LOG_ERROR);
a45443475   Steve French   CIFS: Reduce CONF...
1757
  	cifs_stats_inc(&tcon->num_reads);
ec637e3ff   Steve French   [CIFS] Avoid extr...
1758
  	pSMBr = (READ_RSP *)iov[0].iov_base;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1759
  	if (rc) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1760
  		cERROR(1, "Send error in read = %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1761
1762
1763
1764
1765
1766
1767
  	} 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...
1768
  		if ((data_length > CIFSMaxBufSize)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1769
  				|| (data_length > count)) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1770
1771
  			cFYI(1, "bad length %d for count %d",
  				 data_length, count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1772
1773
1774
  			rc = -EIO;
  			*nbytes = 0;
  		} else {
ec637e3ff   Steve French   [CIFS] Avoid extr...
1775
  			pReadData = (char *) (&pSMBr->hdr.Protocol) +
26f57364d   Steve French   [CIFS] formatting...
1776
1777
  					le16_to_cpu(pSMBr->DataOffset);
  /*			if (rc = copy_to_user(buf, pReadData, data_length)) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1778
  				cERROR(1, "Faulting on read rc = %d",rc);
50c2f7538   Steve French   [CIFS] whitespace...
1779
  				rc = -EFAULT;
26f57364d   Steve French   [CIFS] formatting...
1780
  			}*/ /* can not use copy_to_user when using page cache*/
790fe579f   Steve French   [CIFS] more white...
1781
  			if (*buf)
50c2f7538   Steve French   [CIFS] whitespace...
1782
  				memcpy(*buf, pReadData, data_length);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1783
1784
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1785

4b8f930ff   Steve French   [CIFS] Free small...
1786
  /*	cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
790fe579f   Steve French   [CIFS] more white...
1787
1788
  	if (*buf) {
  		if (resp_buf_type == CIFS_SMALL_BUFFER)
ec637e3ff   Steve French   [CIFS] Avoid extr...
1789
  			cifs_small_buf_release(iov[0].iov_base);
790fe579f   Steve French   [CIFS] more white...
1790
  		else if (resp_buf_type == CIFS_LARGE_BUFFER)
ec637e3ff   Steve French   [CIFS] Avoid extr...
1791
  			cifs_buf_release(iov[0].iov_base);
790fe579f   Steve French   [CIFS] more white...
1792
  	} else if (resp_buf_type != CIFS_NO_BUFFER) {
50c2f7538   Steve French   [CIFS] whitespace...
1793
1794
  		/* return buffer to caller to free */
  		*buf = iov[0].iov_base;
790fe579f   Steve French   [CIFS] more white...
1795
  		if (resp_buf_type == CIFS_SMALL_BUFFER)
ec637e3ff   Steve French   [CIFS] Avoid extr...
1796
  			*pbuf_type = CIFS_SMALL_BUFFER;
790fe579f   Steve French   [CIFS] more white...
1797
  		else if (resp_buf_type == CIFS_LARGE_BUFFER)
ec637e3ff   Steve French   [CIFS] Avoid extr...
1798
  			*pbuf_type = CIFS_LARGE_BUFFER;
6cec2aed8   Steve French   [PATCH] CIFS: CIF...
1799
  	} /* else no valid buffer on return - leave as null */
ec637e3ff   Steve French   [CIFS] Avoid extr...
1800
1801
  
  	/* Note: On -EAGAIN error only caller can retry on handle based calls
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1802
1803
1804
  		since file handle passed in no longer valid */
  	return rc;
  }
ec637e3ff   Steve French   [CIFS] Avoid extr...
1805

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1806
  int
fa2989f44   Pavel Shilovsky   CIFS: Use pid sav...
1807
1808
  CIFSSMBWrite(const int xid, struct cifs_io_parms *io_parms,
  	     unsigned int *nbytes, const char *buf,
50c2f7538   Steve French   [CIFS] whitespace...
1809
  	     const char __user *ubuf, const int long_op)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1810
1811
1812
1813
  {
  	int rc = -EACCES;
  	WRITE_REQ *pSMB = NULL;
  	WRITE_RSP *pSMBr = NULL;
1c9551878   Steve French   [CIFS] Add suppor...
1814
  	int bytes_returned, wct;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1815
1816
  	__u32 bytes_sent;
  	__u16 byte_count;
fa2989f44   Pavel Shilovsky   CIFS: Use pid sav...
1817
1818
1819
  	__u32 pid = io_parms->pid;
  	__u16 netfid = io_parms->netfid;
  	__u64 offset = io_parms->offset;
96daf2b09   Steve French   [CIFS] Rename thr...
1820
  	struct cifs_tcon *tcon = io_parms->tcon;
fa2989f44   Pavel Shilovsky   CIFS: Use pid sav...
1821
  	unsigned int count = io_parms->length;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1822

a24e2d7d8   Steve French   [CIFS] initialize...
1823
  	*nbytes = 0;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1824
  	/* cFYI(1, "write at %lld %d bytes", offset, count);*/
790fe579f   Steve French   [CIFS] more white...
1825
  	if (tcon->ses == NULL)
1c9551878   Steve French   [CIFS] Add suppor...
1826
  		return -ECONNABORTED;
790fe579f   Steve French   [CIFS] more white...
1827
  	if (tcon->ses->capabilities & CAP_LARGE_FILES)
1c9551878   Steve French   [CIFS] Add suppor...
1828
  		wct = 14;
4c3130efd   Steve French   [CIFS] Cleanup: M...
1829
  	else {
1c9551878   Steve French   [CIFS] Add suppor...
1830
  		wct = 12;
4c3130efd   Steve French   [CIFS] Cleanup: M...
1831
1832
1833
1834
1835
  		if ((offset >> 32) > 0) {
  			/* can not handle big offset for old srv */
  			return -EIO;
  		}
  	}
1c9551878   Steve French   [CIFS] Add suppor...
1836
1837
  
  	rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1838
1839
1840
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
fa2989f44   Pavel Shilovsky   CIFS: Use pid sav...
1841
1842
1843
  
  	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
1844
1845
1846
1847
1848
1849
1850
  	/* 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...
1851
  	if (wct == 14)
1c9551878   Steve French   [CIFS] Add suppor...
1852
  		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
50c2f7538   Steve French   [CIFS] whitespace...
1853

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1854
1855
1856
  	pSMB->Reserved = 0xFFFFFFFF;
  	pSMB->WriteMode = 0;
  	pSMB->Remaining = 0;
50c2f7538   Steve French   [CIFS] whitespace...
1857
  	/* Can increase buffer size if buffer is big enough in some cases ie we
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1858
1859
1860
  	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...
1861
  	if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1862
1863
1864
1865
1866
1867
1868
1869
1870
  		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...
1871
  		cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
790fe579f   Steve French   [CIFS] more white...
1872
  	if (buf)
61e748015   Steve French   [CIFS] various mi...
1873
  		memcpy(pSMB->Data, buf, bytes_sent);
790fe579f   Steve French   [CIFS] more white...
1874
1875
  	else if (ubuf) {
  		if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1876
1877
1878
  			cifs_buf_release(pSMB);
  			return -EFAULT;
  		}
e30dcf3a1   Steve French   [CIFS] Add suppor...
1879
  	} else if (count != 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1880
1881
1882
  		/* No buffer */
  		cifs_buf_release(pSMB);
  		return -EINVAL;
e30dcf3a1   Steve French   [CIFS] Add suppor...
1883
  	} /* else setting file size with write of zero bytes */
790fe579f   Steve French   [CIFS] more white...
1884
  	if (wct == 14)
e30dcf3a1   Steve French   [CIFS] Add suppor...
1885
  		byte_count = bytes_sent + 1; /* pad */
ad7a2926b   Steve French   [CIFS] reduce che...
1886
  	else /* wct == 12 */
e30dcf3a1   Steve French   [CIFS] Add suppor...
1887
  		byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
ad7a2926b   Steve French   [CIFS] reduce che...
1888

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

790fe579f   Steve French   [CIFS] more white...
1893
  	if (wct == 14)
1c9551878   Steve French   [CIFS] Add suppor...
1894
  		pSMB->ByteCount = cpu_to_le16(byte_count);
50c2f7538   Steve French   [CIFS] whitespace...
1895
1896
1897
  	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...
1898
1899
1900
  			(struct smb_com_writex_req *)pSMB;
  		pSMBW->ByteCount = cpu_to_le16(byte_count);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1901
1902
1903
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
a45443475   Steve French   CIFS: Reduce CONF...
1904
  	cifs_stats_inc(&tcon->num_writes);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1905
  	if (rc) {
f19159dc5   Steve French   [CIFS] Cleanup va...
1906
  		cFYI(1, "Send error in write = %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1907
1908
1909
1910
  	} else {
  		*nbytes = le16_to_cpu(pSMBr->CountHigh);
  		*nbytes = (*nbytes) << 16;
  		*nbytes += le16_to_cpu(pSMBr->Count);
6513a81e9   Suresh Jayaraman   cifs: Fix a kerne...
1911
1912
1913
1914
1915
1916
1917
1918
  
  		/*
  		 * 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
1919
1920
1921
  	}
  
  	cifs_buf_release(pSMB);
50c2f7538   Steve French   [CIFS] whitespace...
1922
  	/* Note: On -EAGAIN error only caller can retry on handle based calls
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1923
1924
1925
1926
  		since file handle passed in no longer valid */
  
  	return rc;
  }
c28c89fc4   Jeff Layton   cifs: add cifs_as...
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
  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)
  {
  	int i, rc;
  	struct inode *inode = wdata->cfile->dentry->d_inode;
  
  	for (i = 0; i < wdata->nr_pages; i++) {
  		lock_page(wdata->pages[i]);
  		clear_page_dirty_for_io(wdata->pages[i]);
  	}
  
  	do {
  		rc = cifs_async_writev(wdata);
  	} while (rc == -EAGAIN);
  
  	for (i = 0; i < wdata->nr_pages; i++) {
  		if (rc != 0)
  			SetPageError(wdata->pages[i]);
  		unlock_page(wdata->pages[i]);
  	}
  
  	mapping_set_error(inode->i_mapping, rc);
  	kref_put(&wdata->refcount, cifs_writedata_release);
  }
  
  static void
  cifs_writev_complete(struct work_struct *work)
  {
  	struct cifs_writedata *wdata = container_of(work,
  						struct cifs_writedata, work);
  	struct inode *inode = wdata->cfile->dentry->d_inode;
  	int i = 0;
  
  	if (wdata->result == 0) {
  		cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
  		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);
  		page_cache_release(page);
  	}
  	if (wdata->result != -EAGAIN)
  		mapping_set_error(inode->i_mapping, wdata->result);
  	kref_put(&wdata->refcount, cifs_writedata_release);
  }
  
  struct cifs_writedata *
  cifs_writedata_alloc(unsigned int nr_pages)
  {
  	struct cifs_writedata *wdata;
  
  	/* this would overflow */
  	if (nr_pages == 0) {
  		cERROR(1, "%s: called with nr_pages == 0!", __func__);
  		return NULL;
  	}
  
  	/* writedata + number of page pointers */
  	wdata = kzalloc(sizeof(*wdata) +
  			sizeof(struct page *) * (nr_pages - 1), GFP_NOFS);
  	if (wdata != NULL) {
  		INIT_WORK(&wdata->work, cifs_writev_complete);
  		kref_init(&wdata->refcount);
  	}
  	return wdata;
  }
  
  /*
   * Check the midState and signature on received buffer (if any), and queue the
   * 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...
2026
  	struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2027
2028
2029
2030
2031
2032
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
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
  	unsigned int written;
  	WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
  
  	switch (mid->midState) {
  	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;
  	}
  
  	queue_work(system_nrt_wq, &wdata->work);
  	DeleteMidQEntry(mid);
  	atomic_dec(&tcon->ses->server->inFlight);
  	wake_up(&tcon->ses->server->request_q);
  }
  
  /* cifs_async_writev - send an async write, and set up mid to handle result */
  int
  cifs_async_writev(struct cifs_writedata *wdata)
  {
  	int i, rc = -EACCES;
  	WRITE_REQ *smb = NULL;
  	int wct;
96daf2b09   Steve French   [CIFS] Rename thr...
2075
  	struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
  	struct inode *inode = wdata->cfile->dentry->d_inode;
  	struct kvec *iov = NULL;
  
  	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;
  
  	/* 1 iov per page + 1 for header */
  	iov = kzalloc((wdata->nr_pages + 1) * sizeof(*iov), GFP_NOFS);
  	if (iov == NULL) {
  		rc = -ENOMEM;
  		goto async_writev_out;
  	}
fa2989f44   Pavel Shilovsky   CIFS: Use pid sav...
2099
2100
  	smb->hdr.Pid = cpu_to_le16((__u16)wdata->cfile->pid);
  	smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->cfile->pid >> 16));
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
  	smb->AndXCommand = 0xFF;	/* none */
  	smb->Fid = wdata->cfile->netfid;
  	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 */
  	iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
  	iov[0].iov_base = smb;
  
  	/* marshal up the pages into iov array */
  	wdata->bytes = 0;
  	for (i = 0; i < wdata->nr_pages; i++) {
  		iov[i + 1].iov_len = min(inode->i_size -
  				      page_offset(wdata->pages[i]),
  					(loff_t)PAGE_CACHE_SIZE);
  		iov[i + 1].iov_base = kmap(wdata->pages[i]);
  		wdata->bytes += iov[i + 1].iov_len;
  	}
  
  	cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
  
  	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);
  		iov[0].iov_len += 4; /* pad bigger by four bytes */
  	}
  
  	kref_get(&wdata->refcount);
  	rc = cifs_call_async(tcon->ses->server, iov, wdata->nr_pages + 1,
44d22d846   Jeff Layton   cifs: add a callb...
2146
  			     NULL, cifs_writev_callback, wdata, false);
c28c89fc4   Jeff Layton   cifs: add cifs_as...
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
  
  	if (rc == 0)
  		cifs_stats_inc(&tcon->num_writes);
  	else
  		kref_put(&wdata->refcount, cifs_writedata_release);
  
  	/* send is done, unmap pages */
  	for (i = 0; i < wdata->nr_pages; i++)
  		kunmap(wdata->pages[i]);
  
  async_writev_out:
  	cifs_small_buf_release(smb);
  	kfree(iov);
  	return rc;
  }
d6e04ae64   Steve French   [CIFS] CIFS write...
2162
  int
fa2989f44   Pavel Shilovsky   CIFS: Use pid sav...
2163
2164
2165
  CIFSSMBWrite2(const int xid, struct cifs_io_parms *io_parms,
  	      unsigned int *nbytes, struct kvec *iov, int n_vec,
  	      const int long_op)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2166
2167
2168
  {
  	int rc = -EACCES;
  	WRITE_REQ *pSMB = NULL;
ec637e3ff   Steve French   [CIFS] Avoid extr...
2169
  	int wct;
d6e04ae64   Steve French   [CIFS] CIFS write...
2170
  	int smb_hdr_len;
ec637e3ff   Steve French   [CIFS] Avoid extr...
2171
  	int resp_buf_type = 0;
fa2989f44   Pavel Shilovsky   CIFS: Use pid sav...
2172
2173
2174
  	__u32 pid = io_parms->pid;
  	__u16 netfid = io_parms->netfid;
  	__u64 offset = io_parms->offset;
96daf2b09   Steve French   [CIFS] Rename thr...
2175
  	struct cifs_tcon *tcon = io_parms->tcon;
fa2989f44   Pavel Shilovsky   CIFS: Use pid sav...
2176
  	unsigned int count = io_parms->length;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2177

fbec9ab95   Jeff Layton   cifs: vary timeou...
2178
  	*nbytes = 0;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2179
  	cFYI(1, "write2 at %lld %d bytes", (long long)offset, count);
ff7feac96   Steve French   [CIFS] Fix endian...
2180

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

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

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2232

ec637e3ff   Steve French   [CIFS] Avoid extr...
2233
  	rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
133672efb   Steve French   [CIFS] Fix buffer...
2234
  			  long_op);
a45443475   Steve French   CIFS: Reduce CONF...
2235
  	cifs_stats_inc(&tcon->num_writes);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2236
  	if (rc) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2237
  		cFYI(1, "Send error Write2 = %d", rc);
790fe579f   Steve French   [CIFS] more white...
2238
  	} else if (resp_buf_type == 0) {
ec637e3ff   Steve French   [CIFS] Avoid extr...
2239
2240
  		/* presumably this can not happen, but best to be safe */
  		rc = -EIO;
d6e04ae64   Steve French   [CIFS] CIFS write...
2241
  	} else {
ad7a2926b   Steve French   [CIFS] reduce che...
2242
  		WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
d6e04ae64   Steve French   [CIFS] CIFS write...
2243
2244
2245
  		*nbytes = le16_to_cpu(pSMBr->CountHigh);
  		*nbytes = (*nbytes) << 16;
  		*nbytes += le16_to_cpu(pSMBr->Count);
6513a81e9   Suresh Jayaraman   cifs: Fix a kerne...
2246
2247
2248
2249
2250
2251
2252
2253
  
  		/*
  		 * 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...
2254
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2255

4b8f930ff   Steve French   [CIFS] Free small...
2256
  /*	cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
790fe579f   Steve French   [CIFS] more white...
2257
  	if (resp_buf_type == CIFS_SMALL_BUFFER)
ec637e3ff   Steve French   [CIFS] Avoid extr...
2258
  		cifs_small_buf_release(iov[0].iov_base);
790fe579f   Steve French   [CIFS] more white...
2259
  	else if (resp_buf_type == CIFS_LARGE_BUFFER)
ec637e3ff   Steve French   [CIFS] Avoid extr...
2260
  		cifs_buf_release(iov[0].iov_base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2261

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

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
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
  int cifs_lockv(const int xid, struct cifs_tcon *tcon, const __u16 netfid,
  	       const __u8 lock_type, const __u32 num_unlock,
  	       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;
  
  	cFYI(1, "cifs_lockv num lock %d num unlock %d", num_lock, num_unlock);
  
  	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);
  
  	cifs_stats_inc(&tcon->num_locks);
  	rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP);
  	if (rc)
  		cFYI(1, "Send error in cifs_lockv = %d", rc);
  
  	return rc;
  }
d6e04ae64   Steve French   [CIFS] CIFS write...
2308

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

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

b6b38f704   Joe Perches   [CIFS] Neaten cER...
2390
  	cFYI(1, "Posix Lock");
fc94cdb94   Steve French   [CIFS] Fix new PO...
2391

790fe579f   Steve French   [CIFS] more white...
2392
  	if (pLockData == NULL)
ed5f03700   Marcin Slusarz   [CIFS] CIFSSMBPos...
2393
  		return -EINVAL;
fc94cdb94   Steve French   [CIFS] Fix new PO...
2394

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

fc94cdb94   Steve French   [CIFS] Fix new PO...
2490
  plk_err_exit:
08547b036   Steve French   [CIFS] Add posix ...
2491
2492
  	if (pSMB)
  		cifs_small_buf_release(pSMB);
133672efb   Steve French   [CIFS] Fix buffer...
2493
2494
2495
2496
  	if (resp_buf_type == CIFS_SMALL_BUFFER)
  		cifs_small_buf_release(iov[0].iov_base);
  	else if (resp_buf_type == CIFS_LARGE_BUFFER)
  		cifs_buf_release(iov[0].iov_base);
08547b036   Steve French   [CIFS] Add posix ...
2497
2498
2499
2500
2501
2502
2503
2504
  	/* Note: On -EAGAIN error only caller can retry on handle based calls
  	   since file handle passed in no longer valid */
  
  	return rc;
  }
  
  
  int
96daf2b09   Steve French   [CIFS] Rename thr...
2505
  CIFSSMBClose(const int xid, struct cifs_tcon *tcon, int smb_file_id)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2506
2507
2508
  {
  	int rc = 0;
  	CLOSE_REQ *pSMB = NULL;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2509
  	cFYI(1, "In CIFSSMBClose");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2510
2511
2512
  
  /* 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...
2513
  	if (rc == -EAGAIN)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2514
2515
2516
  		return 0;
  	if (rc)
  		return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2517
  	pSMB->FileID = (__u16) smb_file_id;
b815f1e55   Steve French   [CIFS] Allow for ...
2518
  	pSMB->LastWriteTime = 0xFFFFFFFF;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2519
  	pSMB->ByteCount = 0;
133672efb   Steve French   [CIFS] Fix buffer...
2520
  	rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
a45443475   Steve French   CIFS: Reduce CONF...
2521
  	cifs_stats_inc(&tcon->num_closes);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2522
  	if (rc) {
790fe579f   Steve French   [CIFS] more white...
2523
  		if (rc != -EINTR) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2524
  			/* EINTR is expected when user ctl-c to kill app */
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2525
  			cERROR(1, "Send error in Close = %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2526
2527
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2528
  	/* Since session is dead, file will be closed on server already */
790fe579f   Steve French   [CIFS] more white...
2529
  	if (rc == -EAGAIN)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2530
2531
2532
2533
2534
2535
  		rc = 0;
  
  	return rc;
  }
  
  int
96daf2b09   Steve French   [CIFS] Rename thr...
2536
  CIFSSMBFlush(const int xid, struct cifs_tcon *tcon, int smb_file_id)
b298f2235   Steve French   [CIFS] Send SMB f...
2537
2538
2539
  {
  	int rc = 0;
  	FLUSH_REQ *pSMB = NULL;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2540
  	cFYI(1, "In CIFSSMBFlush");
b298f2235   Steve French   [CIFS] Send SMB f...
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
  
  	rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
  	if (rc)
  		return rc;
  
  	pSMB->FileID = (__u16) smb_file_id;
  	pSMB->ByteCount = 0;
  	rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
  	cifs_stats_inc(&tcon->num_flushes);
  	if (rc)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2551
  		cERROR(1, "Send error in Flush = %d", rc);
b298f2235   Steve French   [CIFS] Send SMB f...
2552
2553
2554
2555
2556
  
  	return rc;
  }
  
  int
96daf2b09   Steve French   [CIFS] Rename thr...
2557
  CIFSSMBRename(const int xid, struct cifs_tcon *tcon,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2558
  	      const char *fromName, const char *toName,
737b758c9   Steve French   [PATCH] cifs: cha...
2559
  	      const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2560
2561
2562
2563
2564
2565
2566
  {
  	int rc = 0;
  	RENAME_REQ *pSMB = NULL;
  	RENAME_RSP *pSMBr = NULL;
  	int bytes_returned;
  	int name_len, name_len2;
  	__u16 count;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2567
  	cFYI(1, "In CIFSSMBRename");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
  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) {
  		name_len =
50c2f7538   Steve French   [CIFS] whitespace...
2581
  		    cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
737b758c9   Steve French   [PATCH] cifs: cha...
2582
  				     PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2583
2584
2585
2586
2587
2588
  		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 =
582d21e5e   Steve French   [CIFS] cleanup ol...
2589
  		    cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
737b758c9   Steve French   [PATCH] cifs: cha...
2590
  				     toName, PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2591
2592
  		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
  		name_len2 *= 2;	/* convert to bytes */
50c2f7538   Steve French   [CIFS] whitespace...
2593
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
  		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 ...
2606
  	inc_rfc1001_len(pSMB, count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2607
2608
2609
2610
  	pSMB->ByteCount = cpu_to_le16(count);
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
a45443475   Steve French   CIFS: Reduce CONF...
2611
  	cifs_stats_inc(&tcon->num_renames);
ad7a2926b   Steve French   [CIFS] reduce che...
2612
  	if (rc)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2613
  		cFYI(1, "Send error in rename = %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2614

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2615
2616
2617
2618
2619
2620
2621
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto renameRetry;
  
  	return rc;
  }
96daf2b09   Steve French   [CIFS] Rename thr...
2622
  int CIFSSMBRenameOpenFile(const int xid, struct cifs_tcon *pTcon,
391e57555   Jeff Layton   cifs: remove NULL...
2623
  		int netfid, const char *target_name,
50c2f7538   Steve French   [CIFS] whitespace...
2624
  		const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2625
2626
2627
  {
  	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
  	struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
50c2f7538   Steve French   [CIFS] whitespace...
2628
  	struct set_file_rename *rename_info;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2629
2630
2631
2632
2633
2634
  	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;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2635
  	cFYI(1, "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
2668
  		sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
  		len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
737b758c9   Steve French   [PATCH] cifs: cha...
2669
  					dummy_string, 24, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2670
  	} else {
b1a45695b   Steve French   [CIFS] fix casts ...
2671
  		len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
50c2f7538   Steve French   [CIFS] whitespace...
2672
2673
  					target_name, PATH_MAX, nls_codepage,
  					remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2674
2675
  	}
  	rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
391e57555   Jeff Layton   cifs: remove NULL...
2676
  	count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2677
2678
2679
2680
2681
2682
2683
  	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 ...
2684
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2685
2686
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  	rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
50c2f7538   Steve French   [CIFS] whitespace...
2687
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
a45443475   Steve French   CIFS: Reduce CONF...
2688
  	cifs_stats_inc(&pTcon->num_t2renames);
ad7a2926b   Steve French   [CIFS] reduce che...
2689
  	if (rc)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2690
  		cFYI(1, "Send error in Rename (by file handle) = %d", rc);
a5a2b489b   Steve French   [CIFS] Make CIFS ...
2691

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2692
2693
2694
2695
2696
2697
2698
2699
2700
  	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
96daf2b09   Steve French   [CIFS] Rename thr...
2701
  CIFSSMBCopy(const int xid, struct cifs_tcon *tcon, const char *fromName,
50c2f7538   Steve French   [CIFS] whitespace...
2702
2703
  	    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
2704
2705
2706
2707
2708
2709
2710
  {
  	int rc = 0;
  	COPY_REQ *pSMB = NULL;
  	COPY_RSP *pSMBr = NULL;
  	int bytes_returned;
  	int name_len, name_len2;
  	__u16 count;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2711
  	cFYI(1, "In CIFSSMBCopy");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
  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) {
50c2f7538   Steve French   [CIFS] whitespace...
2724
  		name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
737b758c9   Steve French   [PATCH] cifs: cha...
2725
2726
  					    fromName, PATH_MAX, nls_codepage,
  					    remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2727
2728
2729
2730
2731
  		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...
2732
2733
  		name_len2 =
  		    cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
737b758c9   Steve French   [PATCH] cifs: cha...
2734
  				toName, PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2735
2736
  		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
  		name_len2 *= 2; /* convert to bytes */
50c2f7538   Steve French   [CIFS] whitespace...
2737
  	} else { 	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
  		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 ...
2750
  	inc_rfc1001_len(pSMB, count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2751
2752
2753
2754
2755
  	pSMB->ByteCount = cpu_to_le16(count);
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
  	if (rc) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2756
2757
  		cFYI(1, "Send error in copy = %d with %d files copied",
  			rc, le16_to_cpu(pSMBr->CopyCount));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2758
  	}
0d817bc0d   Steve French   [CIFS] Remove red...
2759
  	cifs_buf_release(pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2760
2761
2762
2763
2764
2765
2766
2767
  
  	if (rc == -EAGAIN)
  		goto copyRetry;
  
  	return rc;
  }
  
  int
96daf2b09   Steve French   [CIFS] Rename thr...
2768
  CIFSUnixCreateSymLink(const int xid, struct cifs_tcon *tcon,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
  		      const char *fromName, const char *toName,
  		      const struct nls_table *nls_codepage)
  {
  	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;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2780
  	cFYI(1, "In Symlink Unix style");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2781
2782
2783
2784
2785
2786
2787
2788
  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 =
e89dc9209   Steve French   [CIFS] Cleanup sp...
2789
  		    cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2790
2791
2792
2793
  				  /* find define for this maxpathcomponent */
  				  , nls_codepage);
  		name_len++;	/* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
2794
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
  		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...
2806
  				InformationLevel) - 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2807
2808
2809
2810
2811
  	offset = param_offset + params;
  
  	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		name_len_target =
e89dc9209   Steve French   [CIFS] Cleanup sp...
2812
  		    cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2813
2814
2815
2816
  				  /* find define for this maxpathcomponent */
  				  , nls_codepage);
  		name_len_target++;	/* trailing null */
  		name_len_target *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
2817
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
  		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 ...
2838
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2839
2840
2841
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
a45443475   Steve French   CIFS: Reduce CONF...
2842
  	cifs_stats_inc(&tcon->num_symlinks);
ad7a2926b   Steve French   [CIFS] reduce che...
2843
  	if (rc)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2844
  		cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2845

0d817bc0d   Steve French   [CIFS] Remove red...
2846
  	cifs_buf_release(pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2847
2848
2849
2850
2851
2852
2853
2854
  
  	if (rc == -EAGAIN)
  		goto createSymLinkRetry;
  
  	return rc;
  }
  
  int
96daf2b09   Steve French   [CIFS] Rename thr...
2855
  CIFSUnixCreateHardLink(const int xid, struct cifs_tcon *tcon,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2856
  		       const char *fromName, const char *toName,
737b758c9   Steve French   [PATCH] cifs: cha...
2857
  		       const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2858
2859
2860
2861
2862
2863
2864
2865
2866
  {
  	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;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2867
  	cFYI(1, "In Create Hard link Unix style");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2868
2869
2870
2871
2872
2873
2874
  createHardLinkRetry:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
b1a45695b   Steve French   [CIFS] fix casts ...
2875
  		name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
737b758c9   Steve French   [PATCH] cifs: cha...
2876
  					    PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2877
2878
  		name_len++;	/* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
2879
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
  		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...
2891
  				InformationLevel) - 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2892
2893
2894
2895
2896
  	offset = param_offset + params;
  
  	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		name_len_target =
b1a45695b   Steve French   [CIFS] fix casts ...
2897
  		    cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
737b758c9   Steve French   [PATCH] cifs: cha...
2898
  				     nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2899
2900
  		name_len_target++;	/* trailing null */
  		name_len_target *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
2901
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
  		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 ...
2922
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2923
2924
2925
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
a45443475   Steve French   CIFS: Reduce CONF...
2926
  	cifs_stats_inc(&tcon->num_hardlinks);
ad7a2926b   Steve French   [CIFS] reduce che...
2927
  	if (rc)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2928
  		cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2929
2930
2931
2932
2933
2934
2935
2936
2937
  
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto createHardLinkRetry;
  
  	return rc;
  }
  
  int
96daf2b09   Steve French   [CIFS] Rename thr...
2938
  CIFSCreateHardLink(const int xid, struct cifs_tcon *tcon,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2939
  		   const char *fromName, const char *toName,
737b758c9   Steve French   [PATCH] cifs: cha...
2940
  		   const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2941
2942
2943
2944
2945
2946
2947
  {
  	int rc = 0;
  	NT_RENAME_REQ *pSMB = NULL;
  	RENAME_RSP *pSMBr = NULL;
  	int bytes_returned;
  	int name_len, name_len2;
  	__u16 count;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2948
  	cFYI(1, "In CIFSCreateHardLink");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
  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 =
b1a45695b   Steve French   [CIFS] fix casts ...
2966
  		    cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
737b758c9   Steve French   [PATCH] cifs: cha...
2967
  				     PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2968
2969
  		name_len++;	/* trailing null */
  		name_len *= 2;
fcc7c09d9   Jeff Layton   cifs: fix buffer ...
2970
2971
2972
2973
  
  		/* 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
2974
  		name_len2 =
50c2f7538   Steve French   [CIFS] whitespace...
2975
  		    cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
737b758c9   Steve French   [PATCH] cifs: cha...
2976
  				     toName, PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2977
2978
  		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
  		name_len2 *= 2;	/* convert to bytes */
50c2f7538   Steve French   [CIFS] whitespace...
2979
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
  		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 /* string type byte */  + name_len + name_len2;
be8e3b004   Steve French   consistently use ...
2992
  	inc_rfc1001_len(pSMB, count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2993
2994
2995
2996
  	pSMB->ByteCount = cpu_to_le16(count);
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
a45443475   Steve French   CIFS: Reduce CONF...
2997
  	cifs_stats_inc(&tcon->num_hardlinks);
ad7a2926b   Steve French   [CIFS] reduce che...
2998
  	if (rc)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2999
  		cFYI(1, "Send error in hard link (NT rename) = %d", rc);
ad7a2926b   Steve French   [CIFS] reduce che...
3000

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3001
3002
3003
3004
3005
3006
3007
3008
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto winCreateHardLinkRetry;
  
  	return rc;
  }
  
  int
96daf2b09   Steve French   [CIFS] Rename thr...
3009
  CIFSSMBUnixQuerySymLink(const int xid, struct cifs_tcon *tcon,
460b96960   Jeff Layton   cifs: change CIFS...
3010
  			const unsigned char *searchName, char **symlinkinfo,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3011
3012
3013
3014
3015
3016
3017
3018
3019
  			const struct nls_table *nls_codepage)
  {
  /* 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...
3020
  	char *data_start;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3021

b6b38f704   Joe Perches   [CIFS] Neaten cER...
3022
  	cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3023
3024
3025
3026
3027
3028
3029
3030
3031
  
  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 =
50c2f7538   Steve French   [CIFS] whitespace...
3032
3033
  		    cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
  				  PATH_MAX, nls_codepage);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3034
3035
  		name_len++;	/* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
3036
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3037
3038
3039
3040
3041
3042
3043
3044
  		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...
3045
  	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3046
3047
3048
3049
3050
3051
  	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...
3052
  	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
  	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 ...
3063
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3064
3065
3066
3067
3068
  	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) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3069
  		cFYI(1, "Send error in QuerySymLinkInfo = %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3070
3071
3072
3073
  	} else {
  		/* decode response */
  
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3074
  		/* BB also check enough total bytes returned */
820a803ff   Jeff Layton   cifs: keep BCC in...
3075
  		if (rc || get_bcc(&pSMBr->hdr) < 2)
460b96960   Jeff Layton   cifs: change CIFS...
3076
  			rc = -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3077
  		else {
0e0d2cf32   Steve French   [CIFS] Remove spa...
3078
  			bool is_unicode;
460b96960   Jeff Layton   cifs: change CIFS...
3079
3080
3081
3082
  			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
3083

0e0d2cf32   Steve French   [CIFS] Remove spa...
3084
3085
3086
3087
  			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
  				is_unicode = true;
  			else
  				is_unicode = false;
737b758c9   Steve French   [PATCH] cifs: cha...
3088
  			/* BB FIXME investigate remapping reserved chars here */
d185cda77   Steve French   [CIFS] rename cif...
3089
  			*symlinkinfo = cifs_strndup_from_ucs(data_start, count,
0e0d2cf32   Steve French   [CIFS] Remove spa...
3090
  						    is_unicode, nls_codepage);
8b6427a2a   Jeff Layton   cifs: fix pointer...
3091
  			if (!*symlinkinfo)
460b96960   Jeff Layton   cifs: change CIFS...
3092
  				rc = -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3093
3094
3095
3096
3097
3098
3099
  		}
  	}
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto querySymLinkRetry;
  	return rc;
  }
c52a95545   Steve French   Don't compile in ...
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
  #ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL
  /*
   *	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
3111
  int
96daf2b09   Steve French   [CIFS] Rename thr...
3112
  CIFSSMBQueryReparseLinkInfo(const int xid, struct cifs_tcon *tcon,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3113
  			const unsigned char *searchName,
50c2f7538   Steve French   [CIFS] whitespace...
3114
  			char *symlinkinfo, const int buflen, __u16 fid,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3115
3116
3117
3118
  			const struct nls_table *nls_codepage)
  {
  	int rc = 0;
  	int bytes_returned;
50c2f7538   Steve French   [CIFS] whitespace...
3119
3120
  	struct smb_com_transaction_ioctl_req *pSMB;
  	struct smb_com_transaction_ioctl_rsp *pSMBr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3121

b6b38f704   Joe Perches   [CIFS] Neaten cER...
3122
  	cFYI(1, "In Windows reparse style QueryLink for path %s", searchName);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3123
3124
3125
3126
3127
3128
3129
3130
3131
  	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...
3132
  	pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
  	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) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3150
  		cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3151
3152
3153
  	} else {		/* decode response */
  		__u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
  		__u32 data_count = le32_to_cpu(pSMBr->DataCount);
820a803ff   Jeff Layton   cifs: keep BCC in...
3154
3155
  		if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
  			/* BB also check enough total bytes returned */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3156
  			rc = -EIO;	/* bad smb */
afe48c31e   Steve French   [CIFS] Fix final ...
3157
3158
3159
3160
  			goto qreparse_out;
  		}
  		if (data_count && (data_count < 2048)) {
  			char *end_of_smb = 2 /* sizeof byte count */ +
820a803ff   Jeff Layton   cifs: keep BCC in...
3161
  			       get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3162

afe48c31e   Steve French   [CIFS] Fix final ...
3163
  			struct reparse_data *reparse_buf =
50c2f7538   Steve French   [CIFS] whitespace...
3164
3165
3166
  						(struct reparse_data *)
  						((char *)&pSMBr->hdr.Protocol
  								 + data_offset);
afe48c31e   Steve French   [CIFS] Fix final ...
3167
3168
3169
3170
3171
3172
3173
  			if ((char *)reparse_buf >= end_of_smb) {
  				rc = -EIO;
  				goto qreparse_out;
  			}
  			if ((reparse_buf->LinkNamesBuf +
  				reparse_buf->TargetNameOffset +
  				reparse_buf->TargetNameLen) > end_of_smb) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3174
  				cFYI(1, "reparse buf beyond SMB");
afe48c31e   Steve French   [CIFS] Fix final ...
3175
3176
3177
  				rc = -EIO;
  				goto qreparse_out;
  			}
50c2f7538   Steve French   [CIFS] whitespace...
3178

afe48c31e   Steve French   [CIFS] Fix final ...
3179
3180
  			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
  				cifs_from_ucs2(symlinkinfo, (__le16 *)
50c2f7538   Steve French   [CIFS] whitespace...
3181
3182
  						(reparse_buf->LinkNamesBuf +
  						reparse_buf->TargetNameOffset),
afe48c31e   Steve French   [CIFS] Fix final ...
3183
3184
3185
3186
3187
3188
3189
3190
3191
  						buflen,
  						reparse_buf->TargetNameLen,
  						nls_codepage, 0);
  			} else { /* ASCII names */
  				strncpy(symlinkinfo,
  					reparse_buf->LinkNamesBuf +
  					reparse_buf->TargetNameOffset,
  					min_t(const int, buflen,
  					   reparse_buf->TargetNameLen));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3192
  			}
afe48c31e   Steve French   [CIFS] Fix final ...
3193
3194
  		} else {
  			rc = -EIO;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3195
3196
  			cFYI(1, "Invalid return data count on "
  				 "get reparse info ioctl");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3197
  		}
afe48c31e   Steve French   [CIFS] Fix final ...
3198
3199
  		symlinkinfo[buflen] = 0; /* just in case so the caller
  					does not go off the end of the buffer */
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3200
  		cFYI(1, "readlink result - %s", symlinkinfo);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3201
  	}
989c7e512   Steve French   [CIFS] remove che...
3202

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3203
  qreparse_out:
4a6d87f1d   Steve French   [CIFS] Add missin...
3204
  	cifs_buf_release(pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3205
3206
3207
3208
3209
3210
  
  	/* Note: On -EAGAIN error only caller can retry on handle based calls
  		since file handle passed in no longer valid */
  
  	return rc;
  }
c52a95545   Steve French   Don't compile in ...
3211
  #endif /* CIFS_SYMLINK_EXPERIMENTAL */ /* BB temporarily unused */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3212
3213
3214
3215
  
  #ifdef CONFIG_CIFS_POSIX
  
  /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
50c2f7538   Steve French   [CIFS] whitespace...
3216
3217
  static void cifs_convert_ace(posix_acl_xattr_entry *ace,
  			     struct cifs_posix_ace *cifs_ace)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3218
3219
  {
  	/* u8 cifs fields do not need le conversion */
ff7feac96   Steve French   [CIFS] Fix endian...
3220
3221
3222
  	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));
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3223
  	/* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3224
3225
3226
3227
3228
  
  	return;
  }
  
  /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
50c2f7538   Steve French   [CIFS] whitespace...
3229
3230
  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
3231
3232
3233
3234
  {
  	int size =  0;
  	int i;
  	__u16 count;
50c2f7538   Steve French   [CIFS] whitespace...
3235
3236
3237
  	struct cifs_posix_ace *pACE;
  	struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
  	posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3238
3239
3240
  
  	if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
  		return -EOPNOTSUPP;
790fe579f   Steve French   [CIFS] more white...
3241
  	if (acl_type & ACL_TYPE_ACCESS) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3242
3243
3244
3245
3246
  		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...
3247
  		if (size_of_data_area < size) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3248
3249
  			cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
  				size_of_data_area, size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3250
3251
  			return -EINVAL;
  		}
790fe579f   Steve French   [CIFS] more white...
3252
  	} else if (acl_type & ACL_TYPE_DEFAULT) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3253
3254
3255
3256
3257
3258
3259
3260
  		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...
3261
  		if (size_of_data_area < size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3262
3263
3264
3265
3266
3267
3268
  			return -EINVAL;
  	} else {
  		/* illegal type */
  		return -EINVAL;
  	}
  
  	size = posix_acl_xattr_size(count);
790fe579f   Steve French   [CIFS] more white...
3269
  	if ((buflen == 0) || (local_acl == NULL)) {
50c2f7538   Steve French   [CIFS] whitespace...
3270
  		/* used to query ACL EA size */
790fe579f   Steve French   [CIFS] more white...
3271
  	} else if (size > buflen) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3272
3273
  		return -ERANGE;
  	} else /* buffer big enough */ {
ff7feac96   Steve French   [CIFS] Fix endian...
3274
  		local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
50c2f7538   Steve French   [CIFS] whitespace...
3275
3276
3277
  		for (i = 0; i < count ; i++) {
  			cifs_convert_ace(&local_acl->a_entries[i], pACE);
  			pACE++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3278
3279
3280
3281
  		}
  	}
  	return size;
  }
50c2f7538   Steve French   [CIFS] whitespace...
3282
3283
  static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
  				     const posix_acl_xattr_entry *local_ace)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3284
3285
  {
  	__u16 rc = 0; /* 0 = ACL converted ok */
ff7feac96   Steve French   [CIFS] Fix endian...
3286
3287
  	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
3288
  	/* BB is there a better way to handle the large uid? */
790fe579f   Steve French   [CIFS] more white...
3289
  	if (local_ace->e_id == cpu_to_le32(-1)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3290
3291
  	/* 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...
3292
  	} else
ff7feac96   Steve French   [CIFS] Fix endian...
3293
  		cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3294
  	/*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3295
3296
3297
3298
  	return rc;
  }
  
  /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
50c2f7538   Steve French   [CIFS] whitespace...
3299
3300
  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
3301
3302
  {
  	__u16 rc = 0;
50c2f7538   Steve French   [CIFS] whitespace...
3303
3304
  	struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
  	posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3305
3306
  	int count;
  	int i;
790fe579f   Steve French   [CIFS] more white...
3307
  	if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3308
3309
3310
  		return 0;
  
  	count = posix_acl_xattr_count((size_t)buflen);
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3311
  	cFYI(1, "setting acl with %d entries from buf of length %d and "
63135e088   Steve French   [CIFS] More white...
3312
  		"version of %d",
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3313
  		count, buflen, le32_to_cpu(local_acl->a_version));
790fe579f   Steve French   [CIFS] more white...
3314
  	if (le32_to_cpu(local_acl->a_version) != 2) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3315
3316
  		cFYI(1, "unknown POSIX ACL version %d",
  		     le32_to_cpu(local_acl->a_version));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3317
3318
3319
  		return 0;
  	}
  	cifs_acl->version = cpu_to_le16(1);
790fe579f   Steve French   [CIFS] more white...
3320
  	if (acl_type == ACL_TYPE_ACCESS)
ff7feac96   Steve French   [CIFS] Fix endian...
3321
  		cifs_acl->access_entry_count = cpu_to_le16(count);
790fe579f   Steve French   [CIFS] more white...
3322
  	else if (acl_type == ACL_TYPE_DEFAULT)
ff7feac96   Steve French   [CIFS] Fix endian...
3323
  		cifs_acl->default_entry_count = cpu_to_le16(count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3324
  	else {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3325
  		cFYI(1, "unknown ACL type %d", acl_type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3326
3327
  		return 0;
  	}
50c2f7538   Steve French   [CIFS] whitespace...
3328
  	for (i = 0; i < count; i++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3329
3330
  		rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
  					&local_acl->a_entries[i]);
790fe579f   Steve French   [CIFS] more white...
3331
  		if (rc != 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3332
3333
3334
3335
  			/* ACE not converted */
  			break;
  		}
  	}
790fe579f   Steve French   [CIFS] more white...
3336
  	if (rc == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3337
3338
3339
3340
3341
3342
3343
3344
  		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
96daf2b09   Steve French   [CIFS] Rename thr...
3345
  CIFSSMBGetPosixACL(const int xid, struct cifs_tcon *tcon,
50c2f7538   Steve French   [CIFS] whitespace...
3346
3347
3348
  		   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
3349
3350
3351
3352
3353
3354
3355
3356
  {
  /* 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...
3357

b6b38f704   Joe Perches   [CIFS] Neaten cER...
3358
  	cFYI(1, "In GetPosixACL (Unix) for path %s", searchName);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3359
3360
3361
3362
3363
3364
  
  queryAclRetry:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  		(void **) &pSMBr);
  	if (rc)
  		return rc;
50c2f7538   Steve French   [CIFS] whitespace...
3365

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3366
3367
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		name_len =
50c2f7538   Steve French   [CIFS] whitespace...
3368
  			cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
737b758c9   Steve French   [PATCH] cifs: cha...
3369
  					 PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3370
3371
3372
3373
  		name_len++;     /* trailing null */
  		name_len *= 2;
  		pSMB->FileName[name_len] = 0;
  		pSMB->FileName[name_len+1] = 0;
50c2f7538   Steve French   [CIFS] whitespace...
3374
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3375
3376
3377
3378
3379
3380
3381
3382
  		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...
3383
  	/* BB find exact max data count below from sess structure BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3384
3385
3386
3387
3388
3389
3390
  	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...
3391
3392
  		offsetof(struct smb_com_transaction2_qpi_req,
  			 InformationLevel) - 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
  	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 ...
3403
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3404
3405
3406
3407
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
0a4b92c05   Steve French   [CIFS] Add worker...
3408
  	cifs_stats_inc(&tcon->num_acl_get);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3409
  	if (rc) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3410
  		cFYI(1, "Send error in Query POSIX ACL = %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3411
3412
  	} else {
  		/* decode response */
50c2f7538   Steve French   [CIFS] whitespace...
3413

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3414
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3415
  		/* BB also check enough total bytes returned */
820a803ff   Jeff Layton   cifs: keep BCC in...
3416
  		if (rc || get_bcc(&pSMBr->hdr) < 2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3417
3418
3419
3420
3421
3422
  			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...
3423
  				buflen, acl_type, count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3424
3425
3426
3427
3428
3429
3430
3431
3432
  		}
  	}
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto queryAclRetry;
  	return rc;
  }
  
  int
96daf2b09   Steve French   [CIFS] Rename thr...
3433
  CIFSSMBSetPosixACL(const int xid, struct cifs_tcon *tcon,
50c2f7538   Steve French   [CIFS] whitespace...
3434
3435
3436
3437
  		   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
3438
3439
3440
3441
3442
3443
3444
3445
  {
  	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;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3446
  	cFYI(1, "In SetPosixACL (Unix) for path %s", fileName);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3447
3448
  setAclRetry:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
50c2f7538   Steve French   [CIFS] whitespace...
3449
  		      (void **) &pSMBr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3450
3451
3452
3453
  	if (rc)
  		return rc;
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		name_len =
50c2f7538   Steve French   [CIFS] whitespace...
3454
  			cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
737b758c9   Steve French   [PATCH] cifs: cha...
3455
  				      PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3456
3457
  		name_len++;     /* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
3458
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3459
3460
3461
3462
3463
3464
  		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...
3465
3466
  	/* BB find max SMB size from sess */
  	pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3467
3468
3469
3470
3471
3472
  	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...
3473
  				InformationLevel) - 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3474
3475
3476
3477
3478
  	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...
3479
  	data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3480

790fe579f   Steve French   [CIFS] more white...
3481
  	if (data_count == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
  		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 ...
3496
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3497
3498
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
50c2f7538   Steve French   [CIFS] whitespace...
3499
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
ad7a2926b   Steve French   [CIFS] reduce che...
3500
  	if (rc)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3501
  		cFYI(1, "Set POSIX ACL returned %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3502
3503
3504
3505
3506
3507
3508
  
  setACLerrorExit:
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto setAclRetry;
  	return rc;
  }
f654bac22   Steve French   [PATCH] cifs: add...
3509
3510
  /* BB fix tabs in this function FIXME BB */
  int
96daf2b09   Steve French   [CIFS] Rename thr...
3511
  CIFSGetExtAttr(const int xid, struct cifs_tcon *tcon,
ad7a2926b   Steve French   [CIFS] reduce che...
3512
  	       const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
f654bac22   Steve French   [PATCH] cifs: add...
3513
  {
50c2f7538   Steve French   [CIFS] whitespace...
3514
3515
3516
3517
3518
  	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...
3519

b6b38f704   Joe Perches   [CIFS] Neaten cER...
3520
  	cFYI(1, "In GetExtAttr");
790fe579f   Steve French   [CIFS] more white...
3521
3522
  	if (tcon == NULL)
  		return -ENODEV;
f654bac22   Steve French   [PATCH] cifs: add...
3523
3524
  
  GetExtAttrRetry:
790fe579f   Steve French   [CIFS] more white...
3525
3526
3527
3528
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  			(void **) &pSMBr);
  	if (rc)
  		return rc;
f654bac22   Steve French   [PATCH] cifs: add...
3529

ad7a2926b   Steve French   [CIFS] reduce che...
3530
  	params = 2 /* level */ + 2 /* fid */;
790fe579f   Steve French   [CIFS] more white...
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
  	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...
3552
  	pSMB->Fid = netfid;
be8e3b004   Steve French   consistently use ...
3553
  	inc_rfc1001_len(pSMB, byte_count);
790fe579f   Steve French   [CIFS] more white...
3554
3555
3556
3557
3558
  	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) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3559
  		cFYI(1, "error %d in GetExtAttr", rc);
790fe579f   Steve French   [CIFS] more white...
3560
3561
3562
  	} else {
  		/* decode response */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
790fe579f   Steve French   [CIFS] more white...
3563
  		/* BB also check enough total bytes returned */
820a803ff   Jeff Layton   cifs: keep BCC in...
3564
  		if (rc || get_bcc(&pSMBr->hdr) < 2)
790fe579f   Steve French   [CIFS] more white...
3565
3566
3567
3568
3569
3570
3571
3572
3573
  			/* 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) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3574
  				cFYI(1, "Illegal size ret in GetExtAttr");
790fe579f   Steve French   [CIFS] more white...
3575
3576
3577
3578
3579
3580
  				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...
3581
  			*pMask = le64_to_cpu(pfinfo->mask);
790fe579f   Steve French   [CIFS] more white...
3582
3583
  		}
  	}
f654bac22   Steve French   [PATCH] cifs: add...
3584
  GetExtAttrOut:
790fe579f   Steve French   [CIFS] more white...
3585
3586
3587
3588
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto GetExtAttrRetry;
  	return rc;
f654bac22   Steve French   [PATCH] cifs: add...
3589
  }
f654bac22   Steve French   [PATCH] cifs: add...
3590
  #endif /* CONFIG_POSIX */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3591

79df1baee   Jeff Layton   cifs: fix use of ...
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
  #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...
3603
  		   const int parm_len, struct cifs_tcon *tcon,
79df1baee   Jeff Layton   cifs: fix use of ...
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
  		   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...
3618
  	pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
79df1baee   Jeff Layton   cifs: fix use of ...
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
  	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...
3637
  	u16 bcc;
79df1baee   Jeff Layton   cifs: fix use of ...
3638
3639
3640
3641
3642
3643
3644
3645
  
  	*pdatalen = 0;
  	*pparmlen = 0;
  
  	if (buf == NULL)
  		return -EINVAL;
  
  	pSMBr = (struct smb_com_ntransact_rsp *)buf;
820a803ff   Jeff Layton   cifs: keep BCC in...
3646
3647
  	bcc = get_bcc(&pSMBr->hdr);
  	end_of_smb = 2 /* sizeof byte count */ + bcc +
79df1baee   Jeff Layton   cifs: fix use of ...
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
  			(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) {
  		cFYI(1, "parms start after end of smb");
  		return -EINVAL;
  	} else if (parm_count + *ppparm > end_of_smb) {
  		cFYI(1, "parm end after end of smb");
  		return -EINVAL;
  	} else if (*ppdata > end_of_smb) {
  		cFYI(1, "data starts after end of smb");
  		return -EINVAL;
  	} else if (data_count + *ppdata > end_of_smb) {
  		cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
  			*ppdata, data_count, (data_count + *ppdata),
  			end_of_smb, pSMBr);
  		return -EINVAL;
820a803ff   Jeff Layton   cifs: keep BCC in...
3673
  	} else if (parm_count + data_count > bcc) {
79df1baee   Jeff Layton   cifs: fix use of ...
3674
3675
3676
3677
3678
3679
3680
  		cFYI(1, "parm count and data count larger than SMB");
  		return -EINVAL;
  	}
  	*pdatalen = data_count;
  	*pparmlen = parm_count;
  	return 0;
  }
0a4b92c05   Steve French   [CIFS] Add worker...
3681
3682
  /* Get Security Descriptor (by handle) from remote server for a file or dir */
  int
96daf2b09   Steve French   [CIFS] Rename thr...
3683
  CIFSSMBGetCIFSACL(const int xid, struct cifs_tcon *tcon, __u16 fid,
630f3f0c4   Steve French   [CIFS] acl suppor...
3684
  		  struct cifs_ntsd **acl_inf, __u32 *pbuflen)
0a4b92c05   Steve French   [CIFS] Add worker...
3685
3686
3687
  {
  	int rc = 0;
  	int buf_type = 0;
ad7a2926b   Steve French   [CIFS] reduce che...
3688
  	QUERY_SEC_DESC_REQ *pSMB;
0a4b92c05   Steve French   [CIFS] Add worker...
3689
  	struct kvec iov[1];
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3690
  	cFYI(1, "GetCifsACL");
0a4b92c05   Steve French   [CIFS] Add worker...
3691

630f3f0c4   Steve French   [CIFS] acl suppor...
3692
3693
  	*pbuflen = 0;
  	*acl_inf = NULL;
b9c7a2bb1   Steve French   [CIFS] ACL suppor...
3694
  	rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
0a4b92c05   Steve French   [CIFS] Add worker...
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
  			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 ...
3706
  	inc_rfc1001_len(pSMB, 11);
0a4b92c05   Steve French   [CIFS] Add worker...
3707
  	iov[0].iov_base = (char *)pSMB;
be8e3b004   Steve French   consistently use ...
3708
  	iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
0a4b92c05   Steve French   [CIFS] Add worker...
3709

a761ac579   Steve French   [CIFS] log better...
3710
  	rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
7749981ec   Jeff Layton   cifs: remove code...
3711
  			 0);
0a4b92c05   Steve French   [CIFS] Add worker...
3712
3713
  	cifs_stats_inc(&tcon->num_acl_get);
  	if (rc) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3714
  		cFYI(1, "Send error in QuerySecDesc = %d", rc);
0a4b92c05   Steve French   [CIFS] Add worker...
3715
  	} else {                /* decode response */
ad7a2926b   Steve French   [CIFS] reduce che...
3716
  		__le32 *parm;
630f3f0c4   Steve French   [CIFS] acl suppor...
3717
3718
  		__u32 parm_len;
  		__u32 acl_len;
50c2f7538   Steve French   [CIFS] whitespace...
3719
  		struct smb_com_ntransact_rsp *pSMBr;
630f3f0c4   Steve French   [CIFS] acl suppor...
3720
  		char *pdata;
0a4b92c05   Steve French   [CIFS] Add worker...
3721
3722
  
  /* validate_nttransact */
50c2f7538   Steve French   [CIFS] whitespace...
3723
  		rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
630f3f0c4   Steve French   [CIFS] acl suppor...
3724
  					&pdata, &parm_len, pbuflen);
790fe579f   Steve French   [CIFS] more white...
3725
  		if (rc)
0a4b92c05   Steve French   [CIFS] Add worker...
3726
3727
  			goto qsec_out;
  		pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3728
  		cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf);
0a4b92c05   Steve French   [CIFS] Add worker...
3729
3730
3731
  
  		if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
  			rc = -EIO;      /* bad smb */
630f3f0c4   Steve French   [CIFS] acl suppor...
3732
  			*pbuflen = 0;
0a4b92c05   Steve French   [CIFS] Add worker...
3733
3734
3735
3736
  			goto qsec_out;
  		}
  
  /* BB check that data area is minimum length and as big as acl_len */
af6f4612f   Steve French   [CIFS] Fix some e...
3737
  		acl_len = le32_to_cpu(*parm);
630f3f0c4   Steve French   [CIFS] acl suppor...
3738
  		if (acl_len != *pbuflen) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3739
3740
  			cERROR(1, "acl length %d does not match %d",
  				   acl_len, *pbuflen);
630f3f0c4   Steve French   [CIFS] acl suppor...
3741
3742
3743
  			if (*pbuflen > acl_len)
  				*pbuflen = acl_len;
  		}
0a4b92c05   Steve French   [CIFS] Add worker...
3744

630f3f0c4   Steve French   [CIFS] acl suppor...
3745
3746
3747
3748
  		/* 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)) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3749
  			cERROR(1, "bad acl length %d", *pbuflen);
630f3f0c4   Steve French   [CIFS] acl suppor...
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
  			rc = -EINVAL;
  			*pbuflen = 0;
  		} else {
  			*acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
  			if (*acl_inf == NULL) {
  				*pbuflen = 0;
  				rc = -ENOMEM;
  			}
  			memcpy(*acl_inf, pdata, *pbuflen);
  		}
0a4b92c05   Steve French   [CIFS] Add worker...
3760
3761
  	}
  qsec_out:
790fe579f   Steve French   [CIFS] more white...
3762
  	if (buf_type == CIFS_SMALL_BUFFER)
0a4b92c05   Steve French   [CIFS] Add worker...
3763
  		cifs_small_buf_release(iov[0].iov_base);
790fe579f   Steve French   [CIFS] more white...
3764
  	else if (buf_type == CIFS_LARGE_BUFFER)
0a4b92c05   Steve French   [CIFS] Add worker...
3765
  		cifs_buf_release(iov[0].iov_base);
4b8f930ff   Steve French   [CIFS] Free small...
3766
  /*	cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
0a4b92c05   Steve French   [CIFS] Add worker...
3767
3768
  	return rc;
  }
97837582b   Steve French   [CIFS] Allow sett...
3769
3770
  
  int
96daf2b09   Steve French   [CIFS] Rename thr...
3771
  CIFSSMBSetCIFSACL(const int xid, struct cifs_tcon *tcon, __u16 fid,
a5ff37696   Shirish Pargaonkar   cifs: Call id to ...
3772
  			struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
97837582b   Steve French   [CIFS] Allow sett...
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
  {
  	__u16 byte_count, param_count, data_count, param_offset, data_offset;
  	int rc = 0;
  	int bytes_returned = 0;
  	SET_SEC_DESC_REQ *pSMB = NULL;
  	NTRANSACT_RSP *pSMBr = NULL;
  
  setCifsAclRetry:
  	rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
  			(void **) &pSMBr);
  	if (rc)
  			return (rc);
  
  	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 ...
3809
  	pSMB->AclFlags = cpu_to_le32(aclflag);
97837582b   Steve French   [CIFS] Allow sett...
3810
3811
3812
3813
3814
  
  	if (pntsd && acllen) {
  		memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
  			(char *) pntsd,
  			acllen);
be8e3b004   Steve French   consistently use ...
3815
  		inc_rfc1001_len(pSMB, byte_count + data_count);
97837582b   Steve French   [CIFS] Allow sett...
3816
  	} else
be8e3b004   Steve French   consistently use ...
3817
  		inc_rfc1001_len(pSMB, byte_count);
97837582b   Steve French   [CIFS] Allow sett...
3818
3819
3820
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3821
  	cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
97837582b   Steve French   [CIFS] Allow sett...
3822
  	if (rc)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3823
  		cFYI(1, "Set CIFS ACL returned %d", rc);
97837582b   Steve French   [CIFS] Allow sett...
3824
3825
3826
3827
3828
3829
3830
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto setCifsAclRetry;
  
  	return (rc);
  }
79df1baee   Jeff Layton   cifs: fix use of ...
3831
  #endif /* CONFIG_CIFS_ACL */
0a4b92c05   Steve French   [CIFS] Add worker...
3832

6b8edfe0f   Steve French   [CIFS] Support fo...
3833
3834
  /* Legacy Query Path Information call for lookup to old servers such
     as Win9x/WinME */
96daf2b09   Steve French   [CIFS] Rename thr...
3835
  int SMBQueryInformation(const int xid, struct cifs_tcon *tcon,
50c2f7538   Steve French   [CIFS] whitespace...
3836
3837
3838
  			const unsigned char *searchName,
  			FILE_ALL_INFO *pFinfo,
  			const struct nls_table *nls_codepage, int remap)
6b8edfe0f   Steve French   [CIFS] Support fo...
3839
  {
ad7a2926b   Steve French   [CIFS] reduce che...
3840
3841
  	QUERY_INFORMATION_REQ *pSMB;
  	QUERY_INFORMATION_RSP *pSMBr;
6b8edfe0f   Steve French   [CIFS] Support fo...
3842
3843
3844
  	int rc = 0;
  	int bytes_returned;
  	int name_len;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3845
  	cFYI(1, "In SMBQPath path %s", searchName);
6b8edfe0f   Steve French   [CIFS] Support fo...
3846
3847
  QInfRetry:
  	rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
50c2f7538   Steve French   [CIFS] whitespace...
3848
  		      (void **) &pSMBr);
6b8edfe0f   Steve French   [CIFS] Support fo...
3849
3850
3851
3852
3853
  	if (rc)
  		return rc;
  
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		name_len =
50c2f7538   Steve French   [CIFS] whitespace...
3854
3855
  			cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
  					PATH_MAX, nls_codepage, remap);
6b8edfe0f   Steve French   [CIFS] Support fo...
3856
3857
  		name_len++;     /* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
3858
  	} else {
6b8edfe0f   Steve French   [CIFS] Support fo...
3859
3860
3861
3862
3863
  		name_len = strnlen(searchName, PATH_MAX);
  		name_len++;     /* trailing null */
  		strncpy(pSMB->FileName, searchName, name_len);
  	}
  	pSMB->BufferFormat = 0x04;
50c2f7538   Steve French   [CIFS] whitespace...
3864
  	name_len++; /* account for buffer type byte */
be8e3b004   Steve French   consistently use ...
3865
  	inc_rfc1001_len(pSMB, (__u16)name_len);
6b8edfe0f   Steve French   [CIFS] Support fo...
3866
3867
3868
  	pSMB->ByteCount = cpu_to_le16(name_len);
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
50c2f7538   Steve French   [CIFS] whitespace...
3869
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6b8edfe0f   Steve French   [CIFS] Support fo...
3870
  	if (rc) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3871
  		cFYI(1, "Send error in QueryInfo = %d", rc);
ad7a2926b   Steve French   [CIFS] reduce che...
3872
  	} else if (pFinfo) {
1bd5bbcb6   Steve French   [CIFS] Legacy tim...
3873
3874
  		struct timespec ts;
  		__u32 time = le32_to_cpu(pSMBr->last_write_time);
ad7a2926b   Steve French   [CIFS] reduce che...
3875
3876
  
  		/* decode response */
1bd5bbcb6   Steve French   [CIFS] Legacy tim...
3877
  		/* BB FIXME - add time zone adjustment BB */
6b8edfe0f   Steve French   [CIFS] Support fo...
3878
  		memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
1bd5bbcb6   Steve French   [CIFS] Legacy tim...
3879
3880
3881
  		ts.tv_nsec = 0;
  		ts.tv_sec = time;
  		/* decode time fields */
733f99acc   Al Viro   [PATCH] new cifs ...
3882
  		pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
1bd5bbcb6   Steve French   [CIFS] Legacy tim...
3883
3884
  		pFinfo->LastWriteTime = pFinfo->ChangeTime;
  		pFinfo->LastAccessTime = 0;
70ca734a1   Steve French   [CIFS] Various mi...
3885
3886
3887
3888
3889
  		pFinfo->AllocationSize =
  			cpu_to_le64(le32_to_cpu(pSMBr->size));
  		pFinfo->EndOfFile = pFinfo->AllocationSize;
  		pFinfo->Attributes =
  			cpu_to_le32(le16_to_cpu(pSMBr->attr));
6b8edfe0f   Steve French   [CIFS] Support fo...
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
  	} 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...
3900
  int
96daf2b09   Steve French   [CIFS] Rename thr...
3901
  CIFSSMBQFileInfo(const int xid, struct cifs_tcon *tcon,
bcd5357f4   Jeff Layton   cifs: add a CIFSS...
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
  		 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 ...
3939
  	inc_rfc1001_len(pSMB, byte_count);
6b8edfe0f   Steve French   [CIFS] Support fo...
3940

bcd5357f4   Jeff Layton   cifs: add a CIFSS...
3941
3942
3943
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  	if (rc) {
f19159dc5   Steve French   [CIFS] Cleanup va...
3944
  		cFYI(1, "Send error in QPathInfo = %d", rc);
bcd5357f4   Jeff Layton   cifs: add a CIFSS...
3945
3946
  	} else {		/* decode response */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
6b8edfe0f   Steve French   [CIFS] Support fo...
3947

bcd5357f4   Jeff Layton   cifs: add a CIFSS...
3948
3949
  		if (rc) /* BB add auto retry on EOPNOTSUPP? */
  			rc = -EIO;
820a803ff   Jeff Layton   cifs: keep BCC in...
3950
  		else if (get_bcc(&pSMBr->hdr) < 40)
bcd5357f4   Jeff Layton   cifs: add a CIFSS...
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
  			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...
3963

bcd5357f4   Jeff Layton   cifs: add a CIFSS...
3964
3965
  	return rc;
  }
6b8edfe0f   Steve French   [CIFS] Support fo...
3966

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3967
  int
96daf2b09   Steve French   [CIFS] Rename thr...
3968
  CIFSSMBQPathInfo(const int xid, struct cifs_tcon *tcon,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3969
  		 const unsigned char *searchName,
ad7a2926b   Steve French   [CIFS] reduce che...
3970
  		 FILE_ALL_INFO *pFindData,
acf1a1b10   Steve French   [CIFS] Level 1 QP...
3971
  		 int legacy /* old style infolevel */,
737b758c9   Steve French   [PATCH] cifs: cha...
3972
  		 const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3973
3974
3975
3976
3977
3978
3979
3980
  {
  /* level 263 SMB_QUERY_FILE_ALL_INFO */
  	TRANSACTION2_QPI_REQ *pSMB = NULL;
  	TRANSACTION2_QPI_RSP *pSMBr = NULL;
  	int rc = 0;
  	int bytes_returned;
  	int name_len;
  	__u16 params, byte_count;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3981
  /* cFYI(1, "In QPathInfo path %s", searchName); */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3982
3983
3984
3985
3986
3987
3988
3989
  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 =
50c2f7538   Steve French   [CIFS] whitespace...
3990
  		    cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
737b758c9   Steve French   [PATCH] cifs: cha...
3991
  				     PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3992
3993
  		name_len++;	/* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
3994
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3995
3996
3997
3998
  		name_len = strnlen(searchName, PATH_MAX);
  		name_len++;	/* trailing null */
  		strncpy(pSMB->FileName, searchName, name_len);
  	}
50c2f7538   Steve French   [CIFS] whitespace...
3999
  	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4000
4001
  	pSMB->TotalDataCount = 0;
  	pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5e   Steve French   [CIFS] cleanup ol...
4002
4003
  	/* BB find exact max SMB PDU from sess structure BB */
  	pSMB->MaxDataCount = cpu_to_le16(4000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4004
4005
4006
4007
4008
4009
  	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...
4010
  	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4011
4012
4013
4014
4015
4016
4017
4018
  	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...
4019
  	if (legacy)
acf1a1b10   Steve French   [CIFS] Level 1 QP...
4020
4021
4022
  		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
4023
  	pSMB->Reserved4 = 0;
be8e3b004   Steve French   consistently use ...
4024
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4025
4026
4027
4028
4029
  	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) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
4030
  		cFYI(1, "Send error in QPathInfo = %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4031
4032
  	} else {		/* decode response */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
acf1a1b10   Steve French   [CIFS] Level 1 QP...
4033
4034
  		if (rc) /* BB add auto retry on EOPNOTSUPP? */
  			rc = -EIO;
820a803ff   Jeff Layton   cifs: keep BCC in...
4035
  		else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4036
  			rc = -EIO;	/* bad smb */
820a803ff   Jeff Layton   cifs: keep BCC in...
4037
  		else if (legacy && get_bcc(&pSMBr->hdr) < 24)
50c2f7538   Steve French   [CIFS] whitespace...
4038
4039
4040
  			rc = -EIO;  /* 24 or 26 expected but we do not read
  					last field */
  		else if (pFindData) {
acf1a1b10   Steve French   [CIFS] Level 1 QP...
4041
  			int size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4042
  			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
ad7a2926b   Steve French   [CIFS] reduce che...
4043
4044
4045
4046
4047
4048
  
  			/* 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 */
  			if (legacy)
acf1a1b10   Steve French   [CIFS] Level 1 QP...
4049
4050
4051
  				size = sizeof(FILE_INFO_STANDARD);
  			else
  				size = sizeof(FILE_ALL_INFO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4052
4053
  			memcpy((char *) pFindData,
  			       (char *) &pSMBr->hdr.Protocol +
acf1a1b10   Steve French   [CIFS] Level 1 QP...
4054
  			       data_offset, size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
  		} else
  		    rc = -ENOMEM;
  	}
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto QPathInfoRetry;
  
  	return rc;
  }
  
  int
96daf2b09   Steve French   [CIFS] Rename thr...
4066
  CIFSSMBUnixQFileInfo(const int xid, struct cifs_tcon *tcon,
c8634fd31   Jeff Layton   cifs: add a CIFSS...
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
  		 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 ...
4104
  	inc_rfc1001_len(pSMB, byte_count);
c8634fd31   Jeff Layton   cifs: add a CIFSS...
4105
4106
4107
4108
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  	if (rc) {
f19159dc5   Steve French   [CIFS] Cleanup va...
4109
  		cFYI(1, "Send error in QPathInfo = %d", rc);
c8634fd31   Jeff Layton   cifs: add a CIFSS...
4110
4111
  	} else {		/* decode response */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
820a803ff   Jeff Layton   cifs: keep BCC in...
4112
  		if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
f19159dc5   Steve French   [CIFS] Cleanup va...
4113
4114
  			cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.
  "
c8634fd31   Jeff Layton   cifs: add a CIFSS...
4115
  				   "Unix Extensions can be disabled on mount "
f19159dc5   Steve French   [CIFS] Cleanup va...
4116
  				   "by specifying the nosfu mount option.");
c8634fd31   Jeff Layton   cifs: add a CIFSS...
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
  			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
96daf2b09   Steve French   [CIFS] Rename thr...
4135
  CIFSSMBUnixQPathInfo(const int xid, struct cifs_tcon *tcon,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4136
  		     const unsigned char *searchName,
582d21e5e   Steve French   [CIFS] cleanup ol...
4137
  		     FILE_UNIX_BASIC_INFO *pFindData,
737b758c9   Steve French   [PATCH] cifs: cha...
4138
  		     const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4139
4140
4141
4142
4143
4144
4145
4146
  {
  /* 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;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
4147
  	cFYI(1, "In QPathInfo (Unix) the path %s", searchName);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4148
4149
4150
4151
4152
4153
4154
4155
  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 =
b1a45695b   Steve French   [CIFS] fix casts ...
4156
  		    cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
737b758c9   Steve French   [PATCH] cifs: cha...
4157
  				  PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4158
4159
  		name_len++;	/* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
4160
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4161
4162
4163
4164
  		name_len = strnlen(searchName, PATH_MAX);
  		name_len++;	/* trailing null */
  		strncpy(pSMB->FileName, searchName, name_len);
  	}
50c2f7538   Steve French   [CIFS] whitespace...
4165
  	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4166
4167
4168
  	pSMB->TotalDataCount = 0;
  	pSMB->MaxParameterCount = cpu_to_le16(2);
  	/* BB find exact max SMB PDU from sess structure BB */
50c2f7538   Steve French   [CIFS] whitespace...
4169
  	pSMB->MaxDataCount = cpu_to_le16(4000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4170
4171
4172
4173
4174
4175
  	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...
4176
  	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
  	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 ...
4187
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4188
4189
4190
4191
4192
  	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) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
4193
  		cFYI(1, "Send error in QPathInfo = %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4194
4195
  	} else {		/* decode response */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
820a803ff   Jeff Layton   cifs: keep BCC in...
4196
  		if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
4197
4198
  			cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.
  "
1e71f25d1   Steve French   [CIFS] Print bett...
4199
  				   "Unix Extensions can be disabled on mount "
b6b38f704   Joe Perches   [CIFS] Neaten cER...
4200
  				   "by specifying the nosfu mount option.");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4201
4202
4203
4204
4205
4206
  			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...
4207
  			       sizeof(FILE_UNIX_BASIC_INFO));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4208
4209
4210
4211
4212
4213
4214
4215
  		}
  	}
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto UnixQPathInfoRetry;
  
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4216
4217
  /* xid, tcon, searchName and codepage are input parms, rest are returned */
  int
96daf2b09   Steve French   [CIFS] Rename thr...
4218
  CIFSFindFirst(const int xid, struct cifs_tcon *tcon,
50c2f7538   Steve French   [CIFS] whitespace...
4219
  	      const char *searchName,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4220
  	      const struct nls_table *nls_codepage,
50c2f7538   Steve French   [CIFS] whitespace...
4221
4222
  	      __u16 *pnetfid,
  	      struct cifs_search_info *psrch_inf, int remap, const char dirsep)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4223
4224
4225
4226
  {
  /* level 257 SMB_ */
  	TRANSACTION2_FFIRST_REQ *pSMB = NULL;
  	TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
ad7a2926b   Steve French   [CIFS] reduce che...
4227
  	T2_FFIRST_RSP_PARMS *parms;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4228
4229
4230
4231
  	int rc = 0;
  	int bytes_returned = 0;
  	int name_len;
  	__u16 params, byte_count;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
4232
  	cFYI(1, "In FindFirst for %s", searchName);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4233
4234
4235
4236
4237
4238
4239
4240
4241
  
  findFirstRetry:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  		      (void **) &pSMBr);
  	if (rc)
  		return rc;
  
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		name_len =
50c2f7538   Steve French   [CIFS] whitespace...
4242
  		    cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
737b758c9   Steve French   [PATCH] cifs: cha...
4243
4244
4245
4246
  				 PATH_MAX, nls_codepage, remap);
  		/* 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
4247
  		name_len *= 2;
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
4248
  		pSMB->FileName[name_len] = dirsep;
737b758c9   Steve French   [PATCH] cifs: cha...
4249
4250
4251
4252
  		pSMB->FileName[name_len+1] = 0;
  		pSMB->FileName[name_len+2] = '*';
  		pSMB->FileName[name_len+3] = 0;
  		name_len += 4; /* now the trailing null */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4253
4254
  		pSMB->FileName[name_len] = 0; /* null terminate just in case */
  		pSMB->FileName[name_len+1] = 0;
737b758c9   Steve French   [PATCH] cifs: cha...
4255
  		name_len += 2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4256
4257
  	} else {	/* BB add check for overrun of SMB buf BB */
  		name_len = strnlen(searchName, PATH_MAX);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4258
  /* BB fix here and in unicode clause above ie
790fe579f   Steve French   [CIFS] more white...
4259
  		if (name_len > buffersize-header)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4260
4261
  			free buffer exit; BB */
  		strncpy(pSMB->FileName, searchName, name_len);
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
4262
  		pSMB->FileName[name_len] = dirsep;
685754767   Steve French   [PATCH] cifs: app...
4263
4264
4265
  		pSMB->FileName[name_len+1] = '*';
  		pSMB->FileName[name_len+2] = 0;
  		name_len += 3;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4266
4267
4268
4269
4270
  	}
  
  	params = 12 + name_len /* includes null */ ;
  	pSMB->TotalDataCount = 0;	/* no EAs */
  	pSMB->MaxParameterCount = cpu_to_le16(10);
c974befa4   Jeff Layton   cifs: untangle se...
4271
  	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4272
4273
4274
4275
4276
4277
4278
4279
4280
  	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...
4281
4282
  	      offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
  		- 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4283
4284
4285
4286
4287
4288
4289
4290
  	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...
4291
4292
  	pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
  	pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4293
4294
4295
4296
4297
  		CIFS_SEARCH_RETURN_RESUME);
  	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 ...
4298
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4299
4300
4301
4302
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
a45443475   Steve French   CIFS: Reduce CONF...
4303
  	cifs_stats_inc(&tcon->num_ffirst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4304

88274815f   Steve French   [CIFS] Fix two re...
4305
4306
  	if (rc) {/* BB add logic to retry regular search if Unix search
  			rejected unexpectedly by server */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4307
  		/* BB Add code to handle unsupported level rc */
b6b38f704   Joe Perches   [CIFS] Neaten cER...
4308
  		cFYI(1, "Error in FindFirst = %d", rc);
1982c344f   Steve French   [CIFS] Ensure tha...
4309

88274815f   Steve French   [CIFS] Fix two re...
4310
  		cifs_buf_release(pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4311
4312
4313
4314
4315
4316
4317
4318
  
  		/* 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...
4319
  		if (rc == 0) {
b77d753c4   Steve French   [CIFS] Check that...
4320
  			unsigned int lnoff;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4321
  			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4b18f2a9c   Steve French   [CIFS] convert us...
4322
  				psrch_inf->unicode = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4323
  			else
4b18f2a9c   Steve French   [CIFS] convert us...
4324
  				psrch_inf->unicode = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4325
4326
  
  			psrch_inf->ntwrk_buf_start = (char *)pSMBr;
d47d7c1a8   Steve French   [CIFS] CIFS readd...
4327
  			psrch_inf->smallBuf = 0;
50c2f7538   Steve French   [CIFS] whitespace...
4328
4329
  			psrch_inf->srch_entries_start =
  				(char *) &pSMBr->hdr.Protocol +
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4330
  					le16_to_cpu(pSMBr->t2.DataOffset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4331
4332
  			parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
  			       le16_to_cpu(pSMBr->t2.ParameterOffset));
790fe579f   Steve French   [CIFS] more white...
4333
  			if (parms->EndofSearch)
4b18f2a9c   Steve French   [CIFS] convert us...
4334
  				psrch_inf->endOfSearch = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4335
  			else
4b18f2a9c   Steve French   [CIFS] convert us...
4336
  				psrch_inf->endOfSearch = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4337

50c2f7538   Steve French   [CIFS] whitespace...
4338
4339
  			psrch_inf->entries_in_buffer =
  					le16_to_cpu(parms->SearchCount);
60808233f   Steve French   [CIFS] Readdir fi...
4340
  			psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4341
  				psrch_inf->entries_in_buffer;
b77d753c4   Steve French   [CIFS] Check that...
4342
  			lnoff = le16_to_cpu(parms->LastNameOffset);
c974befa4   Jeff Layton   cifs: untangle se...
4343
  			if (CIFSMaxBufSize < lnoff) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
4344
  				cERROR(1, "ignoring corrupt resume name");
b77d753c4   Steve French   [CIFS] Check that...
4345
4346
4347
  				psrch_inf->last_entry = NULL;
  				return rc;
  			}
0752f1522   Steve French   [CIFS] make sure ...
4348
  			psrch_inf->last_entry = psrch_inf->srch_entries_start +
b77d753c4   Steve French   [CIFS] Check that...
4349
  							lnoff;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4350
4351
4352
4353
4354
4355
4356
4357
  			*pnetfid = parms->SearchHandle;
  		} else {
  			cifs_buf_release(pSMB);
  		}
  	}
  
  	return rc;
  }
96daf2b09   Steve French   [CIFS] Rename thr...
4358
  int CIFSFindNext(const int xid, struct cifs_tcon *tcon,
50c2f7538   Steve French   [CIFS] whitespace...
4359
  		 __u16 searchHandle, struct cifs_search_info *psrch_inf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4360
4361
4362
  {
  	TRANSACTION2_FNEXT_REQ *pSMB = NULL;
  	TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
ad7a2926b   Steve French   [CIFS] reduce che...
4363
  	T2_FNEXT_RSP_PARMS *parms;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4364
4365
  	char *response_data;
  	int rc = 0;
9438fabb7   Jeff Layton   cifs: fix possibl...
4366
4367
  	int bytes_returned;
  	unsigned int name_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4368
  	__u16 params, byte_count;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
4369
  	cFYI(1, "In FindNext");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4370

4b18f2a9c   Steve French   [CIFS] convert us...
4371
  	if (psrch_inf->endOfSearch)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4372
4373
4374
4375
4376
4377
  		return -ENOENT;
  
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  		(void **) &pSMBr);
  	if (rc)
  		return rc;
50c2f7538   Steve French   [CIFS] whitespace...
4378
  	params = 14; /* includes 2 bytes of null string, converted to LE below*/
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4379
4380
4381
  	byte_count = 0;
  	pSMB->TotalDataCount = 0;       /* no EAs */
  	pSMB->MaxParameterCount = cpu_to_le16(8);
c974befa4   Jeff Layton   cifs: untangle se...
4382
  	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
  	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...
4397
  		cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4398
4399
4400
4401
4402
4403
4404
  	pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
  	pSMB->ResumeKey = psrch_inf->resume_key;
  	pSMB->SearchFlags =
  	      cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
  
  	name_len = psrch_inf->resume_name_len;
  	params += name_len;
790fe579f   Steve French   [CIFS] more white...
4405
  	if (name_len < PATH_MAX) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4406
4407
  		memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
  		byte_count += name_len;
ef6724e32   Steve French   [CIFS] Fix missin...
4408
4409
4410
  		/* 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
4411
4412
4413
4414
4415
4416
4417
  	} 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 ...
4418
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4419
  	pSMB->ByteCount = cpu_to_le16(byte_count);
50c2f7538   Steve French   [CIFS] whitespace...
4420

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4421
4422
  	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  			(struct smb_hdr *) pSMBr, &bytes_returned, 0);
a45443475   Steve French   CIFS: Reduce CONF...
4423
  	cifs_stats_inc(&tcon->num_fnext);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4424
4425
  	if (rc) {
  		if (rc == -EBADF) {
4b18f2a9c   Steve French   [CIFS] convert us...
4426
  			psrch_inf->endOfSearch = true;
6353450a2   Jeff Layton   fix memory leak i...
4427
  			cifs_buf_release(pSMB);
50c2f7538   Steve French   [CIFS] whitespace...
4428
  			rc = 0; /* search probably was closed at end of search*/
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4429
  		} else
b6b38f704   Joe Perches   [CIFS] Neaten cER...
4430
  			cFYI(1, "FindNext returned = %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4431
4432
  	} else {                /* decode response */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
50c2f7538   Steve French   [CIFS] whitespace...
4433

790fe579f   Steve French   [CIFS] more white...
4434
  		if (rc == 0) {
b77d753c4   Steve French   [CIFS] Check that...
4435
  			unsigned int lnoff;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4436
4437
  			/* BB fixme add lock for file (srch_info) struct here */
  			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4b18f2a9c   Steve French   [CIFS] convert us...
4438
  				psrch_inf->unicode = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4439
  			else
4b18f2a9c   Steve French   [CIFS] convert us...
4440
  				psrch_inf->unicode = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4441
4442
4443
4444
4445
  			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...
4446
  			if (psrch_inf->smallBuf)
d47d7c1a8   Steve French   [CIFS] CIFS readd...
4447
4448
4449
4450
  				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
4451
4452
  			psrch_inf->srch_entries_start = response_data;
  			psrch_inf->ntwrk_buf_start = (char *)pSMB;
d47d7c1a8   Steve French   [CIFS] CIFS readd...
4453
  			psrch_inf->smallBuf = 0;
790fe579f   Steve French   [CIFS] more white...
4454
  			if (parms->EndofSearch)
4b18f2a9c   Steve French   [CIFS] convert us...
4455
  				psrch_inf->endOfSearch = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4456
  			else
4b18f2a9c   Steve French   [CIFS] convert us...
4457
  				psrch_inf->endOfSearch = false;
50c2f7538   Steve French   [CIFS] whitespace...
4458
4459
  			psrch_inf->entries_in_buffer =
  						le16_to_cpu(parms->SearchCount);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4460
4461
  			psrch_inf->index_of_last_entry +=
  				psrch_inf->entries_in_buffer;
b77d753c4   Steve French   [CIFS] Check that...
4462
  			lnoff = le16_to_cpu(parms->LastNameOffset);
c974befa4   Jeff Layton   cifs: untangle se...
4463
  			if (CIFSMaxBufSize < lnoff) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
4464
  				cERROR(1, "ignoring corrupt resume name");
b77d753c4   Steve French   [CIFS] Check that...
4465
4466
4467
4468
4469
  				psrch_inf->last_entry = NULL;
  				return rc;
  			} else
  				psrch_inf->last_entry =
  					psrch_inf->srch_entries_start + lnoff;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
4470
4471
  /*  cFYI(1, "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
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
  
  			/* 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
4486
4487
4488
4489
  	return rc;
  }
  
  int
96daf2b09   Steve French   [CIFS] Rename thr...
4490
  CIFSFindClose(const int xid, struct cifs_tcon *tcon,
50c2f7538   Steve French   [CIFS] whitespace...
4491
  	      const __u16 searchHandle)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4492
4493
4494
  {
  	int rc = 0;
  	FINDCLOSE_REQ *pSMB = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4495

b6b38f704   Joe Perches   [CIFS] Neaten cER...
4496
  	cFYI(1, "In CIFSSMBFindClose");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4497
4498
4499
4500
  	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...
4501
  	if (rc == -EAGAIN)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4502
4503
4504
  		return 0;
  	if (rc)
  		return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4505
4506
  	pSMB->FileID = searchHandle;
  	pSMB->ByteCount = 0;
133672efb   Steve French   [CIFS] Fix buffer...
4507
  	rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
ad7a2926b   Steve French   [CIFS] reduce che...
4508
  	if (rc)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
4509
  		cERROR(1, "Send error in FindClose = %d", rc);
ad7a2926b   Steve French   [CIFS] reduce che...
4510

a45443475   Steve French   CIFS: Reduce CONF...
4511
  	cifs_stats_inc(&tcon->num_fclose);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4512
4513
4514
4515
4516
4517
4518
  
  	/* 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
4519
  int
96daf2b09   Steve French   [CIFS] Rename thr...
4520
  CIFSGetSrvInodeNumber(const int xid, struct cifs_tcon *tcon,
50c2f7538   Steve French   [CIFS] whitespace...
4521
  		      const unsigned char *searchName,
ad7a2926b   Steve French   [CIFS] reduce che...
4522
  		      __u64 *inode_number,
50c2f7538   Steve French   [CIFS] whitespace...
4523
  		      const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4524
4525
4526
4527
4528
4529
  {
  	int rc = 0;
  	TRANSACTION2_QPI_REQ *pSMB = NULL;
  	TRANSACTION2_QPI_RSP *pSMBr = NULL;
  	int name_len, bytes_returned;
  	__u16 params, byte_count;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
4530
  	cFYI(1, "In GetSrvInodeNum for %s", searchName);
790fe579f   Steve French   [CIFS] more white...
4531
  	if (tcon == NULL)
50c2f7538   Steve French   [CIFS] whitespace...
4532
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4533
4534
4535
  
  GetInodeNumberRetry:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
50c2f7538   Steve French   [CIFS] whitespace...
4536
  		      (void **) &pSMBr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4537
4538
  	if (rc)
  		return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4539
4540
  	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  		name_len =
b1a45695b   Steve French   [CIFS] fix casts ...
4541
  			cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
50c2f7538   Steve French   [CIFS] whitespace...
4542
  					 PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4543
4544
  		name_len++;     /* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
4545
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
  		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);
  	/* 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...
4562
  		struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
  	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 ...
4573
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4574
4575
4576
4577
4578
  	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) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
4579
  		cFYI(1, "error %d in QueryInternalInfo", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4580
4581
4582
  	} else {
  		/* decode response */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4583
  		/* BB also check enough total bytes returned */
820a803ff   Jeff Layton   cifs: keep BCC in...
4584
  		if (rc || get_bcc(&pSMBr->hdr) < 2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4585
4586
4587
  			/* If rc should we check for EOPNOSUPP and
  			disable the srvino flag? or in caller? */
  			rc = -EIO;      /* bad smb */
50c2f7538   Steve French   [CIFS] whitespace...
4588
  		else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4589
4590
  			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
  			__u16 count = le16_to_cpu(pSMBr->t2.DataCount);
50c2f7538   Steve French   [CIFS] whitespace...
4591
  			struct file_internal_info *pfinfo;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4592
  			/* BB Do we need a cast or hash here ? */
790fe579f   Steve French   [CIFS] more white...
4593
  			if (count < 8) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
4594
  				cFYI(1, "Illegal size ret in QryIntrnlInf");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4595
4596
4597
4598
4599
  				rc = -EIO;
  				goto GetInodeNumOut;
  			}
  			pfinfo = (struct file_internal_info *)
  				(data_offset + (char *) &pSMBr->hdr.Protocol);
85a6dac54   Steve French   [CIFS] Endian con...
4600
  			*inode_number = le64_to_cpu(pfinfo->UniqueId);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4601
4602
4603
4604
4605
4606
4607
4608
  		}
  	}
  GetInodeNumOut:
  	cifs_buf_release(pSMB);
  	if (rc == -EAGAIN)
  		goto GetInodeNumberRetry;
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4609

fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4610
4611
4612
4613
4614
4615
4616
  /* 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...
4617
  parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4618
4619
  		unsigned int *num_of_nodes,
  		struct dfs_info3_param **target_nodes,
2c55608f2   Igor Mammedov   Fixed parsing of ...
4620
4621
  		const struct nls_table *nls_codepage, int remap,
  		const char *searchName)
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4622
4623
4624
4625
4626
  {
  	int i, rc = 0;
  	char *data_end;
  	bool is_unicode;
  	struct dfs_referral_level_3 *ref;
5ca33c6ac   Harvey Harrison   cifs: assorted en...
4627
4628
4629
4630
  	if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
  		is_unicode = true;
  	else
  		is_unicode = false;
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4631
4632
4633
  	*num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
  
  	if (*num_of_nodes < 1) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
4634
4635
4636
  		cERROR(1, "num_referrals: must be at least > 0,"
  			"but we get num_referrals = %d
  ", *num_of_nodes);
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4637
  		rc = -EINVAL;
a1fe78f16   Steve French   [CIFS] Add missin...
4638
  		goto parse_DFS_referrals_exit;
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4639
4640
4641
  	}
  
  	ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
1d92cfd54   Al Viro   cifs endianness f...
4642
  	if (ref->VersionNumber != cpu_to_le16(3)) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
4643
4644
  		cERROR(1, "Referrals of V%d version are not supported,"
  			"should be V3", le16_to_cpu(ref->VersionNumber));
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4645
  		rc = -EINVAL;
a1fe78f16   Steve French   [CIFS] Add missin...
4646
  		goto parse_DFS_referrals_exit;
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4647
4648
4649
4650
4651
  	}
  
  	/* get the upper boundary of the resp buffer */
  	data_end = (char *)(&(pSMBr->PathConsumed)) +
  				le16_to_cpu(pSMBr->t2.DataCount);
f19159dc5   Steve French   [CIFS] Cleanup va...
4652
4653
  	cFYI(1, "num_referrals: %d dfs flags: 0x%x ...
  ",
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4654
  			*num_of_nodes,
b6b38f704   Joe Perches   [CIFS] Neaten cER...
4655
  			le32_to_cpu(pSMBr->DFSFlags));
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4656
4657
4658
4659
  
  	*target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
  			*num_of_nodes, GFP_KERNEL);
  	if (*target_nodes == NULL) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
4660
4661
  		cERROR(1, "Failed to allocate buffer for target_nodes
  ");
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4662
  		rc = -ENOMEM;
a1fe78f16   Steve French   [CIFS] Add missin...
4663
  		goto parse_DFS_referrals_exit;
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4664
  	}
3ad2f3fbb   Daniel Mack   tree-wide: Assort...
4665
  	/* collect necessary data from referrals */
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4666
4667
4668
4669
  	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...
4670
  		node->flags = le32_to_cpu(pSMBr->DFSFlags);
2c55608f2   Igor Mammedov   Fixed parsing of ...
4671
  		if (is_unicode) {
331c31351   Jeff Layton   cifs: fix buffer ...
4672
4673
  			__le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
  						GFP_KERNEL);
2920ee2b4   Steve French   [CIFS] potential ...
4674
4675
4676
4677
  			if (tmp == NULL) {
  				rc = -ENOMEM;
  				goto parse_DFS_referrals_exit;
  			}
2c55608f2   Igor Mammedov   Fixed parsing of ...
4678
4679
  			cifsConvertToUCS((__le16 *) tmp, searchName,
  					PATH_MAX, nls_codepage, remap);
69f801fca   Jeff Layton   cifs: add new fun...
4680
4681
  			node->path_consumed = cifs_ucs2_bytes(tmp,
  					le16_to_cpu(pSMBr->PathConsumed),
2c55608f2   Igor Mammedov   Fixed parsing of ...
4682
4683
4684
4685
  					nls_codepage);
  			kfree(tmp);
  		} else
  			node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4686
4687
4688
4689
4690
4691
  		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;
d185cda77   Steve French   [CIFS] rename cif...
4692
4693
  		node->path_name = cifs_strndup_from_ucs(temp, max_len,
  						      is_unicode, nls_codepage);
d8e2f53ac   Jeff Layton   cifs: fix error h...
4694
4695
  		if (!node->path_name) {
  			rc = -ENOMEM;
a1fe78f16   Steve French   [CIFS] Add missin...
4696
  			goto parse_DFS_referrals_exit;
066ce6899   Jeff Layton   cifs: rename cifs...
4697
  		}
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4698
4699
4700
4701
  
  		/* copy link target UNC */
  		temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
  		max_len = data_end - temp;
d185cda77   Steve French   [CIFS] rename cif...
4702
4703
  		node->node_name = cifs_strndup_from_ucs(temp, max_len,
  						      is_unicode, nls_codepage);
d8e2f53ac   Jeff Layton   cifs: fix error h...
4704
4705
  		if (!node->node_name)
  			rc = -ENOMEM;
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4706
  	}
a1fe78f16   Steve French   [CIFS] Add missin...
4707
  parse_DFS_referrals_exit:
fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4708
4709
4710
4711
4712
4713
4714
  	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
4715
  int
96daf2b09   Steve French   [CIFS] Rename thr...
4716
  CIFSGetDFSRefer(const int xid, struct cifs_ses *ses,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4717
  		const unsigned char *searchName,
c2cf07d59   Steve French   [CIFS] Finishup D...
4718
4719
  		struct dfs_info3_param **target_nodes,
  		unsigned int *num_of_nodes,
737b758c9   Steve French   [PATCH] cifs: cha...
4720
  		const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4721
4722
4723
4724
  {
  /* 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
4725
4726
4727
  	int rc = 0;
  	int bytes_returned;
  	int name_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4728
  	__u16 params, byte_count;
c2cf07d59   Steve French   [CIFS] Finishup D...
4729
4730
  	*num_of_nodes = 0;
  	*target_nodes = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4731

b6b38f704   Joe Perches   [CIFS] Neaten cER...
4732
  	cFYI(1, "In GetDFSRefer the path %s", searchName);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4733
4734
4735
4736
4737
4738
4739
  	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...
4740
4741
  
  	/* server pointer checked in called function,
1982c344f   Steve French   [CIFS] Ensure tha...
4742
4743
  	but should never be null here anyway */
  	pSMB->hdr.Mid = GetNextMid(ses->server);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4744
4745
  	pSMB->hdr.Tid = ses->ipc_tid;
  	pSMB->hdr.Uid = ses->Suid;
26f57364d   Steve French   [CIFS] formatting...
4746
  	if (ses->capabilities & CAP_STATUS32)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4747
  		pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
26f57364d   Steve French   [CIFS] formatting...
4748
  	if (ses->capabilities & CAP_DFS)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4749
  		pSMB->hdr.Flags2 |= SMBFLG2_DFS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4750
4751
4752
4753
  
  	if (ses->capabilities & CAP_UNICODE) {
  		pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
  		name_len =
b1a45695b   Steve French   [CIFS] fix casts ...
4754
  		    cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
737b758c9   Steve French   [PATCH] cifs: cha...
4755
  				     searchName, PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4756
4757
  		name_len++;	/* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
4758
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4759
4760
4761
4762
  		name_len = strnlen(searchName, PATH_MAX);
  		name_len++;	/* trailing null */
  		strncpy(pSMB->RequestFileName, searchName, name_len);
  	}
790fe579f   Steve French   [CIFS] more white...
4763
  	if (ses->server) {
96daf2b09   Steve French   [CIFS] Rename thr...
4764
  		if (ses->server->sec_mode &
1a4e15a04   Steve French   [CIFS] Missing fl...
4765
4766
4767
  		   (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
  			pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
  	}
50c2f7538   Steve French   [CIFS] whitespace...
4768
  	pSMB->hdr.Uid = ses->Suid;
1a4e15a04   Steve French   [CIFS] Missing fl...
4769

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4770
4771
4772
4773
4774
  	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...
4775
4776
  	/* BB find exact max SMB PDU from sess structure BB */
  	pSMB->MaxDataCount = cpu_to_le16(4000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4777
4778
4779
4780
4781
4782
  	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...
4783
  	  struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4784
4785
4786
4787
4788
4789
4790
  	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 ...
4791
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4792
4793
4794
4795
4796
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  
  	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
  			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  	if (rc) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
4797
  		cFYI(1, "Send error in GetDFSRefer = %d", rc);
c2cf07d59   Steve French   [CIFS] Finishup D...
4798
4799
4800
  		goto GetDFSRefExit;
  	}
  	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4801

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

b6b38f704   Joe Perches   [CIFS] Neaten cER...
4808
  	cFYI(1, "Decoding GetDFSRefer response BCC: %d  Offset %d",
820a803ff   Jeff Layton   cifs: keep BCC in...
4809
  				get_bcc(&pSMBr->hdr),
b6b38f704   Joe Perches   [CIFS] Neaten cER...
4810
  				le16_to_cpu(pSMBr->t2.DataOffset));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4811

fec4585fd   Igor Mammedov   CIFSGetDFSRefer c...
4812
  	/* parse returned result into more usable form */
a1fe78f16   Steve French   [CIFS] Add missin...
4813
  	rc = parse_DFS_referrals(pSMBr, num_of_nodes,
2c55608f2   Igor Mammedov   Fixed parsing of ...
4814
4815
  				 target_nodes, nls_codepage, remap,
  				 searchName);
c2cf07d59   Steve French   [CIFS] Finishup D...
4816

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4817
  GetDFSRefExit:
0d817bc0d   Steve French   [CIFS] Remove red...
4818
  	cifs_buf_release(pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4819
4820
4821
4822
4823
4824
  
  	if (rc == -EAGAIN)
  		goto getDFSRetry;
  
  	return rc;
  }
209624388   Steve French   [CIFS] Add suppor...
4825
4826
  /* Query File System Info such as free space to old servers such as Win 9x */
  int
96daf2b09   Steve French   [CIFS] Rename thr...
4827
  SMBOldQFSInfo(const int xid, struct cifs_tcon *tcon, struct kstatfs *FSData)
209624388   Steve French   [CIFS] Add suppor...
4828
4829
4830
4831
4832
4833
4834
4835
  {
  /* 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;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
4836
  	cFYI(1, "OldQFSInfo");
209624388   Steve French   [CIFS] Add suppor...
4837
4838
4839
4840
4841
  oldQFSInfoRetry:
  	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  		(void **) &pSMBr);
  	if (rc)
  		return rc;
209624388   Steve French   [CIFS] Add suppor...
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
  
  	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 ...
4863
  	inc_rfc1001_len(pSMB, byte_count);
209624388   Steve French   [CIFS] Add suppor...
4864
4865
4866
4867
4868
  	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) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
4869
  		cFYI(1, "Send error in QFSInfo = %d", rc);
209624388   Steve French   [CIFS] Add suppor...
4870
4871
  	} else {                /* decode response */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
820a803ff   Jeff Layton   cifs: keep BCC in...
4872
  		if (rc || get_bcc(&pSMBr->hdr) < 18)
209624388   Steve French   [CIFS] Add suppor...
4873
4874
4875
  			rc = -EIO;      /* bad smb */
  		else {
  			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
b6b38f704   Joe Perches   [CIFS] Neaten cER...
4876
  			cFYI(1, "qfsinf resp BCC: %d  Offset %d",
820a803ff   Jeff Layton   cifs: keep BCC in...
4877
  				 get_bcc(&pSMBr->hdr), data_offset);
209624388   Steve French   [CIFS] Add suppor...
4878

50c2f7538   Steve French   [CIFS] whitespace...
4879
  			response_data = (FILE_SYSTEM_ALLOC_INFO *)
209624388   Steve French   [CIFS] Add suppor...
4880
4881
4882
4883
4884
4885
  				(((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...
4886
  			       le32_to_cpu(response_data->TotalAllocationUnits);
209624388   Steve French   [CIFS] Add suppor...
4887
4888
  			FSData->f_bfree = FSData->f_bavail =
  				le32_to_cpu(response_data->FreeAllocationUnits);
b6b38f704   Joe Perches   [CIFS] Neaten cER...
4889
4890
4891
4892
  			cFYI(1, "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...
4893
4894
4895
4896
4897
4898
4899
4900
4901
  		}
  	}
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto oldQFSInfoRetry;
  
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4902
  int
96daf2b09   Steve French   [CIFS] Rename thr...
4903
  CIFSSMBQFSInfo(const int xid, struct cifs_tcon *tcon, struct kstatfs *FSData)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4904
4905
4906
4907
4908
4909
4910
4911
  {
  /* 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;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
4912
  	cFYI(1, "In QFSInfo");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4913
4914
4915
4916
4917
4918
4919
4920
4921
  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...
4922
  	pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4923
4924
4925
4926
4927
4928
4929
4930
4931
  	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...
4932
  		struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4933
4934
4935
4936
4937
4938
  	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 ...
4939
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4940
4941
4942
4943
4944
  	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) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
4945
  		cFYI(1, "Send error in QFSInfo = %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4946
  	} else {		/* decode response */
50c2f7538   Steve French   [CIFS] whitespace...
4947
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4948

820a803ff   Jeff Layton   cifs: keep BCC in...
4949
  		if (rc || get_bcc(&pSMBr->hdr) < 24)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4950
4951
4952
  			rc = -EIO;	/* bad smb */
  		else {
  			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
  
  			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);
b6b38f704   Joe Perches   [CIFS] Neaten cER...
4966
4967
4968
4969
  			cFYI(1, "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
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
  		}
  	}
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto QFSInfoRetry;
  
  	return rc;
  }
  
  int
96daf2b09   Steve French   [CIFS] Rename thr...
4981
  CIFSSMBQFSAttributeInfo(const int xid, struct cifs_tcon *tcon)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4982
4983
4984
4985
4986
4987
4988
4989
  {
  /* 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;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
4990
  	cFYI(1, "In QFSAttributeInfo");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4991
4992
4993
4994
4995
4996
4997
4998
4999
  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...
5000
5001
  	/* BB find exact max SMB PDU from sess structure BB */
  	pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5002
5003
5004
5005
5006
5007
5008
5009
5010
  	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...
5011
  		struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5012
5013
5014
5015
5016
5017
  	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 ...
5018
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5019
5020
5021
5022
5023
  	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) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
5024
  		cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5025
5026
  	} else {		/* decode response */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
820a803ff   Jeff Layton   cifs: keep BCC in...
5027
  		if (rc || get_bcc(&pSMBr->hdr) < 13) {
50c2f7538   Steve French   [CIFS] whitespace...
5028
  			/* BB also check if enough bytes returned */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5029
5030
5031
5032
5033
5034
5035
5036
  			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...
5037
  			       sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
  		}
  	}
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto QFSAttributeRetry;
  
  	return rc;
  }
  
  int
96daf2b09   Steve French   [CIFS] Rename thr...
5049
  CIFSSMBQFSDeviceInfo(const int xid, struct cifs_tcon *tcon)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5050
5051
5052
5053
5054
5055
5056
5057
  {
  /* 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;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
5058
  	cFYI(1, "In QFSDeviceInfo");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5059
5060
5061
5062
5063
5064
5065
5066
5067
  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...
5068
5069
  	/* BB find exact max SMB PDU from sess structure BB */
  	pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5070
5071
5072
5073
5074
5075
5076
5077
5078
  	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...
5079
  		struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5080
5081
5082
5083
5084
5085
5086
  
  	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 ...
5087
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5088
5089
5090
5091
5092
  	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) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
5093
  		cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5094
5095
  	} else {		/* decode response */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
820a803ff   Jeff Layton   cifs: keep BCC in...
5096
5097
  		if (rc || get_bcc(&pSMBr->hdr) <
  			  sizeof(FILE_SYSTEM_DEVICE_INFO))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5098
5099
5100
5101
  			rc = -EIO;	/* bad smb */
  		else {
  			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
  			response_data =
737b758c9   Steve French   [PATCH] cifs: cha...
5102
5103
  			    (FILE_SYSTEM_DEVICE_INFO *)
  				(((char *) &pSMBr->hdr.Protocol) +
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5104
5105
  				 data_offset);
  			memcpy(&tcon->fsDevInfo, response_data,
26f57364d   Steve French   [CIFS] formatting...
5106
  			       sizeof(FILE_SYSTEM_DEVICE_INFO));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
  		}
  	}
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto QFSDeviceRetry;
  
  	return rc;
  }
  
  int
96daf2b09   Steve French   [CIFS] Rename thr...
5118
  CIFSSMBQFSUnixInfo(const int xid, struct cifs_tcon *tcon)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5119
5120
5121
5122
5123
5124
5125
5126
  {
  /* 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;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
5127
  	cFYI(1, "In QFSUnixInfo");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5128
  QFSUnixRetry:
f569599ae   Jeff Layton   cifs: prevent inf...
5129
5130
  	rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
  				   (void **) &pSMB, (void **) &pSMBr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5131
5132
5133
5134
5135
5136
5137
5138
  	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...
5139
5140
  	/* BB find exact max SMB PDU from sess structure BB */
  	pSMB->MaxDataCount = cpu_to_le16(100);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5141
5142
5143
5144
5145
5146
5147
5148
  	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...
5149
5150
  	pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
  			smb_com_transaction2_qfsi_req, InformationLevel) - 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5151
5152
5153
5154
  	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 ...
5155
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5156
5157
5158
5159
5160
  	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) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
5161
  		cERROR(1, "Send error in QFSUnixInfo = %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5162
5163
  	} else {		/* decode response */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
820a803ff   Jeff Layton   cifs: keep BCC in...
5164
  		if (rc || get_bcc(&pSMBr->hdr) < 13) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5165
5166
5167
5168
5169
5170
5171
5172
  			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...
5173
  			       sizeof(FILE_SYSTEM_UNIX_INFO));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
  		}
  	}
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto QFSUnixRetry;
  
  
  	return rc;
  }
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
5184
  int
96daf2b09   Steve French   [CIFS] Rename thr...
5185
  CIFSSMBSetFSUnixInfo(const int xid, struct cifs_tcon *tcon, __u64 cap)
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
5186
5187
5188
5189
5190
5191
5192
  {
  /* 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;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
5193
  	cFYI(1, "In SETFSUnixInfo");
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
5194
  SETFSUnixRetry:
f26282c9a   Steve French   [CIFS] Use correc...
5195
  	/* BB switch to small buf init to save memory */
f569599ae   Jeff Layton   cifs: prevent inf...
5196
5197
  	rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
  					(void **) &pSMB, (void **) &pSMBr);
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
5198
5199
5200
5201
5202
5203
5204
5205
5206
  	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...
5207
5208
  	param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
  				- 4;
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
5209
5210
5211
  	offset = param_offset + params;
  
  	pSMB->MaxParameterCount = cpu_to_le16(4);
582d21e5e   Steve French   [CIFS] cleanup ol...
5212
5213
  	/* BB find exact max SMB PDU from sess structure BB */
  	pSMB->MaxDataCount = cpu_to_le16(100);
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
  	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 ...
5234
  	inc_rfc1001_len(pSMB, byte_count);
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
5235
5236
5237
5238
5239
  	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) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
5240
  		cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
5241
5242
  	} else {		/* decode response */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
ad7a2926b   Steve French   [CIFS] reduce che...
5243
  		if (rc)
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
5244
  			rc = -EIO;	/* bad smb */
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
5245
5246
5247
5248
5249
5250
5251
5252
  	}
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto SETFSUnixRetry;
  
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5253
5254
  
  int
96daf2b09   Steve French   [CIFS] Rename thr...
5255
  CIFSSMBQFSPosixInfo(const int xid, struct cifs_tcon *tcon,
737b758c9   Steve French   [PATCH] cifs: cha...
5256
  		   struct kstatfs *FSData)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5257
5258
5259
5260
5261
5262
5263
5264
  {
  /* 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;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
5265
  	cFYI(1, "In QFSPosixInfo");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
  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...
5277
5278
  	/* BB find exact max SMB PDU from sess structure BB */
  	pSMB->MaxDataCount = cpu_to_le16(100);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5279
5280
5281
5282
5283
5284
5285
5286
  	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...
5287
5288
  	pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
  			smb_com_transaction2_qfsi_req, InformationLevel) - 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5289
5290
5291
5292
  	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 ...
5293
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5294
5295
5296
5297
5298
  	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) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
5299
  		cFYI(1, "Send error in QFSUnixInfo = %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5300
5301
  	} else {		/* decode response */
  		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
820a803ff   Jeff Layton   cifs: keep BCC in...
5302
  		if (rc || get_bcc(&pSMBr->hdr) < 13) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
  			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...
5316
  			if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5317
5318
5319
  				FSData->f_bavail = FSData->f_bfree;
  			} else {
  				FSData->f_bavail =
50c2f7538   Steve French   [CIFS] whitespace...
5320
  				    le64_to_cpu(response_data->UserBlocksAvail);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5321
  			}
790fe579f   Steve French   [CIFS] more white...
5322
  			if (response_data->TotalFileNodes != cpu_to_le64(-1))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5323
  				FSData->f_files =
50c2f7538   Steve French   [CIFS] whitespace...
5324
  				     le64_to_cpu(response_data->TotalFileNodes);
790fe579f   Steve French   [CIFS] more white...
5325
  			if (response_data->FreeFileNodes != cpu_to_le64(-1))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5326
  				FSData->f_ffree =
50c2f7538   Steve French   [CIFS] whitespace...
5327
  				      le64_to_cpu(response_data->FreeFileNodes);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5328
5329
5330
5331
5332
5333
5334
5335
5336
  		}
  	}
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto QFSPosixRetry;
  
  	return rc;
  }
50c2f7538   Steve French   [CIFS] whitespace...
5337
5338
5339
  /* 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
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5340
5341
5342
5343
     routine which is only needed to work around a sharing violation bug
     in Samba which this routine can run into */
  
  int
96daf2b09   Steve French   [CIFS] Rename thr...
5344
  CIFSSMBSetEOF(const int xid, struct cifs_tcon *tcon, const char *fileName,
4b18f2a9c   Steve French   [CIFS] convert us...
5345
  	      __u64 size, bool SetAllocation,
737b758c9   Steve French   [PATCH] cifs: cha...
5346
  	      const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5347
5348
5349
5350
5351
5352
5353
5354
  {
  	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;
  	__u16 params, byte_count, data_count, param_offset, offset;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
5355
  	cFYI(1, "In SetEOF");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5356
5357
5358
5359
5360
5361
5362
5363
  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 =
b1a45695b   Steve French   [CIFS] fix casts ...
5364
  		    cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
737b758c9   Steve French   [PATCH] cifs: cha...
5365
  				     PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5366
5367
  		name_len++;	/* trailing null */
  		name_len *= 2;
3e87d8039   Steve French   [CIFS] Add suppor...
5368
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5369
5370
5371
5372
5373
  		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...
5374
  	data_count = sizeof(struct file_end_of_file_info);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5375
  	pSMB->MaxParameterCount = cpu_to_le16(2);
3e87d8039   Steve French   [CIFS] Add suppor...
5376
  	pSMB->MaxDataCount = cpu_to_le16(4100);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5377
5378
5379
5380
5381
5382
  	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...
5383
  				InformationLevel) - 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5384
  	offset = param_offset + params;
790fe579f   Steve French   [CIFS] more white...
5385
  	if (SetAllocation) {
50c2f7538   Steve French   [CIFS] whitespace...
5386
5387
5388
5389
5390
5391
5392
  		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
5393
5394
  	    if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
  		    pSMB->InformationLevel =
50c2f7538   Steve French   [CIFS] whitespace...
5395
  				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5396
5397
  	    else
  		    pSMB->InformationLevel =
50c2f7538   Steve French   [CIFS] whitespace...
5398
  				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
  	}
  
  	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 ...
5415
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5416
5417
5418
5419
  	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...
5420
  	if (rc)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
5421
  		cFYI(1, "SetPathInfo (file size) returned %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
  
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto SetEOFRetry;
  
  	return rc;
  }
  
  int
96daf2b09   Steve French   [CIFS] Rename thr...
5432
  CIFSSMBSetFileSize(const int xid, struct cifs_tcon *tcon, __u64 size,
4b18f2a9c   Steve French   [CIFS] convert us...
5433
  		   __u16 fid, __u32 pid_of_opener, bool SetAllocation)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5434
5435
  {
  	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5436
5437
  	struct file_end_of_file_info *parm_data;
  	int rc = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5438
  	__u16 params, param_offset, offset, byte_count, count;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
5439
5440
  	cFYI(1, "SetFileSize (via SetFileInfo) %lld",
  			(long long)size);
cd63499cb   Steve French   [PATCH] cifs: Han...
5441
  	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5442
5443
5444
5445
5446
  	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));
50c2f7538   Steve French   [CIFS] whitespace...
5447

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5448
5449
5450
5451
5452
5453
5454
5455
  	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
5456
5457
  	count = sizeof(struct file_end_of_file_info);
  	pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5e   Steve French   [CIFS] cleanup ol...
5458
5459
  	/* BB find exact max SMB PDU from sess structure BB */
  	pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
  	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...
5470
5471
  		(struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
  				+ offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5472
5473
5474
  	pSMB->DataOffset = cpu_to_le16(offset);
  	parm_data->FileSize = cpu_to_le64(size);
  	pSMB->Fid = fid;
790fe579f   Steve French   [CIFS] more white...
5475
  	if (SetAllocation) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5476
5477
5478
5479
5480
5481
  		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...
5482
  	} else /* Set File Size */  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5483
5484
  	    if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
  		    pSMB->InformationLevel =
50c2f7538   Steve French   [CIFS] whitespace...
5485
  				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5486
5487
  	    else
  		    pSMB->InformationLevel =
50c2f7538   Steve French   [CIFS] whitespace...
5488
  				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5489
5490
  	}
  	pSMB->Reserved4 = 0;
be8e3b004   Steve French   consistently use ...
5491
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5492
  	pSMB->ByteCount = cpu_to_le16(byte_count);
133672efb   Steve French   [CIFS] Fix buffer...
5493
  	rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5494
  	if (rc) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
5495
  		cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5496
  	}
50c2f7538   Steve French   [CIFS] whitespace...
5497
  	/* Note: On -EAGAIN error only caller can retry on handle based calls
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5498
5499
5500
5501
  		since file handle passed in no longer valid */
  
  	return rc;
  }
50c2f7538   Steve French   [CIFS] whitespace...
5502
  /* Some legacy servers such as NT4 require that the file times be set on
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5503
5504
5505
5506
5507
5508
     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
96daf2b09   Steve French   [CIFS] Rename thr...
5509
  CIFSSMBSetFileInfo(const int xid, struct cifs_tcon *tcon,
2dd2dfa06   Jeff Layton   Rename CIFSSMBSet...
5510
  		    const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5511
5512
  {
  	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5513
5514
  	char *data_offset;
  	int rc = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5515
  	__u16 params, param_offset, offset, byte_count, count;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
5516
  	cFYI(1, "Set Times (via SetFileInfo)");
cd63499cb   Steve French   [PATCH] cifs: Han...
5517
  	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5518
5519
  	if (rc)
  		return rc;
2dd2dfa06   Jeff Layton   Rename CIFSSMBSet...
5520
5521
  	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...
5522

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5523
5524
5525
5526
5527
5528
5529
5530
  	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;
50c2f7538   Steve French   [CIFS] whitespace...
5531
  	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5532

26f57364d   Steve French   [CIFS] formatting...
5533
  	count = sizeof(FILE_BASIC_INFO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5534
  	pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5e   Steve French   [CIFS] cleanup ol...
5535
5536
  	/* BB find max SMB PDU from sess */
  	pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
  	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 ...
5553
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5554
  	pSMB->ByteCount = cpu_to_le16(byte_count);
50c2f7538   Steve French   [CIFS] whitespace...
5555
  	memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
133672efb   Steve French   [CIFS] Fix buffer...
5556
  	rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
ad7a2926b   Steve French   [CIFS] reduce che...
5557
  	if (rc)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
5558
  		cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5559

50c2f7538   Steve French   [CIFS] whitespace...
5560
  	/* Note: On -EAGAIN error only caller can retry on handle based calls
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5561
5562
5563
5564
  		since file handle passed in no longer valid */
  
  	return rc;
  }
6d22f0989   Jeff Layton   cifs: add functio...
5565
  int
96daf2b09   Steve French   [CIFS] Rename thr...
5566
  CIFSSMBSetFileDisposition(const int xid, struct cifs_tcon *tcon,
6d22f0989   Jeff Layton   cifs: add functio...
5567
5568
5569
5570
5571
5572
  			  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;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
5573
  	cFYI(1, "Set File Disposition (via SetFileInfo)");
6d22f0989   Jeff Layton   cifs: add functio...
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
  	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 ...
5610
  	inc_rfc1001_len(pSMB, byte_count);
6d22f0989   Jeff Layton   cifs: add functio...
5611
5612
5613
5614
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  	*data_offset = delete_file ? 1 : 0;
  	rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
  	if (rc)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
5615
  		cFYI(1, "Send error in SetFileDisposition = %d", rc);
6d22f0989   Jeff Layton   cifs: add functio...
5616
5617
5618
  
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5619
5620
  
  int
96daf2b09   Steve French   [CIFS] Rename thr...
5621
  CIFSSMBSetPathInfo(const int xid, struct cifs_tcon *tcon,
6fc000e51   Jeff Layton   change CIFSSMBSet...
5622
5623
  		   const char *fileName, const FILE_BASIC_INFO *data,
  		   const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5624
5625
5626
5627
5628
5629
5630
5631
  {
  	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;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
5632
  	cFYI(1, "In SetTimes");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5633
5634
5635
5636
5637
5638
5639
5640
5641
  
  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 =
b1a45695b   Steve French   [CIFS] fix casts ...
5642
  		    cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
737b758c9   Steve French   [PATCH] cifs: cha...
5643
  				     PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5644
5645
  		name_len++;	/* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
5646
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5647
5648
5649
5650
5651
5652
  		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...
5653
  	count = sizeof(FILE_BASIC_INFO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5654
  	pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5e   Steve French   [CIFS] cleanup ol...
5655
5656
  	/* BB find max SMB PDU from sess structure BB */
  	pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5657
5658
5659
5660
5661
5662
  	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...
5663
  				InformationLevel) - 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
  	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 ...
5682
  	inc_rfc1001_len(pSMB, byte_count);
26f57364d   Steve French   [CIFS] formatting...
5683
  	memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5684
5685
5686
  	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...
5687
  	if (rc)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
5688
  		cFYI(1, "SetPathInfo (times) returned %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
  
  	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
96daf2b09   Steve French   [CIFS] Rename thr...
5704
  CIFSSMBSetAttrLegacy(int xid, struct cifs_tcon *tcon, char *fileName,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5705
5706
5707
5708
5709
5710
5711
  		__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;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
5712
  	cFYI(1, "In SetAttrLegacy");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5713
5714
5715
5716
5717
5718
5719
5720
5721
  
  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 =
50c2f7538   Steve French   [CIFS] whitespace...
5722
  			ConvertToUCS((__le16 *) pSMB->fileName, fileName,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5723
5724
5725
  				PATH_MAX, nls_codepage);
  		name_len++;     /* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
5726
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5727
5728
5729
5730
5731
5732
  		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 ...
5733
  	inc_rfc1001_len(pSMB, name_len + 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5734
5735
5736
  	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...
5737
  	if (rc)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
5738
  		cFYI(1, "Error in LegacySetAttr = %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5739
5740
5741
5742
5743
5744
5745
5746
5747
  
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto SetAttrLgcyRetry;
  
  	return rc;
  }
  #endif /* temporarily unneeded SetAttr legacy function */
654cf14ac   Jeff Layton   cifs: make a sepa...
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
  static void
  cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
  			const struct cifs_unix_set_info_args *args)
  {
  	u64 mode = args->mode;
  
  	/*
  	 * 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...
5758
  	 * accidentally as happened on one Samba server beta by putting
654cf14ac   Jeff Layton   cifs: make a sepa...
5759
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
  	 * 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);
  	data_offset->Uid = cpu_to_le64(args->uid);
  	data_offset->Gid = cpu_to_le64(args->gid);
  	/* 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
5788
  int
96daf2b09   Steve French   [CIFS] Rename thr...
5789
  CIFSSMBUnixSetFileInfo(const int xid, struct cifs_tcon *tcon,
3bbeeb3c9   Jeff Layton   cifs: add and use...
5790
5791
5792
5793
5794
5795
5796
  		       const struct cifs_unix_set_info_args *args,
  		       u16 fid, u32 pid_of_opener)
  {
  	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
  	FILE_UNIX_BASIC_INFO *data_offset;
  	int rc = 0;
  	u16 params, param_offset, offset, byte_count, count;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
5797
  	cFYI(1, "Set Unix Info (via SetFileInfo)");
3bbeeb3c9   Jeff Layton   cifs: add and use...
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
  	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 = (FILE_UNIX_BASIC_INFO *)
  				((char *)(&pSMB->hdr.Protocol) + offset);
  	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 ...
5835
  	inc_rfc1001_len(pSMB, byte_count);
3bbeeb3c9   Jeff Layton   cifs: add and use...
5836
5837
5838
5839
5840
5841
  	pSMB->ByteCount = cpu_to_le16(byte_count);
  
  	cifs_fill_unix_set_info(data_offset, args);
  
  	rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
  	if (rc)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
5842
  		cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
3bbeeb3c9   Jeff Layton   cifs: add and use...
5843
5844
5845
5846
5847
5848
5849
5850
  
  	/* Note: On -EAGAIN error only caller can retry on handle based calls
  		since file handle passed in no longer valid */
  
  	return rc;
  }
  
  int
96daf2b09   Steve French   [CIFS] Rename thr...
5851
  CIFSSMBUnixSetPathInfo(const int xid, struct cifs_tcon *tcon, char *fileName,
01ea95e3b   Jeff Layton   cifs: rename CIFS...
5852
5853
  		       const struct cifs_unix_set_info_args *args,
  		       const struct nls_table *nls_codepage, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5854
5855
5856
5857
5858
5859
5860
5861
  {
  	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;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
5862
  	cFYI(1, "In SetUID/GID/Mode");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5863
5864
5865
5866
5867
5868
5869
5870
  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 =
50c2f7538   Steve French   [CIFS] whitespace...
5871
  		    cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
737b758c9   Steve French   [PATCH] cifs: cha...
5872
  				     PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5873
5874
  		name_len++;	/* trailing null */
  		name_len *= 2;
3e87d8039   Steve French   [CIFS] Add suppor...
5875
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5876
5877
5878
5879
5880
5881
  		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...
5882
  	count = sizeof(FILE_UNIX_BASIC_INFO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5883
  	pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5e   Steve French   [CIFS] cleanup ol...
5884
5885
  	/* BB find max SMB PDU from sess structure BB */
  	pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5886
5887
5888
5889
5890
5891
  	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...
5892
  				InformationLevel) - 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
  	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 ...
5910
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5911

654cf14ac   Jeff Layton   cifs: make a sepa...
5912
  	cifs_fill_unix_set_info(data_offset, args);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5913
5914
5915
5916
  
  	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...
5917
  	if (rc)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
5918
  		cFYI(1, "SetPathInfo (perms) returned %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5919

0d817bc0d   Steve French   [CIFS] Remove red...
5920
  	cifs_buf_release(pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5921
5922
5923
5924
  	if (rc == -EAGAIN)
  		goto setPermsRetry;
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5925
  #ifdef CONFIG_CIFS_XATTR
31c0519f7   Jeff Layton   cifs: merge CIFSS...
5926
5927
5928
5929
5930
5931
5932
5933
5934
  /*
   * 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
5935
  ssize_t
96daf2b09   Steve French   [CIFS] Rename thr...
5936
  CIFSSMBQAllEAs(const int xid, struct cifs_tcon *tcon,
31c0519f7   Jeff Layton   cifs: merge CIFSS...
5937
5938
5939
  		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
5940
5941
5942
5943
5944
5945
  {
  		/* 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...
5946
  	int list_len;
f0d3868b7   Jeff Layton   cifs: clean up in...
5947
  	struct fealist *ea_response_data;
50c2f7538   Steve French   [CIFS] whitespace...
5948
5949
  	struct fea *temp_fea;
  	char *temp_ptr;
0cd126b50   Jeff Layton   cifs: verify leng...
5950
  	char *end_of_smb;
f0d3868b7   Jeff Layton   cifs: clean up in...
5951
  	__u16 params, byte_count, data_offset;
5980fc966   Jeff Layton   cifs: fix compile...
5952
  	unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5953

b6b38f704   Joe Perches   [CIFS] Neaten cER...
5954
  	cFYI(1, "In Query All EAs path %s", searchName);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5955
5956
5957
5958
5959
5960
5961
  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...
5962
  		list_len =
50c2f7538   Steve French   [CIFS] whitespace...
5963
  		    cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
737b758c9   Steve French   [PATCH] cifs: cha...
5964
  				     PATH_MAX, nls_codepage, remap);
6e462b9f2   Jeff Layton   cifs: rename name...
5965
5966
  		list_len++;	/* trailing null */
  		list_len *= 2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5967
  	} else {	/* BB improve the check for buffer overruns BB */
6e462b9f2   Jeff Layton   cifs: rename name...
5968
5969
5970
  		list_len = strnlen(searchName, PATH_MAX);
  		list_len++;	/* trailing null */
  		strncpy(pSMB->FileName, searchName, list_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5971
  	}
6e462b9f2   Jeff Layton   cifs: rename name...
5972
  	params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5973
5974
  	pSMB->TotalDataCount = 0;
  	pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5e   Steve French   [CIFS] cleanup ol...
5975
  	/* BB find exact max SMB PDU from sess structure BB */
e529614ad   Jeff Layton   cifs: increase ma...
5976
  	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5977
5978
5979
5980
5981
5982
  	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...
5983
  	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
  	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 ...
5994
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5995
5996
5997
5998
5999
  	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) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
6000
  		cFYI(1, "Send error in QueryAllEAs = %d", rc);
f0d3868b7   Jeff Layton   cifs: clean up in...
6001
6002
  		goto QAllEAsOut;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6003

f0d3868b7   Jeff Layton   cifs: clean up in...
6004
6005
6006
6007
6008
6009
  
  	/* 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...
6010
  	if (rc || get_bcc(&pSMBr->hdr) < 4) {
f0d3868b7   Jeff Layton   cifs: clean up in...
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
  		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...
6026
  	list_len = le32_to_cpu(ea_response_data->list_len);
b6b38f704   Joe Perches   [CIFS] Neaten cER...
6027
  	cFYI(1, "ea length %d", list_len);
6e462b9f2   Jeff Layton   cifs: rename name...
6028
  	if (list_len <= 8) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
6029
  		cFYI(1, "empty EA list returned from server");
f0d3868b7   Jeff Layton   cifs: clean up in...
6030
6031
  		goto QAllEAsOut;
  	}
0cd126b50   Jeff Layton   cifs: verify leng...
6032
  	/* make sure list_len doesn't go past end of SMB */
690c522fa   Jeff Layton   cifs: use get/put...
6033
  	end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
0cd126b50   Jeff Layton   cifs: verify leng...
6034
  	if ((char *)ea_response_data + list_len > end_of_smb) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
6035
  		cFYI(1, "EA list appears to go beyond SMB");
0cd126b50   Jeff Layton   cifs: verify leng...
6036
6037
6038
  		rc = -EIO;
  		goto QAllEAsOut;
  	}
f0d3868b7   Jeff Layton   cifs: clean up in...
6039
  	/* account for ea list len */
6e462b9f2   Jeff Layton   cifs: rename name...
6040
  	list_len -= 4;
f0d3868b7   Jeff Layton   cifs: clean up in...
6041
6042
  	temp_fea = ea_response_data->list;
  	temp_ptr = (char *)temp_fea;
6e462b9f2   Jeff Layton   cifs: rename name...
6043
  	while (list_len > 0) {
122ca0076   Steve French   [CIFS] Use unsign...
6044
  		unsigned int name_len;
f0d3868b7   Jeff Layton   cifs: clean up in...
6045
  		__u16 value_len;
0cd126b50   Jeff Layton   cifs: verify leng...
6046

6e462b9f2   Jeff Layton   cifs: rename name...
6047
  		list_len -= 4;
f0d3868b7   Jeff Layton   cifs: clean up in...
6048
  		temp_ptr += 4;
0cd126b50   Jeff Layton   cifs: verify leng...
6049
6050
  		/* make sure we can read name_len and value_len */
  		if (list_len < 0) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
6051
  			cFYI(1, "EA entry goes beyond length of list");
0cd126b50   Jeff Layton   cifs: verify leng...
6052
6053
6054
6055
6056
6057
6058
6059
  			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) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
6060
  			cFYI(1, "EA entry goes beyond length of list");
0cd126b50   Jeff Layton   cifs: verify leng...
6061
6062
6063
  			rc = -EIO;
  			goto QAllEAsOut;
  		}
31c0519f7   Jeff Layton   cifs: merge CIFSS...
6064
  		if (ea_name) {
91d065c47   Jeff Layton   cifs: fix name pa...
6065
  			if (ea_name_len == name_len &&
ac423446d   Jeff Layton   cifs: switch CIFS...
6066
  			    memcmp(ea_name, temp_ptr, name_len) == 0) {
31c0519f7   Jeff Layton   cifs: merge CIFSS...
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
  				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...
6078
  		} else {
31c0519f7   Jeff Layton   cifs: merge CIFSS...
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
  			/* 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
6096
  		}
0cd126b50   Jeff Layton   cifs: verify leng...
6097
  		temp_ptr += name_len + 1 + value_len;
f0d3868b7   Jeff Layton   cifs: clean up in...
6098
  		temp_fea = (struct fea *)temp_ptr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6099
  	}
f0d3868b7   Jeff Layton   cifs: clean up in...
6100

31c0519f7   Jeff Layton   cifs: merge CIFSS...
6101
6102
6103
  	/* didn't find the named attribute */
  	if (ea_name)
  		rc = -ENODATA;
f0d3868b7   Jeff Layton   cifs: clean up in...
6104
  QAllEAsOut:
0d817bc0d   Steve French   [CIFS] Remove red...
6105
  	cifs_buf_release(pSMB);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6106
6107
6108
6109
6110
  	if (rc == -EAGAIN)
  		goto QAllEAsRetry;
  
  	return (ssize_t)rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6111
  int
96daf2b09   Steve French   [CIFS] Rename thr...
6112
  CIFSSMBSetEA(const int xid, struct cifs_tcon *tcon, const char *fileName,
50c2f7538   Steve French   [CIFS] whitespace...
6113
6114
6115
  	     const char *ea_name, const void *ea_value,
  	     const __u16 ea_value_len, const struct nls_table *nls_codepage,
  	     int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6116
6117
6118
6119
6120
6121
6122
6123
  {
  	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;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
6124
  	cFYI(1, "In SetEA");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6125
6126
6127
6128
6129
6130
6131
6132
  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 =
50c2f7538   Steve French   [CIFS] whitespace...
6133
  		    cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
737b758c9   Steve French   [PATCH] cifs: cha...
6134
  				     PATH_MAX, nls_codepage, remap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6135
6136
  		name_len++;	/* trailing null */
  		name_len *= 2;
50c2f7538   Steve French   [CIFS] whitespace...
6137
  	} else {	/* BB improve the check for buffer overruns BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
  		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...
6148
  	if (ea_name == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6149
6150
  		name_len = 0;
  	else
50c2f7538   Steve French   [CIFS] whitespace...
6151
  		name_len = strnlen(ea_name, 255);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6152

dae5dbdbd   Steve French   [CIFS] fix SetEA ...
6153
  	count = sizeof(*parm_data) + ea_value_len + name_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6154
  	pSMB->MaxParameterCount = cpu_to_le16(2);
582d21e5e   Steve French   [CIFS] cleanup ol...
6155
6156
  	/* BB find max SMB PDU from sess */
  	pSMB->MaxDataCount = cpu_to_le16(1000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6157
6158
6159
6160
6161
6162
  	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...
6163
  				InformationLevel) - 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
  	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
6181
  	parm_data->list[0].name_len = (__u8)name_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6182
  	/* EA names are always ASCII */
790fe579f   Steve French   [CIFS] more white...
6183
  	if (ea_name)
50c2f7538   Steve French   [CIFS] whitespace...
6184
  		strncpy(parm_data->list[0].name, ea_name, name_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6185
6186
6187
6188
  	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...
6189
6190
  	/*BB add length check to see if it would fit in
  	     negotiated SMB buffer size BB */
790fe579f   Steve French   [CIFS] more white...
6191
6192
  	/* if (ea_value_len > buffer_size - 512 (enough for header)) */
  	if (ea_value_len)
50c2f7538   Steve French   [CIFS] whitespace...
6193
6194
  		memcpy(parm_data->list[0].name+name_len+1,
  		       ea_value, ea_value_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6195
6196
6197
6198
6199
  
  	pSMB->TotalDataCount = pSMB->DataCount;
  	pSMB->ParameterCount = cpu_to_le16(params);
  	pSMB->TotalParameterCount = pSMB->ParameterCount;
  	pSMB->Reserved4 = 0;
be8e3b004   Steve French   consistently use ...
6200
  	inc_rfc1001_len(pSMB, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6201
6202
6203
  	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...
6204
  	if (rc)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
6205
  		cFYI(1, "SetPathInfo (EA) returned %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6206
6207
6208
6209
6210
6211
6212
6213
  
  	cifs_buf_release(pSMB);
  
  	if (rc == -EAGAIN)
  		goto SetEARetry;
  
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6214
  #endif
0eff0e267   Steve French   Remove unused CIF...
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
  
  #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.
   */
96daf2b09   Steve French   [CIFS] Rename thr...
6237
  int CIFSSMBNotify(const int xid, struct cifs_tcon *tcon,
0eff0e267   Steve French   Remove unused CIF...
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
  		  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;
  
  	cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid);
  	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...
6257
  	pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
0eff0e267   Steve French   Remove unused CIF...
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
  	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) {
  		cFYI(1, "Error in Notify = %d", rc);
  	} 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 */