+static void
+remove_rules_by_type_up_to (BusPolicy *policy,
+ BusPolicyRuleType type,
+ DBusList *up_to)
+{
+ DBusList *link;
+
+ link = _dbus_list_get_first (&policy->rules);
+ while (link != up_to)
+ {
+ BusPolicyRule *rule = link->data;
+ DBusList *next = _dbus_list_get_next_link (&policy->rules, link);
+
+ bus_policy_rule_unref (rule);
+ _dbus_list_remove_link (&policy->rules, link);
+
+ link = next;
+ }
+}
+
+static void
+bus_policy_optimize (BusPolicy *policy)
+{
+ DBusList *link;
+
+ /* The idea here is that if we have:
+ *
+ * <allow send="foo"/>
+ * <deny send="*"/>
+ *
+ * (for example) the deny will always override the allow. So we
+ * delete the allow. Ditto for deny followed by allow, etc. This is
+ * a dumb thing to put in a config file, but the <include> feature
+ * of files allows for an "inheritance and override" pattern where
+ * it could make sense. If an included file wants to "start over"
+ * with a blanket deny, no point keeping the rules from the parent
+ * file.
+ */
+
+ link = _dbus_list_get_first (&policy->rules);
+ while (link != NULL)
+ {
+ BusPolicyRule *rule = link->data;
+ DBusList *next = _dbus_list_get_next_link (&policy->rules, link);
+ dbus_bool_t remove_preceding;
+
+ remove_preceding = FALSE;
+
+ switch (rule->type)
+ {
+ case BUS_POLICY_RULE_SEND:
+ remove_preceding =
+ rule->d.send.message_name == NULL &&
+ rule->d.send.destination == NULL;
+ break;
+ case BUS_POLICY_RULE_RECEIVE:
+ remove_preceding =
+ rule->d.receive.message_name == NULL &&
+ rule->d.receive.origin == NULL;
+ break;
+ case BUS_POLICY_RULE_OWN:
+ remove_preceding =
+ rule->d.own.service_name == NULL;
+ break;
+ }
+
+ if (remove_preceding)
+ remove_rules_by_type_up_to (policy, rule->type,
+ link);
+
+ link = next;
+ }
+}
+