at v6.0 745 lines 18 kB view raw
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#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY 290/* 291 * SMB 1.0 Protocol specific functions 292 */ 293 294int 295cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, 296 struct cifs_sb_info *cifs_sb, const unsigned char *path, 297 char *pbuf, unsigned int *pbytes_read) 298{ 299 int rc; 300 int oplock = 0; 301 struct cifs_fid fid; 302 struct cifs_open_parms oparms; 303 struct cifs_io_parms io_parms = {0}; 304 int buf_type = CIFS_NO_BUFFER; 305 FILE_ALL_INFO file_info; 306 307 oparms.tcon = tcon; 308 oparms.cifs_sb = cifs_sb; 309 oparms.desired_access = GENERIC_READ; 310 oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR); 311 oparms.disposition = FILE_OPEN; 312 oparms.path = path; 313 oparms.fid = &fid; 314 oparms.reconnect = false; 315 316 rc = CIFS_open(xid, &oparms, &oplock, &file_info); 317 if (rc) 318 return rc; 319 320 if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) { 321 rc = -ENOENT; 322 /* it's not a symlink */ 323 goto out; 324 } 325 326 io_parms.netfid = fid.netfid; 327 io_parms.pid = current->tgid; 328 io_parms.tcon = tcon; 329 io_parms.offset = 0; 330 io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; 331 332 rc = CIFSSMBRead(xid, &io_parms, pbytes_read, &pbuf, &buf_type); 333out: 334 CIFSSMBClose(xid, tcon, fid.netfid); 335 return rc; 336} 337 338int 339cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, 340 struct cifs_sb_info *cifs_sb, const unsigned char *path, 341 char *pbuf, unsigned int *pbytes_written) 342{ 343 int rc; 344 int oplock = 0; 345 struct cifs_fid fid; 346 struct cifs_open_parms oparms; 347 struct cifs_io_parms io_parms = {0}; 348 349 oparms.tcon = tcon; 350 oparms.cifs_sb = cifs_sb; 351 oparms.desired_access = GENERIC_WRITE; 352 oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR); 353 oparms.disposition = FILE_CREATE; 354 oparms.path = path; 355 oparms.fid = &fid; 356 oparms.reconnect = false; 357 358 rc = CIFS_open(xid, &oparms, &oplock, NULL); 359 if (rc) 360 return rc; 361 362 io_parms.netfid = fid.netfid; 363 io_parms.pid = current->tgid; 364 io_parms.tcon = tcon; 365 io_parms.offset = 0; 366 io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; 367 368 rc = CIFSSMBWrite(xid, &io_parms, pbytes_written, pbuf); 369 CIFSSMBClose(xid, tcon, fid.netfid); 370 return rc; 371} 372#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ 373 374/* 375 * SMB 2.1/SMB3 Protocol specific functions 376 */ 377int 378smb3_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, 379 struct cifs_sb_info *cifs_sb, const unsigned char *path, 380 char *pbuf, unsigned int *pbytes_read) 381{ 382 int rc; 383 struct cifs_fid fid; 384 struct cifs_open_parms oparms; 385 struct cifs_io_parms io_parms = {0}; 386 int buf_type = CIFS_NO_BUFFER; 387 __le16 *utf16_path; 388 __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; 389 struct smb2_file_all_info *pfile_info = NULL; 390 391 oparms.tcon = tcon; 392 oparms.cifs_sb = cifs_sb; 393 oparms.desired_access = GENERIC_READ; 394 oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR); 395 oparms.disposition = FILE_OPEN; 396 oparms.fid = &fid; 397 oparms.reconnect = false; 398 399 utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); 400 if (utf16_path == NULL) 401 return -ENOMEM; 402 403 pfile_info = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2, 404 GFP_KERNEL); 405 406 if (pfile_info == NULL) { 407 kfree(utf16_path); 408 return -ENOMEM; 409 } 410 411 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, pfile_info, NULL, 412 NULL, NULL); 413 if (rc) 414 goto qmf_out_open_fail; 415 416 if (pfile_info->EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) { 417 /* it's not a symlink */ 418 rc = -ENOENT; /* Is there a better rc to return? */ 419 goto qmf_out; 420 } 421 422 io_parms.netfid = fid.netfid; 423 io_parms.pid = current->tgid; 424 io_parms.tcon = tcon; 425 io_parms.offset = 0; 426 io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; 427 io_parms.persistent_fid = fid.persistent_fid; 428 io_parms.volatile_fid = fid.volatile_fid; 429 rc = SMB2_read(xid, &io_parms, pbytes_read, &pbuf, &buf_type); 430qmf_out: 431 SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); 432qmf_out_open_fail: 433 kfree(utf16_path); 434 kfree(pfile_info); 435 return rc; 436} 437 438int 439smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, 440 struct cifs_sb_info *cifs_sb, const unsigned char *path, 441 char *pbuf, unsigned int *pbytes_written) 442{ 443 int rc; 444 struct cifs_fid fid; 445 struct cifs_open_parms oparms; 446 struct cifs_io_parms io_parms = {0}; 447 __le16 *utf16_path; 448 __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; 449 struct kvec iov[2]; 450 451 cifs_dbg(FYI, "%s: path: %s\n", __func__, path); 452 453 utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); 454 if (!utf16_path) 455 return -ENOMEM; 456 457 oparms.tcon = tcon; 458 oparms.cifs_sb = cifs_sb; 459 oparms.desired_access = GENERIC_WRITE; 460 oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR); 461 oparms.disposition = FILE_CREATE; 462 oparms.fid = &fid; 463 oparms.reconnect = false; 464 465 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, 466 NULL, NULL); 467 if (rc) { 468 kfree(utf16_path); 469 return rc; 470 } 471 472 io_parms.netfid = fid.netfid; 473 io_parms.pid = current->tgid; 474 io_parms.tcon = tcon; 475 io_parms.offset = 0; 476 io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; 477 io_parms.persistent_fid = fid.persistent_fid; 478 io_parms.volatile_fid = fid.volatile_fid; 479 480 /* iov[0] is reserved for smb header */ 481 iov[1].iov_base = pbuf; 482 iov[1].iov_len = CIFS_MF_SYMLINK_FILE_SIZE; 483 484 rc = SMB2_write(xid, &io_parms, pbytes_written, iov, 1); 485 486 /* Make sure we wrote all of the symlink data */ 487 if ((rc == 0) && (*pbytes_written != CIFS_MF_SYMLINK_FILE_SIZE)) 488 rc = -EIO; 489 490 SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); 491 492 kfree(utf16_path); 493 return rc; 494} 495 496/* 497 * M-F Symlink Functions - End 498 */ 499 500int 501cifs_hardlink(struct dentry *old_file, struct inode *inode, 502 struct dentry *direntry) 503{ 504 int rc = -EACCES; 505 unsigned int xid; 506 const char *from_name, *to_name; 507 void *page1, *page2; 508 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 509 struct tcon_link *tlink; 510 struct cifs_tcon *tcon; 511 struct TCP_Server_Info *server; 512 struct cifsInodeInfo *cifsInode; 513 514 if (unlikely(cifs_forced_shutdown(cifs_sb))) 515 return -EIO; 516 517 tlink = cifs_sb_tlink(cifs_sb); 518 if (IS_ERR(tlink)) 519 return PTR_ERR(tlink); 520 tcon = tlink_tcon(tlink); 521 522 xid = get_xid(); 523 page1 = alloc_dentry_path(); 524 page2 = alloc_dentry_path(); 525 526 from_name = build_path_from_dentry(old_file, page1); 527 if (IS_ERR(from_name)) { 528 rc = PTR_ERR(from_name); 529 goto cifs_hl_exit; 530 } 531 to_name = build_path_from_dentry(direntry, page2); 532 if (IS_ERR(to_name)) { 533 rc = PTR_ERR(to_name); 534 goto cifs_hl_exit; 535 } 536 537#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY 538 if (tcon->unix_ext) 539 rc = CIFSUnixCreateHardLink(xid, tcon, from_name, to_name, 540 cifs_sb->local_nls, 541 cifs_remap(cifs_sb)); 542 else { 543#else 544 { 545#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ 546 server = tcon->ses->server; 547 if (!server->ops->create_hardlink) { 548 rc = -ENOSYS; 549 goto cifs_hl_exit; 550 } 551 rc = server->ops->create_hardlink(xid, tcon, from_name, to_name, 552 cifs_sb); 553 if ((rc == -EIO) || (rc == -EINVAL)) 554 rc = -EOPNOTSUPP; 555 } 556 557 d_drop(direntry); /* force new lookup from server of target */ 558 559 /* 560 * if source file is cached (oplocked) revalidate will not go to server 561 * until the file is closed or oplock broken so update nlinks locally 562 */ 563 if (d_really_is_positive(old_file)) { 564 cifsInode = CIFS_I(d_inode(old_file)); 565 if (rc == 0) { 566 spin_lock(&d_inode(old_file)->i_lock); 567 inc_nlink(d_inode(old_file)); 568 spin_unlock(&d_inode(old_file)->i_lock); 569 570 /* 571 * parent dir timestamps will update from srv within a 572 * second, would it really be worth it to set the parent 573 * dir cifs inode time to zero to force revalidate 574 * (faster) for it too? 575 */ 576 } 577 /* 578 * if not oplocked will force revalidate to get info on source 579 * file from srv. Note Samba server prior to 4.2 has bug - 580 * not updating src file ctime on hardlinks but Windows servers 581 * handle it properly 582 */ 583 cifsInode->time = 0; 584 585 /* 586 * Will update parent dir timestamps from srv within a second. 587 * Would it really be worth it to set the parent dir (cifs 588 * inode) time field to zero to force revalidate on parent 589 * directory faster ie 590 * 591 * CIFS_I(inode)->time = 0; 592 */ 593 } 594 595cifs_hl_exit: 596 free_dentry_path(page1); 597 free_dentry_path(page2); 598 free_xid(xid); 599 cifs_put_tlink(tlink); 600 return rc; 601} 602 603const char * 604cifs_get_link(struct dentry *direntry, struct inode *inode, 605 struct delayed_call *done) 606{ 607 int rc = -ENOMEM; 608 unsigned int xid; 609 const char *full_path; 610 void *page; 611 char *target_path = NULL; 612 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 613 struct tcon_link *tlink = NULL; 614 struct cifs_tcon *tcon; 615 struct TCP_Server_Info *server; 616 617 if (!direntry) 618 return ERR_PTR(-ECHILD); 619 620 xid = get_xid(); 621 622 tlink = cifs_sb_tlink(cifs_sb); 623 if (IS_ERR(tlink)) { 624 free_xid(xid); 625 return ERR_CAST(tlink); 626 } 627 tcon = tlink_tcon(tlink); 628 server = tcon->ses->server; 629 630 page = alloc_dentry_path(); 631 full_path = build_path_from_dentry(direntry, page); 632 if (IS_ERR(full_path)) { 633 free_xid(xid); 634 cifs_put_tlink(tlink); 635 free_dentry_path(page); 636 return ERR_CAST(full_path); 637 } 638 639 cifs_dbg(FYI, "Full path: %s inode = 0x%p\n", full_path, inode); 640 641 rc = -EACCES; 642 /* 643 * First try Minshall+French Symlinks, if configured 644 * and fallback to UNIX Extensions Symlinks. 645 */ 646 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) 647 rc = query_mf_symlink(xid, tcon, cifs_sb, full_path, 648 &target_path); 649 650 if (rc != 0 && server->ops->query_symlink) { 651 struct cifsInodeInfo *cifsi = CIFS_I(inode); 652 bool reparse_point = false; 653 654 if (cifsi->cifsAttrs & ATTR_REPARSE) 655 reparse_point = true; 656 657 rc = server->ops->query_symlink(xid, tcon, cifs_sb, full_path, 658 &target_path, reparse_point); 659 } 660 661 free_dentry_path(page); 662 free_xid(xid); 663 cifs_put_tlink(tlink); 664 if (rc != 0) { 665 kfree(target_path); 666 return ERR_PTR(rc); 667 } 668 set_delayed_call(done, kfree_link, target_path); 669 return target_path; 670} 671 672int 673cifs_symlink(struct user_namespace *mnt_userns, struct inode *inode, 674 struct dentry *direntry, const char *symname) 675{ 676 int rc = -EOPNOTSUPP; 677 unsigned int xid; 678 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 679 struct tcon_link *tlink; 680 struct cifs_tcon *pTcon; 681 const char *full_path; 682 void *page; 683 struct inode *newinode = NULL; 684 685 if (unlikely(cifs_forced_shutdown(cifs_sb))) 686 return -EIO; 687 688 page = alloc_dentry_path(); 689 if (!page) 690 return -ENOMEM; 691 692 xid = get_xid(); 693 694 tlink = cifs_sb_tlink(cifs_sb); 695 if (IS_ERR(tlink)) { 696 rc = PTR_ERR(tlink); 697 goto symlink_exit; 698 } 699 pTcon = tlink_tcon(tlink); 700 701 full_path = build_path_from_dentry(direntry, page); 702 if (IS_ERR(full_path)) { 703 rc = PTR_ERR(full_path); 704 goto symlink_exit; 705 } 706 707 cifs_dbg(FYI, "Full path: %s\n", full_path); 708 cifs_dbg(FYI, "symname is %s\n", symname); 709 710 /* BB what if DFS and this volume is on different share? BB */ 711 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) 712 rc = create_mf_symlink(xid, pTcon, cifs_sb, full_path, symname); 713#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY 714 else if (pTcon->unix_ext) 715 rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname, 716 cifs_sb->local_nls, 717 cifs_remap(cifs_sb)); 718#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ 719 /* else 720 rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName, 721 cifs_sb_target->local_nls); */ 722 723 if (rc == 0) { 724 if (pTcon->posix_extensions) 725 rc = smb311_posix_get_inode_info(&newinode, full_path, inode->i_sb, xid); 726 else if (pTcon->unix_ext) 727 rc = cifs_get_inode_info_unix(&newinode, full_path, 728 inode->i_sb, xid); 729 else 730 rc = cifs_get_inode_info(&newinode, full_path, NULL, 731 inode->i_sb, xid, NULL); 732 733 if (rc != 0) { 734 cifs_dbg(FYI, "Create symlink ok, getinodeinfo fail rc = %d\n", 735 rc); 736 } else { 737 d_instantiate(direntry, newinode); 738 } 739 } 740symlink_exit: 741 free_dentry_path(page); 742 cifs_put_tlink(tlink); 743 free_xid(xid); 744 return rc; 745}