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