]> git.ipfire.org Git - pakfire.git/commitdiff
cgroups: Implement recursion again
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 14 Dec 2024 15:06:09 +0000 (15:06 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 14 Dec 2024 15:06:09 +0000 (15:06 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/cgroup.c
tests/libpakfire/cgroup.c

index 5bef076d1d73aa0451aa052d1d0a57cfb7a45463..94a0f09b9e64dec708ddc0c9368c5b4e09544a0b 100644 (file)
@@ -423,13 +423,59 @@ ERROR:
        return r;
 }
 
+static int pakfire_cgroup_create_recursive(struct pakfire_cgroup** cgroup,
+               struct pakfire_ctx* ctx, struct pakfire_cgroup* parent, const char* name, int flags) {
+       struct pakfire_cgroup* child = NULL;
+       char buffer[NAME_MAX];
+       char* p = NULL;
+       int r;
+
+       // Name cannot be empty
+       if (!name || !*name)
+               return -EINVAL;
+
+       // Does the name contain a /?
+       p = strchr(name, '/');
+
+       // We have reached the end of the recursion
+       if (!p)
+               return pakfire_cgroup_open(cgroup, ctx, parent, name, flags);
+
+       // Copy the string to the buffer
+       r = pakfire_string_format(buffer, "%.*s", (int)(p - name), name);
+       if (r < 0)
+               return r;
+
+       // Create the child cgroup
+       r = pakfire_cgroup_child(&child, parent, buffer, flags);
+       if (r < 0)
+               goto ERROR;
+
+       // Continue processing name...
+       r = pakfire_cgroup_create_recursive(cgroup, ctx, child, ++p, flags);
+       if (r < 0)
+               goto ERROR;
+
+       // Done
+
+ERROR:
+       if (child)
+               pakfire_cgroup_unref(child);
+
+       return r;
+}
+
 int pakfire_cgroup_create(struct pakfire_cgroup** cgroup,
                struct pakfire_ctx* ctx, struct pakfire_cgroup* parent, const char* name, int flags) {
        struct pakfire_cgroup* root = NULL;
        int r;
 
-       // If parent is NULL, but name is set, we will create the root group and use it as parent
-       if (name && !parent) {
+       // Name must be set
+       if (!name)
+               return -EINVAL;
+
+       // If parent is NULL, we open the root as parent
+       if (!parent) {
                r = pakfire_cgroup_open(&root, ctx, NULL, NULL, 0);
                if (r < 0)
                        return r;
@@ -438,7 +484,7 @@ int pakfire_cgroup_create(struct pakfire_cgroup** cgroup,
        }
 
        // Recursively create the new cgroup
-       r = pakfire_cgroup_open(cgroup, ctx, parent, name, flags);
+       r = pakfire_cgroup_create_recursive(cgroup, ctx, parent, name, flags);
 
        // Cleanup
        if (root)
index 0970560b2c731634fa378079796b3aac9ddf921d..efe661220b8cd24f561ecc5cdde3084091d2f2b9 100644 (file)
@@ -45,6 +45,30 @@ FAIL:
        return r;
 }
 
+static int test_recursive(const struct test* t) {
+       struct pakfire_cgroup* cgroup = NULL;
+       int r = EXIT_FAILURE;
+
+       // Try to create some invalid cgroups
+       ASSERT(pakfire_cgroup_create(&cgroup, t->ctx, NULL, NULL, 0) == -EINVAL);
+       ASSERT(pakfire_cgroup_create(&cgroup, t->ctx, NULL, "pakfire-test/a/", 0) == -EINVAL);
+
+       // Open a new cgroup
+       ASSERT_SUCCESS(pakfire_cgroup_create(&cgroup, t->ctx, NULL, "pakfire-test/a/b/c", 0));
+
+       // Destroy the cgroup again
+       ASSERT_SUCCESS(pakfire_cgroup_destroy(cgroup));
+
+       // Success
+       r = EXIT_SUCCESS;
+
+FAIL:
+       if (cgroup)
+               pakfire_cgroup_unref(cgroup);
+
+       return r;
+}
+
 static int test_child(const struct test* t) {
        struct pakfire_cgroup* cgroup = NULL;
        struct pakfire_cgroup* child = NULL;
@@ -122,6 +146,7 @@ FAIL:
 
 int main(int argc, const char* argv[]) {
        testsuite_add_test(test_create_and_destroy, 0);
+       testsuite_add_test(test_recursive, 0);
        testsuite_add_test(test_child, 0);
        testsuite_add_test(test_stats, TEST_WANTS_PAKFIRE);