lib/package_alternatives.c: always use relative symlinks in alternatives
This commit adds relative link support to lib/package_alternatives.c. Instead of creating absolute links, xbps will create relative links to the target. This allows to follow links on systems even if the aren't mounted on /.
This commit is contained in:
		| @@ -59,6 +59,50 @@ right(const char *str) | ||||
| 	return strchr(str, ':') + 1; | ||||
| } | ||||
|  | ||||
| static const char * | ||||
| normpath(char *path) { | ||||
| 	char *seg, *p; | ||||
| reinit: | ||||
| 	for (p = path, seg = NULL; *p; p++) { | ||||
| 		if (strncmp(p, "/../", 4) == 0 || strncmp(p, "/..", 4) == 0) { | ||||
| 			memmove(seg ? seg : p, p+3, strlen(p+3) + 1); | ||||
| 			goto reinit; | ||||
| 		} | ||||
| 		else if (strncmp(p, "/./", 3) == 0 || strncmp(p, "/.", 3) == 0) { | ||||
| 			memmove(p, p+2, strlen(p+2) + 1); | ||||
| 		} | ||||
| 		else if (*p == '/') | ||||
| 			seg = p; | ||||
| 	} | ||||
| 	return path; | ||||
| } | ||||
|  | ||||
|  | ||||
| static char * | ||||
| relpath(char *from, char *to) { | ||||
| 	int up; | ||||
| 	char *p = to, *rel; | ||||
| 	assert(from[0] == '/'); | ||||
| 	assert(to[0] == '/'); | ||||
| 	normpath(from); | ||||
| 	normpath(to); | ||||
|  | ||||
| 	for (; *from == *to && *to; from++, to++) { | ||||
| 		if (*to == '/') | ||||
| 			p = to; | ||||
| 	} | ||||
|  | ||||
| 	for (up = -1, from--; from && *from; from = strchr(from + 1, '/'), up++); | ||||
|  | ||||
| 	rel = calloc(3 * up + strlen(p), sizeof(char)); | ||||
|  | ||||
| 	while (up--) | ||||
| 		strcat(rel, "../"); | ||||
| 	if (*p) | ||||
| 		strcat(rel, p+1); | ||||
| 	return rel; | ||||
| } | ||||
|  | ||||
| static int | ||||
| remove_symlinks(struct xbps_handle *xhp, xbps_array_t a, const char *grname) | ||||
| { | ||||
| @@ -135,6 +179,8 @@ create_symlinks(struct xbps_handle *xhp, xbps_array_t a, const char *grname) | ||||
| 		xbps_set_cb_state(xhp, XBPS_STATE_ALTGROUP_LINK_ADDED, 0, NULL, | ||||
| 		    "Creating '%s' alternatives group symlink: %s -> %s", grname, l, tgt); | ||||
| 		unlink(lnk); | ||||
| 		if (tgt[0] == '/') | ||||
| 			tgt = relpath(lnk + strlen(xhp->rootdir), tgt); | ||||
| 		if ((rv = symlink(tgt, lnk)) != 0) { | ||||
| 			xbps_dbg_printf(xhp, "failed to create alt symlink '%s'" | ||||
| 			    "for group '%s': %s\n", lnk, grname, | ||||
|   | ||||
| @@ -19,8 +19,8 @@ register_one_body() { | ||||
| 	atf_check_equal $? 0 | ||||
| 	rv=1 | ||||
| 	if [ -e root/usr/bin/fileA ]; then | ||||
| 		lnk=$(readlink root/usr/bin/file) | ||||
| 		if [ "$lnk" = "/usr/bin/fileA" ]; then | ||||
| 		lnk=$(readlink -f root/usr/bin/file) | ||||
| 		if [ "$lnk" = "$PWD/root/usr/bin/fileA" ]; then | ||||
| 			rv=0 | ||||
| 		fi | ||||
| 		echo "A lnk: $lnk" | ||||
| @@ -46,8 +46,8 @@ register_one_dangling_body() { | ||||
| 	atf_check_equal $? 0 | ||||
| 	rv=1 | ||||
| 	if [ -h root/usr/bin/file ]; then | ||||
| 		lnk=$(readlink root/usr/bin/file) | ||||
| 		if [ "$lnk" = "/usr/bin/fileA" ]; then | ||||
| 		lnk=$(readlink -f root/usr/bin/file) | ||||
| 		if [ "$lnk" = "$PWD/root/usr/bin/fileA" ]; then | ||||
| 			rv=0 | ||||
| 		fi | ||||
| 		echo "A lnk: $lnk" | ||||
| @@ -137,8 +137,8 @@ register_multi_body() { | ||||
| 	atf_check_equal $? 0 | ||||
| 	rv=1 | ||||
| 	if [ -e root/usr/bin/fileA ]; then | ||||
| 		lnk=$(readlink root/usr/bin/file) | ||||
| 		if [ "$lnk" = "/usr/bin/fileA" ]; then | ||||
| 		lnk=$(readlink -f root/usr/bin/file) | ||||
| 		if [ "$lnk" = "$PWD/root/usr/bin/fileA" ]; then | ||||
| 			rv=0 | ||||
| 		fi | ||||
| 		echo "A lnk: $lnk" | ||||
| @@ -149,8 +149,8 @@ register_multi_body() { | ||||
| 	atf_check_equal $? 0 | ||||
| 	rv=1 | ||||
| 	if [ -e root/usr/bin/fileA -a -e root/usr/bin/fileB ]; then | ||||
| 		lnk=$(readlink root/usr/bin/file) | ||||
| 		if [ "$lnk" = "/usr/bin/fileA" ]; then | ||||
| 		lnk=$(readlink -f root/usr/bin/file) | ||||
| 		if [ "$lnk" = "$PWD/root/usr/bin/fileA" ]; then | ||||
| 			rv=0 | ||||
| 		fi | ||||
| 		echo "B lnk: $lnk" | ||||
| @@ -229,8 +229,8 @@ unregister_multi_body() { | ||||
| 	atf_check_equal $? 0 | ||||
|  | ||||
| 	if [ -e root/usr/bin/fileA ]; then | ||||
| 		lnk=$(readlink root/usr/bin/file) | ||||
| 		if [ "$lnk" = "/usr/bin/fileA" ]; then | ||||
| 		lnk=$(readlink -f root/usr/bin/file) | ||||
| 		if [ "$lnk" = "$PWD/root/usr/bin/fileA" ]; then | ||||
| 			rv=0 | ||||
| 		fi | ||||
| 		echo "A lnk: $lnk" | ||||
| @@ -247,8 +247,8 @@ unregister_multi_body() { | ||||
| 	atf_check_equal $? 0 | ||||
|  | ||||
| 	if [ -e root/usr/bin/fileB ]; then | ||||
| 		lnk=$(readlink root/usr/bin/file) | ||||
| 		if [ "$lnk" = "/usr/bin/fileB" ]; then | ||||
| 		lnk=$(readlink -f root/usr/bin/file) | ||||
| 		if [ "$lnk" = "$PWD/root/usr/bin/fileB" ]; then | ||||
| 			rv=0 | ||||
| 		fi | ||||
| 		echo "A lnk: $lnk" | ||||
| @@ -287,8 +287,8 @@ set_pkg_body() { | ||||
|  | ||||
| 	rv=1 | ||||
| 	if [ -e root/usr/bin/B1 ]; then | ||||
| 		lnk=$(readlink root/usr/bin/1) | ||||
| 		if [ "$lnk" = "/usr/bin/B1" ]; then | ||||
| 		lnk=$(readlink -f root/usr/bin/1) | ||||
| 		if [ "$lnk" = "$PWD/root/usr/bin/B1" ]; then | ||||
| 			rv=0 | ||||
| 		fi | ||||
| 		echo "A lnk: $lnk" | ||||
| @@ -297,8 +297,8 @@ set_pkg_body() { | ||||
|  | ||||
| 	rv=1 | ||||
| 	if [ -e root/usr/bin/B2 ]; then | ||||
| 		lnk=$(readlink root/usr/bin/2) | ||||
| 		if [ "$lnk" = "/usr/bin/B2" ]; then | ||||
| 		lnk=$(readlink -f root/usr/bin/2) | ||||
| 		if [ "$lnk" = "$PWD/root/usr/bin/B2" ]; then | ||||
| 			rv=0 | ||||
| 		fi | ||||
| 		echo "A lnk: $lnk" | ||||
| @@ -310,8 +310,8 @@ set_pkg_body() { | ||||
|  | ||||
| 	rv=1 | ||||
| 	if [ -e root/usr/bin/A1 ]; then | ||||
| 		lnk=$(readlink root/usr/bin/1) | ||||
| 		if [ "$lnk" = "/usr/bin/A1" ]; then | ||||
| 		lnk=$(readlink -f root/usr/bin/1) | ||||
| 		if [ "$lnk" = "$PWD/root/usr/bin/A1" ]; then | ||||
| 			rv=0 | ||||
| 		fi | ||||
| 		echo "A lnk: $lnk" | ||||
| @@ -320,8 +320,8 @@ set_pkg_body() { | ||||
|  | ||||
| 	rv=1 | ||||
| 	if [ -e root/usr/bin/A2 ]; then | ||||
| 		lnk=$(readlink root/usr/bin/2) | ||||
| 		if [ "$lnk" = "/usr/bin/A2" ]; then | ||||
| 		lnk=$(readlink -f root/usr/bin/2) | ||||
| 		if [ "$lnk" = "$PWD/root/usr/bin/A2" ]; then | ||||
| 			rv=0 | ||||
| 		fi | ||||
| 		echo "A lnk: $lnk" | ||||
| @@ -353,8 +353,8 @@ set_pkg_group_body() { | ||||
|  | ||||
| 	rv=1 | ||||
| 	if [ -e root/usr/bin/B1 ]; then | ||||
| 		lnk=$(readlink root/usr/bin/1) | ||||
| 		if [ "$lnk" = "/usr/bin/A1" ]; then | ||||
| 		lnk=$(readlink -f root/usr/bin/1) | ||||
| 		if [ "$lnk" = "$PWD/root/usr/bin/A1" ]; then | ||||
| 			rv=0 | ||||
| 		fi | ||||
| 		echo "A lnk: $lnk" | ||||
| @@ -363,8 +363,8 @@ set_pkg_group_body() { | ||||
|  | ||||
| 	rv=1 | ||||
| 	if [ -e root/usr/bin/B2 ]; then | ||||
| 		lnk=$(readlink root/usr/bin/2) | ||||
| 		if [ "$lnk" = "/usr/bin/B2" ]; then | ||||
| 		lnk=$(readlink -f root/usr/bin/2) | ||||
| 		if [ "$lnk" = "$PWD/root/usr/bin/B2" ]; then | ||||
| 			rv=0 | ||||
| 		fi | ||||
| 		echo "A lnk: $lnk" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user