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