• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *   fs/cifs/link.c
3  *
4  *   Copyright (C) International Business Machines  Corp., 2002,2008
5  *   Author(s): Steve French (sfrench@us.ibm.com)
6  *
7  *   This library is free software; you can redistribute it and/or modify
8  *   it under the terms of the GNU Lesser General Public License as published
9  *   by the Free Software Foundation; either version 2.1 of the License, or
10  *   (at your option) any later version.
11  *
12  *   This library is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15  *   the GNU Lesser General Public License for more details.
16  *
17  *   You should have received a copy of the GNU Lesser General Public License
18  *   along with this library; if not, write to the Free Software
19  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */
21 #include <linux/fs.h>
22 #include <linux/stat.h>
23 #include <linux/slab.h>
24 #include <linux/namei.h>
25 #include "cifsfs.h"
26 #include "cifspdu.h"
27 #include "cifsglob.h"
28 #include "cifsproto.h"
29 #include "cifs_debug.h"
30 #include "cifs_fs_sb.h"
31 #include "cifs_unicode.h"
32 #ifdef CONFIG_CIFS_SMB2
33 #include "smb2proto.h"
34 #endif
35 
36 /*
37  * M-F Symlink Functions - Begin
38  */
39 
40 #define CIFS_MF_SYMLINK_LEN_OFFSET (4+1)
41 #define CIFS_MF_SYMLINK_MD5_OFFSET (CIFS_MF_SYMLINK_LEN_OFFSET+(4+1))
42 #define CIFS_MF_SYMLINK_LINK_OFFSET (CIFS_MF_SYMLINK_MD5_OFFSET+(32+1))
43 #define CIFS_MF_SYMLINK_LINK_MAXLEN (1024)
44 #define CIFS_MF_SYMLINK_FILE_SIZE \
45 	(CIFS_MF_SYMLINK_LINK_OFFSET + CIFS_MF_SYMLINK_LINK_MAXLEN)
46 
47 #define CIFS_MF_SYMLINK_LEN_FORMAT "XSym\n%04u\n"
48 #define CIFS_MF_SYMLINK_MD5_FORMAT \
49 	"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n"
50 #define CIFS_MF_SYMLINK_MD5_ARGS(md5_hash) \
51 	md5_hash[0],  md5_hash[1],  md5_hash[2],  md5_hash[3], \
52 	md5_hash[4],  md5_hash[5],  md5_hash[6],  md5_hash[7], \
53 	md5_hash[8],  md5_hash[9],  md5_hash[10], md5_hash[11],\
54 	md5_hash[12], md5_hash[13], md5_hash[14], md5_hash[15]
55 
56 static int
symlink_hash(unsigned int link_len,const char * link_str,u8 * md5_hash)57 symlink_hash(unsigned int link_len, const char *link_str, u8 *md5_hash)
58 {
59 	int rc;
60 	unsigned int size;
61 	struct crypto_shash *md5;
62 	struct sdesc *sdescmd5;
63 
64 	md5 = crypto_alloc_shash("md5", 0, 0);
65 	if (IS_ERR(md5)) {
66 		rc = PTR_ERR(md5);
67 		cifs_dbg(VFS, "%s: Crypto md5 allocation error %d\n",
68 			 __func__, rc);
69 		return rc;
70 	}
71 	size = sizeof(struct shash_desc) + crypto_shash_descsize(md5);
72 	sdescmd5 = kmalloc(size, GFP_KERNEL);
73 	if (!sdescmd5) {
74 		rc = -ENOMEM;
75 		goto symlink_hash_err;
76 	}
77 	sdescmd5->shash.tfm = md5;
78 	sdescmd5->shash.flags = 0x0;
79 
80 	rc = crypto_shash_init(&sdescmd5->shash);
81 	if (rc) {
82 		cifs_dbg(VFS, "%s: Could not init md5 shash\n", __func__);
83 		goto symlink_hash_err;
84 	}
85 	rc = crypto_shash_update(&sdescmd5->shash, link_str, link_len);
86 	if (rc) {
87 		cifs_dbg(VFS, "%s: Could not update with link_str\n", __func__);
88 		goto symlink_hash_err;
89 	}
90 	rc = crypto_shash_final(&sdescmd5->shash, md5_hash);
91 	if (rc)
92 		cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
93 
94 symlink_hash_err:
95 	crypto_free_shash(md5);
96 	kfree(sdescmd5);
97 
98 	return rc;
99 }
100 
101 static int
parse_mf_symlink(const u8 * buf,unsigned int buf_len,unsigned int * _link_len,char ** _link_str)102 parse_mf_symlink(const u8 *buf, unsigned int buf_len, unsigned int *_link_len,
103 		 char **_link_str)
104 {
105 	int rc;
106 	unsigned int link_len;
107 	const char *md5_str1;
108 	const char *link_str;
109 	u8 md5_hash[16];
110 	char md5_str2[34];
111 
112 	if (buf_len != CIFS_MF_SYMLINK_FILE_SIZE)
113 		return -EINVAL;
114 
115 	md5_str1 = (const char *)&buf[CIFS_MF_SYMLINK_MD5_OFFSET];
116 	link_str = (const char *)&buf[CIFS_MF_SYMLINK_LINK_OFFSET];
117 
118 	rc = sscanf(buf, CIFS_MF_SYMLINK_LEN_FORMAT, &link_len);
119 	if (rc != 1)
120 		return -EINVAL;
121 
122 	rc = symlink_hash(link_len, link_str, md5_hash);
123 	if (rc) {
124 		cifs_dbg(FYI, "%s: MD5 hash failure: %d\n", __func__, rc);
125 		return rc;
126 	}
127 
128 	snprintf(md5_str2, sizeof(md5_str2),
129 		 CIFS_MF_SYMLINK_MD5_FORMAT,
130 		 CIFS_MF_SYMLINK_MD5_ARGS(md5_hash));
131 
132 	if (strncmp(md5_str1, md5_str2, 17) != 0)
133 		return -EINVAL;
134 
135 	if (_link_str) {
136 		*_link_str = kstrndup(link_str, link_len, GFP_KERNEL);
137 		if (!*_link_str)
138 			return -ENOMEM;
139 	}
140 
141 	*_link_len = link_len;
142 	return 0;
143 }
144 
145 static int
format_mf_symlink(u8 * buf,unsigned int buf_len,const char * link_str)146 format_mf_symlink(u8 *buf, unsigned int buf_len, const char *link_str)
147 {
148 	int rc;
149 	unsigned int link_len;
150 	unsigned int ofs;
151 	u8 md5_hash[16];
152 
153 	if (buf_len != CIFS_MF_SYMLINK_FILE_SIZE)
154 		return -EINVAL;
155 
156 	link_len = strlen(link_str);
157 
158 	if (link_len > CIFS_MF_SYMLINK_LINK_MAXLEN)
159 		return -ENAMETOOLONG;
160 
161 	rc = symlink_hash(link_len, link_str, md5_hash);
162 	if (rc) {
163 		cifs_dbg(FYI, "%s: MD5 hash failure: %d\n", __func__, rc);
164 		return rc;
165 	}
166 
167 	snprintf(buf, buf_len,
168 		 CIFS_MF_SYMLINK_LEN_FORMAT CIFS_MF_SYMLINK_MD5_FORMAT,
169 		 link_len,
170 		 CIFS_MF_SYMLINK_MD5_ARGS(md5_hash));
171 
172 	ofs = CIFS_MF_SYMLINK_LINK_OFFSET;
173 	memcpy(buf + ofs, link_str, link_len);
174 
175 	ofs += link_len;
176 	if (ofs < CIFS_MF_SYMLINK_FILE_SIZE) {
177 		buf[ofs] = '\n';
178 		ofs++;
179 	}
180 
181 	while (ofs < CIFS_MF_SYMLINK_FILE_SIZE) {
182 		buf[ofs] = ' ';
183 		ofs++;
184 	}
185 
186 	return 0;
187 }
188 
189 bool
couldbe_mf_symlink(const struct cifs_fattr * fattr)190 couldbe_mf_symlink(const struct cifs_fattr *fattr)
191 {
192 	if (!S_ISREG(fattr->cf_mode))
193 		/* it's not a symlink */
194 		return false;
195 
196 	if (fattr->cf_eof != CIFS_MF_SYMLINK_FILE_SIZE)
197 		/* it's not a symlink */
198 		return false;
199 
200 	return true;
201 }
202 
203 static int
create_mf_symlink(const unsigned int xid,struct cifs_tcon * tcon,struct cifs_sb_info * cifs_sb,const char * fromName,const char * toName)204 create_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon,
205 		  struct cifs_sb_info *cifs_sb, const char *fromName,
206 		  const char *toName)
207 {
208 	int rc;
209 	u8 *buf;
210 	unsigned int bytes_written = 0;
211 
212 	buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
213 	if (!buf)
214 		return -ENOMEM;
215 
216 	rc = format_mf_symlink(buf, CIFS_MF_SYMLINK_FILE_SIZE, toName);
217 	if (rc)
218 		goto out;
219 
220 	if (tcon->ses->server->ops->create_mf_symlink)
221 		rc = tcon->ses->server->ops->create_mf_symlink(xid, tcon,
222 					cifs_sb, fromName, buf, &bytes_written);
223 	else
224 		rc = -EOPNOTSUPP;
225 
226 	if (rc)
227 		goto out;
228 
229 	if (bytes_written != CIFS_MF_SYMLINK_FILE_SIZE)
230 		rc = -EIO;
231 out:
232 	kfree(buf);
233 	return rc;
234 }
235 
236 static int
query_mf_symlink(const unsigned int xid,struct cifs_tcon * tcon,struct cifs_sb_info * cifs_sb,const unsigned char * path,char ** symlinkinfo)237 query_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon,
238 		 struct cifs_sb_info *cifs_sb, const unsigned char *path,
239 		 char **symlinkinfo)
240 {
241 	int rc;
242 	u8 *buf = NULL;
243 	unsigned int link_len = 0;
244 	unsigned int bytes_read = 0;
245 
246 	buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
247 	if (!buf)
248 		return -ENOMEM;
249 
250 	if (tcon->ses->server->ops->query_mf_symlink)
251 		rc = tcon->ses->server->ops->query_mf_symlink(xid, tcon,
252 					      cifs_sb, path, buf, &bytes_read);
253 	else
254 		rc = -ENOSYS;
255 
256 	if (rc)
257 		goto out;
258 
259 	if (bytes_read == 0) { /* not a symlink */
260 		rc = -EINVAL;
261 		goto out;
262 	}
263 
264 	rc = parse_mf_symlink(buf, bytes_read, &link_len, symlinkinfo);
265 out:
266 	kfree(buf);
267 	return rc;
268 }
269 
270 int
check_mf_symlink(unsigned int xid,struct cifs_tcon * tcon,struct cifs_sb_info * cifs_sb,struct cifs_fattr * fattr,const unsigned char * path)271 check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
272 		 struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
273 		 const unsigned char *path)
274 {
275 	int rc;
276 	u8 *buf = NULL;
277 	unsigned int link_len = 0;
278 	unsigned int bytes_read = 0;
279 
280 	if (!couldbe_mf_symlink(fattr))
281 		/* it's not a symlink */
282 		return 0;
283 
284 	buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
285 	if (!buf)
286 		return -ENOMEM;
287 
288 	if (tcon->ses->server->ops->query_mf_symlink)
289 		rc = tcon->ses->server->ops->query_mf_symlink(xid, tcon,
290 					      cifs_sb, path, buf, &bytes_read);
291 	else
292 		rc = -ENOSYS;
293 
294 	if (rc)
295 		goto out;
296 
297 	if (bytes_read == 0) /* not a symlink */
298 		goto out;
299 
300 	rc = parse_mf_symlink(buf, bytes_read, &link_len, NULL);
301 	if (rc == -EINVAL) {
302 		/* it's not a symlink */
303 		rc = 0;
304 		goto out;
305 	}
306 
307 	if (rc != 0)
308 		goto out;
309 
310 	/* it is a symlink */
311 	fattr->cf_eof = link_len;
312 	fattr->cf_mode &= ~S_IFMT;
313 	fattr->cf_mode |= S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO;
314 	fattr->cf_dtype = DT_LNK;
315 out:
316 	kfree(buf);
317 	return rc;
318 }
319 
320 /*
321  * SMB 1.0 Protocol specific functions
322  */
323 
324 int
cifs_query_mf_symlink(unsigned int xid,struct cifs_tcon * tcon,struct cifs_sb_info * cifs_sb,const unsigned char * path,char * pbuf,unsigned int * pbytes_read)325 cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
326 		      struct cifs_sb_info *cifs_sb, const unsigned char *path,
327 		      char *pbuf, unsigned int *pbytes_read)
328 {
329 	int rc;
330 	int oplock = 0;
331 	struct cifs_fid fid;
332 	struct cifs_open_parms oparms;
333 	struct cifs_io_parms io_parms;
334 	int buf_type = CIFS_NO_BUFFER;
335 	FILE_ALL_INFO file_info;
336 
337 	oparms.tcon = tcon;
338 	oparms.cifs_sb = cifs_sb;
339 	oparms.desired_access = GENERIC_READ;
340 	oparms.create_options = CREATE_NOT_DIR;
341 	oparms.disposition = FILE_OPEN;
342 	oparms.path = path;
343 	oparms.fid = &fid;
344 	oparms.reconnect = false;
345 
346 	rc = CIFS_open(xid, &oparms, &oplock, &file_info);
347 	if (rc)
348 		return rc;
349 
350 	if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) {
351 		rc = -ENOENT;
352 		/* it's not a symlink */
353 		goto out;
354 	}
355 
356 	io_parms.netfid = fid.netfid;
357 	io_parms.pid = current->tgid;
358 	io_parms.tcon = tcon;
359 	io_parms.offset = 0;
360 	io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
361 
362 	rc = CIFSSMBRead(xid, &io_parms, pbytes_read, &pbuf, &buf_type);
363 out:
364 	CIFSSMBClose(xid, tcon, fid.netfid);
365 	return rc;
366 }
367 
368 int
cifs_create_mf_symlink(unsigned int xid,struct cifs_tcon * tcon,struct cifs_sb_info * cifs_sb,const unsigned char * path,char * pbuf,unsigned int * pbytes_written)369 cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
370 		       struct cifs_sb_info *cifs_sb, const unsigned char *path,
371 		       char *pbuf, unsigned int *pbytes_written)
372 {
373 	int rc;
374 	int oplock = 0;
375 	struct cifs_fid fid;
376 	struct cifs_open_parms oparms;
377 	struct cifs_io_parms io_parms;
378 	int create_options = CREATE_NOT_DIR;
379 
380 	if (backup_cred(cifs_sb))
381 		create_options |= CREATE_OPEN_BACKUP_INTENT;
382 
383 	oparms.tcon = tcon;
384 	oparms.cifs_sb = cifs_sb;
385 	oparms.desired_access = GENERIC_WRITE;
386 	oparms.create_options = create_options;
387 	oparms.disposition = FILE_CREATE;
388 	oparms.path = path;
389 	oparms.fid = &fid;
390 	oparms.reconnect = false;
391 
392 	rc = CIFS_open(xid, &oparms, &oplock, NULL);
393 	if (rc)
394 		return rc;
395 
396 	io_parms.netfid = fid.netfid;
397 	io_parms.pid = current->tgid;
398 	io_parms.tcon = tcon;
399 	io_parms.offset = 0;
400 	io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
401 
402 	rc = CIFSSMBWrite(xid, &io_parms, pbytes_written, pbuf, NULL, 0);
403 	CIFSSMBClose(xid, tcon, fid.netfid);
404 	return rc;
405 }
406 
407 /*
408  * SMB 2.1/SMB3 Protocol specific functions
409  */
410 #ifdef CONFIG_CIFS_SMB2
411 int
smb3_query_mf_symlink(unsigned int xid,struct cifs_tcon * tcon,struct cifs_sb_info * cifs_sb,const unsigned char * path,char * pbuf,unsigned int * pbytes_read)412 smb3_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
413 		      struct cifs_sb_info *cifs_sb, const unsigned char *path,
414 		      char *pbuf, unsigned int *pbytes_read)
415 {
416 	int rc;
417 	struct cifs_fid fid;
418 	struct cifs_open_parms oparms;
419 	struct cifs_io_parms io_parms;
420 	int buf_type = CIFS_NO_BUFFER;
421 	__le16 *utf16_path;
422 	__u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
423 	struct smb2_file_all_info *pfile_info = NULL;
424 
425 	oparms.tcon = tcon;
426 	oparms.cifs_sb = cifs_sb;
427 	oparms.desired_access = GENERIC_READ;
428 	oparms.create_options = CREATE_NOT_DIR;
429 	if (backup_cred(cifs_sb))
430 		oparms.create_options |= CREATE_OPEN_BACKUP_INTENT;
431 	oparms.disposition = FILE_OPEN;
432 	oparms.fid = &fid;
433 	oparms.reconnect = false;
434 
435 	utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
436 	if (utf16_path == NULL)
437 		return -ENOMEM;
438 
439 	pfile_info = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
440 			     GFP_KERNEL);
441 
442 	if (pfile_info == NULL) {
443 		kfree(utf16_path);
444 		return  -ENOMEM;
445 	}
446 
447 	rc = SMB2_open(xid, &oparms, utf16_path, &oplock, pfile_info, NULL);
448 	if (rc)
449 		goto qmf_out_open_fail;
450 
451 	if (pfile_info->EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) {
452 		/* it's not a symlink */
453 		rc = -ENOENT; /* Is there a better rc to return? */
454 		goto qmf_out;
455 	}
456 
457 	io_parms.netfid = fid.netfid;
458 	io_parms.pid = current->tgid;
459 	io_parms.tcon = tcon;
460 	io_parms.offset = 0;
461 	io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
462 	io_parms.persistent_fid = fid.persistent_fid;
463 	io_parms.volatile_fid = fid.volatile_fid;
464 	rc = SMB2_read(xid, &io_parms, pbytes_read, &pbuf, &buf_type);
465 qmf_out:
466 	SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
467 qmf_out_open_fail:
468 	kfree(utf16_path);
469 	kfree(pfile_info);
470 	return rc;
471 }
472 
473 int
smb3_create_mf_symlink(unsigned int xid,struct cifs_tcon * tcon,struct cifs_sb_info * cifs_sb,const unsigned char * path,char * pbuf,unsigned int * pbytes_written)474 smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
475 		       struct cifs_sb_info *cifs_sb, const unsigned char *path,
476 		       char *pbuf, unsigned int *pbytes_written)
477 {
478 	int rc;
479 	struct cifs_fid fid;
480 	struct cifs_open_parms oparms;
481 	struct cifs_io_parms io_parms;
482 	int create_options = CREATE_NOT_DIR;
483 	__le16 *utf16_path;
484 	__u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
485 	struct kvec iov[2];
486 
487 	if (backup_cred(cifs_sb))
488 		create_options |= CREATE_OPEN_BACKUP_INTENT;
489 
490 	cifs_dbg(FYI, "%s: path: %s\n", __func__, path);
491 
492 	utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
493 	if (!utf16_path)
494 		return -ENOMEM;
495 
496 	oparms.tcon = tcon;
497 	oparms.cifs_sb = cifs_sb;
498 	oparms.desired_access = GENERIC_WRITE;
499 	oparms.create_options = create_options;
500 	oparms.disposition = FILE_CREATE;
501 	oparms.fid = &fid;
502 	oparms.reconnect = false;
503 
504 	rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
505 	if (rc) {
506 		kfree(utf16_path);
507 		return rc;
508 	}
509 
510 	io_parms.netfid = fid.netfid;
511 	io_parms.pid = current->tgid;
512 	io_parms.tcon = tcon;
513 	io_parms.offset = 0;
514 	io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
515 	io_parms.persistent_fid = fid.persistent_fid;
516 	io_parms.volatile_fid = fid.volatile_fid;
517 
518 	/* iov[0] is reserved for smb header */
519 	iov[1].iov_base = pbuf;
520 	iov[1].iov_len = CIFS_MF_SYMLINK_FILE_SIZE;
521 
522 	rc = SMB2_write(xid, &io_parms, pbytes_written, iov, 1);
523 
524 	/* Make sure we wrote all of the symlink data */
525 	if ((rc == 0) && (*pbytes_written != CIFS_MF_SYMLINK_FILE_SIZE))
526 		rc = -EIO;
527 
528 	SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
529 
530 	kfree(utf16_path);
531 	return rc;
532 }
533 #endif /* CONFIG_CIFS_SMB2 */
534 
535 /*
536  * M-F Symlink Functions - End
537  */
538 
539 int
cifs_hardlink(struct dentry * old_file,struct inode * inode,struct dentry * direntry)540 cifs_hardlink(struct dentry *old_file, struct inode *inode,
541 	      struct dentry *direntry)
542 {
543 	int rc = -EACCES;
544 	unsigned int xid;
545 	char *from_name = NULL;
546 	char *to_name = NULL;
547 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
548 	struct tcon_link *tlink;
549 	struct cifs_tcon *tcon;
550 	struct TCP_Server_Info *server;
551 	struct cifsInodeInfo *cifsInode;
552 
553 	tlink = cifs_sb_tlink(cifs_sb);
554 	if (IS_ERR(tlink))
555 		return PTR_ERR(tlink);
556 	tcon = tlink_tcon(tlink);
557 
558 	xid = get_xid();
559 
560 	from_name = build_path_from_dentry(old_file);
561 	to_name = build_path_from_dentry(direntry);
562 	if ((from_name == NULL) || (to_name == NULL)) {
563 		rc = -ENOMEM;
564 		goto cifs_hl_exit;
565 	}
566 
567 	if (tcon->unix_ext)
568 		rc = CIFSUnixCreateHardLink(xid, tcon, from_name, to_name,
569 					    cifs_sb->local_nls,
570 					    cifs_remap(cifs_sb));
571 	else {
572 		server = tcon->ses->server;
573 		if (!server->ops->create_hardlink) {
574 			rc = -ENOSYS;
575 			goto cifs_hl_exit;
576 		}
577 		rc = server->ops->create_hardlink(xid, tcon, from_name, to_name,
578 						  cifs_sb);
579 		if ((rc == -EIO) || (rc == -EINVAL))
580 			rc = -EOPNOTSUPP;
581 	}
582 
583 	d_drop(direntry);	/* force new lookup from server of target */
584 
585 	/*
586 	 * if source file is cached (oplocked) revalidate will not go to server
587 	 * until the file is closed or oplock broken so update nlinks locally
588 	 */
589 	if (d_really_is_positive(old_file)) {
590 		cifsInode = CIFS_I(d_inode(old_file));
591 		if (rc == 0) {
592 			spin_lock(&d_inode(old_file)->i_lock);
593 			inc_nlink(d_inode(old_file));
594 			spin_unlock(&d_inode(old_file)->i_lock);
595 
596 			/*
597 			 * parent dir timestamps will update from srv within a
598 			 * second, would it really be worth it to set the parent
599 			 * dir cifs inode time to zero to force revalidate
600 			 * (faster) for it too?
601 			 */
602 		}
603 		/*
604 		 * if not oplocked will force revalidate to get info on source
605 		 * file from srv.  Note Samba server prior to 4.2 has bug -
606 		 * not updating src file ctime on hardlinks but Windows servers
607 		 * handle it properly
608 		 */
609 		cifsInode->time = 0;
610 
611 		/*
612 		 * Will update parent dir timestamps from srv within a second.
613 		 * Would it really be worth it to set the parent dir (cifs
614 		 * inode) time field to zero to force revalidate on parent
615 		 * directory faster ie
616 		 *
617 		 * CIFS_I(inode)->time = 0;
618 		 */
619 	}
620 
621 cifs_hl_exit:
622 	kfree(from_name);
623 	kfree(to_name);
624 	free_xid(xid);
625 	cifs_put_tlink(tlink);
626 	return rc;
627 }
628 
629 const char *
cifs_follow_link(struct dentry * direntry,void ** cookie)630 cifs_follow_link(struct dentry *direntry, void **cookie)
631 {
632 	struct inode *inode = d_inode(direntry);
633 	int rc = -ENOMEM;
634 	unsigned int xid;
635 	char *full_path = NULL;
636 	char *target_path = NULL;
637 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
638 	struct tcon_link *tlink = NULL;
639 	struct cifs_tcon *tcon;
640 	struct TCP_Server_Info *server;
641 
642 	xid = get_xid();
643 
644 	tlink = cifs_sb_tlink(cifs_sb);
645 	if (IS_ERR(tlink)) {
646 		free_xid(xid);
647 		return ERR_CAST(tlink);
648 	}
649 	tcon = tlink_tcon(tlink);
650 	server = tcon->ses->server;
651 
652 	full_path = build_path_from_dentry(direntry);
653 	if (!full_path) {
654 		free_xid(xid);
655 		cifs_put_tlink(tlink);
656 		return ERR_PTR(-ENOMEM);
657 	}
658 
659 	cifs_dbg(FYI, "Full path: %s inode = 0x%p\n", full_path, inode);
660 
661 	rc = -EACCES;
662 	/*
663 	 * First try Minshall+French Symlinks, if configured
664 	 * and fallback to UNIX Extensions Symlinks.
665 	 */
666 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
667 		rc = query_mf_symlink(xid, tcon, cifs_sb, full_path,
668 				      &target_path);
669 
670 	if (rc != 0 && server->ops->query_symlink)
671 		rc = server->ops->query_symlink(xid, tcon, full_path,
672 						&target_path, cifs_sb);
673 
674 	kfree(full_path);
675 	free_xid(xid);
676 	cifs_put_tlink(tlink);
677 	if (rc != 0) {
678 		kfree(target_path);
679 		return ERR_PTR(rc);
680 	}
681 	return *cookie = target_path;
682 }
683 
684 int
cifs_symlink(struct inode * inode,struct dentry * direntry,const char * symname)685 cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
686 {
687 	int rc = -EOPNOTSUPP;
688 	unsigned int xid;
689 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
690 	struct tcon_link *tlink;
691 	struct cifs_tcon *pTcon;
692 	char *full_path = NULL;
693 	struct inode *newinode = NULL;
694 
695 	xid = get_xid();
696 
697 	tlink = cifs_sb_tlink(cifs_sb);
698 	if (IS_ERR(tlink)) {
699 		rc = PTR_ERR(tlink);
700 		goto symlink_exit;
701 	}
702 	pTcon = tlink_tcon(tlink);
703 
704 	full_path = build_path_from_dentry(direntry);
705 	if (full_path == NULL) {
706 		rc = -ENOMEM;
707 		goto symlink_exit;
708 	}
709 
710 	cifs_dbg(FYI, "Full path: %s\n", full_path);
711 	cifs_dbg(FYI, "symname is %s\n", symname);
712 
713 	/* BB what if DFS and this volume is on different share? BB */
714 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
715 		rc = create_mf_symlink(xid, pTcon, cifs_sb, full_path, symname);
716 	else if (pTcon->unix_ext)
717 		rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
718 					   cifs_sb->local_nls,
719 					   cifs_remap(cifs_sb));
720 	/* else
721 	   rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName,
722 					cifs_sb_target->local_nls); */
723 
724 	if (rc == 0) {
725 		if (pTcon->unix_ext)
726 			rc = cifs_get_inode_info_unix(&newinode, full_path,
727 						      inode->i_sb, xid);
728 		else
729 			rc = cifs_get_inode_info(&newinode, full_path, NULL,
730 						 inode->i_sb, xid, NULL);
731 
732 		if (rc != 0) {
733 			cifs_dbg(FYI, "Create symlink ok, getinodeinfo fail rc = %d\n",
734 				 rc);
735 		} else {
736 			d_instantiate(direntry, newinode);
737 		}
738 	}
739 symlink_exit:
740 	kfree(full_path);
741 	cifs_put_tlink(tlink);
742 	free_xid(xid);
743 	return rc;
744 }
745