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