[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