Commit 0862416e authored by Patrick Mochel's avatar Patrick Mochel

sysfs: make symlinks easier.

It's now

int sysfs_create_link(struct kobject * kobj, struct kobject * target, char * name)

So, the caller doesn't have to determine the path of the target nor the depth of
the object we're creating the symlink for; it's all taken care of.
parent d2f8eca7
......@@ -457,34 +457,84 @@ int sysfs_create_file(struct kobject * kobj, struct attribute * attr)
}
static int object_depth(struct kobject * kobj)
{
struct kobject * p = kobj;
int depth = 0;
do { depth++; } while ((p = p->parent));
return depth;
}
static int object_path_length(struct kobject * kobj)
{
struct kobject * p = kobj;
int length = 1;
do {
length += strlen(p->name) + 1;
p = p->parent;
} while (p);
return length;
}
static void fill_object_path(struct kobject * kobj, char * buffer, int length)
{
struct kobject * p;
--length;
for (p = kobj; p; p = p->parent) {
int cur = strlen(p->name);
/* back up enough to print this bus id with '/' */
length -= cur;
strncpy(buffer + length,p->name,cur);
*(buffer + --length) = '/';
}
}
/**
* sysfs_create_symlink - make a symlink
* @kobj: object who's directory we're creating in.
* sysfs_create_link - create symlink between two objects.
* @kobj: object whose directory we're creating the link in.
* @target: object we're pointing to.
* @name: name of the symlink.
* @target: path we're pointing to.
*/
int sysfs_create_link(struct kobject * kobj, char * name, char * target)
int sysfs_create_link(struct kobject * kobj, struct kobject * target, char * name)
{
struct dentry * dentry;
int error;
struct dentry * dentry = kobj->dir.dentry;
struct dentry * d;
int error = 0;
int size;
int depth;
char * path;
char * s;
depth = object_depth(kobj);
size = object_path_length(target) + depth * 3 - 1;
if (size > PATH_MAX)
return -ENAMETOOLONG;
pr_debug("%s: depth = %d, size = %d\n",__FUNCTION__,depth,size);
path = kmalloc(size,GFP_KERNEL);
if (!path)
return -ENOMEM;
memset(path,0,size);
if (kobj) {
struct dentry * parent = kobj->dir.dentry;
for (s = path; depth--; s += 3)
strcpy(s,"../");
down(&parent->d_inode->i_sem);
dentry = get_dentry(parent,name);
if (!IS_ERR(dentry))
error = sysfs_symlink(parent->d_inode,dentry,target);
fill_object_path(target,path,size);
pr_debug("%s: path = '%s'\n",__FUNCTION__,path);
down(&dentry->d_inode->i_sem);
d = get_dentry(dentry,name);
if (!IS_ERR(d))
error = sysfs_symlink(dentry->d_inode,d,path);
else
error = PTR_ERR(dentry);
up(&parent->d_inode->i_sem);
} else
error = -EINVAL;
error = PTR_ERR(d);
up(&dentry->d_inode->i_sem);
kfree(path);
return error;
}
static void hash_and_remove(struct dentry * dir, const char * name)
{
struct dentry * victim;
......
......@@ -41,7 +41,7 @@ extern void
sysfs_remove_file(struct kobject *, struct attribute *);
extern int
sysfs_create_link(struct kobject * kobj, char * name, char * target);
sysfs_create_link(struct kobject * kobj, struct kobject * target, char * name);
extern void
sysfs_remove_link(struct kobject *, char * name);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment