]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: add cg_path_get_unit_path()
authorQuentin Deslandes <qde@naccy.de>
Thu, 26 Jan 2023 18:39:08 +0000 (19:39 +0100)
committerQuentin Deslandes <qde@naccy.de>
Wed, 8 Feb 2023 15:48:58 +0000 (16:48 +0100)
From a given cgroup path, cg_path_get_unit() allows to retrieve the
unit's name. Although, this removes the path to the unit's cgroup,
preventing the result to be used to fetch xattrs.

Introduce cg_path_get_unit_path() which provides the path to the unit's
cgroup. This function behave similarly to cg_path_get_unit() (checking
the validity and escaping the unit's name).

src/basic/cgroup-util.c
src/basic/cgroup-util.h
src/test/test-cgroup-util.c

index a8e4a1bb2d27ec2a0d34a78a4cf61782d91e3233..feda5969390c6f357600e0666c03191d0b1e1053 100644 (file)
@@ -1198,6 +1198,28 @@ int cg_path_get_unit(const char *path, char **ret) {
         return 0;
 }
 
+int cg_path_get_unit_path(const char *path, char **ret) {
+        _cleanup_free_ char *path_copy = NULL;
+        char *unit_name;
+
+        assert(path);
+        assert(ret);
+
+        path_copy = strdup(path);
+        if (!path_copy)
+                return -ENOMEM;
+
+        unit_name = (char *)skip_slices(path_copy);
+        unit_name[strcspn(unit_name, "/")] = 0;
+
+        if (!unit_name_is_valid(cg_unescape(unit_name), UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE))
+                return -ENXIO;
+
+        *ret = TAKE_PTR(path_copy);
+
+        return 0;
+}
+
 int cg_pid_get_unit(pid_t pid, char **unit) {
         _cleanup_free_ char *cgroup = NULL;
         int r;
index c9aae5abf6272e1fd2d7ed71695f2c2d6f294d86..b69f1683dbe781e6b3ab04b1eb07a530097ca841 100644 (file)
@@ -261,6 +261,7 @@ int cg_path_get_cgroupid(const char *path, uint64_t *ret);
 int cg_path_get_session(const char *path, char **session);
 int cg_path_get_owner_uid(const char *path, uid_t *uid);
 int cg_path_get_unit(const char *path, char **unit);
+int cg_path_get_unit_path(const char *path, char **unit);
 int cg_path_get_user_unit(const char *path, char **unit);
 int cg_path_get_machine_name(const char *path, char **machine);
 int cg_path_get_slice(const char *path, char **slice);
index 0b286ed8e458a07fa7c4ad0d784b0cb1a3d23bde..cdf911926ca7792d6629cd99829ec6c98947e78b 100644 (file)
@@ -63,6 +63,33 @@ TEST(path_get_unit) {
         check_p_g_u("/user.slice/user-1000.slice/user@.service/server.service", -ENXIO, NULL);
 }
 
+static void check_p_g_u_p(const char *path, int code, const char *result) {
+        _cleanup_free_ char *unit_path = NULL;
+        int r;
+
+        r = cg_path_get_unit_path(path, &unit_path);
+        printf("%s: %s → %s %d expected %s %d\n", __func__, path, unit_path, r, strnull(result), code);
+        assert_se(r == code);
+        assert_se(streq_ptr(unit_path, result));
+}
+
+TEST(path_get_unit_path) {
+        check_p_g_u_p("/system.slice/foobar.service/sdfdsaf", 0, "/system.slice/foobar.service");
+        check_p_g_u_p("/system.slice/getty@tty5.service", 0, "/system.slice/getty@tty5.service");
+        check_p_g_u_p("/system.slice/getty@tty5.service/aaa/bbb", 0, "/system.slice/getty@tty5.service");
+        check_p_g_u_p("/system.slice/getty@tty5.service/", 0, "/system.slice/getty@tty5.service");
+        check_p_g_u_p("/system.slice/getty@tty6.service/tty5", 0, "/system.slice/getty@tty6.service");
+        check_p_g_u_p("sadfdsafsda", -ENXIO, NULL);
+        check_p_g_u_p("/system.slice/getty####@tty6.service/xxx", -ENXIO, NULL);
+        check_p_g_u_p("/system.slice/system-waldo.slice/foobar.service/sdfdsaf", 0, "/system.slice/system-waldo.slice/foobar.service");
+        check_p_g_u_p("/system.slice/system-waldo.slice/_cpu.service/sdfdsaf", 0, "/system.slice/system-waldo.slice/_cpu.service");
+        check_p_g_u_p("/system.slice/system-waldo.slice/_cpu.service", 0, "/system.slice/system-waldo.slice/_cpu.service");
+        check_p_g_u_p("/user.slice/user-1000.slice/user@1000.service/server.service", 0, "/user.slice/user-1000.slice/user@1000.service");
+        check_p_g_u_p("/user.slice/user-1000.slice/user@.service/server.service", -ENXIO, NULL);
+        check_p_g_u_p("/user.slice/_user-1000.slice/user@1000.service/foobar.slice/foobar@pie.service", 0, "/user.slice/_user-1000.slice/user@1000.service");
+        check_p_g_u_p("/_session-2.scope/_foobar@pie.service/pa/po", 0, "/_session-2.scope");
+}
+
 static void check_p_g_u_u(const char *path, int code, const char *result) {
         _cleanup_free_ char *unit = NULL;
         int r;