PATCH: ifupdown and /var/run/ifstate file

Gabriel L. Somlo somlo at cmu.edu
Tue Mar 6 00:36:29 UTC 2007


Denis,

The previous version of this patch was wrong/incomplete. A new working
one is enclosed.

Extra code is needed to deconstruct the state_list gracefully, so I
added a function to unlink an element from a llist_t to be called from
ifupdown.

Thanks,
Gabriel

diff -NarU5 busybox-svn-17982.orig/include/libbb.h busybox-svn-17982/include/libbb.h
--- busybox-svn-17982.orig/include/libbb.h	2007-02-27 22:45:22.000000000 -0500
+++ busybox-svn-17982/include/libbb.h	2007-03-05 19:26:06.000000000 -0500
@@ -473,10 +473,11 @@
 	struct llist_s *link;
 } llist_t;
 extern void llist_add_to(llist_t **old_head, void *data);
 extern void llist_add_to_end(llist_t **list_head, void *data);
 extern void *llist_pop(llist_t **elm);
+extern void llist_unlink(llist_t **head, llist_t *elm);
 extern void llist_free(llist_t *elm, void (*freeit)(void *data));
 extern llist_t* llist_rev(llist_t *list);
 
 enum {
 	LOGMODE_NONE = 0,
diff -NarU5 busybox-svn-17982.orig/libbb/llist.c busybox-svn-17982/libbb/llist.c
--- busybox-svn-17982.orig/libbb/llist.c	2007-02-27 22:45:21.000000000 -0500
+++ busybox-svn-17982/libbb/llist.c	2007-03-05 19:26:00.000000000 -0500
@@ -43,25 +43,43 @@
 }
 
 /* Remove first element from the list and return it */
 void *llist_pop(llist_t ** head)
 {
-	void *data;
+	void *data, *next;
 
 	if (!*head)
-		data = *head;
-	else {
-		void *next = (*head)->link;
-
-		data = (*head)->data;
-		free(*head);
-		*head = next;
-	}
+		return NULL;
+
+	next = (*head)->link;
+	data = (*head)->data;
+	free(*head);
+	*head = next;
 
 	return data;
 }
 
+/* Unlink arbitrary given element from the list */
+void llist_unlink(llist_t **head, llist_t *elm)
+{
+	llist_t *crt;
+
+	if (!(elm && *head))
+		return;
+
+	if (elm == *head) {
+		*head = (*head)->link;
+		return;
+	}
+
+	for (crt = *head; crt; crt = crt->link)
+		if (crt->link == elm) {
+			crt->link = elm->link;
+			return;
+		}
+}
+
 /* Recursively free all elements in the linked list.  If freeit != NULL
  * call it on each datum in the list */
 void llist_free(llist_t * elm, void (*freeit) (void *data))
 {
 	while (elm) {
diff -NarU5 busybox-svn-17982.orig/networking/ifupdown.c busybox-svn-17982/networking/ifupdown.c
--- busybox-svn-17982.orig/networking/ifupdown.c	2007-02-27 22:45:19.000000000 -0500
+++ busybox-svn-17982/networking/ifupdown.c	2007-03-05 19:29:03.000000000 -0500
@@ -1089,10 +1089,12 @@
 	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";
+	const char *statefile = "/var/run/ifstate";
+	FILE *state_fp;
 	int any_failures = 0;
 
 	cmds = iface_down;
 	if (applet_name[2] == 'u') {
 		/* ifup command */
@@ -1115,10 +1117,23 @@
 	}
 
 	startup_PATH = getenv("PATH");
 	if (!startup_PATH) startup_PATH = "";
 
+	/* Read the previous state from the state file */
+	state_fp = fopen_or_warn(statefile, "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 {
@@ -1164,11 +1179,11 @@
 					bb_error_msg("interface %s already configured", iface);
 					continue;
 				}
 			} else {
 				/* ifdown */
-				if (iface_state) {
+				if (!iface_state) {
 					bb_error_msg("interface %s not configured", iface);
 					continue;
 				}
 			}
 		}
@@ -1234,21 +1249,20 @@
 				} else {
 					free(iface_state->data);
 					iface_state->data = newiface;
 				}
 			} else {
-				/* Remove an interface from the linked list */
+				/* Remove an interface from state_list  */
+				llist_unlink(&state_list, iface_state);
 				free(llist_pop(&iface_state));
 			}
 		}
 	}
 
 	/* Actually write the new state */
 	if (!NO_ACT) {
-		FILE *state_fp;
-
-		state_fp = xfopen("/var/run/ifstate", "w");
+		state_fp = xfopen(statefile, "w");
 		while (state_list) {
 			if (state_list->data) {
 				fprintf(state_fp, "%s\n", state_list->data);
 			}
 			state_list = state_list->link;



More information about the busybox mailing list