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