1 /* 2 * symlink.c - operations for sysfs symlinks. 3 */ 4 5 #include <linux/fs.h> 6 #include <linux/module.h> 7 #include <linux/kobject.h> 8 #include <linux/namei.h> 9 10 #include "sysfs.h" 11 12 static int object_depth(struct kobject * kobj) 13 { 14 struct kobject * p = kobj; 15 int depth = 0; 16 do { depth++; } while ((p = p->parent)); 17 return depth; 18 } 19 20 static int object_path_length(struct kobject * kobj) 21 { 22 struct kobject * p = kobj; 23 int length = 1; 24 do { 25 length += strlen(kobject_name(p)) + 1; 26 p = p->parent; 27 } while (p); 28 return length; 29 } 30 31 static void fill_object_path(struct kobject * kobj, char * buffer, int length) 32 { 33 struct kobject * p; 34 35 --length; 36 for (p = kobj; p; p = p->parent) { 37 int cur = strlen(kobject_name(p)); 38 39 /* back up enough to print this bus id with '/' */ 40 length -= cur; 41 strncpy(buffer + length,kobject_name(p),cur); 42 *(buffer + --length) = '/'; 43 } 44 } 45 46 static int sysfs_add_link(struct dentry * parent, const char * name, struct kobject * target) 47 { 48 struct sysfs_dirent * parent_sd = parent->d_fsdata; 49 struct sysfs_symlink * sl; 50 int error = 0; 51 52 error = -ENOMEM; 53 sl = kmalloc(sizeof(*sl), GFP_KERNEL); 54 if (!sl) 55 goto exit1; 56 57 sl->link_name = kmalloc(strlen(name) + 1, GFP_KERNEL); 58 if (!sl->link_name) 59 goto exit2; 60 61 strcpy(sl->link_name, name); 62 sl->target_kobj = kobject_get(target); 63 64 error = sysfs_make_dirent(parent_sd, NULL, sl, S_IFLNK|S_IRWXUGO, 65 SYSFS_KOBJ_LINK); 66 if (!error) 67 return 0; 68 69 kobject_put(target); 70 kfree(sl->link_name); 71 exit2: 72 kfree(sl); 73 exit1: 74 return error; 75 } 76 77 /** 78 * sysfs_create_link - create symlink between two objects. 79 * @kobj: object whose directory we're creating the link in. 80 * @target: object we're pointing to. 81 * @name: name of the symlink. 82 */ 83 int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name) 84 { 85 struct dentry * dentry = kobj->dentry; 86 int error = -EEXIST; 87 88 BUG_ON(!kobj || !kobj->dentry || !name); 89 90 mutex_lock(&dentry->d_inode->i_mutex); 91 if (!sysfs_dirent_exist(dentry->d_fsdata, name)) 92 error = sysfs_add_link(dentry, name, target); 93 mutex_unlock(&dentry->d_inode->i_mutex); 94 return error; 95 } 96 97 98 /** 99 * sysfs_remove_link - remove symlink in object's directory. 100 * @kobj: object we're acting for. 101 * @name: name of the symlink to remove. 102 */ 103 104 void sysfs_remove_link(struct kobject * kobj, const char * name) 105 { 106 sysfs_hash_and_remove(kobj->dentry,name); 107 } 108 109 static int sysfs_get_target_path(struct kobject * kobj, struct kobject * target, 110 char *path) 111 { 112 char * s; 113 int depth, size; 114 115 depth = object_depth(kobj); 116 size = object_path_length(target) + depth * 3 - 1; 117 if (size > PATH_MAX) 118 return -ENAMETOOLONG; 119 120 pr_debug("%s: depth = %d, size = %d\n", __FUNCTION__, depth, size); 121 122 for (s = path; depth--; s += 3) 123 strcpy(s,"../"); 124 125 fill_object_path(target, path, size); 126 pr_debug("%s: path = '%s'\n", __FUNCTION__, path); 127 128 return 0; 129 } 130 131 static int sysfs_getlink(struct dentry *dentry, char * path) 132 { 133 struct kobject *kobj, *target_kobj; 134 int error = 0; 135 136 kobj = sysfs_get_kobject(dentry->d_parent); 137 if (!kobj) 138 return -EINVAL; 139 140 target_kobj = sysfs_get_kobject(dentry); 141 if (!target_kobj) { 142 kobject_put(kobj); 143 return -EINVAL; 144 } 145 146 down_read(&sysfs_rename_sem); 147 error = sysfs_get_target_path(kobj, target_kobj, path); 148 up_read(&sysfs_rename_sem); 149 150 kobject_put(kobj); 151 kobject_put(target_kobj); 152 return error; 153 154 } 155 156 static void *sysfs_follow_link(struct dentry *dentry, struct nameidata *nd) 157 { 158 int error = -ENOMEM; 159 unsigned long page = get_zeroed_page(GFP_KERNEL); 160 if (page) 161 error = sysfs_getlink(dentry, (char *) page); 162 nd_set_link(nd, error ? ERR_PTR(error) : (char *)page); 163 return NULL; 164 } 165 166 static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) 167 { 168 char *page = nd_get_link(nd); 169 if (!IS_ERR(page)) 170 free_page((unsigned long)page); 171 } 172 173 struct inode_operations sysfs_symlink_inode_operations = { 174 .readlink = generic_readlink, 175 .follow_link = sysfs_follow_link, 176 .put_link = sysfs_put_link, 177 }; 178 179 180 EXPORT_SYMBOL_GPL(sysfs_create_link); 181 EXPORT_SYMBOL_GPL(sysfs_remove_link); 182