|
|
5dca56 |
diff -upr sysfsutils-2.1.0-old/lib/sysfs_utils.c sysfsutils-2.1.0/lib/sysfs_utils.c
|
|
|
5dca56 |
--- sysfsutils-2.1.0-old/lib/sysfs_utils.c 2006-08-07 07:08:01.000000000 +0200
|
|
|
5dca56 |
+++ sysfsutils-2.1.0/lib/sysfs_utils.c 2008-05-13 07:42:50.000000000 +0200
|
|
|
5dca56 |
@@ -117,84 +117,104 @@ int sysfs_get_link(const char *path, cha
|
|
|
5dca56 |
{
|
|
|
5dca56 |
char devdir[SYSFS_PATH_MAX];
|
|
|
5dca56 |
char linkpath[SYSFS_PATH_MAX];
|
|
|
5dca56 |
- char temp_path[SYSFS_PATH_MAX];
|
|
|
5dca56 |
- char *d = NULL, *s = NULL;
|
|
|
5dca56 |
- int slashes = 0, count = 0;
|
|
|
5dca56 |
+ char *d, *s;
|
|
|
5dca56 |
+ int count;
|
|
|
5dca56 |
|
|
|
5dca56 |
if (!path || !target || len == 0) {
|
|
|
5dca56 |
errno = EINVAL;
|
|
|
5dca56 |
return -1;
|
|
|
5dca56 |
}
|
|
|
5dca56 |
|
|
|
5dca56 |
- memset(devdir, 0, SYSFS_PATH_MAX);
|
|
|
5dca56 |
- memset(linkpath, 0, SYSFS_PATH_MAX);
|
|
|
5dca56 |
- memset(temp_path, 0, SYSFS_PATH_MAX);
|
|
|
5dca56 |
- safestrcpy(devdir, path);
|
|
|
5dca56 |
-
|
|
|
5dca56 |
- if ((readlink(path, linkpath, SYSFS_PATH_MAX)) < 0) {
|
|
|
5dca56 |
+ count = readlink(path, linkpath, SYSFS_PATH_MAX);
|
|
|
5dca56 |
+ if (count < 0)
|
|
|
5dca56 |
return -1;
|
|
|
5dca56 |
- }
|
|
|
5dca56 |
- d = linkpath;
|
|
|
5dca56 |
+ else
|
|
|
5dca56 |
+ linkpath[count] = '\0';
|
|
|
5dca56 |
/*
|
|
|
5dca56 |
* Three cases here:
|
|
|
5dca56 |
* 1. relative path => format ../..
|
|
|
5dca56 |
* 2. absolute path => format /abcd/efgh
|
|
|
5dca56 |
* 3. relative path _from_ this dir => format abcd/efgh
|
|
|
5dca56 |
*/
|
|
|
5dca56 |
- switch (*d) {
|
|
|
5dca56 |
- case '.':
|
|
|
5dca56 |
+ if (*linkpath == '/') {
|
|
|
5dca56 |
+ /* absolute path - copy as is */
|
|
|
5dca56 |
+ safestrcpymax(target, linkpath, len);
|
|
|
5dca56 |
+ return 0;
|
|
|
5dca56 |
+ }
|
|
|
5dca56 |
+
|
|
|
5dca56 |
+ safestrcpy(devdir, path);
|
|
|
5dca56 |
+ s = strrchr(devdir, '/');
|
|
|
5dca56 |
+ if (s == NULL)
|
|
|
5dca56 |
+ s = devdir - 1;
|
|
|
5dca56 |
+ d = linkpath;
|
|
|
5dca56 |
+ while (*d == '.') {
|
|
|
5dca56 |
+ if (*(d+1) == '/') {
|
|
|
5dca56 |
/*
|
|
|
5dca56 |
* handle the case where link is of type ./abcd/xxx
|
|
|
5dca56 |
*/
|
|
|
5dca56 |
- safestrcpy(temp_path, devdir);
|
|
|
5dca56 |
- if (*(d+1) == '/')
|
|
|
5dca56 |
- d += 2;
|
|
|
5dca56 |
- else if (*(d+1) == '.')
|
|
|
5dca56 |
- goto parse_path;
|
|
|
5dca56 |
- s = strrchr(temp_path, '/');
|
|
|
5dca56 |
- if (s != NULL) {
|
|
|
5dca56 |
- *(s+1) = '\0';
|
|
|
5dca56 |
- safestrcat(temp_path, d);
|
|
|
5dca56 |
- } else {
|
|
|
5dca56 |
- safestrcpy(temp_path, d);
|
|
|
5dca56 |
- }
|
|
|
5dca56 |
- safestrcpymax(target, temp_path, len);
|
|
|
5dca56 |
- break;
|
|
|
5dca56 |
+ d += 2;
|
|
|
5dca56 |
+ while (*d == '/')
|
|
|
5dca56 |
+ d++;
|
|
|
5dca56 |
+ continue;
|
|
|
5dca56 |
+ } else if (*(d+1) != '.' || *(d+2) != '/')
|
|
|
5dca56 |
/*
|
|
|
5dca56 |
- * relative path, getting rid of leading "../.."
|
|
|
5dca56 |
+ * relative path from this directory, starting
|
|
|
5dca56 |
+ * with a hidden directory
|
|
|
5dca56 |
*/
|
|
|
5dca56 |
-parse_path:
|
|
|
5dca56 |
- while (*d == '/' || *d == '.') {
|
|
|
5dca56 |
- if (*d == '/')
|
|
|
5dca56 |
- slashes++;
|
|
|
5dca56 |
- d++;
|
|
|
5dca56 |
- }
|
|
|
5dca56 |
- d--;
|
|
|
5dca56 |
- s = &devdir[strlen(devdir)-1];
|
|
|
5dca56 |
- while (s != NULL && count != (slashes+1)) {
|
|
|
5dca56 |
+ break;
|
|
|
5dca56 |
+
|
|
|
5dca56 |
+ /*
|
|
|
5dca56 |
+ * relative path, getting rid of leading "../.."; must
|
|
|
5dca56 |
+ * be careful here since any path component of devdir
|
|
|
5dca56 |
+ * could be a symlink again
|
|
|
5dca56 |
+ */
|
|
|
5dca56 |
+ for (;;) {
|
|
|
5dca56 |
+ while (s > devdir && *s == '/') {
|
|
|
5dca56 |
s--;
|
|
|
5dca56 |
- if (*s == '/')
|
|
|
5dca56 |
- count++;
|
|
|
5dca56 |
+ if (*s == '.'
|
|
|
5dca56 |
+ && (s == devdir || *(s-1) == '/'))
|
|
|
5dca56 |
+ s--;
|
|
|
5dca56 |
}
|
|
|
5dca56 |
- safestrcpymax(s, d, (SYSFS_PATH_MAX-strlen(devdir)));
|
|
|
5dca56 |
- safestrcpymax(target, devdir, len);
|
|
|
5dca56 |
- break;
|
|
|
5dca56 |
- case '/':
|
|
|
5dca56 |
- /* absolute path - copy as is */
|
|
|
5dca56 |
- safestrcpymax(target, linkpath, len);
|
|
|
5dca56 |
- break;
|
|
|
5dca56 |
- default:
|
|
|
5dca56 |
- /* relative path from this directory */
|
|
|
5dca56 |
- safestrcpy(temp_path, devdir);
|
|
|
5dca56 |
- s = strrchr(temp_path, '/');
|
|
|
5dca56 |
- if (s != NULL) {
|
|
|
5dca56 |
- *(s+1) = '\0';
|
|
|
5dca56 |
- safestrcat(temp_path, linkpath);
|
|
|
5dca56 |
- } else {
|
|
|
5dca56 |
- safestrcpy(temp_path, linkpath);
|
|
|
5dca56 |
+ *(s+1) = '\0';
|
|
|
5dca56 |
+ if (*devdir == '\0' || sysfs_path_is_link(devdir))
|
|
|
5dca56 |
+ /*
|
|
|
5dca56 |
+ * condition will be true eventually
|
|
|
5dca56 |
+ * because we already know that all
|
|
|
5dca56 |
+ * but the last component of path
|
|
|
5dca56 |
+ * resolve to a directory
|
|
|
5dca56 |
+ */
|
|
|
5dca56 |
+ break;
|
|
|
5dca56 |
+ if (sysfs_get_link(devdir, devdir, SYSFS_PATH_MAX))
|
|
|
5dca56 |
+ return -1;
|
|
|
5dca56 |
+ s = devdir + strlen(devdir) - 1;
|
|
|
5dca56 |
+ }
|
|
|
5dca56 |
+ while (s >= devdir) {
|
|
|
5dca56 |
+ if (*s == '/') {
|
|
|
5dca56 |
+ if (*(s+1) != '.' || *(s+2) != '.'
|
|
|
5dca56 |
+ || *(s+3) != '\0') {
|
|
|
5dca56 |
+ d += 3;
|
|
|
5dca56 |
+ while (*d == '/')
|
|
|
5dca56 |
+ d++;
|
|
|
5dca56 |
+ } else
|
|
|
5dca56 |
+ s += 2;
|
|
|
5dca56 |
+ break;
|
|
|
5dca56 |
}
|
|
|
5dca56 |
- safestrcpymax(target, temp_path, len);
|
|
|
5dca56 |
+ s--;
|
|
|
5dca56 |
+ }
|
|
|
5dca56 |
+ if (s < devdir || *(s+1) == '\0')
|
|
|
5dca56 |
+ break;
|
|
|
5dca56 |
}
|
|
|
5dca56 |
+
|
|
|
5dca56 |
+ /*
|
|
|
5dca56 |
+ * appending to devdir a slash and the (possibly shortened)
|
|
|
5dca56 |
+ * relative path to the link source
|
|
|
5dca56 |
+ */
|
|
|
5dca56 |
+ s++;
|
|
|
5dca56 |
+ if (s > devdir && *s == '\0')
|
|
|
5dca56 |
+ *s++ = '/';
|
|
|
5dca56 |
+ *s = '\0';
|
|
|
5dca56 |
+ safestrcpymax(s, d, SYSFS_PATH_MAX-(s-devdir));
|
|
|
5dca56 |
+ safestrcpymax(target, devdir, len);
|
|
|
5dca56 |
return 0;
|
|
|
5dca56 |
}
|
|
|
5dca56 |
|