mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
102 lines
2.0 KiB
102 lines
2.0 KiB
// SPDX-License-Identifier: GPL-2.0 |
|
#include <linux/stringify.h> |
|
#include <sys/types.h> |
|
#include <sys/stat.h> |
|
#include <fcntl.h> |
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
|
#include "fs.h" |
|
|
|
struct cgroupfs_cache_entry { |
|
char subsys[32]; |
|
char mountpoint[PATH_MAX]; |
|
}; |
|
|
|
/* just cache last used one */ |
|
static struct cgroupfs_cache_entry cached; |
|
|
|
int cgroupfs_find_mountpoint(char *buf, size_t maxlen, const char *subsys) |
|
{ |
|
FILE *fp; |
|
char *line = NULL; |
|
size_t len = 0; |
|
char *p, *path; |
|
char mountpoint[PATH_MAX]; |
|
|
|
if (!strcmp(cached.subsys, subsys)) { |
|
if (strlen(cached.mountpoint) < maxlen) { |
|
strcpy(buf, cached.mountpoint); |
|
return 0; |
|
} |
|
return -1; |
|
} |
|
|
|
fp = fopen("/proc/mounts", "r"); |
|
if (!fp) |
|
return -1; |
|
|
|
/* |
|
* in order to handle split hierarchy, we need to scan /proc/mounts |
|
* and inspect every cgroupfs mount point to find one that has |
|
* the given subsystem. If we found v1, just use it. If not we can |
|
* use v2 path as a fallback. |
|
*/ |
|
mountpoint[0] = '\0'; |
|
|
|
/* |
|
* The /proc/mounts has the follow format: |
|
* |
|
* <devname> <mount point> <fs type> <options> ... |
|
* |
|
*/ |
|
while (getline(&line, &len, fp) != -1) { |
|
/* skip devname */ |
|
p = strchr(line, ' '); |
|
if (p == NULL) |
|
continue; |
|
|
|
/* save the mount point */ |
|
path = ++p; |
|
p = strchr(p, ' '); |
|
if (p == NULL) |
|
continue; |
|
|
|
*p++ = '\0'; |
|
|
|
/* check filesystem type */ |
|
if (strncmp(p, "cgroup", 6)) |
|
continue; |
|
|
|
if (p[6] == '2') { |
|
/* save cgroup v2 path */ |
|
strcpy(mountpoint, path); |
|
continue; |
|
} |
|
|
|
/* now we have cgroup v1, check the options for subsystem */ |
|
p += 7; |
|
|
|
p = strstr(p, subsys); |
|
if (p == NULL) |
|
continue; |
|
|
|
/* sanity check: it should be separated by a space or a comma */ |
|
if (!strchr(" ,", p[-1]) || !strchr(" ,", p[strlen(subsys)])) |
|
continue; |
|
|
|
strcpy(mountpoint, path); |
|
break; |
|
} |
|
free(line); |
|
fclose(fp); |
|
|
|
strncpy(cached.subsys, subsys, sizeof(cached.subsys) - 1); |
|
strcpy(cached.mountpoint, mountpoint); |
|
|
|
if (mountpoint[0] && strlen(mountpoint) < maxlen) { |
|
strcpy(buf, mountpoint); |
|
return 0; |
|
} |
|
return -1; |
|
}
|
|
|