1
2
3
4
5
6
7
8
9#include <linux/sched.h>
10#include <linux/kernel.h>
11#include <linux/errno.h>
12#include <linux/fcntl.h>
13#include <linux/stat.h>
14#include <linux/mm.h>
15#include <linux/slab.h>
16#include <linux/pagemap.h>
17#include <linux/smp_lock.h>
18#include <linux/net.h>
19
20#include <asm/uaccess.h>
21#include <asm/system.h>
22
23#include <linux/smbno.h>
24#include <linux/smb_fs.h>
25
26#include "smb_debug.h"
27#include "proto.h"
28
29int smb_read_link(struct dentry *dentry, char *buffer, int len)
30{
31 char *link;
32 int result;
33 DEBUG1("read link buffer len = %d\n", len);
34
35 result = -ENOMEM;
36 link = kmalloc(SMB_MAXNAMELEN + 1, GFP_KERNEL);
37 if (!link)
38 goto out;
39
40 result = smb_proc_read_link(server_from_dentry(dentry), dentry, link,
41 SMB_MAXNAMELEN);
42 if (result < 0)
43 goto out_free;
44 result = vfs_readlink(dentry, buffer, len, link);
45
46out_free:
47 kfree(link);
48out:
49 return result;
50}
51
52int smb_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
53{
54 DEBUG1("create symlink %s -> %s/%s\n", oldname, DENTRY_PATH(dentry));
55
56 smb_invalid_dir_cache(dir);
57 return smb_proc_symlink(server_from_dentry(dentry), dentry, oldname);
58}
59
60int smb_follow_link(struct dentry *dentry, struct nameidata *nd)
61{
62 char *link;
63 int result;
64
65 DEBUG1("followlink of %s/%s\n", DENTRY_PATH(dentry));
66
67 result = -ENOMEM;
68 link = kmalloc(SMB_MAXNAMELEN + 1, GFP_KERNEL);
69 if (!link)
70 goto out;
71
72 result = smb_proc_read_link(server_from_dentry(dentry), dentry, link,
73 SMB_MAXNAMELEN);
74 if (result < 0 || result >= SMB_MAXNAMELEN)
75 goto out_free;
76 link[result] = 0;
77
78 result = vfs_follow_link(nd, link);
79
80out_free:
81 kfree(link);
82out:
83 return result;
84}
85
86struct inode_operations smb_link_inode_operations =
87{
88 .readlink = smb_read_link,
89 .follow_link = smb_follow_link,
90};
91