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