diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-05-02 21:38:44 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-05-02 21:38:44 +0000 |
commit | bd100b7478340a28fed272e60c87da37dab125e6 (patch) | |
tree | 05041aa120b7b2f7cb5534743f4fb7a509322517 /networking | |
parent | 4ac530c0ef4f2c4c15a177456b01e240bfb9f1aa (diff) |
ifupdown: reread state file before rewriting it.
Fixes "ifup started another ifup" state corruption bug.
Patch by Natanael Copa <natanael.copa@gmail.com>.
Diffstat (limited to 'networking')
-rw-r--r-- | networking/ifupdown.c | 73 |
1 files changed, 37 insertions, 36 deletions
diff --git a/networking/ifupdown.c b/networking/ifupdown.c index 887c2eea5..ff4f7855b 100644 --- a/networking/ifupdown.c +++ b/networking/ifupdown.c @@ -1083,15 +1083,33 @@ static llist_t *find_iface_state(llist_t *state_list, const char *iface) 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 (*cmds)(struct interface_defn_t *) = NULL; struct interfaces_file_t *defn; - llist_t *state_list = NULL; llist_t *target_list = NULL; const char *interfaces = "/etc/network/interfaces"; - FILE *state_fp; bool any_failures = 0; cmds = iface_down; @@ -1118,32 +1136,9 @@ int ifupdown_main(int argc, char **argv) startup_PATH = getenv("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 */ if (DO_ALL) { - if (cmds == iface_up) { - 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; - } + target_list = defn->autointerfaces; } else { llist_add_to_end(&target_list, argv[optind]); } @@ -1170,6 +1165,7 @@ int ifupdown_main(int argc, char **argv) } if (!FORCE) { + llist_t *state_list = read_iface_state(); const llist_t *iface_state = find_iface_state(state_list, iface); if (cmds == iface_up) { @@ -1185,6 +1181,7 @@ int ifupdown_main(int argc, char **argv) continue; } } + llist_free(state_list, free); } #if ENABLE_FEATURE_IFUPDOWN_MAPPING @@ -1239,6 +1236,8 @@ int ifupdown_main(int argc, char **argv) bb_error_msg("ignoring unknown interface %s", liface); any_failures = 1; } else { + /* update the state file */ + llist_t *state_list = read_iface_state(); llist_t *iface_state = find_iface_state(state_list, iface); if (cmds == iface_up) { @@ -1254,19 +1253,21 @@ int ifupdown_main(int argc, char **argv) llist_unlink(&state_list, iface_state); free(llist_pop(&iface_state)); } - } - } - /* Actually write the new state */ - if (!NO_ACT) { - state_fp = xfopen("/var/run/ifstate", "w"); - while (state_list) { - if (state_list->data) { - fprintf(state_fp, "%s\n", state_list->data); + /* Actually write the new state */ + if (!NO_ACT) { + FILE *state_fp = xfopen("/var/run/ifstate", "w"); + llist_t *state = state_list; + while (state) { + 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; |