}
}
-int cg_path_get_unit(const char *path, char **ret) {
- _cleanup_free_ char *unit = NULL;
- const char *e;
+int cg_path_get_unit_full(const char *path, char **ret_unit, char **ret_subgroup) {
int r;
assert(path);
- e = skip_slices(path);
+ const char *e = skip_slices(path);
+ _cleanup_free_ char *unit = NULL;
r = cg_path_decode_unit(e, &unit);
if (r < 0)
return r;
if (endswith(unit, ".slice"))
return -ENXIO;
- if (ret)
- *ret = TAKE_PTR(unit);
+ if (ret_subgroup) {
+ _cleanup_free_ char *subgroup = NULL;
+ e += strcspn(e, "/");
+ e += strspn(e, "/");
+
+ if (isempty(e))
+ subgroup = NULL;
+ else {
+ subgroup = strdup(e);
+ if (!subgroup)
+ return -ENOMEM;
+ }
+
+ path_simplify(subgroup);
+
+ *ret_subgroup = TAKE_PTR(subgroup);
+ }
+
+ if (ret_unit)
+ *ret_unit = TAKE_PTR(unit);
+
return 0;
}
return 0;
}
-int cg_pid_get_unit(pid_t pid, char **ret_unit) {
- _cleanup_free_ char *cgroup = NULL;
+int cg_pid_get_unit_full(pid_t pid, char **ret_unit, char **ret_subgroup) {
int r;
- assert(ret_unit);
-
+ _cleanup_free_ char *cgroup = NULL;
r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
if (r < 0)
return r;
- return cg_path_get_unit(cgroup, ret_unit);
+ return cg_path_get_unit_full(cgroup, ret_unit, ret_subgroup);
}
-int cg_pidref_get_unit(const PidRef *pidref, char **ret) {
- _cleanup_free_ char *unit = NULL;
+int cg_pidref_get_unit_full(const PidRef *pidref, char **ret_unit, char **ret_subgroup) {
int r;
- assert(ret);
-
if (!pidref_is_set(pidref))
return -ESRCH;
if (pidref_is_remote(pidref))
return -EREMOTE;
- r = cg_pid_get_unit(pidref->pid, &unit);
+ _cleanup_free_ char *unit = NULL, *subgroup = NULL;
+ r = cg_pid_get_unit_full(pidref->pid, &unit, &subgroup);
if (r < 0)
return r;
if (r < 0)
return r;
- *ret = TAKE_PTR(unit);
+ if (ret_unit)
+ *ret_unit = TAKE_PTR(unit);
+ if (ret_subgroup)
+ *ret_subgroup = TAKE_PTR(subgroup);
return 0;
}
int cg_path_get_session(const char *path, char **ret_session);
int cg_path_get_owner_uid(const char *path, uid_t *ret_uid);
-int cg_path_get_unit(const char *path, char **ret_unit);
+int cg_path_get_unit_full(const char *path, char **ret_unit, char **ret_subgroup);
+static inline int cg_path_get_unit(const char *path, char **ret_unit) {
+ return cg_path_get_unit_full(path, ret_unit, NULL);
+}
int cg_path_get_unit_path(const char *path, char **ret_unit);
int cg_path_get_user_unit(const char *path, char **ret_unit);
int cg_path_get_machine_name(const char *path, char **ret_machine);
int cg_pidref_get_session(const PidRef *pidref, char **ret);
int cg_pid_get_owner_uid(pid_t pid, uid_t *ret_uid);
int cg_pidref_get_owner_uid(const PidRef *pidref, uid_t *ret);
-int cg_pid_get_unit(pid_t pid, char **ret_unit);
-int cg_pidref_get_unit(const PidRef *pidref, char **ret);
+int cg_pid_get_unit_full(pid_t pid, char **ret_unit, char **ret_subgroup);
+static inline int cg_pid_get_unit(pid_t pid, char **ret_unit) {
+ return cg_pid_get_unit_full(pid, ret_unit, NULL);
+}
+int cg_pidref_get_unit_full(const PidRef *pidref, char **ret_unit, char **ret_subgroup);
+static inline int cg_pidref_get_unit(const PidRef *pidref, char **ret_unit) {
+ return cg_pidref_get_unit_full(pidref, ret_unit, NULL);
+}
int cg_pid_get_user_unit(pid_t pid, char **ret_unit);
int cg_pid_get_machine_name(pid_t pid, char **ret_machine);
int cg_pid_get_slice(pid_t pid, char **ret_slice);
check_p_g_u("/user.slice/user-1000.slice/user@.service/server.service", -ENXIO, NULL);
}
+static void check_p_g_u_f(const char *path, int expected_code, const char *expected_unit, const char *expected_subgroup) {
+ _cleanup_free_ char *unit = NULL, *subgroup = NULL;
+ int r;
+
+ r = cg_path_get_unit_full(path, &unit, &subgroup);
+ printf("%s: %s → %s %s %d expected %s %s %d\n", __func__, path, unit, subgroup, r, strnull(expected_unit), strnull(expected_subgroup), expected_code);
+ ASSERT_EQ(r, expected_code);
+ ASSERT_STREQ(unit, expected_unit);
+ ASSERT_STREQ(subgroup, expected_subgroup);
+}
+
+TEST(path_get_unit_full) {
+ check_p_g_u_f("/system.slice/foobar.service/sdfdsaf", 0, "foobar.service", "sdfdsaf");
+ check_p_g_u_f("/system.slice/foobar.service//sdfdsaf", 0, "foobar.service", "sdfdsaf");
+ check_p_g_u_f("/system.slice/foobar.service/sdfdsaf/", 0, "foobar.service", "sdfdsaf");
+ check_p_g_u_f("/system.slice/foobar.service//sdfdsaf/", 0, "foobar.service", "sdfdsaf");
+ check_p_g_u_f("/system.slice/foobar.service//sdfdsaf//", 0, "foobar.service", "sdfdsaf");
+ check_p_g_u_f("/system.slice/foobar.service/sdfdsaf/urks", 0, "foobar.service", "sdfdsaf/urks");
+ check_p_g_u_f("/system.slice/foobar.service//sdfdsaf//urks", 0, "foobar.service", "sdfdsaf/urks");
+ check_p_g_u_f("/system.slice/foobar.service/sdfdsaf/urks/", 0, "foobar.service", "sdfdsaf/urks");
+ check_p_g_u_f("/system.slice/foobar.service//sdfdsaf//urks//", 0, "foobar.service", "sdfdsaf/urks");
+ check_p_g_u_f("/system.slice/foobar.service", 0, "foobar.service", NULL);
+ check_p_g_u_f("/system.slice/foobar.service/", 0, "foobar.service", NULL);
+ check_p_g_u_f("/system.slice/foobar.service//", 0, "foobar.service", NULL);
+ check_p_g_u_f("/system.slice/", -ENXIO, NULL, NULL);
+ check_p_g_u_f("/system.slice/piff", -ENXIO, NULL, NULL);
+ check_p_g_u_f("/system.service/piff", 0, "system.service", "piff");
+ check_p_g_u_f("//system.service//piff", 0, "system.service", "piff");
+}
+
static void check_p_g_u_p(const char *path, int code, const char *result) {
_cleanup_free_ char *unit_path = NULL;
int r;