diff options
-rw-r--r-- | networking/ifupdown.c | 43 |
1 files changed, 38 insertions, 5 deletions
diff --git a/networking/ifupdown.c b/networking/ifupdown.c index b0bc0d70f..1d0fc53cf 100644 --- a/networking/ifupdown.c +++ b/networking/ifupdown.c | |||
@@ -56,6 +56,7 @@ | |||
56 | #endif | 56 | #endif |
57 | 57 | ||
58 | #define UDHCPC_CMD_OPTIONS CONFIG_IFUPDOWN_UDHCPC_CMD_OPTIONS | 58 | #define UDHCPC_CMD_OPTIONS CONFIG_IFUPDOWN_UDHCPC_CMD_OPTIONS |
59 | #define IFSTATE_FILE_PATH CONFIG_IFUPDOWN_IFSTATE_PATH | ||
59 | 60 | ||
60 | #define debug_noise(args...) /*fprintf(stderr, args)*/ | 61 | #define debug_noise(args...) /*fprintf(stderr, args)*/ |
61 | 62 | ||
@@ -1200,7 +1201,7 @@ static llist_t *find_iface_state(llist_t *state_list, const char *iface) | |||
1200 | static llist_t *read_iface_state(void) | 1201 | static llist_t *read_iface_state(void) |
1201 | { | 1202 | { |
1202 | llist_t *state_list = NULL; | 1203 | llist_t *state_list = NULL; |
1203 | FILE *state_fp = fopen_for_read(CONFIG_IFUPDOWN_IFSTATE_PATH); | 1204 | FILE *state_fp = fopen_for_read(IFSTATE_FILE_PATH); |
1204 | 1205 | ||
1205 | if (state_fp) { | 1206 | if (state_fp) { |
1206 | char *start, *end_ptr; | 1207 | char *start, *end_ptr; |
@@ -1215,6 +1216,38 @@ static llist_t *read_iface_state(void) | |||
1215 | return state_list; | 1216 | return state_list; |
1216 | } | 1217 | } |
1217 | 1218 | ||
1219 | /* read the previous state from the state file */ | ||
1220 | static FILE *open_new_state_file(void) | ||
1221 | { | ||
1222 | int fd, flags, cnt; | ||
1223 | |||
1224 | cnt = 0; | ||
1225 | flags = (O_WRONLY | O_CREAT | O_EXCL); | ||
1226 | for (;;) { | ||
1227 | fd = open(IFSTATE_FILE_PATH".new", flags, 0666); | ||
1228 | if (fd >= 0) | ||
1229 | break; | ||
1230 | if (errno != EEXIST | ||
1231 | || flags == (O_WRONLY | O_CREAT | O_TRUNC) | ||
1232 | ) { | ||
1233 | bb_perror_msg_and_die("can't open '%s'", | ||
1234 | IFSTATE_FILE_PATH".new"); | ||
1235 | } | ||
1236 | /* Someone else created the .new file */ | ||
1237 | if (cnt > 30 * 1000) { | ||
1238 | /* Waited for 30*30/2 = 450 milliseconds, still EEXIST. | ||
1239 | * Assuming a stale file, rewriting it. | ||
1240 | */ | ||
1241 | flags = (O_WRONLY | O_CREAT | O_TRUNC); | ||
1242 | continue; | ||
1243 | } | ||
1244 | usleep(cnt); | ||
1245 | cnt += 1000; | ||
1246 | } | ||
1247 | |||
1248 | return xfdopen_for_write(fd); | ||
1249 | } | ||
1250 | |||
1218 | 1251 | ||
1219 | int ifupdown_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 1252 | int ifupdown_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
1220 | int ifupdown_main(int argc UNUSED_PARAM, char **argv) | 1253 | int ifupdown_main(int argc UNUSED_PARAM, char **argv) |
@@ -1348,7 +1381,7 @@ int ifupdown_main(int argc UNUSED_PARAM, char **argv) | |||
1348 | any_failures = 1; | 1381 | any_failures = 1; |
1349 | } else if (!NO_ACT) { | 1382 | } else if (!NO_ACT) { |
1350 | /* update the state file */ | 1383 | /* update the state file */ |
1351 | FILE *state_fp; | 1384 | FILE *new_state_fp = open_new_state_file(); |
1352 | llist_t *state; | 1385 | llist_t *state; |
1353 | llist_t *state_list = read_iface_state(); | 1386 | llist_t *state_list = read_iface_state(); |
1354 | llist_t *iface_state = find_iface_state(state_list, iface); | 1387 | llist_t *iface_state = find_iface_state(state_list, iface); |
@@ -1368,15 +1401,15 @@ int ifupdown_main(int argc UNUSED_PARAM, char **argv) | |||
1368 | } | 1401 | } |
1369 | 1402 | ||
1370 | /* Actually write the new state */ | 1403 | /* Actually write the new state */ |
1371 | state_fp = xfopen_for_write(CONFIG_IFUPDOWN_IFSTATE_PATH); | ||
1372 | state = state_list; | 1404 | state = state_list; |
1373 | while (state) { | 1405 | while (state) { |
1374 | if (state->data) { | 1406 | if (state->data) { |
1375 | fprintf(state_fp, "%s\n", state->data); | 1407 | fprintf(new_state_fp, "%s\n", state->data); |
1376 | } | 1408 | } |
1377 | state = state->link; | 1409 | state = state->link; |
1378 | } | 1410 | } |
1379 | fclose(state_fp); | 1411 | fclose(new_state_fp); |
1412 | xrename(IFSTATE_FILE_PATH".new", IFSTATE_FILE_PATH); | ||
1380 | llist_free(state_list, free); | 1413 | llist_free(state_list, free); |
1381 | } | 1414 | } |
1382 | next: | 1415 | next: |