]> git.neil.brown.name Git - history.git/commitdiff
sysfs: make symlinks easier.
authorPatrick Mochel <mochel@osdl.org>
Tue, 29 Oct 2002 17:26:38 +0000 (09:26 -0800)
committerPatrick Mochel <mochel@osdl.org>
Tue, 29 Oct 2002 17:26:38 +0000 (09:26 -0800)
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.

fs/sysfs/inode.c
include/linux/sysfs.h

index 804f3655dc73f3a621992e37e3f017b913d243a4..a82726460fcaca642e6399e08254ddf04eb167f4 100644 (file)
@@ -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. 
- *     @name:  name of the symlink.
- *     @target:        path we're pointing to.
+ *     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.
  */
-
-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);
-               else
-                       error = PTR_ERR(dentry);
-               up(&parent->d_inode->i_sem);
-       } else
-               error = -EINVAL;
+       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(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;
index fe82dff179ce5a2b05d1b92e8dc8498117a4e0b8..066a9ccc0fb480043aa8c65301b8e3ad42ea86a1 100644 (file)
@@ -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);