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 | |
| parent | 4ac530c0ef4f2c4c15a177456b01e240bfb9f1aa (diff) | |
| download | busybox-w32-bd100b7478340a28fed272e60c87da37dab125e6.tar.gz busybox-w32-bd100b7478340a28fed272e60c87da37dab125e6.tar.bz2 busybox-w32-bd100b7478340a28fed272e60c87da37dab125e6.zip | |
ifupdown: reread state file before rewriting it.
Fixes "ifup started another ifup" state corruption bug.
Patch by Natanael Copa <natanael.copa@gmail.com>.
| -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) | |||
| 1083 | return NULL; | 1083 | return NULL; |
| 1084 | } | 1084 | } |
| 1085 | 1085 | ||
| 1086 | /* read the previous state from the state file */ | ||
| 1087 | static llist_t *read_iface_state(void) | ||
| 1088 | { | ||
| 1089 | llist_t *state_list = NULL; | ||
| 1090 | FILE *state_fp = fopen("/var/run/ifstate", "r"); | ||
| 1091 | |||
| 1092 | if (state_fp) { | ||
| 1093 | char *start, *end_ptr; | ||
| 1094 | while ((start = xmalloc_fgets(state_fp)) != NULL) { | ||
| 1095 | /* We should only need to check for a single character */ | ||
| 1096 | end_ptr = start + strcspn(start, " \t\n"); | ||
| 1097 | *end_ptr = '\0'; | ||
| 1098 | llist_add_to(&state_list, start); | ||
| 1099 | } | ||
| 1100 | fclose(state_fp); | ||
| 1101 | } | ||
| 1102 | return state_list; | ||
| 1103 | } | ||
| 1104 | |||
| 1105 | |||
| 1086 | int ifupdown_main(int argc, char **argv); | 1106 | int ifupdown_main(int argc, char **argv); |
| 1087 | int ifupdown_main(int argc, char **argv) | 1107 | int ifupdown_main(int argc, char **argv) |
| 1088 | { | 1108 | { |
| 1089 | int (*cmds)(struct interface_defn_t *) = NULL; | 1109 | int (*cmds)(struct interface_defn_t *) = NULL; |
| 1090 | struct interfaces_file_t *defn; | 1110 | struct interfaces_file_t *defn; |
| 1091 | llist_t *state_list = NULL; | ||
| 1092 | llist_t *target_list = NULL; | 1111 | llist_t *target_list = NULL; |
| 1093 | const char *interfaces = "/etc/network/interfaces"; | 1112 | const char *interfaces = "/etc/network/interfaces"; |
| 1094 | FILE *state_fp; | ||
| 1095 | bool any_failures = 0; | 1113 | bool any_failures = 0; |
| 1096 | 1114 | ||
| 1097 | cmds = iface_down; | 1115 | cmds = iface_down; |
| @@ -1118,32 +1136,9 @@ int ifupdown_main(int argc, char **argv) | |||
| 1118 | startup_PATH = getenv("PATH"); | 1136 | startup_PATH = getenv("PATH"); |
| 1119 | if (!startup_PATH) startup_PATH = ""; | 1137 | if (!startup_PATH) startup_PATH = ""; |
| 1120 | 1138 | ||
| 1121 | /* Read the previous state from the state file */ | ||
| 1122 | state_fp = fopen("/var/run/ifstate", "r"); | ||
| 1123 | if (state_fp) { | ||
| 1124 | char *start, *end_ptr; | ||
| 1125 | while ((start = xmalloc_fgets(state_fp)) != NULL) { | ||
| 1126 | /* We should only need to check for a single character */ | ||
| 1127 | end_ptr = start + strcspn(start, " \t\n"); | ||
| 1128 | *end_ptr = '\0'; | ||
| 1129 | llist_add_to(&state_list, start); | ||
| 1130 | } | ||
| 1131 | fclose(state_fp); | ||
| 1132 | } | ||
| 1133 | |||
| 1134 | /* Create a list of interfaces to work on */ | 1139 | /* Create a list of interfaces to work on */ |
| 1135 | if (DO_ALL) { | 1140 | if (DO_ALL) { |
| 1136 | if (cmds == iface_up) { | 1141 | target_list = defn->autointerfaces; |
| 1137 | target_list = defn->autointerfaces; | ||
| 1138 | } else { | ||
| 1139 | /* iface_down */ | ||
| 1140 | const llist_t *list = state_list; | ||
| 1141 | while (list) { | ||
| 1142 | llist_add_to_end(&target_list, xstrdup(list->data)); | ||
| 1143 | list = list->link; | ||
| 1144 | } | ||
| 1145 | target_list = defn->autointerfaces; | ||
| 1146 | } | ||
| 1147 | } else { | 1142 | } else { |
| 1148 | llist_add_to_end(&target_list, argv[optind]); | 1143 | llist_add_to_end(&target_list, argv[optind]); |
| 1149 | } | 1144 | } |
| @@ -1170,6 +1165,7 @@ int ifupdown_main(int argc, char **argv) | |||
| 1170 | } | 1165 | } |
| 1171 | 1166 | ||
| 1172 | if (!FORCE) { | 1167 | if (!FORCE) { |
| 1168 | llist_t *state_list = read_iface_state(); | ||
| 1173 | const llist_t *iface_state = find_iface_state(state_list, iface); | 1169 | const llist_t *iface_state = find_iface_state(state_list, iface); |
| 1174 | 1170 | ||
| 1175 | if (cmds == iface_up) { | 1171 | if (cmds == iface_up) { |
| @@ -1185,6 +1181,7 @@ int ifupdown_main(int argc, char **argv) | |||
| 1185 | continue; | 1181 | continue; |
| 1186 | } | 1182 | } |
| 1187 | } | 1183 | } |
| 1184 | llist_free(state_list, free); | ||
| 1188 | } | 1185 | } |
| 1189 | 1186 | ||
| 1190 | #if ENABLE_FEATURE_IFUPDOWN_MAPPING | 1187 | #if ENABLE_FEATURE_IFUPDOWN_MAPPING |
| @@ -1239,6 +1236,8 @@ int ifupdown_main(int argc, char **argv) | |||
| 1239 | bb_error_msg("ignoring unknown interface %s", liface); | 1236 | bb_error_msg("ignoring unknown interface %s", liface); |
| 1240 | any_failures = 1; | 1237 | any_failures = 1; |
| 1241 | } else { | 1238 | } else { |
| 1239 | /* update the state file */ | ||
| 1240 | llist_t *state_list = read_iface_state(); | ||
| 1242 | llist_t *iface_state = find_iface_state(state_list, iface); | 1241 | llist_t *iface_state = find_iface_state(state_list, iface); |
| 1243 | 1242 | ||
| 1244 | if (cmds == iface_up) { | 1243 | if (cmds == iface_up) { |
| @@ -1254,19 +1253,21 @@ int ifupdown_main(int argc, char **argv) | |||
| 1254 | llist_unlink(&state_list, iface_state); | 1253 | llist_unlink(&state_list, iface_state); |
| 1255 | free(llist_pop(&iface_state)); | 1254 | free(llist_pop(&iface_state)); |
| 1256 | } | 1255 | } |
| 1257 | } | ||
| 1258 | } | ||
| 1259 | 1256 | ||
| 1260 | /* Actually write the new state */ | 1257 | /* Actually write the new state */ |
| 1261 | if (!NO_ACT) { | 1258 | if (!NO_ACT) { |
| 1262 | state_fp = xfopen("/var/run/ifstate", "w"); | 1259 | FILE *state_fp = xfopen("/var/run/ifstate", "w"); |
| 1263 | while (state_list) { | 1260 | llist_t *state = state_list; |
| 1264 | if (state_list->data) { | 1261 | while (state) { |
| 1265 | fprintf(state_fp, "%s\n", state_list->data); | 1262 | if (state->data) { |
| 1263 | fprintf(state_fp, "%s\n", state->data); | ||
| 1264 | } | ||
| 1265 | state = state->link; | ||
| 1266 | } | ||
| 1267 | fclose(state_fp); | ||
| 1266 | } | 1268 | } |
| 1267 | state_list = state_list->link; | 1269 | llist_free(state_list, free); |
| 1268 | } | 1270 | } |
| 1269 | fclose(state_fp); | ||
| 1270 | } | 1271 | } |
| 1271 | 1272 | ||
| 1272 | return any_failures; | 1273 | return any_failures; |
