[LEDE-DEV] [PATCH] pkg_alternatives: pass if the desired symlink already exists

Yousong Zhou yszhou4tech at gmail.com
Tue Jul 11 06:47:04 PDT 2017


This can happen when opkg installs, then configures multiple
alternatives in a batch.  Symlink to the highest prio alternative will
be created in the initial configuring stage causing later symlink call
fail with EEXIST

    Configuring busybox.
    ...
    symlink("/sbin/ip-full", "/home/yousong/j/t/lede-imagebuilder-mvebu.Linux-x86_64/build_dir/target-arm_cortex-a9+vfpv3_musl_eabi/root-mvebu/sbin/ip") = 0
    ...
    Configuring ip-full.
    ...
    symlink("/sbin/ip-full", "/home/yousong/j/t/lede-imagebuilder-mvebu.Linux-x86_64/build_dir/target-arm_cortex-a9+vfpv3_musl_eabi/root-mvebu/sbin/ip") = -1 EEXIST (File exists)
    ...

While at it, "mkdir -p" dirname(path_in_dest) before symlink in case the
following symlink call may fail with ENOENT

Ref: https://github.com/openwrt/packages/issues/4567
Reported-by: Aner Andros <aa at anerandros.info>
Signed-off-by: Yousong Zhou <yszhou4tech at gmail.com>
---
 libopkg/pkg_alternatives.c | 26 +++++++++++++++++++++++---
 1 file changed, 23 insertions(+), 3 deletions(-)

diff --git a/libopkg/pkg_alternatives.c b/libopkg/pkg_alternatives.c
index 890b510..50e9d12 100644
--- a/libopkg/pkg_alternatives.c
+++ b/libopkg/pkg_alternatives.c
@@ -16,8 +16,10 @@
 #include <stdio.h>
 #include <sys/types.h>		/* stat */
 #include <sys/stat.h>
+#include <libgen.h>			/* dirname */
 #include <unistd.h>
 
+#include "file_util.h"
 #include "libbb/libbb.h"
 #include "opkg_message.h"
 #include "pkg.h"
@@ -76,9 +78,27 @@ static int pkg_alternatives_update_path(pkg_t *pkg, const pkg_vec_t *installed,
 		} else if (errno != ENOENT) {
 			goto out;
 		}
-		r = symlink(the_alt->altpath, path_in_dest);
-		if (r)
-			opkg_msg(ERROR, "failed symlinking %s -> %s\n", path_in_dest, the_alt->altpath);
+		{
+			char *path_copy = xstrdup(path_in_dest);
+			char *path_parent = dirname(path_copy);
+
+			r = file_mkdir_hier(path_parent, 0755);
+			free(path_copy);
+			if (r) {
+				goto out;
+			}
+			r = symlink(the_alt->altpath, path_in_dest);
+			if (r && errno == EEXIST) {
+				/*
+				 * the strcmp & unlink check above will make sure that if EEXIST
+				 * happens, the symlink target also matches
+				 */
+				r = 0;
+			}
+			if (r) {
+				opkg_perror(ERROR, "failed symlinking %s -> %s", path_in_dest, the_alt->altpath);
+			}
+		}
 	} else {
 		unlink(path_in_dest);
 		r = 0;
-- 
2.12.2




More information about the Lede-dev mailing list