1 /* pkg_alternatives.c - the opkg package management system
3 Copyright (C) 2017 Yousong Zhou
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License as
7 published by the Free Software Foundation; either version 2, or (at
8 your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
17 #include <sys/types.h> /* stat */
19 #include <libgen.h> /* dirname */
22 #include "file_util.h"
23 #include "libbb/libbb.h"
24 #include "opkg_message.h"
27 #include "pkg_alternatives.h"
28 #include "sprintf_alloc.h"
30 static int pkg_alternatives_update_path(pkg_t *pkg, const pkg_vec_t *installed, const char *path)
32 struct pkg_alternatives *pkg_alts;
33 struct pkg_alternative *the_alt = NULL;
39 for (i = 0; i < installed->len; i++) {
40 pkg_t *pkg = installed->pkgs[i];
41 pkg_alts = pkg_get_ptr(pkg, PKG_ALTERNATIVES);
45 for (j = 0; j < pkg_alts->nalts; j++) {
46 struct pkg_alternative *alt = pkg_alts->alts[j];
48 if (strcmp(path, alt->path))
50 if (!the_alt || the_alt->prio < alt->prio) {
57 /* path is assumed to be an absolute one */
58 sprintf_alloc(&path_in_dest, "%s%s", the_pkg->dest->root_dir, &path[1]);
65 r = lstat(path_in_dest, &sb);
69 if (!S_ISLNK(sb.st_mode)) {
70 opkg_msg(ERROR, "%s exists but is not a symlink\n", path_in_dest);
74 realpath = xreadlink(path_in_dest);
75 if (realpath && strcmp(realpath, the_alt->altpath))
78 } else if (errno != ENOENT) {
82 char *path_copy = xstrdup(path_in_dest);
83 char *path_parent = dirname(path_copy);
85 r = file_mkdir_hier(path_parent, 0755);
90 r = symlink(the_alt->altpath, path_in_dest);
91 if (r && errno == EEXIST) {
93 * the strcmp & unlink check above will make sure that if EEXIST
94 * happens, the symlink target also matches
99 opkg_perror(ERROR, "failed symlinking %s -> %s", path_in_dest, the_alt->altpath);
103 unlink(path_in_dest);
112 int pkg_alternatives_update(pkg_t * pkg)
116 struct pkg_alternatives *pkg_alts;
117 struct pkg_alternative *alt = NULL;
118 pkg_vec_t *installed;
120 pkg_alts = pkg_get_ptr(pkg, PKG_ALTERNATIVES);
124 installed = pkg_vec_alloc();
125 pkg_hash_fetch_all_installed(installed);
126 for (i = 0; i < pkg_alts->nalts; i++) {
127 alt = pkg_alts->alts[i];
128 r |= pkg_alternatives_update_path(pkg, installed, alt->path);
130 pkg_vec_free(installed);