Blame view

fs/cifs/smb2inode.c 7.83 KB
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
  /*
   *   fs/cifs/smb2inode.c
   *
   *   Copyright (C) International Business Machines  Corp., 2002, 2011
   *                 Etersoft, 2012
   *   Author(s): Pavel Shilovsky (pshilovsky@samba.org),
   *              Steve French (sfrench@us.ibm.com)
   *
   *   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
   */
  #include <linux/fs.h>
  #include <linux/stat.h>
  #include <linux/slab.h>
  #include <linux/pagemap.h>
  #include <asm/div64.h>
  #include "cifsfs.h"
  #include "cifspdu.h"
  #include "cifsglob.h"
  #include "cifsproto.h"
  #include "cifs_debug.h"
  #include "cifs_fs_sb.h"
  #include "cifs_unicode.h"
  #include "fscache.h"
  #include "smb2glob.h"
  #include "smb2pdu.h"
  #include "smb2proto.h"
  
  static int
  smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
  		   struct cifs_sb_info *cifs_sb, const char *full_path,
  		   __u32 desired_access, __u32 create_disposition,
ca81983fe   Pavel Shilovsky   CIFS: Respect cre...
44
  		   __u32 create_options, void *data, int command)
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
45
46
  {
  	int rc, tmprc = 0;
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
47
  	__le16 *utf16_path;
2e44b2887   Pavel Shilovsky   CIFS: Process opl...
48
  	__u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
064f6047a   Pavel Shilovsky   CIFS: Make SMB2_o...
49
50
  	struct cifs_open_parms oparms;
  	struct cifs_fid fid;
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
51
52
53
54
  
  	utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
  	if (!utf16_path)
  		return -ENOMEM;
064f6047a   Pavel Shilovsky   CIFS: Make SMB2_o...
55
56
57
58
59
  	oparms.tcon = tcon;
  	oparms.desired_access = desired_access;
  	oparms.disposition = create_disposition;
  	oparms.create_options = create_options;
  	oparms.fid = &fid;
9cbc0b733   Pavel Shilovsky   CIFS: Reconnect d...
60
  	oparms.reconnect = false;
064f6047a   Pavel Shilovsky   CIFS: Make SMB2_o...
61

b42bf8882   Pavel Shilovsky   CIFS: Implement f...
62
  	rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
63
64
65
66
67
68
69
70
71
  	if (rc) {
  		kfree(utf16_path);
  		return rc;
  	}
  
  	switch (command) {
  	case SMB2_OP_DELETE:
  		break;
  	case SMB2_OP_QUERY_INFO:
064f6047a   Pavel Shilovsky   CIFS: Make SMB2_o...
72
73
  		tmprc = SMB2_query_info(xid, tcon, fid.persistent_fid,
  					fid.volatile_fid,
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
74
75
76
77
78
79
80
81
  					(struct smb2_file_all_info *)data);
  		break;
  	case SMB2_OP_MKDIR:
  		/*
  		 * Directories are created through parameters in the
  		 * SMB2_open() call.
  		 */
  		break;
897fba117   Steve French   remove directory ...
82
83
84
85
  	case SMB2_OP_RMDIR:
  		tmprc = SMB2_rmdir(xid, tcon, fid.persistent_fid,
  				   fid.volatile_fid);
  		break;
35143eb5c   Pavel Shilovsky   CIFS: Add SMB2 su...
86
  	case SMB2_OP_RENAME:
064f6047a   Pavel Shilovsky   CIFS: Make SMB2_o...
87
88
  		tmprc = SMB2_rename(xid, tcon, fid.persistent_fid,
  				    fid.volatile_fid, (__le16 *)data);
35143eb5c   Pavel Shilovsky   CIFS: Add SMB2 su...
89
  		break;
568798cc6   Pavel Shilovsky   CIFS: Add SMB2 su...
90
  	case SMB2_OP_HARDLINK:
064f6047a   Pavel Shilovsky   CIFS: Make SMB2_o...
91
92
  		tmprc = SMB2_set_hardlink(xid, tcon, fid.persistent_fid,
  					  fid.volatile_fid, (__le16 *)data);
568798cc6   Pavel Shilovsky   CIFS: Add SMB2 su...
93
  		break;
c839ff244   Pavel Shilovsky   CIFS: Add SMB2 su...
94
  	case SMB2_OP_SET_EOF:
064f6047a   Pavel Shilovsky   CIFS: Make SMB2_o...
95
96
  		tmprc = SMB2_set_eof(xid, tcon, fid.persistent_fid,
  				     fid.volatile_fid, current->tgid,
f29ebb47d   Steve French   Add worker functi...
97
  				     (__le64 *)data, false);
c839ff244   Pavel Shilovsky   CIFS: Add SMB2 su...
98
  		break;
1feeaac75   Pavel Shilovsky   CIFS: Add set_fil...
99
  	case SMB2_OP_SET_INFO:
064f6047a   Pavel Shilovsky   CIFS: Make SMB2_o...
100
101
  		tmprc = SMB2_set_info(xid, tcon, fid.persistent_fid,
  				      fid.volatile_fid,
1feeaac75   Pavel Shilovsky   CIFS: Add set_fil...
102
103
  				      (FILE_BASIC_INFO *)data);
  		break;
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
104
  	default:
f96637be0   Joe Perches   [CIFS] cifs: Rena...
105
106
  		cifs_dbg(VFS, "Invalid command
  ");
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
107
108
  		break;
  	}
064f6047a   Pavel Shilovsky   CIFS: Make SMB2_o...
109
  	rc = SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
110
111
112
113
114
  	if (tmprc)
  		rc = tmprc;
  	kfree(utf16_path);
  	return rc;
  }
f0df737ee   Pavel Shilovsky   CIFS: Add open/cl...
115
  void
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
116
117
118
119
120
121
122
123
124
125
126
127
  move_smb2_info_to_cifs(FILE_ALL_INFO *dst, struct smb2_file_all_info *src)
  {
  	memcpy(dst, src, (size_t)(&src->CurrentByteOffset) - (size_t)src);
  	dst->CurrentByteOffset = src->CurrentByteOffset;
  	dst->Mode = src->Mode;
  	dst->AlignmentRequirement = src->AlignmentRequirement;
  	dst->IndexNumber1 = 0; /* we don't use it */
  }
  
  int
  smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
  		     struct cifs_sb_info *cifs_sb, const char *full_path,
eb85d94bd   Pavel Shilovsky   CIFS: Fix symboli...
128
  		     FILE_ALL_INFO *data, bool *adjust_tz, bool *symlink)
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
129
130
131
132
133
  {
  	int rc;
  	struct smb2_file_all_info *smb2_data;
  
  	*adjust_tz = false;
eb85d94bd   Pavel Shilovsky   CIFS: Fix symboli...
134
  	*symlink = false;
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
135

1bbe4997b   Pavel Shilovsky   CIFS: Fix wrong f...
136
  	smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
137
138
139
140
141
  			    GFP_KERNEL);
  	if (smb2_data == NULL)
  		return -ENOMEM;
  
  	rc = smb2_open_op_close(xid, tcon, cifs_sb, full_path,
eb85d94bd   Pavel Shilovsky   CIFS: Fix symboli...
142
143
144
145
146
147
148
149
150
151
  				FILE_READ_ATTRIBUTES, FILE_OPEN, 0,
  				smb2_data, SMB2_OP_QUERY_INFO);
  	if (rc == -EOPNOTSUPP) {
  		*symlink = true;
  		/* Failed on a symbolic link - query a reparse point info */
  		rc = smb2_open_op_close(xid, tcon, cifs_sb, full_path,
  					FILE_READ_ATTRIBUTES, FILE_OPEN,
  					OPEN_REPARSE_POINT, smb2_data,
  					SMB2_OP_QUERY_INFO);
  	}
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
152
153
154
155
156
157
158
159
  	if (rc)
  		goto out;
  
  	move_smb2_info_to_cifs(data, smb2_data);
  out:
  	kfree(smb2_data);
  	return rc;
  }
