ifupdown: reread state file before rewriting it.
Fixes "ifup started another ifup" state corruption bug. Patch by Natanael Copa <natanael.copa@gmail.com>.
This commit is contained in:
parent
4ac530c0ef
commit
bd100b7478
@ -1083,15 +1083,33 @@ static llist_t *find_iface_state(llist_t *state_list, const char *iface)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* read the previous state from the state file */
|
||||||
|
static llist_t *read_iface_state(void)
|
||||||
|
{
|
||||||
|
llist_t *state_list = NULL;
|
||||||
|
FILE *state_fp = fopen("/var/run/ifstate", "r");
|
||||||
|
|
||||||
|
if (state_fp) {
|
||||||
|
char *start, *end_ptr;
|
||||||
|
while ((start = xmalloc_fgets(state_fp)) != NULL) {
|
||||||
|
/* We should only need to check for a single character */
|
||||||
|
end_ptr = start + strcspn(start, " \t\n");
|
||||||
|
*end_ptr = '\0';
|
||||||
|
llist_add_to(&state_list, start);
|
||||||
|
}
|
||||||
|
fclose(state_fp);
|
||||||
|
}
|
||||||
|
return state_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int ifupdown_main(int argc, char **argv);
|
int ifupdown_main(int argc, char **argv);
|
||||||
int ifupdown_main(int argc, char **argv)
|
int ifupdown_main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int (*cmds)(struct interface_defn_t *) = NULL;
|
int (*cmds)(struct interface_defn_t *) = NULL;
|
||||||
struct interfaces_file_t *defn;
|
struct interfaces_file_t *defn;
|
||||||
llist_t *state_list = NULL;
|
|
||||||
llist_t *target_list = NULL;
|
llist_t *target_list = NULL;
|
||||||
const char *interfaces = "/etc/network/interfaces";
|
const char *interfaces = "/etc/network/interfaces";
|
||||||
FILE *state_fp;
|
|
||||||
bool any_failures = 0;
|
bool any_failures = 0;
|
||||||
|
|
||||||
cmds = iface_down;
|
cmds = iface_down;
|
||||||
@ -1118,32 +1136,9 @@ int ifupdown_main(int argc, char **argv)
|
|||||||
startup_PATH = getenv("PATH");
|
startup_PATH = getenv("PATH");
|
||||||
if (!startup_PATH) startup_PATH = "";
|
if (!startup_PATH) startup_PATH = "";
|
||||||
|
|
||||||
/* Read the previous state from the state file */
|
|
||||||
state_fp = fopen("/var/run/ifstate", "r");
|
|
||||||
if (state_fp) {
|
|
||||||
char *start, *end_ptr;
|
|
||||||
while ((start = xmalloc_fgets(state_fp)) != NULL) {
|
|
||||||
/* We should only need to check for a single character */
|
|
||||||
end_ptr = start + strcspn(start, " \t\n");
|
|
||||||
*end_ptr = '\0';
|
|
||||||
llist_add_to(&state_list, start);
|
|
||||||
}
|
|
||||||
fclose(state_fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create a list of interfaces to work on */
|
/* Create a list of interfaces to work on */
|
||||||
if (DO_ALL) {
|
if (DO_ALL) {
|
||||||
if (cmds == iface_up) {
|
target_list = defn->autointerfaces;
|
||||||
target_list = defn->autointerfaces;
|
|
||||||
} else {
|
|
||||||
/* iface_down */
|
|
||||||
const llist_t *list = state_list;
|
|
||||||
while (list) {
|
|
||||||
llist_add_to_end(&target_list, xstrdup(list->data));
|
|
||||||
list = list->link;
|
|
||||||
}
|
|
||||||
target_list = defn->autointerfaces;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
llist_add_to_end(&target_list, argv[optind]);
|
llist_add_to_end(&target_list, argv[optind]);
|
||||||
}
|
}
|
||||||
@ -1170,6 +1165,7 @@ int ifupdown_main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!FORCE) {
|
if (!FORCE) {
|
||||||
|
llist_t *state_list = read_iface_state();
|
||||||
const llist_t *iface_state = find_iface_state(state_list, iface);
|
const llist_t *iface_state = find_iface_state(state_list, iface);
|
||||||
|
|
||||||
if (cmds == iface_up) {
|
if (cmds == iface_up) {
|
||||||
@ -1185,6 +1181,7 @@ int ifupdown_main(int argc, char **argv)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
llist_free(state_list, free);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_FEATURE_IFUPDOWN_MAPPING
|
#if ENABLE_FEATURE_IFUPDOWN_MAPPING
|
||||||
@ -1239,6 +1236,8 @@ int ifupdown_main(int argc, char **argv)
|
|||||||
bb_error_msg("ignoring unknown interface %s", liface);
|
bb_error_msg("ignoring unknown interface %s", liface);
|
||||||
any_failures = 1;
|
any_failures = 1;
|
||||||
} else {
|
} else {
|
||||||
|
/* update the state file */
|
||||||
|
llist_t *state_list = read_iface_state();
|
||||||
llist_t *iface_state = find_iface_state(state_list, iface);
|
llist_t *iface_state = find_iface_state(state_list, iface);
|
||||||
|
|
||||||
if (cmds == iface_up) {
|
if (cmds == iface_up) {
|
||||||
@ -1254,19 +1253,21 @@ int ifupdown_main(int argc, char **argv)
|
|||||||
llist_unlink(&state_list, iface_state);
|
llist_unlink(&state_list, iface_state);
|
||||||
free(llist_pop(&iface_state));
|
free(llist_pop(&iface_state));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Actually write the new state */
|
/* Actually write the new state */
|
||||||
if (!NO_ACT) {
|
if (!NO_ACT) {
|
||||||
state_fp = xfopen("/var/run/ifstate", "w");
|
FILE *state_fp = xfopen("/var/run/ifstate", "w");
|
||||||
while (state_list) {
|
llist_t *state = state_list;
|
||||||
if (state_list->data) {
|
while (state) {
|
||||||
fprintf(state_fp, "%s\n", state_list->data);
|
if (state->data) {
|
||||||
|
fprintf(state_fp, "%s\n", state->data);
|
||||||
|
}
|
||||||
|
state = state->link;
|
||||||
|
}
|
||||||
|
fclose(state_fp);
|
||||||
}
|
}
|
||||||
state_list = state_list->link;
|
llist_free(state_list, free);
|
||||||
}
|
}
|
||||||
fclose(state_fp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return any_failures;
|
return any_failures;
|
||||||
|
Loading…
Reference in New Issue
Block a user