1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/stringify.h> 3 #include <sys/types.h> 4 #include <sys/stat.h> 5 #include <fcntl.h> 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <string.h> 9 #include "fs.h" 10 11 int cgroupfs_find_mountpoint(char *buf, size_t maxlen, const char *subsys) 12 { 13 FILE *fp; 14 char mountpoint[PATH_MAX + 1], tokens[PATH_MAX + 1], type[PATH_MAX + 1]; 15 char path_v2[PATH_MAX + 1]; 16 char *token, *saved_ptr = NULL; 17 18 fp = fopen("/proc/mounts", "r"); 19 if (!fp) 20 return -1; 21 22 /* 23 * in order to handle split hierarchy, we need to scan /proc/mounts 24 * and inspect every cgroupfs mount point to find one that has 25 * the given subsystem. If we found v1, just use it. If not we can 26 * use v2 path as a fallback. 27 */ 28 path_v2[0] = '\0'; 29 30 while (fscanf(fp, "%*s %"__stringify(PATH_MAX)"s %"__stringify(PATH_MAX)"s %" 31 __stringify(PATH_MAX)"s %*d %*d\n", 32 mountpoint, type, tokens) == 3) { 33 34 if (!strcmp(type, "cgroup")) { 35 36 token = strtok_r(tokens, ",", &saved_ptr); 37 38 while (token != NULL) { 39 if (subsys && !strcmp(token, subsys)) { 40 /* found */ 41 fclose(fp); 42 43 if (strlen(mountpoint) < maxlen) { 44 strcpy(buf, mountpoint); 45 return 0; 46 } 47 return -1; 48 } 49 token = strtok_r(NULL, ",", &saved_ptr); 50 } 51 } 52 53 if (!strcmp(type, "cgroup2")) 54 strcpy(path_v2, mountpoint); 55 } 56 fclose(fp); 57 58 if (path_v2[0] && strlen(path_v2) < maxlen) { 59 strcpy(buf, path_v2); 60 return 0; 61 } 62 return -1; 63 } 64