a0e731839   Pavel Shilovsky   CIFS: Add SMB2 su...
160
161
162
163
164
165
  
  int
  smb2_mkdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
  	   struct cifs_sb_info *cifs_sb)
  {
  	return smb2_open_op_close(xid, tcon, cifs_sb, name,
ca81983fe   Pavel Shilovsky   CIFS: Respect cre...
166
  				  FILE_WRITE_ATTRIBUTES, FILE_CREATE,
a0e731839   Pavel Shilovsky   CIFS: Add SMB2 su...
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
  				  CREATE_NOT_FILE, NULL, SMB2_OP_MKDIR);
  }
  
  void
  smb2_mkdir_setinfo(struct inode *inode, const char *name,
  		   struct cifs_sb_info *cifs_sb, struct cifs_tcon *tcon,
  		   const unsigned int xid)
  {
  	FILE_BASIC_INFO data;
  	struct cifsInodeInfo *cifs_i;
  	u32 dosattrs;
  	int tmprc;
  
  	memset(&data, 0, sizeof(data));
  	cifs_i = CIFS_I(inode);
  	dosattrs = cifs_i->cifsAttrs | ATTR_READONLY;
  	data.Attributes = cpu_to_le32(dosattrs);
  	tmprc = smb2_open_op_close(xid, tcon, cifs_sb, name,
ca81983fe   Pavel Shilovsky   CIFS: Respect cre...
185
  				   FILE_WRITE_ATTRIBUTES, FILE_CREATE,
a0e731839   Pavel Shilovsky   CIFS: Add SMB2 su...
186
187
188
189
  				   CREATE_NOT_FILE, &data, SMB2_OP_SET_INFO);
  	if (tmprc == 0)
  		cifs_i->cifsAttrs = dosattrs;
  }
1a500f010   Pavel Shilovsky   CIFS: Add SMB2 su...
190
191
192
193
194
195
  
  int
  smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
  	   struct cifs_sb_info *cifs_sb)
  {
  	return smb2_open_op_close(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
897fba117   Steve French   remove directory ...
196
197
  				  CREATE_NOT_FILE,
  				  NULL, SMB2_OP_RMDIR);
1a500f010   Pavel Shilovsky   CIFS: Add SMB2 su...
198
  }
