0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/fs.h>
0011 #include <linux/gfp.h>
0012 #include <linux/namei.h>
0013
0014 #include "kernfs-internal.h"
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025 struct kernfs_node *kernfs_create_link(struct kernfs_node *parent,
0026 const char *name,
0027 struct kernfs_node *target)
0028 {
0029 struct kernfs_node *kn;
0030 int error;
0031 kuid_t uid = GLOBAL_ROOT_UID;
0032 kgid_t gid = GLOBAL_ROOT_GID;
0033
0034 if (target->iattr) {
0035 uid = target->iattr->ia_uid;
0036 gid = target->iattr->ia_gid;
0037 }
0038
0039 kn = kernfs_new_node(parent, name, S_IFLNK|0777, uid, gid, KERNFS_LINK);
0040 if (!kn)
0041 return ERR_PTR(-ENOMEM);
0042
0043 if (kernfs_ns_enabled(parent))
0044 kn->ns = target->ns;
0045 kn->symlink.target_kn = target;
0046 kernfs_get(target);
0047
0048 error = kernfs_add_one(kn);
0049 if (!error)
0050 return kn;
0051
0052 kernfs_put(kn);
0053 return ERR_PTR(error);
0054 }
0055
0056 static int kernfs_get_target_path(struct kernfs_node *parent,
0057 struct kernfs_node *target, char *path)
0058 {
0059 struct kernfs_node *base, *kn;
0060 char *s = path;
0061 int len = 0;
0062
0063
0064 base = parent;
0065 while (base->parent) {
0066 kn = target->parent;
0067 while (kn->parent && base != kn)
0068 kn = kn->parent;
0069
0070 if (base == kn)
0071 break;
0072
0073 if ((s - path) + 3 >= PATH_MAX)
0074 return -ENAMETOOLONG;
0075
0076 strcpy(s, "../");
0077 s += 3;
0078 base = base->parent;
0079 }
0080
0081
0082 kn = target;
0083 while (kn->parent && kn != base) {
0084 len += strlen(kn->name) + 1;
0085 kn = kn->parent;
0086 }
0087
0088
0089 if (len < 2)
0090 return -EINVAL;
0091 len--;
0092 if ((s - path) + len >= PATH_MAX)
0093 return -ENAMETOOLONG;
0094
0095
0096 kn = target;
0097 while (kn->parent && kn != base) {
0098 int slen = strlen(kn->name);
0099
0100 len -= slen;
0101 memcpy(s + len, kn->name, slen);
0102 if (len)
0103 s[--len] = '/';
0104
0105 kn = kn->parent;
0106 }
0107
0108 return 0;
0109 }
0110
0111 static int kernfs_getlink(struct inode *inode, char *path)
0112 {
0113 struct kernfs_node *kn = inode->i_private;
0114 struct kernfs_node *parent = kn->parent;
0115 struct kernfs_node *target = kn->symlink.target_kn;
0116 struct kernfs_root *root = kernfs_root(parent);
0117 int error;
0118
0119 down_read(&root->kernfs_rwsem);
0120 error = kernfs_get_target_path(parent, target, path);
0121 up_read(&root->kernfs_rwsem);
0122
0123 return error;
0124 }
0125
0126 static const char *kernfs_iop_get_link(struct dentry *dentry,
0127 struct inode *inode,
0128 struct delayed_call *done)
0129 {
0130 char *body;
0131 int error;
0132
0133 if (!dentry)
0134 return ERR_PTR(-ECHILD);
0135 body = kzalloc(PAGE_SIZE, GFP_KERNEL);
0136 if (!body)
0137 return ERR_PTR(-ENOMEM);
0138 error = kernfs_getlink(inode, body);
0139 if (unlikely(error < 0)) {
0140 kfree(body);
0141 return ERR_PTR(error);
0142 }
0143 set_delayed_call(done, kfree_link, body);
0144 return body;
0145 }
0146
0147 const struct inode_operations kernfs_symlink_iops = {
0148 .listxattr = kernfs_iop_listxattr,
0149 .get_link = kernfs_iop_get_link,
0150 .setattr = kernfs_iop_setattr,
0151 .getattr = kernfs_iop_getattr,
0152 .permission = kernfs_iop_permission,
0153 };