The following commit has been merged in the master branch:
commit 00f67fb88a7c51c14ec1f19dc5b0d666683a62c9
Author: Guillem Jover <[email protected]>
Date: Wed Feb 6 02:05:01 2013 +0100
u-a: Cache current alternative
This will allow to call alternative_get_current() multiple times w/o
needing to perform useless work. It also gets rid of some annoying
resource handling.
diff --git a/utils/update-alternatives.c b/utils/update-alternatives.c
index af52404..28f17f3 100644
--- a/utils/update-alternatives.c
+++ b/utils/update-alternatives.c
@@ -650,6 +650,8 @@ struct commit_operation {
struct alternative {
char *master_name;
char *master_link;
+ char *current;
+
enum alternative_status {
ALT_ST_UNKNOWN,
ALT_ST_AUTO,
@@ -663,6 +665,7 @@ struct alternative {
int ref_count;
bool modified;
+ bool known_current;
};
static void
@@ -689,11 +692,13 @@ alternative_new(const char *name)
alt = xmalloc(sizeof(*alt));
alt->master_name = xstrdup(name);
alt->master_link = NULL;
+ alt->current = NULL;
alt->status = ALT_ST_UNKNOWN;
alt->slaves = NULL;
alt->choices = NULL;
alt->commit_ops = NULL;
alt->modified = false;
+ alt->known_current = false;
alt->ref_count = 1;
return alt;
@@ -743,6 +748,8 @@ alternative_reset(struct alternative *alt)
{
struct slave_link *slave;
+ free(alt->current);
+ alt->current = NULL;
free(alt->master_link);
alt->master_link = NULL;
while (alt->slaves) {
@@ -753,6 +760,7 @@ alternative_reset(struct alternative *alt)
alternative_choices_free(alt);
alternative_commit_operations_free(alt);
alt->modified = false;
+ alt->known_current = false;
}
static void
@@ -1411,18 +1419,30 @@ alternative_get_best(struct alternative *a)
return best;
}
-static char *
+static const char *
+alternative_set_current(struct alternative *a, char *new_choice)
+{
+ a->known_current = true;
+ a->current = new_choice;
+
+ return new_choice;
+}
+
+static const char *
alternative_get_current(struct alternative *a)
{
struct stat st;
char *curlink;
char *file;
+ if (a->known_current)
+ return a->current;
+
xasprintf(&curlink, "%s/%s", altdir, a->master_name);
if (lstat(curlink, &st)) {
if (errno == ENOENT) {
free(curlink);
- return NULL;
+ return alternative_set_current(a, NULL);
}
syserr(_("cannot stat file '%s'"), curlink);
}
@@ -1430,7 +1450,7 @@ alternative_get_current(struct alternative *a)
file = xreadlink(curlink);
free(curlink);
- return file;
+ return alternative_set_current(a, file);
}
static void
@@ -1438,7 +1458,7 @@ alternative_display_query(struct alternative *a)
{
struct fileset *best, *fs;
struct slave_link *sl;
- char *current;
+ const char *current;
pr("Name: %s", a->master_name);
pr("Link: %s", a->master_link);
@@ -1453,7 +1473,6 @@ alternative_display_query(struct alternative *a)
pr("Best: %s", best->master_file);
current = alternative_get_current(a);
pr("Value: %s", current ? current : "none");
- free(current);
for (fs = a->choices; fs; fs = fs->next) {
printf("\n");
@@ -1473,7 +1492,7 @@ alternative_display_query(struct alternative *a)
static void
alternative_display_user(struct alternative *a)
{
- char *current;
+ const char *current;
struct fileset *fs;
struct slave_link *sl;
@@ -1482,7 +1501,6 @@ alternative_display_user(struct alternative *a)
current = alternative_get_current(a);
if (current) {
pr(_(" link currently points to %s"), current);
- free(current);
} else {
pr(_(" link currently absent"));
}
@@ -1515,7 +1533,8 @@ alternative_display_list(struct alternative *a)
static const char *
alternative_select_choice(struct alternative *a)
{
- char *current, *ret, selection[_POSIX_PATH_MAX];
+ const char *current;
+ char *ret, selection[_POSIX_PATH_MAX];
struct fileset *best, *fs;
int len, idx;
@@ -1562,7 +1581,6 @@ alternative_select_choice(struct alternative *a)
"or type selection number: "));
ret = fgets(selection, sizeof(selection), stdin);
if (ret == NULL || strlen(selection) == 0) {
- free(current);
return NULL;
}
selection[strlen(selection) - 1] = '\0';
@@ -1576,7 +1594,6 @@ alternative_select_choice(struct alternative *a)
/* Look up by index */
if (idx == 0) {
alternative_set_status(a, ALT_ST_AUTO);
- free(current);
return xstrdup(best->master_file);
}
idx--;
@@ -1584,7 +1601,6 @@ alternative_select_choice(struct alternative *a)
fs = fs->next;
if (fs) {
alternative_set_status(a, ALT_ST_MANUAL);
- free(current);
return xstrdup(fs->master_file);
}
} else {
@@ -1592,7 +1608,6 @@ alternative_select_choice(struct alternative *a)
fs = alternative_get_fileset(a, selection);
if (fs) {
alternative_set_status(a, ALT_ST_MANUAL);
- free(current);
return xstrdup(selection);
}
}
@@ -1814,7 +1829,8 @@ alternative_remove(struct alternative *a)
static bool
alternative_is_broken(struct alternative *a)
{
- char *altlnk, *wanted, *current;
+ const char *current;
+ char *altlnk, *wanted;
struct fileset *fs;
struct slave_link *sl;
@@ -1836,12 +1852,10 @@ alternative_is_broken(struct alternative *a)
if (current == NULL)
return true;
- if (!alternative_has_choice(a, current)) {
- free(current);
+ if (!alternative_has_choice(a, current))
return false;
- }
+
fs = alternative_get_fileset(a, current);
- free(current);
/* Check slaves */
for (sl = a->slaves; sl; sl = sl->next) {
@@ -2030,13 +2044,12 @@ alternative_get_selections(void)
alternative_map_load_names(alt_map_obj);
for (am = alt_map_obj; am && am->item; am = am->next) {
- char *current;
+ const char *current;
current = alternative_get_current(am->item);
printf("%-30s %-8s %s\n", am->key,
alternative_status_string(am->item->status),
current ? current : "");
- free(current);
}
alternative_map_free(alt_map_obj);
@@ -2240,7 +2253,7 @@ alternative_evolve(struct alternative *a, struct
alternative *b,
static void
alternative_update(struct alternative *a,
- char *current_choice, const char *new_choice)
+ const char *current_choice, const char *new_choice)
{
/* No choice left, remove everything. */
if (!alternative_choices_count(a)) {
@@ -2424,7 +2437,8 @@ main(int argc, char **argv)
/* Set of files to install in the alternative. */
struct fileset *fileset = NULL;
/* Path of alternative we are offering. */
- char *path = NULL, *current_choice = NULL;
+ char *path = NULL;
+ const char *current_choice = NULL;
const char *new_choice = NULL;
int i = 0;
--
dpkg's main repository
--
To UNSUBSCRIBE, email to [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]