return 0;
}
+int image_policy_ignore_designators(const ImagePolicy *p, const PartitionDesignator table[], size_t n_table, ImagePolicy **ret) {
+ assert(p);
+ assert(table || n_table == 0);
+ assert(ret);
+
+ /* Patches the specified image policy, replacing the policy for the specified designators by an
+ * "ignore" policy. Returns a patched copy. This is useful in context where only some of the
+ * available partitions shall be mounted, and hence the policy for the others really doesn't
+ * matter. */
+
+ _cleanup_(image_policy_freep) ImagePolicy *np = image_policy_new(_PARTITION_DESIGNATOR_MAX);
+ if (!np)
+ return -ENOMEM;
+
+ FOREACH_ARRAY(t, table, n_table) {
+ assert(*t >= 0);
+ assert(*t < _PARTITION_DESIGNATOR_MAX);
+
+ if (image_policy_bsearch(np, *t))
+ continue;
+
+ /* Insert an ignore policy for this entry, and sort it to the right place, so that image_policy_bsearch() can work */
+ np->policies[np->n_policies++] = (PartitionPolicy) {
+ .designator = *t,
+ .flags = PARTITION_POLICY_IGNORE,
+ };
+ typesafe_qsort(np->policies, np->n_policies, partition_policy_compare);
+ }
+
+ FOREACH_ARRAY(i, p->policies, p->n_policies) {
+
+ if (image_policy_bsearch(np, i->designator))
+ continue;
+
+ /* Copy the policy entry from the old image policy, and sort it to the right place, so that image_policy_bsearch() can work */
+ np->policies[np->n_policies++] = *i;
+ typesafe_qsort(np->policies, np->n_policies, partition_policy_compare);
+ }
+
+ np->default_flags = p->default_flags;
+
+ /* Return unused space to libc */
+ ImagePolicy *t = realloc(np, offsetof(ImagePolicy, policies) + sizeof(PartitionPolicy) * np->n_policies);
+ if (t)
+ np = t;
+
+ *ret = TAKE_PTR(np);
+ return 0;
+}
+
const ImagePolicy image_policy_allow = {
/* Allow policy */
.n_policies = 0,
test_policy_intersect_one("root=open", "=verity+ignore", "root=verity+ignore:=ignore");
}
+static void test_policy_ignore_designators_one(const char *a, const PartitionDesignator array[], size_t n, const char *b) {
+ _cleanup_(image_policy_freep) ImagePolicy *x = NULL, *y = NULL, *t = NULL;
+
+ ASSERT_OK(image_policy_from_string(a, &x));
+ ASSERT_OK(image_policy_from_string(b, &y));
+
+ _cleanup_free_ char *s1 = NULL, *s2 = NULL, *s3 = NULL;
+ ASSERT_OK(image_policy_to_string(x, true, &s1));
+ ASSERT_OK(image_policy_to_string(y, true, &s2));
+
+ ASSERT_OK(image_policy_ignore_designators(x, array, n, &t));
+
+ ASSERT_OK(image_policy_to_string(t, true, &s3));
+
+ log_info("%s → %s vs. %s", s1, s2, s3);
+
+ ASSERT_TRUE(image_policy_equivalent(t, y));
+}
+
+TEST(image_policy_ignore_designators) {
+ test_policy_ignore_designators_one("-", NULL, 0, "-");
+ test_policy_ignore_designators_one("-", ((const PartitionDesignator[]) { PARTITION_ROOT }), 1, "-");
+ test_policy_ignore_designators_one("*", ((const PartitionDesignator[]) { PARTITION_ROOT }), 1, "root=ignore:=open");
+ test_policy_ignore_designators_one("*", ((const PartitionDesignator[]) { PARTITION_ROOT, PARTITION_USR }), 2, "root=ignore:usr=ignore:=open");
+ test_policy_ignore_designators_one("~", ((const PartitionDesignator[]) { PARTITION_VAR, PARTITION_ESP, PARTITION_VAR }), 2, "var=ignore:esp=ignore:=absent");
+}
+
DEFINE_TEST_MAIN(LOG_INFO);