cbe6f439f   Pavel Shilovsky   CIFS: Add SMB2 su...
199
200
201
202
203
204
  
  int
  smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
  	    struct cifs_sb_info *cifs_sb)
  {
  	return smb2_open_op_close(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
b42bf8882   Pavel Shilovsky   CIFS: Implement f...
205
206
  				  CREATE_DELETE_ON_CLOSE | OPEN_REPARSE_POINT,
  				  NULL, SMB2_OP_DELETE);
cbe6f439f   Pavel Shilovsky   CIFS: Add SMB2 su...
207
  }
35143eb5c   Pavel Shilovsky   CIFS: Add SMB2 su...
208

568798cc6   Pavel Shilovsky   CIFS: Add SMB2 su...
209
210
211
212
  static int
  smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon,
  		   const char *from_name, const char *to_name,
  		   struct cifs_sb_info *cifs_sb, __u32 access, int command)
35143eb5c   Pavel Shilovsky   CIFS: Add SMB2 su...
213
214
215
216
217
218
219
220
221
  {
  	__le16 *smb2_to_name = NULL;
  	int rc;
  
  	smb2_to_name = cifs_convert_path_to_utf16(to_name, cifs_sb);
  	if (smb2_to_name == NULL) {
  		rc = -ENOMEM;
  		goto smb2_rename_path;
  	}
568798cc6   Pavel Shilovsky   CIFS: Add SMB2 su...
222
  	rc = smb2_open_op_close(xid, tcon, cifs_sb, from_name, access,
ca81983fe   Pavel Shilovsky   CIFS: Respect cre...
223
  				FILE_OPEN, 0, smb2_to_name, command);
35143eb5c   Pavel Shilovsky   CIFS: Add SMB2 su...
224
225
226
227
  smb2_rename_path:
  	kfree(smb2_to_name);
  	return rc;
  }
568798cc6   Pavel Shilovsky   CIFS: Add SMB2 su...
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
  
  int
  smb2_rename_path(const unsigned int xid, struct cifs_tcon *tcon,
  		 const char *from_name, const char *to_name,
  		 struct cifs_sb_info *cifs_sb)
  {
  	return smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
  				  DELETE, SMB2_OP_RENAME);
  }
  
  int
  smb2_create_hardlink(const unsigned int xid, struct cifs_tcon *tcon,
  		     const char *from_name, const char *to_name,
  		     struct cifs_sb_info *cifs_sb)
  {
  	return smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
  				  FILE_READ_ATTRIBUTES, SMB2_OP_HARDLINK);
  }
c839ff244   Pavel Shilovsky   CIFS: Add SMB2 su...
246
247
248
249
250
251
252
253
  
  int
  smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon,
  		   const char *full_path, __u64 size,
  		   struct cifs_sb_info *cifs_sb, bool set_alloc)
  {
  	__le64 eof = cpu_to_le64(size);
  	return smb2_open_op_close(xid, tcon, cifs_sb, full_path,
ca81983fe   Pavel Shilovsky   CIFS: Respect cre...
254
  				  FILE_WRITE_DATA, FILE_OPEN, 0, &eof,
c839ff244   Pavel Shilovsky   CIFS: Add SMB2 su...
255
256
  				  SMB2_OP_SET_EOF);
  }
1feeaac75   Pavel Shilovsky   CIFS: Add set_fil...
257
258
259
260
261
262
263
264
  
  int
  smb2_set_file_info(struct inode *inode, const char *full_path,
  		   FILE_BASIC_INFO *buf, const unsigned int xid)
  {
  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
  	struct tcon_link *tlink;
  	int rc;
18dd8e1a6   Steve French   Do not send SMB3 ...
265
266
267
268
  	if ((buf->CreationTime == 0) && (buf->LastAccessTime == 0) &&
  	    (buf->LastWriteTime == 0) && (buf->ChangeTime) &&
  	    (buf->Attributes == 0))
  		return 0; /* would be a no op, no sense sending this */
1feeaac75   Pavel Shilovsky   CIFS: Add set_fil...
269
270
271
  	tlink = cifs_sb_tlink(cifs_sb);
  	if (IS_ERR(tlink))
  		return PTR_ERR(tlink);
18dd8e1a6   Steve French   Do not send SMB3 ...
272

1feeaac75   Pavel Shilovsky   CIFS: Add set_fil...
273
  	rc = smb2_open_op_close(xid, tlink_tcon(tlink), cifs_sb, full_path,
ca81983fe   Pavel Shilovsky   CIFS: Respect cre...
274
  				FILE_WRITE_ATTRIBUTES, FILE_OPEN, 0, buf,
1feeaac75   Pavel Shilovsky   CIFS: Add set_fil...
275
276
277
278
  				SMB2_OP_SET_INFO);
  	cifs_put_tlink(tlink);
  	return rc;
  }