summaryrefslogtreecommitdiff
path: root/src/basic/cgroup-util.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2018-02-09 18:35:52 +0100
committerSven Eden <yamakuzure@gmx.net>2018-05-30 07:59:09 +0200
commitfa4505314d65df4bd778543ea3753d6efd696ca1 (patch)
tree58ad048ec4f6ac83275a0b2f253f90594713d8be /src/basic/cgroup-util.c
parentc3b7f359b022902190c58c1d8f17eb70265bc603 (diff)
cgroup-util: rework cg_get_keyed_attribute() a bit
Let's make sure we don't clobber the return parameter on failure, to follow our coding style. Also, break the loop early if we have all attributes we need. This also changes the keys parameter to a simple char**, so that we can use STRV_MAKE() for passing the list of attributes to read. This also makes it possible to distuingish the case when the whole attribute file doesn't exist from one key in it missing. In the former case we return -ENOENT, in the latter we now return -ENXIO.
Diffstat (limited to 'src/basic/cgroup-util.c')
-rw-r--r--src/basic/cgroup-util.c95
1 files changed, 73 insertions, 22 deletions
diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c
index 7b6f66661..9e5c540c6 100644
--- a/src/basic/cgroup-util.c
+++ b/src/basic/cgroup-util.c
@@ -1076,11 +1076,13 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
continue;
*e = 0;
- FOREACH_WORD_SEPARATOR(word, k, l, ",", state)
+ FOREACH_WORD_SEPARATOR(word, k, l, ",", state) {
if (k == cs && memcmp(word, controller_str, cs) == 0) {
found = true;
break;
}
+ }
+
if (!found)
continue;
}
@@ -2136,46 +2138,95 @@ int cg_get_attribute(const char *controller, const char *path, const char *attri
}
#if 0 /// UNNEEDED by elogind
-int cg_get_keyed_attribute(const char *controller, const char *path, const char *attribute, const char **keys, char **values) {
- _cleanup_free_ char *filename = NULL, *content = NULL;
- char *line, *p;
- int i, r;
+int cg_get_keyed_attribute(
+ const char *controller,
+ const char *path,
+ const char *attribute,
+ char **keys,
+ char **ret_values) {
+
+ _cleanup_free_ char *filename = NULL, *contents = NULL;
+ _cleanup_fclose_ FILE *f = NULL;
+ const char *p;
+ size_t n, i;
+ char **v;
+ int r;
- for (i = 0; keys[i]; i++)
- values[i] = NULL;
+ /* Reads one or more fields of a cgroupsv2 keyed attribute file. The 'keys' parameter should be an strv with
+ * all keys to retrieve. The 'ret_values' parameter should be passed as string size with the same number of
+ * entries as 'keys'. On success each entry will be set to the value of the matching key.
+ *
+ * If the attribute file doesn't exist at all returns ENOENT, if any key is not found returns ENXIO. */
r = cg_get_path(controller, path, attribute, &filename);
if (r < 0)
return r;
- r = read_full_file(filename, &content, NULL);
+ r = read_full_file(filename, &contents, NULL);
if (r < 0)
return r;
- p = content;
- while ((line = strsep(&p, "\n"))) {
- char *key;
+ n = strv_length(keys);
+ if (n == 0) /* No keys to retrieve? That's easy, we are done then */
+ return 0;
- key = strsep(&line, " ");
+ /* Let's build this up in a temporary array for now in order not to clobber the return parameter on failure */
+ v = newa0(char*, n);
- for (i = 0; keys[i]; i++) {
- if (streq(key, keys[i])) {
- values[i] = strdup(line);
- break;
+ for (p = contents; *p;) {
+ const char *w = NULL;
+ size_t n_done = 0;
+
+ for (i = 0; i < n; i++) {
+ if (v[i])
+ n_done ++;
+ else {
+ w = first_word(p, keys[i]);
+ if (w)
+ break;
}
}
- }
- for (i = 0; keys[i]; i++) {
- if (!values[i]) {
- for (i = 0; keys[i]; i++) {
- values[i] = mfree(values[i]);
+ if (w) {
+ char *c;
+ size_t l;
+
+ l = strcspn(w, NEWLINE);
+ c = strndup(w, l);
+ if (!c) {
+ r = -ENOMEM;
+ goto fail;
}
- return -ENOENT;
+
+ v[i] = c;
+ n_done++;
+
+ if (n_done >= n)
+ goto done;
+
+ p = w + l;
+ } else {
+ if (n_done >= n)
+ goto done;
+
+ p += strcspn(p, NEWLINE);
}
+
+ p += strspn(p, NEWLINE);
}
+ r = -ENXIO;
+
+fail:
+ for (i = 0; i < n; i++)
+ free(v[i]);
+
+ return r;
+
+done:
+ memcpy(ret_values, v, sizeof(char*) * n);
return 0;
+
}
int cg_create_everywhere(CGroupMask supported, CGroupMask mask, const char *path) {