|
@@ -19,39 +19,6 @@
|
|
|
|
|
|
#include "sysfs.h"
|
|
#include "sysfs.h"
|
|
|
|
|
|
-static int object_depth(struct sysfs_dirent *sd)
|
|
|
|
-{
|
|
|
|
- int depth = 0;
|
|
|
|
-
|
|
|
|
- for (; sd->s_parent; sd = sd->s_parent)
|
|
|
|
- depth++;
|
|
|
|
-
|
|
|
|
- return depth;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static int object_path_length(struct sysfs_dirent * sd)
|
|
|
|
-{
|
|
|
|
- int length = 1;
|
|
|
|
-
|
|
|
|
- for (; sd->s_parent; sd = sd->s_parent)
|
|
|
|
- length += strlen(sd->s_name) + 1;
|
|
|
|
-
|
|
|
|
- return length;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void fill_object_path(struct sysfs_dirent *sd, char *buffer, int length)
|
|
|
|
-{
|
|
|
|
- --length;
|
|
|
|
- for (; sd->s_parent; sd = sd->s_parent) {
|
|
|
|
- int cur = strlen(sd->s_name);
|
|
|
|
-
|
|
|
|
- /* back up enough to print this bus id with '/' */
|
|
|
|
- length -= cur;
|
|
|
|
- strncpy(buffer + length, sd->s_name, cur);
|
|
|
|
- *(buffer + --length) = '/';
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
/**
|
|
/**
|
|
* sysfs_create_link - create symlink between two objects.
|
|
* sysfs_create_link - create symlink between two objects.
|
|
* @kobj: object whose directory we're creating the link in.
|
|
* @kobj: object whose directory we're creating the link in.
|
|
@@ -112,7 +79,6 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char
|
|
return error;
|
|
return error;
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
/**
|
|
/**
|
|
* sysfs_remove_link - remove symlink in object's directory.
|
|
* sysfs_remove_link - remove symlink in object's directory.
|
|
* @kobj: object we're acting for.
|
|
* @kobj: object we're acting for.
|
|
@@ -124,24 +90,54 @@ void sysfs_remove_link(struct kobject * kobj, const char * name)
|
|
sysfs_hash_and_remove(kobj->sd, name);
|
|
sysfs_hash_and_remove(kobj->sd, name);
|
|
}
|
|
}
|
|
|
|
|
|
-static int sysfs_get_target_path(struct sysfs_dirent * parent_sd,
|
|
|
|
- struct sysfs_dirent * target_sd, char *path)
|
|
|
|
|
|
+static int sysfs_get_target_path(struct sysfs_dirent *parent_sd,
|
|
|
|
+ struct sysfs_dirent *target_sd, char *path)
|
|
{
|
|
{
|
|
- char * s;
|
|
|
|
- int depth, size;
|
|
|
|
|
|
+ struct sysfs_dirent *base, *sd;
|
|
|
|
+ char *s = path;
|
|
|
|
+ int len = 0;
|
|
|
|
+
|
|
|
|
+ /* go up to the root, stop at the base */
|
|
|
|
+ base = parent_sd;
|
|
|
|
+ while (base->s_parent) {
|
|
|
|
+ sd = target_sd->s_parent;
|
|
|
|
+ while (sd->s_parent && base != sd)
|
|
|
|
+ sd = sd->s_parent;
|
|
|
|
+
|
|
|
|
+ if (base == sd)
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ strcpy(s, "../");
|
|
|
|
+ s += 3;
|
|
|
|
+ base = base->s_parent;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* determine end of target string for reverse fillup */
|
|
|
|
+ sd = target_sd;
|
|
|
|
+ while (sd->s_parent && sd != base) {
|
|
|
|
+ len += strlen(sd->s_name) + 1;
|
|
|
|
+ sd = sd->s_parent;
|
|
|
|
+ }
|
|
|
|
|
|
- depth = object_depth(parent_sd);
|
|
|
|
- size = object_path_length(target_sd) + depth * 3 - 1;
|
|
|
|
- if (size > PATH_MAX)
|
|
|
|
|
|
+ /* check limits */
|
|
|
|
+ if (len < 2)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ len--;
|
|
|
|
+ if ((s - path) + len > PATH_MAX)
|
|
return -ENAMETOOLONG;
|
|
return -ENAMETOOLONG;
|
|
|
|
|
|
- pr_debug("%s: depth = %d, size = %d\n", __FUNCTION__, depth, size);
|
|
|
|
|
|
+ /* reverse fillup of target string from target to base */
|
|
|
|
+ sd = target_sd;
|
|
|
|
+ while (sd->s_parent && sd != base) {
|
|
|
|
+ int slen = strlen(sd->s_name);
|
|
|
|
|
|
- for (s = path; depth--; s += 3)
|
|
|
|
- strcpy(s,"../");
|
|
|
|
|
|
+ len -= slen;
|
|
|
|
+ strncpy(s + len, sd->s_name, slen);
|
|
|
|
+ if (len)
|
|
|
|
+ s[--len] = '/';
|
|
|
|
|
|
- fill_object_path(target_sd, path, size);
|
|
|
|
- pr_debug("%s: path = '%s'\n", __FUNCTION__, path);
|
|
|
|
|
|
+ sd = sd->s_parent;
|
|
|
|
+ }
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|