Blame SOURCES/sysfsutils-2.1.0-get_link.patch

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