Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.5.6.
  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
 11struct cgroupfs_cache_entry {
 12	char	subsys[32];
 13	char	mountpoint[PATH_MAX];
 14};
 15
 16/* just cache last used one */
 17static struct cgroupfs_cache_entry *cached;
 18
 19int cgroupfs_find_mountpoint(char *buf, size_t maxlen, const char *subsys)
 20{
 21	FILE *fp;
 22	char *line = NULL;
 23	size_t len = 0;
 24	char *p, *path;
 25	char mountpoint[PATH_MAX];
 26
 27	if (cached && !strcmp(cached->subsys, subsys)) {
 28		if (strlen(cached->mountpoint) < maxlen) {
 29			strcpy(buf, cached->mountpoint);
 30			return 0;
 31		}
 32		return -1;
 33	}
 34
 35	fp = fopen("/proc/mounts", "r");
 36	if (!fp)
 37		return -1;
 38
 39	/*
 40	 * in order to handle split hierarchy, we need to scan /proc/mounts
 41	 * and inspect every cgroupfs mount point to find one that has
 42	 * the given subsystem.  If we found v1, just use it.  If not we can
 43	 * use v2 path as a fallback.
 44	 */
 45	mountpoint[0] = '\0';
 46
 47	/*
 48	 * The /proc/mounts has the follow format:
 49	 *
 50	 *   <devname> <mount point> <fs type> <options> ...
 51	 *
 52	 */
 53	while (getline(&line, &len, fp) != -1) {
 54		/* skip devname */
 55		p = strchr(line, ' ');
 56		if (p == NULL)
 57			continue;
 58
 59		/* save the mount point */
 60		path = ++p;
 61		p = strchr(p, ' ');
 62		if (p == NULL)
 63			continue;
 64
 65		*p++ = '\0';
 66
 67		/* check filesystem type */
 68		if (strncmp(p, "cgroup", 6))
 69			continue;
 70
 71		if (p[6] == '2') {
 72			/* save cgroup v2 path */
 73			strcpy(mountpoint, path);
 74			continue;
 75		}
 76
 77		/* now we have cgroup v1, check the options for subsystem */
 78		p += 7;
 79
 80		p = strstr(p, subsys);
 81		if (p == NULL)
 82			continue;
 83
 84		/* sanity check: it should be separated by a space or a comma */
 85		if (!strchr(" ,", p[-1]) || !strchr(" ,", p[strlen(subsys)]))
 86			continue;
 87
 88		strcpy(mountpoint, path);
 89		break;
 90	}
 91	free(line);
 92	fclose(fp);
 93
 94	if (!cached)
 95		cached = calloc(1, sizeof(*cached));
 96
 97	if (cached) {
 98		strncpy(cached->subsys, subsys, sizeof(cached->subsys) - 1);
 99		strcpy(cached->mountpoint, mountpoint);
100	}
101
102	if (mountpoint[0] && strlen(mountpoint) < maxlen) {
103		strcpy(buf, mountpoint);
104		return 0;
105	}
106	return -1;
107}